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