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 
23 static 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 
62 static void DetectVlanIdFree(DetectEngineCtx *de_ctx, void *ptr)
63 {
64  SCDetectVlanIdFree(ptr);
65 }
66 
67 static 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 
85 static 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 
103 static 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 
112 static 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 
121 static int PrefilterSetupVlanId(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
122 {
124  PrefilterPacketVlanIdSet, PrefilterPacketVlanIdCompare, PrefilterPacketVlanIdMatch);
125 }
126 
127 static bool PrefilterVlanIdIsPrefilterable(const Signature *s)
128 {
129  return PrefilterIsPrefilterableById(s, DETECT_VLAN_ID);
130 }
131 
133 {
134  sigmatch_table[DETECT_VLAN_ID].name = "vlan.id";
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 
144 static 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 
153 static void DetectVlanLayersFree(DetectEngineCtx *de_ctx, void *ptr)
154 {
155  rs_detect_u8_free(ptr);
156 }
157 
158 static 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  return -1;
170  }
171 
174  DetectVlanLayersFree(de_ctx, du8);
175  return -1;
176  }
178 
179  return 0;
180 }
181 
182 static void PrefilterPacketVlanLayersMatch(
183  DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx)
184 {
185  const PrefilterPacketHeaderCtx *ctx = pectx;
186 
187  DetectU8Data du8;
188  du8.mode = ctx->v1.u8[0];
189  du8.arg1 = ctx->v1.u8[1];
190  du8.arg2 = ctx->v1.u8[2];
191 
192  if (DetectVlanLayersMatch(det_ctx, p, NULL, (const SigMatchCtx *)&du8)) {
193  PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt);
194  }
195 }
196 
197 static int PrefilterSetupVlanLayers(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
198 {
200  PrefilterPacketU8Set, PrefilterPacketU8Compare, PrefilterPacketVlanLayersMatch);
201 }
202 
203 static bool PrefilterVlanLayersIsPrefilterable(const Signature *s)
204 {
205  return PrefilterIsPrefilterableById(s, DETECT_VLAN_LAYERS);
206 }
207 
209 {
210  sigmatch_table[DETECT_VLAN_LAYERS].name = "vlan.layers";
211  sigmatch_table[DETECT_VLAN_LAYERS].desc = "match number of vlan layers";
212  sigmatch_table[DETECT_VLAN_LAYERS].url = "/rules/vlan-keywords.html#vlan-layers";
213  sigmatch_table[DETECT_VLAN_LAYERS].Match = DetectVlanLayersMatch;
214  sigmatch_table[DETECT_VLAN_LAYERS].Setup = DetectVlanLayersSetup;
215  sigmatch_table[DETECT_VLAN_LAYERS].Free = DetectVlanLayersFree;
216  sigmatch_table[DETECT_VLAN_LAYERS].SupportsPrefilter = PrefilterVlanLayersIsPrefilterable;
217  sigmatch_table[DETECT_VLAN_LAYERS].SetupPrefilter = PrefilterSetupVlanLayers;
218 }
detect-engine-uint.h
SigTableElmt_::url
const char * url
Definition: detect.h:1311
detect-vlan.h
SIG_MASK_REQUIRE_REAL_PKT
#define SIG_MASK_REQUIRE_REAL_PKT
Definition: detect.h:306
SigTableElmt_::desc
const char * desc
Definition: detect.h:1310
sigmatch_table
SigTableElmt * sigmatch_table
Definition: detect-parse.c:154
SigTableElmt_::Free
void(* Free)(DetectEngineCtx *, void *)
Definition: detect.h:1298
SigTableElmt_::name
const char * name
Definition: detect.h:1308
SigGroupHead_
Container for matching data for a signature group.
Definition: detect.h:1464
Packet_::vlan_idx
uint8_t vlan_idx
Definition: decode.h:504
DetectEngineThreadCtx_::pmq
PrefilterRuleStore pmq
Definition: detect.h:1204
ctx
struct Thresholds ctx
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:843
DetectVlanLayersRegister
void DetectVlanLayersRegister(void)
Definition: detect-vlan.c:208
PrefilterPacketHeaderValue::u8
uint8_t u8[16]
Definition: detect-engine-prefilter-common.h:24
rust.h
DETECT_VLAN_LAYERS
@ DETECT_VLAN_LAYERS
Definition: detect-engine-register.h:337
SigTableElmt_::Setup
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1293
PrefilterPacketHeaderValue::u16
uint16_t u16[8]
Definition: detect-engine-prefilter-common.h:25
SigTableElmt_::SetupPrefilter
int(* SetupPrefilter)(DetectEngineCtx *de_ctx, struct SigGroupHead_ *sgh)
Definition: detect.h:1296
DetectU8Parse
DetectUintData_u8 * DetectU8Parse(const char *u8str)
This function is used to parse u8 options passed via some u8 keyword.
Definition: detect-engine-uint.c:85
PrefilterPacketHeaderCtx_
Definition: detect-engine-prefilter-common.h:35
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:18
DetectEngineThreadCtx_
Definition: detect.h:1098
DetectU8Data
DetectUintData_u8 DetectU8Data
Definition: detect-engine-uint.h:43
DETECT_SM_LIST_MATCH
@ DETECT_SM_LIST_MATCH
Definition: detect.h:114
PrefilterPacketU8Set
void PrefilterPacketU8Set(PrefilterPacketHeaderValue *v, void *smctx)
Definition: detect-engine-uint.c:90
Signature_::flags
uint32_t flags
Definition: detect.h:604
Packet_
Definition: decode.h:476
PrefilterSetupPacketHeader
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))
Definition: detect-engine-prefilter-common.c:404
SigTableElmt_::Match
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1276
SigMatchCtx_
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition: detect.h:344
DetectU8Match
int DetectU8Match(const uint8_t parg, const DetectUintData_u8 *du8)
Definition: detect-engine-uint.c:71
DetectU16Match
int DetectU16Match(const uint16_t parg, const DetectUintData_u16 *du16)
Definition: detect-engine-uint.c:107
VLAN_MAX_LAYERS
#define VLAN_MAX_LAYERS
Definition: decode-vlan.h:51
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:261
SigTableElmt_::SupportsPrefilter
bool(* SupportsPrefilter)(const Signature *s)
Definition: detect.h:1295
detect-parse.h
Signature_
Signature container.
Definition: detect.h:603
PrefilterPacketU8Compare
bool PrefilterPacketU8Compare(PrefilterPacketHeaderValue v, void *smctx)
Definition: detect-engine-uint.c:98
DetectVlanIdRegister
void DetectVlanIdRegister(void)
Definition: detect-vlan.c:132
PrefilterPacketHeaderValue
Definition: detect-engine-prefilter-common.h:23
Packet_::vlan_id
uint16_t vlan_id[VLAN_MAX_LAYERS]
Definition: decode.h:503
SigMatchAppendSMToList
SigMatch * SigMatchAppendSMToList(DetectEngineCtx *de_ctx, Signature *s, uint16_t type, SigMatchCtx *ctx, const int list)
Append a SigMatch to the list type.
Definition: detect-parse.c:463
DETECT_VLAN_ID
@ DETECT_VLAN_ID
Definition: detect-engine-register.h:336
SIG_FLAG_REQUIRE_PACKET
#define SIG_FLAG_REQUIRE_PACKET
Definition: detect.h:250