/*---------------------------------------------------------------------------*/ void phase_update(const linkaddr_t *neighbor, rtimer_clock_t time, uint32_t cycle_time, int mac_status) { struct phase *e; /* If we have an entry for this neighbor already, we renew it. */ e = nbr_table_get_from_lladdr(nbr_phase, neighbor); if(e != NULL) { if(mac_status == MAC_TX_OK) { #if PHASE_DRIFT_CORRECT e->drift = time-e->time; #endif e->time = time; if(cycle_time!=0){ e->cycle=cycle_time; } else{ e->cycle=CONTIKIMAC_CONF_CYCLE_TIME; } } /* If the neighbor didn't reply to us, it may have switched phase (rebooted). We try a number of transmissions to it before we drop it from the phase list. */ if(mac_status == MAC_TX_NOACK) { PRINTF("phase noacks %d to %d.%d\n", e->noacks, neighbor->u8[0], neighbor->u8[1]); e->noacks++; if(e->noacks == 1) { timer_set(&e->noacks_timer, MAX_NOACKS_TIME); } if(e->noacks >= MAX_NOACKS || timer_expired(&e->noacks_timer)) { PRINTF("drop %d\n", neighbor->u8[0]); nbr_table_remove(nbr_phase, e); return; } if(e->noacks >= MAX_NOACKbis){ e->cycle=CONTIKIMAC_CONF_CYCLE_TIME; } } else if(mac_status == MAC_TX_OK) { e->noacks = 0; } } else { /* No matching phase was found, so we allocate a new one. */ if(mac_status == MAC_TX_OK && e == NULL) { e = nbr_table_add_lladdr(nbr_phase, neighbor); if(e) { e->time = time; #if PHASE_DRIFT_CORRECT e->drift = 0; #endif e->noacks = 0; } } } }
/*---------------------------------------------------------------------------*/ 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; }
/*---------------------------------------------------------------------------*/ void rpl_remove_parent(rpl_parent_t *parent) { PRINTF("RPL: Removing parent "); PRINT6ADDR(rpl_get_parent_ipaddr(parent)); PRINTF("\n"); rpl_nullify_parent(parent); nbr_table_remove(rpl_parents, parent); }
/*---------------------------------------------------------------------------*/ void uip_ds6_nbr_rm(uip_ds6_nbr_t *nbr) { if(nbr != NULL) { #if UIP_CONF_IPV6_QUEUE_PKT uip_packetqueue_free(&nbr->packethandle); #endif /* UIP_CONF_IPV6_QUEUE_PKT */ NEIGHBOR_STATE_CHANGED(nbr); nbr_table_remove(ds6_neighbors, nbr); } return; }
/*---------------------------------------------------------------------------*/ static void rm_routelist(struct uip_ds6_route_neighbor_routes *routes) { #if DEBUG != DEBUG_NONE assert_nbr_routes_list_sane(); #endif /* DEBUG != DEBUG_NONE */ PRINTF("uip_ds6_route_rm_routelist\n"); if(routes != NULL && routes->route_list != NULL) { struct uip_ds6_route_neighbor_route *r; r = list_head(routes->route_list); while(r != NULL) { uip_ds6_route_rm(r->route); r = list_head(routes->route_list); } nbr_table_remove(nbr_routes, routes); } #if DEBUG != DEBUG_NONE assert_nbr_routes_list_sane(); #endif /* DEBUG != DEBUG_NONE */ }
/*---------------------------------------------------------------------------*/ static int parse(void) { int result; const linkaddr_t *sender; struct anti_replay_info* info; result = DECORATED_FRAMER.parse(); if(result == FRAMER_FAILED) { return result; } if(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL) != SEC_LVL) { PRINTF("noncoresec: received frame with wrong security level\n"); return FRAMER_FAILED; } sender = packetbuf_addr(PACKETBUF_ADDR_SENDER); if(linkaddr_cmp(sender, &linkaddr_node_addr)) { PRINTF("noncoresec: frame from ourselves\n"); return FRAMER_FAILED; } packetbuf_set_datalen(packetbuf_datalen() - MIC_LEN); if(!aead(result, 0)) { PRINTF("noncoresec: received unauthentic frame %lu\n", anti_replay_get_counter()); return FRAMER_FAILED; } info = nbr_table_get_from_lladdr(anti_replay_table, sender); if(!info) { info = nbr_table_add_lladdr(anti_replay_table, sender, NBR_TABLE_REASON_LLSEC, NULL); if(!info) { PRINTF("noncoresec: could not get nbr_table_item\n"); return FRAMER_FAILED; } /* * Locking avoids replay attacks due to removed neighbor table items. * Unfortunately, an attacker can mount a memory-based DoS attack * on this by replaying broadcast frames from other network parts. * However, this is not an issue as long as the network size does not * exceed NBR_TABLE_MAX_NEIGHBORS. * * To avoid locking, we could swap anti-replay information * to external flash. Locking is also unnecessary when using * pairwise session keys, as done in coresec. */ if(!nbr_table_lock(anti_replay_table, info)) { nbr_table_remove(anti_replay_table, info); PRINTF("noncoresec: could not lock\n"); return FRAMER_FAILED; } anti_replay_init_info(info); } else { if(anti_replay_was_replayed(info)) { PRINTF("noncoresec: received replayed frame %lu\n", anti_replay_get_counter()); return FRAMER_FAILED; } } return result; }
/*---------------------------------------------------------------------------*/ 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; }