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