Exemple #1
0
static void _dispatch_rcv_pkt(gnrc_nettype_t type, uint32_t demux_ctx,
                              gnrc_pktsnip_t *pkt)
{
    gnrc_netreg_entry_t *entry = gnrc_netreg_lookup(type, demux_ctx);

    while (entry) {
        DEBUG("ipv6: Send receive command for %p to %" PRIu16 "\n", (void *)pkt,
              entry->pid);
        gnrc_netapi_receive(entry->pid, pkt);
        entry = gnrc_netreg_getnext(entry);
    }
}
Exemple #2
0
int gnrc_netapi_dispatch(gnrc_nettype_t type, uint32_t demux_ctx,
                         uint16_t cmd, gnrc_pktsnip_t *pkt)
{
    int numof = gnrc_netreg_num(type, demux_ctx);

    if (numof != 0) {
        gnrc_netreg_entry_t *sendto = gnrc_netreg_lookup(type, demux_ctx);

        gnrc_pktbuf_hold(pkt, numof - 1);

        while (sendto) {
            if (_snd_rcv(sendto->pid, cmd, pkt) < 1) {
                /* unable to dispatch packet */
                gnrc_pktbuf_release(pkt);
            }
            sendto = gnrc_netreg_getnext(sendto);
        }
    }

    return numof;
}
Exemple #3
0
void gnrc_icmpv6_echo_req_handle(kernel_pid_t iface, ipv6_hdr_t *ipv6_hdr,
                                 icmpv6_echo_t *echo, uint16_t len)
{
    uint8_t *payload = ((uint8_t *)echo) + sizeof(icmpv6_echo_t);
    gnrc_pktsnip_t *hdr, *pkt;
    gnrc_netreg_entry_t *sendto = NULL;

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

    pkt = gnrc_icmpv6_echo_build(ICMPV6_ECHO_REP, byteorder_ntohs(echo->id),
                                 byteorder_ntohs(echo->seq), payload,
                                 len - sizeof(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 = gnrc_ipv6_hdr_build(pkt, NULL, 0, (uint8_t *)&ipv6_hdr->src,
                                  sizeof(ipv6_addr_t));
    }
    else {
        hdr = gnrc_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");
        gnrc_pktbuf_release(pkt);
        return;
    }

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

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

    LL_PREPEND(pkt, hdr);

    sendto = gnrc_netreg_lookup(GNRC_NETTYPE_IPV6, GNRC_NETREG_DEMUX_CTX_ALL);

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

    /* ICMPv6 is not interested anymore so `- 1` */
    gnrc_pktbuf_hold(pkt, gnrc_netreg_num(GNRC_NETTYPE_IPV6, GNRC_NETREG_DEMUX_CTX_ALL) - 1);

    while (sendto != NULL) {
        if (gnrc_netapi_send(sendto->pid, pkt) < 1) {
            DEBUG("icmpv6_echo: unable to send packet\n");
            gnrc_pktbuf_release(pkt);
        }
        sendto = gnrc_netreg_getnext(sendto);
    }
}
Exemple #4
0
void gnrc_icmpv6_demux(kernel_pid_t iface, gnrc_pktsnip_t *pkt)
{
    gnrc_pktsnip_t *icmpv6, *ipv6;
    icmpv6_hdr_t *hdr;
    gnrc_netreg_entry_t *sendto;

    LL_SEARCH_SCALAR(pkt, icmpv6, type, GNRC_NETTYPE_ICMPV6);

    assert(icmpv6 != NULL);

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

    assert(ipv6 != NULL);

    hdr = (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_GNRC_ICMPV6_ECHO
        case ICMPV6_ECHO_REQ:
            DEBUG("icmpv6: handle echo request.\n");
            gnrc_icmpv6_echo_req_handle(iface, (ipv6_hdr_t *)ipv6->data,
                                        (icmpv6_echo_t *)hdr, icmpv6->size);
            break;
#endif

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

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

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

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

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

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

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

    sendto = gnrc_netreg_lookup(GNRC_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` */
    gnrc_pktbuf_hold(pkt, gnrc_netreg_num(GNRC_NETTYPE_ICMPV6, hdr->type));

    while (sendto != NULL) {
        gnrc_netapi_receive(sendto->pid, pkt);
        sendto = gnrc_netreg_getnext(sendto);
    }
}