]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
alert/eve: convert to jsonbuilder
authorJason Ish <jason.ish@oisf.net>
Sun, 15 Mar 2020 17:05:16 +0000 (11:05 -0600)
committerVictor Julien <victor@inliniac.net>
Wed, 3 Jun 2020 11:36:55 +0000 (13:36 +0200)
Convert alert Eve logging JsonBuilder. Currently
makes heavy use of JsonBuilder being able to log Jansson's json_t
which is a temporary measure until all protocols loggers can be
converted to JsonBuilder.

New functions that replace Jansson versions with JsonBuilder
variations use "Eve" instead of "JSON".

src/output-json-alert.c
src/output-json-alert.h
src/output-json-drop.c
src/output-json-flow.c
src/output-json-flow.h
src/output-json.c
src/output-json.h

index ee64fb151cf7d50f1833ff8d8c8664974acd9418..fed8b3c2b7c4a7795f3e8380ae23c7b3e7c48c52 100644 (file)
@@ -127,7 +127,7 @@ static int AlertJsonDumpStreamSegmentCallback(const Packet *p, void *data, const
     return 1;
 }
 
-static void AlertJsonTls(const Flow *f, json_t *js)
+static void AlertJsonTls(const Flow *f, JsonBuilder *js)
 {
     SSLState *ssl_state = (SSLState *)FlowGetAppState(f);
     if (ssl_state) {
@@ -138,13 +138,14 @@ static void AlertJsonTls(const Flow *f, json_t *js)
         JsonTlsLogJSONBasic(tjs, ssl_state);
         JsonTlsLogJSONExtended(tjs, ssl_state);
 
-        json_object_set_new(js, "tls", tjs);
+        jb_set_jsont(js, "tls", tjs);
+        json_decref(tjs);
     }
 
     return;
 }
 
-static void AlertJsonSsh(const Flow *f, json_t *js)
+static void AlertJsonSsh(const Flow *f, JsonBuilder *js)
 {
     void *ssh_state = FlowGetAppState(f);
     if (ssh_state) {
@@ -153,13 +154,14 @@ static void AlertJsonSsh(const Flow *f, json_t *js)
         if (unlikely(tjs == NULL))
             return;
 
-        json_object_set_new(js, "ssh", tjs);
+        jb_set_jsont(js, "ssh", tjs);
+        json_decref(tjs);
     }
 
     return;
 }
 
-static void AlertJsonDnp3(const Flow *f, const uint64_t tx_id, json_t *js)
+static void AlertJsonDnp3(const Flow *f, const uint64_t tx_id, JsonBuilder *js)
 {
     DNP3State *dnp3_state = (DNP3State *)FlowGetAppState(f);
     if (dnp3_state) {
@@ -180,7 +182,8 @@ static void AlertJsonDnp3(const Flow *f, const uint64_t tx_id, json_t *js)
                         json_object_set_new(dnp3js, "response", response);
                     }
                 }
-                json_object_set_new(js, "dnp3", dnp3js);
+                jb_set_jsont(js, "dnp3", dnp3js);
+                json_decref(dnp3js);
             }
         }
     }
@@ -188,7 +191,7 @@ static void AlertJsonDnp3(const Flow *f, const uint64_t tx_id, json_t *js)
     return;
 }
 
