示例#1
0
/**
 * \brief Checks if the packet sent as the argument, has a valid or invalid
 *        icmpv6 checksum, based on whether icmpv6-csum option for this rule
 *        has been supplied with "valid" or "invalid" argument
 *
 * \param t       Pointer to the tv for this detection module instance
 * \param det_ctx Pointer to the detection engine thread context
 * \param p       Pointer to the Packet currently being matched
 * \param s       Pointer to the Signature, the packet is being currently
 *                matched with
 * \param m       Pointer to the keyword_structure(SigMatch) from the above
 *                Signature, the Packet is being currently matched with
 *
 * \retval 1 if the Packet contents match the keyword option; 0 otherwise
 */
static int DetectICMPV6CsumMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx,
        Packet *p, const Signature *s, const SigMatchCtx *ctx)
{
    const DetectCsumData *cd = (const DetectCsumData *)ctx;

    if (p->ip6h == NULL || p->icmpv6h == NULL || p->proto != IPPROTO_ICMPV6 || PKT_IS_PSEUDOPKT(p) ||
        (GET_PKT_LEN(p) - ((uint8_t *)p->icmpv6h - GET_PKT_DATA(p))) <= 0) {
        return 0;
    }

    if (p->flags & PKT_IGNORE_CHECKSUM) {
        return cd->valid;
    }

    if (p->level4_comp_csum == -1) {
        uint16_t len = IPV6_GET_RAW_PLEN(p->ip6h) -
            ((uint8_t *)p->icmpv6h - (uint8_t *)p->ip6h - IPV6_HEADER_LEN);
        p->level4_comp_csum = ICMPV6CalculateChecksum(p->ip6h->s_ip6_addrs,
                                                      (uint16_t *)p->icmpv6h,
                                                      len);
    }

    if (p->level4_comp_csum == p->icmpv6h->csum && cd->valid == 1)
        return 1;
    else if (p->level4_comp_csum != p->icmpv6h->csum && cd->valid == 0)
        return 1;
    else
        return 0;
}
示例#2
0
/**
 * \brief Get variables and do some checks of the embedded IPV6 packet
 *
 * \param p Pointer to the packet we are filling
 * \param partial_packet  Pointer to the raw packet buffer
 * \param len the len of the rest of the packet not processed yet
 *
 * \retval void No return value
 */
void DecodePartialIPV6(Packet *p, uint8_t *partial_packet, uint16_t len )
{
    /** Check the sizes, the header must fit at least */
    if (len < IPV6_HEADER_LEN) {
        SCLogDebug("ICMPV6_IPV6_TRUNC_PKT");
        ENGINE_SET_EVENT(p, ICMPV6_IPV6_TRUNC_PKT);
        return;
    }

    IPV6Hdr *icmp6_ip6h = (IPV6Hdr*)partial_packet;

    /** Check the embedded version */
    if(((icmp6_ip6h->s_ip6_vfc & 0xf0) >> 4) != 6)
    {
        SCLogDebug("ICMPv6 contains Unknown IPV6 version "
                "ICMPV6_IPV6_UNKNOWN_VER");
        ENGINE_SET_EVENT(p, ICMPV6_IPV6_UNKNOWN_VER);
        return;
    }

    /** We need to fill icmpv6vars */
    p->icmpv6vars.emb_ipv6h = icmp6_ip6h;

    /** Get the IP6 address */
    p->icmpv6vars.emb_ip6_src[0] = icmp6_ip6h->s_ip6_src[0];
    p->icmpv6vars.emb_ip6_src[1] = icmp6_ip6h->s_ip6_src[1];
    p->icmpv6vars.emb_ip6_src[2] = icmp6_ip6h->s_ip6_src[2];
    p->icmpv6vars.emb_ip6_src[3] = icmp6_ip6h->s_ip6_src[3];

    p->icmpv6vars.emb_ip6_dst[0] = icmp6_ip6h->s_ip6_dst[0];
    p->icmpv6vars.emb_ip6_dst[1] = icmp6_ip6h->s_ip6_dst[1];
    p->icmpv6vars.emb_ip6_dst[2] = icmp6_ip6h->s_ip6_dst[2];
    p->icmpv6vars.emb_ip6_dst[3] = icmp6_ip6h->s_ip6_dst[3];

    /** Get protocol and ports inside the embedded ipv6 packet and set the pointers */
    p->icmpv6vars.emb_ip6_proto_next = icmp6_ip6h->s_ip6_nxt;

    switch (icmp6_ip6h->s_ip6_nxt) {
        case IPPROTO_TCP:
            if (len >= IPV6_HEADER_LEN + TCP_HEADER_LEN ) {
                p->icmpv6vars.emb_tcph = (TCPHdr*)(partial_packet + IPV6_HEADER_LEN);
                p->icmpv6vars.emb_sport = p->icmpv6vars.emb_tcph->th_sport;
                p->icmpv6vars.emb_dport = p->icmpv6vars.emb_tcph->th_dport;

                SCLogDebug("ICMPV6->IPV6->TCP header sport: "
                           "%"PRIu8" dport %"PRIu8"", p->icmpv6vars.emb_sport,
                            p->icmpv6vars.emb_dport);
            } else {
                SCLogDebug("Warning, ICMPV6->IPV6->TCP "
                           "header Didn't fit in the packet!");
                p->icmpv6vars.emb_sport = 0;
                p->icmpv6vars.emb_dport = 0;
            }

            break;
        case IPPROTO_UDP:
            if (len >= IPV6_HEADER_LEN + UDP_HEADER_LEN ) {
                p->icmpv6vars.emb_udph = (UDPHdr*)(partial_packet + IPV6_HEADER_LEN);
                p->icmpv6vars.emb_sport = p->icmpv6vars.emb_udph->uh_sport;
                p->icmpv6vars.emb_dport = p->icmpv6vars.emb_udph->uh_dport;

                SCLogDebug("ICMPV6->IPV6->UDP header sport: "
                           "%"PRIu8" dport %"PRIu8"", p->icmpv6vars.emb_sport,
                            p->icmpv6vars.emb_dport);
            } else {
                SCLogDebug("Warning, ICMPV6->IPV6->UDP "
                           "header Didn't fit in the packet!");
                p->icmpv6vars.emb_sport = 0;
                p->icmpv6vars.emb_dport = 0;
            }

            break;
        case IPPROTO_ICMPV6:
            p->icmpv6vars.emb_icmpv6h = (ICMPV6Hdr*)(partial_packet + IPV6_HEADER_LEN);
            p->icmpv6vars.emb_sport = 0;
            p->icmpv6vars.emb_dport = 0;

            SCLogDebug("ICMPV6->IPV6->ICMP header");

            break;
    }

    /* debug print */
#ifdef DEBUG
    char s[46], d[46];
    PrintInet(AF_INET6, (const void *)p->icmpv6vars.emb_ip6_src, s, sizeof(s));
    PrintInet(AF_INET6, (const void *)p->icmpv6vars.emb_ip6_dst, d, sizeof(d));
    SCLogDebug("ICMPv6 embedding IPV6 %s->%s - CLASS: %" PRIu32 " FLOW: "
               "%" PRIu32 " NH: %" PRIu32 " PLEN: %" PRIu32 " HLIM: %" PRIu32,
               s, d, IPV6_GET_RAW_CLASS(icmp6_ip6h), IPV6_GET_RAW_FLOW(icmp6_ip6h),
               IPV6_GET_RAW_NH(icmp6_ip6h), IPV6_GET_RAW_PLEN(icmp6_ip6h), IPV6_GET_RAW_HLIM(icmp6_ip6h));
#endif

    return;
}
示例#3
0
/**
 * \brief Function to decode Teredo packets
 *
 * \retval 0 if packet is not a Teredo packet, 1 if it is
 */
