Beispiel #1
0
/* functions for sending */
static void _send_unicast(kernel_pid_t iface, uint8_t *dst_l2addr,
                          uint16_t dst_l2addr_len, ng_pktsnip_t *pkt)
{
    ng_pktsnip_t *netif;

    if (pkt->type == NG_NETTYPE_NETIF) {
        /* great: someone already added a netif_hdr_t we assume it's wrong
         * to keep it simple
         * XXX: alternative would be to check if ng_netif_hdr_t::dst_l2addr_len
         * is long enough and only then to throw away the header. This causes
         * to much overhead IMHO */
        DEBUG("ipv6: removed old interface header\n");
        pkt = ng_pktbuf_remove_snip(pkt, pkt);
    }

    DEBUG("ipv6: add to interface header to packet\n");
    netif = ng_netif_hdr_build(NULL, 0, dst_l2addr, dst_l2addr_len);

    if (netif == NULL) {
        DEBUG("ipv6: error on interface header allocation, dropping packet\n");
        ng_pktbuf_release(pkt);
        return;
    }

    /* add netif to front of the pkt list */
    LL_PREPEND(pkt, netif);

    DEBUG("ipv6: send unicast over interface %" PRIkernel_pid "\n", iface);
    /* and send to interface */
    _send_to_iface(iface, pkt);
}
Beispiel #2
0
static ng_pktsnip_t *_build_frag_pkt(ng_pktsnip_t *pkt, size_t payload_len,
                                     size_t size)
{
    ng_netif_hdr_t *hdr = pkt->data, *new_hdr;
    ng_pktsnip_t *netif, *frag;

    netif = ng_netif_hdr_build(ng_netif_hdr_get_src_addr(hdr), hdr->src_l2addr_len,
                               ng_netif_hdr_get_dst_addr(hdr), hdr->dst_l2addr_len);

    if (netif == NULL) {
        DEBUG("6lo frag: error allocating new link-layer header\n");
        return NULL;
    }

    new_hdr = netif->data;
    new_hdr->if_pid = hdr->if_pid;
    new_hdr->flags = hdr->flags;
    new_hdr->rssi = hdr->rssi;
    new_hdr->lqi = hdr->lqi;

    frag = ng_pktbuf_add(NULL, NULL, _min(size, payload_len),
                         NG_NETTYPE_SIXLOWPAN);

    if (frag == NULL) {
        DEBUG("6lo frag: error allocating first fragment\n");
        ng_pktbuf_release(netif);
        return NULL;
    }

    LL_PREPEND(frag, netif);

    return frag;
}
Beispiel #3
0
void ng_icmpv6_echo_req_handle(kernel_pid_t iface, ng_ipv6_hdr_t *ipv6_hdr,
                               ng_icmpv6_echo_t *echo, uint16_t len)
{
    uint8_t *payload = ((uint8_t *)echo) + sizeof(ng_icmpv6_echo_t);
    ng_pktsnip_t *hdr, *pkt;
    ng_netreg_entry_t *sendto = NULL;

    if ((echo == NULL) || (len < sizeof(ng_icmpv6_echo_t))) {
        DEBUG("icmpv6_echo: echo was NULL or len (%" PRIu16
              ") was < sizeof(ng_icmpv6_echo_t)\n", len);
        return;
    }

    pkt = ng_icmpv6_echo_build(NG_ICMPV6_ECHO_REP, byteorder_ntohs(echo->id),
                               byteorder_ntohs(echo->seq), payload,
                               len - sizeof(ng_icmpv6_echo_t));

    if (pkt == NULL) {
        DEBUG("icmpv6_echo: no space left in packet buffer\n");
        return;
    }

    if (ipv6_addr_is_multicast(&ipv6_hdr->dst)) {
        hdr = ng_ipv6_hdr_build(pkt, NULL, 0, (uint8_t *)&ipv6_hdr->src,
                                sizeof(ipv6_addr_t));
    }
    else {
        hdr = ng_ipv6_hdr_build(pkt, (uint8_t *)&ipv6_hdr->dst,
                                sizeof(ipv6_addr_t), (uint8_t *)&ipv6_hdr->src,
                                sizeof(ipv6_addr_t));
    }

    if (hdr == NULL) {
        DEBUG("icmpv6_echo: no space left in packet buffer\n");
        ng_pktbuf_release(pkt);
        return;
    }

    pkt = hdr;
    hdr = ng_netif_hdr_build(NULL, 0, NULL, 0);

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

    LL_PREPEND(pkt, hdr);

    sendto = ng_netreg_lookup(NG_NETTYPE_IPV6, NG_NETREG_DEMUX_CTX_ALL);

    if (sendto == NULL) {
        DEBUG("icmpv6_echo: no receivers for IPv6 packets\n");
        ng_pktbuf_release(pkt);
        return;
    }

    /* ICMPv6 is not interested anymore so `- 1` */
    ng_pktbuf_hold(pkt, ng_netreg_num(NG_NETTYPE_IPV6, NG_NETREG_DEMUX_CTX_ALL) - 1);

    while (sendto != NULL) {
        ng_netapi_send(sendto->pid, pkt);
        sendto = ng_netreg_getnext(sendto);
    }
}
Beispiel #4
0
static void _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: 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: 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: 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: 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: 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 = { _rand(0, NG_NDP_MAX_AC_TGT_DELAY), 0 };
        ng_ipv6_nc_t *nc_entry = ng_ipv6_nc_get(iface, tgt);
        DEBUG("ndp: 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);
    }
}
Beispiel #5
0
static void _send_nbr_sol(kernel_pid_t iface, ng_ipv6_addr_t *tgt,
                          ng_ipv6_addr_t *dst)
{
    ng_pktsnip_t *hdr, *pkt = NULL;
    ng_ipv6_addr_t *src = NULL;
    size_t src_len = 0;

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

    /* check if there is a fitting source address to target */
    if ((src = ng_ipv6_netif_find_best_src_addr(iface, tgt)) != NULL) {
        uint8_t l2src[8];
        uint16_t l2src_len;
        src_len = sizeof(ng_ipv6_addr_t);
        l2src_len = _get_l2src(l2src, sizeof(l2src), iface);

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

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

    hdr = ng_ndp_nbr_sol_build(tgt, pkt);

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

    pkt = hdr;
    hdr = ng_ipv6_hdr_build(pkt, (uint8_t *)src, src_len, (uint8_t *)dst,
                            sizeof(ng_ipv6_addr_t));

    if (hdr == NULL) {
        DEBUG("ndp: 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: error allocating netif header.\n");
        return;
    }

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

    LL_PREPEND(pkt, hdr);

    ng_netapi_send(ng_ipv6_pid, pkt);
}
Beispiel #6
0
static void _send_multicast(kernel_pid_t iface, ng_pktsnip_t *pkt,
                            ng_pktsnip_t *ipv6, ng_pktsnip_t *payload,
                            bool prep_hdr)
{
    ng_pktsnip_t *netif;
    kernel_pid_t ifs[NG_NETIF_NUMOF];
    size_t ifnum = 0;

    if (iface == KERNEL_PID_UNDEF) {
        /* get list of interfaces */
        ifnum = ng_netif_get(ifs);

        /* throw away packet if no one is interested */
        if (ifnum == 0) {
            DEBUG("ipv6: no interfaces registered, dropping packet\n");
            ng_pktbuf_release(pkt);
            return;
        }
    }


#if NG_NETIF_NUMOF > 1
    /* netif header not present: send over all interfaces */
    if (iface == KERNEL_PID_UNDEF) {
        /* send packet to link layer */
        ng_pktbuf_hold(pkt, ifnum - 1);

        for (size_t i = 0; i < ifnum; i++) {
            if (prep_hdr) {
                /* need to get second write access (duplication) to fill IPv6
                 * header interface-local */
                ipv6 = ng_pktbuf_start_write(ipv6);

                if (ipv6 == NULL) {
                    DEBUG("ipv6: unable to get write access to IPv6 header, "
                          "for interface %" PRIkernel_pid "\n", ifs[i]);
                    ng_pktbuf_release(pkt);
                    return;
                }

                if (_fill_ipv6_hdr(ifs[i], ipv6, payload) < 0) {
                    /* error on filling up header */
                    ng_pktbuf_release(pkt);
                    return;
                }
            }

            /* allocate interface header */
            netif = ng_netif_hdr_build(NULL, 0, NULL, 0);

            if (netif == NULL) {
                DEBUG("ipv6: error on interface header allocation, "
                      "dropping packet\n");
                ng_pktbuf_release(pkt);
                return;
            }

            LL_PREPEND(pkt, netif);

            _send_multicast_over_iface(ifs[i], pkt, netif);
        }
    }
    else {
        /* iface != KERNEL_PID_UNDEF implies that netif header is present */
        if (prep_hdr) {
            if (_fill_ipv6_hdr(iface, ipv6, payload) < 0) {
                /* error on filling up header */
                ng_pktbuf_release(pkt);
                return;
            }
        }

        netif = pkt;

        _send_multicast_over_iface(iface, pkt, netif);
    }
#else   /* NG_NETIF_NUMOF */
    (void)ifnum; /* not used in this build branch */
    if (iface == KERNEL_PID_UNDEF) {
        iface = ifs[0];

        /* allocate interface header */
        netif = ng_netif_hdr_build(NULL, 0, NULL, 0);

        if (netif == NULL) {
            DEBUG("ipv6: error on interface header allocation, "
                  "dropping packet\n");
            ng_pktbuf_release(pkt);
            return;
        }

        LL_PREPEND(pkt, netif);
    }
    else {
        netif = pkt;
    }

    if (prep_hdr) {
        if (_fill_ipv6_hdr(iface, ipv6, payload) < 0) {
            /* error on filling up header */
            ng_pktbuf_release(pkt);
            return;
        }
    }

    _send_multicast_over_iface(iface, pkt, netif);
#endif  /* NG_NETIF_NUMOF */
}
Beispiel #7
0
void rbuf_add(ng_netif_hdr_t *netif_hdr, ng_pktsnip_t *pkt,
              size_t frag_size, size_t offset)
{
    rbuf_t *entry;
    /* cppcheck is clearly wrong here */
    /* cppcheck-suppress variableScope */
    unsigned int data_offset = 0;
    ng_sixlowpan_frag_t *frag = pkt->data;
    rbuf_int_t *ptr;
    uint8_t *data = ((uint8_t *)pkt->data) + sizeof(ng_sixlowpan_frag_t);

    _rbuf_gc();
    entry = _rbuf_get(ng_netif_hdr_get_src_addr(netif_hdr), netif_hdr->src_l2addr_len,
                      ng_netif_hdr_get_dst_addr(netif_hdr), netif_hdr->dst_l2addr_len,
                      byteorder_ntohs(frag->disp_size) & NG_SIXLOWPAN_FRAG_SIZE_MASK,
                      byteorder_ntohs(frag->tag));

    if (entry == NULL) {
        DEBUG("6lo rbuf: reassembly buffer full.\n");
        return;
    }

    ptr = entry->ints;

    /* dispatches in the first fragment are ignored */
    if (offset == 0) {
        if (data[0] == NG_SIXLOWPAN_UNCOMPRESSED) {
            data++;             /* skip 6LoWPAN dispatch */
            frag_size--;
        }
#ifdef MODULE_NG_SIXLOWPAN_IPHC
        else if (ng_sixlowpan_iphc_is(data)) {
            size_t iphc_len;
            iphc_len = ng_sixlowpan_iphc_decode(entry->pkt, pkt,
                                                sizeof(ng_sixlowpan_frag_t));
            if (iphc_len == 0) {
                DEBUG("6lo rfrag: could not decode IPHC dispatch\n");
                ng_pktbuf_release(entry->pkt);
                _rbuf_rem(entry);
                return;
            }
            data += iphc_len;       /* take remaining data as data */
            frag_size -= iphc_len;  /* and reduce frag size by IPHC dispatch length */
            frag_size += sizeof(ipv6_hdr_t);    /* but add IPv6 header length */
            data_offset += sizeof(ipv6_hdr_t);  /* start copying after IPv6 header */
        }
#endif
    }
    else {
        data++; /* FRAGN header is one byte longer (offset) */
    }

    if ((offset + frag_size) > entry->pkt->size) {
        DEBUG("6lo rfrag: fragment too big for resulting datagram, discarding datagram\n");
        ng_pktbuf_release(entry->pkt);
        _rbuf_rem(entry);
        return;
    }

    while (ptr != NULL) {
        if (_rbuf_int_in(ptr, offset, offset + frag_size - 1)) {
            DEBUG("6lo rfrag: overlapping or same intervals, discarding datagram\n");
            ng_pktbuf_release(entry->pkt);
            _rbuf_rem(entry);
            return;
        }

        ptr = ptr->next;
    }

    if (_rbuf_update_ints(entry, offset, frag_size)) {
        DEBUG("6lo rbuf: add fragment data\n");
        entry->cur_size += (uint16_t)frag_size;
        memcpy(((uint8_t *)entry->pkt->data) + offset + data_offset, data,
               frag_size - data_offset);
    }

    if (entry->cur_size == entry->pkt->size) {
        kernel_pid_t iface = netif_hdr->if_pid;
        ng_pktsnip_t *netif = ng_netif_hdr_build(entry->src, entry->src_len,
                              entry->dst, entry->dst_len);

        if (netif == NULL) {
            DEBUG("6lo rbuf: error allocating netif header\n");
            ng_pktbuf_release(entry->pkt);
            _rbuf_rem(entry);
            return;
        }

        netif_hdr = netif->data;
        netif_hdr->if_pid = iface;
        LL_APPEND(entry->pkt, netif);

        if (!ng_netapi_dispatch_receive(NG_NETTYPE_IPV6, NG_NETREG_DEMUX_CTX_ALL,
                                        entry->pkt)) {
            DEBUG("6lo rbuf: No receivers for this packet found\n");
            ng_pktbuf_release(entry->pkt);
        }

        _rbuf_rem(entry);
    }
}
Beispiel #8
0
void rbuf_add(ng_netif_hdr_t *netif_hdr, ng_sixlowpan_frag_t *frag,
              size_t frag_size, size_t offset)
{
    rbuf_t *entry;
    rbuf_int_t *ptr;
    uint8_t *data = ((uint8_t *)frag) + sizeof(ng_sixlowpan_frag_t);
    uint16_t dg_frag_size = frag_size; /* may differ on first fragment */

    _rbuf_gc();
    entry = _rbuf_get(ng_netif_hdr_get_src_addr(netif_hdr), netif_hdr->src_l2addr_len,
                      ng_netif_hdr_get_dst_addr(netif_hdr), netif_hdr->dst_l2addr_len,
                      byteorder_ntohs(frag->disp_size) & NG_SIXLOWPAN_FRAG_SIZE_MASK,
                      byteorder_ntohs(frag->tag));

    if (entry == NULL) {
        DEBUG("6lo rbuf: reassembly buffer full.\n");
        return;
    }

    ptr = entry->ints;

    /* dispatches in the first fragment are ignored */
    if (offset != 0) {
        switch (((uint8_t *)(entry->pkt->data))[0]) {
            case NG_SIXLOWPAN_UNCOMPRESSED:
                offset++;

                break;

            default:
                break;
        }

        data++;     /* also don't take offset field */
    }
    else {
        switch (data[0]) {
            case NG_SIXLOWPAN_UNCOMPRESSED:
                dg_frag_size--;

                break;

            default:
                break;
        }

    }

    if ((offset + frag_size) > entry->pkt->size) {
        DEBUG("6lo rfrag: fragment too big for resulting datagram, discarding datagram\n");
        ng_pktbuf_release(entry->pkt);
        _rbuf_rem(entry);
        return;
    }

    while (ptr != NULL) {
        if (_rbuf_int_in(ptr, offset, offset + dg_frag_size - 1)) {
            DEBUG("6lo rfrag: overlapping or same intervals, discarding datagram\n");
            ng_pktbuf_release(entry->pkt);
            _rbuf_rem(entry);
            return;
        }

        ptr = ptr->next;
    }

    if (_rbuf_update_ints(entry, offset, dg_frag_size)) {
        if (dg_frag_size < frag_size) {
            /* some dispatches do not count to datagram size and we need
             * more space because of that */
            if (ng_pktbuf_realloc_data(entry->pkt, entry->pkt->size +
                                       (frag_size - dg_frag_size)) < 0) {
                DEBUG("6lo rbuf: could not reallocate packet data.\n");
                return;
            }

            /* move already inserted fragments (frag_size - dg_frag_size) to the right */
            if (entry->cur_size > 0) {
                for (int i = entry->pkt->size - (frag_size - dg_frag_size); i > 0; i--) {
                    uint8_t *d = ((uint8_t *)(entry->pkt->data)) + i;
                    *d = *(d - 1);
                }
            }
        }

        DEBUG("6lo rbuf: add fragment data\n");
        entry->cur_size += (uint16_t)dg_frag_size;
        memcpy(((uint8_t *)entry->pkt->data) + offset, data, frag_size);
    }

    if (entry->cur_size == entry->datagram_size) {
        kernel_pid_t iface = netif_hdr->if_pid;
        ng_pktsnip_t *netif = ng_netif_hdr_build(entry->src, entry->src_len,
                              entry->dst, entry->dst_len);

        if (netif == NULL) {
            DEBUG("6lo rbuf: error allocating netif header\n");
            ng_pktbuf_release(entry->pkt);
            return;
        }

        netif_hdr = netif->data;
        netif_hdr->if_pid = iface;
        LL_APPEND(entry->pkt, netif);

        DEBUG("6lo rbuf: datagram complete, send to self\n");
        ng_netapi_receive(thread_getpid(), entry->pkt);
        _rbuf_rem(entry);
    }
}