-static void AlertJsonDns(const Flow *f, const uint64_t tx_id, json_t *js)
+static void AlertJsonDns(const Flow *f, const uint64_t tx_id, JsonBuilder *js)
 {
     void *dns_state = (void *)FlowGetAppState(f);
     if (dns_state) {
@@ -207,29 +210,47 @@ static void AlertJsonDns(const Flow *f, const uint64_t tx_id, json_t *js)
             if (ajs != NULL) {
                 json_object_set_new(dnsjs, "answer", ajs);
             }
-            json_object_set_new(js, "dns", dnsjs);
+            jb_set_jsont(js, "dns", dnsjs);
+            json_decref(dnsjs);
         }
     }
     return;
 }
 
 static void AlertJsonSourceTarget(const Packet *p, const PacketAlert *pa,
-                                  json_t* ajs, JsonAddrInfo *addr)
+                                  JsonBuilder *js, JsonAddrInfo *addr)
 {
-    json_t *sjs = json_object();
-    if (sjs == NULL) {
-        return;
-    }
-
-    json_t *tjs = json_object();
-    if (tjs == NULL) {
-        json_decref(sjs);
-        return;
+    jb_open_object(js, "source");
+    if (pa->s->flags & SIG_FLAG_DEST_IS_TARGET) {
+        jb_set_string(js, "ip", addr->src_ip);
+        switch (p->proto) {
+            case IPPROTO_ICMP:
+            case IPPROTO_ICMPV6:
+                break;
+            case IPPROTO_UDP:
+            case IPPROTO_TCP:
+            case IPPROTO_SCTP:
+                jb_set_uint(js, "port", addr->sp);
+                break;
+        }
+    } else if (pa->s->flags & SIG_FLAG_SRC_IS_TARGET) {
+        jb_set_string(js, "ip", addr->dst_ip);
+        switch (p->proto) {
+            case IPPROTO_ICMP:
+            case IPPROTO_ICMPV6:
+                break;
+            case IPPROTO_UDP:
+            case IPPROTO_TCP:
+            case IPPROTO_SCTP:
+                jb_set_uint(js, "port", addr->dp);
+                break;
+        }
     }
+    jb_close(js);
 
+    jb_open_object(js, "target");
     if (pa->s->flags & SIG_FLAG_DEST_IS_TARGET) {
-        json_object_set(sjs, "ip", json_string(addr->src_ip));
-        json_object_set(tjs, "ip", json_string(addr->dst_ip));
+        jb_set_string(js, "ip", addr->dst_ip);
         switch (p->proto) {
             case IPPROTO_ICMP:
             case IPPROTO_ICMPV6:
@@ -237,13 +258,11 @@ static void AlertJsonSourceTarget(const Packet *p, const PacketAlert *pa,
             case IPPROTO_UDP:
             case IPPROTO_TCP:
             case IPPROTO_SCTP:
-                json_object_set(sjs, "port", json_integer(addr->sp));
-                json_object_set(tjs, "port", json_integer(addr->dp));
+                jb_set_uint(js, "port", addr->dp);
                 break;
         }
     } else if (pa->s->flags & SIG_FLAG_SRC_IS_TARGET) {
-        json_object_set(sjs, "ip", json_string(addr->dst_ip));
-        json_object_set(tjs, "ip", json_string(addr->src_ip));
+        jb_set_string(js, "ip", addr->src_ip);
         switch (p->proto) {
             case IPPROTO_ICMP:
             case IPPROTO_ICMPV6:
@@ -251,16 +270,15 @@ static void AlertJsonSourceTarget(const Packet *p, const PacketAlert *pa,
             case IPPROTO_UDP:
             case IPPROTO_TCP:
             case IPPROTO_SCTP:
-                json_object_set(sjs, "port", json_integer(addr->dp));
-                json_object_set(tjs, "port", json_integer(addr->sp));
+                jb_set_uint(js, "port", addr->sp);
                 break;
         }
     }
-    json_object_set_new(ajs, "source", sjs);
-    json_object_set_new(ajs, "target", tjs);
+    jb_close(js);
 }
 
-static void AlertJsonMetadata(AlertJsonOutputCtx *json_output_ctx, const PacketAlert *pa, json_t *ajs)
+static void AlertJsonMetadata(AlertJsonOutputCtx *json_output_ctx,
+        const PacketAlert *pa, JsonBuilder *ajs)
 {
     if (pa->s->metadata) {
         const DetectMetadata* kv = pa->s->metadata;
@@ -283,17 +301,15 @@ static void AlertJsonMetadata(AlertJsonOutputCtx *json_output_ctx, const PacketA
             kv = kv->next;
         }
 
-        if (json_object_size(mjs) == 0) {
-            json_decref(mjs);
-        } else {
-            json_object_set_new(ajs, "metadata", mjs);
+        if (json_object_size(mjs) > 0) {
+            jb_set_jsont(ajs, "metadata", mjs);
         }
+        json_decref(mjs);
     }
 }
 
-
-void AlertJsonHeader(void *ctx, const Packet *p, const PacketAlert *pa, json_t *js,
-                     uint16_t flags, JsonAddrInfo *addr)
+void AlertJsonHeader(void *ctx, const Packet *p, const PacketAlert *pa,
+        JsonBuilder *js, uint16_t flags, JsonAddrInfo *addr)
 {
     AlertJsonOutputCtx *json_output_ctx = (AlertJsonOutputCtx *)ctx;
     const char *action = "allowed";
@@ -312,74 +328,76 @@ void AlertJsonHeader(void *ctx, const Packet *p, const PacketAlert *pa, json_t *
     }
 
     /* Add tx_id to root element for correlation with other events. */
-    json_object_del(js, "tx_id");
-    if (pa->flags & PACKET_ALERT_FLAG_TX)
-        json_object_set_new(js, "tx_id", json_integer(pa->tx_id));
-
-    json_t *ajs = json_object();
-    if (ajs == NULL) {
-        return;
+    /* json_object_del(js, "tx_id"); */
+    if (pa->flags & PACKET_ALERT_FLAG_TX) {
+        jb_set_uint(js, "tx_id", pa->tx_id);
     }
 
-    json_object_set_new(ajs, "action", json_string(action));
-    json_object_set_new(ajs, "gid", json_integer(pa->s->gid));
-    json_object_set_new(ajs, "signature_id", json_integer(pa->s->id));
-    json_object_set_new(ajs, "rev", json_integer(pa->s->rev));
-    json_object_set_new(ajs, "signature",
-            SCJsonString((pa->s->msg) ? pa->s->msg : ""));
-    json_object_set_new(ajs, "category",
-            SCJsonString((pa->s->class_msg) ? pa->s->class_msg : ""));
-    json_object_set_new(ajs, "severity", json_integer(pa->s->prio));
+    jb_open_object(js, "alert");
 
-    if (p->tenant_id > 0)
-        json_object_set_new(ajs, "tenant_id", json_integer(p->tenant_id));
+    jb_set_string(js, "action", action);
+    jb_set_uint(js, "gid", pa->s->gid);
+    jb_set_uint(js, "signature_id", pa->s->id);
+    jb_set_uint(js, "rev", pa->s->rev);
+    /* TODO: JsonBuilder should handle unprintable characters like
+     * SCJsonString. */
+    jb_set_string(js, "signature", pa->s->msg ? pa->s->msg: "");
+    jb_set_string(js, "category", pa->s->class_msg ? pa->s->class_msg: "");
+    jb_set_uint(js, "severity", pa->s->prio);
+
+    if (p->tenant_id > 0) {
+        jb_set_uint(js, "tenant_id", p->tenant_id);
+    }
 
     if (addr && pa->s->flags & SIG_FLAG_HAS_TARGET) {
-        AlertJsonSourceTarget(p, pa, ajs, addr);
+        AlertJsonSourceTarget(p, pa, js, addr);
     }
 
     if ((json_output_ctx != NULL) && (flags & LOG_JSON_RULE_METADATA)) {
-        AlertJsonMetadata(json_output_ctx, pa, ajs);
+        AlertJsonMetadata(json_output_ctx, pa, js);
     }
 
     if (flags & LOG_JSON_RULE) {
-        json_object_set_new(ajs, "rule", json_string(pa->s->sig_str));
+        jb_set_string(js, "rule", pa->s->sig_str);
     }
 
-    /* alert */
-    json_object_set_new(js, "alert", ajs);
+    jb_close(js);
 }
 
-static void AlertJsonTunnel(const Packet *p, json_t *js)
+static void AlertJsonTunnel(const Packet *p, JsonBuilder *js)
 {
-    json_t *tunnel = json_object();
-    if (tunnel == NULL)
-        return;
-
     if (p->root == NULL) {
-        json_decref(tunnel);
         return;
     }
 
+    jb_open_object(js, "tunnel");
+
     /* get a lock to access root packet fields */
     SCMutex *m = &p->root->tunnel_mutex;
 
+    JsonAddrInfo addr = json_addr_info_zero;
     SCMutexLock(m);
-    JsonFiveTuple((const Packet *)p->root, 0, tunnel);
+    JsonAddrInfoInit(p->root, 0, &addr);
     SCMutexUnlock(m);
 
-    json_object_set_new(tunnel, "depth", json_integer(p->recursion_level));
+    jb_set_string(js, "src_ip", addr.src_ip);
+    jb_set_uint(js, "src_port", addr.sp);
+    jb_set_string(js, "dest_ip", addr.dst_ip);
+    jb_set_uint(js, "dest_port", addr.dp);
+    jb_set_string(js, "proto", addr.proto);
 
-    json_object_set_new(js, "tunnel", tunnel);
+    jb_set_uint(js, "depth", p->recursion_level);
+
+    jb_close(js);
 }
 
-static void AlertAddPayload(AlertJsonOutputCtx *json_output_ctx, json_t *js, const Packet *p)
+static void AlertAddPayload(AlertJsonOutputCtx *json_output_ctx, JsonBuilder *js, const Packet *p)
 {
     if (json_output_ctx->flags & LOG_JSON_PAYLOAD_BASE64) {
         unsigned long len = p->payload_len * 2 + 1;
         uint8_t encoded[len];
         if (Base64Encode(p->payload, p->payload_len, encoded, &len) == SC_BASE64_OK) {
-            json_object_set_new(js, "payload", json_string((char *)encoded));
+            jb_set_string(js, "payload", (char *)encoded);
         }
     }
 
@@ -390,7 +408,7 @@ static void AlertAddPayload(AlertJsonOutputCtx *json_output_ctx, json_t *js, con
                 p->payload_len + 1,
                 p->payload, p->payload_len);
         printable_buf[p->payload_len] = '\0';
-        json_object_set_new(js, "payload_printable", json_string((char *)printable_buf));
+        jb_set_string(js, "payload_printable", (char *)printable_buf);
     }
 }
 
@@ -412,7 +430,7 @@ static int AlertJson(ThreadVars *tv, JsonAlertLogThread *aft, const Packet *p)
         }
 
         /* First initialize the address info (5-tuple). */
-        JsonAddrInfo addr;
+        JsonAddrInfo addr = json_addr_info_zero;
         JsonAddrInfoInit(p, LOG_DIR_PACKET, &addr);
 
         /* Check for XFF, overwriting address info if needed. */
@@ -443,20 +461,19 @@ static int AlertJson(ThreadVars *tv, JsonAlertLogThread *aft, const Packet *p)
             }
         }
 
-        json_t *js = CreateJSONHeader(p, LOG_DIR_PACKET, "alert", &addr);
-        if (unlikely(js == NULL))
+        JsonBuilder *jb = CreateEveHeader(p, LOG_DIR_PACKET, "alert", &addr);
+        if (unlikely(jb == NULL))
             return TM_ECODE_OK;
-
-        JsonAddCommonOptions(&json_output_ctx->cfg, p, p->flow, js);
+        EveAddCommonOptions(&json_output_ctx->cfg, p, p->flow, jb);
 
         MemBufferReset(aft->json_buffer);
 
         /* alert */
-        AlertJsonHeader(json_output_ctx, p, pa, js, json_output_ctx->flags,
+        AlertJsonHeader(json_output_ctx, p, pa, jb, json_output_ctx->flags,
                 &addr);
 
         if (IS_TUNNEL_PKT(p)) {
-            AlertJsonTunnel(p, js);
+            AlertJsonTunnel(p, jb);
         }
 
         if (json_output_ctx->flags & LOG_JSON_APP_LAYER && p->flow != NULL) {
@@ -471,59 +488,72 @@ static int AlertJson(ThreadVars *tv, JsonAlertLogThread *aft, const Packet *p)
                         if (json_output_ctx->flags & LOG_JSON_HTTP_BODY_BASE64) {
                             JsonHttpLogJSONBodyBase64(hjs, p->flow, pa->tx_id);
                         }
-                        json_object_set_new(js, "http", hjs);
+                        jb_set_jsont(jb, "http", hjs);
+                        json_decref(hjs);
                     }
                     break;
                 case ALPROTO_TLS:
-                    AlertJsonTls(p->flow, js);
+                    AlertJsonTls(p->flow, jb);
                     break;
                 case ALPROTO_SSH:
-                    AlertJsonSsh(p->flow, js);
+                    AlertJsonSsh(p->flow, jb);
                     break;
                 case ALPROTO_SMTP:
                     hjs = JsonSMTPAddMetadata(p->flow, pa->tx_id);
                     if (hjs) {
-                        json_object_set_new(js, "smtp", hjs);
+                        jb_set_jsont(jb, "smtp", hjs);
+                        json_decref(hjs);
                     }
 
                     hjs = JsonEmailAddMetadata(p->flow, pa->tx_id);
                     if (hjs) {
-                        json_object_set_new(js, "email", hjs);
+                        jb_set_jsont(jb, "email", hjs);
+                        json_decref(hjs);
                     }
                     break;
                 case ALPROTO_NFS:
                     hjs = JsonNFSAddMetadataRPC(p->flow, pa->tx_id);
-                    if (hjs)
-                        json_object_set_new(js, "rpc", hjs);
+                    if (hjs) {
+                        jb_set_jsont(jb, "rpc", hjs);
+                        json_decref(hjs);
+                    }
                     hjs = JsonNFSAddMetadata(p->flow, pa->tx_id);
-                    if (hjs)
-                        json_object_set_new(js, "nfs", hjs);
+                    if (hjs) {
+                        jb_set_jsont(jb, "nfs", hjs);
+                        json_decref(hjs);
+                    }
                     break;
                 case ALPROTO_SMB:
                     hjs = JsonSMBAddMetadata(p->flow, pa->tx_id);
-                    if (hjs)
-                        json_object_set_new(js, "smb", hjs);
+                    if (hjs) {
+                        jb_set_jsont(jb, "smb", hjs);
+                        json_decref(hjs);
+                    }
                     break;
                 case ALPROTO_SIP:
                     hjs = JsonSIPAddMetadata(p->flow, pa->tx_id);
-                    if (hjs)
-                        json_object_set_new(js, "sip", hjs);
+                    if (hjs) {
+                        jb_set_jsont(jb, "sip", hjs);
+                        json_decref(hjs);
+                    }
                     break;
                 case ALPROTO_RFB:
                     hjs = JsonRFBAddMetadata(p->flow, pa->tx_id);
                     if (hjs)
-                        json_object_set_new(js, "rfb", hjs);
+                        jb_set_jsont(jb, "rfb", hjs);
                     break;
                 case ALPROTO_FTPDATA:
                     hjs = JsonFTPDataAddMetadata(p->flow);
-                    if (hjs)
-                        json_object_set_new(js, "ftp-data", hjs);
+                    if (hjs) {
+                        jb_set_jsont(jb, "ftp-data", hjs);
+                        json_decref(hjs);
+                    }
                     break;
                 case ALPROTO_DNP3:
-                    AlertJsonDnp3(p->flow, pa->tx_id, js);
+                    AlertJsonDnp3(p->flow, pa->tx_id, jb);
                     break;
                 case ALPROTO_DNS:
-                    AlertJsonDns(p->flow, pa->tx_id, js);
+                    AlertJsonDns(p->flow, pa->tx_id, jb);
                     break;
                 default:
                     break;
@@ -531,12 +561,13 @@ static int AlertJson(ThreadVars *tv, JsonAlertLogThread *aft, const Packet *p)
         }
 
         if (p->flow) {
-            JsonAddAppProto(p->flow, js);
+            EveAddAppProto(p->flow, jb);
             if (json_output_ctx->flags & LOG_JSON_FLOW) {
                 hjs = json_object();
                 if (hjs != NULL) {
                     JsonAddFlow(p->flow, hjs);
-                    json_object_set_new(js, "flow", hjs);
+                    jb_set_jsont(jb, "flow", hjs);
+                    json_decref(hjs);
                 }
             }
         }
@@ -567,7 +598,7 @@ static int AlertJson(ThreadVars *tv, JsonAlertLogThread *aft, const Packet *p)
                         unsigned long len = json_output_ctx->payload_buffer_size * 2;
                         uint8_t encoded[len];
                         Base64Encode(payload->buffer, payload->offset, encoded, &len);
-                        json_object_set_new(js, "payload", json_string((char *)encoded));
+                        jb_set_string(jb, "payload", (char *)encoded);
                     }
 
                     if (json_output_ctx->flags & LOG_JSON_PAYLOAD) {
@@ -576,42 +607,41 @@ static int AlertJson(ThreadVars *tv, JsonAlertLogThread *aft, const Packet *p)
                         PrintStringsToBuffer(printable_buf, &offset,
                                 sizeof(printable_buf),
                                 payload->buffer, payload->offset);
-                        json_object_set_new(js, "payload_printable",
-                                json_string((char *)printable_buf));
+                        jb_set_string(jb, "payload_printable", (char *)printable_buf);
                     }
                 } else if (p->payload_len) {
                     /* Fallback on packet payload */
-                    AlertAddPayload(json_output_ctx, js, p);
+                    AlertAddPayload(json_output_ctx, jb, p);
                 }
             } else {
                 /* This is a single packet and not a stream */
-                AlertAddPayload(json_output_ctx, js, p);
+                AlertAddPayload(json_output_ctx, jb, p);
             }
 
