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 const char *RunModeIdsGetDefaultMode(void)
36 {
37  return "autofp";
38 }
39 
40 int RunModeIdsPcapWorkers(void);
41 
43 {
45  "Single threaded pcap live mode",
48  "Multi threaded pcap live mode. Packets from "
49  "each flow are assigned to a single detect thread, "
50  "unlike \"pcap_live_auto\" where packets from "
51  "the same flow can be processed by any detect "
52  "thread",
55  "Workers pcap live mode, each thread does all"
56  " tasks from acquisition to logging",
58 
59  return;
60 }
61 
62 static void PcapDerefConfig(void *conf)
63 {
64  PcapIfaceConfig *pfp = (PcapIfaceConfig *)conf;
65  /* Pcap config is used only once but cost of this low. */
66  if (SC_ATOMIC_SUB(pfp->ref, 1) == 0) {
67  SCFree(pfp);
68  }
69 }
70 
71 static void *ParsePcapConfig(const char *iface)
72 {
73  const char *threadsstr = NULL;
74  ConfNode *if_root;
75  ConfNode *if_default = NULL;
76  ConfNode *pcap_node;
77  PcapIfaceConfig *aconf = SCMalloc(sizeof(*aconf));
78  const char *tmpbpf;
79  const char *tmpctype;
80  intmax_t value;
81  int promisc = 0;
82  intmax_t snaplen = 0;
83 
84  if (unlikely(aconf == NULL)) {
85  return NULL;
86  }
87 
88  if (iface == NULL) {
89  SCFree(aconf);
90  return NULL;
91  }
92 
93  memset(aconf, 0x00, sizeof(*aconf));
94  strlcpy(aconf->iface, iface, sizeof(aconf->iface));
95 
96  aconf->buffer_size = 0;
97  /* If set command line option has precedence over config */
98  if ((ConfGetInt("pcap.buffer-size", &value)) == 1) {
99  if (value >= 0 && value <= INT_MAX) {
100  SCLogInfo("Pcap will use %d buffer size", (int)value);
101  aconf->buffer_size = value;
102  } else {
103  SCLogWarning(SC_ERR_INVALID_ARGUMENT, "pcap.buffer-size "
104  "value of %"PRIiMAX" is invalid. Valid range is "
105  "0-2147483647", value);
106  }
107  }
108 
110  aconf->bpf_filter = NULL;
111  if ((ConfGet("bpf-filter", &tmpbpf)) == 1) {
112  aconf->bpf_filter = tmpbpf;
113  }
114 
115  SC_ATOMIC_INIT(aconf->ref);
116  aconf->DerefFunc = PcapDerefConfig;
117  aconf->threads = 1;
118 
119  /* Find initial node */
120  pcap_node = ConfGetNode("pcap");
121  if (pcap_node == NULL) {
122  SCLogInfo("Unable to find pcap config using default value");
123  return aconf;
124  }
125 
126  if_root = ConfFindDeviceConfig(pcap_node, iface);
127 
128  if_default = ConfFindDeviceConfig(pcap_node, "default");
129 
130  if (if_root == NULL && if_default == NULL) {
131  SCLogInfo("Unable to find pcap config for "
132  "interface %s, using default value",
133  iface);
134  return aconf;
135  }
136 
137  /* If there is no setting for current interface use default one as main iface */
138  if (if_root == NULL) {
139  if_root = if_default;
140  if_default = NULL;
141  }
142 
143  if (ConfGetChildValueWithDefault(if_root, if_default, "threads", &threadsstr) != 1) {
144  aconf->threads = 1;
145  } else {
146  if (threadsstr != NULL) {
147  aconf->threads = atoi(threadsstr);
148  }
149  }
150  if (aconf->threads == 0) {
151  aconf->threads = 1;
152  }
153  (void) SC_ATOMIC_ADD(aconf->ref, aconf->threads);
154 
155  if (aconf->buffer_size == 0) {
156  const char *s_limit = NULL;
157  int ret;
158  ret = ConfGetChildValueWithDefault(if_root, if_default, "buffer-size", &s_limit);
159  if (ret == 1 && s_limit) {
160  uint64_t bsize = 0;
161 
162  if (ParseSizeStringU64(s_limit, &bsize) < 0) {
164  "Failed to parse pcap buffer size: %s",
165  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) {
174  "Failed to set pcap buffer size: 2gb max. %"PRIu64" > %d", bsize, 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(SC_ERR_INVALID_ARGUMENT, "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 
220  return aconf;
221 }
222 
223 static int PcapConfigGeThreadsCount(void *conf)
224 {
225  PcapIfaceConfig *pfp = (PcapIfaceConfig *)conf;
226  return pfp->threads;
227 }
228 
229 /**
230  * \brief Single thread version of the Pcap live processing.
231  */
233 {
234  int ret;
235  const char *live_dev = NULL;
236 
237  SCEnter();
238 
240  TimeModeSetLive();
241 
242  (void)ConfGet("pcap.single-pcap-dev", &live_dev);
243 
244  ret = RunModeSetLiveCaptureSingle(ParsePcapConfig,
245  PcapConfigGeThreadsCount,
246  "ReceivePcap",
247  "DecodePcap", thread_name_single,
248  live_dev);
249  if (ret != 0) {
250  SCLogError(SC_ERR_RUNMODE, "Runmode start failed");
251  exit(EXIT_FAILURE);
252  }
253 
254  SCLogInfo("RunModeIdsPcapSingle initialised");
255 
256  SCReturnInt(0);
257 }
258 
259 /**
260  * \brief RunModIdsPcapAutoFp set up the following thread packet handlers:
261  * - Receive thread (from pcap device)
262  * - Decode thread
263  * - Stream thread
264  * - Detect: If we have only 1 cpu, it will setup one Detect thread
265  * If we have more than one, it will setup num_cpus - 1
266  * starting from the second cpu available.
267  * - Outputs thread
268  * By default the threads will use the first cpu available
269  * except the Detection threads if we have more than one cpu.
270  *
271  * \retval 0 If all goes well. (If any problem is detected the engine will
272  * exit()).
273  */
275 {
276  int ret;
277  const char *live_dev = NULL;
278 
279  SCEnter();
281  TimeModeSetLive();
282 
283  (void) ConfGet("pcap.single-pcap-dev", &live_dev);
284 
285  ret = RunModeSetLiveCaptureAutoFp(ParsePcapConfig,
286  PcapConfigGeThreadsCount,
287  "ReceivePcap",
288  "DecodePcap", thread_name_autofp,
289  live_dev);
290  if (ret != 0) {
291  SCLogError(SC_ERR_RUNMODE, "Runmode start failed");
292  exit(EXIT_FAILURE);
293  }
294 
295  SCLogInfo("RunModeIdsPcapAutoFp initialised");
296 
297  SCReturnInt(0);
298 }
299 
300 /**
301  * \brief Workers version of the PCAP LIVE processing.
302  *
303  * Start N threads with each thread doing all the work.
304  *
305  */
307 {
308  int ret;
309  const char *live_dev = NULL;
310  SCEnter();
311 
313  TimeModeSetLive();
314 
315  (void) ConfGet("pcap.single-pcap-dev", &live_dev);
316 
317  ret = RunModeSetLiveCaptureWorkers(ParsePcapConfig,
318  PcapConfigGeThreadsCount,
319  "ReceivePcap",
320  "DecodePcap", thread_name_workers,
321  live_dev);
322  if (ret != 0) {
323  SCLogError(SC_ERR_RUNMODE, "Unable to start runmode");
324  exit(EXIT_FAILURE);
325  }
326 
327  SCLogInfo("RunModeIdsPcapWorkers initialised");
328 
329  SCReturnInt(0);
330 }
#define SCLogDebug(...)
Definition: util-debug.h:335
const char * bpf_filter
Definition: source-pcap.h:56
void RunModeInitialize(void)
Definition: runmodes.c:900
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:46
#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:107
void TimeModeSetLive(void)
Definition: util-time.c:90
#define SC_ATOMIC_SUB(name, val)
sub a value from our atomic variable
Definition: util-atomic.h:124
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:57
void RunModeIdsPcapRegister(void)
Definition: runmode-pcap.c:42
#define SC_ATOMIC_INIT(name)
Initialize the previously declared atomic variable and it&#39;s lock.
Definition: util-atomic.h:81
int RunModeIdsPcapWorkers(void)
Workers version of the PCAP LIVE processing.
Definition: runmode-pcap.c:306
ConfNode * ConfFindDeviceConfig(ConfNode *node, const char *iface)
Find the configuration node for a specific device.
Definition: util-conf.c:129
int RunModeIdsPcapAutoFp(void)
RunModIdsPcapAutoFp set up the following thread packet handlers:
Definition: runmode-pcap.c:274
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:35
#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:59
#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:32
#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:232
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:222
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:322
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
void RunModeRegisterNewRunMode(enum RunModes runmode, const char *name, const char *description, int(*RunModeFunc)(void))
Registers a new runmode.
Definition: runmodes.c:419
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