/*---------------------------------------------------------------------------*/ void ip64_dhcpc_configured(const struct ip64_dhcpc_state *s) { uip_ip6addr_t ip6dnsaddr; PRINTF("DHCP Configured with %d.%d.%d.%d\n", s->ipaddr.u8[0], s->ipaddr.u8[1], s->ipaddr.u8[2], s->ipaddr.u8[3]); ip64_set_hostaddr((uip_ip4addr_t *)&s->ipaddr); ip64_set_netmask((uip_ip4addr_t *)&s->netmask); ip64_set_draddr((uip_ip4addr_t *)&s->default_router); if(!uip_ip4addr_cmp((uip_ip4addr_t *)&s->dnsaddr, &uip_all_zeroes_addr)) { //Note: Currently we assume only one DNS server uip_ipaddr_t * dns = uip_nameserver_get(0); //Only update DNS entry if it is empty or already IPv4 if(uip_is_addr_unspecified(dns) || ip64_addr_is_ip64(dns)) { ip64_addr_4to6((uip_ip4addr_t *)&s->dnsaddr, &ip6dnsaddr); uip_nameserver_update(&ip6dnsaddr, uip_ntohs(s->lease_time[0])*65536ul + uip_ntohs(s->lease_time[1])); } } #if CETIC_6LBR cetic_6lbr_ip64_dhcpc_configured(s); #endif }
void tcpip_ipv6_output(void) { uip_ds6_nbr_t *nbr = NULL; uip_ipaddr_t *nexthop; uip_ds6_route_t *route = NULL; if(uip_len == 0) { return; } PRINTF("IPv6 packet send from "); PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINTF(" to "); PRINT6ADDR(&UIP_IP_BUF->destipaddr); PRINTF("\n"); if(uip_len > UIP_LINK_MTU) { UIP_LOG("tcpip_ipv6_output: Packet to big"); uip_clear_buf(); return; } if(uip_is_addr_unspecified(&UIP_IP_BUF->destipaddr)){ UIP_LOG("tcpip_ipv6_output: Destination address unspecified"); uip_clear_buf(); return; } if(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) { /* Next hop determination */ nbr = NULL; /* We first check if the destination address is on our immediate link. If so, we simply use the destination address as our nexthop address. */ if(uip_ds6_is_addr_onlink(&UIP_IP_BUF->destipaddr)){ nexthop = &UIP_IP_BUF->destipaddr; } else { /* Check if we have a route to the destination address. */ route = uip_ds6_route_lookup(&UIP_IP_BUF->destipaddr); /* No route was found - we send to the default route instead. */ if(route == NULL) { #if CETIC_6LBR_SMARTBRIDGE if (uip_ipaddr_prefixcmp(&wsn_net_prefix, &UIP_IP_BUF->destipaddr, 64)) { /* In smart-bridge mode, there is no route towards hosts on the Ethernet side Therefore we have to check the destination and assume the host is on-link */ nexthop = &UIP_IP_BUF->destipaddr; } else #endif #if CETIC_6LBR_ROUTER && UIP_CONF_IPV6_RPL if (is_dodag_root() && uip_ipaddr_prefixcmp(&wsn_net_prefix, &UIP_IP_BUF->destipaddr, 64)) { //In router mode, we drop packets towards unknown mote PRINTF("Dropping wsn packet with no route\n"); uip_len = 0; return; } else #endif #if CETIC_6LBR_IP64 if(ip64_addr_is_ip64(&UIP_IP_BUF->destipaddr)) { #if UIP_CONF_IPV6_RPL rpl_remove_header(); #endif IP64_CONF_UIP_FALLBACK_INTERFACE.output(); uip_len = 0; uip_ext_len = 0; return; } else #endif { PRINTF("tcpip_ipv6_output: no route found, using default route\n"); nexthop = uip_ds6_defrt_choose(); } if(nexthop == NULL) { #ifdef UIP_FALLBACK_INTERFACE PRINTF("FALLBACK: removing ext hdrs & setting proto %d %d\n", uip_ext_len, *((uint8_t *)UIP_IP_BUF + 40)); if(uip_ext_len > 0) { extern void remove_ext_hdr(void); uint8_t proto = *((uint8_t *)UIP_IP_BUF + 40); remove_ext_hdr(); /* This should be copied from the ext header... */ UIP_IP_BUF->proto = proto; } UIP_FALLBACK_INTERFACE.output(); #else PRINTF("tcpip_ipv6_output: Destination off-link but no route\n"); #endif /* !UIP_FALLBACK_INTERFACE */ uip_clear_buf(); return; } } else { /* A route was found, so we look up the nexthop neighbor for the route. */ nexthop = uip_ds6_route_nexthop(route); /* If the nexthop is dead, for example because the neighbor never responded to link-layer acks, we drop its route. */ if(nexthop == NULL) { #if UIP_CONF_IPV6_RPL /* If we are running RPL, and if we are the root of the network, we'll trigger a DIO before we remove the route. */ rpl_dag_t *dag; dag = (rpl_dag_t *)route->state.dag; if(dag != NULL) { rpl_reset_dio_timer(dag->instance); } #endif /* UIP_CONF_IPV6_RPL */ uip_ds6_route_rm(route); /* We don't have a nexthop to send the packet to, so we drop it. */ return; } } #if TCPIP_CONF_ANNOTATE_TRANSMISSIONS if(nexthop != NULL) { static uint8_t annotate_last; static uint8_t annotate_has_last = 0; if(annotate_has_last) { printf("#L %u 0; red\n", annotate_last); } printf("#L %u 1; red\n", nexthop->u8[sizeof(uip_ipaddr_t) - 1]); annotate_last = nexthop->u8[sizeof(uip_ipaddr_t) - 1]; annotate_has_last = 1; } #endif /* TCPIP_CONF_ANNOTATE_TRANSMISSIONS */ } /* End of next hop determination */ #if UIP_CONF_IPV6_RPL if(rpl_update_header_final(nexthop)) { uip_clear_buf(); return; } #endif /* UIP_CONF_IPV6_RPL */ nbr = uip_ds6_nbr_lookup(nexthop); if(nbr == NULL) { #if UIP_ND6_SEND_NA #if CETIC_6LBR && UIP_CONF_IPV6_RPL /* Don't perform NUD if it has been disabled for WSN */ if((nvm_data.global_flags & CETIC_GLOBAL_DISABLE_WSN_NUD) != 0 && uip_ipaddr_prefixcmp(&wsn_net_prefix, &UIP_IP_BUF->destipaddr, 64) && route != NULL) { uip_clear_buf(); return; } #endif if((nbr = uip_ds6_nbr_add(nexthop, NULL, 0, NBR_INCOMPLETE)) == NULL) { uip_clear_buf(); return; } else { #if UIP_CONF_IPV6_QUEUE_PKT /* Copy outgoing pkt in the queuing buffer for later transmit. */ if(uip_packetqueue_alloc(&nbr->packethandle, UIP_DS6_NBR_PACKET_LIFETIME) != NULL) { memcpy(uip_packetqueue_buf(&nbr->packethandle), UIP_IP_BUF, uip_len); uip_packetqueue_set_buflen(&nbr->packethandle, uip_len); } #endif /* RFC4861, 7.2.2: * "If the source address of the packet prompting the solicitation is the * same as one of the addresses assigned to the outgoing interface, that * address SHOULD be placed in the IP Source Address of the outgoing * solicitation. Otherwise, any one of the addresses assigned to the * interface should be used."*/ if(uip_ds6_is_my_addr(&UIP_IP_BUF->srcipaddr)){ uip_nd6_ns_output(&UIP_IP_BUF->srcipaddr, NULL, &nbr->ipaddr); } else { uip_nd6_ns_output(NULL, NULL, &nbr->ipaddr); } stimer_set(&nbr->sendns, uip_ds6_if.retrans_timer / 1000); nbr->nscount = 1; /* Send the first NS try from here (multicast destination IP address). */ } #else /* UIP_ND6_SEND_NA */ uip_len = 0; return; #endif /* UIP_ND6_SEND_NA */ } else { #if UIP_ND6_SEND_NA if(nbr->state == NBR_INCOMPLETE) { PRINTF("tcpip_ipv6_output: nbr cache entry incomplete\n"); #if UIP_CONF_IPV6_QUEUE_PKT /* Copy outgoing pkt in the queuing buffer for later transmit and set the destination nbr to nbr. */ if(uip_packetqueue_alloc(&nbr->packethandle, UIP_DS6_NBR_PACKET_LIFETIME) != NULL) { memcpy(uip_packetqueue_buf(&nbr->packethandle), UIP_IP_BUF, uip_len); uip_packetqueue_set_buflen(&nbr->packethandle, uip_len); } #endif /*UIP_CONF_IPV6_QUEUE_PKT*/ uip_clear_buf(); return; } /* Send in parallel if we are running NUD (nbc state is either STALE, DELAY, or PROBE). See RFC 4861, section 7.3.3 on node behavior. */ #if CETIC_6LBR && UIP_CONF_IPV6_RPL /* Don't update nbr state if we don't want to perform NUD for WSN */ if((nvm_data.global_flags & CETIC_GLOBAL_DISABLE_WSN_NUD) == 0 || !uip_ipaddr_prefixcmp(&wsn_net_prefix, &UIP_IP_BUF->destipaddr, 64) || route == NULL) #endif if(nbr->state == NBR_STALE) { nbr->state = NBR_DELAY; stimer_set(&nbr->reachable, UIP_ND6_DELAY_FIRST_PROBE_TIME); nbr->nscount = 0; PRINTF("tcpip_ipv6_output: nbr cache entry stale moving to delay\n"); } #endif /* UIP_ND6_SEND_NA */ tcpip_output(uip_ds6_nbr_get_ll(nbr)); #if UIP_CONF_IPV6_QUEUE_PKT /* * Send the queued packets from here, may not be 100% perfect though. * This happens in a few cases, for example when instead of receiving a * NA after sendiong a NS, you receive a NS with SLLAO: the entry moves * to STALE, and you must both send a NA and the queued packet. */ if(uip_packetqueue_buflen(&nbr->packethandle) != 0) { uip_len = uip_packetqueue_buflen(&nbr->packethandle); memcpy(UIP_IP_BUF, uip_packetqueue_buf(&nbr->packethandle), uip_len); uip_packetqueue_free(&nbr->packethandle); tcpip_output(uip_ds6_nbr_get_ll(nbr)); } #endif /*UIP_CONF_IPV6_QUEUE_PKT*/ uip_clear_buf(); return; } } /* Multicast IP destination address. */ tcpip_output(NULL); uip_clear_buf(); }
static PT_THREAD(generate_sensors_info(struct httpd_state *s)) { static int i; PSOCK_BEGIN(&s->sout); add("<br /><h2>Sensors list</h2>"); add ("<table>" "<theader><tr class=\"row_first\"><td>Node</td><td>Type</td><td>Web</td><td>Coap</td><td>Parent</td><td>Up PRR</td><td>Down PRR</td><td>Last seen</td><td>Status</td></tr></theader>" "<tbody>"); SEND_STRING(&s->sout, buf); reset_buf(); for(i = 0; i < UIP_DS6_ROUTE_NB; i++) { if(node_info_table[i].isused) { add("<tr><td>"); add("<a href=\"sensor?ip="); ipaddr_add(&node_info_table[i].ipaddr); #if CETIC_NODE_CONFIG_HAS_NAME if ( node_config_loaded ) { add("\">%s (", node_config_get_name(node_config_find_by_ip(&node_info_table[i].ipaddr))); ipaddr_add(&node_info_table[i].ipaddr); add(")</a></td>"); } else #endif { add("\">"); ipaddr_add(&node_info_table[i].ipaddr); add("</a></td>"); } if(0) { } else if(node_info_table[i].ipaddr.u8[8] == 0x02 && node_info_table[i].ipaddr.u8[9] == 0x12 && (node_info_table[i].ipaddr.u8[10] == 0x74 || node_info_table[i].ipaddr.u8[10] == 0x75)) { add("<td>Moteiv Telos</td>"); } else if(node_info_table[i].ipaddr.u8[8] == 0x02 && node_info_table[i].ipaddr.u8[9] == 0x1A && node_info_table[i].ipaddr.u8[10] == 0x4C) { add("<td>Crossbow Sky</td>"); } else if(node_info_table[i].ipaddr.u8[8] == 0xC3 && node_info_table[i].ipaddr.u8[9] == 0x0C && node_info_table[i].ipaddr.u8[10] == 0x00) { add("<td>Zolertia Z1</td>"); } else if(node_info_table[i].ipaddr.u8[8] == 0x02 && node_info_table[i].ipaddr.u8[9] == 0x80 && node_info_table[i].ipaddr.u8[10] == 0xE1) { add("<td>STMicro</td>"); } else if(node_info_table[i].ipaddr.u8[8] == 0x02 && node_info_table[i].ipaddr.u8[9] == 0x12 && node_info_table[i].ipaddr.u8[10] == 0x4B) { add("<td>TI</td>"); } else if(node_info_table[i].ipaddr.u8[8] == 0x02 && node_info_table[i].ipaddr.u8[9] == 0x50 && node_info_table[i].ipaddr.u8[10] == 0xC2 && node_info_table[i].ipaddr.u8[11] == 0xA8 && (node_info_table[i].ipaddr.u8[12] & 0XF0) == 0xC0) { add("<td>Redwire Econotag I</td>"); } else if(node_info_table[i].ipaddr.u8[8] == 0x02 && node_info_table[i].ipaddr.u8[9] == 0x05 && node_info_table[i].ipaddr.u8[10] == 0x0C && node_info_table[i].ipaddr.u8[11] == 0x2A && node_info_table[i].ipaddr.u8[12] == 0x8C) { add("<td>Redwire Econotag I</td>"); } else if(node_info_table[i].ipaddr.u8[8] == 0xEE && node_info_table[i].ipaddr.u8[9] == 0x47 && node_info_table[i].ipaddr.u8[10] == 0x3C) { if(node_info_table[i].ipaddr.u8[11] == 0x4D && node_info_table[i].ipaddr.u8[12] == 0x12) { add("<td>Redwire M12</td>"); } else { add("<td>Redwire Unknown</td>"); } } else if((node_info_table[i].ipaddr.u8[8] & 0x02) == 0) { add("<td>User defined</td>"); } else { add("<td>Unknown</td>"); } SEND_STRING(&s->sout, buf); reset_buf(); #if CETIC_6LBR_IP64 && CETIC_NODE_CONFIG if(ip64_addr_is_ip64(&UIP_IP_BUF->srcipaddr)) { node_config_t * config = node_config_find_by_ip(&node_info_table[i].ipaddr); if(config && (nvm_data.eth_ip64_flags & CETIC_6LBR_IP64_SPECIAL_PORTS) != 0) { add("<td><a href=\"http://"); ip4addr_add(ip64_get_hostaddr()); add(":%d/\">web</a></td>", config->http_port); add("<td><a href=\"coap://"); ip4addr_add(ip64_get_hostaddr()); add(":%d/\">coap</a></td>", config->coap_port); } else { add("<td></td><td></td>"); } } else #endif { add("<td><a href=\"http://["); ipaddr_add(&node_info_table[i].ipaddr); add("]/\">web</a></td>"); add("<td><a href=\"coap://["); ipaddr_add(&node_info_table[i].ipaddr); add("]:5683/\">coap</a></td>"); } if(node_info_table[i].messages_received > 0) { add("<td>"); if((node_info_table[i].flags & NODE_INFO_PARENT_VALID) != 0) { #if CETIC_NODE_CONFIG_HAS_NAME if (node_config_loaded) { add("%s (", node_config_get_name(node_config_find_by_ip(&node_info_table[i].ip_parent))); ipaddr_add(&node_info_table[i].ip_parent); add(")"); } else { ipaddr_add(&node_info_table[i].ip_parent); } #else ipaddr_add(&node_info_table[i].ip_parent); #endif } add("</td>"); if((node_info_table[i].flags & NODE_INFO_UPSTREAM_VALID) != 0) { add("<td>%.1f%%</td>", 100.0 * (node_info_table[i].messages_sent - node_info_table[i].up_messages_lost)/node_info_table[i].messages_sent); } else { add("<td></td>"); } if((node_info_table[i].flags & NODE_INFO_DOWNSTREAM_VALID) != 0) { add("<td>%.1f%%</td>", 100.0 * (node_info_table[i].messages_sent - node_info_table[i].down_messages_lost)/node_info_table[i].messages_sent); } else { add("<td></td>"); } } else { add("<td></td><td></td><td></td>"); } add("<td>%d</td>", (clock_time() - node_info_table[i].last_seen) / CLOCK_SECOND); add("<td>%s</td>", node_info_flags_text(node_info_table[i].flags)); add("</tr>"); SEND_STRING(&s->sout, buf); reset_buf(); } } add("</tbody></table><br />"); add("<br /><h2>Actions</h2>"); add("<form action=\"reset-stats-all\" method=\"get\">"); add("<input type=\"submit\" value=\"Reset all statistics\"/></form><br />"); SEND_STRING(&s->sout, buf); reset_buf(); PSOCK_END(&s->sout); }