Esempio n. 1
0
static void _send(ng_pktsnip_t *pkt)
{
    ng_udp_hdr_t *hdr;
    ng_pktsnip_t *udp_snip;
    ng_netreg_entry_t *sendto;

    /* get udp snip and hdr */
    LL_SEARCH_SCALAR(pkt, udp_snip, type, NG_NETTYPE_UDP);
    udp_snip = ng_pktbuf_start_write(udp_snip);
    if (udp_snip == NULL) {
        DEBUG("udp: cannot send packet: unable to allocate packet\n");
        ng_pktbuf_release(pkt);
        return;
    }
    hdr = (ng_udp_hdr_t *)udp_snip->data;
    /* fill in size field */
    hdr->length = byteorder_htons(ng_pkt_len(udp_snip));

    /* and forward packet to the network layer */
    sendto = ng_netreg_lookup(pkt->type, NG_NETREG_DEMUX_CTX_ALL);
    /* throw away packet if no one is interested */
    if (sendto == NULL) {
        DEBUG("udp: cannot send packet: network layer not found\n");
        ng_pktbuf_release(pkt);
        return;
    }
    /* send packet to network layer */
    ng_pktbuf_hold(pkt, ng_netreg_num(pkt->type, NG_NETREG_DEMUX_CTX_ALL) - 1);
    while (sendto != NULL) {
        ng_netapi_send(sendto->pid, pkt);
        sendto = ng_netreg_getnext(sendto);
    }
}
Esempio n. 2
0
static void test_pktbuf_hold__pkt_external(void)
{
    ng_pktsnip_t pkt = { 1, NULL, TEST_STRING8, sizeof(TEST_STRING8), NG_NETTYPE_TEST };

    ng_pktbuf_hold(&pkt, 1);
    TEST_ASSERT(ng_pktbuf_is_empty());
}
Esempio n. 3
0
static void _send_to_iface(kernel_pid_t iface, ng_pktsnip_t *pkt)
{
    ng_ipv6_netif_t *if_entry = ng_ipv6_netif_get(iface);

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

    if ((if_entry != NULL) && (if_entry->flags & NG_IPV6_NETIF_FLAGS_SIXLOWPAN)) {
        DEBUG("ipv6: send to 6LoWPAN instead\n");
        ng_netreg_entry_t *reg = ng_netreg_lookup(NG_NETTYPE_SIXLOWPAN,
                                                  NG_NETREG_DEMUX_CTX_ALL);

        if (reg != NULL) {
            ng_pktbuf_hold(pkt, ng_netreg_num(NG_NETTYPE_SIXLOWPAN,
                                              NG_NETREG_DEMUX_CTX_ALL) - 1);
        }
        else {
            DEBUG("ipv6: no 6LoWPAN thread found");
        }

        while (reg) {
            ng_netapi_send(reg->pid, pkt);
            reg = ng_netreg_getnext(reg);
        }
    }
    else {
        ng_netapi_send(iface, pkt);
    }
}
Esempio n. 4
0
/**
 * @brief   Function called by the device driver on device events
 *
 * @param[in] event         type of event
 * @param[in] data          optional parameter
 */
