#include "util-log-redis.h"
#include "util-device.h"
#include "util-validate.h"
+#include "util-crypt.h"
#include "flow-var.h"
#include "flow-bit.h"
#define MAX_JSON_SIZE 2048
static void OutputJsonDeInitCtx(OutputCtx *);
+static void CreateJSONCommunityFlowId(json_t *js, const Flow *f, const uint16_t seed);
static const char *TRAFFIC_ID_PREFIX = "traffic/id/";
static const char *TRAFFIC_LABEL_PREFIX = "traffic/label/";
if (cfg->include_metadata) {
JsonAddMetadata(p, f, js);
}
+ if (cfg->include_community_id && f != NULL) {
+ CreateJSONCommunityFlowId(js, f, cfg->community_id_seed);
+ }
}
/** \brief jsonify tcp flags field
json_object_set_new(js, "proto", json_string(proto));
}
+static void CreateJSONCommunityFlowIdv4(json_t *js, const Flow *f,
+ const uint16_t seed)
+{
+ struct {
+ uint16_t seed;
+ uint32_t src;
+ uint32_t dst;
+ uint8_t proto;
+ uint8_t pad0;
+ uint16_t sp;
+ uint16_t dp;
+ } __attribute__((__packed__)) ipv4;
+
+ uint32_t src = f->src.addr_data32[0];
+ uint32_t dst = f->dst.addr_data32[0];
+ uint16_t sp = f->sp;
+ if (f->proto == IPPROTO_ICMP)
+ sp = f->icmp_s.type;
+ sp = htons(sp);
+ uint16_t dp = f->dp;
+ if (f->proto == IPPROTO_ICMP)
+ dp = f->icmp_d.type;
+ dp = htons(dp);
+
+ ipv4.seed = htons(seed);
+ if (ntohl(src) < ntohl(dst) || (src == dst && sp < dp)) {
+ ipv4.src = src;
+ ipv4.dst = dst;
+ ipv4.sp = sp;
+ ipv4.dp = dp;
+ } else {
+ ipv4.src = dst;
+ ipv4.dst = src;
+ ipv4.sp = dp;
+ ipv4.dp = sp;
+ }
+ ipv4.proto = f->proto;
+ ipv4.pad0 = 0;
+
+ uint8_t hash[20];
+ if (ComputeSHA1((const uint8_t *)&ipv4, sizeof(ipv4), hash, sizeof(hash)) == 1) {
+ unsigned char base64buf[64] = "1:";
+ unsigned long out_len = sizeof(base64buf) - 2;
+ if (Base64Encode(hash, sizeof(hash), base64buf+2, &out_len) == SC_BASE64_OK) {
+ json_object_set_new(js, "community_id", json_string((const char *)base64buf));
+ }
+ }
+}
+
+static inline bool FlowHashRawAddressIPv6LtU32(const uint32_t *a, const uint32_t *b)
+{
+ for (int i = 0; i < 4; i++) {
+ if (a[i] < b[i])
+ return true;
+ if (a[i] > b[i])
+ break;
+ }
+
+ return false;
+}
+
+static void CreateJSONCommunityFlowIdv6(json_t *js, const Flow *f,
+ const uint16_t seed)
+{
+ struct {
+ uint16_t seed;
+ uint32_t src[4];
+ uint32_t dst[4];
+ uint8_t proto;
+ uint8_t pad0;
+ uint16_t sp;
+ uint16_t dp;
+ } __attribute__((__packed__)) ipv6;
+
+ uint16_t sp = f->sp;
+ if (f->proto == IPPROTO_ICMPV6)
+ sp = f->icmp_s.type;
+ sp = htons(sp);
+ uint16_t dp = f->dp;
+ if (f->proto == IPPROTO_ICMPV6)
+ dp = f->icmp_d.type;
+ dp = htons(dp);
+
+ ipv6.seed = htons(seed);
+ if (FlowHashRawAddressIPv6LtU32(f->src.addr_data32, f->dst.addr_data32) ||
+ ((memcmp(&f->src, &f->dst, sizeof(f->src)) == 0) && sp < dp))
+ {
+ memcpy(&ipv6.src, &f->src.addr_data32, 16);
+ memcpy(&ipv6.dst, &f->dst.addr_data32, 16);
+ ipv6.sp = sp;
+ ipv6.dp = dp;
+ } else {
+ memcpy(&ipv6.src, &f->dst.addr_data32, 16);
+ memcpy(&ipv6.dst, &f->src.addr_data32, 16);
+ ipv6.sp = dp;
+ ipv6.dp = sp;
+ }
+ ipv6.proto = f->proto;
+ ipv6.pad0 = 0;
+
+ uint8_t hash[20];
+ if (ComputeSHA1((const uint8_t *)&ipv6, sizeof(ipv6), hash, sizeof(hash)) == 1) {
+ unsigned char base64buf[64] = "1:";
+ unsigned long out_len = sizeof(base64buf) - 2;
+ if (Base64Encode(hash, sizeof(hash), base64buf+2, &out_len) == SC_BASE64_OK) {
+ json_object_set_new(js, "community_id", json_string((const char *)base64buf));
+ }
+ }
+}
+
+static void CreateJSONCommunityFlowId(json_t *js, const Flow *f, const uint16_t seed)
+{
+ if (f->flags & FLOW_IPV4)
+ return CreateJSONCommunityFlowIdv4(js, f, seed);
+ else if (f->flags & FLOW_IPV6)
+ return CreateJSONCommunityFlowIdv6(js, f, seed);
+}
+
void CreateJSONFlowId(json_t *js, const Flow *f)
{
if (f == NULL)
json_ctx->cfg.include_metadata = true;
}
+ /* See if we want to enable the community id */
+ const ConfNode *community_id = ConfNodeLookupChild(conf, "community-id");
+ if (community_id && community_id->val && ConfValIsTrue(community_id->val)) {
+ SCLogConfig("Enabling eve community_id logging.");
+ json_ctx->cfg.include_community_id = true;
+ } else {
+ json_ctx->cfg.include_community_id = false;
+ }
+ const char *cid_seed = ConfNodeLookupChildValue(conf, "community-id-seed");
+ if (cid_seed != NULL) {
+ if (ByteExtractStringUint16(&json_ctx->cfg.community_id_seed,
+ 10, 0, cid_seed) == -1)
+ {
+ SCLogError(SC_ERR_INVALID_ARGUMENT,
+ "Failed to initialize JSON output, "
+ "invalid community-id-seed: %s", cid_seed);
+ exit(EXIT_FAILURE);
+ }
+ }
+
/* Do we have a global eve xff configuration? */
const ConfNode *xff = ConfNodeLookupChild(conf, "xff");
if (xff != NULL) {