]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
unix-socket: add/list/remove hostbit commands
authorVictor Julien <victor@inliniac.net>
Thu, 15 Dec 2016 13:49:17 +0000 (14:49 +0100)
committerVictor Julien <victor@inliniac.net>
Thu, 16 Feb 2017 09:35:44 +0000 (10:35 +0100)
add-hostbit adds a named hostbit with an expire time in seconds.
remove-hostbit removes hostbit by name.

add-hostbit, remove-hostbit return success or failure.

list-hostbit returns a json array of hostbits with their name and
expire time:

    {
        "message": {
            "count": 1,
            "hostbits":
                [{
                    "expire": 3222,
                    "name": "firefox-users"
                }]
        },
        "return": "OK"
    }

src/runmode-unix-socket.c
src/runmode-unix-socket.h
src/unix-manager.c

index 092cadaa9981dcddc578c2f04e8486489cb94d9e..7d9ef8ed2670c6133e9bee8862c9653a4de4f326 100644 (file)
@@ -37,6 +37,7 @@
 #include "defrag.h"
 #include "ippair.h"
 #include "app-layer.h"
+#include "host-bit.h"
 
 #include "util-profiling.h"
 
@@ -751,6 +752,259 @@ TmEcode UnixSocketUnregisterTenant(json_t *cmd, json_t* answer, void *data)
     json_object_set_new(answer, "message", json_string("work in progress"));
     return TM_ECODE_OK;
 }
