From: Joyce Yu Date: Mon, 17 Mar 2025 18:58:50 +0000 (-0400) Subject: Eve: use mac addresses from flow for flow timeout X-Git-Tag: suricata-8.0.0-beta1~254 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1c50de4ad0b72d787284df0db86ef6fabb120c85;p=thirdparty%2Fsuricata.git Eve: use mac addresses from flow for flow timeout Ethernet metadata is missing for events triggered on flow timeout pseudopackets. Use the first set of mac addresses stored with the flow to fill in the ether field. Ticket: #5486 --- diff --git a/src/output-json.c b/src/output-json.c index 422191adbc..b6ce328cab 100644 --- a/src/output-json.c +++ b/src/output-json.c @@ -767,6 +767,22 @@ static int CreateJSONEther( JSONFormatAndAddMACAddr(js, "src_mac", src, false); JSONFormatAndAddMACAddr(js, "dest_mac", dst, false); jb_close(js); + } else if (f != NULL) { + /* When pseudopackets do not have associated ethernet metadata, + use the first set of mac addresses stored with their flow. + The first set of macs should come from the flow's first packet, + providing the most fitting representation of the event's ethernet. */ + MacSet *ms = FlowGetStorageById(f, MacSetGetFlowStorageID()); + if (ms != NULL && MacSetSize(ms) > 0) { + uint8_t *src = MacSetGetFirst(ms, MAC_SET_SRC); + uint8_t *dst = MacSetGetFirst(ms, MAC_SET_DST); + if (dst != NULL && src != NULL) { + jb_open_object(js, "ether"); + JSONFormatAndAddMACAddr(js, "src_mac", src, false); + JSONFormatAndAddMACAddr(js, "dest_mac", dst, false); + jb_close(js); + } + } } } else if (f != NULL) { /* we are creating an ether object in a flow context, so we need to diff --git a/src/util-macset.c b/src/util-macset.c index bf3edf0572..bf50c098bb 100644 --- a/src/util-macset.c +++ b/src/util-macset.c @@ -230,6 +230,19 @@ int MacSetForEach(const MacSet *ms, MacSetIteratorFunc IterFunc, void *data) return MacSetIterateSide(ms, IterFunc, MAC_SET_DST, data); } +uint8_t *MacSetGetFirst(const MacSet *ms, MacSetSide side) +{ + switch (ms->state[side]) { + case EMPTY_SET: + return NULL; + case SINGLE_MAC: + return (uint8_t *)ms->singles[side]; + case MULTI_MAC: + return (uint8_t *)ms->buf[side][0]; + } + return NULL; +} + int MacSetSize(const MacSet *ms) { int size = 0; @@ -416,6 +429,39 @@ static int MacSetTest05(void) PASS; } +static int MacSetTest06(void) +{ + SC_ATOMIC_SET(flow_config.memcap, 128); + + MacSet *ms = MacSetInit(10); + FAIL_IF_NULL(ms); + FAIL_IF_NOT(MacSetSize(ms) == 0); + + uint8_t *src0 = MacSetGetFirst(ms, MAC_SET_SRC); + uint8_t *dst0 = MacSetGetFirst(ms, MAC_SET_DST); + + MacAddr addr1 = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x1 }, addr2 = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x2 }, + addr3 = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x3 }, addr4 = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x4 }; + + MacSetAdd(ms, addr1, addr2); + uint8_t *src1 = MacSetGetFirst(ms, MAC_SET_SRC); + uint8_t *dst1 = MacSetGetFirst(ms, MAC_SET_DST); + + MacSetAdd(ms, addr3, addr4); + uint8_t *src2 = MacSetGetFirst(ms, MAC_SET_SRC); + uint8_t *dst2 = MacSetGetFirst(ms, MAC_SET_DST); + + FAIL_IF_NOT_NULL(src0); + FAIL_IF_NOT_NULL(dst0); + FAIL_IF_NOT(src1[5] == addr1[5]); + FAIL_IF_NOT(dst1[5] == addr2[5]); + FAIL_IF_NOT(src2[5] == addr1[5]); + FAIL_IF_NOT(dst2[5] == addr2[5]); + + MacSetFree(ms); + PASS; +} + #endif /* UNITTESTS */ void MacSetRegisterTests(void) @@ -427,5 +473,6 @@ void MacSetRegisterTests(void) UtRegisterTest("MacSetTest03", MacSetTest03); UtRegisterTest("MacSetTest04", MacSetTest04); UtRegisterTest("MacSetTest05", MacSetTest05); + UtRegisterTest("MacSetTest06", MacSetTest06); #endif } diff --git a/src/util-macset.h b/src/util-macset.h index 5f60aa2a18..9749f2aa63 100644 --- a/src/util-macset.h +++ b/src/util-macset.h @@ -37,6 +37,7 @@ void MacSetAdd(MacSet *, const uint8_t *src_addr, const uint8_t *dst_addr); void MacSetAddWithCtr(MacSet *, const uint8_t *src_addr, const uint8_t *dst_addr, ThreadVars *tv, uint16_t ctr_src, uint16_t ctr_dst); int MacSetForEach(const MacSet*, MacSetIteratorFunc, void*); +uint8_t *MacSetGetFirst(const MacSet *, MacSetSide); int MacSetSize(const MacSet*); void MacSetReset(MacSet*); void MacSetFree(MacSet*);