]>
Commit | Line | Data |
---|---|---|
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" | |
42 | #include "cuda-packet-batcher.h" | |
c45d8985 EL |
43 | #include "detect-engine-mpm.h" |
44 | ||
45 | #include "alert-fastlog.h" | |
46 | #include "alert-prelude.h" | |
c45d8985 EL |
47 | #include "alert-unified2-alert.h" |
48 | #include "alert-debuglog.h" | |
49 | ||
50 | #include "util-debug.h" | |
51 | #include "util-time.h" | |
52 | #include "util-cpu.h" | |
53 | #include "util-affinity.h" | |
871b2189 | 54 | #include "util-device.h" |
75c875b1 | 55 | #include "util-runmodes.h" |
c45d8985 | 56 | |
e80b30c0 EL |
57 | #include "source-af-packet.h" |
58 | ||
8879df80 EL |
59 | extern int max_pending_packets; |
60 | ||
e80b30c0 EL |
61 | static const char *default_mode_auto = NULL; |
62 | static const char *default_mode_autofp = NULL; | |
c45d8985 EL |
63 | |
64 | const char *RunModeAFPGetDefaultMode(void) | |
65 | { | |
fbca1a4e | 66 | return default_mode_autofp; |
c45d8985 EL |
67 | } |
68 | ||
69 | void RunModeIdsAFPRegister(void) | |
70 | { | |
8d1fe9f2 | 71 | default_mode_auto = "autofp"; |
c45d8985 EL |
72 | RunModeRegisterNewRunMode(RUNMODE_AFP_DEV, "auto", |
73 | "Multi threaded af-packet mode", | |
74 | RunModeIdsAFPAuto); | |
e80b30c0 EL |
75 | RunModeRegisterNewRunMode(RUNMODE_AFP_DEV, "single", |
76 | "Single threaded af-packet mode", | |
77 | RunModeIdsAFPSingle); | |
beaa909e EL |
78 | RunModeRegisterNewRunMode(RUNMODE_AFP_DEV, "workers", |
79 | "Workers af-packet mode, each thread does all" | |
80 | " tasks from acquisition to logging", | |
81 | RunModeIdsAFPWorkers); | |
e80b30c0 EL |
82 | default_mode_autofp = "autofp"; |
83 | RunModeRegisterNewRunMode(RUNMODE_AFP_DEV, "autofp", | |
84 | "Multi socket AF_PACKET mode. Packets from " | |
85 | "each flow are assigned to a single detect " | |
86 | "thread.", | |
87 | RunModeIdsAFPAutoFp); | |
c45d8985 EL |
88 | return; |
89 | } | |
90 | ||
45d5c3ca EL |
91 | void AFPDerefConfig(void *conf) |
92 | { | |
93 | AFPIfaceConfig *pfp = (AFPIfaceConfig *)conf; | |
94 | /* Pcap config is used only once but cost of this low. */ | |
95 | if (SC_ATOMIC_SUB(pfp->ref, 1) == 0) { | |
96 | SCFree(pfp); | |
97 | } | |
98 | } | |
99 | ||
fbca1a4e EL |
100 | /** |
101 | * \brief extract information from config file | |
102 | * | |
103 | * The returned structure will be freed by the thread init function. | |
104 | * This is thus necessary to or copy the structure before giving it | |
105 | * to thread or to reparse the file for each thread (and thus have | |
106 | * new structure. | |
107 | * | |
108 | * \return a AFPIfaceConfig corresponding to the interface name | |
109 | */ | |
75c875b1 | 110 | void *ParseAFPConfig(const char *iface) |
fbca1a4e EL |
111 | { |
112 | char *threadsstr = NULL; | |
113 | ConfNode *if_root; | |
114 | ConfNode *af_packet_node; | |
115 | AFPIfaceConfig *aconf = SCMalloc(sizeof(*aconf)); | |
116 | char *tmpclusterid; | |
117 | char *tmpctype; | |
662dccd8 | 118 | char *copymodestr; |
fbca1a4e | 119 | intmax_t value; |
67f791e8 | 120 | int boolval; |
f2a6fb8a | 121 | char *bpf_filter = NULL; |
662dccd8 | 122 | char *out_iface = NULL; |
fbca1a4e | 123 | |
e176be6f | 124 | if (unlikely(aconf == NULL)) { |
75c875b1 EL |
125 | return NULL; |
126 | } | |
127 | ||
11bdf483 VJ |
128 | if (iface == NULL) { |
129 | SCFree(aconf); | |
fbca1a4e EL |
130 | return NULL; |
131 | } | |
11bdf483 | 132 | |
fbca1a4e EL |
133 | strlcpy(aconf->iface, iface, sizeof(aconf->iface)); |
134 | aconf->threads = 1; | |
45d5c3ca | 135 | SC_ATOMIC_INIT(aconf->ref); |
0227a87f | 136 | (void) SC_ATOMIC_ADD(aconf->ref, 1); |
fbca1a4e EL |
137 | aconf->buffer_size = 0; |
138 | aconf->cluster_id = 1; | |
139 | aconf->cluster_type = PACKET_FANOUT_HASH; | |
df7dbe36 | 140 | aconf->promisc = 1; |
6062e00c | 141 | aconf->checksum_mode = CHECKSUM_VALIDATION_KERNEL; |
45d5c3ca | 142 | aconf->DerefFunc = AFPDerefConfig; |
49b7b00f | 143 | aconf->flags = 0; |
f2a6fb8a | 144 | aconf->bpf_filter = NULL; |
662dccd8 | 145 | aconf->out_iface = NULL; |
f2a6fb8a EL |
146 | |
147 | if (ConfGet("bpf-filter", &bpf_filter) == 1) { | |
148 | if (strlen(bpf_filter) > 0) { | |
149 | aconf->bpf_filter = bpf_filter; | |
150 | SCLogInfo("Going to use command-line provided bpf filter '%s'", | |
151 | aconf->bpf_filter); | |
152 | } | |
153 | } | |
fbca1a4e EL |
154 | |
155 | /* Find initial node */ | |
156 | af_packet_node = ConfGetNode("af-packet"); | |
157 | if (af_packet_node == NULL) { | |
158 | SCLogInfo("Unable to find af-packet config using default value"); | |
159 | return aconf; | |
160 | } | |
161 | ||
162 | if_root = ConfNodeLookupKeyValue(af_packet_node, "interface", iface); | |
163 | if (if_root == NULL) { | |
164 | SCLogInfo("Unable to find af-packet config for " | |
165 | "interface %s, using default value", | |
166 | iface); | |
167 | return aconf; | |
168 | } | |
169 | ||
170 | if (ConfGetChildValue(if_root, "threads", &threadsstr) != 1) { | |
171 | aconf->threads = 1; | |
172 | } else { | |
173 | if (threadsstr != NULL) { | |
174 | aconf->threads = (uint8_t)atoi(threadsstr); | |
175 | } | |
176 | } | |
177 | if (aconf->threads == 0) { | |
178 | aconf->threads = 1; | |
179 | } | |
45d5c3ca | 180 | |
662dccd8 EL |
181 | if (ConfGetChildValue(if_root, "copy-iface", &out_iface) == 1) { |
182 | if (strlen(out_iface) > 0) { | |
183 | aconf->out_iface = out_iface; | |
184 | } | |
185 | } | |
186 | ||
187 | (void)ConfGetChildValueBool(if_root, "use-mmap", (int *)&boolval); | |
188 | if (boolval) { | |
189 | SCLogInfo("Enabling mmaped capture on iface %s", | |
190 | aconf->iface); | |
191 | aconf->flags |= AFP_RING_MODE; | |
192 | } | |
27b5136b EL |
193 | (void)ConfGetChildValueBool(if_root, "use-emergency-flush", (int *)&boolval); |
194 | if (boolval) { | |
195 | SCLogInfo("Enabling ring emergency flush on iface %s", | |
196 | aconf->iface); | |
197 | aconf->flags |= AFP_EMERGENCY_MODE; | |
198 | } | |
199 | ||
662dccd8 EL |
200 | |
201 | aconf->copy_mode = AFP_COPY_MODE_NONE; | |
202 | if (ConfGetChildValue(if_root, "copy-mode", ©modestr) == 1) { | |
203 | if (aconf->out_iface == NULL) { | |
204 | SCLogInfo("Copy mode activated but no destination" | |
205 | " iface. Disabling feature"); | |
206 | } else if (!(aconf->flags & AFP_RING_MODE)) { | |
207 | SCLogInfo("Copy mode activated but use-mmap " | |
208 | "set to no. Disabling feature"); | |
209 | } else if (strlen(copymodestr) <= 0) { | |
210 | aconf->out_iface = NULL; | |
211 | } else if (strcmp(copymodestr, "ips") == 0) { | |
212 | SCLogInfo("AF_PACKET IPS mode activated %s->%s", | |
213 | iface, | |
214 | aconf->out_iface); | |
215 | aconf->copy_mode = AFP_COPY_MODE_IPS; | |
216 | } else if (strcmp(copymodestr, "tap") == 0) { | |
217 | SCLogInfo("AF_PACKET TAP mode activated %s->%s", | |
218 | iface, | |
219 | aconf->out_iface); | |
220 | aconf->copy_mode = AFP_COPY_MODE_TAP; | |
221 | } else { | |
222 | SCLogInfo("Invalid mode (not in tap, ips)"); | |
223 | } | |
224 | } | |
225 | ||
45d5c3ca | 226 | SC_ATOMIC_RESET(aconf->ref); |
0227a87f | 227 | (void) SC_ATOMIC_ADD(aconf->ref, aconf->threads); |
45d5c3ca | 228 | |
fbca1a4e EL |
229 | if (ConfGetChildValue(if_root, "cluster-id", &tmpclusterid) != 1) { |
230 | SCLogError(SC_ERR_INVALID_ARGUMENT,"Could not get cluster-id from config"); | |
231 | } else { | |
232 | aconf->cluster_id = (uint16_t)atoi(tmpclusterid); | |
233 | SCLogDebug("Going to use cluster-id %" PRId32, aconf->cluster_id); | |
234 | } | |
235 | ||
236 | if (ConfGetChildValue(if_root, "cluster-type", &tmpctype) != 1) { | |
623bb38d | 237 | SCLogError(SC_ERR_GET_CLUSTER_TYPE_FAILED,"Could not get cluster-type from config"); |
fbca1a4e EL |
238 | } else if (strcmp(tmpctype, "cluster_round_robin") == 0) { |
239 | SCLogInfo("Using round-robin cluster mode for AF_PACKET (iface %s)", | |
240 | aconf->iface); | |
241 | aconf->cluster_type = PACKET_FANOUT_LB; | |
242 | } else if (strcmp(tmpctype, "cluster_flow") == 0) { | |
243 | /* In hash mode, we also ask for defragmentation needed to | |
244 | * compute the hash */ | |
245 | uint16_t defrag = 0; | |
246 | SCLogInfo("Using flow cluster mode for AF_PACKET (iface %s)", | |
247 | aconf->iface); | |
248 | ConfGetChildValueBool(if_root, "defrag", (int *)&defrag); | |
249 | if (defrag) { | |
0df4c583 | 250 | SCLogInfo("Using defrag kernel functionality for AF_PACKET (iface %s)", |
fbca1a4e EL |
251 | aconf->iface); |
252 | defrag = PACKET_FANOUT_FLAG_DEFRAG; | |
253 | } | |
254 | aconf->cluster_type = PACKET_FANOUT_HASH | defrag; | |
255 | } else if (strcmp(tmpctype, "cluster_cpu") == 0) { | |
256 | SCLogInfo("Using cpu cluster mode for AF_PACKET (iface %s)", | |
257 | aconf->iface); | |
258 | aconf->cluster_type = PACKET_FANOUT_CPU; | |
259 | } else { | |
260 | SCLogError(SC_ERR_INVALID_CLUSTER_TYPE,"invalid cluster-type %s",tmpctype); | |
11bdf483 | 261 | SCFree(aconf); |
fbca1a4e EL |
262 | return NULL; |
263 | } | |
264 | ||
f2a6fb8a EL |
265 | /*load af_packet bpf filter*/ |
266 | /* command line value has precedence */ | |
267 | if (ConfGet("bpf-filter", &bpf_filter) != 1) { | |
268 | if (ConfGetChildValue(if_root, "bpf-filter", &bpf_filter) == 1) { | |
269 | if (strlen(bpf_filter) > 0) { | |
270 | aconf->bpf_filter = bpf_filter; | |
271 | SCLogInfo("Going to use bpf filter %s", aconf->bpf_filter); | |
272 | } | |
273 | } | |
274 | } | |
275 | ||
fbca1a4e EL |
276 | if ((ConfGetChildValueInt(if_root, "buffer-size", &value)) == 1) { |
277 | aconf->buffer_size = value; | |
278 | } else { | |
279 | aconf->buffer_size = 0; | |
280 | } | |
8879df80 EL |
281 | if ((ConfGetChildValueInt(if_root, "ring-size", &value)) == 1) { |
282 | aconf->ring_size = value; | |
283 | if (value * aconf->threads < max_pending_packets) { | |
284 | aconf->ring_size = max_pending_packets / aconf->threads + 1; | |
285 | SCLogWarning(SC_ERR_AFP_CREATE, "Inefficient setup: ring-size < max_pending_packets. " | |
286 | "Resetting to decent value %d.", aconf->ring_size); | |
287 | /* We want at least that max_pending_packets packets can be handled by the | |
288 | * interface. This is generous if we have multiple interfaces listening. */ | |
289 | } | |
290 | } else { | |
291 | /* We want that max_pending_packets packets can be handled by suricata | |
292 | * for this interface. To take burst into account we multiply the obtained | |
293 | * size by 2. */ | |
294 | aconf->ring_size = max_pending_packets * 2 / aconf->threads; | |
295 | } | |
fbca1a4e | 296 | |
2179ac25 | 297 | (void)ConfGetChildValueBool(if_root, "disable-promisc", (int *)&boolval); |
67f791e8 | 298 | if (boolval) { |
df7dbe36 EL |
299 | SCLogInfo("Disabling promiscuous mode on iface %s", |
300 | aconf->iface); | |
301 | aconf->promisc = 0; | |
302 | } | |
67f791e8 | 303 | |
d24b3a0e | 304 | if (ConfGetChildValue(if_root, "checksum-checks", &tmpctype) == 1) { |
6062e00c | 305 | if (strcmp(tmpctype, "auto") == 0) { |
6062e00c | 306 | aconf->checksum_mode = CHECKSUM_VALIDATION_AUTO; |
6062e00c EL |
307 | } else if (strcmp(tmpctype, "yes") == 0) { |
308 | aconf->checksum_mode = CHECKSUM_VALIDATION_ENABLE; | |
309 | } else if (strcmp(tmpctype, "no") == 0) { | |
310 | aconf->checksum_mode = CHECKSUM_VALIDATION_DISABLE; | |
311 | } else if (strcmp(tmpctype, "kernel") == 0) { | |
312 | aconf->checksum_mode = CHECKSUM_VALIDATION_KERNEL; | |
313 | } else { | |
314 | SCLogError(SC_ERR_INVALID_ARGUMENT, "Invalid value for checksum-checks for %s", aconf->iface); | |
315 | } | |
316 | } | |
df7dbe36 | 317 | |
fbca1a4e EL |
318 | return aconf; |
319 | } | |
320 | ||
75c875b1 EL |
321 | int AFPConfigGeThreadsCount(void *conf) |
322 | { | |
323 | AFPIfaceConfig *afp = (AFPIfaceConfig *)conf; | |
324 | return afp->threads; | |
325 | } | |
fbca1a4e | 326 | |
c45d8985 EL |
327 | /** |
328 | * \brief RunModeIdsAFPAuto set up the following thread packet handlers: | |
e80b30c0 | 329 | * - Receive thread (from live iface) |
c45d8985 EL |
330 | * - Decode thread |
331 | * - Stream thread | |
332 | * - Detect: If we have only 1 cpu, it will setup one Detect thread | |
333 | * If we have more than one, it will setup num_cpus - 1 | |
334 | * starting from the second cpu available. | |
335 | * - Respond/Reject thread | |
336 | * - Outputs thread | |
337 | * By default the threads will use the first cpu available | |
338 | * except the Detection threads if we have more than one cpu. | |
339 | * | |
340 | * \param de_ctx Pointer to the Detection Engine. | |
341 | * | |
342 | * \retval 0 If all goes well. (If any problem is detected the engine will | |
343 | * exit()). | |
344 | */ | |
345 | int RunModeIdsAFPAuto(DetectEngineCtx *de_ctx) | |
346 | { | |
347 | SCEnter(); | |
e80b30c0 EL |
348 | |
349 | #ifdef HAVE_AF_PACKET | |
75c875b1 EL |
350 | int ret; |
351 | char *live_dev = NULL; | |
c45d8985 EL |
352 | |
353 | RunModeInitialize(); | |
c45d8985 | 354 | |
75c875b1 | 355 | TimeModeSetLive(); |
c45d8985 | 356 | |
2179ac25 | 357 | (void)ConfGet("af-packet.live-interface", &live_dev); |
c45d8985 | 358 | |
662dccd8 EL |
359 | if (AFPPeersListInit() != TM_ECODE_OK) { |
360 | SCLogError(SC_ERR_RUNMODE, "Unable to init peers list."); | |
361 | exit(EXIT_FAILURE); | |
362 | } | |
363 | ||
75c875b1 | 364 | ret = RunModeSetLiveCaptureAuto(de_ctx, |
6c55af84 EL |
365 | ParseAFPConfig, |
366 | AFPConfigGeThreadsCount, | |
367 | "ReceiveAFP", | |
75c875b1 EL |
368 | "DecodeAFP", "RecvAFP", |
369 | live_dev); | |
370 | if (ret != 0) { | |
625a1e07 | 371 | SCLogError(SC_ERR_RUNMODE, "Unable to start runmode"); |
c45d8985 EL |
372 | exit(EXIT_FAILURE); |
373 | } | |
374 | ||
662dccd8 EL |
375 | /* In IPS mode each threads must have a peer */ |
376 | if (AFPPeersListCheck() != TM_ECODE_OK) { | |
377 | SCLogError(SC_ERR_RUNMODE, "Some IPS capture threads did not peer."); | |
378 | exit(EXIT_FAILURE); | |
379 | } | |
380 | ||
75c875b1 | 381 | SCLogInfo("RunModeIdsAFPAuto initialised"); |
e80b30c0 EL |
382 | #endif |
383 | SCReturnInt(0); | |
384 | } | |
385 | ||
386 | int RunModeIdsAFPAutoFp(DetectEngineCtx *de_ctx) | |
387 | { | |
388 | SCEnter(); | |
389 | ||
390 | /* We include only if AF_PACKET is enabled */ | |
391 | #ifdef HAVE_AF_PACKET | |
75c875b1 | 392 | int ret; |
e80b30c0 | 393 | char *live_dev = NULL; |
e80b30c0 | 394 | |
fbca1a4e EL |
395 | RunModeInitialize(); |
396 | ||
397 | TimeModeSetLive(); | |
398 | ||
2179ac25 | 399 | (void)ConfGet("af-packet.live-interface", &live_dev); |
fbca1a4e | 400 | |
75c875b1 | 401 | SCLogDebug("live_dev %s", live_dev); |
e80b30c0 | 402 | |
662dccd8 EL |
403 | if (AFPPeersListInit() != TM_ECODE_OK) { |
404 | SCLogError(SC_ERR_RUNMODE, "Unable to init peers list."); | |
405 | exit(EXIT_FAILURE); | |
406 | } | |
407 | ||
75c875b1 EL |
408 | ret = RunModeSetLiveCaptureAutoFp(de_ctx, |
409 | ParseAFPConfig, | |
410 | AFPConfigGeThreadsCount, | |
411 | "ReceiveAFP", | |
412 | "DecodeAFP", "RxAFP", | |
413 | live_dev); | |
414 | if (ret != 0) { | |
625a1e07 | 415 | SCLogError(SC_ERR_RUNMODE, "Unable to start runmode"); |
75c875b1 | 416 | exit(EXIT_FAILURE); |
e80b30c0 EL |
417 | } |
418 | ||
662dccd8 EL |
419 | /* In IPS mode each threads must have a peer */ |
420 | if (AFPPeersListCheck() != TM_ECODE_OK) { | |
421 | SCLogError(SC_ERR_RUNMODE, "Some IPS capture threads did not peer."); | |
422 | exit(EXIT_FAILURE); | |
423 | } | |
e80b30c0 | 424 | |
662dccd8 | 425 | SCLogInfo("RunModeIdsAFPAutoFp initialised"); |
e80b30c0 EL |
426 | #endif /* HAVE_AF_PACKET */ |
427 | ||
428 | SCReturnInt(0); | |
429 | } | |
430 | ||
431 | /** | |
432 | * \brief Single thread version of the AF_PACKET processing. | |
433 | */ | |
434 | int RunModeIdsAFPSingle(DetectEngineCtx *de_ctx) | |
435 | { | |
1aab2470 EL |
436 | #ifdef HAVE_AF_PACKET |
437 | int ret; | |
438 | char *live_dev = NULL; | |
439 | #endif | |
3801e004 AS |
440 | SCEnter(); |
441 | #ifdef HAVE_AF_PACKET | |
e80b30c0 EL |
442 | |
443 | RunModeInitialize(); | |
444 | TimeModeSetLive(); | |
445 | ||
2179ac25 | 446 | (void)ConfGet("af-packet.live-interface", &live_dev); |
e80b30c0 | 447 | |
662dccd8 EL |
448 | if (AFPPeersListInit() != TM_ECODE_OK) { |
449 | SCLogError(SC_ERR_RUNMODE, "Unable to init peers list."); | |
450 | exit(EXIT_FAILURE); | |
451 | } | |
452 | ||
1aab2470 | 453 | ret = RunModeSetLiveCaptureSingle(de_ctx, |
77869a2d EL |
454 | ParseAFPConfig, |
455 | AFPConfigGeThreadsCount, | |
456 | "ReceiveAFP", | |
1aab2470 EL |
457 | "DecodeAFP", "AFPacket", |
458 | live_dev); | |
459 | if (ret != 0) { | |
625a1e07 | 460 | SCLogError(SC_ERR_RUNMODE, "Unable to start runmode"); |
e80b30c0 EL |
461 | exit(EXIT_FAILURE); |
462 | } | |
e80b30c0 | 463 | |
662dccd8 EL |
464 | /* In IPS mode each threads must have a peer */ |
465 | if (AFPPeersListCheck() != TM_ECODE_OK) { | |
466 | SCLogError(SC_ERR_RUNMODE, "Some IPS capture threads did not peer."); | |
467 | exit(EXIT_FAILURE); | |
468 | } | |
469 | ||
1aab2470 | 470 | SCLogInfo("RunModeIdsAFPSingle initialised"); |
e80b30c0 EL |
471 | |
472 | #endif /* HAVE_AF_PACKET */ | |
473 | SCReturnInt(0); | |
c45d8985 | 474 | } |
beaa909e EL |
475 | |
476 | /** | |
477 | * \brief Workers version of the AF_PACKET processing. | |
478 | * | |
479 | * Start N threads with each thread doing all the work. | |
480 | * | |
481 | */ | |
482 | int RunModeIdsAFPWorkers(DetectEngineCtx *de_ctx) | |
483 | { | |
484 | #ifdef HAVE_AF_PACKET | |
485 | int ret; | |
486 | char *live_dev = NULL; | |
487 | #endif | |
488 | SCEnter(); | |
489 | #ifdef HAVE_AF_PACKET | |
490 | ||
491 | RunModeInitialize(); | |
492 | TimeModeSetLive(); | |
493 | ||
2179ac25 | 494 | (void)ConfGet("af-packet.live-interface", &live_dev); |
beaa909e | 495 | |
662dccd8 EL |
496 | if (AFPPeersListInit() != TM_ECODE_OK) { |
497 | SCLogError(SC_ERR_RUNMODE, "Unable to init peers list."); | |
498 | exit(EXIT_FAILURE); | |
499 | } | |
500 | ||
beaa909e EL |
501 | ret = RunModeSetLiveCaptureWorkers(de_ctx, |
502 | ParseAFPConfig, | |
503 | AFPConfigGeThreadsCount, | |
504 | "ReceiveAFP", | |
505 | "DecodeAFP", "AFPacket", | |
506 | live_dev); | |
507 | if (ret != 0) { | |
625a1e07 | 508 | SCLogError(SC_ERR_RUNMODE, "Unable to start runmode"); |
beaa909e EL |
509 | exit(EXIT_FAILURE); |
510 | } | |
511 | ||
662dccd8 EL |
512 | /* In IPS mode each threads must have a peer */ |
513 | if (AFPPeersListCheck() != TM_ECODE_OK) { | |
514 | SCLogError(SC_ERR_RUNMODE, "Some IPS capture threads did not peer."); | |
515 | exit(EXIT_FAILURE); | |
516 | } | |
517 | ||
1ea80952 | 518 | SCLogInfo("RunModeIdsAFPWorkers initialised"); |
beaa909e EL |
519 | |
520 | #endif /* HAVE_AF_PACKET */ | |
521 | SCReturnInt(0); | |
522 | } | |
a6457262 EL |
523 | |
524 | /** | |
525 | * @} | |
526 | */ |