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-private.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  socklen_t 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 (SCConfGet("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 = (socklen_t)(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  UnixClient *safe = NULL;
256  int found = 0;
257 
258  TAILQ_FOREACH_SAFE (item, &this->clients, next, safe) {
259  if (item->fd == fd) {
260  found = 1;
261  break;
262  }
263  }
264 
265  if (found == 0) {
266  SCLogError("No fd found in client list");
267  return;
268  }
269 
270  TAILQ_REMOVE(&this->clients, item, next);
271 
272  close(item->fd);
273  UnixCommandSetMaxFD(this);
274  UnixClientFree(item);
275 }
276 
277 #define UNIX_PROTO_VERSION_LENGTH 200
278 #define UNIX_PROTO_VERSION_V1 "0.1"
279 #define UNIX_PROTO_V1 1
280 #define UNIX_PROTO_VERSION "0.2"
281 #define UNIX_PROTO_V2 2
282 
283 static int UnixCommandSendJSONToClient(UnixClient *client, json_t *js)
284 {
285  MemBufferReset(client->mbuf);
286 
287  OutputJSONMemBufferWrapper wrapper = {
288  .buffer = &client->mbuf,
289  .expand_by = CLIENT_BUFFER_SIZE
290  };
291 
292  int r = json_dump_callback(js, OutputJSONMemBufferCallback, &wrapper,
293  JSON_PRESERVE_ORDER|JSON_COMPACT|JSON_ENSURE_ASCII|
295  if (r != 0) {
296  SCLogWarning("unable to serialize JSON object");
297  return -1;
298  }
299 
300  if (client->version > UNIX_PROTO_V1) {
301  if (MEMBUFFER_OFFSET(client->mbuf) + 1 >= MEMBUFFER_SIZE(client->mbuf)) {
302  MemBufferExpand(&client->mbuf, 1);
303  }
304  MemBufferWriteString(client->mbuf, "\n");
305  }
306 
307  if (send(client->fd, (const char *)MEMBUFFER_BUFFER(client->mbuf),
308  MEMBUFFER_OFFSET(client->mbuf), MSG_NOSIGNAL) == -1)
309  {
310  SCLogWarning("unable to send block of size "
311  "%" PRIuMAX ": %s",
312  (uintmax_t)MEMBUFFER_OFFSET(client->mbuf), strerror(errno));
313  return -1;
314  }
315 
316  SCLogDebug("sent message of size %"PRIuMAX" to client socket %d",
317  (uintmax_t)MEMBUFFER_OFFSET(client->mbuf), client->fd);
318  return 0;
319 }
320 
321 /**
322  * \brief Accept a new client on unix socket
323  *
324  * The function is called when a new user is detected
325  * in UnixMain(). It does the initial protocol negotiation
326  * with client.
327  *
328  * \retval 0 in case of error, 1 in case of success
329  */
330 static int UnixCommandAccept(UnixCommand *this)
331 {
332  char buffer[UNIX_PROTO_VERSION_LENGTH + 1];
333  json_t *client_msg;
334  json_t *server_msg;
335  json_t *version;
336  json_error_t jerror;
337  int client;
338  int client_version;
339  ssize_t ret;
340  UnixClient *uclient = NULL;
341 
342  /* accept client socket */
343  socklen_t len = sizeof(this->client_addr);
344  client = accept(this->socket, (struct sockaddr *) &this->client_addr,
345  &len);
346  if (client < 0) {
347  SCLogInfo("Unix socket: accept() error: %s",
348  strerror(errno));
349  return 0;
350  }
351  SCLogDebug("Unix socket: client connection");
352 
353  /* read client version */
354  buffer[sizeof(buffer)-1] = 0;
355  ret = recv(client, buffer, sizeof(buffer)-1, 0);
356  if (ret < 0) {
357  SCLogInfo("Command server: client doesn't send version");
358  close(client);
359  return 0;
360  }
361  if (ret >= (int)(sizeof(buffer)-1)) {
362  SCLogInfo("Command server: client message is too long, "
363  "disconnect him.");
364  close(client);
365  return 0;
366  }
367  buffer[ret] = 0;
368 
369  client_msg = json_loads(buffer, 0, &jerror);
370  if (client_msg == NULL) {
371  SCLogInfo("Invalid command, error on line %d: %s\n", jerror.line, jerror.text);
372  close(client);
373  return 0;
374  }
375 
376  version = json_object_get(client_msg, "version");
377  if (!json_is_string(version)) {
378  SCLogInfo("error: version is not a string");
379  close(client);
380  json_decref(client_msg);
381  return 0;
382  }
383 
384  /* check client version */
385  if ((strcmp(json_string_value(version), UNIX_PROTO_VERSION) != 0)
386  && (strcmp(json_string_value(version), UNIX_PROTO_VERSION_V1) != 0)) {
387  SCLogInfo("Unix socket: invalid client version: \"%s\"",
388  json_string_value(version));
389  json_decref(client_msg);
390  close(client);
391  return 0;
392  } else {
393  SCLogDebug("Unix socket: client version: \"%s\"",
394  json_string_value(version));
395  if (strcmp(json_string_value(version), UNIX_PROTO_VERSION_V1) == 0) {
396  client_version = UNIX_PROTO_V1;
397  } else {
398  client_version = UNIX_PROTO_V2;
399  }
400  }
401 
402  json_decref(client_msg);
403  /* send answer */
404  server_msg = json_object();
405  if (server_msg == NULL) {
406  close(client);
407  return 0;
408  }
409  json_object_set_new(server_msg, "return", json_string("OK"));
410 
411  uclient = UnixClientAlloc();
412  if (unlikely(uclient == NULL)) {
413  json_decref(server_msg);
414  close(client);
415  return 0;
416  }
417  uclient->fd = client;
418  uclient->version = client_version;
419 
420  if (UnixCommandSendJSONToClient(uclient, server_msg) != 0) {
421  SCLogWarning("Unable to send command");
422 
423  UnixClientFree(uclient);
424  json_decref(server_msg);
425  close(client);
426  return 0;
427  }
428 
429  json_decref(server_msg);
430 
431  /* client connected */
432  SCLogDebug("Unix socket: client connected");
433  TAILQ_INSERT_TAIL(&this->clients, uclient, next);
434  UnixCommandSetMaxFD(this);
435  return 1;
436 }
437 
438 static int UnixCommandBackgroundTasks(UnixCommand* this)
439 {
440  int ret = 1;
441  Task *ltask;
442 
443  TAILQ_FOREACH(ltask, &this->tasks, next) {
444  int fret = ltask->Func(ltask->data);
445  if (fret != TM_ECODE_OK) {
446  ret = 0;
447  }
448  }
449  return ret;
450 }
451 
452 /**
453  * \brief Command dispatcher
454  *
455  * \param this a UnixCommand:: structure
456  * \param command a string containing a json formatted
457  * command
458  *
459  * \retval 0 in case of error, 1 in case of success
460  */
461 static int UnixCommandExecute(UnixCommand * this, char *command, UnixClient *client)
462 {
463  int ret = 1;
464  json_error_t error;
465  json_t *jsoncmd = NULL;
466  json_t *cmd = NULL;
467  json_t *server_msg = json_object();
468  const char * value;
469  int found = 0;
470  Command *lcmd;
471 
472  if (server_msg == NULL) {
473  return 0;
474  }
475 
476  jsoncmd = json_loads(command, 0, &error);
477  if (jsoncmd == NULL) {
478  SCLogInfo("Invalid command, error on line %d: %s\n", error.line, error.text);
479  goto error;
480  }
481 
482  cmd = json_object_get(jsoncmd, "command");
483  if(!json_is_string(cmd)) {
484  SCLogInfo("error: command is not a string");
485  goto error_cmd;
486  }
487  value = json_string_value(cmd);
488 
489  TAILQ_FOREACH(lcmd, &this->commands, next) {
490  if (!strcmp(value, lcmd->name)) {
491  int fret = TM_ECODE_OK;
492  found = 1;
493  if (lcmd->flags & UNIX_CMD_TAKE_ARGS) {
494  cmd = json_object_get(jsoncmd, "arguments");
495  if(!json_is_object(cmd)) {
496  SCLogInfo("error: argument is not an object");
497  goto error_cmd;
498  }
499  }
500  fret = lcmd->Func(cmd, server_msg, lcmd->data);
501  if (fret != TM_ECODE_OK) {
502  ret = 0;
503  }
504  break;
505  }
506  }
507 
508  if (found == 0) {
509  json_object_set_new(server_msg, "message", json_string("Unknown command"));
510  ret = 0;
511  }
512 
513  switch (ret) {
514  case 0:
515  json_object_set_new(server_msg, "return", json_string("NOK"));
516  break;
517  case 1:
518  json_object_set_new(server_msg, "return", json_string("OK"));
519  break;
520  }
521 
522  if (UnixCommandSendJSONToClient(client, server_msg) != 0) {
523  goto error_cmd;
524  }
525 
526  json_decref(jsoncmd);
527  json_decref(server_msg);
528  return ret;
529 
530 error_cmd:
531  json_decref(jsoncmd);
532 error:
533  json_decref(server_msg);
534  UnixCommandClose(this, client->fd);
535  return 0;
536 }
537 
538 static void UnixCommandRun(UnixCommand * this, UnixClient *client)
539 {
540  char buffer[4096];
541  ssize_t ret;
542  if (client->version <= UNIX_PROTO_V1) {
543  ret = recv(client->fd, buffer, sizeof(buffer) - 1, 0);
544  if (ret <= 0) {
545  if (ret == 0) {
546  SCLogDebug("Unix socket: lost connection with client");
547  } else {
548  SCLogError("Unix socket: error on recv() from client: %s", strerror(errno));
549  }
550  UnixCommandClose(this, client->fd);
551  return;
552  }
553  if (ret >= (int)(sizeof(buffer)-1)) {
554  SCLogError("Command server: client command is too long, "
555  "disconnect him.");
556  UnixCommandClose(this, client->fd);
557  }
558  buffer[ret] = 0;
559  } else {
560  int try = 0;
561  int offset = 0;
562  int cmd_over = 0;
563  ret = recv(client->fd, buffer + offset, sizeof(buffer) - offset - 1, 0);
564  do {
565  if (ret <= 0) {
566  if (ret == 0) {
567  SCLogDebug("Unix socket: lost connection with client");
568  } else {
569  SCLogError("Unix socket: error on recv() from client: %s", strerror(errno));
570  }
571  UnixCommandClose(this, client->fd);
572  return;
573  }
574  if (ret >= (int)(sizeof(buffer)- offset - 1)) {
575  SCLogInfo("Command server: client command is too long, "
576  "disconnect him.");
577  UnixCommandClose(this, client->fd);
578  }
579  if (buffer[ret - 1] == '\n') {
580  buffer[ret-1] = 0;
581  cmd_over = 1;
582  } else {
583  struct timeval tv;
584  fd_set select_set;
585  offset += ret;
586  do {
587  FD_ZERO(&select_set);
588  FD_SET(client->fd, &select_set);
589  tv.tv_sec = 0;
590  tv.tv_usec = 200 * 1000;
591  try++;
592  ret = select(client->fd, &select_set, NULL, NULL, &tv);
593  /* catch select() error */
594  if (ret == -1) {
595  /* Signal was caught: just ignore it */
596  if (errno != EINTR) {
597  SCLogInfo("Unix socket: lost connection with client");
598  UnixCommandClose(this, client->fd);
599  return;
600  }
601  }
602  } while (ret == 0 && try < 3);
603  if (ret > 0) {
604  ret = recv(client->fd, buffer + offset,
605  sizeof(buffer) - offset - 1, 0);
606  }
607  }
608  } while (try < 3 && cmd_over == 0);
609 
610  if (try == 3 && cmd_over == 0) {
611  SCLogInfo("Unix socket: incomplete client message, closing connection");
612  UnixCommandClose(this, client->fd);
613  return;
614  }
615  }
616  UnixCommandExecute(this, buffer, client);
617 }
618 
619 /**
620  * \brief Select function
621  *
622  * \retval 0 in case of error, 1 in case of success
623  */
624 static int UnixMain(UnixCommand * this)
625 {
626  struct timeval tv;
627  int ret;
628  fd_set select_set;
629  UnixClient *uclient;
630  UnixClient *tclient;
631 
633  TAILQ_FOREACH_SAFE (uclient, &this->clients, next, tclient) {
634  UnixCommandClose(this, uclient->fd);
635  }
636  return 1;
637  }
638 
639  /* Wait activity on the socket */
640  FD_ZERO(&select_set);
641  FD_SET(this->socket, &select_set);
642  TAILQ_FOREACH(uclient, &this->clients, next) {
643  FD_SET(uclient->fd, &select_set);
644  }
645 
646  tv.tv_sec = 0;
647  tv.tv_usec = 200 * 1000;
648  ret = select(this->select_max, &select_set, NULL, NULL, &tv);
649 
650  /* catch select() error */
651  if (ret == -1) {
652  /* Signal was caught: just ignore it */
653  if (errno == EINTR) {
654  return 1;
655  }
656  SCLogError("Command server: select() fatal error: %s", strerror(errno));
657  return 0;
658  }
659 
660  /* timeout: continue */
661  if (ret == 0) {
662  return 1;
663  }
664 
665  TAILQ_FOREACH_SAFE(uclient, &this->clients, next, tclient) {
666  if (FD_ISSET(uclient->fd, &select_set)) {
667  UnixCommandRun(this, uclient);
668  }
669  }
670  if (FD_ISSET(this->socket, &select_set)) {
671  if (!UnixCommandAccept(this))
672  return 1;
673  }
674 
675  return 1;
676 }
677 
678 static TmEcode UnixManagerShutdownCommand(json_t *cmd,
679  json_t *server_msg, void *data)
680 {
681  SCEnter();
682  json_object_set_new(server_msg, "message", json_string("Closing Suricata"));
683  EngineStop();
685 }
686 
687 static TmEcode UnixManagerVersionCommand(json_t *cmd,
688  json_t *server_msg, void *data)
689 {
690  SCEnter();
691  json_object_set_new(server_msg, "message", json_string(GetProgramVersion()));
693 }
694 
695 static TmEcode UnixManagerUptimeCommand(json_t *cmd,
696  json_t *server_msg, void *data)
697 {
698  SCEnter();
699  time_t uptime;
700  UnixCommand *ucmd = (UnixCommand *)data;
701 
702  uptime = time(NULL) - ucmd->start_timestamp;
703  json_object_set_new(server_msg, "message", json_integer(uptime));
705 }
706 
707 static TmEcode UnixManagerRunningModeCommand(json_t *cmd,
708  json_t *server_msg, void *data)
709 {
710  SCEnter();
711  json_object_set_new(server_msg, "message", json_string(RunmodeGetActive()));
713 }
714 
715 static TmEcode UnixManagerCaptureModeCommand(json_t *cmd,
716  json_t *server_msg, void *data)
717 {
718  SCEnter();
719  json_object_set_new(server_msg, "message", json_string(RunModeGetMainMode()));
721 }
722 
723 static TmEcode UnixManagerReloadRulesWrapper(json_t *cmd, json_t *server_msg, void *data, int do_wait)
724 {
725  SCEnter();
726 
727  if (SuriHasSigFile()) {
728  json_object_set_new(server_msg, "message",
729  json_string("Live rule reload not possible if -s "
730  "or -S option used at runtime."));
732  }
733 
734  int r = DetectEngineReloadStart();
735 
736  if (r == 0 && do_wait) {
737  while (!DetectEngineReloadIsIdle())
738  usleep(100);
739  } else {
740  if (r == -1) {
741  json_object_set_new(server_msg, "message", json_string("Reload already in progress"));
743  }
744  }
745 
746  json_object_set_new(server_msg, "message", json_string("done"));
748 }
749 
750 static TmEcode UnixManagerReloadRules(json_t *cmd, json_t *server_msg, void *data)
751 {
752  return UnixManagerReloadRulesWrapper(cmd, server_msg, data, 1);
753 }
754 
755 static TmEcode UnixManagerNonBlockingReloadRules(json_t *cmd, json_t *server_msg, void *data)
756 {
757  return UnixManagerReloadRulesWrapper(cmd, server_msg, data, 0);
758 }
759 
760 static TmEcode UnixManagerReloadTimeCommand(json_t *cmd,
761  json_t *server_msg, void *data)
762 {
763  SCEnter();
764  TmEcode retval;
765  json_t *jdata = NULL;
766 
767  retval = OutputEngineStatsReloadTime(&jdata);
768  json_object_set_new(server_msg, "message", jdata);
769  SCReturnInt(retval);
770 }
771 
772 static TmEcode UnixManagerRulesetStatsCommand(json_t *cmd,
773  json_t *server_msg, void *data)
774 {
775  SCEnter();
776  TmEcode retval;
777  json_t *jdata = NULL;
778 
779  retval = OutputEngineStatsRuleset(&jdata);
780  json_object_set_new(server_msg, "message", jdata);
781  SCReturnInt(retval);
782 }
783 
784 #ifdef PROFILE_RULES
785 static TmEcode UnixManagerRulesetProfileCommand(json_t *cmd, json_t *server_msg, void *data)
786 {
787  SCEnter();
789 
790  json_t *js = SCProfileRuleTriggerDump(de_ctx);
791  if (js == NULL) {
792  json_object_set_new(server_msg, "message", json_string("NOK"));
794  }
795  json_object_set_new(server_msg, "message", js);
797 }
798 
799 static TmEcode UnixManagerRulesetProfileStartCommand(json_t *cmd, json_t *server_msg, void *data)
800 {
801  SCEnter();
803  json_object_set_new(server_msg, "message", json_string("OK"));
805 }
806 
807 static TmEcode UnixManagerRulesetProfileStopCommand(json_t *cmd, json_t *server_msg, void *data)
808 {
809  SCEnter();
811  json_object_set_new(server_msg, "message", json_string("OK"));
813 }
814 #endif
815 
816 static TmEcode UnixManagerShowFailedRules(json_t *cmd,
817  json_t *server_msg, void *data)
818 {
819  SCEnter();
820  int rules_cnt = 0;
822  if (de_ctx == NULL) {
823  json_object_set_new(server_msg, "message", json_string("Unable to get info"));
825  }
826 
827  /* Since we need to deference de_ctx, we don't want to lost it. */
828  DetectEngineCtx *list = de_ctx;
829  json_t *js_sigs_array = json_array();
830 
831  if (js_sigs_array == NULL) {
832  json_object_set_new(server_msg, "message", json_string("Unable to get info"));
833  goto error;
834  }
835  while (list) {
836  SigString *sigs_str = NULL;
837  TAILQ_FOREACH(sigs_str, &list->sig_stat.failed_sigs, next) {
838  json_t *jdata = json_object();
839  if (jdata == NULL) {
840  json_object_set_new(server_msg, "message", json_string("Unable to get the sig"));
841  goto error;
842  }
843 
844  json_object_set_new(jdata, "tenant_id", json_integer(list->tenant_id));
845  json_object_set_new(jdata, "rule", json_string(sigs_str->sig_str));
846  json_object_set_new(jdata, "filename", json_string(sigs_str->filename));
847  json_object_set_new(jdata, "line", json_integer(sigs_str->line));
848  if (sigs_str->sig_error) {
849  json_object_set_new(jdata, "error", json_string(sigs_str->sig_error));
850  }
851  json_array_append_new(js_sigs_array, jdata);
852  if (++rules_cnt > MAX_FAILED_RULES) {
853  break;
854  }
855  }
856  if (rules_cnt > MAX_FAILED_RULES) {
857  break;
858  }
859  list = list->next;
860  }
861 
862  json_object_set_new(server_msg, "message", js_sigs_array);
865 
866 error:
868  json_object_clear(js_sigs_array);
869  json_decref(js_sigs_array);
871 }
872 
873 static TmEcode UnixManagerConfGetCommand(json_t *cmd,
874  json_t *server_msg, void *data)
875 {
876  SCEnter();
877 
878  const char *confval = NULL;
879  char *variable = NULL;
880 
881  json_t *jarg = json_object_get(cmd, "variable");
882  if(!json_is_string(jarg)) {
883  SCLogInfo("error: variable is not a string");
884  json_object_set_new(server_msg, "message", json_string("variable is not a string"));
886  }
887 
888  variable = (char *)json_string_value(jarg);
889  if (SCConfGet(variable, &confval) != 1) {
890  json_object_set_new(server_msg, "message", json_string("Unable to get value"));
892  }
893 
894  if (confval) {
895  json_object_set_new(server_msg, "message", json_string(confval));
897  }
898 
899  json_object_set_new(server_msg, "message", json_string("No string value"));
901 }
902 
903 static TmEcode UnixManagerListCommand(json_t *cmd,
904  json_t *answer, void *data)
905 {
906  SCEnter();
907  json_t *jdata;
908  json_t *jarray;
909  Command *lcmd = NULL;
910  UnixCommand *gcmd = (UnixCommand *) data;
911  int i = 0;
912 
913  jdata = json_object();
914  if (jdata == NULL) {
915  json_object_set_new(answer, "message",
916  json_string("internal error at json object creation"));
917  return TM_ECODE_FAILED;
918  }
919  jarray = json_array();
920  if (jarray == NULL) {
921  json_object_set_new(answer, "message",
922  json_string("internal error at json object creation"));
923  return TM_ECODE_FAILED;
924  }
925 
926  TAILQ_FOREACH(lcmd, &gcmd->commands, next) {
927  json_array_append_new(jarray, json_string(lcmd->name));
928  i++;
929  }
930 
931  json_object_set_new(jdata, "count", json_integer(i));
932  json_object_set_new(jdata, "commands", jarray);
933  json_object_set_new(answer, "message", jdata);
935 }
936 
937 static TmEcode UnixManagerReopenLogFiles(json_t *cmd, json_t *server_msg, void *data)
938 {
940  json_object_set_new(server_msg, "message", json_string("done"));
942 }
943 
944 #if 0
945 TmEcode UnixManagerReloadRules(json_t *cmd,
946  json_t *server_msg, void *data)
947 {
948  SCEnter();
949  if (suricata_ctl_flags != 0) {
950  json_object_set_new(server_msg, "message",
951  json_string("Live rule swap no longer possible."
952  " Engine in shutdown mode."));
954  } else {
955  /* FIXME : need to check option value */
956  UtilSignalHandlerSetup(SIGUSR2, SignalHandlerSigusr2Idle);
957  DetectEngineSpawnLiveRuleSwapMgmtThread();
958  json_object_set_new(server_msg, "message", json_string("Reloading rules"));
959  }
961 }
962 #endif
963 
964 static UnixCommand command;
965 
966 /**
967  * \brief Add a command to the list of commands
968  *
969  * This function adds a command to the list of commands available
970  * through the unix socket.
971  *
972  * When a command is received from user through the unix socket, the content
973  * of 'Command' field in the JSON message is match against keyword, then the
974  * Func is called. See UnixSocketAddPcapFile() for an example.
975  *
976  * \param keyword name of the command
977  * \param Func function to run when command is received
978  * \param data a pointer to data that are passed to Func when it is run
979  * \param flags a flag now used to tune the command type
980  * \retval TM_ECODE_OK in case of success, TM_ECODE_FAILED in case of failure
981  */
982 TmEcode UnixManagerRegisterCommand(const char * keyword,
983  TmEcode (*Func)(json_t *, json_t *, void *),
984  void *data, int flags)
985 {
986  SCEnter();
987  Command *cmd = NULL;
988  Command *lcmd = NULL;
989 
990  if (Func == NULL) {
991  SCLogError("Null function");
993  }
994 
995  if (keyword == NULL) {
996  SCLogError("Null keyword");
998  }
999 
1000  TAILQ_FOREACH(lcmd, &command.commands, next) {
1001  if (!strcmp(keyword, lcmd->name)) {
1002  SCLogError("%s already registered", keyword);
1004  }
1005  }
1006 
1007  cmd = SCMalloc(sizeof(Command));
1008  if (unlikely(cmd == NULL)) {
1009  SCLogError("Can't alloc cmd");
1011  }
1012  cmd->name = SCStrdup(keyword);
1013  if (unlikely(cmd->name == NULL)) {
1014  SCLogError("Can't alloc cmd name");
1015  SCFree(cmd);
1017  }
1018  cmd->Func = Func;
1019  cmd->data = data;
1020  cmd->flags = flags;
1021  /* Add it to the list */
1022  TAILQ_INSERT_TAIL(&command.commands, cmd, next);
1023 
1025 }
1026 
1027 /**
1028  * \brief Add a task to the list of tasks
1029  *
1030  * This function adds a task to run in the background. The task is run
1031  * each time the UnixMain() function exits from select.
1032  *
1033  * \param Func function to run when a command is received
1034  * \param data a pointer to data that are passed to Func when it is run
1035  * \retval TM_ECODE_OK in case of success, TM_ECODE_FAILED in case of failure
1036  */
1037 TmEcode UnixManagerRegisterBackgroundTask(TmEcode (*Func)(void *),
1038  void *data)
1039 {
1040  SCEnter();
1041  Task *task = NULL;
1042 
1043  if (Func == NULL) {
1044  SCLogError("Null function");
1046  }
1047 
1048  task = SCMalloc(sizeof(Task));
1049  if (unlikely(task == NULL)) {
1050  SCLogError("Can't alloc task");
1052  }
1053  task->Func = Func;
1054  task->data = data;
1055  /* Add it to the list */
1056  TAILQ_INSERT_TAIL(&command.tasks, task, next);
1057 
1059 }
1060 
1061 int UnixManagerInit(void)
1062 {
1063  if (UnixNew(&command) == 0) {
1064  int failure_fatal = 0;
1065  if (SCConfGetBool("engine.init-failure-fatal", &failure_fatal) != 1) {
1066  SCLogDebug("ConfGetBool could not load the value.");
1067  }
1068  if (failure_fatal) {
1069  FatalError("Unable to create unix command socket");
1070  } else {
1071  SCLogWarning("Unable to create unix command socket");
1072  return -1;
1073  }
1074  }
1075 
1076  /* Init Unix socket */
1077  UnixManagerRegisterCommand("shutdown", UnixManagerShutdownCommand, NULL, 0);
1078  UnixManagerRegisterCommand("command-list", UnixManagerListCommand, &command, 0);
1079  UnixManagerRegisterCommand("help", UnixManagerListCommand, &command, 0);
1080  UnixManagerRegisterCommand("version", UnixManagerVersionCommand, &command, 0);
1081  UnixManagerRegisterCommand("uptime", UnixManagerUptimeCommand, &command, 0);
1082  UnixManagerRegisterCommand("running-mode", UnixManagerRunningModeCommand, &command, 0);
1083  UnixManagerRegisterCommand("capture-mode", UnixManagerCaptureModeCommand, &command, 0);
1084  UnixManagerRegisterCommand("conf-get", UnixManagerConfGetCommand, &command, UNIX_CMD_TAKE_ARGS);
1085  UnixManagerRegisterCommand("dump-counters", StatsOutputCounterSocket, NULL, 0);
1086  UnixManagerRegisterCommand("reload-rules", UnixManagerReloadRules, NULL, 0);
1087  UnixManagerRegisterCommand("ruleset-reload-rules", UnixManagerReloadRules, NULL, 0);
1088  UnixManagerRegisterCommand("ruleset-reload-nonblocking", UnixManagerNonBlockingReloadRules, NULL, 0);
1089  UnixManagerRegisterCommand("ruleset-reload-time", UnixManagerReloadTimeCommand, NULL, 0);
1090  UnixManagerRegisterCommand("ruleset-stats", UnixManagerRulesetStatsCommand, NULL, 0);
1091  UnixManagerRegisterCommand("ruleset-failed-rules", UnixManagerShowFailedRules, NULL, 0);
1092 #ifdef PROFILE_RULES
1093  UnixManagerRegisterCommand("ruleset-profile", UnixManagerRulesetProfileCommand, NULL, 0);
1094  UnixManagerRegisterCommand(
1095  "ruleset-profile-start", UnixManagerRulesetProfileStartCommand, NULL, 0);
1096  UnixManagerRegisterCommand(
1097  "ruleset-profile-stop", UnixManagerRulesetProfileStopCommand, NULL, 0);
1098 #endif
1099  UnixManagerRegisterCommand("register-tenant-handler", UnixSocketRegisterTenantHandler, &command, UNIX_CMD_TAKE_ARGS);
1100  UnixManagerRegisterCommand("unregister-tenant-handler", UnixSocketUnregisterTenantHandler, &command, UNIX_CMD_TAKE_ARGS);
1101  UnixManagerRegisterCommand("register-tenant", UnixSocketRegisterTenant, &command, UNIX_CMD_TAKE_ARGS);
1102  UnixManagerRegisterCommand("reload-tenant", UnixSocketReloadTenant, &command, UNIX_CMD_TAKE_ARGS);
1103  UnixManagerRegisterCommand("reload-tenants", UnixSocketReloadTenants, &command, 0);
1104  UnixManagerRegisterCommand("unregister-tenant", UnixSocketUnregisterTenant, &command, UNIX_CMD_TAKE_ARGS);
1105  UnixManagerRegisterCommand("add-hostbit", UnixSocketHostbitAdd, &command, UNIX_CMD_TAKE_ARGS);
1106  UnixManagerRegisterCommand("remove-hostbit", UnixSocketHostbitRemove, &command, UNIX_CMD_TAKE_ARGS);
1107  UnixManagerRegisterCommand("list-hostbit", UnixSocketHostbitList, &command, UNIX_CMD_TAKE_ARGS);
1108  UnixManagerRegisterCommand("reopen-log-files", UnixManagerReopenLogFiles, NULL, 0);
1109  UnixManagerRegisterCommand("memcap-set", UnixSocketSetMemcap, &command, UNIX_CMD_TAKE_ARGS);
1110  UnixManagerRegisterCommand("memcap-show", UnixSocketShowMemcap, &command, UNIX_CMD_TAKE_ARGS);
1111  UnixManagerRegisterCommand("memcap-list", UnixSocketShowAllMemcap, NULL, 0);
1112 
1113  UnixManagerRegisterCommand("dataset-add", UnixSocketDatasetAdd, &command, UNIX_CMD_TAKE_ARGS);
1114  UnixManagerRegisterCommand("dataset-remove", UnixSocketDatasetRemove, &command, UNIX_CMD_TAKE_ARGS);
1115  UnixManagerRegisterCommand(
1116  "dataset-add-json", UnixSocketDatajsonAdd, &command, UNIX_CMD_TAKE_ARGS);
1117  UnixManagerRegisterCommand(
1118  "get-flow-stats-by-id", UnixSocketGetFlowStatsById, &command, UNIX_CMD_TAKE_ARGS);
1119  UnixManagerRegisterCommand("dataset-dump", UnixSocketDatasetDump, NULL, 0);
1120  UnixManagerRegisterCommand(
1121  "dataset-clear", UnixSocketDatasetClear, &command, UNIX_CMD_TAKE_ARGS);
1122  UnixManagerRegisterCommand(
1123  "dataset-lookup", UnixSocketDatasetLookup, &command, UNIX_CMD_TAKE_ARGS);
1124 
1125  return 0;
1126 }
1127 
1128 typedef struct UnixManagerThreadData_ {
1129  int padding;
1130 } UnixManagerThreadData;
1131 
1132 static TmEcode UnixManagerThreadInit(ThreadVars *t, const void *initdata, void **data)
1133 {
1134  UnixManagerThreadData *utd = SCCalloc(1, sizeof(*utd));
1135  if (utd == NULL)
1136  return TM_ECODE_FAILED;
1137 
1138  *data = utd;
1139  return TM_ECODE_OK;
1140 }
1141 
1142 static TmEcode UnixManagerThreadDeinit(ThreadVars *t, void *data)
1143 {
1144  SCFree(data);
1145  return TM_ECODE_OK;
1146 }
1147 
1148 static TmEcode UnixManager(ThreadVars *th_v, void *thread_data)
1149 {
1150  int ret;
1151 
1152  /* set the thread name */
1153  SCLogDebug("%s started...", th_v->name);
1154 
1155  StatsSetupPrivate(th_v);
1156 
1157  /* Set the threads capability */
1158  th_v->cap_flags = 0;
1159  SCDropCaps(th_v);
1160 
1162 
1163  while (1) {
1164  ret = UnixMain(&command);
1165  if (ret == 0) {
1166  SCLogError("Fatal error on unix socket");
1167  }
1168 
1169  if ((ret == 0) || (TmThreadsCheckFlag(th_v, THV_KILL))) {
1170  UnixClient *item;
1171  UnixClient *titem;
1172  TAILQ_FOREACH_SAFE(item, &(&command)->clients, next, titem) {
1173  close(item->fd);
1174  SCFree(item);
1175  }
1176  StatsSyncCounters(th_v);
1177  break;
1178  }
1179 
1180  UnixCommandBackgroundTasks(&command);
1181  }
1182  return TM_ECODE_OK;
1183 }
1184 
1185 
1186 /** \brief Spawn the unix socket manager thread
1187  *
1188  * \param mode if set to 1, init failure cause suricata exit
1189  * */
1190 void UnixManagerThreadSpawn(int mode)
1191 {
1192  ThreadVars *tv_unixmgr = NULL;
1193 
1196 
1198  "UnixManager", 0);
1199 
1200  if (tv_unixmgr == NULL) {
1201  FatalError("TmThreadsCreate failed");
1202  }
1203  if (TmThreadSpawn(tv_unixmgr) != TM_ECODE_OK) {
1204  FatalError("TmThreadSpawn failed");
1205  }
1206  if (mode == 1) {
1207  if (TmThreadsCheckFlag(tv_unixmgr, THV_RUNNING_DONE)) {
1208  FatalError("Unix socket init failed");
1209  }
1210  }
1211 }
1212 
1213 // TODO can't think of a good name
1214 void UnixManagerThreadSpawnNonRunmode(const bool unix_socket)
1215 {
1216  /* Spawn the unix socket manager thread */
1217  if (unix_socket) {
1218  if (UnixManagerInit() == 0) {
1219  UnixManagerRegisterCommand("iface-stat", LiveDeviceIfaceStat, NULL,
1221  UnixManagerRegisterCommand("iface-list", LiveDeviceIfaceList, NULL, 0);
1222  UnixManagerRegisterCommand("iface-bypassed-stat",
1223  LiveDeviceGetBypassedStats, NULL, 0);
1224  /* For backward compatibility */
1225  UnixManagerRegisterCommand("ebpf-bypassed-stat",
1226  LiveDeviceGetBypassedStats, NULL, 0);
1228  }
1229  }
1230 }
1231 
1232 /**
1233  * \brief Used to kill unix manager thread(s).
1234  *
1235  * \todo Kinda hackish since it uses the tv name to identify unix manager
1236  * thread. We need an all weather identification scheme.
1237  */
1238 void UnixSocketKillSocketThread(void)
1239 {
1240  ThreadVars *tv = NULL;
1241 
1242 again:
1244 
1245  /* unix manager thread(s) is/are a part of command threads */
1246  tv = tv_root[TVT_CMD];
1247 
1248  while (tv != NULL) {
1249  if (strcasecmp(tv->name, "UnixManagerThread") == 0) {
1250  /* If the thread dies during init it will have
1251  * THV_RUNNING_DONE set, so we can set the correct flag
1252  * and exit.
1253  */
1258  break;
1259  }
1262  /* Be sure it has shut down */
1263  if (!TmThreadsCheckFlag(tv, THV_CLOSED)) {
1265  usleep(100);
1266  goto again;
1267  }
1268  }
1269  tv = tv->next;
1270  }
1271 
1273 }
1274 
1275 #else /* BUILD_UNIX_SOCKET */
1276 
1278 {
1279  SCLogError("Unix socket is not compiled");
1280 }
1281 
1283 {
1284 }
1285 
1286 void UnixManagerThreadSpawnNonRunmode(const bool unix_socket_enabled)
1287 {
1288 }
1289 
1290 #endif /* BUILD_UNIX_SOCKET */
1291 
1293 {
1294 #if defined(BUILD_UNIX_SOCKET) && defined(HAVE_SYS_UN_H) && defined(HAVE_SYS_STAT_H) && defined(HAVE_SYS_TYPES_H)
1295  tmm_modules[TMM_UNIXMANAGER].name = "UnixManager";
1296  tmm_modules[TMM_UNIXMANAGER].ThreadInit = UnixManagerThreadInit;
1297  tmm_modules[TMM_UNIXMANAGER].ThreadDeinit = UnixManagerThreadDeinit;
1298  tmm_modules[TMM_UNIXMANAGER].Management = UnixManager;
1301 #endif /* BUILD_UNIX_SOCKET */
1302 }
TmModule_::cap_flags
uint8_t cap_flags
Definition: tm-modules.h:77
util-device-private.h
tm-threads.h
TmModuleUnixManagerRegister
void TmModuleUnixManagerRegister(void)
Definition: unix-manager.c:1292
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:1724
detect-engine.h
offset
uint64_t offset
Definition: util-streaming-buffer.h:0
DetectEngineDeReference
void DetectEngineDeReference(DetectEngineCtx **de_ctx)
Definition: detect-engine.c:4637
ThreadVars_::name
char name[16]
Definition: threadvars.h:65
TAILQ_INIT
#define TAILQ_INIT(head)
Definition: queue.h:262
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
SCProfileRuleStopCollection
void SCProfileRuleStopCollection(void)
Definition: util-profiling.c:1419
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:275
SigString_
Definition: detect.h:867
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:932
SCConfGet
int SCConfGet(const char *name, const char **vptr)
Retrieve the value of a configuration node.
Definition: conf.c:350
THV_RUNNING
#define THV_RUNNING
Definition: threadvars.h:55
UnixManagerThreadSpawn
void UnixManagerThreadSpawn(int mode)
Definition: unix-manager.c:1277
DetectEngineGetCurrent
DetectEngineCtx * DetectEngineGetCurrent(void)
Definition: detect-engine.c:3838
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:94
StatsSetupPrivate
int StatsSetupPrivate(ThreadVars *tv)
Definition: counters.c:1209
SCMutexLock
#define SCMutexLock(mut)
Definition: threads-debug.h:117
SCConfGetBool
int SCConfGetBool(const char *name, int *val)
Retrieve a configuration value as a boolean.
Definition: conf.c:497
tv_root
ThreadVars * tv_root[TVT_MAX]
Definition: tm-threads.c:82
util-privs.h
OutputJSONMemBufferWrapper_::buffer
MemBuffer ** buffer
Definition: output-json.h:60
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:199
JSON_ESCAPE_SLASH
#define JSON_ESCAPE_SLASH
Definition: suricata-common.h:290
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:82
runmode-unix-socket.h
TM_ECODE_OK
@ TM_ECODE_OK
Definition: tm-threads-common.h:81
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:53
TAILQ_ENTRY
#define TAILQ_ENTRY(type)
Definition: queue.h:239
SigString_::sig_error
char * sig_error
Definition: detect.h:870
THV_RUNNING_DONE
#define THV_RUNNING_DONE
Definition: threadvars.h:46
util-signal.h
SCCtrlCondInit
#define SCCtrlCondInit
Definition: threads-debug.h:383
UnixManagerThreadSpawnNonRunmode
void UnixManagerThreadSpawnNonRunmode(const bool unix_socket_enabled)
Definition: unix-manager.c:1286
TAILQ_REMOVE
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:312
util-debug.h
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:18
SCProfileRuleStartCollection
void SCProfileRuleStartCollection(void)
Definition: util-profiling.c:1415
output-json.h
SCMutexUnlock
#define SCMutexUnlock(mut)
Definition: threads-debug.h:119
UnixSocketKillSocketThread
void UnixSocketKillSocketThread(void)
Definition: unix-manager.c:1282
TVT_CMD
@ TVT_CMD
Definition: tm-threads-common.h:90
TMM_UNIXMANAGER
@ TMM_UNIXMANAGER
Definition: tm-threads-common.h:74
SCEnter
#define SCEnter(...)
Definition: util-debug.h:277
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:69
THV_KILL
#define THV_KILL
Definition: threadvars.h:40
DetectEngineReloadIsIdle
int DetectEngineReloadIsIdle(void)
Definition: detect-engine.c:1931
SCLogWarning
#define SCLogWarning(...)
Macro used to log WARNING messages.
Definition: util-debug.h:255
GetProgramVersion
const char * GetProgramVersion(void)
get string with program version
Definition: suricata.c:1186
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:279
OutputJSONMemBufferWrapper_
Definition: output-json.h:59
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:735
UNIX_CMD_TAKE_ARGS
#define UNIX_CMD_TAKE_ARGS
Definition: unix-manager.h:29
TmEcode
TmEcode
Definition: tm-threads-common.h:80
name
const char * name
Definition: tm-threads.c:2163
padding
uint32_t padding
Definition: decode-erspan.h:2
TmModule_::name
const char * name
Definition: tm-modules.h:48
MemBuffer_
Definition: util-buffer.h:27
runmodes.h
SCLogInfo
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:225
TAILQ_FOREACH_SAFE
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:329
SigString_::filename
char * filename
Definition: detect.h:868
THV_INIT_DONE
#define THV_INIT_DONE
Definition: threadvars.h:37
util-conf.h
DetectEngineCtx_::sig_stat
SigFileLoaderStat sig_stat
Definition: detect.h:1102
flags
uint8_t flags
Definition: decode-gre.h:0
SuriHasSigFile
int SuriHasSigFile(void)
Definition: suricata.c:225
suricata-common.h
output-json-stats.h
SigString_::line
int line
Definition: detect.h:871
SCCtrlMutex
#define SCCtrlMutex
Definition: threads-debug.h:373
util-path.h
DetectEngineCtx_::next
struct DetectEngineCtx_ * next
Definition: detect.h:1058
UnixManagerInit
int UnixManagerInit(void)
MemBufferFree
void MemBufferFree(MemBuffer *buffer)
Definition: util-buffer.c:86
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:51
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:510
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:470
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:1158
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:32
StatsSyncCounters
void StatsSyncCounters(ThreadVars *tv)
Definition: counters.c:445
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:267
DetectEngineReloadStart
int DetectEngineReloadStart(void)
Definition: detect-engine.c:1897
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:966
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:130
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:73
RunModeGetMainMode
const char * RunModeGetMainMode(void)
Definition: runmodes.c:221
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:869
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:281
DetectEngineCtx_::tenant_id
uint32_t tenant_id
Definition: detect.h:939
TmModule_::flags
uint8_t flags
Definition: tm-modules.h:80
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:172