Example #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);
}
Example #2
0
/*
 *         current                 pkt
 *         |                       |
 *         v                       v
 * IPv6 <- IPv6_EXT <- IPv6_EXT <- UNDEF
 */
void gnrc_ipv6_demux(kernel_pid_t iface, gnrc_pktsnip_t *current, gnrc_pktsnip_t *pkt, uint8_t nh)
{
    bool interested = false;

    current->type = gnrc_nettype_from_protnum(nh);

    switch (nh) {
#ifdef MODULE_GNRC_ICMPV6
        case PROTNUM_ICMPV6:
            assert(current == pkt);
            interested = true;
            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:
            interested = true;

            break;
#endif
        case PROTNUM_IPV6:
            assert(current == pkt);
            interested = true;

            break;
        default:
            (void)iface;
#ifdef MODULE_GNRC_SIXLOWPAN_IPHC_NHC
            /* second statement is true for small 6LoWPAN NHC decompressed frames
             * since in this case it looks like
             *
             * * GNRC_NETTYPE_UNDEF <- pkt
             * v
             * * GNRC_NETTYPE_UDP <- current
             * v
             * * GNRC_NETTYPE_EXT
             * v
             * * GNRC_NETTYPE_IPV6
             */
            assert((current == pkt) || (current == pkt->next));
#else
            assert(current == pkt);
#endif
            break;
    }

    _dispatch_next_header(current, pkt, nh, interested);

    if (!interested) {
        return;
    }

    switch (nh) {
#ifdef MODULE_GNRC_ICMPV6
        case PROTNUM_ICMPV6:
            DEBUG("ipv6: handle ICMPv6 packet (nh = %u)\n", nh);
            gnrc_icmpv6_demux(iface, pkt);
            gnrc_pktbuf_release(pkt);
            return;
#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 = %u)\n", nh);

            gnrc_ipv6_ext_demux(iface, current, pkt, nh);

            return;
#endif
        case PROTNUM_IPV6:
            DEBUG("ipv6: handle encapsulated IPv6 packet (nh = %u)\n", nh);
            _decapsulate(pkt);
            return;
        default:
            assert(false);
            break;
    }

    assert(false);
}