decode/vlan: Decode upto 3 layers of VLAN

Issue: 2816

This commit increase the number of VLAN layers supported by Suricata
from 2 to 3. 3-layers are dubbed "Q-in-Q-in-Q".

Note that 3 layers are not compliant with any existing standard but are
often seen in larger deployments.
pull/8965/head
Jeff Lucovsky 3 years ago committed by Victor Julien
parent 9dc68ac59a
commit 0d2268ddfc

@ -99,7 +99,7 @@ int DecodeERSPAN(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t
}
if (vlan_id > 0) {
if (p->vlan_idx >= 2) {
if (p->vlan_idx > VLAN_MAX_LAYER_IDX) {
ENGINE_SET_EVENT(p,ERSPAN_TOO_MANY_VLAN_LAYERS);
return TM_ECODE_FAILED;
}

@ -62,6 +62,8 @@ int DecodeVLAN(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p,
StatsIncr(tv, dtv->counter_vlan);
else if (p->vlan_idx == 1)
StatsIncr(tv, dtv->counter_vlan_qinq);
else if (p->vlan_idx == 2)
StatsIncr(tv, dtv->counter_vlan_qinqinq);
if(len < VLAN_HEADER_LEN) {
ENGINE_SET_INVALID_EVENT(p, VLAN_HEADER_TOO_SMALL);
@ -70,7 +72,7 @@ int DecodeVLAN(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p,
if (!PacketIncreaseCheckLayers(p)) {
return TM_ECODE_FAILED;
}
if (p->vlan_idx >= 2) {
if (p->vlan_idx > VLAN_MAX_LAYER_IDX) {
ENGINE_SET_EVENT(p,VLAN_HEADER_TOO_MANY_LAYERS);
return TM_ECODE_FAILED;
}
@ -95,7 +97,7 @@ int DecodeVLAN(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p,
uint16_t DecodeVLANGetId(const Packet *p, uint8_t layer)
{
if (unlikely(layer > 1))
if (unlikely(layer > 2))
return 0;
if (p->vlan_idx > layer) {
return p->vlan_id[layer];

@ -39,6 +39,7 @@ uint16_t DecodeVLANGetId(const struct Packet_ *, uint8_t layer);
/* return vlan id in host byte order */
#define VLAN_GET_ID1(p) DecodeVLANGetId((p), 0)
#define VLAN_GET_ID2(p) DecodeVLANGetId((p), 1)
#define VLAN_GET_ID3(p) DecodeVLANGetId((p), 2)
/** Vlan header struct */
typedef struct VLANHdr_ {
@ -51,5 +52,9 @@ typedef struct VLANHdr_ {
void DecodeVLANRegisterTests(void);
/** VLAN max encapsulation layer count/index */
#define VLAN_MAX_LAYERS 3
#define VLAN_MAX_LAYER_IDX (VLAN_MAX_LAYERS - 1)
#endif /* __DECODE_VLAN_H__ */

@ -412,8 +412,7 @@ Packet *PacketDefragPktSetup(Packet *parent, const uint8_t *pkt, uint32_t len, u
p->tenant_id = parent->tenant_id;
/* tell new packet it's part of a tunnel */
SET_TUNNEL_PKT(p);
p->vlan_id[0] = parent->vlan_id[0];
p->vlan_id[1] = parent->vlan_id[1];
memcpy(&p->vlan_id[0], &parent->vlan_id[0], sizeof(p->vlan_id));
p->vlan_idx = parent->vlan_idx;
p->livedev = parent->livedev;
@ -555,6 +554,7 @@ void DecodeRegisterPerfCounters(DecodeThreadVars *dtv, ThreadVars *tv)
dtv->counter_gre = StatsRegisterCounter("decoder.gre", tv);
dtv->counter_vlan = StatsRegisterCounter("decoder.vlan", tv);
dtv->counter_vlan_qinq = StatsRegisterCounter("decoder.vlan_qinq", tv);
dtv->counter_vlan_qinqinq = StatsRegisterCounter("decoder.vlan_qinqinq", tv);
dtv->counter_vxlan = StatsRegisterCounter("decoder.vxlan", tv);
dtv->counter_vntag = StatsRegisterCounter("decoder.vntag", tv);
dtv->counter_ieee8021ah = StatsRegisterCounter("decoder.ieee8021ah", tv);

@ -225,7 +225,6 @@ typedef struct Address_ {
(p)->pktlen = (len); \
} while (0)
/* Port is just a uint16_t */
typedef uint16_t Port;
#define SET_PORT(v, p) ((p) = (v))
@ -453,7 +452,7 @@ typedef struct Packet_
* has the exact same tuple as the lower levels */
uint8_t recursion_level;
uint16_t vlan_id[2];
uint16_t vlan_id[VLAN_MAX_LAYERS];
uint8_t vlan_idx;
/* flow */
@ -700,6 +699,7 @@ typedef struct DecodeThreadVars_
uint16_t counter_gre;
uint16_t counter_vlan;
uint16_t counter_vlan_qinq;
uint16_t counter_vlan_qinqinq;
uint16_t counter_vxlan;
uint16_t counter_vntag;
uint16_t counter_ieee8021ah;
@ -1185,7 +1185,7 @@ static inline bool DecodeNetworkLayer(ThreadVars *tv, DecodeThreadVars *dtv,
case ETHERNET_TYPE_VLAN:
case ETHERNET_TYPE_8021AD:
case ETHERNET_TYPE_8021QINQ:
if (p->vlan_idx >= 2) {
if (p->vlan_idx > VLAN_MAX_LAYER_IDX) {
ENGINE_SET_EVENT(p,VLAN_HEADER_TOO_MANY_LAYERS);
} else {
DecodeVLAN(tv, dtv, p, data, len);

@ -1,4 +1,4 @@
/* Copyright (C) 2007-2012 Open Information Security Foundation
/* Copyright (C) 2007-2022 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
@ -137,8 +137,7 @@ static void DefragTrackerInit(DefragTracker *dt, Packet *p)
dt->af = AF_INET6;
}
dt->proto = IP_GET_IPPROTO(p);
dt->vlan_id[0] = p->vlan_id[0];
dt->vlan_id[1] = p->vlan_id[1];
memcpy(&dt->vlan_id[0], &p->vlan_id[0], sizeof(dt->vlan_id));
dt->policy = DefragGetOsPolicy(p);
dt->host_timeout = DefragPolicyGetHostTimeout(p);
dt->remove = 0;
@ -361,9 +360,10 @@ typedef struct DefragHashKey4_ {
struct {
uint32_t src, dst;
uint32_t id;
uint16_t vlan_id[2];
uint16_t vlan_id[VLAN_MAX_LAYERS];
uint16_t pad[1];
};
uint32_t u32[4];
uint32_t u32[5];
};
} DefragHashKey4;
@ -372,9 +372,10 @@ typedef struct DefragHashKey6_ {
struct {
uint32_t src[4], dst[4];
uint32_t id;
uint16_t vlan_id[2];
uint16_t vlan_id[VLAN_MAX_LAYERS];
uint16_t pad[1];
};
uint32_t u32[10];
uint32_t u32[11];
};
} DefragHashKey6;
@ -392,7 +393,7 @@ static inline uint32_t DefragHashGetKey(Packet *p)
uint32_t key;
if (p->ip4h != NULL) {
DefragHashKey4 dhk;
DefragHashKey4 dhk = { .pad[0] = 0 };
if (p->src.addr_data32[0] > p->dst.addr_data32[0]) {
dhk.src = p->src.addr_data32[0];
dhk.dst = p->dst.addr_data32[0];
@ -401,13 +402,13 @@ static inline uint32_t DefragHashGetKey(Packet *p)
dhk.dst = p->src.addr_data32[0];
}
dhk.id = (uint32_t)IPV4_GET_IPID(p);
dhk.vlan_id[0] = p->vlan_id[0];
dhk.vlan_id[1] = p->vlan_id[1];
memcpy(&dhk.vlan_id[0], &p->vlan_id[0], sizeof(dhk.vlan_id));
uint32_t hash = hashword(dhk.u32, 4, defrag_config.hash_rand);
uint32_t hash =
hashword(dhk.u32, sizeof(dhk.u32) / sizeof(uint32_t), defrag_config.hash_rand);
key = hash % defrag_config.hash_size;
} else if (p->ip6h != NULL) {
DefragHashKey6 dhk;
DefragHashKey6 dhk = { .pad[0] = 0 };
if (DefragHashRawAddressIPv6GtU32(p->src.addr_data32, p->dst.addr_data32)) {
dhk.src[0] = p->src.addr_data32[0];
dhk.src[1] = p->src.addr_data32[1];
@ -428,10 +429,10 @@ static inline uint32_t DefragHashGetKey(Packet *p)
dhk.dst[3] = p->src.addr_data32[3];
}
dhk.id = IPV6_EXTHDR_GET_FH_ID(p);
dhk.vlan_id[0] = p->vlan_id[0];
dhk.vlan_id[1] = p->vlan_id[1];
memcpy(&dhk.vlan_id[0], &p->vlan_id[0], sizeof(dhk.vlan_id));
uint32_t hash = hashword(dhk.u32, 10, defrag_config.hash_rand);
uint32_t hash =
hashword(dhk.u32, sizeof(dhk.u32) / sizeof(uint32_t), defrag_config.hash_rand);
key = hash % defrag_config.hash_size;
} else
key = 0;
@ -441,15 +442,12 @@ static inline uint32_t DefragHashGetKey(Packet *p)
/* Since two or more trackers can have the same hash key, we need to compare
* the tracker with the current tracker key. */
#define CMP_DEFRAGTRACKER(d1,d2,id) \
(((CMP_ADDR(&(d1)->src_addr, &(d2)->src) && \
CMP_ADDR(&(d1)->dst_addr, &(d2)->dst)) || \
(CMP_ADDR(&(d1)->src_addr, &(d2)->dst) && \
CMP_ADDR(&(d1)->dst_addr, &(d2)->src))) && \
(d1)->proto == IP_GET_IPPROTO(d2) && \
(d1)->id == (id) && \
(d1)->vlan_id[0] == (d2)->vlan_id[0] && \
(d1)->vlan_id[1] == (d2)->vlan_id[1])
#define CMP_DEFRAGTRACKER(d1, d2, id) \
(((CMP_ADDR(&(d1)->src_addr, &(d2)->src) && CMP_ADDR(&(d1)->dst_addr, &(d2)->dst)) || \
(CMP_ADDR(&(d1)->src_addr, &(d2)->dst) && CMP_ADDR(&(d1)->dst_addr, &(d2)->src))) && \
(d1)->proto == IP_GET_IPPROTO(d2) && (d1)->id == (id) && \
(d1)->vlan_id[0] == (d2)->vlan_id[0] && (d1)->vlan_id[1] == (d2)->vlan_id[1] && \
(d1)->vlan_id[2] == (d2)->vlan_id[2])
static inline int DefragTrackerCompare(DefragTracker *t, Packet *p)
{

@ -1,4 +1,4 @@
/* Copyright (C) 2007-2012 Open Information Security Foundation
/* Copyright (C) 2007-2022 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
@ -2259,6 +2259,41 @@ static int DefragVlanQinQTest(void)
PASS;
}
/**
* Like DefragVlanTest, but for QinQinQ, testing the third level VLAN ID.
*/
static int DefragVlanQinQinQTest(void)
{
Packet *r = NULL;
DefragInit();
Packet *p1 = BuildTestPacket(IPPROTO_ICMP, 1, 0, 1, 'A', 8);
FAIL_IF_NULL(p1);
Packet *p2 = BuildTestPacket(IPPROTO_ICMP, 1, 1, 0, 'B', 8);
FAIL_IF_NULL(p2);
/* With no VLAN IDs set, packets should re-assemble. */
FAIL_IF((r = Defrag(NULL, NULL, p1)) != NULL);
FAIL_IF((r = Defrag(NULL, NULL, p2)) == NULL);
SCFree(r);
/* With mismatched VLANs, packets should not re-assemble. */
p1->vlan_id[0] = 1;
p2->vlan_id[0] = 1;
p1->vlan_id[1] = 2;
p2->vlan_id[1] = 2;
p1->vlan_id[2] = 3;
p2->vlan_id[2] = 4;
FAIL_IF((r = Defrag(NULL, NULL, p1)) != NULL);
FAIL_IF((r = Defrag(NULL, NULL, p2)) != NULL);
PacketFree(p1);
PacketFree(p2);
DefragDestroy();
PASS;
}
static int DefragTrackerReuseTest(void)
{
int id = 1;
@ -2508,6 +2543,7 @@ void DefragRegisterTests(void)
UtRegisterTest("DefragVlanTest", DefragVlanTest);
UtRegisterTest("DefragVlanQinQTest", DefragVlanQinQTest);
UtRegisterTest("DefragVlanQinQinQTest", DefragVlanQinQinQTest);
UtRegisterTest("DefragTrackerReuseTest", DefragTrackerReuseTest);
UtRegisterTest("DefragTimeoutTest", DefragTimeoutTest);
UtRegisterTest("DefragMfIpv4Test", DefragMfIpv4Test);

@ -87,7 +87,7 @@ typedef struct DefragTracker_ {
SCMutex lock; /**< Mutex for locking list operations on
* this tracker. */
uint16_t vlan_id[2]; /**< VLAN ID tracker applies to. */
uint16_t vlan_id[VLAN_MAX_LAYERS]; /**< VLAN ID tracker applies to. */
uint32_t id; /**< IP ID for this tracker. 32 bits for IPv6, 16
* for IPv4. */

@ -89,9 +89,10 @@ typedef struct FlowHashKey4_ {
uint16_t ports[2];
uint16_t proto; /**< u16 so proto and recur add up to u32 */
uint16_t recur; /**< u16 so proto and recur add up to u32 */
uint16_t vlan_id[2];
uint16_t vlan_id[VLAN_MAX_LAYERS];
uint16_t pad[1];
};
const uint32_t u32[5];
const uint32_t u32[6];
};
} FlowHashKey4;
@ -102,9 +103,10 @@ typedef struct FlowHashKey6_ {
uint16_t ports[2];
uint16_t proto; /**< u16 so proto and recur add up to u32 */
uint16_t recur; /**< u16 so proto and recur add up to u32 */
uint16_t vlan_id[2];
uint16_t vlan_id[VLAN_MAX_LAYERS];
uint16_t pad[1];
};
const uint32_t u32[11];
const uint32_t u32[12];
};
} FlowHashKey6;
@ -112,7 +114,9 @@ uint32_t FlowGetIpPairProtoHash(const Packet *p)
{
uint32_t hash = 0;
if (p->ip4h != NULL) {
FlowHashKey4 fhk;
FlowHashKey4 fhk = {
.pad[0] = 0,
};
int ai = (p->src.addr_data32[0] > p->dst.addr_data32[0]);
fhk.addrs[1 - ai] = p->src.addr_data32[0];
@ -127,10 +131,13 @@ uint32_t FlowGetIpPairProtoHash(const Packet *p)
* is disabled. */
fhk.vlan_id[0] = p->vlan_id[0] & g_vlan_mask;
fhk.vlan_id[1] = p->vlan_id[1] & g_vlan_mask;
fhk.vlan_id[2] = p->vlan_id[2] & g_vlan_mask;
hash = hashword(fhk.u32, 5, flow_config.hash_rand);
hash = hashword(fhk.u32, ARRAY_SIZE(fhk.u32), flow_config.hash_rand);
} else if (p->ip6h != NULL) {
FlowHashKey6 fhk;
FlowHashKey6 fhk = {
.pad[0] = 0,
};
if (FlowHashRawAddressIPv6GtU32(p->src.addr_data32, p->dst.addr_data32)) {
fhk.src[0] = p->src.addr_data32[0];
fhk.src[1] = p->src.addr_data32[1];
@ -157,8 +164,9 @@ uint32_t FlowGetIpPairProtoHash(const Packet *p)
fhk.recur = (uint16_t)p->recursion_level;
fhk.vlan_id[0] = p->vlan_id[0] & g_vlan_mask;
fhk.vlan_id[1] = p->vlan_id[1] & g_vlan_mask;
fhk.vlan_id[2] = p->vlan_id[2] & g_vlan_mask;
hash = hashword(fhk.u32, 11, flow_config.hash_rand);
hash = hashword(fhk.u32, ARRAY_SIZE(fhk.u32), flow_config.hash_rand);
}
return hash;
}
@ -182,7 +190,7 @@ static inline uint32_t FlowGetHash(const Packet *p)
if (p->ip4h != NULL) {
if (p->tcph != NULL || p->udph != NULL) {
FlowHashKey4 fhk;
FlowHashKey4 fhk = { .pad[0] = 0 };
int ai = (p->src.addr_data32[0] > p->dst.addr_data32[0]);
fhk.addrs[1-ai] = p->src.addr_data32[0];
@ -198,13 +206,14 @@ static inline uint32_t FlowGetHash(const Packet *p)
* is disabled. */
fhk.vlan_id[0] = p->vlan_id[0] & g_vlan_mask;
fhk.vlan_id[1] = p->vlan_id[1] & g_vlan_mask;
fhk.vlan_id[2] = p->vlan_id[2] & g_vlan_mask;
hash = hashword(fhk.u32, 5, flow_config.hash_rand);
hash = hashword(fhk.u32, ARRAY_SIZE(fhk.u32), flow_config.hash_rand);
} else if (ICMPV4_DEST_UNREACH_IS_VALID(p)) {
uint32_t psrc = IPV4_GET_RAW_IPSRC_U32(ICMPV4_GET_EMB_IPV4(p));
uint32_t pdst = IPV4_GET_RAW_IPDST_U32(ICMPV4_GET_EMB_IPV4(p));
FlowHashKey4 fhk;
FlowHashKey4 fhk = { .pad[0] = 0 };
const int ai = (psrc > pdst);
fhk.addrs[1-ai] = psrc;
@ -218,11 +227,12 @@ static inline uint32_t FlowGetHash(const Packet *p)
fhk.recur = (uint16_t)p->recursion_level;
fhk.vlan_id[0] = p->vlan_id[0] & g_vlan_mask;
fhk.vlan_id[1] = p->vlan_id[1] & g_vlan_mask;
fhk.vlan_id[2] = p->vlan_id[2] & g_vlan_mask;
hash = hashword(fhk.u32, 5, flow_config.hash_rand);
hash = hashword(fhk.u32, ARRAY_SIZE(fhk.u32), flow_config.hash_rand);
} else {
FlowHashKey4 fhk;
FlowHashKey4 fhk = { .pad[0] = 0 };
const int ai = (p->src.addr_data32[0] > p->dst.addr_data32[0]);
fhk.addrs[1-ai] = p->src.addr_data32[0];
fhk.addrs[ai] = p->dst.addr_data32[0];
@ -232,11 +242,12 @@ static inline uint32_t FlowGetHash(const Packet *p)
fhk.recur = (uint16_t)p->recursion_level;
fhk.vlan_id[0] = p->vlan_id[0] & g_vlan_mask;
fhk.vlan_id[1] = p->vlan_id[1] & g_vlan_mask;
fhk.vlan_id[2] = p->vlan_id[2] & g_vlan_mask;
hash = hashword(fhk.u32, 5, flow_config.hash_rand);
hash = hashword(fhk.u32, ARRAY_SIZE(fhk.u32), flow_config.hash_rand);
}
} else if (p->ip6h != NULL) {
FlowHashKey6 fhk;
FlowHashKey6 fhk = { .pad[0] = 0 };
if (FlowHashRawAddressIPv6GtU32(p->src.addr_data32, p->dst.addr_data32)) {
fhk.src[0] = p->src.addr_data32[0];
fhk.src[1] = p->src.addr_data32[1];
@ -264,8 +275,9 @@ static inline uint32_t FlowGetHash(const Packet *p)
fhk.recur = (uint16_t)p->recursion_level;
fhk.vlan_id[0] = p->vlan_id[0] & g_vlan_mask;
fhk.vlan_id[1] = p->vlan_id[1] & g_vlan_mask;
fhk.vlan_id[2] = p->vlan_id[2] & g_vlan_mask;
hash = hashword(fhk.u32, 11, flow_config.hash_rand);
hash = hashword(fhk.u32, ARRAY_SIZE(fhk.u32), flow_config.hash_rand);
}
return hash;
@ -284,7 +296,9 @@ uint32_t FlowKeyGetHash(FlowKey *fk)
uint32_t hash = 0;
if (fk->src.family == AF_INET) {
FlowHashKey4 fhk;
FlowHashKey4 fhk = {
.pad[0] = 0,
};
int ai = (fk->src.address.address_un_data32[0] > fk->dst.address.address_un_data32[0]);
fhk.addrs[1-ai] = fk->src.address.address_un_data32[0];
fhk.addrs[ai] = fk->dst.address.address_un_data32[0];
@ -297,10 +311,13 @@ uint32_t FlowKeyGetHash(FlowKey *fk)
fhk.recur = (uint16_t)fk->recursion_level;
fhk.vlan_id[0] = fk->vlan_id[0] & g_vlan_mask;
fhk.vlan_id[1] = fk->vlan_id[1] & g_vlan_mask;
fhk.vlan_id[2] = fk->vlan_id[2] & g_vlan_mask;
hash = hashword(fhk.u32, 5, flow_config.hash_rand);
hash = hashword(fhk.u32, ARRAY_SIZE(fhk.u32), flow_config.hash_rand);
} else {
FlowHashKey6 fhk;
FlowHashKey6 fhk = {
.pad[0] = 0,
};
if (FlowHashRawAddressIPv6GtU32(fk->src.address.address_un_data32,
fk->dst.address.address_un_data32)) {
fhk.src[0] = fk->src.address.address_un_data32[0];
@ -329,8 +346,9 @@ uint32_t FlowKeyGetHash(FlowKey *fk)
fhk.recur = (uint16_t)fk->recursion_level;
fhk.vlan_id[0] = fk->vlan_id[0] & g_vlan_mask;
fhk.vlan_id[1] = fk->vlan_id[1] & g_vlan_mask;
fhk.vlan_id[2] = fk->vlan_id[2] & g_vlan_mask;
hash = hashword(fhk.u32, 11, flow_config.hash_rand);
hash = hashword(fhk.u32, ARRAY_SIZE(fhk.u32), flow_config.hash_rand);
}
return hash;
}
@ -355,10 +373,12 @@ static inline bool CmpAddrsAndPorts(const uint32_t src1[4],
src_port1 == dst_port2 && dst_port1 == src_port2);
}
static inline bool CmpVlanIds(const uint16_t vlan_id1[2], const uint16_t vlan_id2[2])
static inline bool CmpVlanIds(
const uint16_t vlan_id1[VLAN_MAX_LAYERS], const uint16_t vlan_id2[VLAN_MAX_LAYERS])
{
return ((vlan_id1[0] ^ vlan_id2[0]) & g_vlan_mask) == 0 &&
((vlan_id1[1] ^ vlan_id2[1]) & g_vlan_mask) == 0;
((vlan_id1[1] ^ vlan_id2[1]) & g_vlan_mask) == 0 &&
((vlan_id1[2] ^ vlan_id2[2]) & g_vlan_mask) == 0;
}
/* Since two or more flows can have the same hash key, we need to compare
@ -993,8 +1013,8 @@ Flow *FlowGetFromFlowKey(FlowKey *key, struct timespec *ttime, const uint32_t ha
return NULL;
}
f->proto = key->proto;
f->vlan_id[0] = key->vlan_id[0];
f->vlan_id[1] = key->vlan_id[1];
memcpy(&f->vlan_id[0], &key->vlan_id[0], sizeof(f->vlan_id));
;
f->src.addr_data32[0] = key->src.addr_data32[0];
f->src.addr_data32[1] = key->src.addr_data32[1];
f->src.addr_data32[2] = key->src.addr_data32[2];

@ -90,8 +90,7 @@ static inline Packet *FlowForceReassemblyPseudoPacketSetup(Packet *p,
p->flags |= PKT_STREAM_EOF;
p->flags |= PKT_HAS_FLOW;
p->flags |= PKT_PSEUDO_STREAM_END;
p->vlan_id[0] = f->vlan_id[0];
p->vlan_id[1] = f->vlan_id[1];
memcpy(&p->vlan_id[0], &f->vlan_id[0], sizeof(p->vlan_id));
p->vlan_idx = f->vlan_idx;
p->livedev = (struct LiveDevice_ *)f->livedev;

@ -150,8 +150,7 @@ void FlowInit(Flow *f, const Packet *p)
f->proto = p->proto;
f->recursion_level = p->recursion_level;
f->vlan_id[0] = p->vlan_id[0];
f->vlan_id[1] = p->vlan_id[1];
memcpy(&f->vlan_id[0], &p->vlan_id[0], sizeof(f->vlan_id));
f->vlan_idx = p->vlan_idx;
f->livedev = p->livedev;

@ -301,7 +301,7 @@ typedef struct FlowKey_
Port sp, dp;
uint8_t proto;
uint8_t recursion_level;
uint16_t vlan_id[2];
uint16_t vlan_id[VLAN_MAX_LAYERS];
} FlowKey;
typedef struct FlowAddress_ {
@ -364,7 +364,7 @@ typedef struct Flow_
};
uint8_t proto;
uint8_t recursion_level;
uint16_t vlan_id[2];
uint16_t vlan_id[VLAN_MAX_LAYERS];
uint8_t vlan_idx;

@ -113,6 +113,9 @@ static JsonBuilder *CreateEveHeaderFromFlow(const Flow *f)
if (f->vlan_idx > 1) {
jb_append_uint(jb, f->vlan_id[1]);
}
if (f->vlan_idx > 2) {
jb_append_uint(jb, f->vlan_id[2]);
}
jb_close(jb);
}

@ -117,6 +117,9 @@ static JsonBuilder *CreateEveHeaderFromNetFlow(const Flow *f, int dir)
if (f->vlan_idx > 1) {
jb_append_uint(js, f->vlan_id[1]);
}
if (f->vlan_idx > 2) {
jb_append_uint(js, f->vlan_id[2]);
}
jb_close(js);
}

@ -836,6 +836,9 @@ JsonBuilder *CreateEveHeader(const Packet *p, enum OutputJsonLogDirection dir,
if (p->vlan_idx > 1) {
jb_append_uint(js, p->vlan_id[1]);
}
if (p->vlan_idx > 2) {
jb_append_uint(js, p->vlan_id[2]);
}
jb_close(js);
}

@ -2209,6 +2209,7 @@ static int AFPBypassCallback(Packet *p)
keys[0]->port16[1] = GET_TCP_DST_PORT(p);
keys[0]->vlan0 = p->vlan_id[0];
keys[0]->vlan1 = p->vlan_id[1];
keys[0]->vlan2 = p->vlan_id[2];
if (IPV4_GET_IPPROTO(p) == IPPROTO_TCP) {
keys[0]->ip_proto = 1;
@ -2234,6 +2235,7 @@ static int AFPBypassCallback(Packet *p)
keys[1]->port16[1] = GET_TCP_SRC_PORT(p);
keys[1]->vlan0 = p->vlan_id[0];
keys[1]->vlan1 = p->vlan_id[1];
keys[1]->vlan2 = p->vlan_id[2];
keys[1]->ip_proto = keys[0]->ip_proto;
if (AFPInsertHalfFlow(p->afp_v.v4_map_fd, keys[1],
@ -2269,6 +2271,7 @@ static int AFPBypassCallback(Packet *p)
keys[0]->port16[1] = GET_TCP_DST_PORT(p);
keys[0]->vlan0 = p->vlan_id[0];
keys[0]->vlan1 = p->vlan_id[1];
keys[0]->vlan2 = p->vlan_id[2];
if (IPV6_GET_NH(p) == IPPROTO_TCP) {
keys[0]->ip_proto = 1;
@ -2296,6 +2299,7 @@ static int AFPBypassCallback(Packet *p)
keys[1]->port16[1] = GET_TCP_SRC_PORT(p);
keys[1]->vlan0 = p->vlan_id[0];
keys[1]->vlan1 = p->vlan_id[1];
keys[1]->vlan2 = p->vlan_id[2];
keys[1]->ip_proto = keys[0]->ip_proto;
if (AFPInsertHalfFlow(p->afp_v.v6_map_fd, keys[1],
@ -2363,6 +2367,7 @@ static int AFPXDPBypassCallback(Packet *p)
keys[0]->port16[1] = htons(p->dp);
keys[0]->vlan0 = p->vlan_id[0];
keys[0]->vlan1 = p->vlan_id[1];
keys[0]->vlan2 = p->vlan_id[2];
if (IPV4_GET_IPPROTO(p) == IPPROTO_TCP) {
keys[0]->ip_proto = 1;
} else {
@ -2387,6 +2392,7 @@ static int AFPXDPBypassCallback(Packet *p)
keys[1]->port16[1] = htons(p->sp);
keys[1]->vlan0 = p->vlan_id[0];
keys[1]->vlan1 = p->vlan_id[1];
keys[1]->vlan2 = p->vlan_id[2];
keys[1]->ip_proto = keys[0]->ip_proto;
if (AFPInsertHalfFlow(p->afp_v.v4_map_fd, keys[1],
p->afp_v.nr_cpus) == 0) {
@ -2420,6 +2426,7 @@ static int AFPXDPBypassCallback(Packet *p)
keys[0]->port16[1] = htons(GET_TCP_DST_PORT(p));
keys[0]->vlan0 = p->vlan_id[0];
keys[0]->vlan1 = p->vlan_id[1];
keys[0]->vlan2 = p->vlan_id[2];
if (IPV6_GET_NH(p) == IPPROTO_TCP) {
keys[0]->ip_proto = 1;
} else {
@ -2446,6 +2453,7 @@ static int AFPXDPBypassCallback(Packet *p)
keys[1]->port16[1] = htons(GET_TCP_SRC_PORT(p));
keys[1]->vlan0 = p->vlan_id[0];
keys[1]->vlan1 = p->vlan_id[1];
keys[1]->vlan2 = p->vlan_id[2];
keys[1]->ip_proto = keys[0]->ip_proto;
if (AFPInsertHalfFlow(p->afp_v.v6_map_fd, keys[1],
p->afp_v.nr_cpus) == 0) {

@ -6504,8 +6504,7 @@ static void StreamTcpPseudoPacketCreateDetectLogFlush(ThreadVars *tv,
np->flags |= PKT_HAS_FLOW;
np->flags |= PKT_IGNORE_CHECKSUM;
np->flags |= PKT_PSEUDO_DETECTLOG_FLUSH;
np->vlan_id[0] = f->vlan_id[0];
np->vlan_id[1] = f->vlan_id[1];
memcpy(&np->vlan_id[0], &f->vlan_id[0], sizeof(np->vlan_id));
np->vlan_idx = f->vlan_idx;
np->livedev = (struct LiveDevice_ *)f->livedev;

@ -751,6 +751,7 @@ static int EBPFForEachFlowV4Table(ThreadVars *th_v, LiveDevice *dev, const char
flow_key.dst.addr_data32[3] = 0;
flow_key.vlan_id[0] = next_key.vlan0;
flow_key.vlan_id[1] = next_key.vlan1;
flow_key.vlan_id[2] = next_key.vlan2;
if (next_key.ip_proto == 1) {
flow_key.proto = IPPROTO_TCP;
} else {
@ -868,6 +869,7 @@ static int EBPFForEachFlowV6Table(ThreadVars *th_v,
}
flow_key.vlan_id[0] = next_key.vlan0;
flow_key.vlan_id[1] = next_key.vlan1;
flow_key.vlan_id[2] = next_key.vlan2;
if (next_key.ip_proto == 1) {
flow_key.proto = IPPROTO_TCP;
} else {

@ -44,6 +44,7 @@ struct flowv4_keys {
__u8 ip_proto:1;
__u16 vlan0:15;
__u16 vlan1;
__u16 vlan2;
};
struct flowv6_keys {
@ -56,6 +57,7 @@ struct flowv6_keys {
__u8 ip_proto:1;
__u16 vlan0:15;
__u16 vlan1;
__u16 vlan2;
};
struct pair {

Loading…
Cancel
Save