void recv_rtr_adv(void) { int8_t trigger_ns = -1; int8_t abro_found = 0; int16_t abro_version = 0; /* later replaced, just to supress warnings */ ipv6_addr_t abro_addr; ipv6_buf = get_ipv6_buf(); opt_hdr_len = RTR_ADV_LEN; rtr_adv_buf = get_rtr_adv_buf(ipv6_ext_hdr_len); ipv6_addr_t newaddr; recvd_cids_len = 0; /* update interface reachable time and retrans timer */ if (rtr_adv_buf->reachable_time != 0) { iface.adv_reachable_time = HTONL(rtr_adv_buf->reachable_time); } if (rtr_adv_buf->retrans_timer != 0) { iface.adv_retrans_timer = HTONL(rtr_adv_buf->retrans_timer); } def_rtr_entry = def_rtr_lst_search(&ipv6_buf->srcaddr); if (rtr_adv_buf->router_lifetime != 0) { if (def_rtr_entry != NULL) { set_remaining_time(&(def_rtr_entry->inval_time), HTONL(rtr_adv_buf->router_lifetime)); } else { def_rtr_lst_add(&(ipv6_buf->srcaddr), HTONL(rtr_adv_buf->router_lifetime)); trigger_ns = 1; } } else { /* remove router from default router list */ if (def_rtr_entry != NULL) { def_rtr_lst_rem(def_rtr_entry); } } mutex_lock(&lowpan_context_mutex); /* read options */ while (packet_length > IPV6HDR_ICMPV6HDR_LEN + opt_hdr_len) { opt_buf = get_opt_buf(ipv6_ext_hdr_len, opt_hdr_len); switch(opt_buf->type) { case (OPT_SLLAO_TYPE): { break; } case (OPT_MTU_TYPE): { break; } /* rfc 4862 section 5.5.3 */ case (OPT_PI_TYPE): { opt_pi_buf = get_opt_pi_buf(ipv6_ext_hdr_len, opt_hdr_len); /* crazy condition, read 5.5.3a-b-c for further information */ if (ipv6_prefix_ll_match(&opt_pi_buf->addr) || (HTONL(opt_pi_buf->pref_ltime) > HTONL(opt_pi_buf->val_ltime))) { break; } else { /* check if on-link flag is set */ if (opt_pi_buf->l_a_reserved1 & OPT_PI_FLAG_L) { /* TODO: do on-link pi handling */ } if (opt_pi_buf->l_a_reserved1 & OPT_PI_FLAG_A) { addr_list_ptr = ipv6_iface_addr_prefix_eq(&opt_pi_buf->addr); if (addr_list_ptr == NULL) { /* 5.5.3d */ if (opt_pi_buf->val_ltime != 0) { /* iid will also be added here */ ipv6_init_addr_prefix(&newaddr, &opt_pi_buf->addr); /* add into address list * TODO: duplicate address detection is not * implementet yet, so all new addresse will * be added with state PREFFERED */ ipv6_iface_add_addr(&newaddr, ADDR_STATE_PREFERRED, opt_pi_buf->val_ltime, opt_pi_buf->pref_ltime, ADDR_CONFIGURED_AUTO); printf("INFO: added address to interface\n"); trigger_ns = 1; } } else { /* 5.5.3e */ set_remaining_time(&(addr_list_ptr->pref_ltime), opt_pi_buf->pref_ltime); /* 7200 = 2hours in seconds */ if (HTONL(opt_pi_buf->val_ltime) > 7200 || HTONL(opt_pi_buf->val_ltime) > get_remaining_time(&(addr_list_ptr->val_ltime))) { set_remaining_time(&(addr_list_ptr->val_ltime), HTONL(opt_pi_buf->val_ltime)); } else { /* reset valid lifetime to 2 hours */ set_remaining_time(&(addr_list_ptr->val_ltime), 7200); } } } } /* TODO: save found prefixes */ break; } case (OPT_6CO_TYPE): { uint8_t comp; uint8_t num; opt_6co_hdr_buf = get_opt_6co_hdr_buf(ipv6_ext_hdr_len, opt_hdr_len); get_opt_6co_flags(&comp, &num, opt_6co_hdr_buf->c_flags); ipv6_addr_t prefix; memset(&prefix, 0, 16); opt_6co_prefix_buf = get_opt_6co_prefix_buf(ipv6_ext_hdr_len, opt_hdr_len + OPT_6CO_HDR_LEN); memcpy(&prefix, opt_6co_prefix_buf, opt_6co_hdr_buf->c_length); lowpan_context_update( num, &prefix, opt_6co_hdr_buf->c_length, comp, HTONS(opt_6co_hdr_buf->val_ltime) ); recvd_cids[recvd_cids_len] = num; recvd_cids_len = (recvd_cids_len + 1) % LOWPAN_CONTEXT_MAX; break; } case (OPT_ABRO_TYPE): { opt_abro_buf = get_opt_abro_buf(ipv6_ext_hdr_len, opt_hdr_len); abro_found = 1; abro_version = HTONS(opt_abro_buf->version); memcpy(&(abro_addr), &(opt_abro_buf->addr), sizeof(ipv6_addr_t)); break; } default: break; } /* multiplied with 8 because options length is in units of 8 bytes */ opt_hdr_len += (opt_buf->length * 8); } if (abro_found) { int i; for (i = 0; i < recvd_cids_len; i++) { abr_add_context(abro_version, &abro_addr, recvd_cids[i]); } } mutex_unlock(&lowpan_context_mutex, 0); if (trigger_ns >= 0) { /* send ns - draft-ietf-6lowpan-nd-15#section-5.5.1 * * section-10.2.4 * "Next the 6LN registers that address with one or more of its * default routers by sending a unicast NS message with an ARO * containing its tentative global IPv6 address to register * * if new address was configured, set src to newaddr(gp16) */ init_nbr_sol(&newaddr, &(ipv6_buf->srcaddr), &(ipv6_buf->srcaddr), OPT_SLLAO, OPT_ARO); #if ENABLE_DEBUG printf("INFO: send neighbor solicitation to: "); ipv6_print_addr(&(ipv6_buf->destaddr)); #endif lowpan_init((ieee_802154_long_t *) & (ipv6_buf->destaddr.uint16[4]), (uint8_t *)ipv6_buf); } }
void demultiplex(border_packet_t *packet) { switch (packet->type) { case (BORDER_PACKET_RAW_TYPE): { fputs(((char *)packet) + sizeof(border_packet_t), stdin); break; } case (BORDER_PACKET_L3_TYPE): { border_l3_header_t *l3_header_buf = (border_l3_header_t *)packet; switch (l3_header_buf->ethertype) { case (BORDER_ETHERTYPE_IPV6): { ipv6_hdr_t *ipv6_buf = (ipv6_hdr_t *)(((unsigned char *)packet) + sizeof(border_l3_header_t)); ipv6_send_packet(ipv6_buf); break; } default: printf("ERROR: Unknown ethertype 0x%04x\n", l3_header_buf->ethertype); break; } break; } case (BORDER_PACKET_CONF_TYPE): { border_conf_header_t *conf_header_buf = (border_conf_header_t *)packet; switch (conf_header_buf->conftype) { case (BORDER_CONF_CONTEXT): { border_context_packet_t *context = (border_context_packet_t *)packet; ipv6_addr_t target_addr; ipv6_addr_set_all_nodes_addr(&target_addr); mutex_lock(&lowpan_context_mutex); lowpan_context_update( context->context.cid, &context->context.prefix, context->context.length, context->context.comp, context->context.lifetime ); mutex_unlock(&lowpan_context_mutex); abr_add_context(context->context.version, abr_addr, context->context.cid); /* Send router advertisement */ break; } case (BORDER_CONF_IPADDR): { //border_addr_packet_t *addr_packet = (border_addr_packet_t *)packet; /* add address */ break; } default: printf("ERROR: Unknown conftype %02x\n", conf_header_buf->conftype); break; } break; } default: printf("ERROR: Unknown border packet type %02x\n", packet->type); break; } }