suricata
detect-vlan.c
Go to the documentation of this file.
1/* Copyright (C) 2024 Open Information Security Foundation
2 *
3 * You can copy, redistribute or modify this Program under the terms of
4 * the GNU General Public License version 2 as published by the Free
5 * Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * version 2 along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include "detect-vlan.h"
19#include "detect-engine-uint.h"
20#include "detect-parse.h"
21#include "rust.h"
22
23static int DetectVlanIdMatch(
24 DetectEngineThreadCtx *det_ctx, Packet *p, const Signature *s, const SigMatchCtx *ctx)
25{
26 const DetectVlanIdData *vdata = (const DetectVlanIdData *)ctx;
27
28 if (p->vlan_idx == 0) {
29 return 0;
30 }
31
32 switch (vdata->layer) {
33 case DETECT_VLAN_ID_ANY:
34 for (int i = 0; i < p->vlan_idx; i++) {
35 if (DetectU16Match(p->vlan_id[i], &vdata->du16)) {
36 return 1;
37 }
38 }
39 return 0;
40 case DETECT_VLAN_ID_ALL:
41 for (int i = 0; i < p->vlan_idx; i++) {
42 if (!DetectU16Match(p->vlan_id[i], &vdata->du16)) {
43 return 0;
44 }
45 }
46 return 1;
47 default:
48 if (vdata->layer < 0) { // Negative layer values for backward indexing.
49 if (((int16_t)p->vlan_idx) + vdata->layer < 0) {
50 return 0;
51 }
52 return DetectU16Match(p->vlan_id[p->vlan_idx + vdata->layer], &vdata->du16);
53 } else {
54 if (p->vlan_idx < vdata->layer) {
55 return 0;
56 }
57 return DetectU16Match(p->vlan_id[vdata->layer], &vdata->du16);
58 }
59 }
60}
61
62static void DetectVlanIdFree(DetectEngineCtx *de_ctx, void *ptr)
63{
64 SCDetectVlanIdFree(ptr);
65}
66
67static int DetectVlanIdSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rawstr)
68{
69 DetectVlanIdData *vdata = SCDetectVlanIdParse(rawstr);
70 if (vdata == NULL) {
71 SCLogError("vlan id invalid %s", rawstr);
72 return -1;
73 }
74
76 de_ctx, s, DETECT_VLAN_ID, (SigMatchCtx *)vdata, DETECT_SM_LIST_MATCH) == NULL) {
77 DetectVlanIdFree(de_ctx, vdata);
78 return -1;
79 }
81
82 return 0;
83}
84
85static void PrefilterPacketVlanIdMatch(DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx)
86{
87 const PrefilterPacketHeaderCtx *ctx = pectx;
88
89 DetectVlanIdData vdata;
90 vdata.du16.mode = ctx->v1.u8[0];
91 vdata.layer = ctx->v1.u8[1];
92 vdata.du16.arg1 = ctx->v1.u16[2];
93 vdata.du16.arg2 = ctx->v1.u16[3];
94
95 if (p->vlan_idx == 0)
96 return;
97
98 if (DetectVlanIdMatch(det_ctx, p, NULL, (const SigMatchCtx *)&vdata)) {
99 PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt);
100 }
101}
102
103static void PrefilterPacketVlanIdSet(PrefilterPacketHeaderValue *v, void *smctx)
104{
105 const DetectVlanIdData *a = smctx;
106 v->u8[0] = a->du16.mode;
107 v->u8[1] = a->layer;
108 v->u16[2] = a->du16.arg1;
109 v->u16[3] = a->du16.arg2;
110}
111
112static bool PrefilterPacketVlanIdCompare(PrefilterPacketHeaderValue v, void *smctx)
113{
114 const DetectVlanIdData *a = smctx;
115 if (v.u8[0] == a->du16.mode && v.u8[1] == a->layer && v.u16[2] == a->du16.arg1 &&
116 v.u16[3] == a->du16.arg2)
117 return true;
118 return false;
119}
120
121static int PrefilterSetupVlanId(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
122{
124 PrefilterPacketVlanIdSet, PrefilterPacketVlanIdCompare, PrefilterPacketVlanIdMatch);
125}
126
127static bool PrefilterVlanIdIsPrefilterable(const Signature *s)
128{
129 return PrefilterIsPrefilterableById(s, DETECT_VLAN_ID);
130}
131
133{
135 sigmatch_table[DETECT_VLAN_ID].desc = "match vlan id";
136 sigmatch_table[DETECT_VLAN_ID].url = "/rules/vlan-keywords.html#vlan-id";
137 sigmatch_table[DETECT_VLAN_ID].Match = DetectVlanIdMatch;
138 sigmatch_table[DETECT_VLAN_ID].Setup = DetectVlanIdSetup;
139 sigmatch_table[DETECT_VLAN_ID].Free = DetectVlanIdFree;
140 sigmatch_table[DETECT_VLAN_ID].SupportsPrefilter = PrefilterVlanIdIsPrefilterable;
141 sigmatch_table[DETECT_VLAN_ID].SetupPrefilter = PrefilterSetupVlanId;
142}
143
144static int DetectVlanLayersMatch(
145 DetectEngineThreadCtx *det_ctx, Packet *p, const Signature *s, const SigMatchCtx *ctx)
146{
147 uint8_t nb = p->vlan_idx;
148
149 const DetectU8Data *du8 = (const DetectU8Data *)ctx;
150 return DetectU8Match(nb, du8);
151}
152
153static void DetectVlanLayersFree(DetectEngineCtx *de_ctx, void *ptr)
154{
155 SCDetectU8Free(ptr);
156}
157
158static int DetectVlanLayersSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rawstr)
159{
160 DetectU8Data *du8 = DetectU8Parse(rawstr);
161
162 if (du8 == NULL) {
163 SCLogError("vlan layers invalid %s", rawstr);
164 return -1;
165 }
166
167 if (du8->arg1 > VLAN_MAX_LAYERS || du8->arg2 > VLAN_MAX_LAYERS) {
168 SCLogError("number of layers out of range %s", rawstr);
169 DetectVlanLayersFree(de_ctx, du8);
170 return -1;
171 }
172
175 DetectVlanLayersFree(de_ctx, du8);
176 return -1;
177 }
179
180 return 0;
181}
182
183static void PrefilterPacketVlanLayersMatch(
184 DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx)
185{
186 const PrefilterPacketHeaderCtx *ctx = pectx;
187
188 DetectU8Data du8;
189 du8.mode = ctx->v1.u8[0];
190 du8.arg1 = ctx->v1.u8[1];
191 du8.arg2 = ctx->v1.u8[2];
192
193 if (DetectVlanLayersMatch(det_ctx, p, NULL, (const SigMatchCtx *)&du8)) {
194 PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt);
195 }
196}
197
198static int PrefilterSetupVlanLayers(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
199{
201 PrefilterPacketU8Set, PrefilterPacketU8Compare, PrefilterPacketVlanLayersMatch);
202}
203
204static bool PrefilterVlanLayersIsPrefilterable(const Signature *s)
205{
206 return PrefilterIsPrefilterableById(s, DETECT_VLAN_LAYERS);
207}
208
210{
211 sigmatch_table[DETECT_VLAN_LAYERS].name = "vlan.layers";
212 sigmatch_table[DETECT_VLAN_LAYERS].desc = "match number of vlan layers";
213 sigmatch_table[DETECT_VLAN_LAYERS].url = "/rules/vlan-keywords.html#vlan-layers";
214 sigmatch_table[DETECT_VLAN_LAYERS].Match = DetectVlanLayersMatch;
215 sigmatch_table[DETECT_VLAN_LAYERS].Setup = DetectVlanLayersSetup;
216 sigmatch_table[DETECT_VLAN_LAYERS].Free = DetectVlanLayersFree;
217 sigmatch_table[DETECT_VLAN_LAYERS].SupportsPrefilter = PrefilterVlanLayersIsPrefilterable;
218 sigmatch_table[DETECT_VLAN_LAYERS].SetupPrefilter = PrefilterSetupVlanLayers;
219}
#define VLAN_MAX_LAYERS
Definition decode-vlan.h:51
int PrefilterSetupPacketHeader(DetectEngineCtx *de_ctx, SigGroupHead *sgh, int sm_type, SignatureMask mask, void(*Set)(PrefilterPacketHeaderValue *v, void *), bool(*Compare)(PrefilterPacketHeaderValue v, void *), void(*Match)(DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx))
@ DETECT_VLAN_LAYERS
DetectUintData_u8 * DetectU8Parse(const char *u8str)
This function is used to parse u8 options passed via some u8 keyword.
int DetectU16Match(const uint16_t parg, const DetectUintData_u16 *du16)
void PrefilterPacketU8Set(PrefilterPacketHeaderValue *v, void *smctx)
int DetectU8Match(const uint8_t parg, const DetectUintData_u8 *du8)
bool PrefilterPacketU8Compare(PrefilterPacketHeaderValue v, void *smctx)
DetectUintData_u8 DetectU8Data
SigMatch * SCSigMatchAppendSMToList(DetectEngineCtx *de_ctx, Signature *s, uint16_t type, SigMatchCtx *ctx, const int list)
Append a SigMatch to the list type.
SigTableElmt * sigmatch_table
void DetectVlanLayersRegister(void)
void DetectVlanIdRegister(void)
#define SIG_FLAG_REQUIRE_PACKET
Definition detect.h:254
#define SIG_MASK_REQUIRE_REAL_PKT
Definition detect.h:316
@ DETECT_SM_LIST_MATCH
Definition detect.h:117
DetectEngineCtx * de_ctx
struct Thresholds ctx
main detection engine ctx
Definition detect.h:932
PrefilterRuleStore pmq
Definition detect.h:1349
uint16_t vlan_id[VLAN_MAX_LAYERS]
Definition decode.h:528
uint8_t vlan_idx
Definition decode.h:529
Container for matching data for a signature group.
Definition detect.h:1629
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition detect.h:351
const char * url
Definition detect.h:1462
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition detect.h:1441
int(* SetupPrefilter)(DetectEngineCtx *de_ctx, struct SigGroupHead_ *sgh)
Definition detect.h:1444
void(* Free)(DetectEngineCtx *, void *)
Definition detect.h:1446
const char * desc
Definition detect.h:1461
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition detect.h:1421
const char * name
Definition detect.h:1459
bool(* SupportsPrefilter)(const Signature *s)
Definition detect.h:1443
Signature container.
Definition detect.h:668
uint32_t flags
Definition detect.h:669
#define SCLogError(...)
Macro used to log ERROR messages.
Definition util-debug.h:267