• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * @file
3  *
4  * IPv6 layer.
5  */
6 
7 /*
8  * Copyright (c) 2010 Inico Technologies Ltd.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without modification,
12  * are permitted provided that the following conditions are met:
13  *
14  * 1. Redistributions of source code must retain the above copyright notice,
15  *    this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright notice,
17  *    this list of conditions and the following disclaimer in the documentation
18  *    and/or other materials provided with the distribution.
19  * 3. The name of the author may not be used to endorse or promote products
20  *    derived from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
23  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
25  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
27  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
31  * OF SUCH DAMAGE.
32  *
33  * This file is part of the lwIP TCP/IP stack.
34  *
35  * Author: Ivan Delamer <delamer@inicotech.com>
36  *
37  *
38  * Please coordinate changes and requests with Ivan Delamer
39  * <delamer@inicotech.com>
40  */
41 
42 #include "lwip/opt.h"
43 
44 #if LWIP_IPV6  /* don't build if not configured for use in lwipopts.h */
45 
46 #include "lwip/def.h"
47 #include "lwip/mem.h"
48 #include "lwip/netif.h"
49 #include "lwip/ip.h"
50 #include "lwip/ip6.h"
51 #include "lwip/ip6_addr.h"
52 #include "lwip/ip6_frag.h"
53 #include "lwip/icmp6.h"
54 #include "lwip/priv/raw_priv.h"
55 #include "lwip/udp.h"
56 #include "lwip/priv/tcp_priv.h"
57 #include "lwip/dhcp6.h"
58 #include "lwip/nd6.h"
59 #include "lwip/mld6.h"
60 #include "lwip/debug.h"
61 #include "lwip/stats.h"
62 
63 #if LWIP_NAT64
64 #include "lwip/nat64.h"
65 #endif
66 
67 #if LWIP_RIPPLE
68 #include "lwip/lwip_rpl.h"
69 #endif
70 
71 #if LWIP_IP6IN4
72 #include "lwip/ip6in4.h"
73 #endif
74 #if LWIP_MPL
75 #include "mcast6.h"
76 #ifndef MCAST6_IS_FROM_CONN_PEER
77 #define MCAST6_IS_FROM_CONN_PEER mcast6_esmrf_from_conn_peer
78 #endif /* MCAST6_IS_FROM_CONN_PEER */
79 
80 #ifndef MCAST6_FORWARD
81 #define MCAST6_FORWARD mcast6_esmrf_in
82 #endif /* MCAST6_FORWARD */
83 #endif /* LWIP_MPL */
84 
85 #ifdef LWIP_HOOK_FILENAME
86 #include LWIP_HOOK_FILENAME
87 #endif
88 
89 #if LWIP_IPV6_FILTER
90 /* This function is called when an ip packet received. The return value of this function will
91  * decide accept or drop a ip packet when LWIP_IPV6_FILTER is Enabled and ip_filter function has been set
92  */
93 static ip_filter_fn ip6_filter = NULL;
94 #endif /* LWIP_IPV6_FILTER */
95 
96 #ifndef LWIP_RPI_LEN
97 #define LWIP_RPI_LEN 6
98 #endif
99 
100 #if LWIP_RIPPLE
101 typedef struct {
102   u32_t route_up:1;
103   u32_t next_hop_nonmesh:1;
104 } pkt_rte_status;
105 static pkt_rte_status g_pkt_rte_stat;
106 
107 int
lwip_get_pkt_route_status(void)108 lwip_get_pkt_route_status(void)
109 {
110   return (int)g_pkt_rte_stat.route_up;
111 }
112 
113 void
lwip_set_pkt_route_status(int up)114 lwip_set_pkt_route_status(int up)
115 {
116   g_pkt_rte_stat.route_up = !!up;
117 }
118 
119 int
lwip_get_rte_nexthop_nonmesh(void)120 lwip_get_rte_nexthop_nonmesh(void)
121 {
122   return (int)g_pkt_rte_stat.next_hop_nonmesh;
123 }
124 
125 void
lwip_set_rte_nexthop_nonmesh(int stat)126 lwip_set_rte_nexthop_nonmesh(int stat)
127 {
128   g_pkt_rte_stat.next_hop_nonmesh = !!stat;
129 }
130 
131 /*
132  * Hardcoded lenghth of HBH,
133  * providing function for future enhancement.
134  */
135 u16_t
lwip_hbh_len(struct pbuf * p)136 lwip_hbh_len(struct pbuf *p)
137 {
138   u16_t hbh_len = 0;
139   /* pbuf alloc will pass NULL as pbuf. */
140   if (p == NULL) {
141   /* 2: add for 8 byte Aligned */
142     hbh_len = IP6_HBH_HLEN + LWIP_RPI_LEN;
143   }
144 
145   return hbh_len;
146 }
147 
148 static err_t
ip6_process_hbh_exth_options(struct pbuf * p,const struct netif * iface)149 ip6_process_hbh_exth_options(struct pbuf *p, const struct netif *iface)
150 {
151   u16_t ext_len;
152   u16_t hbh_opt_offset = IP6_OPT_HLEN; /* skipping first 2 header bytes */
153   u16_t tmp_hbh_opt_offset; /* Used two iterator variables to check overflow. */
154   const struct ip6_hdr *ip6hdr = (struct ip6_hdr *)((char *)(p->payload) - IP6_HLEN); /* for accessing dest */
155 
156   struct ip6_opt_hdr *opt_tlv = NULL;
157   struct ip6_hbh_hdr  *ext_hdr = (struct ip6_hbh_hdr *)(p->payload);
158   (void)iface;
159 
160   LWIP_DEBUGF(IP6_DEBUG, ("Next header is [%x]\n", IP6H_NEXTH(ip6hdr)));
161   if (IP6H_NEXTH(ip6hdr) != IP6_NEXTH_HOPBYHOP) {
162     return 0;
163   }
164 
165   LWIP_DEBUGF(IP6_DEBUG, ("nexth %u, hlen %u\n", ext_hdr->_nexth, ext_hdr->_hlen));
166 #if LWIP_RIPPLE
167   /* do not handle non mesh interface packet. */
168   if (lwip_rpl_is_rpl_netif(iface) == lwIP_FALSE) {
169     return ERR_OK;
170   }
171 #endif
172   if (p->len < IP6_HBH_HLEN) {
173     LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
174                 ("IP6_NEXTH_HOPBYHOP: pbuf (len %"U16_F") is less than 2.\n", p->len));
175     /* free (drop) packet pbufs */
176     IP6_STATS_INC(ip6.lenerr);
177     return -1;
178   }
179 
180   /*
181    * max value can be stored in hbh_ext_len(8 bits) is 255
182    * so max value after multilication and addition will be
183    * ((255 * 8) + 8) : 2048 and local variable u16_t ext_len can
184    * store 65535 implies -> No Overflow.
185    */
186   /* hbh hlen is saved in units of octets excluding first octet. */
187   ext_len = (ext_hdr->_hlen << 3) + 8;
188 
189   /* Validate the received IP packet length gainst the hbh total length */
190   if (ext_len > p->len) {
191     LWIP_ERROR("Received malformed packet\n", 0, return -1);
192   }
193 
194   while (hbh_opt_offset < ext_len) {
195     opt_tlv = (struct ip6_opt_hdr *)((char *)(p->payload) + hbh_opt_offset);
196     switch (opt_tlv->_opt_type) {
197       case LWIP_EXT_HDR_OPT_PAD1:
198         LWIP_DEBUGF(IP6_DEBUG, ("processing PAD1 option\n"));
199         tmp_hbh_opt_offset = hbh_opt_offset + 1;
200         LWIP_ERROR("overflow occured in ext len\n", tmp_hbh_opt_offset > hbh_opt_offset, return -1);
201         hbh_opt_offset = tmp_hbh_opt_offset;
202 
203         break;
204       case LWIP_EXT_HDR_OPT_PADN:
205         LWIP_DEBUGF(IP6_DEBUG, ("processing PADN option\n"));
206         tmp_hbh_opt_offset = (u16_t)(hbh_opt_offset + IP6_HBH_HLEN + opt_tlv->_opt_dlen);
207         LWIP_ERROR("overflow occured in ext len\n", tmp_hbh_opt_offset > hbh_opt_offset, return -1);
208         hbh_opt_offset = tmp_hbh_opt_offset;
209         break;
210       case LWIP_RPL_RPI_TYPE_NEW:
211       case LWIP_RPL_RPI_TYPE_OLD:
212         /*
213          * Fixes situation when a node that is not using RPL
214          * joins a network which does. The received packages will include the
215          * RPL header and processed by the "default" case of the switch
216          * (0x63 & 0xC0 = 0x40). Hence, the packet is discarded as the header
217          * is considered invalid.
218          * Using this fix, the header is ignored, and the next header (if
219          * present) is processed.
220          */
221 #if LWIP_RIPPLE
222         LWIP_DEBUGF(IP6_DEBUG, ("Processing RPL opt\n"));
223         if (lwip_verify_rplext_header((void *)p, hbh_opt_offset)) {
224           LWIP_ERROR("RPL Opt Error: Dropping Pkt\n", 0, ;);
225           return -1;
226         }
227 #endif
228         tmp_hbh_opt_offset = (u16_t)(hbh_opt_offset + IP6_HBH_HLEN + opt_tlv->_opt_dlen);
229         LWIP_ERROR("overflow occured in ext len\n", tmp_hbh_opt_offset > hbh_opt_offset, return -1);
230         hbh_opt_offset = tmp_hbh_opt_offset;
231         p->flags |= PBUF_FLAG_RPI;
232         /* Should we return or process rest of the options */
233         return 0;
234       default:
235         /*
236          * check the two highest order bits of the option
237          * - 00 skip over this option and continue processing the header.
238          * - 01 discard the packet.
239          * - 10 discard the packet and, regardless of whether or not the
240          * - packet's Destination Address was a multicast address, send an
241          * - ICMP Parameter Problem, Code 2, message to the packet's
242          * - Source Address, pointing to the unrecognized Option Type.
243          * - 11 discard the packet and, only if the packet's Destination
244          * - Address was not a multicast address, send an ICMP Parameter
245          * - Problem, Code 2, message to the packet's Source Address,
246          * - pointing to the unrecognized Option Type.
247          */
248         LWIP_DEBUGF(IP6_DEBUG, ("MSB %x\n", opt_tlv->_opt_type));
249         switch (opt_tlv->_opt_type & 0xC0) {
250           case 0:
251             break;
252           case 0x40:
253             return -1;
254           case 0xC0:
255             if (ip6_addr_ismulticast(&ip6hdr->dest)) {
256               return -1;
257             }
258           /* fall-through */
259           case 0x80:
260             icmp6_param_problem(p, ICMP6_PP_OPTION, opt_tlv);
261             return -1;
262           default:
263             break;
264         }
265 
266         tmp_hbh_opt_offset = (u16_t)(hbh_opt_offset + IP6_HBH_HLEN + opt_tlv->_opt_dlen);
267         LWIP_ERROR("overflow occured in ext len\n", tmp_hbh_opt_offset > hbh_opt_offset, return -1);
268         hbh_opt_offset = tmp_hbh_opt_offset;
269         break;
270     }
271   }
272 
273   return ERR_OK;
274 }
275 
276 #ifdef LWIP_HOOK_IP6_ROUTE
277 static err_t
lwip_rpl_same_prefix(const ip6_addr_t * dest)278 lwip_rpl_same_prefix(const ip6_addr_t *dest)
279 {
280   ip6_addr_t prefix;
281   uint8_t len;
282   err_t ret;
283 
284   ret = lwip_rpl_get_default_prefix(&prefix, &len);
285   if (ret != ERR_OK) {
286     return ERR_VAL;
287   }
288   /* now our prefix len is 64, this will be ok. */
289   if (memcmp(dest, &prefix, (len >> 3)) != 0) {
290     return ERR_VAL;
291   }
292   return ERR_OK;
293 }
294 #endif
295 #endif /* LWIP_RIPPLE */
296 /**
297  * Finds the appropriate network interface for a given IPv6 address. It tries to select
298  * a netif following a sequence of heuristics:
299  * 1) if there is only 1 netif, return it
300  * 2) if the destination is a zoned address, match its zone to a netif
301  * 3) if the either the source or destination address is a scoped address,
302  *    match the source address's zone (if set) or address (if not) to a netif
303  * 4) tries to match the destination subnet to a configured address
304  * 5) tries to find a router-announced route
305  * 6) tries to match the (unscoped) source address to the netif
306  * 7) returns the default netif, if configured
307  *
308  * Note that each of the two given addresses may or may not be properly zoned.
309  *
310  * @param src the source IPv6 address, if known
311  * @param dest the destination IPv6 address for which to find the route
312  * @return the netif on which to send to reach dest
313  */
314 struct netif *
ip6_route(const ip6_addr_t * src,const ip6_addr_t * dest)315 ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest)
316 {
317 #if LWIP_SINGLE_NETIF
318   LWIP_UNUSED_ARG(src);
319   LWIP_UNUSED_ARG(dest);
320 #else /* LWIP_SINGLE_NETIF */
321   struct netif *netif;
322   s8_t i;
323 
324   LWIP_ASSERT_CORE_LOCKED();
325 
326 #if !LWIP_SO_DONTROUTE
327   /* If single netif configuration, fast return. */
328   if ((netif_list != NULL) && (netif_list->next == NULL)) {
329     if (!netif_is_up(netif_list) || !netif_is_link_up(netif_list) ||
330         (ip6_addr_has_zone(dest) && !ip6_addr_test_zone(dest, netif_list))) {
331       return NULL;
332     }
333     return netif_list;
334   }
335 #endif
336 
337 #if LWIP_IPV6_SCOPES
338   /* Special processing for zoned destination addresses. This includes link-
339    * local unicast addresses and interface/link-local multicast addresses. Use
340    * the zone to find a matching netif. If the address is not zoned, then there
341    * is technically no "wrong" netif to choose, and we leave routing to other
342    * rules; in most cases this should be the scoped-source rule below. */
343   if (ip6_addr_has_zone(dest)) {
344     IP6_ADDR_ZONECHECK(dest);
345     /* Find a netif based on the zone. For custom mappings, one zone may map
346      * to multiple netifs, so find one that can actually send a packet. */
347     NETIF_FOREACH(netif) {
348       if (ip6_addr_test_zone(dest, netif) &&
349           netif_is_up(netif) && netif_is_link_up(netif)) {
350         NETIF_SET_SCOPE(netif, RT_SCOPE_LINK);
351         return netif;
352       }
353     }
354     /* No matching netif found. Do no try to route to a different netif,
355      * as that would be a zone violation, resulting in any packets sent to
356      * that netif being dropped on output. */
357     return NULL;
358   }
359 #endif /* LWIP_IPV6_SCOPES */
360 
361   /* Special processing for scoped source and destination addresses. If we get
362    * here, the destination address does not have a zone, so either way we need
363    * to look at the source address, which may or may not have a zone. If it
364    * does, the zone is restrictive: there is (typically) only one matching
365    * netif for it, and we should avoid routing to any other netif as that would
366    * result in guaranteed zone violations. For scoped source addresses that do
367    * not have a zone, use (only) a netif that has that source address locally
368    * assigned. This case also applies to the loopback source address, which has
369    * an implied link-local scope. If only the destination address is scoped
370    * (but, again, not zoned), we still want to use only the source address to
371    * determine its zone because that's most likely what the user/application
372    * wants, regardless of whether the source address is scoped. Finally, some
373    * of this story also applies if scoping is disabled altogether. */
374 #if LWIP_IPV6_SCOPES
375   if (ip6_addr_has_scope(dest, IP6_UNKNOWN) ||
376       ip6_addr_has_scope(src, IP6_UNICAST) ||
377 #else /* LWIP_IPV6_SCOPES */
378   if (ip6_addr_islinklocal(dest) || ip6_addr_ismulticast_iflocal(dest) ||
379       ip6_addr_ismulticast_linklocal(dest) || ip6_addr_islinklocal(src) ||
380 #endif /* LWIP_IPV6_SCOPES */
381       ip6_addr_isloopback(src)) {
382 #if LWIP_IPV6_SCOPES
383     if (ip6_addr_has_zone(src)) {
384       /* Find a netif matching the source zone (relatively cheap). */
385       NETIF_FOREACH(netif) {
386         if (netif_is_up(netif) && netif_is_link_up(netif) &&
387             ip6_addr_test_zone(src, netif)) {
388           NETIF_SET_SCOPE(netif, RT_SCOPE_LINK);
389           return netif;
390         }
391       }
392     } else
393 #endif /* LWIP_IPV6_SCOPES */
394     {
395       if (ip6_addr_isany(src)) {
396         /* Use default netif, if Up. */
397         if (netif_default == NULL || !netif_is_up(netif_default) ||
398             !netif_is_link_up(netif_default)) {
399           return NULL;
400         }
401         return netif_default;
402       }
403       /* Find a netif matching the source address (relatively expensive). */
404       NETIF_FOREACH(netif) {
405         if (!netif_is_up(netif) || !netif_is_link_up(netif)) {
406           continue;
407         }
408         for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
409           if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
410               ip6_addr_cmp_zoneless(src, netif_ip6_addr(netif, i))) {
411             NETIF_SET_SCOPE(netif, RT_SCOPE_HOST);
412             return netif;
413           }
414         }
415       }
416     }
417     /* Again, do not use any other netif in this case, as that could result in
418      * zone boundary violations. */
419     return NULL;
420   }
421 
422   /* We come here only if neither source nor destination is scoped. */
423   IP6_ADDR_ZONECHECK(src);
424 
425 #ifdef LWIP_HOOK_IP6_ROUTE
426   netif = LWIP_HOOK_IP6_ROUTE(src, dest);
427   if (netif != NULL) {
428     NETIF_SET_SCOPE(netif, RT_SCOPE_UNIVERSAL);
429     return netif;
430   }
431 #endif
432 
433 #if LWIP_RIPPLE
434   u8_t dest_same_prefix = lwIP_FALSE;
435   if (lwip_rpl_same_prefix(dest) == ERR_OK) {
436     dest_same_prefix = lwIP_TRUE;
437   }
438 
439   /* for the mbr node, first to check the default route */
440   netif = nd6_find_route(dest);
441   if ((netif != NULL) && netif_is_up(netif) && netif_is_link_up(netif) &&
442       (dest_same_prefix == lwIP_TRUE) && (lwip_rpl_is_br() == lwIP_TRUE) &&
443       (lwip_rpl_is_rpl_netif(netif) == lwIP_FALSE)) {
444     return netif;
445   }
446 
447   if ((netif_default != NULL) && netif_is_up(netif_default) && netif_is_link_up(netif_default) &&
448       (dest_same_prefix == lwIP_TRUE) && (lwip_rpl_is_br() == lwIP_TRUE) &&
449       (lwip_rpl_is_rpl_netif(netif_default) == lwIP_FALSE)) {
450     return netif_default;
451   }
452 #endif /* LWIP_RIPPLE */
453 
454 
455   /* See if the destination subnet matches a configured address. In accordance
456    * with RFC 5942, dynamically configured addresses do not have an implied
457    * local subnet, and thus should be considered /128 assignments. However, as
458    * such, the destination address may still match a local address, and so we
459    * still need to check for exact matches here. By (lwIP) policy, statically
460    * configured addresses do always have an implied local /64 subnet. */
461   NETIF_FOREACH(netif) {
462     if (!netif_is_up(netif) || !netif_is_link_up(netif)) {
463       continue;
464     }
465     for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
466       if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
467           ip6_addr_netcmp(dest, netif_ip6_addr(netif, i)) &&
468           (netif_ip6_addr_isstatic(netif, i) ||
469           ip6_addr_nethostcmp(dest, netif_ip6_addr(netif, i)))) {
470         NETIF_SET_SCOPE(netif, RT_SCOPE_UNIVERSAL);
471         return netif;
472       }
473     }
474   }
475 
476   /* Get the netif for a suitable router-announced route. */
477   netif = nd6_find_route(dest);
478   if (netif != NULL) {
479     NETIF_SET_SCOPE(netif, RT_SCOPE_UNIVERSAL);
480     return netif;
481   }
482 
483   /* Try with the netif that matches the source address. Given the earlier rule
484    * for scoped source addresses, this applies to unscoped addresses only. */
485   if (!ip6_addr_isany(src)) {
486     NETIF_FOREACH(netif) {
487       if (!netif_is_up(netif) || !netif_is_link_up(netif)) {
488         continue;
489       }
490       for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
491         if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
492             ip6_addr_cmp(src, netif_ip6_addr(netif, i))) {
493           NETIF_SET_SCOPE(netif, RT_SCOPE_HOST);
494           return netif;
495         }
496       }
497     }
498   }
499 
500 #if LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF
501   /* loopif is disabled, loopback traffic is passed through any netif */
502   if (ip6_addr_isloopback(dest)) {
503     /* don't check for link on loopback traffic */
504     if (netif_default != NULL && netif_is_up(netif_default)) {
505 #if LWIP_SO_DONTROUTE
506       netif_default->scope = RT_SCOPE_HOST;
507 #endif
508       return netif_default;
509     }
510     /* default netif is not up, just use any netif for loopback traffic */
511     NETIF_FOREACH(netif) {
512       if (netif_is_up(netif)) {
513         NETIF_SET_SCOPE(netif, RT_SCOPE_HOST);
514         return netif;
515       }
516     }
517     return NULL;
518   }
519 #endif /* LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF */
520 #endif /* !LWIP_SINGLE_NETIF */
521 
522   /* no matching netif found, use default netif, if up */
523   if ((netif_default == NULL) || !netif_is_up(netif_default) || !netif_is_link_up(netif_default)) {
524     return NULL;
525   }
526   NETIF_SET_SCOPE(netif_default, RT_SCOPE_UNIVERSAL);
527   return netif_default;
528 }
529 
530 /**
531  * @ingroup ip6
532  * Select the best IPv6 source address for a given destination
533  * IPv6 address. Loosely follows RFC 3484. "Strong host" behavior
534  * is assumed.
535  *
536  * @param addr1 IPv6 Address 1
537  * @param addr2 IPv6 Address 2
538  * @param prefix_length Length of network prefix(in bits)
539  * @return
540  * Number of common prefix bits in addr1 & addr2 : On success
541  * -1 : Invalid parameters
542  */
ip6_common_prefix_length(const ip6_addr_t * addr1,const ip6_addr_t * addr2,u8_t prefix_length)543 int ip6_common_prefix_length(const ip6_addr_t *addr1, const ip6_addr_t *addr2, u8_t prefix_length)
544 {
545   int common_prefix_length = 0;
546   int i = 0;
547   int bit_index;
548   u8_t *addr1_char = NULL;
549   u8_t *addr2_char = NULL;
550 
551   LWIP_ERROR("ip6_common_prefix_length: addr1 != NULL", (addr1 != NULL), return -1);
552   LWIP_ERROR("ip6_common_prefix_length: addr2 != NULL", (addr2 != NULL), return -1);
553 
554   if ((prefix_length < 1) || (prefix_length > IP6_ADDR_LEN)) {
555     LWIP_DEBUGF(IP6_DEBUG, ("ip6_common_prefix_length: Prefix length = %"X8_F": is invalid", prefix_length));
556     return -1;
557   }
558 
559   // Checking Word-By-Word
560   while ((common_prefix_length < prefix_length) && (i < IP6_ADDR_U32_ARR_SIZE)) {
561     if (addr1->addr[i] == addr2->addr[i]) {
562       common_prefix_length += 32;  // u32_t occupy 32 bits
563       ++i;
564       continue;
565     }
566     break;
567   }
568 
569   // If Already "prefix_length" number of bits are matched, then skip remaining part of the function
570   if (common_prefix_length >= prefix_length) {
571     goto exit;
572   }
573 
574   // Checking Byte-By-Byte
575   addr1_char = (u8_t *)(addr1);
576   addr2_char = (u8_t *)(addr2);
577 
578   // Advancing i To Proper value so that it now indexes the next byte for comparison
579   i *= 4;  // u32_t occupy 4 u8_t
580 
581   while ((common_prefix_length < prefix_length)) {
582     if (addr1_char[i] == addr2_char[i]) {
583       common_prefix_length += 8;  // u8_t occupy 8 bits
584       ++i;
585       continue;
586     }
587     break;
588   }
589 
590   // If Already "prefix_length" number of bits are matched, then skip remaining part of the function
591   if (common_prefix_length >= prefix_length) {
592     goto exit;
593   }
594 
595   // Checking Bit by Bit
596   // bit_index is set to 7 so that the entire eight bits has to be checked
597   bit_index = 7;
598 
599   // Checking whether the first nibble of the byte matches
600   // This is done so as to reduce the number of bit-by-bit comparisons that may be done afterwards
601   if ((u8_t)(addr1_char[i] >> 4) == (u8_t)(addr2_char[i] >> 4)) {
602     common_prefix_length += 4;
603     // bit_index is set to 3 so that only the last 4 bits has to be checked
604     // (because the first 4 bits have already proved to be equal)
605     bit_index = 3;
606   }
607 
608   // If already "prefix_length" number of bits are matched, then skip remaining part of the function
609   if (common_prefix_length >= prefix_length) {
610     goto exit;
611   }
612 
613   while (bit_index >= 0) {
614     if ((u8_t)(addr1_char[i] >> (u32_t)bit_index) == (u8_t)(addr2_char[i] >> (u32_t)bit_index)) {
615       ++common_prefix_length;
616       --bit_index;
617       continue;
618     }
619     break;
620   }
621 
622 exit:
623   // Placing an upper bound so that the prefix length matched does not go beyond "prefix_length"
624   common_prefix_length = LWIP_MIN(common_prefix_length, prefix_length);
625 
626   return common_prefix_length;
627 }
628 
629 /**
630  * @ingroup ip6
631  * Select the best IPv6 source address for a given destination IPv6 address.
632  *
633  * This implementation follows RFC 6724 Sec. 5 to the following extent:
634  * - Rules 1, 2, 3: fully implemented
635  * - Rules 4, 5, 5.5: not applicable
636  * - Rule 6: not implemented
637  * - Rule 7: not applicable
638  * - Rule 8: limited to "prefer /64 subnet match over non-match"
639  *
640  * For Rule 2, we deliberately deviate from RFC 6724 Sec. 3.1 by considering
641  * ULAs to be of smaller scope than global addresses, to avoid that a preferred
642  * ULA is picked over a deprecated global address when given a global address
643  * as destination, as that would likely result in broken two-way communication.
644  *
645  * As long as temporary addresses are not supported (as used in Rule 7), a
646  * proper implementation of Rule 8 would obviate the need to implement Rule 6.
647  *
648  * @param netif the netif on which to send a packet
649  * @param dest the destination we are trying to reach (possibly not properly
650  *             zoned)
651  * @return the most suitable source address to use, or NULL if no suitable
652  *         source address is found
653  */
654 const ip_addr_t *
ip6_select_source_address(struct netif * netif,const ip6_addr_t * dest)655 ip6_select_source_address(struct netif *netif, const ip6_addr_t *dest)
656 {
657   const ip_addr_t *best_addr;
658   const ip6_addr_t *cand_addr;
659   s8_t dest_scope, cand_scope;
660   s8_t best_scope = IP6_MULTICAST_SCOPE_RESERVED;
661   u8_t i, cand_pref;
662   u8_t best_pref = 0;
663   int best_bits = 0;
664   u8_t prefix_length = 64;
665   int cand_bits;
666 
667   /* Start by determining the scope of the given destination address. These
668    * tests are hopefully (roughly) in order of likeliness to match. */
669   if (ip6_addr_isglobal(dest)) {
670     dest_scope = IP6_MULTICAST_SCOPE_GLOBAL;
671   } else if (ip6_addr_islinklocal(dest) || ip6_addr_isloopback(dest)) {
672     dest_scope = IP6_MULTICAST_SCOPE_LINK_LOCAL;
673   } else if (ip6_addr_isuniquelocal(dest)) {
674     dest_scope = IP6_MULTICAST_SCOPE_ORGANIZATION_LOCAL;
675   } else if (ip6_addr_ismulticast(dest)) {
676     dest_scope = ip6_addr_multicast_scope(dest);
677   } else if (ip6_addr_issitelocal(dest)) {
678     dest_scope = IP6_MULTICAST_SCOPE_SITE_LOCAL;
679   } else {
680     /* no match, consider scope global */
681     dest_scope = IP6_MULTICAST_SCOPE_RESERVEDF;
682   }
683 
684   best_addr = NULL;
685 
686   for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
687     /* Consider only valid (= preferred and deprecated) addresses. */
688     if (!ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) {
689       continue;
690     }
691     /* Determine the scope of this candidate address. Same ordering idea. */
692     cand_addr = netif_ip6_addr(netif, i);
693     if (ip6_addr_isglobal(cand_addr)) {
694       cand_scope = IP6_MULTICAST_SCOPE_GLOBAL;
695     } else if (ip6_addr_islinklocal(cand_addr)) {
696       cand_scope = IP6_MULTICAST_SCOPE_LINK_LOCAL;
697     } else if (ip6_addr_isuniquelocal(cand_addr)) {
698       cand_scope = IP6_MULTICAST_SCOPE_ORGANIZATION_LOCAL;
699     } else if (ip6_addr_issitelocal(cand_addr)) {
700       cand_scope = IP6_MULTICAST_SCOPE_SITE_LOCAL;
701     } else {
702       /* no match, treat as low-priority global scope */
703       cand_scope = IP6_MULTICAST_SCOPE_RESERVEDF;
704     }
705     cand_pref = ip6_addr_ispreferred(netif_ip6_addr_state(netif, i));
706     cand_bits = ip6_common_prefix_length(cand_addr, dest, prefix_length);
707     if (cand_bits == -1) {
708       cand_bits = 0;
709     }
710 
711     if ((best_addr == NULL) || /* no alternative yet */
712         ((cand_scope < best_scope) && (cand_scope >= dest_scope)) ||
713         ((cand_scope > best_scope) && (best_scope < dest_scope)) || /* Rule 2 */
714         ((cand_scope == best_scope) && ((cand_pref > best_pref) || /* Rule 3 */
715         ((cand_pref == best_pref) && (cand_bits > best_bits))))) { /* Rule 8 */
716       /* We found a new "winning" candidate. */
717       best_addr = netif_ip_addr6(netif, i);
718       best_scope = cand_scope;
719       best_pref = cand_pref;
720       best_bits = cand_bits;
721     }
722   }
723 
724   return best_addr; /* may be NULL */
725 }
726 
727 #if LWIP_IPV6_FORWARD
728 #if LWIP_RIPPLE
729 #define IP6_FORWARD_BIG_DROP 1
730 #define IP6_FORWARD_BIG_HANDLED 2
731 #define IP6_FORWARD_BIG_ASSEMBLED 3
732 static int
ip6_forward_big_packet(struct pbuf ** q,struct ip6_hdr ** oiphdr,const struct netif * outp,u8_t * big_packet)733 ip6_forward_big_packet(struct pbuf **q, struct ip6_hdr **oiphdr, const struct netif *outp, u8_t *big_packet)
734 {
735   u16_t ip6_hdr_len;
736   u8_t nexth;
737   u8_t flags;
738   u16_t optlen;
739   struct pbuf *p = *q;
740   struct ip6_hdr *iphdr = *oiphdr;
741 
742   /* send ICMP6 if HL == 0 */
743   if ((IP6H_HOPLIM(iphdr) == 0) || ((IP6H_HOPLIM(iphdr) - 1) == 0)) {
744 #if LWIP_ICMP6
745     /* Don't send ICMP messages in response to ICMP messages */
746     if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) {
747       icmp6_time_exceeded(p, ICMP6_TE_HL);
748     }
749 #endif /* LWIP_ICMP6 */
750     LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward_big_packet:hop limit drop\n"));
751     IP6_STATS_INC(ip6.drop);
752     return IP6_FORWARD_BIG_DROP;
753   }
754   LWIP_UNUSED_ARG(outp);
755   nexth = IP6H_NEXTH(iphdr);
756   ip6_hdr_len = IP6_HLEN;
757 
758   /* find the data in ip6 pkt */
759   /* Move to payload. */
760   (void)pbuf_header(p, -IP6_HLEN);
761   *big_packet = 1;
762   flags = 0;
763   /* Process option extension headers, if present. */
764   while (nexth != IP6_NEXTH_NONE) {
765     if ((nexth == IP6_NEXTH_TCP) || (nexth == IP6_NEXTH_UDP) ||
766         (nexth == IP6_NEXTH_ICMP6) || (flags != 0)) {
767       break;
768     }
769 
770     switch (nexth) {
771       case IP6_NEXTH_HOPBYHOP:
772       case IP6_NEXTH_ENCAPS:
773       case IP6_NEXTH_ROUTING:
774       case IP6_NEXTH_DESTOPTS:
775         /* Get next header type. */
776         nexth = *((u8_t *)p->payload);
777 
778         if (p->len < IP6_HBH_HLEN) {
779           LWIP_DEBUGF(IP6_DEBUG, ("pbuf (len %"U16_F") is less than 2.\n", p->len));
780           IP_STATS_INC(ip6.drop);
781           return IP6_FORWARD_BIG_DROP;
782         }
783         /* Get the header length. */
784         /* 8: go to option length segment and multily by eight */
785         optlen = 8 * (1 + (u16_t)*((u8_t *)p->payload + 1));
786 
787         /* Skip over this header. */
788         if (optlen > p->len) {
789           LWIP_DEBUGF(IP6_DEBUG,
790                       ("IPv6 opt header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 pac dropped.\n",
791                        optlen, p->len));
792           IP_STATS_INC(ip6.drop);
793           return IP6_FORWARD_BIG_DROP;
794         }
795 
796         ip6_hdr_len += optlen;
797         (void)pbuf_header(p, (s16_t)(-(s16_t)optlen));
798         break;
799       case IP6_NEXTH_FRAGMENT: {
800         struct ip6_frag_hdr *frag_hdr = NULL;
801         LWIP_DEBUGF(IP6_DEBUG, ("nat64_ip6_input: packet with Fragment header\n"));
802 
803         frag_hdr = (struct ip6_frag_hdr *)p->payload;
804 
805         if (p->len < IP6_HBH_HLEN) {
806           LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
807                       ("IP6_NEXTH_FRAGMENT:(pbuf len %"U16_F" is less than 2), IPv6 packet dropped.\n",
808                        p->len));
809           IP6_STATS_INC(ip6.drop);
810           return IP6_FORWARD_BIG_DROP;
811         }
812 
813         /* Get next header type. */
814         nexth = frag_hdr->_nexth;
815 
816         /* 8 : Fragment Header length. */
817         optlen = 8;
818         ip6_hdr_len += optlen;
819 
820         /* Make sure this header fits in current pbuf. */
821         if (optlen > p->len) {
822           LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
823                       ("IPv6 opt header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 pac dropped.\n",
824                        optlen, p->len));
825           IP6_STATS_INC(ip6.drop);
826           return IP6_FORWARD_BIG_DROP;
827         }
828 
829         /* check payload length is multiple of 8 octets when mbit is set */
830         if (IP6_FRAG_MBIT(frag_hdr) && ((IP6H_PLEN(iphdr) & 0x7) != 0)) {
831           /* ipv6 payload length is not multiple of 8 octets */
832           icmp6_param_problem(p, ICMP6_PP_FIELD, frag_hdr);
833           LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward_big_packet: packet with invalid payload length dropped\n"));
834           IP6_STATS_INC(ip6.drop);
835           return IP6_FORWARD_BIG_DROP;
836         }
837 
838         /* Offset == 0 and more_fragments == 0? */
839         if ((frag_hdr->_fragment_offset &
840              PP_HTONS(IP6_FRAG_OFFSET_MASK | IP6_FRAG_MORE_FLAG)) == 0) {
841           /*
842            * This is a 1-fragment packet, usually a packet that we have
843            * already reassembled. Skip this header anc continue.
844            */
845           (void)pbuf_header(p, (s16_t)(-(s16_t)optlen));
846         } else {
847 #if LWIP_IPV6_REASS
848           /* reassemble the packet */
849           p = ip6_reass(p);
850           /* packet not fully reassembled yet? */
851           if (p == NULL) {
852             LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward_big_packet:fragment is not fully reassembled yet\n"));
853             /* note: the pkt has been free in the ip6_reass */
854             return IP6_FORWARD_BIG_ASSEMBLED;
855           }
856 
857           /*
858            * Returned p point to IPv6 header.
859            * Update all our variables and pointers and continue.
860            */
861           iphdr = (struct ip6_hdr *)p->payload;
862           nexth = IP6H_NEXTH(iphdr);
863           optlen = 0;
864           ip6_hdr_len = 0;
865           *q = p;
866           *oiphdr = iphdr;
867           (void)pbuf_header(p, -IP6_HLEN);
868           ip6_hdr_len = IP6_HLEN;
869 
870 #else /* LWIP_IPV6_REASS */
871           /* free (drop) packet pbufs */
872           LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward_big_packet: packet with Fragment header dropped.\n"));
873           IP6_STATS_INC(ip6.drop);
874           return IP6_FORWARD_BIG_DROP;
875 #endif /* LWIP_IPV6_REASS */
876         }
877         break;
878       }
879       default:
880         flags = 1;
881         break;
882     }
883   }
884 
885   if ((nexth != IP6_NEXTH_TCP) && (nexth != IP6_NEXTH_UDP) &&
886       (nexth != IP6_NEXTH_ICMP6)) {
887     LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward_big_packet: nexth is not correct.\n"));
888     IP6_STATS_INC(ip6.drop);
889     return IP6_FORWARD_BIG_DROP;
890   }
891 
892   (void)pbuf_header(p, (s16_t)ip6_hdr_len);
893   return IP6_FORWARD_BIG_HANDLED;
894 }
895 #endif
896 /**
897  * Forwards an IPv6 packet. It finds an appropriate route for the
898  * packet, decrements the HL value of the packet, and outputs
899  * the packet on the appropriate interface.
900  *
901  * @param p the packet to forward (p->payload points to IP header)
902  * @param iphdr the IPv6 header of the input packet
903  * @param inp the netif on which this packet was received
904  */
905 static void
ip6_forward(struct pbuf * p,struct ip6_hdr * iphdr,struct netif * inp,u8_t * free_flag)906 ip6_forward(struct pbuf *p, struct ip6_hdr *iphdr, struct netif *inp, u8_t *free_flag)
907 {
908   struct netif *netif;
909   u8_t big_packet = 0;
910 
911   /* do not forward link-local or loopback addresses */
912   if (ip6_addr_islinklocal(ip6_current_dest_addr()) ||
913       ip6_addr_isloopback(ip6_current_dest_addr())) {
914     LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: not forwarding link-local address.\n"));
915     IP6_STATS_INC(ip6.rterr);
916     IP6_STATS_INC(ip6.drop);
917     return;
918   }
919 
920   /* Find network interface where to forward this IP packet to. */
921   netif = ip6_route(IP6_ADDR_ANY6, ip6_current_dest_addr());
922   if (netif == NULL) {
923     LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: no route for %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n",
924         IP6_ADDR_BLOCK1(ip6_current_dest_addr()),
925         IP6_ADDR_BLOCK2(ip6_current_dest_addr()),
926         IP6_ADDR_BLOCK3(ip6_current_dest_addr()),
927         IP6_ADDR_BLOCK4(ip6_current_dest_addr()),
928         IP6_ADDR_BLOCK5(ip6_current_dest_addr()),
929         IP6_ADDR_BLOCK6(ip6_current_dest_addr()),
930         IP6_ADDR_BLOCK7(ip6_current_dest_addr()),
931         IP6_ADDR_BLOCK8(ip6_current_dest_addr())));
932 #if LWIP_ICMP6
933     /* Don't send ICMP messages in response to ICMP messages */
934     if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) {
935       icmp6_dest_unreach(p, ICMP6_DUR_NO_ROUTE);
936     }
937 #endif /* LWIP_ICMP6 */
938     IP6_STATS_INC(ip6.rterr);
939     IP6_STATS_INC(ip6.drop);
940     return;
941   }
942 #if LWIP_IPV6_SCOPES
943   /* Do not forward packets with a zoned (e.g., link-local) source address
944    * outside of their zone. We determined the zone a bit earlier, so we know
945    * that the address is properly zoned here, so we can safely use has_zone.
946    * Also skip packets with a loopback source address (link-local implied). */
947   if ((ip6_addr_has_zone(ip6_current_src_addr()) &&
948       !ip6_addr_test_zone(ip6_current_src_addr(), netif)) ||
949       ip6_addr_isloopback(ip6_current_src_addr())) {
950     LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: not forwarding packet beyond its source address zone.\n"));
951     IP6_STATS_INC(ip6.rterr);
952     IP6_STATS_INC(ip6.drop);
953     return;
954   }
955 #endif /* LWIP_IPV6_SCOPES */
956   /* Do not forward packets onto the same network interface on which
957    * they arrived. */
958   if ((netif == inp)
959 #if LWIP_RIPPLE
960       && (lwip_rpl_is_rpl_netif(inp) == lwIP_FALSE)
961 #endif
962      ) {
963     LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: not bouncing packets back on incoming interface.\n"));
964     IP6_STATS_INC(ip6.rterr);
965     IP6_STATS_INC(ip6.drop);
966     return;
967   }
968 
969 #if LWIP_RIPPLE
970   int ret;
971   if (lwip_rpl_is_br() && (lwip_rpl_is_rpl_netif(inp) == lwIP_FALSE) &&
972       (lwip_rpl_is_rpl_netif(netif) == lwIP_TRUE)) {
973     /* should handle the big packet. */
974     ret = ip6_forward_big_packet(&p, &iphdr, netif, &big_packet);
975     if (ret == IP6_FORWARD_BIG_DROP) {
976       LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: DROP\n"));
977       IP6_STATS_INC(ip6.drop);
978       return;
979     } else if (ret == IP6_FORWARD_BIG_ASSEMBLED) {
980       *free_flag = lwIP_FALSE;
981       LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: ressa\n"));
982       return;
983     }
984   }
985 #else
986   LWIP_UNUSED_ARG(big_packet);
987   LWIP_UNUSED_ARG(free_flag);
988 #endif
989   /* decrement HL */
990   if (IP6H_HOPLIM(iphdr)) {
991     IP6H_HOPLIM_SET(iphdr, IP6H_HOPLIM(iphdr) - 1);
992   }
993   /* send ICMP6 if HL == 0 */
994   if (IP6H_HOPLIM(iphdr) == 0) {
995 #if LWIP_ICMP6
996     /* Don't send ICMP messages in response to ICMP messages */
997     if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) {
998       icmp6_time_exceeded(p, ICMP6_TE_HL);
999     }
1000 #endif /* LWIP_ICMP6 */
1001     IP6_STATS_INC(ip6.drop);
1002     return;
1003   }
1004 
1005   if (netif->mtu && (p->tot_len > netif->mtu) && (big_packet == 0)) {
1006 #if LWIP_ICMP6
1007     /* Don't send ICMP messages in response to ICMP messages */
1008     if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) {
1009       icmp6_packet_too_big(p, netif->mtu);
1010     }
1011 #endif /* LWIP_ICMP6 */
1012     IP6_STATS_INC(ip6.drop);
1013     return;
1014   }
1015 
1016   LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: forwarding packet to %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n",
1017       IP6_ADDR_BLOCK1(ip6_current_dest_addr()),
1018       IP6_ADDR_BLOCK2(ip6_current_dest_addr()),
1019       IP6_ADDR_BLOCK3(ip6_current_dest_addr()),
1020       IP6_ADDR_BLOCK4(ip6_current_dest_addr()),
1021       IP6_ADDR_BLOCK5(ip6_current_dest_addr()),
1022       IP6_ADDR_BLOCK6(ip6_current_dest_addr()),
1023       IP6_ADDR_BLOCK7(ip6_current_dest_addr()),
1024       IP6_ADDR_BLOCK8(ip6_current_dest_addr())));
1025 
1026 #if LWIP_RIPPLE
1027   /* Update the RPI extended header before forwarding */
1028   if ((p->flags & PBUF_FLAG_HBH_SPACE) != 0) {
1029     if (lwip_get_pkt_route_status()) {
1030       p->pkt_up = lwIP_TRUE;
1031     } else {
1032       p->pkt_up = lwIP_FALSE;
1033     }
1034     if (ip6_update_rpi(p, netif) != ERR_OK) {
1035       IP6_STATS_INC(ip6.rterr);
1036       IP6_STATS_INC(ip6.drop);
1037       return;
1038     }
1039   }
1040 #endif
1041   LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: %c%c%"U16_F"\n", netif->name[0], netif->name[1], (u16_t)netif->num));
1042   ip6_debug_print(p);
1043 
1044 #if LWIP_IPV6_FRAG
1045   /* don't fragment if interface has mtu set to 0 [loopif] */
1046   if ((big_packet != 0) && netif_mtu6(netif) &&
1047       (p->tot_len > nd6_get_destination_mtu(ip6_current_dest_addr(), netif))) {
1048     (void)ip6_frag(p, netif, ip6_current_dest_addr());
1049     *free_flag = lwIP_FALSE;
1050     (void)pbuf_free(p);
1051     return;
1052   }
1053 #endif /* LWIP_IPV6_FRAG */
1054 
1055   /* transmit pbuf on chosen interface */
1056   netif->output_ip6(netif, p, ip6_current_dest_addr());
1057   IP6_STATS_INC(ip6.fw);
1058   IP6_STATS_INC(ip6.xmit);
1059   return;
1060 }
1061 #endif /* LWIP_IPV6_FORWARD */
1062 
1063 static u8_t
ip6_process_destination_header_extension_unknown_options(struct pbuf * p,const struct ip6_opt_hdr * opt_hdr)1064 ip6_process_destination_header_extension_unknown_options(struct pbuf *p, const struct ip6_opt_hdr *opt_hdr)
1065 {
1066   u8_t clear_resource = 0;
1067   /* Check 2 MSB of Destination header type. */
1068   switch (IP6_OPT_TYPE_ACTION(opt_hdr)) {
1069     case 1:
1070       /* Discard the packet. */
1071       LWIP_DEBUGF(IP6_DEBUG,
1072                   ("ip6_input: packet with invalid destination option type dropped, \
1073                   highest order 2 bits value is 1\n"));
1074       clear_resource = 1;
1075       break;
1076     case 2:
1077       /* Send ICMP Parameter Problem */
1078       LWIP_DEBUGF(IP6_DEBUG,
1079                   ("ip6_input: packet with invalid destination option type dropped, \
1080                    highest order 2 bits value is 2\n"));
1081       /* move payload pointer back to ip header */
1082       (void)pbuf_header_force(p, (s16_t)((u8_t*)p->payload - (const u8_t *)ip6_current_header()));
1083       icmp6_param_problem(p, ICMP6_PP_OPTION, (const void *)opt_hdr);
1084       clear_resource = 1;
1085       break;
1086     case 3:
1087       /* Send ICMP Parameter Problem if destination address is not a multicast address */
1088       LWIP_DEBUGF(IP6_DEBUG,
1089                   ("ip6_input: packet with invalid destination option type dropped, \
1090                    highest order 2 bits value is 3\n"));
1091       if (!ip6_addr_ismulticast(ip6_current_dest_addr())) {
1092         /* move payload pointer back to ip header */
1093         (void)pbuf_header_force(p, (s16_t)((u8_t*)p->payload - (const u8_t *)ip6_current_header()));
1094         icmp6_param_problem(p, ICMP6_PP_OPTION, (const void *)opt_hdr);
1095       }
1096       clear_resource = 1;
1097       break;
1098 
1099     default:
1100       break;
1101   }
1102 
1103   return clear_resource;
1104 }
1105 /*
1106  * This function is called when there is extension options to be processed in destination header in IPV6 packet
1107  * @param p points to the pbuf buffer
1108  * @param dest_hdr points to the destination header in the IPV6
1109  * @param hlen header lenght of the destination option
1110  * @return need_ip6_input_cleanup = 1 means discard, 0 means continue process the packet
1111  */
ip6_process_destination_header_extension_options(struct pbuf * p,struct ip6_dest_hdr * dest_hdr,u16_t hlen,u8_t * need_ip6_input_cleanup)1112 void ip6_process_destination_header_extension_options(struct pbuf *p, struct ip6_dest_hdr *dest_hdr,
1113                                                       u16_t hlen, u8_t *need_ip6_input_cleanup)
1114 {
1115   s32_t opt_offset;
1116   struct ip6_opt_hdr *opt_hdr = NULL;
1117   if ((p == NULL) || (dest_hdr == NULL) || (need_ip6_input_cleanup == NULL)) {
1118     return;
1119   }
1120   *need_ip6_input_cleanup = 0;
1121 
1122   /* The extended option header starts right after Destination header. */
1123   opt_offset = IP6_DEST_HLEN;
1124   while (opt_offset < (s32_t)hlen) {
1125     s32_t opt_dlen = 0;
1126     u8_t clear_resource = 0;
1127 
1128     opt_hdr = (struct ip6_opt_hdr *)((u8_t *)dest_hdr + opt_offset);
1129 
1130     /*
1131      * @page RFC-2460 RFC-2460
1132      * @par  RFC-2460 Compliance Information
1133      * @par Compliant Section
1134      * IPv6 Extension Headers. Test v6LC.1.2.8: Option Processing, Destination Options Header
1135      * @par Behavior Description
1136      *
1137      * Our node conforms to RFC-2460. \n
1138      *  RFC-2460 does not support below extension options and the features corresponding to it. \n
1139      * @verbatim
1140      *   RFC-3775 --> IPV6 Mobility Support       - IP6_HOME_ADDRESS_OPTION (Option_Type = 201)
1141      *   RFC-2711 --> IPv6 Router Alert Option    - IP6_ROUTER_ALERT_OPTION (Option_Type = 5)
1142      *   RFC-2675 --> IPV6 Jumbo Payload Option   - IP6_JUMBO_OPTION        (Option_Type = 194)
1143      * @endverbatim
1144      * \n
1145      *   For these options and other extension header options, our node action conforms to RFC-2460: \n
1146      *   If the IPv6 node does not recognize the Option_Type, then the action it should take depends
1147      *   on the highest order two bits of the Option_Type.
1148      */
1149     switch (IP6_OPT_TYPE(opt_hdr)) {
1150       case IP6_PAD1_OPTION:
1151         /* PAD1 option deosn't have length and value field */
1152         opt_dlen = -1;
1153         break;
1154 
1155       case IP6_PADN_OPTION:
1156         if ((hlen - opt_offset) >= IP6_OPT_HLEN) { /* malformed packet */
1157           opt_dlen = IP6_OPT_DLEN(opt_hdr);
1158         } else {
1159           /* Discard the packet. */
1160           LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
1161                       ("ip6_input: malformed packet detected in PADN option rocessing, discarding it \n"));
1162           clear_resource = 1;
1163         }
1164         break;
1165 
1166       default:
1167         clear_resource = ip6_process_destination_header_extension_unknown_options(p, opt_hdr);
1168         if (clear_resource == 0) {
1169           /* Skip over this option. */
1170           if ((hlen - opt_offset) >= IP6_OPT_HLEN) { /* malformed packet */
1171             opt_dlen = IP6_OPT_DLEN(opt_hdr);
1172           } else {
1173             /* Discard the packet. */
1174             LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
1175                         ("ip6_input: malformed packet detected in Unknown option processing, discarding it \n"));
1176             clear_resource = 1;
1177           }
1178         }
1179         break;
1180     }
1181 
1182     if (clear_resource != 0) {
1183       (void)pbuf_free(p);
1184       IP6_STATS_INC(ip6.drop);
1185       *need_ip6_input_cleanup = 1;
1186       break;
1187     }
1188     /* Adjust the offset to move to the next extended option header */
1189     opt_offset = opt_offset + IP6_OPT_HLEN + opt_dlen;
1190   }
1191 
1192   return;
1193 }
1194 #if LWIP_IPV6_MLD_QUERIER
1195 static u8_t
ip6_mld6_check(struct pbuf * p,struct ip6_hdr * ip6hdr)1196 ip6_mld6_check(struct pbuf *p, struct ip6_hdr *ip6hdr)
1197 {
1198   u16_t *opt_data;
1199   u32_t offset = 0;
1200   struct ip6_hbh_hdr *hbh_hdr = NULL;
1201   struct ip6_opt_hdr *opt_hdr = NULL;
1202 
1203   if (IP6H_NEXTH(ip6hdr) != IP6_NEXTH_HOPBYHOP) {
1204     return lwIP_FALSE;
1205   }
1206 
1207   /* Move to payload. */
1208   (void)pbuf_header(p, -IP6_HLEN);
1209   if (p->len < sizeof(struct ip6_hbh_hdr)) {
1210     return lwIP_FALSE;
1211   }
1212   hbh_hdr = (struct ip6_hbh_hdr *)(p->payload);
1213   if (hbh_hdr->_nexth != IP6_NEXTH_ICMP6) {
1214     return lwIP_FALSE;
1215   }
1216   offset = IP6_HBH_HLEN;
1217 
1218   opt_hdr = (struct ip6_opt_hdr *)((u8_t *)hbh_hdr + offset);
1219   if (IP6_OPT_TYPE(opt_hdr) != IP6_ROUTER_ALERT_OPTION) {
1220     return lwIP_FALSE;
1221   }
1222   offset += IP6_OPT_HLEN;
1223 
1224   /* Set router alert option data */
1225   opt_data = (u16_t *)((u8_t *)hbh_hdr + offset);
1226   if (*opt_data != IP6_ROUTER_ALERT_VALUE_MLD) {
1227     return lwIP_FALSE;
1228   }
1229 
1230   /* Move to ip6 header */
1231   (void)pbuf_header(p, IP6_HLEN);
1232   return lwIP_TRUE;
1233 }
1234 #endif /* LWIP_IPV6_MLD_QUERIER */
1235 
1236 #if LWIP_IPV6_MLD && LWIP_MPL
1237 static u8_t
ip6_mld6_mpl_check(struct pbuf * p,struct netif * inp)1238 ip6_mld6_mpl_check(struct pbuf *p, struct netif *inp)
1239 {
1240   LWIP_ASSERT("invalid pointer\n", (p != NULL && inp != NULL));
1241   if ((inp->flags & NETIF_IS_RPL_UP) == NETIF_IS_RPL_UP) {
1242     if ((ip6_addr_multicast_scope(ip6_current_dest_addr()) > IP6_MULTICAST_SCOPE_LINK_LOCAL) &&
1243         (MCAST6_IS_FROM_CONN_PEER(p) == MCAST6_FALSE)) {
1244       return lwIP_FALSE;
1245     }
1246   } else {
1247     u8_t mesh_ap;
1248     if ((is_connect_to_ap(&mesh_ap) == lwIP_TRUE) && (mesh_ap == lwIP_TRUE) &&
1249         (is_connected_ap(p->mac_address, sizeof(p->mac_address)) == lwIP_FALSE)) {
1250       return lwIP_FALSE;
1251     }
1252   }
1253   return lwIP_TRUE;
1254 }
1255 #endif /* LWIP_IPV6_MLD && LWIP_MPL */
1256 #if LWIP_RIPPLE && defined(LWIP_NA_PROXY) && LWIP_NA_PROXY
1257 static err_t
ip6_na_proxy(ip6_addr_t * src,ip6_addr_t * target,struct netif * inp)1258 ip6_na_proxy(ip6_addr_t *src, ip6_addr_t *target, struct netif *inp)
1259 {
1260   if (ip6_addr_isany_val(*src)) {
1261     return ERR_ARG;
1262   }
1263 
1264   if (lwip_rpl_is_rpl_netif(inp)) {
1265     /* only the non-mesh node be proxy */
1266     return lwip_rpl_nonmesh_solicited_node(src);
1267   } else if (lwip_rpl_is_br()) {
1268     /* the node behind the MBR will be proxy */
1269     return lwip_rpl_behind_mbr_solicited_node(target);
1270   }
1271 
1272   return ERR_VAL;
1273 }
1274 #endif
1275 
1276 /** Return true if the current input packet should be accepted on this netif */
1277 static int
ip6_input_accept(struct netif * netif)1278 ip6_input_accept(struct netif *netif)
1279 {
1280   /* interface is up? */
1281   if (netif_is_up(netif)) {
1282     u8_t i;
1283     /* unicast to this interface address? address configured? */
1284     /* If custom scopes are used, the destination zone will be tested as
1285       * part of the local-address comparison, but we need to test the source
1286       * scope as well (e.g., is this interface on the same link?). */
1287     for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
1288       if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
1289           ip6_addr_cmp(ip6_current_dest_addr(), netif_ip6_addr(netif, i))
1290 #if IPV6_CUSTOM_SCOPES
1291           && (!ip6_addr_has_zone(ip6_current_src_addr()) ||
1292               ip6_addr_test_zone(ip6_current_src_addr(), netif))
1293 #endif /* IPV6_CUSTOM_SCOPES */
1294       ) {
1295         /* accept on this netif */
1296         return 1;
1297       }
1298     }
1299   }
1300   return 0;
1301 }
1302 
1303 /**
1304  * This function is called by the network interface device driver when
1305  * an IPv6 packet is received. The function does the basic checks of the
1306  * IP header such as packet size being at least larger than the header
1307  * size etc. If the packet was not destined for us, the packet is
1308  * forwarded (using ip6_forward).
1309  *
1310  * Finally, the packet is sent to the upper layer protocol input function.
1311  *
1312  * @param p the received IPv6 packet (p->payload points to IPv6 header)
1313  * @param inp the netif on which this packet was received
1314  * @return ERR_OK if the packet was processed (could return ERR_* if it wasn't
1315  *         processed, but currently always returns ERR_OK)
1316  */
1317 err_t
ip6_input(struct pbuf * p,struct netif * inp)1318 ip6_input(struct pbuf *p, struct netif *inp)
1319 {
1320   struct ip6_hdr *ip6hdr;
1321   struct netif *netif;
1322   const u8_t *nexth;
1323   u16_t hlen, hlen_tot; /* the current header length */
1324 #if LWIP_RAW
1325   raw_input_state_t raw_status;
1326 #endif /* LWIP_RAW */
1327   u8_t need_ip6_input_cleanup = 0;
1328   u8_t assemble_flag;
1329 
1330   LWIP_ASSERT_CORE_LOCKED();
1331 
1332   IP6_STATS_INC(ip6.recv);
1333 
1334 #if LWIP_IPV6_FILTER
1335   if (ip6_filter != NULL && ip6_filter(p, inp) != ERR_OK) {
1336     (void)pbuf_free(p);
1337     IP6_STATS_INC(ip6.drop);
1338     return ERR_OK;
1339   }
1340 #endif /* LWIP_IPV6_FILTER */
1341 
1342   if ((IP6_HLEN > p->len)) {
1343     LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
1344                 ("IPv6 header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet dropped.\n",
1345                 (u16_t)IP6_HLEN, p->len));
1346 
1347     /* free (drop) packet pbufs */
1348     (void)pbuf_free(p);
1349     IP6_STATS_INC(ip6.lenerr);
1350     IP6_STATS_INC(ip6.drop);
1351     return ERR_OK;
1352   }
1353 
1354   /* identify the IP header */
1355   ip6hdr = (struct ip6_hdr *)p->payload;
1356   if (IP6H_V(ip6hdr) != 6) {
1357     LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_WARNING, ("IPv6 packet dropped due to bad version number %"U32_F"\n",
1358         IP6H_V(ip6hdr)));
1359     pbuf_free(p);
1360     IP6_STATS_INC(ip6.err);
1361     IP6_STATS_INC(ip6.drop);
1362     return ERR_OK;
1363   }
1364 
1365 #ifdef LWIP_HOOK_IP6_INPUT
1366   if (LWIP_HOOK_IP6_INPUT(p, inp)) {
1367     /* the packet has been eaten */
1368     return ERR_OK;
1369   }
1370 #endif
1371 
1372   /* header length exceeds first pbuf length, or ip length exceeds total pbuf length? */
1373 
1374   if ((IP6H_PLEN(ip6hdr) + IP6_HLEN) > p->tot_len) {
1375     LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
1376       ("IPv6 (plen %"U16_F") is longer than pbuf (len %"U16_F"), IP packet dropped.\n",
1377           (u16_t)(IP6H_PLEN(ip6hdr) + IP6_HLEN), p->tot_len));
1378 
1379     /* free (drop) packet pbufs */
1380     pbuf_free(p);
1381     IP6_STATS_INC(ip6.lenerr);
1382     IP6_STATS_INC(ip6.drop);
1383     return ERR_OK;
1384   }
1385 
1386   /* Trim pbuf. This should have been done at the netif layer,
1387    * but we'll do it anyway just to be sure that its done. */
1388   pbuf_realloc(p, (u16_t)(IP6_HLEN + IP6H_PLEN(ip6hdr)));
1389 
1390   /* copy IP addresses to aligned ip6_addr_t */
1391   ip_addr_copy_from_ip6_packed(ip_data.current_iphdr_dest, ip6hdr->dest);
1392   ip_addr_copy_from_ip6_packed(ip_data.current_iphdr_src, ip6hdr->src);
1393 
1394   /* Don't accept virtual IPv4 mapped IPv6 addresses.
1395    * Don't accept multicast source addresses. */
1396   if (ip6_addr_isipv4mappedipv6(ip_2_ip6(&ip_data.current_iphdr_dest)) ||
1397      ip6_addr_isipv4mappedipv6(ip_2_ip6(&ip_data.current_iphdr_src)) ||
1398      ip6_addr_ismulticast(ip_2_ip6(&ip_data.current_iphdr_src))) {
1399     /* free (drop) packet pbufs */
1400     pbuf_free(p);
1401     IP6_STATS_INC(ip6.err);
1402     IP6_STATS_INC(ip6.drop);
1403     return ERR_OK;
1404   }
1405 
1406   /* Set the appropriate zone identifier on the addresses. */
1407   ip6_addr_assign_zone(ip_2_ip6(&ip_data.current_iphdr_dest), IP6_UNKNOWN, inp);
1408   ip6_addr_assign_zone(ip_2_ip6(&ip_data.current_iphdr_src), IP6_UNICAST, inp);
1409 
1410 #if LWIP_MPL
1411   /*
1412    * Don't accept the packet which was sent by us.
1413    */
1414   for (netif = netif_list; netif != NULL; netif = netif->next) {
1415     u8_t i;
1416     if (netif->flags & NETIF_FLAG_LOOPBACK) {
1417       continue;
1418     }
1419     for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
1420       if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
1421           ip6_addr_cmp(ip6_current_src_addr(), netif_ip6_addr(netif, i))) {
1422         /* free (drop) packet pbufs */
1423         (void)pbuf_free(p);
1424         IP6_STATS_INC(ip6.err);
1425         IP6_STATS_INC(ip6.drop);
1426         return ERR_OK;
1427       }
1428     }
1429   }
1430 #endif
1431 
1432 #if LWIP_RIPPLE && defined(LWIP_NA_PROXY) && LWIP_NA_PROXY
1433   p->na_proxy = lwIP_FALSE;
1434 #endif
1435   /* current header pointer. */
1436   ip_data.current_ip6_header = ip6hdr;
1437 
1438   /* In netif, used in case we need to send ICMPv6 packets back. */
1439   ip_data.current_netif = inp;
1440   ip_data.current_input_netif = inp;
1441 
1442   /* match packet against an interface, i.e. is this packet for us? */
1443   if (ip6_addr_ismulticast(ip6_current_dest_addr())) {
1444     /* Always joined to multicast if-local and link-local all-nodes group. */
1445     if (ip6_addr_isallnodes_iflocal(ip6_current_dest_addr()) ||
1446         ip6_addr_isallnodes_linklocal(ip6_current_dest_addr())
1447 #if LWIP_RIPPLE
1448         || ip6_addr_isallrpl_nodes_linklocal(ip6_current_dest_addr())
1449         || ip6_addr_isallrouters_linklocal(ip6_current_dest_addr())
1450 #endif
1451        ) {
1452       netif = inp;
1453     }
1454 #if LWIP_IPV6_MLD
1455     else if (mld6_lookfor_group(inp, ip6_current_dest_addr())
1456 #if LWIP_MPL_IPV4_BCAST
1457              || ip6_addr_is_mpl_ip4_bcast(ip6_current_dest_addr())
1458 #endif
1459             ) {
1460       netif = inp;
1461 #if LWIP_MPL
1462       if (ip6_mld6_mpl_check(p, inp) == lwIP_FALSE) {
1463         /* free (drop) packet pbufs */
1464         (void)pbuf_free(p);
1465         IP6_STATS_INC(ip6.err);
1466         IP6_STATS_INC(ip6.drop);
1467         return ERR_OK;
1468       }
1469 #endif
1470     }
1471 #else /* LWIP_IPV6_MLD */
1472     else if (ip6_addr_issolicitednode(ip6_current_dest_addr())) {
1473       u8_t i;
1474       /* Filter solicited node packets when MLD is not enabled
1475        * (for Neighbor discovery). */
1476       netif = NULL;
1477       for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
1478         if (!ip6_addr_isinvalid(netif_ip6_addr_state(inp, i)) &&
1479             ip6_addr_cmp_solicitednode(ip6_current_dest_addr(), netif_ip6_addr(inp, i))) {
1480           netif = inp;
1481           LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: solicited node packet accepted on interface %s\n",
1482               netif->name));
1483           break;
1484         }
1485       }
1486 #if LWIP_RIPPLE && defined(LWIP_NA_PROXY) && LWIP_NA_PROXY
1487       if ((netif == NULL) &&
1488           (ip6_na_proxy(ip6_current_src_addr(), ip6_current_dest_addr(), inp) == ERR_OK)) {
1489         netif = inp;
1490         p->na_proxy = lwIP_TRUE;
1491       }
1492 #endif
1493     }
1494 #endif /* LWIP_IPV6_MLD */
1495 #if LWIP_IPV6_MLD_QUERIER
1496     else if (
1497 #if LWIP_MPL
1498       (ip6_addr_multicast_scope(ip6_current_dest_addr()) > IP6_MULTICAST_SCOPE_LINK_LOCAL) &&
1499        (MCAST6_IS_FROM_CONN_PEER(p) == MCAST6_TRUE) &&
1500 #endif /* LWIP_MPL */
1501        (ip6_addr_isallrouters_linklocal(ip6_current_dest_addr()) ||
1502        (ip6_mld6_check(p, ip6hdr) == lwIP_TRUE))) {
1503       netif = inp;
1504     }
1505 #endif
1506 #if LWIP_RIPPLE && defined(LWIP_NA_PROXY) && LWIP_NA_PROXY
1507     else if (ip6_addr_issolicitednode(ip6_current_dest_addr())) {
1508       u8_t i = 0;
1509       /*
1510        * Filter solicited node packets when MLD is not enabled
1511        * (for Neighbor discovery).
1512        */
1513       netif = NULL;
1514       for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
1515         if (!ip6_addr_isinvalid(netif_ip6_addr_state(inp, i)) &&
1516             ip6_addr_cmp_solicitednode(ip6_current_dest_addr(), netif_ip6_addr(inp, i))) {
1517           netif = inp;
1518           LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: solicited node packet accepted on interface %c%c\n",
1519                                   netif->name[0], netif->name[1]));
1520           break;
1521         }
1522       }
1523 
1524       if ((netif == NULL) &&
1525           (ip6_na_proxy(ip6_current_src_addr(), ip6_current_dest_addr(), inp) == ERR_OK)) {
1526         netif = inp;
1527         p->na_proxy = lwIP_TRUE;
1528       }
1529     }
1530 #endif
1531     else {
1532       netif = NULL;
1533     }
1534 #if LWIP_MPL
1535     if (ip6_addr_multicast_scope(ip6_current_dest_addr()) > IP6_MULTICAST_SCOPE_LINK_LOCAL) {
1536       MCAST6_FORWARD(p, ip6hdr);
1537     }
1538 #endif /* LWIP_MPL */
1539   } else {
1540     /* start trying with inp. if that's not acceptable, start walking the
1541        list of configured netifs. */
1542     if (ip6_input_accept(inp)) {
1543       netif = inp;
1544     } else {
1545       netif = NULL;
1546 #if !IPV6_CUSTOM_SCOPES
1547       /* Shortcut: stop looking for other interfaces if either the source or
1548         * the destination has a scope constrained to this interface. Custom
1549         * scopes may break the 1:1 link/interface mapping, however. */
1550       if (ip6_addr_islinklocal(ip6_current_dest_addr()) ||
1551           ip6_addr_islinklocal(ip6_current_src_addr())) {
1552         goto netif_found;
1553       }
1554 #endif /* !IPV6_CUSTOM_SCOPES */
1555 #if !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF
1556       /* The loopback address is to be considered link-local. Packets to it
1557         * should be dropped on other interfaces, as per RFC 4291 Sec. 2.5.3.
1558         * Its implied scope means packets *from* the loopback address should
1559         * not be accepted on other interfaces, either. These requirements
1560         * cannot be implemented in the case that loopback traffic is sent
1561         * across a non-loopback interface, however. */
1562       if (ip6_addr_isloopback(ip6_current_dest_addr()) ||
1563           ip6_addr_isloopback(ip6_current_src_addr())) {
1564         goto netif_found;
1565       }
1566 #endif /* !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF */
1567 #if !LWIP_SINGLE_NETIF
1568       NETIF_FOREACH(netif) {
1569         if (netif == inp) {
1570           /* we checked that before already */
1571           continue;
1572         }
1573         if (ip6_input_accept(netif)) {
1574           break;
1575         }
1576       }
1577 #endif /* !LWIP_SINGLE_NETIF */
1578     }
1579 netif_found:
1580     LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet accepted on interface %s\n",
1581         netif ? netif->name : "XX"));
1582   }
1583 
1584   /* "::" packet source address? (used in duplicate address detection) */
1585   if (ip6_addr_isany_val(*ip6_current_src_addr()) &&
1586       (!ip6_addr_issolicitednode(ip6_current_dest_addr()))) {
1587     /* packet source is not valid */
1588     /* free (drop) packet pbufs */
1589     LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with src ANY_ADDRESS dropped\n"));
1590     pbuf_free(p);
1591     IP6_STATS_INC(ip6.drop);
1592     goto ip6_input_cleanup;
1593   }
1594 
1595   /* packet not for us? */
1596   if (netif == NULL) {
1597     u8_t free_flag = lwIP_TRUE;
1598     /* packet not for us, route or discard */
1599     LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_TRACE, ("ip6_input: packet not for us.\n"));
1600 #if LWIP_IP6IN4 && LWIP_IP6IN4_PRIOR_NAT64
1601     if (ip6in4_ip6_input(p, ip6hdr, inp, NULL)) {
1602       LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip6in4_ip6_input: packet handle.\n"));
1603       goto ip6_input_cleanup;
1604     }
1605 #endif
1606 #if LWIP_NAT64
1607     if (nat64_ip6_input(p, ip6hdr, inp)) {
1608       LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("nat64_ip6_input: packet handle.\n"));
1609       goto ip6_input_cleanup;
1610     }
1611 #endif /* LWIP_NAT64 */
1612 #if LWIP_IP6IN4 && !LWIP_IP6IN4_PRIOR_NAT64 && !LWIP_NAT64_IP6IN4
1613     if (ip6in4_ip6_input(p, ip6hdr, inp, NULL)) {
1614       LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip6in4_ip6_input: packet handle.\n"));
1615       goto ip6_input_cleanup;
1616     }
1617 #endif
1618 #if LWIP_IPV6_FORWARD
1619     /* non-multicast packet? */
1620     if (!ip6_addr_ismulticast(ip6_current_dest_addr())) {
1621       /* try to forward IP packet on (other) interfaces */
1622 #if LWIP_RIPPLE
1623       (void)pbuf_header(p, -IP6_HLEN);
1624       if (ip6_process_hbh_exth_options(p, inp) == ERR_OK) {
1625         (void)pbuf_header(p, IP6_HLEN);
1626         LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: RPI validation Success\n"));
1627         ip6_forward(p, ip6hdr, inp, &free_flag);
1628       }
1629 #else
1630       ip6_forward(p, ip6hdr, inp, &free_flag);
1631 #endif
1632     }
1633 #endif /* LWIP_IPV6_FORWARD */
1634     if (free_flag == lwIP_TRUE) {
1635       (void)pbuf_free(p);
1636     }
1637     IP6_STATS_INC(ip6.drop);
1638     goto ip6_input_cleanup;
1639   }
1640 
1641   /* current netif pointer. */
1642   ip_data.current_netif = netif;
1643 
1644   /* Save next header type. */
1645   nexth = &IP6H_NEXTH(ip6hdr);
1646 
1647   /* Init header length. */
1648   hlen = hlen_tot = IP6_HLEN;
1649 
1650   /* Move to payload. */
1651   pbuf_remove_header(p, IP6_HLEN);
1652 
1653   /* Process known option extension headers, if present. */
1654   while (*nexth != IP6_NEXTH_NONE)
1655   {
1656     assemble_flag = 0;
1657     switch (*nexth) {
1658     case IP6_NEXTH_HOPBYHOP:
1659     {
1660       s32_t opt_offset;
1661       struct ip6_hbh_hdr *hbh_hdr;
1662       struct ip6_opt_hdr *opt_hdr;
1663       LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Hop-by-Hop options header\n"));
1664 
1665       /* Get and check the header length, while staying in packet bounds. */
1666       hbh_hdr = (struct ip6_hbh_hdr *)p->payload;
1667 
1668       /* Get next header type. */
1669 #if LWIP_RIPPLE
1670       if (ip6_process_hbh_exth_options(p, netif) != ERR_OK) {
1671         LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: RPI validation failed\n"));
1672         (void)pbuf_free(p);
1673         IP6_STATS_INC(ip6.drop);
1674         goto ip6_input_cleanup;
1675       }
1676 #endif
1677       nexth = &IP6_HBH_NEXTH(hbh_hdr);
1678       /*
1679        *@page RFC-2460 RFC-2460
1680        *@par Compliant Section
1681        *Section 4.  IPv6 Extension Headers. Test v6LC.1.2.1: Next Header Zero
1682        *@par Behavior Description
1683        *The lwIP stack will not send back the ICMP Parameter Problem message and discard
1684        *the packet when a packet has Next Header field of zero in a header other than an IPv6 header.
1685        *Also the processing of Hop-by-Hop Options is not performed.
1686        *The exception referred to in the preceding paragraph is the Hop-by-
1687        *Hop Options header, which carries information that must be examined
1688        *and processed by every node along a packet's delivery path, including
1689        *the source and destination nodes.  The Hop-by-Hop Options header,
1690        *when present, must immediately follow the IPv6 header.  Its presence
1691        *is indicated by the value zero in the Next Header field of the IPv6
1692        *header. \n
1693        *If, as a result of processing a header, a node is required to proceed
1694        *to the next header but the Next Header value in the current header is
1695        *unrecognized by the node, it should discard the packet and send an
1696        *ICMP Parameter Problem message to the source of the packet, with an
1697        *ICMP Code value of 1 ("unrecognized Next Header type encountered")
1698        *and the ICMP Pointer field containing the offset of the unrecognized
1699        *value within the original packet.  The same action should be taken if
1700        *a node encounters a Next Header value of zero in any header other \,
1701        *than an IPv6 header. \n
1702        *[RFC 8200 4. IPv6 Extension Headers] Modified the above behavior. By default no need to send
1703        *back the ICMP Parameter Problem message and discard the packet when a packet has Next
1704        *Header field of zero in a header other than an IPv6 header. Also the processing of Hop-by-Hop
1705        *Options header is changed from 'must' to 'may' by every node in the path \n
1706        * \n
1707        *NOTE: While RFC-2460 required that all nodes must examine and
1708        *process the Hop-by-Hop Options header, it is now expected that nodes
1709        *along a packet's delivery path only examine and process the
1710        *Hop-by-Hop Options header if explicitly configured to do so.
1711        */
1712       if (p->len < IP6_OPT_HLEN) {
1713         LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
1714           ("IP6_NEXTH_HOPBYHOP: pbuf (len %"U16_F") is less than 2.\n", p->len));
1715         /* free (drop) packet pbufs */
1716         (void)pbuf_free(p);
1717         IP6_STATS_INC(ip6.lenerr);
1718         IP6_STATS_INC(ip6.drop);
1719         goto ip6_input_cleanup;
1720       }
1721 
1722       /* Get the header length. */
1723       hlen = (u16_t)(8 * (1 + hbh_hdr->_hlen));
1724 
1725       if ((p->len < 8) || (hlen > p->len)) {
1726         LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
1727           ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n",
1728               hlen, p->len));
1729         /* free (drop) packet pbufs */
1730         pbuf_free(p);
1731         IP6_STATS_INC(ip6.lenerr);
1732         IP6_STATS_INC(ip6.drop);
1733         goto ip6_input_cleanup;
1734       }
1735 
1736       hlen_tot = (u16_t)(hlen_tot + hlen);
1737 
1738       /* The extended option header starts right after Hop-by-Hop header. */
1739       opt_offset = IP6_HBH_HLEN;
1740       while (opt_offset < hlen)
1741       {
1742         s32_t opt_dlen = 0;
1743 
1744         opt_hdr = (struct ip6_opt_hdr *)((u8_t *)hbh_hdr + opt_offset);
1745 
1746         switch (IP6_OPT_TYPE(opt_hdr)) {
1747         /* @todo: process IPV6 Hop-by-Hop option data */
1748         case IP6_PAD1_OPTION:
1749           /* PAD1 option doesn't have length and value field */
1750           opt_dlen = -1;
1751           break;
1752         case IP6_PADN_OPTION:
1753           opt_dlen = IP6_OPT_DLEN(opt_hdr);
1754           break;
1755         case IP6_ROUTER_ALERT_OPTION:
1756           opt_dlen = IP6_OPT_DLEN(opt_hdr);
1757           break;
1758         case IP6_JUMBO_OPTION:
1759           opt_dlen = IP6_OPT_DLEN(opt_hdr);
1760           break;
1761         default:
1762           /* Check 2 MSB of Hop-by-Hop header type. */
1763           switch (IP6_OPT_TYPE_ACTION(opt_hdr)) {
1764           case 1:
1765             /* Discard the packet. */
1766             LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid Hop-by-Hop option type dropped.\n"));
1767             pbuf_free(p);
1768             IP6_STATS_INC(ip6.drop);
1769             goto ip6_input_cleanup;
1770           case 2:
1771             /* Send ICMP Parameter Problem */
1772             /* move payload pointer back to ip header */
1773             (void)pbuf_header_force(p, (s16_t)((u8_t*)p->payload - (const u8_t *)ip6_current_header()));
1774             icmp6_param_problem(p, ICMP6_PP_OPTION, (const void *)opt_hdr);
1775             LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid Hop-by-Hop option type dropped.\n"));
1776             pbuf_free(p);
1777             IP6_STATS_INC(ip6.drop);
1778             goto ip6_input_cleanup;
1779           case 3:
1780             /* Send ICMP Parameter Problem if destination address is not a multicast address */
1781             if (!ip6_addr_ismulticast(ip6_current_dest_addr())) {
1782               /* move payload pointer back to ip header */
1783               (void)pbuf_header_force(p, (s16_t)((u8_t*)p->payload - (const u8_t *)ip6_current_header()));
1784               icmp6_param_problem(p, ICMP6_PP_OPTION, (const void *)opt_hdr);
1785             }
1786             LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid Hop-by-Hop option type dropped.\n"));
1787             pbuf_free(p);
1788             IP6_STATS_INC(ip6.drop);
1789             goto ip6_input_cleanup;
1790           default:
1791             /* Skip over this option. */
1792             opt_dlen = IP6_OPT_DLEN(opt_hdr);
1793             break;
1794           }
1795           break;
1796         }
1797 
1798         /* Adjust the offset to move to the next extended option header */
1799         opt_offset = opt_offset + IP6_OPT_HLEN + opt_dlen;
1800       }
1801       pbuf_remove_header(p, hlen);
1802       break;
1803     }
1804     case IP6_NEXTH_DESTOPTS:
1805     {
1806       struct ip6_dest_hdr *dest_hdr;
1807       LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Destination options header\n"));
1808 
1809       dest_hdr = (struct ip6_dest_hdr *)p->payload;
1810 
1811       /* Get next header type. */
1812       nexth = &IP6_DEST_NEXTH(dest_hdr);
1813       if (p->len < IP6_DEST_HLEN) {
1814         LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
1815           ("IP6_NEXTH_DESTOPTS: pbuf (len %"U16_F") is less than 2.\n", p->len));
1816         /* free (drop) packet pbufs */
1817         (void)pbuf_free(p);
1818         IP6_STATS_INC(ip6.lenerr);
1819         IP6_STATS_INC(ip6.drop);
1820         goto ip6_input_cleanup;
1821       }
1822 
1823       /* Get the header length. */
1824       hlen = 8 * (1 + dest_hdr->_hlen);
1825       if ((p->len < 8) || (hlen > p->len)) {
1826         LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
1827           ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n",
1828               hlen, p->len));
1829         /* free (drop) packet pbufs */
1830         pbuf_free(p);
1831         IP6_STATS_INC(ip6.lenerr);
1832         IP6_STATS_INC(ip6.drop);
1833         goto ip6_input_cleanup;
1834       }
1835 
1836       hlen_tot = (u16_t)(hlen_tot + hlen);
1837       /*
1838        *@page RFC-2460 RFC-2460
1839        *@par Compliant Section
1840        *Section 4.  IPv6 Extension Headers. Test v6LC.1.2.8: Option Processing, Destination Options Header
1841        *@par Behavior Description
1842        *Our code conforms to RFC-2460. \n
1843        *   RFC-2460 does not support the following extension options and the features corresponding to it. \n
1844        *@verbatim
1845        *   RFC-3775 --> IPV6 Mobility Support       - IP6_HOME_ADDRESS_OPTION (Option_Type = 201)
1846        *   RFC-2711 --> IPv6 Router Alert Option    - IP6_ROUTER_ALERT_OPTION (Option_Type = 5)
1847        *   RFC-2675 --> IPV6 Jumbo Payload Option   - IP6_JUMBO_OPTION        (Option Type = 194)
1848        *   @endverbatim
1849        *   For these options and other extension header options, our node action will conform to RFC-2460: \n
1850        *   If the IPv6 node does not recognize the Option_Type, then the action it should take depends
1851        *  on the highest order two bits of the Option_Type.
1852        */
1853       /* The extended option header starts right after Destination header. */
1854       ip6_process_destination_header_extension_options(p, dest_hdr, hlen, &need_ip6_input_cleanup);
1855       if (need_ip6_input_cleanup) {
1856         goto ip6_input_cleanup;
1857       }
1858 
1859       pbuf_remove_header(p, hlen);
1860       break;
1861     }
1862     case IP6_NEXTH_ROUTING:
1863     {
1864       struct ip6_rout_hdr *rout_hdr;
1865       LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Routing header\n"));
1866 
1867       rout_hdr = (struct ip6_rout_hdr *)p->payload;
1868 
1869       /* Get next header type. */
1870       nexth = &IP6_ROUT_NEXTH(rout_hdr);
1871       if (p->len < IP6_OPT_HLEN) {
1872         LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
1873           ("IP6_NEXTH_ROUTING: pbuf (len %"U16_F") is less than 2.\n", p->len));
1874         /* free (drop) packet pbufs */
1875         (void)pbuf_free(p);
1876         IP6_STATS_INC(ip6.lenerr);
1877         IP6_STATS_INC(ip6.drop);
1878         goto ip6_input_cleanup;
1879       }
1880 
1881       /* Get the header length. */
1882       hlen = 8 * (1 + rout_hdr->_hlen);
1883 
1884       if ((p->len < 8) || (hlen > p->len)) {
1885         LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
1886           ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n",
1887               hlen, p->len));
1888         /* free (drop) packet pbufs */
1889         pbuf_free(p);
1890         IP6_STATS_INC(ip6.lenerr);
1891         IP6_STATS_INC(ip6.drop);
1892         goto ip6_input_cleanup;
1893       }
1894 
1895       /* Skip over this header. */
1896       hlen_tot = (u16_t)(hlen_tot + hlen);
1897 
1898       /* if segment left value is 0 in routing header, ignore the option */
1899       if (IP6_ROUT_SEG_LEFT(rout_hdr)) {
1900         /* The length field of routing option header must be even */
1901         if (rout_hdr->_hlen & 0x1) {
1902           /* Discard and send parameter field error */
1903           icmp6_param_problem(p, ICMP6_PP_FIELD, &rout_hdr->_hlen);
1904           LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid routing type dropped\n"));
1905           pbuf_free(p);
1906           IP6_STATS_INC(ip6.drop);
1907           goto ip6_input_cleanup;
1908         }
1909 
1910         switch (IP6_ROUT_TYPE(rout_hdr))
1911         {
1912         /* TODO: process routing by the type */
1913         case IP6_ROUT_TYPE2:
1914           break;
1915         case IP6_ROUT_RPL:
1916           break;
1917         default:
1918           /* Discard unrecognized routing type and send parameter field error */
1919           icmp6_param_problem(p, ICMP6_PP_FIELD, &IP6_ROUT_TYPE(rout_hdr));
1920           LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid routing type dropped\n"));
1921           pbuf_free(p);
1922           IP6_STATS_INC(ip6.drop);
1923           goto ip6_input_cleanup;
1924         }
1925       }
1926 
1927       pbuf_remove_header(p, hlen);
1928       break;
1929     }
1930     case IP6_NEXTH_FRAGMENT:
1931     {
1932       struct ip6_frag_hdr *frag_hdr;
1933       LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Fragment header\n"));
1934 
1935       frag_hdr = (struct ip6_frag_hdr *)p->payload;
1936 
1937       if (p->len < IP6_OPT_HLEN) {
1938         LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
1939           ("IP6_NEXTH_FRAGMENT:(pbuf len %"U16_F" is less than 2), IPv6 packet dropped.\n",
1940             p->len));
1941         /* free (drop) packet pbufs */
1942         (void)pbuf_free(p);
1943         IP6_STATS_INC(ip6.lenerr);
1944         IP6_STATS_INC(ip6.drop);
1945         goto ip6_input_cleanup;
1946       }
1947       /* Get next header type. */
1948       nexth = &IP6_FRAG_NEXTH(frag_hdr);
1949 
1950       /* Fragment Header length. */
1951       hlen = 8;
1952 
1953       /* Make sure this header fits in current pbuf. */
1954       if (hlen > p->len) {
1955         LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
1956           ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n",
1957               hlen, p->len));
1958         /* free (drop) packet pbufs */
1959         pbuf_free(p);
1960         IP6_FRAG_STATS_INC(ip6_frag.lenerr);
1961         IP6_FRAG_STATS_INC(ip6_frag.drop);
1962         goto ip6_input_cleanup;
1963       }
1964 
1965       hlen_tot = (u16_t)(hlen_tot + hlen);
1966 
1967       /* check payload length is multiple of 8 octets when mbit is set */
1968       if (IP6_FRAG_MBIT(frag_hdr) && (IP6H_PLEN(ip6hdr) & 0x7)) {
1969         /* move payload pointer back to ip header */
1970         (void)pbuf_header_force(p, (s16_t)((u8_t*)p->payload - (const u8_t *)ip6_current_header()));
1971         /* ipv6 payload length is not multiple of 8 octets */
1972         icmp6_param_problem(p, ICMP6_PP_FIELD, LWIP_PACKED_CAST(const void *, &ip6hdr->_plen));
1973         LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid payload length dropped\n"));
1974         pbuf_free(p);
1975         IP6_FRAG_STATS_INC(ip6_frag.lenerr);
1976         IP6_FRAG_STATS_INC(ip6_frag.drop);
1977         goto ip6_input_cleanup;
1978       }
1979 
1980       /* Offset == 0 and more_fragments == 0? */
1981       if ((frag_hdr->_fragment_offset &
1982            PP_HTONS(IP6_FRAG_OFFSET_MASK | IP6_FRAG_MORE_FLAG)) == 0) {
1983         /* This is a 1-fragment packet. Skip this header and continue. */
1984         pbuf_remove_header(p, hlen);
1985       } else {
1986 #if LWIP_IPV6_REASS
1987         /* reassemble the packet */
1988         ip_data.current_ip_header_tot_len = hlen_tot;
1989         p = ip6_reass(p);
1990         /* packet not fully reassembled yet? */
1991         if (p == NULL) {
1992           goto ip6_input_cleanup;
1993         }
1994 
1995         /* Returned p point to IPv6 header.
1996          * Update all our variables and pointers and continue. */
1997         ip6hdr = (struct ip6_hdr *)p->payload;
1998         nexth = &IP6H_NEXTH(ip6hdr);
1999         hlen = hlen_tot = IP6_HLEN;
2000         assemble_flag = 1;
2001         pbuf_remove_header(p, IP6_HLEN);
2002 
2003 #else /* LWIP_IPV6_REASS */
2004         /* free (drop) packet pbufs */
2005         LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Fragment header dropped (with LWIP_IPV6_REASS==0)\n"));
2006         pbuf_free(p);
2007         IP6_STATS_INC(ip6.opterr);
2008         IP6_STATS_INC(ip6.drop);
2009         goto ip6_input_cleanup;
2010 #endif /* LWIP_IPV6_REASS */
2011       }
2012       break;
2013     }
2014     default:
2015       goto options_done;
2016     }
2017 
2018     if ((assemble_flag == 0) && (*nexth == IP6_NEXTH_HOPBYHOP)) {
2019       /* move payload pointer back to ip header */
2020       (void)pbuf_header_force(p, (s16_t)((u8_t*)p->payload - (const u8_t *)ip6_current_header()));
2021       /* Hop-by-Hop header comes only as a first option */
2022       icmp6_param_problem(p, ICMP6_PP_HEADER, nexth);
2023       LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Hop-by-Hop options header dropped (only valid as a first option)\n"));
2024       pbuf_free(p);
2025       IP6_STATS_INC(ip6.opterr);
2026       IP6_STATS_INC(ip6.drop);
2027       goto ip6_input_cleanup;
2028     }
2029   }
2030 
2031 options_done:
2032 
2033     /* p points to IPv6 header again for raw_input. */
2034   pbuf_add_header_force(p, hlen_tot);
2035   /* send to upper layers */
2036   LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: \n"));
2037   ip6_debug_print(p);
2038   LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len));
2039 
2040   ip_data.current_ip_header_tot_len = hlen_tot;
2041 #if IP_STATS
2042   /* Successfully received bytes */
2043   STATS_INC_NUM(ip6.ip_rx_bytes, p->tot_len);
2044 #endif
2045 
2046   struct ip6_hdr *ip6hdrtmp = (struct ip6_hdr *)p->payload;
2047   u8_t proto = IP6H_NEXTH(ip6hdrtmp);
2048   s8_t is_chksum_invalid = 0;
2049   /* fragmentation data all merged will be given app */
2050   if ((proto == IP6_NEXTH_FRAGMENT) || (proto == IP6_NEXTH_HOPBYHOP)) {
2051     proto = *nexth;
2052   }
2053 #if LWIP_RIPPLE && defined(LWIP_NA_PROXY) && LWIP_NA_PROXY
2054   if ((p->na_proxy == lwIP_TRUE) && (*nexth != IP6_NEXTH_ICMP6)) {
2055     LWIP_DEBUGF(IP6_DEBUG, ("ip6_input:not icmp6, na_proxy return..\n"));
2056     (void)pbuf_free(p);
2057     goto ip6_input_cleanup;
2058   }
2059 #endif
2060   /* Point to payload. */
2061   pbuf_remove_header(p, hlen_tot);
2062 #if LWIP_RAW
2063   /*
2064    * @page RFC-2292 RFC-2292
2065    * @par Compliant Sections
2066    * Section 3. IPv6 Raw Sockets
2067    * Section 3.1. Checksums
2068    * Section 3.2. ICMPv6 Type Filtering
2069    * @par Behavior Description
2070    *      Support IPv6 raw sockets.
2071    *      Support IPv6 raw checksums.
2072    *      Support ICMPv6 Type Filtering.
2073    * @par Non-Compliant Section
2074    * Section 4. Ancillary Data
2075    * @par Behavior Description
2076    *      Ancillary data is not supported.
2077    */
2078   /* raw input did not eat the packet? */
2079   raw_status = raw_input6(p, proto, &is_chksum_invalid);
2080   if (is_chksum_invalid) {
2081     /* checksum validation is failed */
2082     /* It means packet is not given to application either due to checksum failure or some
2083      * or some other recv failure at the application side.
2084      */
2085     LWIP_DEBUGF(IP6_DEBUG, ("ip6_input:Failed in checksum validation proto = %"U16_F" \n", proto));
2086     (void)pbuf_free(p);
2087     IP6_STATS_INC(ip6.chkerr);
2088     IP6_STATS_INC(ip6.drop);
2089     goto ip6_input_cleanup;
2090   }
2091 
2092 #endif /* LWIP_RAW */
2093   switch (*nexth) {
2094   case IP6_NEXTH_NONE:
2095     pbuf_free(p);
2096     break;
2097 #if LWIP_UDP
2098   case IP6_NEXTH_UDP:
2099 #if LWIP_UDPLITE
2100   case IP6_NEXTH_UDPLITE:
2101 #endif /* LWIP_UDPLITE */
2102     udp_input(p, inp);
2103     break;
2104 #endif /* LWIP_UDP */
2105 #if LWIP_TCP
2106   case IP6_NEXTH_TCP:
2107     tcp_input(p, inp);
2108     break;
2109 #endif /* LWIP_TCP */
2110 #if LWIP_ICMP6
2111   case IP6_NEXTH_ICMP6:
2112     icmp6_input(p, inp);
2113     break;
2114 #endif /* LWIP_ICMP */
2115   default:
2116 #if LWIP_RAW
2117       if (raw_status != RAW_INPUT_NONE) {
2118         /* @todo: ipv6 mib in-delivers? */
2119       } else
2120 #endif /* LWIP_RAW */
2121       {
2122 #if LWIP_ICMP6
2123       /* p points to IPv6 header again for raw_input. */
2124       pbuf_add_header_force(p, hlen_tot);
2125       /* send ICMP parameter problem unless it was a multicast or ICMPv6 */
2126       if ((!ip6_addr_ismulticast(ip6_current_dest_addr())) &&
2127           (IP6H_NEXTH(ip6hdr) != IP6_NEXTH_ICMP6)) {
2128         icmp6_param_problem(p, ICMP6_PP_HEADER, nexth);
2129       }
2130 #endif /* LWIP_ICMP */
2131       LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_input: Unsupported transport protocol %"U16_F"\n", (u16_t)IP6H_NEXTH(ip6hdr)));
2132       IP6_STATS_INC(ip6.proterr);
2133       IP6_STATS_INC(ip6.drop);
2134     }
2135     pbuf_free(p);
2136     break;
2137   }
2138 
2139 ip6_input_cleanup:
2140   ip_data.current_netif = NULL;
2141   ip_data.current_input_netif = NULL;
2142   ip_data.current_ip6_header = NULL;
2143   ip_data.current_ip_header_tot_len = 0;
2144   ip6_addr_set_zero(ip6_current_src_addr());
2145   ip6_addr_set_zero(ip6_current_dest_addr());
2146 
2147   return ERR_OK;
2148 }
2149 
2150 
2151 /**
2152  * Sends an IPv6 packet on a network interface. This function constructs
2153  * the IPv6 header. If the source IPv6 address is NULL, the IPv6 "ANY" address is
2154  * used as source (usually during network startup). If the source IPv6 address it
2155  * IP6_ADDR_ANY, the most appropriate IPv6 address of the outgoing network
2156  * interface is filled in as source address. If the destination IPv6 address is
2157  * LWIP_IP_HDRINCL, p is assumed to already include an IPv6 header and
2158  * p->payload points to it instead of the data.
2159  *
2160  * @param p the packet to send (p->payload points to the data, e.g. next
2161             protocol header; if dest == LWIP_IP_HDRINCL, p already includes an
2162             IPv6 header and p->payload points to that IPv6 header)
2163  * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an
2164  *         IP address of the netif is selected and used as source address.
2165  *         if src == NULL, IP6_ADDR_ANY is used as source) (src is possibly not
2166  *         properly zoned)
2167  * @param dest the destination IPv6 address to send the packet to (possibly not
2168  *             properly zoned)
2169  * @param hl the Hop Limit value to be set in the IPv6 header
2170  * @param tc the Traffic Class value to be set in the IPv6 header
2171  * @param nexth the Next Header to be set in the IPv6 header
2172  * @param netif the netif on which to send this packet
2173  * @return ERR_OK if the packet was sent OK
2174  *         ERR_BUF if p doesn't have enough space for IPv6/LINK headers
2175  *         returns errors returned by netif->output_ip6
2176  */
2177 err_t
ip6_output_if(struct pbuf * p,const ip6_addr_t * src,const ip6_addr_t * dest,u8_t hl,u8_t tc,u8_t nexth,struct netif * netif)2178 ip6_output_if(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
2179               u8_t hl, u8_t tc,
2180               u8_t nexth, struct netif *netif)
2181 {
2182   const ip6_addr_t *src_used = src;
2183   if (dest != LWIP_IP_HDRINCL) {
2184     if (src != NULL && ip6_addr_isany(src)) {
2185       src_used = ip_2_ip6(ip6_select_source_address(netif, dest));
2186       if ((src_used == NULL) || ip6_addr_isany(src_used)) {
2187         /* No appropriate source address was found for this packet. */
2188         LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: No suitable source address for packet.\n"));
2189         IP6_STATS_INC(ip6.rterr);
2190         return ERR_RTE;
2191       }
2192     }
2193   }
2194   return ip6_output_if_src(p, src_used, dest, hl, tc, nexth, netif);
2195 }
2196 
2197 /**
2198  * Same as ip6_output_if() but 'src' address is not replaced by netif address
2199  * when it is 'any'.
2200  */
2201 err_t
ip6_output_if_src(struct pbuf * p,const ip6_addr_t * src,const ip6_addr_t * dest,u8_t hl,u8_t tc,u8_t nexth,struct netif * netif)2202 ip6_output_if_src(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
2203                   u8_t hl, u8_t tc,
2204                   u8_t nexth, struct netif *netif)
2205 {
2206   struct ip6_hdr *ip6hdr;
2207   ip6_addr_t dest_addr;
2208 
2209   LWIP_ASSERT_CORE_LOCKED();
2210   LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p);
2211 
2212   /* Should the IPv6 header be generated or is it already included in p? */
2213   if (dest != LWIP_IP_HDRINCL) {
2214 #if LWIP_IPV6_SCOPES
2215     /* If the destination address is scoped but lacks a zone, add a zone now,
2216      * based on the outgoing interface. The lower layers (e.g., nd6) absolutely
2217      * require addresses to be properly zoned for correctness. In some cases,
2218      * earlier attempts will have been made to add a zone to the destination,
2219      * but this function is the only one that is called in all (other) cases,
2220      * so we must do this here. */
2221     if (ip6_addr_lacks_zone(dest, IP6_UNKNOWN)) {
2222       ip6_addr_copy(dest_addr, *dest);
2223       ip6_addr_assign_zone(&dest_addr, IP6_UNKNOWN, netif);
2224       dest = &dest_addr;
2225     }
2226 #endif /* LWIP_IPV6_SCOPES */
2227 
2228 #if LWIP_RIPPLE
2229     if (nexth == IP6_NEXTH_ICMP6) {
2230       /* check ICMP type is neither Echo request nor Echo reply */
2231       if ((*((u8_t *)p->payload) != ICMP6_TYPE_EREQ) && (*((u8_t *)p->payload) != ICMP6_TYPE_EREP)) {
2232         p->flags |= PBUF_FLAG_CTRL_PKT;
2233 #if LWIP_SO_PRIORITY
2234         p->priority = LWIP_PKT_PRIORITY_CTRL;
2235 #endif /* LWIP_SO_PRIORITY */
2236       }
2237     }
2238 #endif /* LWIP_RIPPLE */
2239     /* generate IPv6 header */
2240     if (pbuf_add_header(p, IP6_HLEN)) {
2241       LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: not enough room for IPv6 header in pbuf\n"));
2242       IP6_STATS_INC(ip6.err);
2243       return ERR_BUF;
2244     }
2245 
2246     ip6hdr = (struct ip6_hdr *)p->payload;
2247     LWIP_ASSERT("check that first pbuf can hold struct ip6_hdr",
2248                (p->len >= sizeof(struct ip6_hdr)));
2249 
2250     IP6H_HOPLIM_SET(ip6hdr, hl);
2251     IP6H_NEXTH_SET(ip6hdr, nexth);
2252 
2253     /* dest cannot be NULL here */
2254     ip6_addr_copy_to_packed(ip6hdr->dest, *dest);
2255 
2256     IP6H_VTCFL_SET(ip6hdr, 6, tc, 0);
2257     IP6H_PLEN_SET(ip6hdr, (u16_t)(p->tot_len - IP6_HLEN));
2258 
2259     if (src == NULL) {
2260       src = IP6_ADDR_ANY6;
2261     }
2262     /* src cannot be NULL here */
2263     ip6_addr_copy_to_packed(ip6hdr->src, *src);
2264 
2265   } else {
2266     /* IP header already included in p */
2267     ip6hdr = (struct ip6_hdr *)p->payload;
2268     ip6_addr_copy_from_packed(dest_addr, ip6hdr->dest);
2269     ip6_addr_assign_zone(&dest_addr, IP6_UNKNOWN, netif);
2270     dest = &dest_addr;
2271   }
2272 
2273   IP6_STATS_INC(ip6.xmit);
2274 #if IP_STATS
2275   STATS_INC_NUM(ip6.ip_tx_bytes, p->tot_len);
2276 #endif
2277 
2278   LWIP_DEBUGF(IP6_DEBUG, ("ip6_output_if: %s%"U16_F"\n", netif->name, (u16_t)netif->num));
2279   ip6_debug_print(p);
2280 
2281 #if ENABLE_LOOPBACK
2282   {
2283     int i;
2284 #if !LWIP_HAVE_LOOPIF
2285     if (ip6_addr_isloopback(dest)) {
2286       return netif_loop_output(netif, p);
2287     }
2288 #endif /* !LWIP_HAVE_LOOPIF */
2289     for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
2290       if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
2291           ip6_addr_cmp(dest, netif_ip6_addr(netif, i))) {
2292         /* Packet to self, enqueue it for loopback */
2293         LWIP_DEBUGF(IP6_DEBUG, ("netif_loop_output()\n"));
2294         return netif_loop_output(netif, p);
2295       }
2296     }
2297   }
2298 #if LWIP_MULTICAST_TX_OPTIONS
2299   if ((p->flags & PBUF_FLAG_MCASTLOOP) != 0) {
2300     netif_loop_output(netif, p);
2301   }
2302 #endif /* LWIP_MULTICAST_TX_OPTIONS */
2303 #endif /* ENABLE_LOOPBACK */
2304 #if LWIP_RIPPLE
2305   if ((!ip6_addr_islinklocal(dest)) &&
2306       (!ip6_addr_ismulticast(dest)) &&
2307       (p->flags & PBUF_FLAG_HBH_SPACE) &&
2308       lwip_rpl_is_rpl_netif(netif)) {
2309     struct pbuf *new_p = NULL;
2310     /* add Hop by Hop header for rpl. If space for HBH is not allocated then pbuf will be expanded. */
2311     (void)ip6_route(src, dest);
2312 
2313     if (lwip_get_pkt_route_status()) {
2314       p->pkt_up = lwIP_TRUE;
2315     } else {
2316       p->pkt_up = lwIP_FALSE;
2317     }
2318     new_p = lwip_add_rpi_hdr(p, nexth, lwip_hbh_len(p), 1);
2319     if (new_p == NULL) {
2320       LWIP_ERROR("Could not add HBH header.\n", 0, ;);
2321       IP6_STATS_INC(ip6.err);
2322       return ERR_BUF;
2323     } else {
2324       p = new_p;
2325     }
2326   }
2327 #endif /* LWIP_RIPPLE */
2328 #if LWIP_IPV6_FRAG
2329   /* don't fragment if interface has mtu set to 0 [loopif] */
2330   if (netif_mtu6(netif) && (p->tot_len > nd6_get_destination_mtu(dest, netif))) {
2331     return ip6_frag(p, netif, dest);
2332   }
2333 #endif /* LWIP_IPV6_FRAG */
2334 
2335   LWIP_DEBUGF(IP6_DEBUG, ("netif->output_ip6()\n"));
2336   return netif->output_ip6(netif, p, dest);
2337 }
2338 
2339 /**
2340  * Simple interface to ip6_output_if. It finds the outgoing network
2341  * interface and calls upon ip6_output_if to do the actual work.
2342  *
2343  * @param p the packet to send (p->payload points to the data, e.g. next
2344             protocol header; if dest == LWIP_IP_HDRINCL, p already includes an
2345             IPv6 header and p->payload points to that IPv6 header)
2346  * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an
2347  *         IP address of the netif is selected and used as source address.
2348  *         if src == NULL, IP6_ADDR_ANY is used as source)
2349  * @param dest the destination IPv6 address to send the packet to
2350  * @param hl the Hop Limit value to be set in the IPv6 header
2351  * @param tc the Traffic Class value to be set in the IPv6 header
2352  * @param nexth the Next Header to be set in the IPv6 header
2353  *
2354  * @return ERR_RTE if no route is found
2355  *         see ip_output_if() for more return values
2356  */
2357 err_t
ip6_output(struct pbuf * p,const ip6_addr_t * src,const ip6_addr_t * dest,u8_t hl,u8_t tc,u8_t nexth)2358 ip6_output(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
2359            u8_t hl, u8_t tc, u8_t nexth)
2360 {
2361   struct netif *netif;
2362   struct ip6_hdr *ip6hdr;
2363   ip6_addr_t src_addr, dest_addr;
2364 
2365   LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p);
2366 
2367   IP6_ADDR(&dest_addr, 0, 0, 0, 0);
2368 
2369   if (dest != LWIP_IP_HDRINCL) {
2370     netif = ip6_route(src, dest);
2371   } else {
2372     /* IP header included in p, read addresses. */
2373     ip6hdr = (struct ip6_hdr *)p->payload;
2374     ip6_addr_copy_from_packed(src_addr, ip6hdr->src);
2375     ip6_addr_copy_from_packed(dest_addr, ip6hdr->dest);
2376     netif = ip6_route(&src_addr, &dest_addr);
2377     dest = &dest_addr;
2378   }
2379 
2380   if (netif == NULL) {
2381     LWIP_DEBUGF(IP6_DEBUG, ("ip6_output: no route for %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n",
2382         IP6_ADDR_BLOCK1(dest),
2383         IP6_ADDR_BLOCK2(dest),
2384         IP6_ADDR_BLOCK3(dest),
2385         IP6_ADDR_BLOCK4(dest),
2386         IP6_ADDR_BLOCK5(dest),
2387         IP6_ADDR_BLOCK6(dest),
2388         IP6_ADDR_BLOCK7(dest),
2389         IP6_ADDR_BLOCK8(dest)));
2390     IP6_STATS_INC(ip6.rterr);
2391     return ERR_RTE;
2392   }
2393 
2394   return ip6_output_if(p, src, dest, hl, tc, nexth, netif);
2395 }
2396 
2397 
2398 #if LWIP_NETIF_USE_HINTS
2399 /** Like ip6_output, but takes and addr_hint pointer that is passed on to netif->addr_hint
2400  *  before calling ip6_output_if.
2401  *
2402  * @param p the packet to send (p->payload points to the data, e.g. next
2403             protocol header; if dest == LWIP_IP_HDRINCL, p already includes an
2404             IPv6 header and p->payload points to that IPv6 header)
2405  * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an
2406  *         IP address of the netif is selected and used as source address.
2407  *         if src == NULL, IP6_ADDR_ANY is used as source)
2408  * @param dest the destination IPv6 address to send the packet to
2409  * @param hl the Hop Limit value to be set in the IPv6 header
2410  * @param tc the Traffic Class value to be set in the IPv6 header
2411  * @param nexth the Next Header to be set in the IPv6 header
2412  * @param netif_hint netif output hint pointer set to netif->hint before
2413  *        calling ip_output_if()
2414  *
2415  * @return ERR_RTE if no route is found
2416  *         see ip_output_if() for more return values
2417  */
2418 err_t
ip6_output_hinted(struct pbuf * p,const ip6_addr_t * src,const ip6_addr_t * dest,u8_t hl,u8_t tc,u8_t nexth,struct netif_hint * netif_hint)2419 ip6_output_hinted(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
2420                   u8_t hl, u8_t tc, u8_t nexth, struct netif_hint *netif_hint)
2421 {
2422   struct netif *netif;
2423   struct ip6_hdr *ip6hdr;
2424   ip6_addr_t src_addr, dest_addr;
2425   err_t err;
2426 
2427   LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p);
2428 
2429   if (dest != LWIP_IP_HDRINCL) {
2430     netif = ip6_route(src, dest);
2431   } else {
2432     /* IP header included in p, read addresses. */
2433     ip6hdr = (struct ip6_hdr *)p->payload;
2434     ip6_addr_copy_from_packed(src_addr, ip6hdr->src);
2435     ip6_addr_copy_from_packed(dest_addr, ip6hdr->dest);
2436     netif = ip6_route(&src_addr, &dest_addr);
2437     dest = &dest_addr;
2438   }
2439 
2440   if (netif == NULL) {
2441     LWIP_DEBUGF(IP6_DEBUG, ("ip6_output: no route for %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n",
2442         IP6_ADDR_BLOCK1(dest),
2443         IP6_ADDR_BLOCK2(dest),
2444         IP6_ADDR_BLOCK3(dest),
2445         IP6_ADDR_BLOCK4(dest),
2446         IP6_ADDR_BLOCK5(dest),
2447         IP6_ADDR_BLOCK6(dest),
2448         IP6_ADDR_BLOCK7(dest),
2449         IP6_ADDR_BLOCK8(dest)));
2450     IP6_STATS_INC(ip6.rterr);
2451     return ERR_RTE;
2452   }
2453 
2454   NETIF_SET_HINTS(netif, netif_hint);
2455   err = ip6_output_if(p, src, dest, hl, tc, nexth, netif);
2456   NETIF_RESET_HINTS(netif);
2457 
2458   return err;
2459 }
2460 #endif /* LWIP_NETIF_USE_HINTS*/
2461 
2462 #if LWIP_IPV6_MLD
2463 /**
2464  * Add a hop-by-hop options header with a router alert option and padding.
2465  *
2466  * Used by MLD when sending a Multicast listener report/done message.
2467  *
2468  * @param p the packet to which we will prepend the options header
2469  * @param nexth the next header protocol number (e.g. IP6_NEXTH_ICMP6)
2470  * @param value the value of the router alert option data (e.g. IP6_ROUTER_ALERT_VALUE_MLD)
2471  * @return ERR_OK if hop-by-hop header was added, ERR_* otherwise
2472  */
2473 err_t
ip6_options_add_hbh_ra(struct pbuf * p,u8_t nexth,u8_t value)2474 ip6_options_add_hbh_ra(struct pbuf *p, u8_t nexth, u8_t value)
2475 {
2476   u8_t *opt_data;
2477   u32_t offset = 0;
2478   struct ip6_hbh_hdr *hbh_hdr;
2479   struct ip6_opt_hdr *opt_hdr;
2480 
2481   /* fixed 4 bytes for router alert option and 2 bytes padding */
2482   const u8_t hlen = sizeof(struct ip6_hbh_hdr) + sizeof(struct ip6_opt_hdr) + IP6_ROUTER_ALERT_DLEN;
2483   /* Move pointer to make room for hop-by-hop options header. */
2484   if (pbuf_add_header(p, sizeof(struct ip6_hbh_hdr) + hlen)) {
2485     LWIP_DEBUGF(IP6_DEBUG, ("ip6_options: no space for options header\n"));
2486     IP6_STATS_INC(ip6.err);
2487     return ERR_BUF;
2488   }
2489 
2490   /* Set fields of Hop-by-Hop header */
2491   hbh_hdr = (struct ip6_hbh_hdr *)p->payload;
2492   IP6_HBH_NEXTH(hbh_hdr) = nexth;
2493   hbh_hdr->_hlen = 0;
2494   offset = IP6_HBH_HLEN;
2495 
2496   /* Set router alert options to Hop-by-Hop extended option header */
2497   opt_hdr = (struct ip6_opt_hdr *)((u8_t *)hbh_hdr + offset);
2498   IP6_OPT_TYPE(opt_hdr) = IP6_ROUTER_ALERT_OPTION;
2499   IP6_OPT_DLEN(opt_hdr) = IP6_ROUTER_ALERT_DLEN;
2500   offset += IP6_OPT_HLEN;
2501 
2502   /* Set router alert option data */
2503   opt_data = (u8_t *)hbh_hdr + offset;
2504   opt_data[0] = value;
2505   opt_data[1] = 0;
2506   offset += IP6_OPT_DLEN(opt_hdr);
2507 
2508   /* add 2 bytes padding to make 8 bytes Hop-by-Hop header length */
2509   opt_hdr = (struct ip6_opt_hdr *)((u8_t *)hbh_hdr + offset);
2510   IP6_OPT_TYPE(opt_hdr) = IP6_PADN_OPTION;
2511   IP6_OPT_DLEN(opt_hdr) = 0;
2512 
2513   return ERR_OK;
2514 }
2515 #endif /* LWIP_IPV6_MLD */
2516 
2517 #if LWIP_IPV6_FILTER
2518 /*
2519  * Set ip filter for input packet.
2520  */
set_ip6_filter(ip_filter_fn filter_fn)2521 err_t set_ip6_filter(ip_filter_fn filter_fn)
2522 {
2523     ip6_filter = filter_fn;
2524     return ERR_OK;
2525 }
2526 #endif /* LWIP_IPV6_FILTER */
2527 
2528 #if IP6_DEBUG
2529 /* Print an IPv6 header by using LWIP_DEBUGF
2530  * @param p an IPv6 packet, p->payload pointing to the IPv6 header
2531  */
2532 void
ip6_debug_print(struct pbuf * p)2533 ip6_debug_print(struct pbuf *p)
2534 {
2535   struct ip6_hdr *ip6hdr = (struct ip6_hdr *)p->payload;
2536 
2537   LWIP_DEBUGF(IP6_DEBUG, ("IPv6 header:\n"));
2538   LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n"));
2539   LWIP_DEBUGF(IP6_DEBUG, ("| %2"U16_F" |  %3"U16_F"  |      %7"U32_F"     | (ver, class, flow)\n",
2540                     IP6H_V(ip6hdr),
2541                     IP6H_TC(ip6hdr),
2542                     IP6H_FL(ip6hdr)));
2543   LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n"));
2544   LWIP_DEBUGF(IP6_DEBUG, ("|     %5"U16_F"     |  %3"U16_F"  |  %3"U16_F"  | (plen, nexth, hopl)\n",
2545                     IP6H_PLEN(ip6hdr),
2546                     IP6H_NEXTH(ip6hdr),
2547                     IP6H_HOPLIM(ip6hdr)));
2548   LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n"));
2549   LWIP_DEBUGF(IP6_DEBUG, ("|  %4"X32_F" |  %4"X32_F" |  %4"X32_F" |  %4"X32_F" | (src)\n",
2550                     IP6_ADDR_BLOCK1(&(ip6hdr->src)),
2551                     IP6_ADDR_BLOCK2(&(ip6hdr->src)),
2552                     IP6_ADDR_BLOCK3(&(ip6hdr->src)),
2553                     IP6_ADDR_BLOCK4(&(ip6hdr->src))));
2554   LWIP_DEBUGF(IP6_DEBUG, ("|  %4"X32_F" |  %4"X32_F" |  %4"X32_F" |  %4"X32_F" |\n",
2555                     IP6_ADDR_BLOCK5(&(ip6hdr->src)),
2556                     IP6_ADDR_BLOCK6(&(ip6hdr->src)),
2557                     IP6_ADDR_BLOCK7(&(ip6hdr->src)),
2558                     IP6_ADDR_BLOCK8(&(ip6hdr->src))));
2559   LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n"));
2560   LWIP_DEBUGF(IP6_DEBUG, ("|  %4"X32_F" |  %4"X32_F" |  %4"X32_F" |  %4"X32_F" | (dest)\n",
2561                     IP6_ADDR_BLOCK1(&(ip6hdr->dest)),
2562                     IP6_ADDR_BLOCK2(&(ip6hdr->dest)),
2563                     IP6_ADDR_BLOCK3(&(ip6hdr->dest)),
2564                     IP6_ADDR_BLOCK4(&(ip6hdr->dest))));
2565   LWIP_DEBUGF(IP6_DEBUG, ("|  %4"X32_F" |  %4"X32_F" |  %4"X32_F" |  %4"X32_F" |\n",
2566                     IP6_ADDR_BLOCK5(&(ip6hdr->dest)),
2567                     IP6_ADDR_BLOCK6(&(ip6hdr->dest)),
2568                     IP6_ADDR_BLOCK7(&(ip6hdr->dest)),
2569                     IP6_ADDR_BLOCK8(&(ip6hdr->dest))));
2570   LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n"));
2571 
2572   if (IP6H_NEXTH(ip6hdr) == IP6_NEXTH_ICMP6)
2573   {
2574     struct icmpv6_hdr *icmp6hdr;
2575     pbuf_header(p, (s16_t)(-(s16_t)IP6_HLEN));
2576     icmp6hdr = (struct icmpv6_hdr *)p->payload;
2577     LWIP_DEBUGF(IP6_DEBUG, ("|     %8"U16_F"     |  %8"U16_F"  | (ICMPv6-Type, ICMPv6-Code)\n",
2578                     icmp6hdr->type,
2579                     icmp6hdr->code));
2580     pbuf_header(p, (s16_t)((s16_t)IP6_HLEN));
2581     LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n"));
2582 
2583   }
2584 }
2585 #endif /* IP6_DEBUG */
2586 
2587 #endif /* LWIP_IPV6 */
2588