ReactOS  0.4.13-dev-482-ge57f103
ip.c File Reference
#include "lwip/opt.h"
#include "lwip/ip.h"
#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/ip_frag.h"
#include "lwip/inet_chksum.h"
#include "lwip/netif.h"
#include "lwip/icmp.h"
#include "lwip/igmp.h"
#include "lwip/raw.h"
#include "lwip/udp.h"
#include "lwip/tcp_impl.h"
#include "lwip/snmp.h"
#include "lwip/dhcp.h"
#include "lwip/autoip.h"
#include "lwip/stats.h"
#include "arch/perf.h"
#include <string.h>
Include dependency graph for ip.c:

Go to the source code of this file.

Macros

#define LWIP_INLINE_IP_CHKSUM   1
 
#define CHECKSUM_GEN_IP_INLINE   0
 
#define IP_ACCEPT_LINK_LAYER_ADDRESSING   0
 

Functions

struct netifip_route (ip_addr_t *dest)
 
err_t ip_input (struct pbuf *p, struct netif *inp)
 
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)
 
err_t ip_output (struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, u8_t ttl, u8_t tos, u8_t proto)
 

Variables

struct netifcurrent_netif
 
const struct ip_hdrcurrent_header
 
ip_addr_t current_iphdr_src
 
ip_addr_t current_iphdr_dest
 
static u16_t ip_id
 

Detailed Description

This is the IPv4 layer implementation for incoming and outgoing IP traffic.

See also
ip_frag.c

Definition in file ip.c.

Macro Definition Documentation

◆ CHECKSUM_GEN_IP_INLINE

#define CHECKSUM_GEN_IP_INLINE   0

Definition at line 69 of file ip.c.

◆ IP_ACCEPT_LINK_LAYER_ADDRESSING

#define IP_ACCEPT_LINK_LAYER_ADDRESSING   0

Definition at line 93 of file ip.c.

◆ LWIP_INLINE_IP_CHKSUM

#define LWIP_INLINE_IP_CHKSUM   1

Set this to 0 in the rare case of wanting to call an extra function to generate the IP checksum (in contrast to calculating it on-the-fly).

Definition at line 64 of file ip.c.

Function Documentation

◆ ip_input()

err_t ip_input ( struct pbuf p,
struct netif inp 
)

This function is called by the network interface device driver when an IP packet is received. The function does the basic checks of the IP header such as packet size being at least larger than the header size etc. If the packet was not destined for us, the packet is forwarded (using ip_forward). The IP checksum is always checked.

Finally, the packet is sent to the upper layer protocol input function.

