CDC/ECM driver for mbed, based on USBDevice by mbed-official. Uses PicoTCP to access Ethernet USB device. License: GPLv2

Dependents:   USBEthernet_TEST

Fork of USB_Ethernet by Daniele Lacamera

Committer:
daniele
Date:
Sat Aug 03 13:16:14 2013 +0000
Revision:
2:540f6e142d59
Moved to single package

Who changed what in which revision?

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