/**
 * \brief This function is used to match fragoffset rule option set on a packet
 *
 * \param t pointer to thread vars
 * \param det_ctx pointer to the pattern matcher thread
 * \param p pointer to the current packet
 * \param m pointer to the sigmatch that we will cast into DetectFragOffsetData
 *
 * \retval 0 no match or frag is not set
 * \retval 1 match
 *
 */
int DetectFragOffsetMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signature *s, const SigMatchCtx *ctx)
{
    uint16_t frag = 0;
    const DetectFragOffsetData *fragoff = (const DetectFragOffsetData *)ctx;

    if (PKT_IS_PSEUDOPKT(p))
        return 0;

    if (PKT_IS_IPV4(p)) {
        frag = IPV4_GET_IPOFFSET(p);
    } else if (PKT_IS_IPV6(p)) {
        if(IPV6_EXTHDR_FH(p)) {
            frag = IPV6_EXTHDR_GET_FH_OFFSET(p);
        } else {
            return 0;
        }
    } else {
        SCLogDebug("No IPv4 or IPv6 packet");
        return 0;
    }

    switch (fragoff->mode)  {
        case FRAG_LESS:
            if (frag < fragoff->frag_off) return 1;
            break;
        case FRAG_MORE:
            if (frag > fragoff->frag_off) return 1;
            break;
        default:
            if (frag == fragoff->frag_off) return 1;
    }

    return 0;
}
示例#2
0
static void
PrefilterPacketFragOffsetMatch(DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx)
{
    if (PKT_IS_PSEUDOPKT(p))
        return;

    uint16_t frag;

    if (PKT_IS_IPV4(p)) {
        frag = IPV4_GET_IPOFFSET(p);
    } else if (PKT_IS_IPV6(p)) {
        if (IPV6_EXTHDR_ISSET_FH(p)) {
            frag = IPV6_EXTHDR_GET_FH_OFFSET(p);
        } else {
            return;
        }
    } else {
        SCLogDebug("No IPv4 or IPv6 packet");
        return;
    }

    const PrefilterPacketHeaderCtx *ctx = pectx;
    if (FragOffsetMatch(frag, ctx->v1.u8[0], ctx->v1.u16[1]))
    {
        PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt);
    }
}
示例#3
0
/**
 * \brief This function is used to match fragoffset rule option set on a packet
 *
 * \param t pointer to thread vars
 * \param det_ctx pointer to the pattern matcher thread
 * \param p pointer to the current packet
 * \param m pointer to the sigmatch that we will cast into DetectFragOffsetData
 *
 * \retval 0 no match or frag is not set
 * \retval 1 match
 *
 */
int DetectFragOffsetMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signature *s, const SigMatchCtx *ctx)
{
    uint16_t frag = 0;
    const DetectFragOffsetData *fragoff = (const DetectFragOffsetData *)ctx;

    if (PKT_IS_PSEUDOPKT(p))
        return 0;

    if (PKT_IS_IPV4(p)) {
        frag = IPV4_GET_IPOFFSET(p);
    } else if (PKT_IS_IPV6(p)) {
        if (IPV6_EXTHDR_ISSET_FH(p)) {
            frag = IPV6_EXTHDR_GET_FH_OFFSET(p);
        } else {
            return 0;
        }
    } else {
        SCLogDebug("No IPv4 or IPv6 packet");
        return 0;
    }

    return FragOffsetMatch(frag, fragoff->mode, fragoff->frag_off);;
}
示例#4
0
static void
DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq)
{
    SCEnter();

    uint8_t *orig_pkt = pkt;
    uint8_t nh;
    uint16_t hdrextlen;
    uint16_t plen;
    char dstopts = 0;
    char exthdr_fh_done = 0;

    nh = IPV6_GET_NH(p);
    plen = len;

    while(1)
    {
        if (plen < 2) { /* minimal needed in a hdr */
            SCReturn;
        }

        switch(nh)
        {
            case IPPROTO_TCP:
                IPV6_SET_L4PROTO(p,nh);
                DecodeTCP(tv, dtv, p, pkt, plen, pq);
                SCReturn;

            case IPPROTO_UDP:
                IPV6_SET_L4PROTO(p,nh);
                DecodeUDP(tv, dtv, p, pkt, plen, pq);
                SCReturn;

            case IPPROTO_ICMPV6:
                IPV6_SET_L4PROTO(p,nh);
                DecodeICMPV6(tv, dtv, p, pkt, plen, pq);
                SCReturn;

            case IPPROTO_SCTP:
                IPV6_SET_L4PROTO(p,nh);
                DecodeSCTP(tv, dtv, p, pkt, plen, pq);
                SCReturn;

            case IPPROTO_ROUTING:
                IPV6_SET_L4PROTO(p,nh);
                hdrextlen = 8 + (*(pkt+1) * 8);  /* 8 bytes + length in 8 octet units */

                SCLogDebug("hdrextlen %"PRIu8, hdrextlen);

                if (hdrextlen > plen) {
                    ENGINE_SET_EVENT(p, IPV6_TRUNC_EXTHDR);
                    SCReturn;
                }

                if (p->IPV6_EH_CNT < IPV6_MAX_OPT)
                {
                    p->IPV6_EXTHDRS[p->IPV6_EH_CNT].type = nh;
                    p->IPV6_EXTHDRS[p->IPV6_EH_CNT].next = *pkt;
                    p->IPV6_EXTHDRS[p->IPV6_EH_CNT].len = hdrextlen;
                    p->IPV6_EXTHDRS[p->IPV6_EH_CNT].data = pkt+2;
                    p->IPV6_EH_CNT++;
                }

                if (IPV6_EXTHDR_ISSET_RH(p)) {
                    ENGINE_SET_EVENT(p, IPV6_EXTHDR_DUPL_RH);
                    /* skip past this extension so we can continue parsing the rest
                     * of the packet */
                    nh = *pkt;
                    pkt += hdrextlen;
                    plen -= hdrextlen;
                    break;
                }

                IPV6_EXTHDR_SET_RH(p, pkt);
                IPV6_EXTHDR_RH(p)->ip6rh_len = hdrextlen;
                /** \todo move into own function and load on demand */
                if (IPV6_EXTHDR_RH(p)->ip6rh_type == 0) {
                    uint8_t i;

                    uint8_t n = IPV6_EXTHDR_RH(p)->ip6rh_len / 2;

                    /* because we devide the header len by 2 (as rfc 2460 tells us to)
                     * we devide the result by 8 and not 16 as the header fields are
                     * sized */
                    for (i = 0; i < (n/8) && i < sizeof(IPV6_EXTHDR_RH(p)->ip6rh0_addr)/sizeof(struct in6_addr); ++i) {
                        /* the address header fields are 16 bytes in size */
                        /** \todo do this without memcpy since it's expensive */
                        memcpy(&IPV6_EXTHDR_RH(p)->ip6rh0_addr[i], pkt+(i*16)+8, sizeof(IPV6_EXTHDR_RH(p)->ip6rh0_addr[i]));
                    }
                    IPV6_EXTHDR_RH(p)->ip6rh0_num_addrs = i;
                }

                nh = *pkt;
                pkt += hdrextlen;
                plen -= hdrextlen;
                break;

            case IPPROTO_HOPOPTS:
            case IPPROTO_DSTOPTS:
            {
                IPV6OptHAO *hao = NULL;
                IPV6OptRA *ra = NULL;
                IPV6OptJumbo *jumbo = NULL;
                uint8_t optslen = 0;

                IPV6_SET_L4PROTO(p,nh);
                hdrextlen =  (*(pkt+1) + 1) << 3;
                if (hdrextlen > plen) {
                    ENGINE_SET_EVENT(p, IPV6_TRUNC_EXTHDR);
                    SCReturn;
                }

                if (p->IPV6_EH_CNT < IPV6_MAX_OPT)
                {
                    p->IPV6_EXTHDRS[p->IPV6_EH_CNT].type = nh;
                    p->IPV6_EXTHDRS[p->IPV6_EH_CNT].next = *pkt;
                    p->IPV6_EXTHDRS[p->IPV6_EH_CNT].len = hdrextlen;
                    p->IPV6_EXTHDRS[p->IPV6_EH_CNT].data = pkt+2;
                    p->IPV6_EH_CNT++;
                }

                uint8_t *ptr = pkt + 2; /* +2 to go past nxthdr and len */

                /* point the pointers to right structures
                 * in Packet. */
                if (nh == IPPROTO_HOPOPTS) {
                    if (IPV6_EXTHDR_ISSET_HH(p)) {
                        ENGINE_SET_EVENT(p, IPV6_EXTHDR_DUPL_HH);
                        /* skip past this extension so we can continue parsing the rest
                         * of the packet */
                        nh = *pkt;
                        pkt += hdrextlen;
                        plen -= hdrextlen;
                        break;
                    }

                    IPV6_EXTHDR_SET_HH(p, pkt);
                    hao = &IPV6_EXTHDR_HH_HAO(p);
                    ra = &IPV6_EXTHDR_HH_RA(p);
                    jumbo = &IPV6_EXTHDR_HH_JUMBO(p);

                    optslen = ((IPV6_EXTHDR_HH(p)->ip6hh_len+1)<<3)-2;
                }
                else if (nh == IPPROTO_DSTOPTS)
                {
                    if (dstopts == 0) {
                        IPV6_EXTHDR_SET_DH1(p, pkt);
                        hao = &IPV6_EXTHDR_DH1_HAO(p);
                        ra = &IPV6_EXTHDR_DH1_RA(p);
                        jumbo = &IPV6_EXTHDR_DH2_JUMBO(p);
                        optslen = ((IPV6_EXTHDR_DH1(p)->ip6dh_len+1)<<3)-2;
                        dstopts = 1;
                    } else if (dstopts == 1) {
                        IPV6_EXTHDR_SET_DH2(p, pkt);
                        hao = &IPV6_EXTHDR_DH2_HAO(p);
                        ra = &IPV6_EXTHDR_DH2_RA(p);
                        jumbo = &IPV6_EXTHDR_DH2_JUMBO(p);
                        optslen = ((IPV6_EXTHDR_DH2(p)->ip6dh_len+1)<<3)-2;
                        dstopts = 2;
                    } else {
                        ENGINE_SET_EVENT(p, IPV6_EXTHDR_DUPL_DH);
                        /* skip past this extension so we can continue parsing the rest
                         * of the packet */
                        nh = *pkt;
                        pkt += hdrextlen;
                        plen -= hdrextlen;
                        break;
                    }
                }

                if (optslen > plen) {
                    /* since the packet is long enough (we checked
                     * plen against hdrlen, the optlen must be malformed. */
                    ENGINE_SET_EVENT(p, IPV6_EXTHDR_INVALID_OPTLEN);
                    /* skip past this extension so we can continue parsing the rest
                     * of the packet */
                    nh = *pkt;
                    pkt += hdrextlen;
                    plen -= hdrextlen;
                    break;
                }
/** \todo move into own function to loaded on demand */
                uint16_t offset = 0;
                while(offset < optslen)
                {
                    if (*ptr == IPV6OPT_PADN) /* PadN */
                    {
                        //printf("PadN option\n");
                    }
                    else if (*ptr == IPV6OPT_RA) /* RA */
                    {
                        ra->ip6ra_type = *(ptr);
                        ra->ip6ra_len  = *(ptr + 1);
                        memcpy(&ra->ip6ra_value, (ptr + 2), sizeof(ra->ip6ra_value));
                        ra->ip6ra_value = ntohs(ra->ip6ra_value);
                        //printf("RA option: type %" PRIu32 " len %" PRIu32 " value %" PRIu32 "\n",
                        //    ra->ip6ra_type, ra->ip6ra_len, ra->ip6ra_value);
                    }
                    else if (*ptr == IPV6OPT_JUMBO) /* Jumbo */
                    {
                        jumbo->ip6j_type = *(ptr);
                        jumbo->ip6j_len  = *(ptr+1);
                        memcpy(&jumbo->ip6j_payload_len, (ptr+2), sizeof(jumbo->ip6j_payload_len));
                        jumbo->ip6j_payload_len = ntohl(jumbo->ip6j_payload_len);
                        //printf("Jumbo option: type %" PRIu32 " len %" PRIu32 " payload len %" PRIu32 "\n",
                        //    jumbo->ip6j_type, jumbo->ip6j_len, jumbo->ip6j_payload_len);
                    }
                    else if (*ptr == IPV6OPT_HAO) /* HAO */
                    {
                        hao->ip6hao_type = *(ptr);
                        hao->ip6hao_len  = *(ptr+1);
                        memcpy(&hao->ip6hao_hoa, (ptr+2), sizeof(hao->ip6hao_hoa));
                        //printf("HAO option: type %" PRIu32 " len %" PRIu32 " ",
                        //    hao->ip6hao_type, hao->ip6hao_len);
                        //char addr_buf[46];
                        //PrintInet(AF_INET6, (char *)&(hao->ip6hao_hoa),
                        //    addr_buf,sizeof(addr_buf));
                        //printf("home addr %s\n", addr_buf);
                    }
                    uint16_t optlen = (*(ptr + 1) + 2);
                    ptr += optlen; /* +2 for opt type and opt len fields */
                    offset += optlen;
                }

                nh = *pkt;
                pkt += hdrextlen;
                plen -= hdrextlen;
                break;
            }

            case IPPROTO_FRAGMENT:
                IPV6_SET_L4PROTO(p,nh);
                /* store the offset of this extension into the packet
                 * past the ipv6 header. We use it in defrag for creating
                 * a defragmented packet without the frag header */
                if (exthdr_fh_done == 0) {
                    p->ip6eh.fh_offset = pkt - orig_pkt;
                    exthdr_fh_done = 1;
                }

                hdrextlen = sizeof(IPV6FragHdr);
                if (hdrextlen > plen) {
                    ENGINE_SET_EVENT(p, IPV6_TRUNC_EXTHDR);
                    SCReturn;
                }

                if(p->IPV6_EH_CNT<IPV6_MAX_OPT)
                {
                    p->IPV6_EXTHDRS[p->IPV6_EH_CNT].type = nh;
                    p->IPV6_EXTHDRS[p->IPV6_EH_CNT].next = *pkt;
                    p->IPV6_EXTHDRS[p->IPV6_EH_CNT].len = hdrextlen;
                    p->IPV6_EXTHDRS[p->IPV6_EH_CNT].data = pkt+2;
                    p->IPV6_EH_CNT++;
                }

                if (IPV6_EXTHDR_ISSET_FH(p)) {
                    ENGINE_SET_EVENT(p, IPV6_EXTHDR_DUPL_FH);
                    nh = *pkt;
                    pkt += hdrextlen;
                    plen -= hdrextlen;
                    break;
                }

                /* set the header ptr first */
                IPV6_EXTHDR_SET_FH(p, pkt);

                /* if FH has offset 0 and no more fragments are coming, we
                 * parse this packet further right away, no defrag will be
                 * needed. It is a useless FH then though, so we do set an
                 * decoder event. */
                if (IPV6_EXTHDR_GET_FH_FLAG(p) == 0 && IPV6_EXTHDR_GET_FH_OFFSET(p) == 0) {
                    ENGINE_SET_EVENT(p, IPV6_EXTHDR_USELESS_FH);

                    nh = *pkt;
                    pkt += hdrextlen;
                    plen -= hdrextlen;
                    break;
                }

                /* the rest is parsed upon reassembly */
                SCReturn;

            case IPPROTO_ESP:
            {
                IPV6_SET_L4PROTO(p,nh);
                hdrextlen = sizeof(IPV6EspHdr);
                if (hdrextlen > plen) {
                    ENGINE_SET_EVENT(p, IPV6_TRUNC_EXTHDR);
                    SCReturn;
                }

                if(p->IPV6_EH_CNT<IPV6_MAX_OPT)
                {
                    p->IPV6_EXTHDRS[p->IPV6_EH_CNT].type = nh;
                    p->IPV6_EXTHDRS[p->IPV6_EH_CNT].next = IPPROTO_NONE;
                    p->IPV6_EXTHDRS[p->IPV6_EH_CNT].len = hdrextlen;
                    p->IPV6_EXTHDRS[p->IPV6_EH_CNT].data = pkt+2;
                    p->IPV6_EH_CNT++;
                }

                if (IPV6_EXTHDR_ISSET_EH(p)) {
                    ENGINE_SET_EVENT(p, IPV6_EXTHDR_DUPL_EH);
                    SCReturn;
                }

                IPV6_EXTHDR_SET_EH(p, pkt);

                nh = IPPROTO_NONE;
                pkt += hdrextlen;
                plen -= hdrextlen;
                break;
            }
            case IPPROTO_AH:
            {
                IPV6_SET_L4PROTO(p,nh);
                /* we need the header as a minimum */
                hdrextlen = sizeof(IPV6AuthHdr);
                /* the payload len field is the number of extra 4 byte fields,
                 * IPV6AuthHdr already contains the first */
                if (*(pkt+1) > 0)
                    hdrextlen += ((*(pkt+1) - 1) * 4);

                SCLogDebug("hdrextlen %"PRIu8, hdrextlen);

                if (hdrextlen > plen) {
                    ENGINE_SET_EVENT(p, IPV6_TRUNC_EXTHDR);
                    SCReturn;
                }

                IPV6AuthHdr *ahhdr = (IPV6AuthHdr *)pkt;
                if (ahhdr->ip6ah_reserved != 0x0000) {
                    ENGINE_SET_EVENT(p, IPV6_EXTHDR_AH_RES_NOT_NULL);
                }

                if(p->IPV6_EH_CNT < IPV6_MAX_OPT)
                {
                    p->IPV6_EXTHDRS[p->IPV6_EH_CNT].type = nh;
                    p->IPV6_EXTHDRS[p->IPV6_EH_CNT].next = *pkt;
                    p->IPV6_EXTHDRS[p->IPV6_EH_CNT].len = hdrextlen;
                    p->IPV6_EXTHDRS[p->IPV6_EH_CNT].data = pkt+2;
                    p->IPV6_EH_CNT++;
                }

                if (IPV6_EXTHDR_ISSET_AH(p)) {
                    ENGINE_SET_EVENT(p, IPV6_EXTHDR_DUPL_AH);
                    nh = *pkt;
                    pkt += hdrextlen;
                    plen -= hdrextlen;
                    break;
                }

                IPV6_EXTHDR_SET_AH(p, pkt);

                nh = *pkt;
                pkt += hdrextlen;
                plen -= hdrextlen;
                break;
            }
            case IPPROTO_IPIP:
                IPV6_SET_L4PROTO(p,nh);
                DecodeIPv4inIPv6(tv, dtv, p, pkt, plen, pq);
                SCReturn;
            case IPPROTO_NONE:
                IPV6_SET_L4PROTO(p,nh);
                SCReturn;

            default:
                IPV6_SET_L4PROTO(p,nh);
                SCReturn;
        }
    }

    SCReturn;
}
示例#5
0
void DecodeIPV6(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq)
{
    int ret;

    SCPerfCounterIncr(dtv->counter_ipv6, tv->sc_perf_pca);

    /* do the actual decoding */
    ret = DecodeIPV6Packet (tv, dtv, p, pkt, len);
    if (ret < 0) {
        p->ip6h = NULL;
        return;
    }

#ifdef DEBUG
    if (SCLogDebugEnabled()) { /* only convert the addresses if debug is really enabled */
        /* debug print */
        char s[46], d[46];
        PrintInet(AF_INET6, (const void *)GET_IPV6_SRC_ADDR(p), s, sizeof(s));
        PrintInet(AF_INET6, (const void *)GET_IPV6_DST_ADDR(p), d, sizeof(d));
        SCLogDebug("IPV6 %s->%s - CLASS: %" PRIu32 " FLOW: %" PRIu32 " NH: %" PRIu32 " PLEN: %" PRIu32 " HLIM: %" PRIu32 "", s,d,
                IPV6_GET_CLASS(p), IPV6_GET_FLOW(p), IPV6_GET_NH(p), IPV6_GET_PLEN(p),
                IPV6_GET_HLIM(p));
    }
#endif /* DEBUG */

    /* now process the Ext headers and/or the L4 Layer */
    switch(IPV6_GET_NH(p)) {
        case IPPROTO_TCP:
            IPV6_SET_L4PROTO (p, IPPROTO_TCP);
            return DecodeTCP(tv, dtv, p, pkt + IPV6_HEADER_LEN, IPV6_GET_PLEN(p), pq);
        case IPPROTO_UDP:
            IPV6_SET_L4PROTO (p, IPPROTO_UDP);
            return DecodeUDP(tv, dtv, p, pkt + IPV6_HEADER_LEN, IPV6_GET_PLEN(p), pq);
            break;
        case IPPROTO_ICMPV6:
            IPV6_SET_L4PROTO (p, IPPROTO_ICMPV6);
            return DecodeICMPV6(tv, dtv, p, pkt + IPV6_HEADER_LEN, IPV6_GET_PLEN(p), pq);
        case IPPROTO_SCTP:
            IPV6_SET_L4PROTO (p, IPPROTO_SCTP);
            return DecodeSCTP(tv, dtv, p, pkt + IPV6_HEADER_LEN, IPV6_GET_PLEN(p), pq);
        case IPPROTO_IPIP:
            IPV6_SET_L4PROTO(p, IPPROTO_IPIP);
            return DecodeIPv4inIPv6(tv, dtv, p, pkt + IPV6_HEADER_LEN, IPV6_GET_PLEN(p), pq);
        case IPPROTO_IPV6:
            return DecodeIP6inIP6(tv, dtv, p, pkt + IPV6_HEADER_LEN, IPV6_GET_PLEN(p), pq);
        case IPPROTO_FRAGMENT:
        case IPPROTO_HOPOPTS:
        case IPPROTO_ROUTING:
        case IPPROTO_NONE:
        case IPPROTO_DSTOPTS:
        case IPPROTO_AH:
        case IPPROTO_ESP:
            DecodeIPV6ExtHdrs(tv, dtv, p, pkt + IPV6_HEADER_LEN, IPV6_GET_PLEN(p), pq);
            break;

        default:
            p->proto = IPV6_GET_NH(p);
            break;
    }

    /* Pass to defragger if a fragment. */
    if (IPV6_EXTHDR_ISSET_FH(p)) {
        Packet *rp = Defrag(tv, dtv, NULL, p);
        if (rp != NULL) {
            DecodeIPV6(tv, dtv, rp, (uint8_t *)rp->ip6h, IPV6_GET_PLEN(rp) + IPV6_HEADER_LEN, pq);
            PacketEnqueue(pq, rp);

            /* Not really a tunnel packet, but we're piggybacking that
             * functionality for now. */
            SET_TUNNEL_PKT(p);
        }
    }

#ifdef DEBUG
    if (IPV6_EXTHDR_ISSET_FH(p)) {
        SCLogDebug("IPV6 FRAG - HDRLEN: %" PRIuMAX " NH: %" PRIu32 " OFFSET: %" PRIu32 " ID: %" PRIu32 "",
            (uintmax_t)IPV6_EXTHDR_GET_FH_HDRLEN(p), IPV6_EXTHDR_GET_FH_NH(p),
            IPV6_EXTHDR_GET_FH_OFFSET(p), IPV6_EXTHDR_GET_FH_ID(p));
    }
    if (IPV6_EXTHDR_ISSET_RH(p)) {
        SCLogDebug("IPV6 ROUTE - HDRLEN: %" PRIu32 " NH: %" PRIu32 " TYPE: %" PRIu32 "",
            IPV6_EXTHDR_GET_RH_HDRLEN(p), IPV6_EXTHDR_GET_RH_NH(p),
            IPV6_EXTHDR_GET_RH_TYPE(p));
    }
    if (IPV6_EXTHDR_ISSET_HH(p)) {
        SCLogDebug("IPV6 HOPOPT - HDRLEN: %" PRIu32 " NH: %" PRIu32 "",
            IPV6_EXTHDR_GET_HH_HDRLEN(p), IPV6_EXTHDR_GET_HH_NH(p));
    }
    if (IPV6_EXTHDR_ISSET_DH1(p)) {
        SCLogDebug("IPV6 DSTOPT1 - HDRLEN: %" PRIu32 " NH: %" PRIu32 "",
            IPV6_EXTHDR_GET_DH1_HDRLEN(p), IPV6_EXTHDR_GET_DH1_NH(p));
    }
    if (IPV6_EXTHDR_ISSET_DH2(p)) {
        SCLogDebug("IPV6 DSTOPT2 - HDRLEN: %" PRIu32 " NH: %" PRIu32 "",
            IPV6_EXTHDR_GET_DH2_HDRLEN(p), IPV6_EXTHDR_GET_DH2_NH(p));
    }
#endif
    return;
}
示例#6
0
int DecodeIPV6(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq)
{
    int ret;

    StatsIncr(tv, dtv->counter_ipv6);

    /* do the actual decoding */
    ret = DecodeIPV6Packet (tv, dtv, p, pkt, len);
    if (unlikely(ret < 0)) {
        p->ip6h = NULL;
        return TM_ECODE_FAILED;
    }

#ifdef DEBUG
    if (SCLogDebugEnabled()) { /* only convert the addresses if debug is really enabled */
        /* debug print */
        char s[46], d[46];
        PrintInet(AF_INET6, (const void *)GET_IPV6_SRC_ADDR(p), s, sizeof(s));
        PrintInet(AF_INET6, (const void *)GET_IPV6_DST_ADDR(p), d, sizeof(d));
        SCLogDebug("IPV6 %s->%s - CLASS: %" PRIu32 " FLOW: %" PRIu32 " NH: %" PRIu32 " PLEN: %" PRIu32 " HLIM: %" PRIu32 "", s,d,
                   IPV6_GET_CLASS(p), IPV6_GET_FLOW(p), IPV6_GET_NH(p), IPV6_GET_PLEN(p),
                   IPV6_GET_HLIM(p));
    }
#endif /* DEBUG */

    /* now process the Ext headers and/or the L4 Layer */
    switch(IPV6_GET_NH(p)) {
    case IPPROTO_TCP:
        IPV6_SET_L4PROTO (p, IPPROTO_TCP);
        DecodeTCP(tv, dtv, p, pkt + IPV6_HEADER_LEN, IPV6_GET_PLEN(p), pq);
        return TM_ECODE_OK;
    case IPPROTO_UDP:
        IPV6_SET_L4PROTO (p, IPPROTO_UDP);
        DecodeUDP(tv, dtv, p, pkt + IPV6_HEADER_LEN, IPV6_GET_PLEN(p), pq);
        return TM_ECODE_OK;
    case IPPROTO_ICMPV6:
        IPV6_SET_L4PROTO (p, IPPROTO_ICMPV6);
        DecodeICMPV6(tv, dtv, p, pkt + IPV6_HEADER_LEN, IPV6_GET_PLEN(p), pq);
        return TM_ECODE_OK;
    case IPPROTO_SCTP:
        IPV6_SET_L4PROTO (p, IPPROTO_SCTP);
        DecodeSCTP(tv, dtv, p, pkt + IPV6_HEADER_LEN, IPV6_GET_PLEN(p), pq);
        return TM_ECODE_OK;
    case IPPROTO_IPIP:
        IPV6_SET_L4PROTO(p, IPPROTO_IPIP);
        DecodeIPv4inIPv6(tv, dtv, p, pkt + IPV6_HEADER_LEN, IPV6_GET_PLEN(p), pq);
        return TM_ECODE_OK;
    case IPPROTO_IPV6:
        DecodeIP6inIP6(tv, dtv, p, pkt + IPV6_HEADER_LEN, IPV6_GET_PLEN(p), pq);
        return TM_ECODE_OK;
    case IPPROTO_FRAGMENT:
    case IPPROTO_HOPOPTS:
    case IPPROTO_ROUTING:
    case IPPROTO_NONE:
    case IPPROTO_DSTOPTS:
    case IPPROTO_AH:
    case IPPROTO_ESP:
    case IPPROTO_MH:
    case IPPROTO_HIP:
    case IPPROTO_SHIM6:
        DecodeIPV6ExtHdrs(tv, dtv, p, pkt + IPV6_HEADER_LEN, IPV6_GET_PLEN(p), pq);
        break;
    case IPPROTO_ICMP:
        ENGINE_SET_EVENT(p,IPV6_WITH_ICMPV4);
        break;
    default:
        ENGINE_SET_EVENT(p, IPV6_UNKNOWN_NEXT_HEADER);
        IPV6_SET_L4PROTO (p, IPV6_GET_NH(p));
        break;
    }
    p->proto = IPV6_GET_L4PROTO (p);

    /* Pass to defragger if a fragment. */
    if (IPV6_EXTHDR_ISSET_FH(p)) {
        Packet *rp = Defrag(tv, dtv, p, pq);
        if (rp != NULL) {
            PacketEnqueue(pq,rp);
        }
    }

#ifdef DEBUG
    if (IPV6_EXTHDR_ISSET_FH(p)) {
        SCLogDebug("IPV6 FRAG - HDRLEN: %" PRIuMAX " NH: %" PRIu32 " OFFSET: %" PRIu32 " ID: %" PRIu32 "",
                   (uintmax_t)IPV6_EXTHDR_GET_FH_HDRLEN(p), IPV6_EXTHDR_GET_FH_NH(p),
                   IPV6_EXTHDR_GET_FH_OFFSET(p), IPV6_EXTHDR_GET_FH_ID(p));
    }
    if (IPV6_EXTHDR_ISSET_RH(p)) {
        SCLogDebug("IPV6 ROUTE - HDRLEN: %" PRIu32 " NH: %" PRIu32 " TYPE: %" PRIu32 "",
                   IPV6_EXTHDR_GET_RH_HDRLEN(p), IPV6_EXTHDR_GET_RH_NH(p),
                   IPV6_EXTHDR_GET_RH_TYPE(p));
    }
    if (IPV6_EXTHDR_ISSET_HH(p)) {
        SCLogDebug("IPV6 HOPOPT - HDRLEN: %" PRIu32 " NH: %" PRIu32 "",
                   IPV6_EXTHDR_GET_HH_HDRLEN(p), IPV6_EXTHDR_GET_HH_NH(p));
    }
    if (IPV6_EXTHDR_ISSET_DH1(p)) {
        SCLogDebug("IPV6 DSTOPT1 - HDRLEN: %" PRIu32 " NH: %" PRIu32 "",
                   IPV6_EXTHDR_GET_DH1_HDRLEN(p), IPV6_EXTHDR_GET_DH1_NH(p));
    }
    if (IPV6_EXTHDR_ISSET_DH2(p)) {
        SCLogDebug("IPV6 DSTOPT2 - HDRLEN: %" PRIu32 " NH: %" PRIu32 "",
                   IPV6_EXTHDR_GET_DH2_HDRLEN(p), IPV6_EXTHDR_GET_DH2_NH(p));
    }
#endif
    return TM_ECODE_OK;
}