-            json_object_set_new(js, "stream", json_integer(stream));
+            jb_set_uint(jb, "stream", stream);
         }
 
         /* base64-encoded full packet */
         if (json_output_ctx->flags & LOG_JSON_PACKET) {
-            JsonPacket(p, js, 0);
+            EvePacket(p, jb, 0);
         }
 
         if (have_xff_ip && xff_cfg->flags & XFF_EXTRADATA) {
-            json_object_set_new(js, "xff", json_string(xff_buffer));
+            jb_set_string(jb, "xff", xff_buffer);
         }
 
-        OutputJSONBuffer(js, aft->file_ctx, &aft->json_buffer);
-        json_decref(js);
+        OutputJsonBuilderBuffer(jb, aft->file_ctx, &aft->json_buffer);
+        jb_free(jb);
     }
 
     if ((p->flags & PKT_HAS_TAG) && (json_output_ctx->flags &
             LOG_JSON_TAGGED_PACKETS)) {
         MemBufferReset(aft->json_buffer);
-        json_t *packetjs = CreateJSONHeader(p, LOG_DIR_PACKET, "packet", NULL);
+        JsonBuilder *packetjs = CreateEveHeader(p, LOG_DIR_PACKET, "packet", NULL);
         if (unlikely(packetjs != NULL)) {
-            JsonPacket(p, packetjs, 0);
-            OutputJSONBuffer(packetjs, aft->file_ctx, &aft->json_buffer);
-            json_decref(packetjs);
+            EvePacket(p, packetjs, 0);
+            OutputJsonBuilderBuffer(packetjs, aft->file_ctx, &aft->json_buffer);
+            jb_free(packetjs);
         }
     }
 
