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
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
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
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
00113 #define UIP_ICMP_BUF ((struct uip_icmp_hdr *)&uip_buf[uip_l2_l3_hdr_len])
00114
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
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;
00127 static uint8_t *nd6_opt_llao;
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;
00131 static uip_ipaddr_t ipaddr;
00132 static uip_ds6_prefix_t *prefix;
00133 #endif
00134 static uip_ds6_nbr_t *nbr;
00135 static uip_ds6_defrt_t *defrt;
00136 static uip_ds6_addr_t *addr;
00137
00138
00139
00140
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
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
00176
00177
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
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
00192 if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
00193 PRINTF("NS received is bad\n");
00194 goto discard;
00195 } else {
00196 #endif
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
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
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
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
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
00250
00251
00252
00253
00254 PRINTF("NS received is bad\n");
00255 goto discard;
00256 }
00257 #endif
00258
00259
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
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
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;
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;
00347
00348
00349
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
00402
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
00420
00421
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
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
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
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
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
00511
00512
00513
00514
00515
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
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
00550
00551
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
00558
00559
00560
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
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
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
00589 if((nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr)) == NULL) {
00590
00591 uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr,
00592 &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], 0, NBR_STALE);
00593 } else {
00594
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
00606 }
00607
00608
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
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
00645
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
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
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
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
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
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
00701 #endif
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;
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
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
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
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
00857
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
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
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
00928
00929
00930
00931
00932
00933
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
00943
00944 discard:
00945 uip_len = 0;
00946 return;
00947 }
00948 #endif
00949
00950