bool gnrc_sixlowpan_nd_router_abr_older(sixlowpan_nd_opt_abr_t *abr_opt) { gnrc_sixlowpan_nd_router_abr_t *abr; uint32_t version; if (abr_opt->len != SIXLOWPAN_ND_OPT_ABR_LEN) { /* invalid option received */ return true; } if (_is_me(&abr_opt->braddr)) { return false; } abr = _get_abr(&abr_opt->braddr); if (abr == NULL) { return false; } version = (uint32_t)byteorder_ntohs(abr_opt->vlow); version |= ((uint32_t)byteorder_ntohs(abr_opt->vhigh)) << 16; return (version < abr->version); }
/* router-only functions from net/gnrc/sixlowpan/nd.h */ void gnrc_sixlowpan_nd_opt_abr_handle(kernel_pid_t iface, ndp_rtr_adv_t *rtr_adv, int sicmpv6_size, sixlowpan_nd_opt_abr_t *abr_opt) { uint16_t opt_offset = 0; uint8_t *buf = (uint8_t *)(rtr_adv + 1); gnrc_sixlowpan_nd_router_abr_t *abr; timex_t t = { 0, 0 }; if (_is_me(&abr_opt->braddr)) { return; } /* validity and version was checked in previously called * gnrc_sixlowpan_nd_router_abr_older() */ abr = _get_abr(&abr_opt->braddr); if (abr == NULL) { return; } abr->ltime = byteorder_ntohs(abr_opt->ltime); if (abr->ltime == 0) { abr->ltime = GNRC_SIXLOWPAN_ND_BORDER_ROUTER_DEFAULT_LTIME; return; } sicmpv6_size -= sizeof(ndp_rtr_adv_t); while (sicmpv6_size > 0) { ndp_opt_t *opt = (ndp_opt_t *)(buf + opt_offset); switch (opt->type) { case NDP_OPT_PI: _add_prefix(iface, abr, (ndp_opt_pi_t *)opt); case NDP_OPT_6CTX: _add_ctx(abr, (sixlowpan_nd_opt_6ctx_t *)opt); default: break; } opt_offset += (opt->len * 8); sicmpv6_size -= (opt->len * 8); } abr->version = (uint32_t)byteorder_ntohs(abr_opt->vlow); abr->version |= ((uint32_t)byteorder_ntohs(abr_opt->vhigh)) << 16; abr->addr.u64[0] = abr_opt->braddr.u64[0]; abr->addr.u64[1] = abr_opt->braddr.u64[1]; memset(abr->ctxs, 0, sizeof(abr->ctxs)); abr->prfs = NULL; t.seconds = abr->ltime * 60; xtimer_remove(&abr->ltimer); abr->ltimer_msg.type = GNRC_SIXLOWPAN_ND_MSG_ABR_TIMEOUT; abr->ltimer_msg.content.ptr = (char *) abr; xtimer_set_msg(&abr->ltimer, (uint32_t) timex_uint64(t), &abr->ltimer_msg, gnrc_ipv6_pid); }