Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of PicoTCP by
pico_nat.c
00001 /********************************************************************* 00002 PicoTCP. Copyright (c) 2012 TASS Belgium NV. Some rights reserved. 00003 See LICENSE and COPYING for usage. 00004 00005 . 00006 00007 Authors: Kristof Roelants, Brecht Van Cauwenberghe, 00008 Simon Maes, Philippe Mariman 00009 *********************************************************************/ 00010 00011 #include "pico_stack.h" 00012 #include "pico_frame.h" 00013 #include "pico_tcp.h" 00014 #include "pico_udp.h" 00015 #include "pico_ipv4.h" 00016 #include "pico_addressing.h" 00017 #include "pico_nat.h" 00018 00019 00020 #ifdef PICO_SUPPORT_IPV4 00021 #ifdef PICO_SUPPORT_NAT 00022 00023 #define nat_dbg(...) do{}while(0) 00024 //#define nat_dbg dbg 00025 #define NAT_TCP_TIMEWAIT 240000 /* 4mins (in msec) */ 00026 //#define NAT_TCP_TIMEWAIT 10000 /* 10 sec (in msec) - for testing purposes only*/ 00027 00028 00029 struct pico_nat_key { 00030 struct pico_ip4 pub_addr; 00031 uint16_t pub_port; 00032 struct pico_ip4 priv_addr; 00033 uint16_t priv_port; 00034 uint8_t proto; 00035 /* 00036 del_flags: 00037 1 0 00038 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 00039 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 00040 |F|B|S|R|P|~| CONNECTION ACTIVE | 00041 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 00042 00043 F: FIN from Forwarding packet 00044 B: FIN from Backwarding packet 00045 S: SYN 00046 R: RST 00047 P: Persistant 00048 00049 */ 00050 uint16_t del_flags; 00051 /* Connector for trees */ 00052 }; 00053 00054 static struct pico_ipv4_link pub_link; 00055 static uint8_t enable_nat_flag = 0; 00056 00057 static int nat_cmp_backward(void * ka, void * kb) 00058 { 00059 struct pico_nat_key *a = ka, *b = kb; 00060 if (a->pub_port < b->pub_port) { 00061 return -1; 00062 } 00063 else if (a->pub_port > b->pub_port) { 00064 return 1; 00065 } 00066 else { 00067 if (a->proto < b->proto) { 00068 return -1; 00069 } 00070 else if (a->proto > b->proto) { 00071 return 1; 00072 } 00073 else { 00074 /* a and b are identical */ 00075 return 0; 00076 } 00077 } 00078 } 00079 00080 static int nat_cmp_forward(void * ka, void * kb) 00081 { 00082 struct pico_nat_key *a =ka, *b = kb; 00083 if (a->priv_addr.addr < b->priv_addr.addr) { 00084 return -1; 00085 } 00086 else if (a->priv_addr.addr > b->priv_addr.addr) { 00087 return 1; 00088 } 00089 else { 00090 if (a->priv_port < b->priv_port) { 00091 return -1; 00092 } 00093 else if (a->priv_port > b->priv_port) { 00094 return 1; 00095 } 00096 else { 00097 if (a->proto < b->proto) { 00098 return -1; 00099 } 00100 else if (a->proto > b->proto) { 00101 return 1; 00102 } 00103 else { 00104 /* a and b are identical */ 00105 return 0; 00106 } 00107 } 00108 } 00109 } 00110 00111 PICO_TREE_DECLARE(KEYTable_forward,nat_cmp_forward); 00112 PICO_TREE_DECLARE(KEYTable_backward,nat_cmp_backward); 00113 00114 /* 00115 2 options: 00116 find on proto and pub_port 00117 find on priv_addr, priv_port and proto 00118 zero the unused parameters 00119 */ 00120 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) 00121 { 00122 struct pico_nat_key test; 00123 test.pub_port = pub_port; 00124 test.priv_port = priv_port; 00125 test.proto = proto; 00126 if (priv_addr) 00127 test.priv_addr = *priv_addr; 00128 else 00129 test.priv_addr.addr = 0; 00130 00131 /* returns NULL if test can not be found */ 00132 if (!pub_port) 00133 return pico_tree_findKey(&KEYTable_forward,&test); 00134 else 00135 return pico_tree_findKey(&KEYTable_backward, &test); 00136 } 00137 00138 int pico_ipv4_nat_find(uint16_t pub_port, struct pico_ip4 *priv_addr, uint16_t priv_port, uint8_t proto) 00139 { 00140 struct pico_nat_key *k = NULL; 00141 00142 k = pico_ipv4_nat_find_key(pub_port, priv_addr, priv_port, proto); 00143 if (k) 00144 return 0; 00145 else 00146 return -1; 00147 } 00148 00149 int pico_ipv4_nat_snif_forward(struct pico_nat_key *nk, struct pico_frame *f) 00150 { 00151 uint8_t proto; 00152 struct pico_ipv4_hdr *ipv4_hdr = (struct pico_ipv4_hdr *)f->net_hdr; 00153 struct pico_tcp_hdr *tcp_hdr; 00154 00155 if (!ipv4_hdr) 00156 return -1; 00157 proto = ipv4_hdr->proto; 00158 00159 if (proto == PICO_PROTO_TCP) { 00160 tcp_hdr = (struct pico_tcp_hdr *) f->transport_hdr; 00161 if (!tcp_hdr) 00162 return -1; 00163 if (tcp_hdr->flags & PICO_TCP_FIN) { 00164 nk->del_flags |= PICO_DEL_FLAGS_FIN_FORWARD; //FIN from forwarding packet 00165 } 00166 if (tcp_hdr->flags & PICO_TCP_SYN) { 00167 nk->del_flags |= PICO_DEL_FLAGS_SYN; 00168 } 00169 if (tcp_hdr->flags & PICO_TCP_RST) { 00170 nk->del_flags |= PICO_DEL_FLAGS_RST; 00171 } 00172 } else if (proto == PICO_PROTO_UDP) { 00173 /* set conn active to 1 */ 00174 nk->del_flags &= 0xFE00; 00175 nk->del_flags++; 00176 } 00177 return 0; 00178 } 00179 00180 00181 int pico_ipv4_nat_snif_backward(struct pico_nat_key *nk, struct pico_frame *f) 00182 { 00183 uint8_t proto; 00184 struct pico_ipv4_hdr *ipv4_hdr = (struct pico_ipv4_hdr *)f->net_hdr; 00185 struct pico_tcp_hdr *tcp_hdr; 00186 00187 if (!ipv4_hdr) 00188 return -1; 00189 proto = ipv4_hdr->proto; 00190 00191 if (proto == PICO_PROTO_TCP) { 00192 tcp_hdr = (struct pico_tcp_hdr *) f->transport_hdr; 00193 if (!tcp_hdr) 00194 return -1; 00195 if (tcp_hdr->flags & PICO_TCP_FIN) { 00196 nk->del_flags |= PICO_DEL_FLAGS_FIN_BACKWARD; //FIN from backwarding packet 00197 } 00198 if (tcp_hdr->flags & PICO_TCP_SYN) { 00199 nk->del_flags |= PICO_DEL_FLAGS_SYN; 00200 } 00201 if (tcp_hdr->flags & PICO_TCP_RST) { 00202 nk->del_flags |= PICO_DEL_FLAGS_RST; 00203 } 00204 } else if (proto == PICO_PROTO_UDP) { 00205 /* set conn active to 1 */ 00206 nk->del_flags &= 0xFE00; 00207 nk->del_flags++; 00208 } 00209 return 0; 00210 } 00211 00212 void pico_ipv4_nat_table_cleanup(unsigned long now, void *_unused) 00213 { 00214 struct pico_tree_node * idx, * safe; 00215 struct pico_nat_key *k = NULL; 00216 nat_dbg("NAT: before table cleanup:\n"); 00217 pico_ipv4_nat_print_table(); 00218 00219 //struct pico_nat_key *tmp; 00220 pico_tree_foreach_reverse_safe(idx,&KEYTable_forward,safe){ 00221 k = idx->keyValue; 00222 switch (k->proto) 00223 { 00224 case PICO_PROTO_TCP: 00225 if ((k->del_flags & 0x0800) >> 11) { 00226 /* entry is persistant */ 00227 break; 00228 } 00229 else if ((k->del_flags & 0x01FF) == 0) { 00230 /* conn active is zero, delete entry */ 00231 pico_ipv4_nat_del(k->pub_port, k->proto); 00232 } 00233 else if ((k->del_flags & 0x1000) >> 12) { 00234 /* RST flag set, set conn active to zero */ 00235 k->del_flags &= 0xFE00; 00236 } 00237 else if (((k->del_flags & 0x8000) >> 15) && ((k->del_flags & 0x4000) >> 14)) { 00238 /* FIN1 and FIN2 set, set conn active to zero */ 00239 k->del_flags &= 0xFE00; 00240 } 00241 else if ((k->del_flags & 0x01FF) > 360) { 00242 /* conn is active for 24 hours, delete entry */ 00243 pico_ipv4_nat_del(k->pub_port, k->proto); 00244 } 00245 else { 00246 k->del_flags++; 00247 } 00248 break; 00249 00250 case PICO_PROTO_UDP: 00251 if ((k->del_flags & 0x0800) >> 11) { 00252 /* entry is persistant */ 00253 break; 00254 } 00255 else if ((k->del_flags & 0x01FF) > 1) { 00256 /* Delete entry when it has existed NAT_TCP_TIMEWAIT */ 00257 pico_ipv4_nat_del(k->pub_port, k->proto); 00258 } 00259 else { 00260 k->del_flags++; 00261 } 00262 break; 00263 00264 default: 00265 /* Unknown protocol in NAT table, delete when it has existed NAT_TCP_TIMEWAIT */ 00266 if ((k->del_flags & 0x01FF) > 1) { 00267 pico_ipv4_nat_del(k->pub_port, k->proto); 00268 } 00269 else { 00270 k->del_flags++; 00271 } 00272 } 00273 } 00274 00275 nat_dbg("NAT: after table cleanup:\n"); 00276 pico_ipv4_nat_print_table(); 00277 pico_timer_add(NAT_TCP_TIMEWAIT, pico_ipv4_nat_table_cleanup, NULL); 00278 } 00279 00280 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) 00281 { 00282 struct pico_nat_key *key = pico_zalloc(sizeof(struct pico_nat_key)); 00283 if (!key) { 00284 pico_err = PICO_ERR_ENOMEM; 00285 return -1; 00286 } 00287 00288 key->pub_addr = pub_addr; 00289 key->pub_port = pub_port; 00290 key->priv_addr = priv_addr; 00291 key->priv_port = priv_port; 00292 key->proto = proto; 00293 key->del_flags = 0x0001; /* set conn active to 1, other flags to 0 */ 00294 00295 /* RB_INSERT returns NULL when element added, pointer to the element if already in tree */ 00296 if(!pico_tree_insert(&KEYTable_forward, key) && !pico_tree_insert(&KEYTable_backward, key)){ 00297 return 0; /* New element added */ 00298 } 00299 else { 00300 pico_free(key); 00301 pico_err = PICO_ERR_EINVAL; 00302 return -1; /* Element key already exists */ 00303 } 00304 } 00305 00306 00307 int pico_ipv4_nat_del(uint16_t pub_port, uint8_t proto) 00308 { 00309 struct pico_nat_key *key = NULL; 00310 key = pico_ipv4_nat_find_key(pub_port, NULL, 0, proto); 00311 if (!key) { 00312 nat_dbg("NAT: key to delete not found: proto %u | pub_port %u\n", proto, pub_port); 00313 return -1; 00314 } 00315 else { 00316 nat_dbg("NAT: key to delete found: proto %u | pub_port %u\n", proto, pub_port); 00317 /* RB_REMOVE returns pointer to removed element, NULL to indicate error */ 00318 if(pico_tree_delete(&KEYTable_forward, key) && pico_tree_delete(&KEYTable_backward, key)) 00319 pico_free(key); 00320 else 00321 return -1; /* Error on removing element, do not free! */ 00322 } 00323 return 0; 00324 } 00325 00326 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) 00327 { 00328 struct pico_nat_key *key = NULL; 00329 00330 switch (persistant) 00331 { 00332 case PICO_IPV4_FORWARD_ADD: 00333 if (pico_ipv4_nat_add(pub_addr, pub_port, priv_addr, priv_port, proto) != 0) 00334 return -1; /* pico_err set in nat_add */ 00335 key = pico_ipv4_nat_find_key(pub_port, &priv_addr, priv_port, proto); 00336 if (!key) { 00337 pico_err = PICO_ERR_EAGAIN; 00338 return -1; 00339 } 00340 key->del_flags = (key->del_flags & ~(0x1 << 11)) | (persistant << 11); 00341 break; 00342 00343 case PICO_IPV4_FORWARD_DEL: 00344 return pico_ipv4_nat_del(pub_port, proto); 00345 00346 default: 00347 pico_err = PICO_ERR_EINVAL; 00348 return -1; 00349 } 00350 pico_ipv4_nat_print_table(); 00351 return 0; 00352 } 00353 00354 00355 void pico_ipv4_nat_print_table(void) 00356 { 00357 struct pico_nat_key __attribute__((unused)) *k = NULL ; 00358 struct pico_tree_node * index; 00359 uint16_t i = 0; 00360 00361 nat_dbg("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"); 00362 nat_dbg("+ NAT table +\n"); 00363 nat_dbg("+-----------------------------------------------------------------------------------------------------------------------+\n"); 00364 nat_dbg("+ pointer | private_addr | private_port | proto | pub_addr | pub_port | conn active | FIN1 | FIN2 | SYN | RST | PERS +\n"); 00365 nat_dbg("+-----------------------------------------------------------------------------------------------------------------------+\n"); 00366 00367 pico_tree_foreach(index,&KEYTable_forward){ 00368 k = index->keyValue; 00369 nat_dbg("+ %10p | %08X | %05u | %04u | %08X | %05u | %03u | %u | %u | %u | %u | %u +\n", 00370 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, 00371 ((k->del_flags)&0x4000)>>14, ((k->del_flags)&0x2000)>>13, ((k->del_flags)&0x1000)>>12, ((k->del_flags)&0x0800)>>11); 00372 i++; 00373 } 00374 nat_dbg("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"); 00375 } 00376 00377 int pico_ipv4_nat_generate_key(struct pico_nat_key* nk, struct pico_frame* f, struct pico_ip4 pub_addr) 00378 { 00379 uint16_t pub_port = 0; 00380 uint8_t proto; 00381 struct pico_tcp_hdr *tcp_hdr = NULL; /* forced to use pico_trans */ 00382 struct pico_udp_hdr *udp_hdr = NULL; /* forced to use pico_trans */ 00383 struct pico_ipv4_hdr *ipv4_hdr = (struct pico_ipv4_hdr *)f->net_hdr; 00384 if (!ipv4_hdr) 00385 return -1; 00386 proto = ipv4_hdr->proto; 00387 do { 00388 /* 1. generate valid new NAT port entry */ 00389 uint32_t rand = pico_rand(); 00390 pub_port = (uint16_t) (rand & 0xFFFFU); 00391 pub_port = (uint16_t)(pub_port % (65535 - 1024)) + 1024U; 00392 pub_port = short_be(pub_port); 00393 00394 /* 2. check if already in table, if no exit */ 00395 nat_dbg("NAT: check if generated port %u is free\n", short_be(pub_port)); 00396 if (pico_is_port_free(proto, pub_port, NULL, &pico_proto_ipv4)) 00397 break; 00398 00399 } while (1); 00400 nat_dbg("NAT: port %u is free\n", short_be(pub_port)); 00401 00402 if (proto == PICO_PROTO_TCP) { 00403 tcp_hdr = (struct pico_tcp_hdr *) f->transport_hdr; 00404 if (!tcp_hdr) 00405 return -1; 00406 nk->priv_port = tcp_hdr->trans.sport; 00407 } else if (proto == PICO_PROTO_UDP) { 00408 udp_hdr = (struct pico_udp_hdr *) f->transport_hdr; 00409 if (!udp_hdr) 00410 return -1; 00411 nk->priv_port = udp_hdr->trans.sport; 00412 } else if (proto == PICO_PROTO_ICMP4) { 00413 nk->priv_port = (uint16_t)(ipv4_hdr->src.addr & 0x00FF); 00414 pub_port = (uint16_t)(ipv4_hdr->dst.addr & 0x00FF); 00415 if (!pico_is_port_free(proto, pub_port, NULL, &pico_proto_ipv4)) 00416 return -1; 00417 } 00418 00419 nk->pub_addr = pub_addr; /* get public ip address from device */ 00420 nk->pub_port = pub_port; 00421 nk->priv_addr = ipv4_hdr->src; 00422 nk->proto = ipv4_hdr->proto; 00423 nk->del_flags = 0x0001; /* set conn active to 1 */ 00424 if (pico_ipv4_nat_add(nk->pub_addr, nk->pub_port, nk->priv_addr, nk->priv_port, nk->proto) < 0) { 00425 return -1; 00426 } else { 00427 return 0; 00428 } 00429 } 00430 00431 00432 static int pico_nat_tcp_checksum(struct pico_frame *f) 00433 { 00434 struct pico_tcp_hdr *trans_hdr = (struct pico_tcp_hdr *) f->transport_hdr; 00435 struct pico_ipv4_hdr *net_hdr = (struct pico_ipv4_hdr *) f->net_hdr; 00436 00437 struct tcp_pseudo_hdr_ipv4 pseudo; 00438 if (!trans_hdr || !net_hdr) 00439 return -1; 00440 00441 pseudo.src.addr = net_hdr->src.addr; 00442 pseudo.dst.addr = net_hdr->dst.addr; 00443 pseudo.res = 0; 00444 pseudo.proto = PICO_PROTO_TCP; 00445 pseudo.tcp_len = short_be(f->transport_len); 00446 00447 trans_hdr->crc = 0; 00448 trans_hdr->crc = pico_dualbuffer_checksum(&pseudo, sizeof(struct tcp_pseudo_hdr_ipv4), trans_hdr, f->transport_len); 00449 trans_hdr->crc = short_be(trans_hdr->crc); 00450 return 0; 00451 } 00452 00453 00454 int pico_ipv4_nat_translate(struct pico_nat_key* nk, struct pico_frame* f) 00455 { 00456 uint8_t proto; 00457 struct pico_tcp_hdr *tcp_hdr = NULL; /* forced to use pico_trans */ 00458 struct pico_udp_hdr *udp_hdr = NULL; /* forced to use pico_trans */ 00459 00460 struct pico_ipv4_hdr* ipv4_hdr = (struct pico_ipv4_hdr *)f->net_hdr; 00461 if (!ipv4_hdr) 00462 return -1; 00463 proto = ipv4_hdr->proto; 00464 00465 if (proto == PICO_PROTO_TCP) { 00466 tcp_hdr = (struct pico_tcp_hdr *) f->transport_hdr; 00467 if (!tcp_hdr) 00468 return -1; 00469 tcp_hdr->trans.sport = nk->pub_port; 00470 } else if (proto == PICO_PROTO_UDP) { 00471 udp_hdr = (struct pico_udp_hdr *) f->transport_hdr; 00472 if (!udp_hdr) 00473 return -1; 00474 udp_hdr->trans.sport = nk->pub_port; 00475 } 00476 00477 //if(f->proto == PICO_PROTO_ICMP){ 00478 //} XXX no action 00479 00480 ipv4_hdr->src = nk->pub_addr; 00481 00482 if (proto == PICO_PROTO_TCP) { 00483 pico_nat_tcp_checksum(f); 00484 } else if (proto == PICO_PROTO_UDP){ 00485 udp_hdr->crc = 0; 00486 udp_hdr->crc = short_be(pico_udp_checksum_ipv4(f)); 00487 } 00488 00489 // pico_ipv4_checksum(f); 00490 ipv4_hdr->crc = 0; 00491 ipv4_hdr->crc = short_be(pico_checksum(ipv4_hdr, f->net_len)); 00492 00493 return 0; 00494 } 00495 00496 00497 int pico_ipv4_nat_port_forward(struct pico_frame* f) 00498 { 00499 struct pico_nat_key *nk = NULL; 00500 struct pico_tcp_hdr *tcp_hdr = NULL; 00501 struct pico_udp_hdr *udp_hdr = NULL; 00502 struct pico_icmp4_hdr *icmp_hdr = NULL; 00503 struct pico_ipv4_hdr* ipv4_hdr; 00504 uint16_t pub_port = 0; 00505 uint8_t proto; 00506 00507 ipv4_hdr = (struct pico_ipv4_hdr *)f->net_hdr; 00508 if (!ipv4_hdr) 00509 return -1; 00510 proto = ipv4_hdr->proto; 00511 00512 if (proto == PICO_PROTO_TCP) { 00513 tcp_hdr = (struct pico_tcp_hdr *) f->transport_hdr; 00514 if (!tcp_hdr) 00515 return -1; 00516 pub_port = tcp_hdr->trans.dport; 00517 } else if (proto == PICO_PROTO_UDP) { 00518 udp_hdr = (struct pico_udp_hdr *) f->transport_hdr; 00519 if (!udp_hdr) 00520 return -1; 00521 pub_port = udp_hdr->trans.dport; 00522 } else if (proto == PICO_PROTO_ICMP4) { 00523 icmp_hdr = (struct pico_icmp4_hdr *) f->transport_hdr; 00524 if (!icmp_hdr) 00525 return -1; 00526 /* XXX PRELIMINARY ONLY LAST 16 BITS OF IP */ 00527 pub_port = (uint16_t)(ipv4_hdr->src.addr & 0x00FF); 00528 } 00529 00530 nk = pico_ipv4_nat_find_key(pub_port, 0, 0, proto); 00531 00532 if (!nk) { 00533 nat_dbg("\nNAT: ERROR key not found in table\n"); 00534 return -1; 00535 } else { 00536 pico_ipv4_nat_snif_forward(nk,f); 00537 ipv4_hdr->dst.addr = nk->priv_addr.addr; 00538 00539 if (proto == PICO_PROTO_TCP) { 00540 tcp_hdr->trans.dport = nk->priv_port; 00541 pico_nat_tcp_checksum(f); 00542 } else if (proto == PICO_PROTO_UDP) { 00543 udp_hdr->trans.dport = nk->priv_port; 00544 udp_hdr->crc = 0; 00545 udp_hdr->crc = short_be(pico_udp_checksum_ipv4(f)); 00546 } 00547 } 00548 00549 ipv4_hdr->crc = 0; 00550 ipv4_hdr->crc = short_be(pico_checksum(ipv4_hdr, f->net_len)); 00551 00552 return 0; 00553 } 00554 00555 00556 00557 int pico_ipv4_nat(struct pico_frame *f, struct pico_ip4 pub_addr) 00558 { 00559 /*do nat---------*/ 00560 struct pico_nat_key *nk = NULL; 00561 struct pico_nat_key key; 00562 struct pico_ipv4_hdr *net_hdr = (struct pico_ipv4_hdr *) f->net_hdr; 00563 struct pico_tcp_hdr *tcp_hdr = NULL; 00564 struct pico_udp_hdr *udp_hdr = NULL; 00565 int ret; 00566 uint8_t proto = net_hdr->proto; 00567 uint16_t priv_port = 0; 00568 struct pico_ip4 priv_addr= net_hdr->src; 00569 00570 nk= &key; 00571 00572 /* TODO DELME check if IN */ 00573 if (pub_addr.addr == net_hdr->dst.addr) { 00574 nat_dbg("NAT: backward translation {dst.addr, dport}: {%08X,%u} ->", net_hdr->dst.addr, ((struct pico_trans *)f->transport_hdr)->dport); 00575 ret = pico_ipv4_nat_port_forward(f); /* our IN definition */ 00576 nat_dbg(" {%08X,%u}\n", net_hdr->dst.addr, short_be(((struct pico_trans *)f->transport_hdr)->dport)); 00577 } else { 00578 if (net_hdr->proto == PICO_PROTO_TCP) { 00579 tcp_hdr = (struct pico_tcp_hdr *) f->transport_hdr; 00580 priv_port = tcp_hdr->trans.sport; 00581 } else if (net_hdr->proto == PICO_PROTO_UDP) { 00582 udp_hdr = (struct pico_udp_hdr *) f->transport_hdr; 00583 priv_port = udp_hdr->trans.sport; 00584 } else if (net_hdr->proto == PICO_PROTO_ICMP4) { 00585 //udp_hdr = (struct pico_udp_hdr *) f->transport_hdr; 00586 priv_port = (uint16_t)(net_hdr->src.addr & 0x00FF); 00587 } 00588 00589 ret = pico_ipv4_nat_find(0, &priv_addr, priv_port, proto); 00590 if (ret >= 0) { 00591 // Key is available in table 00592 nk = pico_ipv4_nat_find_key(0, &priv_addr, priv_port, proto); 00593 } else { 00594 nat_dbg("NAT: key not found in NAT table -> generate key\n"); 00595 pico_ipv4_nat_generate_key(nk, f, pub_addr); 00596 } 00597 pico_ipv4_nat_snif_backward(nk,f); 00598 nat_dbg("NAT: forward translation {src.addr, sport}: {%08X,%u} ->", net_hdr->src.addr, short_be(((struct pico_trans *)f->transport_hdr)->sport)); 00599 pico_ipv4_nat_translate(nk, f); /* our OUT definition */ 00600 nat_dbg(" {%08X,%u}\n", net_hdr->src.addr, short_be(((struct pico_trans *)f->transport_hdr)->sport)); 00601 } 00602 return 0; 00603 } 00604 00605 00606 int pico_ipv4_nat_enable(struct pico_ipv4_link *link) 00607 { 00608 if (link == NULL) { 00609 pico_err = PICO_ERR_EINVAL; 00610 return -1; 00611 } 00612 00613 pub_link = *link; 00614 pico_timer_add(NAT_TCP_TIMEWAIT, pico_ipv4_nat_table_cleanup, NULL); 00615 enable_nat_flag = 1; 00616 return 0; 00617 } 00618 00619 int pico_ipv4_nat_disable(void) 00620 { 00621 pub_link.address.addr = 0; 00622 enable_nat_flag = 0; 00623 return 0; 00624 } 00625 00626 00627 int pico_ipv4_nat_isenabled_out(struct pico_ipv4_link *link) 00628 { 00629 if (enable_nat_flag) { 00630 // is pub_link = *link 00631 if (pub_link.address.addr == link->address.addr) 00632 return 0; 00633 else 00634 return -1; 00635 } else { 00636 return -1; 00637 } 00638 } 00639 00640 00641 int pico_ipv4_nat_isenabled_in(struct pico_frame *f) 00642 { 00643 if (enable_nat_flag) { 00644 struct pico_tcp_hdr *tcp_hdr = NULL; 00645 struct pico_udp_hdr *udp_hdr = NULL; 00646 uint16_t pub_port = 0; 00647 int ret; 00648 uint8_t proto; 00649 00650 struct pico_ipv4_hdr *ipv4_hdr = (struct pico_ipv4_hdr *) f->net_hdr; 00651 if (!ipv4_hdr) 00652 return -1; 00653 proto = ipv4_hdr->proto; 00654 00655 if (proto == PICO_PROTO_TCP) { 00656 tcp_hdr = (struct pico_tcp_hdr *) f->transport_hdr; 00657 if (!tcp_hdr) 00658 return -1; 00659 pub_port= tcp_hdr->trans.dport; 00660 } else if (proto == PICO_PROTO_UDP) { 00661 udp_hdr = (struct pico_udp_hdr *) f->transport_hdr; 00662 if (!udp_hdr) 00663 return -1; 00664 pub_port= udp_hdr->trans.dport; 00665 } else if (proto == PICO_PROTO_ICMP4) { 00666 //icmp_hdr = (struct pico_icmp4_hdr *) f->transport_hdr; 00667 //if (!icmp_hdr) 00668 // return -1; 00669 /* XXX PRELIMINARY ONLY LAST 16 BITS OF IP */ 00670 pub_port = (uint16_t)(ipv4_hdr->src.addr & 0x00FF); 00671 } 00672 ret = pico_ipv4_nat_find(pub_port, NULL, 0, proto); 00673 if (ret == 0) 00674 return 0; 00675 else 00676 return -1; 00677 } else { 00678 return -1; 00679 } 00680 } 00681 #endif 00682 #endif 00683
Generated on Thu Jul 14 2022 08:24:59 by
1.7.2