int DecodeTeredo(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint16_t len, PacketQueue *pq)
{

    uint8_t *start = pkt;

    /* Is this packet to short to contain an IPv6 packet ? */
    if (len < IPV6_HEADER_LEN)
        return 0;

    /* Teredo encapsulate IPv6 in UDP and can add some custom message
     * part before the IPv6 packet. In our case, we just want to get
     * over an ORIGIN indication. So we just make one offset if needed. */
    if (start[0] == 0x0) {
        switch (start[1]) {
            /* origin indication: compatible with tunnel */
            case 0x0:
                /* offset is coherent with len and presence of an IPv6 header */
                if (len >= TEREDO_ORIG_INDICATION_LENGTH + IPV6_HEADER_LEN)
                    start += TEREDO_ORIG_INDICATION_LENGTH;
                else
                    return 0;
                break;
            /* authentication: negotiation not real tunnel */
            case 0x1:
                return 0;
            /* this case is not possible in Teredo: not that protocol */
            default:
                return 0;
        }
    }

    /* There is no specific field that we can check to prove that the packet
     * is a Teredo packet. We've zapped here all the possible Teredo header
     * and we should have an IPv6 packet at the start pointer.
     * We then can only do two checks before sending the encapsulated packets
     * to decoding:
     *  - The packet has a protocol version which is IPv6.
     *  - The IPv6 length of the packet matches what remains in buffer.
     */
    if (IP_GET_RAW_VER(start) == 6) {
        IPV6Hdr *thdr = (IPV6Hdr *)start;
        if (len ==  IPV6_HEADER_LEN +
                IPV6_GET_RAW_PLEN(thdr) + (start - pkt)) {
            if (pq != NULL) {
                int blen = len - (start - pkt);
                /* spawn off tunnel packet */
                Packet *tp = PacketPseudoPktSetup(p, start, blen,
                                                  IPPROTO_IPV6);
                if (tp != NULL) {
                    PKT_SET_SRC(tp, PKT_SRC_DECODER_TEREDO);
                    /* send that to the Tunnel decoder */
                    DecodeTunnel(tv, dtv, tp, GET_PKT_DATA(tp), GET_PKT_LEN(tp),
                                 pq, IPPROTO_IPV6);
                    /* add the tp to the packet queue. */
                    PacketEnqueue(pq,tp);
                    SCPerfCounterIncr(dtv->counter_teredo, tv->sc_perf_pca);
                    return 1;
                }
            }
        }
        return 0;
    }

    return 0;
}