ReactOS 0.4.15-dev-7961-gdcf9eb0
ip.c
Go to the documentation of this file.
1
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 "arch/perf.h"
58
59#include <string.h>
60
63#ifndef LWIP_INLINE_IP_CHKSUM
64#define LWIP_INLINE_IP_CHKSUM 1
65#endif
66#if LWIP_INLINE_IP_CHKSUM && CHECKSUM_GEN_IP
67#define CHECKSUM_GEN_IP_INLINE 1
68#else
69#define CHECKSUM_GEN_IP_INLINE 0
70#endif
71
72#if LWIP_DHCP || defined(LWIP_IP_ACCEPT_UDP_PORT)
73#define IP_ACCEPT_LINK_LAYER_ADDRESSING 1
74
80#if LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT)
81/* accept DHCP client port and custom port */
82#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) (((port) == PP_NTOHS(DHCP_CLIENT_PORT)) \
83 || (LWIP_IP_ACCEPT_UDP_PORT(port)))
84#elif defined(LWIP_IP_ACCEPT_UDP_PORT) /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */
85/* accept custom port only */
86#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) (LWIP_IP_ACCEPT_UDP_PORT(port))
87#else /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */
88/* accept DHCP client port only */
89#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) ((port) == PP_NTOHS(DHCP_CLIENT_PORT))
90#endif /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */
91
92#else /* LWIP_DHCP */
93#define IP_ACCEPT_LINK_LAYER_ADDRESSING 0
94#endif /* LWIP_DHCP */
95
101
105const struct ip_hdr *current_header;
110
113
123struct netif *
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}
155
156#if IP_FORWARD
165static int
166ip_canforward(struct pbuf *p)
167{
169
170 if (p->flags & PBUF_FLAG_LLBCAST) {
171 /* don't route link-layer broadcasts */
172 return 0;
173 }
174 if ((p->flags & PBUF_FLAG_LLMCAST) && !IP_MULTICAST(addr)) {
175 /* don't route link-layer multicasts unless the destination address is an IP
176 multicast address */
177 return 0;
178 }
179 if (IP_EXPERIMENTAL(addr)) {
180 return 0;
181 }
182 if (IP_CLASSA(addr)) {
184 if ((net == 0) || (net == (IP_LOOPBACKNET << IP_CLASSA_NSHIFT))) {
185 /* don't route loopback packets */
186 return 0;
187 }
188 }
189 return 1;
190}
191
201static void
202ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
203{
204 struct netif *netif;
205
207
208 if (!ip_canforward(p)) {
209 goto return_noroute;
210 }
211
212 /* RFC3927 2.7: do not forward link-local addresses */
214 LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not forwarding LLA %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
217 goto return_noroute;
218 }
219
220 /* Find network interface where to forward this IP packet to. */
222 if (netif == NULL) {
223 LWIP_DEBUGF(IP_DEBUG, ("ip_forward: no forwarding route for %"U16_F".%"U16_F".%"U16_F".%"U16_F" found\n",
226 /* @todo: send ICMP_DUR_NET? */
227 goto return_noroute;
228 }
229#if !IP_FORWARD_ALLOW_TX_ON_RX_NETIF
230 /* Do not forward packets onto the same network interface on which
231 * they arrived. */
232 if (netif == inp) {
233 LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not bouncing packets back on incoming interface.\n"));
234 goto return_noroute;
235 }
236#endif /* IP_FORWARD_ALLOW_TX_ON_RX_NETIF */
237
238 /* decrement TTL */
239 IPH_TTL_SET(iphdr, IPH_TTL(iphdr) - 1);
240 /* send ICMP if TTL == 0 */
241 if (IPH_TTL(iphdr) == 0) {
243#if LWIP_ICMP
244 /* Don't send ICMP messages in response to ICMP messages */
245 if (IPH_PROTO(iphdr) != IP_PROTO_ICMP) {
246 icmp_time_exceeded(p, ICMP_TE_TTL);
247 }
248#endif /* LWIP_ICMP */
249 return;
250 }
251
252 /* Incrementally update the IP checksum. */
253 if (IPH_CHKSUM(iphdr) >= PP_HTONS(0xffffU - 0x100)) {
254 IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + PP_HTONS(0x100) + 1);
255 } else {
256 IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + PP_HTONS(0x100));
257 }
258
259 LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
262
263 IP_STATS_INC(ip.fw);
264 IP_STATS_INC(ip.xmit);
266
267 PERF_STOP("ip_forward");
268 /* don't fragment if interface has mtu set to 0 [loopif] */
269 if (netif->mtu && (p->tot_len > netif->mtu)) {
270 if ((IPH_OFFSET(iphdr) & PP_NTOHS(IP_DF)) == 0) {
271#if IP_FRAG
272 ip_frag(p, netif, ip_current_dest_addr());
273#else /* IP_FRAG */
274 /* @todo: send ICMP Destination Unreacheable code 13 "Communication administratively prohibited"? */
275#endif /* IP_FRAG */
276 } else {
277 /* send ICMP Destination Unreacheable code 4: "Fragmentation Needed and DF Set" */
278 icmp_dest_unreach(p, ICMP_DUR_FRAG);
279 }
280 return;
281 }
282 /* transmit pbuf on chosen interface */
284 return;
285return_noroute:
287}
288#endif /* IP_FORWARD */
289
304err_t
305ip_input(struct pbuf *p, struct netif *inp)
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}
614
640err_t
642 u8_t ttl, u8_t tos,
643 u8_t proto, struct netif *netif)
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}
799
817err_t
819 u8_t ttl, u8_t tos, u8_t proto)
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}
836
837#if LWIP_NETIF_HWADDRHINT
856err_t
857ip_output_hinted(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
858 u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint)
859{
860 struct netif *netif;
861 err_t err;
862
863 /* pbufs passed to IP must have a ref-count of 1 as their payload pointer
864 gets altered as the packet is passed down the stack */
865 LWIP_ASSERT("p->ref == 1", p->ref == 1);
866
867 if ((netif = ip_route(dest)) == NULL) {
868 LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
870 IP_STATS_INC(ip.rterr);
871 return ERR_RTE;
872 }
873
874 NETIF_SET_HWADDRHINT(netif, addr_hint);
875 err = ip_output_if(p, src, dest, ttl, tos, proto, netif);
877
878 return err;
879}
880#endif /* LWIP_NETIF_HWADDRHINT*/
881
882#if IP_DEBUG
883/* Print an IP header by using LWIP_DEBUGF
884 * @param p an IP packet, p->payload pointing to the IP header
885 */
886void
887ip_debug_print(struct pbuf *p)
888{
889 struct ip_hdr *iphdr = (struct ip_hdr *)p->payload;
890
891 LWIP_DEBUGF(IP_DEBUG, ("IP header:\n"));
892 LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
893 LWIP_DEBUGF(IP_DEBUG, ("|%2"S16_F" |%2"S16_F" | 0x%02"X16_F" | %5"U16_F" | (v, hl, tos, len)\n",
894 IPH_V(iphdr),
895 IPH_HL(iphdr),
896 IPH_TOS(iphdr),
897 ntohs(IPH_LEN(iphdr))));
898 LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
899 LWIP_DEBUGF(IP_DEBUG, ("| %5"U16_F" |%"U16_F"%"U16_F"%"U16_F"| %4"U16_F" | (id, flags, offset)\n",
900 ntohs(IPH_ID(iphdr)),
901 ntohs(IPH_OFFSET(iphdr)) >> 15 & 1,
902 ntohs(IPH_OFFSET(iphdr)) >> 14 & 1,
903 ntohs(IPH_OFFSET(iphdr)) >> 13 & 1,
904 ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK));
905 LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
906 LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | 0x%04"X16_F" | (ttl, proto, chksum)\n",
907 IPH_TTL(iphdr),
908 IPH_PROTO(iphdr),
909 ntohs(IPH_CHKSUM(iphdr))));
910 LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
911 LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (src)\n",
912 ip4_addr1_16(&iphdr->src),
913 ip4_addr2_16(&iphdr->src),
914 ip4_addr3_16(&iphdr->src),
915 ip4_addr4_16(&iphdr->src)));
916 LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
917 LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (dest)\n",
918 ip4_addr1_16(&iphdr->dest),
919 ip4_addr2_16(&iphdr->dest),
920 ip4_addr3_16(&iphdr->dest),
921 ip4_addr4_16(&iphdr->dest)));
922 LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
923}
924#endif /* IP_DEBUG */
#define PP_HTONS(x)
Definition: def.h:88
#define LWIP_MAKE_U16(a, b)
Definition: def.h:52
#define PP_NTOHS(x)
Definition: def.h:89
#define IP_OFFMASK
Definition: dhcpd.h:72
#define IP_DF
Definition: dhcpd.h:70
#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 S16_F
Definition: cc.h:37
#define X32_F
Definition: cc.h:41
unsigned long u32_t
Definition: cc.h:25
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_VHL_SET(hdr, v, hl)
Definition: ip.h:156
#define IPH_V(hdr)
Definition: ip.h:146
#define IPH_LEN_SET(hdr, len)
Definition: ip.h:158
#define IPH_TTL(hdr)
Definition: ip.h:152
#define IPH_TOS(hdr)
Definition: ip.h:148
#define IPH_ID_SET(hdr, id)
Definition: ip.h:159
#define IP_PROTO_UDPLITE
Definition: ip.h:55
#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 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_CHKSUM(hdr)
Definition: ip.h:154
#define IPH_HL(hdr)
Definition: ip.h:147
#define ip_debug_print(p)
Definition: ip.h:214
#define ip_current_dest_addr()
Definition: ip.h:202
#define IPH_TTL_SET(hdr, ttl)
Definition: ip.h:161
#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 IPH_CHKSUM_SET(hdr, chksum)
Definition: ip.h:163
#define IPH_TOS_SET(hdr, tos)
Definition: ip.h:157
#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_ASSERT(message, assertion)
Definition: debug.h:66
#define LWIP_DBG_TRACE
Definition: debug.h:57
#define ERR_OK
Definition: err.h:52
#define ERR_RTE
Definition: err.h:56
#define ERR_BUF
Definition: err.h:54
s8_t err_t
Definition: err.h:47
#define snmp_inc_ipinhdrerrors()
Definition: snmp.h:262
#define snmp_inc_ipoutnoroutes()
Definition: snmp.h:270
#define snmp_inc_ipindelivers()
Definition: snmp.h:267
#define snmp_inc_ipindiscards()
Definition: snmp.h:266
#define snmp_inc_ipoutrequests()
Definition: snmp.h:268
#define snmp_inc_ipinaddrerrors()
Definition: snmp.h:263
#define snmp_inc_ipforwdatagrams()
Definition: snmp.h:264
#define snmp_inc_ipinunknownprotos()
Definition: snmp.h:265
#define snmp_inc_ipoutdiscards()
Definition: snmp.h:269
#define snmp_inc_ipinreceives()
Definition: snmp.h:261
GLenum src
Definition: glext.h:6340
const GLint * first
Definition: glext.h:5794
GLenum const GLvoid * addr
Definition: glext.h:9621
GLfloat GLfloat p
Definition: glext.h:8902
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_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 ip4_addr1_16(ipaddr)
Definition: ip_addr.h:226
#define IP_CLASSA(a)
Definition: ip_addr.h:108
#define ip_addr_ismulticast(addr1)
Definition: ip_addr.h:208
#define ip_addr_netcmp(addr1, addr2, mask)
Definition: ip_addr.h:194
#define ip4_addr2_16(ipaddr)
Definition: ip_addr.h:227
#define IP_CLASSA_NET
Definition: ip_addr.h:109
#define IP_MULTICAST(a)
Definition: ip_addr.h:129
#define ip_addr_islinklocal(addr1)
Definition: ip_addr.h:210
#define ip_addr_copy(dest, src)
Definition: ip_addr.h:162
typedefPACK_STRUCT_END struct ip_addr ip_addr_t
Definition: ip_addr.h:64
#define ip_addr_isbroadcast(ipaddr, netif)
Definition: ip_addr.h:202
#define ip_addr_set_any(ipaddr)
Definition: ip_addr.h:170
#define ip4_addr3_16(ipaddr)
Definition: ip_addr.h:228
#define IP_LOOPBACKNET
Definition: ip_addr.h:134
#define IP_EXPERIMENTAL(a)
Definition: ip_addr.h:131
#define ip4_addr4_16(ipaddr)
Definition: ip_addr.h:229
#define ip4_addr_get_u32(src_ipaddr)
Definition: ip_addr.h:181
#define IP_CLASSA_NSHIFT
Definition: ip_addr.h:110
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
err_t ip_input(struct pbuf *p, struct netif *inp)
Definition: ip.c:305
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
ip_addr_t current_iphdr_dest
Definition: ip.c:109
struct netif * current_netif
Definition: ip.c:100
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:818
static u16_t ip_id
Definition: ip.c:112
struct netif * ip_route(ip_addr_t *dest)
Definition: ip.c:124
@ ICMP_TE_TTL
Definition: icmp.h:66
@ ICMP_DUR_PROTO
Definition: icmp.h:59
@ ICMP_DUR_FRAG
Definition: icmp.h:61
#define MEMCPY(DST, SRC, BYTES)
Definition: macros.h:231
#define htons(x)
Definition: module.h:215
#define ntohs(x)
Definition: module.h:210
static char * dest
Definition: rtl.c:135
struct netif * netif_list
Definition: netif.c:75
struct netif * netif_default
Definition: netif.c:76
#define netif_is_up(netif)
Definition: netif.h:282
#define NETIF_FLAG_IGMP
Definition: netif.h:95
#define NETIF_SET_HWADDRHINT(netif, hint)
Definition: netif.h:321
u8_t pbuf_header(struct pbuf *p, s16_t header_size_increment)
Definition: pbuf.c:511
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 PBUF_FLAG_LLBCAST
Definition: pbuf.h:73
#define PBUF_FLAG_MCASTLOOP
Definition: pbuf.h:71
#define PBUF_FLAG_LLMCAST
Definition: pbuf.h:75
#define PERF_START
Definition: perf.h:3
#define PERF_STOP
Definition: perf.h:4
#define err(...)
#define memset(x, y, z)
Definition: compat.h:39
#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
netif_output_fn output
Definition: netif.h:151
ip_addr_t ip_addr
Definition: netif.h:141
u8_t num
Definition: netif.h:196
u16_t mtu
Definition: netif.h:186
struct netif * next
Definition: netif.h:138
Definition: pbuf.h:79
Definition: dhcpd.h:79
static TNetwork net
Definition: tncon.cpp:351