/** * \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; }
/** * \brief This function is used to match TTL rule option on a packet with those passed via ttl: * * \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 DetectTtlData * * \retval 0 no match * \retval 1 match */ int DetectTtlMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signature *s, SigMatch *m) { int ret = 0; uint8_t pttl; DetectTtlData *ttld = (DetectTtlData *) m->ctx; if (PKT_IS_PSEUDOPKT(p)) return 0; if (PKT_IS_IPV4(p)) { pttl = IPV4_GET_IPTTL(p); } else if (PKT_IS_IPV6(p)) { pttl = IPV6_GET_HLIM(p); } else { SCLogDebug("Packet is of not IPv4 or IPv6"); return ret; } if (ttld->mode == DETECT_TTL_EQ && pttl == ttld->ttl1) ret = 1; else if (ttld->mode == DETECT_TTL_LT && pttl < ttld->ttl1) ret = 1; else if (ttld->mode == DETECT_TTL_GT && pttl > ttld->ttl1) ret = 1; else if (ttld->mode == DETECT_TTL_RA && (pttl > ttld->ttl1 && pttl < ttld->ttl2)) ret = 1; return ret; }
/** * \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; }
/** * \brief Checks if the packet sent as the argument, has a valid or invalid * udpv6 checksum, based on whether udpv6-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 DetectUDPV6CsumMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, const Signature *s, const SigMatchCtx *ctx) { const DetectCsumData *cd = (const DetectCsumData *)ctx; if (p->ip6h == NULL || p->udph == NULL || p->proto != IPPROTO_UDP || PKT_IS_PSEUDOPKT(p)) return 0; if (p->flags & PKT_IGNORE_CHECKSUM) { return cd->valid; } if (p->level4_comp_csum == -1) p->level4_comp_csum = UDPV6Checksum(p->ip6h->s_ip6_addrs, (uint16_t *)p->udph, (p->payload_len + UDP_HEADER_LEN), p->udph->uh_sum); if (p->level4_comp_csum == 0 && cd->valid == 1) return 1; else if (p->level4_comp_csum != 0 && cd->valid == 0) return 1; else return 0; }
/** * \brief Checks if the packet sent as the argument, has a valid or invalid * tcpv4 checksum, based on whether tcpv4-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 DetectTCPV4CsumMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, const Signature *s, const SigMatchCtx *ctx) { const DetectCsumData *cd = (const DetectCsumData *)ctx; if (p->ip4h == NULL || p->tcph == NULL || p->proto != IPPROTO_TCP || PKT_IS_PSEUDOPKT(p)) return 0; if (p->flags & PKT_IGNORE_CHECKSUM) { return cd->valid; } if (p->level4_comp_csum == -1) p->level4_comp_csum = TCPChecksum(p->ip4h->s_ip_addrs, (uint16_t *)p->tcph, (p->payload_len + TCP_GET_HLEN(p)), p->tcph->th_sum); if (p->level4_comp_csum == 0 && cd->valid == 1) return 1; else if (p->level4_comp_csum != 0 && cd->valid == 0) return 1; else return 0; }
/** * \brief This function is used to match TEMPLATE rule option 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 with context that we will cast into DetectTemplateData * * \retval 0 no match * \retval 1 match */ static int DetectTemplateMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signature *s, const SigMatchCtx *ctx) { int ret = 0; const DetectTemplateData *templated = (const DetectTemplateData *) ctx; #if 0 if (PKT_IS_PSEUDOPKT(p)) { /* fake pkt */ } if (PKT_IS_IPV4(p)) { /* ipv4 pkt */ } else if (PKT_IS_IPV6(p)) { /* ipv6 pkt */ } else { SCLogDebug("packet is of not IPv4 or IPv6"); return ret; } #endif /* packet payload access */ if (p->payload != NULL && p->payload_len > 0) { if (templated->arg1 == p->payload[0] && templated->arg2 == p->payload[p->payload_len - 1]) { ret = 1; } } return ret; }
static void PrefilterPacketTtlMatch(DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx) { if (PKT_IS_PSEUDOPKT(p)) { SCReturn; } uint8_t pttl; if (PKT_IS_IPV4(p)) { pttl = IPV4_GET_IPTTL(p); } else if (PKT_IS_IPV6(p)) { pttl = IPV6_GET_HLIM(p); } else { SCLogDebug("Packet is of not IPv4 or IPv6"); return; } const PrefilterPacketHeaderCtx *ctx = pectx; if (PrefilterPacketHeaderExtraMatch(ctx, p) == FALSE) return; if (TtlMatch(pttl, ctx->v1.u8[0], ctx->v1.u8[1], ctx->v1.u8[2])) { SCLogDebug("packet matches ttl/hl %u", pttl); PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt); } }
/** * \brief This function is used to match icode rule option set on a packet with those passed via icode: * * \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 DetectICodeData * * \retval 0 no match * \retval 1 match */ int DetectICodeMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signature *s, SigMatch *m) { int ret = 0; uint8_t picode; DetectICodeData *icd = (DetectICodeData *)m->ctx; if (PKT_IS_PSEUDOPKT(p)) return 0; if (PKT_IS_ICMPV4(p)) { picode = ICMPV4_GET_CODE(p); } else if (PKT_IS_ICMPV6(p)) { picode = ICMPV6_GET_CODE(p); } else { /* Packet not ICMPv4 nor ICMPv6 */ return ret; } switch(icd->mode) { case DETECT_ICODE_EQ: ret = (picode == icd->code1) ? 1 : 0; break; case DETECT_ICODE_LT: ret = (picode < icd->code1) ? 1 : 0; break; case DETECT_ICODE_GT: ret = (picode > icd->code1) ? 1 : 0; break; case DETECT_ICODE_RN: ret = (picode >= icd->code1 && picode <= icd->code2) ? 1 : 0; break; } return ret; }
/** * \brief Check if we need to drop-log this packet * * \param tv Pointer the current thread variables * \param p Pointer the packet which is tested * * \retval bool TRUE or FALSE */ static int LogDropCondition(ThreadVars *tv, const Packet *p) { if (!EngineModeIsIPS()) { SCLogDebug("engine is not running in inline mode, so returning"); return FALSE; } if (PKT_IS_PSEUDOPKT(p)) { SCLogDebug("drop log doesn't log pseudo packets"); return FALSE; } if (p->flow != NULL) { int ret = FALSE; FLOWLOCK_RDLOCK(p->flow); if (p->flow->flags & FLOW_ACTION_DROP) { if (PKT_IS_TOSERVER(p) && !(p->flow->flags & FLOW_TOSERVER_DROP_LOGGED)) ret = TRUE; else if (PKT_IS_TOCLIENT(p) && !(p->flow->flags & FLOW_TOCLIENT_DROP_LOGGED)) ret = TRUE; } FLOWLOCK_UNLOCK(p->flow); return ret; } else if (PACKET_TEST_ACTION(p, ACTION_DROP)) { return TRUE; } return FALSE; }
/** * \brief Decode a packet coming from NFQ */ TmEcode DecodeNFQ(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq) { IPV4Hdr *ip4h = (IPV4Hdr *)GET_PKT_DATA(p); IPV6Hdr *ip6h = (IPV6Hdr *)GET_PKT_DATA(p); DecodeThreadVars *dtv = (DecodeThreadVars *)data; /* XXX HACK: flow timeout can call us for injected pseudo packets * see bug: https://redmine.openinfosecfoundation.org/issues/1107 */ if (PKT_IS_PSEUDOPKT(p)) return TM_ECODE_OK; DecodeUpdatePacketCounters(tv, dtv, p); if (IPV4_GET_RAW_VER(ip4h) == 4) { SCLogDebug("IPv4 packet"); DecodeIPV4(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq); } else if(IPV6_GET_RAW_VER(ip6h) == 6) { SCLogDebug("IPv6 packet"); DecodeIPV6(tv, dtv, p, GET_PKT_DATA(p), GET_PKT_LEN(p), pq); } else { SCLogDebug("packet unsupported by NFQ, first byte: %02x", *GET_PKT_DATA(p)); } PacketDecodeFinalize(tv, dtv, p); return TM_ECODE_OK; }
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); } }
/** * \brief Check if we need to drop-log this packet * * \param tv Pointer the current thread variables * \param p Pointer the packet which is tested * * \retval bool TRUE or FALSE */ static int JsonDropLogCondition(ThreadVars *tv, const Packet *p) { if (!EngineModeIsIPS()) { SCLogDebug("engine is not running in inline mode, so returning"); return FALSE; } if (PKT_IS_PSEUDOPKT(p)) { SCLogDebug("drop log doesn't log pseudo packets"); return FALSE; } if (g_droplog_flows_start && p->flow != NULL) { int ret = FALSE; /* for a flow that will be dropped fully, log just once per direction */ if (p->flow->flags & FLOW_ACTION_DROP) { if (PKT_IS_TOSERVER(p) && !(p->flow->flags & FLOW_TOSERVER_DROP_LOGGED)) ret = TRUE; else if (PKT_IS_TOCLIENT(p) && !(p->flow->flags & FLOW_TOCLIENT_DROP_LOGGED)) ret = TRUE; } /* if drop is caused by signature, log anyway */ if (p->alerts.drop.action != 0) ret = TRUE; return ret; } else if (PACKET_TEST_ACTION(p, ACTION_DROP)) { return TRUE; } return FALSE; }
/** * \internal * \brief This function is used to match packets with a given Ack number * * \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 DetectAckData * * \retval 0 no match * \retval 1 match */ static int DetectAckMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signature *s, const SigMatchCtx *ctx) { const DetectAckData *data = (const DetectAckData *)ctx; /* This is only needed on TCP packets */ if (!(PKT_IS_TCP(p)) || PKT_IS_PSEUDOPKT(p)) { return 0; } return (data->ack == TCP_GET_ACK(p)) ? 1 : 0; }
/** * \internal * \brief This function is used to match packets with a given Seq number * * \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 DetectSeqData * * \retval 0 no match * \retval 1 match */ static int DetectSeqMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signature *s, SigMatch *m) { DetectSeqData *data = (DetectSeqData *)m->ctx; /* This is only needed on TCP packets */ if (!(PKT_IS_TCP(p)) || PKT_IS_PSEUDOPKT(p)) { return 0; } return (data->seq == TCP_GET_SEQ(p)) ? 1 : 0; }
/** * \brief This function is used to match icmp_id 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 DetectIcmpIdData * * \retval 0 no match * \retval 1 match */ int DetectIcmpIdMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signature *s, SigMatch *m) { uint16_t pid; DetectIcmpIdData *iid = (DetectIcmpIdData *)m->ctx; if (PKT_IS_PSEUDOPKT(p)) return 0; if (PKT_IS_ICMPV4(p)) { switch (ICMPV4_GET_TYPE(p)){ case ICMP_ECHOREPLY: case ICMP_ECHO: case ICMP_TIMESTAMP: case ICMP_TIMESTAMPREPLY: case ICMP_INFO_REQUEST: case ICMP_INFO_REPLY: case ICMP_ADDRESS: case ICMP_ADDRESSREPLY: SCLogDebug("ICMPV4_GET_ID(p) %"PRIu16" (network byte order), " "%"PRIu16" (host byte order)", ICMPV4_GET_ID(p), ntohs(ICMPV4_GET_ID(p))); pid = ICMPV4_GET_ID(p); break; default: SCLogDebug("Packet has no id field"); return 0; } } else if (PKT_IS_ICMPV6(p)) { switch (ICMPV6_GET_TYPE(p)) { case ICMP6_ECHO_REQUEST: case ICMP6_ECHO_REPLY: SCLogDebug("ICMPV6_GET_ID(p) %"PRIu16" (network byte order), " "%"PRIu16" (host byte order)", ICMPV6_GET_ID(p), ntohs(ICMPV6_GET_ID(p))); pid = ICMPV6_GET_ID(p); break; default: SCLogDebug("Packet has no id field"); return 0; } } else { SCLogDebug("Packet not ICMPV4 nor ICMPV6"); return 0; } if (pid == iid->id) return 1; return 0; }
/** * \internal * \brief This function is used to match flags on a packet with those passed via flags: * * \param t pointer to thread vars * \param det_ctx pointer to the pattern matcher thread * \param p pointer to the current packet * \param s pointer to the Signature * \param m pointer to the sigmatch * * \retval 0 no match * \retval 1 match */ static int DetectFlagsMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, const Signature *s, const SigMatchCtx *ctx) { SCEnter(); if (!(PKT_IS_TCP(p)) || PKT_IS_PSEUDOPKT(p)) { SCReturnInt(0); } const DetectFlagsData *de = (const DetectFlagsData *)ctx; const uint8_t flags = p->tcph->th_flags; return FlagsMatch(flags, de->modifier, de->flags, de->ignored_flags); }
static void PrefilterPacketAckMatch(DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx) { const PrefilterPacketHeaderCtx *ctx = pectx; if (PrefilterPacketHeaderExtraMatch(ctx, p) == FALSE) return; if ((p->proto) == IPPROTO_TCP && !(PKT_IS_PSEUDOPKT(p)) && (p->tcph != NULL) && (TCP_GET_ACK(p) == ctx->v1.u32[0])) { SCLogDebug("packet matches TCP ack %u", ctx->v1.u32[0]); PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt); } }
static inline _Bool GetIcmpId(Packet *p, uint16_t *id) { if (PKT_IS_PSEUDOPKT(p)) return FALSE; uint16_t pid; if (PKT_IS_ICMPV4(p)) { switch (ICMPV4_GET_TYPE(p)){ case ICMP_ECHOREPLY: case ICMP_ECHO: case ICMP_TIMESTAMP: case ICMP_TIMESTAMPREPLY: case ICMP_INFO_REQUEST: case ICMP_INFO_REPLY: case ICMP_ADDRESS: case ICMP_ADDRESSREPLY: SCLogDebug("ICMPV4_GET_ID(p) %"PRIu16" (network byte order), " "%"PRIu16" (host byte order)", ICMPV4_GET_ID(p), ntohs(ICMPV4_GET_ID(p))); pid = ICMPV4_GET_ID(p); break; default: SCLogDebug("Packet has no id field"); return FALSE; } } else if (PKT_IS_ICMPV6(p)) { switch (ICMPV6_GET_TYPE(p)) { case ICMP6_ECHO_REQUEST: case ICMP6_ECHO_REPLY: SCLogDebug("ICMPV6_GET_ID(p) %"PRIu16" (network byte order), " "%"PRIu16" (host byte order)", ICMPV6_GET_ID(p), ntohs(ICMPV6_GET_ID(p))); pid = ICMPV6_GET_ID(p); break; default: SCLogDebug("Packet has no id field"); return FALSE; } } else { SCLogDebug("Packet not ICMPV4 nor ICMPV6"); return FALSE; } *id = pid; return TRUE; }
/** * \internal * \brief This function is used to match flags on a packet with those passed via dsize: * * \param t pointer to thread vars * \param det_ctx pointer to the pattern matcher thread * \param p pointer to the current packet * \param s pointer to the Signature * \param m pointer to the sigmatch * * \retval 0 no match * \retval 1 match */ int DetectDsizeMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signature *s, const SigMatchCtx *ctx) { SCEnter(); int ret = 0; if (PKT_IS_PSEUDOPKT(p)) { SCReturnInt(0); } const DetectDsizeData *dd = (const DetectDsizeData *)ctx; SCLogDebug("p->payload_len %"PRIu16"", p->payload_len); ret = DsizeMatch(p->payload_len, dd->mode, dd->dsize, dd->dsize2); SCReturnInt(ret); }
/** * \brief Match function for tos keyword. * * \param tv ThreadVars instance. * \param det_ctx Pointer to the detection thread ctx. * \param p Pointer to the packet. * \param m Pointer to the SigMatch containing the tos data. * * \retval 0 no match * \retval 1 match */ static int DetectTosMatch(ThreadVars *tv, DetectEngineThreadCtx *det_ctx, Packet *p, const Signature *s, const SigMatchCtx *ctx) { const DetectTosData *tosd = (const DetectTosData *)ctx; int result = 0; if (!PKT_IS_IPV4(p) || PKT_IS_PSEUDOPKT(p)) { return 0; } if (tosd->tos == IPV4_GET_IPTOS(p)) { SCLogDebug("tos match found for %d\n", tosd->tos); result = 1; } return (tosd->negated ^ result); }
int DetectPayloadLenFieldMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signature *s, SigMatch *m) { DetectPayloadLenFieldData *ed = m->ctx; if (p->ip4h == NULL || PKT_IS_PSEUDOPKT(p) || p->payload_len == 0 || p->payload_len < ed->len + ed->offset) return 0; uint32_t read_len = 0; // This works just for little endian systems and streams memcpy(((char*)&read_len), p->payload + ed->offset, ed->len); //printf("Found len: %d\n", read_len); return read_len == p->payload_len; }
static void PrefilterPacketDsizeMatch(DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx) { if (PKT_IS_PSEUDOPKT(p)) { SCReturn; } const PrefilterPacketHeaderCtx *ctx = pectx; if (PrefilterPacketHeaderExtraMatch(ctx, p) == FALSE) return; const uint16_t dsize = p->payload_len; if (DsizeMatch(dsize, ctx->v1.u8[0], ctx->v1.u16[1], ctx->v1.u16[2])) { SCLogDebug("packet matches dsize %u", dsize); PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt); } }
static void PrefilterPacketFlagsMatch(DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx) { if (!(PKT_IS_TCP(p)) || PKT_IS_PSEUDOPKT(p)) { SCReturn; } const PrefilterPacketHeaderCtx *ctx = pectx; if (PrefilterPacketHeaderExtraMatch(ctx, p) == FALSE) return; const uint8_t flags = p->tcph->th_flags; if (FlagsMatch(flags, ctx->v1.u8[0], ctx->v1.u8[1], ctx->v1.u8[2])) { SCLogDebug("packet matches TCP flags %02x", ctx->v1.u8[1]); PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt); } }
/** * \brief This function is used to match TTL rule option on a packet with those passed via ttl: * * \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 DetectTtlData * * \retval 0 no match * \retval 1 match */ int DetectTtlMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signature *s, const SigMatchCtx *ctx) { if (PKT_IS_PSEUDOPKT(p)) return 0; uint8_t pttl; if (PKT_IS_IPV4(p)) { pttl = IPV4_GET_IPTTL(p); } else if (PKT_IS_IPV6(p)) { pttl = IPV6_GET_HLIM(p); } else { SCLogDebug("Packet is of not IPv4 or IPv6"); return 0; } const DetectTtlData *ttld = (const DetectTtlData *)ctx; return TtlMatch(pttl, ttld->mode, ttld->ttl1, ttld->ttl2); }
/** * \brief This function is used to match the specified id 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 DetectIdData * * \retval 0 no match * \retval 1 match */ int DetectIdMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signature *s, SigMatch *m) { DetectIdData *id_d = (DetectIdData *)m->ctx; /** * To match a ipv4 packet with a "id" rule */ if (!PKT_IS_IPV4(p) || PKT_IS_PSEUDOPKT(p)) { return 0; } if (id_d->id == IPV4_GET_IPID(p)) { SCLogDebug("IPV4 Proto and matched with ip_id: %u.\n", id_d->id); return 1; } return 0; }
/** * \internal * \brief This function is used to match packets with a IPs in an specified country * * \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 DetectGeoipData * * \retval 0 no match * \retval 1 match */ static int DetectGeoipMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signature *s, SigMatch *m) { DetectGeoipData *geoipdata = (DetectGeoipData *)m->ctx; int matches = 0; if (PKT_IS_PSEUDOPKT(p)) return 0; if (PKT_IS_IPV4(p)) { if (geoipdata->flags & ( GEOIP_MATCH_SRC_FLAG | GEOIP_MATCH_BOTH_FLAG )) { if (CheckGeoMatchIPv4(geoipdata, GET_IPV4_SRC_ADDR_U32(p))) { if (geoipdata->flags & GEOIP_MATCH_BOTH_FLAG) matches++; else return 1; } } if (geoipdata->flags & ( GEOIP_MATCH_DST_FLAG | GEOIP_MATCH_BOTH_FLAG )) { if (CheckGeoMatchIPv4(geoipdata, GET_IPV4_DST_ADDR_U32(p))) { if (geoipdata->flags & GEOIP_MATCH_BOTH_FLAG) matches++; else return 1; } } /* if matches == 2 is because match-on is "both" */ if (matches == 2) return 1; } return 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);; }
/** * \internal * \brief This function is used to match fragbits on a packet with those passed via fragbits: * * \param t pointer to thread vars * \param det_ctx pointer to the pattern matcher thread * \param p pointer to the current packet * \param s pointer to the Signature * \param m pointer to the sigmatch * * \retval 0 no match * \retval 1 match */ static int DetectFragBitsMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signature *s, SigMatch *m) { int ret = 0; uint16_t fragbits = 0; DetectFragBitsData *de = (DetectFragBitsData *)m->ctx; if (!de || !PKT_IS_IPV4(p) || !p || PKT_IS_PSEUDOPKT(p)) return ret; if(IPV4_GET_MF(p)) fragbits |= FRAGBITS_HAVE_MF; if(IPV4_GET_DF(p)) fragbits |= FRAGBITS_HAVE_DF; if(IPV4_GET_RF(p)) fragbits |= FRAGBITS_HAVE_RF; switch(de->modifier) { case MODIFIER_ANY: if((fragbits & de->fragbits) > 0) return 1; return ret; case MODIFIER_PLUS: if(((fragbits & de->fragbits) == de->fragbits) && (((fragbits - de->fragbits) > 0))) return 1; return ret; case MODIFIER_NOT: if((fragbits & de->fragbits) != de->fragbits) return 1; return ret; default: if(fragbits == de->fragbits) return 1; } return ret; }
/** * \brief Checks if the packet sent as the argument, has a valid or invalid * icmpv4 checksum, based on whether icmpv4-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 DetectICMPV4CsumMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, const Signature *s, const SigMatchCtx *ctx) { const DetectCsumData *cd = (const DetectCsumData *)ctx; if (p->ip4h == NULL || p->icmpv4h == NULL || p->proto != IPPROTO_ICMP || PKT_IS_PSEUDOPKT(p)) return 0; if (p->flags & PKT_IGNORE_CHECKSUM) { return cd->valid; } if (p->level4_comp_csum == -1) p->level4_comp_csum = ICMPV4CalculateChecksum((uint16_t *)p->icmpv4h, ntohs(IPV4_GET_RAW_IPLEN(p->ip4h)) - IPV4_GET_RAW_HLEN(p->ip4h) * 4); if (p->level4_comp_csum == p->icmpv4h->checksum && cd->valid == 1) return 1; else if (p->level4_comp_csum != p->icmpv4h->checksum && cd->valid == 0) return 1; else return 0; }
/** * \internal * \brief This function is used to match flags on a packet with those passed via dsize: * * \param t pointer to thread vars * \param det_ctx pointer to the pattern matcher thread * \param p pointer to the current packet * \param s pointer to the Signature * \param m pointer to the sigmatch * * \retval 0 no match * \retval 1 match */ int DetectDsizeMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signature *s, SigMatch *m) { SCEnter(); int ret = 0; if (PKT_IS_PSEUDOPKT(p)) { SCReturnInt(0); } DetectDsizeData *dd = (DetectDsizeData *)m->ctx; SCLogDebug("p->payload_len %"PRIu16"", p->payload_len); if (dd->mode == DETECTDSIZE_EQ && dd->dsize == p->payload_len) ret = 1; else if (dd->mode == DETECTDSIZE_LT && p->payload_len < dd->dsize) ret = 1; else if (dd->mode == DETECTDSIZE_GT && p->payload_len > dd->dsize) ret = 1; else if (dd->mode == DETECTDSIZE_RA && p->payload_len > dd->dsize && p->payload_len < dd->dsize2) ret = 1; SCReturnInt(ret); }