00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 #include <string.h>
00044 #include <stdlib.h>
00045 #include "lib/random.h"
00046 #include "net/uip-nd6.h"
00047 #include "net/uip-ds6.h"
00048 #include "net/uip-packetqueue.h"
00049
00050 #define DEBUG DEBUG_NONE
00051 #include "net/uip-debug.h"
00052
00053 #ifdef UIP_CONF_DS6_NEIGHBOR_STATE_CHANGED
00054 #define NEIGHBOR_STATE_CHANGED(n) UIP_CONF_DS6_NEIGHBOR_STATE_CHANGED(n)
00055 void NEIGHBOR_STATE_CHANGED(uip_ds6_nbr_t *n);
00056 #else
00057 #define NEIGHBOR_STATE_CHANGED(n)
00058 #endif
00059
00060 struct etimer uip_ds6_timer_periodic;
00061
00062 #if UIP_CONF_ROUTER
00063 struct stimer uip_ds6_timer_ra;
00064 #if UIP_ND6_SEND_RA
00065 static uint8_t racount;
00066 static uint16_t rand_time;
00067 #endif
00068 #else
00069 struct etimer uip_ds6_timer_rs;
00070 static uint8_t rscount;
00071 #endif
00072
00073
00074
00075 uip_ds6_netif_t uip_ds6_if;
00076 uip_ds6_nbr_t uip_ds6_nbr_cache[UIP_DS6_NBR_NB];
00077 uip_ds6_defrt_t uip_ds6_defrt_list[UIP_DS6_DEFRT_NB];
00078 uip_ds6_prefix_t uip_ds6_prefix_list[UIP_DS6_PREFIX_NB];
00079 uip_ds6_route_t uip_ds6_routing_table[UIP_DS6_ROUTE_NB];
00080
00081
00082
00083
00084 static uip_ipaddr_t loc_fipaddr;
00085
00086
00087 static uip_ipaddr_t *locipaddr;
00088 static uip_ds6_addr_t *locaddr;
00089 static uip_ds6_maddr_t *locmaddr;
00090 static uip_ds6_aaddr_t *locaaddr;
00091 static uip_ds6_prefix_t *locprefix;
00092 static uip_ds6_nbr_t *locnbr;
00093 static uip_ds6_defrt_t *locdefrt;
00094 static uip_ds6_route_t *locroute;
00095
00096
00097 void
00098 uip_ds6_init(void)
00099 {
00100 PRINTF("Init of IPv6 data structures\n");
00101 PRINTF("%u neighbors\n%u default routers\n%u prefixes\n%u routes\n%u unicast addresses\n%u multicast addresses\n%u anycast addresses\n",
00102 UIP_DS6_NBR_NB, UIP_DS6_DEFRT_NB, UIP_DS6_PREFIX_NB, UIP_DS6_ROUTE_NB,
00103 UIP_DS6_ADDR_NB, UIP_DS6_MADDR_NB, UIP_DS6_AADDR_NB);
00104 memset(uip_ds6_nbr_cache, 0, sizeof(uip_ds6_nbr_cache));
00105 memset(uip_ds6_defrt_list, 0, sizeof(uip_ds6_defrt_list));
00106 memset(uip_ds6_prefix_list, 0, sizeof(uip_ds6_prefix_list));
00107 memset(&uip_ds6_if, 0, sizeof(uip_ds6_if));
00108 memset(uip_ds6_routing_table, 0, sizeof(uip_ds6_routing_table));
00109
00110
00111 uip_ds6_if.link_mtu = UIP_LINK_MTU;
00112 uip_ds6_if.cur_hop_limit = UIP_TTL;
00113 uip_ds6_if.base_reachable_time = UIP_ND6_REACHABLE_TIME;
00114 uip_ds6_if.reachable_time = uip_ds6_compute_reachable_time();
00115 uip_ds6_if.retrans_timer = UIP_ND6_RETRANS_TIMER;
00116 uip_ds6_if.maxdadns = UIP_ND6_DEF_MAXDADNS;
00117
00118
00119 uip_create_linklocal_prefix(&loc_fipaddr);
00120 #if UIP_CONF_ROUTER
00121 uip_ds6_prefix_add(&loc_fipaddr, UIP_DEFAULT_PREFIX_LEN, 0, 0, 0, 0);
00122 #else
00123 uip_ds6_prefix_add(&loc_fipaddr, UIP_DEFAULT_PREFIX_LEN, 0);
00124 #endif
00125 uip_ds6_set_addr_iid(&loc_fipaddr, &uip_lladdr);
00126 uip_ds6_addr_add(&loc_fipaddr, 0, ADDR_AUTOCONF);
00127
00128 uip_create_linklocal_allnodes_mcast(&loc_fipaddr);
00129 uip_ds6_maddr_add(&loc_fipaddr);
00130 #if UIP_CONF_ROUTER
00131 uip_create_linklocal_allrouters_mcast(&loc_fipaddr);
00132 uip_ds6_maddr_add(&loc_fipaddr);
00133 #if UIP_ND6_SEND_RA
00134 stimer_set(&uip_ds6_timer_ra, 2);
00135 #endif
00136 #else
00137 etimer_set(&uip_ds6_timer_rs,
00138 random_rand() % (UIP_ND6_MAX_RTR_SOLICITATION_DELAY *
00139 CLOCK_SECOND));
00140 #endif
00141 etimer_set(&uip_ds6_timer_periodic, UIP_DS6_PERIOD);
00142
00143 return;
00144 }
00145
00146
00147
00148 void
00149 uip_ds6_periodic(void)
00150 {
00151
00152 for(locaddr = uip_ds6_if.addr_list;
00153 locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) {
00154 if(locaddr->isused) {
00155 if((!locaddr->isinfinite) && (stimer_expired(&locaddr->vlifetime))) {
00156 uip_ds6_addr_rm(locaddr);
00157 } else if((locaddr->state == ADDR_TENTATIVE)
00158 && (locaddr->dadnscount <= uip_ds6_if.maxdadns)
00159 && (timer_expired(&locaddr->dadtimer))) {
00160 uip_ds6_dad(locaddr);
00161 }
00162 }
00163 }
00164
00165
00166 for(locdefrt = uip_ds6_defrt_list;
00167 locdefrt < uip_ds6_defrt_list + UIP_DS6_DEFRT_NB; locdefrt++) {
00168 if((locdefrt->isused) && (!locdefrt->isinfinite) &&
00169 (stimer_expired(&(locdefrt->lifetime)))) {
00170 uip_ds6_defrt_rm(locdefrt);
00171 }
00172 }
00173
00174 #if !UIP_CONF_ROUTER
00175
00176 for(locprefix = uip_ds6_prefix_list;
00177 locprefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB;
00178 locprefix++) {
00179 if(locprefix->isused && !locprefix->isinfinite
00180 && stimer_expired(&(locprefix->vlifetime))) {
00181 uip_ds6_prefix_rm(locprefix);
00182 }
00183 }
00184 #endif
00185
00186
00187 for(locnbr = uip_ds6_nbr_cache;
00188 locnbr < uip_ds6_nbr_cache + UIP_DS6_NBR_NB;
00189 locnbr++) {
00190 if(locnbr->isused) {
00191 switch(locnbr->state) {
00192 case NBR_INCOMPLETE:
00193 if(locnbr->nscount >= UIP_ND6_MAX_MULTICAST_SOLICIT) {
00194 uip_ds6_nbr_rm(locnbr);
00195 } else if(stimer_expired(&locnbr->sendns)) {
00196 locnbr->nscount++;
00197 PRINTF("NBR_INCOMPLETE: NS %u\n", locnbr->nscount);
00198 uip_nd6_ns_output(NULL, NULL, &locnbr->ipaddr);
00199 stimer_set(&locnbr->sendns, uip_ds6_if.retrans_timer / 1000);
00200 }
00201 break;
00202 case NBR_REACHABLE:
00203 if(stimer_expired(&locnbr->reachable)) {
00204 PRINTF("REACHABLE: moving to STALE (");
00205 PRINT6ADDR(&locnbr->ipaddr);
00206 PRINTF(")\n");
00207 locnbr->state = NBR_STALE;
00208 }
00209 break;
00210 case NBR_DELAY:
00211 if(stimer_expired(&locnbr->reachable)) {
00212 locnbr->state = NBR_PROBE;
00213 locnbr->nscount = 1;
00214 PRINTF("DELAY: moving to PROBE + NS %u\n", locnbr->nscount);
00215 uip_nd6_ns_output(NULL, &locnbr->ipaddr, &locnbr->ipaddr);
00216 stimer_set(&locnbr->sendns, uip_ds6_if.retrans_timer / 1000);
00217 }
00218 break;
00219 case NBR_PROBE:
00220 if(locnbr->nscount >= UIP_ND6_MAX_UNICAST_SOLICIT) {
00221 PRINTF("PROBE END\n");
00222 if((locdefrt = uip_ds6_defrt_lookup(&locnbr->ipaddr)) != NULL) {
00223 uip_ds6_defrt_rm(locdefrt);
00224 }
00225 uip_ds6_nbr_rm(locnbr);
00226 } else if(stimer_expired(&locnbr->sendns)) {
00227 locnbr->nscount++;
00228 PRINTF("PROBE: NS %u\n", locnbr->nscount);
00229 uip_nd6_ns_output(NULL, &locnbr->ipaddr, &locnbr->ipaddr);
00230 stimer_set(&locnbr->sendns, uip_ds6_if.retrans_timer / 1000);
00231 }
00232 break;
00233 default:
00234 break;
00235 }
00236 }
00237 }
00238
00239 #if UIP_CONF_ROUTER & UIP_ND6_SEND_RA
00240
00241 if(stimer_expired(&uip_ds6_timer_ra)) {
00242 uip_ds6_send_ra_periodic();
00243 }
00244 #endif
00245 etimer_reset(&uip_ds6_timer_periodic);
00246 return;
00247 }
00248
00249
00250 uint8_t
00251 uip_ds6_list_loop(uip_ds6_element_t *list, uint8_t size,
00252 uint16_t elementsize, uip_ipaddr_t *ipaddr,
00253 uint8_t ipaddrlen, uip_ds6_element_t **out_element)
00254 {
00255 uip_ds6_element_t *element;
00256
00257 *out_element = NULL;
00258
00259 for(element = list;
00260 element <
00261 (uip_ds6_element_t *)((uint8_t *)list + (size * elementsize));
00262 element = (uip_ds6_element_t *)((uint8_t *)element + elementsize)) {
00263 if(element->isused) {
00264 if(uip_ipaddr_prefixcmp(&element->ipaddr, ipaddr, ipaddrlen)) {
00265 *out_element = element;
00266 return FOUND;
00267 }
00268 } else {
00269 *out_element = element;
00270 }
00271 }
00272
00273 return *out_element != NULL ? FREESPACE : NOSPACE;
00274 }
00275
00276
00277 uip_ds6_nbr_t *
00278 uip_ds6_nbr_add(uip_ipaddr_t *ipaddr, uip_lladdr_t * lladdr,
00279 uint8_t isrouter, uint8_t state)
00280 {
00281 int r;
00282
00283 r = uip_ds6_list_loop
00284 ((uip_ds6_element_t *)uip_ds6_nbr_cache, UIP_DS6_NBR_NB,
00285 sizeof(uip_ds6_nbr_t), ipaddr, 128,
00286 (uip_ds6_element_t **)&locnbr);
00287
00288 if(r == FREESPACE) {
00289 locnbr->isused = 1;
00290 uip_ipaddr_copy(&locnbr->ipaddr, ipaddr);
00291 if(lladdr != NULL) {
00292 memcpy(&locnbr->lladdr, lladdr, UIP_LLADDR_LEN);
00293 } else {
00294 memset(&locnbr->lladdr, 0, UIP_LLADDR_LEN);
00295 }
00296 locnbr->isrouter = isrouter;
00297 locnbr->state = state;
00298 #if UIP_CONF_IPV6_QUEUE_PKT
00299 uip_packetqueue_new(&locnbr->packethandle);
00300 #endif
00301
00302 stimer_set(&locnbr->reachable, 0);
00303 stimer_set(&locnbr->sendns, 0);
00304 locnbr->nscount = 0;
00305 PRINTF("Adding neighbor with ip addr ");
00306 PRINT6ADDR(ipaddr);
00307 PRINTF("link addr ");
00308 PRINTLLADDR((&(locnbr->lladdr)));
00309 PRINTF("state %u\n", state);
00310 NEIGHBOR_STATE_CHANGED(locnbr);
00311
00312 locnbr->last_lookup = clock_time();
00313 return locnbr;
00314 } else if(r == NOSPACE) {
00315
00316
00317 uip_ds6_nbr_t *n, *oldest;
00318 clock_time_t oldest_time;
00319
00320 oldest = NULL;
00321 oldest_time = clock_time();
00322
00323 for(n = uip_ds6_nbr_cache;
00324 n < &uip_ds6_nbr_cache[UIP_DS6_NBR_NB];
00325 n++) {
00326 if(n->isused) {
00327 if(n->last_lookup < oldest_time) {
00328 oldest = n;
00329 oldest_time = n->last_lookup;
00330 }
00331 }
00332 }
00333 if(oldest != NULL) {
00334 uip_ds6_nbr_rm(oldest);
00335 return uip_ds6_nbr_add(ipaddr, lladdr, isrouter, state);
00336 }
00337 }
00338 PRINTF("uip_ds6_nbr_add drop\n");
00339 return NULL;
00340 }
00341
00342
00343 void
00344 uip_ds6_nbr_rm(uip_ds6_nbr_t *nbr)
00345 {
00346 if(nbr != NULL) {
00347 nbr->isused = 0;
00348 #if UIP_CONF_IPV6_QUEUE_PKT
00349 uip_packetqueue_free(&nbr->packethandle);
00350 #endif
00351 NEIGHBOR_STATE_CHANGED(nbr);
00352 }
00353 return;
00354 }
00355
00356
00357 uip_ds6_nbr_t *
00358 uip_ds6_nbr_lookup(uip_ipaddr_t *ipaddr)
00359 {
00360 if(uip_ds6_list_loop
00361 ((uip_ds6_element_t *)uip_ds6_nbr_cache, UIP_DS6_NBR_NB,
00362 sizeof(uip_ds6_nbr_t), ipaddr, 128,
00363 (uip_ds6_element_t **)&locnbr) == FOUND) {
00364 return locnbr;
00365 }
00366 return NULL;
00367 }
00368
00369
00370 uip_ds6_defrt_t *
00371 uip_ds6_defrt_add(uip_ipaddr_t *ipaddr, unsigned long interval)
00372 {
00373 if(uip_ds6_list_loop
00374 ((uip_ds6_element_t *)uip_ds6_defrt_list, UIP_DS6_DEFRT_NB,
00375 sizeof(uip_ds6_defrt_t), ipaddr, 128,
00376 (uip_ds6_element_t **)&locdefrt) == FREESPACE) {
00377 locdefrt->isused = 1;
00378 uip_ipaddr_copy(&locdefrt->ipaddr, ipaddr);
00379 if(interval != 0) {
00380 stimer_set(&locdefrt->lifetime, interval);
00381 locdefrt->isinfinite = 0;
00382 } else {
00383 locdefrt->isinfinite = 1;
00384 }
00385
00386 PRINTF("Adding defrouter with ip addr ");
00387 PRINT6ADDR(&locdefrt->ipaddr);
00388 PRINTF("\n");
00389
00390 ANNOTATE("#L %u 1\n", ipaddr->u8[sizeof(uip_ipaddr_t) - 1]);
00391
00392 return locdefrt;
00393 }
00394 return NULL;
00395 }
00396
00397
00398 void
00399 uip_ds6_defrt_rm(uip_ds6_defrt_t *defrt)
00400 {
00401 if(defrt != NULL) {
00402 defrt->isused = 0;
00403 ANNOTATE("#L %u 0\n", defrt->ipaddr.u8[sizeof(uip_ipaddr_t) - 1]);
00404 }
00405 return;
00406 }
00407
00408
00409 uip_ds6_defrt_t *
00410 uip_ds6_defrt_lookup(uip_ipaddr_t *ipaddr)
00411 {
00412 if(uip_ds6_list_loop((uip_ds6_element_t *)uip_ds6_defrt_list,
00413 UIP_DS6_DEFRT_NB, sizeof(uip_ds6_defrt_t), ipaddr, 128,
00414 (uip_ds6_element_t **)&locdefrt) == FOUND) {
00415 return locdefrt;
00416 }
00417 return NULL;
00418 }
00419
00420
00421 uip_ipaddr_t *
00422 uip_ds6_defrt_choose(void)
00423 {
00424 uip_ds6_nbr_t *bestnbr;
00425
00426 locipaddr = NULL;
00427 for(locdefrt = uip_ds6_defrt_list;
00428 locdefrt < uip_ds6_defrt_list + UIP_DS6_DEFRT_NB; locdefrt++) {
00429 if(locdefrt->isused) {
00430 PRINTF("Defrt, IP address ");
00431 PRINT6ADDR(&locdefrt->ipaddr);
00432 PRINTF("\n");
00433 bestnbr = uip_ds6_nbr_lookup(&locdefrt->ipaddr);
00434 if(bestnbr != NULL && bestnbr->state != NBR_INCOMPLETE) {
00435 PRINTF("Defrt found, IP address ");
00436 PRINT6ADDR(&locdefrt->ipaddr);
00437 PRINTF("\n");
00438 return &locdefrt->ipaddr;
00439 } else {
00440 locipaddr = &locdefrt->ipaddr;
00441 PRINTF("Defrt INCOMPLETE found, IP address ");
00442 PRINT6ADDR(&locdefrt->ipaddr);
00443 PRINTF("\n");
00444 }
00445 }
00446 }
00447 return locipaddr;
00448 }
00449
00450 #if UIP_CONF_ROUTER
00451
00452 uip_ds6_prefix_t *
00453 uip_ds6_prefix_add(uip_ipaddr_t *ipaddr, uint8_t ipaddrlen,
00454 uint8_t advertise, uint8_t flags, unsigned long vtime,
00455 unsigned long ptime)
00456 {
00457 if(uip_ds6_list_loop
00458 ((uip_ds6_element_t *)uip_ds6_prefix_list, UIP_DS6_PREFIX_NB,
00459 sizeof(uip_ds6_prefix_t), ipaddr, ipaddrlen,
00460 (uip_ds6_element_t **)&locprefix) == FREESPACE) {
00461 locprefix->isused = 1;
00462 uip_ipaddr_copy(&locprefix->ipaddr, ipaddr);
00463 locprefix->length = ipaddrlen;
00464 locprefix->advertise = advertise;
00465 locprefix->l_a_reserved = flags;
00466 locprefix->vlifetime = vtime;
00467 locprefix->plifetime = ptime;
00468 PRINTF("Adding prefix ");
00469 PRINT6ADDR(&locprefix->ipaddr);
00470 PRINTF("length %u, flags %x, Valid lifetime %lx, Preffered lifetime %lx\n",
00471 ipaddrlen, flags, vtime, ptime);
00472 return locprefix;
00473 } else {
00474 PRINTF("No more space in Prefix list\n");
00475 }
00476 return NULL;
00477 }
00478
00479
00480 #else
00481 uip_ds6_prefix_t *
00482 uip_ds6_prefix_add(uip_ipaddr_t *ipaddr, uint8_t ipaddrlen,
00483 unsigned long interval)
00484 {
00485 if(uip_ds6_list_loop
00486 ((uip_ds6_element_t *)uip_ds6_prefix_list, UIP_DS6_PREFIX_NB,
00487 sizeof(uip_ds6_prefix_t), ipaddr, ipaddrlen,
00488 (uip_ds6_element_t **)&locprefix) == FREESPACE) {
00489 locprefix->isused = 1;
00490 uip_ipaddr_copy(&locprefix->ipaddr, ipaddr);
00491 locprefix->length = ipaddrlen;
00492 if(interval != 0) {
00493 stimer_set(&(locprefix->vlifetime), interval);
00494 locprefix->isinfinite = 0;
00495 } else {
00496 locprefix->isinfinite = 1;
00497 }
00498 PRINTF("Adding prefix ");
00499 PRINT6ADDR(&locprefix->ipaddr);
00500 PRINTF("length %u, vlifetime%lu\n", ipaddrlen, interval);
00501 }
00502 return NULL;
00503 }
00504 #endif
00505
00506
00507 void
00508 uip_ds6_prefix_rm(uip_ds6_prefix_t * prefix)
00509 {
00510 if(prefix != NULL) {
00511 prefix->isused = 0;
00512 }
00513 return;
00514 }
00515
00516 uip_ds6_prefix_t *
00517 uip_ds6_prefix_lookup(uip_ipaddr_t *ipaddr, uint8_t ipaddrlen)
00518 {
00519 if(uip_ds6_list_loop((uip_ds6_element_t *)uip_ds6_prefix_list,
00520 UIP_DS6_PREFIX_NB, sizeof(uip_ds6_prefix_t),
00521 ipaddr, ipaddrlen,
00522 (uip_ds6_element_t **)&locprefix) == FOUND) {
00523 return locprefix;
00524 }
00525 return NULL;
00526 }
00527
00528
00529 uint8_t
00530 uip_ds6_is_addr_onlink(uip_ipaddr_t *ipaddr)
00531 {
00532 for(locprefix = uip_ds6_prefix_list;
00533 locprefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB; locprefix++) {
00534 if(locprefix->isused &&
00535 uip_ipaddr_prefixcmp(&locprefix->ipaddr, ipaddr, locprefix->length)) {
00536 return 1;
00537 }
00538 }
00539 return 0;
00540 }
00541
00542
00543 uip_ds6_addr_t *
00544 uip_ds6_addr_add(uip_ipaddr_t *ipaddr, unsigned long vlifetime, uint8_t type)
00545 {
00546 if(uip_ds6_list_loop
00547 ((uip_ds6_element_t *)uip_ds6_if.addr_list, UIP_DS6_ADDR_NB,
00548 sizeof(uip_ds6_addr_t), ipaddr, 128,
00549 (uip_ds6_element_t **)&locaddr) == FREESPACE) {
00550 locaddr->isused = 1;
00551 uip_ipaddr_copy(&locaddr->ipaddr, ipaddr);
00552 locaddr->state = ADDR_TENTATIVE;
00553 locaddr->type = type;
00554 if(vlifetime == 0) {
00555 locaddr->isinfinite = 1;
00556 } else {
00557 locaddr->isinfinite = 0;
00558 stimer_set(&(locaddr->vlifetime), vlifetime);
00559 }
00560 timer_set(&locaddr->dadtimer,
00561 random_rand() % (UIP_ND6_MAX_RTR_SOLICITATION_DELAY *
00562 CLOCK_SECOND));
00563 locaddr->dadnscount = 0;
00564 uip_create_solicited_node(ipaddr, &loc_fipaddr);
00565 uip_ds6_maddr_add(&loc_fipaddr);
00566 return locaddr;
00567 }
00568 return NULL;
00569 }
00570
00571
00572 void
00573 uip_ds6_addr_rm(uip_ds6_addr_t *addr)
00574 {
00575 if(addr != NULL) {
00576 uip_create_solicited_node(&addr->ipaddr, &loc_fipaddr);
00577 if((locmaddr = uip_ds6_maddr_lookup(&loc_fipaddr)) != NULL) {
00578 uip_ds6_maddr_rm(locmaddr);
00579 }
00580 addr->isused = 0;
00581 }
00582 return;
00583 }
00584
00585
00586 uip_ds6_addr_t *
00587 uip_ds6_addr_lookup(uip_ipaddr_t *ipaddr)
00588 {
00589 if(uip_ds6_list_loop
00590 ((uip_ds6_element_t *)uip_ds6_if.addr_list, UIP_DS6_ADDR_NB,
00591 sizeof(uip_ds6_addr_t), ipaddr, 128,
00592 (uip_ds6_element_t **)&locaddr) == FOUND) {
00593 return locaddr;
00594 }
00595 return NULL;
00596 }
00597
00598
00599
00600
00601
00602
00603
00604 uip_ds6_addr_t *
00605 uip_ds6_get_link_local(int8_t state)
00606 {
00607 for(locaddr = uip_ds6_if.addr_list;
00608 locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) {
00609 if(locaddr->isused && (state == -1 || locaddr->state == state)
00610 && (uip_is_addr_link_local(&locaddr->ipaddr))) {
00611 return locaddr;
00612 }
00613 }
00614 return NULL;
00615 }
00616
00617
00618
00619
00620
00621
00622
00623 uip_ds6_addr_t *
00624 uip_ds6_get_global(int8_t state)
00625 {
00626 for(locaddr = uip_ds6_if.addr_list;
00627 locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) {
00628 if(locaddr->isused && (state == -1 || locaddr->state == state)
00629 && !(uip_is_addr_link_local(&locaddr->ipaddr))) {
00630 return locaddr;
00631 }
00632 }
00633 return NULL;
00634 }
00635
00636
00637 uip_ds6_maddr_t *
00638 uip_ds6_maddr_add(uip_ipaddr_t *ipaddr)
00639 {
00640 if(uip_ds6_list_loop
00641 ((uip_ds6_element_t *)uip_ds6_if.maddr_list, UIP_DS6_MADDR_NB,
00642 sizeof(uip_ds6_maddr_t), ipaddr, 128,
00643 (uip_ds6_element_t **)&locmaddr) == FREESPACE) {
00644 locmaddr->isused = 1;
00645 uip_ipaddr_copy(&locmaddr->ipaddr, ipaddr);
00646 return locmaddr;
00647 }
00648 return NULL;
00649 }
00650
00651
00652 void
00653 uip_ds6_maddr_rm(uip_ds6_maddr_t * maddr)
00654 {
00655 if(maddr != NULL) {
00656 maddr->isused = 0;
00657 }
00658 return;
00659 }
00660
00661
00662 uip_ds6_maddr_t *
00663 uip_ds6_maddr_lookup(uip_ipaddr_t *ipaddr)
00664 {
00665 if(uip_ds6_list_loop
00666 ((uip_ds6_element_t *)uip_ds6_if.maddr_list, UIP_DS6_MADDR_NB,
00667 sizeof(uip_ds6_maddr_t), ipaddr, 128,
00668 (uip_ds6_element_t **)&locmaddr) == FOUND) {
00669 return locmaddr;
00670 }
00671 return NULL;
00672 }
00673
00674
00675
00676 uip_ds6_aaddr_t *
00677 uip_ds6_aaddr_add(uip_ipaddr_t *ipaddr)
00678 {
00679 if(uip_ds6_list_loop
00680 ((uip_ds6_element_t *)uip_ds6_if.aaddr_list, UIP_DS6_AADDR_NB,
00681 sizeof(uip_ds6_aaddr_t), ipaddr, 128,
00682 (uip_ds6_element_t **)&locaaddr) == FREESPACE) {
00683 locaaddr->isused = 1;
00684 uip_ipaddr_copy(&locaaddr->ipaddr, ipaddr);
00685 return locaaddr;
00686 }
00687 return NULL;
00688 }
00689
00690
00691 void
00692 uip_ds6_aaddr_rm(uip_ds6_aaddr_t * aaddr)
00693 {
00694 if(aaddr != NULL) {
00695 aaddr->isused = 0;
00696 }
00697 return;
00698 }
00699
00700
00701 uip_ds6_aaddr_t *
00702 uip_ds6_aaddr_lookup(uip_ipaddr_t *ipaddr)
00703 {
00704 if(uip_ds6_list_loop((uip_ds6_element_t *)uip_ds6_if.aaddr_list,
00705 UIP_DS6_AADDR_NB, sizeof(uip_ds6_aaddr_t), ipaddr, 128,
00706 (uip_ds6_element_t **)&locaaddr) == FOUND) {
00707 return locaaddr;
00708 }
00709 return NULL;
00710 }
00711
00712
00713 uip_ds6_route_t *
00714 uip_ds6_route_lookup(uip_ipaddr_t *destipaddr)
00715 {
00716 uip_ds6_route_t *locrt = NULL;
00717 uint8_t longestmatch = 0;
00718
00719 PRINTF("DS6: Looking up route for ");
00720 PRINT6ADDR(destipaddr);
00721 PRINTF("\n");
00722
00723 for(locroute = uip_ds6_routing_table;
00724 locroute < uip_ds6_routing_table + UIP_DS6_ROUTE_NB; locroute++) {
00725 if((locroute->isused) && (locroute->length >= longestmatch)
00726 &&
00727 (uip_ipaddr_prefixcmp
00728 (destipaddr, &locroute->ipaddr, locroute->length))) {
00729 longestmatch = locroute->length;
00730 locrt = locroute;
00731 }
00732 }
00733
00734 if(locrt != NULL) {
00735 PRINTF("DS6: Found route:");
00736 PRINT6ADDR(destipaddr);
00737 PRINTF(" via ");
00738 PRINT6ADDR(&locrt->nexthop);
00739 PRINTF("\n");
00740 } else {
00741 PRINTF("DS6: No route found\n");
00742 }
00743
00744 return locrt;
00745 }
00746
00747
00748 uip_ds6_route_t *
00749 uip_ds6_route_add(uip_ipaddr_t *ipaddr, uint8_t length, uip_ipaddr_t *nexthop,
00750 uint8_t metric)
00751 {
00752 if(uip_ds6_list_loop
00753 ((uip_ds6_element_t *)uip_ds6_routing_table, UIP_DS6_ROUTE_NB,
00754 sizeof(uip_ds6_route_t), ipaddr, length,
00755 (uip_ds6_element_t **)&locroute) == FREESPACE) {
00756 locroute->isused = 1;
00757 uip_ipaddr_copy(&(locroute->ipaddr), ipaddr);
00758 locroute->length = length;
00759 uip_ipaddr_copy(&(locroute->nexthop), nexthop);
00760 locroute->metric = metric;
00761
00762 PRINTF("DS6: adding route: ");
00763 PRINT6ADDR(ipaddr);
00764 PRINTF(" via ");
00765 PRINT6ADDR(nexthop);
00766 PRINTF("\n");
00767 ANNOTATE("#L %u 1;blue\n", nexthop->u8[sizeof(uip_ipaddr_t) - 1]);
00768 }
00769
00770 return locroute;
00771 }
00772
00773
00774 void
00775 uip_ds6_route_rm(uip_ds6_route_t *route)
00776 {
00777 route->isused = 0;
00778 #if (DEBUG & DEBUG_ANNOTATE) == DEBUG_ANNOTATE
00779
00780
00781 for(locroute = uip_ds6_routing_table;
00782 locroute < uip_ds6_routing_table + UIP_DS6_ROUTE_NB;
00783 locroute++) {
00784 if(locroute->isused && uip_ipaddr_cmp(&locroute->nexthop, &route->nexthop)) {
00785
00786 return;
00787 }
00788 }
00789 ANNOTATE("#L %u 0\n",route->nexthop.u8[sizeof(uip_ipaddr_t) - 1]);
00790 #endif
00791 }
00792
00793 void
00794 uip_ds6_route_rm_by_nexthop(uip_ipaddr_t *nexthop)
00795 {
00796 for(locroute = uip_ds6_routing_table;
00797 locroute < uip_ds6_routing_table + UIP_DS6_ROUTE_NB;
00798 locroute++) {
00799 if(locroute->isused && uip_ipaddr_cmp(&locroute->nexthop, nexthop)) {
00800 locroute->isused = 0;
00801 }
00802 }
00803 ANNOTATE("#L %u 0\n",nexthop->u8[sizeof(uip_ipaddr_t) - 1]);
00804 }
00805
00806
00807 void
00808 uip_ds6_select_src(uip_ipaddr_t *src, uip_ipaddr_t *dst)
00809 {
00810 uint8_t best = 0;
00811 uint8_t n = 0;
00812 uip_ds6_addr_t *matchaddr = NULL;
00813
00814 if(!uip_is_addr_link_local(dst) && !uip_is_addr_mcast(dst)) {
00815
00816 for(locaddr = uip_ds6_if.addr_list;
00817 locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) {
00818
00819 if(locaddr->isused && locaddr->state == ADDR_PREFERRED &&
00820 !uip_is_addr_link_local(&locaddr->ipaddr)) {
00821 n = get_match_length(dst, &locaddr->ipaddr);
00822 if(n >= best) {
00823 best = n;
00824 matchaddr = locaddr;
00825 }
00826 }
00827 }
00828 } else {
00829 matchaddr = uip_ds6_get_link_local(ADDR_PREFERRED);
00830 }
00831
00832
00833 if(matchaddr == NULL) {
00834 uip_create_unspecified(src);
00835 } else {
00836 uip_ipaddr_copy(src, &matchaddr->ipaddr);
00837 }
00838 }
00839
00840
00841 void
00842 uip_ds6_set_addr_iid(uip_ipaddr_t *ipaddr, uip_lladdr_t * lladdr)
00843 {
00844
00845
00846 #if (UIP_LLADDR_LEN == 8)
00847 memcpy(ipaddr->u8 + 8, lladdr, UIP_LLADDR_LEN);
00848 ipaddr->u8[8] ^= 0x02;
00849 #elif (UIP_LLADDR_LEN == 6)
00850 memcpy(ipaddr->u8 + 8, lladdr, 3);
00851 ipaddr->u8[11] = 0xff;
00852 ipaddr->u8[12] = 0xfe;
00853 memcpy(ipaddr->u8 + 13, (uint8_t *)lladdr + 3, 3);
00854 ipaddr->u8[8] ^= 0x02;
00855 #else
00856 #error uip-ds6.c cannot build interface address when UIP_LLADDR_LEN is not 6 or 8
00857 #endif
00858 }
00859
00860
00861 uint8_t
00862 get_match_length(uip_ipaddr_t *src, uip_ipaddr_t *dst)
00863 {
00864 uint8_t j, k, x_or;
00865 uint8_t len = 0;
00866
00867 for(j = 0; j < 16; j++) {
00868 if(src->u8[j] == dst->u8[j]) {
00869 len += 8;
00870 } else {
00871 x_or = src->u8[j] ^ dst->u8[j];
00872 for(k = 0; k < 8; k++) {
00873 if((x_or & 0x80) == 0) {
00874 len++;
00875 x_or <<= 1;
00876 } else {
00877 break;
00878 }
00879 }
00880 break;
00881 }
00882 }
00883 return len;
00884 }
00885
00886
00887 void
00888 uip_ds6_dad(uip_ds6_addr_t *addr)
00889 {
00890
00891 if(addr->dadnscount < uip_ds6_if.maxdadns) {
00892 uip_nd6_ns_output(NULL, NULL, &addr->ipaddr);
00893 addr->dadnscount++;
00894 timer_set(&addr->dadtimer,
00895 uip_ds6_if.retrans_timer / 1000 * CLOCK_SECOND);
00896 return;
00897 }
00898
00899
00900
00901
00902 PRINTF("DAD succeeded, ipaddr:");
00903 PRINT6ADDR(&addr->ipaddr);
00904 PRINTF("\n");
00905
00906 addr->state = ADDR_PREFERRED;
00907 return;
00908 }
00909
00910
00911
00912
00913
00914
00915 int
00916 uip_ds6_dad_failed(uip_ds6_addr_t * addr)
00917 {
00918 if(uip_is_addr_link_local(&addr->ipaddr)) {
00919 PRINTF("Contiki shutdown, DAD for link local address failed\n");
00920 return 0;
00921 }
00922 uip_ds6_addr_rm(addr);
00923 return 1;
00924 }
00925
00926 #if UIP_CONF_ROUTER
00927 #if UIP_ND6_SEND_RA
00928
00929 void
00930 uip_ds6_send_ra_sollicited(void)
00931 {
00932
00933
00934
00935
00936
00937
00938 rand_time = 0;
00939 PRINTF("Solicited RA, random time %u\n", rand_time);
00940
00941 if(stimer_remaining(&uip_ds6_timer_ra) > rand_time) {
00942 if(stimer_elapsed(&uip_ds6_timer_ra) < UIP_ND6_MIN_DELAY_BETWEEN_RAS) {
00943
00944
00945
00946
00947 } else {
00948 stimer_set(&uip_ds6_timer_ra, rand_time);
00949 }
00950 }
00951 }
00952
00953
00954 void
00955 uip_ds6_send_ra_periodic(void)
00956 {
00957 if(racount > 0) {
00958
00959 uip_nd6_ra_output(NULL);
00960 PRINTF("Sending periodic RA\n");
00961 }
00962
00963 rand_time = UIP_ND6_MIN_RA_INTERVAL + random_rand() %
00964 (uint16_t) (UIP_ND6_MAX_RA_INTERVAL - UIP_ND6_MIN_RA_INTERVAL);
00965 PRINTF("Random time 1 = %u\n", rand_time);
00966
00967 if(racount < UIP_ND6_MAX_INITIAL_RAS) {
00968 if(rand_time > UIP_ND6_MAX_INITIAL_RA_INTERVAL) {
00969 rand_time = UIP_ND6_MAX_INITIAL_RA_INTERVAL;
00970 PRINTF("Random time 2 = %u\n", rand_time);
00971 }
00972 racount++;
00973 }
00974 PRINTF("Random time 3 = %u\n", rand_time);
00975 stimer_set(&uip_ds6_timer_ra, rand_time);
00976 }
00977
00978 #endif
00979 #else
00980
00981 void
00982 uip_ds6_send_rs(void)
00983 {
00984 if((uip_ds6_defrt_choose() == NULL)
00985 && (rscount < UIP_ND6_MAX_RTR_SOLICITATIONS)) {
00986 PRINTF("Sending RS %u\n", rscount);
00987 uip_nd6_rs_output();
00988 rscount++;
00989 etimer_set(&uip_ds6_timer_rs,
00990 UIP_ND6_RTR_SOLICITATION_INTERVAL * CLOCK_SECOND);
00991 } else {
00992 PRINTF("Router found ? (boolean): %u\n",
00993 (uip_ds6_defrt_choose() != NULL));
00994 etimer_stop(&uip_ds6_timer_rs);
00995 }
00996 return;
00997 }
00998
00999 #endif
01000
01001 uint32_t
01002 uip_ds6_compute_reachable_time(void)
01003 {
01004 return (uint32_t) (UIP_ND6_MIN_RANDOM_FACTOR
01005 (uip_ds6_if.base_reachable_time)) +
01006 ((uint16_t) (random_rand() << 8) +
01007 (uint16_t) random_rand()) %
01008 (uint32_t) (UIP_ND6_MAX_RANDOM_FACTOR(uip_ds6_if.base_reachable_time) -
01009 UIP_ND6_MIN_RANDOM_FACTOR(uip_ds6_if.base_reachable_time));
01010 }
01011
01012
01013