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