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

Fork of PicoTCP by Daniele Lacamera

Committer:
tass
Date:
Fri May 17 12:09:59 2013 +0000
Revision:
1:cfe8984a32b4
Parent:
libraries/picotcp/modules/pico_nat.c@0:d7f2341ab245
Update for smaller SOCKETQ

Who changed what in which revision?

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