Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions etc/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -4204,6 +4204,9 @@
"vlan_qinq": {
"type": "integer"
},
"vlan_qinqinq": {
"type": "integer"
},
"vntag": {
"type": "integer"
},
Expand Down
2 changes: 1 addition & 1 deletion src/decode-erspan.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
16 changes: 4 additions & 12 deletions src/decode-vlan.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (C) 2007-2021 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
Expand Down Expand Up @@ -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);
Expand All @@ -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;
}
Expand All @@ -93,16 +95,6 @@ int DecodeVLAN(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p,
return TM_ECODE_OK;
}

uint16_t DecodeVLANGetId(const Packet *p, uint8_t layer)
{
if (unlikely(layer > 1))
return 0;
if (p->vlan_idx > layer) {
return p->vlan_id[layer];
}
return 0;
}

typedef struct IEEE8021ahHdr_ {
uint32_t flags;
uint8_t c_destination[6];
Expand Down
10 changes: 5 additions & 5 deletions src/decode-vlan.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (C) 2007-2010 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
Expand Down Expand Up @@ -36,10 +36,6 @@ uint16_t DecodeVLANGetId(const struct Packet_ *, uint8_t layer);
#define GET_VLAN_ID(vlanh) ((uint16_t)(SCNtohs((vlanh)->vlan_cfi) & 0x0FFF))
#define GET_VLAN_PROTO(vlanh) ((SCNtohs((vlanh)->protocol)))

/* return vlan id in host byte order */
#define VLAN_GET_ID1(p) DecodeVLANGetId((p), 0)
#define VLAN_GET_ID2(p) DecodeVLANGetId((p), 1)

/** Vlan header struct */
typedef struct VLANHdr_ {
uint16_t vlan_cfi;
Expand All @@ -51,5 +47,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__ */

4 changes: 2 additions & 2 deletions src/decode.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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);
Expand Down
6 changes: 3 additions & 3 deletions src/decode.h
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
48 changes: 23 additions & 25 deletions src/defrag-hash.c
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand All @@ -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;

Expand All @@ -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];
Expand All @@ -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];
Expand All @@ -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;
Expand All @@ -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)
{
Expand All @@ -469,7 +467,7 @@ static inline int DefragTrackerCompare(DefragTracker *t, Packet *p)
* Get a new defrag tracker. We're checking memcap first and will try to make room
* if the memcap is reached.
*
* \retval dt *LOCKED* tracker on succes, NULL on error.
* \retval dt *LOCKED* tracker on success, NULL on error.
*/
static DefragTracker *DefragTrackerGetNew(Packet *p)
{
Expand Down
38 changes: 37 additions & 1 deletion src/defrag.c
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/defrag.h
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand Down
Loading