ReactOS 0.4.15-dev-8339-g4028de8
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)));
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)));
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;
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"));
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 PP_HTONS(x)
Definition: def.h:88
#define IP_OFFMASK
Definition: dhcpd.h:72
#define IP_MF
Definition: dhcpd.h:71
#define NULL
Definition: types.h:112
#define X16_F
Definition: cc.h:38
#define U16_F
Definition: cc.h:36
#define X32_F
Definition: cc.h:41
unsigned char u8_t
Definition: cc.h:23
unsigned short u16_t
Definition: cc.h:24
static void ip_forward(struct pbuf *p, struct ip_hdr *iphdr)
Definition: ip6.c:96
#define IPH_V(hdr)
Definition: ip.h:146
#define IP_PROTO_UDPLITE
Definition: ip.h:55
#define IP_PROTO_IGMP
Definition: ip.h:53
#define IPH_OFFSET(hdr)
Definition: ip.h:151
#define IP_PROTO_TCP
Definition: ip.h:56
#define IP_PROTO_UDP
Definition: ip.h:54
#define IPH_HL(hdr)
Definition: ip.h:147
#define ip_debug_print(p)
Definition: ip.h:214
#define IPH_PROTO(hdr)
Definition: ip.h:153
#define IP_PROTO_ICMP
Definition: ip.h:52
#define IP_HLEN
Definition: ip.h:50
#define IPH_ID(hdr)
Definition: ip.h:150
#define IPH_LEN(hdr)
Definition: ip.h:149
#define LWIP_DBG_LEVEL_SERIOUS
Definition: debug.h:47
#define LWIP_DEBUGF(debug, message)
Definition: debug.h:95
#define LWIP_DBG_LEVEL_WARNING
Definition: debug.h:46
#define LWIP_DBG_TRACE
Definition: debug.h:57
#define ERR_OK
Definition: err.h:52
#define snmp_inc_ipinhdrerrors()
Definition: snmp.h:262
#define snmp_inc_ipindelivers()
Definition: snmp.h:267
#define snmp_inc_ipindiscards()
Definition: snmp.h:266
#define snmp_inc_ipinaddrerrors()
Definition: snmp.h:263
#define snmp_inc_ipinunknownprotos()
Definition: snmp.h:265
#define snmp_inc_ipinreceives()
Definition: snmp.h:261
const GLint * first
Definition: glext.h:5794
GLfloat GLfloat p
Definition: glext.h:8902
#define IP_DEBUG
Definition: lwipopts.h:135
u16_t inet_chksum(void *dataptr, u16_t len)
Definition: inet_chksum.c:396
#define ip_addr_cmp(addr1, addr2)
Definition: ip_addr.h:198
#define ip_addr_isany(addr1)
Definition: ip_addr.h:200
#define ip_addr_ismulticast(addr1)
Definition: ip_addr.h:208
#define ip_addr_copy(dest, src)
Definition: ip_addr.h:162
#define ip_addr_isbroadcast(ipaddr, netif)
Definition: ip_addr.h:202
#define ip_addr_set_any(ipaddr)
Definition: ip_addr.h:170
#define ip4_addr_get_u32(src_ipaddr)
Definition: ip_addr.h:181
if(dx< 0)
Definition: linetemp.h:194
const struct ip_hdr * current_header
Definition: ip.c:105
ip_addr_t current_iphdr_src
Definition: ip.c:107
ip_addr_t current_iphdr_dest
Definition: ip.c:109
struct netif * current_netif
Definition: ip.c:100
@ ICMP_DUR_PROTO
Definition: icmp.h:59
#define ntohs(x)
Definition: module.h:210
struct netif * netif_list
Definition: netif.c:75
#define netif_is_up(netif)
Definition: netif.h:282
#define NETIF_FLAG_IGMP
Definition: netif.h:95
void pbuf_realloc(struct pbuf *p, u16_t new_len)
Definition: pbuf.c:430
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:618
#define IP_STATS_INC(x)
Definition: stats.h:203
Definition: ip.h:116
struct ip_addr src dest
Definition: ip.h:96
Definition: dhcpd.h:62
Definition: netif.h:136
u8_t flags
Definition: netif.h:192
char name[2]
Definition: netif.h:194
ip_addr_t netmask
Definition: netif.h:142
ip_addr_t ip_addr
Definition: netif.h:141
struct netif * next
Definition: netif.h:138
Definition: dhcpd.h:79

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 LWIP_ASSERT(message, assertion)
Definition: debug.h:66
#define ERR_RTE
Definition: err.h:56
GLenum src
Definition: glext.h:6340
#define ip4_addr1_16(ipaddr)
Definition: ip_addr.h:226
#define ip4_addr2_16(ipaddr)
Definition: ip_addr.h:227
#define ip4_addr3_16(ipaddr)
Definition: ip_addr.h:228
#define ip4_addr4_16(ipaddr)
Definition: ip_addr.h:229
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
struct netif * ip_route(ip_addr_t *dest)
Definition: ip.c:124
static char * dest
Definition: rtl.c:135

◆ 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
655err_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));
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 LWIP_MAKE_U16(a, b)
Definition: def.h:52
unsigned long u32_t
Definition: cc.h:25
#define IPH_VHL_SET(hdr, v, hl)
Definition: ip.h:156
#define IPH_LEN_SET(hdr, len)
Definition: ip.h:158
#define IPH_ID_SET(hdr, id)
Definition: ip.h:159
#define IPH_PROTO_SET(hdr, proto)
Definition: ip.h:162
#define IPH_OFFSET_SET(hdr, off)
Definition: ip.h:160
#define IP_HDRINCL
Definition: ip.h:64
#define IPH_TTL_SET(hdr, ttl)
Definition: ip.h:161
#define IPH_CHKSUM_SET(hdr, chksum)
Definition: ip.h:163
#define IPH_TOS_SET(hdr, tos)
Definition: ip.h:157
#define ERR_BUF
Definition: err.h:54
s8_t err_t
Definition: err.h:47
#define snmp_inc_ipoutrequests()
Definition: snmp.h:268
#define snmp_inc_ipoutdiscards()
Definition: snmp.h:269
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
typedefPACK_STRUCT_END struct ip_addr ip_addr_t
Definition: ip_addr.h:64
static u16_t ip_id
Definition: ip.c:112
#define MEMCPY(DST, SRC, BYTES)
Definition: macros.h:231
#define htons(x)
Definition: module.h:215
u8_t pbuf_header(struct pbuf *p, s16_t header_size_increment)
Definition: pbuf.c:511
#define PBUF_FLAG_MCASTLOOP
Definition: pbuf.h:71
#define memset(x, y, z)
Definition: compat.h:39
netif_output_fn output
Definition: netif.h:151
u8_t num
Definition: netif.h:196
u16_t mtu
Definition: netif.h:186
Definition: pbuf.h:79

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 }
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}
#define snmp_inc_ipoutnoroutes()
Definition: snmp.h:270
#define ip_addr_netcmp(addr1, addr2, mask)
Definition: ip_addr.h:194
struct netif * netif_default
Definition: netif.c:76

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(), and test_tcp_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(), and test_tcp_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(), and test_tcp_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(), and test_tcp_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.