Contiki 2.6

uip-nd6.c

Go to the documentation of this file.
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  /** @} */