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

Fork of PicoTCP by Daniele Lacamera

Committer:
daniele
Date:
Sat Aug 03 08:50:27 2013 +0000
Revision:
51:18637a3d071f
Parent:
3:b4047e8a0123
Branch for CDC-ECM: Work in progress

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