index 7db5be76fbff21391162fc503ba32fa7d5073e6f..879e39919fff990e0120e87df4a33457e70962f1 100644 (file)
@@ -28,7 +28,7 @@
 #define __OUTPUT_JSON_ALERT_H__
 
 void JsonAlertLogRegister(void);
-void AlertJsonHeader(void *ctx, const Packet *p, const PacketAlert *pa, json_t *js,
+void AlertJsonHeader(void *ctx, const Packet *p, const PacketAlert *pa, JsonBuilder *js,
                      uint16_t flags, JsonAddrInfo *addr);
 
 #endif /* __OUTPUT_JSON_ALERT_H__ */
index f41c8ed872c8a2cddc86f35ee0fbfe7f97c1b4be..8182cfc1d160eb8cdeaa7f83ad877256933567ee 100644 (file)
@@ -90,67 +90,65 @@ static int DropLogJSON (JsonDropLogThread *aft, const Packet *p)
     JsonAddrInfo addr = json_addr_info_zero;
     JsonAddrInfoInit(p, LOG_DIR_PACKET, &addr);
 
-    json_t *js = CreateJSONHeader(p, LOG_DIR_PACKET, "drop", &addr);
+    JsonBuilder *js = CreateEveHeader(p, LOG_DIR_PACKET, "drop", &addr);
     if (unlikely(js == NULL))
         return TM_ECODE_OK;
 
-    JsonAddCommonOptions(&drop_ctx->cfg, p, p->flow, js);
+    EveAddCommonOptions(&drop_ctx->cfg, p, p->flow, js);
 
-    json_t *djs = json_object();
-    if (unlikely(djs == NULL)) {
-        json_decref(js);
-        return TM_ECODE_OK;
-    }
+    jb_open_object(js, "drop");
 
     /* reset */
     MemBufferReset(aft->buffer);
 
     uint16_t proto = 0;
     if (PKT_IS_IPV4(p)) {
-        json_object_set_new(djs, "len", json_integer(IPV4_GET_IPLEN(p)));
-        json_object_set_new(djs, "tos", json_integer(IPV4_GET_IPTOS(p)));
-        json_object_set_new(djs, "ttl", json_integer(IPV4_GET_IPTTL(p)));
-        json_object_set_new(djs, "ipid", json_integer(IPV4_GET_IPID(p)));
+        jb_set_uint(js, "len", IPV4_GET_IPLEN(p));
+        jb_set_uint(js, "tos", IPV4_GET_IPTOS(p));
+        jb_set_uint(js, "ttl", IPV4_GET_IPTTL(p));
+        jb_set_uint(js, "ipid", IPV4_GET_IPID(p));
         proto = IPV4_GET_IPPROTO(p);
     } else if (PKT_IS_IPV6(p)) {
-        json_object_set_new(djs, "len", json_integer(IPV6_GET_PLEN(p)));
-        json_object_set_new(djs, "tc", json_integer(IPV6_GET_CLASS(p)));
-        json_object_set_new(djs, "hoplimit", json_integer(IPV6_GET_HLIM(p)));
-        json_object_set_new(djs, "flowlbl", json_integer(IPV6_GET_FLOW(p)));
+        jb_set_uint(js, "len", IPV6_GET_PLEN(p));
+        jb_set_uint(js, "tc", IPV6_GET_CLASS(p));
+        jb_set_uint(js, "hoplimit", IPV6_GET_HLIM(p));
+        jb_set_uint(js, "flowlbl", IPV6_GET_FLOW(p));
         proto = IPV6_GET_L4PROTO(p);
     }
     switch (proto) {
         case IPPROTO_TCP:
             if (PKT_IS_TCP(p)) {
-                json_object_set_new(djs, "tcpseq", json_integer(TCP_GET_SEQ(p)));
-                json_object_set_new(djs, "tcpack", json_integer(TCP_GET_ACK(p)));
-                json_object_set_new(djs, "tcpwin", json_integer(TCP_GET_WINDOW(p)));
-                json_object_set_new(djs, "syn", TCP_ISSET_FLAG_SYN(p) ? json_true() : json_false());
-                json_object_set_new(djs, "ack", TCP_ISSET_FLAG_ACK(p) ? json_true() : json_false());
-                json_object_set_new(djs, "psh", TCP_ISSET_FLAG_PUSH(p) ? json_true() : json_false());
-                json_object_set_new(djs, "rst", TCP_ISSET_FLAG_RST(p) ? json_true() : json_false());
-                json_object_set_new(djs, "urg", TCP_ISSET_FLAG_URG(p) ? json_true() : json_false());
-                json_object_set_new(djs, "fin", TCP_ISSET_FLAG_FIN(p) ? json_true() : json_false());
-                json_object_set_new(djs, "tcpres", json_integer(TCP_GET_RAW_X2(p->tcph)));
-                json_object_set_new(djs, "tcpurgp", json_integer(TCP_GET_URG_POINTER(p)));
+                jb_set_uint(js, "tcpseq", TCP_GET_SEQ(p));
+                jb_set_uint(js, "tcpack", TCP_GET_ACK(p));
+                jb_set_uint(js, "tcpwin", TCP_GET_WINDOW(p));
+                jb_set_bool(js, "syn", TCP_ISSET_FLAG_SYN(p) ? true : false);
+                jb_set_bool(js, "ack", TCP_ISSET_FLAG_ACK(p) ? true : false);
+                jb_set_bool(js, "psh", TCP_ISSET_FLAG_PUSH(p) ? true : false);
+                jb_set_bool(js, "rst", TCP_ISSET_FLAG_RST(p) ? true : false);
+                jb_set_bool(js, "urg", TCP_ISSET_FLAG_URG(p) ? true : false);
+                jb_set_bool(js, "fin", TCP_ISSET_FLAG_FIN(p) ? true : false);
+                jb_set_uint(js, "tcpres",  TCP_GET_RAW_X2(p->tcph));
+                jb_set_uint(js, "tcpurgp", TCP_GET_URG_POINTER(p));
             }
             break;
         case IPPROTO_UDP:
             if (PKT_IS_UDP(p)) {
-                json_object_set_new(djs, "udplen", json_integer(UDP_GET_LEN(p)));
+                jb_set_uint(js, "udplen", UDP_GET_LEN(p));
             }
             break;
         case IPPROTO_ICMP:
             if (PKT_IS_ICMPV4(p)) {
-                json_object_set_new(djs, "icmp_id", json_integer(ICMPV4_GET_ID(p)));
-                json_object_set_new(djs, "icmp_seq", json_integer(ICMPV4_GET_SEQ(p)));
+                jb_set_uint(js, "icmp_id", ICMPV4_GET_ID(p));
+                jb_set_uint(js, "icmp_seq", ICMPV4_GET_SEQ(p));
             } else if(PKT_IS_ICMPV6(p)) {
-                json_object_set_new(djs, "icmp_id", json_integer(ICMPV6_GET_ID(p)));
-                json_object_set_new(djs, "icmp_seq", json_integer(ICMPV6_GET_SEQ(p)));
+                jb_set_uint(js, "icmp_id", ICMPV6_GET_ID(p));
+                jb_set_uint(js, "icmp_seq", ICMPV6_GET_SEQ(p));
             }
             break;
     }
-    json_object_set_new(js, "drop", djs);
+
+    /* Close drop. */
+    jb_close(js);
 
     if (aft->drop_ctx->flags & LOG_DROP_ALERTS) {
         int logged = 0;
@@ -175,10 +173,8 @@ static int DropLogJSON (JsonDropLogThread *aft, const Packet *p)
         }
     }
 
