Add icmp flow handling.

remotes/origin/master-1.0.x
Victor Julien 15 years ago
parent 71ed2d38f5
commit 10cc9d5b6a

@ -7,6 +7,8 @@
#include "decode-ipv4.h"
#include "decode-icmpv4.h"
#include "flow.h"
#include "util-unittest.h"
#include "util-debug.h"
@ -169,11 +171,13 @@ void DecodeICMPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt
SCLogDebug("ICMPV4 TYPE %" PRIu32 " CODE %" PRIu32 "", p->icmpv4h->type, p->icmpv4h->code);
p->proto = IPPROTO_ICMP;
p->type = p->icmpv4h->type;
p->code = p->icmpv4h->code;
ICMPV4ExtHdr* icmp4eh = (ICMPV4ExtHdr*) p->icmpv4h;
switch (p->icmpv4h->type)
{
{
case ICMP_ECHOREPLY:
p->icmpv4vars.id=icmp4eh->id;
p->icmpv4vars.seq=icmp4eh->seq;
@ -291,7 +295,10 @@ void DecodeICMPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt
default:
DECODER_SET_EVENT(p,ICMPV4_UNKNOWN_TYPE);
}
}
/* Flow is an integral part of us */
FlowHandlePacket(tv, p);
return;
}
@ -314,20 +321,36 @@ static int DecodeICMPV4test01(void) {
Packet p;
ThreadVars tv;
DecodeThreadVars dtv;
int ret = 0;
IPV4Hdr ip4h;
memset(&ip4h, 0, sizeof(IPV4Hdr));
memset(&tv, 0, sizeof(ThreadVars));
memset(&p, 0, sizeof(Packet));
memset(&ip4h, 0, sizeof(IPV4Hdr));
memset(&dtv, 0, sizeof(DecodeThreadVars));
FlowInitConfig(FLOW_QUIET);
p.src.family = AF_INET;
p.dst.family = AF_INET;
p.src.addr_data32[0] = 0x01020304;
p.dst.addr_data32[0] = 0x04030201;
ip4h.ip_src.s_addr = p.src.addr_data32[0];
ip4h.ip_dst.s_addr = p.dst.addr_data32[0];
p.ip4h = &ip4h;
DecodeICMPV4(&tv, &dtv, &p, raw_icmpv4, sizeof(raw_icmpv4), NULL);
if (NULL!=p.icmpv4h) {
if (p.icmpv4h->type==8 && p.icmpv4h->code==0) {
return 1;
ret = 1;
}
}
return 0;
FlowShutdown();
return ret;
}
/** DecodeICMPV4test02
@ -346,21 +369,35 @@ static int DecodeICMPV4test02(void) {
Packet p;
ThreadVars tv;
DecodeThreadVars dtv;
int ret = 0;
IPV4Hdr ip4h;
memset(&ip4h, 0, sizeof(IPV4Hdr));
memset(&tv, 0, sizeof(ThreadVars));
memset(&p, 0, sizeof(Packet));
memset(&dtv, 0, sizeof(DecodeThreadVars));
FlowInitConfig(FLOW_QUIET);
p.src.family = AF_INET;
p.dst.family = AF_INET;
p.src.addr_data32[0] = 0x01020304;
p.dst.addr_data32[0] = 0x04030201;
ip4h.ip_src.s_addr = p.src.addr_data32[0];
ip4h.ip_dst.s_addr = p.dst.addr_data32[0];
p.ip4h = &ip4h;
DecodeICMPV4(&tv, &dtv, &p, raw_icmpv4, sizeof(raw_icmpv4), NULL);
if (NULL!=p.icmpv4h) {
if (p.icmpv4h->type==0 && p.icmpv4h->code==0) {
return 1;
ret = 1;
}
}
return 0;
FlowShutdown();
return ret;
}
/** DecodeICMPV4test03
@ -377,25 +414,39 @@ static int DecodeICMPV4test03(void) {
Packet p;
ThreadVars tv;
DecodeThreadVars dtv;
int ret = 0;
IPV4Hdr ip4h;
memset(&ip4h, 0, sizeof(IPV4Hdr));
memset(&tv, 0, sizeof(ThreadVars));
memset(&p, 0, sizeof(Packet));
memset(&dtv, 0, sizeof(DecodeThreadVars));
FlowInitConfig(FLOW_QUIET);
p.src.family = AF_INET;
p.dst.family = AF_INET;
p.src.addr_data32[0] = 0x01020304;
p.dst.addr_data32[0] = 0x04030201;
ip4h.ip_src.s_addr = p.src.addr_data32[0];
ip4h.ip_dst.s_addr = p.dst.addr_data32[0];
p.ip4h = &ip4h;
DecodeICMPV4(&tv, &dtv, &p, raw_icmpv4, sizeof(raw_icmpv4), NULL);
if (NULL==p.icmpv4h) {
return 0;
if (NULL == p.icmpv4h) {
goto end;
}
// check it's type 11 code 0
if (p.icmpv4h->type!=11 || p.icmpv4h->code!=0) {
return 0;
goto end;
}
// check it's source port 4747 to port 43650
if (p.icmpv4vars.emb_sport != 4747 || p.icmpv4vars.emb_dport != 43650) {
return 0;
goto end;
}
// check the src,dst IPs contained inside
@ -405,11 +456,13 @@ static int DecodeICMPV4test03(void) {
inet_ntop(AF_INET, &(p.icmpv4vars.emb_ip4_dst), d, sizeof(d));
// ICMPv4 embedding IPV4 192.168.1.13->209.85.227.147 pass
if (strcmp(s,"192.168.1.13")!=0 || strcmp(d,"209.85.227.147")!=0 ) {
return 0;
if (strcmp(s, "192.168.1.13") == 0 && strcmp(d, "209.85.227.147") == 0) {
ret = 1;
}
return 1;
end:
FlowShutdown();
return ret;
}
/** DecodeICMPV4test04
@ -428,25 +481,39 @@ static int DecodeICMPV4test04(void) {
Packet p;
ThreadVars tv;
DecodeThreadVars dtv;
int ret = 0;
IPV4Hdr ip4h;
memset(&ip4h, 0, sizeof(IPV4Hdr));
memset(&tv, 0, sizeof(ThreadVars));
memset(&p, 0, sizeof(Packet));
memset(&dtv, 0, sizeof(DecodeThreadVars));
FlowInitConfig(FLOW_QUIET);
p.src.family = AF_INET;
p.dst.family = AF_INET;
p.src.addr_data32[0] = 0x01020304;
p.dst.addr_data32[0] = 0x04030201;
ip4h.ip_src.s_addr = p.src.addr_data32[0];
ip4h.ip_dst.s_addr = p.dst.addr_data32[0];
p.ip4h = &ip4h;
DecodeICMPV4(&tv, &dtv, &p, raw_icmpv4, sizeof(raw_icmpv4), NULL);
if (NULL==p.icmpv4h) {
return 0;
if (NULL == p.icmpv4h) {
goto end;
}
// check the type,code pair is correct - type 3, code 10
if (p.icmpv4h->type!=3 || p.icmpv4h->code!=10) {
return 0;
if (p.icmpv4h->type != 3 || p.icmpv4h->code != 10) {
goto end;
}
// check it's src port 2737 to dst port 12800
if (p.icmpv4vars.emb_sport != 2737 || p.icmpv4vars.emb_dport != 12800) {
return 0;
goto end;
}
// check the src,dst IPs contained inside
@ -456,11 +523,13 @@ static int DecodeICMPV4test04(void) {
inet_ntop(AF_INET, &(p.icmpv4vars.emb_ip4_dst), d, sizeof(d));
// ICMPv4 embedding IPV4 192.168.1.13->88.96.22.41
if (strcmp(s,"192.168.1.13")!=0 || strcmp(d,"88.96.22.41")!=0 ) {
return 0;
if (strcmp(s, "192.168.1.13") == 0 && strcmp(d, "88.96.22.41") == 0) {
ret = 1;
}
return 1;
end:
FlowShutdown();
return ret;
}
static int ICMPV4CalculateValidChecksumtest05(void) {
@ -512,18 +581,33 @@ static int ICMPV4InvalidType07(void) {
Packet p;
ThreadVars tv;
DecodeThreadVars dtv;
int ret = 0;
IPV4Hdr ip4h;
memset(&ip4h, 0, sizeof(IPV4Hdr));
memset(&tv, 0, sizeof(ThreadVars));
memset(&p, 0, sizeof(Packet));
memset(&dtv, 0, sizeof(DecodeThreadVars));
FlowInitConfig(FLOW_QUIET);
p.src.family = AF_INET;
p.dst.family = AF_INET;
p.src.addr_data32[0] = 0x01020304;
p.dst.addr_data32[0] = 0x04030201;
ip4h.ip_src.s_addr = p.src.addr_data32[0];
ip4h.ip_dst.s_addr = p.dst.addr_data32[0];
p.ip4h = &ip4h;
DecodeICMPV4(&tv, &dtv, &p, raw_icmpv4, sizeof(raw_icmpv4), NULL);
if(DECODER_ISSET_EVENT(&p,ICMPV4_UNKNOWN_TYPE)) {
return 1;
ret = 1;
}
return 0;
FlowShutdown();
return ret;
}
/** DecodeICMPV4test08
@ -537,20 +621,35 @@ static int DecodeICMPV4test08(void) {
Packet p;
ThreadVars tv;
DecodeThreadVars dtv;
int ret = 0;
IPV4Hdr ip4h;
memset(&ip4h, 0, sizeof(IPV4Hdr));
memset(&tv, 0, sizeof(ThreadVars));
memset(&p, 0, sizeof(Packet));
memset(&dtv, 0, sizeof(DecodeThreadVars));
FlowInitConfig(FLOW_QUIET);
p.src.family = AF_INET;
p.dst.family = AF_INET;
p.src.addr_data32[0] = 0x01020304;
p.dst.addr_data32[0] = 0x04030201;
ip4h.ip_src.s_addr = p.src.addr_data32[0];
ip4h.ip_dst.s_addr = p.dst.addr_data32[0];
p.ip4h = &ip4h;
DecodeICMPV4(&tv, &dtv, &p, raw_icmpv4, sizeof(raw_icmpv4), NULL);
if (NULL!=p.icmpv4h) {
if (p.icmpv4h->type==8 && p.icmpv4h->code==0) {
return 1;
ret = 1;
}
}
return 0;
FlowShutdown();
return ret;
}
#endif /* UNITTESTS */
@ -559,15 +658,15 @@ static int DecodeICMPV4test08(void) {
*/
void DecodeICMPV4RegisterTests(void) {
#ifdef UNITTESTS
UtRegisterTest("DecodeICMPV4ttest01", DecodeICMPV4test01, 1);
UtRegisterTest("DecodeICMPV4ttest02", DecodeICMPV4test02, 1);
UtRegisterTest("DecodeICMPV4ttest03", DecodeICMPV4test03, 1);
UtRegisterTest("DecodeICMPV4ttest04", DecodeICMPV4test04, 1);
UtRegisterTest("DecodeICMPV4test01", DecodeICMPV4test01, 1);
UtRegisterTest("DecodeICMPV4test02", DecodeICMPV4test02, 1);
UtRegisterTest("DecodeICMPV4test03", DecodeICMPV4test03, 1);
UtRegisterTest("DecodeICMPV4test04", DecodeICMPV4test04, 1);
UtRegisterTest("ICMPV4CalculateValidChecksumtest05",
ICMPV4CalculateValidChecksumtest05, 1);
UtRegisterTest("ICMPV4CalculateInvalidChecksumtest06",
ICMPV4CalculateInvalidChecksumtest06, 0);
UtRegisterTest("DecodeICMPV4InvalidType", ICMPV4InvalidType07, 1);
UtRegisterTest("DecodeICMPV4ttest08", DecodeICMPV4test08, 1);
UtRegisterTest("DecodeICMPV4test08", DecodeICMPV4test08, 1);
#endif /* UNITTESTS */
}

@ -212,6 +212,8 @@ void DecodeICMPV6(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p,
p->icmpv6h = (ICMPV6Hdr *)pkt;
p->proto = IPPROTO_ICMPV6;
p->type = p->icmpv6h->type;
p->code = p->icmpv6h->code;
SCLogDebug("ICMPV6 TYPE %" PRIu32 " CODE %" PRIu32 "", p->icmpv6h->type,
p->icmpv6h->code);
@ -312,6 +314,9 @@ void DecodeICMPV6(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p,
if (DECODER_ISSET_EVENT(p, ICMPV6_UNKNOWN_TYPE))
SCLogDebug("Unknown Type, ICMPV6_UNKNOWN_TYPE");
/* Flow is an integral part of us */
FlowHandlePacket(tv, p);
return;
}

@ -14,6 +14,8 @@
#include "decode-pppoe.h"
#include "decode-events.h"
#include "flow.h"
#include "util-unittest.h"
#include "util-debug.h"
@ -230,24 +232,30 @@ static int DecodePPPOEtest02 (void) {
Packet p;
ThreadVars tv;
DecodeThreadVars dtv;
int ret = 0;
memset(&tv, 0, sizeof(ThreadVars));
memset(&p, 0, sizeof(Packet));
memset(&dtv, 0, sizeof(DecodeThreadVars));
FlowInitConfig(FLOW_QUIET);
DecodePPPOESession(&tv, &dtv, &p, raw_pppoe, sizeof(raw_pppoe), NULL);
if(DECODER_ISSET_EVENT(&p,PPPOE_PKT_TOO_SMALL)) {
return 1;
goto end;
}
// and we insist that the invalid ICMP encapsulated (type 0xab, code 0xcd) is flagged
if(! DECODER_ISSET_EVENT(&p,ICMPV4_UNKNOWN_TYPE)) {
return 1;
goto end;
}
return 0;
ret = 1;
end:
FlowShutdown();
return ret;
}
@ -276,7 +284,7 @@ static int DecodePPPOEtest03 (void) {
DecodePPPOEDiscovery(&tv, &dtv, &p, raw_pppoe, sizeof(raw_pppoe), NULL);
return 0; // TODO
return 1; // TODO
}
/** DecodePPPOEtest04
@ -349,8 +357,8 @@ static int DecodePPPOEtest05 (void) {
void DecodePPPOERegisterTests(void) {
#ifdef UNITTESTS
UtRegisterTest("DecodePPPOEtest01", DecodePPPOEtest01, 1);
UtRegisterTest("DecodePPPOEtest02", DecodePPPOEtest02, 0);
UtRegisterTest("DecodePPPOEtest03", DecodePPPOEtest03, 0);
UtRegisterTest("DecodePPPOEtest02", DecodePPPOEtest02, 1);
UtRegisterTest("DecodePPPOEtest03", DecodePPPOEtest03, 1);
UtRegisterTest("DecodePPPOEtest04", DecodePPPOEtest04, 1);
UtRegisterTest("DecodePPPOEtest05", DecodePPPOEtest05, 1);
#endif /* UNITTESTS */

@ -188,8 +188,14 @@ typedef struct Packet_
* the Packet as a hash key */
Address src;
Address dst;
Port sp;
Port dp;
union {
Port sp;
uint8_t type;
};
union {
Port dp;
uint8_t code;
};
uint8_t proto;
/* make sure we can't be attacked on when the tunneled packet
* has the exact same tuple as the lower levels */

@ -318,14 +318,25 @@ int DetectIcmpIdMatchTest01 (void) {
DecodeThreadVars dtv;
ThreadVars th_v;
DetectEngineThreadCtx *det_ctx = NULL;
IPV4Hdr ip4h;
memset(&p, 0, sizeof(Packet));
memset(&ip4h, 0, sizeof(IPV4Hdr));
memset(&dtv, 0, sizeof(DecodeThreadVars));
memset(&th_v, 0, sizeof(ThreadVars));
DecodeICMPV4(&th_v, &dtv, &p, raw_icmpv4, sizeof(raw_icmpv4), NULL);
FlowInitConfig(FLOW_QUIET);
p.src.family = AF_INET;
p.dst.family = AF_INET;
p.src.addr_data32[0] = 0x01020304;
p.dst.addr_data32[0] = 0x04030201;
ip4h.ip_src.s_addr = p.src.addr_data32[0];
ip4h.ip_dst.s_addr = p.dst.addr_data32[0];
p.ip4h = &ip4h;
DecodeICMPV4(&th_v, &dtv, &p, raw_icmpv4, sizeof(raw_icmpv4), NULL);
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL) {
@ -365,6 +376,7 @@ cleanup:
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
DetectEngineCtxFree(de_ctx);
FlowShutdown();
end:
return result;
@ -391,14 +403,23 @@ int DetectIcmpIdMatchTest02 (void) {
DecodeThreadVars dtv;
ThreadVars th_v;
DetectEngineThreadCtx *det_ctx = NULL;
IPV4Hdr ip4h;
memset(&p, 0, sizeof(Packet));
memset(&ip4h, 0, sizeof(IPV4Hdr));
memset(&dtv, 0, sizeof(DecodeThreadVars));
memset(&th_v, 0, sizeof(ThreadVars));
FlowInitConfig(FLOW_QUIET);
p.src.addr_data32[0] = 0x01020304;
p.dst.addr_data32[0] = 0x04030201;
ip4h.ip_src.s_addr = p.src.addr_data32[0];
ip4h.ip_dst.s_addr = p.dst.addr_data32[0];
p.ip4h = &ip4h;
DecodeICMPV4(&th_v, &dtv, &p, raw_icmpv4, sizeof(raw_icmpv4), NULL);
p.src.family = AF_INET;
p.dst.family = AF_INET;
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL) {
@ -430,6 +451,7 @@ cleanup:
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
DetectEngineCtxFree(de_ctx);
FlowShutdown();
end:
return result;
}

@ -415,17 +415,17 @@ inline SigGroupHead *SigMatchSignaturesGetSgh(ThreadVars *th_v, DetectEngineCtx
if (dport != NULL) {
sgh = dport->sh;
} else {
SCLogDebug("no dst port found for the packet");
SCLogDebug("no dst port group found for the packet");
}
} else {
SCLogDebug("no src port found for the packet");
SCLogDebug("no src port group found for the packet");
}
}
} else {
SCLogDebug("no dst address found for the packet");
SCLogDebug("no dst address group found for the packet");
}
} else {
SCLogDebug("no src address found for the packet");
SCLogDebug("no src address group found for the packet");
}
SCReturnPtr(sgh, "SigGroupHead");
@ -616,14 +616,18 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh
det_ctx->pkts++;
SCLogDebug("p->flowflags 0x%02x", p->flowflags);
/* match the ip only signatures */
if ((p->flowflags & FLOW_PKT_TOSERVER && !(p->flowflags & FLOW_PKT_TOSERVER_IPONLY_SET)) ||
(p->flowflags & FLOW_PKT_TOCLIENT && !(p->flowflags & FLOW_PKT_TOCLIENT_IPONLY_SET))) {
IPOnlyMatchPacket(de_ctx, &de_ctx->io_ctx, &det_ctx->io_ctx, p);
/* save in the flow that we scanned this direction... locking is
* done in the FlowSetIPOnlyFlag function. */
if (p->flow != NULL)
FlowSetIPOnlyFlag(p->flow, p->flowflags & FLOW_PKT_TOSERVER ? 1 : 0);
SCLogDebug("testing against \"ip-only\"");
IPOnlyMatchPacket(de_ctx, &de_ctx->io_ctx, &det_ctx->io_ctx, p);
/* save in the flow that we scanned this direction... locking is
* done in the FlowSetIPOnlyFlag function. */
if (p->flow != NULL)
FlowSetIPOnlyFlag(p->flow, p->flowflags & FLOW_PKT_TOSERVER ? 1 : 0);
}
/* we assume we don't have an uri when we start inspection */
@ -945,6 +949,12 @@ int SignatureIsIPOnly(DetectEngineCtx *de_ctx, Signature *s) {
if (!(s->flags & SIG_FLAG_DP_ANY))
return 0;
/*
} else if ((s->proto.proto[IPPROTO_ICMP / 8] & (1 << (IPPROTO_ICMP % 8))) ||
(s->proto.proto[IPPROTO_ICMPV6 / 8] & (1 << (IPPROTO_ICMPV6 % 8)))) {
SCLogDebug("ICMP sigs are not IP-Only until we support ICMP in flow.");
return 0;
*/
}
}