Parameters
pthe received IP packet (p->payload points to IP header)
inpthe netif on which this packet was received
Returns
ERR_OK if the packet was processed (could return ERR_* if it wasn't processed, but currently always returns ERR_OK)

Definition at line 305 of file ip.c.

306 {
307  struct ip_hdr *iphdr;
308  struct netif *netif;
309  u16_t iphdr_hlen;
310  u16_t iphdr_len;
311 #if IP_ACCEPT_LINK_LAYER_ADDRESSING
312  int check_ip_src=1;
313 #endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */
314 
315  IP_STATS_INC(ip.recv);
317 
318  /* identify the IP header */
319  iphdr = (struct ip_hdr *)p->payload;
320  if (IPH_V(iphdr) != 4) {
321  LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_WARNING, ("IP packet dropped due to bad version number %"U16_F"\n", IPH_V(iphdr)));
322  ip_debug_print(p);
323  pbuf_free(p);
324  IP_STATS_INC(ip.err);
325  IP_STATS_INC(ip.drop);
327  return ERR_OK;
328  }
329 
330 #ifdef LWIP_HOOK_IP4_INPUT
331  if (LWIP_HOOK_IP4_INPUT(p, inp)) {
332  /* the packet has been eaten */
333  return ERR_OK;
334  }
335 #endif
336 
337  /* obtain IP header length in number of 32-bit words */
338  iphdr_hlen = IPH_HL(iphdr);
339  /* calculate IP header length in bytes */
340  iphdr_hlen *= 4;
341  /* obtain ip length in bytes */
342  iphdr_len = ntohs(IPH_LEN(iphdr));
343 
344  /* header length exceeds first pbuf length, or ip length exceeds total pbuf length? */
345  if ((iphdr_hlen > p->len) || (iphdr_len > p->tot_len)) {
346  if (iphdr_hlen > p->len) {
348  ("IP header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet dropped.\n",
349  iphdr_hlen, p->len));
350  }
351  if (iphdr_len > p->tot_len) {
353  ("IP (len %"U16_F") is longer than pbuf (len %"U16_F"), IP packet dropped.\n",
354  iphdr_len, p->tot_len));
355  }
356  /* free (drop) packet pbufs */
357  pbuf_free(p);
358  IP_STATS_INC(ip.lenerr);
359  IP_STATS_INC(ip.drop);
361  return ERR_OK;
362  }
363 
364  /* verify checksum */
365 #if CHECKSUM_CHECK_IP
366  if (inet_chksum(iphdr, iphdr_hlen) != 0) {
367 
369  ("Checksum (0x%"X16_F") failed, IP packet dropped.\n", inet_chksum(iphdr, iphdr_hlen)));
370  ip_debug_print(p);
371  pbuf_free(p);
372  IP_STATS_INC(ip.chkerr);
373  IP_STATS_INC(ip.drop);
375  return ERR_OK;
376  }
377 #endif
378 
379  /* Trim pbuf. This should have been done at the netif layer,
380  * but we'll do it anyway just to be sure that its done. */
381  pbuf_realloc(p, iphdr_len);
382 
383  /* copy IP addresses to aligned ip_addr_t */
385  ip_addr_copy(current_iphdr_src, iphdr->src);
386 
387  /* match packet against an interface, i.e. is this packet for us? */
388 #if LWIP_IGMP
390  if ((inp->flags & NETIF_FLAG_IGMP) && (igmp_lookfor_group(inp, &current_iphdr_dest))) {
391  netif = inp;
392  } else {
393  netif = NULL;
394  }
395  } else
396 #endif /* LWIP_IGMP */
397  {
398  /* start trying with inp. if that's not acceptable, start walking the
399  list of configured netifs.
400  'first' is used as a boolean to mark whether we started walking the list */
401  int first = 1;
402  netif = inp;
403  do {
404  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",
409 
410  /* interface is up and configured? */
411  if ((netif_is_up(netif)) && (!ip_addr_isany(&(netif->ip_addr)))) {
412  /* unicast to this interface address? */
414  /* or broadcast on this interface network address? */
416  LWIP_DEBUGF(IP_DEBUG, ("ip_input: packet accepted on interface %c%c\n",
417  netif->name[0], netif->name[1]));
418  /* break out of for loop */
419  break;
420  }
421 #if LWIP_AUTOIP
422  /* connections to link-local addresses must persist after changing
423  the netif's address (RFC3927 ch. 1.9) */
424  if ((netif->autoip != NULL) &&
425  ip_addr_cmp(&current_iphdr_dest, &(netif->autoip->llipaddr))) {
426  LWIP_DEBUGF(IP_DEBUG, ("ip_input: LLA packet accepted on interface %c%c\n",
427  netif->name[0], netif->name[1]));
428  /* break out of for loop */
429  break;
430  }
431 #endif /* LWIP_AUTOIP */
432  }
433  if (first) {
434  first = 0;
435  netif = netif_list;
436  } else {
437  netif = netif->next;
438  }
439  if (netif == inp) {
440  netif = netif->next;
441  }
442  } while(netif != NULL);
443  }
444 
445 #if IP_ACCEPT_LINK_LAYER_ADDRESSING
446  /* Pass DHCP messages regardless of destination address. DHCP traffic is addressed
447  * using link layer addressing (such as Ethernet MAC) so we must not filter on IP.
448  * According to RFC 1542 section 3.1.1, referred by RFC 2131).
449  *
450  * If you want to accept private broadcast communication while a netif is down,
451  * define LWIP_IP_ACCEPT_UDP_PORT(dst_port), e.g.:
452  *
453  * #define LWIP_IP_ACCEPT_UDP_PORT(dst_port) ((dst_port) == PP_NTOHS(12345))
454  */
455  if (netif == NULL) {
456  /* remote port is DHCP server? */
457  if (IPH_PROTO(iphdr) == IP_PROTO_UDP) {
458  struct udp_hdr *udphdr = (struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen);
459  LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: UDP packet to DHCP client port %"U16_F"\n",
460  ntohs(udphdr->dest)));
461  if (IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(udphdr->dest)) {
462  LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: DHCP packet accepted.\n"));
463  netif = inp;
464  check_ip_src = 0;
465  }
466  }
467  }
468 #endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */
469 
470  /* broadcast or multicast packet source address? Compliant with RFC 1122: 3.2.1.3 */
471 #if IP_ACCEPT_LINK_LAYER_ADDRESSING
472  /* DHCP servers need 0.0.0.0 to be allowed as source address (RFC 1.1.2.2: 3.2.1.3/a) */
473  if (check_ip_src && !ip_addr_isany(&current_iphdr_src))
474 #endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */
475  { if ((ip_addr_isbroadcast(&current_iphdr_src, inp)) ||
477  /* packet source is not valid */
478  LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("ip_input: packet source is not valid.\n"));
479  /* free (drop) packet pbufs */
480  pbuf_free(p);
481  IP_STATS_INC(ip.drop);
484  return ERR_OK;
485  }
486  }
487 
488  /* packet not for us? */
489  if (netif == NULL) {
490  /* packet not for us, route or discard */
491  LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: packet not for us.\n"));
492 #if IP_FORWARD
493  /* non-broadcast packet? */
495  /* try to forward IP packet on (other) interfaces */
496  ip_forward(p, iphdr, inp);
497  } else
498 #endif /* IP_FORWARD */
499  {
502  }
503  pbuf_free(p);
504  return ERR_OK;
505  }
506  /* packet consists of multiple fragments? */
507  if ((IPH_OFFSET(iphdr) & PP_HTONS(IP_OFFMASK | IP_MF)) != 0) {
508 #if IP_REASSEMBLY /* packet fragment reassembly code present? */
509  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",
510  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));
511  /* reassemble the packet*/
512  p = ip_reass(p);
513  /* packet not fully reassembled yet? */
514  if (p == NULL) {
515  return ERR_OK;
516  }
517  iphdr = (struct ip_hdr *)p->payload;
518 #else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */
519  pbuf_free(p);
520  LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since it was fragmented (0x%"X16_F") (while IP_REASSEMBLY == 0).\n",
521  ntohs(IPH_OFFSET(iphdr))));
522  IP_STATS_INC(ip.opterr);
523  IP_STATS_INC(ip.drop);
524  /* unsupported protocol feature */
526  return ERR_OK;
527 #endif /* IP_REASSEMBLY */
528  }
529 
530 #if IP_OPTIONS_ALLOWED == 0 /* no support for IP options in the IP header? */
531 
532 #if LWIP_IGMP
533  /* there is an extra "router alert" option in IGMP messages which we allow for but do not police */
534  if((iphdr_hlen > IP_HLEN) && (IPH_PROTO(iphdr) != IP_PROTO_IGMP)) {
535 #else
536  if (iphdr_hlen > IP_HLEN) {
537 #endif /* LWIP_IGMP */
538  LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since there were IP options (while IP_OPTIONS_ALLOWED == 0).\n"));
539  pbuf_free(p);
540  IP_STATS_INC(ip.opterr);
541  IP_STATS_INC(ip.drop);
542  /* unsupported protocol feature */
544  return ERR_OK;
545  }
546 #endif /* IP_OPTIONS_ALLOWED == 0 */
547 
548  /* send to upper layers */
549  LWIP_DEBUGF(IP_DEBUG, ("ip_input: \n"));
550  ip_debug_print(p);
551  LWIP_DEBUGF(IP_DEBUG, ("ip_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len));
552 
553  current_netif = inp;
554  current_header = iphdr;
555 
556 #if LWIP_RAW
557  /* raw input did not eat the packet? */
558  if (raw_input(p, inp) == 0)
559 #endif /* LWIP_RAW */
560  {
561  switch (IPH_PROTO(iphdr)) {
562 #if LWIP_UDP
563  case IP_PROTO_UDP:
564 #if LWIP_UDPLITE
565  case IP_PROTO_UDPLITE:
566 #endif /* LWIP_UDPLITE */
568  udp_input(p, inp);
569  break;
570 #endif /* LWIP_UDP */
571 #if LWIP_TCP
572  case IP_PROTO_TCP:
574  tcp_input(p, inp);
575  break;
576 #endif /* LWIP_TCP */
577 #if LWIP_ICMP
578  case IP_PROTO_ICMP:
580  icmp_input(p, inp);
581  break;
582 #endif /* LWIP_ICMP */
583 #if LWIP_IGMP
584  case IP_PROTO_IGMP:
585  igmp_input(p, inp, &current_iphdr_dest);
586  break;
587 #endif /* LWIP_IGMP */
588  default:
589 #if LWIP_ICMP
590  /* send ICMP destination protocol unreachable unless is was a broadcast */
593  p->payload = iphdr;
594  icmp_dest_unreach(p, ICMP_DUR_PROTO);
595  }
596 #endif /* LWIP_ICMP */
597  pbuf_free(p);
598 
599  LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("Unsupported transport protocol %"U16_F"\n", IPH_PROTO(iphdr)));
600 
601  IP_STATS_INC(ip.proterr);
602  IP_STATS_INC(ip.drop);
604  }
605  }
606 
611 
612  return ERR_OK;
613 }
#define X32_F
Definition: cc.h:41
struct netif * netif_list
Definition: netif.c:75
#define ip_addr_copy(dest, src)
Definition: ip_addr.h:162
#define IPH_ID(hdr)
Definition: ip.h:150
#define snmp_inc_ipinunknownprotos()
Definition: snmp.h:265
#define IP_PROTO_UDPLITE
Definition: ip.h:55
#define IPH_PROTO(hdr)
Definition: ip.h:153
#define IPH_OFFSET(hdr)
Definition: ip.h:151
#define IP_PROTO_ICMP
Definition: ip.h:52
const GLint * first
Definition: glext.h:5794
const struct ip_hdr * current_header
Definition: ip.c:105
void pbuf_realloc(struct pbuf *p, u16_t new_len)
Definition: pbuf.c:430
#define ntohs(x)
Definition: module.h:208
ip_addr_t current_iphdr_dest
Definition: ip.c:109
#define IP_PROTO_IGMP
Definition: ip.h:53
#define ip_addr_isbroadcast(ipaddr, netif)
Definition: ip_addr.h:202
#define IP_DEBUG
Definition: opt.h:1961
#define IP_PROTO_TCP
Definition: ip.h:56
#define snmp_inc_ipindiscards()
Definition: snmp.h:266
smooth NULL
Definition: ftsmooth.c:416
#define snmp_inc_ipinreceives()
Definition: snmp.h:261
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:618
#define IP_HLEN
Definition: ip.h:50
#define LWIP_DEBUGF(debug, message)
Definition: debug.h:95
#define PP_HTONS(x)
Definition: def.h:88
#define snmp_inc_ipindelivers()
Definition: snmp.h:267
u16_t inet_chksum(void *dataptr, u16_t len)
Definition: inet_chksum.c:396
Definition: dhcpd.h:79
#define U16_F
Definition: cc.h:36
#define snmp_inc_ipinhdrerrors()
Definition: snmp.h:262
#define ERR_OK
Definition: err.h:52
struct netif * next
Definition: netif.h:138
Definition: dhcpd.h:61
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define ip_addr_ismulticast(addr1)
Definition: ip_addr.h:208
#define IPH_V(hdr)
Definition: ip.h:146
u8_t flags
Definition: netif.h:192
#define X16_F
Definition: cc.h:38
#define IP_PROTO_UDP
Definition: ip.h:54
Definition: netif.h:136
#define NETIF_FLAG_IGMP
Definition: netif.h:95
ip_addr_t ip_addr
Definition: netif.h:141
#define LWIP_DBG_LEVEL_WARNING
Definition: debug.h:46
#define snmp_inc_ipinaddrerrors()
Definition: snmp.h:263
struct ip_addr src dest
Definition: ip.h:96
#define IP_MF
Definition: dhcpd.h:71
#define ip_addr_isany(addr1)
Definition: ip_addr.h:200
Definition: ip.h:116
#define LWIP_DBG_LEVEL_SERIOUS
Definition: debug.h:47
#define ip_addr_cmp(addr1, addr2)
Definition: ip_addr.h:198
#define IPH_HL(hdr)
Definition: ip.h:147
ip_addr_t current_iphdr_src
Definition: ip.c:107
unsigned char u8_t
Definition: cc.h:23
#define LWIP_DBG_TRACE
Definition: debug.h:57
#define IPH_LEN(hdr)
Definition: ip.h:149
struct netif * current_netif
Definition: ip.c:100
#define IP_STATS_INC(x)
Definition: stats.h:203
char name[2]
Definition: netif.h:194
ip_addr_t netmask
Definition: netif.h:142
#define ip_debug_print(p)
Definition: ip.h:214
#define netif_is_up(netif)
Definition: netif.h:282
unsigned short u16_t
Definition: cc.h:24
#define IP_OFFMASK
Definition: dhcpd.h:72
static void ip_forward(struct pbuf *p, struct ip_hdr *iphdr)
Definition: ip6.c:96
GLfloat GLfloat p
Definition: glext.h:8902
#define ip4_addr_get_u32(src_ipaddr)
Definition: ip_addr.h:181
#define ip_addr_set_any(ipaddr)
Definition: ip_addr.h:170