-    OutputJSONBuffer(js, aft->drop_ctx->file_ctx, &aft->buffer);
-    json_object_del(js, "drop");
-    json_object_clear(js);
-    json_decref(js);
+    OutputJsonBuilderBuffer(js, aft->drop_ctx->file_ctx, &aft->buffer);
+    jb_free(js);
 
     return TM_ECODE_OK;
 }
index 6f58b5da992af4e6a431f75f7696de4438a3f043..a3c26c17b582346515a87b604b363cc31570c83e 100644 (file)
@@ -200,6 +200,27 @@ void JsonAddAppProto(Flow *f, json_t *js)
 
 }
 
+void EveAddAppProto(Flow *f, JsonBuilder *js)
+{
+    if (f->alproto) {
+        jb_set_string(js, "app_proto", AppProtoToString(f->alproto));
+    }
+    if (f->alproto_ts && f->alproto_ts != f->alproto) {
+        jb_set_string(js, "app_proto_ts", AppProtoToString(f->alproto_ts));
+    }
+    if (f->alproto_tc && f->alproto_tc != f->alproto) {
+        jb_set_string(js, "app_proto_tc", AppProtoToString(f->alproto_tc));
+    }
+    if (f->alproto_orig != f->alproto && f->alproto_orig != ALPROTO_UNKNOWN) {
+        jb_set_string(js, "app_proto_orig", AppProtoToString(f->alproto_orig));
+    }
+    if (f->alproto_expect != f->alproto && f->alproto_expect != ALPROTO_UNKNOWN) {
+        jb_set_string(js, "app_proto_expected",
+                AppProtoToString(f->alproto_expect));
+    }
+
+}
+
 void JsonAddFlow(Flow *f, json_t *js)
 {
     FlowBypassInfo *fc = FlowGetStorageById(f, GetFlowBypassInfoID());
index d4b017b522719a9e02bbc1dadc5e85ad74a2e51b..ffdeafef5b385fa8cb7183541bf8762e094d61a6 100644 (file)
@@ -27,5 +27,6 @@
 void JsonFlowLogRegister(void);
 void JsonAddFlow(Flow *f, json_t *js);
 void JsonAddAppProto(Flow *f, json_t *js);
+void EveAddAppProto(Flow *f, JsonBuilder *js);
 
 #endif /* __OUTPUT_JSON_FLOW_H__ */
index ff6ca1616302b942d7066355ee96756b3514730f..11aa6eefe2a3a9e352d3323fc31e24bf41d6fece 100644 (file)
@@ -76,6 +76,7 @@
 
 static void OutputJsonDeInitCtx(OutputCtx *);
 static void CreateJSONCommunityFlowId(json_t *js, const Flow *f, const uint16_t seed);
+static void CreateEveCommunityFlowId(JsonBuilder *js, const Flow *f, const uint16_t seed);
 
 static const char *TRAFFIC_ID_PREFIX = "traffic/id/";
 static const char *TRAFFIC_LABEL_PREFIX = "traffic/label/";
@@ -150,6 +151,7 @@ json_t *JsonAddStringN(const char *string, size_t size)
 
     return SCJsonString(tmpbuf);
 }
+
 static void JsonAddPacketvars(const Packet *p, json_t *js_vars)
 {
     if (p == NULL || p->pktvar == NULL) {
@@ -204,6 +206,53 @@ static void JsonAddPacketvars(const Packet *p, json_t *js_vars)
     }
 }
 
