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