1 /* Copyright (C) 2007-2020 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 /**
19  * \file
20  *
21  * \author Victor Julien <victor@inliniac.net>
22  */
23 
24 #include "suricata-common.h"
25 
26 #if HAVE_GETOPT_H
27 #include <getopt.h>
28 #endif
29 
30 #if HAVE_SIGNAL_H
31 #include <signal.h>
32 #endif
33 
34 #ifdef HAVE_NSS
35 #include <prinit.h>
36 #include <nss.h>
37 #endif
38 
39 #include "suricata.h"
40 #include "decode.h"
41 #include "feature.h"
42 #include "detect.h"
43 #include "packet-queue.h"
44 #include "threads.h"
45 #include "threadvars.h"
46 #include "flow-worker.h"
47 
48 #include "util-atomic.h"
49 #include "util-spm.h"
50 #include "util-cpu.h"
51 #include "util-action.h"
52 #include "util-pidfile.h"
53 #include "util-ioctl.h"
54 #include "util-device.h"
55 #include "util-misc.h"
56 #include "util-running-modes.h"
57 
58 #include "detect-engine.h"
59 #include "detect-parse.h"
60 #include "detect-fast-pattern.h"
61 #include "detect-engine-tag.h"
62 #include "detect-engine-threshold.h"
63 #include "detect-engine-address.h"
64 #include "detect-engine-port.h"
65 #include "detect-engine-mpm.h"
66 
67 #include "tm-queuehandlers.h"
68 #include "tm-queues.h"
69 #include "tm-threads.h"
70 
71 #include "tmqh-flow.h"
72 
73 #include "conf.h"
74 #include "conf-yaml-loader.h"
75 
76 #include "datasets.h"
77 
78 #include "stream-tcp.h"
79 
80 #include "source-nfq.h"
81 #include "source-nfq-prototypes.h"
82 
83 #include "source-nflog.h"
84 
85 #include "source-ipfw.h"
86 
87 #include "source-pcap.h"
88 #include "source-pcap-file.h"
89 
90 #include "source-pfring.h"
91 
92 #include "source-erf-file.h"
93 #include "source-erf-dag.h"
94 #include "source-napatech.h"
95 
96 #include "source-af-packet.h"
97 #include "source-netmap.h"
98 
99 #include "source-windivert.h"
100 #include "source-windivert-prototypes.h"
101 
102 #include "respond-reject.h"
103 
104 #include "flow.h"
105 #include "flow-timeout.h"
106 #include "flow-manager.h"
107 #include "flow-bypass.h"
108 #include "flow-var.h"
109 #include "flow-bit.h"
110 #include "pkt-var.h"
111 #include "host-bit.h"
112 
113 #include "ippair.h"
114 #include "ippair-bit.h"
115 
116 #include "host.h"
117 #include "unix-manager.h"
118 
119 #include "app-layer.h"
120 #include "app-layer-parser.h"
121 #include "app-layer-htp.h"
122 #include "app-layer-ssl.h"
123 #include "app-layer-ssh.h"
124 #include "app-layer-ftp.h"
125 #include "app-layer-smtp.h"
126 #include "app-layer-modbus.h"
127 #include "app-layer-enip.h"
128 #include "app-layer-dnp3.h"
129 #include "app-layer-smb.h"
130 #include "app-layer-dcerpc.h"
131 
132 #include "output-filestore.h"
133 
134 #include "util-ebpf.h"
135 #include "util-radix-tree.h"
136 #include "util-host-os-info.h"
137 #include "util-cidr.h"
138 #include "util-unittest.h"
139 #include "util-unittest-helper.h"
140 #include "util-time.h"
141 #include "util-rule-vars.h"
142 #include "util-classification-config.h"
143 #include "util-threshold-config.h"
144 #include "util-reference-config.h"
145 #include "util-profiling.h"
146 #include "util-magic.h"
147 #include "util-signal.h"
148 
149 #include "util-coredump-config.h"
150 
151 #include "util-decode-mime.h"
152 
153 #include "defrag.h"
154 
155 #include "runmodes.h"
156 #include "runmode-unittests.h"
157 
158 #include "util-debug.h"
159 #include "util-error.h"
160 #include "util-daemon.h"
161 #include "util-byte.h"
162 #include "reputation.h"
163 
164 #include "output.h"
165 
166 #include "util-privs.h"
167 
168 #include "tmqh-packetpool.h"
169 
170 #include "util-proto-name.h"
171 #include "util-mpm-hs.h"
172 #include "util-storage.h"
173 #include "host-storage.h"
174 
175 #include "util-lua.h"
176 
177 #include "util-plugin.h"
178 
179 #include "rust.h"
180 
181 /*
182  * we put this here, because we only use it here in main.
183  */
184 volatile sig_atomic_t sigint_count = 0;
185 volatile sig_atomic_t sighup_count = 0;
186 volatile sig_atomic_t sigterm_count = 0;
187 volatile sig_atomic_t sigusr2_count = 0;
188 
189 /*
190  * Flag to indicate if the engine is at the initialization
191  * or already processing packets. 3 stages: SURICATA_INIT,
192  * SURICATA_RUNTIME and SURICATA_FINALIZE
193  */
194 SC_ATOMIC_DECLARE(unsigned int, engine_stage);
195 
196 /* Max packets processed simultaniously per thread. */
197 #define DEFAULT_MAX_PENDING_PACKETS 1024
198 
199 /** suricata engine control flags */
200 volatile uint8_t suricata_ctl_flags = 0;
201 
202 /** Run mode selected */
203 int run_mode = RUNMODE_UNKNOWN;
204 
205 /** Engine mode: inline (ENGINE_MODE_IPS) or just
206   * detection mode (ENGINE_MODE_IDS by default) */
207 static enum EngineMode g_engine_mode = ENGINE_MODE_IDS;
208 
209 /** Host mode: set if box is sniffing only
210  * or is a router */
211 uint8_t host_mode = SURI_HOST_IS_SNIFFER_ONLY;
212 
213 /** Maximum packets to simultaneously process. */
214 intmax_t max_pending_packets;
215 
216 /** global indicating if detection is enabled */
217 int g_detect_disabled = 0;
218 
219 /** set caps or not */
220 int sc_set_caps = FALSE;
221 
222 /** highest mtu of the interfaces we monitor */
223 int g_default_mtu = 0;
224 
225 bool g_system = false;
226 
227 /** disable randomness to get reproducible results accross runs */
228 #ifndef AFLFUZZ_NO_RANDOM
229 int g_disable_randomness = 0;
230 #else
231 int g_disable_randomness = 1;
232 #endif
233 
234 /** determine (without branching) if we include the vlan_ids when hashing or
235   * comparing flows */
236 uint16_t g_vlan_mask = 0xffff;
237 
238 /** Suricata instance */
239 SCInstance suricata;
240 
SuriHasSigFile(void)241 int SuriHasSigFile(void)
242 {
243     return (suricata.sig_file != NULL);
244 }
245 
EngineModeIsIPS(void)246 int EngineModeIsIPS(void)
247 {
248     return (g_engine_mode == ENGINE_MODE_IPS);
249 }
250 
EngineModeIsIDS(void)251 int EngineModeIsIDS(void)
252 {
253     return (g_engine_mode == ENGINE_MODE_IDS);
254 }
255 
EngineModeSetIPS(void)256 void EngineModeSetIPS(void)
257 {
258     g_engine_mode = ENGINE_MODE_IPS;
259 }
260 
EngineModeSetIDS(void)261 void EngineModeSetIDS(void)
262 {
263     g_engine_mode = ENGINE_MODE_IDS;
264 }
265 
RunmodeIsUnittests(void)266 int RunmodeIsUnittests(void)
267 {
268     if (run_mode == RUNMODE_UNITTEST)
269         return 1;
270 
271     return 0;
272 }
273 
RunmodeGetCurrent(void)274 int RunmodeGetCurrent(void)
275 {
276     return run_mode;
277 }
278 
279 /** signal handlers
280  *
281  *  WARNING: don't use the SCLog* API in the handlers. The API is complex
282  *  with memory allocation possibly happening, calls to syslog, json message
283  *  construction, etc.
284  */
285 
286 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
SignalHandlerSigint(int sig)287 static void SignalHandlerSigint(/*@unused@*/ int sig)
288 {
289     sigint_count = 1;
290 }
SignalHandlerSigterm(int sig)291 static void SignalHandlerSigterm(/*@unused@*/ int sig)
292 {
293     sigterm_count = 1;
294 }
295 #endif
296 
297 #ifndef OS_WIN32
298 /**
299  * SIGUSR2 handler.  Just set sigusr2_count.  The main loop will act on
300  * it.
301  */
SignalHandlerSigusr2(int sig)302 static void SignalHandlerSigusr2(int sig)
303 {
304     if (sigusr2_count < 2)
305         sigusr2_count++;
306 }
307 
308 /**
309  * SIGHUP handler.  Just set sighup_count.  The main loop will act on
310  * it.
311  */
SignalHandlerSigHup(int sig)312 static void SignalHandlerSigHup(/*@unused@*/ int sig)
313 {
314     sighup_count = 1;
315 }
316 #endif
317 
GlobalsInitPreConfig(void)318 void GlobalsInitPreConfig(void)
319 {
320     TimeInit();
321     SupportFastPatternForSigMatchTypes();
322     SCThresholdConfGlobalInit();
323 }
324 
GlobalsDestroy(SCInstance * suri)325 static void GlobalsDestroy(SCInstance *suri)
326 {
327     HostShutdown();
328     HTPFreeConfig();
329     HTPAtExitPrintStats();
330 
331     AppLayerHtpPrintStats();
332 
333     /* TODO this can do into it's own func */
334     DetectEngineCtx *de_ctx = DetectEngineGetCurrent();
335     if (de_ctx) {
336         DetectEngineMoveToFreeList(de_ctx);
337         DetectEngineDeReference(&de_ctx);
338     }
339     DetectEnginePruneFreeList();
340 
341     AppLayerDeSetup();
342     DatasetsSave();
343     DatasetsDestroy();
344     TagDestroyCtx();
345 
346     LiveDeviceListClean();
347     OutputDeregisterAll();
348     FeatureTrackingRelease();
349     TimeDeinit();
350     SCProtoNameDeInit();
351     if (!suri->disabled_detect) {
352         SCReferenceConfDeinit();
353         SCClassConfDeinit();
354     }
355     TmqhCleanup();
356     TmModuleRunDeInit();
357     ParseSizeDeinit();
358 #ifdef HAVE_NSS
359     if (NSS_IsInitialized()) {
360         NSS_Shutdown();
361         PR_Cleanup();
362     }
363 #endif
364 
365 #ifdef HAVE_AF_PACKET
366     AFPPeersListClean();
367 #endif
368 
369 #ifdef NFQ
370     NFQContextsClean();
371 #endif
372 
373 #ifdef BUILD_HYPERSCAN
374     MpmHSGlobalCleanup();
375 #endif
376 
377     ConfDeInit();
378 #ifdef HAVE_LUAJIT
379     LuajitFreeStatesPool();
380 #endif
381     SCLogDeInitLogModule();
382     DetectParseFreeRegexes();
383     SCThresholdConfGlobalFree();
384 
385     SCPidfileRemove(suri->pid_filename);
386     SCFree(suri->pid_filename);
387     suri->pid_filename = NULL;
388 }
389 
390 /** \brief make sure threads can stop the engine by calling this
391  *  function. Purpose: pcap file mode needs to be able to tell the
392  *  engine the file eof is reached. */
EngineStop(void)393 void EngineStop(void)
394 {
395     suricata_ctl_flags |= SURICATA_STOP;
396 }
397 
398 /**
399  * \brief Used to indicate that the current task is done.
400  *
401  * This is mainly used by pcap-file to tell it has finished
402  * to treat a pcap files when running in unix-socket mode.
403  */
EngineDone(void)404 void EngineDone(void)
405 {
406     suricata_ctl_flags |= SURICATA_DONE;
407 }
408 
SetBpfString(int argc,char * argv[])409 static int SetBpfString(int argc, char *argv[])
410 {
411     char *bpf_filter = NULL;
412     uint32_t bpf_len = 0;
413     int tmpindex = 0;
414 
415     /* attempt to parse remaining args as bpf filter */
416     tmpindex = argc;
417     while(argv[tmpindex] != NULL) {
418         bpf_len+=strlen(argv[tmpindex]) + 1;
419         tmpindex++;
420     }
421 
422     if (bpf_len == 0)
423         return TM_ECODE_OK;
424 
425     if (EngineModeIsIPS()) {
426         SCLogError(SC_ERR_NOT_SUPPORTED,
427                    "BPF filter not available in IPS mode."
428                    " Use firewall filtering if possible.");
429         return TM_ECODE_FAILED;
430     }
431 
432     bpf_filter = SCMalloc(bpf_len);
433     if (unlikely(bpf_filter == NULL))
434         return TM_ECODE_OK;
435     memset(bpf_filter, 0x00, bpf_len);
436 
437     tmpindex = optind;
438     while(argv[tmpindex] != NULL) {
439         strlcat(bpf_filter, argv[tmpindex],bpf_len);
440         if(argv[tmpindex + 1] != NULL) {
441             strlcat(bpf_filter," ", bpf_len);
442         }
443         tmpindex++;
444     }
445 
446     if(strlen(bpf_filter) > 0) {
447         if (ConfSetFinal("bpf-filter", bpf_filter) != 1) {
448             SCLogError(SC_ERR_FATAL, "Failed to set bpf filter.");
449             SCFree(bpf_filter);
450             return TM_ECODE_FAILED;
451         }
452     }
453     SCFree(bpf_filter);
454 
455     return TM_ECODE_OK;
456 }
457 
SetBpfStringFromFile(char * filename)458 static void SetBpfStringFromFile(char *filename)
459 {
460     char *bpf_filter = NULL;
461     char *bpf_comment_tmp = NULL;
462     char *bpf_comment_start =  NULL;
463     uint32_t bpf_len = 0;
464 #ifdef OS_WIN32
465     struct _stat st;
466 #else
467     struct stat st;
468 #endif /* OS_WIN32 */
469     FILE *fp = NULL;
470     size_t nm = 0;
471 
472     if (EngineModeIsIPS()) {
473                    FatalError(SC_ERR_FATAL,
474                               "BPF filter not available in IPS mode."
475                               " Use firewall filtering if possible.");
476     }
477 
478 #ifdef OS_WIN32
479     if(_stat(filename, &st) != 0) {
480 #else
481     if(stat(filename, &st) != 0) {
482 #endif /* OS_WIN32 */
483         SCLogError(SC_ERR_FOPEN, "Failed to stat file %s", filename);
484         exit(EXIT_FAILURE);
485     }
486     bpf_len = st.st_size + 1;
487 
488     // coverity[toctou : FALSE]
489     fp = fopen(filename,"r");
490     if (fp == NULL) {
491         SCLogError(SC_ERR_FOPEN, "Failed to open file %s", filename);
492         exit(EXIT_FAILURE);
493     }
494 
495     bpf_filter = SCMalloc(bpf_len * sizeof(char));
496     if (unlikely(bpf_filter == NULL)) {
497         SCLogError(SC_ERR_MEM_ALLOC, "Failed to allocate buffer for bpf filter in file %s", filename);
498         exit(EXIT_FAILURE);
499     }
500     memset(bpf_filter, 0x00, bpf_len);
501 
502     nm = fread(bpf_filter, 1, bpf_len - 1, fp);
503     if ((ferror(fp) != 0) || (nm != (bpf_len - 1))) {
504         SCLogError(SC_ERR_BPF, "Failed to read complete BPF file %s", filename);
505         SCFree(bpf_filter);
506         fclose(fp);
507         exit(EXIT_FAILURE);
508     }
509     fclose(fp);
510     bpf_filter[nm] = '\0';
511 
512     if(strlen(bpf_filter) > 0) {
513         /*replace comments with space*/
514         bpf_comment_start = bpf_filter;
515         while((bpf_comment_tmp = strchr(bpf_comment_start, '#')) != NULL) {
516             while((*bpf_comment_tmp !='\0') &&
517                 (*bpf_comment_tmp != '\r') && (*bpf_comment_tmp != '\n'))
518             {
519                 *bpf_comment_tmp++ = ' ';
520             }
521             bpf_comment_start = bpf_comment_tmp;
522         }
523         /*remove remaining '\r' and '\n' */
524         while((bpf_comment_tmp = strchr(bpf_filter, '\r')) != NULL) {
525             *bpf_comment_tmp = ' ';
526         }
527         while((bpf_comment_tmp = strchr(bpf_filter, '\n')) != NULL) {
528             *bpf_comment_tmp = ' ';
529         }
530         /* cut trailing spaces */
531         while (strlen(bpf_filter) > 0 &&
532                 bpf_filter[strlen(bpf_filter)-1] == ' ')
533         {
534             bpf_filter[strlen(bpf_filter)-1] = '\0';
535         }
536         if (strlen(bpf_filter) > 0) {
537             if(ConfSetFinal("bpf-filter", bpf_filter) != 1) {
538                 SCLogError(SC_ERR_FOPEN, "ERROR: Failed to set bpf filter!");
539                 SCFree(bpf_filter);
540                 exit(EXIT_FAILURE);
541             }
542         }
543     }
544     SCFree(bpf_filter);
545 }
546 
547 static void PrintUsage(const char *progname)
548 {
549 #ifdef REVISION
550     printf("%s %s (%s)\n", PROG_NAME, PROG_VER, xstr(REVISION));
551 #else
552     printf("%s %s\n", PROG_NAME, PROG_VER);
553 #endif
554     printf("USAGE: %s [OPTIONS] [BPF FILTER]\n\n", progname);
555     printf("\t-c <path>                            : path to configuration file\n");
556     printf("\t-T                                   : test configuration file (use with -c)\n");
557     printf("\t-i <dev or ip>                       : run in pcap live mode\n");
558     printf("\t-F <bpf filter file>                 : bpf filter file\n");
559     printf("\t-r <path>                            : run in pcap file/offline mode\n");
560 #ifdef NFQ
561     printf("\t-q <qid[:qid]>                       : run in inline nfqueue mode (use colon to specify a range of queues)\n");
562 #endif /* NFQ */
563 #ifdef IPFW
564     printf("\t-d <divert port>                     : run in inline ipfw divert mode\n");
565 #endif /* IPFW */
566     printf("\t-s <path>                            : path to signature file loaded in addition to suricata.yaml settings (optional)\n");
567     printf("\t-S <path>                            : path to signature file loaded exclusively (optional)\n");
568     printf("\t-l <dir>                             : default log directory\n");
569 #ifndef OS_WIN32
570     printf("\t-D                                   : run as daemon\n");
571 #else
572     printf("\t--service-install                    : install as service\n");
573     printf("\t--service-remove                     : remove service\n");
574     printf("\t--service-change-params              : change service startup parameters\n");
575 #endif /* OS_WIN32 */
576     printf("\t-k [all|none]                        : force checksum check (all) or disabled it (none)\n");
577     printf("\t-V                                   : display Suricata version\n");
578     printf("\t-v                                   : be more verbose (use multiple times to increase verbosity)\n");
579 #ifdef UNITTESTS
580     printf("\t-u                                   : run the unittests and exit\n");
581     printf("\t-U, --unittest-filter=REGEX          : filter unittests with a regex\n");
582     printf("\t--list-unittests                     : list unit tests\n");
583     printf("\t--fatal-unittests                    : enable fatal failure on unittest error\n");
584     printf("\t--unittests-coverage                 : display unittest coverage report\n");
585 #endif /* UNITTESTS */
586     printf("\t--list-app-layer-protos              : list supported app layer protocols\n");
587     printf("\t--list-keywords[=all|csv|<kword>]    : list keywords implemented by the engine\n");
588     printf("\t--list-runmodes                      : list supported runmodes\n");
589     printf("\t--runmode <runmode_id>               : specific runmode modification the engine should run.  The argument\n"
590            "\t                                       supplied should be the id for the runmode obtained by running\n"
591            "\t                                       --list-runmodes\n");
592     printf("\t--engine-analysis                    : print reports on analysis of different sections in the engine and exit.\n"
593            "\t                                       Please have a look at the conf parameter engine-analysis on what reports\n"
594            "\t                                       can be printed\n");
595     printf("\t--pidfile <file>                     : write pid to this file\n");
596     printf("\t--init-errors-fatal                  : enable fatal failure on signature init error\n");
597     printf("\t--disable-detection                  : disable detection engine\n");
598     printf("\t--dump-config                        : show the running configuration\n");
599     printf("\t--dump-features                      : display provided features\n");
600     printf("\t--build-info                         : display build information\n");
601     printf("\t--pcap[=<dev>]                       : run in pcap mode, no value select interfaces from suricata.yaml\n");
602     printf("\t--pcap-file-continuous               : when running in pcap mode with a directory, continue checking directory for pcaps until interrupted\n");
603     printf("\t--pcap-file-delete                   : when running in replay mode (-r with directory or file), will delete pcap files that have been processed when done\n");
604     printf("\t--pcap-file-recursive                : will descend into subdirectories when running in replay mode (-r)\n");
605 #ifdef HAVE_PCAP_SET_BUFF
606     printf("\t--pcap-buffer-size                   : size of the pcap buffer value from 0 - %i\n",INT_MAX);
607 #endif /* HAVE_SET_PCAP_BUFF */
608 #ifdef HAVE_AF_PACKET
609     printf("\t--af-packet[=<dev>]                  : run in af-packet mode, no value select interfaces from suricata.yaml\n");
610 #endif
611 #ifdef HAVE_NETMAP
612     printf("\t--netmap[=<dev>]                     : run in netmap mode, no value select interfaces from suricata.yaml\n");
613 #endif
614 #ifdef HAVE_PFRING
615     printf("\t--pfring[=<dev>]                     : run in pfring mode, use interfaces from suricata.yaml\n");
616     printf("\t--pfring-int <dev>                   : run in pfring mode, use interface <dev>\n");
617     printf("\t--pfring-cluster-id <id>             : pfring cluster id \n");
618     printf("\t--pfring-cluster-type <type>         : pfring cluster type for PF_RING 4.1.2 and later cluster_round_robin|cluster_flow\n");
619 #endif /* HAVE_PFRING */
620     printf("\t--simulate-ips                       : force engine into IPS mode. Useful for QA\n");
621 #ifdef HAVE_LIBCAP_NG
622     printf("\t--user <user>                        : run suricata as this user after init\n");
623     printf("\t--group <group>                      : run suricata as this group after init\n");
624 #endif /* HAVE_LIBCAP_NG */
625     printf("\t--erf-in <path>                      : process an ERF file\n");
626 #ifdef HAVE_DAG
627     printf("\t--dag <dagX:Y>                       : process ERF records from DAG interface X, stream Y\n");
628 #endif
629 #ifdef HAVE_NAPATECH
630     printf("\t--napatech                           : run Napatech Streams using the API\n");
631 #endif
632 #ifdef BUILD_UNIX_SOCKET
633     printf("\t--unix-socket[=<file>]               : use unix socket to control suricata work\n");
634 #endif
635 #ifdef WINDIVERT
636     printf("\t--windivert <filter>                 : run in inline WinDivert mode\n");
637     printf("\t--windivert-forward <filter>         : run in inline WinDivert mode, as a gateway\n");
638 #endif
639 #ifdef HAVE_LIBNET11
640     printf("\t--reject-dev <dev>                   : send reject packets from this interface\n");
641 #endif
642     printf("\t--set name=value                     : set a configuration value\n");
643     printf("\n");
644     printf("\nTo run the engine with default configuration on "
645             "interface eth0 with signature file \"signatures.rules\", run the "
646             "command as:\n\n%s -c suricata.yaml -s signatures.rules -i eth0 \n\n",
647             progname);
648 }
649 
650 static void PrintBuildInfo(void)
651 {
652     const char *bits = "<unknown>-bits";
653     const char *endian = "<unknown>-endian";
654     char features[2048] = "";
655     const char *tls;
656 
657     printf("This is %s version %s\n", PROG_NAME, GetProgramVersion());
658 
659 #ifdef DEBUG
660     strlcat(features, "DEBUG ", sizeof(features));
661 #endif
662 #ifdef DEBUG_VALIDATION
663     strlcat(features, "DEBUG_VALIDATION ", sizeof(features));
664 #endif
665 #ifdef UNITTESTS
666     strlcat(features, "UNITTESTS ", sizeof(features));
667 #endif
668 #ifdef NFQ
669     strlcat(features, "NFQ ", sizeof(features));
670 #endif
671 #ifdef IPFW
672     strlcat(features, "IPFW ", sizeof(features));
673 #endif
674 #ifdef HAVE_PCAP_SET_BUFF
675     strlcat(features, "PCAP_SET_BUFF ", sizeof(features));
676 #endif
677 #ifdef HAVE_PFRING
678     strlcat(features, "PF_RING ", sizeof(features));
679 #endif
680 #ifdef HAVE_AF_PACKET
681     strlcat(features, "AF_PACKET ", sizeof(features));
682 #endif
683 #ifdef HAVE_NETMAP
684     strlcat(features, "NETMAP ", sizeof(features));
685 #endif
686 #ifdef HAVE_PACKET_FANOUT
687     strlcat(features, "HAVE_PACKET_FANOUT ", sizeof(features));
688 #endif
689 #ifdef HAVE_DAG
690     strlcat(features, "DAG ", sizeof(features));
691 #endif
692 #ifdef HAVE_LIBCAP_NG
693     strlcat(features, "LIBCAP_NG ", sizeof(features));
694 #endif
695 #ifdef HAVE_LIBNET11
696     strlcat(features, "LIBNET1.1 ", sizeof(features));
697 #endif
698 #ifdef HAVE_HTP_URI_NORMALIZE_HOOK
699     strlcat(features, "HAVE_HTP_URI_NORMALIZE_HOOK ", sizeof(features));
700 #endif
701 #ifdef PCRE_HAVE_JIT
702     strlcat(features, "PCRE_JIT ", sizeof(features));
703 #endif
704 #ifdef HAVE_NSS
705     strlcat(features, "HAVE_NSS ", sizeof(features));
706 #endif
707 #ifdef HTTP2_DECOMPRESSION
708     strlcat(features, "HTTP2_DECOMPRESSION ", sizeof(features));
709 #endif
710 #ifdef HAVE_LUA
711     strlcat(features, "HAVE_LUA ", sizeof(features));
712 #endif
713 #ifdef HAVE_LUAJIT
714     strlcat(features, "HAVE_LUAJIT ", sizeof(features));
715 #endif
716     strlcat(features, "HAVE_LIBJANSSON ", sizeof(features));
717 #ifdef PROFILING
718     strlcat(features, "PROFILING ", sizeof(features));
719 #endif
720 #ifdef PROFILE_LOCKING
721     strlcat(features, "PROFILE_LOCKING ", sizeof(features));
722 #endif
723 #if defined(TLS_C11) || defined(TLS_GNU)
724     strlcat(features, "TLS ", sizeof(features));
725 #endif
726 #if defined(TLS_C11)
727     strlcat(features, "TLS_C11 ", sizeof(features));
728 #elif defined(TLS_GNU)
729     strlcat(features, "TLS_GNU ", sizeof(features));
730 #endif
731 #ifdef HAVE_MAGIC
732     strlcat(features, "MAGIC ", sizeof(features));
733 #endif
734     strlcat(features, "RUST ", sizeof(features));
735     if (strlen(features) == 0) {
736         strlcat(features, "none", sizeof(features));
737     }
738 
739     printf("Features: %s\n", features);
740 
741     /* SIMD stuff */
742     memset(features, 0x00, sizeof(features));
743 #if defined(__SSE4_2__)
744     strlcat(features, "SSE_4_2 ", sizeof(features));
745 #endif
746 #if defined(__SSE4_1__)
747     strlcat(features, "SSE_4_1 ", sizeof(features));
748 #endif
749 #if defined(__SSE3__)
750     strlcat(features, "SSE_3 ", sizeof(features));
751 #endif
752     if (strlen(features) == 0) {
753         strlcat(features, "none", sizeof(features));
754     }
755     printf("SIMD support: %s\n", features);
756 
757     /* atomics stuff */
758     memset(features, 0x00, sizeof(features));
759 #if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1)
760     strlcat(features, "1 ", sizeof(features));
761 #endif
762 #if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2)
763     strlcat(features, "2 ", sizeof(features));
764 #endif
765 #if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
766     strlcat(features, "4 ", sizeof(features));
767 #endif
768 #if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)
769     strlcat(features, "8 ", sizeof(features));
770 #endif
771 #if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16)
772     strlcat(features, "16 ", sizeof(features));
773 #endif
774     if (strlen(features) == 0) {
775         strlcat(features, "none", sizeof(features));
776     } else {
777         strlcat(features, "byte(s)", sizeof(features));
778     }
779     printf("Atomic intrinsics: %s\n", features);
780 
781 #if __WORDSIZE == 64
782     bits = "64-bits";
783 #elif __WORDSIZE == 32
784     bits = "32-bits";
785 #endif
786 
787 #if __BYTE_ORDER == __BIG_ENDIAN
788     endian = "Big-endian";
789 #elif __BYTE_ORDER == __LITTLE_ENDIAN
790     endian = "Little-endian";
791 #endif
792 
793     printf("%s, %s architecture\n", bits, endian);
794 #ifdef __GNUC__
795     printf("GCC version %s, C version %"PRIiMAX"\n", __VERSION__, (intmax_t)__STDC_VERSION__);
796 #else
797     printf("C version %"PRIiMAX"\n", (intmax_t)__STDC_VERSION__);
798 #endif
799 
800 #if __SSP__ == 1
801     printf("compiled with -fstack-protector\n");
802 #endif
803 #if __SSP_ALL__ == 2
804     printf("compiled with -fstack-protector-all\n");
805 #endif
806 /*
807  * Workaround for special defines of _FORTIFY_SOURCE like
808  * FORTIFY_SOURCE=((defined __OPTIMIZE && OPTIMIZE > 0) ? 2 : 0)
809  * which is used by Gentoo for example and would result in the error
810  * 'defined' undeclared when _FORTIFY_SOURCE used via %d in printf func
811  *
812  */
813 #if _FORTIFY_SOURCE == 2
814     printf("compiled with _FORTIFY_SOURCE=2\n");
815 #elif _FORTIFY_SOURCE == 1
816     printf("compiled with _FORTIFY_SOURCE=1\n");
817 #elif _FORTIFY_SOURCE == 0
818     printf("compiled with _FORTIFY_SOURCE=0\n");
819 #endif
820 #ifdef CLS
821     printf("L1 cache line size (CLS)=%d\n", CLS);
822 #endif
823 #if defined(TLS_C11)
824     tls = "_Thread_local";
825 #elif defined(TLS_GNU)
826     tls = "__thread";
827 #else
828 #error "Unsupported thread local"
829 #endif
830     printf("thread local storage method: %s\n", tls);
831 
832     printf("compiled with %s, linked against %s\n",
833            HTP_VERSION_STRING_FULL, htp_get_version());
834     printf("\n");
835 #include "build-info.h"
836 }
837 
838 int coverage_unittests;
839 int g_ut_modules;
840 int g_ut_covered;
841 
842 void RegisterAllModules(void)
843 {
844     // zero all module storage
845     memset(tmm_modules, 0, TMM_SIZE * sizeof(TmModule));
846 
847     /* commanders */
848     TmModuleUnixManagerRegister();
849     /* managers */
850     TmModuleFlowManagerRegister();
851     TmModuleFlowRecyclerRegister();
852     TmModuleBypassedFlowManagerRegister();
853     /* nfq */
854     TmModuleReceiveNFQRegister();
855     TmModuleVerdictNFQRegister();
856     TmModuleDecodeNFQRegister();
857     /* ipfw */
858     TmModuleReceiveIPFWRegister();
859     TmModuleVerdictIPFWRegister();
860     TmModuleDecodeIPFWRegister();
861     /* pcap live */
862     TmModuleReceivePcapRegister();
863     TmModuleDecodePcapRegister();
864     /* pcap file */
865     TmModuleReceivePcapFileRegister();
866     TmModuleDecodePcapFileRegister();
867     /* af-packet */
868     TmModuleReceiveAFPRegister();
869     TmModuleDecodeAFPRegister();
870     /* netmap */
871     TmModuleReceiveNetmapRegister();
872     TmModuleDecodeNetmapRegister();
873     /* pfring */
874     TmModuleReceivePfringRegister();
875     TmModuleDecodePfringRegister();
876     /* dag file */
877     TmModuleReceiveErfFileRegister();
878     TmModuleDecodeErfFileRegister();
879     /* dag live */
880     TmModuleReceiveErfDagRegister();
881     TmModuleDecodeErfDagRegister();
882     /* napatech */
883     TmModuleNapatechStreamRegister();
884     TmModuleNapatechDecodeRegister();
885 
886     /* flow worker */
887     TmModuleFlowWorkerRegister();
888     /* respond-reject */
889     TmModuleRespondRejectRegister();
890 
891     /* log api */
892     TmModuleLoggerRegister();
893     TmModuleStatsLoggerRegister();
894 
895     TmModuleDebugList();
896     /* nflog */
897     TmModuleReceiveNFLOGRegister();
898     TmModuleDecodeNFLOGRegister();
899 
900     /* windivert */
901     TmModuleReceiveWinDivertRegister();
902     TmModuleVerdictWinDivertRegister();
903     TmModuleDecodeWinDivertRegister();
904 }
905 
906 static TmEcode LoadYamlConfig(SCInstance *suri)
907 {
908     SCEnter();
909 
910     if (suri->conf_filename == NULL)
911         suri->conf_filename = DEFAULT_CONF_FILE;
912 
913     if (ConfYamlLoadFile(suri->conf_filename) != 0) {
914         /* Error already displayed. */
915         SCReturnInt(TM_ECODE_FAILED);
916     }
917 
918     SCReturnInt(TM_ECODE_OK);
919 }
920 
921 static TmEcode ParseInterfacesList(const int runmode, char *pcap_dev)
922 {
923     SCEnter();
924 
925     /* run the selected runmode */
926     if (runmode == RUNMODE_PCAP_DEV) {
927         if (strlen(pcap_dev) == 0) {
928             int ret = LiveBuildDeviceList("pcap");
929             if (ret == 0) {
930                 SCLogError(SC_ERR_INITIALIZATION, "No interface found in config for pcap");
931                 SCReturnInt(TM_ECODE_FAILED);
932             }
933         }
934     } else if (runmode == RUNMODE_PFRING) {
935         /* FIXME add backward compat support */
936         /* iface has been set on command line */
937         if (strlen(pcap_dev)) {
938             if (ConfSetFinal("pfring.live-interface", pcap_dev) != 1) {
939                 SCLogError(SC_ERR_INITIALIZATION, "Failed to set pfring.live-interface");
940                 SCReturnInt(TM_ECODE_FAILED);
941             }
942         } else {
943             /* not an error condition if we have a 1.0 config */
944             LiveBuildDeviceList("pfring");
945         }
946 #ifdef HAVE_AF_PACKET
947     } else if (runmode == RUNMODE_AFP_DEV) {
948         /* iface has been set on command line */
949         if (strlen(pcap_dev)) {
950             if (ConfSetFinal("af-packet.live-interface", pcap_dev) != 1) {
951                 SCLogError(SC_ERR_INITIALIZATION, "Failed to set af-packet.live-interface");
952                 SCReturnInt(TM_ECODE_FAILED);
953             }
954         } else {
955             int ret = LiveBuildDeviceList("af-packet");
956             if (ret == 0) {
957                 SCLogError(SC_ERR_INITIALIZATION, "No interface found in config for af-packet");
958                 SCReturnInt(TM_ECODE_FAILED);
959             }
960         }
961 #endif
962 #ifdef HAVE_NETMAP
963     } else if (runmode == RUNMODE_NETMAP) {
964         /* iface has been set on command line */
965         if (strlen(pcap_dev)) {
966             if (ConfSetFinal("netmap.live-interface", pcap_dev) != 1) {
967                 SCLogError(SC_ERR_INITIALIZATION, "Failed to set netmap.live-interface");
968                 SCReturnInt(TM_ECODE_FAILED);
969             }
970         } else {
971             int ret = LiveBuildDeviceList("netmap");
972             if (ret == 0) {
973                 SCLogError(SC_ERR_INITIALIZATION, "No interface found in config for netmap");
974                 SCReturnInt(TM_ECODE_FAILED);
975             }
976         }
977 #endif
978 #ifdef HAVE_NFLOG
979     } else if (runmode == RUNMODE_NFLOG) {
980         int ret = LiveBuildDeviceListCustom("nflog", "group");
981         if (ret == 0) {
982             SCLogError(SC_ERR_INITIALIZATION, "No group found in config for nflog");
983             SCReturnInt(TM_ECODE_FAILED);
984         }
985 #endif
986     }
987 
988     SCReturnInt(TM_ECODE_OK);
989 }
990 
991 static void SCInstanceInit(SCInstance *suri, const char *progname)
992 {
993     memset(suri, 0x00, sizeof(*suri));
994 
995     suri->progname = progname;
996     suri->run_mode = RUNMODE_UNKNOWN;
997 
998     memset(suri->pcap_dev, 0, sizeof(suri->pcap_dev));
999     suri->sig_file = NULL;
1000     suri->sig_file_exclusive = FALSE;
1001     suri->pid_filename = NULL;
1002     suri->regex_arg = NULL;
1003 
1004     suri->keyword_info = NULL;
1005     suri->runmode_custom_mode = NULL;
1006 #ifndef OS_WIN32
1007     suri->user_name = NULL;
1008     suri->group_name = NULL;
1009     suri->do_setuid = FALSE;
1010     suri->do_setgid = FALSE;
1011     suri->userid = 0;
1012     suri->groupid = 0;
1013 #endif /* OS_WIN32 */
1014     suri->delayed_detect = 0;
1015     suri->daemon = 0;
1016     suri->offline = 0;
1017     suri->verbose = 0;
1018     /* use -1 as unknown */
1019     suri->checksum_validation = -1;
1020 #if HAVE_DETECT_DISABLED==1
1021     g_detect_disabled = suri->disabled_detect = 1;
1022 #else
1023     g_detect_disabled = suri->disabled_detect = 0;
1024 #endif
1025 }
1026 
1027 const char *GetDocURL(void)
1028 {
1029     const char *prog_ver = GetProgramVersion();
1030     if (strstr(prog_ver, "RELEASE") != NULL) {
1031         return DOC_URL "suricata-" PROG_VER;
1032     }
1033     return DOC_URL "latest";
1034 }
1035 
1036 /** \brief get string with program version
1037  *
1038  *  Get the program version as passed to us from AC_INIT
1039  *
1040  *  Add 'RELEASE' is no '-dev' in the version. Add the REVISION if passed
1041  *  to us.
1042  *
1043  *  Possible outputs:
1044  *  release:      '5.0.1 RELEASE'
1045  *  dev with rev: '5.0.1-dev (64a789bbf 2019-10-18)'
1046  *  dev w/o rev:  '5.0.1-dev'
1047  */
1048 const char *GetProgramVersion(void)
1049 {
1050     if (strstr(PROG_VER, "-dev") == NULL) {
1051         return PROG_VER " RELEASE";
1052     } else {
1053 #ifdef REVISION
1054         return PROG_VER " (" xstr(REVISION) ")";
1055 #else
1056         return PROG_VER;
1057 #endif
1058     }
1059 }
1060 
1061 static TmEcode PrintVersion(void)
1062 {
1063     printf("This is %s version %s\n", PROG_NAME, GetProgramVersion());
1064     return TM_ECODE_OK;
1065 }
1066 
1067 static TmEcode LogVersion(SCInstance *suri)
1068 {
1069     const char *mode = suri->system ? "SYSTEM" : "USER";
1070     SCLogNotice("This is %s version %s running in %s mode",
1071             PROG_NAME, GetProgramVersion(), mode);
1072     return TM_ECODE_OK;
1073 }
1074 
1075 static void SCSetStartTime(SCInstance *suri)
1076 {
1077     memset(&suri->start_time, 0, sizeof(suri->start_time));
1078     gettimeofday(&suri->start_time, NULL);
1079 }
1080 
1081 static void SCPrintElapsedTime(struct timeval *start_time)
1082 {
1083     if (start_time == NULL)
1084         return;
1085     struct timeval end_time;
1086     memset(&end_time, 0, sizeof(end_time));
1087     gettimeofday(&end_time, NULL);
1088     uint64_t milliseconds = ((end_time.tv_sec - start_time->tv_sec) * 1000) +
1089         (((1000000 + end_time.tv_usec - start_time->tv_usec) / 1000) - 1000);
1090     SCLogInfo("time elapsed %.3fs", (float)milliseconds/(float)1000);
1091 }
1092 
1093 static int ParseCommandLineAfpacket(SCInstance *suri, const char *in_arg)
1094 {
1095 #ifdef HAVE_AF_PACKET
1096     if (suri->run_mode == RUNMODE_UNKNOWN) {
1097         suri->run_mode = RUNMODE_AFP_DEV;
1098         if (in_arg) {
1099             LiveRegisterDeviceName(in_arg);
1100             memset(suri->pcap_dev, 0, sizeof(suri->pcap_dev));
1101             strlcpy(suri->pcap_dev, in_arg, sizeof(suri->pcap_dev));
1102         }
1103     } else if (suri->run_mode == RUNMODE_AFP_DEV) {
1104         if (in_arg) {
1105             LiveRegisterDeviceName(in_arg);
1106         } else {
1107             SCLogInfo("Multiple af-packet option without interface on each is useless");
1108         }
1109     } else {
1110         SCLogError(SC_ERR_MULTIPLE_RUN_MODE, "more than one run mode "
1111                 "has been specified");
1112         PrintUsage(suri->progname);
1113         return TM_ECODE_FAILED;
1114     }
1115     return TM_ECODE_OK;
1116 #else
1117     SCLogError(SC_ERR_NO_AF_PACKET,"AF_PACKET not enabled. On Linux "
1118             "host, make sure to pass --enable-af-packet to "
1119             "configure when building.");
1120     return TM_ECODE_FAILED;
1121 #endif
1122 }
1123 
1124 static int ParseCommandLinePcapLive(SCInstance *suri, const char *in_arg)
1125 {
1126     memset(suri->pcap_dev, 0, sizeof(suri->pcap_dev));
1127 
1128     if (in_arg != NULL) {
1129         /* some windows shells require escaping of the \ in \Device. Otherwise
1130          * the backslashes are stripped. We put them back here. */
1131         if (strlen(in_arg) > 9 && strncmp(in_arg, "DeviceNPF", 9) == 0) {
1132             snprintf(suri->pcap_dev, sizeof(suri->pcap_dev), "\\Device\\NPF%s", in_arg+9);
1133         } else {
1134             strlcpy(suri->pcap_dev, in_arg, sizeof(suri->pcap_dev));
1135             PcapTranslateIPToDevice(suri->pcap_dev, sizeof(suri->pcap_dev));
1136         }
1137 
1138         if (strcmp(suri->pcap_dev, in_arg) != 0) {
1139             SCLogInfo("translated %s to pcap device %s", in_arg, suri->pcap_dev);
1140         } else if (strlen(suri->pcap_dev) > 0 && isdigit((unsigned char)suri->pcap_dev[0])) {
1141             SCLogError(SC_ERR_PCAP_TRANSLATE, "failed to find a pcap device for IP %s", in_arg);
1142             return TM_ECODE_FAILED;
1143         }
1144     }
1145 
1146     if (suri->run_mode == RUNMODE_UNKNOWN) {
1147         suri->run_mode = RUNMODE_PCAP_DEV;
1148         if (in_arg) {
1149             LiveRegisterDeviceName(suri->pcap_dev);
1150         }
1151     } else if (suri->run_mode == RUNMODE_PCAP_DEV) {
1152         LiveRegisterDeviceName(suri->pcap_dev);
1153     } else {
1154         SCLogError(SC_ERR_MULTIPLE_RUN_MODE, "more than one run mode "
1155                 "has been specified");
1156         PrintUsage(suri->progname);
1157         return TM_ECODE_FAILED;
1158     }
1159     return TM_ECODE_OK;
1160 }
1161 
1162 /**
1163  * Helper function to check if log directory is writable
1164  */
1165 static bool IsLogDirectoryWritable(const char* str)
1166 {
1167     if (access(str, W_OK) == 0)
1168         return true;
1169     return false;
1170 }
1171 
1172 static TmEcode ParseCommandLine(int argc, char** argv, SCInstance *suri)
1173 {
1174     int opt;
1175 
1176     int dump_config = 0;
1177     int dump_features = 0;
1178     int list_app_layer_protocols = 0;
1179     int list_unittests = 0;
1180     int list_runmodes = 0;
1181     int list_keywords = 0;
1182     int build_info = 0;
1183     int conf_test = 0;
1184     int engine_analysis = 0;
1185     int ret = TM_ECODE_OK;
1186 
1187 #ifdef UNITTESTS
1188     coverage_unittests = 0;
1189     g_ut_modules = 0;
1190     g_ut_covered = 0;
1191 #endif
1192 
1193     struct option long_opts[] = {
1194         {"dump-config", 0, &dump_config, 1},
1195         {"dump-features", 0, &dump_features, 1},
1196         {"pfring", optional_argument, 0, 0},
1197         {"pfring-int", required_argument, 0, 0},
1198         {"pfring-cluster-id", required_argument, 0, 0},
1199         {"pfring-cluster-type", required_argument, 0, 0},
1200         {"af-packet", optional_argument, 0, 0},
1201         {"netmap", optional_argument, 0, 0},
1202         {"pcap", optional_argument, 0, 0},
1203         {"pcap-file-continuous", 0, 0, 0},
1204         {"pcap-file-delete", 0, 0, 0},
1205         {"pcap-file-recursive", 0, 0, 0},
1206         {"simulate-ips", 0, 0 , 0},
1207         {"no-random", 0, &g_disable_randomness, 1},
1208         {"strict-rule-keywords", optional_argument, 0, 0},
1209 
1210         {"capture-plugin", required_argument, 0, 0},
1211         {"capture-plugin-args", required_argument, 0, 0},
1212 
1213 #ifdef BUILD_UNIX_SOCKET
1214         {"unix-socket", optional_argument, 0, 0},
1215 #endif
1216         {"pcap-buffer-size", required_argument, 0, 0},
1217         {"unittest-filter", required_argument, 0, 'U'},
1218         {"list-app-layer-protos", 0, &list_app_layer_protocols, 1},
1219         {"list-unittests", 0, &list_unittests, 1},
1220         {"list-runmodes", 0, &list_runmodes, 1},
1221         {"list-keywords", optional_argument, &list_keywords, 1},
1222         {"runmode", required_argument, NULL, 0},
1223         {"engine-analysis", 0, &engine_analysis, 1},
1224 #ifdef OS_WIN32
1225 		{"service-install", 0, 0, 0},
1226 		{"service-remove", 0, 0, 0},
1227 		{"service-change-params", 0, 0, 0},
1228 #endif /* OS_WIN32 */
1229         {"pidfile", required_argument, 0, 0},
1230         {"init-errors-fatal", 0, 0, 0},
1231         {"disable-detection", 0, 0, 0},
1232         {"fatal-unittests", 0, 0, 0},
1233         {"unittests-coverage", 0, &coverage_unittests, 1},
1234         {"user", required_argument, 0, 0},
1235         {"group", required_argument, 0, 0},
1236         {"erf-in", required_argument, 0, 0},
1237         {"dag", required_argument, 0, 0},
1238         {"napatech", 0, 0, 0},
1239         {"build-info", 0, &build_info, 1},
1240         {"data-dir", required_argument, 0, 0},
1241 #ifdef WINDIVERT
1242         {"windivert", required_argument, 0, 0},
1243         {"windivert-forward", required_argument, 0, 0},
1244 #endif
1245 #ifdef HAVE_LIBNET11
1246         {"reject-dev", required_argument, 0, 0},
1247 #endif
1248         {"set", required_argument, 0, 0},
1249 #ifdef HAVE_NFLOG
1250         {"nflog", optional_argument, 0, 0},
1251 #endif
1252         {NULL, 0, NULL, 0}
1253     };
1254 
1255     /* getopt_long stores the option index here. */
1256     int option_index = 0;
1257 
1258     char short_opts[] = "c:TDhi:l:q:d:r:us:S:U:VF:vk:";
1259 
1260     while ((opt = getopt_long(argc, argv, short_opts, long_opts, &option_index)) != -1) {
1261         switch (opt) {
1262         case 0:
1263             if (strcmp((long_opts[option_index]).name , "pfring") == 0 ||
1264                 strcmp((long_opts[option_index]).name , "pfring-int") == 0) {
1265 #ifdef HAVE_PFRING
1266                 suri->run_mode = RUNMODE_PFRING;
1267                 if (optarg != NULL) {
1268                     memset(suri->pcap_dev, 0, sizeof(suri->pcap_dev));
1269                     strlcpy(suri->pcap_dev, optarg,
1270                             ((strlen(optarg) < sizeof(suri->pcap_dev)) ?
1271                              (strlen(optarg) + 1) : sizeof(suri->pcap_dev)));
1272                     LiveRegisterDeviceName(optarg);
1273                 }
1274 #else
1275                 SCLogError(SC_ERR_NO_PF_RING,"PF_RING not enabled. Make sure "
1276                         "to pass --enable-pfring to configure when building.");
1277                 return TM_ECODE_FAILED;
1278 #endif /* HAVE_PFRING */
1279             }
1280             else if(strcmp((long_opts[option_index]).name , "pfring-cluster-id") == 0){
1281 #ifdef HAVE_PFRING
1282                 if (ConfSetFinal("pfring.cluster-id", optarg) != 1) {
1283                     fprintf(stderr, "ERROR: Failed to set pfring.cluster-id.\n");
1284                     return TM_ECODE_FAILED;
1285                 }
1286 #else
1287                 SCLogError(SC_ERR_NO_PF_RING,"PF_RING not enabled. Make sure "
1288                         "to pass --enable-pfring to configure when building.");
1289                 return TM_ECODE_FAILED;
1290 #endif /* HAVE_PFRING */
1291             }
1292             else if(strcmp((long_opts[option_index]).name , "pfring-cluster-type") == 0){
1293 #ifdef HAVE_PFRING
1294                 if (ConfSetFinal("pfring.cluster-type", optarg) != 1) {
1295                     fprintf(stderr, "ERROR: Failed to set pfring.cluster-type.\n");
1296                     return TM_ECODE_FAILED;
1297                 }
1298 #else
1299                 SCLogError(SC_ERR_NO_PF_RING,"PF_RING not enabled. Make sure "
1300                         "to pass --enable-pfring to configure when building.");
1301                 return TM_ECODE_FAILED;
1302 #endif /* HAVE_PFRING */
1303             }
1304             else if (strcmp((long_opts[option_index]).name , "capture-plugin") == 0){
1305                 suri->run_mode = RUNMODE_PLUGIN;
1306                 suri->capture_plugin_name = optarg;
1307             }
1308             else if (strcmp((long_opts[option_index]).name , "capture-plugin-args") == 0){
1309                 suri->capture_plugin_args = optarg;
1310             }
1311             else if (strcmp((long_opts[option_index]).name , "af-packet") == 0)
1312             {
1313                 if (ParseCommandLineAfpacket(suri, optarg) != TM_ECODE_OK) {
1314                     return TM_ECODE_FAILED;
1315                 }
1316             } else if (strcmp((long_opts[option_index]).name , "netmap") == 0){
1317 #ifdef HAVE_NETMAP
1318                 if (suri->run_mode == RUNMODE_UNKNOWN) {
1319                     suri->run_mode = RUNMODE_NETMAP;
1320                     if (optarg) {
1321                         LiveRegisterDeviceName(optarg);
1322                         memset(suri->pcap_dev, 0, sizeof(suri->pcap_dev));
1323                         strlcpy(suri->pcap_dev, optarg,
1324                                 ((strlen(optarg) < sizeof(suri->pcap_dev)) ?
1325                                  (strlen(optarg) + 1) : sizeof(suri->pcap_dev)));
1326                     }
1327                 } else if (suri->run_mode == RUNMODE_NETMAP) {
1328                     if (optarg) {
1329                         LiveRegisterDeviceName(optarg);
1330                     } else {
1331                         SCLogInfo("Multiple netmap option without interface on each is useless");
1332                         break;
1333                     }
1334                 } else {
1335                     SCLogError(SC_ERR_MULTIPLE_RUN_MODE, "more than one run mode "
1336                             "has been specified");
1337                     PrintUsage(argv[0]);
1338                     return TM_ECODE_FAILED;
1339                 }
1340 #else
1341                     SCLogError(SC_ERR_NO_NETMAP, "NETMAP not enabled.");
1342                     return TM_ECODE_FAILED;
1343 #endif
1344             } else if (strcmp((long_opts[option_index]).name, "nflog") == 0) {
1345 #ifdef HAVE_NFLOG
1346                 if (suri->run_mode == RUNMODE_UNKNOWN) {
1347                     suri->run_mode = RUNMODE_NFLOG;
1348                     LiveBuildDeviceListCustom("nflog", "group");
1349                 }
1350 #else
1351                 SCLogError(SC_ERR_NFLOG_NOSUPPORT, "NFLOG not enabled.");
1352                 return TM_ECODE_FAILED;
1353 #endif /* HAVE_NFLOG */
1354             } else if (strcmp((long_opts[option_index]).name , "pcap") == 0) {
1355                 if (ParseCommandLinePcapLive(suri, optarg) != TM_ECODE_OK) {
1356                     return TM_ECODE_FAILED;
1357                 }
1358             } else if(strcmp((long_opts[option_index]).name, "simulate-ips") == 0) {
1359                 SCLogInfo("Setting IPS mode");
1360                 EngineModeSetIPS();
1361             } else if(strcmp((long_opts[option_index]).name, "init-errors-fatal") == 0) {
1362                 if (ConfSetFinal("engine.init-failure-fatal", "1") != 1) {
1363                     fprintf(stderr, "ERROR: Failed to set engine init-failure-fatal.\n");
1364                     return TM_ECODE_FAILED;
1365                 }
1366 #ifdef BUILD_UNIX_SOCKET
1367             } else if (strcmp((long_opts[option_index]).name , "unix-socket") == 0) {
1368                 if (suri->run_mode == RUNMODE_UNKNOWN) {
1369                     suri->run_mode = RUNMODE_UNIX_SOCKET;
1370                     if (optarg) {
1371                         if (ConfSetFinal("unix-command.filename", optarg) != 1) {
1372                             fprintf(stderr, "ERROR: Failed to set unix-command.filename.\n");
1373                             return TM_ECODE_FAILED;
1374                         }
1375 
1376                     }
1377                 } else {
1378                     SCLogError(SC_ERR_MULTIPLE_RUN_MODE, "more than one run mode "
1379                             "has been specified");
1380                     PrintUsage(argv[0]);
1381                     return TM_ECODE_FAILED;
1382                 }
1383 #endif
1384             }
1385             else if(strcmp((long_opts[option_index]).name, "list-app-layer-protocols") == 0) {
1386                 /* listing all supported app layer protocols */
1387             }
1388             else if(strcmp((long_opts[option_index]).name, "list-unittests") == 0) {
1389 #ifdef UNITTESTS
1390                 suri->run_mode = RUNMODE_LIST_UNITTEST;
1391 #else
1392                 fprintf(stderr, "ERROR: Unit tests not enabled. Make sure to pass --enable-unittests to configure when building.\n");
1393                 return TM_ECODE_FAILED;
1394 #endif /* UNITTESTS */
1395             } else if (strcmp((long_opts[option_index]).name, "list-runmodes") == 0) {
1396                 suri->run_mode = RUNMODE_LIST_RUNMODES;
1397                 return TM_ECODE_OK;
1398             } else if (strcmp((long_opts[option_index]).name, "list-keywords") == 0) {
1399                 if (optarg) {
1400                     if (strcmp("short",optarg)) {
1401                         suri->keyword_info = optarg;
1402                     }
1403                 }
1404             } else if (strcmp((long_opts[option_index]).name, "runmode") == 0) {
1405                 suri->runmode_custom_mode = optarg;
1406             } else if(strcmp((long_opts[option_index]).name, "engine-analysis") == 0) {
1407                 // do nothing for now
1408             }
1409 #ifdef OS_WIN32
1410             else if(strcmp((long_opts[option_index]).name, "service-install") == 0) {
1411                 suri->run_mode = RUNMODE_INSTALL_SERVICE;
1412                 return TM_ECODE_OK;
1413             }
1414             else if(strcmp((long_opts[option_index]).name, "service-remove") == 0) {
1415                 suri->run_mode = RUNMODE_REMOVE_SERVICE;
1416                 return TM_ECODE_OK;
1417             }
1418             else if(strcmp((long_opts[option_index]).name, "service-change-params") == 0) {
1419                 suri->run_mode = RUNMODE_CHANGE_SERVICE_PARAMS;
1420                 return TM_ECODE_OK;
1421             }
1422 #endif /* OS_WIN32 */
1423             else if(strcmp((long_opts[option_index]).name, "pidfile") == 0) {
1424                 suri->pid_filename = SCStrdup(optarg);
1425                 if (suri->pid_filename == NULL) {
1426                     SCLogError(SC_ERR_MEM_ALLOC, "strdup failed: %s",
1427                         strerror(errno));
1428                     return TM_ECODE_FAILED;
1429                 }
1430             }
1431             else if(strcmp((long_opts[option_index]).name, "disable-detection") == 0) {
1432                 g_detect_disabled = suri->disabled_detect = 1;
1433             }
1434             else if(strcmp((long_opts[option_index]).name, "fatal-unittests") == 0) {
1435 #ifdef UNITTESTS
1436                 unittests_fatal = 1;
1437 #else
1438                 fprintf(stderr, "ERROR: Unit tests not enabled. Make sure to pass --enable-unittests to configure when building.\n");
1439                 return TM_ECODE_FAILED;
1440 #endif /* UNITTESTS */
1441             }
1442             else if(strcmp((long_opts[option_index]).name, "user") == 0) {
1443 #ifndef HAVE_LIBCAP_NG
1444                 SCLogError(SC_ERR_LIBCAP_NG_REQUIRED, "libcap-ng is required to"
1445                         " drop privileges, but it was not compiled into Suricata.");
1446                 return TM_ECODE_FAILED;
1447 #else
1448                 suri->user_name = optarg;
1449                 suri->do_setuid = TRUE;
1450 #endif /* HAVE_LIBCAP_NG */
1451             }
1452             else if(strcmp((long_opts[option_index]).name, "group") == 0) {
1453 #ifndef HAVE_LIBCAP_NG
1454                 SCLogError(SC_ERR_LIBCAP_NG_REQUIRED, "libcap-ng is required to"
1455                         " drop privileges, but it was not compiled into Suricata.");
1456                 return TM_ECODE_FAILED;
1457 #else
1458                 suri->group_name = optarg;
1459                 suri->do_setgid = TRUE;
1460 #endif /* HAVE_LIBCAP_NG */
1461             }
1462             else if (strcmp((long_opts[option_index]).name, "erf-in") == 0) {
1463                 suri->run_mode = RUNMODE_ERF_FILE;
1464                 if (ConfSetFinal("erf-file.file", optarg) != 1) {
1465                     fprintf(stderr, "ERROR: Failed to set erf-file.file\n");
1466                     return TM_ECODE_FAILED;
1467                 }
1468             }
1469             else if (strcmp((long_opts[option_index]).name, "dag") == 0) {
1470 #ifdef HAVE_DAG
1471                 if (suri->run_mode == RUNMODE_UNKNOWN) {
1472                     suri->run_mode = RUNMODE_DAG;
1473                 }
1474                 else if (suri->run_mode != RUNMODE_DAG) {
1475                     SCLogError(SC_ERR_MULTIPLE_RUN_MODE,
1476                         "more than one run mode has been specified");
1477                     PrintUsage(argv[0]);
1478                     return TM_ECODE_FAILED;
1479                 }
1480                 LiveRegisterDeviceName(optarg);
1481 #else
1482                 SCLogError(SC_ERR_DAG_REQUIRED, "libdag and a DAG card are required"
1483 						" to receive packets using --dag.");
1484                 return TM_ECODE_FAILED;
1485 #endif /* HAVE_DAG */
1486             } else if (strcmp((long_opts[option_index]).name, "napatech") == 0) {
1487 #ifdef HAVE_NAPATECH
1488                 suri->run_mode = RUNMODE_NAPATECH;
1489 #else
1490                 SCLogError(SC_ERR_NAPATECH_REQUIRED, "libntapi and a Napatech adapter are required"
1491                                                      " to capture packets using --napatech.");
1492                 return TM_ECODE_FAILED;
1493 #endif /* HAVE_NAPATECH */
1494             } else if (strcmp((long_opts[option_index]).name, "pcap-buffer-size") == 0) {
1495 #ifdef HAVE_PCAP_SET_BUFF
1496                 if (ConfSetFinal("pcap.buffer-size", optarg) != 1) {
1497                     fprintf(stderr, "ERROR: Failed to set pcap-buffer-size.\n");
1498                     return TM_ECODE_FAILED;
1499                 }
1500 #else
1501                 SCLogError(SC_ERR_NO_PCAP_SET_BUFFER_SIZE, "The version of libpcap you have"
1502                         " doesn't support setting buffer size.");
1503 #endif /* HAVE_PCAP_SET_BUFF */
1504             } else if (strcmp((long_opts[option_index]).name, "build-info") == 0) {
1505                 suri->run_mode = RUNMODE_PRINT_BUILDINFO;
1506                 return TM_ECODE_OK;
1507             } else if (strcmp((long_opts[option_index]).name, "windivert-forward") == 0) {
1508 #ifdef WINDIVERT
1509                 if (suri->run_mode == RUNMODE_UNKNOWN) {
1510                     suri->run_mode = RUNMODE_WINDIVERT;
1511                     if (WinDivertRegisterQueue(true, optarg) == -1) {
1512                         exit(EXIT_FAILURE);
1513                     }
1514                 } else if (suri->run_mode == RUNMODE_WINDIVERT) {
1515                     if (WinDivertRegisterQueue(true, optarg) == -1) {
1516                         exit(EXIT_FAILURE);
1517                     }
1518                 } else {
1519                     SCLogError(SC_ERR_MULTIPLE_RUN_MODE, "more than one run mode "
1520                                                         "has been specified");
1521                     PrintUsage(argv[0]);
1522                     exit(EXIT_FAILURE);
1523                 }
1524             }
1525             else if(strcmp((long_opts[option_index]).name, "windivert") == 0) {
1526                 if (suri->run_mode == RUNMODE_UNKNOWN) {
1527                     suri->run_mode = RUNMODE_WINDIVERT;
1528                     if (WinDivertRegisterQueue(false, optarg) == -1) {
1529                         exit(EXIT_FAILURE);
1530                     }
1531                 } else if (suri->run_mode == RUNMODE_WINDIVERT) {
1532                     if (WinDivertRegisterQueue(false, optarg) == -1) {
1533                         exit(EXIT_FAILURE);
1534                     }
1535                 } else {
1536                     SCLogError(SC_ERR_MULTIPLE_RUN_MODE, "more than one run mode "
1537                                                         "has been specified");
1538                     PrintUsage(argv[0]);
1539                     exit(EXIT_FAILURE);
1540                 }
1541 #else
1542                 SCLogError(SC_ERR_WINDIVERT_NOSUPPORT,"WinDivert not enabled. Make sure to pass --enable-windivert to configure when building.");
1543                 return TM_ECODE_FAILED;
1544 #endif /* WINDIVERT */
1545             } else if(strcmp((long_opts[option_index]).name, "reject-dev") == 0) {
1546 #ifdef HAVE_LIBNET11
1547                 BUG_ON(optarg == NULL); /* for static analysis */
1548                 extern char *g_reject_dev;
1549                 extern uint16_t g_reject_dev_mtu;
1550                 g_reject_dev = optarg;
1551                 int mtu = GetIfaceMTU(g_reject_dev);
1552                 if (mtu > 0) {
1553                     g_reject_dev_mtu = (uint16_t)mtu;
1554                 }
1555 #else
1556                 SCLogError(SC_ERR_LIBNET_NOT_ENABLED,
1557                         "Libnet 1.1 support not enabled. Compile Suricata with libnet support.");
1558                 return TM_ECODE_FAILED;
1559 #endif
1560             }
1561             else if (strcmp((long_opts[option_index]).name, "set") == 0) {
1562                 if (optarg != NULL) {
1563                     /* Quick validation. */
1564                     char *val = strchr(optarg, '=');
1565                     if (val == NULL) {
1566                                 FatalError(SC_ERR_FATAL,
1567                                            "Invalid argument for --set, must be key=val.");
1568                     }
1569                     if (!ConfSetFromString(optarg, 1)) {
1570                         fprintf(stderr, "Failed to set configuration value %s.",
1571                                 optarg);
1572                         exit(EXIT_FAILURE);
1573                     }
1574                 }
1575             }
1576             else if (strcmp((long_opts[option_index]).name, "pcap-file-continuous") == 0) {
1577                 if (ConfSetFinal("pcap-file.continuous", "true") != 1) {
1578                     SCLogError(SC_ERR_CMD_LINE, "Failed to set pcap-file.continuous");
1579                     return TM_ECODE_FAILED;
1580                 }
1581             }
1582             else if (strcmp((long_opts[option_index]).name, "pcap-file-delete") == 0) {
1583                 if (ConfSetFinal("pcap-file.delete-when-done", "true") != 1) {
1584                     SCLogError(SC_ERR_CMD_LINE, "Failed to set pcap-file.delete-when-done");
1585                     return TM_ECODE_FAILED;
1586                 }
1587             }
1588             else if (strcmp((long_opts[option_index]).name, "pcap-file-recursive") == 0) {
1589                 if (ConfSetFinal("pcap-file.recursive", "true") != 1) {
1590                     SCLogError(SC_ERR_CMD_LINE, "ERROR: Failed to set pcap-file.recursive");
1591                     return TM_ECODE_FAILED;
1592                 }
1593             }
1594             else if (strcmp((long_opts[option_index]).name, "data-dir") == 0) {
1595                 if (optarg == NULL) {
1596                     SCLogError(SC_ERR_INITIALIZATION, "no option argument (optarg) for -d");
1597                     return TM_ECODE_FAILED;
1598                 }
1599 
1600                 if (ConfigSetDataDirectory(optarg) != TM_ECODE_OK) {
1601                     SCLogError(SC_ERR_FATAL, "Failed to set data directory.");
1602                     return TM_ECODE_FAILED;
1603                 }
1604                 if (ConfigCheckDataDirectory(optarg) != TM_ECODE_OK) {
1605                     SCLogError(SC_ERR_LOGDIR_CMDLINE, "The data directory \"%s\""
1606                             " supplied at the commandline (-d %s) doesn't "
1607                             "exist. Shutting down the engine.", optarg, optarg);
1608                     return TM_ECODE_FAILED;
1609                 }
1610                 suri->set_datadir = true;
1611             } else if (strcmp((long_opts[option_index]).name , "strict-rule-keywords") == 0){
1612                 if (optarg == NULL) {
1613                     suri->strict_rule_parsing_string = SCStrdup("all");
1614                 } else {
1615                     suri->strict_rule_parsing_string = SCStrdup(optarg);
1616                 }
1617                 if (suri->strict_rule_parsing_string == NULL) {
1618                     FatalError(SC_ERR_MEM_ALLOC, "failed to duplicate 'strict' string");
1619                 }
1620             }
1621             break;
1622         case 'c':
1623             suri->conf_filename = optarg;
1624             break;
1625         case 'T':
1626             SCLogInfo("Running suricata under test mode");
1627             conf_test = 1;
1628             if (ConfSetFinal("engine.init-failure-fatal", "1") != 1) {
1629                 fprintf(stderr, "ERROR: Failed to set engine init-failure-fatal.\n");
1630                 return TM_ECODE_FAILED;
1631             }
1632             break;
1633 #ifndef OS_WIN32
1634         case 'D':
1635             suri->daemon = 1;
1636             break;
1637 #endif /* OS_WIN32 */
1638         case 'h':
1639             suri->run_mode = RUNMODE_PRINT_USAGE;
1640             return TM_ECODE_OK;
1641         case 'i':
1642             if (optarg == NULL) {
1643                 SCLogError(SC_ERR_INITIALIZATION, "no option argument (optarg) for -i");
1644                 return TM_ECODE_FAILED;
1645             }
1646 #ifdef HAVE_AF_PACKET
1647             if (ParseCommandLineAfpacket(suri, optarg) != TM_ECODE_OK) {
1648                 return TM_ECODE_FAILED;
1649             }
1650 #else /* not afpacket */
1651             /* warn user if netmap or pf-ring are available */
1652 #if defined HAVE_PFRING || HAVE_NETMAP
1653             int i = 0;
1654 #ifdef HAVE_PFRING
1655             i++;
1656 #endif
1657 #ifdef HAVE_NETMAP
1658             i++;
1659 #endif
1660             SCLogWarning(SC_WARN_FASTER_CAPTURE_AVAILABLE, "faster capture "
1661                     "option%s %s available:"
1662 #ifdef HAVE_PFRING
1663                     " PF_RING (--pfring-int=%s)"
1664 #endif
1665 #ifdef HAVE_NETMAP
1666                     " NETMAP (--netmap=%s)"
1667 #endif
1668                     ". Use --pcap=%s to suppress this warning",
1669                     i == 1 ? "" : "s", i == 1 ? "is" : "are"
1670 #ifdef HAVE_PFRING
1671                     , optarg
1672 #endif
1673 #ifdef HAVE_NETMAP
1674                     , optarg
1675 #endif
1676                     , optarg
1677                     );
1678 #endif /* have faster methods */
1679             if (ParseCommandLinePcapLive(suri, optarg) != TM_ECODE_OK) {
1680                 return TM_ECODE_FAILED;
1681             }
1682 #endif
1683             break;
1684         case 'l':
1685             if (optarg == NULL) {
1686                 SCLogError(SC_ERR_INITIALIZATION, "no option argument (optarg) for -l");
1687                 return TM_ECODE_FAILED;
1688             }
1689 
1690             if (ConfigSetLogDirectory(optarg) != TM_ECODE_OK) {
1691                 SCLogError(SC_ERR_FATAL, "Failed to set log directory.");
1692                 return TM_ECODE_FAILED;
1693             }
1694             if (ConfigCheckLogDirectoryExists(optarg) != TM_ECODE_OK) {
1695                 SCLogError(SC_ERR_LOGDIR_CMDLINE, "The logging directory \"%s\""
1696                         " supplied at the commandline (-l %s) doesn't "
1697                         "exist. Shutting down the engine.", optarg, optarg);
1698                 return TM_ECODE_FAILED;
1699             }
1700             if (!IsLogDirectoryWritable(optarg)) {
1701                 SCLogError(SC_ERR_LOGDIR_CMDLINE, "The logging directory \"%s\""
1702                         " supplied at the commandline (-l %s) is not "
1703                         "writable. Shutting down the engine.", optarg, optarg);
1704                 return TM_ECODE_FAILED;
1705             }
1706             suri->set_logdir = true;
1707 
1708             break;
1709         case 'q':
1710 #ifdef NFQ
1711             if (suri->run_mode == RUNMODE_UNKNOWN) {
1712                 suri->run_mode = RUNMODE_NFQ;
1713                 EngineModeSetIPS();
1714                 if (NFQParseAndRegisterQueues(optarg) == -1)
1715                     return TM_ECODE_FAILED;
1716             } else if (suri->run_mode == RUNMODE_NFQ) {
1717                 if (NFQParseAndRegisterQueues(optarg) == -1)
1718                     return TM_ECODE_FAILED;
1719             } else {
1720                 SCLogError(SC_ERR_MULTIPLE_RUN_MODE, "more than one run mode "
1721                                                      "has been specified");
1722                 PrintUsage(argv[0]);
1723                 return TM_ECODE_FAILED;
1724             }
1725 #else
1726             SCLogError(SC_ERR_NFQ_NOSUPPORT,"NFQUEUE not enabled. Make sure to pass --enable-nfqueue to configure when building.");
1727             return TM_ECODE_FAILED;
1728 #endif /* NFQ */
1729             break;
1730         case 'd':
1731 #ifdef IPFW
1732             if (suri->run_mode == RUNMODE_UNKNOWN) {
1733                 suri->run_mode = RUNMODE_IPFW;
1734                 EngineModeSetIPS();
1735                 if (IPFWRegisterQueue(optarg) == -1)
1736                     return TM_ECODE_FAILED;
1737             } else if (suri->run_mode == RUNMODE_IPFW) {
1738                 if (IPFWRegisterQueue(optarg) == -1)
1739                     return TM_ECODE_FAILED;
1740             } else {
1741                 SCLogError(SC_ERR_MULTIPLE_RUN_MODE, "more than one run mode "
1742                                                      "has been specified");
1743                 PrintUsage(argv[0]);
1744                 return TM_ECODE_FAILED;
1745             }
1746 #else
1747             SCLogError(SC_ERR_IPFW_NOSUPPORT,"IPFW not enabled. Make sure to pass --enable-ipfw to configure when building.");
1748             return TM_ECODE_FAILED;
1749 #endif /* IPFW */
1750             break;
1751         case 'r':
1752             BUG_ON(optarg == NULL); /* for static analysis */
1753             if (suri->run_mode == RUNMODE_UNKNOWN) {
1754                 suri->run_mode = RUNMODE_PCAP_FILE;
1755             } else {
1756                 SCLogError(SC_ERR_MULTIPLE_RUN_MODE, "more than one run mode "
1757                                                      "has been specified");
1758                 PrintUsage(argv[0]);
1759                 return TM_ECODE_FAILED;
1760             }
1761 #ifdef OS_WIN32
1762             struct _stat buf;
1763             if(_stat(optarg, &buf) != 0) {
1764 #else
1765             struct stat buf;
1766             if (stat(optarg, &buf) != 0) {
1767 #endif /* OS_WIN32 */
1768                 SCLogError(SC_ERR_INITIALIZATION, "ERROR: Pcap file does not exist\n");
1769                 return TM_ECODE_FAILED;
1770             }
1771             if (ConfSetFinal("pcap-file.file", optarg) != 1) {
1772                 SCLogError(SC_ERR_INITIALIZATION, "ERROR: Failed to set pcap-file.file\n");
1773                 return TM_ECODE_FAILED;
1774             }
1775 
1776             break;
1777         case 's':
1778             if (suri->sig_file != NULL) {
1779                 SCLogError(SC_ERR_CMD_LINE, "can't have multiple -s options or mix -s and -S.");
1780                 return TM_ECODE_FAILED;
1781             }
1782             suri->sig_file = optarg;
1783             break;
1784         case 'S':
1785             if (suri->sig_file != NULL) {
1786                 SCLogError(SC_ERR_CMD_LINE, "can't have multiple -S options or mix -s and -S.");
1787                 return TM_ECODE_FAILED;
1788             }
1789             suri->sig_file = optarg;
1790             suri->sig_file_exclusive = TRUE;
1791             break;
1792         case 'u':
1793 #ifdef UNITTESTS
1794             if (suri->run_mode == RUNMODE_UNKNOWN) {
1795                 suri->run_mode = RUNMODE_UNITTEST;
1796             } else {
1797                 SCLogError(SC_ERR_MULTIPLE_RUN_MODE, "more than one run mode has"
1798                                                      " been specified");
1799                 PrintUsage(argv[0]);
1800                 return TM_ECODE_FAILED;
1801             }
1802 #else
1803             fprintf(stderr, "ERROR: Unit tests not enabled. Make sure to pass --enable-unittests to configure when building.\n");
1804             return TM_ECODE_FAILED;
1805 #endif /* UNITTESTS */
1806             break;
1807         case 'U':
1808 #ifdef UNITTESTS
1809             suri->regex_arg = optarg;
1810 
1811             if(strlen(suri->regex_arg) == 0)
1812                 suri->regex_arg = NULL;
1813 #endif
1814             break;
1815         case 'V':
1816             suri->run_mode = RUNMODE_PRINT_VERSION;
1817             return TM_ECODE_OK;
1818         case 'F':
1819             if (optarg == NULL) {
1820                 SCLogError(SC_ERR_INITIALIZATION, "no option argument (optarg) for -F");
1821                 return TM_ECODE_FAILED;
1822             }
1823 
1824             SetBpfStringFromFile(optarg);
1825             break;
1826         case 'v':
1827             suri->verbose++;
1828             break;
1829         case 'k':
1830             if (optarg == NULL) {
1831                 SCLogError(SC_ERR_INITIALIZATION, "no option argument (optarg) for -k");
1832                 return TM_ECODE_FAILED;
1833             }
1834             if (!strcmp("all", optarg))
1835                 suri->checksum_validation = 1;
1836             else if (!strcmp("none", optarg))
1837                 suri->checksum_validation = 0;
1838             else {
1839                 SCLogError(SC_ERR_INITIALIZATION, "option '%s' invalid for -k", optarg);
1840                 return TM_ECODE_FAILED;
1841             }
1842             break;
1843         default:
1844             PrintUsage(argv[0]);
1845             return TM_ECODE_FAILED;
1846         }
1847     }
1848 
1849     if (suri->disabled_detect && suri->sig_file != NULL) {
1850         SCLogError(SC_ERR_INITIALIZATION, "can't use -s/-S when detection is disabled");
1851         return TM_ECODE_FAILED;
1852     }
1853 
1854     if ((suri->run_mode == RUNMODE_UNIX_SOCKET) && suri->set_logdir) {
1855         SCLogError(SC_ERR_INITIALIZATION,
1856                 "can't use -l and unix socket runmode at the same time");
1857         return TM_ECODE_FAILED;
1858     }
1859 
1860     /* save the runmode from the commandline (if any) */
1861     suri->aux_run_mode = suri->run_mode;
1862 
1863     if (list_app_layer_protocols)
1864         suri->run_mode = RUNMODE_LIST_APP_LAYERS;
1865     if (list_keywords)
1866         suri->run_mode = RUNMODE_LIST_KEYWORDS;
1867     if (list_unittests)
1868         suri->run_mode = RUNMODE_LIST_UNITTEST;
1869     if (dump_config)
1870         suri->run_mode = RUNMODE_DUMP_CONFIG;
1871     if (dump_features)
1872         suri->run_mode = RUNMODE_DUMP_FEATURES;
1873     if (conf_test)
1874         suri->run_mode = RUNMODE_CONF_TEST;
1875     if (engine_analysis)
1876         suri->run_mode = RUNMODE_ENGINE_ANALYSIS;
1877 
1878     suri->offline = IsRunModeOffline(suri->run_mode);
1879     g_system = suri->system = IsRunModeSystem(suri->run_mode);
1880 
1881     ret = SetBpfString(optind, argv);
1882     if (ret != TM_ECODE_OK)
1883         return ret;
1884 
1885     return TM_ECODE_OK;
1886 }
1887 
1888 #ifdef OS_WIN32
1889 static int WindowsInitService(int argc, char **argv)
1890 {
1891     if (SCRunningAsService()) {
1892         char path[MAX_PATH];
1893         char *p = NULL;
1894         strlcpy(path, argv[0], MAX_PATH);
1895         if ((p = strrchr(path, '\\'))) {
1896             *p = '\0';
1897         }
1898         if (!SetCurrentDirectory(path)) {
1899             SCLogError(SC_ERR_FATAL, "Can't set current directory to: %s", path);
1900             return -1;
1901         }
1902         SCLogInfo("Current directory is set to: %s", path);
1903         SCServiceInit(argc, argv);
1904     }
1905 
1906     /* Windows socket subsystem initialization */
1907     WSADATA wsaData;
1908     if (0 != WSAStartup(MAKEWORD(2, 2), &wsaData)) {
1909         SCLogError(SC_ERR_FATAL, "Can't initialize Windows sockets: %d", WSAGetLastError());
1910         return -1;
1911     }
1912 
1913     return 0;
1914 }
1915 #endif /* OS_WIN32 */
1916 
1917 static int MayDaemonize(SCInstance *suri)
1918 {
1919     if (suri->daemon == 1 && suri->pid_filename == NULL) {
1920         const char *pid_filename;
1921 
1922         if (ConfGet("pid-file", &pid_filename) == 1) {
1923             SCLogInfo("Use pid file %s from config file.", pid_filename);
1924         } else {
1925             pid_filename = DEFAULT_PID_FILENAME;
1926         }
1927         /* The pid file name may be in config memory, but is needed later. */
1928         suri->pid_filename = SCStrdup(pid_filename);
1929         if (suri->pid_filename == NULL) {
1930             SCLogError(SC_ERR_MEM_ALLOC, "strdup failed: %s", strerror(errno));
1931             return TM_ECODE_FAILED;
1932         }
1933     }
1934 
1935     if (suri->pid_filename != NULL && SCPidfileTestRunning(suri->pid_filename) != 0) {
1936         SCFree(suri->pid_filename);
1937         suri->pid_filename = NULL;
1938         return TM_ECODE_FAILED;
1939     }
1940 
1941     if (suri->daemon == 1) {
1942         Daemonize();
1943     }
1944 
1945     if (suri->pid_filename != NULL) {
1946         if (SCPidfileCreate(suri->pid_filename) != 0) {
1947             SCFree(suri->pid_filename);
1948             suri->pid_filename = NULL;
1949             SCLogError(SC_ERR_PIDFILE_DAEMON,
1950                     "Unable to create PID file, concurrent run of"
1951                     " Suricata can occur.");
1952             SCLogError(SC_ERR_PIDFILE_DAEMON,
1953                     "PID file creation WILL be mandatory for daemon mode"
1954                     " in future version");
1955         }
1956     }
1957 
1958     return TM_ECODE_OK;
1959 }
1960 
1961 static int InitSignalHandler(SCInstance *suri)
1962 {
1963     /* registering signals we use */
1964 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1965     UtilSignalHandlerSetup(SIGINT, SignalHandlerSigint);
1966     UtilSignalHandlerSetup(SIGTERM, SignalHandlerSigterm);
1967 #endif
1968 #ifndef OS_WIN32
1969     UtilSignalHandlerSetup(SIGHUP, SignalHandlerSigHup);
1970     UtilSignalHandlerSetup(SIGPIPE, SIG_IGN);
1971     UtilSignalHandlerSetup(SIGSYS, SIG_IGN);
1972 
1973     /* Try to get user/group to run suricata as if
1974        command line as not decide of that */
1975     if (suri->do_setuid == FALSE && suri->do_setgid == FALSE) {
1976         const char *id;
1977         if (ConfGet("run-as.user", &id) == 1) {
1978             suri->do_setuid = TRUE;
1979             suri->user_name = id;
1980         }
1981         if (ConfGet("run-as.group", &id) == 1) {
1982             suri->do_setgid = TRUE;
1983             suri->group_name = id;
1984         }
1985     }
1986     /* Get the suricata user ID to given user ID */
1987     if (suri->do_setuid == TRUE) {
1988         if (SCGetUserID(suri->user_name, suri->group_name,
1989                         &suri->userid, &suri->groupid) != 0) {
1990             SCLogError(SC_ERR_UID_FAILED, "failed in getting user ID");
1991             return TM_ECODE_FAILED;
1992         }
1993 
1994         sc_set_caps = TRUE;
1995     /* Get the suricata group ID to given group ID */
1996     } else if (suri->do_setgid == TRUE) {
1997         if (SCGetGroupID(suri->group_name, &suri->groupid) != 0) {
1998             SCLogError(SC_ERR_GID_FAILED, "failed in getting group ID");
1999             return TM_ECODE_FAILED;
2000         }
2001 
2002         sc_set_caps = TRUE;
2003     }
2004 #endif /* OS_WIN32 */
2005 
2006     return TM_ECODE_OK;
2007 }
2008 
2009 /* initialization code for both the main modes and for
2010  * unix socket mode.
2011  *
2012  * Will be run once per pcap in unix-socket mode */
2013 void PreRunInit(const int runmode)
2014 {
2015     /* Initialize Datasets to be able to use them with unix socket */
2016     DatasetsInit();
2017     if (runmode == RUNMODE_UNIX_SOCKET)
2018         return;
2019 
2020     StatsInit();
2021 #ifdef PROFILING
2022     SCProfilingRulesGlobalInit();
2023     SCProfilingKeywordsGlobalInit();
2024     SCProfilingPrefilterGlobalInit();
2025     SCProfilingSghsGlobalInit();
2026     SCProfilingInit();
2027 #endif /* PROFILING */
2028     DefragInit();
2029     FlowInitConfig(FLOW_QUIET);
2030     IPPairInitConfig(FLOW_QUIET);
2031     StreamTcpInitConfig(STREAM_VERBOSE);
2032     AppLayerParserPostStreamSetup();
2033     AppLayerRegisterGlobalCounters();
2034     OutputFilestoreRegisterGlobalCounters();
2035 }
2036 
2037 /* tasks we need to run before packets start flowing,
2038  * but after we dropped privs */
2039 void PreRunPostPrivsDropInit(const int runmode)
2040 {
2041     StatsSetupPostConfigPreOutput();
2042     RunModeInitializeOutputs();
2043 
2044     if (runmode == RUNMODE_UNIX_SOCKET) {
2045         /* As the above did some necessary startup initialization, it
2046          * also setup some outputs where only one is allowed, so
2047          * deinitialize to the state that unix-mode does after every
2048          * pcap. */
2049         PostRunDeinit(RUNMODE_PCAP_FILE, NULL);
2050         return;
2051     }
2052 
2053     StatsSetupPostConfigPostOutput();
2054 }
2055 
2056 /* clean up / shutdown code for both the main modes and for
2057  * unix socket mode.
2058  *
2059  * Will be run once per pcap in unix-socket mode */
2060 void PostRunDeinit(const int runmode, struct timeval *start_time)
2061 {
2062     if (runmode == RUNMODE_UNIX_SOCKET)
2063         return;
2064 
2065     /* needed by FlowForceReassembly */
2066     PacketPoolInit();
2067 
2068     /* handle graceful shutdown of the flow engine, it's helper
2069      * threads and the packet threads */
2070     FlowDisableFlowManagerThread();
2071     TmThreadDisableReceiveThreads();
2072     FlowForceReassembly();
2073     TmThreadDisablePacketThreads();
2074     SCPrintElapsedTime(start_time);
2075     FlowDisableFlowRecyclerThread();
2076 
2077     /* kill the stats threads */
2078     TmThreadKillThreadsFamily(TVT_MGMT);
2079     TmThreadClearThreadsFamily(TVT_MGMT);
2080 
2081     /* kill packet threads -- already in 'disabled' state */
2082     TmThreadKillThreadsFamily(TVT_PPT);
2083     TmThreadClearThreadsFamily(TVT_PPT);
2084 
2085     PacketPoolDestroy();
2086 
2087     /* mgt and ppt threads killed, we can run non thread-safe
2088      * shutdown functions */
2089     StatsReleaseResources();
2090     DecodeUnregisterCounters();
2091     RunModeShutDown();
2092     FlowShutdown();
2093     IPPairShutdown();
2094     HostCleanup();
2095     StreamTcpFreeConfig(STREAM_VERBOSE);
2096     DefragDestroy();
2097 
2098     TmqResetQueues();
2099 #ifdef PROFILING
2100     if (profiling_rules_enabled)
2101         SCProfilingDump();
2102     SCProfilingDestroy();
2103 #endif
2104 }
2105 
2106 
2107 static int StartInternalRunMode(SCInstance *suri, int argc, char **argv)
2108 {
2109     /* Treat internal running mode */
2110     switch(suri->run_mode) {
2111         case RUNMODE_LIST_KEYWORDS:
2112             ListKeywords(suri->keyword_info);
2113             return TM_ECODE_DONE;
2114         case RUNMODE_LIST_APP_LAYERS:
2115             if (suri->conf_filename != NULL) {
2116                 ListAppLayerProtocols(suri->conf_filename);
2117             } else {
2118                 ListAppLayerProtocols(DEFAULT_CONF_FILE);
2119             }
2120             return TM_ECODE_DONE;
2121         case RUNMODE_PRINT_VERSION:
2122             PrintVersion();
2123             return TM_ECODE_DONE;
2124         case RUNMODE_PRINT_BUILDINFO:
2125             PrintBuildInfo();
2126             return TM_ECODE_DONE;
2127         case RUNMODE_PRINT_USAGE:
2128             PrintUsage(argv[0]);
2129             return TM_ECODE_DONE;
2130         case RUNMODE_LIST_RUNMODES:
2131             RunModeListRunmodes();
2132             return TM_ECODE_DONE;
2133         case RUNMODE_LIST_UNITTEST:
2134             RunUnittests(1, suri->regex_arg);
2135         case RUNMODE_UNITTEST:
2136             RunUnittests(0, suri->regex_arg);
2137 #ifdef OS_WIN32
2138         case RUNMODE_INSTALL_SERVICE:
2139             if (SCServiceInstall(argc, argv)) {
2140                 return TM_ECODE_FAILED;
2141             }
2142             SCLogInfo("Suricata service has been successfuly installed.");
2143             return TM_ECODE_DONE;
2144         case RUNMODE_REMOVE_SERVICE:
2145             if (SCServiceRemove(argc, argv)) {
2146                 return TM_ECODE_FAILED;
2147             }
2148             SCLogInfo("Suricata service has been successfuly removed.");
2149             return TM_ECODE_DONE;
2150         case RUNMODE_CHANGE_SERVICE_PARAMS:
2151             if (SCServiceChangeParams(argc, argv)) {
2152                 return TM_ECODE_FAILED;
2153             }
2154             SCLogInfo("Suricata service startup parameters has been successfuly changed.");
2155             return TM_ECODE_DONE;
2156 #endif /* OS_WIN32 */
2157         default:
2158             /* simply continue for other running mode */
2159             break;
2160     }
2161     return TM_ECODE_OK;
2162 }
2163 
2164 static int FinalizeRunMode(SCInstance *suri, char **argv)
2165 {
2166     switch (suri->run_mode) {
2167         case RUNMODE_UNKNOWN:
2168             PrintUsage(argv[0]);
2169             return TM_ECODE_FAILED;
2170         default:
2171             break;
2172     }
2173     /* Set the global run mode and offline flag. */
2174     run_mode = suri->run_mode;
2175 
2176     if (!CheckValidDaemonModes(suri->daemon, suri->run_mode)) {
2177         return TM_ECODE_FAILED;
2178     }
2179 
2180     return TM_ECODE_OK;
2181 }
2182 
2183 static void SetupDelayedDetect(SCInstance *suri)
2184 {
2185     /* In offline mode delayed init of detect is a bad idea */
2186     if (suri->offline) {
2187         suri->delayed_detect = 0;
2188     } else {
2189         if (ConfGetBool("detect.delayed-detect", &suri->delayed_detect) != 1) {
2190             ConfNode *denode = NULL;
2191             ConfNode *decnf = ConfGetNode("detect-engine");
2192             if (decnf != NULL) {
2193                 TAILQ_FOREACH(denode, &decnf->head, next) {
2194                     if (strcmp(denode->val, "delayed-detect") == 0) {
2195                         (void)ConfGetChildValueBool(denode, "delayed-detect", &suri->delayed_detect);
2196                     }
2197                 }
2198             }
2199         }
2200     }
2201 
2202     SCLogConfig("Delayed detect %s", suri->delayed_detect ? "enabled" : "disabled");
2203     if (suri->delayed_detect) {
2204         SCLogInfo("Packets will start being processed before signatures are active.");
2205     }
2206 
2207 }
2208 
2209 static int LoadSignatures(DetectEngineCtx *de_ctx, SCInstance *suri)
2210 {
2211     if (SigLoadSignatures(de_ctx, suri->sig_file, suri->sig_file_exclusive) < 0) {
2212         SCLogError(SC_ERR_NO_RULES_LOADED, "Loading signatures failed.");
2213         if (de_ctx->failure_fatal)
2214             return TM_ECODE_FAILED;
2215     }
2216 
2217     return TM_ECODE_OK;
2218 }
2219 
2220 static int ConfigGetCaptureValue(SCInstance *suri)
2221 {
2222     /* Pull the max pending packets from the config, if not found fall
2223      * back on a sane default. */
2224     if (ConfGetInt("max-pending-packets", &max_pending_packets) != 1)
2225         max_pending_packets = DEFAULT_MAX_PENDING_PACKETS;
2226     if (max_pending_packets >= 65535) {
2227         SCLogError(SC_ERR_INVALID_YAML_CONF_ENTRY,
2228                 "Maximum max-pending-packets setting is 65534. "
2229                 "Please check %s for errors", suri->conf_filename);
2230         return TM_ECODE_FAILED;
2231     }
2232 
2233     SCLogDebug("Max pending packets set to %"PRIiMAX, max_pending_packets);
2234 
2235     /* Pull the default packet size from the config, if not found fall
2236      * back on a sane default. */
2237     const char *temp_default_packet_size;
2238     if ((ConfGet("default-packet-size", &temp_default_packet_size)) != 1) {
2239         int mtu = 0;
2240         int lthread;
2241         int nlive;
2242         int strip_trailing_plus = 0;
2243         switch (suri->run_mode) {
2244 #ifdef WINDIVERT
2245             case RUNMODE_WINDIVERT:
2246                 /* by default, WinDivert collects from all devices */
2247                 mtu = GetGlobalMTUWin32();
2248 
2249                 if (mtu > 0) {
2250                     g_default_mtu = mtu;
2251                     /* SLL_HEADER_LEN is the longest header + 8 for VLAN */
2252                     default_packet_size = mtu + SLL_HEADER_LEN + 8;
2253                     break;
2254                 }
2255 
2256                 g_default_mtu = DEFAULT_MTU;
2257                 default_packet_size = DEFAULT_PACKET_SIZE;
2258                 break;
2259 #endif /* WINDIVERT */
2260             case RUNMODE_NETMAP:
2261                 /* in netmap igb0+ has a special meaning, however the
2262                  * interface really is igb0 */
2263                 strip_trailing_plus = 1;
2264                 /* fall through */
2265             case RUNMODE_PCAP_DEV:
2266             case RUNMODE_AFP_DEV:
2267             case RUNMODE_PFRING:
2268                 nlive = LiveGetDeviceNameCount();
2269                 for (lthread = 0; lthread < nlive; lthread++) {
2270                     const char *live_dev = LiveGetDeviceNameName(lthread);
2271                     char dev[128]; /* need to be able to support GUID names on Windows */
2272                     (void)strlcpy(dev, live_dev, sizeof(dev));
2273 
2274                     if (strip_trailing_plus) {
2275                         size_t len = strlen(dev);
2276                         if (len &&
2277                                 (dev[len-1] == '+' ||
2278                                  dev[len-1] == '^' ||
2279                                  dev[len-1] == '*'))
2280                         {
2281                             dev[len-1] = '\0';
2282                         }
2283                     }
2284                     mtu = GetIfaceMTU(dev);
2285                     g_default_mtu = MAX(mtu, g_default_mtu);
2286 
2287                     unsigned int iface_max_packet_size = GetIfaceMaxPacketSize(dev);
2288                     if (iface_max_packet_size > default_packet_size)
2289                         default_packet_size = iface_max_packet_size;
2290                 }
2291                 if (default_packet_size)
2292                     break;
2293                 /* fall through */
2294             default:
2295                 g_default_mtu = DEFAULT_MTU;
2296                 default_packet_size = DEFAULT_PACKET_SIZE;
2297         }
2298     } else {
2299         if (ParseSizeStringU32(temp_default_packet_size, &default_packet_size) < 0) {
2300             SCLogError(SC_ERR_SIZE_PARSE, "Error parsing max-pending-packets "
2301                        "from conf file - %s.  Killing engine",
2302                        temp_default_packet_size);
2303             return TM_ECODE_FAILED;
2304         }
2305     }
2306 
2307     SCLogDebug("Default packet size set to %"PRIu32, default_packet_size);
2308 
2309     return TM_ECODE_OK;
2310 }
2311 
2312 static void PostRunStartedDetectSetup(const SCInstance *suri)
2313 {
2314 #ifndef OS_WIN32
2315     /* registering signal handlers we use. We setup usr2 here, so that one
2316      * can't call it during the first sig load phase or while threads are still
2317      * starting up. */
2318     if (DetectEngineEnabled() && suri->delayed_detect == 0) {
2319         UtilSignalHandlerSetup(SIGUSR2, SignalHandlerSigusr2);
2320         UtilSignalUnblock(SIGUSR2);
2321     }
2322 #endif
2323     if (suri->delayed_detect) {
2324         /* force 'reload', this will load the rules and swap engines */
2325         DetectEngineReload(suri);
2326         SCLogNotice("Signature(s) loaded, Detect thread(s) activated.");
2327 #ifndef OS_WIN32
2328         UtilSignalHandlerSetup(SIGUSR2, SignalHandlerSigusr2);
2329         UtilSignalUnblock(SIGUSR2);
2330 #endif
2331     }
2332 }
2333 
2334 void PostConfLoadedDetectSetup(SCInstance *suri)
2335 {
2336     DetectEngineCtx *de_ctx = NULL;
2337     if (!suri->disabled_detect) {
2338         SCClassConfInit();
2339         SCReferenceConfInit();
2340         SetupDelayedDetect(suri);
2341         int mt_enabled = 0;
2342         (void)ConfGetBool("multi-detect.enabled", &mt_enabled);
2343         int default_tenant = 0;
2344         if (mt_enabled)
2345             (void)ConfGetBool("multi-detect.default", &default_tenant);
2346         if (DetectEngineMultiTenantSetup() == -1) {
2347             FatalError(SC_ERR_FATAL, "initializing multi-detect "
2348                        "detection engine contexts failed.");
2349         }
2350         if (suri->delayed_detect && suri->run_mode != RUNMODE_CONF_TEST) {
2351             de_ctx = DetectEngineCtxInitStubForDD();
2352         } else if (mt_enabled && !default_tenant && suri->run_mode != RUNMODE_CONF_TEST) {
2353             de_ctx = DetectEngineCtxInitStubForMT();
2354         } else {
2355             de_ctx = DetectEngineCtxInit();
2356         }
2357         if (de_ctx == NULL) {
2358             FatalError(SC_ERR_FATAL, "initializing detection engine "
2359                        "context failed.");
2360         }
2361 
2362         if (de_ctx->type == DETECT_ENGINE_TYPE_NORMAL) {
2363             if (LoadSignatures(de_ctx, suri) != TM_ECODE_OK)
2364                 exit(EXIT_FAILURE);
2365         }
2366 
2367         gettimeofday(&de_ctx->last_reload, NULL);
2368         DetectEngineAddToMaster(de_ctx);
2369         DetectEngineBumpVersion();
2370     }
2371 }
2372 
2373 static int PostDeviceFinalizedSetup(SCInstance *suri)
2374 {
2375     SCEnter();
2376 
2377 #ifdef HAVE_AF_PACKET
2378     if (suri->run_mode == RUNMODE_AFP_DEV) {
2379         if (AFPRunModeIsIPS()) {
2380             SCLogInfo("AF_PACKET: Setting IPS mode");
2381             EngineModeSetIPS();
2382         }
2383     }
2384 #endif
2385 #ifdef HAVE_NETMAP
2386     if (suri->run_mode == RUNMODE_NETMAP) {
2387         if (NetmapRunModeIsIPS()) {
2388             SCLogInfo("Netmap: Setting IPS mode");
2389             EngineModeSetIPS();
2390         }
2391     }
2392 #endif
2393 
2394     SCReturnInt(TM_ECODE_OK);
2395 }
2396 
2397 static void PostConfLoadedSetupHostMode(void)
2398 {
2399     const char *hostmode = NULL;
2400 
2401     if (ConfGetValue("host-mode", &hostmode) == 1) {
2402         if (!strcmp(hostmode, "router")) {
2403             host_mode = SURI_HOST_IS_ROUTER;
2404         } else if (!strcmp(hostmode, "sniffer-only")) {
2405             host_mode = SURI_HOST_IS_SNIFFER_ONLY;
2406         } else {
2407             if (strcmp(hostmode, "auto") != 0) {
2408                 WarnInvalidConfEntry("host-mode", "%s", "auto");
2409             }
2410             if (EngineModeIsIPS()) {
2411                 host_mode = SURI_HOST_IS_ROUTER;
2412             } else {
2413                 host_mode = SURI_HOST_IS_SNIFFER_ONLY;
2414             }
2415         }
2416     } else {
2417         if (EngineModeIsIPS()) {
2418             host_mode = SURI_HOST_IS_ROUTER;
2419             SCLogInfo("No 'host-mode': suricata is in IPS mode, using "
2420                       "default setting 'router'");
2421         } else {
2422             host_mode = SURI_HOST_IS_SNIFFER_ONLY;
2423             SCLogInfo("No 'host-mode': suricata is in IDS mode, using "
2424                       "default setting 'sniffer-only'");
2425         }
2426     }
2427 
2428 }
2429 
2430 static void SetupUserMode(SCInstance *suri)
2431 {
2432     /* apply 'user mode' config updates here */
2433     if (suri->system == false) {
2434         if (suri->set_logdir == false) {
2435             /* override log dir to current work dir" */
2436             if (ConfigSetLogDirectory((char *)".") != TM_ECODE_OK) {
2437                 FatalError(SC_ERR_LOGDIR_CONFIG, "could not set USER mode logdir");
2438             }
2439         }
2440         if (suri->set_datadir == false) {
2441             /* override data dir to current work dir" */
2442             if (ConfigSetDataDirectory((char *)".") != TM_ECODE_OK) {
2443                 FatalError(SC_ERR_LOGDIR_CONFIG, "could not set USER mode datadir");
2444             }
2445         }
2446     }
2447 }
2448 
2449 /**
2450  * This function is meant to contain code that needs
2451  * to be run once the configuration has been loaded.
2452  */
2453 int PostConfLoadedSetup(SCInstance *suri)
2454 {
2455     /* do this as early as possible #1577 #1955 */
2456 #ifdef HAVE_LUAJIT
2457     if (LuajitSetupStatesPool() != 0) {
2458         SCReturnInt(TM_ECODE_FAILED);
2459     }
2460 #endif
2461 
2462     /* load the pattern matchers */
2463     MpmTableSetup();
2464     SpmTableSetup();
2465 
2466     int disable_offloading;
2467     if (ConfGetBool("capture.disable-offloading", &disable_offloading) == 0)
2468         disable_offloading = 1;
2469     if (disable_offloading) {
2470         LiveSetOffloadDisable();
2471     } else {
2472         LiveSetOffloadWarn();
2473     }
2474 
2475     if (suri->checksum_validation == -1) {
2476         const char *cv = NULL;
2477         if (ConfGetValue("capture.checksum-validation", &cv) == 1) {
2478             if (strcmp(cv, "none") == 0) {
2479                 suri->checksum_validation = 0;
2480             } else if (strcmp(cv, "all") == 0) {
2481                 suri->checksum_validation = 1;
2482             }
2483         }
2484     }
2485     switch (suri->checksum_validation) {
2486         case 0:
2487             ConfSet("stream.checksum-validation", "0");
2488             break;
2489         case 1:
2490             ConfSet("stream.checksum-validation", "1");
2491             break;
2492     }
2493 
2494     if (suri->runmode_custom_mode) {
2495         ConfSet("runmode", suri->runmode_custom_mode);
2496     }
2497 
2498     StorageInit();
2499 #ifdef HAVE_PACKET_EBPF
2500     if (suri->run_mode == RUNMODE_AFP_DEV) {
2501         EBPFRegisterExtension();
2502         LiveDevRegisterExtension();
2503     }
2504 #endif
2505     RegisterFlowBypassInfo();
2506 
2507     MacSetRegisterFlowStorage();
2508 
2509     AppLayerSetup();
2510 
2511     /* Suricata will use this umask if provided. By default it will use the
2512        umask passed on from the shell. */
2513     const char *custom_umask;
2514     if (ConfGet("umask", &custom_umask) == 1) {
2515         uint16_t mask;
2516         if (StringParseUint16(&mask, 8, strlen(custom_umask),
2517                                     custom_umask) > 0) {
2518             umask((mode_t)mask);
2519         }
2520     }
2521 
2522 
2523     if (ConfigGetCaptureValue(suri) != TM_ECODE_OK) {
2524         SCReturnInt(TM_ECODE_FAILED);
2525     }
2526 
2527 #ifdef NFQ
2528     if (suri->run_mode == RUNMODE_NFQ)
2529         NFQInitConfig(FALSE);
2530 #endif
2531 
2532     /* Load the Host-OS lookup. */
2533     SCHInfoLoadFromConfig();
2534 
2535     if (suri->run_mode == RUNMODE_ENGINE_ANALYSIS) {
2536         SCLogInfo("== Carrying out Engine Analysis ==");
2537         const char *temp = NULL;
2538         if (ConfGet("engine-analysis", &temp) == 0) {
2539             SCLogInfo("no engine-analysis parameter(s) defined in conf file.  "
2540                       "Please define/enable them in the conf to use this "
2541                       "feature.");
2542             SCReturnInt(TM_ECODE_FAILED);
2543         }
2544     }
2545 
2546     /* hardcoded initialization code */
2547     SigTableSetup(); /* load the rule keywords */
2548     SigTableApplyStrictCommandlineOption(suri->strict_rule_parsing_string);
2549     TmqhSetup();
2550 
2551     CIDRInit();
2552     SCProtoNameInit();
2553 
2554     TagInitCtx();
2555     PacketAlertTagInit();
2556     ThresholdInit();
2557     HostBitInitCtx();
2558     IPPairBitInitCtx();
2559 
2560     if (DetectAddressTestConfVars() < 0) {
2561         SCLogError(SC_ERR_INVALID_YAML_CONF_ENTRY,
2562                 "basic address vars test failed. Please check %s for errors",
2563                 suri->conf_filename);
2564         SCReturnInt(TM_ECODE_FAILED);
2565     }
2566     if (DetectPortTestConfVars() < 0) {
2567         SCLogError(SC_ERR_INVALID_YAML_CONF_ENTRY,
2568                 "basic port vars test failed. Please check %s for errors",
2569                 suri->conf_filename);
2570         SCReturnInt(TM_ECODE_FAILED);
2571     }
2572 
2573     FeatureTrackingRegister(); /* must occur prior to output mod registration */
2574     RegisterAllModules();
2575 #ifdef HAVE_PLUGINS
2576     SCPluginsLoad(suri->capture_plugin_name, suri->capture_plugin_args);
2577 #endif
2578     AppLayerHtpNeedFileInspection();
2579 
2580     StorageFinalize();
2581 
2582     TmModuleRunInit();
2583 
2584     if (MayDaemonize(suri) != TM_ECODE_OK)
2585         SCReturnInt(TM_ECODE_FAILED);
2586 
2587     if (InitSignalHandler(suri) != TM_ECODE_OK)
2588         SCReturnInt(TM_ECODE_FAILED);
2589 
2590     /* Check for the existance of the default logging directory which we pick
2591      * from suricata.yaml.  If not found, shut the engine down */
2592     suri->log_dir = ConfigGetLogDirectory();
2593 
2594     if (ConfigCheckLogDirectoryExists(suri->log_dir) != TM_ECODE_OK) {
2595         SCLogError(SC_ERR_LOGDIR_CONFIG, "The logging directory \"%s\" "
2596                 "supplied by %s (default-log-dir) doesn't exist. "
2597                 "Shutting down the engine", suri->log_dir, suri->conf_filename);
2598         SCReturnInt(TM_ECODE_FAILED);
2599     }
2600     if (!IsLogDirectoryWritable(suri->log_dir)) {
2601         SCLogError(SC_ERR_LOGDIR_CONFIG, "The logging directory \"%s\" "
2602                 "supplied by %s (default-log-dir) is not writable. "
2603                 "Shutting down the engine", suri->log_dir, suri->conf_filename);
2604         SCReturnInt(TM_ECODE_FAILED);
2605     }
2606 
2607 
2608 #ifdef HAVE_NSS
2609     if (suri->run_mode != RUNMODE_CONF_TEST) {
2610         /* init NSS for hashing */
2611         PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
2612         NSS_NoDB_Init(NULL);
2613     }
2614 #endif
2615 
2616     if (suri->disabled_detect) {
2617         SCLogConfig("detection engine disabled");
2618         /* disable raw reassembly */
2619         (void)ConfSetFinal("stream.reassembly.raw", "false");
2620     }
2621 
2622     HostInitConfig(HOST_VERBOSE);
2623 
2624     CoredumpLoadConfig();
2625 
2626     DecodeGlobalConfig();
2627 
2628     LiveDeviceFinalize();
2629 
2630     /* set engine mode if L2 IPS */
2631     if (PostDeviceFinalizedSetup(suri) != TM_ECODE_OK) {
2632         exit(EXIT_FAILURE);
2633     }
2634 
2635     /* hostmode depends on engine mode being set */
2636     PostConfLoadedSetupHostMode();
2637 
2638     PreRunInit(suri->run_mode);
2639 
2640     SCReturnInt(TM_ECODE_OK);
2641 }
2642 
2643 static void SuricataMainLoop(SCInstance *suri)
2644 {
2645     while(1) {
2646         if (sigterm_count || sigint_count) {
2647             suricata_ctl_flags |= SURICATA_STOP;
2648         }
2649 
2650         if (suricata_ctl_flags & SURICATA_STOP) {
2651             SCLogNotice("Signal Received.  Stopping engine.");
2652             break;
2653         }
2654 
2655         TmThreadCheckThreadState();
2656 
2657         if (sighup_count > 0) {
2658             OutputNotifyFileRotation();
2659             sighup_count--;
2660         }
2661 
2662         if (sigusr2_count > 0) {
2663             if (!(DetectEngineReloadIsStart())) {
2664                 DetectEngineReloadStart();
2665                 DetectEngineReload(suri);
2666                 DetectEngineReloadSetIdle();
2667                 sigusr2_count--;
2668             }
2669 
2670         } else if (DetectEngineReloadIsStart()) {
2671             DetectEngineReload(suri);
2672             DetectEngineReloadSetIdle();
2673         }
2674 
2675         usleep(10* 1000);
2676     }
2677 }
2678 
2679 /**
2680  * \brief Global initialization common to all runmodes.
2681  *
2682  * This can be used by fuzz targets.
2683  */
2684 
2685 int InitGlobal(void) {
2686     suricata_context.SCLogMessage = SCLogMessage;
2687     suricata_context.DetectEngineStateFree = DetectEngineStateFree;
2688     suricata_context.AppLayerDecoderEventsSetEventRaw = AppLayerDecoderEventsSetEventRaw;
2689     suricata_context.AppLayerDecoderEventsFreeEvents = AppLayerDecoderEventsFreeEvents;
2690     suricata_context.AppLayerParserTriggerRawStreamReassembly =
2691             AppLayerParserTriggerRawStreamReassembly;
2692 
2693     suricata_context.FileOpenFileWithId = FileOpenFileWithId;
2694     suricata_context.FileCloseFileById = FileCloseFileById;
2695     suricata_context.FileAppendDataById = FileAppendDataById;
2696     suricata_context.FileAppendGAPById = FileAppendGAPById;
2697     suricata_context.FileContainerRecycle = FileContainerRecycle;
2698     suricata_context.FilePrune = FilePrune;
2699     suricata_context.FileSetTx = FileContainerSetTx;
2700 
2701     rs_init(&suricata_context);
2702 
2703     SC_ATOMIC_INIT(engine_stage);
2704 
2705     /* initialize the logging subsys */
2706     SCLogInitLogModule(NULL);
2707 
2708     (void)SCSetThreadName("Suricata-Main");
2709 
2710     /* Ignore SIGUSR2 as early as possble. We redeclare interest
2711      * once we're done launching threads. The goal is to either die
2712      * completely or handle any and all SIGUSR2s correctly.
2713      */
2714 #ifndef OS_WIN32
2715     UtilSignalHandlerSetup(SIGUSR2, SIG_IGN);
2716     if (UtilSignalBlock(SIGUSR2)) {
2717         SCLogError(SC_ERR_INITIALIZATION, "SIGUSR2 initialization error");
2718         return EXIT_FAILURE;
2719     }
2720 #endif
2721 
2722     ParseSizeInit();
2723     RunModeRegisterRunModes();
2724 
2725     /* Initialize the configuration module. */
2726     ConfInit();
2727 
2728     return 0;
2729 }
2730 
2731 int SuricataMain(int argc, char **argv)
2732 {
2733     SCInstanceInit(&suricata, argv[0]);
2734 
2735     if (InitGlobal() != 0) {
2736         exit(EXIT_FAILURE);
2737     }
2738 
2739 #ifdef OS_WIN32
2740     /* service initialization */
2741     if (WindowsInitService(argc, argv) != 0) {
2742         exit(EXIT_FAILURE);
2743     }
2744 #endif /* OS_WIN32 */
2745 
2746     if (ParseCommandLine(argc, argv, &suricata) != TM_ECODE_OK) {
2747         exit(EXIT_FAILURE);
2748     }
2749 
2750     if (FinalizeRunMode(&suricata, argv) != TM_ECODE_OK) {
2751         exit(EXIT_FAILURE);
2752     }
2753 
2754     switch (StartInternalRunMode(&suricata, argc, argv)) {
2755         case TM_ECODE_DONE:
2756             exit(EXIT_SUCCESS);
2757         case TM_ECODE_FAILED:
2758             exit(EXIT_FAILURE);
2759     }
2760 
2761     /* Initializations for global vars, queues, etc (memsets, mutex init..) */
2762     GlobalsInitPreConfig();
2763 
2764     /* Load yaml configuration file if provided. */
2765     if (LoadYamlConfig(&suricata) != TM_ECODE_OK) {
2766         exit(EXIT_FAILURE);
2767     }
2768 
2769     if (suricata.run_mode == RUNMODE_DUMP_CONFIG) {
2770         ConfDump();
2771         exit(EXIT_SUCCESS);
2772     }
2773 
2774     int vlan_tracking = 1;
2775     if (ConfGetBool("vlan.use-for-tracking", &vlan_tracking) == 1 && !vlan_tracking) {
2776         /* Ignore vlan_ids when comparing flows. */
2777         g_vlan_mask = 0x0000;
2778     }
2779     SCLogDebug("vlan tracking is %s", vlan_tracking == 1 ? "enabled" : "disabled");
2780 
2781     SetupUserMode(&suricata);
2782 
2783     /* Since our config is now loaded we can finish configurating the
2784      * logging module. */
2785     SCLogLoadConfig(suricata.daemon, suricata.verbose);
2786 
2787     LogVersion(&suricata);
2788     UtilCpuPrintSummary();
2789 
2790     if (ParseInterfacesList(suricata.aux_run_mode, suricata.pcap_dev) != TM_ECODE_OK) {
2791         exit(EXIT_FAILURE);
2792     }
2793 
2794     if (PostConfLoadedSetup(&suricata) != TM_ECODE_OK) {
2795         exit(EXIT_FAILURE);
2796     }
2797 
2798     SCDropMainThreadCaps(suricata.userid, suricata.groupid);
2799 
2800     /* Re-enable coredumps after privileges are dropped. */
2801     CoredumpEnable();
2802 
2803     PreRunPostPrivsDropInit(suricata.run_mode);
2804 
2805     PostConfLoadedDetectSetup(&suricata);
2806     if (suricata.run_mode == RUNMODE_ENGINE_ANALYSIS) {
2807         goto out;
2808     } else if (suricata.run_mode == RUNMODE_CONF_TEST){
2809         SCLogNotice("Configuration provided was successfully loaded. Exiting.");
2810         goto out;
2811     } else if (suricata.run_mode == RUNMODE_DUMP_FEATURES) {
2812         FeatureDump();
2813         goto out;
2814     }
2815 
2816     SCSetStartTime(&suricata);
2817     RunModeDispatch(suricata.run_mode, suricata.runmode_custom_mode,
2818             suricata.capture_plugin_name, suricata.capture_plugin_args);
2819     if (suricata.run_mode != RUNMODE_UNIX_SOCKET) {
2820         UnixManagerThreadSpawnNonRunmode();
2821     }
2822 
2823     /* Wait till all the threads have been initialized */
2824     if (TmThreadWaitOnThreadInit() == TM_ECODE_FAILED) {
2825         FatalError(SC_ERR_FATAL, "Engine initialization failed, "
2826                    "aborting...");
2827     }
2828 
2829     SC_ATOMIC_SET(engine_stage, SURICATA_RUNTIME);
2830     PacketPoolPostRunmodes();
2831 
2832     /* Un-pause all the paused threads */
2833     TmThreadContinueThreads();
2834 
2835     PostRunStartedDetectSetup(&suricata);
2836 
2837     SCPledge();
2838     SuricataMainLoop(&suricata);
2839 
2840     /* Update the engine stage/status flag */
2841     SC_ATOMIC_SET(engine_stage, SURICATA_DEINIT);
2842 
2843     UnixSocketKillSocketThread();
2844     PostRunDeinit(suricata.run_mode, &suricata.start_time);
2845     /* kill remaining threads */
2846     TmThreadKillThreads();
2847 
2848 out:
2849     GlobalsDestroy(&suricata);
2850 
2851     exit(EXIT_SUCCESS);
2852 }
2853