+static void EveAddPacketVars(const Packet *p, JsonBuilder *js_vars)
+{
+    if (p == NULL || p->pktvar == NULL) {
+        return;
+    }
+    PktVar *pv = p->pktvar;
+    bool open = false;
+    while (pv != NULL) {
+        if (pv->key || pv->id > 0) {
+            if (!open) {
+                jb_open_array(js_vars, "pktvars");
+                open = true;
+            }
+            jb_start_object(js_vars);
+
+            if (pv->key != NULL) {
+                uint32_t offset = 0;
+                uint8_t keybuf[pv->key_len + 1];
+                PrintStringsToBuffer(keybuf, &offset,
+                        sizeof(keybuf),
+                        pv->key, pv->key_len);
+                uint32_t len = pv->value_len;
+                uint8_t printable_buf[len + 1];
+                offset = 0;
+                PrintStringsToBuffer(printable_buf, &offset,
+                        sizeof(printable_buf),
+                        pv->value, pv->value_len);
+                jb_set_string(js_vars, (char *)keybuf, (char *)printable_buf);
+            } else {
+                const char *varname = VarNameStoreLookupById(pv->id, VAR_TYPE_PKT_VAR);
+                uint32_t len = pv->value_len;
+                uint8_t printable_buf[len + 1];
+                uint32_t offset = 0;
+                PrintStringsToBuffer(printable_buf, &offset,
+                        sizeof(printable_buf),
+                        pv->value, pv->value_len);
+                jb_set_string(js_vars, varname, (char *)printable_buf);
+            }
+            jb_close(js_vars);
+        }
+        pv = pv->next;
+    }
+    if (open) {
+        jb_close(js_vars);
+    }
+}
+
 /**
  * \brief Check if string s has prefix prefix.
  *
@@ -365,6 +414,144 @@ static void JsonAddFlowVars(const Flow *f, json_t *js_root, json_t **js_traffic)
     }
 }
 
+static void EveAddFlowVars(const Flow *f, JsonBuilder *js_root, JsonBuilder **js_traffic)
+{
+    if (f == NULL || f->flowvar == NULL) {
+        return;
+    }
+    JsonBuilder *js_flowvars = NULL;
+    JsonBuilder *js_traffic_id = NULL;
+    JsonBuilder *js_traffic_label = NULL;
+    JsonBuilder *js_flowints = NULL;
+    JsonBuilder *js_flowbits = NULL;
+    GenericVar *gv = f->flowvar;
+    while (gv != NULL) {
+        if (gv->type == DETECT_FLOWVAR || gv->type == DETECT_FLOWINT) {
+            FlowVar *fv = (FlowVar *)gv;
+            if (fv->datatype == FLOWVAR_TYPE_STR && fv->key == NULL) {
+                const char *varname = VarNameStoreLookupById(fv->idx,
+                        VAR_TYPE_FLOW_VAR);
+                if (varname) {
+                    if (js_flowvars == NULL) {
+                        js_flowvars = jb_new_array();
+                        if (js_flowvars == NULL)
+                            break;
+                    }
+
+                    uint32_t len = fv->data.fv_str.value_len;
+                    uint8_t printable_buf[len + 1];
+                    uint32_t offset = 0;
+                    PrintStringsToBuffer(printable_buf, &offset,
+                            sizeof(printable_buf),
+                            fv->data.fv_str.value, fv->data.fv_str.value_len);
+
+                    jb_start_object(js_flowvars);
+                    jb_set_string(js_flowvars, varname, (char *)printable_buf);
+                    jb_close(js_flowvars);
+                }
+            } else if (fv->datatype == FLOWVAR_TYPE_STR && fv->key != NULL) {
+                if (js_flowvars == NULL) {
+                    js_flowvars = jb_new_array();
+                    if (js_flowvars == NULL)
+                        break;
+                }
+
+                uint8_t keybuf[fv->keylen + 1];
+                uint32_t offset = 0;
+                PrintStringsToBuffer(keybuf, &offset,
+                        sizeof(keybuf),
+                        fv->key, fv->keylen);
+
+                uint32_t len = fv->data.fv_str.value_len;
+                uint8_t printable_buf[len + 1];
+                offset = 0;
+                PrintStringsToBuffer(printable_buf, &offset,
+                        sizeof(printable_buf),
+                        fv->data.fv_str.value, fv->data.fv_str.value_len);
+
+                jb_start_object(js_flowvars);
+                jb_set_string(js_flowvars, (const char *)keybuf, (char *)printable_buf);
+                jb_close(js_flowvars);
+            } else if (fv->datatype == FLOWVAR_TYPE_INT) {
+                const char *varname = VarNameStoreLookupById(fv->idx,
+                        VAR_TYPE_FLOW_INT);
+                if (varname) {
+                    if (js_flowints == NULL) {
+                        js_flowints = jb_new_object();
+                        if (js_flowints == NULL)
+                            break;
+                    }
+                    jb_set_uint(js_flowints, varname, fv->data.fv_int.value);
+                }
+
+            }
+        } else if (gv->type == DETECT_FLOWBITS) {
+            FlowBit *fb = (FlowBit *)gv;
+            const char *varname = VarNameStoreLookupById(fb->idx,
+                    VAR_TYPE_FLOW_BIT);
+            if (varname) {
+                if (SCStringHasPrefix(varname, TRAFFIC_ID_PREFIX)) {
+                    if (js_traffic_id == NULL) {
+                        js_traffic_id = jb_new_array();
+                        if (unlikely(js_traffic_id == NULL)) {
+                            break;
+                        }
+                    }
+                    jb_append_string(js_traffic_id, &varname[traffic_id_prefix_len]);
+                } else if (SCStringHasPrefix(varname, TRAFFIC_LABEL_PREFIX)) {
+                    if (js_traffic_label == NULL) {
+                        js_traffic_label = jb_new_array();
+                        if (unlikely(js_traffic_label == NULL)) {
+                            break;
+                        }
+                    }
+                    jb_append_string(js_traffic_label, &varname[traffic_label_prefix_len]);
+                } else {
+                    if (js_flowbits == NULL) {
+                        js_flowbits = jb_new_array();
+                        if (unlikely(js_flowbits == NULL))
+                            break;
+                    }
+                    jb_append_string(js_flowbits, varname);
+                }
+            }
+        }
+        gv = gv->next;
+    }
+    if (js_flowbits) {
+        jb_close(js_flowbits);
+        jb_set_object(js_root, "flowbits", js_flowbits);
+        jb_free(js_flowbits);
+    }
+    if (js_flowints) {
+        jb_close(js_flowints);
+        jb_set_object(js_root, "flowints", js_flowints);
+        jb_free(js_flowints);
+    }
+    if (js_flowvars) {
+        jb_close(js_flowvars);
+        jb_set_object(js_root, "flowvars", js_flowvars);
+        jb_free(js_flowvars);
+    }
+
+    if (js_traffic_id != NULL || js_traffic_label != NULL) {
+        *js_traffic = jb_new_object();
+        if (likely(*js_traffic != NULL)) {
+            if (js_traffic_id != NULL) {
+                jb_close(js_traffic_id);
+                jb_set_object(*js_traffic, "id", js_traffic_id);
+                jb_free(js_traffic_id);
+            }
+            if (js_traffic_label != NULL) {
+                jb_close(js_traffic_label);
+                jb_set_object(*js_traffic, "label", js_traffic_label);
+                jb_free(js_traffic_label);
+            }
+            jb_close(*js_traffic);
+        }
+    }
+}
+
 /**
  * \brief Add top-level metadata to the eve json object.
  */
