suricata
unix-manager.c
Go to the documentation of this file.
1 /* Copyright (C) 2013-2018 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 Eric Leblond <eric@regit.org>
22  */
23 
24 #include "suricata-common.h"
25 #include "suricata.h"
26 #include "unix-manager.h"
27 #include "detect-engine.h"
28 #include "tm-threads.h"
29 #include "runmodes.h"
30 #include "conf.h"
31 
32 #include "output-json-stats.h"
33 
34 #include "util-privs.h"
35 #include "util-debug.h"
36 #include "util-device.h"
37 #include "util-ebpf.h"
38 #include "util-signal.h"
39 #include "util-buffer.h"
40 
41 #if (defined BUILD_UNIX_SOCKET) && (defined HAVE_SYS_UN_H) && (defined HAVE_SYS_STAT_H) && (defined HAVE_SYS_TYPES_H)
42 #include <sys/un.h>
43 #include <sys/stat.h>
44 #include <sys/types.h>
45 
46 #include "output.h"
47 #include "output-json.h"
48 
49 // MSG_NOSIGNAL does not exists on OS X
50 #ifdef OS_DARWIN
51 # ifndef MSG_NOSIGNAL
52 # define MSG_NOSIGNAL SO_NOSIGPIPE
53 # endif
54 #endif
55 
56 #define SOCKET_PATH LOCAL_STATE_DIR "/run/suricata/"
57 #define SOCKET_FILENAME "suricata-command.socket"
58 #define SOCKET_TARGET SOCKET_PATH SOCKET_FILENAME
59 
62 
63 #define MAX_FAILED_RULES 20
64 
65 typedef struct Command_ {
66  char *name;
67  TmEcode (*Func)(json_t *, json_t *, void *);
68  void *data;
69  int flags;
70  TAILQ_ENTRY(Command_) next;
71 } Command;
72 
73 typedef struct Task_ {
74  TmEcode (*Func)(void *);
75  void *data;
76  TAILQ_ENTRY(Task_) next;
77 } Task;
78 
79 #define CLIENT_BUFFER_SIZE 4096
80 typedef struct UnixClient_ {
81  int fd;
82  MemBuffer *mbuf; /**< buffer for response construction */
83  int version;
84  TAILQ_ENTRY(UnixClient_) next;
85 } UnixClient;
86 
87 typedef struct UnixCommand_ {
88  time_t start_timestamp;
89  int socket;
90  struct sockaddr_un client_addr;
91  int select_max;
92  TAILQ_HEAD(, Command_) commands;
93  TAILQ_HEAD(, Task_) tasks;
94  TAILQ_HEAD(, UnixClient_) clients;
95 } UnixCommand;
96 
97 /**
98  * \brief Create a command unix socket on system
99  *
100  * \retval 0 in case of error, 1 in case of success
101  */
102 static int UnixNew(UnixCommand * this)
103 {
104  struct sockaddr_un addr;
105  int len;
106  int ret;
107  int on = 1;
108  char sockettarget[PATH_MAX];
109  const char *socketname;
110 
111  this->start_timestamp = time(NULL);
112  this->socket = -1;
113  this->select_max = 0;
114 
115  TAILQ_INIT(&this->commands);
116  TAILQ_INIT(&this->tasks);
117  TAILQ_INIT(&this->clients);
118 
119  int check_dir = 0;
120  if (ConfGet("unix-command.filename", &socketname) == 1) {
121  if (PathIsAbsolute(socketname)) {
122  strlcpy(sockettarget, socketname, sizeof(sockettarget));
123  } else {
124  snprintf(sockettarget, sizeof(sockettarget), "%s/%s",
125  SOCKET_PATH, socketname);
126  check_dir = 1;
127  }
128  } else {
129  strlcpy(sockettarget, SOCKET_TARGET, sizeof(sockettarget));
130  check_dir = 1;
131  }
132  SCLogInfo("Using unix socket file '%s'", sockettarget);
133 
134  if (check_dir) {
135  struct stat stat_buf;
136  /* coverity[toctou] */
137  if (stat(SOCKET_PATH, &stat_buf) != 0) {
138  /* coverity[toctou] */
139  ret = SCMkDir(SOCKET_PATH, S_IRWXU|S_IXGRP|S_IRGRP);
140  if (ret != 0) {
141  int err = errno;
142  if (err != EEXIST) {
144  "Cannot create socket directory %s: %s",
145  SOCKET_PATH, strerror(err));
146  return 0;
147  }
148  } else {
149  SCLogInfo("Created socket directory %s",
150  SOCKET_PATH);
151  }
152  }
153  }
154 
155  /* Remove socket file */
156  (void) unlink(sockettarget);
157 
158  /* set address */
159  addr.sun_family = AF_UNIX;
160  strlcpy(addr.sun_path, sockettarget, sizeof(addr.sun_path));
161  addr.sun_path[sizeof(addr.sun_path) - 1] = 0;
162  len = strlen(addr.sun_path) + sizeof(addr.sun_family) + 1;
163 
164  /* create socket */
165  this->socket = socket(AF_UNIX, SOCK_STREAM, 0);
166  if (this->socket == -1) {
168  "Unix Socket: unable to create UNIX socket %s: %s",
169  addr.sun_path, strerror(errno));
170  return 0;
171  }
172  this->select_max = this->socket + 1;
173 
174  /* set reuse option */
175  ret = setsockopt(this->socket, SOL_SOCKET, SO_REUSEADDR,
176  (char *) &on, sizeof(on));
177  if ( ret != 0 ) {
179  "Cannot set sockets options: %s.", strerror(errno));
180  }
181 
182  /* bind socket */
183  ret = bind(this->socket, (struct sockaddr *) &addr, len);
184  if (ret == -1) {
186  "Unix socket: UNIX socket bind(%s) error: %s",
187  sockettarget, strerror(errno));
188  return 0;
189  }
190 
191 #if !(defined OS_FREEBSD || defined __OpenBSD__)
192  /* Set file mode: will not fully work on most system, the group
193  * permission is not changed on some Linux. *BSD won't do the
194  * chmod: it returns EINVAL when calling chmod on sockets. */
195  ret = chmod(sockettarget, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
196  if (ret == -1) {
197  int err = errno;
199  "Unable to change permission on socket: %s (%d)",
200  strerror(err),
201  err);
202  }
203 #endif
204 
205  /* listen */
206  if (listen(this->socket, 1) == -1) {
208  "Command server: UNIX socket listen() error: %s",
209  strerror(errno));
210  return 0;
211  }
212  return 1;
213 }
214 
215 static void UnixCommandSetMaxFD(UnixCommand *this)
216 {
217  UnixClient *item;
218 
219  if (this == NULL) {
220  SCLogError(SC_ERR_INVALID_ARGUMENT, "Unix command is NULL, warn devel");
221  return;
222  }
223 
224  this->select_max = this->socket + 1;
225  TAILQ_FOREACH(item, &this->clients, next) {
226  if (item->fd >= this->select_max) {
227  this->select_max = item->fd + 1;
228  }
229  }
230 }
231 
232 static UnixClient *UnixClientAlloc(void)
233 {
234  UnixClient *uclient = SCMalloc(sizeof(UnixClient));
235  if (unlikely(uclient == NULL)) {
236  SCLogError(SC_ERR_MEM_ALLOC, "Can't allocate new client");
237  return NULL;
238  }
239  uclient->mbuf = MemBufferCreateNew(CLIENT_BUFFER_SIZE);
240  if (uclient->mbuf == NULL) {
241  SCLogError(SC_ERR_MEM_ALLOC, "Can't allocate new client send buffer");
242  SCFree(uclient);
243  return NULL;
244  }
245  return uclient;
246 }
247 
248 static void UnixClientFree(UnixClient *c)
249 {
250  if (c != NULL) {
251  MemBufferFree(c->mbuf);
252  SCFree(c);
253  }
254 }
255 
256 /**
257  * \brief Close the unix socket
258  */
259 static void UnixCommandClose(UnixCommand *this, int fd)
260 {
261  UnixClient *item;
262  int found = 0;
263 
264  TAILQ_FOREACH(item, &this->clients, next) {
265  if (item->fd == fd) {
266  found = 1;
267  break;
268  }
269  }
270 
271  if (found == 0) {
272  SCLogError(SC_ERR_INVALID_VALUE, "No fd found in client list");
273  return;
274  }
275 
276  TAILQ_REMOVE(&this->clients, item, next);
277 
278  close(item->fd);
279  UnixCommandSetMaxFD(this);
280  UnixClientFree(item);
281 }
282 
283 #define UNIX_PROTO_VERSION_LENGTH 200
284 #define UNIX_PROTO_VERSION_V1 "0.1"
285 #define UNIX_PROTO_V1 1
286 #define UNIX_PROTO_VERSION "0.2"
287 #define UNIX_PROTO_V2 2
288 
289 static int UnixCommandSendJSONToClient(UnixClient *client, json_t *js)
290 {
291  MemBufferReset(client->mbuf);
292 
293  OutputJSONMemBufferWrapper wrapper = {
294  .buffer = &client->mbuf,
295  .expand_by = CLIENT_BUFFER_SIZE
296  };
297 
298  int r = json_dump_callback(js, OutputJSONMemBufferCallback, &wrapper,
299  JSON_PRESERVE_ORDER|JSON_COMPACT|JSON_ENSURE_ASCII|
301  if (r != 0) {
302  SCLogWarning(SC_ERR_SOCKET, "unable to serialize JSON object");
303  return -1;
304  }
305 
306  if (client->version > UNIX_PROTO_V1) {
307  if (MEMBUFFER_OFFSET(client->mbuf) + 1 >= MEMBUFFER_SIZE(client->mbuf)) {
308  MemBufferExpand(&client->mbuf, 1);
309  }
310  MemBufferWriteRaw(client->mbuf, "\n", 1);
311  }
312 
313  if (send(client->fd, (const char *)MEMBUFFER_BUFFER(client->mbuf),
314  MEMBUFFER_OFFSET(client->mbuf), MSG_NOSIGNAL) == -1)
315  {
316  SCLogWarning(SC_ERR_SOCKET, "unable to send block of size "
317  "%"PRIuMAX": %s", (uintmax_t)MEMBUFFER_OFFSET(client->mbuf),
318  strerror(errno));
319  return -1;
320  }
321 
322  SCLogDebug("sent message of size %"PRIuMAX" to client socket %d",
323  (uintmax_t)MEMBUFFER_OFFSET(client->mbuf), client->fd);
324  return 0;
325 }
326 
327 /**
328  * \brief Accept a new client on unix socket
329  *
330  * The function is called when a new user is detected
331  * in UnixMain(). It does the initial protocol negotiation
332  * with client.
333  *
334  * \retval 0 in case of error, 1 in case of success
335  */
336 static int UnixCommandAccept(UnixCommand *this)
337 {
338  char buffer[UNIX_PROTO_VERSION_LENGTH + 1];
339  json_t *client_msg;
340  json_t *server_msg;
341  json_t *version;
342  json_error_t jerror;
343  int client;
344  int client_version;
345  int ret;
346  UnixClient *uclient = NULL;
347 
348  /* accept client socket */
349  socklen_t len = sizeof(this->client_addr);
350  client = accept(this->socket, (struct sockaddr *) &this->client_addr,
351  &len);
352  if (client < 0) {
353  SCLogInfo("Unix socket: accept() error: %s",
354  strerror(errno));
355  return 0;
356  }
357  SCLogDebug("Unix socket: client connection");
358 
359  /* read client version */
360  buffer[sizeof(buffer)-1] = 0;
361  ret = recv(client, buffer, sizeof(buffer)-1, 0);
362  if (ret < 0) {
363  SCLogInfo("Command server: client doesn't send version");
364  close(client);
365  return 0;
366  }
367  if (ret >= (int)(sizeof(buffer)-1)) {
368  SCLogInfo("Command server: client message is too long, "
369  "disconnect him.");
370  close(client);
371  return 0;
372  }
373  buffer[ret] = 0;
374 
375  client_msg = json_loads(buffer, 0, &jerror);
376  if (client_msg == NULL) {
377  SCLogInfo("Invalid command, error on line %d: %s\n", jerror.line, jerror.text);
378  close(client);
379  return 0;
380  }
381 
382  version = json_object_get(client_msg, "version");
383  if (!json_is_string(version)) {
384  SCLogInfo("error: version is not a string");
385  close(client);
386  json_decref(client_msg);
387  return 0;
388  }
389 
390  /* check client version */
391  if ((strcmp(json_string_value(version), UNIX_PROTO_VERSION) != 0)
392  && (strcmp(json_string_value(version), UNIX_PROTO_VERSION_V1) != 0)) {
393  SCLogInfo("Unix socket: invalid client version: \"%s\"",
394  json_string_value(version));
395  json_decref(client_msg);
396  close(client);
397  return 0;
398  } else {
399  SCLogDebug("Unix socket: client version: \"%s\"",
400  json_string_value(version));
401  if (strcmp(json_string_value(version), UNIX_PROTO_VERSION_V1) == 0) {
402  client_version = UNIX_PROTO_V1;
403  } else {
404  client_version = UNIX_PROTO_V2;
405  }
406  }
407 
408  json_decref(client_msg);
409  /* send answer */
410  server_msg = json_object();
411  if (server_msg == NULL) {
412  close(client);
413  return 0;
414  }
415  json_object_set_new(server_msg, "return", json_string("OK"));
416 
417  uclient = UnixClientAlloc();
418  if (unlikely(uclient == NULL)) {
419  SCLogError(SC_ERR_MEM_ALLOC, "Can't allocate new client");
420  json_decref(server_msg);
421  close(client);
422  return 0;
423  }
424  uclient->fd = client;
425  uclient->version = client_version;
426 
427  if (UnixCommandSendJSONToClient(uclient, server_msg) != 0) {
428  SCLogWarning(SC_ERR_SOCKET, "Unable to send command");
429 
430  UnixClientFree(uclient);
431  json_decref(server_msg);
432  close(client);
433  return 0;
434  }
435 
436  json_decref(server_msg);
437 
438  /* client connected */
439  SCLogDebug("Unix socket: client connected");
440  TAILQ_INSERT_TAIL(&this->clients, uclient, next);
441  UnixCommandSetMaxFD(this);
442  return 1;
443 }
444 
445 static int UnixCommandBackgroundTasks(UnixCommand* this)
446 {
447  int ret = 1;
448  Task *ltask;
449 
450  TAILQ_FOREACH(ltask, &this->tasks, next) {
451  int fret = ltask->Func(ltask->data);
452  if (fret != TM_ECODE_OK) {
453  ret = 0;
454  }
455  }
456  return ret;
457 }
458 
459 /**
460  * \brief Command dispatcher
461  *
462  * \param this a UnixCommand:: structure
463  * \param command a string containing a json formatted
464  * command
465  *
466  * \retval 0 in case of error, 1 in case of success
467  */
468 static int UnixCommandExecute(UnixCommand * this, char *command, UnixClient *client)
469 {
470  int ret = 1;
471  json_error_t error;
472  json_t *jsoncmd = NULL;
473  json_t *cmd = NULL;
474  json_t *server_msg = json_object();
475  const char * value;
476  int found = 0;
477  Command *lcmd;
478 
479  if (server_msg == NULL) {
480  return 0;
481  }
482 
483  jsoncmd = json_loads(command, 0, &error);
484  if (jsoncmd == NULL) {
485  SCLogInfo("Invalid command, error on line %d: %s\n", error.line, error.text);
486  goto error;
487  }
488 
489  cmd = json_object_get(jsoncmd, "command");
490  if(!json_is_string(cmd)) {
491  SCLogInfo("error: command is not a string");
492  goto error_cmd;
493  }
494  value = json_string_value(cmd);
495 
496  TAILQ_FOREACH(lcmd, &this->commands, next) {
497  if (!strcmp(value, lcmd->name)) {
498  int fret = TM_ECODE_OK;
499  found = 1;
500  if (lcmd->flags & UNIX_CMD_TAKE_ARGS) {
501  cmd = json_object_get(jsoncmd, "arguments");
502  if(!json_is_object(cmd)) {
503  SCLogInfo("error: argument is not an object");
504  goto error_cmd;
505  }
506  }
507  fret = lcmd->Func(cmd, server_msg, lcmd->data);
508  if (fret != TM_ECODE_OK) {
509  ret = 0;
510  }
511  break;
512  }
513  }
514 
515  if (found == 0) {
516  json_object_set_new(server_msg, "message", json_string("Unknown command"));
517  ret = 0;
518  }
519 
520  switch (ret) {
521  case 0:
522  json_object_set_new(server_msg, "return", json_string("NOK"));
523  break;
524  case 1:
525  json_object_set_new(server_msg, "return", json_string("OK"));
526  break;
527  }
528 
529  if (UnixCommandSendJSONToClient(client, server_msg) != 0) {
530  goto error;
531  }
532 
533  json_decref(jsoncmd);
534  json_decref(server_msg);
535  return ret;
536 
537 error_cmd:
538  json_decref(jsoncmd);
539 error:
540  json_decref(server_msg);
541  UnixCommandClose(this, client->fd);
542  return 0;
543 }
544 
545 static void UnixCommandRun(UnixCommand * this, UnixClient *client)
546 {
547  char buffer[4096];
548  int ret;
549  if (client->version <= UNIX_PROTO_V1) {
550  ret = recv(client->fd, buffer, sizeof(buffer) - 1, 0);
551  if (ret <= 0) {
552  if (ret == 0) {
553  SCLogDebug("Unix socket: lost connection with client");
554  } else {
555  SCLogError(SC_ERR_SOCKET, "Unix socket: error on recv() from client: %s",
556  strerror(errno));
557  }
558  UnixCommandClose(this, client->fd);
559  return;
560  }
561  if (ret >= (int)(sizeof(buffer)-1)) {
562  SCLogError(SC_ERR_SOCKET, "Command server: client command is too long, "
563  "disconnect him.");
564  UnixCommandClose(this, client->fd);
565  }
566  buffer[ret] = 0;
567  } else {
568  int try = 0;
569  int offset = 0;
570  int cmd_over = 0;
571  ret = recv(client->fd, buffer + offset, sizeof(buffer) - offset - 1, 0);
572  do {
573  if (ret <= 0) {
574  if (ret == 0) {
575  SCLogInfo("Unix socket: lost connection with client");
576  } else {
577  SCLogInfo("Unix socket: error on recv() from client: %s",
578  strerror(errno));
579  }
580  UnixCommandClose(this, client->fd);
581  return;
582  }
583  if (ret >= (int)(sizeof(buffer)- offset - 1)) {
584  SCLogInfo("Command server: client command is too long, "
585  "disconnect him.");
586  UnixCommandClose(this, client->fd);
587  }
588  if (buffer[ret - 1] == '\n') {
589  buffer[ret-1] = 0;
590  cmd_over = 1;
591  } else {
592  struct timeval tv;
593  fd_set select_set;
594  offset += ret;
595  do {
596  FD_ZERO(&select_set);
597  FD_SET(client->fd, &select_set);
598  tv.tv_sec = 0;
599  tv.tv_usec = 200 * 1000;
600  try++;
601  ret = select(client->fd, &select_set, NULL, NULL, &tv);
602  /* catch select() error */
603  if (ret == -1) {
604  /* Signal was caught: just ignore it */
605  if (errno != EINTR) {
606  SCLogInfo("Unix socket: lost connection with client");
607  UnixCommandClose(this, client->fd);
608  return;
609  }
610  }
611  } while (ret == 0 && try < 3);
612  if (ret > 0) {
613  ret = recv(client->fd, buffer + offset,
614  sizeof(buffer) - offset - 1, 0);
615  }
616  }
617  } while (try < 3 && cmd_over == 0);
618 
619  if (try == 3 && cmd_over == 0) {
620  SCLogInfo("Unix socket: imcomplete client message, closing connection");
621  UnixCommandClose(this, client->fd);
622  return;
623  }
624  }
625  UnixCommandExecute(this, buffer, client);
626 }
627 
628 /**
629  * \brief Select function
630  *
631  * \retval 0 in case of error, 1 in case of success
632  */
633 static int UnixMain(UnixCommand * this)
634 {
635  struct timeval tv;
636  int ret;
637  fd_set select_set;
638  UnixClient *uclient;
639  UnixClient *tclient;
640 
641  /* Wait activity on the socket */
642  FD_ZERO(&select_set);
643  FD_SET(this->socket, &select_set);
644  TAILQ_FOREACH(uclient, &this->clients, next) {
645  FD_SET(uclient->fd, &select_set);
646  }
647 
648  tv.tv_sec = 0;
649  tv.tv_usec = 200 * 1000;
650  ret = select(this->select_max, &select_set, NULL, NULL, &tv);
651 
652  /* catch select() error */
653  if (ret == -1) {
654  /* Signal was caught: just ignore it */
655  if (errno == EINTR) {
656  return 1;
657  }
658  SCLogError(SC_ERR_SOCKET, "Command server: select() fatal error: %s", strerror(errno));
659  return 0;
660  }
661 
663  TAILQ_FOREACH_SAFE(uclient, &this->clients, next, tclient) {
664  UnixCommandClose(this, uclient->fd);
665  }
666  return 1;
667  }
668 
669  /* timeout: continue */
670  if (ret == 0) {
671  return 1;
672  }
673 
674  TAILQ_FOREACH_SAFE(uclient, &this->clients, next, tclient) {
675  if (FD_ISSET(uclient->fd, &select_set)) {
676  UnixCommandRun(this, uclient);
677  }
678  }
679  if (FD_ISSET(this->socket, &select_set)) {
680  if (!UnixCommandAccept(this))
681  return 1;
682  }
683 
684  return 1;
685 }
686 
687 static TmEcode UnixManagerShutdownCommand(json_t *cmd,
688  json_t *server_msg, void *data)
689 {
690  SCEnter();
691  json_object_set_new(server_msg, "message", json_string("Closing Suricata"));
692  EngineStop();
694 }
695 
696 static TmEcode UnixManagerVersionCommand(json_t *cmd,
697  json_t *server_msg, void *data)
698 {
699  SCEnter();
700  json_object_set_new(server_msg, "message", json_string(GetProgramVersion()));
702 }
703 
704 static TmEcode UnixManagerUptimeCommand(json_t *cmd,
705  json_t *server_msg, void *data)
706 {
707  SCEnter();
708  int uptime;
709  UnixCommand *ucmd = (UnixCommand *)data;
710 
711  uptime = time(NULL) - ucmd->start_timestamp;
712  json_object_set_new(server_msg, "message", json_integer(uptime));
714 }
715 
716 static TmEcode UnixManagerRunningModeCommand(json_t *cmd,
717  json_t *server_msg, void *data)
718 {
719  SCEnter();
720  json_object_set_new(server_msg, "message", json_string(RunmodeGetActive()));
722 }
723 
724 static TmEcode UnixManagerCaptureModeCommand(json_t *cmd,
725  json_t *server_msg, void *data)
726 {
727  SCEnter();
728  json_object_set_new(server_msg, "message", json_string(RunModeGetMainMode()));
730 }
731 
732 static TmEcode UnixManagerReloadRulesWrapper(json_t *cmd, json_t *server_msg, void *data, int do_wait)
733 {
734  SCEnter();
735 
736  if (SuriHasSigFile()) {
737  json_object_set_new(server_msg, "message",
738  json_string("Live rule reload not possible if -s "
739  "or -S option used at runtime."));
741  }
742 
743  int r = DetectEngineReloadStart();
744 
745  if (r == 0 && do_wait) {
746  while (!DetectEngineReloadIsIdle())
747  usleep(100);
748  } else {
749  if (r == -1) {
750  json_object_set_new(server_msg, "message", json_string("Reload already in progress"));
752  }
753  }
754 
755  json_object_set_new(server_msg, "message", json_string("done"));
757 }
758 
759 static TmEcode UnixManagerReloadRules(json_t *cmd, json_t *server_msg, void *data)
760 {
761  return UnixManagerReloadRulesWrapper(cmd, server_msg, data, 1);
762 }
763 
764 static TmEcode UnixManagerNonBlockingReloadRules(json_t *cmd, json_t *server_msg, void *data)
765 {
766  return UnixManagerReloadRulesWrapper(cmd, server_msg, data, 0);
767 }
768 
769 static TmEcode UnixManagerReloadTimeCommand(json_t *cmd,
770  json_t *server_msg, void *data)
771 {
772  SCEnter();
773  TmEcode retval;
774  json_t *jdata = NULL;
775 
776  retval = OutputEngineStatsReloadTime(&jdata);
777  json_object_set_new(server_msg, "message", jdata);
778  SCReturnInt(retval);
779 }
780 
781 static TmEcode UnixManagerRulesetStatsCommand(json_t *cmd,
782  json_t *server_msg, void *data)
783 {
784  SCEnter();
785  TmEcode retval;
786  json_t *jdata = NULL;
787 
788  retval = OutputEngineStatsRuleset(&jdata);
789  json_object_set_new(server_msg, "message", jdata);
790  SCReturnInt(retval);
791 }
792 
793 static TmEcode UnixManagerShowFailedRules(json_t *cmd,
794  json_t *server_msg, void *data)
795 {
796  SCEnter();
797  int rules_cnt = 0;
799  if (de_ctx == NULL) {
800  json_object_set_new(server_msg, "message", json_string("Unable to get info"));
802  }
803 
804  /* Since we need to deference de_ctx, we don't want to lost it. */
805  DetectEngineCtx *list = de_ctx;
806  json_t *js_sigs_array = json_array();
807 
808  if (js_sigs_array == NULL) {
809  json_object_set_new(server_msg, "message", json_string("Unable to get info"));
810  goto error;
811  }
812  while (list) {
813  SigString *sigs_str = NULL;
814  TAILQ_FOREACH(sigs_str, &list->sig_stat.failed_sigs, next) {
815  json_t *jdata = json_object();
816  if (jdata == NULL) {
817  json_object_set_new(server_msg, "message", json_string("Unable to get the sig"));
818  goto error;
819  }
820 
821  json_object_set_new(jdata, "tenant_id", json_integer(list->tenant_id));
822  json_object_set_new(jdata, "rule", json_string(sigs_str->sig_str));
823  json_object_set_new(jdata, "filename", json_string(sigs_str->filename));
824  json_object_set_new(jdata, "line", json_integer(sigs_str->line));
825  if (sigs_str->sig_error) {
826  json_object_set_new(jdata, "error", json_string(sigs_str->sig_error));
827  }
828  json_array_append_new(js_sigs_array, jdata);
829  if (++rules_cnt > MAX_FAILED_RULES) {
830  break;
831  }
832  }
833  if (rules_cnt > MAX_FAILED_RULES) {
834  break;
835  }
836  list = list->next;
837  }
838 
839  json_object_set_new(server_msg, "message", js_sigs_array);
842 
843 error:
845  json_object_clear(js_sigs_array);
846  json_decref(js_sigs_array);
848 }
849 
850 static TmEcode UnixManagerConfGetCommand(json_t *cmd,
851  json_t *server_msg, void *data)
852 {
853  SCEnter();
854 
855  const char *confval = NULL;
856  char *variable = NULL;
857 
858  json_t *jarg = json_object_get(cmd, "variable");
859  if(!json_is_string(jarg)) {
860  SCLogInfo("error: variable is not a string");
861  json_object_set_new(server_msg, "message", json_string("variable is not a string"));
863  }
864 
865  variable = (char *)json_string_value(jarg);
866  if (ConfGet(variable, &confval) != 1) {
867  json_object_set_new(server_msg, "message", json_string("Unable to get value"));
869  }
870 
871  if (confval) {
872  json_object_set_new(server_msg, "message", json_string(confval));
874  }
875 
876  json_object_set_new(server_msg, "message", json_string("No string value"));
878 }
879 
880 static TmEcode UnixManagerListCommand(json_t *cmd,
881  json_t *answer, void *data)
882 {
883  SCEnter();
884  json_t *jdata;
885  json_t *jarray;
886  Command *lcmd = NULL;
887  UnixCommand *gcmd = (UnixCommand *) data;
888  int i = 0;
889 
890  jdata = json_object();
891  if (jdata == NULL) {
892  json_object_set_new(answer, "message",
893  json_string("internal error at json object creation"));
894  return TM_ECODE_FAILED;
895  }
896  jarray = json_array();
897  if (jarray == NULL) {
898  json_object_set_new(answer, "message",
899  json_string("internal error at json object creation"));
900  return TM_ECODE_FAILED;
901  }
902 
903  TAILQ_FOREACH(lcmd, &gcmd->commands, next) {
904  json_array_append_new(jarray, json_string(lcmd->name));
905  i++;
906  }
907 
908  json_object_set_new(jdata, "count", json_integer(i));
909  json_object_set_new(jdata, "commands", jarray);
910  json_object_set_new(answer, "message", jdata);
912 }
913 
914 static TmEcode UnixManagerReopenLogFiles(json_t *cmd, json_t *server_msg, void *data)
915 {
917  json_object_set_new(server_msg, "message", json_string("done"));
919 }
920 
921 #if 0
922 TmEcode UnixManagerReloadRules(json_t *cmd,
923  json_t *server_msg, void *data)
924 {
925  SCEnter();
926  if (suricata_ctl_flags != 0) {
927  json_object_set_new(server_msg, "message",
928  json_string("Live rule swap no longer possible."
929  " Engine in shutdown mode."));
931  } else {
932  /* FIXME : need to check option value */
933  UtilSignalHandlerSetup(SIGUSR2, SignalHandlerSigusr2Idle);
934  DetectEngineSpawnLiveRuleSwapMgmtThread();
935  json_object_set_new(server_msg, "message", json_string("Reloading rules"));
936  }
938 }
939 #endif
940 
941 static UnixCommand command;
942 
943 /**
944  * \brief Add a command to the list of commands
945  *
946  * This function adds a command to the list of commands available
947  * through the unix socket.
948  *
949  * When a command is received from user through the unix socket, the content
950  * of 'Command' field in the JSON message is match against keyword, then the
951  * Func is called. See UnixSocketAddPcapFile() for an example.
952  *
953  * \param keyword name of the command
954  * \param Func function to run when command is received
955  * \param data a pointer to data that are passed to Func when it is run
956  * \param flags a flag now used to tune the command type
957  * \retval TM_ECODE_OK in case of success, TM_ECODE_FAILED in case of failure
958  */
959 TmEcode UnixManagerRegisterCommand(const char * keyword,
960  TmEcode (*Func)(json_t *, json_t *, void *),
961  void *data, int flags)
962 {
963  SCEnter();
964  Command *cmd = NULL;
965  Command *lcmd = NULL;
966 
967  if (Func == NULL) {
968  SCLogError(SC_ERR_INVALID_ARGUMENT, "Null function");
970  }
971 
972  if (keyword == NULL) {
973  SCLogError(SC_ERR_INVALID_ARGUMENT, "Null keyword");
975  }
976 
977  TAILQ_FOREACH(lcmd, &command.commands, next) {
978  if (!strcmp(keyword, lcmd->name)) {
979  SCLogError(SC_ERR_INVALID_ARGUMENT, "%s already registered", keyword);
981  }
982  }
983 
984  cmd = SCMalloc(sizeof(Command));
985  if (unlikely(cmd == NULL)) {
986  SCLogError(SC_ERR_MEM_ALLOC, "Can't alloc cmd");
988  }
989  cmd->name = SCStrdup(keyword);
990  if (unlikely(cmd->name == NULL)) {
991  SCLogError(SC_ERR_MEM_ALLOC, "Can't alloc cmd name");
992  SCFree(cmd);
994  }
995  cmd->Func = Func;
996  cmd->data = data;
997  cmd->flags = flags;
998  /* Add it to the list */
999  TAILQ_INSERT_TAIL(&command.commands, cmd, next);
1000 
1002 }
1003 
1004 /**
1005  * \brief Add a task to the list of tasks
1006  *
1007  * This function adds a task to run in the background. The task is run
1008  * each time the UnixMain() function exits from select.
1009  *
1010  * \param Func function to run when a command is received
1011  * \param data a pointer to data that are passed to Func when it is run
1012  * \retval TM_ECODE_OK in case of success, TM_ECODE_FAILED in case of failure
1013  */
1014 TmEcode UnixManagerRegisterBackgroundTask(TmEcode (*Func)(void *),
1015  void *data)
1016 {
1017  SCEnter();
1018  Task *task = NULL;
1019 
1020  if (Func == NULL) {
1021  SCLogError(SC_ERR_INVALID_ARGUMENT, "Null function");
1023  }
1024 
1025  task = SCMalloc(sizeof(Task));
1026  if (unlikely(task == NULL)) {
1027  SCLogError(SC_ERR_MEM_ALLOC, "Can't alloc task");
1029  }
1030  task->Func = Func;
1031  task->data = data;
1032  /* Add it to the list */
1033  TAILQ_INSERT_TAIL(&command.tasks, task, next);
1034 
1036 }
1037 
1038 int UnixManagerInit(void)
1039 {
1040  if (UnixNew(&command) == 0) {
1041  int failure_fatal = 0;
1042  if (ConfGetBool("engine.init-failure-fatal", &failure_fatal) != 1) {
1043  SCLogDebug("ConfGetBool could not load the value.");
1044  }
1045  if (failure_fatal) {
1047  "Unable to create unix command socket");
1048  exit(EXIT_FAILURE);
1049  } else {
1051  "Unable to create unix command socket");
1052  return -1;
1053  }
1054  }
1055 
1056  /* Init Unix socket */
1057  UnixManagerRegisterCommand("shutdown", UnixManagerShutdownCommand, NULL, 0);
1058  UnixManagerRegisterCommand("command-list", UnixManagerListCommand, &command, 0);
1059  UnixManagerRegisterCommand("help", UnixManagerListCommand, &command, 0);
1060  UnixManagerRegisterCommand("version", UnixManagerVersionCommand, &command, 0);
1061  UnixManagerRegisterCommand("uptime", UnixManagerUptimeCommand, &command, 0);
1062  UnixManagerRegisterCommand("running-mode", UnixManagerRunningModeCommand, &command, 0);
1063  UnixManagerRegisterCommand("capture-mode", UnixManagerCaptureModeCommand, &command, 0);
1064  UnixManagerRegisterCommand("conf-get", UnixManagerConfGetCommand, &command, UNIX_CMD_TAKE_ARGS);
1065  UnixManagerRegisterCommand("dump-counters", StatsOutputCounterSocket, NULL, 0);
1066  UnixManagerRegisterCommand("reload-rules", UnixManagerReloadRules, NULL, 0);
1067  UnixManagerRegisterCommand("ruleset-reload-rules", UnixManagerReloadRules, NULL, 0);
1068  UnixManagerRegisterCommand("ruleset-reload-nonblocking", UnixManagerNonBlockingReloadRules, NULL, 0);
1069  UnixManagerRegisterCommand("ruleset-reload-time", UnixManagerReloadTimeCommand, NULL, 0);
1070  UnixManagerRegisterCommand("ruleset-stats", UnixManagerRulesetStatsCommand, NULL, 0);
1071  UnixManagerRegisterCommand("ruleset-failed-rules", UnixManagerShowFailedRules, NULL, 0);
1072  UnixManagerRegisterCommand("register-tenant-handler", UnixSocketRegisterTenantHandler, &command, UNIX_CMD_TAKE_ARGS);
1073  UnixManagerRegisterCommand("unregister-tenant-handler", UnixSocketUnregisterTenantHandler, &command, UNIX_CMD_TAKE_ARGS);
1074  UnixManagerRegisterCommand("register-tenant", UnixSocketRegisterTenant, &command, UNIX_CMD_TAKE_ARGS);
1075  UnixManagerRegisterCommand("reload-tenant", UnixSocketReloadTenant, &command, UNIX_CMD_TAKE_ARGS);
1076  UnixManagerRegisterCommand("unregister-tenant", UnixSocketUnregisterTenant, &command, UNIX_CMD_TAKE_ARGS);
1077  UnixManagerRegisterCommand("add-hostbit", UnixSocketHostbitAdd, &command, UNIX_CMD_TAKE_ARGS);
1078  UnixManagerRegisterCommand("remove-hostbit", UnixSocketHostbitRemove, &command, UNIX_CMD_TAKE_ARGS);
1079  UnixManagerRegisterCommand("list-hostbit", UnixSocketHostbitList, &command, UNIX_CMD_TAKE_ARGS);
1080  UnixManagerRegisterCommand("reopen-log-files", UnixManagerReopenLogFiles, NULL, 0);
1081  UnixManagerRegisterCommand("memcap-set", UnixSocketSetMemcap, &command, UNIX_CMD_TAKE_ARGS);
1082  UnixManagerRegisterCommand("memcap-show", UnixSocketShowMemcap, &command, UNIX_CMD_TAKE_ARGS);
1083  UnixManagerRegisterCommand("memcap-list", UnixSocketShowAllMemcap, NULL, 0);
1084 
1085  UnixManagerRegisterCommand("dataset-add", UnixSocketDatasetAdd, &command, UNIX_CMD_TAKE_ARGS);
1086  UnixManagerRegisterCommand("dataset-remove", UnixSocketDatasetRemove, &command, UNIX_CMD_TAKE_ARGS);
1087 
1088  return 0;
1089 }
1090 
1091 typedef struct UnixManagerThreadData_ {
1092  int padding;
1093 } UnixManagerThreadData;
1094 
1095 static TmEcode UnixManagerThreadInit(ThreadVars *t, const void *initdata, void **data)
1096 {
1097  UnixManagerThreadData *utd = SCCalloc(1, sizeof(*utd));
1098  if (utd == NULL)
1099  return TM_ECODE_FAILED;
1100 
1101  *data = utd;
1102  return TM_ECODE_OK;
1103 }
1104 
1105 static TmEcode UnixManagerThreadDeinit(ThreadVars *t, void *data)
1106 {
1107  SCFree(data);
1108  return TM_ECODE_OK;
1109 }
1110 
1111 static TmEcode UnixManager(ThreadVars *th_v, void *thread_data)
1112 {
1113  int ret;
1114 
1115  /* set the thread name */
1116  SCLogDebug("%s started...", th_v->name);
1117 
1118  StatsSetupPrivate(th_v);
1119 
1120  /* Set the threads capability */
1121  th_v->cap_flags = 0;
1122  SCDropCaps(th_v);
1123 
1125  while (1) {
1126  ret = UnixMain(&command);
1127  if (ret == 0) {
1128  SCLogError(SC_ERR_FATAL, "Fatal error on unix socket");
1129  }
1130 
1131  if ((ret == 0) || (TmThreadsCheckFlag(th_v, THV_KILL))) {
1132  UnixClient *item;
1133  UnixClient *titem;
1134  TAILQ_FOREACH_SAFE(item, &(&command)->clients, next, titem) {
1135  close(item->fd);
1136  SCFree(item);
1137  }
1138  StatsSyncCounters(th_v);
1139  break;
1140  }
1141 
1142  UnixCommandBackgroundTasks(&command);
1143  }
1144  return TM_ECODE_OK;
1145 }
1146 
1147 
1148 /** \brief Spawn the unix socket manager thread
1149  *
1150  * \param mode if set to 1, init failure cause suricata exit
1151  * */
1152 void UnixManagerThreadSpawn(int mode)
1153 {
1154  ThreadVars *tv_unixmgr = NULL;
1155 
1158 
1160  "UnixManager", 0);
1161 
1162  if (tv_unixmgr == NULL) {
1163  SCLogError(SC_ERR_INITIALIZATION, "TmThreadsCreate failed");
1164  exit(EXIT_FAILURE);
1165  }
1166  if (TmThreadSpawn(tv_unixmgr) != TM_ECODE_OK) {
1167  SCLogError(SC_ERR_INITIALIZATION, "TmThreadSpawn failed");
1168  exit(EXIT_FAILURE);
1169  }
1170  if (mode == 1) {
1171  if (TmThreadsCheckFlag(tv_unixmgr, THV_RUNNING_DONE)) {
1172  SCLogError(SC_ERR_INITIALIZATION, "Unix socket init failed");
1173  exit(EXIT_FAILURE);
1174  }
1175  }
1176  return;
1177 }
1178 
1179 // TODO can't think of a good name
1181 {
1182  /* Spawn the unix socket manager thread */
1183  int unix_socket = ConfUnixSocketIsEnable();
1184  if (unix_socket == 1) {
1185  if (UnixManagerInit() == 0) {
1186  UnixManagerRegisterCommand("iface-stat", LiveDeviceIfaceStat, NULL,
1188  UnixManagerRegisterCommand("iface-list", LiveDeviceIfaceList, NULL, 0);
1189  UnixManagerRegisterCommand("iface-bypassed-stat",
1190  LiveDeviceGetBypassedStats, NULL, 0);
1191  /* For backward compatibility */
1192  UnixManagerRegisterCommand("ebpf-bypassed-stat",
1193  LiveDeviceGetBypassedStats, NULL, 0);
1195  }
1196  }
1197 }
1198 
1199 /**
1200  * \brief Used to kill unix manager thread(s).
1201  *
1202  * \todo Kinda hackish since it uses the tv name to identify unix manager
1203  * thread. We need an all weather identification scheme.
1204  */
1205 void UnixSocketKillSocketThread(void)
1206 {
1207  ThreadVars *tv = NULL;
1208 
1209 again:
1211 
1212  /* unix manager thread(s) is/are a part of command threads */
1213  tv = tv_root[TVT_CMD];
1214 
1215  while (tv != NULL) {
1216  if (strcasecmp(tv->name, "UnixManagerThread") == 0) {
1217  /* If the thread dies during init it will have
1218  * THV_RUNNING_DONE set, so we can set the correct flag
1219  * and exit.
1220  */
1225  break;
1226  }
1229  /* Be sure it has shut down */
1230  if (!TmThreadsCheckFlag(tv, THV_CLOSED)) {
1232  usleep(100);
1233  goto again;
1234  }
1235  }
1236  tv = tv->next;
1237  }
1238 
1240  return;
1241 }
1242 
1243 #else /* BUILD_UNIX_SOCKET */
1244 
1246 {
1247  SCLogError(SC_ERR_UNIMPLEMENTED, "Unix socket is not compiled");
1248  return;
1249 }
1250 
1252 {
1253  return;
1254 }
1255 
1257 {
1258  return;
1259 }
1260 
1261 #endif /* BUILD_UNIX_SOCKET */
1262 
1264 {
1265 #if defined(BUILD_UNIX_SOCKET) && defined(HAVE_SYS_UN_H) && defined(HAVE_SYS_STAT_H) && defined(HAVE_SYS_TYPES_H)
1266  tmm_modules[TMM_UNIXMANAGER].name = "UnixManager";
1267  tmm_modules[TMM_UNIXMANAGER].ThreadInit = UnixManagerThreadInit;
1268  tmm_modules[TMM_UNIXMANAGER].ThreadDeinit = UnixManagerThreadDeinit;
1269  tmm_modules[TMM_UNIXMANAGER].Management = UnixManager;
1272 #endif /* BUILD_UNIX_SOCKET */
1273 }
TmModule_::cap_flags
uint8_t cap_flags
Definition: tm-modules.h:67
tm-threads.h
DetectEngineCtx_::tenant_id
int tenant_id
Definition: detect.h:770
TmModuleUnixManagerRegister
void TmModuleUnixManagerRegister(void)
Definition: unix-manager.c:1263
len
uint8_t len
Definition: app-layer-dnp3.h:2
TmThreadSpawn
TmEcode TmThreadSpawn(ThreadVars *tv)
Spawns a thread associated with the ThreadVars instance tv.
Definition: tm-threads.c:1630
detect-engine.h
offset
uint64_t offset
Definition: util-streaming-buffer.h:0
DetectEngineDeReference
void DetectEngineDeReference(DetectEngineCtx **de_ctx)
Definition: detect-engine.c:3929
ThreadVars_::name
char name[16]
Definition: threadvars.h:65
SC_ERR_INVALID_VALUE
@ SC_ERR_INVALID_VALUE
Definition: util-error.h:160
TAILQ_INIT
#define TAILQ_INIT(head)
Definition: queue.h:370
SC_ERR_SOCKET
@ SC_ERR_SOCKET
Definition: util-error.h:232
ConfGetBool
int ConfGetBool(const char *name, int *val)
Retrieve a configuration value as an boolen.
Definition: conf.c:517
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
MemBufferExpand
int MemBufferExpand(MemBuffer **buffer, uint32_t expand_by)
expand membuffer by size of 'expand_by'
Definition: util-buffer.c:60
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:298
SigString_
Definition: detect.h:719
TmThreadsSetFlag
void TmThreadsSetFlag(ThreadVars *tv, uint32_t flag)
Set a thread flag.
Definition: tm-threads.c:97
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:0
THV_DEINIT
#define THV_DEINIT
Definition: threadvars.h:46
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:766
UnixManagerThreadSpawn
void UnixManagerThreadSpawn(int mode)
Definition: unix-manager.c:1245
DetectEngineGetCurrent
DetectEngineCtx * DetectEngineGetCurrent(void)
Definition: detect-engine.c:3228
UtilSignalHandlerSetup
void UtilSignalHandlerSetup(int sig, void(*handler)(int))
Definition: util-signal.c:60
TAILQ_FOREACH
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:350
SURICATA_STOP
#define SURICATA_STOP
Definition: suricata.h:90
StatsSetupPrivate
int StatsSetupPrivate(ThreadVars *tv)
Definition: counters.c:1200
SCMutexLock
#define SCMutexLock(mut)
Definition: threads-debug.h:117
tv_root
ThreadVars * tv_root[TVT_MAX]
Definition: tm-threads.c:78
util-privs.h
OutputJSONMemBufferWrapper_::buffer
MemBuffer ** buffer
Definition: output-json.h:66
SCDropCaps
#define SCDropCaps(...)
Definition: util-privs.h:37
TAILQ_INSERT_TAIL
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:385
RunmodeGetActive
char * RunmodeGetActive(void)
Definition: runmodes.c:187
JSON_ESCAPE_SLASH
#define JSON_ESCAPE_SLASH
Definition: suricata-common.h:258
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:79
TM_ECODE_OK
@ TM_ECODE_OK
Definition: tm-threads-common.h:78
ThreadVars_::cap_flags
uint8_t cap_flags
Definition: threadvars.h:81
strlcpy
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: util-strlcpyu.c:43
TmModule_::ThreadDeinit
TmEcode(* ThreadDeinit)(ThreadVars *, void *)
Definition: tm-modules.h:49
TAILQ_ENTRY
#define TAILQ_ENTRY(type)
Definition: queue.h:330
SigString_::sig_error
char * sig_error
Definition: detect.h:722
THV_RUNNING_DONE
#define THV_RUNNING_DONE
Definition: threadvars.h:47
util-signal.h
ConfGet
int ConfGet(const char *name, const char **vptr)
Retrieve the value of a configuration node.
Definition: conf.c:331
SCCtrlCondInit
#define SCCtrlCondInit
Definition: threads-debug.h:383
UnixManagerThreadSpawnNonRunmode
void UnixManagerThreadSpawnNonRunmode(void)
Definition: unix-manager.c:1256
TAILQ_REMOVE
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:412
util-device.h
util-debug.h
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:17
output-json.h
SCMutexUnlock
#define SCMutexUnlock(mut)
Definition: threads-debug.h:119
MemBufferWriteRaw
#define MemBufferWriteRaw(dst, raw_buffer, raw_buffer_len)
Write a raw buffer to the MemBuffer dst.
Definition: util-buffer.h:133
UnixSocketKillSocketThread
void UnixSocketKillSocketThread(void)
Definition: unix-manager.c:1251
TMM_UNIXMANAGER
@ TMM_UNIXMANAGER
Definition: tm-threads-common.h:71
SCEnter
#define SCEnter(...)
Definition: util-debug.h:300
SCCtrlCondT
#define SCCtrlCondT
Definition: threads-debug.h:382
util-ebpf.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:58
TmModule_::Management
TmEcode(* Management)(ThreadVars *, void *)
Definition: tm-modules.h:59
THV_KILL
#define THV_KILL
Definition: threadvars.h:41
DetectEngineReloadIsIdle
int DetectEngineReloadIsIdle(void)
Definition: detect-engine.c:1568
SC_ERR_INVALID_ARGUMENT
@ SC_ERR_INVALID_ARGUMENT
Definition: util-error.h:43
GetProgramVersion
const char * GetProgramVersion(void)
get string with program version
Definition: suricata.c:1043
ThreadVars_::next
struct ThreadVars_ * next
Definition: threadvars.h:123
OutputEngineStatsReloadTime
TmEcode OutputEngineStatsReloadTime(json_t **jdata)
Definition: output-json-stats.c:160
tv_root_lock
SCMutex tv_root_lock
Definition: tm-threads.c:81
SCReturn
#define SCReturn
Definition: util-debug.h:302
OutputJSONMemBufferWrapper_
Definition: output-json.h:65
tmm_modules
TmModule tmm_modules[TMM_SIZE]
Definition: tm-modules.c:33
conf.h
OutputNotifyFileRotation
void OutputNotifyFileRotation(void)
Notifies all registered file rotation notification flags.
Definition: output.c:918
UNIX_CMD_TAKE_ARGS
#define UNIX_CMD_TAKE_ARGS
Definition: unix-manager.h:27
TmEcode
TmEcode
Definition: tm-threads-common.h:77
padding
uint32_t padding
Definition: decode-erspan.h:2
TVT_CMD
@ TVT_CMD
Definition: tm-threads-common.h:87
TmModule_::name
const char * name
Definition: tm-modules.h:44
MemBuffer_
Definition: util-buffer.h:27
runmodes.h
SCLogInfo
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:217
TAILQ_FOREACH_SAFE
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:356
SigString_::filename
char * filename
Definition: detect.h:720
THV_INIT_DONE
#define THV_INIT_DONE
Definition: threadvars.h:38
MemBufferReset
#define MemBufferReset(mem_buffer)
Reset the mem buffer.
Definition: util-buffer.h:42
DetectEngineCtx_::sig_stat
SigFileLoaderStat sig_stat
Definition: detect.h:947
flags
uint8_t flags
Definition: decode-gre.h:0
SuriHasSigFile
int SuriHasSigFile(void)
Definition: suricata.c:239
suricata-common.h
output-json-stats.h
SigString_::line
int line
Definition: detect.h:723
SCCtrlMutex
#define SCCtrlMutex
Definition: threads-debug.h:373
DetectEngineCtx_::next
struct DetectEngineCtx_ * next
Definition: detect.h:904
UnixManagerInit
int UnixManagerInit(void)
MemBufferFree
void MemBufferFree(MemBuffer *buffer)
Definition: util-buffer.c:82
PathIsAbsolute
int PathIsAbsolute(const char *path)
Check if a path is absolute.
Definition: util-path.c:39
SCLogError
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:257
version
uint8_t version
Definition: decode-gre.h:1
TmModule_::ThreadInit
TmEcode(* ThreadInit)(ThreadVars *, const void *, void **)
Definition: tm-modules.h:47
SCMkDir
#define SCMkDir(a, b)
Definition: util-path.h:29
SCStrdup
#define SCStrdup(s)
Definition: util-mem.h:56
EngineStop
void EngineStop(void)
make sure threads can stop the engine by calling this function. Purpose: pcap file mode needs to be a...
Definition: suricata.c:391
TmThreadCreateCmdThreadByName
ThreadVars * TmThreadCreateCmdThreadByName(const char *name, const char *module, int mucond)
Creates and returns the TV instance for a Command thread (CMD). This function supports only custom sl...
Definition: tm-threads.c:1132
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:29
SC_ERR_UNIMPLEMENTED
@ SC_ERR_UNIMPLEMENTED
Definition: util-error.h:118
unix_manager_ctrl_mutex
SCCtrlMutex unix_manager_ctrl_mutex
ConfUnixSocketIsEnable
int ConfUnixSocketIsEnable(void)
Definition: util-conf.c:144
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
unix-manager.h
DetectEngineReloadStart
int DetectEngineReloadStart(void)
Definition: detect-engine.c:1534
SCLogWarning
#define SCLogWarning(err_code,...)
Macro used to log WARNING messages.
Definition: util-debug.h:244
SCFree
#define SCFree(p)
Definition: util-mem.h:61
SC_ERR_FATAL
@ SC_ERR_FATAL
Definition: util-error.h:203
MEMBUFFER_SIZE
#define MEMBUFFER_SIZE(mem_buffer)
Get the MemBuffers current size.
Definition: util-buffer.h:60
util-buffer.h
unix_manager_ctrl_cond
SCCtrlCondT unix_manager_ctrl_cond
TAILQ_HEAD
#define TAILQ_HEAD(name, type)
Definition: queue.h:321
SCCtrlMutexInit
#define SCCtrlMutexInit(mut, mutattr)
Definition: threads-debug.h:375
OutputJSONMemBufferCallback
int OutputJSONMemBufferCallback(const char *str, size_t size, void *data)
Definition: output-json.c:1389
TM_FLAG_COMMAND_TM
#define TM_FLAG_COMMAND_TM
Definition: tm-modules.h:37
SC_ERR_MEM_ALLOC
@ SC_ERR_MEM_ALLOC
Definition: util-error.h:31
suricata.h
OutputEngineStatsRuleset
TmEcode OutputEngineStatsRuleset(json_t **jdata)
Definition: output-json-stats.c:164
thread_name_unix_socket
const char * thread_name_unix_socket
Definition: runmodes.c:68
StatsSyncCounters
#define StatsSyncCounters(tv)
Definition: counters.h:134
RunModeGetMainMode
const char * RunModeGetMainMode(void)
Definition: runmodes.c:199
SC_ERR_INITIALIZATION
@ SC_ERR_INITIALIZATION
Definition: util-error.h:75
MEMBUFFER_BUFFER
#define MEMBUFFER_BUFFER(mem_buffer)
Get the MemBuffers underlying buffer.
Definition: util-buffer.h:50
SigString_::sig_str
char * sig_str
Definition: detect.h:721
TmThreadsCheckFlag
int TmThreadsCheckFlag(ThreadVars *tv, uint32_t flag)
Check if a thread flag is set.
Definition: tm-threads.c:89
MEMBUFFER_OFFSET
#define MEMBUFFER_OFFSET(mem_buffer)
Get the MemBuffers current offset.
Definition: util-buffer.h:55
THV_CLOSED
#define THV_CLOSED
Definition: threadvars.h:43
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:304
SC_ERR_OPENING_FILE
@ SC_ERR_OPENING_FILE
Definition: util-error.h:70
TmModule_::flags
uint8_t flags
Definition: tm-modules.h:70
MemBufferCreateNew
MemBuffer * MemBufferCreateNew(uint32_t size)
Definition: util-buffer.c:32
output.h
suricata_ctl_flags
volatile uint8_t suricata_ctl_flags
Definition: suricata.c:198