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