@@ -389,6 +576,29 @@ static void JsonAddMetadata(const Packet *p, const Flow *f, json_t *js)
     }
 }
 
+static void EveAddMetadata(const Packet *p, const Flow *f, JsonBuilder *js)
+{
+    if ((p && p->pktvar) || (f && f->flowvar)) {
+        JsonBuilder *js_vars = jb_new_object();
+        if (js_vars) {
+            if (f && f->flowvar) {
+                JsonBuilder *js_traffic = NULL;
+                EveAddFlowVars(f, js_vars, &js_traffic);
+                if (js_traffic != NULL) {
+                    jb_set_object(js, "traffic", js_traffic);
+                    jb_free(js_traffic);
+                }
+            }
+            if (p && p->pktvar) {
+                EveAddPacketVars(p, js_vars);
+            }
+            jb_close(js_vars);
+            jb_set_object(js, "metadata", js_vars);
+            jb_free(js_vars);
+        }
+    }
+}
+
 void JsonAddCommonOptions(const OutputJsonCommonSettings *cfg,
         const Packet *p, const Flow *f, json_t *js)
 {
@@ -400,6 +610,17 @@ void JsonAddCommonOptions(const OutputJsonCommonSettings *cfg,
     }
 }
 
+void EveAddCommonOptions(const OutputJsonCommonSettings *cfg,
+        const Packet *p, const Flow *f, JsonBuilder *js)
+{
+    if (cfg->include_metadata) {
+        EveAddMetadata(p, f, js);
+    }
+    if (cfg->include_community_id && f != NULL) {
+        CreateEveCommunityFlowId(js, f, cfg->community_id_seed);
+    }
+}
+
 /**
  * \brief Jsonify a packet
  *
@@ -424,6 +645,32 @@ void JsonPacket(const Packet *p, json_t *js, unsigned long max_length)
     json_object_set_new(packetinfo_js, "linktype", json_integer(p->datalink));
     json_object_set_new(js, "packet_info", packetinfo_js);
 }
+
+/**
+ * \brief Jsonify a packet
+ *
+ * \param p Packet
+ * \param js JSON object
+ * \param max_length If non-zero, restricts the number of packet data bytes handled.
+ */
+void EvePacket(const Packet *p, JsonBuilder *js, unsigned long max_length)
+{
+    unsigned long max_len = max_length == 0 ? GET_PKT_LEN(p) : max_length;
+    unsigned long len = 2 * max_len;
+    uint8_t encoded_packet[len];
+    if (Base64Encode((unsigned char*) GET_PKT_DATA(p), max_len, encoded_packet, &len) == SC_BASE64_OK) {
+        jb_set_string(js, "packet", (char *)encoded_packet);
+    }
+
+    if (!jb_open_object(js, "packet_info")) {
+        return;
+    }
+    if (!jb_set_uint(js, "linktype", p->datalink)) {
+        return;
+    }
+    jb_close(js);
+}
+
 /** \brief jsonify tcp flags field
  *  Only add 'true' fields in an attempt to keep things reasonably compact.
  */
@@ -706,8 +953,10 @@ void JsonFiveTuple(const Packet *p, enum OutputJsonLogDirection dir, json_t *js)
     json_object_set_new(js, "proto", json_string(proto));
 }
 
-static void CreateJSONCommunityFlowIdv4(json_t *js, const Flow *f,
-        const uint16_t seed)
+#define COMMUNITY_ID_BUF_SIZE 64
+
+static bool CalculateCommunityFlowIdv4(const Flow *f,
+        const uint16_t seed, unsigned char *base64buf)
 {
     struct {
         uint16_t seed;
@@ -747,12 +996,13 @@ static void CreateJSONCommunityFlowIdv4(json_t *js, const Flow *f,
 
     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;
+        strlcpy((char *)base64buf, "1:", COMMUNITY_ID_BUF_SIZE);
+        unsigned long out_len = COMMUNITY_ID_BUF_SIZE - 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));
+            return true;
         }
     }
+    return false;
 }
 
 static inline bool FlowHashRawAddressIPv6LtU32(const uint32_t *a, const uint32_t *b)
@@ -767,8 +1017,8 @@ static inline bool FlowHashRawAddressIPv6LtU32(const uint32_t *a, const uint32_t
     return false;
 }
 
-static void CreateJSONCommunityFlowIdv6(json_t *js, const Flow *f,
-        const uint16_t seed)
+static bool CalculateCommunityFlowIdv6(const Flow *f,
+        const uint16_t seed, unsigned char *base64buf)
 {
     struct {
         uint16_t seed;
@@ -808,20 +1058,41 @@ static void CreateJSONCommunityFlowIdv6(json_t *js, const Flow *f,
 
     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;
+        strlcpy((char *)base64buf, "1:", COMMUNITY_ID_BUF_SIZE);
+        unsigned long out_len = COMMUNITY_ID_BUF_SIZE - 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));
+            return true;
         }
     }
+    return false;
 }
 
 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);
+    unsigned char buf[COMMUNITY_ID_BUF_SIZE];
+    if (f->flags & FLOW_IPV4) {
+        if (CalculateCommunityFlowIdv4(f, seed, buf)) {
+            json_object_set_new(js, "community_id", json_string((const char *)buf));
+        }
+    } else if (f->flags & FLOW_IPV6) {
+        if (CalculateCommunityFlowIdv6(f, seed, buf)) {
+            json_object_set_new(js, "community_id", json_string((const char *)buf));
+        }
+    }
+}
+
+static void CreateEveCommunityFlowId(JsonBuilder *js, const Flow *f, const uint16_t seed)
+{
+    unsigned char buf[COMMUNITY_ID_BUF_SIZE];
+    if (f->flags & FLOW_IPV4) {
+        if (CalculateCommunityFlowIdv4(f, seed, buf)) {
+            jb_set_string(js, "community_id", (const char *)buf);
+        }
+    } else if (f->flags & FLOW_IPV6) {
+        if (CalculateCommunityFlowIdv6(f, seed, buf)) {
+            jb_set_string(js, "community_id", (const char *)buf);
+        }
+    }
 }
 
 void CreateJSONFlowId(json_t *js, const Flow *f)
@@ -835,6 +1106,18 @@ void CreateJSONFlowId(json_t *js, const Flow *f)
     }
 }
 