Referenced by netif_init(), tcpip_input(), and tcpip_thread().

◆ ip_output()

err_t ip_output ( struct pbuf p,
ip_addr_t src,
ip_addr_t dest,
u8_t  ttl,
u8_t  tos,
u8_t  proto 
)

Simple interface to ip_output_if. It finds the outgoing network interface and calls upon ip_output_if to do the actual work.

Parameters
pthe packet to send (p->payload points to the data, e.g. next protocol header; if dest == IP_HDRINCL, p already includes an IP header and p->payload points to that IP header)
srcthe source IP address to send from (if src == IP_ADDR_ANY, the IP address of the netif used to send is used as source address)
destthe destination IP address to send the packet to
ttlthe TTL value to be set in the IP header
tosthe TOS value to be set in the IP header
protothe PROTOCOL to be set in the IP header
Returns
ERR_RTE if no route is found see ip_output_if() for more return values

Definition at line 818 of file ip.c.

820 {
821  struct netif *netif;
822 
823  /* pbufs passed to IP must have a ref-count of 1 as their payload pointer
824  gets altered as the packet is passed down the stack */
825  LWIP_ASSERT("p->ref == 1", p->ref == 1);
826 
827  if ((netif = ip_route(dest)) == NULL) {
828  LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
830  IP_STATS_INC(ip.rterr);
831  return ERR_RTE;
832  }
833 
834  return ip_output_if(p, src, dest, ttl, tos, proto, netif);
835 }
#define ERR_RTE
Definition: err.h:56
#define ip4_addr1_16(ipaddr)
Definition: ip_addr.h:226
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:66
struct netif * ip_route(ip_addr_t *dest)
Definition: ip.c:124
#define IP_DEBUG
Definition: opt.h:1961
smooth NULL
Definition: ftsmooth.c:416
#define LWIP_DEBUGF(debug, message)
Definition: debug.h:95
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:641
#define ip4_addr2_16(ipaddr)
Definition: ip_addr.h:227
#define U16_F
Definition: cc.h:36
Definition: dhcpd.h:61
Definition: netif.h:136
#define ip4_addr3_16(ipaddr)
Definition: ip_addr.h:228
GLenum src
Definition: glext.h:6340
#define ip4_addr4_16(ipaddr)
Definition: ip_addr.h:229
#define IP_STATS_INC(x)
Definition: stats.h:203
static char * dest
Definition: rtl.c:135
GLfloat GLfloat p
Definition: glext.h:8902

