1 /** 2 * NAT - NAT implementation for lwIP supporting TCP/UDP and ICMP. 3 * Copyright (c) 2009 Christian Walter, ?Embedded Solutions, Vienna 2009. 4 * Copyright (c) 2010 lwIP project ;-) 5 * COPYRIGHT (C) 2015, RT-Thread Development Team 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without modification, 9 * are permitted provided that the following conditions are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright notice, 12 * this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright notice, 14 * this list of conditions and the following disclaimer in the documentation 15 * and/or other materials provided with the distribution. 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 20 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 22 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 24 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 27 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 28 * OF SUCH DAMAGE. 29 * 30 * Change Logs: 31 * Date Author Notes 32 * 2015-01-26 Hichard porting to RT-Thread 33 * 2015-01-27 Bernard code cleanup for lwIP in RT-Thread 34 */ 35 36 /* 37 * TODOS: 38 * - we should decide if we want to use static tables for NAT or a linked 39 * list. 40 * - we should allocate icmp ping id if multiple clients are sending 41 * ping requests. 42 * - maybe we could hash the identifiers for TCP, ICMP and UDP and use 43 * a single table structure. This would reduce the code amount although 44 * it will cost performance. 45 * - NAT code must check for broadcast addresses and NOT forward 46 * them. 47 * 48 * - netif_remove must notify NAT code when a NAT'ed interface is removed 49 * - allocate NAT entries from a new memp pool instead of the heap 50 * - let ttl be ticks, not seconds 51 * 52 * HOWTO USE: 53 * 54 * Shows how to create NAT between a PPP interface and an internal NIC. 55 * In this case the network 213.129.231.168/29 is nat'ed when packets 56 * are sent to the destination network 10.0.0.0/24 (untypical example - 57 * most users will have the other way around). 58 * 59 * Step 1) Execute when network interfaces are ready. 60 * 61 * new_nat_entry.out_if = (struct netif *)&PPP_IF; 62 * new_nat_entry.in_if = (struct netif *)&EMAC_if; 63 * IP4_ADDR(&new_nat_entry.source_net, 213, 129, 231, 168); 64 * IP4_ADDR(&new_nat_entry.source_netmask, 255, 255, 255, 248); 65 * IP4_ADDR(&new_nat_entry.dest_net, 10, 0, 0, 0); 66 * IP4_ADDR(&new_nat_entry.source_netmask, 255, 0, 0, 0); 67 * ip_nat_add(&new_nat_entry); 68 */ 69 70 #include "ipv4_nat.h" 71 #include "lwip/opt.h" 72 73 #ifdef LWIP_USING_NAT 74 75 #include "lwip/ip.h" 76 #include "lwip/inet.h" 77 #include "lwip/netif.h" 78 #include "lwip/ip_addr.h" 79 #include "lwip/icmp.h" 80 #include "lwip/tcp_impl.h" 81 #include "lwip/udp.h" 82 #include "lwip/mem.h" 83 #include "lwip/sys.h" 84 #include "lwip/timers.h" 85 #include "netif/etharp.h" 86 87 #include <limits.h> 88 #include <string.h> 89 90 /** Define this to enable debug output of this module */ 91 #ifndef LWIP_NAT_DEBUG 92 #define LWIP_NAT_DEBUG LWIP_DBG_OFF 93 #endif 94 95 #define LWIP_NAT_TTL_INFINITE (INT_MAX) 96 #define LWIP_NAT_DEFAULT_TTL_SECONDS (128) 97 #define LWIP_NAT_FORWARD_HEADER_SIZE_MIN (sizeof(struct eth_hdr)) 98 99 #define LWIP_NAT_DEFAULT_STATE_TABLES_ICMP (4) 100 #define LWIP_NAT_DEFAULT_STATE_TABLES_TCP (32) 101 #define LWIP_NAT_DEFAULT_STATE_TABLES_UDP (32) 102 103 #define LWIP_NAT_DEFAULT_TCP_SOURCE_PORT (40000) 104 #define LWIP_NAT_DEFAULT_UDP_SOURCE_PORT (40000) 105 106 #define IPNAT_ENTRY_RESET(x) do { \ 107 (x)->ttl = 0; \ 108 } while(0) 109 110 typedef struct ip_nat_conf 111 { 112 struct ip_nat_conf *next; 113 ip_nat_entry_t entry; 114 } ip_nat_conf_t; 115 116 typedef struct ip_nat_entry_common 117 { 118 s32_t ttl; /* @todo: do we really need this to be signed?? */ 119 ip_addr_t source; 120 ip_addr_t dest; 121 ip_nat_conf_t *cfg; 122 } ip_nat_entry_common_t; 123 124 typedef struct ip_nat_entries_icmp 125 { 126 ip_nat_entry_common_t common; 127 u16_t id; 128 u16_t seqno; 129 } ip_nat_entries_icmp_t; 130 131 typedef struct ip_nat_entries_tcp 132 { 133 ip_nat_entry_common_t common; 134 u16_t nport; 135 u16_t sport; 136 u16_t dport; 137 } ip_nat_entries_tcp_t; 138 139 typedef struct ip_nat_entries_udp 140 { 141 ip_nat_entry_common_t common; 142 u16_t nport; 143 u16_t sport; 144 u16_t dport; 145 } ip_nat_entries_udp_t; 146 147 typedef union u_nat_entry 148 { 149 ip_nat_entry_common_t *cmn; 150 ip_nat_entries_tcp_t *tcp; 151 ip_nat_entries_icmp_t *icmp; 152 ip_nat_entries_udp_t *udp; 153 } nat_entry_t; 154 155 static ip_nat_conf_t *ip_nat_cfg = NULL; 156 static ip_nat_entries_icmp_t ip_nat_icmp_table[LWIP_NAT_DEFAULT_STATE_TABLES_ICMP]; 157 static ip_nat_entries_tcp_t ip_nat_tcp_table[LWIP_NAT_DEFAULT_STATE_TABLES_TCP]; 158 static ip_nat_entries_udp_t ip_nat_udp_table[LWIP_NAT_DEFAULT_STATE_TABLES_UDP]; 159 160 /* ----------------------- Static functions (COMMON) --------------------*/ 161 static void ip_nat_chksum_adjust(u8_t *chksum, const u8_t *optr, s16_t olen, const u8_t *nptr, s16_t nlen); 162 static void ip_nat_cmn_init(ip_nat_conf_t *nat_config, const struct ip_hdr *iphdr, 163 ip_nat_entry_common_t *nat_entry); 164 static ip_nat_conf_t *ip_nat_shallnat(const struct ip_hdr *iphdr); 165 static void ip_nat_reset_state(ip_nat_conf_t *cfg); 166 167 /* ----------------------- Static functions (DEBUG) ---------------------*/ 168 #if defined(LWIP_DEBUG) && (LWIP_NAT_DEBUG & LWIP_DBG_ON) 169 static void ip_nat_dbg_dump(const char *msg, const struct ip_hdr *iphdr); 170 static void ip_nat_dbg_dump_ip(const ip_addr_t *addr); 171 static void ip_nat_dbg_dump_icmp_nat_entry(const char *msg, const ip_nat_entries_icmp_t *nat_entry); 172 static void ip_nat_dbg_dump_tcp_nat_entry(const char *msg, const ip_nat_entries_tcp_t *nat_entry); 173 static void ip_nat_dbg_dump_udp_nat_entry(const char *msg, const ip_nat_entries_udp_t *nat_entry); 174 static void ip_nat_dbg_dump_init(ip_nat_conf_t *ip_nat_cfg_new); 175 static void ip_nat_dbg_dump_remove(ip_nat_conf_t *cur); 176 #else /* defined(LWIP_DEBUG) && (LWIP_NAT_DEBUG & LWIP_DBG_ON) */ 177 #define ip_nat_dbg_dump(msg, iphdr) 178 #define ip_nat_dbg_dump_ip(addr) 179 #define ip_nat_dbg_dump_icmp_nat_entry(msg, nat_entry) 180 #define ip_nat_dbg_dump_tcp_nat_entry(msg, nat_entry) 181 #define ip_nat_dbg_dump_udp_nat_entry(msg, nat_entry) 182 #define ip_nat_dbg_dump_init(ip_nat_cfg_new) 183 #define ip_nat_dbg_dump_remove(cur) 184 #endif /* defined(LWIP_DEBUG) && (LWIP_NAT_DEBUG & LWIP_DBG_ON) */ 185 186 /* ----------------------- Static functions (TCP) -----------------------*/ 187 static ip_nat_entries_tcp_t *ip_nat_tcp_lookup_incoming(const struct ip_hdr *iphdr, const struct tcp_hdr *tcphdr); 188 static ip_nat_entries_tcp_t *ip_nat_tcp_lookup_outgoing(ip_nat_conf_t *nat_config, 189 const struct ip_hdr *iphdr, const struct tcp_hdr *tcphdr, 190 u8_t allocate); 191 192 /* ----------------------- Static functions (UDP) -----------------------*/ 193 static ip_nat_entries_udp_t *ip_nat_udp_lookup_incoming(const struct ip_hdr *iphdr, const struct udp_hdr *udphdr); 194 static ip_nat_entries_udp_t *ip_nat_udp_lookup_outgoing(ip_nat_conf_t *nat_config, 195 const struct ip_hdr *iphdr, const struct udp_hdr *udphdr, 196 u8_t allocate); 197 198 /** 199 * Timer callback function that calls ip_nat_tmr() and reschedules itself. 200 * 201 * @param arg unused argument 202 */ 203 static void 204 nat_timer(void *arg) 205 { 206 LWIP_UNUSED_ARG(arg); 207 LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: nat_timer()\n")); 208 209 ip_nat_tmr(); 210 sys_timeout(LWIP_NAT_TMR_INTERVAL_SEC * 1000, nat_timer, NULL); 211 } 212 213 /** Initialize this module */ 214 void 215 ip_nat_init(void) 216 { 217 int i; 218 extern void lwip_ip_input_set_hook(int (*hook)(struct pbuf *p, struct netif *inp)); 219 220 /* @todo: this can be omitted since we trust static variables 221 to be initialized to zero */ 222 for (i = 0; i < LWIP_NAT_DEFAULT_STATE_TABLES_ICMP; i++) { 223 IPNAT_ENTRY_RESET(&ip_nat_icmp_table[i].common); 224 } 225 for (i = 0; i < LWIP_NAT_DEFAULT_STATE_TABLES_TCP; i++) { 226 IPNAT_ENTRY_RESET(&ip_nat_tcp_table[i].common); 227 } 228 for (i = 0; i < LWIP_NAT_DEFAULT_STATE_TABLES_UDP; i++) { 229 IPNAT_ENTRY_RESET(&ip_nat_udp_table[i].common); 230 } 231 232 /* we must lock scheduler to protect following code */ 233 rt_enter_critical(); 234 235 /* add a lwip timer for NAT */ 236 sys_timeout(LWIP_NAT_TMR_INTERVAL_SEC * 1000, nat_timer, NULL); 237 238 /* un-protect */ 239 rt_exit_critical(); 240 } 241 242 /** Allocate a new ip_nat_conf_t item */ 243 static ip_nat_conf_t* 244 ip_nat_alloc(void) 245 { 246 ip_nat_conf_t *ret = (ip_nat_conf_t*)mem_malloc(sizeof(ip_nat_conf_t)); 247 return ret; 248 } 249 250 /** Free a removed ip_nat_conf_t item */ 251 static void 252 ip_nat_free(ip_nat_conf_t *item) 253 { 254 LWIP_ASSERT("item != NULL", item != NULL); 255 mem_free(item); 256 } 257 258 /** Add a new NAT entry 259 * 260 * @param new_entry pointer to a structure used to initialize the entry 261 * @return ERR_OK if succeeded 262 */ 263 err_t 264 ip_nat_add(const ip_nat_entry_t *new_entry) 265 { 266 err_t err = ERR_VAL; 267 ip_nat_conf_t *cur = ip_nat_cfg; 268 ip_nat_conf_t *ip_nat_cfg_new = ip_nat_alloc(); 269 LWIP_ASSERT("new_entry != NULL", new_entry != NULL); 270 271 if (ip_nat_cfg_new != NULL) { 272 SMEMCPY(&ip_nat_cfg_new->entry, new_entry, sizeof(ip_nat_entry_t)); 273 ip_nat_cfg_new->next = NULL; 274 275 ip_nat_dbg_dump_init(ip_nat_cfg_new); 276 277 if (ip_nat_cfg == NULL) { 278 ip_nat_cfg = ip_nat_cfg_new; 279 } else { 280 /* @todo: do we really need to enqueue the new entry at the end?? */ 281 while (cur->next != NULL) { 282 cur = cur->next; 283 } 284 cur->next = ip_nat_cfg_new; 285 } 286 err = ERR_OK; 287 } else { 288 err = ERR_MEM; 289 } 290 return err; 291 } 292 293 /** Remove a NAT entry previously added by 'ip_nat_add()'. 294 * 295 * @param remove_entry describes the entry to remove 296 */ 297 void 298 ip_nat_remove(const ip_nat_entry_t *remove_entry) 299 { 300 ip_nat_conf_t *cur = ip_nat_cfg; 301 ip_nat_conf_t *next; 302 ip_nat_conf_t *previous = NULL; 303 304 while (cur != NULL) { 305 /* Remove the NAT interfaces */ 306 if ((cur->entry.source_net.addr == remove_entry->source_net.addr) && 307 (cur->entry.source_netmask.addr == remove_entry->source_netmask.addr) && 308 (cur->entry.dest_net.addr == remove_entry->dest_net.addr) && 309 (cur->entry.dest_netmask.addr == remove_entry->dest_netmask.addr) && 310 (cur->entry.out_if == remove_entry->out_if) && 311 (cur->entry.in_if == remove_entry->in_if)) 312 { 313 ip_nat_dbg_dump_remove(cur); 314 315 ip_nat_reset_state(cur); 316 next = cur->next; 317 if (cur == ip_nat_cfg) { 318 ip_nat_cfg = next; 319 } else { 320 LWIP_ASSERT("NULL != previous", NULL != previous); 321 previous->next = next; 322 } 323 /* free 'cur' or there will be a memory leak */ 324 ip_nat_free(cur); 325 return; 326 } else { 327 previous = cur; 328 cur = cur->next; 329 } 330 } 331 } 332 333 /** Reset a NAT configured entry to be reused. 334 * Effectively calls IPNAT_ENTRY_RESET() on 'cfg'. 335 * 336 * @param cfg NAT entry to reset 337 */ 338 static void 339 ip_nat_reset_state(ip_nat_conf_t *cfg) 340 { 341 int i; 342 343 /* @todo: optimize this!!! 344 why do we search for it anyway, if we have the pointer??? */ 345 for (i = 0; i < LWIP_NAT_DEFAULT_STATE_TABLES_ICMP; i++) { 346 if(ip_nat_icmp_table[i].common.cfg == cfg) { 347 IPNAT_ENTRY_RESET(&ip_nat_icmp_table[i].common); 348 } 349 } 350 for (i = 0; i < LWIP_NAT_DEFAULT_STATE_TABLES_TCP; i++) { 351 if(ip_nat_tcp_table[i].common.cfg == cfg) { 352 IPNAT_ENTRY_RESET(&ip_nat_tcp_table[i].common); 353 } 354 } 355 for (i = 0; i < LWIP_NAT_DEFAULT_STATE_TABLES_UDP; i++) { 356 if(ip_nat_udp_table[i].common.cfg == cfg) { 357 IPNAT_ENTRY_RESET(&ip_nat_udp_table[i].common); 358 } 359 } 360 } 361 362 /** Check if this packet should be routed or should be translated 363 * 364 * @param iphdr the IP header to check 365 * @return - a NAT entry if the packet shall be translated, 366 * - NULL if the packet shall be routed normally 367 */ 368 static ip_nat_conf_t * 369 ip_nat_shallnat(const struct ip_hdr *iphdr) 370 { 371 ip_nat_conf_t *nat_config = ip_nat_cfg; 372 373 for (nat_config = ip_nat_cfg; nat_config != NULL; nat_config = nat_config->next) { 374 if (ip_addr_netcmp(&(iphdr->dest), &(nat_config->entry.dest_net), 375 &(nat_config->entry.dest_netmask)) || 376 ip_addr_netcmp(&(iphdr->src), &(nat_config->entry.source_net), 377 &(nat_config->entry.source_netmask))) { 378 break; 379 } 380 } 381 382 return nat_config; 383 } 384 385 /** Check if the IP header can be hidden and if the remaining packet 386 * is long enough. p->payload is reset to the IP header on return. 387 * 388 * @param p received packet, p->payload pointing to IP header 389 * @param min_size minimum p->tot_len after hiding IP header 390 * @return a pointer to the next header (after IP header), 391 * NULL if hiding IP header fails or the packet is too short 392 */ 393 static void* 394 ip_nat_check_header(struct pbuf *p, u16_t min_size) 395 { 396 void *ret = NULL; 397 struct ip_hdr *iphdr = (struct ip_hdr*)p->payload; 398 s16_t iphdr_len = IPH_HL(iphdr) * 4; 399 400 if(!pbuf_header(p, -iphdr_len)) { 401 if(p->tot_len >= min_size) { 402 ret = p->payload; 403 } 404 /* Restore pbuf payload pointer from previous header check. */ 405 pbuf_header(p, iphdr_len); 406 } 407 return ret; 408 } 409 410 /** Input processing: check if a received packet belongs to a NAT entry 411 * and if so, translated it and send it on. 412 * 413 * @param p received packet 414 * @return 1 if the packet has been consumed (it was a NAT packet), 415 * 0 if the packet has not been consumed (no NAT packet) 416 */ 417 u8_t 418 ip_nat_input(struct pbuf *p) 419 { 420 struct ip_hdr *iphdr = (struct ip_hdr*)p->payload; 421 struct tcp_hdr *tcphdr; 422 struct udp_hdr *udphdr; 423 struct icmp_echo_hdr *icmphdr; 424 nat_entry_t nat_entry; 425 err_t err; 426 u8_t consumed = 0; 427 int i; 428 struct pbuf *q = NULL; 429 430 nat_entry.cmn = NULL; 431 ip_nat_dbg_dump("ip_nat_in: checking nat for", iphdr); 432 433 switch (IPH_PROTO(iphdr)) { 434 case IP_PROTO_TCP: 435 tcphdr = (struct tcp_hdr*)ip_nat_check_header(p, sizeof(struct tcp_hdr)); 436 if (tcphdr == NULL) { 437 LWIP_DEBUGF(LWIP_NAT_DEBUG, ("ip_nat_input: short tcp packet (%" U16_F " bytes) discarded\n", p->tot_len)); 438 } else { 439 nat_entry.tcp = ip_nat_tcp_lookup_incoming(iphdr, tcphdr); 440 if (nat_entry.tcp != NULL) { 441 /* Refresh TCP entry */ 442 nat_entry.tcp->common.ttl = LWIP_NAT_DEFAULT_TTL_SECONDS; 443 tcphdr->dest = nat_entry.tcp->sport; 444 /* Adjust TCP checksum for changed destination port */ 445 ip_nat_chksum_adjust((u8_t *)&(tcphdr->chksum), 446 (u8_t *)&(nat_entry.tcp->nport), 2, (u8_t *)&(tcphdr->dest), 2); 447 /* Adjust TCP checksum for changing dest IP address */ 448 ip_nat_chksum_adjust((u8_t *)&(tcphdr->chksum), 449 (u8_t *)&(nat_entry.cmn->cfg->entry.out_if->ip_addr.addr), 4, 450 (u8_t *)&(nat_entry.cmn->source.addr), 4); 451 452 consumed = 1; 453 } 454 } 455 break; 456 457 case IP_PROTO_UDP: 458 udphdr = (struct udp_hdr *)ip_nat_check_header(p, sizeof(struct udp_hdr)); 459 if (udphdr == NULL) { 460 LWIP_DEBUGF(LWIP_NAT_DEBUG, 461 ("ip_nat_input: short udp packet (%" U16_F " bytes) discarded\n", 462 p->tot_len)); 463 } else { 464 nat_entry.udp = ip_nat_udp_lookup_incoming(iphdr, udphdr); 465 if (nat_entry.udp != NULL) { 466 /* Refresh UDP entry */ 467 nat_entry.udp->common.ttl = LWIP_NAT_DEFAULT_TTL_SECONDS; 468 udphdr->dest = nat_entry.udp->sport; 469 /* Adjust UDP checksum for changed destination port */ 470 ip_nat_chksum_adjust((u8_t *)&(udphdr->chksum), 471 (u8_t *)&(nat_entry.udp->nport), 2, (u8_t *)&(udphdr->dest), 2); 472 /* Adjust UDP checksum for changing dest IP address */ 473 ip_nat_chksum_adjust((u8_t *)&(udphdr->chksum), 474 (u8_t *)&(nat_entry.cmn->cfg->entry.out_if->ip_addr.addr), 4, 475 (u8_t *)&(nat_entry.cmn->source.addr), 4); 476 477 consumed = 1; 478 } 479 } 480 break; 481 482 case IP_PROTO_ICMP: 483 icmphdr = (struct icmp_echo_hdr *)ip_nat_check_header(p, sizeof(struct icmp_echo_hdr)); 484 if (icmphdr == NULL) { 485 LWIP_DEBUGF(LWIP_NAT_DEBUG, 486 ("ip_nat_out: short icmp echo reply packet (%" U16_F " bytes) discarded\n", 487 p->tot_len)); 488 } else { 489 if (ICMP_ER == ICMPH_TYPE(icmphdr)) { 490 for (i = 0; i < LWIP_NAT_DEFAULT_STATE_TABLES_ICMP; i++) { 491 nat_entry.icmp = &ip_nat_icmp_table[i]; 492 if ((nat_entry.icmp->common.ttl) && 493 (iphdr->src.addr == nat_entry.icmp->common.dest.addr) && 494 (nat_entry.icmp->id == icmphdr->id) && 495 (nat_entry.icmp->seqno == icmphdr->seqno)) { 496 ip_nat_dbg_dump_icmp_nat_entry("found existing nat entry: ", nat_entry.icmp); 497 consumed = 1; 498 IPNAT_ENTRY_RESET(nat_entry.cmn); 499 break; 500 } 501 } 502 } 503 } 504 break; 505 506 default: 507 break; 508 } 509 510 if(consumed) { 511 /* packet consumed, send it out on in_if */ 512 struct netif *in_if; 513 514 /* check if the pbuf has room for link headers */ 515 if (pbuf_header(p, PBUF_LINK_HLEN)) { 516 /* pbuf has no room for link headers, allocate an extra pbuf */ 517 q = pbuf_alloc(PBUF_LINK, 0, PBUF_RAM); 518 if (q == NULL) { 519 LWIP_DEBUGF(LWIP_NAT_DEBUG, ("ip_nat_input: no pbuf for outgoing header\n")); 520 // rt_kprintf("ip_nat_input: no pbuf for outgoing header\n"); 521 /* @todo: stats? */ 522 pbuf_free(p); 523 p = NULL; 524 return 1; 525 } else { 526 pbuf_cat(q, p); 527 } 528 } else { 529 /* restore p->payload to IP header */ 530 if (pbuf_header(p, -PBUF_LINK_HLEN)) { 531 LWIP_DEBUGF(LWIP_NAT_DEBUG, ("ip_nat_input: restoring header failed\n")); 532 // rt_kprintf("ip_nat_input: restoring header failed\n"); 533 /* @todo: stats? */ 534 pbuf_free(p); 535 p = NULL; 536 return 1; 537 } 538 else q = p; 539 } 540 /* if we come here, q is the pbuf to send (either points to p or to a chain) */ 541 in_if = nat_entry.cmn->cfg->entry.in_if; 542 iphdr->dest.addr = nat_entry.cmn->source.addr; 543 ip_nat_chksum_adjust((u8_t *) & IPH_CHKSUM(iphdr), 544 (u8_t *) & (nat_entry.cmn->cfg->entry.out_if->ip_addr.addr), 4, 545 (u8_t *) & (iphdr->dest.addr), 4); 546 547 ip_nat_dbg_dump("ip_nat_input: packet back to source after nat: ", iphdr); 548 LWIP_DEBUGF(LWIP_NAT_DEBUG, ("ip_nat_input: sending packet on interface (")); 549 ip_nat_dbg_dump_ip(&(in_if->ip_addr)); 550 LWIP_DEBUGF(LWIP_NAT_DEBUG, (")\n")); 551 552 err = in_if->output(in_if, q, (ip_addr_t *)&(iphdr->dest)); 553 if(err != ERR_OK) { 554 LWIP_DEBUGF(LWIP_NAT_DEBUG, 555 ("ip_nat_input: failed to send rewritten packet. link layer returned %d\n", 556 err)); 557 // rt_kprintf("ip_nat_input: failed to send rewritten packet. link layer returned %d\n", err); 558 } 559 /* now that q (and/or p) is sent (or not), give up the reference to it 560 this frees the input pbuf (p) as we have consumed it. */ 561 pbuf_free(q); 562 } 563 return consumed; 564 } 565 566 /** Check if one NAT entry timed out */ 567 static void 568 ip_nat_check_timeout(ip_nat_entry_common_t *nat_entry) 569 { 570 if(nat_entry->ttl > 0) { 571 if(nat_entry->ttl != LWIP_NAT_TTL_INFINITE) { 572 /* this is not a 'no-timeout' entry */ 573 if(nat_entry->ttl > LWIP_NAT_TMR_INTERVAL_SEC) { 574 nat_entry->ttl -= LWIP_NAT_TMR_INTERVAL_SEC; 575 } else { 576 nat_entry->ttl = 0; 577 } 578 } 579 } 580 } 581 582 /** The NAT timer function, to be called at an interval of 583 * LWIP_NAT_TMR_INTERVAL_SEC seconds. 584 */ 585 void 586 ip_nat_tmr(void) 587 { 588 int i; 589 590 LWIP_DEBUGF(LWIP_NAT_DEBUG, ("ip_nat_tmr: removing old entries\n")); 591 592 for(i = 0; i < LWIP_NAT_DEFAULT_STATE_TABLES_ICMP; i++) { 593 ip_nat_check_timeout((ip_nat_entry_common_t *) & ip_nat_icmp_table[i]); 594 } 595 for(i = 0; i < LWIP_NAT_DEFAULT_STATE_TABLES_TCP; i++) { 596 ip_nat_check_timeout((ip_nat_entry_common_t *) & ip_nat_tcp_table[i]); 597 } 598 for(i = 0; i < LWIP_NAT_DEFAULT_STATE_TABLES_UDP; i++) { 599 ip_nat_check_timeout((ip_nat_entry_common_t *) & ip_nat_udp_table[i]); 600 } 601 } 602 603 /** Check if we want to perform NAT with this packet. If so, send it out on 604 * the correct interface. 605 * 606 * @param p the packet to test/send 607 * @return 1: the packet has been sent using NAT, 608 * 0: the packet did not belong to a NAT entry 609 */ 610 u8_t 611 ip_nat_out(struct pbuf *p) 612 { 613 u8_t sent = 0; 614 err_t err; 615 struct ip_hdr *iphdr = p->payload; 616 struct icmp_echo_hdr *icmphdr; 617 struct tcp_hdr *tcphdr; 618 struct udp_hdr *udphdr; 619 ip_nat_conf_t *nat_config; 620 nat_entry_t nat_entry; 621 int i; 622 623 nat_entry.cmn = NULL; 624 625 ip_nat_dbg_dump("ip_nat_out: checking nat for", iphdr); 626 627 /* Check if this packet should be routed or should be translated */ 628 nat_config = ip_nat_shallnat(iphdr); 629 if (nat_config != NULL ) { 630 if (nat_config->entry.out_if == NULL) { 631 LWIP_DEBUGF(LWIP_NAT_DEBUG, ("ip_nat_out: no external interface for nat table entry\n")); 632 } else { 633 switch (IPH_PROTO(iphdr)) 634 { 635 case IP_PROTO_TCP: 636 tcphdr = (struct tcp_hdr *)ip_nat_check_header(p, sizeof(struct tcp_hdr)); 637 if (tcphdr == NULL) { 638 LWIP_DEBUGF(LWIP_NAT_DEBUG, 639 ("ip_nat_out: short tcp packet (%" U16_F " bytes) discarded\n", p->tot_len)); 640 } else { 641 nat_entry.tcp = ip_nat_tcp_lookup_outgoing(nat_config, iphdr, tcphdr, 1); 642 if (nat_entry.tcp != NULL) { 643 /* Adjust TCP checksum for changing source port */ 644 tcphdr->src = nat_entry.tcp->nport; 645 ip_nat_chksum_adjust((u8_t *)&(tcphdr->chksum), 646 (u8_t *)&(nat_entry.tcp->sport), 2, (u8_t *)&(tcphdr->src), 2); 647 /* Adjust TCP checksum for changing source IP address */ 648 ip_nat_chksum_adjust((u8_t *)&(tcphdr->chksum), 649 (u8_t *)&(nat_entry.cmn->source.addr), 4, 650 (u8_t *)&(nat_entry.cmn->cfg->entry.out_if->ip_addr.addr), 4); 651 } 652 } 653 break; 654 655 case IP_PROTO_UDP: 656 udphdr = (struct udp_hdr *)ip_nat_check_header(p, sizeof(struct udp_hdr)); 657 if (udphdr == NULL) { 658 LWIP_DEBUGF(LWIP_NAT_DEBUG, 659 ("ip_nat_out: short udp packet (%" U16_F " bytes) discarded\n", p->tot_len)); 660 } else { 661 nat_entry.udp = ip_nat_udp_lookup_outgoing(nat_config, iphdr, udphdr, 1); 662 if (nat_entry.udp != NULL) { 663 /* Adjust UDP checksum for changing source port */ 664 udphdr->src = nat_entry.udp->nport; 665 ip_nat_chksum_adjust((u8_t *)&(udphdr->chksum), 666 (u8_t *)&(nat_entry.udp->sport), 2, (u8_t *) & (udphdr->src), 2); 667 /* Adjust UDP checksum for changing source IP address */ 668 ip_nat_chksum_adjust((u8_t *)&(udphdr->chksum), 669 (u8_t *)&(nat_entry.cmn->source.addr), 4, 670 (u8_t *)&(nat_entry.cmn->cfg->entry.out_if->ip_addr.addr), 4); 671 } 672 } 673 break; 674 675 case IP_PROTO_ICMP: 676 icmphdr = (struct icmp_echo_hdr *)ip_nat_check_header(p, sizeof(struct icmp_echo_hdr)); 677 if(icmphdr == NULL) { 678 LWIP_DEBUGF(LWIP_NAT_DEBUG, 679 ("ip_nat_out: short icmp echo packet (%" U16_F " bytes) discarded\n", p->tot_len)); 680 } else { 681 if (ICMPH_TYPE(icmphdr) == ICMP_ECHO) { 682 for (i = 0; i < LWIP_NAT_DEFAULT_STATE_TABLES_ICMP; i++) { 683 if (!ip_nat_icmp_table[i].common.ttl) { 684 nat_entry.icmp = &ip_nat_icmp_table[i]; 685 ip_nat_cmn_init(nat_config, iphdr, nat_entry.cmn); 686 nat_entry.icmp->id = icmphdr->id; 687 nat_entry.icmp->seqno = icmphdr->seqno; 688 ip_nat_dbg_dump_icmp_nat_entry(" ip_nat_out: created new NAT entry ", nat_entry.icmp); 689 break; 690 } 691 } 692 if (NULL == nat_entry.icmp) 693 { 694 LWIP_DEBUGF(LWIP_NAT_DEBUG, ("ip_nat_out: no more NAT entries for ICMP available\n")); 695 } 696 } 697 } 698 break; 699 default: 700 break; 701 } 702 703 if (nat_entry.cmn != NULL) { 704 struct netif *out_if = nat_entry.cmn->cfg->entry.out_if; 705 /* Exchange the IP source address with the address of the interface 706 * where the packet will be sent. 707 */ 708 /* @todo: check nat_config->entry.out_if agains nat_entry.cmn->cfg->entry.out_if */ 709 iphdr->src.addr = nat_config->entry.out_if->ip_addr.addr; 710 ip_nat_chksum_adjust((u8_t *) & IPH_CHKSUM(iphdr), 711 (u8_t *) & (nat_entry.cmn->source.addr), 4, (u8_t *) & iphdr->src.addr, 4); 712 713 ip_nat_dbg_dump("ip_nat_out: rewritten packet", iphdr); 714 LWIP_DEBUGF(LWIP_NAT_DEBUG, ("ip_nat_out: sending packet on interface (")); 715 ip_nat_dbg_dump_ip(&(out_if->ip_addr)); 716 LWIP_DEBUGF(LWIP_NAT_DEBUG, (")\n")); 717 718 err = out_if->output(out_if, p, (ip_addr_t *)&(iphdr->dest)); 719 if (err != ERR_OK) { 720 LWIP_DEBUGF(LWIP_NAT_DEBUG, 721 ("ip_nat_out: failed to send rewritten packet. link layer returned %d\n", err)); 722 // rt_kprintf("ip_nat_out: failed to send rewritten packet. link layer returned %d\n", err); 723 } else { 724 sent = 1; 725 } 726 } 727 } 728 } 729 730 return sent; 731 } 732 733 /** Initialize common parts of a NAT entry 734 * 735 * @param nat_config NAT config entry 736 * @param iphdr IP header from which to initialize the entry 737 * @param nat_entry entry to initialize 738 */ 739 static void 740 ip_nat_cmn_init(ip_nat_conf_t *nat_config, const struct ip_hdr *iphdr, ip_nat_entry_common_t *nat_entry) 741 { 742 LWIP_ASSERT("NULL != nat_entry", NULL != nat_entry); 743 LWIP_ASSERT("NULL != nat_config", NULL != nat_config); 744 LWIP_ASSERT("NULL != iphdr", NULL != iphdr); 745 nat_entry->cfg = nat_config; 746 nat_entry->dest = *((ip_addr_t *)&iphdr->dest); 747 nat_entry->source = *((ip_addr_t *)&iphdr->src); 748 nat_entry->ttl = LWIP_NAT_DEFAULT_TTL_SECONDS; 749 } 750 751 /** 752 * This function checks for incoming packets if we already have a NAT entry. 753 * If yes a pointer to the NAT entry is returned. Otherwise NULL. 754 * 755 * @param nat_config NAT configuration. 756 * @param iphdr The IP header. 757 * @param udphdr The UDP header. 758 * @return A pointer to an existing NAT entry or 759 * NULL if none is found. 760 */ 761 static ip_nat_entries_udp_t * 762 ip_nat_udp_lookup_incoming(const struct ip_hdr *iphdr, const struct udp_hdr *udphdr) 763 { 764 int i; 765 ip_nat_entries_udp_t *nat_entry = NULL; 766 767 for (i = 0; i < LWIP_NAT_DEFAULT_STATE_TABLES_UDP; i++) { 768 if (ip_nat_udp_table[i].common.ttl) { 769 if ((iphdr->src.addr == ip_nat_udp_table[i].common.dest.addr) && 770 (udphdr->src == ip_nat_udp_table[i].dport) && 771 (udphdr->dest == ip_nat_udp_table[i].nport)) { 772 nat_entry = &ip_nat_udp_table[i]; 773 ip_nat_dbg_dump_udp_nat_entry("ip_nat_udp_lookup_incoming: found existing nat entry: ", 774 nat_entry); 775 break; 776 } 777 } 778 } 779 return nat_entry; 780 } 781 782 /** 783 * This function checks if we already have a NAT entry for this UDP connection. 784 * If yes the a pointer to this NAT entry is returned. 785 * 786 * @param iphdr The IP header. 787 * @param udphdr The UDP header. 788 * @param allocate If no existing NAT entry is found and this flag is true 789 * a NAT entry is allocated. 790 */ 791 static ip_nat_entries_udp_t * 792 ip_nat_udp_lookup_outgoing(ip_nat_conf_t *nat_config, const struct ip_hdr *iphdr, 793 const struct udp_hdr *udphdr, u8_t allocate) 794 { 795 int i; 796 nat_entry_t nat_entry; 797 int last_free = -1; 798 799 nat_entry.cmn = NULL; 800 for (i = 0; i < LWIP_NAT_DEFAULT_STATE_TABLES_UDP; i++) { 801 if (ip_nat_udp_table[i].common.ttl) { 802 if ((iphdr->src.addr == ip_nat_udp_table[i].common.source.addr) && 803 (iphdr->dest.addr == ip_nat_udp_table[i].common.dest.addr) && 804 (udphdr->src == ip_nat_udp_table[i].sport) && 805 (udphdr->dest == ip_nat_udp_table[i].dport)) { 806 nat_entry.udp = &ip_nat_udp_table[i]; 807 808 ip_nat_dbg_dump_udp_nat_entry("ip_nat_udp_lookup_outgoing: found existing nat entry: ", 809 nat_entry.udp); 810 break; 811 } 812 } else { 813 last_free = i; 814 } 815 } 816 if (nat_entry.cmn == NULL) { 817 if (allocate) { 818 if (last_free != -1) { 819 nat_entry.udp = &ip_nat_udp_table[last_free]; 820 nat_entry.udp->nport = htons((u16_t) (LWIP_NAT_DEFAULT_UDP_SOURCE_PORT + i)); 821 nat_entry.udp->sport = udphdr->src; 822 nat_entry.udp->dport = udphdr->dest; 823 ip_nat_cmn_init(nat_config, iphdr, nat_entry.cmn); 824 825 ip_nat_dbg_dump_udp_nat_entry("ip_nat_udp_lookup_outgoing: created new nat entry: ", 826 nat_entry.udp); 827 } else { 828 LWIP_DEBUGF(LWIP_NAT_DEBUG, ("ip_nat_udp_lookup_outgoing: no more NAT entries available\n")); 829 // rt_kprintf("ip_nat_udp_lookup_outgoing: no more NAT entries available\n"); 830 } 831 } 832 } 833 return nat_entry.udp; 834 } 835 836 /** 837 * This function checks for incoming packets if we already have a NAT entry. 838 * If yes a pointer to the NAT entry is returned. Otherwise NULL. 839 * 840 * @param nat_config NAT configuration. 841 * @param iphdr The IP header. 842 * @param tcphdr The TCP header. 843 * @return A pointer to an existing NAT entry or NULL if none is found. 844 */ 845 static ip_nat_entries_tcp_t * 846 ip_nat_tcp_lookup_incoming(const struct ip_hdr *iphdr, const struct tcp_hdr *tcphdr) 847 { 848 int i; 849 ip_nat_entries_tcp_t *nat_entry = NULL; 850 851 for (i = 0; i < LWIP_NAT_DEFAULT_STATE_TABLES_TCP; i++) { 852 if (ip_nat_tcp_table[i].common.ttl) { 853 if ((iphdr->src.addr == ip_nat_tcp_table[i].common.dest.addr) && 854 (tcphdr->src == ip_nat_tcp_table[i].dport) && 855 (tcphdr->dest == ip_nat_tcp_table[i].nport)) { 856 nat_entry = &ip_nat_tcp_table[i]; 857 858 ip_nat_dbg_dump_tcp_nat_entry("ip_nat_tcp_lookup_incoming: found existing nat entry: ", 859 nat_entry); 860 break; 861 } 862 } 863 } 864 return nat_entry; 865 } 866 867 /** 868 * This function checks if we already have a NAT entry for this TCP connection. 869 * If yes the a pointer to this NAT entry is returned. 870 * 871 * @param iphdr The IP header. 872 * @param tcphdr The TCP header. 873 * @param allocate If no existing NAT entry is found and this flag is true 874 * a NAT entry is allocated. 875 */ 876 static ip_nat_entries_tcp_t * 877 ip_nat_tcp_lookup_outgoing(ip_nat_conf_t *nat_config, const struct ip_hdr *iphdr, 878 const struct tcp_hdr *tcphdr, u8_t allocate) 879 { 880 int i; 881 nat_entry_t nat_entry; 882 int last_free = -1; 883 884 nat_entry.cmn = NULL; 885 for (i = 0; i < LWIP_NAT_DEFAULT_STATE_TABLES_TCP; i++) { 886 if (ip_nat_tcp_table[i].common.ttl) { 887 if ((iphdr->src.addr == ip_nat_tcp_table[i].common.source.addr) && 888 (iphdr->dest.addr == ip_nat_tcp_table[i].common.dest.addr) && 889 (tcphdr->src == ip_nat_tcp_table[i].sport) && 890 (tcphdr->dest == ip_nat_tcp_table[i].dport)) { 891 nat_entry.tcp = &ip_nat_tcp_table[i]; 892 893 ip_nat_dbg_dump_tcp_nat_entry("ip_nat_tcp_lookup_outgoing: found existing nat entry: ", 894 nat_entry.tcp); 895 break; 896 } 897 } else { 898 last_free = i; 899 } 900 } 901 if (nat_entry.cmn == NULL) { 902 if (allocate) { 903 if (last_free != -1) { 904 nat_entry.tcp = &ip_nat_tcp_table[last_free]; 905 nat_entry.tcp->nport = htons((u16_t) (LWIP_NAT_DEFAULT_TCP_SOURCE_PORT + i)); 906 nat_entry.tcp->sport = tcphdr->src; 907 nat_entry.tcp->dport = tcphdr->dest; 908 ip_nat_cmn_init(nat_config, iphdr, nat_entry.cmn); 909 910 ip_nat_dbg_dump_tcp_nat_entry("ip_nat_tcp_lookup_outgoing: created new nat entry: ", 911 nat_entry.tcp); 912 } else { 913 LWIP_DEBUGF(LWIP_NAT_DEBUG, ("ip_nat_udp_lookup_outgoing: no more NAT entries available\n")); 914 // rt_kprintf("ip_nat_udp_lookup_outgoing: no more NAT entries available\n"); 915 } 916 } 917 } 918 return nat_entry.tcp; 919 } 920 921 /** Adjusts the checksum of a NAT'ed packet without having to completely recalculate it 922 * @todo: verify this works for little- and big-endian 923 * 924 * @param chksum points to the chksum in the packet 925 * @param optr points to the old data in the packet 926 * @param olen length of old data 927 * @param nptr points to the new data in the packet 928 * @param nlen length of new data 929 */ 930 static void 931 ip_nat_chksum_adjust(u8_t *chksum, const u8_t *optr, s16_t olen, const u8_t *nptr, s16_t nlen) 932 { 933 s32_t x, oldval, newval; 934 935 LWIP_ASSERT("NULL != chksum", NULL != chksum); 936 LWIP_ASSERT("NULL != optr", NULL != optr); 937 LWIP_ASSERT("NULL != nptr", NULL != nptr); 938 LWIP_DEBUGF(LWIP_NAT_DEBUG, ("ip_nat_chksum_adjust: chksum=%p, optr=%p, olen=%" U16_F ", nptr=%p, nlen=%" U16_F "\n", 939 chksum, optr, olen, nptr, nlen)); 940 x = chksum[0] * 256 + chksum[1]; 941 x = ~x & 0xFFFF; 942 while (olen) { 943 oldval = optr[0] * 256 + optr[1]; 944 optr += 2; 945 x -= oldval & 0xffff; 946 if (x <= 0) { 947 x--; 948 x &= 0xffff; 949 } 950 olen -= 2; 951 } 952 while (nlen) { 953 newval = nptr[0] * 256 + nptr[1]; 954 nptr += 2; 955 x += newval & 0xffff; 956 if (x & 0x10000) { 957 x++; 958 x &= 0xffff; 959 } 960 nlen -= 2; 961 } 962 x = ~x & 0xFFFF; 963 chksum[0] = x / 256; 964 chksum[1] = x & 0xff; 965 LWIP_DEBUGF(LWIP_NAT_DEBUG, ("ip_nat_chksum_adjust: chksum = 0x%x\n", *((u16_t *) chksum))); 966 } 967 968 #if defined(LWIP_DEBUG) && (LWIP_NAT_DEBUG & LWIP_DBG_ON) 969 /** 970 * This function dumps an IP address 971 * 972 * @param addr IP address 973 */ 974 static void 975 ip_nat_dbg_dump_ip(const ip_addr_t *addr) 976 { 977 LWIP_ASSERT("NULL != addr", NULL != addr); 978 LWIP_DEBUGF(LWIP_NAT_DEBUG, ("%" U16_F ".%" U16_F ".%" U16_F ".%" U16_F, 979 ip4_addr1(addr), ip4_addr2(addr), ip4_addr3(addr), ip4_addr4(addr))); 980 } 981 982 /** 983 * This function dumps an IP header 984 * 985 * @param msg a message to print 986 * @param iphdr IP header 987 */ 988 static void 989 ip_nat_dbg_dump(const char *msg, const struct ip_hdr *iphdr) 990 { 991 LWIP_ASSERT("NULL != msg", NULL != msg); 992 LWIP_ASSERT("NULL != iphdr", NULL != iphdr); 993 LWIP_DEBUGF(LWIP_NAT_DEBUG, ("%s: IP: (", msg)); 994 ip_nat_dbg_dump_ip((ip_addr_t *)&(iphdr->src)); 995 LWIP_DEBUGF(LWIP_NAT_DEBUG, (" --> ")); 996 ip_nat_dbg_dump_ip((ip_addr_t *)&(iphdr->dest)); 997 LWIP_DEBUGF(LWIP_NAT_DEBUG, (" id=%" U16_F ", chksum=%" U16_F ")\n", 998 ntohs(IPH_ID(iphdr)), ntohs(IPH_CHKSUM(iphdr)))); 999 } 1000 1001 /** 1002 * This function dumps an ICMP echo reply/recho request nat entry. 1003 * 1004 * @param msg a message to print 1005 * @param nat_entry the ICMP NAT entry to print 1006 */ 1007 static void 1008 ip_nat_dbg_dump_icmp_nat_entry(const char *msg, const ip_nat_entries_icmp_t *nat_entry) 1009 { 1010 LWIP_ASSERT("NULL != msg", NULL != msg); 1011 LWIP_ASSERT("NULL != nat_entry", NULL != nat_entry); 1012 LWIP_ASSERT("NULL != nat_entry->common.cfg", NULL != nat_entry->common.cfg); 1013 LWIP_ASSERT("NULL != nat_entry->common.cfg->entry.out_if", 1014 NULL != nat_entry->common.cfg->entry.out_if); 1015 LWIP_DEBUGF(LWIP_NAT_DEBUG, ("%s", msg)); 1016 LWIP_DEBUGF(LWIP_NAT_DEBUG, ("ICMP : (")); 1017 ip_nat_dbg_dump_ip(&(nat_entry->common.source)); 1018 LWIP_DEBUGF(LWIP_NAT_DEBUG, (" --> ")); 1019 ip_nat_dbg_dump_ip(&(nat_entry->common.dest)); 1020 LWIP_DEBUGF(LWIP_NAT_DEBUG, (" id=%" U16_F, ntohs(nat_entry->id))); 1021 LWIP_DEBUGF(LWIP_NAT_DEBUG, (", seq=%" U16_F, ntohs(nat_entry->seqno))); 1022 LWIP_DEBUGF(LWIP_NAT_DEBUG, (") mapped at (")); 1023 ip_nat_dbg_dump_ip(&(nat_entry->common.cfg->entry.out_if->ip_addr)); 1024 LWIP_DEBUGF(LWIP_NAT_DEBUG, (" --> ")); 1025 ip_nat_dbg_dump_ip(&(nat_entry->common.dest)); 1026 LWIP_DEBUGF(LWIP_NAT_DEBUG, (" id=%" U16_F, ntohs(nat_entry->id))); 1027 LWIP_DEBUGF(LWIP_NAT_DEBUG, (", seq=%" U16_F, ntohs(nat_entry->seqno))); 1028 LWIP_DEBUGF(LWIP_NAT_DEBUG, (")\n")); 1029 } 1030 1031 /** 1032 * This function dumps an TCP nat entry. 1033 * 1034 * @param msg a message to print 1035 * @param nat_entry the TCP NAT entry to print 1036 */ 1037 static void 1038 ip_nat_dbg_dump_tcp_nat_entry(const char *msg, const ip_nat_entries_tcp_t *nat_entry) 1039 { 1040 LWIP_ASSERT("NULL != msg", NULL != msg); 1041 LWIP_ASSERT("NULL != nat_entry", NULL != nat_entry); 1042 LWIP_ASSERT("NULL != nat_entry->common.cfg", NULL != nat_entry->common.cfg); 1043 LWIP_ASSERT("NULL != nat_entry->common.cfg->entry.out_if", 1044 NULL != nat_entry->common.cfg->entry.out_if); 1045 LWIP_DEBUGF(LWIP_NAT_DEBUG, ("%s", msg)); 1046 LWIP_DEBUGF(LWIP_NAT_DEBUG, ("TCP : (")); 1047 ip_nat_dbg_dump_ip(&(nat_entry->common.source)); 1048 LWIP_DEBUGF(LWIP_NAT_DEBUG, (":%" U16_F, ntohs(nat_entry->sport))); 1049 LWIP_DEBUGF(LWIP_NAT_DEBUG, (" --> ")); 1050 ip_nat_dbg_dump_ip(&(nat_entry->common.dest)); 1051 LWIP_DEBUGF(LWIP_NAT_DEBUG, (":%" U16_F, ntohs(nat_entry->dport))); 1052 LWIP_DEBUGF(LWIP_NAT_DEBUG, (") mapped at (")); 1053 ip_nat_dbg_dump_ip(&(nat_entry->common.cfg->entry.out_if->ip_addr)); 1054 LWIP_DEBUGF(LWIP_NAT_DEBUG, (":%" U16_F, ntohs(nat_entry->nport))); 1055 LWIP_DEBUGF(LWIP_NAT_DEBUG, (" --> ")); 1056 ip_nat_dbg_dump_ip(&(nat_entry->common.dest)); 1057 LWIP_DEBUGF(LWIP_NAT_DEBUG, (":%" U16_F, ntohs(nat_entry->dport))); 1058 LWIP_DEBUGF(LWIP_NAT_DEBUG, (")\n")); 1059 } 1060 1061 /** 1062 * This function dumps a UDP NAT entry. 1063 * 1064 * @param msg a message to print 1065 * @param nat_entry the UDP NAT entry to print 1066 */ 1067 static void 1068 ip_nat_dbg_dump_udp_nat_entry(const char *msg, const ip_nat_entries_udp_t *nat_entry) 1069 { 1070 LWIP_ASSERT("NULL != msg", NULL != msg); 1071 LWIP_ASSERT("NULL != nat_entry", NULL != nat_entry); 1072 LWIP_ASSERT("NULL != nat_entry->common.cfg", NULL != nat_entry->common.cfg); 1073 LWIP_ASSERT("NULL != nat_entry->common.cfg->entry.out_if", 1074 NULL != nat_entry->common.cfg->entry.out_if); 1075 LWIP_DEBUGF(LWIP_NAT_DEBUG, ("%s", msg)); 1076 LWIP_DEBUGF(LWIP_NAT_DEBUG, ("UDP : (")); 1077 ip_nat_dbg_dump_ip(&(nat_entry->common.source)); 1078 LWIP_DEBUGF(LWIP_NAT_DEBUG, (":%" U16_F, ntohs(nat_entry->sport))); 1079 LWIP_DEBUGF(LWIP_NAT_DEBUG, (" --> ")); 1080 ip_nat_dbg_dump_ip(&(nat_entry->common.dest)); 1081 LWIP_DEBUGF(LWIP_NAT_DEBUG, (":%" U16_F, ntohs(nat_entry->dport))); 1082 LWIP_DEBUGF(LWIP_NAT_DEBUG, (") mapped at (")); 1083 ip_nat_dbg_dump_ip(&(nat_entry->common.cfg->entry.out_if->ip_addr)); 1084 LWIP_DEBUGF(LWIP_NAT_DEBUG, (":%" U16_F, ntohs(nat_entry->nport))); 1085 LWIP_DEBUGF(LWIP_NAT_DEBUG, (" --> ")); 1086 ip_nat_dbg_dump_ip(&(nat_entry->common.dest)); 1087 LWIP_DEBUGF(LWIP_NAT_DEBUG, (":%" U16_F, ntohs(nat_entry->dport))); 1088 LWIP_DEBUGF(LWIP_NAT_DEBUG, (")\n")); 1089 } 1090 1091 /** Prints some info when creating a new NAT entry */ 1092 static void 1093 ip_nat_dbg_dump_init(ip_nat_conf_t *ip_nat_cfg_new) 1094 { 1095 LWIP_DEBUGF(LWIP_NAT_DEBUG, ("ip_nat_init: added new NAT interface\n")); 1096 LWIP_DEBUGF(LWIP_NAT_DEBUG, ("ip_nat_init: ")); 1097 ip_nat_dbg_dump_ip(&(ip_nat_cfg_new->entry.source_net)); 1098 LWIP_DEBUGF(LWIP_NAT_DEBUG, ("/")); 1099 ip_nat_dbg_dump_ip(&(ip_nat_cfg_new->entry.source_netmask)); 1100 LWIP_DEBUGF(LWIP_NAT_DEBUG, ("@")); 1101 ip_nat_dbg_dump_ip(&(ip_nat_cfg_new->entry.in_if->ip_addr)); 1102 LWIP_DEBUGF(LWIP_NAT_DEBUG, (" --> ")); 1103 ip_nat_dbg_dump_ip(&(ip_nat_cfg_new->entry.dest_net)); 1104 LWIP_DEBUGF(LWIP_NAT_DEBUG, ("/")); 1105 ip_nat_dbg_dump_ip(&(ip_nat_cfg_new->entry.dest_netmask)); 1106 LWIP_DEBUGF(LWIP_NAT_DEBUG, ("@")); 1107 ip_nat_dbg_dump_ip(&(ip_nat_cfg_new->entry.out_if->ip_addr)); 1108 LWIP_DEBUGF(LWIP_NAT_DEBUG, ("\n")); 1109 } 1110 1111 /** Prints some info when removing a NAT entry */ 1112 static void 1113 ip_nat_dbg_dump_remove(ip_nat_conf_t *cur) 1114 { 1115 LWIP_DEBUGF(LWIP_NAT_DEBUG, ("ip_nat_remove: removing existing NAT interface\n")); 1116 LWIP_DEBUGF(LWIP_NAT_DEBUG, ("ip_nat_remove: ")); 1117 ip_nat_dbg_dump_ip(&(cur->entry.source_net)); 1118 LWIP_DEBUGF(LWIP_NAT_DEBUG, ("/")); 1119 ip_nat_dbg_dump_ip(&(cur->entry.source_netmask)); 1120 LWIP_DEBUGF(LWIP_NAT_DEBUG, ("@")); 1121 ip_nat_dbg_dump_ip(&(cur->entry.in_if->ip_addr)); 1122 LWIP_DEBUGF(LWIP_NAT_DEBUG, (" --> ")); 1123 ip_nat_dbg_dump_ip(&(cur->entry.dest_net)); 1124 LWIP_DEBUGF(LWIP_NAT_DEBUG, ("/")); 1125 ip_nat_dbg_dump_ip(&(cur->entry.dest_netmask)); 1126 LWIP_DEBUGF(LWIP_NAT_DEBUG, ("@")); 1127 ip_nat_dbg_dump_ip(&(cur->entry.out_if->ip_addr)); 1128 LWIP_DEBUGF(LWIP_NAT_DEBUG, ("\n")); 1129 } 1130 #endif /* defined(LWIP_DEBUG) && (LWIP_NAT_DEBUG & LWIP_DBG_ON) */ 1131 1132 #endif /* IP_NAT */ 1133