Free (GPLv2) TCP/IP stack developed by TASS Belgium

Dependents:   lpc1768-picotcp-demo ZeroMQ_PicoTCP_Publisher_demo TCPSocket_HelloWorld_PicoTCP Pico_TCP_UDP_Test ... more

PicoTCP. Copyright (c) 2013 TASS Belgium NV.

Released under the GNU General Public License, version 2.

Different licensing models may exist, at the sole discretion of the Copyright holders.

Official homepage: http://www.picotcp.com

Bug tracker: https://github.com/tass-belgium/picotcp/issues

Development steps:

  • initial integration with mbed RTOS
  • generic mbed Ethernet driver
  • high performance NXP LPC1768 specific Ethernet driver
  • Multi-threading support for mbed RTOS
  • Berkeley sockets and integration with the New Socket API
  • Fork of the apps running on top of the New Socket API
  • Scheduling optimizations
  • Debugging/benchmarking/testing

Demo application (measuring TCP sender performance):

Import programlpc1768-picotcp-demo

A PicoTCP demo app testing the ethernet throughput on the lpc1768 mbed board.

Committer:
tass
Date:
Thu Sep 19 12:38:53 2013 +0000
Revision:
63:97f481e33cb2
Parent:
51:ab4529a384a6
Update from the master branch

Who changed what in which revision?

