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 #if DEBUG
00080 #include <stdio.h>
00081 #define PRINTF(...) printf(__VA_ARGS__)
00082 #define PRINT6ADDR(addr) PRINTF(" %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x ", ((u8_t *)addr)[0], ((u8_t *)addr)[1], ((u8_t *)addr)[2], ((u8_t *)addr)[3], ((u8_t *)addr)[4], ((u8_t *)addr)[5], ((u8_t *)addr)[6], ((u8_t *)addr)[7], ((u8_t *)addr)[8], ((u8_t *)addr)[9], ((u8_t *)addr)[10], ((u8_t *)addr)[11], ((u8_t *)addr)[12], ((u8_t *)addr)[13], ((u8_t *)addr)[14], ((u8_t *)addr)[15])
00083 #define PRINTLLADDR(lladdr) PRINTF(" %02x:%02x:%02x:%02x:%02x:%02x ",lladdr->addr[0], lladdr->addr[1], lladdr->addr[2], lladdr->addr[3],lladdr->addr[4], lladdr->addr[5])
00084 #else
00085 #define PRINTF(...)
00086 #define PRINT6ADDR(addr)
00087 #define PRINTLLADDR(addr)
00088 #endif
00089 
00090 #if UIP_LOGGING
00091 #include <stdio.h>
00092 void uip_log(char *msg);
00093 
00094 #define UIP_LOG(m) uip_log(m)
00095 #else
00096 #define UIP_LOG(m)
00097 #endif /* UIP_LOGGING == 1 */
00098 
00099 /*------------------------------------------------------------------*/
00100 /** @{ */
00101 /** \name Pointers to the header structures.
00102  *  All pointers except UIP_IP_BUF depend on uip_ext_len, which at
00103  *  packet reception, is the total length of the extension headers.
00104  *  
00105  *  The pointer to ND6 options header also depends on nd6_opt_offset,
00106  *  which we set in each function.
00107  *
00108  *  Care should be taken when manipulating these buffers about the
00109  *  value of these length variables
00110  */
00111 
00112 #define UIP_IP_BUF                ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])  /**< Pointer to IP header */
00113 #define UIP_ICMP_BUF            ((struct uip_icmp_hdr *)&uip_buf[uip_l2_l3_hdr_len])  /**< Pointer to ICMP header*/
00114 /**@{  Pointers to messages just after icmp header */
00115 #define UIP_ND6_RS_BUF            ((uip_nd6_rs *)&uip_buf[uip_l2_l3_icmp_hdr_len])
00116 #define UIP_ND6_RA_BUF            ((uip_nd6_ra *)&uip_buf[uip_l2_l3_icmp_hdr_len])
00117 #define UIP_ND6_NS_BUF            ((uip_nd6_ns *)&uip_buf[uip_l2_l3_icmp_hdr_len])
00118 #define UIP_ND6_NA_BUF            ((uip_nd6_na *)&uip_buf[uip_l2_l3_icmp_hdr_len])
00119 /** @} */
00120 /** Pointer to ND option */
00121 #define UIP_ND6_OPT_HDR_BUF  ((uip_nd6_opt_hdr *)&uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset])
00122 #define UIP_ND6_OPT_PREFIX_BUF ((uip_nd6_opt_prefix_info *)&uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset])
00123 #define UIP_ND6_OPT_MTU_BUF ((uip_nd6_opt_mtu *)&uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset])
00124 /** @} */
00125 
00126 static uint8_t nd6_opt_offset;                     /** Offset from the end of the icmpv6 header to the option in uip_buf*/
00127 static uint8_t *nd6_opt_llao;   /**  Pointer to llao option in uip_buf */
00128 
00129 #if !UIP_CONF_ROUTER            // TBD see if we move it to ra_input
00130 static uip_nd6_opt_prefix_info *nd6_opt_prefix_info; /**  Pointer to prefix information option in uip_buf */
00131 static uip_ipaddr_t ipaddr;
00132 static uip_ds6_prefix_t *prefix; /**  Pointer to a prefix list entry */
00133 #endif
00134 static uip_ds6_nbr_t *nbr; /**  Pointer to a nbr cache entry*/
00135 static uip_ds6_defrt_t *defrt; /**  Pointer to a router list entry */
00136 static uip_ds6_addr_t *addr; /**  Pointer to an interface address */
00137 
00138 
00139 /*------------------------------------------------------------------*/
00140 /* create a llao */ 
00141 static void
00142 create_llao(uint8_t *llao, uint8_t type) {
00143   llao[UIP_ND6_OPT_TYPE_OFFSET] = type;
00144   llao[UIP_ND6_OPT_LEN_OFFSET] = UIP_ND6_OPT_LLAO_LEN >> 3;
00145   memcpy(&llao[UIP_ND6_OPT_DATA_OFFSET], &uip_lladdr, UIP_LLADDR_LEN);
00146   /* padding on some */
00147   memset(&llao[UIP_ND6_OPT_DATA_OFFSET + UIP_LLADDR_LEN], 0,
00148          UIP_ND6_OPT_LLAO_LEN - 2 - UIP_LLADDR_LEN);
00149 }
00150 
00151 /*------------------------------------------------------------------*/
00152 
00153 
00154 void
00155 uip_nd6_ns_input(void)
00156 {
00157   PRINTF("Received NS from");
00158   PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
00159   PRINTF("to");
00160   PRINT6ADDR(&UIP_IP_BUF->destipaddr);
00161   PRINTF("with target address");
00162   PRINT6ADDR((uip_ipaddr_t *) (&UIP_ND6_NS_BUF->tgtipaddr));
00163   PRINTF("\n");
00164   UIP_STAT(++uip_stat.nd6.recv);
00165 
00166   u8_t flags;
00167 
00168 #if UIP_CONF_IPV6_CHECKS
00169   if((UIP_IP_BUF->ttl != UIP_ND6_HOP_LIMIT) ||
00170      (uip_is_addr_mcast(&UIP_ND6_NS_BUF->tgtipaddr)) ||
00171      (UIP_ICMP_BUF->icode != 0)) {
00172     PRINTF("NS received is bad\n");
00173     goto discard;
00174   }
00175 #endif /* UIP_CONF_IPV6_CHECKS */
00176 
00177   /* Options processing */
00178   nd6_opt_llao = NULL;
00179   nd6_opt_offset = UIP_ND6_NS_LEN;
00180   while(uip_l3_icmp_hdr_len + nd6_opt_offset < uip_len) {
00181 #if UIP_CONF_IPV6_CHECKS
00182     if(UIP_ND6_OPT_HDR_BUF->len == 0) {
00183       PRINTF("NS received is bad\n");
00184       goto discard;
00185     }
00186 #endif /* UIP_CONF_IPV6_CHECKS */
00187     switch (UIP_ND6_OPT_HDR_BUF->type) {
00188     case UIP_ND6_OPT_SLLAO:
00189       nd6_opt_llao = &uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset];
00190 #if UIP_CONF_IPV6_CHECKS
00191       /* There must be NO option in a DAD NS */
00192       if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
00193         PRINTF("NS received is bad\n");
00194         goto discard;
00195       } else {
00196 #endif /*UIP_CONF_IPV6_CHECKS */
00197         nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr);
00198         if(nbr == NULL) {
00199           uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr,
00200                           (uip_lladdr_t *)&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
00201                           0, NBR_STALE);
00202         } else {
00203           if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
00204                     &nbr->lladdr, UIP_LLADDR_LEN) != 0) {
00205             memcpy(&nbr->lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
00206                    UIP_LLADDR_LEN);
00207             nbr->state = NBR_STALE;
00208           } else {
00209             if(nbr->state == NBR_INCOMPLETE) {
00210               nbr->state = NBR_STALE;
00211             }
00212           }
00213         }
00214 #if UIP_CONF_IPV6_CHECKS
00215       }
00216 #endif /*UIP_CONF_IPV6_CHECKS */
00217       break;
00218     default:
00219       PRINTF("ND option not supported in NS");
00220       break;
00221     }
00222     nd6_opt_offset += (UIP_ND6_OPT_HDR_BUF->len << 3);
00223   }
00224 
00225   addr = uip_ds6_addr_lookup(&UIP_ND6_NS_BUF->tgtipaddr);
00226   if(addr != NULL) {
00227     if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
00228       /* DAD CASE */
00229 #if UIP_CONF_IPV6_CHECKS
00230       if(!uip_is_addr_solicited_node(&UIP_IP_BUF->destipaddr)) {
00231         PRINTF("NS received is bad\n");
00232         goto discard;
00233       }
00234 #endif /* UIP_CONF_IPV6_CHECKS */
00235       if(addr->state != ADDR_TENTATIVE) {
00236         uip_create_linklocal_allnodes_mcast(&UIP_IP_BUF->destipaddr);
00237         uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr);
00238         flags = UIP_ND6_NA_FLAG_OVERRIDE;
00239         goto create_na;
00240       } else {
00241           /** \todo if I sent a NS before him, I win */
00242         uip_ds6_dad_failed(addr);
00243         goto discard;
00244       }
00245     }
00246 #if UIP_CONF_IPV6_CHECKS
00247     if(uip_ds6_is_my_addr(&UIP_IP_BUF->srcipaddr)) {
00248         /**
00249          * \NOTE do we do something here? we both are using the same address.
00250          * If we are doing dad, we could cancel it, though we should receive a
00251          * NA in response of DAD NS we sent, hence DAD will fail anyway. If we
00252          * were not doing DAD, it means there is a duplicate in the network!
00253          */
00254       PRINTF("NS received is bad\n");
00255       goto discard;
00256     }
00257 #endif /*UIP_CONF_IPV6_CHECKS */
00258 
00259     /* Address resolution case */
00260     if(uip_is_addr_solicited_node(&UIP_IP_BUF->destipaddr)) {
00261       uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &UIP_IP_BUF->srcipaddr);
00262       uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, &UIP_ND6_NS_BUF->tgtipaddr);
00263       flags = UIP_ND6_NA_FLAG_SOLICITED | UIP_ND6_NA_FLAG_OVERRIDE;
00264       goto create_na;
00265     }
00266 
00267     /* NUD CASE */
00268     if(uip_ds6_addr_lookup(&UIP_IP_BUF->destipaddr) == addr) {
00269       uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &UIP_IP_BUF->srcipaddr);
00270       uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, &UIP_ND6_NS_BUF->tgtipaddr);
00271       flags = UIP_ND6_NA_FLAG_SOLICITED | UIP_ND6_NA_FLAG_OVERRIDE;
00272       goto create_na;
00273     } else {
00274 #if UIP_CONF_IPV6_CHECKS
00275       PRINTF("NS received is bad\n");
00276       goto discard;
00277 #endif /* UIP_CONF_IPV6_CHECKS */
00278     }
00279   } else {
00280     goto discard;
00281   }
00282 
00283 
00284 create_na:
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     UIP_IP_BUF->len[1] =
00358       UIP_ICMPH_LEN + UIP_ND6_NS_LEN + UIP_ND6_OPT_LLAO_LEN;
00359 
00360     create_llao(&uip_buf[uip_l2_l3_icmp_hdr_len + UIP_ND6_NS_LEN],
00361                 UIP_ND6_OPT_SLLAO);
00362 
00363     uip_len =
00364       UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_NS_LEN + UIP_ND6_OPT_LLAO_LEN;
00365   } else {
00366     uip_create_unspecified(&UIP_IP_BUF->srcipaddr);
00367     UIP_IP_BUF->len[1] = UIP_ICMPH_LEN + UIP_ND6_NS_LEN;
00368     uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_NS_LEN;
00369   }
00370 
00371   UIP_ICMP_BUF->icmpchksum = 0;
00372   UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
00373 
00374   UIP_STAT(++uip_stat.nd6.sent);
00375   PRINTF("Sending NS to");
00376   PRINT6ADDR(&UIP_IP_BUF->destipaddr);
00377   PRINTF("from");
00378   PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
00379   PRINTF("with target address");
00380   PRINT6ADDR(tgt);
00381   PRINTF("\n");
00382   return;
00383 }
00384 
00385 
00386 
00387 /*------------------------------------------------------------------*/
00388 void
00389 uip_nd6_na_input(void)
00390 {
00391   PRINTF("Received NA from");
00392   PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
00393   PRINTF("to");
00394   PRINT6ADDR(&UIP_IP_BUF->destipaddr);
00395   PRINTF("with target address");
00396   PRINT6ADDR((uip_ipaddr_t *) (&UIP_ND6_NA_BUF->tgtipaddr));
00397   PRINTF("\n");
00398   UIP_STAT(++uip_stat.nd6.recv);
00399 
00400   /* 
00401    * booleans. the three last one are not 0 or 1 but 0 or 0x80, 0x40, 0x20
00402    * but it works. Be careful though, do not use tests such as is_router == 1 
00403    */
00404   u8_t is_llchange = 0;
00405   u8_t is_router = ((UIP_ND6_NA_BUF->flagsreserved & UIP_ND6_NA_FLAG_ROUTER));
00406   u8_t is_solicited =
00407     ((UIP_ND6_NA_BUF->flagsreserved & UIP_ND6_NA_FLAG_SOLICITED));
00408   u8_t is_override =
00409     ((UIP_ND6_NA_BUF->flagsreserved & UIP_ND6_NA_FLAG_OVERRIDE));
00410 
00411 #if UIP_CONF_IPV6_CHECKS
00412   if((UIP_IP_BUF->ttl != UIP_ND6_HOP_LIMIT) ||
00413      (UIP_ICMP_BUF->icode != 0) ||
00414      (uip_is_addr_mcast(&UIP_ND6_NA_BUF->tgtipaddr)) ||
00415      (is_solicited && uip_is_addr_mcast(&UIP_IP_BUF->destipaddr))) {
00416     PRINTF("NA received is bad\n");
00417     goto discard;
00418   }
00419 #endif /*UIP_CONF_IPV6_CHECKS */
00420 
00421   /* Options processing: we handle TLLAO, and must ignore others */
00422   nd6_opt_offset = UIP_ND6_NA_LEN;
00423   nd6_opt_llao = NULL;
00424   while(uip_l3_icmp_hdr_len + nd6_opt_offset < uip_len) {
00425 #if UIP_CONF_IPV6_CHECKS
00426     if(UIP_ND6_OPT_HDR_BUF->len == 0) {
00427       PRINTF("NA received is bad\n");
00428       goto discard;
00429     }
00430 #endif /*UIP_CONF_IPV6_CHECKS */
00431     switch (UIP_ND6_OPT_HDR_BUF->type) {
00432     case UIP_ND6_OPT_TLLAO:
00433       nd6_opt_llao = (uint8_t *)UIP_ND6_OPT_HDR_BUF;
00434       break;
00435     default:
00436       PRINTF("ND option not supported in NA\n");
00437       break;
00438     }
00439     nd6_opt_offset += (UIP_ND6_OPT_HDR_BUF->len << 3);
00440   }
00441   addr = uip_ds6_addr_lookup(&UIP_ND6_NA_BUF->tgtipaddr);
00442   /* Message processing, including TLLAO if any */
00443   if(addr != NULL) {
00444     if(addr->state == ADDR_TENTATIVE) {
00445       uip_ds6_dad_failed(addr);
00446     }
00447     PRINTF("NA received is bad\n");
00448     goto discard;
00449   } else {
00450     nbr = uip_ds6_nbr_lookup(&UIP_ND6_NA_BUF->tgtipaddr);
00451     if(nbr == NULL) {
00452       goto discard;
00453     }
00454     if(nd6_opt_llao != 0) {
00455       is_llchange =
00456         memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], (void *)(&nbr->lladdr),
00457                UIP_LLADDR_LEN);
00458     }
00459     if(nbr->state == NBR_INCOMPLETE) {
00460       if(nd6_opt_llao == NULL) {
00461         goto discard;
00462       }
00463       memcpy(&nbr->lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
00464              UIP_LLADDR_LEN);
00465       if(is_solicited) {
00466         nbr->state = NBR_REACHABLE;
00467         nbr->nscount = 0;
00468 
00469         /* reachable time is stored in ms */
00470         stimer_set(&(nbr->reachable), uip_ds6_if.reachable_time / 1000);
00471 
00472       } else {
00473         nbr->state = NBR_STALE;
00474       }
00475       nbr->isrouter = is_router;
00476     } else {
00477       if(!is_override && is_llchange) {
00478         if(nbr->state == NBR_REACHABLE) {
00479           nbr->state = NBR_STALE;
00480         }
00481         goto discard;
00482       } else {
00483         if(is_override || (!is_override && nd6_opt_llao != 0 && !is_llchange)
00484            || nd6_opt_llao == 0) {
00485           if(nd6_opt_llao != 0) {
00486             memcpy(&nbr->lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
00487                    UIP_LLADDR_LEN);
00488           }
00489           if(is_solicited) {
00490             nbr->state = NBR_REACHABLE;
00491             /* reachable time is stored in ms */
00492             stimer_set(&(nbr->reachable), uip_ds6_if.reachable_time / 1000);
00493           } else {
00494             if(nd6_opt_llao != 0 && is_llchange) {
00495               nbr->state = NBR_STALE;
00496             }
00497           }
00498         }
00499       }
00500       if(nbr->isrouter && !is_router) {
00501         defrt = uip_ds6_defrt_lookup(&UIP_IP_BUF->srcipaddr);
00502         if(defrt != NULL) {
00503           uip_ds6_defrt_rm(defrt);
00504         }
00505       }
00506       nbr->isrouter = is_router;
00507     }
00508   }
00509 #if UIP_CONF_IPV6_QUEUE_PKT
00510   /* The nbr is now reachable, check if we had buffered a pkt for it */
00511   /*if(nbr->queue_buf_len != 0) {
00512     uip_len = nbr->queue_buf_len;
00513     memcpy(UIP_IP_BUF, nbr->queue_buf, uip_len);
00514     nbr->queue_buf_len = 0;
00515     return;
00516     }*/
00517   if(uip_packetqueue_buflen(&nbr->packethandle) != 0) {
00518     uip_len = uip_packetqueue_buflen(&nbr->packethandle);
00519     memcpy(UIP_IP_BUF, uip_packetqueue_buf(&nbr->packethandle), uip_len);
00520     uip_packetqueue_free(&nbr->packethandle);
00521     return;
00522   }
00523   
00524 #endif /*UIP_CONF_IPV6_QUEUE_PKT */
00525 
00526 discard:
00527   uip_len = 0;
00528   return;
00529 }
00530 
00531 
00532 #if UIP_CONF_ROUTER
00533 #if UIP_ND6_SEND_RA
00534 /*---------------------------------------------------------------------------*/
00535 void
00536 uip_nd6_rs_input(void)
00537 {
00538 
00539   PRINTF("Received RS from");
00540   PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
00541   PRINTF("to");
00542   PRINT6ADDR(&UIP_IP_BUF->destipaddr);
00543   PRINTF("\n");
00544   UIP_STAT(++uip_stat.nd6.recv);
00545 
00546 
00547 #if UIP_CONF_IPV6_CHECKS
00548   /*
00549    * Check hop limit / icmp code 
00550    * target address must not be multicast
00551    * if the NA is solicited, dest must not be multicast
00552    */
00553   if((UIP_IP_BUF->ttl != UIP_ND6_HOP_LIMIT) || (UIP_ICMP_BUF->icode != 0)) {
00554     PRINTF("RS received is bad\n");
00555     goto discard;
00556   }
00557 #endif /*UIP_CONF_IPV6_CHECKS */
00558 
00559   /* Only valid option is Source Link-Layer Address option any thing
00560      else is discarded */
00561   nd6_opt_offset = UIP_ND6_RS_LEN;
00562   nd6_opt_llao = NULL;
00563 
00564   while(uip_l3_icmp_hdr_len + nd6_opt_offset < uip_len) {
00565 #if UIP_CONF_IPV6_CHECKS
00566     if(UIP_ND6_OPT_HDR_BUF->len == 0) {
00567       PRINTF("RS received is bad\n");
00568       goto discard;
00569     }
00570 #endif /*UIP_CONF_IPV6_CHECKS */
00571     switch (UIP_ND6_OPT_HDR_BUF->type) {
00572     case UIP_ND6_OPT_SLLAO:
00573       nd6_opt_llao = UIP_ND6_OPT_HDR_BUF;
00574       break;
00575     default:
00576       PRINTF("ND option not supported in RS\n");
00577       break;
00578     }
00579     nd6_opt_offset += (UIP_ND6_OPT_HDR_BUF->len << 3);
00580   }
00581   /* Options processing: only SLLAO */
00582   if(nd6_opt_llao != NULL) {
00583 #if UIP_CONF_IPV6_CHECKS
00584     if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
00585       PRINTF("RS received is bad\n");
00586       goto discard;
00587     } else {
00588 #endif /*UIP_CONF_IPV6_CHECKS */
00589       if((nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr)) == NULL) {
00590         /* we need to add the neighbor */
00591         uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr,
00592                         &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], 0, NBR_STALE);
00593       } else {
00594         /* If LL address changed, set neighbor state to stale */
00595         if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
00596                   &nbr->lladdr, UIP_LLADDR_LEN) != 0) {
00597           memcpy(&nbr->lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
00598                  UIP_LLADDR_LEN);
00599           nbr->state = NBR_STALE;
00600         }
00601         nbr->isrouter = 0;
00602       }
00603 #if UIP_CONF_IPV6_CHECKS
00604     }
00605 #endif /*UIP_CONF_IPV6_CHECKS */
00606   }
00607 
00608   /* Schedule a sollicited RA */
00609   uip_ds6_send_ra_sollicited();
00610 
00611 discard:
00612   uip_len = 0;
00613   return;
00614 }
00615 
00616 /*---------------------------------------------------------------------------*/
00617 void
00618 uip_nd6_ra_output(uip_ipaddr_t * dest)
00619 {
00620 
00621   UIP_IP_BUF->vtc = 0x60;
00622   UIP_IP_BUF->tcflow = 0;
00623   UIP_IP_BUF->flow = 0;
00624   UIP_IP_BUF->proto = UIP_PROTO_ICMP6;
00625   UIP_IP_BUF->ttl = UIP_ND6_HOP_LIMIT;
00626 
00627   if(dest == NULL) {
00628     uip_create_linklocal_allnodes_mcast(&UIP_IP_BUF->destipaddr);
00629   } else {
00630     /* For sollicited RA */
00631     uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, dest);
00632   }
00633   uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr);
00634 
00635   UIP_ICMP_BUF->type = ICMP6_RA;
00636   UIP_ICMP_BUF->icode = 0;
00637 
00638   UIP_ND6_RA_BUF->cur_ttl = uip_ds6_if.cur_hop_limit;
00639 
00640   UIP_ND6_RA_BUF->flags_reserved =
00641     (UIP_ND6_M_FLAG << 7) | (UIP_ND6_O_FLAG << 6);
00642 
00643   UIP_ND6_RA_BUF->router_lifetime = uip_htons(UIP_ND6_ROUTER_LIFETIME);
00644   //UIP_ND6_RA_BUF->reachable_time = uip_htonl(uip_ds6_if.reachable_time);
00645   //UIP_ND6_RA_BUF->retrans_timer = uip_htonl(uip_ds6_if.retrans_timer);
00646   UIP_ND6_RA_BUF->reachable_time = 0;
00647   UIP_ND6_RA_BUF->retrans_timer = 0;
00648 
00649   uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_RA_LEN;
00650   nd6_opt_offset = UIP_ND6_RA_LEN;
00651 
00652 
00653   /* Prefix list */
00654   for(prefix = uip_ds6_prefix_list;
00655       prefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB; prefix++) {
00656     if((prefix->isused) && (prefix->advertise)) {
00657       UIP_ND6_OPT_PREFIX_BUF->type = UIP_ND6_OPT_PREFIX_INFO;
00658       UIP_ND6_OPT_PREFIX_BUF->len = UIP_ND6_OPT_PREFIX_INFO_LEN / 8;
00659       UIP_ND6_OPT_PREFIX_BUF->preflen = prefix->length;
00660       UIP_ND6_OPT_PREFIX_BUF->flagsreserved1 = prefix->l_a_reserved;
00661       UIP_ND6_OPT_PREFIX_BUF->validlt = uip_htonl(prefix->vlifetime);
00662       UIP_ND6_OPT_PREFIX_BUF->preferredlt = uip_htonl(prefix->plifetime);
00663       UIP_ND6_OPT_PREFIX_BUF->reserved2 = 0;
00664       uip_ipaddr_copy(&(UIP_ND6_OPT_PREFIX_BUF->prefix), &(prefix->ipaddr));
00665       nd6_opt_offset += UIP_ND6_OPT_PREFIX_INFO_LEN;
00666       uip_len += UIP_ND6_OPT_PREFIX_INFO_LEN;
00667     }
00668   }
00669 
00670   /* Source link-layer option */
00671   create_llao((uint8_t *)UIP_ND6_OPT_HDR_BUF, UIP_ND6_OPT_SLLAO);
00672 
00673   uip_len += UIP_ND6_OPT_LLAO_LEN;
00674   nd6_opt_offset += UIP_ND6_OPT_LLAO_LEN;
00675 
00676   /* MTU */
00677   UIP_ND6_OPT_MTU_BUF->type = UIP_ND6_OPT_MTU;
00678   UIP_ND6_OPT_MTU_BUF->len = UIP_ND6_OPT_MTU_LEN >> 3;
00679   UIP_ND6_OPT_MTU_BUF->reserved = 0;
00680   //UIP_ND6_OPT_MTU_BUF->mtu = uip_htonl(uip_ds6_if.link_mtu);
00681   UIP_ND6_OPT_MTU_BUF->mtu = uip_htonl(1500);
00682 
00683   uip_len += UIP_ND6_OPT_MTU_LEN;
00684   nd6_opt_offset += UIP_ND6_OPT_MTU_LEN;
00685   UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
00686   UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
00687 
00688   /*ICMP checksum */
00689   UIP_ICMP_BUF->icmpchksum = 0;
00690   UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
00691 
00692   UIP_STAT(++uip_stat.nd6.sent);
00693   PRINTF("Sending RA to");
00694   PRINT6ADDR(&UIP_IP_BUF->destipaddr);
00695   PRINTF("from");
00696   PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
00697   PRINTF("\n");
00698   return;
00699 }
00700 #endif /* UIP_ND6_SEND_RA */
00701 #endif /* UIP_CONF_ROUTER */
00702 
00703 #if !UIP_CONF_ROUTER
00704 /*---------------------------------------------------------------------------*/
00705 void
00706 uip_nd6_rs_output(void)
00707 {
00708   UIP_IP_BUF->vtc = 0x60;
00709   UIP_IP_BUF->tcflow = 0;
00710   UIP_IP_BUF->flow = 0;
00711   UIP_IP_BUF->proto = UIP_PROTO_ICMP6;
00712   UIP_IP_BUF->ttl = UIP_ND6_HOP_LIMIT;
00713   uip_create_linklocal_allrouters_mcast(&UIP_IP_BUF->destipaddr);
00714   uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr);
00715   UIP_ICMP_BUF->type = ICMP6_RS;
00716   UIP_ICMP_BUF->icode = 0;
00717   UIP_IP_BUF->len[0] = 0;       /* length will not be more than 255 */
00718 
00719   if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
00720     UIP_IP_BUF->len[1] = UIP_ICMPH_LEN + UIP_ND6_RS_LEN;
00721     uip_len = uip_l3_icmp_hdr_len + UIP_ND6_RS_LEN;
00722   } else {
00723     uip_len = uip_l3_icmp_hdr_len + UIP_ND6_RS_LEN + UIP_ND6_OPT_LLAO_LEN;
00724     UIP_IP_BUF->len[1] =
00725       UIP_ICMPH_LEN + UIP_ND6_RS_LEN + UIP_ND6_OPT_LLAO_LEN;
00726 
00727     create_llao(&uip_buf[uip_l2_l3_icmp_hdr_len + UIP_ND6_RS_LEN],
00728                 UIP_ND6_OPT_SLLAO);
00729   }
00730 
00731   UIP_ICMP_BUF->icmpchksum = 0;
00732   UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
00733 
00734   UIP_STAT(++uip_stat.nd6.sent);
00735   PRINTF("Sendin RS to");
00736   PRINT6ADDR(&UIP_IP_BUF->destipaddr);
00737   PRINTF("from");
00738   PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
00739   PRINTF("\n");
00740   return;
00741 }
00742 
00743 
00744 /*---------------------------------------------------------------------------*/
00745 void
00746 uip_nd6_ra_input(void)
00747 {
00748   PRINTF("Received RA from");
00749   PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
00750   PRINTF("to");
00751   PRINT6ADDR(&UIP_IP_BUF->destipaddr);
00752   PRINTF("\n");
00753   UIP_STAT(++uip_stat.nd6.recv);
00754 
00755 #if UIP_CONF_IPV6_CHECKS
00756   if((UIP_IP_BUF->ttl != UIP_ND6_HOP_LIMIT) ||
00757      (!uip_is_addr_link_local(&UIP_IP_BUF->srcipaddr)) ||
00758      (UIP_ICMP_BUF->icode != 0)) {
00759     PRINTF("RA received is bad");
00760     goto discard;
00761   }
00762 #endif /*UIP_CONF_IPV6_CHECKS */
00763 
00764   if(UIP_ND6_RA_BUF->cur_ttl != 0) {
00765     uip_ds6_if.cur_hop_limit = UIP_ND6_RA_BUF->cur_ttl;
00766     PRINTF("uip_ds6_if.cur_hop_limit %u\n", uip_ds6_if.cur_hop_limit);
00767   }
00768 
00769   if(UIP_ND6_RA_BUF->reachable_time != 0) {
00770     if(uip_ds6_if.base_reachable_time !=
00771        uip_ntohl(UIP_ND6_RA_BUF->reachable_time)) {
00772       uip_ds6_if.base_reachable_time = uip_ntohl(UIP_ND6_RA_BUF->reachable_time);
00773       uip_ds6_if.reachable_time = uip_ds6_compute_reachable_time();
00774     }
00775   }
00776   if(UIP_ND6_RA_BUF->retrans_timer != 0) {
00777     uip_ds6_if.retrans_timer = uip_ntohl(UIP_ND6_RA_BUF->retrans_timer);
00778   }
00779 
00780   /* Options processing */
00781   nd6_opt_offset = UIP_ND6_RA_LEN;
00782   while(uip_l3_icmp_hdr_len + nd6_opt_offset < uip_len) {
00783     if(UIP_ND6_OPT_HDR_BUF->len == 0) {
00784       PRINTF("RA received is bad");
00785       goto discard;
00786     }
00787     switch (UIP_ND6_OPT_HDR_BUF->type) {
00788     case UIP_ND6_OPT_SLLAO:
00789       PRINTF("Processing SLLAO option in RA\n");
00790       nd6_opt_llao = (uint8_t *) UIP_ND6_OPT_HDR_BUF;
00791       nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr);
00792       if(nbr == NULL) {
00793         nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr,
00794                               (uip_lladdr_t *)&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
00795                               1, NBR_STALE);
00796       } else {
00797         if(nbr->state == NBR_INCOMPLETE) {
00798           nbr->state = NBR_STALE;
00799         }
00800         if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
00801                   &nbr->lladdr, UIP_LLADDR_LEN) != 0) {
00802           memcpy(&nbr->lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
00803                  UIP_LLADDR_LEN);
00804           nbr->state = NBR_STALE;
00805         }
00806         nbr->isrouter = 1;
00807       }
00808       break;
00809     case UIP_ND6_OPT_MTU:
00810       PRINTF("Processing MTU option in RA\n");
00811       uip_ds6_if.link_mtu =
00812         uip_ntohl(((uip_nd6_opt_mtu *) UIP_ND6_OPT_HDR_BUF)->mtu);
00813       break;
00814     case UIP_ND6_OPT_PREFIX_INFO:
00815       PRINTF("Processing PREFIX option in RA\n");
00816       nd6_opt_prefix_info = (uip_nd6_opt_prefix_info *) UIP_ND6_OPT_HDR_BUF;
00817       if((uip_ntohl(nd6_opt_prefix_info->validlt) >=
00818           uip_ntohl(nd6_opt_prefix_info->preferredlt))
00819          && (!uip_is_addr_link_local(&nd6_opt_prefix_info->prefix))) {
00820         /* on-link flag related processing */
00821         if(nd6_opt_prefix_info->flagsreserved1 & UIP_ND6_RA_FLAG_ONLINK) {
00822           prefix =
00823             uip_ds6_prefix_lookup(&nd6_opt_prefix_info->prefix,
00824                                   nd6_opt_prefix_info->preflen);
00825           if(prefix == NULL) {
00826             if(nd6_opt_prefix_info->validlt != 0) {
00827               if(nd6_opt_prefix_info->validlt != UIP_ND6_INFINITE_LIFETIME) {
00828                 prefix = uip_ds6_prefix_add(&nd6_opt_prefix_info->prefix,
00829                                             nd6_opt_prefix_info->preflen,
00830                                             uip_ntohl(nd6_opt_prefix_info->
00831                                                   validlt));
00832               } else {
00833                 prefix = uip_ds6_prefix_add(&nd6_opt_prefix_info->prefix,
00834                                             nd6_opt_prefix_info->preflen, 0);
00835               }
00836             }
00837           } else {
00838             switch (nd6_opt_prefix_info->validlt) {
00839             case 0:
00840               uip_ds6_prefix_rm(prefix);
00841               break;
00842             case UIP_ND6_INFINITE_LIFETIME:
00843               prefix->isinfinite = 1;
00844               break;
00845             default:
00846               PRINTF("Updating timer of prefix");
00847               PRINT6ADDR(&prefix->ipaddr);
00848               PRINTF("new value %lu\n", uip_ntohl(nd6_opt_prefix_info->validlt));
00849               stimer_set(&prefix->vlifetime,
00850                          uip_ntohl(nd6_opt_prefix_info->validlt));
00851               prefix->isinfinite = 0;
00852               break;
00853             }
00854           }
00855         }
00856         /* End of on-link flag related processing */
00857         /* autonomous flag related processing */
00858         if((nd6_opt_prefix_info->flagsreserved1 & UIP_ND6_RA_FLAG_AUTONOMOUS)
00859            && (nd6_opt_prefix_info->validlt != 0)
00860            && (nd6_opt_prefix_info->preflen == UIP_DEFAULT_PREFIX_LEN)) {
00861           
00862           uip_ipaddr_copy(&ipaddr, &nd6_opt_prefix_info->prefix);
00863           uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr);
00864           addr = uip_ds6_addr_lookup(&ipaddr);
00865           if((addr != NULL) && (addr->type == ADDR_AUTOCONF)) {
00866             if(nd6_opt_prefix_info->validlt != UIP_ND6_INFINITE_LIFETIME) {
00867               /* The processing below is defined in RFC4862 section 5.5.3 e */
00868               if((uip_ntohl(nd6_opt_prefix_info->validlt) > 2 * 60 * 60) ||
00869                  (uip_ntohl(nd6_opt_prefix_info->validlt) >
00870                   stimer_remaining(&addr->vlifetime))) {
00871                 PRINTF("Updating timer of address");
00872                 PRINT6ADDR(&addr->ipaddr);
00873                 PRINTF("new value %lu\n",
00874                        uip_ntohl(nd6_opt_prefix_info->validlt));
00875                 stimer_set(&addr->vlifetime,
00876                            uip_ntohl(nd6_opt_prefix_info->validlt));
00877               } else {
00878                 stimer_set(&addr->vlifetime, 2 * 60 * 60);
00879                 PRINTF("Updating timer of address ");
00880                 PRINT6ADDR(&addr->ipaddr);
00881                 PRINTF("new value %lu\n", (unsigned long)(2 * 60 * 60));
00882               }
00883               addr->isinfinite = 0;
00884             } else {
00885               addr->isinfinite = 1;
00886             }
00887           } else {
00888             if(uip_ntohl(nd6_opt_prefix_info->validlt) ==
00889                UIP_ND6_INFINITE_LIFETIME) {
00890               uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF);
00891             } else {
00892               uip_ds6_addr_add(&ipaddr, uip_ntohl(nd6_opt_prefix_info->validlt),
00893                                ADDR_AUTOCONF);
00894             }
00895           }
00896         }
00897         /* End of autonomous flag related processing */
00898       }
00899       break;
00900     default:
00901       PRINTF("ND option not supported in RA");
00902       break;
00903     }
00904     nd6_opt_offset += (UIP_ND6_OPT_HDR_BUF->len << 3);
00905   }
00906 
00907   defrt = uip_ds6_defrt_lookup(&UIP_IP_BUF->srcipaddr);
00908   if(UIP_ND6_RA_BUF->router_lifetime != 0) {
00909     if(nbr != NULL) {
00910       nbr->isrouter = 1;
00911     }
00912     if(defrt == NULL) {
00913       uip_ds6_defrt_add(&UIP_IP_BUF->srcipaddr,
00914                         (unsigned
00915                          long)(uip_ntohs(UIP_ND6_RA_BUF->router_lifetime)));
00916     } else {
00917       stimer_set(&(defrt->lifetime),
00918                  (unsigned long)(uip_ntohs(UIP_ND6_RA_BUF->router_lifetime)));
00919     }
00920   } else {
00921     if(defrt != NULL) {
00922       uip_ds6_defrt_rm(defrt);
00923     }
00924   }
00925 
00926 #if UIP_CONF_IPV6_QUEUE_PKT
00927   /* If the nbr just became reachable (e.g. it was in NBR_INCOMPLETE state
00928    * and we got a SLLAO), check if we had buffered a pkt for it */
00929   /*  if((nbr != NULL) && (nbr->queue_buf_len != 0)) {
00930     uip_len = nbr->queue_buf_len;
00931     memcpy(UIP_IP_BUF, nbr->queue_buf, uip_len);
00932     nbr->queue_buf_len = 0;
00933     return;
00934     }*/
00935   if(nbr != NULL && uip_packetqueue_buflen(&nbr->packethandle) != 0) {
00936     uip_len = uip_packetqueue_buflen(&nbr->packethandle);
00937     memcpy(UIP_IP_BUF, uip_packetqueue_buf(&nbr->packethandle), uip_len);
00938     uip_packetqueue_free(&nbr->packethandle);
00939     return;
00940   }
00941 
00942 #endif /*UIP_CONF_IPV6_QUEUE_PKT */
00943 
00944 discard:
00945   uip_len = 0;
00946   return;
00947 }
00948 #endif /* !UIP_CONF_ROUTER */
00949 
00950  /** @} */

Generated on Mon Apr 11 14:23:32 2011 for Contiki 2.5 by  doxygen 1.6.1