suricata
runmode-pcap.c
Go to the documentation of this file.
1/* Copyright (C) 2007-2022 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 "suricata-common.h"
19#include "runmode-pcap.h"
20#include "runmodes.h"
21#include "output.h"
22
23#include "util-conf.h"
24#include "util-debug.h"
25#include "util-time.h"
26#include "util-cpu.h"
27#include "util-device-private.h"
28#include "util-runmodes.h"
29#include "util-misc.h"
30#include "util-byte.h"
31
32const char *RunModeIdsGetDefaultMode(void)
33{
34 return "autofp";
35}
36
37int RunModeIdsPcapWorkers(void);
38
40{
41 RunModeRegisterNewRunMode(RUNMODE_PCAP_DEV, "single", "Single threaded pcap live mode",
44 "Multi-threaded pcap live mode. Packets from each flow are assigned to a consistent "
45 "detection thread",
48 "Workers pcap live mode, each thread does all"
49 " tasks from acquisition to logging",
51}
52
53static void PcapDerefConfig(void *conf)
54{
55 PcapIfaceConfig *pfp = (PcapIfaceConfig *)conf;
56 /* Pcap config is used only once but cost of this low. */
57 if (SC_ATOMIC_SUB(pfp->ref, 1) == 1) {
58 SCFree(pfp);
59 }
60}
61
62static void *ParsePcapConfig(const char *iface)
63{
64 const char *threadsstr = NULL;
65 SCConfNode *if_root;
66 SCConfNode *if_default = NULL;
67 SCConfNode *pcap_node;
68 PcapIfaceConfig *aconf = SCMalloc(sizeof(*aconf));
69 const char *tmpbpf;
70 const char *tmpctype;
71 intmax_t value;
72 int promisc = 0;
73 intmax_t snaplen = 0;
74
75 if (unlikely(aconf == NULL)) {
76 return NULL;
77 }
78
79 if (iface == NULL) {
80 SCFree(aconf);
81 return NULL;
82 }
83
84 memset(aconf, 0x00, sizeof(*aconf));
85 strlcpy(aconf->iface, iface, sizeof(aconf->iface));
86
87 aconf->buffer_size = 0;
88 /* If set command line option has precedence over config */
89 if ((SCConfGetInt("pcap.buffer-size", &value)) == 1) {
90 if (value >= 0 && value <= INT_MAX) {
91 SCLogInfo("Pcap will use %d buffer size", (int)value);
92 aconf->buffer_size = (int)value;
93 } else {
94 SCLogWarning("pcap.buffer-size "
95 "value of %" PRIiMAX " is invalid. Valid range is "
96 "0-2147483647",
97 value);
98 }
99 }
100
102 aconf->bpf_filter = NULL;
103 if ((SCConfGet("bpf-filter", &tmpbpf)) == 1) {
104 aconf->bpf_filter = tmpbpf;
105 }
106
107 SC_ATOMIC_INIT(aconf->ref);
108 aconf->DerefFunc = PcapDerefConfig;
109 aconf->threads = 1;
110
111 /* Find initial node */
112 pcap_node = SCConfGetNode("pcap");
113 if (pcap_node == NULL) {
114 SCLogInfo("Unable to find pcap config using default value");
115 return aconf;
116 }
117
118 if_root = ConfFindDeviceConfig(pcap_node, iface);
119
120 if_default = ConfFindDeviceConfig(pcap_node, "default");
121
122 if (if_root == NULL && if_default == NULL) {
123 SCLogInfo("Unable to find pcap config for "
124 "interface %s, using default value",
125 iface);
126 return aconf;
127 }
128
129 /* If there is no setting for current interface use default one as main iface */
130 if (if_root == NULL) {
131 if_root = if_default;
132 if_default = NULL;
133 }
134
135 if (SCConfGetChildValueWithDefault(if_root, if_default, "threads", &threadsstr) != 1) {
136 aconf->threads = 1;
137 } else {
138 if (threadsstr != NULL) {
139 if (StringParseInt32(&aconf->threads, 10, 0, (const char *)threadsstr) < 0) {
140 SCLogWarning("Invalid value for "
141 "pcap.threads: %s, resetting to 1",
142 threadsstr);
143 aconf->threads = 1;
144 }
145 }
146 }
147 if (aconf->threads == 0) {
148 aconf->threads = 1;
149 }
150 (void) SC_ATOMIC_ADD(aconf->ref, aconf->threads);
151
152 if (aconf->buffer_size == 0) {
153 const char *s_limit = NULL;
154 int ret;
155 ret = SCConfGetChildValueWithDefault(if_root, if_default, "buffer-size", &s_limit);
156 if (ret == 1 && s_limit) {
157 uint64_t bsize = 0;
158
159 if (ParseSizeStringU64(s_limit, &bsize) < 0) {
160 SCLogError("Failed to parse pcap buffer size: %s", s_limit);
161 } else {
162 /* the string 2gb returns 2147483648 which is 1 to high
163 * for a int. */
164 if (bsize == (uint64_t)((uint64_t)INT_MAX + (uint64_t)1))
165 bsize = (uint64_t)INT_MAX;
166
167 if (bsize > INT_MAX) {
168 SCLogError("Failed to set pcap buffer size: 2gb max. %" PRIu64 " > %d", bsize,
169 INT_MAX);
170 } else {
171 aconf->buffer_size = (int)bsize;
172 }
173 }
174 }
175 }
176
177 if (aconf->bpf_filter == NULL) {
178 /* set bpf filter if we have one */
179 if (SCConfGetChildValueWithDefault(if_root, if_default, "bpf-filter", &tmpbpf) != 1) {
180 SCLogDebug("could not get bpf or none specified");
181 } else {
182 aconf->bpf_filter = tmpbpf;
183 }
184 } else {
185 SCLogInfo("BPF filter set from command line or via old 'bpf-filter' option.");
186 }
187
188 if (SCConfGetChildValueWithDefault(if_root, if_default, "checksum-checks", &tmpctype) == 1) {
189 if (strcmp(tmpctype, "auto") == 0) {
191 } else if (SCConfValIsTrue(tmpctype)) {
193 } else if (SCConfValIsFalse(tmpctype)) {
195 } else {
196 SCLogError("Invalid value for checksum-checks for %s", aconf->iface);
197 }
198 }
199
200 aconf->promisc = LIBPCAP_PROMISC;
201 if (SCConfGetChildValueBoolWithDefault(if_root, if_default, "promisc", &promisc) != 1) {
202 SCLogDebug("could not get promisc or none specified");
203 } else {
204 aconf->promisc = promisc;
205 }
206
207 aconf->snaplen = 0;
208 if (SCConfGetChildValueIntWithDefault(if_root, if_default, "snaplen", &snaplen) != 1) {
209 SCLogDebug("could not get snaplen or none specified");
210 } else if (snaplen < INT_MIN || snaplen > INT_MAX) {
211 SCLogDebug("snaplen value is not in the accepted range");
212 } else {
213 aconf->snaplen = (int)snaplen;
214 }
215
216 return aconf;
217}
218
219static int PcapConfigGeThreadsCount(void *conf)
220{
221 PcapIfaceConfig *pfp = (PcapIfaceConfig *)conf;
222 return pfp->threads;
223}
224
225/**
226 * \brief Single thread version of the Pcap live processing.
227 */
229{
230 int ret;
231 const char *live_dev = NULL;
232
233 SCEnter();
234
236
237 (void)SCConfGet("pcap.single-pcap-dev", &live_dev);
238
239 ret = RunModeSetLiveCaptureSingle(ParsePcapConfig,
240 PcapConfigGeThreadsCount,
241 "ReceivePcap",
242 "DecodePcap", thread_name_single,
243 live_dev);
244 if (ret != 0) {
245 FatalError("Runmode start failed");
246 }
247
248 SCLogDebug("RunModeIdsPcapSingle initialised");
249
250 SCReturnInt(0);
251}
252
253/**
254 * \brief RunModIdsPcapAutoFp set up the following thread packet handlers:
255 * - Receive thread (from pcap device)
256 * - Decode thread
257 * - Stream thread
258 * - Detect: If we have only 1 cpu, it will setup one Detect thread
259 * If we have more than one, it will setup num_cpus - 1
260 * starting from the second cpu available.
261 * - Outputs thread
262 * By default the threads will use the first cpu available
263 * except the Detection threads if we have more than one cpu.
264 *
265 * \retval 0 If all goes well. (If any problem is detected the engine will
266 * exit()).
267 */
269{
270 int ret;
271 const char *live_dev = NULL;
272
273 SCEnter();
275
276 (void)SCConfGet("pcap.single-pcap-dev", &live_dev);
277
278 ret = RunModeSetLiveCaptureAutoFp(ParsePcapConfig, PcapConfigGeThreadsCount, "ReceivePcap",
279 "DecodePcap", thread_name_autofp, live_dev);
280 if (ret != 0) {
281 FatalError("Runmode start failed");
282 }
283
284 SCLogDebug("RunModeIdsPcapAutoFp initialised");
285
286 SCReturnInt(0);
287}
288
289/**
290 * \brief Workers version of the PCAP LIVE processing.
291 *
292 * Start N threads with each thread doing all the work.
293 *
294 */
296{
297 int ret;
298 const char *live_dev = NULL;
299 SCEnter();
300
302
303 (void)SCConfGet("pcap.single-pcap-dev", &live_dev);
304
305 ret = RunModeSetLiveCaptureWorkers(ParsePcapConfig, PcapConfigGeThreadsCount, "ReceivePcap",
306 "DecodePcap", thread_name_workers, live_dev);
307 if (ret != 0) {
308 FatalError("Unable to start runmode");
309 }
310
311 SCLogDebug("RunModeIdsPcapWorkers initialised");
312
313 SCReturnInt(0);
314}
SCConfNode * SCConfGetNode(const char *name)
Get a SCConfNode by name.
Definition conf.c:181
int SCConfValIsTrue(const char *val)
Check if a value is true.
Definition conf.c:551
int SCConfGetChildValueWithDefault(const SCConfNode *base, const SCConfNode *dflt, const char *name, const char **vptr)
Definition conf.c:393
int SCConfGetInt(const char *name, intmax_t *val)
Retrieve a configuration value as an integer.
Definition conf.c:414
int SCConfValIsFalse(const char *val)
Check if a value is false.
Definition conf.c:576
int SCConfGet(const char *name, const char **vptr)
Retrieve the value of a configuration node.
Definition conf.c:350
int SCConfGetChildValueBoolWithDefault(const SCConfNode *base, const SCConfNode *dflt, const char *name, int *val)
Definition conf.c:528
int SCConfGetChildValueIntWithDefault(const SCConfNode *base, const SCConfNode *dflt, const char *name, intmax_t *val)
Definition conf.c:476
@ CHECKSUM_VALIDATION_AUTO
Definition decode.h:45
@ CHECKSUM_VALIDATION_ENABLE
Definition decode.h:44
@ CHECKSUM_VALIDATION_DISABLE
Definition decode.h:43
void RunModeIdsPcapRegister(void)
int RunModeIdsPcapWorkers(void)
Workers version of the PCAP LIVE processing.
int RunModeIdsPcapSingle(void)
Single thread version of the Pcap live processing.
int RunModeIdsPcapAutoFp(void)
RunModIdsPcapAutoFp set up the following thread packet handlers:
const char * RunModeIdsGetDefaultMode(void)
const char * thread_name_single
Definition runmodes.c:67
void RunModeRegisterNewRunMode(enum SCRunModes runmode, const char *name, const char *description, int(*RunModeFunc)(void), int(*RunModeIsIPSEnabled)(void))
Registers a new runmode.
Definition runmodes.c:486
const char * thread_name_autofp
Definition runmodes.c:66
const char * thread_name_workers
Definition runmodes.c:68
@ RUNMODE_PCAP_DEV
Definition runmodes.h:29
#define LIBPCAP_PROMISC
Definition source-pcap.h:32
char iface[PCAP_IFACE_NAME_LENGTH]
Definition source-pcap.h:46
ChecksumValidationMode checksum_mode
Definition source-pcap.h:57
const char * bpf_filter
Definition source-pcap.h:56
void(* DerefFunc)(void *)
Definition source-pcap.h:59
size_t strlcpy(char *dst, const char *src, size_t siz)
#define SC_ATOMIC_ADD(name, val)
add a value to our atomic variable
#define SC_ATOMIC_INIT(name)
wrapper for initializing an atomic variable.
#define SC_ATOMIC_SUB(name, val)
sub a value from our atomic variable
int StringParseInt32(int32_t *res, int base, size_t len, const char *str)
Definition util-byte.c:622
SCConfNode * ConfFindDeviceConfig(SCConfNode *node, const char *iface)
Find the configuration node for a specific device.
Definition util-conf.c:121
#define SCEnter(...)
Definition util-debug.h:277
#define FatalError(...)
Definition util-debug.h:510
#define SCLogDebug(...)
Definition util-debug.h:275
#define SCReturnInt(x)
Definition util-debug.h:281
#define SCLogWarning(...)
Macro used to log WARNING messages.
Definition util-debug.h:255
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition util-debug.h:225
#define SCLogError(...)
Macro used to log ERROR messages.
Definition util-debug.h:267
#define SCMalloc(sz)
Definition util-mem.h:47
#define SCFree(p)
Definition util-mem.h:61
int ParseSizeStringU64(const char *size, uint64_t *res)
Definition util-misc.c:190
#define unlikely(expr)
int RunModeSetLiveCaptureSingle(ConfigIfaceParserFunc ConfigParser, ConfigIfaceThreadsCountFunc ModThreadsCount, const char *recv_mod_name, const char *decode_mod_name, const char *thread_name, const char *live_dev)
int RunModeSetLiveCaptureWorkers(ConfigIfaceParserFunc ConfigParser, ConfigIfaceThreadsCountFunc ModThreadsCount, const char *recv_mod_name, const char *decode_mod_name, const char *thread_name, const char *live_dev)
int RunModeSetLiveCaptureAutoFp(ConfigIfaceParserFunc ConfigParser, ConfigIfaceThreadsCountFunc ModThreadsCount, const char *recv_mod_name, const char *decode_mod_name, const char *thread_name, const char *live_dev)
void TimeModeSetLive(void)
Definition util-time.c:99