/* Sends a ping packet out the radio */ static void raven_ping6(uip_ipaddr_t *addr, int len) { UIP_IP_BUF->vtc = 0x60; UIP_IP_BUF->tcflow = 0; UIP_IP_BUF->flow = 0; UIP_IP_BUF->proto = UIP_PROTO_ICMP6; UIP_IP_BUF->ttl = UIP_TTL; uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, addr); uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr); UIP_ICMP_BUF->type = ICMP6_ECHO_REQUEST; UIP_ICMP_BUF->icode = 0; /* set identifier and sequence number to 0 */ memset((void *)UIP_ICMP_BUF + UIP_ICMPH_LEN, 0, UIP_ICMP6_ECHO_REQUEST_LEN); /* put len bytes of all one data */ memset((void *)UIP_ICMP_BUF + UIP_ICMPH_LEN + UIP_ICMP6_ECHO_REQUEST_LEN, 1, len); uip_len = UIP_ICMPH_LEN + UIP_ICMP6_ECHO_REQUEST_LEN + UIP_IPH_LEN + len; UIP_IP_BUF->len[0] = (u8_t)((uip_len - 40) >> 8); UIP_IP_BUF->len[1] = (u8_t)((uip_len - 40) & 0x00FF); UIP_ICMP_BUF->icmpchksum = 0; UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum(); tcpip_ipv6_output(); }
/*---------------------------------------------------------------------------*/ static void send_ping(uip_ipaddr_t *dest_addr) #if UIP_CONF_IPV6 { static uint16_t count; UIP_IP_BUF->vtc = 0x60; UIP_IP_BUF->tcflow = 1; UIP_IP_BUF->flow = 0; UIP_IP_BUF->proto = UIP_PROTO_ICMP6; UIP_IP_BUF->ttl = uip_ds6_if.cur_hop_limit; uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, dest_addr); uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr); UIP_ICMP_BUF->type = ICMP6_ECHO_REQUEST; UIP_ICMP_BUF->icode = 0; /* set identifier and sequence number to 0 */ memset((uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN, 0, 4); /* put one byte of data */ memset((uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN + UIP_ICMP6_ECHO_REQUEST_LEN, count, PING_DATALEN); count++; uip_len = UIP_ICMPH_LEN + UIP_ICMP6_ECHO_REQUEST_LEN + UIP_IPH_LEN + PING_DATALEN; UIP_IP_BUF->len[0] = (uint8_t)((uip_len - 40) >> 8); UIP_IP_BUF->len[1] = (uint8_t)((uip_len - 40) & 0x00ff); UIP_ICMP_BUF->icmpchksum = 0; UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum(); tcpip_ipv6_output(); }
/* Sends a ping packet out the radio */ void raven_ping6(void) { /* ping ipv6.google.com*/ uip_ip6addr(&ping_addr,0x2001,0x420,0x5FFF,0x7D,0x2D0,0xB7FF,0xFE23,0xE6DB); //uip_ip6addr(&ping_addr, 0x2001, 0x4860, 0, 0x2001, 0, 0, 0, 0x68); //uip_ip6addr(&ping_addr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 1); UIP_IP_BUF->vtc = 0x60; UIP_IP_BUF->tcflow = 1; UIP_IP_BUF->flow = 0; UIP_IP_BUF->proto = UIP_PROTO_ICMP6; //UIP_IP_BUF->ttl = uip_netif_physical_if.cur_hop_limit; UIP_IP_BUF->ttl = uip_ds6_if.cur_hop_limit; uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &ping_addr); //uip_netif_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr); uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr); UIP_ICMP_BUF->type = ICMP6_ECHO_REQUEST; UIP_ICMP_BUF->icode = 0; /* set identifier and sequence number to 0 */ memset((void *)UIP_ICMP_BUF + UIP_ICMPH_LEN, 0, 4); uip_len = UIP_ICMPH_LEN + UIP_ICMP6_ECHO_REQUEST_LEN + UIP_IPH_LEN; UIP_IP_BUF->len[0] = (uint8_t)((uip_len - 40) >> 8); UIP_IP_BUF->len[1] = (uint8_t)((uip_len - 40) & 0x00FF); UIP_ICMP_BUF->icmpchksum = 0; UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum(); tcpip_ipv6_output(); }
/*------------------------------------------------------------------*/ void uip_nd6_ns_output(uip_ipaddr_t * src, uip_ipaddr_t * dest, uip_ipaddr_t * tgt) { uip_ext_len = 0; UIP_IP_BUF->vtc = 0x60; UIP_IP_BUF->tcflow = 0; UIP_IP_BUF->flow = 0; UIP_IP_BUF->proto = UIP_PROTO_ICMP6; UIP_IP_BUF->ttl = UIP_ND6_HOP_LIMIT; if(dest == NULL) { uip_create_solicited_node(tgt, &UIP_IP_BUF->destipaddr); } else { uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, dest); } UIP_ICMP_BUF->type = ICMP6_NS; UIP_ICMP_BUF->icode = 0; UIP_ND6_NS_BUF->reserved = 0; uip_ipaddr_copy((uip_ipaddr_t *) &UIP_ND6_NS_BUF->tgtipaddr, tgt); UIP_IP_BUF->len[0] = 0; /* length will not be more than 255 */ /* * check if we add a SLLAO option: for DAD, MUST NOT, for NUD, MAY * (here yes), for Address resolution , MUST */ if(!(uip_ds6_is_my_addr(tgt))) { if(src != NULL) { uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, src); } else { uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr); } UIP_IP_BUF->len[1] = UIP_ICMPH_LEN + UIP_ND6_NS_LEN + UIP_ND6_OPT_LLAO_LEN; create_llao(&uip_buf[uip_l2_l3_icmp_hdr_len + UIP_ND6_NS_LEN], UIP_ND6_OPT_SLLAO); uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_NS_LEN + UIP_ND6_OPT_LLAO_LEN; } else { uip_create_unspecified(&UIP_IP_BUF->srcipaddr); UIP_IP_BUF->len[1] = UIP_ICMPH_LEN + UIP_ND6_NS_LEN; uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_NS_LEN; } UIP_ICMP_BUF->icmpchksum = 0; UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum(); UIP_STAT(++uip_stat.nd6.sent); PRINTF("Sending NS to"); PRINT6ADDR(&UIP_IP_BUF->destipaddr); PRINTF("from"); PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINTF("with target address"); PRINT6ADDR(tgt); PRINTF("\n"); return; }
/*---------------------------------------------------------------------------*/ void uip_icmp6_echo_request_input(void) { #if UIP_CONF_IPV6_RPL u8_t temp_ext_len; #endif /* UIP_CONF_IPV6_RPL */ /* * we send an echo reply. It is trivial if there was no extension * headers in the request otherwise we need to remove the extension * headers and change a few fields */ PRINTF("Received Echo Request from"); PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINTF("to"); PRINT6ADDR(&UIP_IP_BUF->destipaddr); PRINTF("\n"); /* IP header */ UIP_IP_BUF->ttl = uip_ds6_if.cur_hop_limit; if(uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)){ uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &UIP_IP_BUF->srcipaddr); uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr); } else { uip_ipaddr_copy(&tmp_ipaddr, &UIP_IP_BUF->srcipaddr); uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr); uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &tmp_ipaddr); } if(uip_ext_len > 0) { #if UIP_CONF_IPV6_RPL if ((temp_ext_len=rpl_invert_header())) { /* If there were other extension headers*/ UIP_FIRST_EXT_BUF->next = UIP_PROTO_ICMP6; if (uip_ext_len != temp_ext_len) { uip_len -= (uip_ext_len - temp_ext_len); UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); /* move the echo request payload (starting after the icmp header) * to the new location in the reply. * The shift is equal to the length of the remaining extension headers present * Note: UIP_ICMP_BUF still points to the echo request at this stage */ memmove((uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN - (uip_ext_len - temp_ext_len), (uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN, (uip_len - UIP_IPH_LEN - temp_ext_len - UIP_ICMPH_LEN)); } uip_ext_len=temp_ext_len; } else {
/* Useful for debugging so allow external calls */ void raven_ping6(void) { #define PING_GOOGLE 0 UIP_IP_BUF->vtc = 0x60; UIP_IP_BUF->tcflow = 1; UIP_IP_BUF->flow = 0; UIP_IP_BUF->proto = UIP_PROTO_ICMP6; UIP_IP_BUF->ttl = uip_ds6_if.cur_hop_limit; #if PING_GOOGLE if (seqno==1) { uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, uip_ds6_defrt_choose()); //the default router } else if (seqno==2) { uip_ip6addr(&UIP_IP_BUF->destipaddr,0x2001,0x4860,0x800f,0x0000,0x0000,0x0000,0x0000,0x0093); //ipv6.google.com } else if (seqno==3) { uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, uip_ds6_defrt_choose()); //the default router } else { // uip_ip6addr(&UIP_IP_BUF->destipaddr,0x2001,0x0420,0x5FFF,0x007D,0x02D0,0xB7FF,0xFE23,0xE6DB); //?.cisco.com uip_ip6addr(&UIP_IP_BUF->destipaddr,0x2001,0x0420,0x0000,0x0010,0x0250,0x8bff,0xfee8,0xf800); //six.cisco.com } #else uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, uip_ds6_defrt_choose()); //the default router #endif uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr); UIP_ICMP_BUF->type = ICMP6_ECHO_REQUEST; UIP_ICMP_BUF->icode = 0; /* set identifier and sequence number to 0 */ memset((void *)UIP_ICMP_BUF + UIP_ICMPH_LEN, 0, 4); /* put one byte of data */ memset((void *)UIP_ICMP_BUF + UIP_ICMPH_LEN + UIP_ICMP6_ECHO_REQUEST_LEN, count, PING6_DATALEN); uip_len = UIP_ICMPH_LEN + UIP_ICMP6_ECHO_REQUEST_LEN + UIP_IPH_LEN + PING6_DATALEN; UIP_IP_BUF->len[0] = (uint8_t)((uip_len - 40) >> 8); UIP_IP_BUF->len[1] = (uint8_t)((uip_len - 40) & 0x00FF); UIP_ICMP_BUF->icmpchksum = 0; UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum(); tcpip_ipv6_output(); }
/*---------------------------------------------------------------------------*/ static void ping6handler() { if(count < PING6_NB) { UIP_IP_BUF->vtc = 0x60; UIP_IP_BUF->tcflow = 1; UIP_IP_BUF->flow = 0; UIP_IP_BUF->proto = UIP_PROTO_ICMP6; UIP_IP_BUF->ttl = uip_ds6_if.cur_hop_limit; uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &dest_addr); uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr); UIP_ICMP_BUF->type = ICMP6_ECHO_REQUEST; UIP_ICMP_BUF->icode = 0; /* set identifier and sequence number to 0 */ memset((uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN, 0, 4); /* put one byte of data */ memset((uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN + UIP_ICMP6_ECHO_REQUEST_LEN, count, PING6_DATALEN); uip_len = UIP_ICMPH_LEN + UIP_ICMP6_ECHO_REQUEST_LEN + UIP_IPH_LEN + PING6_DATALEN; UIP_IP_BUF->len[0] = (uint8_t)((uip_len - 40) >> 8); UIP_IP_BUF->len[1] = (uint8_t)((uip_len - 40) & 0x00FF); UIP_ICMP_BUF->icmpchksum = 0; UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum(); PRINTF("Echo Request to "); PRINT6ADDR(&UIP_IP_BUF->destipaddr); PRINTF(" from "); PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINTF("\n"); UIP_STAT(++uip_stat.icmp.sent); tcpip_ipv6_output(); count++; etimer_set(&ping6_periodic_timer, 3 * CLOCK_SECOND); } else {
/*---------------------------------------------------------------------------*/ static void echo_request_input(void) { /* * we send an echo reply. It is trivial if there was no extension * headers in the request otherwise we need to remove the extension * headers and change a few fields */ PRINTF("Received Echo Request from "); PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINTF(" to "); PRINT6ADDR(&UIP_IP_BUF->destipaddr); PRINTF("\n"); /* IP header */ UIP_IP_BUF->ttl = uip_ds6_if.cur_hop_limit; if(uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)){ uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &UIP_IP_BUF->srcipaddr); uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr); } else { uip_ipaddr_copy(&tmp_ipaddr, &UIP_IP_BUF->srcipaddr); uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr); uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &tmp_ipaddr); } if(uip_ext_len > 0) { /* Remove extension headers if any */ UIP_IP_BUF->proto = UIP_PROTO_ICMP6; uip_len -= uip_ext_len; UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); /* move the echo request payload (starting after the icmp header) * to the new location in the reply. * The shift is equal to the length of the extension headers present * Note: UIP_ICMP_BUF still points to the echo request at this stage */ memmove((uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN - uip_ext_len, (uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN, (uip_len - UIP_IPH_LEN - UIP_ICMPH_LEN)); uip_ext_len = 0; }
/*---------------------------------------------------------------------------*/ void uip_nd6_rs_output(void) { UIP_IP_BUF->vtc = 0x60; UIP_IP_BUF->tcflow = 0; UIP_IP_BUF->flow = 0; UIP_IP_BUF->proto = UIP_PROTO_ICMP6; UIP_IP_BUF->ttl = UIP_ND6_HOP_LIMIT; uip_create_linklocal_allrouters_mcast(&UIP_IP_BUF->destipaddr); uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr); UIP_ICMP_BUF->type = ICMP6_RS; UIP_ICMP_BUF->icode = 0; UIP_IP_BUF->len[0] = 0; /* length will not be more than 255 */ if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) { UIP_IP_BUF->len[1] = UIP_ICMPH_LEN + UIP_ND6_RS_LEN; uip_len = uip_l3_icmp_hdr_len + UIP_ND6_RS_LEN; } else { uip_len = uip_l3_icmp_hdr_len + UIP_ND6_RS_LEN + UIP_ND6_OPT_LLAO_LEN; UIP_IP_BUF->len[1] = UIP_ICMPH_LEN + UIP_ND6_RS_LEN + UIP_ND6_OPT_LLAO_LEN; create_llao(&uip_buf[uip_l2_l3_icmp_hdr_len + UIP_ND6_RS_LEN], UIP_ND6_OPT_SLLAO); } UIP_ICMP_BUF->icmpchksum = 0; UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum(); UIP_STAT(++uip_stat.nd6.sent); PRINTF("Sendin RS to"); PRINT6ADDR(&UIP_IP_BUF->destipaddr); PRINTF("from"); PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINTF("\n"); return; }
/*---------------------------------------------------------------------------*/ static u8_t ping6handler(process_event_t ev, process_data_t data) { if(ev == tcpip_icmp6_event) { switch(*((uint8_t *)data)){ case ICMP6_ECHO_REPLY: PRINTF("Echo reply received.\n"); break; default: PRINTF("Other ICMP6 message received.\n"); } return 1; } if(count == 0){ #if MACDEBUG #if NODE #else #error Must define NODE as the node id to ping #endif // Setup destination address. // aaaa::280:e102:0:4874 addr[0] = 0xbbbb; addr[7] = 0x0002; //addr[4] = 0x0280; //addr[5] = 0xe102; //addr[6] = 0x0000; //addr[7] = 0x4874; //addr[4] = 0x0011; //addr[5] = 0x22ff; //addr[6] = 0xfe33; //addr[7] = 0x4401; uip_ip6addr(&dest_addr, addr[0], addr[1],addr[2], addr[3],addr[4],addr[5],addr[6],addr[7]); // Set the command to fool the 'if' below. memcpy(command, (void *)"ping6", 5); #else /* prompt */ printf("> "); /** \note the scanf here is blocking (the all stack is blocked waiting * for user input). This is far from ideal and could be improved */ scanf("%s", command); if(strcmp(command,"ping6") != 0){ PRINTF("> invalid command\n"); return 0; } if(scanf(" %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", &addr[0],&addr[1],&addr[2],&addr[3], &addr[4],&addr[5],&addr[6],&addr[7]) == 8){ uip_ip6addr(&dest_addr, addr[0], addr[1],addr[2], addr[3],addr[4],addr[5],addr[6],addr[7]); } else { PRINTF("> invalid ipv6 address format\n"); return 0; } #endif } if((strcmp(command,"ping6") == 0) && (count < PING6_NB)){ UIP_IP_BUF->vtc = 0x60; UIP_IP_BUF->tcflow = 1; UIP_IP_BUF->flow = 0; UIP_IP_BUF->proto = UIP_PROTO_ICMP6; UIP_IP_BUF->ttl = uip_ds6_if.cur_hop_limit; uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &dest_addr); uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr); UIP_ICMP_BUF->type = ICMP6_ECHO_REQUEST; UIP_ICMP_BUF->icode = 0; /* set identifier and sequence number to 0 */ memset((uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN, 0, 4); /* put one byte of data */ memset((uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN + UIP_ICMP6_ECHO_REQUEST_LEN, count, PING6_DATALEN); uip_len = UIP_ICMPH_LEN + UIP_ICMP6_ECHO_REQUEST_LEN + UIP_IPH_LEN + PING6_DATALEN; UIP_IP_BUF->len[0] = (u8_t)((uip_len - 40) >> 8); UIP_IP_BUF->len[1] = (u8_t)((uip_len - 40) & 0x00FF); UIP_ICMP_BUF->icmpchksum = 0; UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum(); PRINTF("Sending Echo Request to"); PRINT6ADDR(&UIP_IP_BUF->destipaddr); PRINTF("from"); PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINTF("\n"); UIP_STAT(++uip_stat.icmp.sent); tcpip_ipv6_output(); count++; etimer_set(&ping6_periodic_timer, 3 * CLOCK_SECOND); return 1; }
/*---------------------------------------------------------------------------*/ void uip_nd6_ra_output(uip_ipaddr_t * dest) { UIP_IP_BUF->vtc = 0x60; UIP_IP_BUF->tcflow = 0; UIP_IP_BUF->flow = 0; UIP_IP_BUF->proto = UIP_PROTO_ICMP6; UIP_IP_BUF->ttl = UIP_ND6_HOP_LIMIT; if(dest == NULL) { uip_create_linklocal_allnodes_mcast(&UIP_IP_BUF->destipaddr); } else { /* For sollicited RA */ uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, dest); } uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr); UIP_ICMP_BUF->type = ICMP6_RA; UIP_ICMP_BUF->icode = 0; UIP_ND6_RA_BUF->cur_ttl = uip_ds6_if.cur_hop_limit; UIP_ND6_RA_BUF->flags_reserved = (UIP_ND6_M_FLAG << 7) | (UIP_ND6_O_FLAG << 6); UIP_ND6_RA_BUF->router_lifetime = uip_htons(UIP_ND6_ROUTER_LIFETIME); //UIP_ND6_RA_BUF->reachable_time = uip_htonl(uip_ds6_if.reachable_time); //UIP_ND6_RA_BUF->retrans_timer = uip_htonl(uip_ds6_if.retrans_timer); UIP_ND6_RA_BUF->reachable_time = 0; UIP_ND6_RA_BUF->retrans_timer = 0; uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_RA_LEN; nd6_opt_offset = UIP_ND6_RA_LEN; /* Prefix list */ for(prefix = uip_ds6_prefix_list; prefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB; prefix++) { if((prefix->isused) && (prefix->advertise)) { UIP_ND6_OPT_PREFIX_BUF->type = UIP_ND6_OPT_PREFIX_INFO; UIP_ND6_OPT_PREFIX_BUF->len = UIP_ND6_OPT_PREFIX_INFO_LEN / 8; UIP_ND6_OPT_PREFIX_BUF->preflen = prefix->length; UIP_ND6_OPT_PREFIX_BUF->flagsreserved1 = prefix->l_a_reserved; UIP_ND6_OPT_PREFIX_BUF->validlt = uip_htonl(prefix->vlifetime); UIP_ND6_OPT_PREFIX_BUF->preferredlt = uip_htonl(prefix->plifetime); UIP_ND6_OPT_PREFIX_BUF->reserved2 = 0; uip_ipaddr_copy(&(UIP_ND6_OPT_PREFIX_BUF->prefix), &(prefix->ipaddr)); nd6_opt_offset += UIP_ND6_OPT_PREFIX_INFO_LEN; uip_len += UIP_ND6_OPT_PREFIX_INFO_LEN; } } /* Source link-layer option */ create_llao((uint8_t *)UIP_ND6_OPT_HDR_BUF, UIP_ND6_OPT_SLLAO); uip_len += UIP_ND6_OPT_LLAO_LEN; nd6_opt_offset += UIP_ND6_OPT_LLAO_LEN; /* MTU */ UIP_ND6_OPT_MTU_BUF->type = UIP_ND6_OPT_MTU; UIP_ND6_OPT_MTU_BUF->len = UIP_ND6_OPT_MTU_LEN >> 3; UIP_ND6_OPT_MTU_BUF->reserved = 0; //UIP_ND6_OPT_MTU_BUF->mtu = uip_htonl(uip_ds6_if.link_mtu); UIP_ND6_OPT_MTU_BUF->mtu = uip_htonl(1500); uip_len += UIP_ND6_OPT_MTU_LEN; nd6_opt_offset += UIP_ND6_OPT_MTU_LEN; #if UIP_CONF_DS6_ROUTE_INFORMATION for(rtinfo = uip_ds6_route_info_list; rtinfo < uip_ds6_route_info_list + UIP_DS6_ROUTE_INFO_NB; rtinfo++) { if((rtinfo->isused)) { UIP_ND6_OPT_ROUTE_BUF->type = UIP_ND6_OPT_ROUTE_INFO; UIP_ND6_OPT_ROUTE_BUF->len =(rtinfo->length >> 6) + 1 ; UIP_ND6_OPT_ROUTE_BUF->preflen = rtinfo->length; UIP_ND6_OPT_ROUTE_BUF->flagsreserved = rtinfo->flags; UIP_ND6_OPT_ROUTE_BUF->rlifetime = uip_htonl(rtinfo->lifetime); uip_ipaddr_copy(&(UIP_ND6_OPT_ROUTE_BUF->prefix), &(rtinfo->ipaddr)); nd6_opt_offset += ((rtinfo->length >> 6) + 1)<<3; uip_len += ((rtinfo->length >> 6) + 1)<<3; } }
static void ns_input(void) { uint8_t flags; #if CETIC_6LBR_SMARTBRIDGE uip_ds6_route_t * route; #endif uip_ipaddr_t tgtipaddr; PRINTF("Received NS from "); PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINTF(" to "); PRINT6ADDR(&UIP_IP_BUF->destipaddr); PRINTF(" with target address"); PRINT6ADDR((uip_ipaddr_t *) (&UIP_ND6_NS_BUF->tgtipaddr)); PRINTF("\n"); UIP_STAT(++uip_stat.nd6.recv); #if UIP_CONF_IPV6_CHECKS if((UIP_IP_BUF->ttl != UIP_ND6_HOP_LIMIT) || (uip_is_addr_mcast(&UIP_ND6_NS_BUF->tgtipaddr)) || (UIP_ICMP_BUF->icode != 0)) { PRINTF("NS received is bad\n"); goto discard; } #endif /* UIP_CONF_IPV6_CHECKS */ /* Options processing */ nd6_opt_llao = NULL; nd6_opt_offset = UIP_ND6_NS_LEN; while(uip_l3_icmp_hdr_len + nd6_opt_offset < uip_len) { #if UIP_CONF_IPV6_CHECKS if(UIP_ND6_OPT_HDR_BUF->len == 0) { PRINTF("NS received is bad\n"); goto discard; } #endif /* UIP_CONF_IPV6_CHECKS */ switch (UIP_ND6_OPT_HDR_BUF->type) { case UIP_ND6_OPT_SLLAO: nd6_opt_llao = &uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset]; #if UIP_CONF_IPV6_CHECKS /* There must be NO option in a DAD NS */ if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) { PRINTF("NS received is bad\n"); goto discard; } else { #endif /*UIP_CONF_IPV6_CHECKS */ nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr); if(nbr == NULL) { /* Copy link address to a uip_lladdr_t first * to ensure the second argument to uip_ds6_nbr_add is word-aligned */ uip_lladdr_t lladdr; memcpy(&lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], UIP_LLADDR_LEN); uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr, 0, NBR_STALE); } else { uip_lladdr_t *lladdr = (uip_lladdr_t *)uip_ds6_nbr_get_ll(nbr); if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], lladdr, UIP_LLADDR_LEN) != 0) { memcpy(lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], UIP_LLADDR_LEN); nbr->state = NBR_STALE; } else { if(nbr->state == NBR_INCOMPLETE) { nbr->state = NBR_STALE; } } } #if UIP_CONF_IPV6_CHECKS } #endif /*UIP_CONF_IPV6_CHECKS */ break; default: PRINTF("ND option not supported in NS"); break; } nd6_opt_offset += (UIP_ND6_OPT_HDR_BUF->len << 3); } memcpy(&tgtipaddr, &UIP_ND6_NS_BUF->tgtipaddr, sizeof(tgtipaddr)); addr = uip_ds6_addr_lookup(&tgtipaddr); #if CETIC_6LBR_SMARTBRIDGE //ND Proxy implementation if ( addr == NULL ) { if ( (route = uip_ds6_route_lookup(&tgtipaddr)) != NULL ) { if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) { /* DAD CASE */ uip_create_linklocal_allnodes_mcast(&tgtipaddr); uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, &tgtipaddr); flags = UIP_ND6_NA_FLAG_OVERRIDE; goto create_na; } else { uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &UIP_IP_BUF->srcipaddr); uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, &tgtipaddr); flags = UIP_ND6_NA_FLAG_SOLICITED | UIP_ND6_NA_FLAG_OVERRIDE; goto create_na; } } } #endif if(addr != NULL) { #if UIP_ND6_DEF_MAXDADNS > 0 if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) { /* DAD CASE */ #if UIP_CONF_IPV6_CHECKS if(!uip_is_addr_solicited_node(&UIP_IP_BUF->destipaddr)) { PRINTF("NS received is bad\n"); goto discard; } #endif /* UIP_CONF_IPV6_CHECKS */ if(addr->state != ADDR_TENTATIVE) { uip_create_linklocal_allnodes_mcast(&UIP_IP_BUF->destipaddr); uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr); flags = UIP_ND6_NA_FLAG_OVERRIDE; goto create_na; } else { /** \todo if I sent a NS before him, I win */ uip_ds6_dad_failed(addr); goto discard; } #else /* UIP_ND6_DEF_MAXDADNS > 0 */ if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) { /* DAD CASE */ goto discard; #endif /* UIP_ND6_DEF_MAXDADNS > 0 */ } #if UIP_CONF_IPV6_CHECKS if(uip_ds6_is_my_addr(&UIP_IP_BUF->srcipaddr)) { /** * \NOTE do we do something here? we both are using the same address. * If we are doing dad, we could cancel it, though we should receive a * NA in response of DAD NS we sent, hence DAD will fail anyway. If we * were not doing DAD, it means there is a duplicate in the network! */ PRINTF("NS received is bad\n"); goto discard; } #endif /*UIP_CONF_IPV6_CHECKS */ /* Address resolution case */ if(uip_is_addr_solicited_node(&UIP_IP_BUF->destipaddr)) { uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &UIP_IP_BUF->srcipaddr); uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, &tgtipaddr); flags = UIP_ND6_NA_FLAG_SOLICITED | UIP_ND6_NA_FLAG_OVERRIDE; goto create_na; } /* NUD CASE */ if(uip_ds6_addr_lookup(&UIP_IP_BUF->destipaddr) == addr) { uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &UIP_IP_BUF->srcipaddr); uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, &tgtipaddr); flags = UIP_ND6_NA_FLAG_SOLICITED | UIP_ND6_NA_FLAG_OVERRIDE; goto create_na; } else { #if UIP_CONF_IPV6_CHECKS PRINTF("NS received is bad\n"); goto discard; #endif /* UIP_CONF_IPV6_CHECKS */ } } else { goto discard; } create_na: /* If the node is a router it should set R flag in NAs */ #if UIP_CONF_ROUTER flags = flags | UIP_ND6_NA_FLAG_ROUTER; #endif uip_ext_len = 0; UIP_IP_BUF->vtc = 0x60; UIP_IP_BUF->tcflow = 0; UIP_IP_BUF->flow = 0; UIP_IP_BUF->len[0] = 0; /* length will not be more than 255 */ UIP_IP_BUF->len[1] = UIP_ICMPH_LEN + UIP_ND6_NA_LEN + UIP_ND6_OPT_LLAO_LEN; UIP_IP_BUF->proto = UIP_PROTO_ICMP6; UIP_IP_BUF->ttl = UIP_ND6_HOP_LIMIT; UIP_ICMP_BUF->type = ICMP6_NA; UIP_ICMP_BUF->icode = 0; UIP_ND6_NA_BUF->flagsreserved = flags; memcpy(&UIP_ND6_NA_BUF->tgtipaddr, &tgtipaddr, sizeof(uip_ipaddr_t)); create_llao(&uip_buf[uip_l2_l3_icmp_hdr_len + UIP_ND6_NA_LEN], UIP_ND6_OPT_TLLAO); UIP_ICMP_BUF->icmpchksum = 0; UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum(); uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_NA_LEN + UIP_ND6_OPT_LLAO_LEN; UIP_STAT(++uip_stat.nd6.sent); PRINTF("Sending NA to "); PRINT6ADDR(&UIP_IP_BUF->destipaddr); PRINTF(" from "); PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINTF(" with target address "); PRINT6ADDR(&UIP_ND6_NA_BUF->tgtipaddr); PRINTF("\n"); return; discard: uip_clear_buf(); return; } #endif /* UIP_ND6_SEND_NA */ /*------------------------------------------------------------------*/ void uip_nd6_ns_output(uip_ipaddr_t * src, uip_ipaddr_t * dest, uip_ipaddr_t * tgt) { uip_ext_len = 0; UIP_IP_BUF->vtc = 0x60; UIP_IP_BUF->tcflow = 0; UIP_IP_BUF->flow = 0; UIP_IP_BUF->proto = UIP_PROTO_ICMP6; UIP_IP_BUF->ttl = UIP_ND6_HOP_LIMIT; if(dest == NULL) { uip_create_solicited_node(tgt, &UIP_IP_BUF->destipaddr); } else { uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, dest); } UIP_ICMP_BUF->type = ICMP6_NS; UIP_ICMP_BUF->icode = 0; UIP_ND6_NS_BUF->reserved = 0; uip_ipaddr_copy((uip_ipaddr_t *) &UIP_ND6_NS_BUF->tgtipaddr, tgt); UIP_IP_BUF->len[0] = 0; /* length will not be more than 255 */ /* * check if we add a SLLAO option: for DAD, MUST NOT, for NUD, MAY * (here yes), for Address resolution , MUST */ if(!(uip_ds6_is_my_addr(tgt))) { if(src != NULL) { uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, src); } else { uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr); } if (uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) { PRINTF("Dropping NS due to no suitable source address\n"); uip_clear_buf(); return; } UIP_IP_BUF->len[1] = UIP_ICMPH_LEN + UIP_ND6_NS_LEN + UIP_ND6_OPT_LLAO_LEN; create_llao(&uip_buf[uip_l2_l3_icmp_hdr_len + UIP_ND6_NS_LEN], UIP_ND6_OPT_SLLAO); uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_NS_LEN + UIP_ND6_OPT_LLAO_LEN; } else { uip_create_unspecified(&UIP_IP_BUF->srcipaddr); UIP_IP_BUF->len[1] = UIP_ICMPH_LEN + UIP_ND6_NS_LEN; uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_NS_LEN; } UIP_ICMP_BUF->icmpchksum = 0; UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum(); UIP_STAT(++uip_stat.nd6.sent); PRINTF("Sending NS to"); PRINT6ADDR(&UIP_IP_BUF->destipaddr); PRINTF("from"); PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINTF("with target address"); PRINT6ADDR(tgt); PRINTF("\n"); return; }
/*---------------------------------------------------------------------------*/ void uip_nd6_ra_output(uip_ipaddr_t * dest) { UIP_IP_BUF->vtc = 0x60; UIP_IP_BUF->tcflow = 0; UIP_IP_BUF->flow = 0; UIP_IP_BUF->proto = UIP_PROTO_ICMP6; UIP_IP_BUF->ttl = UIP_ND6_HOP_LIMIT; if(dest == NULL) { uip_create_linklocal_allnodes_mcast(&UIP_IP_BUF->destipaddr); } else { /* For sollicited RA */ uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, dest); } uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr); UIP_ICMP_BUF->type = ICMP6_RA; UIP_ICMP_BUF->icode = 0; UIP_ND6_RA_BUF->cur_ttl = uip_ds6_if.cur_hop_limit; UIP_ND6_RA_BUF->flags_reserved = (UIP_ND6_M_FLAG << 7) | (UIP_ND6_O_FLAG << 6); UIP_ND6_RA_BUF->router_lifetime = uip_htons(UIP_ND6_ROUTER_LIFETIME); //UIP_ND6_RA_BUF->reachable_time = uip_htonl(uip_ds6_if.reachable_time); //UIP_ND6_RA_BUF->retrans_timer = uip_htonl(uip_ds6_if.retrans_timer); UIP_ND6_RA_BUF->reachable_time = 0; UIP_ND6_RA_BUF->retrans_timer = 0; uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_RA_LEN; nd6_opt_offset = UIP_ND6_RA_LEN; #if !UIP_CONF_ROUTER /* Prefix list */ for(prefix = uip_ds6_prefix_list; prefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB; prefix++) { if((prefix->isused) && (prefix->advertise)) { UIP_ND6_OPT_PREFIX_BUF->type = UIP_ND6_OPT_PREFIX_INFO; UIP_ND6_OPT_PREFIX_BUF->len = UIP_ND6_OPT_PREFIX_INFO_LEN / 8; UIP_ND6_OPT_PREFIX_BUF->preflen = prefix->length; UIP_ND6_OPT_PREFIX_BUF->flagsreserved1 = prefix->l_a_reserved; UIP_ND6_OPT_PREFIX_BUF->validlt = uip_htonl(prefix->vlifetime); UIP_ND6_OPT_PREFIX_BUF->preferredlt = uip_htonl(prefix->plifetime); UIP_ND6_OPT_PREFIX_BUF->reserved2 = 0; uip_ipaddr_copy(&(UIP_ND6_OPT_PREFIX_BUF->prefix), &(prefix->ipaddr)); nd6_opt_offset += UIP_ND6_OPT_PREFIX_INFO_LEN; uip_len += UIP_ND6_OPT_PREFIX_INFO_LEN; } } #endif /* !UIP_CONF_ROUTER */ /* Source link-layer option */ create_llao((uint8_t *)UIP_ND6_OPT_HDR_BUF, UIP_ND6_OPT_SLLAO); uip_len += UIP_ND6_OPT_LLAO_LEN; nd6_opt_offset += UIP_ND6_OPT_LLAO_LEN; /* MTU */ UIP_ND6_OPT_MTU_BUF->type = UIP_ND6_OPT_MTU; UIP_ND6_OPT_MTU_BUF->len = UIP_ND6_OPT_MTU_LEN >> 3; UIP_ND6_OPT_MTU_BUF->reserved = 0; //UIP_ND6_OPT_MTU_BUF->mtu = uip_htonl(uip_ds6_if.link_mtu); UIP_ND6_OPT_MTU_BUF->mtu = uip_htonl(1500); uip_len += UIP_ND6_OPT_MTU_LEN; nd6_opt_offset += UIP_ND6_OPT_MTU_LEN; UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); /*ICMP checksum */ UIP_ICMP_BUF->icmpchksum = 0; UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum(); UIP_STAT(++uip_stat.nd6.sent); PRINTF("Sending RA to"); PRINT6ADDR(&UIP_IP_BUF->destipaddr); PRINTF("from"); PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINTF("\n"); return; }
/*---------------------------------------------------------------------------*/ static uint8_t ping6handler(process_event_t ev, process_data_t data) { if(count == 0){ #if MACDEBUG // Setup destination address. addr[0] = 0xFE80; addr[4] = 0x6466; addr[5] = 0x6666; addr[6] = 0x6666; addr[7] = 0x6666; uip_ip6addr(&dest_addr, addr[0], addr[1],addr[2], addr[3],addr[4],addr[5],addr[6],addr[7]); // Set the command to fool the 'if' below. memcpy(command, (void *)"ping6", 5); #else /* prompt */ printf("> "); /** \note the scanf here is blocking (the all stack is blocked waiting * for user input). This is far from ideal and could be improved */ // scanf("%s", command); command[0] = 'p'; command[1] = 'i'; command[2] = 'n'; command[3] = 'g'; command[4] = '6'; if(strcmp(command,"ping6") != 0){ PRINTF("> invalid command\n"); return 0; } /* if(scanf(" %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", &addr[0],&addr[1],&addr[2],&addr[3], &addr[4],&addr[5],&addr[6],&addr[7]) == 8){ */ uip_ip6addr(&dest_addr, addr[0], addr[1],addr[2], addr[3],addr[4],addr[5],addr[6],addr[7]); /* } else { PRINTF("> invalid ipv6 address format\n"); return 0; }*/ #endif } if((strcmp(command,"ping6") == 0) && (count < PING6_NB)){ UIP_IP_BUF->vtc = 0x60; UIP_IP_BUF->tcflow = 1; UIP_IP_BUF->flow = 0; UIP_IP_BUF->proto = UIP_PROTO_ICMP6; UIP_IP_BUF->ttl = uip_ds6_if.cur_hop_limit; uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &dest_addr); uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr); UIP_ICMP_BUF->type = ICMP6_ECHO_REQUEST; UIP_ICMP_BUF->icode = 0; /* set identifier and sequence number to 0 */ memset((uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN, 0, 4); /* put one byte of data */ memset((uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN + UIP_ICMP6_ECHO_REQUEST_LEN, count, PING6_DATALEN); uip_len = UIP_ICMPH_LEN + UIP_ICMP6_ECHO_REQUEST_LEN + UIP_IPH_LEN + PING6_DATALEN; UIP_IP_BUF->len[0] = (uint8_t)((uip_len - 40) >> 8); UIP_IP_BUF->len[1] = (uint8_t)((uip_len - 40) & 0x00FF); UIP_ICMP_BUF->icmpchksum = 0; UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum(); PRINTF("Sending Echo Request to"); PRINT6ADDR(&UIP_IP_BUF->destipaddr); PRINTF("from"); PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINTF("\n"); UIP_STAT(++uip_stat.icmp.sent); tcpip_ipv6_output(); count++; etimer_set(&ping6_periodic_timer, 3 * CLOCK_SECOND); return 1; }
void uip_nd6_ns_input(void) { u8_t flags; PRINTF("Received NS from"); PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINTF("to"); PRINT6ADDR(&UIP_IP_BUF->destipaddr); PRINTF("with target address"); PRINT6ADDR((uip_ipaddr_t *) (&UIP_ND6_NS_BUF->tgtipaddr)); PRINTF("\n"); UIP_STAT(++uip_stat.nd6.recv); #if UIP_CONF_IPV6_CHECKS if((UIP_IP_BUF->ttl != UIP_ND6_HOP_LIMIT) || (uip_is_addr_mcast(&UIP_ND6_NS_BUF->tgtipaddr)) || (UIP_ICMP_BUF->icode != 0)) { PRINTF("NS received is bad\n"); goto discard; } #endif /* UIP_CONF_IPV6_CHECKS */ /* Options processing */ nd6_opt_llao = NULL; nd6_opt_offset = UIP_ND6_NS_LEN; while(uip_l3_icmp_hdr_len + nd6_opt_offset < uip_len) { #if UIP_CONF_IPV6_CHECKS if(UIP_ND6_OPT_HDR_BUF->len == 0) { PRINTF("NS received is bad\n"); goto discard; } #endif /* UIP_CONF_IPV6_CHECKS */ switch (UIP_ND6_OPT_HDR_BUF->type) { case UIP_ND6_OPT_SLLAO: nd6_opt_llao = &uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset]; #if UIP_CONF_IPV6_CHECKS /* There must be NO option in a DAD NS */ if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) { PRINTF("NS received is bad\n"); goto discard; } else { #endif /*UIP_CONF_IPV6_CHECKS */ nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr); if(nbr == NULL) { uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, (uip_lladdr_t *)&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], 0, NBR_STALE); } else { if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], &nbr->lladdr, UIP_LLADDR_LEN) != 0) { memcpy(&nbr->lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], UIP_LLADDR_LEN); nbr->state = NBR_STALE; } else { if(nbr->state == NBR_INCOMPLETE) { nbr->state = NBR_STALE; } } } #if UIP_CONF_IPV6_CHECKS } #endif /*UIP_CONF_IPV6_CHECKS */ break; default: PRINTF("ND option not supported in NS"); break; } nd6_opt_offset += (UIP_ND6_OPT_HDR_BUF->len << 3); } addr = uip_ds6_addr_lookup(&UIP_ND6_NS_BUF->tgtipaddr); if(addr != NULL) { if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) { /* DAD CASE */ #if UIP_CONF_IPV6_CHECKS if(!uip_is_addr_solicited_node(&UIP_IP_BUF->destipaddr)) { PRINTF("NS received is bad\n"); goto discard; } #endif /* UIP_CONF_IPV6_CHECKS */ if(addr->state != ADDR_TENTATIVE) { uip_create_linklocal_allnodes_mcast(&UIP_IP_BUF->destipaddr); uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr); flags = UIP_ND6_NA_FLAG_OVERRIDE; goto create_na; } else { /** \todo if I sent a NS before him, I win */ uip_ds6_dad_failed(addr); goto discard; } } #if UIP_CONF_IPV6_CHECKS if(uip_ds6_is_my_addr(&UIP_IP_BUF->srcipaddr)) { /** * \NOTE do we do something here? we both are using the same address. * If we are doing dad, we could cancel it, though we should receive a * NA in response of DAD NS we sent, hence DAD will fail anyway. If we * were not doing DAD, it means there is a duplicate in the network! */ PRINTF("NS received is bad\n"); goto discard; } #endif /*UIP_CONF_IPV6_CHECKS */ /* Address resolution case */ if(uip_is_addr_solicited_node(&UIP_IP_BUF->destipaddr)) { uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &UIP_IP_BUF->srcipaddr); uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, &UIP_ND6_NS_BUF->tgtipaddr); flags = UIP_ND6_NA_FLAG_SOLICITED | UIP_ND6_NA_FLAG_OVERRIDE; goto create_na; } /* NUD CASE */ if(uip_ds6_addr_lookup(&UIP_IP_BUF->destipaddr) == addr) { uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &UIP_IP_BUF->srcipaddr); uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, &UIP_ND6_NS_BUF->tgtipaddr); flags = UIP_ND6_NA_FLAG_SOLICITED | UIP_ND6_NA_FLAG_OVERRIDE; goto create_na; } else { #if UIP_CONF_IPV6_CHECKS PRINTF("NS received is bad\n"); goto discard; #endif /* UIP_CONF_IPV6_CHECKS */ } } else { goto discard; } create_na: uip_ext_len = 0; UIP_IP_BUF->vtc = 0x60; UIP_IP_BUF->tcflow = 0; UIP_IP_BUF->flow = 0; UIP_IP_BUF->len[0] = 0; /* length will not be more than 255 */ UIP_IP_BUF->len[1] = UIP_ICMPH_LEN + UIP_ND6_NA_LEN + UIP_ND6_OPT_LLAO_LEN; UIP_IP_BUF->proto = UIP_PROTO_ICMP6; UIP_IP_BUF->ttl = UIP_ND6_HOP_LIMIT; UIP_ICMP_BUF->type = ICMP6_NA; UIP_ICMP_BUF->icode = 0; UIP_ND6_NA_BUF->flagsreserved = flags; memcpy(&UIP_ND6_NA_BUF->tgtipaddr, &addr->ipaddr, sizeof(uip_ipaddr_t)); create_llao(&uip_buf[uip_l2_l3_icmp_hdr_len + UIP_ND6_NA_LEN], UIP_ND6_OPT_TLLAO); UIP_ICMP_BUF->icmpchksum = 0; UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum(); uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_NA_LEN + UIP_ND6_OPT_LLAO_LEN; UIP_STAT(++uip_stat.nd6.sent); PRINTF("Sending NA to"); PRINT6ADDR(&UIP_IP_BUF->destipaddr); PRINTF("from"); PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINTF("with target address"); PRINT6ADDR(&UIP_ND6_NA_BUF->tgtipaddr); PRINTF("\n"); return; discard: uip_len = 0; return; }