Ejemplo n.º 1
0
void gnrc_ipv6_demux(kernel_pid_t iface, gnrc_pktsnip_t *pkt, uint8_t nh)
{
    int receiver_num;

    pkt->type = gnrc_nettype_from_protnum(nh);

    switch (nh) {
#ifdef MODULE_GNRC_ICMPV6
        case PROTNUM_ICMPV6:
            DEBUG("ipv6: handle ICMPv6 packet (nh = %" PRIu8 ")\n", nh);
            gnrc_icmpv6_demux(iface, pkt);
            break;
#endif
#ifdef MODULE_GNRC_IPV6_EXT
        case PROTNUM_IPV6_EXT_HOPOPT:
        case PROTNUM_IPV6_EXT_DST:
        case PROTNUM_IPV6_EXT_RH:
        case PROTNUM_IPV6_EXT_FRAG:
        case PROTNUM_IPV6_EXT_AH:
        case PROTNUM_IPV6_EXT_ESP:
        case PROTNUM_IPV6_EXT_MOB:
            DEBUG("ipv6: handle extension header (nh = %" PRIu8 ")\n", nh);
            if (!gnrc_ipv6_ext_demux(iface, pkt, nh)) {
                DEBUG("ipv6: unable to parse extension headers.\n");
                gnrc_pktbuf_release(pkt);
                return;
            }
#endif
        case PROTNUM_IPV6:
            DEBUG("ipv6: handle encapsulated IPv6 packet (nh = %" PRIu8 ")\n", nh);
            _decapsulate(pkt);
            break;
        default:
            (void)iface;
            break;
    }

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

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

    gnrc_pktbuf_hold(pkt, receiver_num - 1);    /* IPv6 is not interested anymore so `- 1` */

    /* XXX can't use gnrc_netapi_dispatch_receive() twice here since a call to that function
     *     implicitly hands all rights to the packet to one of the receiving threads. As a result,
     *     the second call to gnrc_netapi_dispatch_receive() would be invalid */
    _dispatch_rcv_pkt(pkt->type, GNRC_NETREG_DEMUX_CTX_ALL, pkt);
    _dispatch_rcv_pkt(GNRC_NETTYPE_IPV6, nh, pkt);
}
Ejemplo n.º 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;
}
Ejemplo n.º 3
0
/* internal functions */
static void _dispatch_next_header(gnrc_pktsnip_t *current, gnrc_pktsnip_t *pkt,
                                  uint8_t nh, bool interested)
{
#ifdef MODULE_GNRC_IPV6_EXT
    const bool should_dispatch_current_type = ((current->type != GNRC_NETTYPE_IPV6_EXT) ||
                                               (current->next->type == GNRC_NETTYPE_IPV6));
#else
    const bool should_dispatch_current_type = (current->next->type == GNRC_NETTYPE_IPV6);
#endif

    DEBUG("ipv6: forward nh = %u to other threads\n", nh);

    /* dispatch IPv6 extension header only once */
    if (should_dispatch_current_type) {
        bool should_release = (gnrc_netreg_num(GNRC_NETTYPE_IPV6, nh) == 0) &&
                              (!interested);

        if (!should_release) {
            gnrc_pktbuf_hold(pkt, 1);   /* don't remove from packet buffer in
                                         * next dispatch */
        }
        if (gnrc_netapi_dispatch_receive(current->type,
                                         GNRC_NETREG_DEMUX_CTX_ALL,
                                         pkt) == 0) {
            gnrc_pktbuf_release(pkt);
        }

        if (should_release) {
            return;
        }
    }
    if (interested) {
        gnrc_pktbuf_hold(pkt, 1);   /* don't remove from packet buffer in
                                     * next dispatch */
    }
    if (gnrc_netapi_dispatch_receive(GNRC_NETTYPE_IPV6, nh, pkt) == 0) {
        gnrc_pktbuf_release(pkt);
    }
}
Ejemplo n.º 4
0
int _tftp_init_ctxt(ipv6_addr_t *addr, const char *file_name,
                    tftp_opcodes_t op, tftp_mode_t mode, tftp_context_type type,
                    tftp_start_cb_t start, tftp_stop_cb_t stop,
                    tftp_data_cb_t data, bool enable_options, tftp_context_t *ctxt)
{

    if (!addr) {
        return TS_FAILED;
    }

    memset(ctxt, 0, sizeof(*ctxt));

    /* set the default context parameters */
    ctxt->op = op;
    ctxt->ct = type;
    ctxt->data_cb = data;
    ctxt->start_cb = start;
    ctxt->stop_cb = stop;
    memcpy(&(ctxt->peer), addr, sizeof(ctxt->peer));
    ctxt->mode = mode;
    if (file_name) {
        strncpy(ctxt->file_name, file_name, GNRC_TFTP_MAX_FILENAME_LEN);
    }
    ctxt->file_name[GNRC_TFTP_MAX_FILENAME_LEN - 1] = 0;
    ctxt->dst_port = GNRC_TFTP_DEFAULT_DST_PORT;
    ctxt->enable_options = enable_options;

    /* transport layer parameters */
    ctxt->block_size = GNRC_TFTP_MAX_TRANSFER_UNIT;
    ctxt->block_timeout = GNRC_TFTP_DEFAULT_TIMEOUT;
    ctxt->write_finished = false;

    /* generate a random source UDP source port */
    do {
        ctxt->src_port = (random_uint32() & 0xff) + GNRC_TFTP_DEFAULT_SRC_PORT;
    } while (gnrc_netreg_num(GNRC_NETTYPE_UDP, ctxt->src_port));

    return TS_FINISHED;
}
Ejemplo n.º 5
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);
    }
}
Ejemplo n.º 6
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);
    }
}