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 
35 static const char *default_mode = NULL;
36 
37 const char *RunModeIdsGetDefaultMode(void)
38 {
39  return default_mode;
40 }
41 
42 int RunModeIdsPcapWorkers(void);
43 
45 {
47  "Single threaded pcap live mode",
49  default_mode = "autofp";
51  "Multi threaded pcap live mode. Packets from "
52  "each flow are assigned to a single detect thread, "
53  "unlike \"pcap_live_auto\" where packets from "
54  "the same flow can be processed by any detect "
55  "thread",
58  "Workers pcap live mode, each thread does all"
59  " tasks from acquisition to logging",
61 
62  return;
63 }
64 
65 static void PcapDerefConfig(void *conf)
66 {
67  PcapIfaceConfig *pfp = (PcapIfaceConfig *)conf;
68  /* Pcap config is used only once but cost of this low. */
69  if (SC_ATOMIC_SUB(pfp->ref, 1) == 0) {
70  SCFree(pfp);
71  }
72 }
73 
74 static void *ParsePcapConfig(const char *iface)
75 {
76  const char *threadsstr = NULL;
77  ConfNode *if_root;
78  ConfNode *if_default = NULL;
79  ConfNode *pcap_node;
80  PcapIfaceConfig *aconf = SCMalloc(sizeof(*aconf));
81  const char *tmpbpf;
82  const char *tmpctype;
83  intmax_t value;
84  int promisc = 0;
85  intmax_t snaplen = 0;
86 
87  if (unlikely(aconf == NULL)) {
88  return NULL;
89  }
90 
91  if (iface == NULL) {
92  SCFree(aconf);
93  return NULL;
94  }
95 
96  memset(aconf, 0x00, sizeof(*aconf));
97  strlcpy(aconf->iface, iface, sizeof(aconf->iface));
98 
99  aconf->buffer_size = 0;
100  /* If set command line option has precedence over config */
101  if ((ConfGetInt("pcap.buffer-size", &value)) == 1) {
102  if (value >= 0 && value <= INT_MAX) {
103  SCLogInfo("Pcap will use %d buffer size", (int)value);
104  aconf->buffer_size = value;
105  } else {
106  SCLogWarning(SC_ERR_INVALID_ARGUMENT, "pcap.buffer-size "
107  "value of %"PRIiMAX" is invalid. Valid range is "
108  "0-2147483647", value);
109  }
110  }
111 
113  aconf->bpf_filter = NULL;
114  if ((ConfGet("bpf-filter", &tmpbpf)) == 1) {
115  aconf->bpf_filter = tmpbpf;
116  }
117 
118  SC_ATOMIC_INIT(aconf->ref);
119  aconf->DerefFunc = PcapDerefConfig;
120  aconf->threads = 1;
121 
122  /* Find initial node */
123  pcap_node = ConfGetNode("pcap");
124  if (pcap_node == NULL) {
125  SCLogInfo("Unable to find pcap config using default value");
126  return aconf;
127  }
128 
129  if_root = ConfFindDeviceConfig(pcap_node, iface);
130 
131  if_default = ConfFindDeviceConfig(pcap_node, "default");
132 
133  if (if_root == NULL && if_default == NULL) {
134  SCLogInfo("Unable to find pcap config for "
135  "interface %s, using default value",
136  iface);
137  return aconf;
138  }
139 
140  /* If there is no setting for current interface use default one as main iface */
141  if (if_root == NULL) {
142  if_root = if_default;
143  if_default = NULL;
144  }
145 
146  if (ConfGetChildValueWithDefault(if_root, if_default, "threads", &threadsstr) != 1) {
147  aconf->threads = 1;
148  } else {
149  if (threadsstr != NULL) {
150  aconf->threads = atoi(threadsstr);
151  }
152  }
153  if (aconf->threads == 0) {
154  aconf->threads = 1;
155  }
156  (void) SC_ATOMIC_ADD(aconf->ref, aconf->threads);
157 
158  if (aconf->buffer_size == 0) {
159  const char *s_limit = NULL;
160  int ret;
161  ret = ConfGetChildValueWithDefault(if_root, if_default, "buffer-size", &s_limit);
162  if (ret == 1 && s_limit) {
163  uint64_t bsize = 0;
164 
165  if (ParseSizeStringU64(s_limit, &bsize) < 0) {
167  "Failed to parse pcap buffer size: %s",
168  s_limit);
169  } else {
170  /* the string 2gb returns 2147483648 which is 1 to high
171  * for a int. */
172  if (bsize == (uint64_t)((uint64_t)INT_MAX + (uint64_t)1))
173  bsize = (uint64_t)INT_MAX;
174 
175  if (bsize > INT_MAX) {
177  "Failed to set pcap buffer size: 2gb max. %"PRIu64" > %d", bsize, INT_MAX);
178  } else {
179  aconf->buffer_size = (int)bsize;
180  }
181  }
182  }
183  }
184 
185  if (aconf->bpf_filter == NULL) {
186  /* set bpf filter if we have one */
187  if (ConfGetChildValueWithDefault(if_root, if_default, "bpf-filter", &tmpbpf) != 1) {
188  SCLogDebug("could not get bpf or none specified");
189  } else {
190  aconf->bpf_filter = tmpbpf;
191  }
192  } else {
193  SCLogInfo("BPF filter set from command line or via old 'bpf-filter' option.");
194  }
195 
196  if (ConfGetChildValueWithDefault(if_root, if_default, "checksum-checks", &tmpctype) == 1) {
197  if (strcmp(tmpctype, "auto") == 0) {
199  } else if (ConfValIsTrue(tmpctype)) {
201  } else if (ConfValIsFalse(tmpctype)) {
203  } else {
204  SCLogError(SC_ERR_INVALID_ARGUMENT, "Invalid value for checksum-checks for %s", aconf->iface);
205  }
206  }
207 
208  aconf->promisc = LIBPCAP_PROMISC;
209  if (ConfGetChildValueBoolWithDefault(if_root, if_default, "promisc", &promisc) != 1) {
210  SCLogDebug("could not get promisc or none specified");
211  } else {
212  aconf->promisc = promisc;
213  }
214 
215  aconf->snaplen = 0;
216  if (ConfGetChildValueIntWithDefault(if_root, if_default, "snaplen", &snaplen) != 1) {
217  SCLogDebug("could not get snaplen or none specified");
218  } else {
219  aconf->snaplen = snaplen;
220  }
221 
222 
223  return aconf;
224 }
225 
226 static int PcapConfigGeThreadsCount(void *conf)
227 {
228  PcapIfaceConfig *pfp = (PcapIfaceConfig *)conf;
229  return pfp->threads;
230 }
231 
232 /**
233  * \brief Single thread version of the Pcap live processing.
234  */
236 {
237  int ret;
238  const char *live_dev = NULL;
239 
240  SCEnter();
241 
243  TimeModeSetLive();
244 
245  (void)ConfGet("pcap.single-pcap-dev", &live_dev);
246 
247  ret = RunModeSetLiveCaptureSingle(ParsePcapConfig,
248  PcapConfigGeThreadsCount,
249  "ReceivePcap",
250  "DecodePcap", thread_name_single,
251  live_dev);
252  if (ret != 0) {
253  SCLogError(SC_ERR_RUNMODE, "Runmode start failed");
254  exit(EXIT_FAILURE);
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  SCLogError(SC_ERR_RUNMODE, "Runmode start failed");
295  exit(EXIT_FAILURE);
296  }
297 
298  SCLogInfo("RunModeIdsPcapAutoFp initialised");
299 
300  SCReturnInt(0);
301 }
302 
303 /**
304  * \brief Workers version of the PCAP LIVE processing.
305  *
306  * Start N threads with each thread doing all the work.
307  *
308  */
310 {
311  int ret;
312  const char *live_dev = NULL;
313  SCEnter();
314 
316  TimeModeSetLive();
317 
318  (void) ConfGet("pcap.single-pcap-dev", &live_dev);
319 
320  ret = RunModeSetLiveCaptureWorkers(ParsePcapConfig,
321  PcapConfigGeThreadsCount,
322  "ReceivePcap",
323  "DecodePcap", thread_name_workers,
324  live_dev);
325  if (ret != 0) {
326  SCLogError(SC_ERR_RUNMODE, "Unable to start runmode");
327  exit(EXIT_FAILURE);
328  }
329 
330  SCLogInfo("RunModeIdsPcapWorkers initialised");
331 
332  SCReturnInt(0);
333 }
#define SCLogDebug(...)
Definition: util-debug.h:335
const char * bpf_filter
Definition: source-pcap.h:61
void RunModeInitialize(void)
Definition: runmodes.c:912
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: util-strlcpyu.c:43
char iface[PCAP_IFACE_NAME_LENGTH]
Definition: source-pcap.h:51
void RunModeRegisterNewRunMode(int runmode, const char *name, const char *description, int(*RunModeFunc)(void))
Registers a new runmode.
Definition: runmodes.c:426
#define unlikely(expr)
Definition: util-optimize.h:35
const char * thread_name_single
Definition: runmodes.c:62
#define SC_ATOMIC_ADD(name, val)
add a value to our atomic variable
Definition: util-atomic.h:108
void TimeModeSetLive(void)
Definition: util-time.c:82
#define SC_ATOMIC_SUB(name, val)
sub a value from our atomic variable
Definition: util-atomic.h:125
int ConfGet(const char *name, const char **vptr)
Retrieve the value of a configuration node.
Definition: conf.c:331
int ParseSizeStringU64(const char *size, uint64_t *res)
Definition: util-misc.c:203
ChecksumValidationMode checksum_mode
Definition: source-pcap.h:62
void RunModeIdsPcapRegister(void)
Definition: runmode-pcap.c:44
#define SC_ATOMIC_INIT(name)
Initialize the previously declared atomic variable and it&#39;s lock.
Definition: util-atomic.h:82
int RunModeIdsPcapWorkers(void)
Workers version of the PCAP LIVE processing.
Definition: runmode-pcap.c:309
ConfNode * ConfFindDeviceConfig(ConfNode *node, const char *iface)
Find the configuration node for a specific device.
Definition: util-conf.c:81
int RunModeIdsPcapAutoFp(void)
RunModIdsPcapAutoFp set up the following thread packet handlers:
Definition: runmode-pcap.c:277
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:89
const char * RunModeIdsGetDefaultMode(void)
Definition: runmode-pcap.c:37
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:294
int ConfGetChildValueIntWithDefault(const ConfNode *base, const ConfNode *dflt, const char *name, intmax_t *val)
Definition: conf.c:495
void(* DerefFunc)(void *)
Definition: source-pcap.h:64
#define SCEnter(...)
Definition: util-debug.h:337
int ConfValIsFalse(const char *val)
Check if a value is false.
Definition: conf.c:591
#define LIBPCAP_PROMISC
Definition: source-pcap.h:37
#define SCReturnInt(x)
Definition: util-debug.h:341
#define SCLogWarning(err_code,...)
Macro used to log WARNING messages.
Definition: util-debug.h:281
int ConfValIsTrue(const char *val)
Check if a value is true.
Definition: conf.c:566
int RunModeIdsPcapSingle(void)
Single thread version of the Pcap live processing.
Definition: runmode-pcap.c:235
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: conf.h:32
#define SCMalloc(a)
Definition: util-mem.h:174
int ConfGetChildValueWithDefault(const ConfNode *base, const ConfNode *dflt, const char *name, const char **vptr)
Definition: conf.c:416
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:254
#define SCFree(a)
Definition: util-mem.h:236
int ConfGetInt(const char *name, intmax_t *val)
Retrieve a configuration value as an integer.
Definition: conf.c:437
const char * thread_name_autofp
Definition: runmodes.c:61
ConfNode * ConfGetNode(const char *name)
Get a ConfNode by name.
Definition: conf.c:176
int ConfGetChildValueBoolWithDefault(const ConfNode *base, const ConfNode *dflt, const char *name, int *val)
Definition: conf.c:543
int RunModeSetLiveCaptureWorkers(ConfigIfaceParserFunc ConfigParser, ConfigIfaceThreadsCountFunc ModThreadsCount, const char *recv_mod_name, const char *decode_mod_name, const char *thread_name, const char *live_dev)
const char * thread_name_workers
Definition: runmodes.c:63