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