Project

General

Profile

Unix Socket

Introduction

Suricata can listen to a unix socket and accept commands from the user. The exchange protocol is JSON-based and the format of the message has been done to be generic and it is described in this commit message. An example script called suricatasc is provided in the source and installed automatically when updating Suricata.

Protocol

The protocol is the following:
  • Client connects to the socket
  • It sends a version message: { "version": "$VERSION_ID" }
  • Server answers with { "return": "OK|NOK" }

If server returns OK, the client is now allowed to send commands.

The format of command is the following:

 {
   "command": "CMDNAME",
   "arguments": JSON_OBJECT
 }

For example, to ask suricata to treat a pcap we have:

 {
   "command": "pcap-file",
   "arguments": { "filename": "smtp-clean.pcap", "output-dir": "/tmp/out" }
 }

The server will try to execute the "command" specified with the
(optional) provided "arguments".
The answer by server is the following:

 {
   "return": "OK|NOK",
   "message": JSON_OBJECT or information string
 }

Adding new commands

Adding new command is made via an internal API. A function has to be called to declare new command. These functions are dependant of unix socket code and must be contionally called:

#ifdef BUILD_UNIX_SOCKET
            UnixManagerRegisterCommand("iface-stat", LiveDeviceIfaceStat, NULL,
                                       UNIX_CMD_TAKE_ARGS);
            UnixManagerRegisterCommand("iface-list", LiveDeviceIfaceList, NULL, 0);
#endif

Adding a regular command

To add a regular command to unix socket, a call to UnixManagerRegisterCommand must be made.
TmEcode UnixManagerRegisterCommand(const char * keyword, 
        TmEcode (*Func)(json_t *, json_t *, void *),
        void *data, int flags)


With:
  • keyword: name of the command
  • Func: function to run when command is received
  • data: a pointer to data that are pass to Func when runned
  • flags: a flag now used to tune the command type. The two values of flags are UNIX_CMD_TAKE_ARGS to specify that the command need an argument and 0 if not.

The function return TM_ECODE_OK in case of success, TM_ECODE_FAILED in case of failure.

To add a command, the main work is to write the callback function which has following prototype:

TmEcode LiveDeviceIfaceStat(json_t *cmd, json_t *answer, void *data)

First argument is the arguments object provided in the user command. Second argument is a Json object that will be the answer message.
The return value of the function indicate if command was a success or a failure. This return value fixes the value of return in the answer message.

The callback function has to handle json_t object which are object from the JANSSON library. So this library has to be directly use in the function code.

A good code example is LiveDeviceIfaceList function at source:src/util-device.c#L195

Adding a periodic task

By calling the UnixManagerRegisterBackgroundTask function it is possible to declare a task to be run in background. The declaration is the following:

TmEcode UnixManagerRegisterBackgroundTask(TmEcode (*Func)(void *), void *data)

Func is going to be run at least every 200ms and will be passed the pointer data.