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;
141  sigmatch_table[DETECT_VLAN_ID].SupportsPrefilter = PrefilterVlanIdIsPrefilterable;
142  sigmatch_table[DETECT_VLAN_ID].SetupPrefilter = PrefilterSetupVlanId;
143 }
144 
145 static int DetectVlanLayersMatch(
146  DetectEngineThreadCtx *det_ctx, Packet *p, const Signature *s, const SigMatchCtx *ctx)
147 {
148  uint8_t nb = p->vlan_idx;
149 
150  const DetectU8Data *du8 = (const DetectU8Data *)ctx;
151  return DetectU8Match(nb, du8);
152 }
153 
154 static void DetectVlanLayersFree(DetectEngineCtx *de_ctx, void *ptr)
155 {
156  SCDetectU8Free(ptr);
157 }
158 
159 static int DetectVlanLayersSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rawstr)
160 {
161  DetectU8Data *du8 = DetectU8Parse(rawstr);
162 
163  if (du8 == NULL) {
164  SCLogError("vlan layers invalid %s", rawstr);
165  return -1;
166  }
167 
168  if (du8->arg1 > VLAN_MAX_LAYERS || du8->arg2 > VLAN_MAX_LAYERS) {
169  SCLogError("number of layers out of range %s", rawstr);
170  DetectVlanLayersFree(de_ctx, du8);
171  return -1;
172  }
173 
176  DetectVlanLayersFree(de_ctx, du8);
177  return -1;
178  }
180 
181  return 0;
182 }
183 
184 static void PrefilterPacketVlanLayersMatch(
185  DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx)
186 {
187  const PrefilterPacketHeaderCtx *ctx = pectx;
188 
189  DetectU8Data du8;
190  du8.mode = ctx->v1.u8[0];
191  du8.arg1 = ctx->v1.u8[1];
192  du8.arg2 = ctx->v1.u8[2];
193 
194  if (DetectVlanLayersMatch(det_ctx, p, NULL, (const SigMatchCtx *)&du8)) {
195  PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt);
196  }
197 }
198 
199 static int PrefilterSetupVlanLayers(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
200 {
202  PrefilterPacketU8Set, PrefilterPacketU8Compare, PrefilterPacketVlanLayersMatch);
203 }
204 
205 static bool PrefilterVlanLayersIsPrefilterable(const Signature *s)
206 {
207  return PrefilterIsPrefilterableById(s, DETECT_VLAN_LAYERS);
208 }
209 
211 {
212  sigmatch_table[DETECT_VLAN_LAYERS].name = "vlan.layers";
213  sigmatch_table[DETECT_VLAN_LAYERS].desc = "match number of vlan layers";
214  sigmatch_table[DETECT_VLAN_LAYERS].url = "/rules/vlan-keywords.html#vlan-layers";
215  sigmatch_table[DETECT_VLAN_LAYERS].Match = DetectVlanLayersMatch;
216  sigmatch_table[DETECT_VLAN_LAYERS].Setup = DetectVlanLayersSetup;
217  sigmatch_table[DETECT_VLAN_LAYERS].Free = DetectVlanLayersFree;
218  sigmatch_table[DETECT_VLAN_LAYERS].SupportsPrefilter = PrefilterVlanLayersIsPrefilterable;
219  sigmatch_table[DETECT_VLAN_LAYERS].SetupPrefilter = PrefilterSetupVlanLayers;
221 }
SIGMATCH_INFO_UINT16
#define SIGMATCH_INFO_UINT16
Definition: detect.h:1688
detect-engine-uint.h
SigTableElmt_::url
const char * url
Definition: detect.h:1460
detect-vlan.h
SIG_MASK_REQUIRE_REAL_PKT
#define SIG_MASK_REQUIRE_REAL_PKT
Definition: detect.h:316
SigTableElmt_::desc
const char * desc
Definition: detect.h:1459
sigmatch_table
SigTableElmt * sigmatch_table
Definition: detect-parse.c:79
SigTableElmt_::Free
void(* Free)(DetectEngineCtx *, void *)
Definition: detect.h:1444
SigTableElmt_::name
const char * name
Definition: detect.h:1457
SigGroupHead_
Container for matching data for a signature group.
Definition: detect.h:1627
SigTableElmt_::flags
uint32_t flags
Definition: detect.h:1448
Packet_::vlan_idx
uint8_t vlan_idx
Definition: decode.h:529
DetectEngineThreadCtx_::pmq
PrefilterRuleStore pmq
Definition: detect.h:1347
ctx
struct Thresholds ctx
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:932
DetectVlanLayersRegister
void DetectVlanLayersRegister(void)
Definition: detect-vlan.c:210
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:326
SigTableElmt_::Setup
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1439
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:1442
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:1244
SIGMATCH_INFO_MULTI_UINT
#define SIGMATCH_INFO_MULTI_UINT
Definition: detect.h:1694
SCSigMatchAppendSMToList
SigMatch * SCSigMatchAppendSMToList(DetectEngineCtx *de_ctx, Signature *s, uint16_t type, SigMatchCtx *ctx, const int list)
Append a SigMatch to the list type.
Definition: detect-parse.c:388
DetectU8Data
DetectUintData_u8 DetectU8Data
Definition: detect-engine-uint.h:43
DETECT_SM_LIST_MATCH
@ DETECT_SM_LIST_MATCH
Definition: detect.h:117
PrefilterPacketU8Set
void PrefilterPacketU8Set(PrefilterPacketHeaderValue *v, void *smctx)
Definition: detect-engine-uint.c:90
Signature_::flags
uint32_t flags
Definition: detect.h:669
Packet_
Definition: decode.h:501
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:470
SigTableElmt_::Match
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1419
SigMatchCtx_
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition: detect.h:351
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:271
SigTableElmt_::SupportsPrefilter
bool(* SupportsPrefilter)(const Signature *s)
Definition: detect.h:1441
detect-parse.h
Signature_
Signature container.
Definition: detect.h:668
SIGMATCH_INFO_UINT8
#define SIGMATCH_INFO_UINT8
Definition: detect.h:1686
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:528
DETECT_VLAN_ID
@ DETECT_VLAN_ID
Definition: detect-engine-register.h:325
SIG_FLAG_REQUIRE_PACKET
#define SIG_FLAG_REQUIRE_PACKET
Definition: detect.h:254