Пример #1
0
void gnrc_ndp_nbr_sol_handle(kernel_pid_t iface, gnrc_pktsnip_t *pkt,
                             ipv6_hdr_t *ipv6, ndp_nbr_sol_t *nbr_sol,
                             size_t icmpv6_size)
{
    uint16_t opt_offset = 0;
    uint8_t l2src[GNRC_IPV6_NC_L2_ADDR_MAX];
    uint8_t *buf = ((uint8_t *)nbr_sol) + sizeof(ndp_nbr_sol_t);
    ipv6_addr_t *tgt;
    int sicmpv6_size = (int)icmpv6_size, l2src_len = 0;
    DEBUG("ndp: received neighbor solicitation (src: %s, ",
          ipv6_addr_to_str(addr_str, &ipv6->src, sizeof(addr_str)));
    DEBUG("dst: %s, ",
          ipv6_addr_to_str(addr_str, &ipv6->dst, sizeof(addr_str)));
    DEBUG("tgt: %s)\n",
          ipv6_addr_to_str(addr_str, &nbr_sol->tgt, sizeof(addr_str)));
    /* check validity */
    if ((ipv6->hl != 255) || (nbr_sol->code != 0) ||
        (icmpv6_size < sizeof(ndp_nbr_sol_t)) ||
        ipv6_addr_is_multicast(&nbr_sol->tgt) ||
        (ipv6_addr_is_unspecified(&ipv6->src) &&
         ipv6_addr_is_solicited_node(&ipv6->dst))) {
        DEBUG("ndp: neighbor solicitation was invalid.\n");
        /* ipv6 releases */
        return;
    }
    if ((tgt = gnrc_ipv6_netif_find_addr(iface, &nbr_sol->tgt)) == NULL) {
        DEBUG("ndp: Target address is not to interface %" PRIkernel_pid "\n",
              iface);
        /* ipv6 releases */
        return;
    }
    sicmpv6_size -= sizeof(ndp_nbr_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, nbr_sol->type, opt,
                                                                   l2src)) < 0) {
                    /* -ENOTSUP can not happen, since the function only returns this for invalid
                     * message types containing the SL2A. Neighbor solicitations are not an
                     * invalid message type for SL2A. According to that, we don't need to watch
                     * out for that here, but regardless, the source link-layer address option
                     * is invalid. */
                    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);
    gnrc_ndp_internal_send_nbr_adv(iface, tgt, &ipv6->src, ipv6_addr_is_multicast(&ipv6->dst),
                                   NULL);
}
Пример #2
0
void gnrc_ndp_nbr_sol_handle(kernel_pid_t iface, gnrc_pktsnip_t *pkt,
                             ipv6_hdr_t *ipv6, ndp_nbr_sol_t *nbr_sol,
                             size_t icmpv6_size)
{
    uint16_t opt_offset = 0;
    uint8_t l2src[GNRC_IPV6_NC_L2_ADDR_MAX];
    uint8_t *buf = ((uint8_t *)nbr_sol) + sizeof(ndp_nbr_sol_t);
    ipv6_addr_t *tgt, nbr_adv_dst;
    gnrc_pktsnip_t *nbr_adv_opts = NULL;
#ifdef MODULE_GNRC_SIXLOWPAN_ND_ROUTER
    ndp_opt_t *sl2a_opt = NULL;
    sixlowpan_nd_opt_ar_t *ar_opt = NULL;
#endif
    int sicmpv6_size = (int)icmpv6_size, l2src_len = 0;
    DEBUG("ndp: received neighbor solicitation (src: %s, ",
          ipv6_addr_to_str(addr_str, &ipv6->src, sizeof(addr_str)));
    DEBUG("dst: %s, ",
          ipv6_addr_to_str(addr_str, &ipv6->dst, sizeof(addr_str)));
    DEBUG("tgt: %s)\n",
          ipv6_addr_to_str(addr_str, &nbr_sol->tgt, sizeof(addr_str)));
    /* check validity */
    if ((ipv6->hl != 255) || (nbr_sol->code != 0) ||
        (icmpv6_size < sizeof(ndp_nbr_sol_t)) ||
        ipv6_addr_is_multicast(&nbr_sol->tgt) ||
        (ipv6_addr_is_unspecified(&ipv6->src) &&
         ipv6_addr_is_solicited_node(&ipv6->dst))) {
        DEBUG("ndp: neighbor solicitation was invalid.\n");
        /* ipv6 releases */
        return;
    }
    if ((tgt = gnrc_ipv6_netif_find_addr(iface, &nbr_sol->tgt)) == NULL) {
        DEBUG("ndp: Target address is not to interface %" PRIkernel_pid "\n",
              iface);
        /* ipv6 releases */
        return;
    }
    sicmpv6_size -= sizeof(ndp_nbr_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, nbr_sol->type, opt,
                                                                   l2src)) < 0) {
                    /* -ENOTSUP can not happen, since the function only returns this for invalid
                     * message types containing the SL2A. Neighbor solicitations are not an
                     * invalid message type for SL2A. According to that, we don't need to watch
                     * out for that here, but regardless, the source link-layer address option
                     * is invalid. */
                    return;
                }
