inline void check_ipv6()

in src/filtration/packet.h [170:262]


    inline void check_ipv6() __attribute__((always_inline))
    {
        if(dlen < sizeof(IPv6Header)) return;
        auto header = reinterpret_cast<const IPv6Header*>(data);

        if(header->version() != 6) return;

        data += sizeof(IPv6Header);
        dlen -= sizeof(IPv6Header);

        const uint32_t payload = header->payload_len();
        if(payload == 0) return;   // The length is set to zero when a Hop-by-Hop extension header carries a Jumbo Payload option
        if(dlen < payload) return; // truncated packet

        dlen = payload; // skip padding at the end
        // handling optional headers
        uint8_t htype = header->nexthdr();
    switch_type: // TODO: remove ugly goto
        switch(htype)
        {
        case ip::NextProtocol::TCP:
            check_tcp();
            break;
        case ip::NextProtocol::UDP:
            check_udp();
            break;

        case ip::NextProtocol::HOPOPTS:
        {
            auto               hbh = reinterpret_cast<const ipv6_hbh*>(data);
            const unsigned int size{1U + hbh->hbh_len};

            if(dlen < size) return; // truncated packet

            data += size;
            dlen -= size;

            htype = hbh->hbh_nexthdr;
            goto switch_type;
        }

        case ip::NextProtocol::DSTOPTS:
        {
            auto               dest = reinterpret_cast<const ipv6_dest*>(data);
            const unsigned int size{1U + dest->dest_len};

            if(dlen < size) return; // truncated packet

            data += size;
            dlen -= size;

            htype = dest->dest_nexthdr;
            goto switch_type;
        }

        case ip::NextProtocol::ROUTING:
        {
            auto               route = reinterpret_cast<const ipv6_route*>(data);
            const unsigned int size{1U + route->route_len};

            if(dlen < size) return; // truncated packet

            data += size;
            dlen -= size;

            htype = route->route_nexthdr;
            goto switch_type;
        }

        case ip::NextProtocol::FRAGMENT:
        {
            auto frag = reinterpret_cast<const ipv6_frag*>(data);

            // isn't first fragment (offset != 0)
            if((ntohs(frag->frag_offlg) & ipv6_frag::OFFSET) != 0) return;

            const unsigned int size{sizeof(ipv6_frag)};

            if(dlen < size) return; // truncated packet

            data += size;
            dlen -= size;

            htype = frag->frag_nexthdr;
            goto switch_type;
        }
        case ip::NextProtocol::NONE:
        default: // unknown header
            return;
        }

        ipv6 = header;
    }