Exemplo n.º 1
0
void gnrc_ndp_internal_set_state(gnrc_ipv6_nc_t *nc_entry, uint8_t state)
{
    gnrc_ipv6_netif_t *ipv6_iface;
    uint32_t t = GNRC_NDP_FIRST_PROBE_DELAY * SEC_IN_USEC;

    nc_entry->flags &= ~GNRC_IPV6_NC_STATE_MASK;
    nc_entry->flags |= state;

    DEBUG("ndp internal: set %s state to ",
          ipv6_addr_to_str(addr_str, &nc_entry->ipv6_addr, sizeof(addr_str)));

    switch (state) {
        case GNRC_IPV6_NC_STATE_REACHABLE:
            ipv6_iface = gnrc_ipv6_netif_get(nc_entry->iface);
            DEBUG("REACHABLE (reachable time = %" PRIu32 " us)\n", ipv6_iface->reach_time);
            t = ipv6_iface->reach_time;

            /* we intentionally fall through here to set the desired timeout t */
        case GNRC_IPV6_NC_STATE_DELAY:
#if ENABLE_DEBUG
            if (state == GNRC_IPV6_NC_STATE_DELAY) {
                DEBUG("DELAY (probe with unicast NS in %u seconds)\n",
                      GNRC_NDP_FIRST_PROBE_DELAY);
            }
#endif
            gnrc_ndp_internal_reset_nbr_sol_timer(nc_entry, t, GNRC_NDP_MSG_NC_STATE_TIMEOUT,
                                                  gnrc_ipv6_pid);
            break;

        case GNRC_IPV6_NC_STATE_PROBE:
            ipv6_iface = gnrc_ipv6_netif_get(nc_entry->iface);

            nc_entry->probes_remaining = GNRC_NDP_MAX_UC_NBR_SOL_NUMOF;
            DEBUG("PROBE (probe with %" PRIu8 " unicast NS every %" PRIu32 " us)\n",
                  nc_entry->probes_remaining, ipv6_iface->retrans_timer);

            gnrc_ndp_internal_send_nbr_sol(nc_entry->iface, NULL, &nc_entry->ipv6_addr,
                                           &nc_entry->ipv6_addr);

            mutex_lock(&ipv6_iface->mutex);
            gnrc_ndp_internal_reset_nbr_sol_timer(nc_entry, ipv6_iface->retrans_timer,
                                                  GNRC_NDP_MSG_NBR_SOL_RETRANS, gnrc_ipv6_pid);
            mutex_unlock(&ipv6_iface->mutex);
            break;

#ifdef ENABLE_DEBUG
        case GNRC_IPV6_NC_STATE_STALE:
            DEBUG("STALE (go into DELAY on next packet)\n");
            break;
#endif

        default:
            DEBUG("errorneous or unknown\n");
            break;
    }
}
Exemplo n.º 2
0
static void _add_prefix(kernel_pid_t iface, gnrc_sixlowpan_nd_router_abr_t *abr,
                        ndp_opt_pi_t *pi_opt)
{
    gnrc_sixlowpan_nd_router_prf_t *prf_ent;
    gnrc_ipv6_netif_t *ipv6_iface = gnrc_ipv6_netif_get(iface);
    ipv6_addr_t *prefix;

    if ((pi_opt->len != NDP_OPT_PI_LEN) || ipv6_addr_is_link_local(&pi_opt->prefix) ||
        (pi_opt->flags & NDP_OPT_PI_FLAGS_A) ||
        (pi_opt->flags & NDP_OPT_PI_FLAGS_L) ||
        (pi_opt->valid_ltime.u32 == 0)) {
        return;
    }

    prefix = gnrc_ipv6_netif_match_prefix(iface, &pi_opt->prefix);

    prf_ent = _get_free_prefix(&pi_opt->prefix, pi_opt->prefix_len);

    if (prf_ent != NULL) {
        prf_ent->iface = ipv6_iface;
        prf_ent->prefix = container_of(prefix, gnrc_ipv6_netif_addr_t, addr);
    }

    LL_PREPEND(abr->prfs, prf_ent);
}
Exemplo n.º 3
0
void gnrc_sixlowpan_nd_uc_rtr_sol(gnrc_ipv6_nc_t *nce)
{
    assert(gnrc_ipv6_netif_get(nce->iface)->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN);
    /* neighbor is not a router anymore */
    if (!(nce->flags & GNRC_IPV6_NC_IS_ROUTER) || ipv6_addr_is_unspecified(&nce->ipv6_addr)) {
        /* and there are no routers anymore */
        if (gnrc_ipv6_nc_get_next_router(NULL) == NULL) {
            /* start search for routers */
            gnrc_sixlowpan_nd_init(gnrc_ipv6_netif_get(nce->iface));
        }
        /* otherwise ignore this call */
        return;
    }
    /* next RS is rescheduled by RA handle function */
    gnrc_ndp_internal_send_rtr_sol(nce->iface, &nce->ipv6_addr);
}
Exemplo n.º 4
0
static void _send_to_iface(kernel_pid_t iface, gnrc_pktsnip_t *pkt)
{
    ((gnrc_netif_hdr_t *)pkt->data)->if_pid = iface;
    gnrc_ipv6_netif_t *if_entry = gnrc_ipv6_netif_get(iface);

    assert(if_entry != NULL);
    if (gnrc_pkt_len(pkt->next) > if_entry->mtu) {
        DEBUG("ipv6: packet too big\n");
        gnrc_pktbuf_release(pkt);
        return;
    }
#ifdef MODULE_NETSTATS_IPV6
    if_entry->stats.tx_success++;
    if_entry->stats.tx_bytes += gnrc_pkt_len(pkt->next);
#endif

#ifdef MODULE_GNRC_SIXLOWPAN
    if (if_entry->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN) {
        DEBUG("ipv6: send to 6LoWPAN instead\n");
        if (!gnrc_netapi_dispatch_send(GNRC_NETTYPE_SIXLOWPAN, GNRC_NETREG_DEMUX_CTX_ALL, pkt)) {
            DEBUG("ipv6: no 6LoWPAN thread found");
            gnrc_pktbuf_release(pkt);
        }
        return;
    }
#endif
    if (gnrc_netapi_send(iface, pkt) < 1) {
        DEBUG("ipv6: unable to send packet\n");
        gnrc_pktbuf_release(pkt);
    }
}
Exemplo n.º 5
0
static int _netif_mtu(kernel_pid_t dev, char *mtu_str)
{
#ifdef MODULE_GNRC_IPV6_NETIF
    int mtu;
    gnrc_ipv6_netif_t *entry;
    if (((mtu = atoi(mtu_str)) < IPV6_MIN_MTU) || (mtu > UINT16_MAX)) {
        printf("error: MTU must be between %" PRIu16 " and %" PRIu16 "\n",
               (uint16_t)IPV6_MIN_MTU, (uint16_t)UINT16_MAX);
        return 1;
    }
    if ((entry = gnrc_ipv6_netif_get(dev)) == NULL) {
        puts("error: unable to set MTU.");
        return 1;
    }
    entry->mtu = mtu;
    printf("success: set MTU %u interface %" PRIkernel_pid "\n", mtu,
           dev);
    return 0;
#else
    (void)dev;
    (void)mtu_str;
    puts("error: unable to set MTU.");
    return 1;
#endif
}
Exemplo n.º 6
0
gnrc_ipv6_nc_t *gnrc_ipv6_nc_still_reachable(const ipv6_addr_t *ipv6_addr)
{
    gnrc_ipv6_nc_t *entry = gnrc_ipv6_nc_get(KERNEL_PID_UNDEF, ipv6_addr);

    if (entry == NULL) {
        DEBUG("ipv6_nc: No entry found for %s\n",
              ipv6_addr_to_str(addr_str, ipv6_addr, sizeof(addr_str)));
        return NULL;
    }

    if ((gnrc_ipv6_nc_get_state(entry) != GNRC_IPV6_NC_STATE_INCOMPLETE) &&
        (gnrc_ipv6_nc_get_state(entry) != GNRC_IPV6_NC_STATE_UNMANAGED)) {
#if defined(MODULE_GNRC_IPV6_NETIF) && defined(MODULE_VTIMER) && defined(MODULE_GNRC_IPV6)
        gnrc_ipv6_netif_t *iface = gnrc_ipv6_netif_get(entry->iface);
        timex_t t = iface->reach_time;

        vtimer_remove(&entry->nbr_sol_timer);
        vtimer_set_msg(&entry->nbr_sol_timer, t, gnrc_ipv6_pid,
                       GNRC_NDP_MSG_NC_STATE_TIMEOUT, entry);
#endif

        DEBUG("ipv6_nc: Marking entry %s as reachable\n",
              ipv6_addr_to_str(addr_str, ipv6_addr, sizeof(addr_str)));
        entry->flags &= ~(GNRC_IPV6_NC_STATE_MASK >> GNRC_IPV6_NC_STATE_POS);
        entry->flags |= (GNRC_IPV6_NC_STATE_REACHABLE >> GNRC_IPV6_NC_STATE_POS);
    }
Exemplo n.º 7
0
/* sets an entry to stale if its l2addr differs from the given one or creates it stale if it
 * does not exist */
static void _stale_nc(kernel_pid_t iface, ipv6_addr_t *ipaddr, uint8_t *l2addr,
                      int l2addr_len)
{
    if (l2addr_len != -ENOTSUP) {
        gnrc_ipv6_nc_t *nc_entry = gnrc_ipv6_nc_get(iface, ipaddr);
        if (nc_entry == NULL) {
#ifdef MODULE_GNRC_SIXLOWPAN_ND_ROUTER
            /* tentative type see https://tools.ietf.org/html/rfc6775#section-6.3 */
            gnrc_ipv6_netif_t *ipv6_iface = gnrc_ipv6_netif_get(iface);
            if ((ipv6_iface == NULL) || (ipv6_iface->flags & GNRC_IPV6_NETIF_FLAGS_ROUTER)) {
                timex_t t = { GNRC_SIXLOWPAN_ND_TENTATIVE_NCE_LIFETIME, 0 };
                gnrc_ipv6_nc_add(iface, ipaddr, l2addr, (uint16_t)l2addr_len,
                                 GNRC_IPV6_NC_STATE_STALE | GNRC_IPV6_NC_TYPE_TENTATIVE);
                vtimer_remove(&nc_entry->type_timeout);
                vtimer_set_msg(&nc_entry->type_timeout, t, gnrc_ipv6_pid,
                               GNRC_SIXLOWPAN_ND_MSG_AR_TIMEOUT, nc_entry);
                return;
            }
#endif
            gnrc_ipv6_nc_add(iface, ipaddr, l2addr, (uint16_t)l2addr_len,
                             GNRC_IPV6_NC_STATE_STALE);
        }
        else if (((uint16_t)l2addr_len != nc_entry->l2_addr_len) ||
                 (memcmp(l2addr, nc_entry->l2_addr, l2addr_len) != 0)) {
            /* if entry exists but l2 address differs: set */
            nc_entry->l2_addr_len = (uint16_t)l2addr_len;
            memcpy(nc_entry->l2_addr, l2addr, l2addr_len);
            gnrc_ndp_internal_set_state(nc_entry, GNRC_IPV6_NC_STATE_STALE);
        }
    }
}
Exemplo n.º 8
0
static int _fill_ipv6_hdr(kernel_pid_t iface, gnrc_pktsnip_t *ipv6,
                          gnrc_pktsnip_t *payload)
{
    int res;
    ipv6_hdr_t *hdr = ipv6->data;

    hdr->len = byteorder_htons(gnrc_pkt_len(payload));
    DEBUG("ipv6: set payload length to %u (network byteorder %04" PRIx16 ")\n",
          (unsigned) gnrc_pkt_len(payload), hdr->len.u16);

    /* check if e.g. extension header was not already marked */
    if (hdr->nh == PROTNUM_RESERVED) {
        hdr->nh = gnrc_nettype_to_protnum(payload->type);

        /* if still reserved: mark no next header */
        if (hdr->nh == PROTNUM_RESERVED) {
            hdr->nh = PROTNUM_IPV6_NONXT;
        }
    }

    DEBUG("ipv6: set next header to %u\n", hdr->nh);

    if (hdr->hl == 0) {
        if (iface == KERNEL_PID_UNDEF) {
            hdr->hl = GNRC_IPV6_NETIF_DEFAULT_HL;
        }
        else {
            hdr->hl = gnrc_ipv6_netif_get(iface)->cur_hl;
        }
    }

    if (ipv6_addr_is_unspecified(&hdr->src)) {
        if (ipv6_addr_is_loopback(&hdr->dst)) {
            ipv6_addr_set_loopback(&hdr->src);
        }
        else {
            ipv6_addr_t *src = gnrc_ipv6_netif_find_best_src_addr(iface, &hdr->dst, false);

            if (src != NULL) {
                DEBUG("ipv6: set packet source to %s\n",
                      ipv6_addr_to_str(addr_str, src, sizeof(addr_str)));
                memcpy(&hdr->src, src, sizeof(ipv6_addr_t));
            }
            /* Otherwise leave unspecified */
        }
    }

    DEBUG("ipv6: calculate checksum for upper header.\n");

    if ((res = gnrc_netreg_calc_csum(payload, ipv6)) < 0) {
        if (res != -ENOENT) {   /* if there is no checksum we are okay */
            DEBUG("ipv6: checksum calculation failed.\n");
            return res;
        }
    }

    return 0;
}
Exemplo n.º 9
0
void gnrc_sixlowpan_nd_rtr_sol_reschedule(gnrc_ipv6_nc_t *nce, uint32_t sec_delay)
{
    assert(nce != NULL);
    assert(sec_delay != 0U);
    gnrc_ipv6_netif_t *iface = gnrc_ipv6_netif_get(nce->iface);
    vtimer_remove(&iface->rtr_sol_timer);
    vtimer_set_msg(&iface->rtr_sol_timer, timex_set(sec_delay, 0), gnrc_ipv6_pid,
                   GNRC_SIXLOWPAN_ND_MSG_MC_RTR_SOL, iface);
}
Exemplo n.º 10
0
void gnrc_ipv6_netif_init_by_dev(void)
{
    kernel_pid_t ifs[GNRC_NETIF_NUMOF];
    size_t ifnum = gnrc_netif_get(ifs);

    for (size_t i = 0; i < ifnum; i++) {
        ipv6_addr_t addr;
        eui64_t iid;
        gnrc_ipv6_netif_t *ipv6_if = gnrc_ipv6_netif_get(ifs[i]);

        if (ipv6_if == NULL) {
            continue;
        }

        mutex_lock(&ipv6_if->mutex);

#ifdef MODULE_GNRC_SIXLOWPAN
        gnrc_nettype_t if_type = GNRC_NETTYPE_UNDEF;

        if ((gnrc_netapi_get(ifs[i], NETOPT_PROTO, 0, &if_type,
                             sizeof(if_type)) != -ENOTSUP) &&
            (if_type == GNRC_NETTYPE_SIXLOWPAN)) {
            uint16_t src_len = 8;
            uint16_t max_frag_size = UINT16_MAX;

            DEBUG("ipv6 netif: Set 6LoWPAN flag\n");
            ipv6_ifs[i].flags |= GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN;
            /* use EUI-64 (8-byte address) for IID generation and for sending
             * packets */
            gnrc_netapi_set(ifs[i], NETOPT_SRC_LEN, 0, &src_len,
                            sizeof(src_len)); /* don't care for result */

            if (gnrc_netapi_get(ifs[i], NETOPT_MAX_PACKET_SIZE,
                                0, &max_frag_size, sizeof(max_frag_size)) < 0) {
                /* if error we assume it works */
                DEBUG("ipv6 netif: Can not get max packet size from interface %"
                      PRIkernel_pid "\n", ifs[i]);
            }

            gnrc_sixlowpan_netif_add(ifs[i], max_frag_size);
        }
#endif

        if ((gnrc_netapi_get(ifs[i], NETOPT_IPV6_IID, 0, &iid,
                             sizeof(eui64_t)) < 0)) {
            mutex_unlock(&ipv6_if->mutex);
            continue;
        }

        ipv6_addr_set_aiid(&addr, iid.uint8);
        ipv6_addr_set_link_local_prefix(&addr);
        _add_addr_to_entry(ipv6_if, &addr, 64, 0);

        mutex_unlock(&ipv6_if->mutex);
    }
}
Exemplo n.º 11
0
void gnrc_sixlowpan_nd_rtr_sol_reschedule(gnrc_ipv6_nc_t *nce, uint32_t sec_delay)
{
    assert(nce != NULL);
    assert(sec_delay != 0U);
    gnrc_ipv6_netif_t *iface = gnrc_ipv6_netif_get(nce->iface);
    xtimer_remove(&iface->rtr_sol_timer);
    iface->rtr_sol_msg.type = GNRC_SIXLOWPAN_ND_MSG_MC_RTR_SOL;
    iface->rtr_sol_msg.content.ptr = (char *) iface;
    xtimer_set_msg(&iface->rtr_sol_timer, sec_delay * SEC_IN_USEC, &iface->rtr_sol_msg,
                   gnrc_ipv6_pid);
}
Exemplo n.º 12
0
void gnrc_ipv6_netif_reset_addr(kernel_pid_t pid)
{
    gnrc_ipv6_netif_t *entry = gnrc_ipv6_netif_get(pid);

    if (entry == NULL) {
        return;
    }

    mutex_lock(&entry->mutex);

    _reset_addr_from_entry(entry);

    mutex_unlock(&entry->mutex);
}
Exemplo n.º 13
0
ipv6_addr_t *gnrc_ipv6_netif_match_prefix(kernel_pid_t pid, const ipv6_addr_t *prefix)
{
    ipv6_addr_t *res = NULL;
    gnrc_ipv6_netif_t *iface = gnrc_ipv6_netif_get(pid);

    mutex_lock(&(iface->mutex));

    if (_find_by_prefix_unsafe(&res, iface, prefix, NULL) > 0) {
        mutex_unlock(&(iface->mutex));
        return res;
    }

    mutex_unlock(&(iface->mutex));

    return NULL;
}
Exemplo n.º 14
0
void gnrc_ipv6_netif_remove_addr(kernel_pid_t pid, ipv6_addr_t *addr)
{
    if (pid == KERNEL_PID_UNDEF) {
        for (int i = 0; i < GNRC_NETIF_NUMOF; i++) {
            if (ipv6_ifs[i].pid == KERNEL_PID_UNDEF) {
                continue;
            }

            _remove_addr_from_entry(ipv6_ifs + i, addr);
        }
    }
    else {
        gnrc_ipv6_netif_t *entry = gnrc_ipv6_netif_get(pid);

        _remove_addr_from_entry(entry, addr);
    }
}
Exemplo n.º 15
0
static void *_ipv6_fwd_eventloop(void *arg)
{
    (void)arg;

    msg_t msg, msg_q[8];
    gnrc_netreg_entry_t me_reg;

    msg_init_queue(msg_q, 8);

    me_reg.demux_ctx = GNRC_NETREG_DEMUX_CTX_ALL;
    me_reg.pid = thread_getpid();

    gnrc_netreg_register(GNRC_NETTYPE_SIXLOWPAN, &me_reg);

    while(1) {
        msg_receive(&msg);
        gnrc_pktsnip_t *pkt = msg.content.ptr;
        if(msg.type == GNRC_NETAPI_MSG_TYPE_SND) {
            gnrc_pktsnip_t *ipv6 = gnrc_pktsnip_search_type(pkt, GNRC_NETTYPE_IPV6);
            ipv6 = ipv6->data;

            ipv6_hdr_t *ipv6_hdr =(ipv6_hdr_t *)ipv6;

            /* get the first IPv6 interface and prints its address */
            kernel_pid_t ifs[GNRC_NETIF_NUMOF];
            gnrc_netif_get(ifs);
            gnrc_ipv6_netif_t *entry = gnrc_ipv6_netif_get(ifs[0]);
            for (int i = 0; i < GNRC_IPV6_NETIF_ADDR_NUMOF; i++) {
                if ( (!ipv6_addr_is_link_local(&entry->addrs[i].addr)) && (!ipv6_addr_is_link_local(&ipv6_hdr->src)) 
                    && (!ipv6_addr_is_link_local(&ipv6_hdr->dst)) && !(entry->addrs[i].flags & GNRC_IPV6_NETIF_ADDR_FLAGS_NON_UNICAST)
                    && (!ipv6_addr_is_unspecified(&entry->addrs[i].addr)) ) {

                    if(!ipv6_addr_equal(&entry->addrs[i].addr, &(ipv6_hdr->src))){

                        char addr_str[IPV6_ADDR_MAX_STR_LEN];
                        printf("IPv6 ROUTER: forward from src = %s ", ipv6_addr_to_str(addr_str, &(ipv6_hdr->src), sizeof(addr_str)) );
                        printf("to dst = %s\n",ipv6_addr_to_str(addr_str, &(ipv6_hdr->dst), sizeof(addr_str)));
                    }
                }
            }
        }
        gnrc_pktbuf_release(pkt);
    }
    /* never reached */
    return NULL;
}
Exemplo n.º 16
0
/**
 * Initialize this node to join a RPL routing network.
 * @param  iface_pid  The ID for the RPL interface
 * @return            true on successful init, false otherwise
 */
bool rpl_init(kernel_pid_t iface_pid)
{

    // Check if interface exists
    gnrc_ipv6_netif_t* entry = NULL;

    entry = gnrc_ipv6_netif_get(iface_pid);

    if (entry == NULL) {
        puts("unknown interface specified");
        return false;
    }

    // RPL init
    gnrc_rpl_init(iface_pid);

    return true;
}
Exemplo n.º 17
0
bool gnrc_ndp_internal_mtu_opt_handle(kernel_pid_t iface, uint8_t icmpv6_type,
                                      ndp_opt_mtu_t *mtu_opt)
{
    gnrc_ipv6_netif_t *if_entry = gnrc_ipv6_netif_get(iface);

    if ((mtu_opt->len != NDP_OPT_MTU_LEN)) {
        DEBUG("ndp: invalid MTU option received\n");
        return false;
    }
    if (icmpv6_type != ICMPV6_RTR_ADV) {
        /* else discard silently */
        return true;
    }
    mutex_lock(&if_entry->mutex);
    if_entry->mtu = byteorder_ntohl(mtu_opt->mtu);
    mutex_unlock(&if_entry->mutex);
    return true;
}
Exemplo n.º 18
0
ipv6_addr_t *gnrc_ipv6_netif_add_addr(kernel_pid_t pid, const ipv6_addr_t *addr,
                                      uint8_t prefix_len, uint8_t flags)
{
    gnrc_ipv6_netif_t *entry = gnrc_ipv6_netif_get(pid);
    ipv6_addr_t *res;

    if ((entry == NULL) || (addr == NULL) || (ipv6_addr_is_unspecified(addr)) ||
        ((prefix_len - 1) > 127)) {    /* prefix_len < 1 || prefix_len > 128 */
        return NULL;
    }

    mutex_lock(&entry->mutex);

    res = _add_addr_to_entry(entry, addr, prefix_len, flags);

    mutex_unlock(&entry->mutex);

    return res;
}
Exemplo n.º 19
0
ipv6_addr_t *gnrc_ipv6_netif_find_best_src_addr(kernel_pid_t pid, const ipv6_addr_t *dst)
{
    gnrc_ipv6_netif_t *iface = gnrc_ipv6_netif_get(pid);
    ipv6_addr_t *best_src = NULL;
    mutex_lock(&(iface->mutex));
    BITFIELD(candidate_set, GNRC_IPV6_NETIF_ADDR_NUMOF);
    memset(candidate_set, 0, sizeof(candidate_set));

    int first_candidate = _create_candidate_set(iface, dst, candidate_set);
    if (first_candidate >= 0) {
        best_src = _source_address_selection(iface, dst, candidate_set);
        if (best_src == NULL) {
            best_src = &(iface->addrs[first_candidate].addr);
        }
    }
    mutex_unlock(&(iface->mutex));

    return best_src;
}
Exemplo n.º 20
0
/* sets an entry to stale if its l2addr differs from the given one or creates it stale if it
 * does not exist */
static void _stale_nc(kernel_pid_t iface, ipv6_addr_t *ipaddr, uint8_t *l2addr,
                      int l2addr_len)
{
    if (l2addr_len != -ENOTSUP) {
        gnrc_ipv6_nc_t *nc_entry = gnrc_ipv6_nc_get(iface, ipaddr);
        if (nc_entry == NULL) {
#ifdef MODULE_GNRC_SIXLOWPAN_ND_ROUTER
            /* tentative type see https://tools.ietf.org/html/rfc6775#section-6.3 */
            gnrc_ipv6_netif_t *ipv6_iface = gnrc_ipv6_netif_get(iface);
            if ((ipv6_iface->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN) &&
                (ipv6_iface->flags & GNRC_IPV6_NETIF_FLAGS_ROUTER)) {
                if ((nc_entry = gnrc_ipv6_nc_add(iface, ipaddr, l2addr,
                                                 (uint16_t)l2addr_len,
                                                 GNRC_IPV6_NC_STATE_STALE |
                                                 GNRC_IPV6_NC_TYPE_TENTATIVE)) != NULL) {
                    xtimer_set_msg(&nc_entry->type_timeout,
                                   (GNRC_SIXLOWPAN_ND_TENTATIVE_NCE_LIFETIME * SEC_IN_USEC),
                                   &nc_entry->type_timeout_msg,
                                   gnrc_ipv6_pid);
                }
                return;
            }
#endif
            gnrc_ipv6_nc_add(iface, ipaddr, l2addr, (uint16_t)l2addr_len,
                             GNRC_IPV6_NC_STATE_STALE);
        }
#ifdef MODULE_GNRC_SIXLOWPAN_ND_ROUTER
        /* unreachable set in gnrc_ndp_retrans_nbr_sol() will just be staled */
        else if (gnrc_ipv6_nc_get_state(nc_entry) == GNRC_IPV6_NC_STATE_UNREACHABLE) {
            gnrc_ndp_internal_set_state(nc_entry, GNRC_IPV6_NC_STATE_STALE);
        }
#endif
        else if (((uint16_t)l2addr_len != nc_entry->l2_addr_len) ||
                 (memcmp(l2addr, nc_entry->l2_addr, l2addr_len) != 0)) {
            /* if entry exists but l2 address differs: set */
            nc_entry->l2_addr_len = (uint16_t)l2addr_len;
            memcpy(nc_entry->l2_addr, l2addr, l2addr_len);
            gnrc_ndp_internal_set_state(nc_entry, GNRC_IPV6_NC_STATE_STALE);
        }
    }
}
Exemplo n.º 21
0
void gnrc_ipv6_netif_remove(kernel_pid_t pid)
{
    gnrc_ipv6_netif_t *entry = gnrc_ipv6_netif_get(pid);

    if (entry == NULL) {
        return;
    }

#ifdef MODULE_GNRC_NDP
    gnrc_ndp_netif_remove(entry);
#endif

    mutex_lock(&entry->mutex);

    _reset_addr_from_entry(entry);
    DEBUG("ipv6 netif: Remove IPv6 interface %" PRIkernel_pid "\n", pid);
    entry->pid = KERNEL_PID_UNDEF;
    entry->flags = 0;

    mutex_unlock(&entry->mutex);
}
Exemplo n.º 22
0
static void _nc_remove(kernel_pid_t iface, gnrc_ipv6_nc_t *entry)
{
    (void) iface;
    if (entry == NULL) {
        return;
    }

    DEBUG("ipv6_nc: Remove %s for interface %" PRIkernel_pid "\n",
          ipv6_addr_to_str(addr_str, &(entry->ipv6_addr), sizeof(addr_str)),
          iface);

#ifdef MODULE_GNRC_NDP_NODE
    while (entry->pkts != NULL) {
        gnrc_pktbuf_release(entry->pkts->pkt);
        entry->pkts->pkt = NULL;
        gnrc_pktqueue_remove_head(&entry->pkts);
    }
#endif
#ifdef MODULE_GNRC_SIXLOWPAN_ND_ROUTER
    xtimer_remove(&entry->type_timeout);

    gnrc_ipv6_netif_t *if_entry = gnrc_ipv6_netif_get(iface);

    if ((if_entry != NULL) && (if_entry->rtr_adv_msg.content.ptr == (char *) entry)) {
        /* cancel timer set by gnrc_ndp_rtr_sol_handle */
        xtimer_remove(&if_entry->rtr_adv_timer);
    }
#endif
#if defined(MODULE_GNRC_NDP_ROUTER) || defined(MODULE_GNRC_SIXLOWPAN_ND_BORDER_ROUTER)
    xtimer_remove(&entry->rtr_adv_timer);
#endif

    xtimer_remove(&entry->rtr_timeout);
    xtimer_remove(&entry->nbr_sol_timer);
    xtimer_remove(&entry->nbr_adv_timer);

    ipv6_addr_set_unspecified(&(entry->ipv6_addr));
    entry->iface = KERNEL_PID_UNDEF;
    entry->flags = 0;
}
Exemplo n.º 23
0
ipv6_addr_t *gnrc_ipv6_netif_find_addr(kernel_pid_t pid, const ipv6_addr_t *addr)
{
    gnrc_ipv6_netif_t *entry = gnrc_ipv6_netif_get(pid);

    if (entry == NULL) {
        return NULL;
    }

    mutex_lock(&entry->mutex);

    for (int i = 0; i < GNRC_IPV6_NETIF_ADDR_NUMOF; i++) {
        if (ipv6_addr_equal(&(entry->addrs[i].addr), addr)) {
            mutex_unlock(&entry->mutex);
            DEBUG("ipv6 netif: Found %s on interface %" PRIkernel_pid "\n",
                  ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)),
                  pid);
            return &(entry->addrs[i].addr);
        }
    }

    mutex_unlock(&entry->mutex);

    return NULL;
}
Exemplo n.º 24
0
static int _netif_flag(char *cmd, kernel_pid_t dev, char *flag)
{
    netopt_enable_t set = NETOPT_ENABLE;

    if (flag[0] == '-') {
        set = NETOPT_DISABLE;
        flag++;
    }

    if (strcmp(flag, "promisc") == 0) {
        return _netif_set_flag(dev, NETOPT_PROMISCUOUSMODE, set);
    }
    else if (strcmp(flag, "preload") == 0) {
        return _netif_set_flag(dev, NETOPT_PRELOADING, set);
    }
    else if (strcmp(flag, "autoack") == 0) {
        return _netif_set_flag(dev, NETOPT_AUTOACK, set);
    }
    else if (strcmp(flag, "raw") == 0) {
        return _netif_set_flag(dev, NETOPT_RAWMODE, set);
    }
    else if (strcmp(flag, "6lo") == 0) {
#ifdef MODULE_GNRC_IPV6_NETIF
        gnrc_ipv6_netif_t *entry = gnrc_ipv6_netif_get(dev);

        if (entry == NULL) {
            puts("error: unable to (un)set 6LoWPAN support");
            return 1;
        }

        mutex_lock(&entry->mutex);

        if (set) {
            entry->flags |= GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN;
            printf("success: set 6LoWPAN support on interface %" PRIkernel_pid
                   "\n", dev);
        }
        else {
            entry->flags &= ~GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN;
            printf("success: unset 6LoWPAN support on interface %" PRIkernel_pid
                   "\n", dev);
        }

        mutex_unlock(&entry->mutex);

        return 0;
#else
        puts("error: unable to (un)set 6LoWPAN support");

        return 1;
#endif
    }
    else if (strcmp(flag, "iphc") == 0) {
#if defined(MODULE_GNRC_SIXLOWPAN_NETIF) && defined(MODULE_GNRC_SIXLOWPAN_IPHC)
        gnrc_sixlowpan_netif_t *entry = gnrc_sixlowpan_netif_get(dev);

        if (entry == NULL) {
            puts("error: unable to (un)set IPHC");
            return 1;
        }

        if (set) {
            entry->iphc_enabled = true;
            printf("success: enable IPHC on interface %" PRIkernel_pid "\n", dev);
        }
        else {
            entry->iphc_enabled = false;
            printf("success: disable IPHC on interface %" PRIkernel_pid "\n", dev);
        }
        return 0;
#else
        puts("error: unable to (un)set IPHC.");
        return 1;
#endif
    }

    _flag_usage(cmd);
    return 1;
}
Exemplo n.º 25
0
static void _netif_list(kernel_pid_t dev)
{
    uint8_t hwaddr[MAX_ADDR_LEN];
    uint16_t u16;
    int16_t i16;
    int res;
    netopt_state_t state;
    netopt_enable_t enable;
    bool linebreak = false;
#ifdef MODULE_GNRC_IPV6_NETIF
    gnrc_ipv6_netif_t *entry = gnrc_ipv6_netif_get(dev);
    char ipv6_addr[IPV6_ADDR_MAX_STR_LEN];
#endif


    printf("Iface %2d  ", dev);

    res = gnrc_netapi_get(dev, NETOPT_ADDRESS, 0, hwaddr, sizeof(hwaddr));

    if (res >= 0) {
        char hwaddr_str[res * 3];
        printf(" HWaddr: ");
        printf("%s", gnrc_netif_addr_to_str(hwaddr_str, sizeof(hwaddr_str),
                                            hwaddr, res));
        printf(" ");
    }

    res = gnrc_netapi_get(dev, NETOPT_CHANNEL, 0, &u16, sizeof(u16));

    if (res >= 0) {
        printf(" Channel: %" PRIu16 " ", u16);
    }

    res = gnrc_netapi_get(dev, NETOPT_NID, 0, &u16, sizeof(u16));

    if (res >= 0) {
        printf(" NID: 0x%" PRIx16 " ", u16);
    }

    res = gnrc_netapi_get(dev, NETOPT_TX_POWER, 0, &i16, sizeof(i16));

    if (res >= 0) {
        printf(" TX-Power: %" PRIi16 "dBm ", i16);
    }

    res = gnrc_netapi_get(dev, NETOPT_STATE, 0, &state, sizeof(state));

    if (res >= 0) {
        printf(" State: ");
        _print_netopt_state(state);
    }

    printf("\n           ");

    res = gnrc_netapi_get(dev, NETOPT_ADDRESS_LONG, 0, hwaddr, sizeof(hwaddr));

    if (res >= 0) {
        char hwaddr_str[res * 3];
        printf("Long HWaddr: ");
        printf("%s", gnrc_netif_addr_to_str(hwaddr_str, sizeof(hwaddr_str),
                                            hwaddr, res));
        printf("\n           ");
    }

    res = gnrc_netapi_get(dev, NETOPT_PROMISCUOUSMODE, 0, &enable, sizeof(enable));

    if ((res >= 0) && (enable == NETOPT_ENABLE)) {
        printf("PROMISC  ");
        linebreak = true;
    }

    res = gnrc_netapi_get(dev, NETOPT_AUTOACK, 0, &enable, sizeof(enable));

    if ((res >= 0) && (enable == NETOPT_ENABLE)) {
        printf("AUTOACK  ");
        linebreak = true;
    }

    res = gnrc_netapi_get(dev, NETOPT_PRELOADING, 0, &enable, sizeof(enable));

    if ((res >= 0) && (enable == NETOPT_ENABLE)) {
        printf("PRELOAD  ");
        linebreak = true;
    }

    res = gnrc_netapi_get(dev, NETOPT_RAWMODE, 0, &enable, sizeof(enable));

    if ((res >= 0) && (enable == NETOPT_ENABLE)) {
        printf("RAWMODE  ");
        linebreak = true;
    }

#ifdef MODULE_GNRC_IPV6_NETIF
    if ((entry != NULL) && (entry->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN)) {
        printf("6LO ");
        linebreak = true;
    }
#endif

#if defined(MODULE_GNRC_SIXLOWPAN_NETIF) && defined(MODULE_GNRC_SIXLOWPAN_IPHC)
    gnrc_sixlowpan_netif_t *sixlo_entry = gnrc_sixlowpan_netif_get(dev);

    if ((sixlo_entry != NULL) && (sixlo_entry->iphc_enabled)) {
        printf("IPHC ");
        linebreak = true;
    }
#endif

    if (linebreak) {
        printf("\n           ");
    }

    res = gnrc_netapi_get(dev, NETOPT_SRC_LEN, 0, &u16, sizeof(u16));

    if (res >= 0) {
        printf("Source address length: %" PRIu16 "\n           ", u16);
    }

#ifdef MODULE_GNRC_IPV6_NETIF
    for (int i = 0; i < GNRC_IPV6_NETIF_ADDR_NUMOF; i++) {
        if (!ipv6_addr_is_unspecified(&entry->addrs[i].addr)) {
            printf("inet6 addr: ");

            if (ipv6_addr_to_str(ipv6_addr, &entry->addrs[i].addr,
                                 IPV6_ADDR_MAX_STR_LEN)) {
                printf("%s/%" PRIu8 "  scope: ", ipv6_addr,
                       entry->addrs[i].prefix_len);

                if ((ipv6_addr_is_link_local(&entry->addrs[i].addr))) {
                    printf("local");
                }
                else {
                    printf("global");
                }

                if (entry->addrs[i].flags & GNRC_IPV6_NETIF_ADDR_FLAGS_NON_UNICAST) {
                    if (ipv6_addr_is_multicast(&entry->addrs[i].addr)) {
                        printf(" [multicast]");
                    }
                    else {
                        printf(" [anycast]");
                    }
                }
            }
            else {
                printf("error in conversion");
            }

            printf("\n           ");
        }
    }
#endif

    puts("");
}
Exemplo n.º 26
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);
    }
}
Exemplo n.º 27
0
void gnrc_ipv6_netif_init_by_dev(void)
{
    kernel_pid_t ifs[GNRC_NETIF_NUMOF];
    size_t ifnum = gnrc_netif_get(ifs);
#ifdef MODULE_GNRC_SIXLOWPAN_ND_BORDER_ROUTER
    bool abr_init = false;
#endif

    for (size_t i = 0; i < ifnum; i++) {
        ipv6_addr_t addr;
        eui64_t iid;
        uint16_t tmp;
        gnrc_ipv6_netif_t *ipv6_if = gnrc_ipv6_netif_get(ifs[i]);

        if (ipv6_if == NULL) {
            continue;
        }

        mutex_lock(&ipv6_if->mutex);

#ifdef MODULE_GNRC_SIXLOWPAN
        gnrc_nettype_t if_type = GNRC_NETTYPE_UNDEF;

        if ((gnrc_netapi_get(ifs[i], NETOPT_PROTO, 0, &if_type,
                             sizeof(if_type)) != -ENOTSUP) &&
            (if_type == GNRC_NETTYPE_SIXLOWPAN)) {
            uint16_t src_len = 8;
            uint16_t max_frag_size = UINT16_MAX;

            DEBUG("ipv6 netif: Set 6LoWPAN flag\n");
            ipv6_ifs[i].flags |= GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN;

            /* the router flag must be set early here, because otherwise
             * _add_addr_to_entry() wouldn't set the solicited node address.
             * However, addresses have to be configured before calling
             * gnrc_ipv6_netif_set_router().
             */
#ifdef MODULE_GNRC_SIXLOWPAN_ND_ROUTER
            DEBUG("ipv6 netif: Set router flag\n");
            ipv6_ifs[i].flags |= GNRC_IPV6_NETIF_FLAGS_ROUTER;
#endif
            /* use EUI-64 (8-byte address) for IID generation and for sending
             * packets */
            gnrc_netapi_set(ifs[i], NETOPT_SRC_LEN, 0, &src_len,
                            sizeof(src_len)); /* don't care for result */

            if (gnrc_netapi_get(ifs[i], NETOPT_MAX_PACKET_SIZE,
                                0, &max_frag_size, sizeof(max_frag_size)) < 0) {
                /* if error we assume it works */
                DEBUG("ipv6 netif: Can not get max packet size from interface %"
                      PRIkernel_pid "\n", ifs[i]);
            }

            gnrc_sixlowpan_netif_add(ifs[i], max_frag_size);
        }
#endif

        /* set link-local address */
        if ((gnrc_netapi_get(ifs[i], NETOPT_IPV6_IID, 0, &iid,
                             sizeof(eui64_t)) < 0)) {
            mutex_unlock(&ipv6_if->mutex);
            continue;
        }

        ipv6_addr_set_aiid(&addr, iid.uint8);
        ipv6_addr_set_link_local_prefix(&addr);
        _add_addr_to_entry(ipv6_if, &addr, 64, 0);

        /* set link MTU */
        if ((gnrc_netapi_get(ifs[i], NETOPT_MAX_PACKET_SIZE, 0, &tmp,
                             sizeof(uint16_t)) >= 0)) {
            if (tmp >= IPV6_MIN_MTU) {
                ipv6_if->mtu = tmp;
            }
            /* otherwise leave at GNRC_IPV6_NETIF_DEFAULT_MTU as initialized in
             * gnrc_ipv6_netif_add() */
        }

        if (gnrc_netapi_get(ifs[i], NETOPT_IS_WIRED, 0, &tmp, sizeof(int)) > 0) {
            ipv6_if->flags |= GNRC_IPV6_NETIF_FLAGS_IS_WIRED;
        }
        else {
            ipv6_if->flags &= ~GNRC_IPV6_NETIF_FLAGS_IS_WIRED;
        }

        mutex_unlock(&ipv6_if->mutex);
#if (defined(MODULE_GNRC_NDP_ROUTER) || defined(MODULE_GNRC_SIXLOWPAN_ND_ROUTER))
        gnrc_ipv6_netif_set_router(ipv6_if, true);
#endif
#ifdef MODULE_GNRC_SIXLOWPAN_ND
        if (ipv6_if->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN) {
#ifdef MODULE_GNRC_SIXLOWPAN_ND_BORDER_ROUTER
            /* first interface wins */
            if (!abr_init) {
                gnrc_sixlowpan_nd_router_abr_create(&addr, 0);
                gnrc_ipv6_netif_set_rtr_adv(ipv6_if, true);
                abr_init = true;
            }
#endif
            gnrc_sixlowpan_nd_init(ipv6_if);
            continue;   /* skip gnrc_ndp_host_init() */
        }
#endif
#ifdef MODULE_GNRC_NDP_HOST
        /* start periodic router solicitations */
        gnrc_ndp_host_init(ipv6_if);
#endif
    }
}
Exemplo n.º 28
0
void gnrc_ndp_internal_send_nbr_sol(kernel_pid_t iface, ipv6_addr_t *src, ipv6_addr_t *tgt,
                                    ipv6_addr_t *dst)
{
#ifdef MODULE_GNRC_SIXLOWPAN_ND
    gnrc_ipv6_netif_t *ipv6_iface = gnrc_ipv6_netif_get(iface);
    assert(ipv6_iface != NULL);
#endif
    gnrc_pktsnip_t *hdr, *pkt = NULL;
    /* both suppressions, since they are needed in the MODULE_GNRC_SIXLOWPAN_ND branch */
    /* cppcheck-suppress variableScope */
    uint8_t l2src[8];
    /* cppcheck-suppress variableScope */
    size_t l2src_len = 0;

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

    /* check if there is a fitting source address to target */
    if (src == NULL) {
        src = gnrc_ipv6_netif_find_best_src_addr(iface, tgt);
    }
    if (src != NULL) {
        l2src_len = _get_l2src(iface, l2src, sizeof(l2src));

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

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

#ifdef MODULE_GNRC_SIXLOWPAN_ND
    if (ipv6_iface->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN) {
        if (l2src_len != sizeof(eui64_t)) {
            l2src_len = (uint16_t)gnrc_netapi_get(iface, NETOPT_ADDRESS_LONG, 0, l2src,
                                                  sizeof(l2src));
            if (l2src_len != sizeof(eui64_t)) {
                DEBUG("ndp internal: can't get EUI-64 of the interface\n");
                gnrc_pktbuf_release(pkt);
                return;
            }
        }
        hdr = gnrc_sixlowpan_nd_opt_ar_build(0, GNRC_SIXLOWPAN_ND_AR_LTIME, (eui64_t *)l2src, pkt);
        if (hdr == NULL) {
            DEBUG("ndp internal: error allocatin Address Registration option.\n");
            gnrc_pktbuf_release(pkt);
            return;
        }
        pkt = hdr;
    }
#endif

    hdr = gnrc_ndp_nbr_sol_build(tgt, pkt);

    if (hdr == NULL) {
        DEBUG("ndp internal: error allocating Neighbor solicitation.\n");
        gnrc_pktbuf_release(pkt);
        return;
    }
    pkt = hdr;
    hdr = _build_headers(iface, pkt, dst, src);
    if (hdr == NULL) {
        DEBUG("ndp internal: error adding lower-layer headers.\n");
        gnrc_pktbuf_release(pkt);
        return;
    }
    else if (gnrc_netapi_send(gnrc_ipv6_pid, hdr) < 1) {
        DEBUG("ndp internal: unable to send neighbor solicitation\n");
        gnrc_pktbuf_release(hdr);
    }
}
Exemplo n.º 29
0
void gnrc_ndp_internal_send_rtr_adv(kernel_pid_t iface, ipv6_addr_t *src, ipv6_addr_t *dst,
                                    bool fin)
{
    gnrc_pktsnip_t *hdr, *pkt = NULL;
    ipv6_addr_t all_nodes = IPV6_ADDR_ALL_NODES_LINK_LOCAL;
    gnrc_ipv6_netif_t *ipv6_iface = gnrc_ipv6_netif_get(iface);
    uint32_t reach_time = 0, retrans_timer = 0;
    uint16_t adv_ltime = 0;
    uint8_t cur_hl = 0;

    if (dst == NULL) {
        dst = &all_nodes;
    }
    DEBUG("ndp internal: send router advertisement (iface: %" PRIkernel_pid ", dst: %s%s\n",
          iface, ipv6_addr_to_str(addr_str, dst, sizeof(addr_str)), fin ? ", final" : "");
    mutex_lock(&ipv6_iface->mutex);
#ifdef MODULE_GNRC_SIXLOWPAN_ND_ROUTER
    if (!(ipv6_iface->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN)) {
#endif
    hdr = _add_pios(ipv6_iface, pkt);
    if (hdr == NULL) {
        /* pkt already released in _add_pios */
        mutex_unlock(&ipv6_iface->mutex);
        return;
    }
    pkt = hdr;
#ifdef MODULE_GNRC_SIXLOWPAN_ND_ROUTER
    }
    else {
        gnrc_sixlowpan_nd_router_abr_t *abr = gnrc_sixlowpan_nd_router_abr_get();
        if (abr != NULL) {
            gnrc_sixlowpan_nd_router_prf_t *prf = abr->prfs;
            /* add prefixes from border router */
            while (prf) {
                bool processed_before = false;
                /* skip if prefix does not belong to iface */
                if (prf->iface != ipv6_iface) {
                    prf = prf->next;
                    continue;
                }
                /* skip if prefix has been processed already */
                for (gnrc_sixlowpan_nd_router_prf_t *tmp = abr->prfs; tmp != prf; tmp = tmp->next) {
                    if ((processed_before =
                             _check_prefixes(prf->prefix, tmp->prefix))) {
                        break;
                    }
                }

                if (processed_before) {
                    prf = prf->next;
                    continue;
                }

                if (_pio_from_iface_addr(&hdr, prf->prefix, pkt)) {
                    if (hdr != NULL) {
                        pkt = hdr;
                    }
                    else {
                        DEBUG("ndp rtr: error allocating PIO\n");
                        gnrc_pktbuf_release(pkt);
                        return;
                    }
                }
                prf = prf->next;
            }
            for (unsigned int i = 0; i < GNRC_SIXLOWPAN_CTX_SIZE; i++) {
                gnrc_sixlowpan_ctx_t *ctx;
                if (!bf_isset(abr->ctxs, i)) {
                    continue;
                }
                ctx = gnrc_sixlowpan_ctx_lookup_id(i);
                hdr = gnrc_sixlowpan_nd_opt_6ctx_build(ctx->prefix_len, ctx->flags_id, ctx->ltime,
                                                       &ctx->prefix, pkt);
                if (hdr == NULL) {
                    DEBUG("ndp rtr: error allocating 6CO\n");
                    gnrc_pktbuf_release(pkt);
                    return;
                }
                pkt = hdr;
            }
            hdr = gnrc_sixlowpan_nd_opt_abr_build(abr->version, abr->ltime, &abr->addr, pkt);
            if (hdr == NULL) {
                DEBUG("ndp internal: error allocating ABRO.\n");
                gnrc_pktbuf_release(pkt);
                return;
            }
            pkt = hdr;
        }
    }
#endif /* MODULE_GNRC_SIXLOWPAN_ND_ROUTER */
    if (ipv6_iface->flags & GNRC_IPV6_NETIF_FLAGS_ADV_MTU) {
        if ((hdr = gnrc_ndp_opt_mtu_build(ipv6_iface->mtu, pkt)) == NULL) {
            DEBUG("ndp rtr: no space left in packet buffer\n");
            mutex_unlock(&ipv6_iface->mutex);
            gnrc_pktbuf_release(pkt);
            return;
        }
        pkt = hdr;
    }
    if (src == NULL) {
        mutex_unlock(&ipv6_iface->mutex);
        /* get address from source selection algorithm */
        src = gnrc_ipv6_netif_find_best_src_addr(iface, dst);
        mutex_lock(&ipv6_iface->mutex);
    }
    /* add SL2A for source address */
    if (src != NULL) {
        DEBUG(" - SL2A\n");
        uint8_t l2src[8];
        size_t l2src_len;
        /* optimization note: MAY also be omitted to facilitate in-bound load balancing over
         * replicated interfaces.
         * source: https://tools.ietf.org/html/rfc4861#section-6.2.3 */
        l2src_len = _get_l2src(iface, l2src, sizeof(l2src));
        if (l2src_len > 0) {
            /* add source address link-layer address option */
            hdr = gnrc_ndp_opt_sl2a_build(l2src, l2src_len, pkt);

            if (hdr == NULL) {
                DEBUG("ndp internal: error allocating Source Link-layer address option.\n");
                mutex_unlock(&ipv6_iface->mutex);
                gnrc_pktbuf_release(pkt);
                return;
            }
            pkt = hdr;
        }
    }
    if (ipv6_iface->flags & GNRC_IPV6_NETIF_FLAGS_ADV_CUR_HL) {
        cur_hl = ipv6_iface->cur_hl;
    }
    if (ipv6_iface->flags & GNRC_IPV6_NETIF_FLAGS_ADV_REACH_TIME) {

        if (ipv6_iface->reach_time > (3600 * SEC_IN_USEC)) { /* reach_time > 1 hour */
            reach_time = (3600 * SEC_IN_MS);
        }
        else {
            reach_time = ipv6_iface->reach_time / MS_IN_USEC;
        }
    }
    if (ipv6_iface->flags & GNRC_IPV6_NETIF_FLAGS_ADV_RETRANS_TIMER) {
        retrans_timer = ipv6_iface->retrans_timer / MS_IN_USEC;
    }
    if (!fin) {
        adv_ltime = ipv6_iface->adv_ltime;
    }
    mutex_unlock(&ipv6_iface->mutex);
    hdr = gnrc_ndp_rtr_adv_build(cur_hl,
                                 (ipv6_iface->flags & (GNRC_IPV6_NETIF_FLAGS_OTHER_CONF |
                                                       GNRC_IPV6_NETIF_FLAGS_MANAGED)) >> 8,
                                 adv_ltime, reach_time, retrans_timer, pkt);
    if (hdr == NULL) {
        DEBUG("ndp internal: error allocating router advertisement.\n");
        gnrc_pktbuf_release(pkt);
        return;
    }
    pkt = hdr;
    hdr = _build_headers(iface, pkt, dst, src);
    if (hdr == NULL) {
        DEBUG("ndp internal: error adding lower-layer headers.\n");
        gnrc_pktbuf_release(pkt);
        return;
    }
    else if (gnrc_netapi_send(gnrc_ipv6_pid, hdr) < 1) {
        DEBUG("ndp internal: unable to send router advertisement\n");
        gnrc_pktbuf_release(hdr);
    }
}
Exemplo n.º 30
0
bool gnrc_ndp_internal_pi_opt_handle(kernel_pid_t iface, uint8_t icmpv6_type,
                                     ndp_opt_pi_t *pi_opt)
{
    ipv6_addr_t *prefix;
    gnrc_ipv6_netif_addr_t *netif_addr;

    if ((pi_opt->len != NDP_OPT_PI_LEN)) {
        DEBUG("ndp: invalid PI option received\n");
        return false;
    }
    if (icmpv6_type != ICMPV6_RTR_ADV || ipv6_addr_is_link_local(&pi_opt->prefix)) {
        /* else discard silently */
        return true;
    }
#ifdef MODULE_GNRC_SIXLOWPAN_ND
    if ((gnrc_ipv6_netif_get(iface)->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN) &&
        (pi_opt->flags & NDP_OPT_PI_FLAGS_L)) {
        /* ignore: see https://tools.ietf.org/html/rfc6775#section-5.4 */
        return true;
    }
#endif
    prefix = gnrc_ipv6_netif_find_addr(iface, &pi_opt->prefix);
    if (((prefix == NULL) ||
         (gnrc_ipv6_netif_addr_get(prefix)->prefix_len != pi_opt->prefix_len)) &&
        (pi_opt->valid_ltime.u32 != 0)) {
        ipv6_addr_t pref_addr;

        if ((gnrc_netapi_get(iface, NETOPT_IPV6_IID, 0, &pref_addr.u64[1],
                             sizeof(eui64_t)) < 0)) {
            DEBUG("ndp: could not get IID from interface %d\n", iface);
            return false;
        }
        ipv6_addr_init_prefix(&pref_addr, &pi_opt->prefix, pi_opt->prefix_len);
        prefix = gnrc_ipv6_netif_add_addr(iface, &pref_addr,
                                          pi_opt->prefix_len,
                                          pi_opt->flags & NDP_OPT_PI_FLAGS_MASK);
        if (prefix == NULL) {
            DEBUG("ndp: could not add prefix to interface %d\n", iface);
            return false;
        }
#ifdef MODULE_GNRC_SIXLOWPAN_ND_ROUTER
        gnrc_sixlowpan_nd_router_set_rtr_adv(gnrc_ipv6_netif_get(iface), true);
#endif
    }
    netif_addr = gnrc_ipv6_netif_addr_get(prefix);
    if (pi_opt->valid_ltime.u32 == 0) {
        if (prefix != NULL) {
            gnrc_ipv6_netif_remove_addr(iface, &netif_addr->addr);
        }

        return true;
    }
    netif_addr->valid = byteorder_ntohl(pi_opt->valid_ltime);
    netif_addr->preferred = byteorder_ntohl(pi_opt->pref_ltime);
    if (netif_addr->valid != UINT32_MAX) {
        xtimer_set_msg(&netif_addr->valid_timeout,
                       (byteorder_ntohl(pi_opt->valid_ltime) * SEC_IN_USEC),
                       &netif_addr->valid_timeout_msg, thread_getpid());
    }
    /* TODO: preferred lifetime for address auto configuration */
    /* on-link flag MUST stay set if it was */
    netif_addr->flags &= ~NDP_OPT_PI_FLAGS_A;
    netif_addr->flags |= (pi_opt->flags & NDP_OPT_PI_FLAGS_MASK);
    return true;
}