+
+/**
+ * \brief Command to add a hostbit
+ *
+ * \param cmd the content of command Arguments as a json_t object
+ * \param answer the json_t object that has to be used to answer
+ */
+TmEcode UnixSocketHostbitAdd(json_t *cmd, json_t* answer, void *data_usused)
+{
+    /* 1 get ip address */
+    json_t *jarg = json_object_get(cmd, "ipaddress");
+    if (!json_is_string(jarg)) {
+        json_object_set_new(answer, "message", json_string("ipaddress is not an string"));
+        return TM_ECODE_FAILED;
+    }
+    const char *ipaddress = json_string_value(jarg);
+
+    Address a;
+    struct in_addr in;
+    memset(&in, 0, sizeof(in));
+    if (inet_pton(AF_INET, ipaddress, &in) != 1) {
+        uint32_t in6[4];
+        memset(&in6, 0, sizeof(in6));
+        if (inet_pton(AF_INET6, ipaddress, &in) != 1) {
+            json_object_set_new(answer, "message", json_string("invalid address string"));
+            return TM_ECODE_FAILED;
+        } else {
+            a.family = AF_INET6;
+            a.addr_data32[0] = in6[0];
+            a.addr_data32[1] = in6[1];
+            a.addr_data32[2] = in6[2];
+            a.addr_data32[3] = in6[3];
+        }
+    } else {
+        a.family = AF_INET;
+        a.addr_data32[0] = in.s_addr;
+        a.addr_data32[1] = 0;
+        a.addr_data32[2] = 0;
+        a.addr_data32[3] = 0;
+    }
+
+    /* 2 get variable name */
+    jarg = json_object_get(cmd, "hostbit");
+    if (!json_is_string(jarg)) {
+        json_object_set_new(answer, "message", json_string("hostbit is not a string"));
+        return TM_ECODE_FAILED;
+    }
+    const char *hostbit = json_string_value(jarg);
+    uint32_t idx = VarNameStoreLookupByName(hostbit, VAR_TYPE_HOST_BIT);
+    if (idx == 0) {
+        json_object_set_new(answer, "message", json_string("hostbit not found"));
+        return TM_ECODE_FAILED;
+    }
+
+    /* 3 get expire */
+    jarg = json_object_get(cmd, "expire");
+    if (!json_is_integer(jarg)) {
+        json_object_set_new(answer, "message", json_string("expire is not an integer"));
+        return TM_ECODE_FAILED;
+    }
+    uint32_t expire = json_integer_value(jarg);
+
+    SCLogInfo("add-hostbit: ip %s hostbit %s expire %us", ipaddress, hostbit, expire);
+
+    struct timeval current_time;
+    TimeGet(&current_time);
+    Host *host = HostGetHostFromHash(&a);
+    if (host) {
+        HostBitSet(host, idx, current_time.tv_sec + expire);
+        HostUnlock(host);
+
+        json_object_set_new(answer, "message", json_string("hostbit added"));
+        return TM_ECODE_OK;
+    } else {
+        json_object_set_new(answer, "message", json_string("couldn't create host"));
+        return TM_ECODE_FAILED;
+    }
+}
+
+/**
+ * \brief Command to remove a hostbit
+ *
+ * \param cmd the content of command Arguments as a json_t object
+ * \param answer the json_t object that has to be used to answer
+ */
+TmEcode UnixSocketHostbitRemove(json_t *cmd, json_t* answer, void *data_unused)
+{
+    /* 1 get ip address */
+    json_t *jarg = json_object_get(cmd, "ipaddress");
+    if (!json_is_string(jarg)) {
+        json_object_set_new(answer, "message", json_string("ipaddress is not an string"));
+        return TM_ECODE_FAILED;
+    }
+    const char *ipaddress = json_string_value(jarg);
+
+    Address a;
+    struct in_addr in;
+    memset(&in, 0, sizeof(in));
+    if (inet_pton(AF_INET, ipaddress, &in) != 1) {
+        uint32_t in6[4];
+        memset(&in6, 0, sizeof(in6));
+        if (inet_pton(AF_INET6, ipaddress, &in) != 1) {
+            json_object_set_new(answer, "message", json_string("invalid address string"));
+            return TM_ECODE_FAILED;
+        } else {
+            a.family = AF_INET6;
+            a.addr_data32[0] = in6[0];
+            a.addr_data32[1] = in6[1];
+            a.addr_data32[2] = in6[2];
+            a.addr_data32[3] = in6[3];
+        }
+    } else {
+        a.family = AF_INET;
+        a.addr_data32[0] = in.s_addr;
+        a.addr_data32[1] = 0;
+        a.addr_data32[2] = 0;
+        a.addr_data32[3] = 0;
+    }
+
+    /* 2 get variable name */
+    jarg = json_object_get(cmd, "hostbit");
+    if (!json_is_string(jarg)) {
+        json_object_set_new(answer, "message", json_string("hostbit is not a string"));
+        return TM_ECODE_FAILED;
+    }
+
+    const char *hostbit = json_string_value(jarg);
+    uint32_t idx = VarNameStoreLookupByName(hostbit, VAR_TYPE_HOST_BIT);
+    if (idx == 0) {
+        json_object_set_new(answer, "message", json_string("hostbit not found"));
+        return TM_ECODE_FAILED;
+    }
+
+    SCLogInfo("remove-hostbit: %s %s", ipaddress, hostbit);
+
+    Host *host = HostLookupHostFromHash(&a);
+    if (host) {
+        HostBitUnset(host, idx);
+        HostUnlock(host);
+        json_object_set_new(answer, "message", json_string("hostbit removed"));
+        return TM_ECODE_OK;
+    } else {
+        json_object_set_new(answer, "message", json_string("host not found"));
+        return TM_ECODE_FAILED;
+    }
+}
+
+/**
+ * \brief Command to list hostbits for an ip
+ *
+ * \param cmd the content of command Arguments as a json_t object
+ * \param answer the json_t object that has to be used to answer
+ *
+ * Message looks like:
+ * {"message": {"count": 1, "hostbits": [{"expire": 3222, "name": "firefox-users"}]}, "return": "OK"}
+ *
+ * \retval r TM_ECODE_OK or TM_ECODE_FAILED
+ */
+TmEcode UnixSocketHostbitList(json_t *cmd, json_t* answer, void *data_unused)
+{
+    /* 1 get ip address */
+    json_t *jarg = json_object_get(cmd, "ipaddress");
+    if (!json_is_string(jarg)) {
+        json_object_set_new(answer, "message", json_string("ipaddress is not an string"));
+        return TM_ECODE_FAILED;
+    }
+    const char *ipaddress = json_string_value(jarg);
+
+    Address a;
+    struct in_addr in;
+    memset(&in, 0, sizeof(in));
+    if (inet_pton(AF_INET, ipaddress, &in) != 1) {
+        uint32_t in6[4];
+        memset(&in6, 0, sizeof(in6));
+        if (inet_pton(AF_INET6, ipaddress, &in) != 1) {
+            json_object_set_new(answer, "message", json_string("invalid address string"));
+            return TM_ECODE_FAILED;
+        } else {
+            a.family = AF_INET6;
+            a.addr_data32[0] = in6[0];
+            a.addr_data32[1] = in6[1];
+            a.addr_data32[2] = in6[2];
+            a.addr_data32[3] = in6[3];
+        }
+    } else {
+        a.family = AF_INET;
+        a.addr_data32[0] = in.s_addr;
+        a.addr_data32[1] = 0;
+        a.addr_data32[2] = 0;
+        a.addr_data32[3] = 0;
+    }
+
+    SCLogInfo("list-hostbit: %s", ipaddress);
+
+    struct timeval ts;
+    memset(&ts, 0, sizeof(ts));
+    TimeGet(&ts);
+
+    struct Bit {
+        uint32_t id;
+        uint32_t expire;
+    } bits[256];
+    memset(&bits, 0, sizeof(bits));
+    int i = 0, use = 0;
+
+    Host *host = HostLookupHostFromHash(&a);
+    if (!host) {
+        json_object_set_new(answer, "message", json_string("host not found"));
+        return TM_ECODE_FAILED;
+    }
+
+    XBit *iter = NULL;
+    while (use < 256 && HostBitList(host, &iter) == 1) {
+        bits[use].id = iter->idx;
+        bits[use].expire = iter->expire;
+        use++;
+    }
+    HostUnlock(host);
+
+    json_t *jdata = json_object();
+    json_t *jarray = json_array();
+    if (jarray == NULL || jdata == NULL) {
+        if (jdata != NULL)
+            json_decref(jdata);
+        if (jarray != NULL)
+            json_decref(jarray);
+        json_object_set_new(answer, "message",
+                            json_string("internal error at json object creation"));
+        return TM_ECODE_FAILED;
+    }
+
+    for (i = 0; i < use; i++) {
+        json_t *bitobject = json_object();
+        if (bitobject == NULL)
+            continue;
+        uint32_t expire = 0;
+        if ((uint32_t)ts.tv_sec < bits[i].expire)
+            expire = bits[i].expire - (uint32_t)ts.tv_sec;
+
+        const char *name = VarNameStoreLookupById(bits[i].id, VAR_TYPE_HOST_BIT);
+        if (name == NULL)
+            continue;
+        json_object_set_new(bitobject, "name", json_string(name));
+        SCLogDebug("xbit %s expire %u", name, expire);
+        json_object_set_new(bitobject, "expire", json_integer(expire));
+        json_array_append_new(jarray, bitobject);
+    }
+
+    json_object_set_new(jdata, "count", json_integer(i));
+    json_object_set_new(jdata, "hostbits", jarray);
+    json_object_set_new(answer, "message", jdata);
+    return TM_ECODE_OK;
+}
 #endif /* BUILD_UNIX_SOCKET */
 
 /**
index 20b0fea496d0569771e001a8686c9816b7b168b4..78ef53626514db01890575ef00158556b314ff9b 100644 (file)
@@ -37,6 +37,9 @@ TmEcode UnixSocketUnregisterTenantHandler(json_t *cmd, json_t* answer, void *dat
 TmEcode UnixSocketRegisterTenant(json_t *cmd, json_t* answer, void *data);
 TmEcode UnixSocketReloadTenant(json_t *cmd, json_t* answer, void *data);
 TmEcode UnixSocketUnregisterTenant(json_t *cmd, json_t* answer, void *data);
+TmEcode UnixSocketHostbitAdd(json_t *cmd, json_t* answer, void *data);
+TmEcode UnixSocketHostbitRemove(json_t *cmd, json_t* answer, void *data);
+TmEcode UnixSocketHostbitList(json_t *cmd, json_t* answer, void *data);
 #endif
 
 #endif /* __RUNMODE_UNIX_SOCKET_H__ */
index 559a8b398019bf851f71fdbf4ed1ee250e34618d..2e8cf5a94a31dc3aee692421a21220bbb298ba49 100644 (file)
@@ -932,6 +932,9 @@ static TmEcode UnixManagerThreadInit(ThreadVars *t, void *initdata, void **data)
     UnixManagerRegisterCommand("register-tenant", UnixSocketRegisterTenant, &command, UNIX_CMD_TAKE_ARGS);
     UnixManagerRegisterCommand("reload-tenant", UnixSocketReloadTenant, &command, UNIX_CMD_TAKE_ARGS);
     UnixManagerRegisterCommand("unregister-tenant", UnixSocketUnregisterTenant, &command, UNIX_CMD_TAKE_ARGS);
+    UnixManagerRegisterCommand("add-hostbit", UnixSocketHostbitAdd, &command, UNIX_CMD_TAKE_ARGS);
+    UnixManagerRegisterCommand("remove-hostbit", UnixSocketHostbitRemove, &command, UNIX_CMD_TAKE_ARGS);
+    UnixManagerRegisterCommand("list-hostbit", UnixSocketHostbitList, &command, UNIX_CMD_TAKE_ARGS);
 
     *data = utd;
     return TM_ECODE_OK;