示例#1
0
static inline void _set_reach_time(gnrc_ipv6_netif_t *if_entry, uint32_t mean)
{
    uint32_t reach_time = genrand_uint32_range(GNRC_NDP_MIN_RAND, GNRC_NDP_MAX_RAND);

    if_entry->reach_time_base = mean;
    /* to avoid floating point number computation and have higher value entropy, the
     * boundaries for the random value are multiplied by 10 and we need to account for that */
    reach_time = (reach_time * if_entry->reach_time_base) / 10;
    if_entry->reach_time = reach_time;
}
示例#2
0
文件: ng_ndp.c 项目: Lexandro92/RIOT
void ng_ndp_netif_add(ng_ipv6_netif_t *iface)
{
    uint32_t reach_time = genrand_uint32_range(NG_NDP_MIN_RAND, NG_NDP_MAX_RAND);

    /* set default values */
    mutex_lock(&iface->mutex);
    iface->reach_time_base = NG_NDP_REACH_TIME;
    reach_time = (reach_time * iface->reach_time_base) / 10;
    iface->reach_time = timex_set(0, reach_time);
    timex_normalize(&iface->reach_time);
    iface->retrans_timer = timex_set(0, NG_NDP_RETRANS_TIMER);
    timex_normalize(&iface->retrans_timer);
    mutex_unlock(&iface->mutex);
}
示例#3
0
static void _send_rtr_adv(gnrc_ipv6_netif_t *iface, ipv6_addr_t *dst)
{
    bool fin;
    uint32_t interval;

    mutex_lock(&iface->mutex);
    fin = (iface->adv_ltime == 0);
    assert((iface->min_adv_int != 0) && (iface->max_adv_int != 0));
    interval = genrand_uint32_range(iface->min_adv_int, iface->max_adv_int);
    if (!fin && !((iface->flags | GNRC_IPV6_NETIF_FLAGS_ROUTER) &&
                  (iface->flags | GNRC_IPV6_NETIF_FLAGS_RTR_ADV))) {
        DEBUG("ndp rtr: interface %" PRIkernel_pid " is not an advertising interface\n",
              iface->pid);
        return;
    }
    if (iface->rtr_adv_count > 1) { /* regard for off-by-one error */
        iface->rtr_adv_count--;
        if (!fin && (interval > GNRC_NDP_MAX_INIT_RTR_ADV_INT)) {
            interval = GNRC_NDP_MAX_INIT_RTR_ADV_INT;
        }
    }
    if (!fin || (iface->rtr_adv_count > 1)) {   /* regard for off-by-one-error */
        /* reset timer for next router advertisement */
        xtimer_remove(&iface->rtr_adv_timer);
        iface->rtr_adv_msg.type = GNRC_NDP_MSG_RTR_ADV_RETRANS;
        iface->rtr_adv_msg.content.ptr = (char *) iface;
        xtimer_set_msg(&iface->rtr_adv_timer, interval * SEC_IN_USEC, &iface->rtr_adv_msg,
                       gnrc_ipv6_pid);
    }
    mutex_unlock(&iface->mutex);
    for (int i = 0; i < GNRC_IPV6_NETIF_ADDR_NUMOF; i++) {
        ipv6_addr_t *src = &iface->addrs[i].addr;

        if (!ipv6_addr_is_unspecified(src) && ipv6_addr_is_link_local(src) &&
            !gnrc_ipv6_netif_addr_is_non_unicast(src)) {
            /* send one for every link local address (ideally there is only one) */
            gnrc_ndp_internal_send_rtr_adv(iface->pid, src, dst, fin);
        }
    }
}
示例#4
0
static int _implicit_bind(socket_t *s, void *addr)
{
    ipv6_addr_t unspec;
    ipv6_addr_t *best_match;
    int res;

    /* TODO: ensure that this port hasn't been used yet */
    s->src_port = (uint16_t)genrand_uint32_range(1LU << 10U, 1LU << 16U);

    /* find the best matching source address */
    if ((best_match = conn_find_best_source(addr)) == NULL) {
        ipv6_addr_set_unspecified(&unspec);
        best_match = &unspec;
    }
    switch (s->type) {
#ifdef MODULE_CONN_TCP
        case SOCK_STREAM:
            res = conn_tcp_create(&s->conn.udp, best_match, sizeof(unspec),
                                  s->domain, s->src_port);
            break;
#endif
#ifdef MODULE_CONN_UDP
        case SOCK_DGRAM:
            res = conn_udp_create(&s->conn.udp, best_match, sizeof(unspec),
                                  s->domain, s->src_port);
            break;
#endif
        default:
            res = -1;
            break;
    }
    if (res < 0) {
        errno = -res;
    }
    else {
        s->bound = true;
    }
    return res;
}
示例#5
0
void gnrc_ndp_internal_send_nbr_adv(kernel_pid_t iface, ipv6_addr_t *tgt, ipv6_addr_t *dst,
                                    bool supply_tl2a, gnrc_pktsnip_t *ext_opts)
{
    gnrc_pktsnip_t *hdr, *pkt = ext_opts;
    uint8_t adv_flags = 0;

    DEBUG("ndp internal: send neighbor advertisement (iface: %" PRIkernel_pid ", tgt: %s, ",
          iface, ipv6_addr_to_str(addr_str, tgt, sizeof(addr_str)));
    DEBUG("dst: %s, supply_tl2a: %d)\n",
          ipv6_addr_to_str(addr_str, dst, sizeof(addr_str)), supply_tl2a);

    if ((gnrc_ipv6_netif_get(iface)->flags & GNRC_IPV6_NETIF_FLAGS_ROUTER) &&
        (gnrc_ipv6_netif_get(iface)->flags & GNRC_IPV6_NETIF_FLAGS_RTR_ADV)) {
        adv_flags |= NDP_NBR_ADV_FLAGS_R;
    }

    if (ipv6_addr_is_unspecified(dst)) {
        ipv6_addr_set_all_nodes_multicast(dst, IPV6_ADDR_MCAST_SCP_LINK_LOCAL);
    }
    else {
        adv_flags |= NDP_NBR_ADV_FLAGS_S;
    }

    if (supply_tl2a) {
        uint8_t l2src[8];
        size_t l2src_len;
        /* we previously checked if we are the target, so we can take our L2src */
        l2src_len = _get_l2src(iface, l2src, sizeof(l2src));

        if (l2src_len > 0) {
            /* add target address link-layer address option */
            pkt = gnrc_ndp_opt_tl2a_build(l2src, l2src_len, pkt);

            if (pkt == NULL) {
                DEBUG("ndp internal: error allocating Target Link-layer address option.\n");
                gnrc_pktbuf_release(ext_opts);
                return;
            }
        }
    }

    /* TODO: also check if the node provides proxy servies for tgt */
    if ((pkt != NULL) && !gnrc_ipv6_netif_addr_is_non_unicast(tgt)) {
        /* TL2A is not supplied and tgt is not anycast */
        adv_flags |= NDP_NBR_ADV_FLAGS_O;
    }

    hdr = gnrc_ndp_nbr_adv_build(adv_flags, tgt, pkt);

    if (hdr == NULL) {
        DEBUG("ndp internal: error allocating Neighbor advertisement.\n");
        gnrc_pktbuf_release(pkt);
        return;
    }
    pkt = hdr;
    hdr = _build_headers(iface, pkt, dst, NULL);
    if (hdr == NULL) {
        DEBUG("ndp internal: error adding lower-layer headers.\n");
        gnrc_pktbuf_release(pkt);
        return;
    }
    if (gnrc_ipv6_netif_addr_is_non_unicast(tgt)) {
        /* avoid collision for anycast addresses
         * (see https://tools.ietf.org/html/rfc4861#section-7.2.7) */
        uint32_t delay = genrand_uint32_range(0, GNRC_NDP_MAX_AC_TGT_DELAY * SEC_IN_USEC);
        gnrc_ipv6_nc_t *nc_entry = gnrc_ipv6_nc_get(iface, dst);
        DEBUG("ndp internal: delay neighbor advertisement for %" PRIu32 " sec.",
              (delay / SEC_IN_USEC));

        /* nc_entry must be set so no need to check it */
        assert(nc_entry);

        _send_delayed(&nc_entry->nbr_adv_timer, &nc_entry->nbr_adv_msg, delay, hdr);
    }
    else if (gnrc_netapi_send(gnrc_ipv6_pid, hdr) < 1) {
        DEBUG("ndp internal: unable to send neighbor advertisement\n");
        gnrc_pktbuf_release(hdr);
    }
}
示例#6
0
static inline uint32_t _binary_exp_backoff(uint32_t base_sec, unsigned int exp)
{
    return genrand_uint32_range(0, (1 << exp)) * base_sec;
}
示例#7
0
文件: gnrc_ndp.c 项目: Otmane123/RIOT
void gnrc_ndp_rtr_sol_handle(kernel_pid_t iface, gnrc_pktsnip_t *pkt,
                             ipv6_hdr_t *ipv6, ndp_rtr_sol_t *rtr_sol,
                             size_t icmpv6_size)
{
    gnrc_ipv6_netif_t *if_entry = gnrc_ipv6_netif_get(iface);

    if (if_entry->flags & GNRC_IPV6_NETIF_FLAGS_ROUTER) {
        int sicmpv6_size = (int)icmpv6_size, l2src_len = 0;
        uint8_t l2src[GNRC_IPV6_NC_L2_ADDR_MAX];
        uint16_t opt_offset = 0;
        uint8_t *buf = (uint8_t *)(rtr_sol + 1);
        /* check validity */
        if ((ipv6->hl != 255) || (rtr_sol->code != 0) ||
            (icmpv6_size < sizeof(ndp_rtr_sol_t))) {
            DEBUG("ndp: router solicitation was invalid\n");
            return;
        }
        sicmpv6_size -= sizeof(ndp_rtr_sol_t);
        while (sicmpv6_size > 0) {
            ndp_opt_t *opt = (ndp_opt_t *)(buf + opt_offset);

            switch (opt->type) {
                case NDP_OPT_SL2A:
                    if ((l2src_len = gnrc_ndp_internal_sl2a_opt_handle(pkt, ipv6, rtr_sol->type, opt,
                                                                       l2src)) < 0) {
                        /* -ENOTSUP can not happen */
                        /* invalid source link-layer address option */
                        return;
                    }
                    break;

                default:
                    /* silently discard all other options */
                    break;
            }

            opt_offset += (opt->len * 8);
            sicmpv6_size -= (opt->len * 8);

#if ENABLE_DEBUG
            if (sicmpv6_size < 0) {
                DEBUG("ndp: Option parsing out of sync.\n");
            }
#endif
        }
        _stale_nc(iface, &ipv6->src, l2src, l2src_len);
        /* send delayed */
        if (if_entry->flags & GNRC_IPV6_NETIF_FLAGS_RTR_ADV) {
            uint32_t delay;
            uint32_t ms = GNRC_NDP_MAX_RTR_ADV_DELAY;
#ifdef MODULE_GNRC_SIXLOWPAN_ND_ROUTER
            if (if_entry->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN) {
                ms = GNRC_SIXLOWPAN_ND_MAX_RTR_ADV_DELAY;
            }
#endif
            delay = genrand_uint32_range(0, ms);
            xtimer_remove(&if_entry->rtr_adv_timer);
#ifdef MODULE_GNRC_SIXLOWPAN_ND_ROUTER
            /* in case of a 6LBR we have to check if the interface is actually
             * the 6lo interface */
            if (if_entry->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN) {
                gnrc_ipv6_nc_t *nc_entry = gnrc_ipv6_nc_get(iface, &ipv6->src);
                if (nc_entry != NULL) {
                    if_entry->rtr_adv_msg.type = GNRC_NDP_MSG_RTR_ADV_SIXLOWPAN_DELAY;
                    if_entry->rtr_adv_msg.content.ptr = (char *) nc_entry;
                    xtimer_set_msg(&if_entry->rtr_adv_timer, delay, &if_entry->rtr_adv_msg,
                                   gnrc_ipv6_pid);
                }
            }
#elif defined(MODULE_GNRC_NDP_ROUTER) || defined(MODULE_GNRC_SIXLOWPAN_ND_BORDER_ROUTER)
            if (ipv6_addr_is_unspecified(&ipv6->src)) {
                /* either multicast, if source unspecified */
                if_entry->rtr_adv_msg.type = GNRC_NDP_MSG_RTR_ADV_RETRANS;
                if_entry->rtr_adv_msg.content.ptr = (char *) if_entry;
                xtimer_set_msg(&if_entry->rtr_adv_timer, delay, &if_entry->rtr_adv_msg,
                               gnrc_ipv6_pid);
            }
            else {
                /* or unicast, if source is known */
                /* XXX: can't just use GNRC_NETAPI_MSG_TYPE_SND, since the next retransmission
                 * must also be set. */
                gnrc_ipv6_nc_t *nc_entry = gnrc_ipv6_nc_get(iface, &ipv6->src);
                xtimer_set_msg(&nc_entry->rtr_adv_timer, delay, &nc_entry->rtr_adv_msg,
                               gnrc_ipv6_pid);
            }
#endif
        }
    }
    /* otherwise ignore silently */
}
示例#8
0
文件: gnrc_ndp.c 项目: popwolf/RIOT
void gnrc_ndp_rtr_sol_handle(kernel_pid_t iface, gnrc_pktsnip_t *pkt,
                             ipv6_hdr_t *ipv6, ndp_rtr_sol_t *rtr_sol,
                             size_t icmpv6_size)
{
    gnrc_ipv6_netif_t *if_entry = gnrc_ipv6_netif_get(iface);

    if (if_entry->flags & GNRC_IPV6_NETIF_FLAGS_ROUTER) {
        int sicmpv6_size = (int)icmpv6_size, l2src_len = 0;
        uint8_t l2src[GNRC_IPV6_NC_L2_ADDR_MAX];
        uint16_t opt_offset = 0;
        uint8_t *buf = (uint8_t *)(rtr_sol + 1);
        /* check validity */
        if ((ipv6->hl != 255) || (rtr_sol->code != 0) ||
            (icmpv6_size < sizeof(ndp_rtr_sol_t))) {
            DEBUG("ndp: router solicitation was invalid\n");
            return;
        }
        sicmpv6_size -= sizeof(ndp_rtr_sol_t);
        while (sicmpv6_size > 0) {
            ndp_opt_t *opt = (ndp_opt_t *)(buf + opt_offset);

            switch (opt->type) {
                case NDP_OPT_SL2A:
                    if ((l2src_len = gnrc_ndp_internal_sl2a_opt_handle(pkt, ipv6, rtr_sol->type, opt,
                                                                       l2src)) < 0) {
                        /* -ENOTSUP can not happen */
                        /* invalid source link-layer address option */
                        return;
                    }
                    break;

                default:
                    /* silently discard all other options */
                    break;
            }

            opt_offset += (opt->len * 8);
            sicmpv6_size -= (opt->len * 8);
        }
        _stale_nc(iface, &ipv6->src, l2src, l2src_len);
        /* send delayed */
        if (if_entry->flags & GNRC_IPV6_NETIF_FLAGS_RTR_ADV) {
            timex_t delay = timex_set(0, genrand_uint32_range(0, GNRC_NDP_MAX_RTR_ADV_DELAY));
            vtimer_remove(&if_entry->rtr_adv_timer);
            if (ipv6_addr_is_unspecified(&ipv6->src)) {
                /* either multicast, if source unspecified */
                vtimer_set_msg(&if_entry->rtr_adv_timer, delay, gnrc_ipv6_pid,
                               GNRC_NDP_MSG_RTR_ADV_RETRANS, if_entry);
            }
            else {
                /* or unicast, if source is known */
                /* XXX: can't just use GNRC_NETAPI_MSG_TYPE_SND, since the next retransmission
                 * must also be set. */
                gnrc_ipv6_nc_t *nc_entry = gnrc_ipv6_nc_get(iface, &ipv6->src);
                vtimer_set_msg(&if_entry->rtr_adv_timer, delay, gnrc_ipv6_pid,
                               GNRC_NDP_MSG_RTR_ADV_DELAY, nc_entry);
            }
        }
    }
    /* otherwise ignore silently */
}
示例#9
0
void ng_ndp_internal_send_nbr_adv(kernel_pid_t iface, ng_ipv6_addr_t *tgt,
                                  ng_ipv6_addr_t *dst, bool supply_tl2a)
{
    ng_pktsnip_t *hdr, *pkt = NULL;
    uint8_t adv_flags = 0;

    DEBUG("ndp internal: send neighbor advertisement (iface: %" PRIkernel_pid ", tgt: %s, ",
          iface, ng_ipv6_addr_to_str(addr_str, tgt, sizeof(addr_str)));
    DEBUG("dst: %s, supply_tl2a: %d)\n",
          ng_ipv6_addr_to_str(addr_str, dst, sizeof(addr_str)), supply_tl2a);

    if (ng_ipv6_netif_get(iface)->flags & NG_IPV6_NETIF_FLAGS_ROUTER) {
        adv_flags |= NG_NDP_NBR_ADV_FLAGS_R;
    }

    if (ng_ipv6_addr_is_unspecified(dst)) {
        ng_ipv6_addr_set_all_nodes_multicast(dst,
                                             NG_IPV6_ADDR_MCAST_SCP_LINK_LOCAL);
    }
    else {
        adv_flags |= NG_NDP_NBR_ADV_FLAGS_S;
    }

    if (supply_tl2a) {
        uint8_t l2src[8];
        uint16_t l2src_len;
        /* we previously checked if we are the target, so we can take our L2src */
        l2src_len = _get_l2src(l2src, sizeof(l2src), iface);

        if (l2src_len > 0) {
            /* add target address link-layer address option */
            pkt = ng_ndp_opt_tl2a_build(l2src, l2src_len, NULL);

            if (pkt == NULL) {
                DEBUG("ndp internal: error allocating Target Link-layer address option.\n");
                ng_pktbuf_release(pkt);
                return;
            }
        }
    }

    /* TODO: also check if the node provides proxy servies for tgt */
    if ((pkt != NULL) && !ng_ipv6_netif_addr_is_non_unicast(tgt)) {
        /* TL2A is not supplied and tgt is not anycast */
        adv_flags |= NG_NDP_NBR_ADV_FLAGS_O;
    }

    hdr = ng_ndp_nbr_adv_build(adv_flags, tgt, pkt);

    if (hdr == NULL) {
        DEBUG("ndp internal: error allocating Neighbor advertisement.\n");
        ng_pktbuf_release(pkt);
        return;
    }

    pkt = hdr;
    hdr = ng_ipv6_hdr_build(pkt, NULL, 0, (uint8_t *)dst,
                            sizeof(ng_ipv6_addr_t));

    if (hdr == NULL) {
        DEBUG("ndp internal: error allocating IPv6 header.\n");
        ng_pktbuf_release(pkt);
        return;
    }

    ((ng_ipv6_hdr_t *)hdr->data)->hl = 255;

    pkt = hdr;
    /* add netif header for send interface specification */
    hdr = ng_netif_hdr_build(NULL, 0, NULL, 0);

    if (hdr == NULL) {
        DEBUG("ndp internal: error allocating netif header.\n");
        return;
    }

    ((ng_netif_hdr_t *)hdr->data)->if_pid = iface;

    LL_PREPEND(pkt, hdr);

    if (ng_ipv6_netif_addr_is_non_unicast(tgt)) {
        /* avoid collision for anycast addresses
         * (see https://tools.ietf.org/html/rfc4861#section-7.2.7) */
        timex_t delay = { 0, genrand_uint32_range(0, NG_NDP_MAX_AC_TGT_DELAY * SEC_IN_USEC) };
        timex_normalize(&delay);
        ng_ipv6_nc_t *nc_entry = ng_ipv6_nc_get(iface, tgt);
        DEBUG("ndp internal: delay neighbor advertisement for %" PRIu32 " sec.",
              delay.seconds);

        /* nc_entry must be set so no need to check it */
        _send_delayed(&nc_entry->nbr_adv_timer, delay, pkt);
    }
    else {
        ng_netapi_send(ng_ipv6_pid, pkt);
    }
}