Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
lwip_ip6.c
00001 /** 00002 * @file 00003 * 00004 * IPv6 layer. 00005 */ 00006 00007 /* 00008 * Copyright (c) 2010 Inico Technologies Ltd. 00009 * All rights reserved. 00010 * 00011 * Redistribution and use in source and binary forms, with or without modification, 00012 * are permitted provided that the following conditions are met: 00013 * 00014 * 1. Redistributions of source code must retain the above copyright notice, 00015 * this list of conditions and the following disclaimer. 00016 * 2. Redistributions in binary form must reproduce the above copyright notice, 00017 * this list of conditions and the following disclaimer in the documentation 00018 * and/or other materials provided with the distribution. 00019 * 3. The name of the author may not be used to endorse or promote products 00020 * derived from this software without specific prior written permission. 00021 * 00022 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 00023 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00024 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 00025 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00026 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 00027 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00028 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00029 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 00030 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 00031 * OF SUCH DAMAGE. 00032 * 00033 * This file is part of the lwIP TCP/IP stack. 00034 * 00035 * Author: Ivan Delamer <delamer@inicotech.com> 00036 * 00037 * 00038 * Please coordinate changes and requests with Ivan Delamer 00039 * <delamer@inicotech.com> 00040 */ 00041 00042 #include "lwip/opt.h" 00043 00044 #if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ 00045 00046 #include "lwip/def.h" 00047 #include "lwip/mem.h" 00048 #include "lwip/netif.h" 00049 #include "lwip/ip.h" 00050 #include "lwip/ip6.h" 00051 #include "lwip/ip6_addr.h" 00052 #include "lwip/ip6_frag.h" 00053 #include "lwip/icmp6.h" 00054 #include "lwip/priv/raw_priv.h" 00055 #include "lwip/udp.h" 00056 #include "lwip/priv/tcp_priv.h" 00057 #include "lwip/dhcp6.h" 00058 #include "lwip/nd6.h" 00059 #include "lwip/mld6.h" 00060 #include "lwip/debug.h" 00061 #include "lwip/stats.h" 00062 00063 #ifdef LWIP_HOOK_FILENAME 00064 #include LWIP_HOOK_FILENAME 00065 #endif 00066 00067 /** 00068 * Finds the appropriate network interface for a given IPv6 address. It tries to select 00069 * a netif following a sequence of heuristics: 00070 * 1) if there is only 1 netif, return it 00071 * 2) if the destination is a zoned address, match its zone to a netif 00072 * 3) if the either the source or destination address is a scoped address, 00073 * match the source address's zone (if set) or address (if not) to a netif 00074 * 4) tries to match the destination subnet to a configured address 00075 * 5) tries to find a router-announced route 00076 * 6) tries to match the (unscoped) source address to the netif 00077 * 7) returns the default netif, if configured 00078 * 00079 * Note that each of the two given addresses may or may not be properly zoned. 00080 * 00081 * @param src the source IPv6 address, if known 00082 * @param dest the destination IPv6 address for which to find the route 00083 * @return the netif on which to send to reach dest 00084 */ 00085 struct netif * 00086 ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest) 00087 { 00088 #if LWIP_SINGLE_NETIF 00089 LWIP_UNUSED_ARG(src); 00090 LWIP_UNUSED_ARG(dest); 00091 #else /* LWIP_SINGLE_NETIF */ 00092 struct netif *netif; 00093 s8_t i; 00094 00095 LWIP_ASSERT_CORE_LOCKED(); 00096 00097 /* If single netif configuration, fast return. */ 00098 if ((netif_list != NULL) && (netif_list->next == NULL)) { 00099 if (!netif_is_up(netif_list) || !netif_is_link_up(netif_list) || 00100 (ip6_addr_has_zone(dest) && !ip6_addr_test_zone(dest, netif_list))) { 00101 return NULL; 00102 } 00103 return netif_list; 00104 } 00105 00106 #if LWIP_IPV6_SCOPES 00107 /* Special processing for zoned destination addresses. This includes link- 00108 * local unicast addresses and interface/link-local multicast addresses. Use 00109 * the zone to find a matching netif. If the address is not zoned, then there 00110 * is technically no "wrong" netif to choose, and we leave routing to other 00111 * rules; in most cases this should be the scoped-source rule below. */ 00112 if (ip6_addr_has_zone(dest)) { 00113 IP6_ADDR_ZONECHECK(dest); 00114 /* Find a netif based on the zone. For custom mappings, one zone may map 00115 * to multiple netifs, so find one that can actually send a packet. */ 00116 NETIF_FOREACH(netif) { 00117 if (ip6_addr_test_zone(dest, netif) && 00118 netif_is_up(netif) && netif_is_link_up(netif)) { 00119 return netif; 00120 } 00121 } 00122 /* No matching netif found. Do no try to route to a different netif, 00123 * as that would be a zone violation, resulting in any packets sent to 00124 * that netif being dropped on output. */ 00125 return NULL; 00126 } 00127 #endif /* LWIP_IPV6_SCOPES */ 00128 00129 /* Special processing for scoped source and destination addresses. If we get 00130 * here, the destination address does not have a zone, so either way we need 00131 * to look at the source address, which may or may not have a zone. If it 00132 * does, the zone is restrictive: there is (typically) only one matching 00133 * netif for it, and we should avoid routing to any other netif as that would 00134 * result in guaranteed zone violations. For scoped source addresses that do 00135 * not have a zone, use (only) a netif that has that source address locally 00136 * assigned. This case also applies to the loopback source address, which has 00137 * an implied link-local scope. If only the destination address is scoped 00138 * (but, again, not zoned), we still want to use only the source address to 00139 * determine its zone because that's most likely what the user/application 00140 * wants, regardless of whether the source address is scoped. Finally, some 00141 * of this story also applies if scoping is disabled altogether. */ 00142 #if LWIP_IPV6_SCOPES 00143 if (ip6_addr_has_scope(dest, IP6_UNKNOWN) || 00144 ip6_addr_has_scope(src, IP6_UNICAST) || 00145 #else /* LWIP_IPV6_SCOPES */ 00146 if (ip6_addr_islinklocal(dest) || ip6_addr_ismulticast_iflocal(dest) || 00147 ip6_addr_ismulticast_linklocal(dest) || ip6_addr_islinklocal(src) || 00148 #endif /* LWIP_IPV6_SCOPES */ 00149 ip6_addr_isloopback(src)) { 00150 #if LWIP_IPV6_SCOPES 00151 if (ip6_addr_has_zone(src)) { 00152 /* Find a netif matching the source zone (relatively cheap). */ 00153 NETIF_FOREACH(netif) { 00154 if (netif_is_up(netif) && netif_is_link_up(netif) && 00155 ip6_addr_test_zone(src, netif)) { 00156 return netif; 00157 } 00158 } 00159 } else 00160 #endif /* LWIP_IPV6_SCOPES */ 00161 { 00162 /* Find a netif matching the source address (relatively expensive). */ 00163 NETIF_FOREACH(netif) { 00164 if (!netif_is_up(netif) || !netif_is_link_up(netif)) { 00165 continue; 00166 } 00167 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 00168 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && 00169 ip6_addr_cmp_zoneless(src, netif_ip6_addr(netif, i))) { 00170 return netif; 00171 } 00172 } 00173 } 00174 } 00175 /* Again, do not use any other netif in this case, as that could result in 00176 * zone boundary violations. */ 00177 return NULL; 00178 } 00179 00180 /* We come here only if neither source nor destination is scoped. */ 00181 IP6_ADDR_ZONECHECK(src); 00182 00183 #ifdef LWIP_HOOK_IP6_ROUTE 00184 netif = LWIP_HOOK_IP6_ROUTE(src, dest); 00185 if (netif != NULL) { 00186 return netif; 00187 } 00188 #endif 00189 00190 /* See if the destination subnet matches a configured address. In accordance 00191 * with RFC 5942, dynamically configured addresses do not have an implied 00192 * local subnet, and thus should be considered /128 assignments. However, as 00193 * such, the destination address may still match a local address, and so we 00194 * still need to check for exact matches here. By (lwIP) policy, statically 00195 * configured addresses do always have an implied local /64 subnet. */ 00196 NETIF_FOREACH(netif) { 00197 if (!netif_is_up(netif) || !netif_is_link_up(netif)) { 00198 continue; 00199 } 00200 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 00201 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && 00202 ip6_addr_netcmp(dest, netif_ip6_addr(netif, i)) && 00203 (netif_ip6_addr_isstatic(netif, i) || 00204 ip6_addr_nethostcmp(dest, netif_ip6_addr(netif, i)))) { 00205 return netif; 00206 } 00207 } 00208 } 00209 00210 /* Get the netif for a suitable router-announced route. */ 00211 netif = nd6_find_route(dest); 00212 if (netif != NULL) { 00213 return netif; 00214 } 00215 00216 /* Try with the netif that matches the source address. Given the earlier rule 00217 * for scoped source addresses, this applies to unscoped addresses only. */ 00218 if (!ip6_addr_isany(src)) { 00219 NETIF_FOREACH(netif) { 00220 if (!netif_is_up(netif) || !netif_is_link_up(netif)) { 00221 continue; 00222 } 00223 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 00224 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && 00225 ip6_addr_cmp(src, netif_ip6_addr(netif, i))) { 00226 return netif; 00227 } 00228 } 00229 } 00230 } 00231 00232 #if LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF 00233 /* loopif is disabled, loopback traffic is passed through any netif */ 00234 if (ip6_addr_isloopback(dest)) { 00235 /* don't check for link on loopback traffic */ 00236 if (netif_default != NULL && netif_is_up(netif_default)) { 00237 return netif_default; 00238 } 00239 /* default netif is not up, just use any netif for loopback traffic */ 00240 NETIF_FOREACH(netif) { 00241 if (netif_is_up(netif)) { 00242 return netif; 00243 } 00244 } 00245 return NULL; 00246 } 00247 #endif /* LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF */ 00248 #endif /* !LWIP_SINGLE_NETIF */ 00249 00250 /* no matching netif found, use default netif, if up */ 00251 if ((netif_default == NULL) || !netif_is_up(netif_default) || !netif_is_link_up(netif_default)) { 00252 return NULL; 00253 } 00254 return netif_default; 00255 } 00256 00257 /** 00258 * @ingroup ip6 00259 * Select the best IPv6 source address for a given destination IPv6 address. 00260 * 00261 * This implementation follows RFC 6724 Sec. 5 to the following extent: 00262 * - Rules 1, 2, 3: fully implemented 00263 * - Rules 4, 5, 5.5: not applicable 00264 * - Rule 6: not implemented 00265 * - Rule 7: not applicable 00266 * - Rule 8: limited to "prefer /64 subnet match over non-match" 00267 * 00268 * For Rule 2, we deliberately deviate from RFC 6724 Sec. 3.1 by considering 00269 * ULAs to be of smaller scope than global addresses, to avoid that a preferred 00270 * ULA is picked over a deprecated global address when given a global address 00271 * as destination, as that would likely result in broken two-way communication. 00272 * 00273 * As long as temporary addresses are not supported (as used in Rule 7), a 00274 * proper implementation of Rule 8 would obviate the need to implement Rule 6. 00275 * 00276 * @param netif the netif on which to send a packet 00277 * @param dest the destination we are trying to reach (possibly not properly 00278 * zoned) 00279 * @return the most suitable source address to use, or NULL if no suitable 00280 * source address is found 00281 */ 00282 const ip_addr_t * 00283 ip6_select_source_address(struct netif *netif, const ip6_addr_t *dest) 00284 { 00285 const ip_addr_t *best_addr; 00286 const ip6_addr_t *cand_addr; 00287 s8_t dest_scope, cand_scope; 00288 s8_t best_scope = IP6_MULTICAST_SCOPE_RESERVED; 00289 u8_t i, cand_pref, cand_bits; 00290 u8_t best_pref = 0; 00291 u8_t best_bits = 0; 00292 00293 /* Start by determining the scope of the given destination address. These 00294 * tests are hopefully (roughly) in order of likeliness to match. */ 00295 if (ip6_addr_isglobal(dest)) { 00296 dest_scope = IP6_MULTICAST_SCOPE_GLOBAL; 00297 } else if (ip6_addr_islinklocal(dest) || ip6_addr_isloopback(dest)) { 00298 dest_scope = IP6_MULTICAST_SCOPE_LINK_LOCAL; 00299 } else if (ip6_addr_isuniquelocal(dest)) { 00300 dest_scope = IP6_MULTICAST_SCOPE_ORGANIZATION_LOCAL; 00301 } else if (ip6_addr_ismulticast(dest)) { 00302 dest_scope = ip6_addr_multicast_scope(dest); 00303 } else if (ip6_addr_issitelocal(dest)) { 00304 dest_scope = IP6_MULTICAST_SCOPE_SITE_LOCAL; 00305 } else { 00306 /* no match, consider scope global */ 00307 dest_scope = IP6_MULTICAST_SCOPE_GLOBAL; 00308 } 00309 00310 best_addr = NULL; 00311 00312 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 00313 /* Consider only valid (= preferred and deprecated) addresses. */ 00314 if (!ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) { 00315 continue; 00316 } 00317 /* Determine the scope of this candidate address. Same ordering idea. */ 00318 cand_addr = netif_ip6_addr(netif, i); 00319 if (ip6_addr_isglobal(cand_addr)) { 00320 cand_scope = IP6_MULTICAST_SCOPE_GLOBAL; 00321 } else if (ip6_addr_islinklocal(cand_addr)) { 00322 cand_scope = IP6_MULTICAST_SCOPE_LINK_LOCAL; 00323 } else if (ip6_addr_isuniquelocal(cand_addr)) { 00324 cand_scope = IP6_MULTICAST_SCOPE_ORGANIZATION_LOCAL; 00325 } else if (ip6_addr_issitelocal(cand_addr)) { 00326 cand_scope = IP6_MULTICAST_SCOPE_SITE_LOCAL; 00327 } else { 00328 /* no match, treat as low-priority global scope */ 00329 cand_scope = IP6_MULTICAST_SCOPE_RESERVEDF; 00330 } 00331 cand_pref = ip6_addr_ispreferred(netif_ip6_addr_state(netif, i)); 00332 /* @todo compute the actual common bits, for longest matching prefix. */ 00333 /* We cannot count on the destination address having a proper zone 00334 * assignment, so do not compare zones in this case. */ 00335 cand_bits = ip6_addr_netcmp_zoneless(cand_addr, dest); /* just 1 or 0 for now */ 00336 if (cand_bits && ip6_addr_nethostcmp(cand_addr, dest)) { 00337 return netif_ip_addr6(netif, i); /* Rule 1 */ 00338 } 00339 if ((best_addr == NULL) || /* no alternative yet */ 00340 ((cand_scope < best_scope) && (cand_scope >= dest_scope)) || 00341 ((cand_scope > best_scope) && (best_scope < dest_scope)) || /* Rule 2 */ 00342 ((cand_scope == best_scope) && ((cand_pref > best_pref) || /* Rule 3 */ 00343 ((cand_pref == best_pref) && (cand_bits > best_bits))))) { /* Rule 8 */ 00344 /* We found a new "winning" candidate. */ 00345 best_addr = netif_ip_addr6(netif, i); 00346 best_scope = cand_scope; 00347 best_pref = cand_pref; 00348 best_bits = cand_bits; 00349 } 00350 } 00351 00352 return best_addr; /* may be NULL */ 00353 } 00354 00355 #if LWIP_IPV6_FORWARD 00356 /** 00357 * Forwards an IPv6 packet. It finds an appropriate route for the 00358 * packet, decrements the HL value of the packet, and outputs 00359 * the packet on the appropriate interface. 00360 * 00361 * @param p the packet to forward (p->payload points to IP header) 00362 * @param iphdr the IPv6 header of the input packet 00363 * @param inp the netif on which this packet was received 00364 */ 00365 static void 00366 ip6_forward(struct pbuf *p, struct ip6_hdr *iphdr, struct netif *inp) 00367 { 00368 struct netif *netif; 00369 00370 /* do not forward link-local or loopback addresses */ 00371 if (ip6_addr_islinklocal(ip6_current_dest_addr()) || 00372 ip6_addr_isloopback(ip6_current_dest_addr())) { 00373 LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: not forwarding link-local address.\n")); 00374 IP6_STATS_INC(ip6.rterr); 00375 IP6_STATS_INC(ip6.drop); 00376 return; 00377 } 00378 00379 /* Find network interface where to forward this IP packet to. */ 00380 netif = ip6_route(IP6_ADDR_ANY6, ip6_current_dest_addr()); 00381 if (netif == NULL) { 00382 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", 00383 IP6_ADDR_BLOCK1(ip6_current_dest_addr()), 00384 IP6_ADDR_BLOCK2(ip6_current_dest_addr()), 00385 IP6_ADDR_BLOCK3(ip6_current_dest_addr()), 00386 IP6_ADDR_BLOCK4(ip6_current_dest_addr()), 00387 IP6_ADDR_BLOCK5(ip6_current_dest_addr()), 00388 IP6_ADDR_BLOCK6(ip6_current_dest_addr()), 00389 IP6_ADDR_BLOCK7(ip6_current_dest_addr()), 00390 IP6_ADDR_BLOCK8(ip6_current_dest_addr()))); 00391 #if LWIP_ICMP6 00392 /* Don't send ICMP messages in response to ICMP messages */ 00393 if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) { 00394 icmp6_dest_unreach(p, ICMP6_DUR_NO_ROUTE); 00395 } 00396 #endif /* LWIP_ICMP6 */ 00397 IP6_STATS_INC(ip6.rterr); 00398 IP6_STATS_INC(ip6.drop); 00399 return; 00400 } 00401 #if LWIP_IPV6_SCOPES 00402 /* Do not forward packets with a zoned (e.g., link-local) source address 00403 * outside of their zone. We determined the zone a bit earlier, so we know 00404 * that the address is properly zoned here, so we can safely use has_zone. 00405 * Also skip packets with a loopback source address (link-local implied). */ 00406 if ((ip6_addr_has_zone(ip6_current_src_addr()) && 00407 !ip6_addr_test_zone(ip6_current_src_addr(), netif)) || 00408 ip6_addr_isloopback(ip6_current_src_addr())) { 00409 LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: not forwarding packet beyond its source address zone.\n")); 00410 IP6_STATS_INC(ip6.rterr); 00411 IP6_STATS_INC(ip6.drop); 00412 return; 00413 } 00414 #endif /* LWIP_IPV6_SCOPES */ 00415 /* Do not forward packets onto the same network interface on which 00416 * they arrived. */ 00417 if (netif == inp) { 00418 LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: not bouncing packets back on incoming interface.\n")); 00419 IP6_STATS_INC(ip6.rterr); 00420 IP6_STATS_INC(ip6.drop); 00421 return; 00422 } 00423 00424 /* decrement HL */ 00425 IP6H_HOPLIM_SET(iphdr, IP6H_HOPLIM(iphdr) - 1); 00426 /* send ICMP6 if HL == 0 */ 00427 if (IP6H_HOPLIM(iphdr) == 0) { 00428 #if LWIP_ICMP6 00429 /* Don't send ICMP messages in response to ICMP messages */ 00430 if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) { 00431 icmp6_time_exceeded(p, ICMP6_TE_HL); 00432 } 00433 #endif /* LWIP_ICMP6 */ 00434 IP6_STATS_INC(ip6.drop); 00435 return; 00436 } 00437 00438 if (netif->mtu && (p->tot_len > netif->mtu)) { 00439 #if LWIP_ICMP6 00440 /* Don't send ICMP messages in response to ICMP messages */ 00441 if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) { 00442 icmp6_packet_too_big(p, netif->mtu); 00443 } 00444 #endif /* LWIP_ICMP6 */ 00445 IP6_STATS_INC(ip6.drop); 00446 return; 00447 } 00448 00449 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", 00450 IP6_ADDR_BLOCK1(ip6_current_dest_addr()), 00451 IP6_ADDR_BLOCK2(ip6_current_dest_addr()), 00452 IP6_ADDR_BLOCK3(ip6_current_dest_addr()), 00453 IP6_ADDR_BLOCK4(ip6_current_dest_addr()), 00454 IP6_ADDR_BLOCK5(ip6_current_dest_addr()), 00455 IP6_ADDR_BLOCK6(ip6_current_dest_addr()), 00456 IP6_ADDR_BLOCK7(ip6_current_dest_addr()), 00457 IP6_ADDR_BLOCK8(ip6_current_dest_addr()))); 00458 00459 /* transmit pbuf on chosen interface */ 00460 netif->output_ip6(netif, p, ip6_current_dest_addr()); 00461 IP6_STATS_INC(ip6.fw); 00462 IP6_STATS_INC(ip6.xmit); 00463 return; 00464 } 00465 #endif /* LWIP_IPV6_FORWARD */ 00466 00467 /** Return true if the current input packet should be accepted on this netif */ 00468 static int 00469 ip6_input_accept(struct netif *netif) 00470 { 00471 /* interface is up? */ 00472 if (netif_is_up(netif)) { 00473 u8_t i; 00474 /* unicast to this interface address? address configured? */ 00475 /* If custom scopes are used, the destination zone will be tested as 00476 * part of the local-address comparison, but we need to test the source 00477 * scope as well (e.g., is this interface on the same link?). */ 00478 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 00479 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && 00480 ip6_addr_cmp(ip6_current_dest_addr(), netif_ip6_addr(netif, i)) 00481 #if IPV6_CUSTOM_SCOPES 00482 && (!ip6_addr_has_zone(ip6_current_src_addr()) || 00483 ip6_addr_test_zone(ip6_current_src_addr(), netif)) 00484 #endif /* IPV6_CUSTOM_SCOPES */ 00485 ) { 00486 /* accept on this netif */ 00487 return 1; 00488 } 00489 } 00490 } 00491 return 0; 00492 } 00493 00494 /** 00495 * This function is called by the network interface device driver when 00496 * an IPv6 packet is received. The function does the basic checks of the 00497 * IP header such as packet size being at least larger than the header 00498 * size etc. If the packet was not destined for us, the packet is 00499 * forwarded (using ip6_forward). 00500 * 00501 * Finally, the packet is sent to the upper layer protocol input function. 00502 * 00503 * @param p the received IPv6 packet (p->payload points to IPv6 header) 00504 * @param inp the netif on which this packet was received 00505 * @return ERR_OK if the packet was processed (could return ERR_* if it wasn't 00506 * processed, but currently always returns ERR_OK) 00507 */ 00508 err_t 00509 ip6_input(struct pbuf *p, struct netif *inp) 00510 { 00511 struct ip6_hdr *ip6hdr; 00512 struct netif *netif; 00513 const u8_t *nexth; 00514 u16_t hlen, hlen_tot; /* the current header length */ 00515 #if 0 /*IP_ACCEPT_LINK_LAYER_ADDRESSING*/ 00516 @todo 00517 int check_ip_src=1; 00518 #endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */ 00519 #if LWIP_RAW 00520 raw_input_state_t raw_status; 00521 #endif /* LWIP_RAW */ 00522 00523 LWIP_ASSERT_CORE_LOCKED(); 00524 00525 IP6_STATS_INC(ip6.recv); 00526 00527 /* identify the IP header */ 00528 ip6hdr = (struct ip6_hdr *)p->payload; 00529 if (IP6H_V(ip6hdr) != 6) { 00530 LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_WARNING, ("IPv6 packet dropped due to bad version number %"U32_F"\n", 00531 IP6H_V(ip6hdr))); 00532 pbuf_free(p); 00533 IP6_STATS_INC(ip6.err); 00534 IP6_STATS_INC(ip6.drop); 00535 return ERR_OK; 00536 } 00537 00538 #ifdef LWIP_HOOK_IP6_INPUT 00539 if (LWIP_HOOK_IP6_INPUT(p, inp)) { 00540 /* the packet has been eaten */ 00541 return ERR_OK; 00542 } 00543 #endif 00544 00545 /* header length exceeds first pbuf length, or ip length exceeds total pbuf length? */ 00546 if ((IP6_HLEN > p->len) || (IP6H_PLEN(ip6hdr) > (p->tot_len - IP6_HLEN))) { 00547 if (IP6_HLEN > p->len) { 00548 LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, 00549 ("IPv6 header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet dropped.\n", 00550 (u16_t)IP6_HLEN, p->len)); 00551 } 00552 if ((IP6H_PLEN(ip6hdr) + IP6_HLEN) > p->tot_len) { 00553 LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, 00554 ("IPv6 (plen %"U16_F") is longer than pbuf (len %"U16_F"), IP packet dropped.\n", 00555 (u16_t)(IP6H_PLEN(ip6hdr) + IP6_HLEN), p->tot_len)); 00556 } 00557 /* free (drop) packet pbufs */ 00558 pbuf_free(p); 00559 IP6_STATS_INC(ip6.lenerr); 00560 IP6_STATS_INC(ip6.drop); 00561 return ERR_OK; 00562 } 00563 00564 /* Trim pbuf. This should have been done at the netif layer, 00565 * but we'll do it anyway just to be sure that its done. */ 00566 pbuf_realloc(p, (u16_t)(IP6_HLEN + IP6H_PLEN(ip6hdr))); 00567 00568 /* copy IP addresses to aligned ip6_addr_t */ 00569 ip_addr_copy_from_ip6_packed(ip_data.current_iphdr_dest, ip6hdr->dest); 00570 ip_addr_copy_from_ip6_packed(ip_data.current_iphdr_src, ip6hdr->src); 00571 00572 /* Don't accept virtual IPv4 mapped IPv6 addresses. 00573 * Don't accept multicast source addresses. */ 00574 if (ip6_addr_isipv4mappedipv6(ip_2_ip6(&ip_data.current_iphdr_dest)) || 00575 ip6_addr_isipv4mappedipv6(ip_2_ip6(&ip_data.current_iphdr_src)) || 00576 ip6_addr_ismulticast(ip_2_ip6(&ip_data.current_iphdr_src))) { 00577 /* free (drop) packet pbufs */ 00578 pbuf_free(p); 00579 IP6_STATS_INC(ip6.err); 00580 IP6_STATS_INC(ip6.drop); 00581 return ERR_OK; 00582 } 00583 00584 /* Set the appropriate zone identifier on the addresses. */ 00585 ip6_addr_assign_zone(ip_2_ip6(&ip_data.current_iphdr_dest), IP6_UNKNOWN, inp); 00586 ip6_addr_assign_zone(ip_2_ip6(&ip_data.current_iphdr_src), IP6_UNICAST, inp); 00587 00588 /* current header pointer. */ 00589 ip_data.current_ip6_header = ip6hdr; 00590 00591 /* In netif, used in case we need to send ICMPv6 packets back. */ 00592 ip_data.current_netif = inp; 00593 ip_data.current_input_netif = inp; 00594 00595 /* match packet against an interface, i.e. is this packet for us? */ 00596 if (ip6_addr_ismulticast(ip6_current_dest_addr())) { 00597 /* Always joined to multicast if-local and link-local all-nodes group. */ 00598 if (ip6_addr_isallnodes_iflocal(ip6_current_dest_addr()) || 00599 ip6_addr_isallnodes_linklocal(ip6_current_dest_addr())) { 00600 netif = inp; 00601 } 00602 #if LWIP_IPV6_MLD 00603 else if (mld6_lookfor_group(inp, ip6_current_dest_addr())) { 00604 netif = inp; 00605 } 00606 #else /* LWIP_IPV6_MLD */ 00607 else if (ip6_addr_issolicitednode(ip6_current_dest_addr())) { 00608 u8_t i; 00609 /* Filter solicited node packets when MLD is not enabled 00610 * (for Neighbor discovery). */ 00611 netif = NULL; 00612 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 00613 if (ip6_addr_isvalid(netif_ip6_addr_state(inp, i)) && 00614 ip6_addr_cmp_solicitednode(ip6_current_dest_addr(), netif_ip6_addr(inp, i))) { 00615 netif = inp; 00616 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: solicited node packet accepted on interface %c%c\n", 00617 netif->name[0], netif->name[1])); 00618 break; 00619 } 00620 } 00621 } 00622 #endif /* LWIP_IPV6_MLD */ 00623 else { 00624 netif = NULL; 00625 } 00626 } else { 00627 /* start trying with inp. if that's not acceptable, start walking the 00628 list of configured netifs. */ 00629 if (ip6_input_accept(inp)) { 00630 netif = inp; 00631 } else { 00632 netif = NULL; 00633 #if !IPV6_CUSTOM_SCOPES 00634 /* Shortcut: stop looking for other interfaces if either the source or 00635 * the destination has a scope constrained to this interface. Custom 00636 * scopes may break the 1:1 link/interface mapping, however. */ 00637 if (ip6_addr_islinklocal(ip6_current_dest_addr()) || 00638 ip6_addr_islinklocal(ip6_current_src_addr())) { 00639 goto netif_found; 00640 } 00641 #endif /* !IPV6_CUSTOM_SCOPES */ 00642 #if !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF 00643 /* The loopback address is to be considered link-local. Packets to it 00644 * should be dropped on other interfaces, as per RFC 4291 Sec. 2.5.3. 00645 * Its implied scope means packets *from* the loopback address should 00646 * not be accepted on other interfaces, either. These requirements 00647 * cannot be implemented in the case that loopback traffic is sent 00648 * across a non-loopback interface, however. */ 00649 if (ip6_addr_isloopback(ip6_current_dest_addr()) || 00650 ip6_addr_isloopback(ip6_current_src_addr())) { 00651 goto netif_found; 00652 } 00653 #endif /* !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF */ 00654 #if !LWIP_SINGLE_NETIF 00655 NETIF_FOREACH(netif) { 00656 if (netif == inp) { 00657 /* we checked that before already */ 00658 continue; 00659 } 00660 if (ip6_input_accept(netif)) { 00661 break; 00662 } 00663 } 00664 #endif /* !LWIP_SINGLE_NETIF */ 00665 } 00666 netif_found: 00667 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet accepted on interface %c%c\n", 00668 netif ? netif->name[0] : 'X', netif? netif->name[1] : 'X')); 00669 } 00670 00671 /* "::" packet source address? (used in duplicate address detection) */ 00672 if (ip6_addr_isany(ip6_current_src_addr()) && 00673 (!ip6_addr_issolicitednode(ip6_current_dest_addr()))) { 00674 /* packet source is not valid */ 00675 /* free (drop) packet pbufs */ 00676 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with src ANY_ADDRESS dropped\n")); 00677 pbuf_free(p); 00678 IP6_STATS_INC(ip6.drop); 00679 goto ip6_input_cleanup; 00680 } 00681 00682 /* packet not for us? */ 00683 if (netif == NULL) { 00684 /* packet not for us, route or discard */ 00685 LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_TRACE, ("ip6_input: packet not for us.\n")); 00686 #if LWIP_IPV6_FORWARD 00687 /* non-multicast packet? */ 00688 if (!ip6_addr_ismulticast(ip6_current_dest_addr())) { 00689 /* try to forward IP packet on (other) interfaces */ 00690 ip6_forward(p, ip6hdr, inp); 00691 } 00692 #endif /* LWIP_IPV6_FORWARD */ 00693 pbuf_free(p); 00694 goto ip6_input_cleanup; 00695 } 00696 00697 /* current netif pointer. */ 00698 ip_data.current_netif = netif; 00699 00700 /* Save next header type. */ 00701 nexth = &IP6H_NEXTH(ip6hdr); 00702 00703 /* Init header length. */ 00704 hlen = hlen_tot = IP6_HLEN; 00705 00706 /* Move to payload. */ 00707 pbuf_remove_header(p, IP6_HLEN); 00708 00709 /* Process known option extension headers, if present. */ 00710 while (*nexth != IP6_NEXTH_NONE) 00711 { 00712 switch (*nexth) { 00713 case IP6_NEXTH_HOPBYHOP: 00714 { 00715 s32_t opt_offset; 00716 struct ip6_hbh_hdr *hbh_hdr; 00717 struct ip6_opt_hdr *opt_hdr; 00718 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Hop-by-Hop options header\n")); 00719 00720 /* Get and check the header length, while staying in packet bounds. */ 00721 hbh_hdr = (struct ip6_hbh_hdr *)p->payload; 00722 00723 /* Get next header type. */ 00724 nexth = &IP6_HBH_NEXTH(hbh_hdr); 00725 00726 /* Get the header length. */ 00727 hlen = (u16_t)(8 * (1 + hbh_hdr->_hlen)); 00728 00729 if ((p->len < 8) || (hlen > p->len)) { 00730 LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, 00731 ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n", 00732 hlen, p->len)); 00733 /* free (drop) packet pbufs */ 00734 pbuf_free(p); 00735 IP6_STATS_INC(ip6.lenerr); 00736 IP6_STATS_INC(ip6.drop); 00737 goto ip6_input_cleanup; 00738 } 00739 00740 hlen_tot = (u16_t)(hlen_tot + hlen); 00741 00742 /* The extended option header starts right after Hop-by-Hop header. */ 00743 opt_offset = IP6_HBH_HLEN; 00744 while (opt_offset < hlen) 00745 { 00746 s32_t opt_dlen = 0; 00747 00748 opt_hdr = (struct ip6_opt_hdr *)((u8_t *)hbh_hdr + opt_offset); 00749 00750 switch (IP6_OPT_TYPE(opt_hdr)) { 00751 /* @todo: process IPV6 Hop-by-Hop option data */ 00752 case IP6_PAD1_OPTION: 00753 /* PAD1 option doesn't have length and value field */ 00754 opt_dlen = -1; 00755 break; 00756 case IP6_PADN_OPTION: 00757 opt_dlen = IP6_OPT_DLEN(opt_hdr); 00758 break; 00759 case IP6_ROUTER_ALERT_OPTION: 00760 opt_dlen = IP6_OPT_DLEN(opt_hdr); 00761 break; 00762 case IP6_JUMBO_OPTION: 00763 opt_dlen = IP6_OPT_DLEN(opt_hdr); 00764 break; 00765 default: 00766 /* Check 2 MSB of Hop-by-Hop header type. */ 00767 switch (IP6_OPT_TYPE_ACTION(opt_hdr)) { 00768 case 1: 00769 /* Discard the packet. */ 00770 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid Hop-by-Hop option type dropped.\n")); 00771 pbuf_free(p); 00772 IP6_STATS_INC(ip6.drop); 00773 goto ip6_input_cleanup; 00774 case 2: 00775 /* Send ICMP Parameter Problem */ 00776 icmp6_param_problem(p, ICMP6_PP_OPTION, opt_hdr); 00777 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid Hop-by-Hop option type dropped.\n")); 00778 pbuf_free(p); 00779 IP6_STATS_INC(ip6.drop); 00780 goto ip6_input_cleanup; 00781 case 3: 00782 /* Send ICMP Parameter Problem if destination address is not a multicast address */ 00783 if (!ip6_addr_ismulticast(ip6_current_dest_addr())) { 00784 icmp6_param_problem(p, ICMP6_PP_OPTION, opt_hdr); 00785 } 00786 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid Hop-by-Hop option type dropped.\n")); 00787 pbuf_free(p); 00788 IP6_STATS_INC(ip6.drop); 00789 goto ip6_input_cleanup; 00790 default: 00791 /* Skip over this option. */ 00792 opt_dlen = IP6_OPT_DLEN(opt_hdr); 00793 break; 00794 } 00795 break; 00796 } 00797 00798 /* Adjust the offset to move to the next extended option header */ 00799 opt_offset = opt_offset + IP6_OPT_HLEN + opt_dlen; 00800 } 00801 pbuf_remove_header(p, hlen); 00802 break; 00803 } 00804 case IP6_NEXTH_DESTOPTS: 00805 { 00806 s32_t opt_offset; 00807 struct ip6_dest_hdr *dest_hdr; 00808 struct ip6_opt_hdr *opt_hdr; 00809 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Destination options header\n")); 00810 00811 dest_hdr = (struct ip6_dest_hdr *)p->payload; 00812 00813 /* Get next header type. */ 00814 nexth = &IP6_DEST_NEXTH(dest_hdr); 00815 00816 /* Get the header length. */ 00817 hlen = 8 * (1 + dest_hdr->_hlen); 00818 if ((p->len < 8) || (hlen > p->len)) { 00819 LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, 00820 ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n", 00821 hlen, p->len)); 00822 /* free (drop) packet pbufs */ 00823 pbuf_free(p); 00824 IP6_STATS_INC(ip6.lenerr); 00825 IP6_STATS_INC(ip6.drop); 00826 goto ip6_input_cleanup; 00827 } 00828 00829 hlen_tot = (u16_t)(hlen_tot + hlen); 00830 00831 /* The extended option header starts right after Destination header. */ 00832 opt_offset = IP6_DEST_HLEN; 00833 while (opt_offset < hlen) 00834 { 00835 s32_t opt_dlen = 0; 00836 00837 opt_hdr = (struct ip6_opt_hdr *)((u8_t *)dest_hdr + opt_offset); 00838 00839 switch (IP6_OPT_TYPE(opt_hdr)) 00840 { 00841 /* @todo: process IPV6 Destination option data */ 00842 case IP6_PAD1_OPTION: 00843 /* PAD1 option deosn't have length and value field */ 00844 opt_dlen = -1; 00845 break; 00846 case IP6_PADN_OPTION: 00847 opt_dlen = IP6_OPT_DLEN(opt_hdr); 00848 break; 00849 case IP6_ROUTER_ALERT_OPTION: 00850 opt_dlen = IP6_OPT_DLEN(opt_hdr); 00851 break; 00852 case IP6_JUMBO_OPTION: 00853 opt_dlen = IP6_OPT_DLEN(opt_hdr); 00854 break; 00855 case IP6_HOME_ADDRESS_OPTION: 00856 opt_dlen = IP6_OPT_DLEN(opt_hdr); 00857 break; 00858 default: 00859 /* Check 2 MSB of Destination header type. */ 00860 switch (IP6_OPT_TYPE_ACTION(opt_hdr)) 00861 { 00862 case 1: 00863 /* Discard the packet. */ 00864 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid destination option type dropped.\n")); 00865 pbuf_free(p); 00866 IP6_STATS_INC(ip6.drop); 00867 goto ip6_input_cleanup; 00868 case 2: 00869 /* Send ICMP Parameter Problem */ 00870 icmp6_param_problem(p, ICMP6_PP_OPTION, opt_hdr); 00871 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid destination option type dropped.\n")); 00872 pbuf_free(p); 00873 IP6_STATS_INC(ip6.drop); 00874 goto ip6_input_cleanup; 00875 case 3: 00876 /* Send ICMP Parameter Problem if destination address is not a multicast address */ 00877 if (!ip6_addr_ismulticast(ip6_current_dest_addr())) { 00878 icmp6_param_problem(p, ICMP6_PP_OPTION, opt_hdr); 00879 } 00880 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid destination option type dropped.\n")); 00881 pbuf_free(p); 00882 IP6_STATS_INC(ip6.drop); 00883 goto ip6_input_cleanup; 00884 default: 00885 /* Skip over this option. */ 00886 opt_dlen = IP6_OPT_DLEN(opt_hdr); 00887 break; 00888 } 00889 break; 00890 } 00891 00892 /* Adjust the offset to move to the next extended option header */ 00893 opt_offset = opt_offset + IP6_OPT_HLEN + opt_dlen; 00894 } 00895 00896 pbuf_remove_header(p, hlen); 00897 break; 00898 } 00899 case IP6_NEXTH_ROUTING: 00900 { 00901 struct ip6_rout_hdr *rout_hdr; 00902 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Routing header\n")); 00903 00904 rout_hdr = (struct ip6_rout_hdr *)p->payload; 00905 00906 /* Get next header type. */ 00907 nexth = &IP6_ROUT_NEXTH(rout_hdr); 00908 00909 /* Get the header length. */ 00910 hlen = 8 * (1 + rout_hdr->_hlen); 00911 00912 if ((p->len < 8) || (hlen > p->len)) { 00913 LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, 00914 ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n", 00915 hlen, p->len)); 00916 /* free (drop) packet pbufs */ 00917 pbuf_free(p); 00918 IP6_STATS_INC(ip6.lenerr); 00919 IP6_STATS_INC(ip6.drop); 00920 goto ip6_input_cleanup; 00921 } 00922 00923 /* Skip over this header. */ 00924 hlen_tot = (u16_t)(hlen_tot + hlen); 00925 00926 /* if segment left value is 0 in routing header, ignore the option */ 00927 if (IP6_ROUT_SEG_LEFT(rout_hdr)) { 00928 /* The length field of routing option header must be even */ 00929 if (rout_hdr->_hlen & 0x1) { 00930 /* Discard and send parameter field error */ 00931 icmp6_param_problem(p, ICMP6_PP_FIELD, &rout_hdr->_hlen); 00932 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid routing type dropped\n")); 00933 pbuf_free(p); 00934 IP6_STATS_INC(ip6.drop); 00935 goto ip6_input_cleanup; 00936 } 00937 00938 switch (IP6_ROUT_TYPE(rout_hdr)) 00939 { 00940 /* TODO: process routing by the type */ 00941 case IP6_ROUT_TYPE2: 00942 break; 00943 case IP6_ROUT_RPL: 00944 break; 00945 default: 00946 /* Discard unrecognized routing type and send parameter field error */ 00947 icmp6_param_problem(p, ICMP6_PP_FIELD, &IP6_ROUT_TYPE(rout_hdr)); 00948 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid routing type dropped\n")); 00949 pbuf_free(p); 00950 IP6_STATS_INC(ip6.drop); 00951 goto ip6_input_cleanup; 00952 } 00953 } 00954 00955 pbuf_remove_header(p, hlen); 00956 break; 00957 } 00958 case IP6_NEXTH_FRAGMENT: 00959 { 00960 struct ip6_frag_hdr *frag_hdr; 00961 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Fragment header\n")); 00962 00963 frag_hdr = (struct ip6_frag_hdr *)p->payload; 00964 00965 /* Get next header type. */ 00966 nexth = &IP6_FRAG_NEXTH(frag_hdr); 00967 00968 /* Fragment Header length. */ 00969 hlen = 8; 00970 00971 /* Make sure this header fits in current pbuf. */ 00972 if (hlen > p->len) { 00973 LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, 00974 ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n", 00975 hlen, p->len)); 00976 /* free (drop) packet pbufs */ 00977 pbuf_free(p); 00978 IP6_FRAG_STATS_INC(ip6_frag.lenerr); 00979 IP6_FRAG_STATS_INC(ip6_frag.drop); 00980 goto ip6_input_cleanup; 00981 } 00982 00983 hlen_tot = (u16_t)(hlen_tot + hlen); 00984 00985 /* check payload length is multiple of 8 octets when mbit is set */ 00986 if (IP6_FRAG_MBIT(frag_hdr) && (IP6H_PLEN(ip6hdr) & 0x7)) { 00987 /* ipv6 payload length is not multiple of 8 octets */ 00988 icmp6_param_problem(p, ICMP6_PP_FIELD, LWIP_PACKED_CAST(const void *, &ip6hdr->_plen)); 00989 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with invalid payload length dropped\n")); 00990 pbuf_free(p); 00991 IP6_STATS_INC(ip6.drop); 00992 goto ip6_input_cleanup; 00993 } 00994 00995 /* Offset == 0 and more_fragments == 0? */ 00996 if ((frag_hdr->_fragment_offset & 00997 PP_HTONS(IP6_FRAG_OFFSET_MASK | IP6_FRAG_MORE_FLAG)) == 0) { 00998 /* This is a 1-fragment packet. Skip this header and continue. */ 00999 pbuf_remove_header(p, hlen); 01000 } else { 01001 #if LWIP_IPV6_REASS 01002 /* reassemble the packet */ 01003 ip_data.current_ip_header_tot_len = hlen_tot; 01004 p = ip6_reass(p); 01005 /* packet not fully reassembled yet? */ 01006 if (p == NULL) { 01007 goto ip6_input_cleanup; 01008 } 01009 01010 /* Returned p point to IPv6 header. 01011 * Update all our variables and pointers and continue. */ 01012 ip6hdr = (struct ip6_hdr *)p->payload; 01013 nexth = &IP6H_NEXTH(ip6hdr); 01014 hlen = hlen_tot = IP6_HLEN; 01015 pbuf_remove_header(p, IP6_HLEN); 01016 01017 #else /* LWIP_IPV6_REASS */ 01018 /* free (drop) packet pbufs */ 01019 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Fragment header dropped (with LWIP_IPV6_REASS==0)\n")); 01020 pbuf_free(p); 01021 IP6_STATS_INC(ip6.opterr); 01022 IP6_STATS_INC(ip6.drop); 01023 goto ip6_input_cleanup; 01024 #endif /* LWIP_IPV6_REASS */ 01025 } 01026 break; 01027 } 01028 default: 01029 goto options_done; 01030 } 01031 01032 if (*nexth == IP6_NEXTH_HOPBYHOP) { 01033 /* Hop-by-Hop header comes only as a first option */ 01034 icmp6_param_problem(p, ICMP6_PP_HEADER, nexth); 01035 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Hop-by-Hop options header dropped (only valid as a first option)\n")); 01036 pbuf_free(p); 01037 IP6_STATS_INC(ip6.drop); 01038 goto ip6_input_cleanup; 01039 } 01040 } 01041 01042 options_done: 01043 01044 /* send to upper layers */ 01045 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: \n")); 01046 ip6_debug_print(p); 01047 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len)); 01048 01049 ip_data.current_ip_header_tot_len = hlen_tot; 01050 01051 #if LWIP_RAW 01052 /* p points to IPv6 header again for raw_input. */ 01053 pbuf_add_header_force(p, hlen_tot); 01054 /* raw input did not eat the packet? */ 01055 raw_status = raw_input(p, inp); 01056 if (raw_status != RAW_INPUT_EATEN) 01057 { 01058 /* Point to payload. */ 01059 pbuf_remove_header(p, hlen_tot); 01060 #else /* LWIP_RAW */ 01061 { 01062 #endif /* LWIP_RAW */ 01063 switch (*nexth) { 01064 case IP6_NEXTH_NONE: 01065 pbuf_free(p); 01066 break; 01067 #if LWIP_UDP 01068 case IP6_NEXTH_UDP: 01069 #if LWIP_UDPLITE 01070 case IP6_NEXTH_UDPLITE: 01071 #endif /* LWIP_UDPLITE */ 01072 udp_input(p, inp); 01073 break; 01074 #endif /* LWIP_UDP */ 01075 #if LWIP_TCP 01076 case IP6_NEXTH_TCP: 01077 tcp_input(p, inp); 01078 break; 01079 #endif /* LWIP_TCP */ 01080 #if LWIP_ICMP6 01081 case IP6_NEXTH_ICMP6: 01082 icmp6_input(p, inp); 01083 break; 01084 #endif /* LWIP_ICMP */ 01085 default: 01086 #if LWIP_RAW 01087 if (raw_status == RAW_INPUT_DELIVERED) { 01088 /* @todo: ipv6 mib in-delivers? */ 01089 } else 01090 #endif /* LWIP_RAW */ 01091 { 01092 #if LWIP_ICMP6 01093 /* p points to IPv6 header again for raw_input. */ 01094 pbuf_add_header_force(p, hlen_tot); 01095 /* send ICMP parameter problem unless it was a multicast or ICMPv6 */ 01096 if ((!ip6_addr_ismulticast(ip6_current_dest_addr())) && 01097 (IP6H_NEXTH(ip6hdr) != IP6_NEXTH_ICMP6)) { 01098 icmp6_param_problem(p, ICMP6_PP_HEADER, nexth); 01099 } 01100 #endif /* LWIP_ICMP */ 01101 LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_input: Unsupported transport protocol %"U16_F"\n", (u16_t)IP6H_NEXTH(ip6hdr))); 01102 IP6_STATS_INC(ip6.proterr); 01103 IP6_STATS_INC(ip6.drop); 01104 } 01105 pbuf_free(p); 01106 break; 01107 } 01108 } 01109 01110 ip6_input_cleanup: 01111 ip_data.current_netif = NULL; 01112 ip_data.current_input_netif = NULL; 01113 ip_data.current_ip6_header = NULL; 01114 ip_data.current_ip_header_tot_len = 0; 01115 ip6_addr_set_zero(ip6_current_src_addr()); 01116 ip6_addr_set_zero(ip6_current_dest_addr()); 01117 01118 return ERR_OK; 01119 } 01120 01121 01122 /** 01123 * Sends an IPv6 packet on a network interface. This function constructs 01124 * the IPv6 header. If the source IPv6 address is NULL, the IPv6 "ANY" address is 01125 * used as source (usually during network startup). If the source IPv6 address it 01126 * IP6_ADDR_ANY, the most appropriate IPv6 address of the outgoing network 01127 * interface is filled in as source address. If the destination IPv6 address is 01128 * LWIP_IP_HDRINCL, p is assumed to already include an IPv6 header and 01129 * p->payload points to it instead of the data. 01130 * 01131 * @param p the packet to send (p->payload points to the data, e.g. next 01132 protocol header; if dest == LWIP_IP_HDRINCL, p already includes an 01133 IPv6 header and p->payload points to that IPv6 header) 01134 * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an 01135 * IP address of the netif is selected and used as source address. 01136 * if src == NULL, IP6_ADDR_ANY is used as source) (src is possibly not 01137 * properly zoned) 01138 * @param dest the destination IPv6 address to send the packet to (possibly not 01139 * properly zoned) 01140 * @param hl the Hop Limit value to be set in the IPv6 header 01141 * @param tc the Traffic Class value to be set in the IPv6 header 01142 * @param nexth the Next Header to be set in the IPv6 header 01143 * @param netif the netif on which to send this packet 01144 * @return ERR_OK if the packet was sent OK 01145 * ERR_BUF if p doesn't have enough space for IPv6/LINK headers 01146 * returns errors returned by netif->output_ip6 01147 */ 01148 err_t 01149 ip6_output_if(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, 01150 u8_t hl, u8_t tc, 01151 u8_t nexth, struct netif *netif) 01152 { 01153 const ip6_addr_t *src_used = src; 01154 if (dest != LWIP_IP_HDRINCL) { 01155 if (src != NULL && ip6_addr_isany(src)) { 01156 src_used = ip_2_ip6(ip6_select_source_address(netif, dest)); 01157 if ((src_used == NULL) || ip6_addr_isany(src_used)) { 01158 /* No appropriate source address was found for this packet. */ 01159 LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: No suitable source address for packet.\n")); 01160 IP6_STATS_INC(ip6.rterr); 01161 return ERR_RTE; 01162 } 01163 } 01164 } 01165 return ip6_output_if_src(p, src_used, dest, hl, tc, nexth, netif); 01166 } 01167 01168 /** 01169 * Same as ip6_output_if() but 'src' address is not replaced by netif address 01170 * when it is 'any'. 01171 */ 01172 err_t 01173 ip6_output_if_src(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, 01174 u8_t hl, u8_t tc, 01175 u8_t nexth, struct netif *netif) 01176 { 01177 struct ip6_hdr *ip6hdr; 01178 ip6_addr_t dest_addr; 01179 01180 LWIP_ASSERT_CORE_LOCKED(); 01181 LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); 01182 01183 /* Should the IPv6 header be generated or is it already included in p? */ 01184 if (dest != LWIP_IP_HDRINCL) { 01185 #if LWIP_IPV6_SCOPES 01186 /* If the destination address is scoped but lacks a zone, add a zone now, 01187 * based on the outgoing interface. The lower layers (e.g., nd6) absolutely 01188 * require addresses to be properly zoned for correctness. In some cases, 01189 * earlier attempts will have been made to add a zone to the destination, 01190 * but this function is the only one that is called in all (other) cases, 01191 * so we must do this here. */ 01192 if (ip6_addr_lacks_zone(dest, IP6_UNKNOWN)) { 01193 ip6_addr_copy(dest_addr, *dest); 01194 ip6_addr_assign_zone(&dest_addr, IP6_UNKNOWN, netif); 01195 dest = &dest_addr; 01196 } 01197 #endif /* LWIP_IPV6_SCOPES */ 01198 01199 /* generate IPv6 header */ 01200 if (pbuf_add_header(p, IP6_HLEN)) { 01201 LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: not enough room for IPv6 header in pbuf\n")); 01202 IP6_STATS_INC(ip6.err); 01203 return ERR_BUF; 01204 } 01205 01206 ip6hdr = (struct ip6_hdr *)p->payload; 01207 LWIP_ASSERT("check that first pbuf can hold struct ip6_hdr", 01208 (p->len >= sizeof(struct ip6_hdr))); 01209 01210 IP6H_HOPLIM_SET(ip6hdr, hl); 01211 IP6H_NEXTH_SET(ip6hdr, nexth); 01212 01213 /* dest cannot be NULL here */ 01214 ip6_addr_copy_to_packed(ip6hdr->dest, *dest); 01215 01216 IP6H_VTCFL_SET(ip6hdr, 6, tc, 0); 01217 IP6H_PLEN_SET(ip6hdr, (u16_t)(p->tot_len - IP6_HLEN)); 01218 01219 if (src == NULL) { 01220 src = IP6_ADDR_ANY6; 01221 } 01222 /* src cannot be NULL here */ 01223 ip6_addr_copy_to_packed(ip6hdr->src, *src); 01224 01225 } else { 01226 /* IP header already included in p */ 01227 ip6hdr = (struct ip6_hdr *)p->payload; 01228 ip6_addr_copy_from_packed(dest_addr, ip6hdr->dest); 01229 ip6_addr_assign_zone(&dest_addr, IP6_UNKNOWN, netif); 01230 dest = &dest_addr; 01231 } 01232 01233 IP6_STATS_INC(ip6.xmit); 01234 01235 LWIP_DEBUGF(IP6_DEBUG, ("ip6_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], (u16_t)netif->num)); 01236 ip6_debug_print(p); 01237 01238 #if ENABLE_LOOPBACK 01239 { 01240 int i; 01241 #if !LWIP_HAVE_LOOPIF 01242 if (ip6_addr_isloopback(dest)) { 01243 return netif_loop_output(netif, p); 01244 } 01245 #endif /* !LWIP_HAVE_LOOPIF */ 01246 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 01247 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && 01248 ip6_addr_cmp(dest, netif_ip6_addr(netif, i))) { 01249 /* Packet to self, enqueue it for loopback */ 01250 LWIP_DEBUGF(IP6_DEBUG, ("netif_loop_output()\n")); 01251 return netif_loop_output(netif, p); 01252 } 01253 } 01254 } 01255 #if LWIP_MULTICAST_TX_OPTIONS 01256 if ((p->flags & PBUF_FLAG_MCASTLOOP) != 0) { 01257 netif_loop_output(netif, p); 01258 } 01259 #endif /* LWIP_MULTICAST_TX_OPTIONS */ 01260 #endif /* ENABLE_LOOPBACK */ 01261 #if LWIP_IPV6_FRAG 01262 /* don't fragment if interface has mtu set to 0 [loopif] */ 01263 if (netif_mtu6(netif) && (p->tot_len > nd6_get_destination_mtu(dest, netif))) { 01264 return ip6_frag(p, netif, dest); 01265 } 01266 #endif /* LWIP_IPV6_FRAG */ 01267 01268 LWIP_DEBUGF(IP6_DEBUG, ("netif->output_ip6()\n")); 01269 return netif->output_ip6(netif, p, dest); 01270 } 01271 01272 /** 01273 * Simple interface to ip6_output_if. It finds the outgoing network 01274 * interface and calls upon ip6_output_if to do the actual work. 01275 * 01276 * @param p the packet to send (p->payload points to the data, e.g. next 01277 protocol header; if dest == LWIP_IP_HDRINCL, p already includes an 01278 IPv6 header and p->payload points to that IPv6 header) 01279 * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an 01280 * IP address of the netif is selected and used as source address. 01281 * if src == NULL, IP6_ADDR_ANY is used as source) 01282 * @param dest the destination IPv6 address to send the packet to 01283 * @param hl the Hop Limit value to be set in the IPv6 header 01284 * @param tc the Traffic Class value to be set in the IPv6 header 01285 * @param nexth the Next Header to be set in the IPv6 header 01286 * 01287 * @return ERR_RTE if no route is found 01288 * see ip_output_if() for more return values 01289 */ 01290 err_t 01291 ip6_output(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, 01292 u8_t hl, u8_t tc, u8_t nexth) 01293 { 01294 struct netif *netif; 01295 struct ip6_hdr *ip6hdr; 01296 ip6_addr_t src_addr, dest_addr; 01297 01298 LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); 01299 01300 if (dest != LWIP_IP_HDRINCL) { 01301 netif = ip6_route(src, dest); 01302 } else { 01303 /* IP header included in p, read addresses. */ 01304 ip6hdr = (struct ip6_hdr *)p->payload; 01305 ip6_addr_copy_from_packed(src_addr, ip6hdr->src); 01306 ip6_addr_copy_from_packed(dest_addr, ip6hdr->dest); 01307 netif = ip6_route(&src_addr, &dest_addr); 01308 } 01309 01310 if (netif == NULL) { 01311 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", 01312 IP6_ADDR_BLOCK1(dest), 01313 IP6_ADDR_BLOCK2(dest), 01314 IP6_ADDR_BLOCK3(dest), 01315 IP6_ADDR_BLOCK4(dest), 01316 IP6_ADDR_BLOCK5(dest), 01317 IP6_ADDR_BLOCK6(dest), 01318 IP6_ADDR_BLOCK7(dest), 01319 IP6_ADDR_BLOCK8(dest))); 01320 IP6_STATS_INC(ip6.rterr); 01321 return ERR_RTE; 01322 } 01323 01324 return ip6_output_if(p, src, dest, hl, tc, nexth, netif); 01325 } 01326 01327 01328 #if LWIP_NETIF_USE_HINTS 01329 /** Like ip6_output, but takes and addr_hint pointer that is passed on to netif->addr_hint 01330 * before calling ip6_output_if. 01331 * 01332 * @param p the packet to send (p->payload points to the data, e.g. next 01333 protocol header; if dest == LWIP_IP_HDRINCL, p already includes an 01334 IPv6 header and p->payload points to that IPv6 header) 01335 * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an 01336 * IP address of the netif is selected and used as source address. 01337 * if src == NULL, IP6_ADDR_ANY is used as source) 01338 * @param dest the destination IPv6 address to send the packet to 01339 * @param hl the Hop Limit value to be set in the IPv6 header 01340 * @param tc the Traffic Class value to be set in the IPv6 header 01341 * @param nexth the Next Header to be set in the IPv6 header 01342 * @param netif_hint netif output hint pointer set to netif->hint before 01343 * calling ip_output_if() 01344 * 01345 * @return ERR_RTE if no route is found 01346 * see ip_output_if() for more return values 01347 */ 01348 err_t 01349 ip6_output_hinted(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, 01350 u8_t hl, u8_t tc, u8_t nexth, struct netif_hint *netif_hint) 01351 { 01352 struct netif *netif; 01353 struct ip6_hdr *ip6hdr; 01354 ip6_addr_t src_addr, dest_addr; 01355 err_t err; 01356 01357 LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); 01358 01359 if (dest != LWIP_IP_HDRINCL) { 01360 netif = ip6_route(src, dest); 01361 } else { 01362 /* IP header included in p, read addresses. */ 01363 ip6hdr = (struct ip6_hdr *)p->payload; 01364 ip6_addr_copy_from_packed(src_addr, ip6hdr->src); 01365 ip6_addr_copy_from_packed(dest_addr, ip6hdr->dest); 01366 netif = ip6_route(&src_addr, &dest_addr); 01367 } 01368 01369 if (netif == NULL) { 01370 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", 01371 IP6_ADDR_BLOCK1(dest), 01372 IP6_ADDR_BLOCK2(dest), 01373 IP6_ADDR_BLOCK3(dest), 01374 IP6_ADDR_BLOCK4(dest), 01375 IP6_ADDR_BLOCK5(dest), 01376 IP6_ADDR_BLOCK6(dest), 01377 IP6_ADDR_BLOCK7(dest), 01378 IP6_ADDR_BLOCK8(dest))); 01379 IP6_STATS_INC(ip6.rterr); 01380 return ERR_RTE; 01381 } 01382 01383 NETIF_SET_HINTS(netif, netif_hint); 01384 err = ip6_output_if(p, src, dest, hl, tc, nexth, netif); 01385 NETIF_RESET_HINTS(netif); 01386 01387 return err; 01388 } 01389 #endif /* LWIP_NETIF_USE_HINTS*/ 01390 01391 #if LWIP_IPV6_MLD 01392 /** 01393 * Add a hop-by-hop options header with a router alert option and padding. 01394 * 01395 * Used by MLD when sending a Multicast listener report/done message. 01396 * 01397 * @param p the packet to which we will prepend the options header 01398 * @param nexth the next header protocol number (e.g. IP6_NEXTH_ICMP6) 01399 * @param value the value of the router alert option data (e.g. IP6_ROUTER_ALERT_VALUE_MLD) 01400 * @return ERR_OK if hop-by-hop header was added, ERR_* otherwise 01401 */ 01402 err_t 01403 ip6_options_add_hbh_ra(struct pbuf *p, u8_t nexth, u8_t value) 01404 { 01405 u8_t *opt_data; 01406 u32_t offset = 0; 01407 struct ip6_hbh_hdr *hbh_hdr; 01408 struct ip6_opt_hdr *opt_hdr; 01409 01410 /* fixed 4 bytes for router alert option and 2 bytes padding */ 01411 const u8_t hlen = (sizeof(struct ip6_opt_hdr) * 2) + IP6_ROUTER_ALERT_DLEN; 01412 /* Move pointer to make room for hop-by-hop options header. */ 01413 if (pbuf_add_header(p, sizeof(struct ip6_hbh_hdr) + hlen)) { 01414 LWIP_DEBUGF(IP6_DEBUG, ("ip6_options: no space for options header\n")); 01415 IP6_STATS_INC(ip6.err); 01416 return ERR_BUF; 01417 } 01418 01419 /* Set fields of Hop-by-Hop header */ 01420 hbh_hdr = (struct ip6_hbh_hdr *)p->payload; 01421 IP6_HBH_NEXTH(hbh_hdr) = nexth; 01422 hbh_hdr->_hlen = 0; 01423 offset = IP6_HBH_HLEN; 01424 01425 /* Set router alert options to Hop-by-Hop extended option header */ 01426 opt_hdr = (struct ip6_opt_hdr *)((u8_t *)hbh_hdr + offset); 01427 IP6_OPT_TYPE(opt_hdr) = IP6_ROUTER_ALERT_OPTION; 01428 IP6_OPT_DLEN(opt_hdr) = IP6_ROUTER_ALERT_DLEN; 01429 offset += IP6_OPT_HLEN; 01430 01431 /* Set router alert option data */ 01432 opt_data = (u8_t *)hbh_hdr + offset; 01433 opt_data[0] = value; 01434 opt_data[1] = 0; 01435 offset += IP6_OPT_DLEN(opt_hdr); 01436 01437 /* add 2 bytes padding to make 8 bytes Hop-by-Hop header length */ 01438 opt_hdr = (struct ip6_opt_hdr *)((u8_t *)hbh_hdr + offset); 01439 IP6_OPT_TYPE(opt_hdr) = IP6_PADN_OPTION; 01440 IP6_OPT_DLEN(opt_hdr) = 0; 01441 01442 return ERR_OK; 01443 } 01444 #endif /* LWIP_IPV6_MLD */ 01445 01446 #if IP6_DEBUG 01447 /* Print an IPv6 header by using LWIP_DEBUGF 01448 * @param p an IPv6 packet, p->payload pointing to the IPv6 header 01449 */ 01450 void 01451 ip6_debug_print(struct pbuf *p) 01452 { 01453 struct ip6_hdr *ip6hdr = (struct ip6_hdr *)p->payload; 01454 01455 TRACE_TO_ASCII_HEX_DUMPF("IP>", IP6H_PLEN(ip6hdr) + 40, (char *) ip6hdr); 01456 01457 LWIP_DEBUGF(IP6_DEBUG, ("IPv6 header:\n")); 01458 LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); 01459 LWIP_DEBUGF(IP6_DEBUG, ("| %2"U16_F" | %3"U16_F" | %7"U32_F" | (ver, class, flow)\n", 01460 IP6H_V(ip6hdr), 01461 IP6H_TC(ip6hdr), 01462 IP6H_FL(ip6hdr))); 01463 LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); 01464 LWIP_DEBUGF(IP6_DEBUG, ("| %5"U16_F" | %3"U16_F" | %3"U16_F" | (plen, nexth, hopl)\n", 01465 IP6H_PLEN(ip6hdr), 01466 IP6H_NEXTH(ip6hdr), 01467 IP6H_HOPLIM(ip6hdr))); 01468 LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); 01469 LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" | (src)\n", 01470 IP6_ADDR_BLOCK1(&(ip6hdr->src)), 01471 IP6_ADDR_BLOCK2(&(ip6hdr->src)), 01472 IP6_ADDR_BLOCK3(&(ip6hdr->src)), 01473 IP6_ADDR_BLOCK4(&(ip6hdr->src)))); 01474 LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" |\n", 01475 IP6_ADDR_BLOCK5(&(ip6hdr->src)), 01476 IP6_ADDR_BLOCK6(&(ip6hdr->src)), 01477 IP6_ADDR_BLOCK7(&(ip6hdr->src)), 01478 IP6_ADDR_BLOCK8(&(ip6hdr->src)))); 01479 LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); 01480 LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" | (dest)\n", 01481 IP6_ADDR_BLOCK1(&(ip6hdr->dest)), 01482 IP6_ADDR_BLOCK2(&(ip6hdr->dest)), 01483 IP6_ADDR_BLOCK3(&(ip6hdr->dest)), 01484 IP6_ADDR_BLOCK4(&(ip6hdr->dest)))); 01485 LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" |\n", 01486 IP6_ADDR_BLOCK5(&(ip6hdr->dest)), 01487 IP6_ADDR_BLOCK6(&(ip6hdr->dest)), 01488 IP6_ADDR_BLOCK7(&(ip6hdr->dest)), 01489 IP6_ADDR_BLOCK8(&(ip6hdr->dest)))); 01490 LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); 01491 } 01492 #endif /* IP6_DEBUG */ 01493 01494 #endif /* LWIP_IPV6 */
Generated on Tue Jul 12 2022 13:54:28 by
