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