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: mbed-os-example-blinky-gr-lychee GR-Boads_Camera_sample GR-Boards_Audio_Recoder GR-Boads_Camera_DisplayApp ... more
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/raw.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 /** 00064 * Finds the appropriate network interface for a given IPv6 address. It tries to select 00065 * a netif following a sequence of heuristics: 00066 * 1) if there is only 1 netif, return it 00067 * 2) if the destination is a link-local address, try to match the src address to a netif. 00068 * this is a tricky case because with multiple netifs, link-local addresses only have 00069 * meaning within a particular subnet/link. 00070 * 3) tries to match the destination subnet to a configured address 00071 * 4) tries to find a router 00072 * 5) tries to match the source address to the netif 00073 * 6) returns the default netif, if configured 00074 * 00075 * @param src the source IPv6 address, if known 00076 * @param dest the destination IPv6 address for which to find the route 00077 * @return the netif on which to send to reach dest 00078 */ 00079 struct netif * 00080 ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest) 00081 { 00082 struct netif *netif; 00083 s8_t i; 00084 00085 /* If single netif configuration, fast return. */ 00086 if ((netif_list != NULL) && (netif_list->next == NULL)) { 00087 if (!netif_is_up(netif_list) || !netif_is_link_up(netif_list)) { 00088 return NULL; 00089 } 00090 return netif_list; 00091 } 00092 00093 /* Special processing for link-local addresses. */ 00094 if (ip6_addr_islinklocal(dest)) { 00095 if (ip6_addr_isany(src)) { 00096 /* Use default netif, if Up. */ 00097 if (netif_default == NULL || !netif_is_up(netif_default) || 00098 !netif_is_link_up(netif_default)) { 00099 return NULL; 00100 } 00101 return netif_default; 00102 } 00103 00104 /* Try to find the netif for the source address, checking that link is up. */ 00105 for (netif = netif_list; netif != NULL; netif = netif->next) { 00106 if (!netif_is_up(netif) || !netif_is_link_up(netif)) { 00107 continue; 00108 } 00109 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 00110 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && 00111 ip6_addr_cmp(src, netif_ip6_addr(netif, i))) { 00112 return netif; 00113 } 00114 } 00115 } 00116 00117 /* netif not found, use default netif, if up */ 00118 if (netif_default == NULL || !netif_is_up(netif_default) || 00119 !netif_is_link_up(netif_default)) { 00120 return NULL; 00121 } 00122 return netif_default; 00123 } 00124 00125 /* we come here for non-link-local addresses */ 00126 #ifdef LWIP_HOOK_IP6_ROUTE 00127 netif = LWIP_HOOK_IP6_ROUTE(src, dest); 00128 if (netif != NULL) { 00129 return netif; 00130 } 00131 #endif 00132 00133 /* See if the destination subnet matches a configured address. */ 00134 for (netif = netif_list; netif != NULL; netif = netif->next) { 00135 if (!netif_is_up(netif) || !netif_is_link_up(netif)) { 00136 continue; 00137 } 00138 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 00139 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && 00140 ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) { 00141 return netif; 00142 } 00143 } 00144 } 00145 00146 /* Get the netif for a suitable router. */ 00147 netif = nd6_find_route(dest); 00148 if ((netif != NULL) && netif_is_up(netif) && netif_is_link_up(netif)) { 00149 return netif; 00150 } 00151 00152 /* try with the netif that matches the source address. */ 00153 if (!ip6_addr_isany(src)) { 00154 for (netif = netif_list; netif != NULL; netif = netif->next) { 00155 if (!netif_is_up(netif) || !netif_is_link_up(netif)) { 00156 continue; 00157 } 00158 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 00159 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && 00160 ip6_addr_cmp(src, netif_ip6_addr(netif, i))) { 00161 return netif; 00162 } 00163 } 00164 } 00165 } 00166 00167 #if LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF 00168 /* loopif is disabled, loopback traffic is passed through any netif */ 00169 if (ip6_addr_isloopback(dest)) { 00170 /* don't check for link on loopback traffic */ 00171 if (netif_default != NULL && netif_is_up(netif_default)) { 00172 return netif_default; 00173 } 00174 /* default netif is not up, just use any netif for loopback traffic */ 00175 for (netif = netif_list; netif != NULL; netif = netif->next) { 00176 if (netif_is_up(netif)) { 00177 return netif; 00178 } 00179 } 00180 return NULL; 00181 } 00182 #endif /* LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF */ 00183 00184 /* no matching netif found, use default netif, if up */ 00185 if ((netif_default == NULL) || !netif_is_up(netif_default) || !netif_is_link_up(netif_default)) { 00186 return NULL; 00187 } 00188 return netif_default; 00189 } 00190 00191 /** 00192 * @ingroup ip6 00193 * Select the best IPv6 source address for a given destination 00194 * IPv6 address. Loosely follows RFC 3484. "Strong host" behavior 00195 * is assumed. 00196 * 00197 * @param netif the netif on which to send a packet 00198 * @param dest the destination we are trying to reach 00199 * @return the most suitable source address to use, or NULL if no suitable 00200 * source address is found 00201 */ 00202 const ip_addr_t * 00203 ip6_select_source_address(struct netif *netif, const ip6_addr_t *dest) 00204 { 00205 const ip_addr_t *src = NULL; 00206 u8_t i; 00207 00208 /* If dest is link-local, choose a link-local source. */ 00209 if (ip6_addr_islinklocal(dest) || ip6_addr_ismulticast_linklocal(dest) || ip6_addr_ismulticast_iflocal(dest)) { 00210 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 00211 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && 00212 ip6_addr_islinklocal(netif_ip6_addr(netif, i))) { 00213 return netif_ip_addr6(netif, i); 00214 } 00215 } 00216 } 00217 00218 /* Choose a site-local with matching prefix. */ 00219 if (ip6_addr_issitelocal(dest) || ip6_addr_ismulticast_sitelocal(dest)) { 00220 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 00221 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && 00222 ip6_addr_issitelocal(netif_ip6_addr(netif, i)) && 00223 ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) { 00224 return netif_ip_addr6(netif, i); 00225 } 00226 } 00227 } 00228 00229 /* Choose a unique-local with matching prefix. */ 00230 if (ip6_addr_isuniquelocal(dest) || ip6_addr_ismulticast_orglocal(dest)) { 00231 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 00232 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && 00233 ip6_addr_isuniquelocal(netif_ip6_addr(netif, i)) && 00234 ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) { 00235 return netif_ip_addr6(netif, i); 00236 } 00237 } 00238 } 00239 00240 /* Choose a global with best matching prefix. */ 00241 if (ip6_addr_isglobal(dest) || ip6_addr_ismulticast_global(dest)) { 00242 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 00243 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && 00244 ip6_addr_isglobal(netif_ip6_addr(netif, i))) { 00245 if (src == NULL) { 00246 src = netif_ip_addr6(netif, i); 00247 } 00248 else { 00249 /* Replace src only if we find a prefix match. */ 00250 /* @todo find longest matching prefix. */ 00251 if ((!(ip6_addr_netcmp(ip_2_ip6(src), dest))) && 00252 ip6_addr_netcmp(netif_ip6_addr(netif, i), dest)) { 00253 src = netif_ip_addr6(netif, i); 00254 } 00255 } 00256 } 00257 } 00258 if (src != NULL) { 00259 return src; 00260 } 00261 } 00262 00263 /* Last resort: see if arbitrary prefix matches. */ 00264 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 00265 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && 00266 ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) { 00267 return netif_ip_addr6(netif, i); 00268 } 00269 } 00270 00271 return NULL; 00272 } 00273 00274 #if LWIP_IPV6_FORWARD 00275 /** 00276 * Forwards an IPv6 packet. It finds an appropriate route for the 00277 * packet, decrements the HL value of the packet, and outputs 00278 * the packet on the appropriate interface. 00279 * 00280 * @param p the packet to forward (p->payload points to IP header) 00281 * @param iphdr the IPv6 header of the input packet 00282 * @param inp the netif on which this packet was received 00283 */ 00284 static void 00285 ip6_forward(struct pbuf *p, struct ip6_hdr *iphdr, struct netif *inp) 00286 { 00287 struct netif *netif; 00288 00289 /* do not forward link-local or loopback addresses */ 00290 if (ip6_addr_islinklocal(ip6_current_dest_addr()) || 00291 ip6_addr_isloopback(ip6_current_dest_addr())) { 00292 LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: not forwarding link-local address.\n")); 00293 IP6_STATS_INC(ip6.rterr); 00294 IP6_STATS_INC(ip6.drop); 00295 return; 00296 } 00297 00298 /* Find network interface where to forward this IP packet to. */ 00299 netif = ip6_route(IP6_ADDR_ANY6, ip6_current_dest_addr()); 00300 if (netif == NULL) { 00301 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", 00302 IP6_ADDR_BLOCK1(ip6_current_dest_addr()), 00303 IP6_ADDR_BLOCK2(ip6_current_dest_addr()), 00304 IP6_ADDR_BLOCK3(ip6_current_dest_addr()), 00305 IP6_ADDR_BLOCK4(ip6_current_dest_addr()), 00306 IP6_ADDR_BLOCK5(ip6_current_dest_addr()), 00307 IP6_ADDR_BLOCK6(ip6_current_dest_addr()), 00308 IP6_ADDR_BLOCK7(ip6_current_dest_addr()), 00309 IP6_ADDR_BLOCK8(ip6_current_dest_addr()))); 00310 #if LWIP_ICMP6 00311 /* Don't send ICMP messages in response to ICMP messages */ 00312 if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) { 00313 icmp6_dest_unreach(p, ICMP6_DUR_NO_ROUTE); 00314 } 00315 #endif /* LWIP_ICMP6 */ 00316 IP6_STATS_INC(ip6.rterr); 00317 IP6_STATS_INC(ip6.drop); 00318 return; 00319 } 00320 /* Do not forward packets onto the same network interface on which 00321 * they arrived. */ 00322 if (netif == inp) { 00323 LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: not bouncing packets back on incoming interface.\n")); 00324 IP6_STATS_INC(ip6.rterr); 00325 IP6_STATS_INC(ip6.drop); 00326 return; 00327 } 00328 00329 /* decrement HL */ 00330 IP6H_HOPLIM_SET(iphdr, IP6H_HOPLIM(iphdr) - 1); 00331 /* send ICMP6 if HL == 0 */ 00332 if (IP6H_HOPLIM(iphdr) == 0) { 00333 #if LWIP_ICMP6 00334 /* Don't send ICMP messages in response to ICMP messages */ 00335 if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) { 00336 icmp6_time_exceeded(p, ICMP6_TE_HL); 00337 } 00338 #endif /* LWIP_ICMP6 */ 00339 IP6_STATS_INC(ip6.drop); 00340 return; 00341 } 00342 00343 if (netif->mtu && (p->tot_len > netif->mtu)) { 00344 #if LWIP_ICMP6 00345 /* Don't send ICMP messages in response to ICMP messages */ 00346 if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) { 00347 icmp6_packet_too_big(p, netif->mtu); 00348 } 00349 #endif /* LWIP_ICMP6 */ 00350 IP6_STATS_INC(ip6.drop); 00351 return; 00352 } 00353 00354 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", 00355 IP6_ADDR_BLOCK1(ip6_current_dest_addr()), 00356 IP6_ADDR_BLOCK2(ip6_current_dest_addr()), 00357 IP6_ADDR_BLOCK3(ip6_current_dest_addr()), 00358 IP6_ADDR_BLOCK4(ip6_current_dest_addr()), 00359 IP6_ADDR_BLOCK5(ip6_current_dest_addr()), 00360 IP6_ADDR_BLOCK6(ip6_current_dest_addr()), 00361 IP6_ADDR_BLOCK7(ip6_current_dest_addr()), 00362 IP6_ADDR_BLOCK8(ip6_current_dest_addr()))); 00363 00364 /* transmit pbuf on chosen interface */ 00365 netif->output_ip6(netif, p, ip6_current_dest_addr()); 00366 IP6_STATS_INC(ip6.fw); 00367 IP6_STATS_INC(ip6.xmit); 00368 return; 00369 } 00370 #endif /* LWIP_IPV6_FORWARD */ 00371 00372 /** 00373 * This function is called by the network interface device driver when 00374 * an IPv6 packet is received. The function does the basic checks of the 00375 * IP header such as packet size being at least larger than the header 00376 * size etc. If the packet was not destined for us, the packet is 00377 * forwarded (using ip6_forward). 00378 * 00379 * Finally, the packet is sent to the upper layer protocol input function. 00380 * 00381 * @param p the received IPv6 packet (p->payload points to IPv6 header) 00382 * @param inp the netif on which this packet was received 00383 * @return ERR_OK if the packet was processed (could return ERR_* if it wasn't 00384 * processed, but currently always returns ERR_OK) 00385 */ 00386 err_t 00387 ip6_input(struct pbuf *p, struct netif *inp) 00388 { 00389 struct ip6_hdr *ip6hdr; 00390 struct netif *netif; 00391 u8_t nexth; 00392 u16_t hlen; /* the current header length */ 00393 u8_t i; 00394 #if 0 /*IP_ACCEPT_LINK_LAYER_ADDRESSING*/ 00395 @todo 00396 int check_ip_src=1; 00397 #endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */ 00398 00399 IP6_STATS_INC(ip6.recv); 00400 00401 /* identify the IP header */ 00402 ip6hdr = (struct ip6_hdr *)p->payload; 00403 if (IP6H_V(ip6hdr) != 6) { 00404 LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_WARNING, ("IPv6 packet dropped due to bad version number %"U32_F"\n", 00405 IP6H_V(ip6hdr))); 00406 pbuf_free(p); 00407 IP6_STATS_INC(ip6.err); 00408 IP6_STATS_INC(ip6.drop); 00409 return ERR_OK; 00410 } 00411 00412 #ifdef LWIP_HOOK_IP6_INPUT 00413 if (LWIP_HOOK_IP6_INPUT(p, inp)) { 00414 /* the packet has been eaten */ 00415 return ERR_OK; 00416 } 00417 #endif 00418 00419 /* header length exceeds first pbuf length, or ip length exceeds total pbuf length? */ 00420 if ((IP6_HLEN > p->len) || ((IP6H_PLEN(ip6hdr) + IP6_HLEN) > p->tot_len)) { 00421 if (IP6_HLEN > p->len) { 00422 LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, 00423 ("IPv6 header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet dropped.\n", 00424 (u16_t)IP6_HLEN, p->len)); 00425 } 00426 if ((IP6H_PLEN(ip6hdr) + IP6_HLEN) > p->tot_len) { 00427 LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, 00428 ("IPv6 (plen %"U16_F") is longer than pbuf (len %"U16_F"), IP packet dropped.\n", 00429 (u16_t)(IP6H_PLEN(ip6hdr) + IP6_HLEN), p->tot_len)); 00430 } 00431 /* free (drop) packet pbufs */ 00432 pbuf_free(p); 00433 IP6_STATS_INC(ip6.lenerr); 00434 IP6_STATS_INC(ip6.drop); 00435 return ERR_OK; 00436 } 00437 00438 /* Trim pbuf. This should have been done at the netif layer, 00439 * but we'll do it anyway just to be sure that its done. */ 00440 pbuf_realloc(p, IP6_HLEN + IP6H_PLEN(ip6hdr)); 00441 00442 /* copy IP addresses to aligned ip6_addr_t */ 00443 ip_addr_copy_from_ip6(ip_data.current_iphdr_dest, ip6hdr->dest); 00444 ip_addr_copy_from_ip6(ip_data.current_iphdr_src, ip6hdr->src); 00445 00446 /* Don't accept virtual IPv6 mapped IPv4 addresses */ 00447 if (ip6_addr_isipv6mappedipv4(ip_2_ip6(&ip_data.current_iphdr_dest)) || 00448 ip6_addr_isipv6mappedipv4(ip_2_ip6(&ip_data.current_iphdr_src)) ) { 00449 IP6_STATS_INC(ip6.err); 00450 IP6_STATS_INC(ip6.drop); 00451 return ERR_OK; 00452 } 00453 00454 /* current header pointer. */ 00455 ip_data.current_ip6_header = ip6hdr; 00456 00457 /* In netif, used in case we need to send ICMPv6 packets back. */ 00458 ip_data.current_netif = inp; 00459 ip_data.current_input_netif = inp; 00460 00461 /* match packet against an interface, i.e. is this packet for us? */ 00462 if (ip6_addr_ismulticast(ip6_current_dest_addr())) { 00463 /* Always joined to multicast if-local and link-local all-nodes group. */ 00464 if (ip6_addr_isallnodes_iflocal(ip6_current_dest_addr()) || 00465 ip6_addr_isallnodes_linklocal(ip6_current_dest_addr())) { 00466 netif = inp; 00467 } 00468 #if LWIP_IPV6_MLD 00469 else if (mld6_lookfor_group(inp, ip6_current_dest_addr())) { 00470 netif = inp; 00471 } 00472 #else /* LWIP_IPV6_MLD */ 00473 else if (ip6_addr_issolicitednode(ip6_current_dest_addr())) { 00474 /* Filter solicited node packets when MLD is not enabled 00475 * (for Neighbor discovery). */ 00476 netif = NULL; 00477 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 00478 if (ip6_addr_isvalid(netif_ip6_addr_state(inp, i)) && 00479 ip6_addr_cmp_solicitednode(ip6_current_dest_addr(), netif_ip6_addr(inp, i))) { 00480 netif = inp; 00481 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: solicited node packet accepted on interface %c%c\n", 00482 netif->name[0], netif->name[1])); 00483 break; 00484 } 00485 } 00486 } 00487 #endif /* LWIP_IPV6_MLD */ 00488 else { 00489 netif = NULL; 00490 } 00491 } else { 00492 /* start trying with inp. if that's not acceptable, start walking the 00493 list of configured netifs. 00494 'first' is used as a boolean to mark whether we started walking the list */ 00495 int first = 1; 00496 netif = inp; 00497 do { 00498 /* interface is up? */ 00499 if (netif_is_up(netif)) { 00500 /* unicast to this interface address? address configured? */ 00501 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 00502 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && 00503 ip6_addr_cmp(ip6_current_dest_addr(), netif_ip6_addr(netif, i))) { 00504 /* exit outer loop */ 00505 goto netif_found; 00506 } 00507 } 00508 } 00509 if (first) { 00510 if (ip6_addr_islinklocal(ip6_current_dest_addr()) 00511 #if !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF 00512 || ip6_addr_isloopback(ip6_current_dest_addr()) 00513 #endif /* !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF */ 00514 ) { 00515 /* Do not match link-local addresses to other netifs. The loopback 00516 * address is to be considered link-local and packets to it should be 00517 * dropped on other interfaces, as per RFC 4291 Sec. 2.5.3. This 00518 * requirement cannot be implemented in the case that loopback 00519 * traffic is sent across a non-loopback interface, however. 00520 */ 00521 netif = NULL; 00522 break; 00523 } 00524 first = 0; 00525 netif = netif_list; 00526 } else { 00527 netif = netif->next; 00528 } 00529 if (netif == inp) { 00530 netif = netif->next; 00531 } 00532 } while (netif != NULL); 00533 netif_found: 00534 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet accepted on interface %c%c\n", 00535 netif ? netif->name[0] : 'X', netif? netif->name[1] : 'X')); 00536 } 00537 00538 /* "::" packet source address? (used in duplicate address detection) */ 00539 if (ip6_addr_isany(ip6_current_src_addr()) && 00540 (!ip6_addr_issolicitednode(ip6_current_dest_addr()))) { 00541 /* packet source is not valid */ 00542 /* free (drop) packet pbufs */ 00543 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with src ANY_ADDRESS dropped\n")); 00544 pbuf_free(p); 00545 IP6_STATS_INC(ip6.drop); 00546 goto ip6_input_cleanup; 00547 } 00548 00549 /* packet not for us? */ 00550 if (netif == NULL) { 00551 /* packet not for us, route or discard */ 00552 LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_TRACE, ("ip6_input: packet not for us.\n")); 00553 #if LWIP_IPV6_FORWARD 00554 /* non-multicast packet? */ 00555 if (!ip6_addr_ismulticast(ip6_current_dest_addr())) { 00556 /* try to forward IP packet on (other) interfaces */ 00557 ip6_forward(p, ip6hdr, inp); 00558 } 00559 #endif /* LWIP_IPV6_FORWARD */ 00560 pbuf_free(p); 00561 goto ip6_input_cleanup; 00562 } 00563 00564 /* current netif pointer. */ 00565 ip_data.current_netif = netif; 00566 00567 /* Save next header type. */ 00568 nexth = IP6H_NEXTH(ip6hdr); 00569 00570 /* Init header length. */ 00571 hlen = ip_data.current_ip_header_tot_len = IP6_HLEN; 00572 00573 /* Move to payload. */ 00574 pbuf_header(p, -IP6_HLEN); 00575 00576 /* Process known option extension headers, if present. */ 00577 while (nexth != IP6_NEXTH_NONE) 00578 { 00579 switch (nexth) { 00580 case IP6_NEXTH_HOPBYHOP: 00581 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Hop-by-Hop options header\n")); 00582 /* Get next header type. */ 00583 nexth = *((u8_t *)p->payload); 00584 00585 /* Get the header length. */ 00586 hlen = 8 * (1 + *((u8_t *)p->payload + 1)); 00587 ip_data.current_ip_header_tot_len += hlen; 00588 00589 /* Skip over this header. */ 00590 if (hlen > p->len) { 00591 LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, 00592 ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n", 00593 hlen, p->len)); 00594 /* free (drop) packet pbufs */ 00595 pbuf_free(p); 00596 IP6_STATS_INC(ip6.lenerr); 00597 IP6_STATS_INC(ip6.drop); 00598 goto ip6_input_cleanup; 00599 } 00600 00601 pbuf_header(p, -(s16_t)hlen); 00602 break; 00603 case IP6_NEXTH_DESTOPTS: 00604 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Destination options header\n")); 00605 /* Get next header type. */ 00606 nexth = *((u8_t *)p->payload); 00607 00608 /* Get the header length. */ 00609 hlen = 8 * (1 + *((u8_t *)p->payload + 1)); 00610 ip_data.current_ip_header_tot_len += hlen; 00611 00612 /* Skip over this header. */ 00613 if (hlen > p->len) { 00614 LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, 00615 ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n", 00616 hlen, p->len)); 00617 /* free (drop) packet pbufs */ 00618 pbuf_free(p); 00619 IP6_STATS_INC(ip6.lenerr); 00620 IP6_STATS_INC(ip6.drop); 00621 goto ip6_input_cleanup; 00622 } 00623 00624 pbuf_header(p, -(s16_t)hlen); 00625 break; 00626 case IP6_NEXTH_ROUTING: 00627 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Routing header\n")); 00628 /* Get next header type. */ 00629 nexth = *((u8_t *)p->payload); 00630 00631 /* Get the header length. */ 00632 hlen = 8 * (1 + *((u8_t *)p->payload + 1)); 00633 ip_data.current_ip_header_tot_len += hlen; 00634 00635 /* Skip over this header. */ 00636 if (hlen > p->len) { 00637 LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, 00638 ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n", 00639 hlen, p->len)); 00640 /* free (drop) packet pbufs */ 00641 pbuf_free(p); 00642 IP6_STATS_INC(ip6.lenerr); 00643 IP6_STATS_INC(ip6.drop); 00644 goto ip6_input_cleanup; 00645 } 00646 00647 pbuf_header(p, -(s16_t)hlen); 00648 break; 00649 00650 case IP6_NEXTH_FRAGMENT: 00651 { 00652 struct ip6_frag_hdr *frag_hdr; 00653 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Fragment header\n")); 00654 00655 frag_hdr = (struct ip6_frag_hdr *)p->payload; 00656 00657 /* Get next header type. */ 00658 nexth = frag_hdr->_nexth; 00659 00660 /* Fragment Header length. */ 00661 hlen = 8; 00662 ip_data.current_ip_header_tot_len += hlen; 00663 00664 /* Make sure this header fits in current pbuf. */ 00665 if (hlen > p->len) { 00666 LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, 00667 ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n", 00668 hlen, p->len)); 00669 /* free (drop) packet pbufs */ 00670 pbuf_free(p); 00671 IP6_FRAG_STATS_INC(ip6_frag.lenerr); 00672 IP6_FRAG_STATS_INC(ip6_frag.drop); 00673 goto ip6_input_cleanup; 00674 } 00675 00676 /* Offset == 0 and more_fragments == 0? */ 00677 if ((frag_hdr->_fragment_offset & 00678 PP_HTONS(IP6_FRAG_OFFSET_MASK | IP6_FRAG_MORE_FLAG)) == 0) { 00679 /* This is a 1-fragment packet, usually a packet that we have 00680 * already reassembled. Skip this header anc continue. */ 00681 pbuf_header(p, -(s16_t)hlen); 00682 } else { 00683 #if LWIP_IPV6_REASS 00684 00685 /* reassemble the packet */ 00686 p = ip6_reass(p); 00687 /* packet not fully reassembled yet? */ 00688 if (p == NULL) { 00689 goto ip6_input_cleanup; 00690 } 00691 00692 /* Returned p point to IPv6 header. 00693 * Update all our variables and pointers and continue. */ 00694 ip6hdr = (struct ip6_hdr *)p->payload; 00695 nexth = IP6H_NEXTH(ip6hdr); 00696 hlen = ip_data.current_ip_header_tot_len = IP6_HLEN; 00697 pbuf_header(p, -IP6_HLEN); 00698 00699 #else /* LWIP_IPV6_REASS */ 00700 /* free (drop) packet pbufs */ 00701 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Fragment header dropped (with LWIP_IPV6_REASS==0)\n")); 00702 pbuf_free(p); 00703 IP6_STATS_INC(ip6.opterr); 00704 IP6_STATS_INC(ip6.drop); 00705 goto ip6_input_cleanup; 00706 #endif /* LWIP_IPV6_REASS */ 00707 } 00708 break; 00709 } 00710 default: 00711 goto options_done; 00712 break; 00713 } 00714 } 00715 options_done: 00716 00717 /* p points to IPv6 header again. */ 00718 pbuf_header_force(p, (s16_t)ip_data.current_ip_header_tot_len); 00719 00720 /* send to upper layers */ 00721 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: \n")); 00722 ip6_debug_print(p); 00723 LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len)); 00724 00725 #if LWIP_RAW 00726 /* raw input did not eat the packet? */ 00727 if (raw_input(p, inp) == 0) 00728 #endif /* LWIP_RAW */ 00729 { 00730 switch (nexth) { 00731 case IP6_NEXTH_NONE: 00732 pbuf_free(p); 00733 break; 00734 #if LWIP_UDP 00735 case IP6_NEXTH_UDP: 00736 #if LWIP_UDPLITE 00737 case IP6_NEXTH_UDPLITE: 00738 #endif /* LWIP_UDPLITE */ 00739 /* Point to payload. */ 00740 pbuf_header(p, -(s16_t)ip_data.current_ip_header_tot_len); 00741 udp_input(p, inp); 00742 break; 00743 #endif /* LWIP_UDP */ 00744 #if LWIP_TCP 00745 case IP6_NEXTH_TCP: 00746 /* Point to payload. */ 00747 pbuf_header(p, -(s16_t)ip_data.current_ip_header_tot_len); 00748 tcp_input(p, inp); 00749 break; 00750 #endif /* LWIP_TCP */ 00751 #if LWIP_ICMP6 00752 case IP6_NEXTH_ICMP6: 00753 /* Point to payload. */ 00754 pbuf_header(p, -(s16_t)ip_data.current_ip_header_tot_len); 00755 icmp6_input(p, inp); 00756 break; 00757 #endif /* LWIP_ICMP */ 00758 default: 00759 #if LWIP_ICMP6 00760 /* send ICMP parameter problem unless it was a multicast or ICMPv6 */ 00761 if ((!ip6_addr_ismulticast(ip6_current_dest_addr())) && 00762 (IP6H_NEXTH(ip6hdr) != IP6_NEXTH_ICMP6)) { 00763 icmp6_param_problem(p, ICMP6_PP_HEADER, ip_data.current_ip_header_tot_len - hlen); 00764 } 00765 #endif /* LWIP_ICMP */ 00766 LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_input: Unsupported transport protocol %"U16_F"\n", (u16_t)IP6H_NEXTH(ip6hdr))); 00767 pbuf_free(p); 00768 IP6_STATS_INC(ip6.proterr); 00769 IP6_STATS_INC(ip6.drop); 00770 break; 00771 } 00772 } 00773 00774 ip6_input_cleanup: 00775 ip_data.current_netif = NULL; 00776 ip_data.current_input_netif = NULL; 00777 ip_data.current_ip6_header = NULL; 00778 ip_data.current_ip_header_tot_len = 0; 00779 ip6_addr_set_zero(ip6_current_src_addr()); 00780 ip6_addr_set_zero(ip6_current_dest_addr()); 00781 00782 return ERR_OK; 00783 } 00784 00785 00786 /** 00787 * Sends an IPv6 packet on a network interface. This function constructs 00788 * the IPv6 header. If the source IPv6 address is NULL, the IPv6 "ANY" address is 00789 * used as source (usually during network startup). If the source IPv6 address it 00790 * IP6_ADDR_ANY, the most appropriate IPv6 address of the outgoing network 00791 * interface is filled in as source address. If the destination IPv6 address is 00792 * LWIP_IP_HDRINCL, p is assumed to already include an IPv6 header and 00793 * p->payload points to it instead of the data. 00794 * 00795 * @param p the packet to send (p->payload points to the data, e.g. next 00796 protocol header; if dest == LWIP_IP_HDRINCL, p already includes an 00797 IPv6 header and p->payload points to that IPv6 header) 00798 * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an 00799 * IP address of the netif is selected and used as source address. 00800 * if src == NULL, IP6_ADDR_ANY is used as source) 00801 * @param dest the destination IPv6 address to send the packet to 00802 * @param hl the Hop Limit value to be set in the IPv6 header 00803 * @param tc the Traffic Class value to be set in the IPv6 header 00804 * @param nexth the Next Header to be set in the IPv6 header 00805 * @param netif the netif on which to send this packet 00806 * @return ERR_OK if the packet was sent OK 00807 * ERR_BUF if p doesn't have enough space for IPv6/LINK headers 00808 * returns errors returned by netif->output 00809 */ 00810 err_t 00811 ip6_output_if(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, 00812 u8_t hl, u8_t tc, 00813 u8_t nexth, struct netif *netif) 00814 { 00815 const ip6_addr_t *src_used = src; 00816 if (dest != LWIP_IP_HDRINCL) { 00817 if (src != NULL && ip6_addr_isany(src)) { 00818 src = ip_2_ip6(ip6_select_source_address(netif, dest)); 00819 if ((src == NULL) || ip6_addr_isany(src)) { 00820 /* No appropriate source address was found for this packet. */ 00821 LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: No suitable source address for packet.\n")); 00822 IP6_STATS_INC(ip6.rterr); 00823 return ERR_RTE; 00824 } 00825 } 00826 } 00827 return ip6_output_if_src(p, src_used, dest, hl, tc, nexth, netif); 00828 } 00829 00830 /** 00831 * Same as ip6_output_if() but 'src' address is not replaced by netif address 00832 * when it is 'any'. 00833 */ 00834 err_t 00835 ip6_output_if_src(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, 00836 u8_t hl, u8_t tc, 00837 u8_t nexth, struct netif *netif) 00838 { 00839 struct ip6_hdr *ip6hdr; 00840 ip6_addr_t dest_addr; 00841 00842 LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); 00843 00844 /* Should the IPv6 header be generated or is it already included in p? */ 00845 if (dest != LWIP_IP_HDRINCL) { 00846 /* generate IPv6 header */ 00847 if (pbuf_header(p, IP6_HLEN)) { 00848 LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: not enough room for IPv6 header in pbuf\n")); 00849 IP6_STATS_INC(ip6.err); 00850 return ERR_BUF; 00851 } 00852 00853 ip6hdr = (struct ip6_hdr *)p->payload; 00854 LWIP_ASSERT("check that first pbuf can hold struct ip6_hdr", 00855 (p->len >= sizeof(struct ip6_hdr))); 00856 00857 IP6H_HOPLIM_SET(ip6hdr, hl); 00858 IP6H_NEXTH_SET(ip6hdr, nexth); 00859 00860 /* dest cannot be NULL here */ 00861 ip6_addr_copy(ip6hdr->dest, *dest); 00862 00863 IP6H_VTCFL_SET(ip6hdr, 6, tc, 0); 00864 IP6H_PLEN_SET(ip6hdr, p->tot_len - IP6_HLEN); 00865 00866 if (src == NULL) { 00867 src = IP6_ADDR_ANY6; 00868 } 00869 /* src cannot be NULL here */ 00870 ip6_addr_copy(ip6hdr->src, *src); 00871 00872 } else { 00873 /* IP header already included in p */ 00874 ip6hdr = (struct ip6_hdr *)p->payload; 00875 ip6_addr_copy(dest_addr, ip6hdr->dest); 00876 dest = &dest_addr; 00877 } 00878 00879 IP6_STATS_INC(ip6.xmit); 00880 00881 LWIP_DEBUGF(IP6_DEBUG, ("ip6_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], (u16_t)netif->num)); 00882 ip6_debug_print(p); 00883 00884 #if ENABLE_LOOPBACK 00885 { 00886 int i; 00887 #if !LWIP_HAVE_LOOPIF 00888 if (ip6_addr_isloopback(dest)) { 00889 return netif_loop_output(netif, p); 00890 } 00891 #endif /* !LWIP_HAVE_LOOPIF */ 00892 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 00893 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && 00894 ip6_addr_cmp(dest, netif_ip6_addr(netif, i))) { 00895 /* Packet to self, enqueue it for loopback */ 00896 LWIP_DEBUGF(IP6_DEBUG, ("netif_loop_output()\n")); 00897 return netif_loop_output(netif, p); 00898 } 00899 } 00900 } 00901 #endif /* ENABLE_LOOPBACK */ 00902 #if LWIP_IPV6_FRAG 00903 /* don't fragment if interface has mtu set to 0 [loopif] */ 00904 if (netif->mtu && (p->tot_len > nd6_get_destination_mtu(dest, netif))) { 00905 return ip6_frag(p, netif, dest); 00906 } 00907 #endif /* LWIP_IPV6_FRAG */ 00908 00909 LWIP_DEBUGF(IP6_DEBUG, ("netif->output_ip6()\n")); 00910 return netif->output_ip6(netif, p, dest); 00911 } 00912 00913 /** 00914 * Simple interface to ip6_output_if. It finds the outgoing network 00915 * interface and calls upon ip6_output_if to do the actual work. 00916 * 00917 * @param p the packet to send (p->payload points to the data, e.g. next 00918 protocol header; if dest == LWIP_IP_HDRINCL, p already includes an 00919 IPv6 header and p->payload points to that IPv6 header) 00920 * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an 00921 * IP address of the netif is selected and used as source address. 00922 * if src == NULL, IP6_ADDR_ANY is used as source) 00923 * @param dest the destination IPv6 address to send the packet to 00924 * @param hl the Hop Limit value to be set in the IPv6 header 00925 * @param tc the Traffic Class value to be set in the IPv6 header 00926 * @param nexth the Next Header to be set in the IPv6 header 00927 * 00928 * @return ERR_RTE if no route is found 00929 * see ip_output_if() for more return values 00930 */ 00931 err_t 00932 ip6_output(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, 00933 u8_t hl, u8_t tc, u8_t nexth) 00934 { 00935 struct netif *netif; 00936 struct ip6_hdr *ip6hdr; 00937 ip6_addr_t src_addr, dest_addr; 00938 00939 LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); 00940 00941 if (dest != LWIP_IP_HDRINCL) { 00942 netif = ip6_route(src, dest); 00943 } else { 00944 /* IP header included in p, read addresses. */ 00945 ip6hdr = (struct ip6_hdr *)p->payload; 00946 ip6_addr_copy(src_addr, ip6hdr->src); 00947 ip6_addr_copy(dest_addr, ip6hdr->dest); 00948 netif = ip6_route(&src_addr, &dest_addr); 00949 } 00950 00951 if (netif == NULL) { 00952 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", 00953 IP6_ADDR_BLOCK1(dest), 00954 IP6_ADDR_BLOCK2(dest), 00955 IP6_ADDR_BLOCK3(dest), 00956 IP6_ADDR_BLOCK4(dest), 00957 IP6_ADDR_BLOCK5(dest), 00958 IP6_ADDR_BLOCK6(dest), 00959 IP6_ADDR_BLOCK7(dest), 00960 IP6_ADDR_BLOCK8(dest))); 00961 IP6_STATS_INC(ip6.rterr); 00962 return ERR_RTE; 00963 } 00964 00965 return ip6_output_if(p, src, dest, hl, tc, nexth, netif); 00966 } 00967 00968 00969 #if LWIP_NETIF_HWADDRHINT 00970 /** Like ip6_output, but takes and addr_hint pointer that is passed on to netif->addr_hint 00971 * before calling ip6_output_if. 00972 * 00973 * @param p the packet to send (p->payload points to the data, e.g. next 00974 protocol header; if dest == LWIP_IP_HDRINCL, p already includes an 00975 IPv6 header and p->payload points to that IPv6 header) 00976 * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an 00977 * IP address of the netif is selected and used as source address. 00978 * if src == NULL, IP6_ADDR_ANY is used as source) 00979 * @param dest the destination IPv6 address to send the packet to 00980 * @param hl the Hop Limit value to be set in the IPv6 header 00981 * @param tc the Traffic Class value to be set in the IPv6 header 00982 * @param nexth the Next Header to be set in the IPv6 header 00983 * @param addr_hint address hint pointer set to netif->addr_hint before 00984 * calling ip_output_if() 00985 * 00986 * @return ERR_RTE if no route is found 00987 * see ip_output_if() for more return values 00988 */ 00989 err_t 00990 ip6_output_hinted(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, 00991 u8_t hl, u8_t tc, u8_t nexth, u8_t *addr_hint) 00992 { 00993 struct netif *netif; 00994 struct ip6_hdr *ip6hdr; 00995 ip6_addr_t src_addr, dest_addr; 00996 err_t err; 00997 00998 LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); 00999 01000 if (dest != LWIP_IP_HDRINCL) { 01001 netif = ip6_route(src, dest); 01002 } else { 01003 /* IP header included in p, read addresses. */ 01004 ip6hdr = (struct ip6_hdr *)p->payload; 01005 ip6_addr_copy(src_addr, ip6hdr->src); 01006 ip6_addr_copy(dest_addr, ip6hdr->dest); 01007 netif = ip6_route(&src_addr, &dest_addr); 01008 } 01009 01010 if (netif == NULL) { 01011 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", 01012 IP6_ADDR_BLOCK1(dest), 01013 IP6_ADDR_BLOCK2(dest), 01014 IP6_ADDR_BLOCK3(dest), 01015 IP6_ADDR_BLOCK4(dest), 01016 IP6_ADDR_BLOCK5(dest), 01017 IP6_ADDR_BLOCK6(dest), 01018 IP6_ADDR_BLOCK7(dest), 01019 IP6_ADDR_BLOCK8(dest))); 01020 IP6_STATS_INC(ip6.rterr); 01021 return ERR_RTE; 01022 } 01023 01024 NETIF_SET_HWADDRHINT(netif, addr_hint); 01025 err = ip6_output_if(p, src, dest, hl, tc, nexth, netif); 01026 NETIF_SET_HWADDRHINT(netif, NULL); 01027 01028 return err; 01029 } 01030 #endif /* LWIP_NETIF_HWADDRHINT*/ 01031 01032 #if LWIP_IPV6_MLD 01033 /** 01034 * Add a hop-by-hop options header with a router alert option and padding. 01035 * 01036 * Used by MLD when sending a Multicast listener report/done message. 01037 * 01038 * @param p the packet to which we will prepend the options header 01039 * @param nexth the next header protocol number (e.g. IP6_NEXTH_ICMP6) 01040 * @param value the value of the router alert option data (e.g. IP6_ROUTER_ALERT_VALUE_MLD) 01041 * @return ERR_OK if hop-by-hop header was added, ERR_* otherwise 01042 */ 01043 err_t 01044 ip6_options_add_hbh_ra(struct pbuf *p, u8_t nexth, u8_t value) 01045 { 01046 struct ip6_hbh_hdr *hbh_hdr; 01047 01048 /* Move pointer to make room for hop-by-hop options header. */ 01049 if (pbuf_header(p, sizeof(struct ip6_hbh_hdr))) { 01050 LWIP_DEBUGF(IP6_DEBUG, ("ip6_options: no space for options header\n")); 01051 IP6_STATS_INC(ip6.err); 01052 return ERR_BUF; 01053 } 01054 01055 hbh_hdr = (struct ip6_hbh_hdr *)p->payload; 01056 01057 /* Set fields. */ 01058 hbh_hdr->_nexth = nexth; 01059 hbh_hdr->_hlen = 0; 01060 hbh_hdr->_ra_opt_type = IP6_ROUTER_ALERT_OPTION; 01061 hbh_hdr->_ra_opt_dlen = 2; 01062 hbh_hdr->_ra_opt_data = value; 01063 hbh_hdr->_padn_opt_type = IP6_PADN_ALERT_OPTION; 01064 hbh_hdr->_padn_opt_dlen = 0; 01065 01066 return ERR_OK; 01067 } 01068 #endif /* LWIP_IPV6_MLD */ 01069 01070 #if IP6_DEBUG 01071 /* Print an IPv6 header by using LWIP_DEBUGF 01072 * @param p an IPv6 packet, p->payload pointing to the IPv6 header 01073 */ 01074 void 01075 ip6_debug_print(struct pbuf *p) 01076 { 01077 struct ip6_hdr *ip6hdr = (struct ip6_hdr *)p->payload; 01078 01079 LWIP_DEBUGF(IP6_DEBUG, ("IPv6 header:\n")); 01080 LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); 01081 LWIP_DEBUGF(IP6_DEBUG, ("| %2"U16_F" | %3"U16_F" | %7"U32_F" | (ver, class, flow)\n", 01082 IP6H_V(ip6hdr), 01083 IP6H_TC(ip6hdr), 01084 IP6H_FL(ip6hdr))); 01085 LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); 01086 LWIP_DEBUGF(IP6_DEBUG, ("| %5"U16_F" | %3"U16_F" | %3"U16_F" | (plen, nexth, hopl)\n", 01087 IP6H_PLEN(ip6hdr), 01088 IP6H_NEXTH(ip6hdr), 01089 IP6H_HOPLIM(ip6hdr))); 01090 LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); 01091 LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" | (src)\n", 01092 IP6_ADDR_BLOCK1(&(ip6hdr->src)), 01093 IP6_ADDR_BLOCK2(&(ip6hdr->src)), 01094 IP6_ADDR_BLOCK3(&(ip6hdr->src)), 01095 IP6_ADDR_BLOCK4(&(ip6hdr->src)))); 01096 LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" |\n", 01097 IP6_ADDR_BLOCK5(&(ip6hdr->src)), 01098 IP6_ADDR_BLOCK6(&(ip6hdr->src)), 01099 IP6_ADDR_BLOCK7(&(ip6hdr->src)), 01100 IP6_ADDR_BLOCK8(&(ip6hdr->src)))); 01101 LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); 01102 LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" | (dest)\n", 01103 IP6_ADDR_BLOCK1(&(ip6hdr->dest)), 01104 IP6_ADDR_BLOCK2(&(ip6hdr->dest)), 01105 IP6_ADDR_BLOCK3(&(ip6hdr->dest)), 01106 IP6_ADDR_BLOCK4(&(ip6hdr->dest)))); 01107 LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" |\n", 01108 IP6_ADDR_BLOCK5(&(ip6hdr->dest)), 01109 IP6_ADDR_BLOCK6(&(ip6hdr->dest)), 01110 IP6_ADDR_BLOCK7(&(ip6hdr->dest)), 01111 IP6_ADDR_BLOCK8(&(ip6hdr->dest)))); 01112 LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); 01113 } 01114 #endif /* IP6_DEBUG */ 01115 01116 #endif /* LWIP_IPV6 */
Generated on Tue Jul 12 2022 11:02:26 by
 1.7.2
 1.7.2