static uint8_t bridge_output(uip_lladdr_t * dest) { int isBroadcast = IS_BROADCAST_ADDR(dest); int wsnDest = 0; if(!isBroadcast) { LOG6LBR_LLADDR_PRINTF(PACKET, PF_OUT, dest, "bridge_output: Sending packet to "); } else { LOG6LBR_PRINTF(PACKET, PF_OUT, "bridge_output: Sending packet to Broadcast\n"); } if(isBroadcast) { //Obviously we can not guess the target segment for a multicast packet //So we have to check the packet source prefix (and match it on the Ethernet segment prefix) //or, in case of link-local packet, check packet type and/or packet data if((UIP_IP_BUF->proto == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type == ICMP6_RA) || (UIP_IP_BUF->proto == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type == ICMP6_NS && uip_ipaddr_prefixcmp(&wsn_net_prefix, &UIP_ND6_NS_BUF->tgtipaddr, 64)) || uip_ipaddr_prefixcmp(&wsn_net_prefix, &UIP_IP_BUF->srcipaddr, 64)) { wsnDest = 1; } } if(wsnDest || IS_EUI64_ADDR(dest)) { wireless_output(NULL, dest); } else { eth_output(NULL, dest); } return 0; }
/*---------------------------------------------------------------------------*/ void cetic_6lbr_set_prefix(uip_ipaddr_t * prefix, unsigned len, uip_ipaddr_t * ipaddr) { #if CETIC_6LBR_SMARTBRIDGE int new_prefix = !uip_ipaddr_prefixcmp(&wsn_net_prefix, prefix, len); int new_dag_prefix = cetic_dag == NULL || !uip_ipaddr_prefixcmp(&cetic_dag->prefix_info.prefix, prefix, len); if((nvm_data.mode & CETIC_MODE_WAIT_RA_MASK) == 0) { LOG6LBR_DEBUG("Ignoring RA\n"); return; } if(new_prefix) { LOG6LBR_6ADDR(INFO, prefix, "Setting prefix : "); uip_ipaddr_copy(&wsn_ip_addr, ipaddr); uip_ipaddr_copy(&wsn_net_prefix, prefix); wsn_net_prefix_len = len; LOG6LBR_6ADDR(INFO, &wsn_ip_addr, "Tentative global IPv6 address : "); #if CONTIKI_TARGET_NATIVE cetic_6lbr_save_ip(); #endif } if(new_dag_prefix) { if((nvm_data.rpl_config & CETIC_6LBR_MODE_GLOBAL_DODAG) != 0) { cetic_dag = rpl_set_root(nvm_data.rpl_instance_id, &wsn_ip_addr); rpl_set_prefix(cetic_dag, prefix, len); LOG6LBR_6ADDR(INFO, &cetic_dag->dag_id, "Configured as DODAG Root "); } else { rpl_set_prefix(cetic_dag, prefix, len); LOG6LBR_6ADDR(INFO, prefix, "Setting DAG prefix : "); rpl_repair_root(RPL_DEFAULT_INSTANCE); } } #endif }
/*---------------------------------------------------------------------------*/ uint8_t uip_ds6_list_loop(uip_ds6_element_t *list, uint8_t size, uint16_t elementsize, uip_ipaddr_t *ipaddr, uint8_t ipaddrlen, uip_ds6_element_t **out_element) { uip_ds6_element_t *element; *out_element = NULL; for(element = list; element < (uip_ds6_element_t *)((uint8_t *)list + (size * elementsize)); element = (uip_ds6_element_t *)((uint8_t *)element + elementsize)) { if(element->isused) { if(uip_ipaddr_prefixcmp(&element->ipaddr, ipaddr, ipaddrlen)) { *out_element = element; return FOUND; } } else { *out_element = element; } } return *out_element != NULL ? FREESPACE : NOSPACE; }
/*---------------------------------------------------------------------------*/ u8_t uip_ds6_list_loop(uip_ds6_element_t * list, u8_t size, u16_t elementsize, uip_ipaddr_t * ipaddr, u8_t ipaddrlen, uip_ds6_element_t ** out_element) { uip_ds6_element_t *element; *out_element = NULL; for(element = list; element < (uip_ds6_element_t *) ((u8_t *) list + (size * elementsize)); element = (uip_ds6_element_t *) ((u8_t *) element + elementsize)) { // printf("+ %p %d\n", &element->isused, element->isused); if(element->isused) { if(uip_ipaddr_prefixcmp(&(element->ipaddr), ipaddr, ipaddrlen)) { *out_element = element; return FOUND; } } else { *out_element = element; } } if(*out_element != NULL) { return FREESPACE; } else { return NOSPACE; } }
/*---------------------------------------------------------------------------*/ 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; }
void cetic_6lbr_set_prefix(uip_ipaddr_t * prefix, unsigned len, uip_ipaddr_t * ipaddr) { #if CETIC_6LBR_SMARTBRIDGE int new_prefix = cetic_dag != NULL && !uip_ipaddr_prefixcmp(&cetic_dag->prefix_info.prefix, prefix, len); if((nvm_data.mode & CETIC_MODE_WAIT_RA_MASK) == 0) { LOG6LBR_DEBUG("Ignoring RA\n"); return; } LOG6LBR_INFO("CETIC_BRIDGE : set_prefix\n"); uip_ipaddr_copy(&wsn_ip_addr, ipaddr); if(cetic_dag != NULL) { rpl_set_prefix(cetic_dag, prefix, len); uip_ipaddr_copy(&wsn_net_prefix, prefix); wsn_net_prefix_len = len; if(new_prefix) { LOG6LBR_6ADDR(INFO, prefix, "Setting DAG prefix : "); rpl_repair_root(RPL_DEFAULT_INSTANCE); } } #if CONTIKI_TARGET_NATIVE cetic_6lbr_save_ip(); #endif #endif }
/*---------------------------------------------------------------------------*/ uip_ds6_route_t * uip_ds6_route_lookup(uip_ipaddr_t *destipaddr) { uip_ds6_route_t *locrt = NULL; uint8_t longestmatch = 0; PRINTF("DS6: Looking up route for "); PRINT6ADDR(destipaddr); PRINTF("\n"); for(locroute = uip_ds6_routing_table; locroute < uip_ds6_routing_table + UIP_DS6_ROUTE_NB; locroute++) { if((locroute->isused) && (locroute->length >= longestmatch) && (uip_ipaddr_prefixcmp (destipaddr, &locroute->ipaddr, locroute->length))) { longestmatch = locroute->length; locrt = locroute; } } if(locrt != NULL) { PRINTF("DS6: Found route:"); PRINT6ADDR(destipaddr); PRINTF(" via "); PRINT6ADDR(&locrt->nexthop); PRINTF("\n"); } else { PRINTF("DS6: No route found\n"); } return locrt; }
/*---------------------------------------------------------------------------*/ static void check_prefix(rpl_prefix_t *last_prefix, rpl_prefix_t *new_prefix) { uip_ipaddr_t ipaddr; uip_ds6_addr_t *rep; if(last_prefix != NULL && new_prefix != NULL && last_prefix->length == new_prefix->length && uip_ipaddr_prefixcmp(&last_prefix->prefix, &new_prefix->prefix, new_prefix->length) && last_prefix->flags == new_prefix->flags) { /* Nothing has changed. */ return; } if(last_prefix != NULL) { set_ip_from_prefix(&ipaddr, last_prefix); rep = uip_ds6_addr_lookup(&ipaddr); if(rep != NULL) { PRINTF("RPL: removing global IP address "); PRINT6ADDR(&ipaddr); PRINTF("\n"); uip_ds6_addr_rm(rep); } } if(new_prefix != NULL) { set_ip_from_prefix(&ipaddr, new_prefix); if(uip_ds6_addr_lookup(&ipaddr) == NULL) { PRINTF("RPL: adding global IP address "); PRINT6ADDR(&ipaddr); PRINTF("\n"); uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); } } }
/*---------------------------------------------------------------------------*/ struct uip_netif_addr * uip_netif_addr_lookup(uip_ipaddr_t *ipaddr, u8_t length, uip_netif_type type) { for(i = 0; i < UIP_CONF_NETIF_MAX_ADDRESSES; i ++) { if((uip_netif_physical_if.addresses[i].state != NOT_USED) && (uip_netif_physical_if.addresses[i].type == type || type == 0) && (uip_ipaddr_prefixcmp(&(uip_netif_physical_if.addresses[i].ipaddr), ipaddr, length))) { return &uip_netif_physical_if.addresses[i]; } } return NULL; }
/*---------------------------------------------------------------------------*/ uint8_t uip_ds6_is_addr_onlink(uip_ipaddr_t *ipaddr) { for(locprefix = uip_ds6_prefix_list; locprefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB; locprefix++) { if(locprefix->isused && uip_ipaddr_prefixcmp(&locprefix->ipaddr, ipaddr, locprefix->length)) { return 1; } } return 0; }
/*---------------------------------------------------------------------------*/ uip_ds6_prefix_t * uip_ds6_prefix_lookup_from_ipaddr(uip_ipaddr_t *ipaddr) { for(locprefix = uip_ds6_prefix_list; locprefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB; locprefix++) { if(locprefix->isused && uip_ipaddr_prefixcmp(&locprefix->ipaddr, ipaddr, locprefix->length)) { return locprefix; } } return NULL; }
/*---------------------------------------------------------------------------*/ uip_ds6_context_pref_t * uip_ds6_context_pref_lookup(uip_ipaddr_t *ipaddr) { for(loccontext = uip_ds6_context_pref_list; loccontext < uip_ds6_context_pref_list + UIP_DS6_CONTEXT_PREF_NB; loccontext++) { if(loccontext->state != CONTEXT_PREF_ST_FREE && uip_ipaddr_prefixcmp(ipaddr, &loccontext->ipaddr, loccontext->length)) { return loccontext; } } return NULL; }
pgw_addr_context_t* pgw_context_lookup_by_prefix(uip_ipaddr_t *prefix) { for(loccontext = pgw_addr_context_table; loccontext < pgw_addr_context_table + SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS; loccontext++) { if(loccontext->state != NOT_IN_USE) { if (uip_ipaddr_prefixcmp(prefix, &loccontext->prefix, loccontext->length)) { return loccontext; } } } return NULL; }
static uint8_t bridge_output(uip_lladdr_t * dest) { int ethernetDest = 0; if(uip_len == 0) { LOG6LBR_ERROR("Trying to send empty packet\n"); return 0; } if(!IS_BROADCAST_ADDR(dest)) { LOG6LBR_LLADDR_PRINTF(PACKET, PF_OUT, dest, "bridge_output: Sending packet to "); } else { LOG6LBR_PRINTF(PACKET, PF_OUT, "bridge_output: Sending packet to Broadcast\n"); } if(IS_BROADCAST_ADDR(dest)) { //Obviously we can not guess the target segment for a multicast packet //So we have to check the packet source prefix (and match it on the Ethernet segment prefix) //or, in case of link-local packet, check packet type and/or packet data if((UIP_IP_BUF->proto == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type == ICMP6_RA) || (UIP_IP_BUF->proto == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type == ICMP6_NS && uip_ipaddr_prefixcmp(ð_net_prefix, &UIP_ND6_NS_BUF->tgtipaddr, 64)) || uip_ipaddr_prefixcmp(ð_net_prefix, &UIP_IP_BUF->srcipaddr, 64)) { ethernetDest = 1; } } if(ethernetDest || IS_EUI48_ADDR(dest)) { eth_output(NULL, dest); } else { #if CETIC_6LBR_ONE_ITF eth_output(&wsn_mac_addr, dest); #else wireless_output(NULL, dest); #endif } return 0; }
/*---------------------------------------------------------------------------*/ uip_ds6_route_t * uip_ds6_route_lookup(uip_ipaddr_t *destipaddr) { uip_ds6_route_t *locrt = NULL; uint8_t longestmatch = 0; PRINTF("DS6: Looking up route for "); PRINT6ADDR(destipaddr); PRINTF("\n"); for(locroute = uip_ds6_routing_table; locroute < uip_ds6_routing_table + UIP_DS6_ROUTE_NB; locroute++) { if((locroute->isused) && (locroute->length >= longestmatch) && (uip_ipaddr_prefixcmp (destipaddr, &locroute->ipaddr, locroute->length))) { longestmatch = locroute->length; locrt = locroute; } } if(locrt != NULL) { #ifdef UIP_DS6_ROUTE_STATE_CLEAN switch (locrt->state.learned_from) { case RPL_ROUTE_FROM_UNICAST_DAO: case RPL_ROUTE_FROM_MULTICAST_DAO: case RPL_ROUTE_FROM_DIO: if(UIP_DS6_ROUTE_STATE_CLEAN(&locrt->state)) { uip_ds6_route_rm(locrt); //TODO : verify that the prefix len is 128 mob_lost_node(locrt); PRINTF("DS6: Route timeout\n"); return NULL; } break; default: break; } #endif /* UIP_DS6_ROUTE_STATE_TYPE */ PRINTF("DS6: Found route:"); PRINT6ADDR(destipaddr); PRINTF(" via "); PRINT6ADDR(&locrt->nexthop); PRINTF("\n"); } else { PRINTF("DS6: No route found\n"); } return locrt; }
/*---------------------------------------------------------------------------*/ 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; }
/** * \brief Searches for a context by prefix. * * \param length The length of the prefix that is valid * * \param prefix The prefix of the context to search. * * \returns If found, returns a pointer to the context. Otherwise * returns NULL. */ uip_ds6_addr_context_t *uip_ds6_context_lookup_by_prefix(uip_ipaddr_t *prefix) { uip_ds6_addr_context_t* context; for(context = uip_ds6_addr_context_table; context < uip_ds6_addr_context_table + SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS; context++) { if(context->state != NOT_IN_USE) { if (uip_ipaddr_prefixcmp(prefix, &context->prefix, context->length)) { return context; } } } return NULL; }
/** \brief find the context corresponding to prefix ipaddr */ static struct sicslowpan_addr_context* addr_context_lookup_by_prefix(uip_ipaddr_t *ipaddr) { /* Remove code to avoid warnings and save flash if no context is used */ #if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0 int i; for(i = 0; i < SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS; i++) { if((addr_contexts[i].used == 1) && uip_ipaddr_prefixcmp(&addr_contexts[i].prefix, ipaddr, 64)) { return &addr_contexts[i]; } } #endif /* SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0 */ return NULL; }
/*---------------------------------------------------------------------------*/ uint8_t uip_ds6_is_addr_onlink(uip_ipaddr_t *ipaddr) { #if CONF_6LOWPAN_ND return uip_is_addr_link_local(ipaddr); #else /* CONF_6LOWPAN_ND */ for(locprefix = uip_ds6_prefix_list; locprefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB; locprefix++) { if(locprefix->isused && uip_ipaddr_prefixcmp(&locprefix->ipaddr, ipaddr, locprefix->length)) { return 1; } } return 0; #endif /* CONF_6LOWPAN_ND */ }
/*---------------------------------------------------------------------------*/ 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; }
int rpl_matching_used_prefix(uip_ipaddr_t *prefix) { int i; rpl_instance_t *instance, *end; for(instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES; instance < end; ++instance) { if(instance->used) { for(i = 0; i < RPL_MAX_DODAG_PER_INSTANCE; ++i) { if((instance->dag_table[i].used) && (uip_ipaddr_prefixcmp(&instance->dag_table[i].prefix_info.prefix, prefix, instance->dag_table[i].prefix_info.length))) { return 1; } } } } return 0; }
/*---------------------------------------------------------------------------*/ 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; }
static uint8_t bridge_output(const uip_lladdr_t * dest) { int ethernetDest = 0; int wsnDest = 0; if(uip_len == 0) { LOG6LBR_ERROR("Trying to send empty packet\n"); return 0; } if(!IS_BROADCAST_ADDR(dest)) { LOG6LBR_LLADDR_PRINTF(PACKET, PF_OUT, dest, "bridge_output: Sending packet to "); } else { LOG6LBR_PRINTF(PACKET, PF_OUT, "bridge_output: Sending packet to Broadcast\n"); } if(uip_ipaddr_prefixcmp(ð_net_prefix, &UIP_IP_BUF->destipaddr, 64)) { LOG6LBR_6ADDR_PRINTF(PACKET, PF_OUT, ð_net_prefix, "dest prefix eth : "); LOG6LBR_6ADDR_PRINTF(PACKET, PF_OUT, &UIP_IP_BUF->destipaddr, "dest eth : "); //Packet destinated to the Ethernet subnet ethernetDest = 1; } else if(uip_ipaddr_prefixcmp(&wsn_net_prefix, &UIP_IP_BUF->destipaddr, 64)) { LOG6LBR_6ADDR_PRINTF(PACKET, PF_OUT, &wsn_net_prefix, "dest prefix wsn : "); LOG6LBR_6ADDR_PRINTF(PACKET, PF_OUT, &UIP_IP_BUF->destipaddr, "dest prefix wsn : "); //Packet destinated to the WSN subnet wsnDest = 1; } else if(IS_EUI64_ADDR(dest)) { //Destination unknown but next-hop is in WSN subnet wsnDest = 1; } else if (IS_EUI48_ADDR(dest)) { //Destination unknown but next-hop is in Ethernet subnet ethernetDest = 1; } else { //Obviously we can not guess the target segment for a multicast packet //So we have to check the packet source prefix (and match it on the Ethernet segment prefix) //or, in case of link-local packet, check packet type and/or packet data #if UIP_CONF_IPV6_RPL //in RPL mode, RA and RS packets are used to configure the Ethernet subnet if(UIP_IP_BUF->proto == UIP_PROTO_ICMP6 && (UIP_ICMP_BUF->type == ICMP6_RA || UIP_ICMP_BUF->type == ICMP6_RS)) { ethernetDest = 1; } else if (UIP_IP_BUF->proto == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type == ICMP6_NS && uip_ipaddr_prefixcmp(ð_net_prefix, &UIP_ND6_NS_BUF->tgtipaddr, 64)) { ethernetDest = 1; #else //in NDP mode, RA and RS packets are used to configure the WSN subnet if(UIP_IP_BUF->proto == UIP_PROTO_ICMP6 && (UIP_ICMP_BUF->type == ICMP6_RA || UIP_ICMP_BUF->type == ICMP6_RS)) { wsnDest = 1; } else if (UIP_IP_BUF->proto == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type == ICMP6_NS && uip_ipaddr_prefixcmp(&wsn_net_prefix, &UIP_ND6_NS_BUF->tgtipaddr, 64)) { wsnDest = 1; #endif } else if(UIP_IP_BUF->proto == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type == ICMP6_RPL) { //RPL packets are always for WSN subnet wsnDest = 1; } else if(uip_ipaddr_prefixcmp(ð_net_prefix, &UIP_IP_BUF->srcipaddr, 64)) { //Packet type unknown, but source is from Ethernet subnet ethernetDest = 1; } else if(uip_ipaddr_prefixcmp(&wsn_net_prefix, &UIP_IP_BUF->srcipaddr, 64)) { //Packet type unknown, but source is from WSN subnet wsnDest = 1; } else { // We could not guess the destination, forward to both ethernetDest = 1; wsnDest = 1; } } if(wsnDest) { #if CETIC_6LBR_ONE_ITF eth_output(&wsn_mac_addr, dest); #else wireless_output(NULL, dest); #endif } if(ethernetDest) { eth_output(NULL, dest); } return 0; } #endif /*---------------------------------------------------------------------------*/ void packet_filter_init(void) { wireless_outputfunc = tcpip_get_outputfunc(); tcpip_set_outputfunc(bridge_output); tcpip_inputfunc = tcpip_get_inputfunc(); tcpip_set_inputfunc(wireless_input); }
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(); }