MeterLogger
ip.c
Go to the documentation of this file.
1 /**
2  * @file
3  * This is the IPv4 layer implementation for incoming and outgoing IP traffic.
4  *
5  * @see ip_frag.c
6  *
7  */
8 
9 /*
10  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
11  * All rights reserved.
12  *
13  * Redistribution and use in source and binary forms, with or without modification,
14  * are permitted provided that the following conditions are met:
15  *
16  * 1. Redistributions of source code must retain the above copyright notice,
17  * this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright notice,
19  * this list of conditions and the following disclaimer in the documentation
20  * and/or other materials provided with the distribution.
21  * 3. The name of the author may not be used to endorse or promote products
22  * derived from this software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
25  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
27  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
29  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
32  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
33  * OF SUCH DAMAGE.
34  *
35  * This file is part of the lwIP TCP/IP stack.
36  *
37  * Author: Adam Dunkels <adam@sics.se>
38  *
39  */
40 
41 #include "lwip/opt.h"
42 #include "lwip/ip.h"
43 #include "lwip/def.h"
44 #include "lwip/mem.h"
45 #include "lwip/ip_frag.h"
46 #include "lwip/inet_chksum.h"
47 #include "lwip/netif.h"
48 #include "lwip/icmp.h"
49 #include "lwip/igmp.h"
50 #include "lwip/raw.h"
51 #include "lwip/udp.h"
52 #include "lwip/tcp_impl.h"
53 #include "lwip/snmp.h"
54 #include "lwip/dhcp.h"
55 #include "lwip/autoip.h"
56 #include "lwip/stats.h"
57 #include "lwip/lwip_napt.h"
58 #include "arch/perf.h"
59 
60 #include <string.h>
61 
62 /** Set this to 0 in the rare case of wanting to call an extra function to
63  * generate the IP checksum (in contrast to calculating it on-the-fly). */
64 #ifndef LWIP_INLINE_IP_CHKSUM
65 #define LWIP_INLINE_IP_CHKSUM 1
66 #endif
67 #if LWIP_INLINE_IP_CHKSUM && CHECKSUM_GEN_IP
68 #define CHECKSUM_GEN_IP_INLINE 1
69 #else
70 #define CHECKSUM_GEN_IP_INLINE 0
71 #endif
72 
73 #if LWIP_DHCP || defined(LWIP_IP_ACCEPT_UDP_PORT)
74 #define IP_ACCEPT_LINK_LAYER_ADDRESSING 1
75 
76 /** Some defines for DHCP to let link-layer-addressed packets through while the
77  * netif is down.
78  * To use this in your own application/protocol, define LWIP_IP_ACCEPT_UDP_PORT
79  * to return 1 if the port is accepted and 0 if the port is not accepted.
80  */
81 #if LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT)
82 /* accept DHCP client port and custom port */
83 #define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) (((port) == PP_NTOHS(DHCP_CLIENT_PORT)) \
84  || (LWIP_IP_ACCEPT_UDP_PORT(port)))
85 #elif defined(LWIP_IP_ACCEPT_UDP_PORT) /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */
86 /* accept custom port only */
87 #define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) (LWIP_IP_ACCEPT_UDP_PORT(dst_port))
88 #else /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */
89 /* accept DHCP client port only */
90 #define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) ((port) == PP_NTOHS(DHCP_CLIENT_PORT))
91 #endif /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */
92 
93 #else /* LWIP_DHCP */
94 #define IP_ACCEPT_LINK_LAYER_ADDRESSING 0
95 #endif /* LWIP_DHCP */
96 
97 /**
98  * The interface that provided the packet for the current callback
99  * invocation.
100  */
102 
103 /**
104  * Header of the input packet currently being processed.
105  */
106 const struct ip_hdr *current_header;
107 /** Source IP address of current_header */
109 /** Destination IP address of current_header */
111 
112 /** The IP header ID of the next outgoing IP packet */
113 static u16_t ip_id;
114 
115 /**
116  * Finds the appropriate network interface for a given IP address. It
117  * searches the list of network interfaces linearly. A match is found
118  * if the masked IP address of the network interface equals the masked
119  * IP address given to the function.
120  *
121  * @param dest the destination IP address for which to find the route
122  * @return the netif on which to send to reach dest
123  */
124 struct netif *
126 {
127  struct netif *netif;
128 
129  /* iterate through netifs */
130  for(netif = netif_list; netif != NULL; netif = netif->next) {
131  /* network mask matches? */
132  if (netif_is_up(netif)) {
133  if (ip_addr_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) {
134  /* return netif on which to forward IP packet */
135  return netif;
136  }
137  }
138  }
139  /* iterate through netifs */
140  for(netif = netif_list; netif != NULL; netif = netif->next) {
141  /* network mask matches? */
142  if (netif_is_up(netif)) {
143  if (!ip_addr_isbroadcast(dest, netif) && netif == (struct netif *)eagle_lwip_getif(0)) {
144  return netif;
145  }
146  }
147  }
148  if ((netif_default == NULL) || (!netif_is_up(netif_default))) {
149  LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_route: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
150  ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest)));
151  IP_STATS_INC(ip.rterr);
153  return NULL;
154  }
155  /* no matching netif found, use default netif */
156  return netif_default;
157 }
158 
159 /**
160  * Finds the appropriate network interface for a source IP address. It
161  * searches the list of network interfaces linearly. A match is found
162  * if the masked IP address of the network interface equals the masked
163  * IP address given to the function.
164  *
165  * @param source the sourcination IP address for which to find the route
166  * @return the netif on which to send to reach source
167  */
168 
169 struct netif *ICACHE_FLASH_ATTR
170 ip_router(ip_addr_t *dest, ip_addr_t *source){
171  struct netif *netif;
172  /* iterate through netifs */
173  for(netif = netif_list; netif != NULL; netif = netif->next) {
174  /* network mask matches? */
175 
176  if (netif_is_up(netif)) {
177  if (ip_addr_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) {
178  /* return netif on which to forward IP packet */
179  return netif;
180  }
181  }
182 
183  if (netif_is_up(netif)) {
184  if (ip_addr_netcmp(source, &(netif->ip_addr), &(netif->netmask))) {
185  /* return netif on which to forward IP packet */
186  return netif;
187  }
188  }
189  }
190 
191  if ((netif_default == NULL) || (!netif_is_up(netif_default))) {
192  LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_route: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
193  ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest)));
194  IP_STATS_INC(ip.rterr);
196  return NULL;
197  }
198  /* no matching netif found, use default netif */
199  os_printf("ip_router %d %p\n", __LINE__, netif_default);
200  return netif_default;
201 }
202 
203 
204 #if IP_FORWARD
205 #if IP_NAPT
206 
207 #define NO_IDX ((u16_t)-1)
208 #define NT(x) ((x) == NO_IDX ? NULL : &ip_napt_table[x])
209 
210 u16_t napt_list = NO_IDX, napt_list_last = NO_IDX, napt_free = 0;
211 
212 static struct napt_table *ip_napt_table;
213 struct portmap_table *ip_portmap_table;
214 
215 int nr_active_napt_tcp = 0, nr_active_napt_udp = 0, nr_active_napt_icmp = 0;
216 uint16_t ip_napt_max = 0;
217 uint8_t ip_portmap_max = 0;
218 
220 ip_napt_init(uint16_t max_nat, uint8_t max_portmap)
221 {
222  u16_t i;
223 
224  ip_napt_max = max_nat;
225  ip_portmap_max = max_portmap;
226 
227  ip_napt_table = (struct napt_table*)os_zalloc(sizeof(struct napt_table[ip_napt_max]));
228  ip_portmap_table = (struct portmap_table*)os_zalloc(sizeof(struct portmap_table[ip_portmap_max]));
229 
230  for (i = 0; i < ip_napt_max - 1; i++)
231  ip_napt_table[i].next = i + 1;
232  ip_napt_table[i].next = NO_IDX;
233 }
234 
236 ip_napt_enable(u32_t addr, int enable)
237 {
238  struct netif *netif;
239  for (netif = netif_list; netif; netif = netif->next) {
240  if (netif_is_up(netif) && !ip_addr_isany(&netif->ip_addr) && netif->ip_addr.addr == addr) {
241  netif->napt = !!enable;
242  break;
243  }
244  }
245 }
246 
248 ip_napt_enable_no(u8_t number, int enable)
249 {
250  struct netif *netif;
251  for (netif = netif_list; netif; netif = netif->next) {
252  if (netif->num == number) {
253  netif->napt = !!enable;
254  break;
255  }
256  }
257 }
258 
259 void ICACHE_FLASH_ATTR checksumadjust(unsigned char *chksum, unsigned char *optr,
260  int olen, unsigned char *nptr, int nlen)
261  /* assuming: unsigned char is 8 bits, long is 32 bits.
262  - chksum points to the chksum in the packet
263  - optr points to the old data in the packet
264  - nptr points to the new data in the packet
265  */
266  {
267  long x, old, new;
268  x=chksum[0]*256+chksum[1];
269  x=~x & 0xFFFF;
270  while (olen)
271  {
272  old=optr[0]*256+optr[1]; optr+=2;
273  x-=old & 0xffff;
274  if (x<=0) { x--; x&=0xffff; }
275  olen-=2;
276  }
277  while (nlen)
278  {
279  new=nptr[0]*256+nptr[1]; nptr+=2;
280  x+=new & 0xffff;
281  if (x & 0x10000) { x++; x&=0xffff; }
282  nlen-=2;
283  }
284  x=~x & 0xFFFF;
285  chksum[0]=x/256; chksum[1]=x & 0xff;
286  }
287 
288 
289 /* t must be indexed by napt_free */
290 static void ICACHE_FLASH_ATTR
291 ip_napt_insert(struct napt_table *t)
292 {
293  u16_t ti = t - ip_napt_table;
294  if (ti != napt_free) *((int*)1)=1; //DEBUG
295  napt_free = t->next;
296  t->prev = NO_IDX;
297  t->next = napt_list;
298  if (napt_list != NO_IDX)
299  NT(napt_list)->prev = ti;
300  napt_list = ti;
301  if (napt_list_last == NO_IDX)
302  napt_list_last = ti;
303 
304 #if LWIP_TCP
305  if (t->proto == IP_PROTO_TCP)
306  nr_active_napt_tcp++;
307 #endif
308 #if LWIP_UDP
309  if (t->proto == IP_PROTO_UDP)
310  nr_active_napt_udp++;
311 #endif
312 #if LWIP_ICMP
313  if (t->proto == IP_PROTO_ICMP)
314  nr_active_napt_icmp++;
315 #endif
316 //os_printf("T: %d, U: %d, I: %d\r\n", nr_active_napt_tcp, nr_active_napt_udp, nr_active_napt_icmp);
317 }
318 
319 static void ICACHE_FLASH_ATTR
320 ip_napt_free(struct napt_table *t)
321 {
322  u16_t ti = t - ip_napt_table;
323  if (ti == napt_list)
324  napt_list = t->next;
325  if (ti == napt_list_last)
326  napt_list_last = t->prev;
327  if (t->next != NO_IDX)
328  NT(t->next)->prev = t->prev;
329  if (t->prev != NO_IDX)
330  NT(t->prev)->next = t->next;
331  t->prev = NO_IDX;
332  t->next = napt_free;
333  napt_free = ti;
334 
335 #if LWIP_TCP
336  if (t->proto == IP_PROTO_TCP)
337  nr_active_napt_tcp--;
338 #endif
339 #if LWIP_UDP
340  if (t->proto == IP_PROTO_UDP)
341  nr_active_napt_udp--;
342 #endif
343 #if LWIP_ICMP
344  if (t->proto == IP_PROTO_ICMP)
345  nr_active_napt_icmp--;
346 #endif
347 }
348 
349 #if LWIP_TCP
350 static u8_t ICACHE_FLASH_ATTR
351 ip_napt_find_port(u8_t proto, u16_t port)
352 {
353  int i, next;
354  for (i = napt_list; i != NO_IDX; i = next) {
355  struct napt_table *t = &ip_napt_table[i];
356  next = t->next;
357  if (t->proto == proto && t->mport == port)
358  return 1;
359  }
360  return 0;
361 }
362 
363 static struct portmap_table * ICACHE_FLASH_ATTR
364 ip_portmap_find(u8_t proto, u16_t mport);
365 
366 static u8_t ICACHE_FLASH_ATTR
367 tcp_listening(u16_t port)
368 {
369  struct tcp_pcb_listen *t;
370  for (t = tcp_listen_pcbs.listen_pcbs; t; t = t->next)
371  if (t->local_port == port)
372  return 1;
373  if (ip_portmap_find(IP_PROTO_TCP, port))
374  return 1;
375  return 0;
376 }
377 #endif // LWIP_TCP
378 
379 #if LWIP_UDP
380 static u8_t ICACHE_FLASH_ATTR
381 udp_listening(u16_t port)
382 {
383  struct udp_pcb *pcb;
384  for (pcb = udp_pcbs; pcb; pcb = pcb->next)
385  if (pcb->local_port == port)
386  return 1;
387  if (ip_portmap_find(IP_PROTO_UDP, port))
388  return 1;
389  return 0;
390 }
391 #endif // LWIP_UDP
392 
394 ip_napt_new_port(u8_t proto, u16_t port)
395 {
396  if (PP_NTOHS(port) >= IP_NAPT_PORT_RANGE_START && PP_NTOHS(port) <= IP_NAPT_PORT_RANGE_END)
397  if (!ip_napt_find_port(proto, port) && !tcp_listening(port))
398  return port;
399  for (;;) {
400  port = PP_HTONS(IP_NAPT_PORT_RANGE_START +
401  os_random() % (IP_NAPT_PORT_RANGE_END - IP_NAPT_PORT_RANGE_START + 1));
402  if (ip_napt_find_port(proto, port))
403  continue;
404 #if LWIP_TCP
405  if (proto == IP_PROTO_TCP && tcp_listening(port))
406  continue;
407 #endif // LWIP_TCP
408 #if LWIP_UDP
409  if (proto == IP_PROTO_UDP && udp_listening(port))
410  continue;
411 #endif // LWIP_UDP
412 
413  return port;
414  }
415 }
416 
417 static struct napt_table* ICACHE_FLASH_ATTR
418 ip_napt_find(u8_t proto, u32_t addr, u16_t port, u16_t mport, u8_t dest)
419 {
420  u16_t i, next;
421  struct napt_table *t;
422  u32_t now = sys_now();
423  for (i = napt_list; i != NO_IDX; i = next) {
424  t = NT(i);
425  next = t->next;
426 #if LWIP_TCP
427  if (t->proto == IP_PROTO_TCP &&
428  (((t->finack1 && t->finack2 || !t->synack) &&
429  now - t->last > IP_NAPT_TIMEOUT_MS_TCP_DISCON) ||
430  now - t->last > IP_NAPT_TIMEOUT_MS_TCP)) {
431  ip_napt_free(t);
432  continue;
433  }
434 #endif
435 #if LWIP_UDP
436  if (t->proto == IP_PROTO_UDP && now - t->last > IP_NAPT_TIMEOUT_MS_UDP) {
437  ip_napt_free(t);
438  continue;
439  }
440 #endif
441 #if LWIP_ICMP
442  if (t->proto == IP_PROTO_ICMP && now - t->last > IP_NAPT_TIMEOUT_MS_ICMP) {
443  ip_napt_free(t);
444  continue;
445  }
446 #endif
447  if (dest == 0 && t->proto == proto && t->src == addr && t->sport == port) {
448  t->last = now;
449  return t;
450  }
451  if (dest == 1 && t->proto == proto && t->dest == addr && t->dport == port
452  && t->mport == mport) {
453  t->last = now;
454  return t;
455  }
456  }
457 
458  return NULL;
459 }
460 
462 ip_napt_add(u8_t proto, u32_t src, u16_t sport, u32_t dest, u16_t dport)
463 {
464  struct napt_table *t = ip_napt_find(proto, src, sport, 0, 0);
465  if (t) {
466  t->last = sys_now();
467  t->dest = dest;
468  t->dport = dport;
469  /* move this entry to the top of napt_list */
470  ip_napt_free(t);
471  ip_napt_insert(t);
472  return t->mport;
473  }
474  t = NT(napt_free);
475  if (t) {
476  u16_t mport = sport;
477 #if LWIP_TCP
478  if (proto == IP_PROTO_TCP)
479  mport = ip_napt_new_port(IP_PROTO_TCP, sport);
480 #endif
481 #if LWIP_TCP
482  if (proto == IP_PROTO_UDP)
483  mport = ip_napt_new_port(IP_PROTO_UDP, sport);
484 #endif
485  t->last = sys_now();
486  t->src = src;
487  t->dest = dest;
488  t->sport = sport;
489  t->dport = dport;
490  t->mport = mport;
491  t->proto = proto;
492  t->fin1 = t->fin2 = t->finack1 = t->finack2 = t->synack = t->rst = 0;
493  ip_napt_insert(t);
494  return mport;
495  }
496  os_printf("NAT table full\n");
497  return 0;
498 }
499 
501 ip_portmap_add(u8_t proto, u32_t maddr, u16_t mport, u32_t daddr, u16_t dport)
502 {
503  mport = PP_HTONS(mport);
504  dport = PP_HTONS(dport);
505  int i;
506 
507  for (i = 0; i < ip_portmap_max; i++) {
508  struct portmap_table *p = &ip_portmap_table[i];
509  if (p->valid && p->proto == proto && p->mport == mport) {
510  p->dport = dport;
511  p->daddr = daddr;
512  } else if (!p->valid) {
513  p->maddr = maddr;
514  p->daddr = daddr;
515  p->mport = mport;
516  p->dport = dport;
517  p->proto = proto;
518  p->valid = 1;
519  return 1;
520  }
521  }
522  return 0;
523 }
524 
525 static struct portmap_table * ICACHE_FLASH_ATTR
526 ip_portmap_find(u8_t proto, u16_t mport)
527 {
528  int i;
529  for (i = 0; i < ip_portmap_max; i++) {
530  struct portmap_table *p = &ip_portmap_table[i];
531  if (!p->valid)
532  return 0;
533  if (p->proto == proto && p->mport == mport)
534  return p;
535  }
536  return NULL;
537 }
538 
539 static struct portmap_table * ICACHE_FLASH_ATTR
540 ip_portmap_find_dest(u8_t proto, u16_t dport, u32_t daddr)
541 {
542  int i;
543  for (i = 0; i < ip_portmap_max; i++) {
544  struct portmap_table *p = &ip_portmap_table[i];
545  if (!p->valid)
546  return 0;
547  if (p->proto == proto && p->dport == dport && p->daddr == daddr)
548  return p;
549  }
550  return NULL;
551 }
552 
553 
555 ip_portmap_remove(u8_t proto, u16_t mport)
556 {
557  mport = PP_HTONS(mport);
558  struct portmap_table *last = &ip_portmap_table[ip_portmap_max - 1];
559  struct portmap_table *m = ip_portmap_find(proto, mport);
560  if (!m)
561  return 0;
562  for (; m != last; m++)
563  memcpy(m, m + 1, sizeof(*m));
564  last->valid = 0;
565  return 1;
566 }
567 
568 #if LWIP_TCP
570 ip_napt_modify_port_tcp(struct tcp_hdr *tcphdr, u8_t dest, u16_t newval)
571 {
572  if (dest) {
573  checksumadjust((char *)&tcphdr->chksum, (char *)&tcphdr->dest, 2, (char *)&newval, 2);
574  tcphdr->dest = newval;
575  } else {
576  checksumadjust((char *)&tcphdr->chksum, (char *)&tcphdr->src, 2, (char *)&newval, 2);
577  tcphdr->src = newval;
578  }
579 }
580 
581 
583 ip_napt_modify_addr_tcp(struct tcp_hdr *tcphdr, ip_addr_p_t *oldval, u32_t newval)
584 {
585  checksumadjust((char *)&tcphdr->chksum, (char *)&oldval->addr, 4, (char *)&newval, 4);
586 }
587 #endif // LWIP_TCP
588 
589 #if LWIP_UDP
591 ip_napt_modify_port_udp(struct udp_hdr *udphdr, u8_t dest, u16_t newval)
592 {
593  if (dest) {
594  checksumadjust((char *)&udphdr->chksum, (char *)&udphdr->dest, 2, (char *)&newval, 2);
595  udphdr->dest = newval;
596  } else {
597  checksumadjust((char *)&udphdr->chksum, (char *)&udphdr->src, 2, (char *)&newval, 2);
598  udphdr->src = newval;
599  }
600 }
601 
603 ip_napt_modify_addr_udp(struct udp_hdr *udphdr, ip_addr_p_t *oldval, u32_t newval)
604 {
605  checksumadjust((char *)&udphdr->chksum, (char *)&oldval->addr, 4, (char *)&newval, 4);
606 }
607 #endif // LWIP_UDP
608 
610 ip_napt_modify_addr(struct ip_hdr *iphdr, ip_addr_p_t *field, u32_t newval)
611 {
612  checksumadjust((char *)&IPH_CHKSUM(iphdr), (char *)&field->addr, 4, (char *)&newval, 4);
613  field->addr = newval;
614 }
615 
616 
617 /**
618  * NAPT for an input packet. It checks weather the destination is on NAPT
619  * table and modifythe packet destination address and port if needed.
620  *
621  * @param p the packet to forward (p->payload points to IP header)
622  * @param iphdr the IP header of the input packet
623  * @param inp the netif on which this packet was received
624  */
625 static void ICACHE_FLASH_ATTR
626 ip_napt_recv(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
627 {
628  struct portmap_table *m;
629  struct napt_table *t;
630 
631 #if LWIP_ICMP
632  /* NAPT for ICMP Echo Request using identifier */
633  if (IPH_PROTO(iphdr) == IP_PROTO_ICMP) {
634  struct icmp_echo_hdr *iecho = (struct icmp_echo_hdr *)((u8_t *)p->payload + IPH_HL(iphdr) * 4);
635  if (iecho->type == ICMP_ER) {
636  t = ip_napt_find(IP_PROTO_ICMP, iphdr->src.addr, iecho->id, iecho->id, 1);
637  if (!t)
638  return;
639  ip_napt_modify_addr(iphdr, &iphdr->dest, t->src);
640  return;
641  }
642 
643  return;
644  }
645 #endif // LWIP_ICMP
646 
647 #if LWIP_TCP
648  if (IPH_PROTO(iphdr) == IP_PROTO_TCP) {
649  struct tcp_hdr *tcphdr = (struct tcp_hdr *)((u8_t *)p->payload + IPH_HL(iphdr) * 4);
650  m = ip_portmap_find(IP_PROTO_TCP, tcphdr->dest);
651  if (m) {
652  /* packet to mapped port: rewrite destination */
653  if (m->dport != tcphdr->dest)
654  ip_napt_modify_port_tcp(tcphdr, 1, m->dport);
655  ip_napt_modify_addr_tcp(tcphdr, &iphdr->dest, m->daddr);
656  ip_napt_modify_addr(iphdr, &iphdr->dest, m->daddr);
657  return;
658  }
659  t = ip_napt_find(IP_PROTO_TCP, iphdr->src.addr, tcphdr->src, tcphdr->dest, 1);
660  if (!t)
661  return; /* Unknown TCP session; do nothing */
662 
663  if (t->sport != tcphdr->dest)
664  ip_napt_modify_port_tcp(tcphdr, 1, t->sport);
665  ip_napt_modify_addr_tcp(tcphdr, &iphdr->dest, t->src);
666  ip_napt_modify_addr(iphdr, &iphdr->dest, t->src);
667 
668  if ((TCPH_FLAGS(tcphdr) & (TCP_SYN|TCP_ACK)) == (TCP_SYN|TCP_ACK))
669  t->synack = 1;
670  if ((TCPH_FLAGS(tcphdr) & TCP_FIN))
671  t->fin1 = 1;
672  if (t->fin2 && (TCPH_FLAGS(tcphdr) & TCP_ACK))
673  t->finack2 = 1; /* FIXME: Currently ignoring ACK seq... */
674  if (TCPH_FLAGS(tcphdr) & TCP_RST)
675  t->rst = 1;
676  return;
677  }
678 #endif // LWIP_TCP
679 
680 #if LWIP_UDP
681  if (IPH_PROTO(iphdr) == IP_PROTO_UDP) {
682  struct udp_hdr *udphdr = (struct udp_hdr *)((u8_t *)p->payload + IPH_HL(iphdr) * 4);
683  m = ip_portmap_find(IP_PROTO_UDP, udphdr->dest);
684  if (m) {
685  /* packet to mapped port: rewrite destination */
686  if (m->dport != udphdr->dest)
687  ip_napt_modify_port_udp(udphdr, 1, m->dport);
688  ip_napt_modify_addr_udp(udphdr, &iphdr->dest, m->daddr);
689  ip_napt_modify_addr(iphdr, &iphdr->dest, m->daddr);
690  return;
691  }
692  t = ip_napt_find(IP_PROTO_UDP, iphdr->src.addr, udphdr->src, udphdr->dest, 1);
693  if (!t)
694  return; /* Unknown session; do nothing */
695 
696  if (t->sport != udphdr->dest)
697  ip_napt_modify_port_udp(udphdr, 1, t->sport);
698  ip_napt_modify_addr_udp(udphdr, &iphdr->dest, t->src);
699  ip_napt_modify_addr(iphdr, &iphdr->dest, t->src);
700  return;
701  }
702 #endif // LWIP_UDP
703 }
704 
705 /**
706  * NAPT for a forwarded packet. It checks weather we need NAPT and modify
707  * the packet source address and port if needed.
708  *
709  * @param p the packet to forward (p->payload points to IP header)
710  * @param iphdr the IP header of the input packet
711  * @param inp the netif on which this packet was received
712  * @param outp the netif on which this packet will be sent
713  * @return ERR_OK if packet should be sent, or ERR_RTE if it should be dropped
714  */
716 ip_napt_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp, struct netif *outp)
717 {
718  if (!inp->napt)
719  return ERR_OK;
720 
721 #if LWIP_ICMP
722  /* NAPT for ICMP Echo Request using identifier */
723  if (IPH_PROTO(iphdr) == IP_PROTO_ICMP) {
724  struct icmp_echo_hdr *iecho = (struct icmp_echo_hdr *)((u8_t *)p->payload + IPH_HL(iphdr) * 4);
725  if (iecho->type == ICMP_ECHO) {
726  /* register src addr and iecho->id and dest info */
727  ip_napt_add(IP_PROTO_ICMP, iphdr->src.addr, iecho->id, iphdr->dest.addr, iecho->id);
728 
729  ip_napt_modify_addr(iphdr, &iphdr->src, outp->ip_addr.addr);
730  }
731  return ERR_OK;
732  }
733 #endif
734 
735 #if LWIP_TCP
736  if (IPH_PROTO(iphdr) == IP_PROTO_TCP) {
737  struct tcp_hdr *tcphdr = (struct tcp_hdr *)((u8_t *)p->payload + IPH_HL(iphdr) * 4);
738  u16_t mport;
739 
740  struct portmap_table *m = ip_portmap_find_dest(IP_PROTO_TCP, tcphdr->src, iphdr->src.addr);
741  if (m) {
742  /* packet from port-mapped dest addr/port: rewrite source to this node */
743  if (m->mport != tcphdr->src)
744  ip_napt_modify_port_tcp(tcphdr, 0, m->mport);
745  ip_napt_modify_addr_tcp(tcphdr, &iphdr->src, m->maddr);
746  ip_napt_modify_addr(iphdr, &iphdr->src, m->maddr);
747  return ERR_OK;
748  }
749  if ((TCPH_FLAGS(tcphdr) & (TCP_SYN|TCP_ACK)) == TCP_SYN &&
750  PP_NTOHS(tcphdr->src) >= 1024) {
751  /* Register new TCP session to NAPT */
752  mport = ip_napt_add(IP_PROTO_TCP, iphdr->src.addr, tcphdr->src,
753  iphdr->dest.addr, tcphdr->dest);
754  } else {
755  struct napt_table *t = ip_napt_find(IP_PROTO_TCP, iphdr->src.addr, tcphdr->src, 0, 0);
756  if (!t || t->dest != iphdr->dest.addr || t->dport != tcphdr->dest) {
757 #if LWIP_ICMP
758  icmp_dest_unreach(p, ICMP_DUR_PORT);
759 #endif
760  return ERR_RTE; /* Drop unknown TCP session */
761  }
762  mport = t->mport;
763  if ((TCPH_FLAGS(tcphdr) & TCP_FIN))
764  t->fin2 = 1;
765  if (t->fin1 && (TCPH_FLAGS(tcphdr) & TCP_ACK))
766  t->finack1 = 1; /* FIXME: Currently ignoring ACK seq... */
767  if (TCPH_FLAGS(tcphdr) & TCP_RST)
768  t->rst = 1;
769  }
770 
771  if (mport != tcphdr->src)
772  ip_napt_modify_port_tcp(tcphdr, 0, mport);
773  ip_napt_modify_addr_tcp(tcphdr, &iphdr->src, outp->ip_addr.addr);
774  ip_napt_modify_addr(iphdr, &iphdr->src, outp->ip_addr.addr);
775  return ERR_OK;
776  }
777 #endif
778 
779 #if LWIP_UDP
780  if (IPH_PROTO(iphdr) == IP_PROTO_UDP) {
781  struct udp_hdr *udphdr = (struct udp_hdr *)((u8_t *)p->payload + IPH_HL(iphdr) * 4);
782  u16_t mport;
783 
784  struct portmap_table *m = ip_portmap_find_dest(IP_PROTO_UDP, udphdr->src, iphdr->src.addr);
785  if (m) {
786  /* packet from port-mapped dest addr/port: rewrite source to this node */
787  if (m->mport != udphdr->src)
788  ip_napt_modify_port_udp(udphdr, 0, m->mport);
789  ip_napt_modify_addr_udp(udphdr, &iphdr->src, m->maddr);
790  ip_napt_modify_addr(iphdr, &iphdr->src, m->maddr);
791  return ERR_OK;
792  }
793  if (PP_NTOHS(udphdr->src) >= 1024) {
794  /* Register new UDP session */
795  mport = ip_napt_add(IP_PROTO_UDP, iphdr->src.addr, udphdr->src,
796  iphdr->dest.addr, udphdr->dest);
797  } else {
798  struct napt_table *t = ip_napt_find(IP_PROTO_UDP, iphdr->src.addr, udphdr->src, 0, 0);
799  if (!t || t->dest != iphdr->dest.addr || t->dport != udphdr->dest) {
800 #if LWIP_ICMP
801  icmp_dest_unreach(p, ICMP_DUR_PORT);
802 #endif
803  return ERR_RTE; /* Drop unknown UDP session */
804  }
805  mport = t->mport;
806  }
807 
808  if (mport != udphdr->src)
809  ip_napt_modify_port_udp(udphdr, 0, mport);
810  ip_napt_modify_addr_udp(udphdr, &iphdr->src, outp->ip_addr.addr);
811  ip_napt_modify_addr(iphdr, &iphdr->src, outp->ip_addr.addr);
812  return ERR_OK;
813  }
814 #endif
815 
816  return ERR_OK;
817 }
818 #endif // IP_NAPT
819 
820 /**
821  * Forwards an IP packet. It finds an appropriate route for the
822  * packet, decrements the TTL value of the packet, adjusts the
823  * checksum and outputs the packet on the appropriate interface.
824  *
825  * @param p the packet to forward (p->payload points to IP header)
826  * @param iphdr the IP header of the input packet
827  * @param inp the netif on which this packet was received
828  */
829 static void ICACHE_FLASH_ATTR
830 ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
831 {
832  struct netif *netif;
833 
834  PERF_START;
835 
836  /* RFC3927 2.7: do not forward link-local addresses */
838  LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not forwarding LLA %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
841  goto return_noroute;
842  }
843 
844  /* Find network interface where to forward this IP packet to. */
845  netif = ip_route(&current_iphdr_dest);
846  if (netif == NULL) {
847  LWIP_DEBUGF(IP_DEBUG, ("ip_forward: no forwarding route for %"U16_F".%"U16_F".%"U16_F".%"U16_F" found\n",
850  goto return_noroute;
851  }
852  /* Do not forward packets onto the same network interface on which
853  * they arrived. */
854  if (netif == inp) {
855  LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not bouncing packets back on incoming interface.\n"));
856  goto return_noroute;
857  }
858 
859  /* decrement TTL */
860  IPH_TTL_SET(iphdr, IPH_TTL(iphdr) - 1);
861  /* send ICMP if TTL == 0 */
862  if (IPH_TTL(iphdr) == 0) {
864 #if LWIP_ICMP
865  /* Don't send ICMP messages in response to ICMP messages */
866  if (IPH_PROTO(iphdr) != IP_PROTO_ICMP) {
867  icmp_time_exceeded(p, ICMP_TE_TTL);
868  }
869 #endif /* LWIP_ICMP */
870  return;
871  }
872 
873 #if IP_NAPT
874  if (ip_napt_forward(p, iphdr, inp, netif) != ERR_OK)
875  return;
876 #endif
877 
878  /* Incrementally update the IP checksum. */
879  if (IPH_CHKSUM(iphdr) >= PP_HTONS(0xffff - 0x100)) {
880  IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + PP_HTONS(0x100) + 1);
881  } else {
882  IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + PP_HTONS(0x100));
883  }
884 
885 /* os_printf("Old: %4x ", PP_NTOHS(IPH_CHKSUM(iphdr)));
886 
887  IPH_CHKSUM_SET(iphdr, 0);
888  IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
889  os_printf("Now: %4x\r\n", PP_NTOHS(IPH_CHKSUM(iphdr)));
890 */
891  LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
894 
895  IP_STATS_INC(ip.fw);
896  IP_STATS_INC(ip.xmit);
898 
899  PERF_STOP("ip_forward");
900  /* transmit pbuf on chosen interface */
901  netif->output(netif, p, &current_iphdr_dest);
902  return;
903 return_noroute:
905 }
906 #endif /* IP_FORWARD */
907 
908 /**
909  * This function is called by the network interface device driver when
910  * an IP packet is received. The function does the basic checks of the
911  * IP header such as packet size being at least larger than the header
912  * size etc. If the packet was not destined for us, the packet is
913  * forwarded (using ip_forward). The IP checksum is always checked.
914  *
915  * Finally, the packet is sent to the upper layer protocol input function.
916  *
917  * @param p the received IP packet (p->payload points to IP header)
918  * @param inp the netif on which this packet was received
919  * @return ERR_OK if the packet was processed (could return ERR_* if it wasn't
920  * processed, but currently always returns ERR_OK)
921  */
922 err_t
923 ip_input(struct pbuf *p, struct netif *inp)
924 {
925  struct ip_hdr *iphdr;
926  struct netif *netif;
927  u16_t iphdr_hlen;
928  u16_t iphdr_len;
929 #if IP_ACCEPT_LINK_LAYER_ADDRESSING
930  int check_ip_src=1;
931 #endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */
932 
933  IP_STATS_INC(ip.recv);
935 
936  /* identify the IP header */
937  iphdr = (struct ip_hdr *)p->payload;
938  if (IPH_V(iphdr) != 4) {
939  LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_WARNING, ("IP packet dropped due to bad version number %"U16_F"\n", IPH_V(iphdr)));
940  ip_debug_print(p);
941  pbuf_free(p);
942  IP_STATS_INC(ip.err);
943  IP_STATS_INC(ip.drop);
945  return ERR_OK;
946  }
947 
948  /* obtain IP header length in number of 32-bit words */
949  iphdr_hlen = IPH_HL(iphdr);
950  /* calculate IP header length in bytes */
951  iphdr_hlen *= 4;
952  /* obtain ip length in bytes */
953  iphdr_len = ntohs(IPH_LEN(iphdr));
954 
955  /* header length exceeds first pbuf length, or ip length exceeds total pbuf length? */
956  if ((iphdr_hlen > p->len) || (iphdr_len > p->tot_len)) {
957  if (iphdr_hlen > p->len) {
959  ("IP header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet dropped.\n",
960  iphdr_hlen, p->len));
961  }
962  if (iphdr_len > p->tot_len) {
964  ("IP (len %"U16_F") is longer than pbuf (len %"U16_F"), IP packet dropped.\n",
965  iphdr_len, p->tot_len));
966  }
967  /* free (drop) packet pbufs */
968  pbuf_free(p);
969  IP_STATS_INC(ip.lenerr);
970  IP_STATS_INC(ip.drop);
972  return ERR_OK;
973  }
974 
975  /* verify checksum */
976 #if CHECKSUM_CHECK_IP
977  if (inet_chksum(iphdr, iphdr_hlen) != 0) {
978 
980  ("Checksum (0x%"X16_F") failed, IP packet dropped.\n", inet_chksum(iphdr, iphdr_hlen)));
981  ip_debug_print(p);
982  pbuf_free(p);
983  IP_STATS_INC(ip.chkerr);
984  IP_STATS_INC(ip.drop);
986  return ERR_OK;
987  }
988 #endif
989 
990 #if IP_NAPT
991  /* for unicast packet, check NAPT table and modify dest if needed */
992  if (!inp->napt && ip_addr_cmp(&iphdr->dest, &(inp->ip_addr)))
993  ip_napt_recv(p, iphdr, netif);
994 #endif
995 
996  /* Trim pbuf. This should have been done at the netif layer,
997  * but we'll do it anyway just to be sure that its done. */
998  pbuf_realloc(p, iphdr_len);
999 
1000  /* copy IP addresses to aligned ip_addr_t */
1001  ip_addr_copy(current_iphdr_dest, iphdr->dest);
1002  ip_addr_copy(current_iphdr_src, iphdr->src);
1003 
1004  /* match packet against an interface, i.e. is this packet for us? */
1005 #if LWIP_IGMP
1007  if ((inp->flags & NETIF_FLAG_IGMP) && (igmp_lookfor_group(inp, &current_iphdr_dest))) {
1008  netif = inp;
1009  } else {
1010  netif = NULL;
1011  }
1012  } else
1013 #endif /* LWIP_IGMP */
1014  {
1015  /* start trying with inp. if that's not acceptable, start walking the
1016  list of configured netifs.
1017  'first' is used as a boolean to mark whether we started walking the list */
1018  int first = 1;
1019  netif = inp;
1020  do {
1021  LWIP_DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest 0x%"X32_F" netif->ip_addr 0x%"X32_F" (0x%"X32_F", 0x%"X32_F", 0x%"X32_F")\n",
1022  ip4_addr_get_u32(&iphdr->dest), ip4_addr_get_u32(&netif->ip_addr),
1023  ip4_addr_get_u32(&iphdr->dest) & ip4_addr_get_u32(&netif->netmask),
1024  ip4_addr_get_u32(&netif->ip_addr) & ip4_addr_get_u32(&netif->netmask),
1025  ip4_addr_get_u32(&iphdr->dest) & ~ip4_addr_get_u32(&netif->netmask)));
1026 
1027  /* interface is up and configured? */
1028  if ((netif_is_up(netif)) && (!ip_addr_isany(&(netif->ip_addr)))) {
1029  /* unicast to this interface address? */
1030  if (ip_addr_cmp(&current_iphdr_dest, &(netif->ip_addr)) ||
1031  /* or broadcast on this interface network address? */
1033  LWIP_DEBUGF(IP_DEBUG, ("ip_input: packet accepted on interface %c%c\n",
1034  netif->name[0], netif->name[1]));
1035  /* break out of for loop */
1036  break;
1037  }
1038 #if LWIP_AUTOIP
1039  /* connections to link-local addresses must persist after changing
1040  the netif's address (RFC3927 ch. 1.9) */
1041  if ((netif->autoip != NULL) &&
1042  ip_addr_cmp(&current_iphdr_dest, &(netif->autoip->llipaddr))) {
1043  LWIP_DEBUGF(IP_DEBUG, ("ip_input: LLA packet accepted on interface %c%c\n",
1044  netif->name[0], netif->name[1]));
1045  /* break out of for loop */
1046  break;
1047  }
1048 #endif /* LWIP_AUTOIP */
1049  }
1050  if (first) {
1051  first = 0;
1052  netif = netif_list;
1053  } else {
1054  netif = netif->next;
1055  }
1056  if (netif == inp) {
1057  netif = netif->next;
1058  }
1059  } while(netif != NULL);
1060  }
1061 
1062 #if IP_ACCEPT_LINK_LAYER_ADDRESSING
1063  /* Pass DHCP messages regardless of destination address. DHCP traffic is addressed
1064  * using link layer addressing (such as Ethernet MAC) so we must not filter on IP.
1065  * According to RFC 1542 section 3.1.1, referred by RFC 2131).
1066  *
1067  * If you want to accept private broadcast communication while a netif is down,
1068  * define LWIP_IP_ACCEPT_UDP_PORT(dst_port), e.g.:
1069  *
1070  * #define LWIP_IP_ACCEPT_UDP_PORT(dst_port) ((dst_port) == PP_NTOHS(12345))
1071  */
1072  if (netif == NULL) {
1073  /* remote port is DHCP server? */
1074  if (IPH_PROTO(iphdr) == IP_PROTO_UDP) {
1075  struct udp_hdr *udphdr = (struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen);
1076  LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: UDP packet to DHCP client port %"U16_F"\n",
1077  ntohs(udphdr->dest)));
1078  if (IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(udphdr->dest)) {
1079  LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: DHCP packet accepted.\n"));
1080  netif = inp;
1081  check_ip_src = 0;
1082  }
1083  }
1084  }
1085 #endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */
1086 
1087  /* broadcast or multicast packet source address? Compliant with RFC 1122: 3.2.1.3 */
1088 #if IP_ACCEPT_LINK_LAYER_ADDRESSING
1089  /* DHCP servers need 0.0.0.0 to be allowed as source address (RFC 1.1.2.2: 3.2.1.3/a) */
1090  if (check_ip_src && !ip_addr_isany(&current_iphdr_src))
1091 #endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */
1092  { if ((ip_addr_isbroadcast(&current_iphdr_src, inp)) ||
1094  /* packet source is not valid */
1095  LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("ip_input: packet source is not valid.\n"));
1096  /* free (drop) packet pbufs */
1097  pbuf_free(p);
1098  IP_STATS_INC(ip.drop);
1101  return ERR_OK;
1102  }
1103  }
1104 
1105  /* packet not for us? */
1106  if (netif == NULL) {
1107  /* packet not for us, route or discard */
1108  LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: packet not for us.\n"));
1109 #if IP_FORWARD
1110  /* non-broadcast packet? */
1112  /* try to forward IP packet on (other) interfaces */
1113  ip_forward(p, iphdr, inp);
1114  } else
1115 #endif /* IP_FORWARD */
1116  {
1119  }
1120  pbuf_free(p);
1121  return ERR_OK;
1122  }
1123  /* packet consists of multiple fragments? */
1124  if ((IPH_OFFSET(iphdr) & PP_HTONS(IP_OFFMASK | IP_MF)) != 0) {
1125 #if IP_REASSEMBLY /* packet fragment reassembly code present? */
1126  LWIP_DEBUGF(IP_DEBUG, ("IP packet is a fragment (id=0x%04"X16_F" tot_len=%"U16_F" len=%"U16_F" MF=%"U16_F" offset=%"U16_F"), calling ip_reass()\n",
1127  ntohs(IPH_ID(iphdr)), p->tot_len, ntohs(IPH_LEN(iphdr)), !!(IPH_OFFSET(iphdr) & PP_HTONS(IP_MF)), (ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8));
1128  /* reassemble the packet*/
1129  p = ip_reass(p);
1130  /* packet not fully reassembled yet? */
1131  if (p == NULL) {
1132  return ERR_OK;
1133  }
1134  iphdr = (struct ip_hdr *)p->payload;
1135 #else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */
1136  pbuf_free(p);
1137  LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since it was fragmented (0x%"X16_F") (while IP_REASSEMBLY == 0).\n",
1138  ntohs(IPH_OFFSET(iphdr))));
1139  IP_STATS_INC(ip.opterr);
1140  IP_STATS_INC(ip.drop);
1141  /* unsupported protocol feature */
1143  return ERR_OK;
1144 #endif /* IP_REASSEMBLY */
1145  }
1146 
1147 #if IP_OPTIONS_ALLOWED == 0 /* no support for IP options in the IP header? */
1148 
1149 #if LWIP_IGMP
1150  /* there is an extra "router alert" option in IGMP messages which we allow for but do not police */
1151  if((iphdr_hlen > IP_HLEN) && (IPH_PROTO(iphdr) != IP_PROTO_IGMP)) {
1152 #else
1153  if (iphdr_hlen > IP_HLEN) {
1154 #endif /* LWIP_IGMP */
1155  LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since there were IP options (while IP_OPTIONS_ALLOWED == 0).\n"));
1156  pbuf_free(p);
1157  IP_STATS_INC(ip.opterr);
1158  IP_STATS_INC(ip.drop);
1159  /* unsupported protocol feature */
1161  return ERR_OK;
1162  }
1163 #endif /* IP_OPTIONS_ALLOWED == 0 */
1164 
1165  /* send to upper layers */
1166  LWIP_DEBUGF(IP_DEBUG, ("ip_input: \n"));
1167  ip_debug_print(p);
1168  LWIP_DEBUGF(IP_DEBUG, ("ip_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len));
1169 
1170  current_netif = inp;
1171  current_header = iphdr;
1172 
1173 #if LWIP_RAW
1174  /* raw input did not eat the packet? */
1175  if (raw_input(p, inp) == 0)
1176 #endif /* LWIP_RAW */
1177  {
1178 
1179  switch (IPH_PROTO(iphdr)) {
1180 #if LWIP_UDP
1181  case IP_PROTO_UDP:
1182 #if LWIP_UDPLITE
1183  case IP_PROTO_UDPLITE:
1184 #endif /* LWIP_UDPLITE */
1186  udp_input(p, inp);
1187  break;
1188 #endif /* LWIP_UDP */
1189 #if LWIP_TCP
1190  case IP_PROTO_TCP:
1192  tcp_input(p, inp);
1193  break;
1194 #endif /* LWIP_TCP */
1195 #if LWIP_ICMP
1196  case IP_PROTO_ICMP:
1198  icmp_input(p, inp);
1199  break;
1200 #endif /* LWIP_ICMP */
1201 #if LWIP_IGMP
1202  case IP_PROTO_IGMP:
1203  igmp_input(p, inp, &current_iphdr_dest);
1204  break;
1205 #endif /* LWIP_IGMP */
1206  default:
1207 #if LWIP_ICMP
1208  /* send ICMP destination protocol unreachable unless is was a broadcast */
1211  p->payload = iphdr;
1212  icmp_dest_unreach(p, ICMP_DUR_PROTO);
1213  }
1214 #endif /* LWIP_ICMP */
1215  pbuf_free(p);
1216 
1217  LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("Unsupported transport protocol %"U16_F"\n", IPH_PROTO(iphdr)));
1218 
1219  IP_STATS_INC(ip.proterr);
1220  IP_STATS_INC(ip.drop);
1222  }
1223  }
1224 
1225  current_netif = NULL;
1226  current_header = NULL;
1229 
1230  return ERR_OK;
1231 }
1232 
1233 /**
1234  * Sends an IP packet on a network interface. This function constructs
1235  * the IP header and calculates the IP header checksum. If the source
1236  * IP address is NULL, the IP address of the outgoing network
1237  * interface is filled in as source address.
1238  * If the destination IP address is IP_HDRINCL, p is assumed to already
1239  * include an IP header and p->payload points to it instead of the data.
1240  *
1241  * @param p the packet to send (p->payload points to the data, e.g. next
1242  protocol header; if dest == IP_HDRINCL, p already includes an IP
1243  header and p->payload points to that IP header)
1244  * @param src the source IP address to send from (if src == IP_ADDR_ANY, the
1245  * IP address of the netif used to send is used as source address)
1246  * @param dest the destination IP address to send the packet to
1247  * @param ttl the TTL value to be set in the IP header
1248  * @param tos the TOS value to be set in the IP header
1249  * @param proto the PROTOCOL to be set in the IP header
1250  * @param netif the netif on which to send this packet
1251  * @return ERR_OK if the packet was sent OK
1252  * ERR_BUF if p doesn't have enough space for IP/LINK headers
1253  * returns errors returned by netif->output
1254  *
1255  * @note ip_id: RFC791 "some host may be able to simply use
1256  * unique identifiers independent of destination"
1257  */
1258 err_t
1259 ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
1260  u8_t ttl, u8_t tos,
1261  u8_t proto, struct netif *netif)
1262 {
1263 #if IP_OPTIONS_SEND
1264  return ip_output_if_opt(p, src, dest, ttl, tos, proto, netif, NULL, 0);
1265 }
1266 
1267 /**
1268  * Same as ip_output_if() but with the possibility to include IP options:
1269  *
1270  * @ param ip_options pointer to the IP options, copied into the IP header
1271  * @ param optlen length of ip_options
1272  */
1273 err_t ip_output_if_opt(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
1274  u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options,
1275  u16_t optlen)
1276 {
1277 #endif /* IP_OPTIONS_SEND */
1278  struct ip_hdr *iphdr;
1279  ip_addr_t dest_addr;
1280 #if CHECKSUM_GEN_IP_INLINE
1281  u32_t chk_sum = 0;
1282 #endif /* CHECKSUM_GEN_IP_INLINE */
1283 
1284  /* pbufs passed to IP must have a ref-count of 1 as their payload pointer
1285  gets altered as the packet is passed down the stack */
1286  LWIP_ASSERT("p->ref == 1", p->ref == 1);
1287 
1289 
1290  /* Should the IP header be generated or is it already included in p? */
1291  if (dest != IP_HDRINCL) {
1292  u16_t ip_hlen = IP_HLEN;
1293 #if IP_OPTIONS_SEND
1294  u16_t optlen_aligned = 0;
1295  if (optlen != 0) {
1296 #if CHECKSUM_GEN_IP_INLINE
1297  int i;
1298 #endif /* CHECKSUM_GEN_IP_INLINE */
1299  /* round up to a multiple of 4 */
1300  optlen_aligned = ((optlen + 3) & ~3);
1301  ip_hlen += optlen_aligned;
1302  /* First write in the IP options */
1303  if (pbuf_header(p, optlen_aligned)) {
1304  LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_output_if_opt: not enough room for IP options in pbuf\n"));
1305  IP_STATS_INC(ip.err);
1307  return ERR_BUF;
1308  }
1309  MEMCPY(p->payload, ip_options, optlen);
1310  if (optlen < optlen_aligned) {
1311  /* zero the remaining bytes */
1312  os_memset(((char*)p->payload) + optlen, 0, optlen_aligned - optlen);
1313  }
1314 #if CHECKSUM_GEN_IP_INLINE
1315  for (i = 0; i < optlen_aligned/2; i++) {
1316  chk_sum += ((u16_t*)p->payload)[i];
1317  }
1318 #endif /* CHECKSUM_GEN_IP_INLINE */
1319  }
1320 #endif /* IP_OPTIONS_SEND */
1321  /* generate IP header */
1322  if (pbuf_header(p, IP_HLEN)) {
1323  LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_output: not enough room for IP header in pbuf\n"));
1324 
1325  IP_STATS_INC(ip.err);
1327  return ERR_BUF;
1328  }
1329 
1330  iphdr = (struct ip_hdr *)p->payload;
1331  LWIP_ASSERT("check that first pbuf can hold struct ip_hdr",
1332  (p->len >= sizeof(struct ip_hdr)));
1333 
1334  IPH_TTL_SET(iphdr, ttl);
1335  IPH_PROTO_SET(iphdr, proto);
1336 #if CHECKSUM_GEN_IP_INLINE
1337  chk_sum += LWIP_MAKE_U16(proto, ttl);
1338 #endif /* CHECKSUM_GEN_IP_INLINE */
1339 
1340  /* dest cannot be NULL here */
1341  ip_addr_copy(iphdr->dest, *dest);
1342 #if CHECKSUM_GEN_IP_INLINE
1343  chk_sum += ip4_addr_get_u32(&iphdr->dest) & 0xFFFF;
1344  chk_sum += ip4_addr_get_u32(&iphdr->dest) >> 16;
1345 #endif /* CHECKSUM_GEN_IP_INLINE */
1346 
1347  IPH_VHLTOS_SET(iphdr, 4, ip_hlen / 4, tos);
1348 #if CHECKSUM_GEN_IP_INLINE
1349  chk_sum += iphdr->_v_hl_tos;
1350 #endif /* CHECKSUM_GEN_IP_INLINE */
1351  IPH_LEN_SET(iphdr, htons(p->tot_len));
1352 #if CHECKSUM_GEN_IP_INLINE
1353  chk_sum += iphdr->_len;
1354 #endif /* CHECKSUM_GEN_IP_INLINE */
1355  IPH_OFFSET_SET(iphdr, 0);
1356  IPH_ID_SET(iphdr, htons(ip_id));
1357 #if CHECKSUM_GEN_IP_INLINE
1358  chk_sum += iphdr->_id;
1359 #endif /* CHECKSUM_GEN_IP_INLINE */
1360  ++ip_id;
1361 
1362  if (ip_addr_isany(src)) {
1363  ip_addr_copy(iphdr->src, netif->ip_addr);
1364  } else {
1365  /* src cannot be NULL here */
1366  ip_addr_copy(iphdr->src, *src);
1367  }
1368 
1369 #if CHECKSUM_GEN_IP_INLINE
1370  chk_sum += ip4_addr_get_u32(&iphdr->src) & 0xFFFF;
1371  chk_sum += ip4_addr_get_u32(&iphdr->src) >> 16;
1372  chk_sum = (chk_sum >> 16) + (chk_sum & 0xFFFF);
1373  chk_sum = (chk_sum >> 16) + chk_sum;
1374  chk_sum = ~chk_sum;
1375  iphdr->_chksum = chk_sum; /* network order */
1376 #else /* CHECKSUM_GEN_IP_INLINE */
1377  IPH_CHKSUM_SET(iphdr, 0);
1378 #if CHECKSUM_GEN_IP
1379  IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, ip_hlen));
1380 #endif
1381 #endif /* CHECKSUM_GEN_IP_INLINE */
1382  } else {
1383  /* IP header already included in p */
1384  iphdr = (struct ip_hdr *)p->payload;
1385  ip_addr_copy(dest_addr, iphdr->dest);
1386  dest = &dest_addr;
1387  }
1388 
1389  IP_STATS_INC(ip.xmit);
1390 
1391  LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], netif->num));
1392  ip_debug_print(p);
1393 
1394 #if ENABLE_LOOPBACK
1395  if (ip_addr_cmp(dest, &netif->ip_addr)) {
1396  /* Packet to self, enqueue it for loopback */
1397  LWIP_DEBUGF(IP_DEBUG, ("netif_loop_output()"));
1398  return netif_loop_output(netif, p, dest);
1399  }
1400 #if LWIP_IGMP
1401  if ((p->flags & PBUF_FLAG_MCASTLOOP) != 0) {
1402  netif_loop_output(netif, p, dest);
1403  }
1404 #endif /* LWIP_IGMP */
1405 #endif /* ENABLE_LOOPBACK */
1406 #if IP_FRAG
1407  /* don't fragment if interface has mtu set to 0 [loopif] */
1408  if (netif->mtu && (p->tot_len > netif->mtu)) {
1409  return ip_frag(p, netif, dest);
1410  }
1411 #endif /* IP_FRAG */
1412 
1413  LWIP_DEBUGF(IP_DEBUG, ("netif->output()\n"));
1414  return netif->output(netif, p, dest);
1415 }
1416 
1417 /**
1418  * Simple interface to ip_output_if. It finds the outgoing network
1419  * interface and calls upon ip_output_if to do the actual work.
1420  *
1421  * @param p the packet to send (p->payload points to the data, e.g. next
1422  protocol header; if dest == IP_HDRINCL, p already includes an IP
1423  header and p->payload points to that IP header)
1424  * @param src the source IP address to send from (if src == IP_ADDR_ANY, the
1425  * IP address of the netif used to send is used as source address)
1426  * @param dest the destination IP address to send the packet to
1427  * @param ttl the TTL value to be set in the IP header
1428  * @param tos the TOS value to be set in the IP header
1429  * @param proto the PROTOCOL to be set in the IP header
1430  *
1431  * @return ERR_RTE if no route is found
1432  * see ip_output_if() for more return values
1433  */
1434 err_t
1435 ip_output(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
1436  u8_t ttl, u8_t tos, u8_t proto)
1437 {
1438  struct netif *netif;
1439 
1440  /* pbufs passed to IP must have a ref-count of 1 as their payload pointer
1441  gets altered as the packet is passed down the stack */
1442  LWIP_ASSERT("p->ref == 1", p->ref == 1);
1443 
1444  if ((netif = ip_route(dest)) == NULL) {
1445  LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
1446  ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest)));
1447  IP_STATS_INC(ip.rterr);
1448  return ERR_RTE;
1449  }
1450 
1451  return ip_output_if(p, src, dest, ttl, tos, proto, netif);
1452 }
1453 
1454 #if LWIP_NETIF_HWADDRHINT
1455 /** Like ip_output, but takes and addr_hint pointer that is passed on to netif->addr_hint
1456  * before calling ip_output_if.
1457  *
1458  * @param p the packet to send (p->payload points to the data, e.g. next
1459  protocol header; if dest == IP_HDRINCL, p already includes an IP
1460  header and p->payload points to that IP header)
1461  * @param src the source IP address to send from (if src == IP_ADDR_ANY, the
1462  * IP address of the netif used to send is used as source address)
1463  * @param dest the destination IP address to send the packet to
1464  * @param ttl the TTL value to be set in the IP header
1465  * @param tos the TOS value to be set in the IP header
1466  * @param proto the PROTOCOL to be set in the IP header
1467  * @param addr_hint address hint pointer set to netif->addr_hint before
1468  * calling ip_output_if()
1469  *
1470  * @return ERR_RTE if no route is found
1471  * see ip_output_if() for more return values
1472  */
1473 err_t
1474 ip_output_hinted(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
1475  u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint)
1476 {
1477  struct netif *netif;
1478  err_t err;
1479 
1480  /* pbufs passed to IP must have a ref-count of 1 as their payload pointer
1481  gets altered as the packet is passed down the stack */
1482  LWIP_ASSERT("p->ref == 1", p->ref == 1);
1483 
1484  if ((netif = ip_route(dest)) == NULL) {
1485  LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
1486  ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest)));
1487  IP_STATS_INC(ip.rterr);
1488  return ERR_RTE;
1489  }
1490 
1491  netif->addr_hint = addr_hint;
1492  err = ip_output_if(p, src, dest, ttl, tos, proto, netif);
1493  netif->addr_hint = NULL;
1494 
1495  return err;
1496 }
1497 #endif /* LWIP_NETIF_HWADDRHINT*/
1498 
1499 #if IP_DEBUG
1500 /* Print an IP header by using LWIP_DEBUGF
1501  * @param p an IP packet, p->payload pointing to the IP header
1502  */
1503 void
1504 ip_debug_print(struct pbuf *p)
1505 {
1506  struct ip_hdr *iphdr = (struct ip_hdr *)p->payload;
1507  u8_t *payload;
1508 
1509  payload = (u8_t *)iphdr + IP_HLEN;
1510 
1511  LWIP_DEBUGF(IP_DEBUG, ("IP header:\n"));
1512  LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
1513  LWIP_DEBUGF(IP_DEBUG, ("|%2"S16_F" |%2"S16_F" | 0x%02"X16_F" | %5"U16_F" | (v, hl, tos, len)\n",
1514  IPH_V(iphdr),
1515  IPH_HL(iphdr),
1516  IPH_TOS(iphdr),
1517  ntohs(IPH_LEN(iphdr))));
1518  LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
1519  LWIP_DEBUGF(IP_DEBUG, ("| %5"U16_F" |%"U16_F"%"U16_F"%"U16_F"| %4"U16_F" | (id, flags, offset)\n",
1520  ntohs(IPH_ID(iphdr)),
1521  ntohs(IPH_OFFSET(iphdr)) >> 15 & 1,
1522  ntohs(IPH_OFFSET(iphdr)) >> 14 & 1,
1523  ntohs(IPH_OFFSET(iphdr)) >> 13 & 1,
1524  ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK));
1525  LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
1526  LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | 0x%04"X16_F" | (ttl, proto, chksum)\n",
1527  IPH_TTL(iphdr),
1528  IPH_PROTO(iphdr),
1529  ntohs(IPH_CHKSUM(iphdr))));
1530  LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
1531  LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (src)\n",
1532  ip4_addr1_16(&iphdr->src),
1533  ip4_addr2_16(&iphdr->src),
1534  ip4_addr3_16(&iphdr->src),
1535  ip4_addr4_16(&iphdr->src)));
1536  LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
1537  LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (dest)\n",
1538  ip4_addr1_16(&iphdr->dest),
1539  ip4_addr2_16(&iphdr->dest),
1540  ip4_addr3_16(&iphdr->dest),
1541  ip4_addr4_16(&iphdr->dest)));
1542  LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
1543 }
1544 #endif /* IP_DEBUG */
#define ip4_addr_get_u32(src_ipaddr)
Definition: ip_addr.h:181
#define IP_PROTO_ICMP
Definition: ip.h:52
static u16_t ip_id
Definition: ip.c:113
u16_t tot_len
Definition: pbuf.h:90
#define IP_MF
Definition: ip.h:127
#define ip4_addr3_16(ipaddr)
Definition: ip_addr.h:228
#define ICMP_ECHO
Definition: icmp.h:48
err_t ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, u8_t ttl, u8_t tos, u8_t proto, struct netif *netif)
Definition: ip.c:1259
struct netif * current_netif
Definition: ip.c:101
u16_t len
Definition: pbuf.h:93
#define IPH_V(hdr)
Definition: ip.h:144
u16_t inet_chksum(void *dataptr, u16_t len) ICACHE_FLASH_ATTR
Definition: inet_chksum.c:396
#define IPH_TOS(hdr)
Definition: ip.h:146
#define ip_addr_netcmp(addr1, addr2, mask)
Definition: ip_addr.h:194
#define U16_F
Definition: cc.h:61
#define ICMP_ER
Definition: icmp.h:44
struct netif * netif_list
Definition: netif.c:75
err_t ip_input(struct pbuf *p, struct netif *inp)
Definition: ip.c:923
#define IPH_VHLTOS_SET(hdr, v, hl, tos)
Definition: ip.h:154
#define NULL
Definition: def.h:47
#define PERF_STOP(x)
Definition: perf.h:38
#define htons(x)
Definition: def.h:81
#define IP_PROTO_TCP
Definition: ip.h:56
#define IPH_TTL(hdr)
Definition: ip.h:150
netif_output_fn output
Definition: netif.h:154
#define snmp_inc_ipoutdiscards()
Definition: snmp.h:269
#define LWIP_DBG_TRACE
Definition: debug.h:56
#define ICACHE_FLASH_ATTR
Definition: c_types.h:99
#define IPH_PROTO_SET(hdr, proto)
Definition: ip.h:159
u8_t num
Definition: netif.h:197
#define IPH_HL(hdr)
Definition: ip.h:145
#define IP_HDRINCL
Definition: ip.h:64
#define IP_PROTO_IGMP
Definition: ip.h:53
struct netif * eagle_lwip_getif(uint8 index)
#define snmp_inc_ipinreceives()
Definition: snmp.h:261
#define PERF_START
Definition: perf.h:37
#define IP_DEBUG
Definition: opt.h:1875
static u32_t sys_now(void) ICACHE_FLASH_ATTR
Definition: sys.h:235
#define os_printf
Definition: osapi.h:62
#define IPH_CHKSUM(hdr)
Definition: ip.h:152
#define os_zalloc(s)
Definition: mem.h:44
#define PBUF_FLAG_MCASTLOOP
Definition: pbuf.h:74
#define snmp_inc_ipoutnoroutes()
Definition: snmp.h:270
#define PP_HTONS(x)
Definition: def.h:92
#define snmp_inc_ipindelivers()
Definition: snmp.h:267
#define ip_addr_islinklocal(addr1)
Definition: ip_addr.h:210
u8_t flags
Definition: pbuf.h:99
unsigned long u32_t
Definition: cc.h:56
#define ERR_RTE
Definition: err.h:56
#define LWIP_DEBUGF(debug, message)
Definition: debug.h:94
#define os_memset
Definition: osapi.h:38
#define ip_addr_cmp(addr1, addr2)
Definition: ip_addr.h:198
#define IPH_OFFSET_SET(hdr, off)
Definition: ip.h:157
#define ip_addr_copy(dest, src)
Definition: ip_addr.h:162
#define LWIP_DBG_LEVEL_SERIOUS
Definition: debug.h:46
struct netif * next
Definition: netif.h:141
#define ERR_OK
Definition: err.h:52
#define snmp_inc_ipforwdatagrams()
Definition: snmp.h:264
#define IPH_LEN(hdr)
Definition: ip.h:147
#define IP_OFFMASK
Definition: ip.h:128
unsigned long os_random(void)
Definition: pbuf.h:76
struct netif * netif_default
Definition: netif.c:76
u8_t flags
Definition: netif.h:193
#define snmp_inc_ipinhdrerrors()
Definition: snmp.h:262
s8_t err_t
Definition: err.h:47
#define ip_debug_print(p)
Definition: ip.h:206
#define ip_addr_set_any(ipaddr)
Definition: ip_addr.h:170
typedefPACK_STRUCT_END struct ip_addr ip_addr_t
Definition: ip_addr.h:64
struct netif * ip_route(ip_addr_t *dest)
Definition: ip.c:125
#define LWIP_DBG_LEVEL_WARNING
Definition: debug.h:45
Definition: netif.h:139
#define NETIF_FLAG_IGMP
Definition: netif.h:95
#define ip4_addr4_16(ipaddr)
Definition: ip_addr.h:229
ip_addr_t ip_addr
Definition: netif.h:144
#define snmp_inc_ipindiscards()
Definition: snmp.h:266
#define ip_addr_isany(addr1)
Definition: ip_addr.h:200
u16_t mtu
Definition: netif.h:187
#define snmp_inc_ipinunknownprotos()
Definition: snmp.h:265
err_t ip_output(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, u8_t ttl, u8_t tos, u8_t proto)
Definition: ip.c:1435
#define IPH_CHKSUM_SET(hdr, chksum)
Definition: ip.h:160
#define S16_F
Definition: cc.h:60
u8_t pbuf_free(struct pbuf *p) ICACHE_FLASH_ATTR
Definition: pbuf.c:685
ip_addr_t current_iphdr_src
Definition: ip.c:108
#define IPH_TTL_SET(hdr, ttl)
Definition: ip.h:158
#define IP_PROTO_UDP
Definition: ip.h:54
#define snmp_inc_ipinaddrerrors()
Definition: snmp.h:263
ip_addr_t current_iphdr_dest
Definition: ip.c:110
#define ip_addr_isbroadcast(ipaddr, netif)
Definition: ip_addr.h:202
Definition: ip.h:116
#define PP_NTOHS(x)
Definition: def.h:93
#define IP_HLEN
Definition: ip.h:50
u8_t pbuf_header(struct pbuf *p, s16_t header_size) ICACHE_FLASH_ATTR
Definition: pbuf.c:573
#define IPH_OFFSET(hdr)
Definition: ip.h:149
#define ip4_addr1_16(ipaddr)
Definition: ip_addr.h:226
unsigned char u8_t
Definition: cc.h:52
#define MEMCPY(dst, src, len)
Definition: opt.h:84
#define IPH_ID_SET(hdr, id)
Definition: ip.h:156
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:65
#define memcpy(x, a, b)
Definition: platform.h:22
void * payload
Definition: pbuf.h:81
#define IP_STATS_INC(x)
Definition: stats.h:203
char name[2]
Definition: netif.h:195
#define IP_PROTO_UDPLITE
Definition: ip.h:55
#define ip4_addr2_16(ipaddr)
Definition: ip_addr.h:227
ip_addr_t netmask
Definition: netif.h:145
#define netif_is_up(netif)
Definition: netif.h:286
#define X32_F
Definition: cc.h:66
#define IPH_LEN_SET(hdr, len)
Definition: ip.h:155
void pbuf_realloc(struct pbuf *p, u16_t size) ICACHE_FLASH_ATTR
Definition: pbuf.c:492
#define ip_addr_ismulticast(addr1)
Definition: ip_addr.h:208
u16_t ref
Definition: pbuf.h:106
#define LWIP_MAKE_U16(a, b)
Definition: def.h:56
const struct ip_hdr * current_header
Definition: ip.c:106
struct netif *ICACHE_FLASH_ATTR ip_router(ip_addr_t *dest, ip_addr_t *source)
Definition: ip.c:170
#define ntohs(x)
Definition: def.h:82
#define IPH_PROTO(hdr)
Definition: ip.h:151
#define snmp_inc_ipoutrequests()
Definition: snmp.h:268
unsigned short u16_t
Definition: cc.h:54
#define X16_F
Definition: cc.h:62
#define ERR_BUF
Definition: err.h:54
#define IPH_ID(hdr)
Definition: ip.h:148