/*---------------------------------------------------------------------------*/ void uip_ds6_route_rm(uip_ds6_route_t *route) { #if DEBUG != DEBUG_NONE assert_nbr_routes_list_sane(); #endif /* DEBUG != DEBUG_NONE */ if(route != NULL && route->routes != NULL) { PRINTF("uip_ds6_route_rm: removing route: "); PRINT6ADDR(&route->ipaddr); PRINTF("\n"); list_remove(route->routes->route_list, route); if(list_head(route->routes->route_list) == NULL) { /* If this was the only route using this neighbor, remove the neibhor from the table */ PRINTF("uip_ds6_route_rm: removing neighbor too\n"); nbr_table_remove(nbr_routes, route->routes->route_list); } memb_free(&routememb, route); num_routes--; PRINTF("uip_ds6_route_rm num %d\n", num_routes); #if UIP_DS6_NOTIFICATIONS call_route_callback(UIP_DS6_NOTIFICATION_ROUTE_RM, &route->ipaddr, uip_ds6_route_nexthop(route)); #endif #if 0 //(DEBUG & DEBUG_ANNOTATE) == DEBUG_ANNOTATE /* we need to check if this was the last route towards "nexthop" */ /* if so - remove that link (annotation) */ uip_ds6_route_t *r; for(r = uip_ds6_route_head(); r != NULL; r = uip_ds6_route_next(r)) { uip_ipaddr_t *nextr, *nextroute; nextr = uip_ds6_route_nexthop(r); nextroute = uip_ds6_route_nexthop(route); if(nextr != NULL && nextroute != NULL && uip_ipaddr_cmp(nextr, nextroute)) { /* we found another link using the specific nexthop, so keep the #L */ return; } } ANNOTATE("#L %u 0\n", uip_ds6_route_nexthop(route)->u8[sizeof(uip_ipaddr_t) - 1]); #endif } #if DEBUG != DEBUG_NONE assert_nbr_routes_list_sane(); #endif /* DEBUG != DEBUG_NONE */ return; }
/*---------------------------------------------------------------------------*/ uip_ds6_route_t * uip_ds6_route_lookup(uip_ipaddr_t *addr) { uip_ds6_route_t *r; uip_ds6_route_t *found_route; uint8_t longestmatch; //ADILA EDIT 10/11/14 //uint8_t found_route_ch; //------------------- PRINTF("uip-ds6-route: Looking up route for "); PRINT6ADDR(addr); PRINTF("\n"); found_route = NULL; longestmatch = 0; for(r = uip_ds6_route_head(); r != NULL; r = uip_ds6_route_next(r)) { if(r->length >= longestmatch && uip_ipaddr_prefixcmp(addr, &r->ipaddr, r->length)) { longestmatch = r->length; found_route = r; //ADILA EDIT 10/11/14 //found_route_ch = r->nbrCh; //------------------- } } if(found_route != NULL) { PRINTF("uip-ds6-route: Found route: "); PRINT6ADDR(addr); PRINTF(" via "); PRINT6ADDR(uip_ds6_route_nexthop(found_route)); PRINTF("\n"); //ADILA EDIT 10/11/14 /* printf("uip-ds6-route: Found route: "); uip_debug_ipaddr_print(addr); printf(" via "); uip_debug_ipaddr_print(uip_ds6_route_nexthop(found_route)); printf("\n"); */ //printf("FOUND ROUTE CHANGE TO NEXTHOP CHANNEL %d\n\n", found_route_ch); /*printf("Found route change to nexthop channel %d ", found_route_ch); uip_debug_ipaddr_print(uip_ds6_route_nexthop(found_route)); printf("\n");*/ //PRINTF("FOUND ROUTE CHANGE TO NEXTHOP CHANNEL %d\n\n", found_route_ch); //@ //cc2420_set_channel(found_route_ch); //------------------- } else { PRINTF("uip-ds6-route: No route found\n"); } return found_route; }
/*---------------------------------------------------------------------------*/ static unsigned short make_routes(void *p) { static const char httpd_cgi_rtes1[] HTTPD_STRING_ATTR = "(%u (via "; static const char httpd_cgi_rtes2[] HTTPD_STRING_ATTR = ") %lus<br>"; static const char httpd_cgi_rtes3[] HTTPD_STRING_ATTR = ")<br>"; uint8_t i,j=0; uint16_t numprinted; uip_ds6_route_t *r; numprinted = httpd_snprintf((char *)uip_appdata, uip_mss(),httpd_cgi_addrh); for(r = uip_ds6_route_head(); r != NULL; r = uip_ds6_route_next(r)) { j++; numprinted += httpd_cgi_sprint_ip6(r->ipaddr, uip_appdata + numprinted); numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_rtes1, r->length); numprinted += httpd_cgi_sprint_ip6(uip_ds6_route_nexthop(r), uip_appdata + numprinted); if(r->state.lifetime < 3600) { numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_rtes2, r->state.lifetime); } else { numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_rtes3); } } if (j==0) numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_addrn); numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_addrf,UIP_DS6_ROUTE_NB-j); return numprinted; }
uint16_t create_route_msg(char *buf, uip_ds6_route_t *r) { uint8_t n = 0; n += sprintf(&(buf[n]), "{\"dest\":\""); n += ipaddr_add(&r->ipaddr, &(buf[n])); n += sprintf(&(buf[n]), "\",\"next\":\""); n += ipaddr_add(uip_ds6_route_nexthop(r), &(buf[n])); n += sprintf(&(buf[n]), "\"}"); buf[n] = 0; PRINTF("buf: %s\n", buf); return n; }
uip_ds6_route_t * uip_ds6_route_lookup_by_nexthop(uip_ipaddr_t *ipaddr) { uip_ds6_route_t *r; for(r = uip_ds6_route_head(); r != NULL; r = uip_ds6_route_next(r)) { if(uip_ipaddr_cmp(uip_ds6_route_nexthop(r), ipaddr)) { return r; } } return NULL; }
/*---------------------------------------------------------------------------*/ uip_ds6_route_t * uip_ds6_route_lookup(uip_ipaddr_t *addr) { uip_ds6_route_t *r; uip_ds6_route_t *found_route; uint8_t longestmatch; PRINTF("uip-ds6-route: Looking up route for "); PRINT6ADDR(addr); PRINTF("\n"); found_route = NULL; longestmatch = 0; for(r = uip_ds6_route_head(); r != NULL; r = uip_ds6_route_next(r)) { if(r->length >= longestmatch && uip_ipaddr_prefixcmp(addr, &r->ipaddr, r->length)) { longestmatch = r->length; found_route = r; /* check if total match - e.g. all 128 bits do match */ if(longestmatch == 128) { break; } } } if(found_route != NULL) { PRINTF("uip-ds6-route: Found route: "); PRINT6ADDR(addr); PRINTF(" via "); PRINT6ADDR(uip_ds6_route_nexthop(found_route)); PRINTF("\n"); } else { PRINTF("uip-ds6-route: No route found\n"); } if(found_route != NULL && found_route != list_head(routelist)) { /* If we found a route, we put it at the start of the routeslist list. The list is ordered by how recently we looked them up: the least recently used route will be at the end of the list - for fast lookups (assuming multiple packets to the same node). */ list_remove(routelist, found_route); list_push(routelist, found_route); } return found_route; }
/*---------------------------------------------------------------------------*/ static uint16_t print_routes(char *msg, int size) { uip_ds6_route_t *r = uip_ds6_route_head(); int len = strlen(msg); while(r != NULL && len < size + 30) { /* output a route entry */ len += sprint_addr6(&msg[len], &r->ipaddr); len += snprintf(&msg[len], size, "->"); len += sprint_addr6(&msg[len], uip_ds6_route_nexthop(r)); len += snprintf(&msg[len], size, "\n"); r = uip_ds6_route_next(r); } return len; }
/*---------------------------------------------------------------------------*/ void rpl_remove_routes_by_nexthop(uip_ipaddr_t *nexthop, rpl_dag_t *dag) { uip_ds6_route_t *r; r = uip_ds6_route_head(); while(r != NULL) { if(uip_ipaddr_cmp(uip_ds6_route_nexthop(r), nexthop) && r->state.dag == dag) { r->state.lifetime = 0; } r = uip_ds6_route_next(r); } ANNOTATE("#L %u 0\n", nexthop->u8[sizeof(uip_ipaddr_t) - 1]); }
/*---------------------------------------------------------------------------*/ static void print_network_status(void) { int i; uint8_t state; uip_ds6_defrt_t *default_route; uip_ds6_route_t *route; PRINTA("--- Network status ---\n"); /* Our IPv6 addresses */ PRINTA("- Server IPv6 addresses:\n"); for(i = 0; i < UIP_DS6_ADDR_NB; i++) { state = uip_ds6_if.addr_list[i].state; if(uip_ds6_if.addr_list[i].isused && (state == ADDR_TENTATIVE || state == ADDR_PREFERRED)) { PRINTA("-%d- ",i); uip_debug_ipaddr_print(&uip_ds6_if.addr_list[i].ipaddr); PRINTA("\n"); } } /* Our default route */ PRINTA("- Default route:\n"); default_route = uip_ds6_defrt_lookup(uip_ds6_defrt_choose()); if(default_route != NULL) { PRINTA("-- "); uip_debug_ipaddr_print(&default_route->ipaddr);; PRINTA(" (lifetime: %lu seconds)\n", (unsigned long)default_route->lifetime.interval); } else { PRINTA("-- None\n"); } /* Our routing entries */ PRINTA("- Routing entries (%u in total):\n", uip_ds6_route_num_routes()); route = uip_ds6_route_head(); while(route != NULL) { PRINTA("-- "); uip_debug_ipaddr_print(&route->ipaddr); PRINTA(" via "); uip_debug_ipaddr_print(uip_ds6_route_nexthop(route)); PRINTA(" (lifetime: %lu seconds)\n", (unsigned long)route->state.lifetime); route = uip_ds6_route_next(route); } PRINTA("----------------------\n"); }
/*---------------------------------------------------------------------------*/ uip_ds6_route_t * uip_ds6_route_lookup(uip_ipaddr_t *addr) { uip_ds6_route_t *r; uip_ds6_route_t *found_route; uint8_t longestmatch; PRINTF("uip-ds6-route: Looking up route for "); PRINT6ADDR(addr); PRINTF("\n"); found_route = NULL; longestmatch = 0; for(r = uip_ds6_route_head(); r != NULL; r = uip_ds6_route_next(r)) { if(r->length >= longestmatch && uip_ipaddr_prefixcmp(addr, &r->ipaddr, r->length)) { longestmatch = r->length; found_route = r; } } if(found_route != NULL) { PRINTF("uip-ds6-route: Found route: "); PRINT6ADDR(addr); PRINTF(" via "); PRINT6ADDR(uip_ds6_route_nexthop(found_route)); PRINTF("\n"); } else { PRINTF("uip-ds6-route: No route found\n"); } if(found_route != NULL) { /* If we found a route, we put it at the end of the routeslist list. The list is ordered by how recently we looked them up: the least recently used route will be at the start of the list. */ list_remove(routelist, found_route); list_add(routelist, found_route); } return found_route; }
uint16_t create_route_msg(char *buf, uip_ds6_route_t *r) { uint8_t n = 0; n += sprintf(&(buf[n]), "{\"dest\":\""); // sprintf for buffer prints n += ipaddr_add(&r->ipaddr, &(buf[n])); // push IP address in Buffer n += sprintf(&(buf[n]), "\",\"next\":\""); n += ipaddr_add(uip_ds6_route_nexthop(r), &(buf[n])); // Next hop address in Buffer n += sprintf(&(buf[n]), "\"}"); buf[n] = 0; //clear present n value of buffer PRINTF("buf: %s\n",buf); // show the present thing in the whole buffer return n; }
/*---------------------------------------------------------------------------*/ uip_ds6_route_t * uip_ds6_route_lookup(uip_ipaddr_t *addr) { uip_ds6_route_t *r; uip_ds6_route_t *found_route; uint8_t longestmatch; PRINTF("uip-ds6-route: Looking up route for "); PRINT6ADDR(addr); PRINTF("\n"); found_route = NULL; longestmatch = 0; for(r = uip_ds6_route_head(); r != NULL; r = uip_ds6_route_next(r)) { if(r->length >= longestmatch && uip_ipaddr_prefixcmp(addr, &r->ipaddr, r->length)) { longestmatch = r->length; found_route = r; } } if(found_route != NULL) { PRINTF("uip-ds6-route: Found route: "); PRINT6ADDR(addr); PRINTF(" via "); PRINT6ADDR(uip_ds6_route_nexthop(found_route)); PRINTF("\n"); } else { PRINTF("uip-ds6-route: No route found\n"); } return found_route; }
/*---------------------------------------------------------------------------*/ uip_ds6_route_t * uip_ds6_route_add(uip_ipaddr_t *ipaddr, uint8_t length, uip_ipaddr_t *nexthop) { uip_ds6_route_t *r; struct uip_ds6_route_neighbor_route *nbrr; #if DEBUG != DEBUG_NONE assert_nbr_routes_list_sane(); #endif /* DEBUG != DEBUG_NONE */ /* Get link-layer address of next hop, make sure it is in neighbor table */ const uip_lladdr_t *nexthop_lladdr = uip_ds6_nbr_lladdr_from_ipaddr(nexthop); if(nexthop_lladdr == NULL) { PRINTF("uip_ds6_route_add: neighbor link-local address unknown for "); PRINT6ADDR(nexthop); PRINTF("\n"); return NULL; } /* First make sure that we don't add a route twice. If we find an existing route for our destination, we'll delete the old one first. */ r = uip_ds6_route_lookup(ipaddr); if(r != NULL) { uip_ipaddr_t *current_nexthop; current_nexthop = uip_ds6_route_nexthop(r); if(current_nexthop != NULL && uip_ipaddr_cmp(nexthop, current_nexthop)) { /* no need to update route - already correct! */ return r; } PRINTF("uip_ds6_route_add: old route for "); PRINT6ADDR(ipaddr); PRINTF(" found, deleting it\n"); uip_ds6_route_rm(r); } { struct uip_ds6_route_neighbor_routes *routes; /* If there is no routing entry, create one. We first need to check if we have room for this route. If not, we remove the least recently used one we have. */ if(uip_ds6_route_num_routes() == UIP_DS6_ROUTE_NB) { uip_ds6_route_t *oldest; oldest = NULL; #if UIP_DS6_ROUTE_REMOVE_LEAST_RECENTLY_USED /* Removing the oldest route entry from the route table. The least recently used route is the first route on the list. */ oldest = list_tail(routelist); #endif if(oldest == NULL) { return NULL; } PRINTF("uip_ds6_route_add: dropping route to "); PRINT6ADDR(&oldest->ipaddr); PRINTF("\n"); uip_ds6_route_rm(oldest); } /* Every neighbor on our neighbor table holds a struct uip_ds6_route_neighbor_routes which holds a list of routes that go through the neighbor. We add our route entry to this list. We first check to see if we already have this neighbor in our nbr_route table. If so, the neighbor already has a route entry list. */ routes = nbr_table_get_from_lladdr(nbr_routes, (linkaddr_t *)nexthop_lladdr); if(routes == NULL) { /* If the neighbor did not have an entry in our neighbor table, we create one. The nbr_table_add_lladdr() function returns a pointer to a pointer that we may use for our own purposes. We initialize this pointer with the list of routing entries that are attached to this neighbor. */ routes = nbr_table_add_lladdr(nbr_routes, (linkaddr_t *)nexthop_lladdr, NBR_TABLE_REASON_ROUTE, NULL); if(routes == NULL) { /* This should not happen, as we explicitly deallocated one route table entry above. */ PRINTF("uip_ds6_route_add: could not allocate neighbor table entry\n"); return NULL; } LIST_STRUCT_INIT(routes, route_list); #ifdef NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK((const linkaddr_t *)nexthop_lladdr); #endif } /* Allocate a routing entry and populate it. */ r = memb_alloc(&routememb); if(r == NULL) { /* This should not happen, as we explicitly deallocated one route table entry above. */ PRINTF("uip_ds6_route_add: could not allocate route\n"); return NULL; } /* add new routes first - assuming that there is a reason to add this and that there is a packet coming soon. */ list_push(routelist, r); nbrr = memb_alloc(&neighborroutememb); if(nbrr == NULL) { /* This should not happen, as we explicitly deallocated one route table entry above. */ PRINTF("uip_ds6_route_add: could not allocate neighbor route list entry\n"); memb_free(&routememb, r); return NULL; } nbrr->route = r; /* Add the route to this neighbor */ list_add(routes->route_list, nbrr); r->neighbor_routes = routes; num_routes++; PRINTF("uip_ds6_route_add num %d\n", num_routes); /* lock this entry so that nexthop is not removed */ nbr_table_lock(nbr_routes, routes); } uip_ipaddr_copy(&(r->ipaddr), ipaddr); r->length = length; #ifdef UIP_DS6_ROUTE_STATE_TYPE memset(&r->state, 0, sizeof(UIP_DS6_ROUTE_STATE_TYPE)); #endif PRINTF("uip_ds6_route_add: adding route: "); PRINT6ADDR(ipaddr); PRINTF(" via "); PRINT6ADDR(nexthop); PRINTF("\n"); ANNOTATE("#L %u 1;blue\n", nexthop->u8[sizeof(uip_ipaddr_t) - 1]); #if UIP_DS6_NOTIFICATIONS call_route_callback(UIP_DS6_NOTIFICATION_ROUTE_ADD, ipaddr, nexthop); #endif #if DEBUG != DEBUG_NONE assert_nbr_routes_list_sane(); #endif /* DEBUG != DEBUG_NONE */ #ifdef NETSTACK_CONF_ROUTE_ADDED_CALLBACK NETSTACK_CONF_ROUTE_ADDED_CALLBACK(ipaddr); #endif /* NETSTACK_CONF_ROUTE_ADDED_CALLBACK*/ return r; }
static PT_THREAD(generate_network(struct httpd_state *s)) { static int i; static uip_ds6_route_t *r; static uip_ds6_defrt_t *dr; static uip_ds6_nbr_t *nbr; #if CETIC_6LBR_WITH_MULTICAST static uip_mcast6_route_t *mcast_route; #endif #if RPL_WITH_NON_STORING static rpl_ns_node_t *link; #endif PSOCK_BEGIN(&s->sout); add("<br /><h2>Addresses</h2><pre>"); SEND_STRING(&s->sout, buf); reset_buf(); for(i = 0; i < UIP_DS6_ADDR_NB; i++) { if(uip_ds6_if.addr_list[i].isused) { ipaddr_add(&uip_ds6_if.addr_list[i].ipaddr); add(" "); add_address_type(uip_ds6_if.addr_list[i].type); add(" "); add_address_state(uip_ds6_if.addr_list[i].state); if(!uip_ds6_if.addr_list[i].isinfinite) { add(" %u s", stimer_remaining(&uip_ds6_if.addr_list[i].vlifetime)); } add("\n"); SEND_STRING(&s->sout, buf); reset_buf(); } } add("</pre><h2>Multicast groups</h2><pre>"); for(i = 0; i < UIP_DS6_MADDR_NB; i++) { if(uip_ds6_if.maddr_list[i].isused) { ipaddr_add(&uip_ds6_if.maddr_list[i].ipaddr); add("\n"); SEND_STRING(&s->sout, buf); reset_buf(); } } add("</pre><h2>Prefixes</h2><pre>"); for(i = 0; i < UIP_DS6_PREFIX_NB; i++) { if(uip_ds6_prefix_list[i].isused) { ipaddr_add(&uip_ds6_prefix_list[i].ipaddr); #if UIP_CONF_ROUTER if(uip_ds6_prefix_list[i].advertise) { add(" Adv"); } #else if(uip_ds6_prefix_list[i].isinfinite) { add(" Inf"); } #endif add("\n"); } } SEND_STRING(&s->sout, buf); reset_buf(); #if CETIC_6LBR_WITH_IP64 if((nvm_data.global_flags & CETIC_GLOBAL_IP64) != 0) { add("</pre><h2>IP64</h2><pre>"); if((nvm_data.eth_ip64_flags & CETIC_6LBR_IP64_DHCP) == 0 || ip64_hostaddr_is_configured()) { add("Address : "); ip4addr_add(ip64_get_hostaddr()); add("<br />"); add("Netmask : "); ip4addr_add(ip64_get_netmask()); add("<br />"); add("Gateway : "); ip4addr_add(ip64_get_draddr()); add("<br />"); if((nvm_data.eth_ip64_flags & CETIC_6LBR_IP64_DHCP) != 0) { add("DHCP Server : "); ip4addr_add_u8(cetic_6lbr_ip64_dhcp_state->serverid); add("<br />"); add("DHCP lease time : %d s<br />", uip_ntohs(cetic_6lbr_ip64_dhcp_state->lease_time[0])*65536ul + uip_ntohs(cetic_6lbr_ip64_dhcp_state->lease_time[1])); } } else { add("Waiting configuration<br />"); } SEND_STRING(&s->sout, buf); reset_buf(); } #endif add("</pre><h2>Neighbors</h2><pre>"); for(nbr = nbr_table_head(ds6_neighbors); nbr != NULL; nbr = nbr_table_next(ds6_neighbors, nbr)) { if ((nvm_data.global_flags & CETIC_GLOBAL_DISABLE_CONFIG) == 0) { add("[<a href=\"nbr-rm?"); ipaddr_add(&nbr->ipaddr); add("\">del</a>] "); } #if CETIC_6LBR_NODE_CONFIG_HAS_NAME if ( node_config_loaded ) { add("%s : ", node_config_get_name(node_config_find_by_lladdr(uip_ds6_nbr_get_ll(nbr)))); } #endif ipaddr_add(&nbr->ipaddr); add(" "); lladdr_add(uip_ds6_nbr_get_ll(nbr)); add(" "); add_network_cases(nbr->state); #if UIP_SWITCH_LOOKUP if(nbr->ifindex != NETWORK_ITF_UNKNOWN) { add(" if:%u", nbr->ifindex); } #endif add("\n"); SEND_STRING(&s->sout, buf); reset_buf(); } add("</pre><h2>Routes</h2><pre>"); SEND_STRING(&s->sout, buf); reset_buf(); for(r = uip_ds6_route_head(), i = 0; r != NULL; r = uip_ds6_route_next(r), ++i) { if ((nvm_data.global_flags & CETIC_GLOBAL_DISABLE_CONFIG) == 0) { add("[<a href=\"route-rm?"); ipaddr_add(&r->ipaddr); add("\">del</a>] "); } #if CETIC_6LBR_NODE_CONFIG_HAS_NAME if ( node_config_loaded ) { add("%s (", node_config_get_name(node_config_find_by_ip(&r->ipaddr))); ipaddr_add(&r->ipaddr); add("/%u) via ", r->length); } else { ipaddr_add(&r->ipaddr); add("/%u via ", r->length); } if ( node_config_loaded ) { add("%s (", node_config_get_name(node_config_find_by_ip(uip_ds6_route_nexthop(r)))); ipaddr_add(uip_ds6_route_nexthop(r)); add(")"); } else { ipaddr_add(uip_ds6_route_nexthop(r)); } #else ipaddr_add(&r->ipaddr); add("/%u via ", r->length); ipaddr_add(uip_ds6_route_nexthop(r)); #endif #if CETIC_6LBR_WITH_RPL if(r->state.lifetime != RPL_ROUTE_INFINITE_LIFETIME) { #else if(r->neighbor_routes != NULL) { #endif add(" %lu s\n", r->state.lifetime); } else { add("Inf\n"); } SEND_STRING(&s->sout, buf); reset_buf(); } #if RPL_WITH_NON_STORING add("</pre><h2>Links</h2><pre>"); for(link = rpl_ns_node_head(); link != NULL; link = rpl_ns_node_next(link)) { if(link->parent != NULL) { uip_ipaddr_t child_ipaddr; uip_ipaddr_t parent_ipaddr; rpl_ns_get_node_global_addr(&child_ipaddr, link); rpl_ns_get_node_global_addr(&parent_ipaddr, link->parent); #if CETIC_6LBR_NODE_CONFIG_HAS_NAME if ( node_config_loaded ) { add("%s (", node_config_get_name(node_config_find_by_ip(&child_ipaddr))); ipaddr_add(&child_ipaddr); add(") via "); } else { ipaddr_add(&child_ipaddr); add(" via "); } if ( node_config_loaded ) { add("%s (", node_config_get_name(node_config_find_by_ip(&parent_ipaddr))); ipaddr_add(&parent_ipaddr); add(")"); } else { ipaddr_add(&parent_ipaddr); } #else ipaddr_add(&child_ipaddr); add(" via "); ipaddr_add(&parent_ipaddr); #endif add(" %lu s\n", link->lifetime); SEND_STRING(&s->sout, buf); reset_buf(); } } #endif #if CETIC_6LBR_WITH_MULTICAST add("</pre><h2>Routed multicast groups</h2><pre>"); for(mcast_route = uip_mcast6_route_list_head(), i = 0; mcast_route != NULL; mcast_route = list_item_next(mcast_route), ++i) { if ((nvm_data.global_flags & CETIC_GLOBAL_DISABLE_CONFIG) == 0) { add("[<a href=\"mcast-rm?"); ipaddr_add(&mcast_route->group); add("\">del</a>] "); } ipaddr_add(&mcast_route->group); add(" %lu s\n", mcast_route->lifetime); SEND_STRING(&s->sout, buf); reset_buf(); } #endif add("</pre><h2>Default Routers</h2><pre>"); for(dr = uip_ds6_defrt_head(); dr != NULL; dr = list_item_next(r)) { ipaddr_add(&dr->ipaddr); if(dr->isinfinite) { add(" Inf"); } else { add(" %u s", stimer_remaining(&dr->lifetime)); } add("\n"); SEND_STRING(&s->sout, buf); reset_buf(); } #if UIP_CONF_DS6_ROUTE_INFORMATION add("</pre><h2>Route info</h2><pre>"); for(i = 0; i < UIP_DS6_ROUTE_INFO_NB; i++) { if(uip_ds6_route_info_list[i].isused) { ipaddr_add(&uip_ds6_route_info_list[i].ipaddr); add("/%u (%x) %u s\n", uip_ds6_route_info_list[i].length, uip_ds6_route_info_list[i].flags, uip_ds6_route_info_list[i].lifetime); } } SEND_STRING(&s->sout, buf); reset_buf(); #endif add("</pre><h2>DNS server</h2><pre>"); //Note: Currently we assume only one DNS server uip_ipaddr_t * dns = uip_nameserver_get(0); if(!uip_is_addr_unspecified(dns)) { ipaddr_add(dns); add(" %u s\n", uip_nameserver_next_expiration()); } SEND_STRING(&s->sout, buf); reset_buf(); #if CETIC_6LBR_WITH_IP64 if((nvm_data.global_flags & CETIC_GLOBAL_IP64) != 0) { add("</pre><h2>IP64 connections mapping</h2><pre>"); static struct ip64_addrmap_entry *m; for(m = ip64_addrmap_list(); m != NULL; m = list_item_next(m)) { if(timer_expired(&m->timer)) continue; ipaddr_add(&m->ip6addr); add("%%%d (%d)", m->ip6port, m->protocol); if(m->ip6to4 && m->ip4to6) { add(" <-> "); } else if(m->ip6to4) { add(" -> "); } else { add(" <- "); } ip4addr_add(&m->ip4addr); add("%%%d : %d (%x) %us\n", m->ip4port, m->mapped_port, m->flags, (m->timer.interval - (clock_time() - m->timer.start)) / CLOCK_SECOND); SEND_STRING(&s->sout, buf); reset_buf(); } } #endif #if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0 add("</pre><h2>6LoWPAN Prefix contexts</h2><pre>"); for(i = 0; i < SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS; i++) { if(addr_contexts[i].used == 1) { add("%d : ", addr_contexts[i].number); ipaddr_add_u8_len(addr_contexts[i].prefix, 8); add("\n"); } } add("</pre><br />"); SEND_STRING(&s->sout, buf); reset_buf(); #endif #if CETIC_6LBR_TRANSPARENTBRIDGE add("<h2>HW Prefixes cache</h2><pre>"); for(i = 0; i < prefixCounter; i++) { add("%02x:%02x:%02x\n", prefixBuffer[i][0], prefixBuffer[i][1], prefixBuffer[i][2]); } SEND_STRING(&s->sout, buf); add("</pre><br />"); reset_buf(); #endif PSOCK_END(&s->sout); } static void add_network_cases(const uint8_t state) { switch (state) { case NBR_INCOMPLETE: add("Incomplete"); break; case NBR_REACHABLE: add("Reachable"); break; case NBR_STALE: add("Stale"); break; case NBR_DELAY: add("Delay"); break; case NBR_PROBE: add("Probe"); break; } } static httpd_cgi_call_t * webserver_network_route_add(struct httpd_state *s) { #if UIP_DS6_STATIC_ROUTES uip_ds6_route_t *route; uip_ipaddr_t ipaddr; uint8_t length; uip_ipaddr_t nexthop; char *p; char *sep; webserver_result_title = "Network"; webserver_result_text = "Add route: Route not created"; do { if(!s->query) break; p = s->query; sep = index(p, '='); if(sep == NULL) break; *sep = 0; if(strcmp(p, "target") != 0) break; p = sep + 1; sep = index(p, '&'); if(sep == NULL) break; *sep = 0; if(uiplib_ipaddrconv(p, &ipaddr) == 0) break; p = sep + 1; sep = index(p, '='); if(sep == NULL) break; *sep = 0; if(strcmp(p, "length") != 0) break; p = sep + 1; sep = index(p, '&'); if(sep == NULL) break; *sep = 0; length = atoi(p); p = sep + 1; sep = index(p, '='); if(sep == NULL) break; *sep = 0; if(strcmp(p, "nexthop") != 0) break; p = sep + 1; if(uiplib_ipaddrconv(p, &nexthop) == 0) break; route = uip_ds6_route_add_static(&ipaddr, length, &nexthop); if(route) { webserver_result_text = "Route created"; } } while (0); #else webserver_result_title = "Network"; webserver_result_text = "Add route: not supported"; #endif return &webserver_result_page; }
void tcpip_ipv6_output(void) { uip_ds6_nbr_t *nbr = NULL; uip_ipaddr_t *nexthop; if(uip_len == 0) { return; } 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 { uip_ds6_route_t *route; /* 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) { 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; } /* Inform the other end that the destination is not reachable. If it's * not informed routes might get lost unexpectedly until there's a need * to send a new packet to the peer */ if(UIP_FALLBACK_INTERFACE.output() < 0) { PRINTF("FALLBACK: output error. Reporting DST UNREACH\n"); uip_icmp6_error_output(ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR, 0); uip_flags = 0; tcpip_ipv6_output(); return; } #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 global repair berfore we remove the route. */ rpl_dag_t *dag; rpl_instance_t *instance; dag = (rpl_dag_t *)route->state.dag; if(dag != NULL) { instance = dag->instance; rpl_repair_root(instance->instance_id); } #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((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(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_routes(struct httpd_state *s)) { static uip_ds6_route_t *r; static uip_ds6_nbr_t *nbr; #if BUF_USES_STACK char buf[256]; #endif #if WEBSERVER_CONF_LOADTIME static clock_time_t numticks; numticks = clock_time(); #endif PSOCK_BEGIN(&s->sout); SEND_STRING(&s->sout, TOP); #if BUF_USES_STACK bufptr = buf;bufend=bufptr+sizeof(buf); #else blen = 0; #endif ADD("Neighbors<pre>"); for(nbr = nbr_table_head(ds6_neighbors); nbr != NULL; nbr = nbr_table_next(ds6_neighbors, nbr)) { #if WEBSERVER_CONF_NEIGHBOR_STATUS #if BUF_USES_STACK {char* j=bufptr+25; ipaddr_add(&nbr->ipaddr); while (bufptr < j) ADD(" "); switch (nbr->state) { case NBR_INCOMPLETE: ADD(" INCOMPLETE");break; case NBR_REACHABLE: ADD(" REACHABLE");break; case NBR_STALE: ADD(" STALE");break; case NBR_DELAY: ADD(" DELAY");break; case NBR_PROBE: ADD(" NBR_PROBE");break; } } #else {uint8_t j=blen+25; ipaddr_add(&nbr->ipaddr); while (blen < j) ADD(" "); switch (nbr->state) { case NBR_INCOMPLETE: ADD(" INCOMPLETE");break; case NBR_REACHABLE: ADD(" REACHABLE");break; case NBR_STALE: ADD(" STALE");break; case NBR_DELAY: ADD(" DELAY");break; case NBR_PROBE: ADD(" NBR_PROBE");break; } } #endif #else ipaddr_add(&nbr->ipaddr); #endif ADD("\n"); #if BUF_USES_STACK if(bufptr > bufend - 45) { SEND_STRING(&s->sout, buf); bufptr = buf; bufend = bufptr + sizeof(buf); } #else if(blen > sizeof(buf) - 45) { SEND_STRING(&s->sout, buf); blen = 0; } #endif } ADD("</pre>Routes<pre>"); SEND_STRING(&s->sout, buf); #if BUF_USES_STACK bufptr = buf; bufend = bufptr + sizeof(buf); #else blen = 0; #endif for(r = uip_ds6_route_head(); r != NULL; r = uip_ds6_route_next(r)) { #if BUF_USES_STACK #if WEBSERVER_CONF_ROUTE_LINKS ADD("<a href=http://["); ipaddr_add(&r->ipaddr); ADD("]/status.shtml>"); ipaddr_add(&r->ipaddr); ADD("</a>"); #else ipaddr_add(&r->ipaddr); #endif #else #if WEBSERVER_CONF_ROUTE_LINKS ADD("<a href=http://["); ipaddr_add(&r->ipaddr); ADD("]/status.shtml>"); SEND_STRING(&s->sout, buf); //TODO: why tunslip6 needs an output here, wpcapslip does not blen = 0; ipaddr_add(&r->ipaddr); ADD("</a>"); #else ipaddr_add(&r->ipaddr); #endif #endif ADD("/%u (via ", r->length); ipaddr_add(uip_ds6_route_nexthop(r)); if(1 || (r->state.lifetime < 600)) { ADD(") %lus\n", (unsigned long)r->state.lifetime); } else { ADD(")\n"); } SEND_STRING(&s->sout, buf); #if BUF_USES_STACK bufptr = buf; bufend = bufptr + sizeof(buf); #else blen = 0; #endif } ADD("</pre>"); #if WEBSERVER_CONF_FILESTATS static uint16_t numtimes; ADD("<br><i>This page sent %u times</i>",++numtimes); #endif #if WEBSERVER_CONF_LOADTIME numticks = clock_time() - numticks + 1; ADD(" <i>(%u.%02u sec)</i>",numticks/CLOCK_SECOND,(100*(numticks%CLOCK_SECOND))/CLOCK_SECOND)); #endif SEND_STRING(&s->sout, buf); SEND_STRING(&s->sout, BOTTOM); PSOCK_END(&s->sout); }
static void generate_routes() { static uip_ds6_route_t *r; static uip_ds6_nbr_t *nbr; #if BUF_USES_STACK char buf[256]; bufptr = buf;bufend=bufptr+sizeof(buf); #else blen = 0; #endif ADD("Neighbors\n"); for(nbr = nbr_table_head(ds6_neighbors); nbr != NULL; nbr = nbr_table_next(ds6_neighbors, nbr)) { #if BUF_USES_STACK {char* j=bufptr+25; ipaddr_add(&nbr->ipaddr); while (bufptr < j) ADD(" "); switch (nbr->state) { case NBR_INCOMPLETE: ADD(" INCOMPLETE");break; case NBR_REACHABLE: ADD(" REACHABLE");break; case NBR_STALE: ADD(" STALE");break; case NBR_DELAY: ADD(" DELAY");break; case NBR_PROBE: ADD(" NBR_PROBE");break; } } #else {uint8_t j=blen+25; ipaddr_add(&nbr->ipaddr); while (blen < j) ADD(" "); switch (nbr->state) { case NBR_INCOMPLETE: ADD(" INCOMPLETE");break; case NBR_REACHABLE: ADD(" REACHABLE");break; case NBR_STALE: ADD(" STALE");break; case NBR_DELAY: ADD(" DELAY");break; case NBR_PROBE: ADD(" NBR_PROBE");break; } } #endif ADD("\n"); #if BUF_USES_STACK if(bufptr > bufend - 45) { PRINTF("%s", buf); bufptr = buf; bufend = bufptr + sizeof(buf); } #else if(blen > sizeof(buf) - 45) { PRINTF("%s", buf); blen = 0; } #endif } ADD("\nRoutes\n"); PRINTF("%s", buf); #if BUF_USES_STACK bufptr = buf; bufend = bufptr + sizeof(buf); #else blen = 0; #endif for(r = uip_ds6_route_head(); r != NULL; r = uip_ds6_route_next(r)) { ipaddr_add(&r->ipaddr); ADD("/%u (via ", r->length); ipaddr_add(uip_ds6_route_nexthop(r)); if(1 || (r->state.lifetime < 600)) { ADD(") %us\n", (unsigned int)r->state.lifetime); // iotlab printf does not have %lu } else { ADD(")\n"); } PRINTF("%s", buf); #if BUF_USES_STACK bufptr = buf; bufend = bufptr + sizeof(buf); #else blen = 0; #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(); }
/*---------------------------------Main Routine----------------------------*/ int main(void) { /* GCC depends on register r1 set to 0 (?) */ asm volatile ("clr r1"); /* Initialize in a subroutine to maximize stack space */ initialize(); #if DEBUG {struct process *p; for(p = PROCESS_LIST();p != NULL; p = ((struct process *)p->next)) { PRINTA("Process=%p Thread=%p Name=\"%s\" \n",p,p->thread,PROCESS_NAME_STRING(p)); } } #endif while(1) { process_run(); watchdog_periodic(); /* Print rssi of all received packets, useful for range testing */ #ifdef RF230_MIN_RX_POWER uint8_t lastprint; if (rf230_last_rssi != lastprint) { //can be set in halbb.c interrupt routine PRINTA("%u ",rf230_last_rssi); lastprint=rf230_last_rssi; } #endif #if 0 /* Clock.c can trigger a periodic PLL calibration in the RF230BB driver. * This can show when that happens. */ extern uint8_t rf230_calibrated; if (rf230_calibrated) { PRINTA("\nRF230 calibrated!\n"); rf230_calibrated=0; } #endif #if TESTRTIMER /* Timeout can be increased up to 8 seconds maximum. * A one second cycle is convenient for triggering the various debug printouts. * The triggers are staggered to avoid printing everything at once. * My Jackdaw is 4% slow. */ if (rtimerflag) { rtimer_set(&rt, RTIMER_NOW()+ RTIMER_ARCH_SECOND*1UL, 1,(void *) rtimercycle, NULL); rtimerflag=0; #if STAMPS if ((rtime%STAMPS)==0) { PRINTA("%us ",rtime); if (rtime%STAMPS*10) PRINTA("\n"); } #endif rtime+=1; #if PINGS && UIP_CONF_IPV6_RPL extern void raven_ping6(void); if ((rtime%PINGS)==1) { PRINTA("**Ping\n"); raven_ping6(); } #endif #if ROUTES && UIP_CONF_IPV6_RPL if ((rtime%ROUTES)==2) { extern uip_ds6_netif_t uip_ds6_if; uint8_t i,j; uip_ds6_nbr_t *nbr; PRINTA("\nAddresses [%u max]\n",UIP_DS6_ADDR_NB); for (i=0;i<UIP_DS6_ADDR_NB;i++) { if (uip_ds6_if.addr_list[i].isused) { uip_debug_ipaddr_print(&uip_ds6_if.addr_list[i].ipaddr); PRINTA("\n"); } } PRINTA("\nNeighbors [%u max]\n",NBR_TABLE_MAX_NEIGHBORS); for(nbr = nbr_table_head(ds6_neighbors); nbr != NULL; nbr = nbr_table_next(ds6_neighbors, nbr)) { uip_debug_ipaddr_print(&nbr->ipaddr); PRINTA("\n"); j=0; } if (j) PRINTA(" <none>"); PRINTA("\nRoutes [%u max]\n",UIP_DS6_ROUTE_NB); uip_ds6_route_t *r; for(r = uip_ds6_route_head(); r != NULL; r = uip_ds6_route_next(r)) { if(r->isused) { uip_debug_ipaddr_print(&r->ipaddr); PRINTA("/%u (via ", r->length); uip_debug_ipaddr_print(uip_ds6_route_nexthop(r)); // if(r->state.lifetime < 600) { PRINTA(") %lus\n", r->state.lifetime); // } else { // PRINTA(")\n"); // } j=0; } } if (j) PRINTA(" <none>"); PRINTA("\n---------\n"); } #endif #if STACKMONITOR && CONFIG_STACK_MONITOR if ((rtime%STACKMONITOR)==3) { extern uint16_t __bss_end; uint16_t p=(uint16_t)&__bss_end; do { if (*(uint16_t *)p != 0x4242) { PRINTA("Never-used stack > %d bytes\n",p-(uint16_t)&__bss_end); break; } p+=100; } while (p<RAMEND-10); } #endif } #endif /* TESTRTIMER */ //Use with RF230BB DEBUGFLOW to show path through driver #if RF230BB&&0 extern uint8_t debugflowsize,debugflow[]; //in rf230bb.c if (debugflowsize) { debugflow[debugflowsize]=0; PRINTA("%s",debugflow); debugflowsize=0; } #endif } return 0; }
/*---------------------------------------------------------------------------*/ static PT_THREAD(generate_routes(struct httpd_state *s)) { static int i; static uip_ds6_route_t *r; static uip_ds6_nbr_t *nbr; PSOCK_BEGIN(&s->sout); SEND_STRING(&s->sout, TOP); blen = 0; ADD("Neighbors<pre>"); for(nbr = nbr_table_head(ds6_neighbors); nbr != NULL; nbr = nbr_table_next(ds6_neighbors, nbr)) { ipaddr_add(&nbr->ipaddr); ADD("\n"); if(blen > sizeof(buf) - 45) { SEND_STRING(&s->sout, buf); blen = 0; } } ADD("</pre>Routes<pre>"); SEND_STRING(&s->sout, buf); blen = 0; for(r = uip_ds6_route_head(); r != NULL; r = uip_ds6_route_next(r)) { ipaddr_add(&r->ipaddr); ADD("/%u (via ", r->length); ipaddr_add(uip_ds6_route_nexthop(r)); if(r->state.lifetime < 600) { ADD(") %lus\n", (unsigned long)r->state.lifetime); } else { ADD(")\n"); } SEND_STRING(&s->sout, buf); blen = 0; } ADD("</pre>"); //if(blen > 0) { SEND_STRING(&s->sout, buf); // blen = 0; //} if(sensor_count > 0) { ADD("</pre>Sensors<pre>"); SEND_STRING(&s->sout, buf); blen = 0; for(i = 0; i < sensor_count; i++) { ADD("%s\n", sensors[i]); SEND_STRING(&s->sout, buf); blen = 0; } ADD("</pre>"); SEND_STRING(&s->sout, buf); } SEND_STRING(&s->sout, BOTTOM); PSOCK_END(&s->sout); }
/*---------------------------------------------------------------------------*/ void uip_ds6_route_rm(uip_ds6_route_t *route) { struct uip_ds6_route_neighbor_route *neighbor_route; #if DEBUG != DEBUG_NONE assert_nbr_routes_list_sane(); #endif /* DEBUG != DEBUG_NONE */ if(route != NULL && route->neighbor_routes != NULL) { PRINTF("uip_ds6_route_rm: removing route: "); PRINT6ADDR(&route->ipaddr); PRINTF("\n"); /* Remove the route from the route list */ list_remove(routelist, route); /* Find the corresponding neighbor_route and remove it. */ for(neighbor_route = list_head(route->neighbor_routes->route_list); neighbor_route != NULL && neighbor_route->route != route; neighbor_route = list_item_next(neighbor_route)); if(neighbor_route == NULL) { PRINTF("uip_ds6_route_rm: neighbor_route was NULL for "); uip_debug_ipaddr_print(&route->ipaddr); PRINTF("\n"); } list_remove(route->neighbor_routes->route_list, neighbor_route); if(list_head(route->neighbor_routes->route_list) == NULL) { /* If this was the only route using this neighbor, remove the neighbor from the table - this implicitly unlocks nexthop */ #if (DEBUG) & DEBUG_ANNOTATE uip_ipaddr_t *nexthop = uip_ds6_route_nexthop(route); if(nexthop != NULL) { ANNOTATE("#L %u 0\n", nexthop->u8[sizeof(uip_ipaddr_t) - 1]); } #endif /* (DEBUG) & DEBUG_ANNOTATE */ PRINTF("uip_ds6_route_rm: removing neighbor too\n"); nbr_table_remove(nbr_routes, route->neighbor_routes->route_list); #ifdef NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK( (const linkaddr_t *)nbr_table_get_lladdr(nbr_routes, route->neighbor_routes->route_list)); #endif } memb_free(&routememb, route); memb_free(&neighborroutememb, neighbor_route); num_routes--; PRINTF("uip_ds6_route_rm num %d\n", num_routes); #if UIP_DS6_NOTIFICATIONS call_route_callback(UIP_DS6_NOTIFICATION_ROUTE_RM, &route->ipaddr, uip_ds6_route_nexthop(route)); #endif #ifdef NETSTACK_CONF_ROUTE_REMOVED_CALLBACK NETSTACK_CONF_ROUTE_REMOVED_CALLBACK(&route->ipaddr); #endif /* NETSTACK_CONF_ROUTE_REMOVED_CALLBACK*/ } #if DEBUG != DEBUG_NONE assert_nbr_routes_list_sane(); #endif /* DEBUG != DEBUG_NONE */ return; }
/*---------------------------------------------------------------------------*/ static unsigned short make_route(void *p) { static const char httpd_cgi_rtesh[] HTTPD_STRING_ATTR = " "; static const char httpd_cgi_rtes0[] HTTPD_STRING_ATTR = "<tr><td>"; static const char httpd_cgi_rtes1[] HTTPD_STRING_ATTR = "</td><td>%u</td><td>"; static const char httpd_cgi_rtes2[] HTTPD_STRING_ATTR = ", %lu s"; uint16_t numprinted; struct httpd_state *s = (struct httpd_state *)p; uip_ds6_route_t *r; // conn = &uip_conns[s->u.count]; numprinted = httpd_snprintf((char *)uip_appdata, uip_mss(), httpd_cgi_rtesh); if(numprinted >= uip_mss()) { return write_mss_error(11); } { r = s->u.ptr; /* <tr><td> */ numprinted += httpd_snprintf((char *)uip_appdata + numprinted, uip_mss() - numprinted, httpd_cgi_rtes0); if(numprinted >= uip_mss()) { return write_mss_error(12); } numprinted += httpd_cgi_sprint_ip6(&r->ipaddr, (char *)uip_appdata + numprinted); if(numprinted >= uip_mss()) { return write_mss_error(13); } uip_ds6_nbr_t *n; uip_ipaddr_t *nexthop; int nopath = 0; nexthop = uip_ds6_route_nexthop(r); n = uip_ds6_nbr_lookup(nexthop); if(r != NULL) { nopath = r->state.nopath_received; } numprinted += httpd_snprintf((char *)uip_appdata + numprinted, uip_mss() - numprinted, httpd_cgi_rtes1, nopath); if(numprinted >= uip_mss()) { return write_mss_error(14); } if(nexthop != NULL) { numprinted += httpd_cgi_sprint_ip6(nexthop, (char *)uip_appdata + numprinted); } if(numprinted >= uip_mss()) { return write_mss_error(15); } if(r->state.lifetime < 3600L * 24) { numprinted += httpd_snprintf((char *)uip_appdata + numprinted, uip_mss() - numprinted, httpd_cgi_rtes2, r->state.lifetime); if(numprinted >= uip_mss()) { return write_mss_error(16); } } /* Ping */ if(simple_udp_ping_has_reply(&r->ipaddr)) { int delay = simple_udp_ping_get_delay(&r->ipaddr); numprinted += httpd_snprintf((char *)uip_appdata + numprinted, uip_mss() - numprinted, "</td><td>%u ms", delay); if(numprinted >= uip_mss()) { return write_mss_error(6); } } else if(simple_udp_ping_has_sent(&r->ipaddr)) { numprinted += httpd_snprintf((char *)uip_appdata + numprinted, uip_mss() - numprinted, "</td><td>Ping scheduled..."); if(numprinted >= uip_mss()) { return write_mss_error(7); } } else { numprinted += httpd_snprintf((char *)uip_appdata + numprinted, uip_mss() - numprinted, "</td><td>-"); if(numprinted >= uip_mss()) { return write_mss_error(8); } } numprinted += httpd_snprintf((char *)uip_appdata + numprinted, uip_mss() - numprinted, httpd_cgi_addrb); if(numprinted >= uip_mss()) { return write_mss_error(9); } } return numprinted; }