◆ ip_output_if()

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 
)

Sends an IP packet on a network interface. This function constructs the IP header and calculates the IP header checksum. If the source IP address is NULL, the IP address of the outgoing network interface is filled in as source address. If the destination IP address is IP_HDRINCL, p is assumed to already include an IP header and p->payload points to it instead of the data.

Parameters
pthe packet to send (p->payload points to the data, e.g. next protocol header; if dest == IP_HDRINCL, p already includes an IP header and p->payload points to that IP header)
srcthe source IP address to send from (if src == IP_ADDR_ANY, the IP address of the netif used to send is used as source address)
destthe destination IP address to send the packet to
ttlthe TTL value to be set in the IP header
tosthe TOS value to be set in the IP header
protothe PROTOCOL to be set in the IP header
netifthe netif on which to send this packet
Returns
ERR_OK if the packet was sent OK ERR_BUF if p doesn't have enough space for IP/LINK headers returns errors returned by netif->output
Note
ip_id: RFC791 "some host may be able to simply use unique identifiers independent of destination"

Definition at line 641 of file ip.c.

644 {
645 #if IP_OPTIONS_SEND
646  return ip_output_if_opt(p, src, dest, ttl, tos, proto, netif, NULL, 0);
647 }
648 
655 err_t ip_output_if_opt(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
656  u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options,
657  u16_t optlen)
658 {
659 #endif /* IP_OPTIONS_SEND */
660  struct ip_hdr *iphdr;
661  ip_addr_t dest_addr;
662 #if CHECKSUM_GEN_IP_INLINE
663  u32_t chk_sum = 0;
664 #endif /* CHECKSUM_GEN_IP_INLINE */
665 
666  /* pbufs passed to IP must have a ref-count of 1 as their payload pointer
667  gets altered as the packet is passed down the stack */
668  LWIP_ASSERT("p->ref == 1", p->ref == 1);
669 
671 
672  /* Should the IP header be generated or is it already included in p? */
673  if (dest != IP_HDRINCL) {
674  u16_t ip_hlen = IP_HLEN;
675 #if IP_OPTIONS_SEND
676  u16_t optlen_aligned = 0;
677  if (optlen != 0) {
678 #if CHECKSUM_GEN_IP_INLINE
679  int i;
680 #endif /* CHECKSUM_GEN_IP_INLINE */
681  /* round up to a multiple of 4 */
682  optlen_aligned = ((optlen + 3) & ~3);
683  ip_hlen += optlen_aligned;
684  /* First write in the IP options */
685  if (pbuf_header(p, optlen_aligned)) {
686  LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_output_if_opt: not enough room for IP options in pbuf\n"));
687  IP_STATS_INC(ip.err);
689  return ERR_BUF;
690  }
691  MEMCPY(p->payload, ip_options, optlen);
692  if (optlen < optlen_aligned) {
693  /* zero the remaining bytes */
694  memset(((char*)p->payload) + optlen, 0, optlen_aligned - optlen);
695  }
696 #if CHECKSUM_GEN_IP_INLINE
697  for (i = 0; i < optlen_aligned/2; i++) {
698  chk_sum += ((u16_t*)p->payload)[i];
699  }
700 #endif /* CHECKSUM_GEN_IP_INLINE */
701  }
702 #endif /* IP_OPTIONS_SEND */
703  /* generate IP header */
704  if (pbuf_header(p, IP_HLEN)) {
705  LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_output: not enough room for IP header in pbuf\n"));
706 
707  IP_STATS_INC(ip.err);
709  return ERR_BUF;
710  }
711 
712  iphdr = (struct ip_hdr *)p->payload;
713  LWIP_ASSERT("check that first pbuf can hold struct ip_hdr",
714  (p->len >= sizeof(struct ip_hdr)));
715 
716  IPH_TTL_SET(iphdr, ttl);
717  IPH_PROTO_SET(iphdr, proto);
718 #if CHECKSUM_GEN_IP_INLINE
719  chk_sum += LWIP_MAKE_U16(proto, ttl);
720 #endif /* CHECKSUM_GEN_IP_INLINE */
721 
722  /* dest cannot be NULL here */
723  ip_addr_copy(iphdr->dest, *dest);
724 #if CHECKSUM_GEN_IP_INLINE
725  chk_sum += ip4_addr_get_u32(&iphdr->dest) & 0xFFFF;
726  chk_sum += ip4_addr_get_u32(&iphdr->dest) >> 16;
727 #endif /* CHECKSUM_GEN_IP_INLINE */
728 
729  IPH_VHL_SET(iphdr, 4, ip_hlen / 4);
730  IPH_TOS_SET(iphdr, tos);
731 #if CHECKSUM_GEN_IP_INLINE
732  chk_sum += LWIP_MAKE_U16(tos, iphdr->_v_hl);
733 #endif /* CHECKSUM_GEN_IP_INLINE */
734  IPH_LEN_SET(iphdr, htons(p->tot_len));
735 #if CHECKSUM_GEN_IP_INLINE
736  chk_sum += iphdr->_len;
737 #endif /* CHECKSUM_GEN_IP_INLINE */
738  IPH_OFFSET_SET(iphdr, 0);
739  IPH_ID_SET(iphdr, htons(ip_id));
740 #if CHECKSUM_GEN_IP_INLINE
741  chk_sum += iphdr->_id;
742 #endif /* CHECKSUM_GEN_IP_INLINE */
743  ++ip_id;
744 
745  if (ip_addr_isany(src)) {
746  ip_addr_copy(iphdr->src, netif->ip_addr);
747  } else {
748  /* src cannot be NULL here */
749  ip_addr_copy(iphdr->src, *src);
750  }
751 
752 #if CHECKSUM_GEN_IP_INLINE
753  chk_sum += ip4_addr_get_u32(&iphdr->src) & 0xFFFF;
754  chk_sum += ip4_addr_get_u32(&iphdr->src) >> 16;
755  chk_sum = (chk_sum >> 16) + (chk_sum & 0xFFFF);
756  chk_sum = (chk_sum >> 16) + chk_sum;
757  chk_sum = ~chk_sum;
758  iphdr->_chksum = chk_sum; /* network order */
759 #else /* CHECKSUM_GEN_IP_INLINE */
760  IPH_CHKSUM_SET(iphdr, 0);
761 #if CHECKSUM_GEN_IP
762  IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, ip_hlen));
763 #endif
764 #endif /* CHECKSUM_GEN_IP_INLINE */
765  } else {
766  /* IP header already included in p */
767  iphdr = (struct ip_hdr *)p->payload;
768  ip_addr_copy(dest_addr, iphdr->dest);
769  dest = &dest_addr;
770  }
771 
772  IP_STATS_INC(ip.xmit);
773 
774  LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], netif->num));
775  ip_debug_print(p);
776 
777 #if ENABLE_LOOPBACK
778  if (ip_addr_cmp(dest, &netif->ip_addr)) {
779  /* Packet to self, enqueue it for loopback */
780  LWIP_DEBUGF(IP_DEBUG, ("netif_loop_output()"));
781  return netif_loop_output(netif, p, dest);
782  }
783 #if LWIP_IGMP
784  if ((p->flags & PBUF_FLAG_MCASTLOOP) != 0) {
785  netif_loop_output(netif, p, dest);
786  }
787 #endif /* LWIP_IGMP */
788 #endif /* ENABLE_LOOPBACK */
789 #if IP_FRAG
790  /* don't fragment if interface has mtu set to 0 [loopif] */
791  if (netif->mtu && (p->tot_len > netif->mtu)) {
792  return ip_frag(p, netif, dest);
793  }
794 #endif /* IP_FRAG */
795 
796  LWIP_DEBUGF(IP_DEBUG, ("netif->output()"));
797  return netif->output(netif, p, dest);
798 }
#define ip_addr_copy(dest, src)
Definition: ip_addr.h:162
#define IPH_TOS_SET(hdr, tos)
Definition: ip.h:157
#define IPH_TTL_SET(hdr, ttl)
Definition: ip.h:161
u8_t pbuf_header(struct pbuf *p, s16_t header_size_increment)
Definition: pbuf.c:511
#define snmp_inc_ipoutdiscards()
Definition: snmp.h:269
typedefPACK_STRUCT_END struct ip_addr ip_addr_t
Definition: ip_addr.h:64
netif_output_fn output
Definition: netif.h:151
static u16_t ip_id
Definition: ip.c:112
u8_t num
Definition: netif.h:196
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:66
#define IPH_VHL_SET(hdr, v, hl)
Definition: ip.h:156
#define IP_DEBUG
Definition: opt.h:1961
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define IP_HDRINCL
Definition: ws2ipdef.h:28
#define PBUF_FLAG_MCASTLOOP
Definition: pbuf.h:71
smooth NULL
Definition: ftsmooth.c:416
s8_t err_t
Definition: err.h:47
#define IP_HLEN
Definition: ip.h:50
#define LWIP_DEBUGF(debug, message)
Definition: debug.h:95
#define snmp_inc_ipoutrequests()
Definition: snmp.h:268
u16_t inet_chksum(void *dataptr, u16_t len)
Definition: inet_chksum.c:396
#define U16_F
Definition: cc.h:36
Definition: dhcpd.h:61
Definition: pbuf.h:79
unsigned long u32_t
Definition: cc.h:25
#define MEMCPY(DST, SRC, BYTES)
Definition: macros.h:231
Definition: netif.h:136
ip_addr_t ip_addr
Definition: netif.h:141
struct ip_addr src dest
Definition: ip.h:96
u16_t mtu
Definition: netif.h:186
GLenum src
Definition: glext.h:6340
#define IPH_OFFSET_SET(hdr, off)
Definition: ip.h:160
#define IPH_ID_SET(hdr, id)
Definition: ip.h:159
#define ip_addr_isany(addr1)
Definition: ip_addr.h:200
Definition: ip.h:116
#define LWIP_DBG_LEVEL_SERIOUS
Definition: debug.h:47
#define ip_addr_cmp(addr1, addr2)
Definition: ip_addr.h:198
#define ERR_BUF
Definition: err.h:54
unsigned char u8_t
Definition: cc.h:23
#define IP_STATS_INC(x)
Definition: stats.h:203
char name[2]
Definition: netif.h:194
#define IPH_CHKSUM_SET(hdr, chksum)
Definition: ip.h:163
#define ip_debug_print(p)
Definition: ip.h:214
#define IPH_PROTO_SET(hdr, proto)
Definition: ip.h:162
static char * dest
Definition: rtl.c:135
unsigned short u16_t
Definition: cc.h:24
GLfloat GLfloat p
Definition: glext.h:8902
#define htons(x)
Definition: module.h:213
#define LWIP_MAKE_U16(a, b)
Definition: def.h:52
#define memset(x, y, z)
Definition: compat.h:39
#define IPH_LEN_SET(hdr, len)
Definition: ip.h:158
#define ip4_addr_get_u32(src_ipaddr)
Definition: ip_addr.h:181

