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/raw.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 #ifdef LWIP_DECLARE_HOOK
64 LWIP_DECLARE_HOOK
65 #endif
66 
67 /**
68  * Finds the appropriate network interface for a given IPv6 address. It tries to select
69  * a netif following a sequence of heuristics:
70  * 1) if there is only 1 netif, return it
71  * 2) if the destination is a link-local address, try to match the src address to a netif.
72  *    this is a tricky case because with multiple netifs, link-local addresses only have
73  *    meaning within a particular subnet/link.
74  * 3) tries to match the destination subnet to a configured address
75  * 4) tries to find a router
76  * 5) tries to match the source address to the netif
77  * 6) returns the default netif, if configured
78  *
79  * @param src the source IPv6 address, if known
80  * @param dest the destination IPv6 address for which to find the route
81  * @return the netif on which to send to reach dest
82  */
83 struct netif *
ip6_route(const ip6_addr_t * src,const ip6_addr_t * dest)84 ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest)
85 {
86   struct netif *netif;
87   s8_t i;
88 
89   /* If single netif configuration, fast return. */
90   if ((netif_list != NULL) && (netif_list->next == NULL)) {
91     if (!netif_is_up(netif_list) || !netif_is_link_up(netif_list)) {
92       return NULL;
93     }
94     return netif_list;
95   }
96 
97   /* Special processing for link-local addresses. */
98   if (ip6_addr_islinklocal(dest)) {
99     if (ip6_addr_isany(src)) {
100       /* Use default netif, if Up. */
101       if (!netif_is_up(netif_default) || !netif_is_link_up(netif_default)) {
102         return NULL;
103       }
104       return netif_default;
105     }
106 
107     /* Try to find the netif for the source address, checking that link is up. */
108     for (netif = netif_list; netif != NULL; netif = netif->next) {
109       if (!netif_is_up(netif) || !netif_is_link_up(netif)) {
110         continue;
111       }
112       for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
113         if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
114             ip6_addr_cmp(src, netif_ip6_addr(netif, i))) {
115           return netif;
116         }
117       }
118     }
119 
120     /* netif not found, use default netif, if up */
121     if (!netif_is_up(netif_default) || !netif_is_link_up(netif_default)) {
122       return NULL;
123     }
124     return netif_default;
125   }
126 
127   /* we come here for non-link-local addresses */
128 #ifdef LWIP_HOOK_IP6_ROUTE
129   netif = LWIP_HOOK_IP6_ROUTE(src, dest);
130   if (netif != NULL) {
131     return netif;
132   }
133 #endif
134 
135   /* See if the destination subnet matches a configured address. */
136   for (netif = netif_list; netif != NULL; netif = netif->next) {
137     if (!netif_is_up(netif) || !netif_is_link_up(netif)) {
138       continue;
139     }
140     for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
141       if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
142           ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) {
143         return netif;
144       }
145     }
146   }
147 
148   /* Get the netif for a suitable router. */
149   i = nd6_select_router(dest, NULL);
150   if (i >= 0) {
151     if (default_router_list[i].neighbor_entry != NULL) {
152       if (default_router_list[i].neighbor_entry->netif != NULL) {
153         if (netif_is_up(default_router_list[i].neighbor_entry->netif) && netif_is_link_up(default_router_list[i].neighbor_entry->netif)) {
154           return default_router_list[i].neighbor_entry->netif;
155         }
156       }
157     }
158   }
159 
160   /* try with the netif that matches the source address. */
161   if (!ip6_addr_isany(src)) {
162     for (netif = netif_list; netif != NULL; netif = netif->next) {
163       if (!netif_is_up(netif) || !netif_is_link_up(netif)) {
164         continue;
165       }
166       for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
167         if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
168             ip6_addr_cmp(src, netif_ip6_addr(netif, i))) {
169           return netif;
170         }
171       }
172     }
173   }
174 
175 #if LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF
176   /* loopif is disabled, loopback traffic is passed through any netif */
177   if (ip6_addr_isloopback(dest)) {
178     /* don't check for link on loopback traffic */
179     if (netif_is_up(netif_default)) {
180       return netif_default;
181     }
182     /* default netif is not up, just use any netif for loopback traffic */
183     for (netif = netif_list; netif != NULL; netif = netif->next) {
184       if (netif_is_up(netif)) {
185         return netif;
186       }
187     }
188     return NULL;
189   }
190 #endif /* LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF */
191 
192   /* no matching netif found, use default netif, if up */
193   if ((netif_default == NULL) || !netif_is_up(netif_default) || !netif_is_link_up(netif_default)) {
194     return NULL;
195   }
196   return netif_default;
197 }
198 
199 /**
200  * @ingroup ip6
201  * Select the best IPv6 source address for a given destination
202  * IPv6 address. Loosely follows RFC 3484. "Strong host" behavior
203  * is assumed.
204  *
205  * @param netif the netif on which to send a packet
206  * @param dest the destination we are trying to reach
207  * @return the most suitable source address to use, or NULL if no suitable
208  *         source address is found
209  */
210 const ip_addr_t *
ip6_select_source_address(struct netif * netif,const ip6_addr_t * dest)211 ip6_select_source_address(struct netif *netif, const ip6_addr_t *dest)
212 {
213   const ip_addr_t *src = NULL;
214   u8_t i;
215 
216   /* If dest is link-local, choose a link-local source. */
217   if (ip6_addr_islinklocal(dest) || ip6_addr_ismulticast_linklocal(dest) || ip6_addr_ismulticast_iflocal(dest)) {
218     for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
219       if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
220           ip6_addr_islinklocal(netif_ip6_addr(netif, i))) {
221         return netif_ip_addr6(netif, i);
222       }
223     }
224   }
225 
226   /* Choose a site-local with matching prefix. */
227   if (ip6_addr_issitelocal(dest) || ip6_addr_ismulticast_sitelocal(dest)) {
228     for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
229       if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
230           ip6_addr_issitelocal(netif_ip6_addr(netif, i)) &&
231           ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) {
232         return netif_ip_addr6(netif, i);
233       }
234     }
235   }
236 
237   /* Choose a unique-local with matching prefix. */
238   if (ip6_addr_isuniquelocal(dest) || ip6_addr_ismulticast_orglocal(dest)) {
239     for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
240       if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
241           ip6_addr_isuniquelocal(netif_ip6_addr(netif, i)) &&
242           ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) {
243         return netif_ip_addr6(netif, i);
244       }
245     }
246   }
247 
248   /* Choose a global with best matching prefix. */
249   if (ip6_addr_isglobal(dest) || ip6_addr_ismulticast_global(dest)) {
250     for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
251       if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
252           ip6_addr_isglobal(netif_ip6_addr(netif, i))) {
253         if (src == NULL) {
254           src = netif_ip_addr6(netif, i);
255         }
256         else {
257           /* Replace src only if we find a prefix match. */
258           /* @todo find longest matching prefix. */
259           if ((!(ip6_addr_netcmp(ip_2_ip6(src), dest))) &&
260               ip6_addr_netcmp(netif_ip6_addr(netif, i), dest)) {
261             src = netif_ip_addr6(netif, i);
262           }
263         }
264       }
265     }
266     if (src != NULL) {
267       return src;
268     }
269   }
270 
271   /* Last resort: see if arbitrary prefix matches. */
272   for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
273     if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
274         ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) {
275       return netif_ip_addr6(netif, i);
276     }
277   }
278 
279   return NULL;
280 }
281 
282 #if LWIP_IPV6_FORWARD
283 /**
284  * Forwards an IPv6 packet. It finds an appropriate route for the
285  * packet, decrements the HL value of the packet, and outputs
286  * the packet on the appropriate interface.
287  *
288  * @param p the packet to forward (p->payload points to IP header)
289  * @param iphdr the IPv6 header of the input packet
290  * @param inp the netif on which this packet was received
291  */
292 static void
ip6_forward(struct pbuf * p,struct ip6_hdr * iphdr,struct netif * inp)293 ip6_forward(struct pbuf *p, struct ip6_hdr *iphdr, struct netif *inp)
294 {
295   struct netif *netif;
296 
297   /* do not forward link-local addresses */
298   if (ip6_addr_islinklocal(ip6_current_dest_addr())) {
299     LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: not forwarding link-local address.\n"));
300     IP6_STATS_INC(ip6.rterr);
301     IP6_STATS_INC(ip6.drop);
302     return;
303   }
304 
305   /* Find network interface where to forward this IP packet to. */
306   netif = ip6_route(IP6_ADDR_ANY6, ip6_current_dest_addr());
307   if (netif == NULL) {
308     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",
309         IP6_ADDR_BLOCK1(ip6_current_dest_addr()),
310         IP6_ADDR_BLOCK2(ip6_current_dest_addr()),
311         IP6_ADDR_BLOCK3(ip6_current_dest_addr()),
312         IP6_ADDR_BLOCK4(ip6_current_dest_addr()),
313         IP6_ADDR_BLOCK5(ip6_current_dest_addr()),
314         IP6_ADDR_BLOCK6(ip6_current_dest_addr()),
315         IP6_ADDR_BLOCK7(ip6_current_dest_addr()),
316         IP6_ADDR_BLOCK8(ip6_current_dest_addr())));
317 #if LWIP_ICMP6
318     /* Don't send ICMP messages in response to ICMP messages */
319     if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) {
320       icmp6_dest_unreach(p, ICMP6_DUR_NO_ROUTE);
321     }
322 #endif /* LWIP_ICMP6 */
323     IP6_STATS_INC(ip6.rterr);
324     IP6_STATS_INC(ip6.drop);
325     return;
326   }
327   /* Do not forward packets onto the same network interface on which
328    * they arrived. */
329   if (netif == inp) {
330     LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: not bouncing packets back on incoming interface.\n"));
331     IP6_STATS_INC(ip6.rterr);
332     IP6_STATS_INC(ip6.drop);
333     return;
334   }
335 
336   /* decrement HL */
337   IP6H_HOPLIM_SET(iphdr, IP6H_HOPLIM(iphdr) - 1);
338   /* send ICMP6 if HL == 0 */
339   if (IP6H_HOPLIM(iphdr) == 0) {
340 #if LWIP_ICMP6
341     /* Don't send ICMP messages in response to ICMP messages */
342     if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) {
343       icmp6_time_exceeded(p, ICMP6_TE_HL);
344     }
345 #endif /* LWIP_ICMP6 */
346     IP6_STATS_INC(ip6.drop);
347     return;
348   }
349 
350   if (netif->mtu && (p->tot_len > netif->mtu)) {
351 #if LWIP_ICMP6
352     /* Don't send ICMP messages in response to ICMP messages */
353     if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) {
354       icmp6_packet_too_big(p, netif->mtu);
355     }
356 #endif /* LWIP_ICMP6 */
357     IP6_STATS_INC(ip6.drop);
358     return;
359   }
360 
361   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",
362       IP6_ADDR_BLOCK1(ip6_current_dest_addr()),
363       IP6_ADDR_BLOCK2(ip6_current_dest_addr()),
364       IP6_ADDR_BLOCK3(ip6_current_dest_addr()),
365       IP6_ADDR_BLOCK4(ip6_current_dest_addr()),
366       IP6_ADDR_BLOCK5(ip6_current_dest_addr()),
367       IP6_ADDR_BLOCK6(ip6_current_dest_addr()),
368       IP6_ADDR_BLOCK7(ip6_current_dest_addr()),
369       IP6_ADDR_BLOCK8(ip6_current_dest_addr())));
370 
371   /* transmit pbuf on chosen interface */
372   netif->output_ip6(netif, p, ip6_current_dest_addr());
373   IP6_STATS_INC(ip6.fw);
374   IP6_STATS_INC(ip6.xmit);
375   return;
376 }
377 #endif /* LWIP_IPV6_FORWARD */
378 
379 /**
380  * This function is called by the network interface device driver when
381  * an IPv6 packet is received. The function does the basic checks of the
382  * IP header such as packet size being at least larger than the header
383  * size etc. If the packet was not destined for us, the packet is
384  * forwarded (using ip6_forward).
385  *
386  * Finally, the packet is sent to the upper layer protocol input function.
387  *
388  * @param p the received IPv6 packet (p->payload points to IPv6 header)
389  * @param inp the netif on which this packet was received
390  * @return ERR_OK if the packet was processed (could return ERR_* if it wasn't
391  *         processed, but currently always returns ERR_OK)
392  */
393 err_t
ip6_input(struct pbuf * p,struct netif * inp)394 ip6_input(struct pbuf *p, struct netif *inp)
395 {
396   struct ip6_hdr *ip6hdr =  NULL;
397   struct netif *netif = NULL;
398   u8_t nexth;
399   u16_t hlen; /* the current header length */
400   u8_t i;
401 #if 0 /*IP_ACCEPT_LINK_LAYER_ADDRESSING*/
402   @todo
403   int check_ip_src=1;
404 #endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */
405 
406   IP6_STATS_INC(ip6.recv);
407 
408   /* identify the IP header */
409   ip6hdr = (struct ip6_hdr *)p->payload;
410   if (IP6H_V(ip6hdr) != 6) {
411     LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_WARNING, ("IPv6 packet dropped due to bad version number %"U32_F"\n",
412         IP6H_V(ip6hdr)));
413     pbuf_free(p);
414     IP6_STATS_INC(ip6.err);
415     IP6_STATS_INC(ip6.drop);
416     return ERR_OK;
417   }
418 
419 #ifdef LWIP_HOOK_IP6_INPUT
420   if (LWIP_HOOK_IP6_INPUT(p, inp)) {
421     /* the packet has been eaten */
422     return ERR_OK;
423   }
424 #endif
425 
426   /* header length exceeds first pbuf length, or ip length exceeds total pbuf length? */
427   if ((IP6_HLEN > p->len) || ((IP6H_PLEN(ip6hdr) + IP6_HLEN) > p->tot_len)) {
428     if (IP6_HLEN > p->len) {
429       LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
430         ("IPv6 header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet dropped.\n",
431             (u16_t)IP6_HLEN, p->len));
432     }
433     if ((IP6H_PLEN(ip6hdr) + IP6_HLEN) > p->tot_len) {
434       LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
435         ("IPv6 (plen %"U16_F") is longer than pbuf (len %"U16_F"), IP packet dropped.\n",
436             (u16_t)(IP6H_PLEN(ip6hdr) + IP6_HLEN), p->tot_len));
437     }
438     /* free (drop) packet pbufs */
439     pbuf_free(p);
440     IP6_STATS_INC(ip6.lenerr);
441     IP6_STATS_INC(ip6.drop);
442     return ERR_OK;
443   }
444 
445   /* Trim pbuf. This should have been done at the netif layer,
446    * but we'll do it anyway just to be sure that its done. */
447   pbuf_realloc(p, IP6_HLEN + IP6H_PLEN(ip6hdr));
448 
449   /* copy IP addresses to aligned ip6_addr_t */
450   ip_addr_copy_from_ip6(ip_data.current_iphdr_dest, ip6hdr->dest);
451   ip_addr_copy_from_ip6(ip_data.current_iphdr_src, ip6hdr->src);
452 
453   /* Don't accept virtual IPv6 mapped IPv4 addresses */
454   if (ip6_addr_isipv6mappedipv4(ip_2_ip6(&ip_data.current_iphdr_dest)) ||
455      ip6_addr_isipv6mappedipv4(ip_2_ip6(&ip_data.current_iphdr_src))     ) {
456     IP6_STATS_INC(ip6.err);
457     IP6_STATS_INC(ip6.drop);
458     return ERR_OK;
459   }
460 
461   /* current header pointer. */
462   ip_data.current_ip6_header = ip6hdr;
463 
464   /* In netif, used in case we need to send ICMPv6 packets back. */
465   ip_data.current_netif = inp;
466   ip_data.current_input_netif = inp;
467 
468   /* match packet against an interface, i.e. is this packet for us? */
469   if (ip6_addr_ismulticast(ip6_current_dest_addr())) {
470     /* Always joined to multicast if-local and link-local all-nodes group. */
471     if (ip6_addr_isallnodes_iflocal(ip6_current_dest_addr()) ||
472         ip6_addr_isallnodes_linklocal(ip6_current_dest_addr())) {
473       netif = inp;
474     }
475 #if LWIP_IPV6_MLD
476     else if (mld6_lookfor_group(inp, ip6_current_dest_addr())) {
477       netif = inp;
478     }
479 #else /* LWIP_IPV6_MLD */
480     else if (ip6_addr_issolicitednode(ip6_current_dest_addr())) {
481       /* Filter solicited node packets when MLD is not enabled
482        * (for Neighbor discovery). */
483       netif = NULL;
484       for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
485         if (ip6_addr_isvalid(netif_ip6_addr_state(inp, i)) &&
486             ip6_addr_cmp_solicitednode(ip6_current_dest_addr(), netif_ip6_addr(inp, i))) {
487           netif = inp;
488           LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: solicited node packet accepted on interface %c%c\n",
489               netif->name[0], netif->name[1]));
490           break;
491         }
492       }
493     }
494 #endif /* LWIP_IPV6_MLD */
495     else {
496 #ifdef LWIP_HOOK_MESH_IS_MCAST_SUBSCRIBED
497       if (LWIP_HOOK_MESH_IS_MCAST_SUBSCRIBED(ip6_current_dest_addr())) {
498         netif = inp;
499       }
500 #else
501       netif = NULL;
502 #endif
503     }
504   } else {
505     /* start trying with inp. if that's not acceptable, start walking the
506        list of configured netifs.
507        'first' is used as a boolean to mark whether we started walking the list */
508     int first = 1;
509     netif = inp;
510     do {
511       /* interface is up? */
512       if (netif_is_up(netif)) {
513         /* unicast to this interface address? address configured? */
514         for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
515           if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
516               ip6_addr_cmp(ip6_current_dest_addr(), netif_ip6_addr(netif, i))) {
517             /* exit outer loop */
518             goto netif_found;
519           }
520         }
521       }
522       if (ip6_addr_islinklocal(ip6_current_dest_addr())) {
523         /* Do not match link-local addresses to other netifs. */
524         netif = NULL;
525         break;
526       }
527       if (first) {
528         first = 0;
529         netif = netif_list;
530       } else {
531         netif = netif->next;
532       }
533       if (netif == inp) {
534         netif = netif->next;
535       }
536     } while (netif != NULL);
537 netif_found:
538     LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet accepted on interface %c%c\n",
539         netif ? netif->name[0] : 'X', netif? netif->name[1] : 'X'));
540   }
541 
542   /* "::" packet source address? (used in duplicate address detection) */
543   if (ip6_addr_isany(ip6_current_src_addr()) &&
544       (!ip6_addr_issolicitednode(ip6_current_dest_addr()))) {
545     /* packet source is not valid */
546     /* free (drop) packet pbufs */
547     LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with src ANY_ADDRESS dropped\n"));
548     pbuf_free(p);
549     IP6_STATS_INC(ip6.drop);
550     goto ip6_input_cleanup;
551   }
552 
553   /* packet not for us? */
554   if (netif == NULL) {
555     /* packet not for us, route or discard */
556     LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_TRACE, ("ip6_input: packet not for us.\n"));
557 #if LWIP_IPV6_FORWARD
558     /* non-multicast packet? */
559     if (!ip6_addr_ismulticast(ip6_current_dest_addr())) {
560       /* try to forward IP packet on (other) interfaces */
561       ip6_forward(p, ip6hdr, inp);
562     }
563 #endif /* LWIP_IPV6_FORWARD */
564     pbuf_free(p);
565     goto ip6_input_cleanup;
566   }
567 
568   /* current netif pointer. */
569   ip_data.current_netif = netif;
570 
571   /* Save next header type. */
572   nexth = IP6H_NEXTH(ip6hdr);
573 
574   /* Init header length. */
575   hlen = ip_data.current_ip_header_tot_len = IP6_HLEN;
576 
577   /* Move to payload. */
578   pbuf_header(p, -IP6_HLEN);
579 
580   /* Process known option extension headers, if present. */
581   while (nexth != IP6_NEXTH_NONE)
582   {
583     switch (nexth) {
584     case IP6_NEXTH_HOPBYHOP:
585       LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Hop-by-Hop options header\n"));
586       /* Get next header type. */
587       nexth = *((u8_t *)p->payload);
588 
589       /* Get the header length. */
590       hlen = 8 * (1 + *((u8_t *)p->payload + 1));
591       ip_data.current_ip_header_tot_len += hlen;
592 
593       /* Skip over this header. */
594       if (hlen > p->len) {
595         LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
596           ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n",
597               hlen, p->len));
598         /* free (drop) packet pbufs */
599         pbuf_free(p);
600         IP6_STATS_INC(ip6.lenerr);
601         IP6_STATS_INC(ip6.drop);
602         goto ip6_input_cleanup;
603       }
604 
605       pbuf_header(p, -(s16_t)hlen);
606       break;
607     case IP6_NEXTH_DESTOPTS:
608       LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Destination options header\n"));
609       /* Get next header type. */
610       nexth = *((u8_t *)p->payload);
611 
612       /* Get the header length. */
613       hlen = 8 * (1 + *((u8_t *)p->payload + 1));
614       ip_data.current_ip_header_tot_len += hlen;
615 
616       /* Skip over this header. */
617       if (hlen > p->len) {
618         LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
619           ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n",
620               hlen, p->len));
621         /* free (drop) packet pbufs */
622         pbuf_free(p);
623         IP6_STATS_INC(ip6.lenerr);
624         IP6_STATS_INC(ip6.drop);
625         goto ip6_input_cleanup;
626       }
627 
628       pbuf_header(p, -(s16_t)hlen);
629       break;
630     case IP6_NEXTH_ROUTING:
631       LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Routing header\n"));
632       /* Get next header type. */
633       nexth = *((u8_t *)p->payload);
634 
635       /* Get the header length. */
636       hlen = 8 * (1 + *((u8_t *)p->payload + 1));
637       ip_data.current_ip_header_tot_len += hlen;
638 
639       /* Skip over this header. */
640       if (hlen > p->len) {
641         LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
642           ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n",
643               hlen, p->len));
644         /* free (drop) packet pbufs */
645         pbuf_free(p);
646         IP6_STATS_INC(ip6.lenerr);
647         IP6_STATS_INC(ip6.drop);
648         goto ip6_input_cleanup;
649       }
650 
651       pbuf_header(p, -(s16_t)hlen);
652       break;
653 
654     case IP6_NEXTH_FRAGMENT:
655     {
656       struct ip6_frag_hdr *frag_hdr;
657       LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Fragment header\n"));
658 
659       frag_hdr = (struct ip6_frag_hdr *)p->payload;
660 
661       /* Get next header type. */
662       nexth = frag_hdr->_nexth;
663 
664       /* Fragment Header length. */
665       hlen = 8;
666       ip_data.current_ip_header_tot_len += hlen;
667 
668       /* Make sure this header fits in current pbuf. */
669       if (hlen > p->len) {
670         LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
671           ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n",
672               hlen, p->len));
673         /* free (drop) packet pbufs */
674         pbuf_free(p);
675         IP6_FRAG_STATS_INC(ip6_frag.lenerr);
676         IP6_FRAG_STATS_INC(ip6_frag.drop);
677         goto ip6_input_cleanup;
678       }
679 
680       /* Offset == 0 and more_fragments == 0? */
681       if ((frag_hdr->_fragment_offset &
682            PP_HTONS(IP6_FRAG_OFFSET_MASK | IP6_FRAG_MORE_FLAG)) == 0) {
683         /* This is a 1-fragment packet, usually a packet that we have
684          * already reassembled. Skip this header anc continue. */
685         pbuf_header(p, -(s16_t)hlen);
686       } else {
687 #if LWIP_IPV6_REASS
688 
689         /* reassemble the packet */
690         p = ip6_reass(p);
691         /* packet not fully reassembled yet? */
692         if (p == NULL) {
693           goto ip6_input_cleanup;
694         }
695 
696         /* Returned p point to IPv6 header.
697          * Update all our variables and pointers and continue. */
698         ip6hdr = (struct ip6_hdr *)p->payload;
699         nexth = IP6H_NEXTH(ip6hdr);
700         hlen = ip_data.current_ip_header_tot_len = IP6_HLEN;
701         pbuf_header(p, -IP6_HLEN);
702 
703 #else /* LWIP_IPV6_REASS */
704         /* free (drop) packet pbufs */
705         LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Fragment header dropped (with LWIP_IPV6_REASS==0)\n"));
706         pbuf_free(p);
707         IP6_STATS_INC(ip6.opterr);
708         IP6_STATS_INC(ip6.drop);
709         goto ip6_input_cleanup;
710 #endif /* LWIP_IPV6_REASS */
711       }
712       break;
713     }
714     default:
715       goto options_done;
716     }
717   }
718 options_done:
719 
720   /* p points to IPv6 header again. */
721   pbuf_header_force(p, ip_data.current_ip_header_tot_len);
722 
723   /* send to upper layers */
724   LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: \n"));
725   ip6_debug_print(p);
726   LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len));
727 
728 #if LWIP_RAW
729   /* raw input did not eat the packet? */
730   if (raw_input(p, inp) == 0)
731 #endif /* LWIP_RAW */
732   {
733     switch (nexth) {
734     case IP6_NEXTH_NONE:
735       pbuf_free(p);
736       break;
737 #if LWIP_UDP
738     case IP6_NEXTH_UDP:
739 #if LWIP_UDPLITE
740     case IP6_NEXTH_UDPLITE:
741 #endif /* LWIP_UDPLITE */
742       /* Point to payload. */
743       pbuf_header(p, -(s16_t)ip_data.current_ip_header_tot_len);
744       udp_input(p, inp);
745       break;
746 #endif /* LWIP_UDP */
747 #if LWIP_TCP
748     case IP6_NEXTH_TCP:
749       /* Point to payload. */
750       pbuf_header(p, -(s16_t)ip_data.current_ip_header_tot_len);
751       tcp_input(p, inp);
752       break;
753 #endif /* LWIP_TCP */
754 #if LWIP_ICMP6
755     case IP6_NEXTH_ICMP6:
756       /* Point to payload. */
757       pbuf_header(p, -(s16_t)ip_data.current_ip_header_tot_len);
758       icmp6_input(p, inp);
759       break;
760 #endif /* LWIP_ICMP */
761     default:
762 #if LWIP_ICMP6
763       /* send ICMP parameter problem unless it was a multicast or ICMPv6 */
764       if ((!ip6_addr_ismulticast(ip6_current_dest_addr())) &&
765           (IP6H_NEXTH(ip6hdr) != IP6_NEXTH_ICMP6)) {
766         icmp6_param_problem(p, ICMP6_PP_HEADER, ip_data.current_ip_header_tot_len - hlen);
767       }
768 #endif /* LWIP_ICMP */
769       LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_input: Unsupported transport protocol %"U16_F"\n", (u16_t)IP6H_NEXTH(ip6hdr)));
770       pbuf_free(p);
771       IP6_STATS_INC(ip6.proterr);
772       IP6_STATS_INC(ip6.drop);
773       break;
774     }
775   }
776 
777 ip6_input_cleanup:
778   ip_data.current_netif = NULL;
779   ip_data.current_input_netif = NULL;
780   ip_data.current_ip6_header = NULL;
781   ip_data.current_ip_header_tot_len = 0;
782   ip6_addr_set_zero(ip6_current_src_addr());
783   ip6_addr_set_zero(ip6_current_dest_addr());
784 
785   return ERR_OK;
786 }
787 
788 
789 /**
790  * Sends an IPv6 packet on a network interface. This function constructs
791  * the IPv6 header. If the source IPv6 address is NULL, the IPv6 "ANY" address is
792  * used as source (usually during network startup). If the source IPv6 address it
793  * IP6_ADDR_ANY, the most appropriate IPv6 address of the outgoing network
794  * interface is filled in as source address. If the destination IPv6 address is
795  * LWIP_IP_HDRINCL, p is assumed to already include an IPv6 header and
796  * p->payload points to it instead of the data.
797  *
798  * @param p the packet to send (p->payload points to the data, e.g. next
799             protocol header; if dest == LWIP_IP_HDRINCL, p already includes an
800             IPv6 header and p->payload points to that IPv6 header)
801  * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an
802  *         IP address of the netif is selected and used as source address.
803  *         if src == NULL, IP6_ADDR_ANY is used as source)
804  * @param dest the destination IPv6 address to send the packet to
805  * @param hl the Hop Limit value to be set in the IPv6 header
806  * @param tc the Traffic Class value to be set in the IPv6 header
807  * @param nexth the Next Header to be set in the IPv6 header
808  * @param netif the netif on which to send this packet
809  * @return ERR_OK if the packet was sent OK
810  *         ERR_BUF if p doesn't have enough space for IPv6/LINK headers
811  *         returns errors returned by netif->output
812  */
813 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)814 ip6_output_if(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
815              u8_t hl, u8_t tc,
816              u8_t nexth, struct netif *netif)
817 {
818   const ip6_addr_t *src_used = src;
819   if (dest != LWIP_IP_HDRINCL) {
820     if (src != NULL && ip6_addr_isany(src)) {
821       src = ip_2_ip6(ip6_select_source_address(netif, dest));
822       if ((src == NULL) || ip6_addr_isany(src)) {
823         /* No appropriate source address was found for this packet. */
824         LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: No suitable source address for packet.\n"));
825         IP6_STATS_INC(ip6.rterr);
826         return ERR_RTE;
827       }
828     }
829   }
830   return ip6_output_if_src(p, src_used, dest, hl, tc, nexth, netif);
831 }
832 
833 /**
834  * Same as ip6_output_if() but 'src' address is not replaced by netif address
835  * when it is 'any'.
836  */
837 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)838 ip6_output_if_src(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
839              u8_t hl, u8_t tc,
840              u8_t nexth, struct netif *netif)
841 {
842   struct ip6_hdr *ip6hdr;
843   ip6_addr_t dest_addr;
844 
845   LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p);
846 
847   /* Should the IPv6 header be generated or is it already included in p? */
848   if (dest != LWIP_IP_HDRINCL) {
849     /* generate IPv6 header */
850     if (pbuf_header(p, IP6_HLEN)) {
851       LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: not enough room for IPv6 header in pbuf\n"));
852       IP6_STATS_INC(ip6.err);
853       return ERR_BUF;
854     }
855 
856     ip6hdr = (struct ip6_hdr *)p->payload;
857     LWIP_ASSERT("check that first pbuf can hold struct ip6_hdr",
858                (p->len >= sizeof(struct ip6_hdr)));
859 
860     IP6H_HOPLIM_SET(ip6hdr, hl);
861     IP6H_NEXTH_SET(ip6hdr, nexth);
862 
863     /* dest cannot be NULL here */
864     ip6_addr_copy(ip6hdr->dest, *dest);
865 
866     IP6H_VTCFL_SET(ip6hdr, 6, tc, 0);
867     IP6H_PLEN_SET(ip6hdr, p->tot_len - IP6_HLEN);
868 
869     if (src == NULL) {
870       src = IP6_ADDR_ANY6;
871     }
872     /* src cannot be NULL here */
873     ip6_addr_copy(ip6hdr->src, *src);
874 
875   } else {
876     /* IP header already included in p */
877     ip6hdr = (struct ip6_hdr *)p->payload;
878     ip6_addr_copy(dest_addr, ip6hdr->dest);
879     dest = &dest_addr;
880   }
881 
882   IP6_STATS_INC(ip6.xmit);
883 
884   LWIP_DEBUGF(IP6_DEBUG, ("ip6_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], (u16_t)netif->num));
885   ip6_debug_print(p);
886 
887 #if ENABLE_LOOPBACK
888   {
889     int i;
890 #if !LWIP_HAVE_LOOPIF
891     if (ip6_addr_isloopback(dest)) {
892       return netif_loop_output(netif, p);
893     }
894 #endif /* !LWIP_HAVE_LOOPIF */
895     for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
896       if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
897           ip6_addr_cmp(dest, netif_ip6_addr(netif, i))) {
898         /* Packet to self, enqueue it for loopback */
899         LWIP_DEBUGF(IP6_DEBUG, ("netif_loop_output()\n"));
900         return netif_loop_output(netif, p);
901       }
902     }
903   }
904 #endif /* ENABLE_LOOPBACK */
905 #if LWIP_IPV6_FRAG
906   /* don't fragment if interface has mtu set to 0 [loopif] */
907   if (netif->mtu && (p->tot_len > nd6_get_destination_mtu(dest, netif))) {
908     return ip6_frag(p, netif, dest);
909   }
910 #endif /* LWIP_IPV6_FRAG */
911 
912   LWIP_DEBUGF(IP6_DEBUG, ("netif->output_ip6()\n"));
913   return netif->output_ip6(netif, p, dest);
914 }
915 
916 /**
917  * Simple interface to ip6_output_if. It finds the outgoing network
918  * interface and calls upon ip6_output_if to do the actual work.
919  *
920  * @param p the packet to send (p->payload points to the data, e.g. next
921             protocol header; if dest == LWIP_IP_HDRINCL, p already includes an
922             IPv6 header and p->payload points to that IPv6 header)
923  * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an
924  *         IP address of the netif is selected and used as source address.
925  *         if src == NULL, IP6_ADDR_ANY is used as source)
926  * @param dest the destination IPv6 address to send the packet to
927  * @param hl the Hop Limit value to be set in the IPv6 header
928  * @param tc the Traffic Class value to be set in the IPv6 header
929  * @param nexth the Next Header to be set in the IPv6 header
930  *
931  * @return ERR_RTE if no route is found
932  *         see ip_output_if() for more return values
933  */
934 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)935 ip6_output(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
936           u8_t hl, u8_t tc, u8_t nexth)
937 {
938   struct netif *netif;
939   struct ip6_hdr *ip6hdr;
940   ip6_addr_t src_addr, dest_addr;
941 
942   LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p);
943 
944   if (dest != LWIP_IP_HDRINCL) {
945     netif = ip6_route(src, dest);
946   } else {
947     /* IP header included in p, read addresses. */
948     ip6hdr = (struct ip6_hdr *)p->payload;
949     ip6_addr_copy(src_addr, ip6hdr->src);
950     ip6_addr_copy(dest_addr, ip6hdr->dest);
951     netif = ip6_route(&src_addr, &dest_addr);
952   }
953 
954   if (netif == NULL) {
955     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",
956         IP6_ADDR_BLOCK1(dest),
957         IP6_ADDR_BLOCK2(dest),
958         IP6_ADDR_BLOCK3(dest),
959         IP6_ADDR_BLOCK4(dest),
960         IP6_ADDR_BLOCK5(dest),
961         IP6_ADDR_BLOCK6(dest),
962         IP6_ADDR_BLOCK7(dest),
963         IP6_ADDR_BLOCK8(dest)));
964     IP6_STATS_INC(ip6.rterr);
965     return ERR_RTE;
966   }
967 
968   return ip6_output_if(p, src, dest, hl, tc, nexth, netif);
969 }
970 
971 
972 #if LWIP_NETIF_HWADDRHINT
973 /** Like ip6_output, but takes and addr_hint pointer that is passed on to netif->addr_hint
974  *  before calling ip6_output_if.
975  *
976  * @param p the packet to send (p->payload points to the data, e.g. next
977             protocol header; if dest == LWIP_IP_HDRINCL, p already includes an
978             IPv6 header and p->payload points to that IPv6 header)
979  * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an
980  *         IP address of the netif is selected and used as source address.
981  *         if src == NULL, IP6_ADDR_ANY is used as source)
982  * @param dest the destination IPv6 address to send the packet to
983  * @param hl the Hop Limit value to be set in the IPv6 header
984  * @param tc the Traffic Class value to be set in the IPv6 header
985  * @param nexth the Next Header to be set in the IPv6 header
986  * @param addr_hint address hint pointer set to netif->addr_hint before
987  *        calling ip_output_if()
988  *
989  * @return ERR_RTE if no route is found
990  *         see ip_output_if() for more return values
991  */
992 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,u8_t * addr_hint)993 ip6_output_hinted(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest,
994           u8_t hl, u8_t tc, u8_t nexth, u8_t *addr_hint)
995 {
996   struct netif *netif;
997   struct ip6_hdr *ip6hdr;
998   ip6_addr_t src_addr, dest_addr;
999   err_t err;
1000 
1001   LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p);
1002 
1003   if (dest != LWIP_IP_HDRINCL) {
1004     netif = ip6_route(src, dest);
1005   } else {
1006     /* IP header included in p, read addresses. */
1007     ip6hdr = (struct ip6_hdr *)p->payload;
1008     ip6_addr_copy(src_addr, ip6hdr->src);
1009     ip6_addr_copy(dest_addr, ip6hdr->dest);
1010     netif = ip6_route(&src_addr, &dest_addr);
1011   }
1012 
1013   if (netif == NULL) {
1014     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",
1015         IP6_ADDR_BLOCK1(dest),
1016         IP6_ADDR_BLOCK2(dest),
1017         IP6_ADDR_BLOCK3(dest),
1018         IP6_ADDR_BLOCK4(dest),
1019         IP6_ADDR_BLOCK5(dest),
1020         IP6_ADDR_BLOCK6(dest),
1021         IP6_ADDR_BLOCK7(dest),
1022         IP6_ADDR_BLOCK8(dest)));
1023     IP6_STATS_INC(ip6.rterr);
1024     return ERR_RTE;
1025   }
1026 
1027   NETIF_SET_HWADDRHINT(netif, addr_hint);
1028   err = ip6_output_if(p, src, dest, hl, tc, nexth, netif);
1029   NETIF_SET_HWADDRHINT(netif, NULL);
1030 
1031   return err;
1032 }
1033 #endif /* LWIP_NETIF_HWADDRHINT*/
1034 
1035 #if LWIP_IPV6_MLD
1036 /**
1037  * Add a hop-by-hop options header with a router alert option and padding.
1038  *
1039  * Used by MLD when sending a Multicast listener report/done message.
1040  *
1041  * @param p the packet to which we will prepend the options header
1042  * @param nexth the next header protocol number (e.g. IP6_NEXTH_ICMP6)
1043  * @param value the value of the router alert option data (e.g. IP6_ROUTER_ALERT_VALUE_MLD)
1044  * @return ERR_OK if hop-by-hop header was added, ERR_* otherwise
1045  */
1046 err_t
ip6_options_add_hbh_ra(struct pbuf * p,u8_t nexth,u8_t value)1047 ip6_options_add_hbh_ra(struct pbuf *p, u8_t nexth, u8_t value)
1048 {
1049   struct ip6_hbh_hdr *hbh_hdr;
1050 
1051   /* Move pointer to make room for hop-by-hop options header. */
1052   if (pbuf_header(p, sizeof(struct ip6_hbh_hdr))) {
1053     LWIP_DEBUGF(IP6_DEBUG, ("ip6_options: no space for options header\n"));
1054     IP6_STATS_INC(ip6.err);
1055     return ERR_BUF;
1056   }
1057 
1058   hbh_hdr = (struct ip6_hbh_hdr *)p->payload;
1059 
1060   /* Set fields. */
1061   hbh_hdr->_nexth = nexth;
1062   hbh_hdr->_hlen = 0;
1063   hbh_hdr->_ra_opt_type = IP6_ROUTER_ALERT_OPTION;
1064   hbh_hdr->_ra_opt_dlen = 2;
1065   hbh_hdr->_ra_opt_data = value;
1066   hbh_hdr->_padn_opt_type = IP6_PADN_ALERT_OPTION;
1067   hbh_hdr->_padn_opt_dlen = 0;
1068 
1069   return ERR_OK;
1070 }
1071 #endif /* LWIP_IPV6_MLD */
1072 
1073 #if IP6_DEBUG
1074 /* Print an IPv6 header by using LWIP_DEBUGF
1075  * @param p an IPv6 packet, p->payload pointing to the IPv6 header
1076  */
1077 void
ip6_debug_print(struct pbuf * p)1078 ip6_debug_print(struct pbuf *p)
1079 {
1080   struct ip6_hdr *ip6hdr = (struct ip6_hdr *)p->payload;
1081 
1082   LWIP_DEBUGF(IP6_DEBUG, ("IPv6 header:\n"));
1083   LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n"));
1084   LWIP_DEBUGF(IP6_DEBUG, ("| %2"U16_F" |  %3"U16_F"  |      %7"U32_F"     | (ver, class, flow)\n",
1085                     IP6H_V(ip6hdr),
1086                     IP6H_TC(ip6hdr),
1087                     IP6H_FL(ip6hdr)));
1088   LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n"));
1089   LWIP_DEBUGF(IP6_DEBUG, ("|     %5"U16_F"     |  %3"U16_F"  |  %3"U16_F"  | (plen, nexth, hopl)\n",
1090                     IP6H_PLEN(ip6hdr),
1091                     IP6H_NEXTH(ip6hdr),
1092                     IP6H_HOPLIM(ip6hdr)));
1093   LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n"));
1094   LWIP_DEBUGF(IP6_DEBUG, ("|  %4"X32_F" |  %4"X32_F" |  %4"X32_F" |  %4"X32_F" | (src)\n",
1095                     IP6_ADDR_BLOCK1(&(ip6hdr->src)),
1096                     IP6_ADDR_BLOCK2(&(ip6hdr->src)),
1097                     IP6_ADDR_BLOCK3(&(ip6hdr->src)),
1098                     IP6_ADDR_BLOCK4(&(ip6hdr->src))));
1099   LWIP_DEBUGF(IP6_DEBUG, ("|  %4"X32_F" |  %4"X32_F" |  %4"X32_F" |  %4"X32_F" |\n",
1100                     IP6_ADDR_BLOCK5(&(ip6hdr->src)),
1101                     IP6_ADDR_BLOCK6(&(ip6hdr->src)),
1102                     IP6_ADDR_BLOCK7(&(ip6hdr->src)),
1103                     IP6_ADDR_BLOCK8(&(ip6hdr->src))));
1104   LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n"));
1105   LWIP_DEBUGF(IP6_DEBUG, ("|  %4"X32_F" |  %4"X32_F" |  %4"X32_F" |  %4"X32_F" | (dest)\n",
1106                     IP6_ADDR_BLOCK1(&(ip6hdr->dest)),
1107                     IP6_ADDR_BLOCK2(&(ip6hdr->dest)),
1108                     IP6_ADDR_BLOCK3(&(ip6hdr->dest)),
1109                     IP6_ADDR_BLOCK4(&(ip6hdr->dest))));
1110   LWIP_DEBUGF(IP6_DEBUG, ("|  %4"X32_F" |  %4"X32_F" |  %4"X32_F" |  %4"X32_F" |\n",
1111                     IP6_ADDR_BLOCK5(&(ip6hdr->dest)),
1112                     IP6_ADDR_BLOCK6(&(ip6hdr->dest)),
1113                     IP6_ADDR_BLOCK7(&(ip6hdr->dest)),
1114                     IP6_ADDR_BLOCK8(&(ip6hdr->dest))));
1115   LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n"));
1116 }
1117 #endif /* IP6_DEBUG */
1118 
1119 #endif /* LWIP_IPV6 */
1120