Contiki 2.6
|
00001 /** 00002 * \addtogroup uip6 00003 * @{ 00004 */ 00005 00006 /** 00007 * \file 00008 * Neighbor discovery (RFC 4861) 00009 * \author Mathilde Durvy <mdurvy@cisco.com> 00010 * \author Julien Abeille <jabeille@cisco.com> 00011 */ 00012 00013 /* 00014 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 00015 * All rights reserved. 00016 * 00017 * Redistribution and use in source and binary forms, with or without 00018 * modification, are permitted provided that the following conditions 00019 * are met: 00020 * 1. Redistributions of source code must retain the above copyright 00021 * notice, this list of conditions and the following disclaimer. 00022 * 2. Redistributions in binary form must reproduce the above copyright 00023 * notice, this list of conditions and the following disclaimer in the 00024 * documentation and/or other materials provided with the distribution. 00025 * 3. Neither the name of the project nor the names of its contributors 00026 * may be used to endorse or promote products derived from this software 00027 * without specific prior written permission. 00028 * 00029 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 00030 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00031 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00032 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 00033 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00034 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00035 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00036 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00037 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00038 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00039 * SUCH DAMAGE. 00040 */ 00041 /* 00042 * Copyright (c) 2006, Swedish Institute of Computer Science. 00043 * All rights reserved. 00044 * 00045 * Redistribution and use in source and binary forms, with or without 00046 * modification, are permitted provided that the following conditions 00047 * are met: 00048 * 1. Redistributions of source code must retain the above copyright 00049 * notice, this list of conditions and the following disclaimer. 00050 * 2. Redistributions in binary form must reproduce the above copyright 00051 * notice, this list of conditions and the following disclaimer in the 00052 * documentation and/or other materials provided with the distribution. 00053 * 3. Neither the name of the Institute nor the names of its contributors 00054 * may be used to endorse or promote products derived from this software 00055 * without specific prior written permission. 00056 * 00057 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 00058 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00059 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00060 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 00061 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00062 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00063 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00064 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00065 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00066 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00067 * SUCH DAMAGE. 00068 * 00069 */ 00070 00071 #include <string.h> 00072 #include "net/uip-icmp6.h" 00073 #include "net/uip-nd6.h" 00074 #include "net/uip-ds6.h" 00075 #include "lib/random.h" 00076 00077 /*------------------------------------------------------------------*/ 00078 #define DEBUG 0 00079 #include "net/uip-debug.h" 00080 00081 #if UIP_LOGGING 00082 #include <stdio.h> 00083 void uip_log(char *msg); 00084 00085 #define UIP_LOG(m) uip_log(m) 00086 #else 00087 #define UIP_LOG(m) 00088 #endif /* UIP_LOGGING == 1 */ 00089 00090 /*------------------------------------------------------------------*/ 00091 /** @{ */ 00092 /** \name Pointers to the header structures. 00093 * All pointers except UIP_IP_BUF depend on uip_ext_len, which at 00094 * packet reception, is the total length of the extension headers. 00095 * 00096 * The pointer to ND6 options header also depends on nd6_opt_offset, 00097 * which we set in each function. 00098 * 00099 * Care should be taken when manipulating these buffers about the 00100 * value of these length variables 00101 */ 00102 00103 #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) /**< Pointer to IP header */ 00104 #define UIP_ICMP_BUF ((struct uip_icmp_hdr *)&uip_buf[uip_l2_l3_hdr_len]) /**< Pointer to ICMP header*/ 00105 /**@{ Pointers to messages just after icmp header */ 00106 #define UIP_ND6_RS_BUF ((uip_nd6_rs *)&uip_buf[uip_l2_l3_icmp_hdr_len]) 00107 #define UIP_ND6_RA_BUF ((uip_nd6_ra *)&uip_buf[uip_l2_l3_icmp_hdr_len]) 00108 #define UIP_ND6_NS_BUF ((uip_nd6_ns *)&uip_buf[uip_l2_l3_icmp_hdr_len]) 00109 #define UIP_ND6_NA_BUF ((uip_nd6_na *)&uip_buf[uip_l2_l3_icmp_hdr_len]) 00110 /** @} */ 00111 /** Pointer to ND option */ 00112 #define UIP_ND6_OPT_HDR_BUF ((uip_nd6_opt_hdr *)&uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset]) 00113 #define UIP_ND6_OPT_PREFIX_BUF ((uip_nd6_opt_prefix_info *)&uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset]) 00114 #define UIP_ND6_OPT_MTU_BUF ((uip_nd6_opt_mtu *)&uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset]) 00115 /** @} */ 00116 00117 static uint8_t nd6_opt_offset; /** Offset from the end of the icmpv6 header to the option in uip_buf*/ 00118 static uint8_t *nd6_opt_llao; /** Pointer to llao option in uip_buf */ 00119 00120 #if !UIP_CONF_ROUTER // TBD see if we move it to ra_input 00121 static uip_nd6_opt_prefix_info *nd6_opt_prefix_info; /** Pointer to prefix information option in uip_buf */ 00122 static uip_ipaddr_t ipaddr; 00123 static uip_ds6_prefix_t *prefix; /** Pointer to a prefix list entry */ 00124 #endif 00125 static uip_ds6_nbr_t *nbr; /** Pointer to a nbr cache entry*/ 00126 static uip_ds6_defrt_t *defrt; /** Pointer to a router list entry */ 00127 static uip_ds6_addr_t *addr; /** Pointer to an interface address */ 00128 00129 00130 /*------------------------------------------------------------------*/ 00131 /* create a llao */ 00132 static void 00133 create_llao(uint8_t *llao, uint8_t type) { 00134 llao[UIP_ND6_OPT_TYPE_OFFSET] = type; 00135 llao[UIP_ND6_OPT_LEN_OFFSET] = UIP_ND6_OPT_LLAO_LEN >> 3; 00136 memcpy(&llao[UIP_ND6_OPT_DATA_OFFSET], &uip_lladdr, UIP_LLADDR_LEN); 00137 /* padding on some */ 00138 memset(&llao[UIP_ND6_OPT_DATA_OFFSET + UIP_LLADDR_LEN], 0, 00139 UIP_ND6_OPT_LLAO_LEN - 2 - UIP_LLADDR_LEN); 00140 } 00141 00142 /*------------------------------------------------------------------*/ 00143 00144 00145 void 00146 uip_nd6_ns_input(void) 00147 { 00148 uint8_t flags; 00149 PRINTF("Received NS from "); 00150 PRINT6ADDR(&UIP_IP_BUF->srcipaddr); 00151 PRINTF(" to "); 00152 PRINT6ADDR(&UIP_IP_BUF->destipaddr); 00153 PRINTF(" with target address"); 00154 PRINT6ADDR((uip_ipaddr_t *) (&UIP_ND6_NS_BUF->tgtipaddr)); 00155 PRINTF("\n"); 00156 UIP_STAT(++uip_stat.nd6.recv); 00157 00158 #if UIP_CONF_IPV6_CHECKS 00159 if((UIP_IP_BUF->ttl != UIP_ND6_HOP_LIMIT) || 00160 (uip_is_addr_mcast(&UIP_ND6_NS_BUF->tgtipaddr)) || 00161 (UIP_ICMP_BUF->icode != 0)) { 00162 PRINTF("NS received is bad\n"); 00163 goto discard; 00164 } 00165 #endif /* UIP_CONF_IPV6_CHECKS */ 00166 00167 /* Options processing */ 00168 nd6_opt_llao = NULL; 00169 nd6_opt_offset = UIP_ND6_NS_LEN; 00170 while(uip_l3_icmp_hdr_len + nd6_opt_offset < uip_len) { 00171 #if UIP_CONF_IPV6_CHECKS 00172 if(UIP_ND6_OPT_HDR_BUF->len == 0) { 00173 PRINTF("NS received is bad\n"); 00174 goto discard; 00175 } 00176 #endif /* UIP_CONF_IPV6_CHECKS */ 00177 switch (UIP_ND6_OPT_HDR_BUF->type) { 00178 case UIP_ND6_OPT_SLLAO: 00179 nd6_opt_llao = &uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset]; 00180 #if UIP_CONF_IPV6_CHECKS 00181 /* There must be NO option in a DAD NS */ 00182 if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) { 00183 PRINTF("NS received is bad\n"); 00184 goto discard; 00185 } else { 00186 #endif /*UIP_CONF_IPV6_CHECKS */ 00187 nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr); 00188 if(nbr == NULL) { 00189 uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, 00190 (uip_lladdr_t *)&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], 00191 0, NBR_STALE); 00192 } else { 00193 if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], 00194 &nbr->lladdr, UIP_LLADDR_LEN) != 0) { 00195 memcpy(&nbr->lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], 00196 UIP_LLADDR_LEN); 00197 nbr->state = NBR_STALE; 00198 } else { 00199 if(nbr->state == NBR_INCOMPLETE) { 00200 nbr->state = NBR_STALE; 00201 } 00202 } 00203 } 00204 #if UIP_CONF_IPV6_CHECKS 00205 } 00206 #endif /*UIP_CONF_IPV6_CHECKS */ 00207 break; 00208 default: 00209 PRINTF("ND option not supported in NS"); 00210 break; 00211 } 00212 nd6_opt_offset += (UIP_ND6_OPT_HDR_BUF->len << 3); 00213 } 00214 00215 addr = uip_ds6_addr_lookup(&UIP_ND6_NS_BUF->tgtipaddr); 00216 if(addr != NULL) { 00217 #if UIP_ND6_DEF_MAXDADNS > 0 00218 if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) { 00219 /* DAD CASE */ 00220 #if UIP_CONF_IPV6_CHECKS 00221 if(!uip_is_addr_solicited_node(&UIP_IP_BUF->destipaddr)) { 00222 PRINTF("NS received is bad\n"); 00223 goto discard; 00224 } 00225 #endif /* UIP_CONF_IPV6_CHECKS */ 00226 if(addr->state != ADDR_TENTATIVE) { 00227 uip_create_linklocal_allnodes_mcast(&UIP_IP_BUF->destipaddr); 00228 uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr); 00229 flags = UIP_ND6_NA_FLAG_OVERRIDE; 00230 goto create_na; 00231 } else { 00232 /** \todo if I sent a NS before him, I win */ 00233 uip_ds6_dad_failed(addr); 00234 goto discard; 00235 } 00236 #else /* UIP_ND6_DEF_MAXDADNS > 0 */ 00237 if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) { 00238 /* DAD CASE */ 00239 goto discard; 00240 #endif /* UIP_ND6_DEF_MAXDADNS > 0 */ 00241 } 00242 #if UIP_CONF_IPV6_CHECKS 00243 if(uip_ds6_is_my_addr(&UIP_IP_BUF->srcipaddr)) { 00244 /** 00245 * \NOTE do we do something here? we both are using the same address. 00246 * If we are doing dad, we could cancel it, though we should receive a 00247 * NA in response of DAD NS we sent, hence DAD will fail anyway. If we 00248 * were not doing DAD, it means there is a duplicate in the network! 00249 */ 00250 PRINTF("NS received is bad\n"); 00251 goto discard; 00252 } 00253 #endif /*UIP_CONF_IPV6_CHECKS */ 00254 00255 /* Address resolution case */ 00256 if(uip_is_addr_solicited_node(&UIP_IP_BUF->destipaddr)) { 00257 uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &UIP_IP_BUF->srcipaddr); 00258 uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, &UIP_ND6_NS_BUF->tgtipaddr); 00259 flags = UIP_ND6_NA_FLAG_SOLICITED | UIP_ND6_NA_FLAG_OVERRIDE; 00260 goto create_na; 00261 } 00262 00263 /* NUD CASE */ 00264 if(uip_ds6_addr_lookup(&UIP_IP_BUF->destipaddr) == addr) { 00265 uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &UIP_IP_BUF->srcipaddr); 00266 uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, &UIP_ND6_NS_BUF->tgtipaddr); 00267 flags = UIP_ND6_NA_FLAG_SOLICITED | UIP_ND6_NA_FLAG_OVERRIDE; 00268 goto create_na; 00269 } else { 00270 #if UIP_CONF_IPV6_CHECKS 00271 PRINTF("NS received is bad\n"); 00272 goto discard; 00273 #endif /* UIP_CONF_IPV6_CHECKS */ 00274 } 00275 } else { 00276 goto discard; 00277 } 00278 00279 00280 create_na: 00281 /* If the node is a router it should set R flag in NAs */ 00282 #if UIP_CONF_ROUTER 00283 flags = flags | UIP_ND6_NA_FLAG_ROUTER; 00284 #endif 00285 uip_ext_len = 0; 00286 UIP_IP_BUF->vtc = 0x60; 00287 UIP_IP_BUF->tcflow = 0; 00288 UIP_IP_BUF->flow = 0; 00289 UIP_IP_BUF->len[0] = 0; /* length will not be more than 255 */ 00290 UIP_IP_BUF->len[1] = UIP_ICMPH_LEN + UIP_ND6_NA_LEN + UIP_ND6_OPT_LLAO_LEN; 00291 UIP_IP_BUF->proto = UIP_PROTO_ICMP6; 00292 UIP_IP_BUF->ttl = UIP_ND6_HOP_LIMIT; 00293 00294 UIP_ICMP_BUF->type = ICMP6_NA; 00295 UIP_ICMP_BUF->icode = 0; 00296 00297 UIP_ND6_NA_BUF->flagsreserved = flags; 00298 memcpy(&UIP_ND6_NA_BUF->tgtipaddr, &addr->ipaddr, sizeof(uip_ipaddr_t)); 00299 00300 create_llao(&uip_buf[uip_l2_l3_icmp_hdr_len + UIP_ND6_NA_LEN], 00301 UIP_ND6_OPT_TLLAO); 00302 00303 UIP_ICMP_BUF->icmpchksum = 0; 00304 UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum(); 00305 00306 uip_len = 00307 UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_NA_LEN + UIP_ND6_OPT_LLAO_LEN; 00308 00309 UIP_STAT(++uip_stat.nd6.sent); 00310 PRINTF("Sending NA to "); 00311 PRINT6ADDR(&UIP_IP_BUF->destipaddr); 00312 PRINTF(" from "); 00313 PRINT6ADDR(&UIP_IP_BUF->srcipaddr); 00314 PRINTF(" with target address "); 00315 PRINT6ADDR(&UIP_ND6_NA_BUF->tgtipaddr); 00316 PRINTF("\n"); 00317 return; 00318 00319 discard: 00320 uip_len = 0; 00321 return; 00322 } 00323 00324 00325 00326 /*------------------------------------------------------------------*/ 00327 void 00328 uip_nd6_ns_output(uip_ipaddr_t * src, uip_ipaddr_t * dest, uip_ipaddr_t * tgt) 00329 { 00330 uip_ext_len = 0; 00331 UIP_IP_BUF->vtc = 0x60; 00332 UIP_IP_BUF->tcflow = 0; 00333 UIP_IP_BUF->flow = 0; 00334 UIP_IP_BUF->proto = UIP_PROTO_ICMP6; 00335 UIP_IP_BUF->ttl = UIP_ND6_HOP_LIMIT; 00336 00337 if(dest == NULL) { 00338 uip_create_solicited_node(tgt, &UIP_IP_BUF->destipaddr); 00339 } else { 00340 uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, dest); 00341 } 00342 UIP_ICMP_BUF->type = ICMP6_NS; 00343 UIP_ICMP_BUF->icode = 0; 00344 UIP_ND6_NS_BUF->reserved = 0; 00345 uip_ipaddr_copy((uip_ipaddr_t *) &UIP_ND6_NS_BUF->tgtipaddr, tgt); 00346 UIP_IP_BUF->len[0] = 0; /* length will not be more than 255 */ 00347 /* 00348 * check if we add a SLLAO option: for DAD, MUST NOT, for NUD, MAY 00349 * (here yes), for Address resolution , MUST 00350 */ 00351 if(!(uip_ds6_is_my_addr(tgt))) { 00352 if(src != NULL) { 00353 uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, src); 00354 } else { 00355 uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr); 00356 } 00357 if (uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) { 00358 PRINTF("Dropping NS due to no suitable source address\n"); 00359 uip_len = 0; 00360 return; 00361 } 00362 UIP_IP_BUF->len[1] = 00363 UIP_ICMPH_LEN + UIP_ND6_NS_LEN + UIP_ND6_OPT_LLAO_LEN; 00364 00365 create_llao(&uip_buf[uip_l2_l3_icmp_hdr_len + UIP_ND6_NS_LEN], 00366 UIP_ND6_OPT_SLLAO); 00367 00368 uip_len = 00369 UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_NS_LEN + UIP_ND6_OPT_LLAO_LEN; 00370 } else { 00371 uip_create_unspecified(&UIP_IP_BUF->srcipaddr); 00372 UIP_IP_BUF->len[1] = UIP_ICMPH_LEN + UIP_ND6_NS_LEN; 00373 uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_NS_LEN; 00374 } 00375 00376 UIP_ICMP_BUF->icmpchksum = 0; 00377 UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum(); 00378 00379 UIP_STAT(++uip_stat.nd6.sent); 00380 PRINTF("Sending NS to"); 00381 PRINT6ADDR(&UIP_IP_BUF->destipaddr); 00382 PRINTF("from"); 00383 PRINT6ADDR(&UIP_IP_BUF->srcipaddr); 00384 PRINTF("with target address"); 00385 PRINT6ADDR(tgt); 00386 PRINTF("\n"); 00387 return; 00388 } 00389 00390 00391 00392 /*------------------------------------------------------------------*/ 00393 void 00394 uip_nd6_na_input(void) 00395 { 00396 uint8_t is_llchange; 00397 uint8_t is_router; 00398 uint8_t is_solicited; 00399 uint8_t is_override; 00400 00401 PRINTF("Received NA from"); 00402 PRINT6ADDR(&UIP_IP_BUF->srcipaddr); 00403 PRINTF("to"); 00404 PRINT6ADDR(&UIP_IP_BUF->destipaddr); 00405 PRINTF("with target address"); 00406 PRINT6ADDR((uip_ipaddr_t *) (&UIP_ND6_NA_BUF->tgtipaddr)); 00407 PRINTF("\n"); 00408 UIP_STAT(++uip_stat.nd6.recv); 00409 00410 /* 00411 * booleans. the three last one are not 0 or 1 but 0 or 0x80, 0x40, 0x20 00412 * but it works. Be careful though, do not use tests such as is_router == 1 00413 */ 00414 is_llchange = 0; 00415 is_router = ((UIP_ND6_NA_BUF->flagsreserved & UIP_ND6_NA_FLAG_ROUTER)); 00416 is_solicited = 00417 ((UIP_ND6_NA_BUF->flagsreserved & UIP_ND6_NA_FLAG_SOLICITED)); 00418 is_override = 00419 ((UIP_ND6_NA_BUF->flagsreserved & UIP_ND6_NA_FLAG_OVERRIDE)); 00420 00421 #if UIP_CONF_IPV6_CHECKS 00422 if((UIP_IP_BUF->ttl != UIP_ND6_HOP_LIMIT) || 00423 (UIP_ICMP_BUF->icode != 0) || 00424 (uip_is_addr_mcast(&UIP_ND6_NA_BUF->tgtipaddr)) || 00425 (is_solicited && uip_is_addr_mcast(&UIP_IP_BUF->destipaddr))) { 00426 PRINTF("NA received is bad\n"); 00427 goto discard; 00428 } 00429 #endif /*UIP_CONF_IPV6_CHECKS */ 00430 00431 /* Options processing: we handle TLLAO, and must ignore others */ 00432 nd6_opt_offset = UIP_ND6_NA_LEN; 00433 nd6_opt_llao = NULL; 00434 while(uip_l3_icmp_hdr_len + nd6_opt_offset < uip_len) { 00435 #if UIP_CONF_IPV6_CHECKS 00436 if(UIP_ND6_OPT_HDR_BUF->len == 0) { 00437 PRINTF("NA received is bad\n"); 00438 goto discard; 00439 } 00440 #endif /*UIP_CONF_IPV6_CHECKS */ 00441 switch (UIP_ND6_OPT_HDR_BUF->type) { 00442 case UIP_ND6_OPT_TLLAO: 00443 nd6_opt_llao = (uint8_t *)UIP_ND6_OPT_HDR_BUF; 00444 break; 00445 default: 00446 PRINTF("ND option not supported in NA\n"); 00447 break; 00448 } 00449 nd6_opt_offset += (UIP_ND6_OPT_HDR_BUF->len << 3); 00450 } 00451 addr = uip_ds6_addr_lookup(&UIP_ND6_NA_BUF->tgtipaddr); 00452 /* Message processing, including TLLAO if any */ 00453 if(addr != NULL) { 00454 #if UIP_ND6_DEF_MAXDADNS > 0 00455 if(addr->state == ADDR_TENTATIVE) { 00456 uip_ds6_dad_failed(addr); 00457 } 00458 #endif /*UIP_ND6_DEF_MAXDADNS > 0 */ 00459 PRINTF("NA received is bad\n"); 00460 goto discard; 00461 } else { 00462 nbr = uip_ds6_nbr_lookup(&UIP_ND6_NA_BUF->tgtipaddr); 00463 if(nbr == NULL) { 00464 goto discard; 00465 } 00466 if(nd6_opt_llao != 0) { 00467 is_llchange = 00468 memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], (void *)(&nbr->lladdr), 00469 UIP_LLADDR_LEN); 00470 } 00471 if(nbr->state == NBR_INCOMPLETE) { 00472 if(nd6_opt_llao == NULL) { 00473 goto discard; 00474 } 00475 memcpy(&nbr->lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], 00476 UIP_LLADDR_LEN); 00477 if(is_solicited) { 00478 nbr->state = NBR_REACHABLE; 00479 nbr->nscount = 0; 00480 00481 /* reachable time is stored in ms */ 00482 stimer_set(&(nbr->reachable), uip_ds6_if.reachable_time / 1000); 00483 00484 } else { 00485 nbr->state = NBR_STALE; 00486 } 00487 nbr->isrouter = is_router; 00488 } else { 00489 if(!is_override && is_llchange) { 00490 if(nbr->state == NBR_REACHABLE) { 00491 nbr->state = NBR_STALE; 00492 } 00493 goto discard; 00494 } else { 00495 if(is_override || (!is_override && nd6_opt_llao != 0 && !is_llchange) 00496 || nd6_opt_llao == 0) { 00497 if(nd6_opt_llao != 0) { 00498 memcpy(&nbr->lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], 00499 UIP_LLADDR_LEN); 00500 } 00501 if(is_solicited) { 00502 nbr->state = NBR_REACHABLE; 00503 /* reachable time is stored in ms */ 00504 stimer_set(&(nbr->reachable), uip_ds6_if.reachable_time / 1000); 00505 } else { 00506 if(nd6_opt_llao != 0 && is_llchange) { 00507 nbr->state = NBR_STALE; 00508 } 00509 } 00510 } 00511 } 00512 if(nbr->isrouter && !is_router) { 00513 defrt = uip_ds6_defrt_lookup(&UIP_IP_BUF->srcipaddr); 00514 if(defrt != NULL) { 00515 uip_ds6_defrt_rm(defrt); 00516 } 00517 } 00518 nbr->isrouter = is_router; 00519 } 00520 } 00521 #if UIP_CONF_IPV6_QUEUE_PKT 00522 /* The nbr is now reachable, check if we had buffered a pkt for it */ 00523 /*if(nbr->queue_buf_len != 0) { 00524 uip_len = nbr->queue_buf_len; 00525 memcpy(UIP_IP_BUF, nbr->queue_buf, uip_len); 00526 nbr->queue_buf_len = 0; 00527 return; 00528 }*/ 00529 if(uip_packetqueue_buflen(&nbr->packethandle) != 0) { 00530 uip_len = uip_packetqueue_buflen(&nbr->packethandle); 00531 memcpy(UIP_IP_BUF, uip_packetqueue_buf(&nbr->packethandle), uip_len); 00532 uip_packetqueue_free(&nbr->packethandle); 00533 return; 00534 } 00535 00536 #endif /*UIP_CONF_IPV6_QUEUE_PKT */ 00537 00538 discard: 00539 uip_len = 0; 00540 return; 00541 } 00542 00543 00544 #if UIP_CONF_ROUTER 00545 #if UIP_ND6_SEND_RA 00546 /*---------------------------------------------------------------------------*/ 00547 void 00548 uip_nd6_rs_input(void) 00549 { 00550 00551 PRINTF("Received RS from"); 00552 PRINT6ADDR(&UIP_IP_BUF->srcipaddr); 00553 PRINTF("to"); 00554 PRINT6ADDR(&UIP_IP_BUF->destipaddr); 00555 PRINTF("\n"); 00556 UIP_STAT(++uip_stat.nd6.recv); 00557 00558 00559 #if UIP_CONF_IPV6_CHECKS 00560 /* 00561 * Check hop limit / icmp code 00562 * target address must not be multicast 00563 * if the NA is solicited, dest must not be multicast 00564 */ 00565 if((UIP_IP_BUF->ttl != UIP_ND6_HOP_LIMIT) || (UIP_ICMP_BUF->icode != 0)) { 00566 PRINTF("RS received is bad\n"); 00567 goto discard; 00568 } 00569 #endif /*UIP_CONF_IPV6_CHECKS */ 00570 00571 /* Only valid option is Source Link-Layer Address option any thing 00572 else is discarded */ 00573 nd6_opt_offset = UIP_ND6_RS_LEN; 00574 nd6_opt_llao = NULL; 00575 00576 while(uip_l3_icmp_hdr_len + nd6_opt_offset < uip_len) { 00577 #if UIP_CONF_IPV6_CHECKS 00578 if(UIP_ND6_OPT_HDR_BUF->len == 0) { 00579 PRINTF("RS received is bad\n"); 00580 goto discard; 00581 } 00582 #endif /*UIP_CONF_IPV6_CHECKS */ 00583 switch (UIP_ND6_OPT_HDR_BUF->type) { 00584 case UIP_ND6_OPT_SLLAO: 00585 nd6_opt_llao = UIP_ND6_OPT_HDR_BUF; 00586 break; 00587 default: 00588 PRINTF("ND option not supported in RS\n"); 00589 break; 00590 } 00591 nd6_opt_offset += (UIP_ND6_OPT_HDR_BUF->len << 3); 00592 } 00593 /* Options processing: only SLLAO */ 00594 if(nd6_opt_llao != NULL) { 00595 #if UIP_CONF_IPV6_CHECKS 00596 if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) { 00597 PRINTF("RS received is bad\n"); 00598 goto discard; 00599 } else { 00600 #endif /*UIP_CONF_IPV6_CHECKS */ 00601 if((nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr)) == NULL) { 00602 /* we need to add the neighbor */ 00603 uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, 00604 &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], 0, NBR_STALE); 00605 } else { 00606 /* If LL address changed, set neighbor state to stale */ 00607 if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], 00608 &nbr->lladdr, UIP_LLADDR_LEN) != 0) { 00609 memcpy(&nbr->lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], 00610 UIP_LLADDR_LEN); 00611 nbr->state = NBR_STALE; 00612 } 00613 nbr->isrouter = 0; 00614 } 00615 #if UIP_CONF_IPV6_CHECKS 00616 } 00617 #endif /*UIP_CONF_IPV6_CHECKS */ 00618 } 00619 00620 /* Schedule a sollicited RA */ 00621 uip_ds6_send_ra_sollicited(); 00622 00623 discard: 00624 uip_len = 0; 00625 return; 00626 } 00627 00628 /*---------------------------------------------------------------------------*/ 00629 void 00630 uip_nd6_ra_output(uip_ipaddr_t * dest) 00631 { 00632 00633 UIP_IP_BUF->vtc = 0x60; 00634 UIP_IP_BUF->tcflow = 0; 00635 UIP_IP_BUF->flow = 0; 00636 UIP_IP_BUF->proto = UIP_PROTO_ICMP6; 00637 UIP_IP_BUF->ttl = UIP_ND6_HOP_LIMIT; 00638 00639 if(dest == NULL) { 00640 uip_create_linklocal_allnodes_mcast(&UIP_IP_BUF->destipaddr); 00641 } else { 00642 /* For sollicited RA */ 00643 uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, dest); 00644 } 00645 uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr); 00646 00647 UIP_ICMP_BUF->type = ICMP6_RA; 00648 UIP_ICMP_BUF->icode = 0; 00649 00650 UIP_ND6_RA_BUF->cur_ttl = uip_ds6_if.cur_hop_limit; 00651 00652 UIP_ND6_RA_BUF->flags_reserved = 00653 (UIP_ND6_M_FLAG << 7) | (UIP_ND6_O_FLAG << 6); 00654 00655 UIP_ND6_RA_BUF->router_lifetime = uip_htons(UIP_ND6_ROUTER_LIFETIME); 00656 //UIP_ND6_RA_BUF->reachable_time = uip_htonl(uip_ds6_if.reachable_time); 00657 //UIP_ND6_RA_BUF->retrans_timer = uip_htonl(uip_ds6_if.retrans_timer); 00658 UIP_ND6_RA_BUF->reachable_time = 0; 00659 UIP_ND6_RA_BUF->retrans_timer = 0; 00660 00661 uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_RA_LEN; 00662 nd6_opt_offset = UIP_ND6_RA_LEN; 00663 00664 00665 /* Prefix list */ 00666 for(prefix = uip_ds6_prefix_list; 00667 prefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB; prefix++) { 00668 if((prefix->isused) && (prefix->advertise)) { 00669 UIP_ND6_OPT_PREFIX_BUF->type = UIP_ND6_OPT_PREFIX_INFO; 00670 UIP_ND6_OPT_PREFIX_BUF->len = UIP_ND6_OPT_PREFIX_INFO_LEN / 8; 00671 UIP_ND6_OPT_PREFIX_BUF->preflen = prefix->length; 00672 UIP_ND6_OPT_PREFIX_BUF->flagsreserved1 = prefix->l_a_reserved; 00673 UIP_ND6_OPT_PREFIX_BUF->validlt = uip_htonl(prefix->vlifetime); 00674 UIP_ND6_OPT_PREFIX_BUF->preferredlt = uip_htonl(prefix->plifetime); 00675 UIP_ND6_OPT_PREFIX_BUF->reserved2 = 0; 00676 uip_ipaddr_copy(&(UIP_ND6_OPT_PREFIX_BUF->prefix), &(prefix->ipaddr)); 00677 nd6_opt_offset += UIP_ND6_OPT_PREFIX_INFO_LEN; 00678 uip_len += UIP_ND6_OPT_PREFIX_INFO_LEN; 00679 } 00680 } 00681 00682 /* Source link-layer option */ 00683 create_llao((uint8_t *)UIP_ND6_OPT_HDR_BUF, UIP_ND6_OPT_SLLAO); 00684 00685 uip_len += UIP_ND6_OPT_LLAO_LEN; 00686 nd6_opt_offset += UIP_ND6_OPT_LLAO_LEN; 00687 00688 /* MTU */ 00689 UIP_ND6_OPT_MTU_BUF->type = UIP_ND6_OPT_MTU; 00690 UIP_ND6_OPT_MTU_BUF->len = UIP_ND6_OPT_MTU_LEN >> 3; 00691 UIP_ND6_OPT_MTU_BUF->reserved = 0; 00692 //UIP_ND6_OPT_MTU_BUF->mtu = uip_htonl(uip_ds6_if.link_mtu); 00693 UIP_ND6_OPT_MTU_BUF->mtu = uip_htonl(1500); 00694 00695 uip_len += UIP_ND6_OPT_MTU_LEN; 00696 nd6_opt_offset += UIP_ND6_OPT_MTU_LEN; 00697 UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); 00698 UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); 00699 00700 /*ICMP checksum */ 00701 UIP_ICMP_BUF->icmpchksum = 0; 00702 UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum(); 00703 00704 UIP_STAT(++uip_stat.nd6.sent); 00705 PRINTF("Sending RA to"); 00706 PRINT6ADDR(&UIP_IP_BUF->destipaddr); 00707 PRINTF("from"); 00708 PRINT6ADDR(&UIP_IP_BUF->srcipaddr); 00709 PRINTF("\n"); 00710 return; 00711 } 00712 #endif /* UIP_ND6_SEND_RA */ 00713 #endif /* UIP_CONF_ROUTER */ 00714 00715 #if !UIP_CONF_ROUTER 00716 /*---------------------------------------------------------------------------*/ 00717 void 00718 uip_nd6_rs_output(void) 00719 { 00720 UIP_IP_BUF->vtc = 0x60; 00721 UIP_IP_BUF->tcflow = 0; 00722 UIP_IP_BUF->flow = 0; 00723 UIP_IP_BUF->proto = UIP_PROTO_ICMP6; 00724 UIP_IP_BUF->ttl = UIP_ND6_HOP_LIMIT; 00725 uip_create_linklocal_allrouters_mcast(&UIP_IP_BUF->destipaddr); 00726 uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr); 00727 UIP_ICMP_BUF->type = ICMP6_RS; 00728 UIP_ICMP_BUF->icode = 0; 00729 UIP_IP_BUF->len[0] = 0; /* length will not be more than 255 */ 00730 00731 if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) { 00732 UIP_IP_BUF->len[1] = UIP_ICMPH_LEN + UIP_ND6_RS_LEN; 00733 uip_len = uip_l3_icmp_hdr_len + UIP_ND6_RS_LEN; 00734 } else { 00735 uip_len = uip_l3_icmp_hdr_len + UIP_ND6_RS_LEN + UIP_ND6_OPT_LLAO_LEN; 00736 UIP_IP_BUF->len[1] = 00737 UIP_ICMPH_LEN + UIP_ND6_RS_LEN + UIP_ND6_OPT_LLAO_LEN; 00738 00739 create_llao(&uip_buf[uip_l2_l3_icmp_hdr_len + UIP_ND6_RS_LEN], 00740 UIP_ND6_OPT_SLLAO); 00741 } 00742 00743 UIP_ICMP_BUF->icmpchksum = 0; 00744 UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum(); 00745 00746 UIP_STAT(++uip_stat.nd6.sent); 00747 PRINTF("Sendin RS to"); 00748 PRINT6ADDR(&UIP_IP_BUF->destipaddr); 00749 PRINTF("from"); 00750 PRINT6ADDR(&UIP_IP_BUF->srcipaddr); 00751 PRINTF("\n"); 00752 return; 00753 } 00754 00755 00756 /*---------------------------------------------------------------------------*/ 00757 void 00758 uip_nd6_ra_input(void) 00759 { 00760 PRINTF("Received RA from"); 00761 PRINT6ADDR(&UIP_IP_BUF->srcipaddr); 00762 PRINTF("to"); 00763 PRINT6ADDR(&UIP_IP_BUF->destipaddr); 00764 PRINTF("\n"); 00765 UIP_STAT(++uip_stat.nd6.recv); 00766 00767 #if UIP_CONF_IPV6_CHECKS 00768 if((UIP_IP_BUF->ttl != UIP_ND6_HOP_LIMIT) || 00769 (!uip_is_addr_link_local(&UIP_IP_BUF->srcipaddr)) || 00770 (UIP_ICMP_BUF->icode != 0)) { 00771 PRINTF("RA received is bad"); 00772 goto discard; 00773 } 00774 #endif /*UIP_CONF_IPV6_CHECKS */ 00775 00776 if(UIP_ND6_RA_BUF->cur_ttl != 0) { 00777 uip_ds6_if.cur_hop_limit = UIP_ND6_RA_BUF->cur_ttl; 00778 PRINTF("uip_ds6_if.cur_hop_limit %u\n", uip_ds6_if.cur_hop_limit); 00779 } 00780 00781 if(UIP_ND6_RA_BUF->reachable_time != 0) { 00782 if(uip_ds6_if.base_reachable_time != 00783 uip_ntohl(UIP_ND6_RA_BUF->reachable_time)) { 00784 uip_ds6_if.base_reachable_time = uip_ntohl(UIP_ND6_RA_BUF->reachable_time); 00785 uip_ds6_if.reachable_time = uip_ds6_compute_reachable_time(); 00786 } 00787 } 00788 if(UIP_ND6_RA_BUF->retrans_timer != 0) { 00789 uip_ds6_if.retrans_timer = uip_ntohl(UIP_ND6_RA_BUF->retrans_timer); 00790 } 00791 00792 /* Options processing */ 00793 nd6_opt_offset = UIP_ND6_RA_LEN; 00794 while(uip_l3_icmp_hdr_len + nd6_opt_offset < uip_len) { 00795 if(UIP_ND6_OPT_HDR_BUF->len == 0) { 00796 PRINTF("RA received is bad"); 00797 goto discard; 00798 } 00799 switch (UIP_ND6_OPT_HDR_BUF->type) { 00800 case UIP_ND6_OPT_SLLAO: 00801 PRINTF("Processing SLLAO option in RA\n"); 00802 nd6_opt_llao = (uint8_t *) UIP_ND6_OPT_HDR_BUF; 00803 nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr); 00804 if(nbr == NULL) { 00805 nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, 00806 (uip_lladdr_t *)&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], 00807 1, NBR_STALE); 00808 } else { 00809 if(nbr->state == NBR_INCOMPLETE) { 00810 nbr->state = NBR_STALE; 00811 } 00812 if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], 00813 &nbr->lladdr, UIP_LLADDR_LEN) != 0) { 00814 memcpy(&nbr->lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], 00815 UIP_LLADDR_LEN); 00816 nbr->state = NBR_STALE; 00817 } 00818 nbr->isrouter = 1; 00819 } 00820 break; 00821 case UIP_ND6_OPT_MTU: 00822 PRINTF("Processing MTU option in RA\n"); 00823 uip_ds6_if.link_mtu = 00824 uip_ntohl(((uip_nd6_opt_mtu *) UIP_ND6_OPT_HDR_BUF)->mtu); 00825 break; 00826 case UIP_ND6_OPT_PREFIX_INFO: 00827 PRINTF("Processing PREFIX option in RA\n"); 00828 nd6_opt_prefix_info = (uip_nd6_opt_prefix_info *) UIP_ND6_OPT_HDR_BUF; 00829 if((uip_ntohl(nd6_opt_prefix_info->validlt) >= 00830 uip_ntohl(nd6_opt_prefix_info->preferredlt)) 00831 && (!uip_is_addr_link_local(&nd6_opt_prefix_info->prefix))) { 00832 /* on-link flag related processing */ 00833 if(nd6_opt_prefix_info->flagsreserved1 & UIP_ND6_RA_FLAG_ONLINK) { 00834 prefix = 00835 uip_ds6_prefix_lookup(&nd6_opt_prefix_info->prefix, 00836 nd6_opt_prefix_info->preflen); 00837 if(prefix == NULL) { 00838 if(nd6_opt_prefix_info->validlt != 0) { 00839 if(nd6_opt_prefix_info->validlt != UIP_ND6_INFINITE_LIFETIME) { 00840 prefix = uip_ds6_prefix_add(&nd6_opt_prefix_info->prefix, 00841 nd6_opt_prefix_info->preflen, 00842 uip_ntohl(nd6_opt_prefix_info-> 00843 validlt)); 00844 } else { 00845 prefix = uip_ds6_prefix_add(&nd6_opt_prefix_info->prefix, 00846 nd6_opt_prefix_info->preflen, 0); 00847 } 00848 } 00849 } else { 00850 switch (nd6_opt_prefix_info->validlt) { 00851 case 0: 00852 uip_ds6_prefix_rm(prefix); 00853 break; 00854 case UIP_ND6_INFINITE_LIFETIME: 00855 prefix->isinfinite = 1; 00856 break; 00857 default: 00858 PRINTF("Updating timer of prefix"); 00859 PRINT6ADDR(&prefix->ipaddr); 00860 PRINTF("new value %lu\n", uip_ntohl(nd6_opt_prefix_info->validlt)); 00861 stimer_set(&prefix->vlifetime, 00862 uip_ntohl(nd6_opt_prefix_info->validlt)); 00863 prefix->isinfinite = 0; 00864 break; 00865 } 00866 } 00867 } 00868 /* End of on-link flag related processing */ 00869 /* autonomous flag related processing */ 00870 if((nd6_opt_prefix_info->flagsreserved1 & UIP_ND6_RA_FLAG_AUTONOMOUS) 00871 && (nd6_opt_prefix_info->validlt != 0) 00872 && (nd6_opt_prefix_info->preflen == UIP_DEFAULT_PREFIX_LEN)) { 00873 00874 uip_ipaddr_copy(&ipaddr, &nd6_opt_prefix_info->prefix); 00875 uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); 00876 addr = uip_ds6_addr_lookup(&ipaddr); 00877 if((addr != NULL) && (addr->type == ADDR_AUTOCONF)) { 00878 if(nd6_opt_prefix_info->validlt != UIP_ND6_INFINITE_LIFETIME) { 00879 /* The processing below is defined in RFC4862 section 5.5.3 e */ 00880 if((uip_ntohl(nd6_opt_prefix_info->validlt) > 2 * 60 * 60) || 00881 (uip_ntohl(nd6_opt_prefix_info->validlt) > 00882 stimer_remaining(&addr->vlifetime))) { 00883 PRINTF("Updating timer of address"); 00884 PRINT6ADDR(&addr->ipaddr); 00885 PRINTF("new value %lu\n", 00886 uip_ntohl(nd6_opt_prefix_info->validlt)); 00887 stimer_set(&addr->vlifetime, 00888 uip_ntohl(nd6_opt_prefix_info->validlt)); 00889 } else { 00890 stimer_set(&addr->vlifetime, 2 * 60 * 60); 00891 PRINTF("Updating timer of address "); 00892 PRINT6ADDR(&addr->ipaddr); 00893 PRINTF("new value %lu\n", (unsigned long)(2 * 60 * 60)); 00894 } 00895 addr->isinfinite = 0; 00896 } else { 00897 addr->isinfinite = 1; 00898 } 00899 } else { 00900 if(uip_ntohl(nd6_opt_prefix_info->validlt) == 00901 UIP_ND6_INFINITE_LIFETIME) { 00902 uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); 00903 } else { 00904 uip_ds6_addr_add(&ipaddr, uip_ntohl(nd6_opt_prefix_info->validlt), 00905 ADDR_AUTOCONF); 00906 } 00907 } 00908 } 00909 /* End of autonomous flag related processing */ 00910 } 00911 break; 00912 default: 00913 PRINTF("ND option not supported in RA"); 00914 break; 00915 } 00916 nd6_opt_offset += (UIP_ND6_OPT_HDR_BUF->len << 3); 00917 } 00918 00919 defrt = uip_ds6_defrt_lookup(&UIP_IP_BUF->srcipaddr); 00920 if(UIP_ND6_RA_BUF->router_lifetime != 0) { 00921 if(nbr != NULL) { 00922 nbr->isrouter = 1; 00923 } 00924 if(defrt == NULL) { 00925 uip_ds6_defrt_add(&UIP_IP_BUF->srcipaddr, 00926 (unsigned 00927 long)(uip_ntohs(UIP_ND6_RA_BUF->router_lifetime))); 00928 } else { 00929 stimer_set(&(defrt->lifetime), 00930 (unsigned long)(uip_ntohs(UIP_ND6_RA_BUF->router_lifetime))); 00931 } 00932 } else { 00933 if(defrt != NULL) { 00934 uip_ds6_defrt_rm(defrt); 00935 } 00936 } 00937 00938 #if UIP_CONF_IPV6_QUEUE_PKT 00939 /* If the nbr just became reachable (e.g. it was in NBR_INCOMPLETE state 00940 * and we got a SLLAO), check if we had buffered a pkt for it */ 00941 /* if((nbr != NULL) && (nbr->queue_buf_len != 0)) { 00942 uip_len = nbr->queue_buf_len; 00943 memcpy(UIP_IP_BUF, nbr->queue_buf, uip_len); 00944 nbr->queue_buf_len = 0; 00945 return; 00946 }*/ 00947 if(nbr != NULL && uip_packetqueue_buflen(&nbr->packethandle) != 0) { 00948 uip_len = uip_packetqueue_buflen(&nbr->packethandle); 00949 memcpy(UIP_IP_BUF, uip_packetqueue_buf(&nbr->packethandle), uip_len); 00950 uip_packetqueue_free(&nbr->packethandle); 00951 return; 00952 } 00953 00954 #endif /*UIP_CONF_IPV6_QUEUE_PKT */ 00955 00956 discard: 00957 uip_len = 0; 00958 return; 00959 } 00960 #endif /* !UIP_CONF_ROUTER */ 00961 00962 /** @} */