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