@ -99,6 +99,12 @@ void FlowInit(Flow *f, Packet *p)
} else if (p->udph != NULL) { /* XXX MACRO */
SET_UDP_SRC_PORT(p,&f->sp);
SET_UDP_DST_PORT(p,&f->dp);
} else if (p->icmpv4h != NULL) {
f->type = p->type;
f->code = p->code;
} else if (p->icmpv6h != NULL) {
f->type = p->type;
f->code = p->code;
} /* XXX handle default */
else {
printf("FIXME: %s:%s:%" PRId32 "\n", __FILE__, __FUNCTION__, __LINE__);

@ -8,6 +8,8 @@
/* only clear the parts that won't be overwritten
* in FlowInit anyway */
#define CLEAR_FLOW(f) { \
(f)->sp = 0; \
(f)->dp = 0; \
(f)->flags = 0; \
(f)->todstpktcnt = 0; \
(f)->tosrcpktcnt = 0; \

@ -319,6 +319,42 @@ void FlowDecrUsecnt(ThreadVars *tv, Packet *p) {
SCMutexUnlock(&p->flow->m);
}
#define TOSERVER 0
#define TOCLIENT 1
/**
* \brief determine the direction of the packet compared to the flow
* \retval 0 to_server
* \retval 1 to_client
*/
static inline int FlowGetPacketDirection(Flow *f, Packet *p) {
if (p->proto == IPPROTO_TCP || p->proto == IPPROTO_UDP) {
if (!(CMP_PORT(p->sp,p->dp))) {
/* update flags and counters */
if (CMP_PORT(f->sp,p->sp)) {
return TOSERVER;
} else {
return TOCLIENT;
}
} else {
if (CMP_ADDR(&f->src,&p->src)) {
return TOSERVER;
} else {
return TOCLIENT;
}
}
} else if (p->proto == IPPROTO_ICMP || p->proto == IPPROTO_ICMPV6) {
if (CMP_ADDR(&f->src,&p->src)) {
return TOSERVER;
} else {
return TOCLIENT;
}
}
/* default to toserver */
return TOSERVER;
}
/** \brief Entry point for packet flow handling
*
* This is called for every packet.
@ -341,7 +377,7 @@ void FlowHandlePacket (ThreadVars *tv, Packet *p)
COPY_TIMESTAMP(&p->ts, &f->lastts);
/* update flags and counters */
if (CMP_PORT(f->sp,p->sp)) {
if (FlowGetPacketDirection(f,p) == TOSERVER) {
f->flags |= FLOW_TO_DST_SEEN;
f->todstpktcnt++;
p->flowflags |= FLOW_PKT_TOSERVER;

@ -50,7 +50,14 @@ typedef struct FlowKey_
typedef struct Flow_
{
Address src, dst;
Port sp, dp;
union {
Port sp; /**< tcp/udp source port */
uint8_t type; /**< icmp type */
};
union {
Port dp; /**< tcp/udp destination port */
uint8_t code; /**< icmp code */
};
uint8_t proto;
uint8_t recursion_level;

@ -52,7 +52,7 @@ typedef enum {
} SCLogOPIface;
/* The default log_format, if it is not supplied by the user */
#define SC_LOG_DEF_LOG_FORMAT "%t - (%f:%l) <%d> (%n) -- "
#define SC_LOG_DEF_LOG_FORMAT "[%i] %t - (%f:%l) <%d> (%n) -- "
/* The maximum length of the log message */
#define SC_LOG_MAX_LOG_MSG_LEN 1024

Loading…
Cancel
Save