static void _event_cb(ng_netdev_event_t event, void *data)
{
    DEBUG("nomac: event triggered -> %i\n", event);
    /* NOMAC only understands the RX_COMPLETE event... */
    if (event == NETDEV_EVENT_RX_COMPLETE) {
        ng_pktsnip_t *pkt;
        ng_netreg_entry_t *sendto;

        /* get pointer to the received packet */
        pkt = (ng_pktsnip_t *)data;
        /* find out, who to send the packet to */
        sendto = ng_netreg_lookup(pkt->type, NG_NETREG_DEMUX_CTX_ALL);
        /* throw away packet if no one is interested */
        if (sendto == NULL) {
            DEBUG("nomac: unable to forward packet of type %i\n", pkt->type);
            ng_pktbuf_release(pkt);
            return;
        }
        /* send the packet to everyone interested in it's type */
        ng_pktbuf_hold(pkt, ng_netreg_num(pkt->type, NG_NETREG_DEMUX_CTX_ALL) - 1);
        while (sendto != NULL) {
            DEBUG("nomac: sending pkt %p to PID %u\n", (void*)pkt, sendto->pid);
            ng_netapi_receive(sendto->pid, pkt);
            sendto = ng_netreg_getnext(sendto);
        }
    }
}
Esempio n. 5
0
void ng_ipv6_demux(kernel_pid_t iface, ng_pktsnip_t *pkt, uint8_t nh)
{
    int receiver_num;

    pkt->type = ng_nettype_from_protnum(nh);

    switch (nh) {
        case NG_PROTNUM_ICMPV6:
            ng_icmpv6_demux(iface, pkt);
            break;
        /* TODO: add extension header handling */
        default:
            break;
    }

    receiver_num = ng_netreg_num(pkt->type, NG_NETREG_DEMUX_CTX_ALL) +
                   ng_netreg_num(NG_NETTYPE_IPV6, nh);

    if (receiver_num == 0) {
        DEBUG("ipv6: unable to forward packet as no one is interested in it\n");
        ng_pktbuf_release(pkt);
        return;
    }

    ng_pktbuf_hold(pkt, receiver_num - 1);
    /* IPv6 is not interested anymore so `- 1` */
    _dispatch_rcv_pkt(pkt->type, NG_NETREG_DEMUX_CTX_ALL, pkt);
    _dispatch_rcv_pkt(NG_NETTYPE_IPV6, nh, pkt);
}
Esempio n. 6
0
static void test_pktbuf_hold__success2(void)
{
    ng_pktsnip_t *pkt = ng_pktbuf_add(NULL, TEST_STRING16, sizeof(TEST_STRING16), NG_NETTYPE_TEST);

    ng_pktbuf_hold(pkt, TEST_UINT8);

    TEST_ASSERT_EQUAL_INT(TEST_UINT8 + 1, pkt->users);
}
Esempio n. 7
0
static void send(char *addr_str, char *port_str, char *data)
{
    uint8_t port[2];
    uint16_t tmp;
    ng_pktsnip_t *payload, *udp, *ip;
    ng_ipv6_addr_t addr;
    ng_netreg_entry_t *sendto;

    /* parse destination address */
    if (ng_ipv6_addr_from_str(&addr, addr_str) == NULL) {
        puts("Error: unable to parse destination address");
        return;
    }
    /* parse port */
    tmp = (uint16_t)atoi(port_str);
    if (tmp == 0) {
        puts("Error: unable to parse destination port");
        return;
    }
    port[0] = (uint8_t)tmp;
    port[1] = tmp >> 8;

    /* allocate payload */
    payload = ng_pktbuf_add(NULL, data, strlen(data), NG_NETTYPE_UNDEF);
    if (payload == NULL) {
        puts("Error: unable to copy data to packet buffer");
        return;
    }
    /* allocate UDP header, set source port := destination port */
    udp = ng_udp_hdr_build(payload, port, 2, port, 2);
    if (udp == NULL) {
        puts("Error: unable to allocate UDP header");
        ng_pktbuf_release(payload);
        return;
    }
    /* allocate IPv6 header */
    ip = ng_ipv6_hdr_build(udp, NULL, 0, (uint8_t *)&addr, sizeof(addr));
    if (ip == NULL) {
        puts("Error: unable to allocate IPv6 header");
        ng_pktbuf_release(udp);
        return;
    }
    /* send packet */
    sendto = ng_netreg_lookup(NG_NETTYPE_UDP, NG_NETREG_DEMUX_CTX_ALL);
    if (sendto == NULL) {
        puts("Error: unable to locate UDP thread");
        ng_pktbuf_release(ip);
        return;
    }
    ng_pktbuf_hold(ip, ng_netreg_num(NG_NETTYPE_UDP,
                                     NG_NETREG_DEMUX_CTX_ALL) - 1);
    while (sendto != NULL) {
        ng_netapi_send(sendto->pid, ip);
        sendto = ng_netreg_getnext(sendto);
    }
    printf("Success: send %i byte to %s:%u\n", payload->size, addr_str, tmp);
}
Esempio n. 8
0
static void test_pktbuf_realloc_data__pkt_users_gt_1(void)
{
    ng_pktsnip_t *pkt = ng_pktbuf_add(NULL, NULL, sizeof(TEST_STRING8), NG_NETTYPE_UNDEF);
    ng_pktbuf_hold(pkt, 1);

    TEST_ASSERT_EQUAL_INT(EINVAL, ng_pktbuf_realloc_data(pkt, sizeof(TEST_STRING8) - 1));
    ng_pktbuf_release(pkt);
    ng_pktbuf_release(pkt);
    TEST_ASSERT(ng_pktbuf_is_empty());
}
Esempio n. 9
0
static void test_pktbuf_hold__success(void)
{
    ng_pktsnip_t *pkt = ng_pktbuf_add(NULL, TEST_STRING16, sizeof(TEST_STRING16), NG_NETTYPE_TEST);

    for (uint8_t i = 0; i < TEST_UINT8; i++) {
        uint8_t prev_users = pkt->users;
        ng_pktbuf_hold(pkt, 1);
        TEST_ASSERT_EQUAL_INT(prev_users + 1, pkt->users);
    }
}
Esempio n. 10
0
/* SLIP receive handler */
static void _slip_receive(ng_slip_dev_t *dev, size_t bytes)
{
    ng_netif_hdr_t *hdr;
    ng_netreg_entry_t *sendto;
    ng_pktsnip_t *pkt, *netif_hdr;

    pkt = ng_pktbuf_add(NULL, NULL, bytes, NG_NETTYPE_UNDEF);

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

    netif_hdr = ng_pktbuf_add(pkt, NULL, sizeof(ng_netif_hdr_t),
                              NG_NETTYPE_NETIF);

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

    hdr = netif_hdr->data;
    ng_netif_hdr_init(hdr, 0, 0);
    hdr->if_pid = thread_getpid();

    if (ringbuffer_get(dev->in_buf, pkt->data, bytes) != bytes) {
        DEBUG("slip: could not read %zu bytes from ringbuffer\n", bytes);
        ng_pktbuf_release(pkt);
        return;
    }

#ifdef MODULE_NG_IPV6
    if ((pkt->size >= sizeof(ipv6_hdr_t)) && ipv6_hdr_is(pkt->data)) {
        pkt->type = NG_NETTYPE_IPV6;
    }
#endif

    sendto = ng_netreg_lookup(pkt->type, NG_NETREG_DEMUX_CTX_ALL);

    if (sendto == NULL) {
        DEBUG("slip: unable to forward packet of type %i\n", pkt->type);
        ng_pktbuf_release(pkt);
    }

    ng_pktbuf_hold(pkt, ng_netreg_num(pkt->type, NG_NETREG_DEMUX_CTX_ALL) - 1);

    while (sendto != NULL) {
        DEBUG("slip: sending pkt %p to PID %u\n", pkt, sendto->pid);
        ng_netapi_receive(sendto->pid, pkt);
        sendto = ng_netreg_getnext(sendto);
    }
}
Esempio n. 11
0
static void _receive(ng_pktsnip_t *pkt)
{
    ng_pktsnip_t *udp, *ipv6;
    ng_udp_hdr_t *hdr;
    uint32_t port;
    ng_netreg_entry_t *sendto;

    /* mark UDP header */
    udp = ng_pktbuf_start_write(pkt);
    if (udp == NULL) {
        DEBUG("udp: unable to get write access to packet\n");
        ng_pktbuf_release(pkt);
        return;
    }
    pkt = udp;
    udp = ng_pktbuf_add(pkt, pkt->data, sizeof(ng_udp_hdr_t), NG_NETTYPE_UDP);
    if (udp == NULL) {
        DEBUG("udp: error marking UDP header, dropping packet\n");
        ng_pktbuf_release(pkt);
        return;
    }
    /* mark payload as Type: UNDEF */
    pkt->type = NG_NETTYPE_UNDEF;
    /* get explicit pointer to UDP header */
    hdr = (ng_udp_hdr_t *)udp->data;

    LL_SEARCH_SCALAR(pkt, ipv6, type, NG_NETTYPE_IPV6);

    /* validate checksum */
    if (_calc_csum(udp, ipv6, pkt)) {
        DEBUG("udp: received packet with invalid checksum, dropping it\n");
        ng_pktbuf_release(pkt);
        return;
    }

    /* get port (netreg demux context) */
    port = (uint32_t)byteorder_ntohs(hdr->dst_port);

    /* send payload to receivers */
    sendto = ng_netreg_lookup(NG_NETTYPE_UDP, port);
    if (sendto == NULL) {
        DEBUG("udp: unable to forward packet as no one is interested in it\n");
        ng_pktbuf_release(pkt);
        return;
    }
    ng_pktbuf_hold(pkt, ng_netreg_num(NG_NETTYPE_UDP, port) - 1);
    while (sendto != NULL) {
        ng_netapi_receive(sendto->pid, pkt);
        sendto = ng_netreg_getnext(sendto);
    }
}
Esempio n. 12
0
void ng_ipv6_demux(kernel_pid_t iface, ng_pktsnip_t *pkt, uint8_t nh)
{
    int receiver_num;

    pkt->type = ng_nettype_from_protnum(nh);

    switch (nh) {
        case NG_PROTNUM_ICMPV6:
            DEBUG("ipv6: handle ICMPv6 packet (nh = %" PRIu8 ")\n", nh);
            ng_icmpv6_demux(iface, pkt);
            break;
#ifdef MODULE_NG_IPV6_EXT
        case NG_PROTNUM_IPV6_EXT_HOPOPT:
        case NG_PROTNUM_IPV6_EXT_DST:
        case NG_PROTNUM_IPV6_EXT_RH:
        case NG_PROTNUM_IPV6_EXT_FRAG:
        case NG_PROTNUM_IPV6_EXT_AH:
        case NG_PROTNUM_IPV6_EXT_ESP:
        case NG_PROTNUM_IPV6_EXT_MOB:
            DEBUG("ipv6: handle extension header (nh = %" PRIu8 ")\n", nh);
            if (!ng_ipv6_ext_demux(iface, pkt, nh)) {
                DEBUG("ipv6: unable to parse extension headers.\n");
                ng_pktbuf_release(pkt);
                return;
            }
#endif
        case NG_PROTNUM_IPV6:
            DEBUG("ipv6: handle encapsulated IPv6 packet (nh = %" PRIu8 ")\n", nh);
            _decapsulate(pkt);
            break;
        default:
            break;
    }

    DEBUG("ipv6: forward nh = %" PRIu8 " to other threads\n", nh);
    receiver_num = ng_netreg_num(pkt->type, NG_NETREG_DEMUX_CTX_ALL) +
                   ng_netreg_num(NG_NETTYPE_IPV6, nh);

    if (receiver_num == 0) {
        DEBUG("ipv6: unable to forward packet as no one is interested in it\n");
        ng_pktbuf_release(pkt);
        return;
    }

    ng_pktbuf_hold(pkt, receiver_num - 1);
    /* IPv6 is not interested anymore so `- 1` */
    _dispatch_rcv_pkt(pkt->type, NG_NETREG_DEMUX_CTX_ALL, pkt);
    _dispatch_rcv_pkt(NG_NETTYPE_IPV6, nh, pkt);
}
Esempio n. 13
0
static void test_pktbuf_start_write__pkt_users_2(void)
{
    ng_pktsnip_t *pkt_copy, *pkt = ng_pktbuf_add(NULL, TEST_STRING16, sizeof(TEST_STRING16),
                                   NG_NETTYPE_TEST);

    ng_pktbuf_hold(pkt, 1);
    TEST_ASSERT_NOT_NULL((pkt_copy = ng_pktbuf_start_write(pkt)));
    TEST_ASSERT(pkt != pkt_copy);
    TEST_ASSERT(pkt->next == pkt_copy->next);
    TEST_ASSERT_EQUAL_STRING(pkt->data, pkt_copy->data);
    TEST_ASSERT_EQUAL_INT(pkt->size, pkt_copy->size);
    TEST_ASSERT_EQUAL_INT(pkt->type, pkt_copy->type);
    TEST_ASSERT_EQUAL_INT(pkt->users, pkt_copy->users);
    TEST_ASSERT_EQUAL_INT(1, pkt->users);

    ng_pktbuf_release(pkt_copy);
    ng_pktbuf_release(pkt);
    TEST_ASSERT(ng_pktbuf_is_empty());
}
Esempio n. 14
0
static void udp_send(const char *str)
{
    uint8_t data[20];
    ng_pktsnip_t *payload, *udp, *ip;
    ng_netreg_entry_t *sendto;

    memcpy(data, str, strlen(str));

    /* allocate payload */
    payload = ng_pktbuf_add(NULL, data, strlen(str), NG_NETTYPE_UNDEF);
    if (payload == NULL) {
        puts("Error: unable to copy data to packet buffer");
        return;
    }
    /* allocate UDP header, set source port := destination port */
    udp = ng_udp_hdr_build(payload, port, 2, port, 2);
    if (udp == NULL) {
        puts("Error: unable to allocate UDP header");
        ng_pktbuf_release(payload);
        return;
    }
    /* allocate IPv6 header */
    ip = ng_ipv6_hdr_build(udp, NULL, 0, (uint8_t *)&addr, sizeof(addr));
    if (ip == NULL) {
        puts("Error: unable to allocate IPv6 header");
        ng_pktbuf_release(udp);
        return;
    }
    /* send packet */
    sendto = ng_netreg_lookup(NG_NETTYPE_UDP, NG_NETREG_DEMUX_CTX_ALL);
    if (sendto == NULL) {
        puts("Error: unable to locate UDP thread");
        ng_pktbuf_release(ip);
        return;
    }
    ng_pktbuf_hold(ip, ng_netreg_num(NG_NETTYPE_UDP,
                                     NG_NETREG_DEMUX_CTX_ALL) - 1);
    while (sendto != NULL) {
        ng_netapi_send(sendto->pid, ip);
        sendto = ng_netreg_getnext(sendto);
    }
    printf("Send %s\n", str);
}
Esempio n. 15
0
static void test_pktbuf_release__success(void)
{
    ng_pktsnip_t *pkt = ng_pktbuf_add(NULL, TEST_STRING16, sizeof(TEST_STRING16), NG_NETTYPE_UNDEF);

    for (uint8_t i = 0; i < TEST_UINT8; i++) {
        uint8_t prev_users = pkt->users;
        ng_pktbuf_hold(pkt, 1);
        TEST_ASSERT_EQUAL_INT(prev_users + 1, pkt->users);
    }

    TEST_ASSERT(!ng_pktbuf_is_empty());

    for (uint8_t i = 0; i < TEST_UINT8; i++) {
        uint8_t prev_users = pkt->users;
        ng_pktbuf_release(pkt);
        TEST_ASSERT_EQUAL_INT(prev_users - 1, pkt->users);
    }

    TEST_ASSERT(!ng_pktbuf_is_empty());
    ng_pktbuf_release(pkt);
    TEST_ASSERT(ng_pktbuf_is_empty());
}
Esempio n. 16
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);
    }
}
Esempio n. 17
0
void _receive(ng_pktsnip_t *pkt)
{
    ng_pktsnip_t *payload;
    uint8_t *dispatch;
    ng_netreg_entry_t *entry;

    LL_SEARCH_SCALAR(pkt, payload, type, NG_NETTYPE_SIXLOWPAN);

    if ((payload == NULL) || (payload->size < 1)) {
        DEBUG("6lo: Received packet has no 6LoWPAN payload\n");
        ng_pktbuf_release(pkt);
    }

    dispatch = payload->data;

    if (dispatch[0] == NG_SIXLOWPAN_UNCOMPRESSED) {
        ng_pktsnip_t *sixlowpan;
        DEBUG("6lo: received uncompressed IPv6 packet\n");
        payload = ng_pktbuf_start_write(payload);

        if (payload == NULL) {
            DEBUG("6lo: can not get write access on received packet\n");
#if defined(DEVELHELP) && defined(ENABLE_DEBUG)
            ng_pktbuf_stats();
#endif
            ng_pktbuf_release(pkt);
            return;
        }

        /* packet is uncompressed: just mark and remove the dispatch */
        sixlowpan = ng_pktbuf_add(payload, payload->data, sizeof(uint8_t),
                                  NG_NETTYPE_SIXLOWPAN);
        LL_DELETE(pkt, sixlowpan);
        ng_pktbuf_release(sixlowpan);
    }
#ifdef MODULE_NG_SIXLOWPAN_FRAG
    else if (ng_sixlowpan_frag_is((ng_sixlowpan_frag_t *)dispatch)) {
        DEBUG("6lo: received 6LoWPAN fragment\n");
        ng_sixlowpan_frag_handle_pkt(pkt);
    }
#endif
    else {
        DEBUG("6lo: dispatch %02x ... is not supported\n",
              dispatch[0]);
        ng_pktbuf_release(pkt);
        return;
    }

    payload->type = NG_NETTYPE_IPV6;

    entry = ng_netreg_lookup(NG_NETTYPE_IPV6, NG_NETREG_DEMUX_CTX_ALL);

    if (entry == NULL) {
        DEBUG("ipv6: No receivers for this packet found\n");
        ng_pktbuf_release(pkt);
        return;
    }

    ng_pktbuf_hold(pkt, ng_netreg_num(NG_NETTYPE_IPV6, NG_NETREG_DEMUX_CTX_ALL) - 1);

    while (entry) {
        DEBUG("6lo: Send receive command for %p to %" PRIu16 "\n",
              (void *)pkt, entry->pid);
        ng_netapi_receive(entry->pid, pkt);
        entry = ng_netreg_getnext(entry);
    }
}
Esempio n. 18
0
static void test_pktbuf_hold__pkt_null(void)
{
    ng_pktbuf_hold(NULL, 1);
    TEST_ASSERT(ng_pktbuf_is_empty());
}
Esempio n. 19
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 */
}
Esempio n. 20
0
kernel_pid_t ng_ndp_next_hop_l2addr(uint8_t *l2addr, uint8_t *l2addr_len,
                                    kernel_pid_t iface, ng_ipv6_addr_t *dst,
                                    ng_pktsnip_t *pkt)
{
    ng_ipv6_addr_t *next_hop_ip = NULL, *prefix = NULL;

#ifdef MODULE_NG_IPV6_EXT_RH
    next_hop_ip = ng_ipv6_ext_rh_next_hop(hdr);
#endif
#ifdef MODULE_FIB
    size_t next_hop_size = sizeof(ng_ipv6_addr_t);
    uint32_t next_hop_flags = 0;
    ng_ipv6_addr_t next_hop_actual; /* FIB copies address into this variable */

    if ((next_hop_ip == NULL) &&
        (fib_get_next_hop(&iface, next_hop_actual.u8, &next_hop_size,
                          &next_hop_flags, (uint8_t *)dst,
                          sizeof(ng_ipv6_addr_t), 0) >= 0) &&
        (next_hop_size == sizeof(ng_ipv6_addr_t))) {
        next_hop_ip = &next_hop_actual;
    }

#endif

    if (next_hop_ip == NULL) {            /* no route to host */
        if (iface == KERNEL_PID_UNDEF) {
            /* ng_ipv6_netif_t doubles as prefix list */
            iface = ng_ipv6_netif_find_by_prefix(&prefix, dst);
        }
        else {
            /* ng_ipv6_netif_t doubles as prefix list */
            prefix = ng_ipv6_netif_match_prefix(iface, dst);
        }

        if ((prefix != NULL) &&             /* prefix is on-link */
            (ng_ipv6_netif_addr_get(prefix)->flags &
             NG_IPV6_NETIF_ADDR_FLAGS_NDP_ON_LINK)) {
            next_hop_ip = dst;
#ifdef MODULE_FIB
            /* We don't care if FIB is full, this is just for efficiency
             * for later sends */
            fib_add_entry(iface, (uint8_t *)dst, sizeof(ng_ipv6_addr_t), 0,
                          (uint8_t *)next_hop_ip, sizeof(ng_ipv6_addr_t), 0,
                          FIB_LIFETIME_NO_EXPIRE);
#endif
        }
    }

    if (next_hop_ip == NULL) {
        next_hop_ip = _default_router();
#ifdef MODULE_FIB
        /* We don't care if FIB is full, this is just for efficiency for later
         * sends */
        fib_add_entry(iface, (uint8_t *)dst, sizeof(ng_ipv6_addr_t), 0,
                      (uint8_t *)next_hop_ip, sizeof(ng_ipv6_addr_t), 0,
                      FIB_LIFETIME_NO_EXPIRE);
#endif
    }

    if (next_hop_ip != NULL) {
        ng_ipv6_nc_t *nc_entry = ng_ipv6_nc_get(iface, next_hop_ip);

        if ((nc_entry != NULL) && ng_ipv6_nc_is_reachable(nc_entry)) {
            DEBUG("ndp: found reachable neighbor (%s => ",
                  ng_ipv6_addr_to_str(addr_str, &nc_entry->ipv6_addr, sizeof(addr_str)));
            DEBUG("%s)\n",
                  ng_netif_addr_to_str(addr_str, sizeof(addr_str),
                                       nc_entry->l2_addr, nc_entry->l2_addr_len));

            if (ng_ipv6_nc_get_state(nc_entry) == NG_IPV6_NC_STATE_STALE) {
                _set_state(nc_entry, NG_IPV6_NC_STATE_DELAY);
            }

            memcpy(l2addr, nc_entry->l2_addr, nc_entry->l2_addr_len);
            *l2addr_len = nc_entry->l2_addr_len;
            /* TODO: unreachability check */
            return nc_entry->iface;
        }
        else if (nc_entry == NULL) {
            ng_pktqueue_t *pkt_node;
            ng_ipv6_addr_t dst_sol;

            nc_entry = ng_ipv6_nc_add(iface, next_hop_ip, NULL, 0,
                                      NG_IPV6_NC_STATE_INCOMPLETE << NG_IPV6_NC_STATE_POS);

            if (nc_entry == NULL) {
                DEBUG("ndp: could not create neighbor cache entry\n");
                return KERNEL_PID_UNDEF;
            }

            pkt_node = _alloc_pkt_node(pkt);

            if (pkt_node == NULL) {
                DEBUG("ndp: could not add packet to packet queue\n");
            }
            else {
                /* prevent packet from being released by IPv6 */
                ng_pktbuf_hold(pkt_node->pkt, 1);
                ng_pktqueue_add(&nc_entry->pkts, pkt_node);
            }

            /* address resolution */
            ng_ipv6_addr_set_solicited_nodes(&dst_sol, next_hop_ip);

            if (iface == KERNEL_PID_UNDEF) {
                timex_t t = { 0, NG_NDP_RETRANS_TIMER };
                kernel_pid_t ifs[NG_NETIF_NUMOF];
                size_t ifnum = ng_netif_get(ifs);

                for (size_t i = 0; i < ifnum; i++) {
                    _send_nbr_sol(ifs[i], next_hop_ip, &dst_sol);
                }

                vtimer_remove(&nc_entry->nbr_sol_timer);
                vtimer_set_msg(&nc_entry->nbr_sol_timer, t, ng_ipv6_pid,
                               NG_NDP_MSG_NBR_SOL_RETRANS, nc_entry);
            }
            else {
                ng_ipv6_netif_t *ipv6_iface = ng_ipv6_netif_get(iface);

                _send_nbr_sol(iface, next_hop_ip, &dst_sol);

                mutex_lock(&ipv6_iface->mutex);
                vtimer_remove(&nc_entry->nbr_sol_timer);
                vtimer_set_msg(&nc_entry->nbr_sol_timer,
                               ipv6_iface->retrans_timer, ng_ipv6_pid,
                               NG_NDP_MSG_NBR_SOL_RETRANS, nc_entry);
                mutex_unlock(&ipv6_iface->mutex);
            }
        }
    }

    return KERNEL_PID_UNDEF;
}
Esempio n. 21
0
void ng_icmpv6_demux(kernel_pid_t iface, ng_pktsnip_t *pkt)
{
    ng_pktsnip_t *icmpv6, *ipv6;
    ng_icmpv6_hdr_t *hdr;
    ng_netreg_entry_t *sendto;

    LL_SEARCH_SCALAR(pkt, icmpv6, type, NG_NETTYPE_ICMPV6);

    /* there can be extension headers between IPv6 and ICMPv6 header so we have
     * to search it */
    LL_SEARCH_SCALAR(icmpv6, ipv6, type, NG_NETTYPE_IPV6);

    hdr = (ng_icmpv6_hdr_t *)icmpv6->data;

    if (_calc_csum(icmpv6, ipv6, pkt)) {
        DEBUG("icmpv6: wrong checksum.\n");
        /* don't release: IPv6 does this */
        return;
    }

    switch (hdr->type) {
        /* TODO: handle ICMPv6 errors */
#ifdef MODULE_NG_ICMPV6_ECHO
        case NG_ICMPV6_ECHO_REQ:
            DEBUG("icmpv6: handle echo request.\n");
            ng_icmpv6_echo_req_handle(iface, (ng_ipv6_hdr_t *)ipv6->data,
                                      (ng_icmpv6_echo_t *)hdr, icmpv6->size);
            break;
#endif

        case NG_ICMPV6_RTR_SOL:
            DEBUG("icmpv6: router solicitation received\n");
            /* TODO */
            break;

        case NG_ICMPV6_RTR_ADV:
            DEBUG("icmpv6: router advertisement received\n");
            /* TODO */
            break;

        case NG_ICMPV6_NBR_SOL:
            DEBUG("icmpv6: neighbor solicitation received\n");
            ng_ndp_nbr_sol_handle(iface, pkt, ipv6->data, (ng_ndp_nbr_sol_t *)hdr,
                                  icmpv6->size);
            break;

        case NG_ICMPV6_NBR_ADV:
            DEBUG("icmpv6: neighbor advertisement received\n");
            ng_ndp_nbr_adv_handle(iface, pkt, ipv6->data, (ng_ndp_nbr_adv_t *)hdr,
                                  icmpv6->size);
            break;

        case NG_ICMPV6_REDIRECT:
            DEBUG("icmpv6: redirect message received\n");
            /* TODO */
            break;

#ifdef MODULE_NG_RPL
        case NG_ICMPV6_RPL_CTRL:
            DEBUG("icmpv6: RPL control message received\n");
            /* TODO */
            break;
#endif

        default:
            DEBUG("icmpv6: unknown type field %" PRIu8 "\n", hdr->type);
            break;
    }

    /* ICMPv6-all will be send in ng_ipv6.c so only dispatch of subtypes is
     * needed */

    sendto = ng_netreg_lookup(NG_NETTYPE_ICMPV6, hdr->type);

    if (sendto == NULL) {
        DEBUG("icmpv6: no receivers for ICMPv6 type %" PRIu8 "\n", hdr->type);
        /* don't release: IPv6 does this */
        return;
    }

    /* ICMPv6 is not interested anymore so `- 1` */
    ng_pktbuf_hold(pkt, ng_netreg_num(NG_NETTYPE_ICMPV6, hdr->type));

    while (sendto != NULL) {
        ng_netapi_receive(sendto->pid, pkt);
        sendto = ng_netreg_getnext(sendto);
    }
}