#ifdef MODULE_GNRC_SIXLOWPAN_ND_ROUTER
                sl2a_opt = opt;
                break;
            case NDP_OPT_AR:
                /* actually handling at the end of the function (see below) */
                ar_opt = (sixlowpan_nd_opt_ar_t *)opt;
#endif
                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
    }
#ifdef MODULE_GNRC_SIXLOWPAN_ND_ROUTER
    gnrc_ipv6_netif_t *ipv6_iface = gnrc_ipv6_netif_get(iface);
    assert(ipv6_iface != NULL);
    if ((sl2a_opt != NULL) && (ar_opt != NULL) &&
        (ipv6_iface->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN) &&
        (ipv6_iface->flags & GNRC_IPV6_NETIF_FLAGS_ROUTER)) {
        uint8_t status = gnrc_sixlowpan_nd_opt_ar_handle(iface, ipv6,
                                                         nbr_sol->type,
                                                         &ipv6->src, ar_opt,
                                                         l2src, l2src_len);
        /* check for multihop DAD return */
        nbr_adv_opts = gnrc_sixlowpan_nd_opt_ar_build(status, GNRC_SIXLOWPAN_ND_AR_LTIME,
                                                      &ar_opt->eui64, NULL);
        if (status == 0) {
            memcpy(&nbr_adv_dst, &ipv6->src, sizeof(ipv6_addr_t));
        }
        else {
            /* see https://tools.ietf.org/html/rfc6775#section-6.5.2 */
            eui64_t iid;
            ieee802154_get_iid(&iid, ar_opt->eui64.uint8, sizeof(eui64_t));
            ipv6_addr_set_iid(&nbr_adv_dst, iid.uint64.u64);
            ipv6_addr_set_link_local_prefix(&nbr_adv_dst);
        }
    }
    else {  /* gnrc_sixlowpan_nd_opt_ar_handle updates neighbor cache */
        _stale_nc(iface, &ipv6->src, l2src, l2src_len);
        memcpy(&nbr_adv_dst, &ipv6->src, sizeof(ipv6_addr_t));
    }
#else
    _stale_nc(iface, &ipv6->src, l2src, l2src_len);
    memcpy(&nbr_adv_dst, &ipv6->src, sizeof(ipv6_addr_t));
#endif
    gnrc_ndp_internal_send_nbr_adv(iface, tgt, &nbr_adv_dst, ipv6_addr_is_multicast(&ipv6->dst),
                                   nbr_adv_opts);
}
Пример #3
0
/* random helper function */
void ng_ndp_nbr_sol_handle(kernel_pid_t iface, ng_pktsnip_t *pkt,
                           ipv6_hdr_t *ipv6, ng_ndp_nbr_sol_t *nbr_sol,
                           size_t icmpv6_size)
{
    uint16_t opt_offset = 0;
    uint8_t *buf = ((uint8_t *)nbr_sol) + sizeof(ng_ndp_nbr_sol_t);
    ipv6_addr_t *tgt;
    int sicmpv6_size = (int)icmpv6_size;

    DEBUG("ndp: received neighbor solicitation (src: %s, ",
          ipv6_addr_to_str(addr_str, &ipv6->src, sizeof(addr_str)));
    DEBUG("dst: %s, ",
          ipv6_addr_to_str(addr_str, &ipv6->dst, sizeof(addr_str)));
    DEBUG("tgt: %s)\n",
          ipv6_addr_to_str(addr_str, &nbr_sol->tgt, sizeof(addr_str)));

    /* check validity */
    if ((ipv6->hl != 255) || (nbr_sol->code != 0) ||
        (icmpv6_size < sizeof(ng_ndp_nbr_sol_t)) ||
        ipv6_addr_is_multicast(&nbr_sol->tgt) ||
        (ipv6_addr_is_unspecified(&ipv6->src) &&
         ipv6_addr_is_solicited_node(&ipv6->dst))) {
        DEBUG("ndp: neighbor solicitation was invalid.\n");
        /* ipv6 releases */
        return;
    }

    if ((tgt = ng_ipv6_netif_find_addr(iface, &nbr_sol->tgt)) == NULL) {
        DEBUG("ndp: Target address is not to interface %" PRIkernel_pid "\n",
              iface);
        /* ipv6 releases */
        return;
    }

    sicmpv6_size -= sizeof(ng_ndp_nbr_sol_t);

    while (sicmpv6_size > 0) {
        ng_ndp_opt_t *opt = (ng_ndp_opt_t *)(buf + opt_offset);

        switch (opt->type) {
            case NG_NDP_OPT_SL2A:
                if (!ng_ndp_internal_sl2a_opt_handle(iface, pkt, ipv6, nbr_sol->type, opt)) {
                    /* 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);
    }

    ng_ndp_internal_send_nbr_adv(iface, tgt, &ipv6->src,
                                 ipv6_addr_is_multicast(&ipv6->dst));

    return;
}