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.
Fork of mbed-os by
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 13:15:53 by
