]> git.ipfire.org Git - people/ms/suricata.git/blame - src/runmode-af-packet.c
stream-tcp: add option to accept invalid packets
[people/ms/suricata.git] / src / runmode-af-packet.c
CommitLineData
c78e112e 1/* Copyright (C) 2011,2012 Open Information Security Foundation
c45d8985
EL
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
a6457262
EL
18/**
19 * \ingroup afppacket
20 *
21 * @{
22 */
23
e80b30c0
EL
24/**
25 * \file
26 *
27 * \author Eric Leblond <eric@regit.org>
28 *
29 * AF_PACKET socket runmode
30 *
31 */
32
33
c45d8985 34#include "suricata-common.h"
e80b30c0 35#include "config.h"
c45d8985
EL
36#include "tm-threads.h"
37#include "conf.h"
38#include "runmodes.h"
39#include "runmode-af-packet.h"
40#include "log-httplog.h"
41#include "output.h"
c45d8985
EL
42#include "detect-engine-mpm.h"
43
44#include "alert-fastlog.h"
45#include "alert-prelude.h"
c45d8985
EL
46#include "alert-unified2-alert.h"
47#include "alert-debuglog.h"
48
49#include "util-debug.h"
50#include "util-time.h"
51#include "util-cpu.h"
52#include "util-affinity.h"
871b2189 53#include "util-device.h"
75c875b1 54#include "util-runmodes.h"
56373e5b 55#include "util-ioctl.h"
c45d8985 56
e80b30c0
EL
57#include "source-af-packet.h"
58
8879df80
EL
59extern int max_pending_packets;
60
c174c9d7 61static const char *default_mode_workers = NULL;
c45d8985
EL
62
63const char *RunModeAFPGetDefaultMode(void)
64{
c174c9d7 65 return default_mode_workers;
c45d8985
EL
66}
67
68void RunModeIdsAFPRegister(void)
69{
e80b30c0
EL
70 RunModeRegisterNewRunMode(RUNMODE_AFP_DEV, "single",
71 "Single threaded af-packet mode",
72 RunModeIdsAFPSingle);
beaa909e
EL
73 RunModeRegisterNewRunMode(RUNMODE_AFP_DEV, "workers",
74 "Workers af-packet mode, each thread does all"
75 " tasks from acquisition to logging",
76 RunModeIdsAFPWorkers);
c174c9d7 77 default_mode_workers = "workers";
e80b30c0
EL
78 RunModeRegisterNewRunMode(RUNMODE_AFP_DEV, "autofp",
79 "Multi socket AF_PACKET mode. Packets from "
80 "each flow are assigned to a single detect "
81 "thread.",
82 RunModeIdsAFPAutoFp);
c45d8985
EL
83 return;
84}
85
994bc15c
EL
86
87#ifdef HAVE_AF_PACKET
88
ab1200fb 89static void AFPDerefConfig(void *conf)
45d5c3ca
EL
90{
91 AFPIfaceConfig *pfp = (AFPIfaceConfig *)conf;
92 /* Pcap config is used only once but cost of this low. */
93 if (SC_ATOMIC_SUB(pfp->ref, 1) == 0) {
94 SCFree(pfp);
95 }
96}
97
f89a4219
VJ
98/* if cluster id is not set, assign it automagically, uniq value per
99 * interface. */
100static int cluster_id_auto = 1;
101
fbca1a4e
EL
102/**
103 * \brief extract information from config file
104 *
105 * The returned structure will be freed by the thread init function.
106 * This is thus necessary to or copy the structure before giving it
107 * to thread or to reparse the file for each thread (and thus have
108 * new structure.
109 *
110 * \return a AFPIfaceConfig corresponding to the interface name
111 */
ab1200fb 112static void *ParseAFPConfig(const char *iface)
fbca1a4e 113{
ab1200fb 114 const char *threadsstr = NULL;
fbca1a4e 115 ConfNode *if_root;
4ae27756 116 ConfNode *if_default = NULL;
fbca1a4e 117 ConfNode *af_packet_node;
ab1200fb
VJ
118 const char *tmpclusterid;
119 const char *tmpctype;
120 const char *copymodestr;
fbca1a4e 121 intmax_t value;
67f791e8 122 int boolval;
ab1200fb
VJ
123 const char *bpf_filter = NULL;
124 const char *out_iface = NULL;
3bb40894 125 int cluster_type = PACKET_FANOUT_HASH;
fbca1a4e 126
9f7ba071 127 if (iface == NULL) {
75c875b1
EL
128 return NULL;
129 }
130
9f7ba071
VJ
131 AFPIfaceConfig *aconf = SCCalloc(1, sizeof(*aconf));
132 if (unlikely(aconf == NULL)) {
fbca1a4e
EL
133 return NULL;
134 }
11bdf483 135
fbca1a4e 136 strlcpy(aconf->iface, iface, sizeof(aconf->iface));
9f7ba071 137 aconf->threads = 0;
45d5c3ca 138 SC_ATOMIC_INIT(aconf->ref);
0227a87f 139 (void) SC_ATOMIC_ADD(aconf->ref, 1);
fbca1a4e
EL
140 aconf->buffer_size = 0;
141 aconf->cluster_id = 1;
3bb40894 142 aconf->cluster_type = cluster_type | PACKET_FANOUT_FLAG_DEFRAG;
df7dbe36 143 aconf->promisc = 1;
6062e00c 144 aconf->checksum_mode = CHECKSUM_VALIDATION_KERNEL;
45d5c3ca 145 aconf->DerefFunc = AFPDerefConfig;
f7124b11 146 aconf->flags = AFP_RING_MODE;
f2a6fb8a 147 aconf->bpf_filter = NULL;
662dccd8 148 aconf->out_iface = NULL;
c8b3f441 149 aconf->copy_mode = AFP_COPY_MODE_NONE;
9f7ba071
VJ
150 aconf->block_timeout = 10;
151 aconf->block_size = getpagesize() << AFP_BLOCK_SIZE_DEFAULT_ORDER;
f2a6fb8a
EL
152
153 if (ConfGet("bpf-filter", &bpf_filter) == 1) {
154 if (strlen(bpf_filter) > 0) {
155 aconf->bpf_filter = bpf_filter;
b3bf7a57 156 SCLogConfig("Going to use command-line provided bpf filter '%s'",
f2a6fb8a
EL
157 aconf->bpf_filter);
158 }
159 }
fbca1a4e
EL
160
161 /* Find initial node */
162 af_packet_node = ConfGetNode("af-packet");
163 if (af_packet_node == NULL) {
9f7ba071
VJ
164 SCLogInfo("unable to find af-packet config using default values");
165 goto finalize;
fbca1a4e
EL
166 }
167
aa8e747e 168 if_root = ConfFindDeviceConfig(af_packet_node, iface);
aa8e747e 169 if_default = ConfFindDeviceConfig(af_packet_node, "default");
4ae27756
EL
170
171 if (if_root == NULL && if_default == NULL) {
9f7ba071
VJ
172 SCLogInfo("unable to find af-packet config for "
173 "interface \"%s\" or \"default\", using default values",
fbca1a4e 174 iface);
9f7ba071 175 goto finalize;
fbca1a4e
EL
176 }
177
4ae27756
EL
178 /* If there is no setting for current interface use default one as main iface */
179 if (if_root == NULL) {
180 if_root = if_default;
181 if_default = NULL;
182 }
183
184 if (ConfGetChildValueWithDefault(if_root, if_default, "threads", &threadsstr) != 1) {
c174c9d7 185 aconf->threads = 0;
fbca1a4e
EL
186 } else {
187 if (threadsstr != NULL) {
c174c9d7
VJ
188 if (strcmp(threadsstr, "auto") == 0) {
189 aconf->threads = 0;
190 } else {
191 aconf->threads = (uint8_t)atoi(threadsstr);
192 }
fbca1a4e
EL
193 }
194 }
45d5c3ca 195
4ae27756 196 if (ConfGetChildValueWithDefault(if_root, if_default, "copy-iface", &out_iface) == 1) {
662dccd8
EL
197 if (strlen(out_iface) > 0) {
198 aconf->out_iface = out_iface;
199 }
200 }
201
876b356b 202 if (ConfGetChildValueBoolWithDefault(if_root, if_default, "use-mmap", (int *)&boolval) == 1) {
f7124b11 203 if (!boolval) {
b3bf7a57 204 SCLogConfig("Disabling mmaped capture on iface %s",
876b356b 205 aconf->iface);
f7124b11 206 aconf->flags &= ~(AFP_RING_MODE|AFP_TPACKET_V3);
876b356b 207 }
662dccd8 208 }
876b356b 209
8035d834
EL
210 if (aconf->flags & AFP_RING_MODE) {
211 (void)ConfGetChildValueBoolWithDefault(if_root, if_default,
212 "mmap-locked", (int *)&boolval);
213 if (boolval) {
b3bf7a57 214 SCLogConfig("Enabling locked memory for mmap on iface %s",
bae1b03c 215 aconf->iface);
8035d834
EL
216 aconf->flags |= AFP_MMAP_LOCKED;
217 }
f7124b11
VJ
218
219 if (ConfGetChildValueBoolWithDefault(if_root, if_default,
220 "tpacket-v3", (int *)&boolval) == 1)
221 {
222 if (boolval) {
223 if (strcasecmp(RunmodeGetActive(), "workers") == 0) {
8035d834 224#ifdef HAVE_TPACKET_V3
f7124b11
VJ
225 SCLogConfig("Enabling tpacket v3 capture on iface %s",
226 aconf->iface);
227 aconf->flags |= AFP_TPACKET_V3;
c2d0d938 228#else
f7124b11
VJ
229 SCLogNotice("System too old for tpacket v3 switching to v2");
230 aconf->flags &= ~AFP_TPACKET_V3;
c2d0d938 231#endif
f7124b11
VJ
232 } else {
233 SCLogWarning(SC_ERR_RUNMODE,
234 "tpacket v3 is only implemented for 'workers' runmode."
235 " Switching to tpacket v2.");
236 aconf->flags &= ~AFP_TPACKET_V3;
237 }
8035d834 238 } else {
9f7ba071 239 aconf->flags &= ~AFP_TPACKET_V3;
8035d834
EL
240 }
241 }
f7124b11 242
8035d834
EL
243 (void)ConfGetChildValueBoolWithDefault(if_root, if_default,
244 "use-emergency-flush", (int *)&boolval);
245 if (boolval) {
b3bf7a57 246 SCLogConfig("Enabling ring emergency flush on iface %s",
8035d834
EL
247 aconf->iface);
248 aconf->flags |= AFP_EMERGENCY_MODE;
bae1b03c 249 }
27b5136b
EL
250 }
251
662dccd8 252 aconf->copy_mode = AFP_COPY_MODE_NONE;
4ae27756 253 if (ConfGetChildValueWithDefault(if_root, if_default, "copy-mode", &copymodestr) == 1) {
662dccd8
EL
254 if (aconf->out_iface == NULL) {
255 SCLogInfo("Copy mode activated but no destination"
256 " iface. Disabling feature");
257 } else if (!(aconf->flags & AFP_RING_MODE)) {
258 SCLogInfo("Copy mode activated but use-mmap "
259 "set to no. Disabling feature");
260 } else if (strlen(copymodestr) <= 0) {
261 aconf->out_iface = NULL;
262 } else if (strcmp(copymodestr, "ips") == 0) {
263 SCLogInfo("AF_PACKET IPS mode activated %s->%s",
264 iface,
265 aconf->out_iface);
266 aconf->copy_mode = AFP_COPY_MODE_IPS;
267 } else if (strcmp(copymodestr, "tap") == 0) {
268 SCLogInfo("AF_PACKET TAP mode activated %s->%s",
269 iface,
270 aconf->out_iface);
271 aconf->copy_mode = AFP_COPY_MODE_TAP;
272 } else {
273 SCLogInfo("Invalid mode (not in tap, ips)");
274 }
275 }
276
4ae27756 277 if (ConfGetChildValueWithDefault(if_root, if_default, "cluster-id", &tmpclusterid) != 1) {
f89a4219 278 aconf->cluster_id = (uint16_t)(cluster_id_auto++);
fbca1a4e
EL
279 } else {
280 aconf->cluster_id = (uint16_t)atoi(tmpclusterid);
281 SCLogDebug("Going to use cluster-id %" PRId32, aconf->cluster_id);
282 }
283
4ae27756 284 if (ConfGetChildValueWithDefault(if_root, if_default, "cluster-type", &tmpctype) != 1) {
f89a4219
VJ
285 /* default to our safest choice: flow hashing + defrag enabled */
286 aconf->cluster_type = PACKET_FANOUT_HASH | PACKET_FANOUT_FLAG_DEFRAG;
3bb40894 287 cluster_type = PACKET_FANOUT_HASH;
fbca1a4e 288 } else if (strcmp(tmpctype, "cluster_round_robin") == 0) {
b3bf7a57 289 SCLogConfig("Using round-robin cluster mode for AF_PACKET (iface %s)",
fbca1a4e
EL
290 aconf->iface);
291 aconf->cluster_type = PACKET_FANOUT_LB;
3bb40894 292 cluster_type = PACKET_FANOUT_LB;
fbca1a4e
EL
293 } else if (strcmp(tmpctype, "cluster_flow") == 0) {
294 /* In hash mode, we also ask for defragmentation needed to
295 * compute the hash */
296 uint16_t defrag = 0;
4c6595f4 297 int conf_val = 0;
b3bf7a57 298 SCLogConfig("Using flow cluster mode for AF_PACKET (iface %s)",
fbca1a4e 299 aconf->iface);
4c6595f4
EL
300 ConfGetChildValueBoolWithDefault(if_root, if_default, "defrag", &conf_val);
301 if (conf_val) {
b3bf7a57 302 SCLogConfig("Using defrag kernel functionality for AF_PACKET (iface %s)",
fbca1a4e
EL
303 aconf->iface);
304 defrag = PACKET_FANOUT_FLAG_DEFRAG;
305 }
306 aconf->cluster_type = PACKET_FANOUT_HASH | defrag;
3bb40894 307 cluster_type = PACKET_FANOUT_HASH;
fbca1a4e 308 } else if (strcmp(tmpctype, "cluster_cpu") == 0) {
b3bf7a57 309 SCLogConfig("Using cpu cluster mode for AF_PACKET (iface %s)",
fbca1a4e
EL
310 aconf->iface);
311 aconf->cluster_type = PACKET_FANOUT_CPU;
3bb40894 312 cluster_type = PACKET_FANOUT_CPU;
dc306f3b 313 } else if (strcmp(tmpctype, "cluster_qm") == 0) {
b3bf7a57 314 SCLogConfig("Using queue based cluster mode for AF_PACKET (iface %s)",
dc306f3b
EL
315 aconf->iface);
316 aconf->cluster_type = PACKET_FANOUT_QM;
3bb40894 317 cluster_type = PACKET_FANOUT_QM;
dc306f3b 318 } else if (strcmp(tmpctype, "cluster_random") == 0) {
b3bf7a57 319 SCLogConfig("Using random based cluster mode for AF_PACKET (iface %s)",
dc306f3b
EL
320 aconf->iface);
321 aconf->cluster_type = PACKET_FANOUT_RND;
3bb40894 322 cluster_type = PACKET_FANOUT_RND;
dc306f3b 323 } else if (strcmp(tmpctype, "cluster_rollover") == 0) {
b3bf7a57 324 SCLogConfig("Using rollover based cluster mode for AF_PACKET (iface %s)",
dc306f3b
EL
325 aconf->iface);
326 aconf->cluster_type = PACKET_FANOUT_ROLLOVER;
3bb40894 327 cluster_type = PACKET_FANOUT_ROLLOVER;
dc306f3b 328
fbca1a4e 329 } else {
9f7ba071 330 SCLogWarning(SC_ERR_INVALID_CLUSTER_TYPE,"invalid cluster-type %s",tmpctype);
fbca1a4e
EL
331 }
332
8fde842f
EL
333 int conf_val = 0;
334 ConfGetChildValueBoolWithDefault(if_root, if_default, "rollover", &conf_val);
335 if (conf_val) {
b3bf7a57 336 SCLogConfig("Using rollover kernel functionality for AF_PACKET (iface %s)",
8fde842f
EL
337 aconf->iface);
338 aconf->cluster_type |= PACKET_FANOUT_FLAG_ROLLOVER;
339 }
340
f2a6fb8a
EL
341 /*load af_packet bpf filter*/
342 /* command line value has precedence */
343 if (ConfGet("bpf-filter", &bpf_filter) != 1) {
4ae27756 344 if (ConfGetChildValueWithDefault(if_root, if_default, "bpf-filter", &bpf_filter) == 1) {
f2a6fb8a
EL
345 if (strlen(bpf_filter) > 0) {
346 aconf->bpf_filter = bpf_filter;
b3bf7a57 347 SCLogConfig("Going to use bpf filter %s", aconf->bpf_filter);
f2a6fb8a
EL
348 }
349 }
350 }
351
4ae27756 352 if ((ConfGetChildValueIntWithDefault(if_root, if_default, "buffer-size", &value)) == 1) {
fbca1a4e
EL
353 aconf->buffer_size = value;
354 } else {
355 aconf->buffer_size = 0;
356 }
4ae27756 357 if ((ConfGetChildValueIntWithDefault(if_root, if_default, "ring-size", &value)) == 1) {
8879df80 358 aconf->ring_size = value;
8879df80 359 }
fbca1a4e 360
fa902abe
EL
361 if ((ConfGetChildValueIntWithDefault(if_root, if_default, "block-size", &value)) == 1) {
362 if (value % getpagesize()) {
363 SCLogError(SC_ERR_INVALID_VALUE, "Block-size must be a multiple of pagesize.");
364 } else {
365 aconf->block_size = value;
366 }
367 }
368
234aefdf 369 if ((ConfGetChildValueIntWithDefault(if_root, if_default, "block-timeout", &value)) == 1) {
fa902abe
EL
370 aconf->block_timeout = value;
371 } else {
372 aconf->block_timeout = 10;
373 }
374
4ae27756 375 (void)ConfGetChildValueBoolWithDefault(if_root, if_default, "disable-promisc", (int *)&boolval);
67f791e8 376 if (boolval) {
b3bf7a57 377 SCLogConfig("Disabling promiscuous mode on iface %s",
df7dbe36
EL
378 aconf->iface);
379 aconf->promisc = 0;
380 }
67f791e8 381
4ae27756 382 if (ConfGetChildValueWithDefault(if_root, if_default, "checksum-checks", &tmpctype) == 1) {
6062e00c 383 if (strcmp(tmpctype, "auto") == 0) {
6062e00c 384 aconf->checksum_mode = CHECKSUM_VALIDATION_AUTO;
d18e2f6e 385 } else if (ConfValIsTrue(tmpctype)) {
6062e00c 386 aconf->checksum_mode = CHECKSUM_VALIDATION_ENABLE;
d18e2f6e 387 } else if (ConfValIsFalse(tmpctype)) {
6062e00c
EL
388 aconf->checksum_mode = CHECKSUM_VALIDATION_DISABLE;
389 } else if (strcmp(tmpctype, "kernel") == 0) {
390 aconf->checksum_mode = CHECKSUM_VALIDATION_KERNEL;
391 } else {
392 SCLogError(SC_ERR_INVALID_ARGUMENT, "Invalid value for checksum-checks for %s", aconf->iface);
393 }
394 }
df7dbe36 395
9f7ba071
VJ
396finalize:
397
402bdf9b
VJ
398 /* if the number of threads is not 1, we need to first check if fanout
399 * functions on this system. */
400 if (aconf->threads != 1) {
401 if (AFPIsFanoutSupported() == 0) {
402 if (aconf->threads != 0) {
403 SCLogNotice("fanout not supported on this system, falling "
404 "back to 1 capture thread");
405 }
406 aconf->threads = 1;
407 }
408 }
409
410 /* try to automagically set the proper number of threads */
9f7ba071 411 if (aconf->threads == 0) {
3bb40894
VJ
412 /* for cluster_flow use core count */
413 if (cluster_type == PACKET_FANOUT_HASH) {
414 aconf->threads = (int)UtilCpuGetNumProcessorsOnline();
415 SCLogPerf("%u cores, so using %u threads", aconf->threads, aconf->threads);
416
417 /* for cluster_qm use RSS queue count */
418 } else if (cluster_type == PACKET_FANOUT_QM) {
419 int rss_queues = GetIfaceRSSQueuesNum(iface);
420 if (rss_queues > 0) {
9f7ba071 421 aconf->threads = rss_queues;
3bb40894 422 SCLogPerf("%d RSS queues, so using %u threads", rss_queues, aconf->threads);
9f7ba071
VJ
423 }
424 }
3bb40894 425
4111331a
VJ
426 if (aconf->threads) {
427 SCLogPerf("Using %d AF_PACKET threads for interface %s",
428 aconf->threads, iface);
429 }
9f7ba071
VJ
430 }
431 if (aconf->threads <= 0) {
432 aconf->threads = 1;
433 }
434 SC_ATOMIC_RESET(aconf->ref);
435 (void) SC_ATOMIC_ADD(aconf->ref, aconf->threads);
436
437 if (aconf->ring_size != 0) {
438 if (aconf->ring_size * aconf->threads < max_pending_packets) {
439 aconf->ring_size = max_pending_packets / aconf->threads + 1;
440 SCLogWarning(SC_ERR_AFP_CREATE, "Inefficient setup: ring-size < max_pending_packets. "
441 "Resetting to decent value %d.", aconf->ring_size);
442 /* We want at least that max_pending_packets packets can be handled by the
443 * interface. This is generous if we have multiple interfaces listening. */
444 }
445 } else {
446 /* We want that max_pending_packets packets can be handled by suricata
447 * for this interface. To take burst into account we multiply the obtained
448 * size by 2. */
449 aconf->ring_size = max_pending_packets * 2 / aconf->threads;
450 }
b7bf299e
EL
451
452 int ltype = AFPGetLinkType(iface);
453 switch (ltype) {
454 case LINKTYPE_ETHERNET:
9b80c21d 455 /* af-packet can handle csum offloading */
9d48720f
VJ
456 if (LiveGetOffload() == 0) {
457 if (GetIfaceOffloading(iface, 0, 1) == 1) {
458 SCLogWarning(SC_ERR_AFP_CREATE,
459 "Using AF_PACKET with offloading activated leads to capture problems");
460 }
461 } else {
499e27de 462 DisableIfaceOffloading(LiveGetDevice(iface), 0, 1);
b7bf299e 463 }
9d48720f 464 break;
b7bf299e
EL
465 case -1:
466 default:
467 break;
e951afb9
VJ
468 }
469
bed18678
VJ
470 char *active_runmode = RunmodeGetActive();
471 if (active_runmode && !strcmp("workers", active_runmode)) {
472 aconf->flags |= AFP_ZERO_COPY;
bed18678
VJ
473 } else {
474 /* If we are using copy mode we need a lock */
475 aconf->flags |= AFP_SOCK_PROTECT;
476 }
477
478 /* If we are in RING mode, then we can use ZERO copy
479 * by using the data release mechanism */
480 if (aconf->flags & AFP_RING_MODE) {
481 aconf->flags |= AFP_ZERO_COPY;
9f7ba071
VJ
482 }
483
484 if (aconf->flags & AFP_ZERO_COPY) {
b3bf7a57 485 SCLogConfig("%s: enabling zero copy mode by using data release call", iface);
bed18678
VJ
486 }
487
fbca1a4e
EL
488 return aconf;
489}
490
ab1200fb 491static int AFPConfigGeThreadsCount(void *conf)
75c875b1
EL
492{
493 AFPIfaceConfig *afp = (AFPIfaceConfig *)conf;
494 return afp->threads;
495}
fbca1a4e 496
1e36053e
EL
497int AFPRunModeIsIPS()
498{
499 int nlive = LiveGetDeviceCount();
500 int ldev;
501 ConfNode *if_root;
502 ConfNode *if_default = NULL;
503 ConfNode *af_packet_node;
504 int has_ips = 0;
505 int has_ids = 0;
506
507 /* Find initial node */
508 af_packet_node = ConfGetNode("af-packet");
509 if (af_packet_node == NULL) {
510 return 0;
511 }
512
513 if_default = ConfNodeLookupKeyValue(af_packet_node, "interface", "default");
514
515 for (ldev = 0; ldev < nlive; ldev++) {
5c974f92 516 const char *live_dev = LiveGetDeviceName(ldev);
7cdc5706
VJ
517 if (live_dev == NULL) {
518 SCLogError(SC_ERR_INVALID_VALUE, "Problem with config file");
519 return 0;
520 }
ab1200fb 521 const char *copymodestr = NULL;
aa8e747e 522 if_root = ConfFindDeviceConfig(af_packet_node, live_dev);
1e36053e
EL
523
524 if (if_root == NULL) {
525 if (if_default == NULL) {
526 SCLogError(SC_ERR_INVALID_VALUE, "Problem with config file");
527 return 0;
528 }
529 if_root = if_default;
530 }
531
532 if (ConfGetChildValueWithDefault(if_root, if_default, "copy-mode", &copymodestr) == 1) {
533 if (strcmp(copymodestr, "ips") == 0) {
534 has_ips = 1;
535 } else {
536 has_ids = 1;
537 }
538 } else {
539 has_ids = 1;
540 }
541 }
542
543 if (has_ids && has_ips) {
544 SCLogInfo("AF_PACKET mode using IPS and IDS mode");
545 for (ldev = 0; ldev < nlive; ldev++) {
5c974f92 546 const char *live_dev = LiveGetDeviceName(ldev);
7cdc5706
VJ
547 if (live_dev == NULL) {
548 SCLogError(SC_ERR_INVALID_VALUE, "Problem with config file");
549 return 0;
550 }
1e36053e 551 if_root = ConfNodeLookupKeyValue(af_packet_node, "interface", live_dev);
ab1200fb 552 const char *copymodestr = NULL;
1e36053e
EL
553
554 if (if_root == NULL) {
555 if (if_default == NULL) {
556 SCLogError(SC_ERR_INVALID_VALUE, "Problem with config file");
557 return 0;
558 }
559 if_root = if_default;
560 }
561
562 if (! ((ConfGetChildValueWithDefault(if_root, if_default, "copy-mode", &copymodestr) == 1) &&
563 (strcmp(copymodestr, "ips") == 0))) {
564 SCLogError(SC_ERR_INVALID_ARGUMENT,
565 "AF_PACKET IPS mode used and interface '%s' is in IDS or TAP mode. "
566 "Sniffing '%s' but expect bad result as stream-inline is activated.",
567 live_dev, live_dev);
568 }
569 }
570 }
571
572 return has_ips;
573}
574
994bc15c
EL
575#endif
576
577
38b349af 578int RunModeIdsAFPAutoFp(void)
e80b30c0
EL
579{
580 SCEnter();
581
582/* We include only if AF_PACKET is enabled */
583#ifdef HAVE_AF_PACKET
75c875b1 584 int ret;
ab1200fb 585 const char *live_dev = NULL;
e80b30c0 586
fbca1a4e
EL
587 RunModeInitialize();
588
589 TimeModeSetLive();
590
2179ac25 591 (void)ConfGet("af-packet.live-interface", &live_dev);
fbca1a4e 592
75c875b1 593 SCLogDebug("live_dev %s", live_dev);
e80b30c0 594
662dccd8
EL
595 if (AFPPeersListInit() != TM_ECODE_OK) {
596 SCLogError(SC_ERR_RUNMODE, "Unable to init peers list.");
597 exit(EXIT_FAILURE);
598 }
599
38b349af 600 ret = RunModeSetLiveCaptureAutoFp(ParseAFPConfig,
75c875b1
EL
601 AFPConfigGeThreadsCount,
602 "ReceiveAFP",
41c768ce 603 "DecodeAFP", thread_name_autofp,
75c875b1
EL
604 live_dev);
605 if (ret != 0) {
625a1e07 606 SCLogError(SC_ERR_RUNMODE, "Unable to start runmode");
75c875b1 607 exit(EXIT_FAILURE);
e80b30c0
EL
608 }
609
662dccd8
EL
610 /* In IPS mode each threads must have a peer */
611 if (AFPPeersListCheck() != TM_ECODE_OK) {
612 SCLogError(SC_ERR_RUNMODE, "Some IPS capture threads did not peer.");
613 exit(EXIT_FAILURE);
614 }
e80b30c0 615
86a3f064 616 SCLogDebug("RunModeIdsAFPAutoFp initialised");
e80b30c0
EL
617#endif /* HAVE_AF_PACKET */
618
619 SCReturnInt(0);
620}
621
622/**
623 * \brief Single thread version of the AF_PACKET processing.
624 */
38b349af 625int RunModeIdsAFPSingle(void)
e80b30c0 626{
38b349af 627 SCEnter();
1aab2470
EL
628#ifdef HAVE_AF_PACKET
629 int ret;
ab1200fb 630 const char *live_dev = NULL;
e80b30c0
EL
631
632 RunModeInitialize();
633 TimeModeSetLive();
634
2179ac25 635 (void)ConfGet("af-packet.live-interface", &live_dev);
e80b30c0 636
662dccd8
EL
637 if (AFPPeersListInit() != TM_ECODE_OK) {
638 SCLogError(SC_ERR_RUNMODE, "Unable to init peers list.");
639 exit(EXIT_FAILURE);
640 }
641
38b349af 642 ret = RunModeSetLiveCaptureSingle(ParseAFPConfig,
77869a2d
EL
643 AFPConfigGeThreadsCount,
644 "ReceiveAFP",
41c768ce 645 "DecodeAFP", thread_name_single,
1aab2470
EL
646 live_dev);
647 if (ret != 0) {
625a1e07 648 SCLogError(SC_ERR_RUNMODE, "Unable to start runmode");
e80b30c0
EL
649 exit(EXIT_FAILURE);
650 }
e80b30c0 651
662dccd8
EL
652 /* In IPS mode each threads must have a peer */
653 if (AFPPeersListCheck() != TM_ECODE_OK) {
654 SCLogError(SC_ERR_RUNMODE, "Some IPS capture threads did not peer.");
655 exit(EXIT_FAILURE);
656 }
657
86a3f064 658 SCLogDebug("RunModeIdsAFPSingle initialised");
e80b30c0
EL
659
660#endif /* HAVE_AF_PACKET */
661 SCReturnInt(0);
c45d8985 662}
beaa909e
EL
663
664/**
665 * \brief Workers version of the AF_PACKET processing.
666 *
667 * Start N threads with each thread doing all the work.
668 *
669 */
38b349af 670int RunModeIdsAFPWorkers(void)
beaa909e 671{
38b349af 672 SCEnter();
beaa909e
EL
673#ifdef HAVE_AF_PACKET
674 int ret;
ab1200fb 675 const char *live_dev = NULL;
beaa909e
EL
676
677 RunModeInitialize();
678 TimeModeSetLive();
679
2179ac25 680 (void)ConfGet("af-packet.live-interface", &live_dev);
beaa909e 681
662dccd8
EL
682 if (AFPPeersListInit() != TM_ECODE_OK) {
683 SCLogError(SC_ERR_RUNMODE, "Unable to init peers list.");
684 exit(EXIT_FAILURE);
685 }
686
38b349af 687 ret = RunModeSetLiveCaptureWorkers(ParseAFPConfig,
beaa909e
EL
688 AFPConfigGeThreadsCount,
689 "ReceiveAFP",
41c768ce 690 "DecodeAFP", thread_name_workers,
beaa909e
EL
691 live_dev);
692 if (ret != 0) {
625a1e07 693 SCLogError(SC_ERR_RUNMODE, "Unable to start runmode");
beaa909e
EL
694 exit(EXIT_FAILURE);
695 }
696
662dccd8
EL
697 /* In IPS mode each threads must have a peer */
698 if (AFPPeersListCheck() != TM_ECODE_OK) {
699 SCLogError(SC_ERR_RUNMODE, "Some IPS capture threads did not peer.");
700 exit(EXIT_FAILURE);
701 }
702
86a3f064 703 SCLogDebug("RunModeIdsAFPWorkers initialised");
beaa909e
EL
704
705#endif /* HAVE_AF_PACKET */
706 SCReturnInt(0);
707}
a6457262
EL
708
709/**
710 * @}
711 */