UserRevisionLine numberNew contents of line
daniele 3:b4047e8a0123 1 /*********************************************************************
daniele 3:b4047e8a0123 2 PicoTCP. Copyright (c) 2012 TASS Belgium NV. Some rights reserved.
daniele 3:b4047e8a0123 3 See LICENSE and COPYING for usage.
daniele 3:b4047e8a0123 4
daniele 3:b4047e8a0123 5 .
daniele 3:b4047e8a0123 6
daniele 3:b4047e8a0123 7 Authors: Kristof Roelants, Brecht Van Cauwenberghe,
daniele 3:b4047e8a0123 8 Simon Maes, Philippe Mariman
daniele 3:b4047e8a0123 9 *********************************************************************/
daniele 3:b4047e8a0123 10
daniele 3:b4047e8a0123 11 #include "pico_stack.h"
daniele 3:b4047e8a0123 12 #include "pico_frame.h"
daniele 3:b4047e8a0123 13 #include "pico_tcp.h"
daniele 3:b4047e8a0123 14 #include "pico_udp.h"
daniele 3:b4047e8a0123 15 #include "pico_ipv4.h"
daniele 3:b4047e8a0123 16 #include "pico_addressing.h"
daniele 3:b4047e8a0123 17 #include "pico_nat.h"
daniele 3:b4047e8a0123 18
tass 63:97f481e33cb2 19
daniele 3:b4047e8a0123 20 #ifdef PICO_SUPPORT_IPV4
daniele 3:b4047e8a0123 21 #ifdef PICO_SUPPORT_NAT
daniele 3:b4047e8a0123 22
daniele 3:b4047e8a0123 23 #define nat_dbg(...) do{}while(0)
daniele 3:b4047e8a0123 24 //#define nat_dbg dbg
tass 63:97f481e33cb2 25 #define NAT_TCP_TIMEWAIT 240000 /* 4mins (in msec) */
tass 63:97f481e33cb2 26 //#define NAT_TCP_TIMEWAIT 10000 /* 10 sec (in msec) - for testing purposes only*/
tass 63:97f481e33cb2 27
daniele 3:b4047e8a0123 28
tass 63:97f481e33cb2 29 struct pico_nat_key {
tass 63:97f481e33cb2 30 struct pico_ip4 pub_addr;
tass 63:97f481e33cb2 31 uint16_t pub_port;
tass 63:97f481e33cb2 32 struct pico_ip4 priv_addr;
tass 63:97f481e33cb2 33 uint16_t priv_port;
daniele 3:b4047e8a0123 34 uint8_t proto;
tass 63:97f481e33cb2 35 /*
tass 63:97f481e33cb2 36 del_flags:
tass 63:97f481e33cb2 37 1 0
tass 63:97f481e33cb2 38 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
tass 63:97f481e33cb2 39 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
tass 63:97f481e33cb2 40 |F|B|S|R|P|~| CONNECTION ACTIVE |
tass 63:97f481e33cb2 41 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
tass 63:97f481e33cb2 42
tass 63:97f481e33cb2 43 F: FIN from Forwarding packet
tass 63:97f481e33cb2 44 B: FIN from Backwarding packet
tass 63:97f481e33cb2 45 S: SYN
tass 63:97f481e33cb2 46 R: RST
tass 63:97f481e33cb2 47 P: Persistant
tass 63:97f481e33cb2 48
tass 63:97f481e33cb2 49 */
tass 63:97f481e33cb2 50 uint16_t del_flags;
tass 63:97f481e33cb2 51 /* Connector for trees */
daniele 3:b4047e8a0123 52 };
daniele 3:b4047e8a0123 53
tass 63:97f481e33cb2 54 static struct pico_ipv4_link pub_link;
tass 63:97f481e33cb2 55 static uint8_t enable_nat_flag = 0;
daniele 3:b4047e8a0123 56
tass 63:97f481e33cb2 57 static int nat_cmp_backward(void * ka, void * kb)
daniele 3:b4047e8a0123 58 {
tass 63:97f481e33cb2 59 struct pico_nat_key *a = ka, *b = kb;
tass 63:97f481e33cb2 60 if (a->pub_port < b->pub_port) {
daniele 3:b4047e8a0123 61 return -1;
tass 63:97f481e33cb2 62 }
tass 63:97f481e33cb2 63 else if (a->pub_port > b->pub_port) {
daniele 3:b4047e8a0123 64 return 1;
tass 63:97f481e33cb2 65 }
tass 63:97f481e33cb2 66 else {
tass 63:97f481e33cb2 67 if (a->proto < b->proto) {
tass 63:97f481e33cb2 68 return -1;
tass 63:97f481e33cb2 69 }
tass 63:97f481e33cb2 70 else if (a->proto > b->proto) {
daniele 3:b4047e8a0123 71 return 1;
tass 63:97f481e33cb2 72 }
tass 63:97f481e33cb2 73 else {
tass 63:97f481e33cb2 74 /* a and b are identical */
tass 63:97f481e33cb2 75 return 0;
tass 63:97f481e33cb2 76 }
tass 63:97f481e33cb2 77 }
daniele 3:b4047e8a0123 78 }
daniele 3:b4047e8a0123 79
tass 63:97f481e33cb2 80 static int nat_cmp_forward(void * ka, void * kb)
daniele 3:b4047e8a0123 81 {
tass 63:97f481e33cb2 82 struct pico_nat_key *a =ka, *b = kb;
tass 63:97f481e33cb2 83 if (a->priv_addr.addr < b->priv_addr.addr) {
daniele 3:b4047e8a0123 84 return -1;
tass 63:97f481e33cb2 85 }
tass 63:97f481e33cb2 86 else if (a->priv_addr.addr > b->priv_addr.addr) {
daniele 3:b4047e8a0123 87 return 1;
tass 63:97f481e33cb2 88 }
tass 63:97f481e33cb2 89 else {
tass 63:97f481e33cb2 90 if (a->priv_port < b->priv_port) {
tass 63:97f481e33cb2 91 return -1;
tass 63:97f481e33cb2 92 }
tass 63:97f481e33cb2 93 else if (a->priv_port > b->priv_port) {
tass 63:97f481e33cb2 94 return 1;
tass 63:97f481e33cb2 95 }
tass 63:97f481e33cb2 96 else {
tass 63:97f481e33cb2 97 if (a->proto < b->proto) {
tass 63:97f481e33cb2 98 return -1;
tass 63:97f481e33cb2 99 }
tass 63:97f481e33cb2 100 else if (a->proto > b->proto) {
tass 63:97f481e33cb2 101 return 1;
tass 63:97f481e33cb2 102 }
tass 63:97f481e33cb2 103 else {
tass 63:97f481e33cb2 104 /* a and b are identical */
tass 63:97f481e33cb2 105 return 0;
tass 63:97f481e33cb2 106 }
tass 63:97f481e33cb2 107 }
tass 63:97f481e33cb2 108 }
daniele 3:b4047e8a0123 109 }
daniele 3:b4047e8a0123 110
tass 63:97f481e33cb2 111 PICO_TREE_DECLARE(KEYTable_forward,nat_cmp_forward);
tass 63:97f481e33cb2 112 PICO_TREE_DECLARE(KEYTable_backward,nat_cmp_backward);
daniele 3:b4047e8a0123 113
daniele 3:b4047e8a0123 114 /*
daniele 3:b4047e8a0123 115 2 options:
tass 63:97f481e33cb2 116 find on proto and pub_port
tass 63:97f481e33cb2 117 find on priv_addr, priv_port and proto
daniele 3:b4047e8a0123 118 zero the unused parameters
daniele 3:b4047e8a0123 119 */
tass 63:97f481e33cb2 120 static struct pico_nat_key *pico_ipv4_nat_find_key(uint16_t pub_port, struct pico_ip4 *priv_addr, uint16_t priv_port, uint8_t proto)
daniele 3:b4047e8a0123 121 {
tass 63:97f481e33cb2 122 struct pico_nat_key test;
tass 63:97f481e33cb2 123 test.pub_port = pub_port;
tass 63:97f481e33cb2 124 test.priv_port = priv_port;
daniele 3:b4047e8a0123 125 test.proto = proto;
tass 63:97f481e33cb2 126 if (priv_addr)
tass 63:97f481e33cb2 127 test.priv_addr = *priv_addr;
tass 63:97f481e33cb2 128 else
tass 63:97f481e33cb2 129 test.priv_addr.addr = 0;
daniele 3:b4047e8a0123 130
tass 63:97f481e33cb2 131 /* returns NULL if test can not be found */
tass 63:97f481e33cb2 132 if (!pub_port)
tass 63:97f481e33cb2 133 return pico_tree_findKey(&KEYTable_forward,&test);
daniele 3:b4047e8a0123 134 else
tass 63:97f481e33cb2 135 return pico_tree_findKey(&KEYTable_backward, &test);
daniele 3:b4047e8a0123 136 }
daniele 3:b4047e8a0123 137
tass 63:97f481e33cb2 138 int pico_ipv4_nat_find(uint16_t pub_port, struct pico_ip4 *priv_addr, uint16_t priv_port, uint8_t proto)
daniele 3:b4047e8a0123 139 {
tass 63:97f481e33cb2 140 struct pico_nat_key *k = NULL;
daniele 3:b4047e8a0123 141
tass 63:97f481e33cb2 142 k = pico_ipv4_nat_find_key(pub_port, priv_addr, priv_port, proto);
tass 63:97f481e33cb2 143 if (k)
tass 63:97f481e33cb2 144 return 0;
tass 51:ab4529a384a6 145 else
tass 63:97f481e33cb2 146 return -1;
daniele 3:b4047e8a0123 147 }
daniele 3:b4047e8a0123 148
tass 63:97f481e33cb2 149 int pico_ipv4_nat_snif_forward(struct pico_nat_key *nk, struct pico_frame *f)
daniele 3:b4047e8a0123 150 {
tass 63:97f481e33cb2 151 uint8_t proto;
tass 63:97f481e33cb2 152 struct pico_ipv4_hdr *ipv4_hdr = (struct pico_ipv4_hdr *)f->net_hdr;
tass 63:97f481e33cb2 153 struct pico_tcp_hdr *tcp_hdr;
tass 63:97f481e33cb2 154
tass 63:97f481e33cb2 155 if (!ipv4_hdr)
tass 63:97f481e33cb2 156 return -1;
tass 63:97f481e33cb2 157 proto = ipv4_hdr->proto;
daniele 3:b4047e8a0123 158
tass 63:97f481e33cb2 159 if (proto == PICO_PROTO_TCP) {
tass 63:97f481e33cb2 160 tcp_hdr = (struct pico_tcp_hdr *) f->transport_hdr;
tass 63:97f481e33cb2 161 if (!tcp_hdr)
tass 63:97f481e33cb2 162 return -1;
tass 63:97f481e33cb2 163 if (tcp_hdr->flags & PICO_TCP_FIN) {
tass 63:97f481e33cb2 164 nk->del_flags |= PICO_DEL_FLAGS_FIN_FORWARD; //FIN from forwarding packet
tass 63:97f481e33cb2 165 }
tass 63:97f481e33cb2 166 if (tcp_hdr->flags & PICO_TCP_SYN) {
tass 63:97f481e33cb2 167 nk->del_flags |= PICO_DEL_FLAGS_SYN;
tass 63:97f481e33cb2 168 }
tass 63:97f481e33cb2 169 if (tcp_hdr->flags & PICO_TCP_RST) {
tass 63:97f481e33cb2 170 nk->del_flags |= PICO_DEL_FLAGS_RST;
tass 63:97f481e33cb2 171 }
tass 63:97f481e33cb2 172 } else if (proto == PICO_PROTO_UDP) {
tass 63:97f481e33cb2 173 /* set conn active to 1 */
tass 63:97f481e33cb2 174 nk->del_flags &= 0xFE00;
tass 63:97f481e33cb2 175 nk->del_flags++;
tass 63:97f481e33cb2 176 }
tass 63:97f481e33cb2 177 return 0;
daniele 3:b4047e8a0123 178 }
daniele 3:b4047e8a0123 179
tass 63:97f481e33cb2 180
tass 63:97f481e33cb2 181 int pico_ipv4_nat_snif_backward(struct pico_nat_key *nk, struct pico_frame *f)
daniele 3:b4047e8a0123 182 {
tass 63:97f481e33cb2 183 uint8_t proto;
tass 63:97f481e33cb2 184 struct pico_ipv4_hdr *ipv4_hdr = (struct pico_ipv4_hdr *)f->net_hdr;
tass 63:97f481e33cb2 185 struct pico_tcp_hdr *tcp_hdr;
tass 63:97f481e33cb2 186
tass 63:97f481e33cb2 187 if (!ipv4_hdr)
tass 63:97f481e33cb2 188 return -1;
tass 63:97f481e33cb2 189 proto = ipv4_hdr->proto;
tass 63:97f481e33cb2 190
tass 63:97f481e33cb2 191 if (proto == PICO_PROTO_TCP) {
tass 63:97f481e33cb2 192 tcp_hdr = (struct pico_tcp_hdr *) f->transport_hdr;
tass 63:97f481e33cb2 193 if (!tcp_hdr)
tass 63:97f481e33cb2 194 return -1;
tass 63:97f481e33cb2 195 if (tcp_hdr->flags & PICO_TCP_FIN) {
tass 63:97f481e33cb2 196 nk->del_flags |= PICO_DEL_FLAGS_FIN_BACKWARD; //FIN from backwarding packet
tass 63:97f481e33cb2 197 }
tass 63:97f481e33cb2 198 if (tcp_hdr->flags & PICO_TCP_SYN) {
tass 63:97f481e33cb2 199 nk->del_flags |= PICO_DEL_FLAGS_SYN;
tass 63:97f481e33cb2 200 }
tass 63:97f481e33cb2 201 if (tcp_hdr->flags & PICO_TCP_RST) {
tass 63:97f481e33cb2 202 nk->del_flags |= PICO_DEL_FLAGS_RST;
tass 63:97f481e33cb2 203 }
tass 63:97f481e33cb2 204 } else if (proto == PICO_PROTO_UDP) {
tass 63:97f481e33cb2 205 /* set conn active to 1 */
tass 63:97f481e33cb2 206 nk->del_flags &= 0xFE00;
tass 63:97f481e33cb2 207 nk->del_flags++;
daniele 3:b4047e8a0123 208 }
daniele 3:b4047e8a0123 209 return 0;
daniele 3:b4047e8a0123 210 }
daniele 3:b4047e8a0123 211
tass 63:97f481e33cb2 212 void pico_ipv4_nat_table_cleanup(unsigned long now, void *_unused)
daniele 3:b4047e8a0123 213 {
tass 63:97f481e33cb2 214 struct pico_tree_node * idx, * safe;
tass 63:97f481e33cb2 215 struct pico_nat_key *k = NULL;
tass 51:ab4529a384a6 216 nat_dbg("NAT: before table cleanup:\n");
daniele 3:b4047e8a0123 217 pico_ipv4_nat_print_table();
daniele 3:b4047e8a0123 218
tass 63:97f481e33cb2 219 //struct pico_nat_key *tmp;
tass 63:97f481e33cb2 220 pico_tree_foreach_reverse_safe(idx,&KEYTable_forward,safe){
tass 63:97f481e33cb2 221 k = idx->keyValue;
tass 63:97f481e33cb2 222 switch (k->proto)
daniele 3:b4047e8a0123 223 {
daniele 3:b4047e8a0123 224 case PICO_PROTO_TCP:
tass 63:97f481e33cb2 225 if ((k->del_flags & 0x0800) >> 11) {
tass 63:97f481e33cb2 226 /* entry is persistant */
daniele 3:b4047e8a0123 227 break;
tass 63:97f481e33cb2 228 }
tass 63:97f481e33cb2 229 else if ((k->del_flags & 0x01FF) == 0) {
tass 63:97f481e33cb2 230 /* conn active is zero, delete entry */
tass 63:97f481e33cb2 231 pico_ipv4_nat_del(k->pub_port, k->proto);
tass 63:97f481e33cb2 232 }
tass 63:97f481e33cb2 233 else if ((k->del_flags & 0x1000) >> 12) {
tass 63:97f481e33cb2 234 /* RST flag set, set conn active to zero */
tass 63:97f481e33cb2 235 k->del_flags &= 0xFE00;
tass 63:97f481e33cb2 236 }
tass 63:97f481e33cb2 237 else if (((k->del_flags & 0x8000) >> 15) && ((k->del_flags & 0x4000) >> 14)) {
tass 63:97f481e33cb2 238 /* FIN1 and FIN2 set, set conn active to zero */
tass 63:97f481e33cb2 239 k->del_flags &= 0xFE00;
tass 63:97f481e33cb2 240 }
tass 63:97f481e33cb2 241 else if ((k->del_flags & 0x01FF) > 360) {
tass 63:97f481e33cb2 242 /* conn is active for 24 hours, delete entry */
tass 63:97f481e33cb2 243 pico_ipv4_nat_del(k->pub_port, k->proto);
tass 63:97f481e33cb2 244 }
tass 63:97f481e33cb2 245 else {
tass 63:97f481e33cb2 246 k->del_flags++;
tass 63:97f481e33cb2 247 }
daniele 3:b4047e8a0123 248 break;
daniele 3:b4047e8a0123 249
daniele 3:b4047e8a0123 250 case PICO_PROTO_UDP:
tass 63:97f481e33cb2 251 if ((k->del_flags & 0x0800) >> 11) {
tass 63:97f481e33cb2 252 /* entry is persistant */
daniele 3:b4047e8a0123 253 break;
tass 63:97f481e33cb2 254 }
tass 63:97f481e33cb2 255 else if ((k->del_flags & 0x01FF) > 1) {
tass 63:97f481e33cb2 256 /* Delete entry when it has existed NAT_TCP_TIMEWAIT */
tass 63:97f481e33cb2 257 pico_ipv4_nat_del(k->pub_port, k->proto);
tass 63:97f481e33cb2 258 }
tass 63:97f481e33cb2 259 else {
tass 63:97f481e33cb2 260 k->del_flags++;
tass 63:97f481e33cb2 261 }
daniele 3:b4047e8a0123 262 break;
daniele 3:b4047e8a0123 263
daniele 3:b4047e8a0123 264 default:
tass 63:97f481e33cb2 265 /* Unknown protocol in NAT table, delete when it has existed NAT_TCP_TIMEWAIT */
tass 63:97f481e33cb2 266 if ((k->del_flags & 0x01FF) > 1) {
tass 63:97f481e33cb2 267 pico_ipv4_nat_del(k->pub_port, k->proto);
tass 63:97f481e33cb2 268 }
tass 63:97f481e33cb2 269 else {
tass 63:97f481e33cb2 270 k->del_flags++;
tass 63:97f481e33cb2 271 }
daniele 3:b4047e8a0123 272 }
daniele 3:b4047e8a0123 273 }
daniele 3:b4047e8a0123 274
daniele 3:b4047e8a0123 275 nat_dbg("NAT: after table cleanup:\n");
daniele 3:b4047e8a0123 276 pico_ipv4_nat_print_table();
tass 63:97f481e33cb2 277 pico_timer_add(NAT_TCP_TIMEWAIT, pico_ipv4_nat_table_cleanup, NULL);
tass 63:97f481e33cb2 278 }
tass 63:97f481e33cb2 279
tass 63:97f481e33cb2 280 int pico_ipv4_nat_add(struct pico_ip4 pub_addr, uint16_t pub_port, struct pico_ip4 priv_addr, uint16_t priv_port, uint8_t proto)
tass 63:97f481e33cb2 281 {
tass 63:97f481e33cb2 282 struct pico_nat_key *key = pico_zalloc(sizeof(struct pico_nat_key));
tass 63:97f481e33cb2 283 if (!key) {
tass 63:97f481e33cb2 284 pico_err = PICO_ERR_ENOMEM;
tass 63:97f481e33cb2 285 return -1;
tass 63:97f481e33cb2 286 }
tass 63:97f481e33cb2 287
tass 63:97f481e33cb2 288 key->pub_addr = pub_addr;
tass 63:97f481e33cb2 289 key->pub_port = pub_port;
tass 63:97f481e33cb2 290 key->priv_addr = priv_addr;
tass 63:97f481e33cb2 291 key->priv_port = priv_port;
tass 63:97f481e33cb2 292 key->proto = proto;
tass 63:97f481e33cb2 293 key->del_flags = 0x0001; /* set conn active to 1, other flags to 0 */
tass 63:97f481e33cb2 294
tass 63:97f481e33cb2 295 /* RB_INSERT returns NULL when element added, pointer to the element if already in tree */
tass 63:97f481e33cb2 296 if(!pico_tree_insert(&KEYTable_forward, key) && !pico_tree_insert(&KEYTable_backward, key)){
tass 63:97f481e33cb2 297 return 0; /* New element added */
tass 63:97f481e33cb2 298 }
tass 63:97f481e33cb2 299 else {
tass 63:97f481e33cb2 300 pico_free(key);
tass 63:97f481e33cb2 301 pico_err = PICO_ERR_EINVAL;
tass 63:97f481e33cb2 302 return -1; /* Element key already exists */
tass 63:97f481e33cb2 303 }
daniele 3:b4047e8a0123 304 }
daniele 3:b4047e8a0123 305
daniele 3:b4047e8a0123 306
tass 63:97f481e33cb2 307 int pico_ipv4_nat_del(uint16_t pub_port, uint8_t proto)
tass 63:97f481e33cb2 308 {
tass 63:97f481e33cb2 309 struct pico_nat_key *key = NULL;
tass 63:97f481e33cb2 310 key = pico_ipv4_nat_find_key(pub_port, NULL, 0, proto);
tass 63:97f481e33cb2 311 if (!key) {
tass 63:97f481e33cb2 312 nat_dbg("NAT: key to delete not found: proto %u | pub_port %u\n", proto, pub_port);
tass 63:97f481e33cb2 313 return -1;
tass 63:97f481e33cb2 314 }
tass 63:97f481e33cb2 315 else {
tass 63:97f481e33cb2 316 nat_dbg("NAT: key to delete found: proto %u | pub_port %u\n", proto, pub_port);
tass 63:97f481e33cb2 317 /* RB_REMOVE returns pointer to removed element, NULL to indicate error */
tass 63:97f481e33cb2 318 if(pico_tree_delete(&KEYTable_forward, key) && pico_tree_delete(&KEYTable_backward, key))
tass 63:97f481e33cb2 319 pico_free(key);
tass 63:97f481e33cb2 320 else
tass 63:97f481e33cb2 321 return -1; /* Error on removing element, do not free! */
tass 63:97f481e33cb2 322 }
tass 63:97f481e33cb2 323 return 0;
tass 63:97f481e33cb2 324 }
tass 63:97f481e33cb2 325
tass 63:97f481e33cb2 326 int pico_ipv4_port_forward(struct pico_ip4 pub_addr, uint16_t pub_port, struct pico_ip4 priv_addr, uint16_t priv_port, uint8_t proto, uint8_t persistant)
tass 63:97f481e33cb2 327 {
tass 63:97f481e33cb2 328 struct pico_nat_key *key = NULL;
tass 63:97f481e33cb2 329
tass 63:97f481e33cb2 330 switch (persistant)
daniele 3:b4047e8a0123 331 {
tass 63:97f481e33cb2 332 case PICO_IPV4_FORWARD_ADD:
tass 63:97f481e33cb2 333 if (pico_ipv4_nat_add(pub_addr, pub_port, priv_addr, priv_port, proto) != 0)
tass 63:97f481e33cb2 334 return -1; /* pico_err set in nat_add */
tass 63:97f481e33cb2 335 key = pico_ipv4_nat_find_key(pub_port, &priv_addr, priv_port, proto);
tass 63:97f481e33cb2 336 if (!key) {
daniele 3:b4047e8a0123 337 pico_err = PICO_ERR_EAGAIN;
daniele 3:b4047e8a0123 338 return -1;
daniele 3:b4047e8a0123 339 }
tass 63:97f481e33cb2 340 key->del_flags = (key->del_flags & ~(0x1 << 11)) | (persistant << 11);
daniele 3:b4047e8a0123 341 break;
daniele 3:b4047e8a0123 342
tass 63:97f481e33cb2 343 case PICO_IPV4_FORWARD_DEL:
tass 63:97f481e33cb2 344 return pico_ipv4_nat_del(pub_port, proto);
daniele 3:b4047e8a0123 345
daniele 3:b4047e8a0123 346 default:
daniele 3:b4047e8a0123 347 pico_err = PICO_ERR_EINVAL;
daniele 3:b4047e8a0123 348 return -1;
daniele 3:b4047e8a0123 349 }
daniele 3:b4047e8a0123 350 pico_ipv4_nat_print_table();
daniele 3:b4047e8a0123 351 return 0;
daniele 3:b4047e8a0123 352 }
daniele 3:b4047e8a0123 353
tass 63:97f481e33cb2 354
tass 63:97f481e33cb2 355 void pico_ipv4_nat_print_table(void)
daniele 3:b4047e8a0123 356 {
tass 63:97f481e33cb2 357 struct pico_nat_key __attribute__((unused)) *k = NULL ;
tass 63:97f481e33cb2 358 struct pico_tree_node * index;
tass 63:97f481e33cb2 359 uint16_t i = 0;
tass 63:97f481e33cb2 360
tass 63:97f481e33cb2 361 nat_dbg("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
tass 63:97f481e33cb2 362 nat_dbg("+ NAT table +\n");
tass 63:97f481e33cb2 363 nat_dbg("+-----------------------------------------------------------------------------------------------------------------------+\n");
tass 63:97f481e33cb2 364 nat_dbg("+ pointer | private_addr | private_port | proto | pub_addr | pub_port | conn active | FIN1 | FIN2 | SYN | RST | PERS +\n");
tass 63:97f481e33cb2 365 nat_dbg("+-----------------------------------------------------------------------------------------------------------------------+\n");
tass 51:ab4529a384a6 366
tass 63:97f481e33cb2 367 pico_tree_foreach(index,&KEYTable_forward){
tass 63:97f481e33cb2 368 k = index->keyValue;
tass 63:97f481e33cb2 369 nat_dbg("+ %10p | %08X | %05u | %04u | %08X | %05u | %03u | %u | %u | %u | %u | %u +\n",
tass 63:97f481e33cb2 370 k, k->priv_addr.addr, k->priv_port, k->proto, k->pub_addr.addr, k->pub_port, (k->del_flags)&0x01FF, ((k->del_flags)&0x8000)>>15,
tass 63:97f481e33cb2 371 ((k->del_flags)&0x4000)>>14, ((k->del_flags)&0x2000)>>13, ((k->del_flags)&0x1000)>>12, ((k->del_flags)&0x0800)>>11);
tass 63:97f481e33cb2 372 i++;
tass 63:97f481e33cb2 373 }
tass 63:97f481e33cb2 374 nat_dbg("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
tass 63:97f481e33cb2 375 }
daniele 3:b4047e8a0123 376
tass 63:97f481e33cb2 377 int pico_ipv4_nat_generate_key(struct pico_nat_key* nk, struct pico_frame* f, struct pico_ip4 pub_addr)
tass 63:97f481e33cb2 378 {
tass 63:97f481e33cb2 379 uint16_t pub_port = 0;
tass 63:97f481e33cb2 380 uint8_t proto;
tass 63:97f481e33cb2 381 struct pico_tcp_hdr *tcp_hdr = NULL; /* forced to use pico_trans */
tass 63:97f481e33cb2 382 struct pico_udp_hdr *udp_hdr = NULL; /* forced to use pico_trans */
tass 63:97f481e33cb2 383 struct pico_ipv4_hdr *ipv4_hdr = (struct pico_ipv4_hdr *)f->net_hdr;
tass 63:97f481e33cb2 384 if (!ipv4_hdr)
tass 63:97f481e33cb2 385 return -1;
tass 63:97f481e33cb2 386 proto = ipv4_hdr->proto;
tass 63:97f481e33cb2 387 do {
tass 63:97f481e33cb2 388 /* 1. generate valid new NAT port entry */
tass 63:97f481e33cb2 389 uint32_t rand = pico_rand();
tass 63:97f481e33cb2 390 pub_port = (uint16_t) (rand & 0xFFFFU);
tass 63:97f481e33cb2 391 pub_port = (uint16_t)(pub_port % (65535 - 1024)) + 1024U;
tass 63:97f481e33cb2 392 pub_port = short_be(pub_port);
tass 63:97f481e33cb2 393
tass 63:97f481e33cb2 394 /* 2. check if already in table, if no exit */
tass 63:97f481e33cb2 395 nat_dbg("NAT: check if generated port %u is free\n", short_be(pub_port));
tass 63:97f481e33cb2 396 if (pico_is_port_free(proto, pub_port, NULL, &pico_proto_ipv4))
daniele 3:b4047e8a0123 397 break;
tass 63:97f481e33cb2 398
tass 63:97f481e33cb2 399 } while (1);
tass 63:97f481e33cb2 400 nat_dbg("NAT: port %u is free\n", short_be(pub_port));
tass 63:97f481e33cb2 401
tass 63:97f481e33cb2 402 if (proto == PICO_PROTO_TCP) {
tass 63:97f481e33cb2 403 tcp_hdr = (struct pico_tcp_hdr *) f->transport_hdr;
tass 63:97f481e33cb2 404 if (!tcp_hdr)
tass 63:97f481e33cb2 405 return -1;
tass 63:97f481e33cb2 406 nk->priv_port = tcp_hdr->trans.sport;
tass 63:97f481e33cb2 407 } else if (proto == PICO_PROTO_UDP) {
tass 63:97f481e33cb2 408 udp_hdr = (struct pico_udp_hdr *) f->transport_hdr;
tass 63:97f481e33cb2 409 if (!udp_hdr)
tass 63:97f481e33cb2 410 return -1;
tass 63:97f481e33cb2 411 nk->priv_port = udp_hdr->trans.sport;
tass 63:97f481e33cb2 412 } else if (proto == PICO_PROTO_ICMP4) {
tass 63:97f481e33cb2 413 nk->priv_port = (uint16_t)(ipv4_hdr->src.addr & 0x00FF);
tass 63:97f481e33cb2 414 pub_port = (uint16_t)(ipv4_hdr->dst.addr & 0x00FF);
tass 63:97f481e33cb2 415 if (!pico_is_port_free(proto, pub_port, NULL, &pico_proto_ipv4))
daniele 3:b4047e8a0123 416 return -1;
daniele 3:b4047e8a0123 417 }
daniele 3:b4047e8a0123 418
tass 63:97f481e33cb2 419 nk->pub_addr = pub_addr; /* get public ip address from device */
tass 63:97f481e33cb2 420 nk->pub_port = pub_port;
tass 63:97f481e33cb2 421 nk->priv_addr = ipv4_hdr->src;
tass 63:97f481e33cb2 422 nk->proto = ipv4_hdr->proto;
tass 63:97f481e33cb2 423 nk->del_flags = 0x0001; /* set conn active to 1 */
tass 63:97f481e33cb2 424 if (pico_ipv4_nat_add(nk->pub_addr, nk->pub_port, nk->priv_addr, nk->priv_port, nk->proto) < 0) {
tass 63:97f481e33cb2 425 return -1;
tass 63:97f481e33cb2 426 } else {
tass 63:97f481e33cb2 427 return 0;
tass 63:97f481e33cb2 428 }
tass 63:97f481e33cb2 429 }
tass 63:97f481e33cb2 430
tass 63:97f481e33cb2 431
tass 63:97f481e33cb2 432 static int pico_nat_tcp_checksum(struct pico_frame *f)
tass 63:97f481e33cb2 433 {
tass 63:97f481e33cb2 434 struct pico_tcp_hdr *trans_hdr = (struct pico_tcp_hdr *) f->transport_hdr;
tass 63:97f481e33cb2 435 struct pico_ipv4_hdr *net_hdr = (struct pico_ipv4_hdr *) f->net_hdr;
tass 63:97f481e33cb2 436
tass 63:97f481e33cb2 437 struct tcp_pseudo_hdr_ipv4 pseudo;
tass 63:97f481e33cb2 438 if (!trans_hdr || !net_hdr)
tass 63:97f481e33cb2 439 return -1;
tass 63:97f481e33cb2 440
tass 63:97f481e33cb2 441 pseudo.src.addr = net_hdr->src.addr;
tass 63:97f481e33cb2 442 pseudo.dst.addr = net_hdr->dst.addr;
tass 63:97f481e33cb2 443 pseudo.res = 0;
tass 63:97f481e33cb2 444 pseudo.proto = PICO_PROTO_TCP;
tass 63:97f481e33cb2 445 pseudo.tcp_len = short_be(f->transport_len);
tass 63:97f481e33cb2 446
tass 63:97f481e33cb2 447 trans_hdr->crc = 0;
tass 63:97f481e33cb2 448 trans_hdr->crc = pico_dualbuffer_checksum(&pseudo, sizeof(struct tcp_pseudo_hdr_ipv4), trans_hdr, f->transport_len);
tass 63:97f481e33cb2 449 trans_hdr->crc = short_be(trans_hdr->crc);
tass 63:97f481e33cb2 450 return 0;
tass 63:97f481e33cb2 451 }
tass 63:97f481e33cb2 452
daniele 3:b4047e8a0123 453
tass 63:97f481e33cb2 454 int pico_ipv4_nat_translate(struct pico_nat_key* nk, struct pico_frame* f)
tass 63:97f481e33cb2 455 {
tass 63:97f481e33cb2 456 uint8_t proto;
tass 63:97f481e33cb2 457 struct pico_tcp_hdr *tcp_hdr = NULL; /* forced to use pico_trans */
tass 63:97f481e33cb2 458 struct pico_udp_hdr *udp_hdr = NULL; /* forced to use pico_trans */
tass 63:97f481e33cb2 459
tass 63:97f481e33cb2 460 struct pico_ipv4_hdr* ipv4_hdr = (struct pico_ipv4_hdr *)f->net_hdr;
tass 63:97f481e33cb2 461 if (!ipv4_hdr)
tass 63:97f481e33cb2 462 return -1;
tass 63:97f481e33cb2 463 proto = ipv4_hdr->proto;
tass 63:97f481e33cb2 464
tass 63:97f481e33cb2 465 if (proto == PICO_PROTO_TCP) {
tass 63:97f481e33cb2 466 tcp_hdr = (struct pico_tcp_hdr *) f->transport_hdr;
tass 63:97f481e33cb2 467 if (!tcp_hdr)
tass 63:97f481e33cb2 468 return -1;
tass 63:97f481e33cb2 469 tcp_hdr->trans.sport = nk->pub_port;
tass 63:97f481e33cb2 470 } else if (proto == PICO_PROTO_UDP) {
tass 63:97f481e33cb2 471 udp_hdr = (struct pico_udp_hdr *) f->transport_hdr;
tass 63:97f481e33cb2 472 if (!udp_hdr)
tass 63:97f481e33cb2 473 return -1;
tass 63:97f481e33cb2 474 udp_hdr->trans.sport = nk->pub_port;
tass 63:97f481e33cb2 475 }
tass 63:97f481e33cb2 476
tass 63:97f481e33cb2 477 //if(f->proto == PICO_PROTO_ICMP){
tass 63:97f481e33cb2 478 //} XXX no action
tass 63:97f481e33cb2 479
tass 63:97f481e33cb2 480 ipv4_hdr->src = nk->pub_addr;
tass 63:97f481e33cb2 481
tass 63:97f481e33cb2 482 if (proto == PICO_PROTO_TCP) {
tass 63:97f481e33cb2 483 pico_nat_tcp_checksum(f);
tass 63:97f481e33cb2 484 } else if (proto == PICO_PROTO_UDP){
tass 63:97f481e33cb2 485 udp_hdr->crc = 0;
tass 63:97f481e33cb2 486 udp_hdr->crc = short_be(pico_udp_checksum_ipv4(f));
tass 63:97f481e33cb2 487 }
tass 63:97f481e33cb2 488
tass 63:97f481e33cb2 489 // pico_ipv4_checksum(f);
tass 63:97f481e33cb2 490 ipv4_hdr->crc = 0;
tass 63:97f481e33cb2 491 ipv4_hdr->crc = short_be(pico_checksum(ipv4_hdr, f->net_len));
daniele 3:b4047e8a0123 492
daniele 3:b4047e8a0123 493 return 0;
daniele 3:b4047e8a0123 494 }
daniele 3:b4047e8a0123 495
tass 63:97f481e33cb2 496
tass 63:97f481e33cb2 497 int pico_ipv4_nat_port_forward(struct pico_frame* f)
daniele 3:b4047e8a0123 498 {
tass 63:97f481e33cb2 499 struct pico_nat_key *nk = NULL;
tass 63:97f481e33cb2 500 struct pico_tcp_hdr *tcp_hdr = NULL;
tass 63:97f481e33cb2 501 struct pico_udp_hdr *udp_hdr = NULL;
tass 63:97f481e33cb2 502 struct pico_icmp4_hdr *icmp_hdr = NULL;
tass 63:97f481e33cb2 503 struct pico_ipv4_hdr* ipv4_hdr;
tass 63:97f481e33cb2 504 uint16_t pub_port = 0;
tass 63:97f481e33cb2 505 uint8_t proto;
daniele 3:b4047e8a0123 506
tass 63:97f481e33cb2 507 ipv4_hdr = (struct pico_ipv4_hdr *)f->net_hdr;
tass 63:97f481e33cb2 508 if (!ipv4_hdr)
tass 63:97f481e33cb2 509 return -1;
tass 63:97f481e33cb2 510 proto = ipv4_hdr->proto;
tass 63:97f481e33cb2 511
tass 63:97f481e33cb2 512 if (proto == PICO_PROTO_TCP) {
tass 63:97f481e33cb2 513 tcp_hdr = (struct pico_tcp_hdr *) f->transport_hdr;
tass 63:97f481e33cb2 514 if (!tcp_hdr)
tass 63:97f481e33cb2 515 return -1;
tass 63:97f481e33cb2 516 pub_port = tcp_hdr->trans.dport;
tass 63:97f481e33cb2 517 } else if (proto == PICO_PROTO_UDP) {
tass 63:97f481e33cb2 518 udp_hdr = (struct pico_udp_hdr *) f->transport_hdr;
tass 63:97f481e33cb2 519 if (!udp_hdr)
tass 63:97f481e33cb2 520 return -1;
tass 63:97f481e33cb2 521 pub_port = udp_hdr->trans.dport;
tass 63:97f481e33cb2 522 } else if (proto == PICO_PROTO_ICMP4) {
tass 63:97f481e33cb2 523 icmp_hdr = (struct pico_icmp4_hdr *) f->transport_hdr;
tass 63:97f481e33cb2 524 if (!icmp_hdr)
tass 63:97f481e33cb2 525 return -1;
tass 63:97f481e33cb2 526 /* XXX PRELIMINARY ONLY LAST 16 BITS OF IP */
tass 63:97f481e33cb2 527 pub_port = (uint16_t)(ipv4_hdr->src.addr & 0x00FF);
tass 63:97f481e33cb2 528 }
tass 63:97f481e33cb2 529
tass 63:97f481e33cb2 530 nk = pico_ipv4_nat_find_key(pub_port, 0, 0, proto);
tass 63:97f481e33cb2 531
tass 63:97f481e33cb2 532 if (!nk) {
tass 63:97f481e33cb2 533 nat_dbg("\nNAT: ERROR key not found in table\n");
tass 63:97f481e33cb2 534 return -1;
tass 63:97f481e33cb2 535 } else {
tass 63:97f481e33cb2 536 pico_ipv4_nat_snif_forward(nk,f);
tass 63:97f481e33cb2 537 ipv4_hdr->dst.addr = nk->priv_addr.addr;
tass 63:97f481e33cb2 538
tass 63:97f481e33cb2 539 if (proto == PICO_PROTO_TCP) {
tass 63:97f481e33cb2 540 tcp_hdr->trans.dport = nk->priv_port;
tass 63:97f481e33cb2 541 pico_nat_tcp_checksum(f);
tass 63:97f481e33cb2 542 } else if (proto == PICO_PROTO_UDP) {
tass 63:97f481e33cb2 543 udp_hdr->trans.dport = nk->priv_port;
tass 63:97f481e33cb2 544 udp_hdr->crc = 0;
tass 63:97f481e33cb2 545 udp_hdr->crc = short_be(pico_udp_checksum_ipv4(f));
tass 51:ab4529a384a6 546 }
daniele 3:b4047e8a0123 547 }
daniele 3:b4047e8a0123 548
tass 63:97f481e33cb2 549 ipv4_hdr->crc = 0;
tass 63:97f481e33cb2 550 ipv4_hdr->crc = short_be(pico_checksum(ipv4_hdr, f->net_len));
tass 63:97f481e33cb2 551
tass 63:97f481e33cb2 552 return 0;
tass 63:97f481e33cb2 553 }
tass 63:97f481e33cb2 554
tass 63:97f481e33cb2 555
tass 63:97f481e33cb2 556
tass 63:97f481e33cb2 557 int pico_ipv4_nat(struct pico_frame *f, struct pico_ip4 pub_addr)
tass 63:97f481e33cb2 558 {
tass 63:97f481e33cb2 559 /*do nat---------*/
tass 63:97f481e33cb2 560 struct pico_nat_key *nk = NULL;
tass 63:97f481e33cb2 561 struct pico_nat_key key;
tass 63:97f481e33cb2 562 struct pico_ipv4_hdr *net_hdr = (struct pico_ipv4_hdr *) f->net_hdr;
tass 63:97f481e33cb2 563 struct pico_tcp_hdr *tcp_hdr = NULL;
tass 63:97f481e33cb2 564 struct pico_udp_hdr *udp_hdr = NULL;
tass 63:97f481e33cb2 565 int ret;
tass 63:97f481e33cb2 566 uint8_t proto = net_hdr->proto;
tass 63:97f481e33cb2 567 uint16_t priv_port = 0;
tass 63:97f481e33cb2 568 struct pico_ip4 priv_addr= net_hdr->src;
tass 63:97f481e33cb2 569
tass 63:97f481e33cb2 570 nk= &key;
daniele 3:b4047e8a0123 571
tass 63:97f481e33cb2 572 /* TODO DELME check if IN */
tass 63:97f481e33cb2 573 if (pub_addr.addr == net_hdr->dst.addr) {
tass 63:97f481e33cb2 574 nat_dbg("NAT: backward translation {dst.addr, dport}: {%08X,%u} ->", net_hdr->dst.addr, ((struct pico_trans *)f->transport_hdr)->dport);
tass 63:97f481e33cb2 575 ret = pico_ipv4_nat_port_forward(f); /* our IN definition */
tass 63:97f481e33cb2 576 nat_dbg(" {%08X,%u}\n", net_hdr->dst.addr, short_be(((struct pico_trans *)f->transport_hdr)->dport));
tass 63:97f481e33cb2 577 } else {
tass 63:97f481e33cb2 578 if (net_hdr->proto == PICO_PROTO_TCP) {
tass 63:97f481e33cb2 579 tcp_hdr = (struct pico_tcp_hdr *) f->transport_hdr;
tass 63:97f481e33cb2 580 priv_port = tcp_hdr->trans.sport;
tass 63:97f481e33cb2 581 } else if (net_hdr->proto == PICO_PROTO_UDP) {
tass 63:97f481e33cb2 582 udp_hdr = (struct pico_udp_hdr *) f->transport_hdr;
tass 63:97f481e33cb2 583 priv_port = udp_hdr->trans.sport;
tass 63:97f481e33cb2 584 } else if (net_hdr->proto == PICO_PROTO_ICMP4) {
tass 63:97f481e33cb2 585 //udp_hdr = (struct pico_udp_hdr *) f->transport_hdr;
tass 63:97f481e33cb2 586 priv_port = (uint16_t)(net_hdr->src.addr & 0x00FF);
tass 63:97f481e33cb2 587 }
daniele 3:b4047e8a0123 588
tass 63:97f481e33cb2 589 ret = pico_ipv4_nat_find(0, &priv_addr, priv_port, proto);
tass 63:97f481e33cb2 590 if (ret >= 0) {
tass 63:97f481e33cb2 591 // Key is available in table
tass 63:97f481e33cb2 592 nk = pico_ipv4_nat_find_key(0, &priv_addr, priv_port, proto);
tass 63:97f481e33cb2 593 } else {
tass 63:97f481e33cb2 594 nat_dbg("NAT: key not found in NAT table -> generate key\n");
tass 63:97f481e33cb2 595 pico_ipv4_nat_generate_key(nk, f, pub_addr);
tass 63:97f481e33cb2 596 }
tass 63:97f481e33cb2 597 pico_ipv4_nat_snif_backward(nk,f);
tass 63:97f481e33cb2 598 nat_dbg("NAT: forward translation {src.addr, sport}: {%08X,%u} ->", net_hdr->src.addr, short_be(((struct pico_trans *)f->transport_hdr)->sport));
tass 63:97f481e33cb2 599 pico_ipv4_nat_translate(nk, f); /* our OUT definition */
tass 63:97f481e33cb2 600 nat_dbg(" {%08X,%u}\n", net_hdr->src.addr, short_be(((struct pico_trans *)f->transport_hdr)->sport));
tass 63:97f481e33cb2 601 }
daniele 3:b4047e8a0123 602 return 0;
daniele 3:b4047e8a0123 603 }
daniele 3:b4047e8a0123 604
tass 63:97f481e33cb2 605
daniele 3:b4047e8a0123 606 int pico_ipv4_nat_enable(struct pico_ipv4_link *link)
daniele 3:b4047e8a0123 607 {
daniele 3:b4047e8a0123 608 if (link == NULL) {
daniele 3:b4047e8a0123 609 pico_err = PICO_ERR_EINVAL;
daniele 3:b4047e8a0123 610 return -1;
daniele 3:b4047e8a0123 611 }
daniele 3:b4047e8a0123 612
tass 63:97f481e33cb2 613 pub_link = *link;
tass 63:97f481e33cb2 614 pico_timer_add(NAT_TCP_TIMEWAIT, pico_ipv4_nat_table_cleanup, NULL);
tass 63:97f481e33cb2 615 enable_nat_flag = 1;
daniele 3:b4047e8a0123 616 return 0;
daniele 3:b4047e8a0123 617 }
daniele 3:b4047e8a0123 618
daniele 3:b4047e8a0123 619 int pico_ipv4_nat_disable(void)
daniele 3:b4047e8a0123 620 {
tass 63:97f481e33cb2 621 pub_link.address.addr = 0;
tass 63:97f481e33cb2 622 enable_nat_flag = 0;
daniele 3:b4047e8a0123 623 return 0;
daniele 3:b4047e8a0123 624 }
daniele 3:b4047e8a0123 625
tass 63:97f481e33cb2 626
tass 63:97f481e33cb2 627 int pico_ipv4_nat_isenabled_out(struct pico_ipv4_link *link)
daniele 3:b4047e8a0123 628 {
tass 63:97f481e33cb2 629 if (enable_nat_flag) {
tass 63:97f481e33cb2 630 // is pub_link = *link
tass 63:97f481e33cb2 631 if (pub_link.address.addr == link->address.addr)
tass 63:97f481e33cb2 632 return 0;
tass 63:97f481e33cb2 633 else
tass 63:97f481e33cb2 634 return -1;
tass 63:97f481e33cb2 635 } else {
tass 63:97f481e33cb2 636 return -1;
tass 63:97f481e33cb2 637 }
daniele 3:b4047e8a0123 638 }
daniele 3:b4047e8a0123 639
tass 63:97f481e33cb2 640
tass 63:97f481e33cb2 641 int pico_ipv4_nat_isenabled_in(struct pico_frame *f)
tass 63:97f481e33cb2 642 {
tass 63:97f481e33cb2 643 if (enable_nat_flag) {
tass 63:97f481e33cb2 644 struct pico_tcp_hdr *tcp_hdr = NULL;
tass 63:97f481e33cb2 645 struct pico_udp_hdr *udp_hdr = NULL;
tass 63:97f481e33cb2 646 uint16_t pub_port = 0;
tass 63:97f481e33cb2 647 int ret;
tass 63:97f481e33cb2 648 uint8_t proto;
tass 63:97f481e33cb2 649
tass 63:97f481e33cb2 650 struct pico_ipv4_hdr *ipv4_hdr = (struct pico_ipv4_hdr *) f->net_hdr;
tass 63:97f481e33cb2 651 if (!ipv4_hdr)
tass 63:97f481e33cb2 652 return -1;
tass 63:97f481e33cb2 653 proto = ipv4_hdr->proto;
tass 63:97f481e33cb2 654
tass 63:97f481e33cb2 655 if (proto == PICO_PROTO_TCP) {
tass 63:97f481e33cb2 656 tcp_hdr = (struct pico_tcp_hdr *) f->transport_hdr;
tass 63:97f481e33cb2 657 if (!tcp_hdr)
tass 63:97f481e33cb2 658 return -1;
tass 63:97f481e33cb2 659 pub_port= tcp_hdr->trans.dport;
tass 63:97f481e33cb2 660 } else if (proto == PICO_PROTO_UDP) {
tass 63:97f481e33cb2 661 udp_hdr = (struct pico_udp_hdr *) f->transport_hdr;
tass 63:97f481e33cb2 662 if (!udp_hdr)
tass 63:97f481e33cb2 663 return -1;
tass 63:97f481e33cb2 664 pub_port= udp_hdr->trans.dport;
tass 63:97f481e33cb2 665 } else if (proto == PICO_PROTO_ICMP4) {
tass 63:97f481e33cb2 666 //icmp_hdr = (struct pico_icmp4_hdr *) f->transport_hdr;
tass 63:97f481e33cb2 667 //if (!icmp_hdr)
tass 63:97f481e33cb2 668 // return -1;
tass 63:97f481e33cb2 669 /* XXX PRELIMINARY ONLY LAST 16 BITS OF IP */
tass 63:97f481e33cb2 670 pub_port = (uint16_t)(ipv4_hdr->src.addr & 0x00FF);
tass 63:97f481e33cb2 671 }
tass 63:97f481e33cb2 672 ret = pico_ipv4_nat_find(pub_port, NULL, 0, proto);
tass 63:97f481e33cb2 673 if (ret == 0)
tass 63:97f481e33cb2 674 return 0;
tass 63:97f481e33cb2 675 else
tass 63:97f481e33cb2 676 return -1;
tass 63:97f481e33cb2 677 } else {
tass 63:97f481e33cb2 678 return -1;
tass 63:97f481e33cb2 679 }
tass 63:97f481e33cb2 680 }
daniele 3:b4047e8a0123 681 #endif
daniele 3:b4047e8a0123 682 #endif
tass 63:97f481e33cb2 683