+void CreateEveFlowId(JsonBuilder *js, const Flow *f)
+{
+    if (f == NULL) {
+        return;
+    }
+    int64_t flow_id = FlowGetId(f);
+    jb_set_uint(js, "flow_id", flow_id);
+    if (f->parent_id) {
+        jb_set_uint(js, "parent_id", f->parent_id);
+    }
+}
+
 json_t *CreateJSONHeader(const Packet *p, enum OutputJsonLogDirection dir,
                          const char *event_type, JsonAddrInfo *addr)
 {
@@ -917,6 +1200,83 @@ json_t *CreateJSONHeader(const Packet *p, enum OutputJsonLogDirection dir,
     return js;
 }
 
+JsonBuilder *CreateEveHeader(const Packet *p, enum OutputJsonLogDirection dir,
+        const char *event_type, JsonAddrInfo *addr)
+{
+    char timebuf[64];
+    const Flow *f = (const Flow *)p->flow;
+
+    JsonBuilder *js = jb_new_object();
+    if (unlikely(js == NULL)) {
+        return NULL;
+    }
+
+    CreateIsoTimeString(&p->ts, timebuf, sizeof(timebuf));
+
+    jb_set_string(js, "timestamp", timebuf);
+
+    CreateEveFlowId(js, f);
+
+    /* sensor id */
+    if (sensor_id >= 0) {
+        jb_set_uint(js, "sensor_id", sensor_id);
+    }
+
+    /* input interface */
+    if (p->livedev) {
+        jb_set_string(js, "in_iface", p->livedev->dev);
+    }
+
+    /* pcap_cnt */
+    if (p->pcap_cnt != 0) {
+        jb_set_uint(js, "pcap_cnt", p->pcap_cnt);
+    }
+
+    if (event_type) {
+        jb_set_string(js, "event_type", event_type);
+    }
+
+    /* vlan */
+    if (p->vlan_idx > 0) {
+        jb_open_array(js, "vlan");
+        jb_append_uint(js, p->vlan_id[0]);
+        if (p->vlan_idx > 1) {
+            jb_append_uint(js, p->vlan_id[1]);
+        }
+        jb_close(js);
+    }
+
+    /* 5-tuple */
+    JsonAddrInfo addr_info = json_addr_info_zero;
+    if (addr == NULL) {
+        JsonAddrInfoInit(p, dir, &addr_info);
+        addr = &addr_info;
+    }
+    jb_set_string(js, "src_ip", addr->src_ip);
+    jb_set_uint(js, "src_port", addr->sp);
+    jb_set_string(js, "dest_ip", addr->dst_ip);
+    jb_set_uint(js, "dest_port", addr->dp);
+    jb_set_string(js, "proto", addr->proto);
+
+    /* icmp */
+    switch (p->proto) {
+        case IPPROTO_ICMP:
+            if (p->icmpv4h) {
+                jb_set_uint(js, "icmp_type", p->icmpv4h->type);
+                jb_set_uint(js, "icmp_code", p->icmpv4h->code);
+            }
+            break;
+        case IPPROTO_ICMPV6:
+            if (p->icmpv6h) {
+                jb_set_uint(js, "icmp_type", p->icmpv6h->type);
+                jb_set_uint(js, "icmp_code", p->icmpv6h->code);
+            }
+            break;
+    }
+
+    return js;
+}
+
 json_t *CreateJSONHeaderWithTxId(const Packet *p, enum OutputJsonLogDirection dir,
                                  const char *event_type, uint64_t tx_id)
 {
@@ -972,6 +1332,33 @@ int OutputJSONBuffer(json_t *js, LogFileCtx *file_ctx, MemBuffer **buffer)
     return 0;
 }
 
+int OutputJsonBuilderBuffer(JsonBuilder *js, LogFileCtx *file_ctx, MemBuffer **buffer)
+{
+    if (file_ctx->sensor_name) {
+        jb_set_string(js, "host", file_ctx->sensor_name);
+    }
+
+    if (file_ctx->is_pcap_offline) {
+        jb_set_string(js, "pcap_filename", PcapFileGetFilename());
+    }
+
+    jb_close(js);
+
+    if (file_ctx->prefix) {
+        MemBufferWriteRaw((*buffer), file_ctx->prefix, file_ctx->prefix_len);
+    }
+
+    size_t jslen = jb_len(js);
+    if (MEMBUFFER_OFFSET(*buffer) + jslen >= MEMBUFFER_SIZE(*buffer)) {
+        MemBufferExpand(buffer, jslen);
+    }
+
+    MemBufferWriteRaw((*buffer), jb_ptr(js), jslen);
+    LogFileWrite(file_ctx, *buffer);
+
+    return 0;
+}
+
 /**
  * \brief Create a new LogFileCtx for "fast" output style.
  * \param conf The configuration node for this output.
index d928a9ee4c12810c47d59c8390e21e73da6fa548..01c00702329b4c6e9531dbf0d1a9fe74d12280d7 100644 (file)
@@ -28,6 +28,7 @@
 #include "util-buffer.h"
 #include "util-logopenfile.h"
 #include "output.h"
+#include "rust.h"
 
 #include "app-layer-htp-xff.h"
 
@@ -69,15 +70,21 @@ typedef struct OutputJSONMemBufferWrapper_ {
 int OutputJSONMemBufferCallback(const char *str, size_t size, void *data);
 
 void CreateJSONFlowId(json_t *js, const Flow *f);
+void CreateEveFlowId(JsonBuilder *js, const Flow *f);
 void JsonTcpFlags(uint8_t flags, json_t *js);
 void JsonPacket(const Packet *p, json_t *js, unsigned long max_length);
+void EvePacket(const Packet *p, JsonBuilder *js, unsigned long max_length);
 void JsonFiveTuple(const Packet *, enum OutputJsonLogDirection, json_t *);
 json_t *CreateJSONHeader(const Packet *p,
         enum OutputJsonLogDirection dir, const char *event_type,
         JsonAddrInfo *addr);
+JsonBuilder *CreateEveHeader(const Packet *p,
+        enum OutputJsonLogDirection dir, const char *event_type,
+        JsonAddrInfo *addr);
 json_t *CreateJSONHeaderWithTxId(const Packet *p,
         enum OutputJsonLogDirection dir, const char *event_type, uint64_t tx_id);
 int OutputJSONBuffer(json_t *js, LogFileCtx *file_ctx, MemBuffer **buffer);
+int OutputJsonBuilderBuffer(JsonBuilder *js, LogFileCtx *file_ctx, MemBuffer **buffer);
 OutputInitResult OutputJsonInitCtx(ConfNode *);
 
 OutputInitResult OutputJsonLogInitSub(ConfNode *conf, OutputCtx *parent_ctx);
@@ -112,5 +119,7 @@ void SCJsonDecref(json_t *js);
 
 void JsonAddCommonOptions(const OutputJsonCommonSettings *cfg,
         const Packet *p, const Flow *f, json_t *js);
+void EveAddCommonOptions(const OutputJsonCommonSettings *cfg,
+        const Packet *p, const Flow *f, JsonBuilder *js);
 
 #endif /* __OUTPUT_JSON_H__ */