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 each flow are assigned to a consistent "
45  "detection thread",
46  RunModeIdsPcapAutoFp, NULL);
48  "Workers pcap live mode, each thread does all"
49  " tasks from acquisition to logging",
50  RunModeIdsPcapWorkers, NULL);
51 }
52 
53 static 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 
62 static void *ParsePcapConfig(const char *iface)
63 {
64  const char *threadsstr = NULL;
65  ConfNode *if_root;
66  ConfNode *if_default = NULL;
67  ConfNode *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 ((ConfGetInt("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 ((ConfGet("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 = ConfGetNode("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 (ConfGetChildValueWithDefault(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 = ConfGetChildValueWithDefault(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 (ConfGetChildValueWithDefault(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 (ConfGetChildValueWithDefault(if_root, if_default, "checksum-checks", &tmpctype) == 1) {
189  if (strcmp(tmpctype, "auto") == 0) {
191  } else if (ConfValIsTrue(tmpctype)) {
193  } else if (ConfValIsFalse(tmpctype)) {
195  } else {
196  SCLogError("Invalid value for checksum-checks for %s", aconf->iface);
197  }
198  }
199 
200  aconf->promisc = LIBPCAP_PROMISC;
201  if (ConfGetChildValueBoolWithDefault(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 (ConfGetChildValueIntWithDefault(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 
219 static 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 
235  TimeModeSetLive();
236 
237  (void)ConfGet("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();
274  TimeModeSetLive();
275 
276  (void) ConfGet("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 
301  TimeModeSetLive();
302 
303  (void) ConfGet("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 }
thread_name_workers
const char * thread_name_workers
Definition: runmodes.c:66
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:321
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
ConfGetChildValueBoolWithDefault
int ConfGetChildValueBoolWithDefault(const ConfNode *base, const ConfNode *dflt, const char *name, int *val)
Definition: conf.c:513
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
ParseSizeStringU64
int ParseSizeStringU64(const char *size, uint64_t *res)
Definition: util-misc.c:190
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:332
util-runmodes.h
thread_name_autofp
const char * thread_name_autofp
Definition: runmodes.c:64
RUNMODE_PCAP_DEV
@ RUNMODE_PCAP_DEV
Definition: runmodes.h:29
CHECKSUM_VALIDATION_DISABLE
@ CHECKSUM_VALIDATION_DISABLE
Definition: decode.h:42
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:461
thread_name_single
const char * thread_name_single
Definition: runmodes.c:65
ConfValIsTrue
int ConfValIsTrue(const char *val)
Check if a value is true.
Definition: conf.c:536
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:52
CHECKSUM_VALIDATION_ENABLE
@ CHECKSUM_VALIDATION_ENABLE
Definition: decode.h:43
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:44
util-device.h
util-debug.h
util-cpu.h
RunModeRegisterNewRunMode
void RunModeRegisterNewRunMode(enum RunModes runmode, const char *name, const char *description, int(*RunModeFunc)(void), int(*RunModeIsIPSEnabled)(void))
Registers a new runmode.
Definition: runmodes.c:465
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:228
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:341
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:268
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:561
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:350
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:295
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:275
output.h
RunModeIdsGetDefaultMode
const char * RunModeIdsGetDefaultMode(void)
Definition: runmode-pcap.c:32