Example #1
0
void gnrc_icmpv6_demux(gnrc_netif_t *netif, gnrc_pktsnip_t *pkt)
{
    gnrc_pktsnip_t *icmpv6, *ipv6;
    icmpv6_hdr_t *hdr;

    icmpv6 = gnrc_pktsnip_search_type(pkt, GNRC_NETTYPE_ICMPV6);

    assert(icmpv6 != NULL);

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

    assert(ipv6 != NULL);

    if (icmpv6->size < sizeof(icmpv6_hdr_t)) {
        DEBUG("icmpv6: packet too short.\n");
        return;
    }

    /* Note: size will be checked again in packet handlers */

    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(netif, (ipv6_hdr_t *)ipv6->data,
                                        (icmpv6_echo_t *)hdr, icmpv6->size);
            break;
#endif

        case ICMPV6_RTR_SOL:
        case ICMPV6_RTR_ADV:
        case ICMPV6_NBR_SOL:
        case ICMPV6_NBR_ADV:
        case ICMPV6_REDIRECT:
        case ICMPV6_DAR:
        case ICMPV6_DAC:
            DEBUG("icmpv6: NDP message received. Handle with gnrc_ipv6_nib\n");
            gnrc_ipv6_nib_handle_pkt(netif, ipv6->data, hdr, icmpv6->size);
            break;

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

    /* ICMPv6-all will be send in gnrc_ipv6.c so only dispatch of subtypes is
     * needed */
    if (!gnrc_netapi_dispatch_receive(GNRC_NETTYPE_ICMPV6, hdr->type, pkt)) {
        DEBUG("icmpv6: no one interested in type %d\n", hdr->type);
        gnrc_pktbuf_release(pkt);
    }
}
Example #2
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);
    }
}