Referenced by ip_output().

◆ ip_route()

struct netif* ip_route ( ip_addr_t dest)

Finds the appropriate network interface for a given IP address. It searches the list of network interfaces linearly. A match is found if the masked IP address of the network interface equals the masked IP address given to the function.

Parameters
destthe destination IP address for which to find the route
Returns
the netif on which to send to reach dest

Definition at line 124 of file ip.c.

125 {
126  struct netif *netif;
127 
128 #ifdef LWIP_HOOK_IP4_ROUTE
129  netif = LWIP_HOOK_IP4_ROUTE(dest);
130  if (netif != NULL) {
131  return netif;
132  }
133 #endif
134 
135  /* iterate through netifs */
136  for (netif = netif_list; netif != NULL; netif = netif->next) {
137  /* network mask matches? */
138  if (netif_is_up(netif)) {
139  if (ip_addr_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) {
140  /* return netif on which to forward IP packet */
141  return netif;
142  }
143  }
144  }
145  if ((netif_default == NULL) || (!netif_is_up(netif_default))) {
146  LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_route: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
148  IP_STATS_INC(ip.rterr);
150  return NULL;
151  }
152  /* no matching netif found, use default netif */
153  return netif_default;
154 }
struct netif * netif_list
Definition: netif.c:75
struct netif * netif_default
Definition: netif.c:76
#define snmp_inc_ipoutnoroutes()
Definition: snmp.h:270
#define ip4_addr1_16(ipaddr)
Definition: ip_addr.h:226
#define IP_DEBUG
Definition: opt.h:1961
smooth NULL
Definition: ftsmooth.c:416
#define LWIP_DEBUGF(debug, message)
Definition: debug.h:95
#define ip4_addr2_16(ipaddr)
Definition: ip_addr.h:227
#define U16_F
Definition: cc.h:36
struct netif * next
Definition: netif.h:138
Definition: dhcpd.h:61
Definition: netif.h:136
ip_addr_t ip_addr
Definition: netif.h:141
#define ip4_addr3_16(ipaddr)
Definition: ip_addr.h:228
#define ip4_addr4_16(ipaddr)
Definition: ip_addr.h:229
#define LWIP_DBG_LEVEL_SERIOUS
Definition: debug.h:47
#define IP_STATS_INC(x)
Definition: stats.h:203
ip_addr_t netmask
Definition: netif.h:142
#define netif_is_up(netif)
Definition: netif.h:282
static char * dest
Definition: rtl.c:135
#define ip_addr_netcmp(addr1, addr2, mask)
Definition: ip_addr.h:194

Referenced by ip_output().

Variable Documentation

◆ current_header

const struct ip_hdr* current_header

Header of the input packet currently being processed.

Definition at line 105 of file ip.c.

Referenced by ip_input().

◆ current_iphdr_dest

ip_addr_t current_iphdr_dest

Destination IP address of current_header

Definition at line 109 of file ip.c.

Referenced by ip_input().

◆ current_iphdr_src

ip_addr_t current_iphdr_src

Source IP address of current_header

Definition at line 107 of file ip.c.

Referenced by ip_input().

◆ current_netif

struct netif* current_netif

The interface that provided the packet for the current callback invocation.

Definition at line 100 of file ip.c.

Referenced by ip_input().

◆ ip_id

u16_t ip_id
static

The IP header ID of the next outgoing IP packet

Definition at line 112 of file ip.c.