/* Sends a ping packet out the radio */ static 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, 0xaaaa, 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_ipaddr_copy(&UIP_IP_BUF->destipaddr, &ping_addr); uip_netif_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] = (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(); }
/*------------------------------------------------------------------*/ void uip_nd6_io_ns_output(uip_ipaddr_t *src, uip_ipaddr_t *dest, uip_ipaddr_t *tgt) { /* IP header fields */ 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; /* * The caller must put a valid tgt address. * For dest, if the caller is doing DAD or Address resolution, he sets * dest to NULL and we forge dest as the sollicited node mcast address * for tgt. * If the caller is sending the NS for NUD, dest is unicast and the caller * specifies it in the arguments */ 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; /* Copy the tgt address */ 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 * i.e. if and only if tgt is our address (in this case it is DAD), we do * not add it */ if(!(uip_netif_is_addr_my_unicast(tgt))) { if(src != NULL) { uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, src); } else { uip_netif_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; uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_NS_LEN + UIP_ND6_OPT_LLAO_LEN; nd6_opt_llao = (struct uip_nd6_opt_llao *)&uip_buf[uip_l2_l3_icmp_hdr_len + UIP_ND6_NS_LEN]; nd6_opt_llao->type = UIP_ND6_OPT_SLLAO; /* type of the option */ /* * length of the option: 2 bytes for type, length, plus the length of * the L2 address. It must be in units of 8 bytes */ nd6_opt_llao->len = UIP_ND6_OPT_LLAO_LEN >> 3; memcpy(&nd6_opt_llao->addr, &uip_lladdr, UIP_LLADDR_LEN); /* padding if needed */ memset((void *)(&nd6_opt_llao->addr) + UIP_LLADDR_LEN, 0, UIP_ND6_OPT_LLAO_LEN - 2 - UIP_LLADDR_LEN); } else {
/* Sends a ping packet out the radio */ static void raven_ping6(void) { /* ping the router */ // Setup destination address. struct uip_nd6_defrouter *defrouter; uint8_t i,tmp; defrouter = uip_nd6_choose_defrouter(); /* Get address from defrouter struct */ memcpy(addr, defrouter->nb->ipaddr.u8, 16); /* Swap the bytes in the address array */ for (i=0;i<8;i++) { tmp = addr[i] & 0xff; addr[i] >>= 8; addr[i] |= tmp << 8; } uip_ip6addr(&dest_addr, addr[0], addr[1],addr[2], addr[3],addr[4],addr[5],addr[6],addr[7]); 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_ipaddr_copy(&UIP_IP_BUF->destipaddr, &dest_addr); uip_netif_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] = (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(); }
void uip_icmp6_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_netif_physical_if[interface_number].cur_hop_limit; if(uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)){ uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &UIP_IP_BUF->srcipaddr); uip_netif_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 there were extension headers*/ 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 */ #ifdef RB memmove(((void *)UIP_ICMP_BUF + (void *)( UIP_ICMPH_LEN - uip_ext_len)), (((void *)UIP_ICMP_BUF) +( (void *)UIP_ICMPH_LEN)), ((uip_len - UIP_IPH_LEN) - UIP_ICMPH_LEN)); #endif memmove(((void *) (UIP_ICMP_BUF + (( UIP_ICMPH_LEN - uip_ext_len)))), ((void *) (UIP_ICMP_BUF + (UIP_ICMPH_LEN))), ((uip_len - UIP_IPH_LEN) - UIP_ICMPH_LEN)); }
/*------------------------------------------------------------------*/ void uip_nd6_io_ns_input(void) { 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); u8_t flags; #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)) { goto badpkt; } #endif /* UIP_CONF_IPV6_CHECKS */ /* Options reading: we handle only SLLAO for now */ 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) { goto badpkt; } #endif /* UIP_CONF_IPV6_CHECKS */ switch(UIP_ND6_OPT_HDR_BUF->type) { case UIP_ND6_OPT_SLLAO: nd6_opt_llao = (struct uip_nd6_opt_llao *)UIP_ND6_OPT_HDR_BUF; break; default: UIP_LOG("ND option not supported in NS"); break; } nd6_opt_offset += (UIP_ND6_OPT_HDR_BUF->len << 3); } /* Options processing: only SLLAO */ if(nd6_opt_llao != NULL) { #if UIP_CONF_IPV6_CHECKS /* There must be NO option in a DAD NS */ if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) { goto badpkt; } else { #endif /*UIP_CONF_IPV6_CHECKS*/ neighbor = uip_nd6_nbrcache_lookup(&UIP_IP_BUF->srcipaddr); if(neighbor == NULL) { /* we need to add the neighbor*/ uip_nd6_nbrcache_add(&UIP_IP_BUF->srcipaddr, &nd6_opt_llao->addr, 0, STALE); } else { /* If LL address changed, set neighbor state to stale */ if(memcmp(&nd6_opt_llao->addr, &neighbor->lladdr, UIP_LLADDR_LEN) != 0) { memcpy(&neighbor->lladdr, &nd6_opt_llao->addr, UIP_LLADDR_LEN); neighbor->state = STALE; } else { /* If neighbor state is INCOMPLETE, set to STALE */ if(neighbor->state == INCOMPLETE) { neighbor->state = STALE; } } } #if UIP_CONF_IPV6_CHECKS } #endif /*UIP_CONF_IPV6_CHECKS*/ } /* * Rest of NS processing: Depends on the purpose of the NS: NUD or DAD or * Address Resolution */ /** \note we use ifaddr to remember the target address */ ifaddr = uip_netif_addr_lookup(&UIP_ND6_NS_BUF->tgtipaddr, 128, 0); if(ifaddr != NULL) { if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)){ /* DAD CASE */ #if UIP_CONF_IPV6_CHECKS /* Dst address must be solicited node mcast address */ if(!uip_netif_is_addr_my_solicited(&UIP_IP_BUF->destipaddr)){ goto badpkt; } #endif /* UIP_CONF_IPV6_CHECKS */ /* * If my address is not tentative, then send a NA to all nodes with * TLLAO flags are: override = yes. */ if(ifaddr->state!=TENTATIVE) { /* * we need to send a NA, we set the src, dest, flags. tgt remains the * same and the rest is done at "create_na" */ uip_create_linklocal_allnodes_mcast(&UIP_IP_BUF->destipaddr); uip_netif_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_netif_dad_failed(&UIP_ND6_NS_BUF->tgtipaddr); goto discard; } } #if UIP_CONF_IPV6_CHECKS /* Duplicate check */ if(uip_netif_is_addr_my_unicast(&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! */ goto badpkt; } #endif /*UIP_CONF_IPV6_CHECKS*/ /* Address resolution case */ if(uip_netif_is_addr_my_solicited(&UIP_IP_BUF->destipaddr)){ /* * we need to send a NA, we set the src, dest, flags. The rest is * set at the "create_na" label. */ 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. at this point the packet must be for us! we check this, * and at the same time if target == dest */ if(uip_netif_addr_lookup(&UIP_IP_BUF->destipaddr, 128, 0) == ifaddr){ /* * we need to send a NA, we set the src, dest, flags. The rest is set * at the "create_na" label. */ 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 goto badpkt; #endif /* UIP_CONF_IPV6_CHECKS */ } } else { goto discard; } create_na: /* * Fill the part of the NA which is common to all NAs. If the NS contained * extension headers, we must set the target address properly */ uip_ext_len = 0; /* IP header */ 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; /* ICMP header */ UIP_ICMP_BUF->type = ICMP6_NA; UIP_ICMP_BUF->icode = 0; /* NA static part */ UIP_ND6_NA_BUF->flagsreserved = flags; memcpy(&UIP_ND6_NA_BUF->tgtipaddr, &ifaddr->ipaddr, sizeof(uip_ipaddr_t)); /* NA option: TLLAO. note that length field is in unit of 8 bytes */ uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_NA_LEN + UIP_ND6_OPT_LLAO_LEN; nd6_opt_llao = (struct uip_nd6_opt_llao *)&uip_buf[uip_l2_l3_icmp_hdr_len + UIP_ND6_NA_LEN]; nd6_opt_llao->type = UIP_ND6_OPT_TLLAO; nd6_opt_llao->len = UIP_ND6_OPT_LLAO_LEN >> 3; memcpy(&(nd6_opt_llao->addr), &uip_lladdr, UIP_LLADDR_LEN); /* padding if needed */ memset((void *)(&nd6_opt_llao->addr) + UIP_LLADDR_LEN, 0, UIP_ND6_OPT_LLAO_LEN - 2 - UIP_LLADDR_LEN); /*ICMP checksum*/ UIP_ICMP_BUF->icmpchksum = 0; UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum(); 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; #if UIP_CONF_IPV6_CHECKS badpkt: UIP_STAT(++uip_stat.nd6.drop); UIP_LOG("NS received is bad"); #endif /* UIP_CONF_IPV6_CHECKS */ discard: uip_len = 0; return; }
/*---------------------------------------------------------------------------*/ static u8_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); 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_netif_physical_if.cur_hop_limit; uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &dest_addr); uip_netif_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] = (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; }