suricata
output-json.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-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 Tom DeCanio <td@npulsetech.com>
22  *
23  * Logs detection and monitoring events in JSON format.
24  *
25  */
26 
27 #include "suricata-common.h"
28 #include "debug.h"
29 #include "detect.h"
30 #include "flow.h"
31 #include "conf.h"
32 
33 #include "threads.h"
34 #include "tm-threads.h"
35 #include "threadvars.h"
36 #include "util-debug.h"
37 
38 #include "util-unittest.h"
39 #include "util-unittest-helper.h"
40 
41 #include "detect-parse.h"
42 #include "detect-engine.h"
43 #include "detect-engine-mpm.h"
44 #include "detect-reference.h"
45 #include "app-layer-parser.h"
47 #include "util-syslog.h"
48 
49 #include "output.h"
50 #include "output-json.h"
51 
52 #include "util-byte.h"
53 #include "util-privs.h"
54 #include "util-print.h"
55 #include "util-proto-name.h"
56 #include "util-optimize.h"
57 #include "util-buffer.h"
58 #include "util-logopenfile.h"
59 #include "util-log-redis.h"
60 #include "util-device.h"
61 #include "util-validate.h"
62 #include "util-crypt.h"
63 
64 #include "flow-var.h"
65 #include "flow-bit.h"
66 
67 #include "source-pcap-file.h"
68 
69 #ifndef HAVE_LIBJANSSON
70 
71 /** Handle the case where no JSON support is compiled in.
72  *
73  */
74 
75 int OutputJsonOpenFileCtx(LogFileCtx *, char *);
76 
77 void OutputJsonRegister (void)
78 {
79  SCLogDebug("Can't register JSON output - JSON support was disabled during build.");
80 }
81 
82 #else /* implied we do have JSON support */
83 
84 #define DEFAULT_LOG_FILENAME "eve.json"
85 #define DEFAULT_ALERT_SYSLOG_FACILITY_STR "local0"
86 #define DEFAULT_ALERT_SYSLOG_FACILITY LOG_LOCAL0
87 #define DEFAULT_ALERT_SYSLOG_LEVEL LOG_INFO
88 #define MODULE_NAME "OutputJSON"
89 
90 #define OUTPUT_BUFFER_SIZE 65536
91 #define MAX_JSON_SIZE 2048
92 
93 static void OutputJsonDeInitCtx(OutputCtx *);
94 static void CreateJSONCommunityFlowId(json_t *js, const Flow *f, const uint16_t seed);
95 
96 static const char *TRAFFIC_ID_PREFIX = "traffic/id/";
97 static const char *TRAFFIC_LABEL_PREFIX = "traffic/label/";
98 static size_t traffic_id_prefix_len = 0;
99 static size_t traffic_label_prefix_len = 0;
100 
101 void OutputJsonRegister (void)
102 {
103  OutputRegisterModule(MODULE_NAME, "eve-log", OutputJsonInitCtx);
104 
105  traffic_id_prefix_len = strlen(TRAFFIC_ID_PREFIX);
106  traffic_label_prefix_len = strlen(TRAFFIC_LABEL_PREFIX);
107 }
108 
109 json_t *SCJsonBool(int val)
110 {
111  return (val ? json_true() : json_false());
112 }
113 
114 /**
115  * Wrap json_decref. This is mainly to expose this function to Rust as its
116  * defined in the Jansson header file as an inline function.
117  */
118 void SCJsonDecref(json_t *json)
119 {
120  json_decref(json);
121 }
122 
123 json_t *SCJsonString(const char *val)
124 {
125  if (val == NULL){
126  return NULL;
127  }
128  json_t * retval = json_string(val);
129  char retbuf[MAX_JSON_SIZE] = {0};
130  if (retval == NULL) {
131  uint32_t u = 0;
132  uint32_t offset = 0;
133  for (u = 0; u < strlen(val); u++) {
134  if (isprint(val[u])) {
135  PrintBufferData(retbuf, &offset, MAX_JSON_SIZE-1, "%c",
136  val[u]);
137  } else {
138  PrintBufferData(retbuf, &offset, MAX_JSON_SIZE-1,
139  "\\x%02X", val[u]);
140  }
141  }
142  retbuf[offset] = '\0';
143  retval = json_string(retbuf);
144  }
145  return retval;
146 }
147 
148 /* Default Sensor ID value */
149 static int64_t sensor_id = -1; /* -1 = not defined */
150 
151 static void JsonAddPacketvars(const Packet *p, json_t *js_vars)
152 {
153  if (p == NULL || p->pktvar == NULL) {
154  return;
155  }
156  json_t *js_pktvars = NULL;
157  PktVar *pv = p->pktvar;
158  while (pv != NULL) {
159  if (pv->key || pv->id > 0) {
160  if (js_pktvars == NULL) {
161  js_pktvars = json_array();
162  if (js_pktvars == NULL)
163  break;
164  }
165  json_t *js_pair = json_object();
166  if (js_pair == NULL) {
167  break;
168  }
169 
170  if (pv->key != NULL) {
171  uint32_t offset = 0;
172  uint8_t keybuf[pv->key_len + 1];
173  PrintStringsToBuffer(keybuf, &offset,
174  sizeof(keybuf),
175  pv->key, pv->key_len);
176  uint32_t len = pv->value_len;
177  uint8_t printable_buf[len + 1];
178  offset = 0;
179  PrintStringsToBuffer(printable_buf, &offset,
180  sizeof(printable_buf),
181  pv->value, pv->value_len);
182  json_object_set_new(js_pair, (char *)keybuf,
183  json_string((char *)printable_buf));
184  } else {
185  const char *varname = VarNameStoreLookupById(pv->id, VAR_TYPE_PKT_VAR);
186  uint32_t len = pv->value_len;
187  uint8_t printable_buf[len + 1];
188  uint32_t offset = 0;
189  PrintStringsToBuffer(printable_buf, &offset,
190  sizeof(printable_buf),
191  pv->value, pv->value_len);
192 
193  json_object_set_new(js_pair, varname,
194  json_string((char *)printable_buf));
195  }
196  json_array_append_new(js_pktvars, js_pair);
197  }
198  pv = pv->next;
199  }
200  if (js_pktvars) {
201  json_object_set_new(js_vars, "pktvars", js_pktvars);
202  }
203 }
204 
205 /**
206  * \brief Check if string s has prefix prefix.
207  *
208  * \retval true if string has prefix
209  * \retval false if string does not have prefix
210  *
211  * TODO: Move to file with other string handling functions.
212  */
213 static bool SCStringHasPrefix(const char *s, const char *prefix)
214 {
215  if (strncmp(s, prefix, strlen(prefix)) == 0) {
216  return true;
217  }
218  return false;
219 }
220 
221 /**
222  * \brief Add flow variables to a json object.
223  *
224  * Adds "flowvars" (map), "flowints" (map) and "flowbits" (array) to
225  * the json object provided as js_root.
226  */
227 static void JsonAddFlowVars(const Flow *f, json_t *js_root, json_t **js_traffic)
228 {
229  if (f == NULL || f->flowvar == NULL) {
230  return;
231  }
232  json_t *js_flowvars = NULL;
233  json_t *js_traffic_id = NULL;
234  json_t *js_traffic_label = NULL;
235  json_t *js_flowints = NULL;
236  json_t *js_flowbits = NULL;
237  GenericVar *gv = f->flowvar;
238  while (gv != NULL) {
239  if (gv->type == DETECT_FLOWVAR || gv->type == DETECT_FLOWINT) {
240  FlowVar *fv = (FlowVar *)gv;
241  if (fv->datatype == FLOWVAR_TYPE_STR && fv->key == NULL) {
242  const char *varname = VarNameStoreLookupById(fv->idx,
244  if (varname) {
245  if (js_flowvars == NULL) {
246  js_flowvars = json_array();
247  if (js_flowvars == NULL)
248  break;
249  }
250 
251  uint32_t len = fv->data.fv_str.value_len;
252  uint8_t printable_buf[len + 1];
253  uint32_t offset = 0;
254  PrintStringsToBuffer(printable_buf, &offset,
255  sizeof(printable_buf),
256  fv->data.fv_str.value, fv->data.fv_str.value_len);
257 
258  json_t *js_flowvar = json_object();
259  if (unlikely(js_flowvar == NULL)) {
260  break;
261  }
262  json_object_set_new(js_flowvar, varname,
263  json_string((char *)printable_buf));
264  json_array_append_new(js_flowvars, js_flowvar);
265  }
266  } else if (fv->datatype == FLOWVAR_TYPE_STR && fv->key != NULL) {
267  if (js_flowvars == NULL) {
268  js_flowvars = json_array();
269  if (js_flowvars == NULL)
270  break;
271  }
272 
273  uint8_t keybuf[fv->keylen + 1];
274  uint32_t offset = 0;
275  PrintStringsToBuffer(keybuf, &offset,
276  sizeof(keybuf),
277  fv->key, fv->keylen);
278 
279  uint32_t len = fv->data.fv_str.value_len;
280  uint8_t printable_buf[len + 1];
281  offset = 0;
282  PrintStringsToBuffer(printable_buf, &offset,
283  sizeof(printable_buf),
284  fv->data.fv_str.value, fv->data.fv_str.value_len);
285 
286  json_t *js_flowvar = json_object();
287  if (unlikely(js_flowvar == NULL)) {
288  break;
289  }
290  json_object_set_new(js_flowvar, (const char *)keybuf,
291  json_string((char *)printable_buf));
292  json_array_append_new(js_flowvars, js_flowvar);
293  } else if (fv->datatype == FLOWVAR_TYPE_INT) {
294  const char *varname = VarNameStoreLookupById(fv->idx,
296  if (varname) {
297  if (js_flowints == NULL) {
298  js_flowints = json_object();
299  if (js_flowints == NULL)
300  break;
301  }
302 
303  json_object_set_new(js_flowints, varname,
304  json_integer(fv->data.fv_int.value));
305  }
306 
307  }
308  } else if (gv->type == DETECT_FLOWBITS) {
309  FlowBit *fb = (FlowBit *)gv;
310  const char *varname = VarNameStoreLookupById(fb->idx,
312  if (varname) {
313  if (SCStringHasPrefix(varname, TRAFFIC_ID_PREFIX)) {
314  if (js_traffic_id == NULL) {
315  js_traffic_id = json_array();
316  if (unlikely(js_traffic_id == NULL)) {
317  break;
318  }
319  }
320  json_array_append_new(js_traffic_id,
321  json_string(&varname[traffic_id_prefix_len]));
322  } else if (SCStringHasPrefix(varname, TRAFFIC_LABEL_PREFIX)) {
323  if (js_traffic_label == NULL) {
324  js_traffic_label = json_array();
325  if (unlikely(js_traffic_label == NULL)) {
326  break;
327  }
328  }
329  json_array_append_new(js_traffic_label,
330  json_string(&varname[traffic_label_prefix_len]));
331  } else {
332  if (js_flowbits == NULL) {
333  js_flowbits = json_array();
334  if (unlikely(js_flowbits == NULL))
335  break;
336  }
337  json_array_append_new(js_flowbits, json_string(varname));
338  }
339  }
340  }
341  gv = gv->next;
342  }
343  if (js_flowbits) {
344  json_object_set_new(js_root, "flowbits", js_flowbits);
345  }
346  if (js_flowints) {
347  json_object_set_new(js_root, "flowints", js_flowints);
348  }
349  if (js_flowvars) {
350  json_object_set_new(js_root, "flowvars", js_flowvars);
351  }
352 
353  if (js_traffic_id != NULL || js_traffic_label != NULL) {
354  *js_traffic = json_object();
355  if (likely(*js_traffic != NULL)) {
356  if (js_traffic_id != NULL) {
357  json_object_set_new(*js_traffic, "id", js_traffic_id);
358  }
359  if (js_traffic_label != NULL) {
360  json_object_set_new(*js_traffic, "label", js_traffic_label);
361  }
362  }
363  }
364 }
365 
366 /**
367  * \brief Add top-level metadata to the eve json object.
368  */
369 static void JsonAddMetadata(const Packet *p, const Flow *f, json_t *js)
370 {
371  if ((p && p->pktvar) || (f && f->flowvar)) {
372  json_t *js_vars = json_object();
373  json_t *js_traffic = NULL;
374  if (js_vars) {
375  if (f && f->flowvar) {
376  JsonAddFlowVars(f, js_vars, &js_traffic);
377  if (js_traffic != NULL) {
378  json_object_set_new(js, "traffic", js_traffic);
379  }
380  }
381  if (p && p->pktvar) {
382  JsonAddPacketvars(p, js_vars);
383  }
384 
385  json_object_set_new(js, "metadata", js_vars);
386  }
387  }
388 }
389 
390 void JsonAddCommonOptions(const OutputJsonCommonSettings *cfg,
391  const Packet *p, const Flow *f, json_t *js)
392 {
393  if (cfg->include_metadata) {
394  JsonAddMetadata(p, f, js);
395  }
396  if (cfg->include_community_id && f != NULL) {
397  CreateJSONCommunityFlowId(js, f, cfg->community_id_seed);
398  }
399 }
400 
401 /**
402  * \brief Jsonify a packet
403  *
404  * \param p Packet
405  * \param js JSON object
406  * \param max_length If non-zero, restricts the number of packet data bytes handled.
407  */
408 void JsonPacket(const Packet *p, json_t *js, unsigned long max_length)
409 {
410  unsigned long max_len = max_length == 0 ? GET_PKT_LEN(p) : max_length;
411  unsigned long len = 2 * max_len;
412  uint8_t encoded_packet[len];
413  Base64Encode((unsigned char*) GET_PKT_DATA(p), max_len, encoded_packet, &len);
414  json_object_set_new(js, "packet", json_string((char *)encoded_packet));
415 
416  /* Create packet info. */
417  json_t *packetinfo_js = json_object();
418  if (unlikely(packetinfo_js == NULL)) {
419  return;
420  }
421  json_object_set_new(packetinfo_js, "linktype", json_integer(p->datalink));
422  json_object_set_new(js, "packet_info", packetinfo_js);
423 }
424 /** \brief jsonify tcp flags field
425  * Only add 'true' fields in an attempt to keep things reasonably compact.
426  */
427 void JsonTcpFlags(uint8_t flags, json_t *js)
428 {
429  if (flags & TH_SYN)
430  json_object_set_new(js, "syn", json_true());
431  if (flags & TH_FIN)
432  json_object_set_new(js, "fin", json_true());
433  if (flags & TH_RST)
434  json_object_set_new(js, "rst", json_true());
435  if (flags & TH_PUSH)
436  json_object_set_new(js, "psh", json_true());
437  if (flags & TH_ACK)
438  json_object_set_new(js, "ack", json_true());
439  if (flags & TH_URG)
440  json_object_set_new(js, "urg", json_true());
441  if (flags & TH_ECN)
442  json_object_set_new(js, "ecn", json_true());
443  if (flags & TH_CWR)
444  json_object_set_new(js, "cwr", json_true());
445 }
446 
447 /**
448  * \brief Add five tuple from packet to JSON object
449  *
450  * \param p Packet
451  * \param dir log direction (packet or flow)
452  * \param js JSON object
453  */
454 void JsonFiveTuple(const Packet *p, enum OutputJsonLogDirection dir, json_t *js)
455 {
456  char srcip[46] = {0}, dstip[46] = {0};
457  Port sp, dp;
458  char proto[16];
459 
460  switch (dir) {
461  case LOG_DIR_PACKET:
462  if (PKT_IS_IPV4(p)) {
463  PrintInet(AF_INET, (const void *)GET_IPV4_SRC_ADDR_PTR(p),
464  srcip, sizeof(srcip));
465  PrintInet(AF_INET, (const void *)GET_IPV4_DST_ADDR_PTR(p),
466  dstip, sizeof(dstip));
467  } else if (PKT_IS_IPV6(p)) {
468  PrintInet(AF_INET6, (const void *)GET_IPV6_SRC_ADDR(p),
469  srcip, sizeof(srcip));
470  PrintInet(AF_INET6, (const void *)GET_IPV6_DST_ADDR(p),
471  dstip, sizeof(dstip));
472  } else {
473  /* Not an IP packet so don't do anything */
474  return;
475  }
476  sp = p->sp;
477  dp = p->dp;
478  break;
479  case LOG_DIR_FLOW:
480  case LOG_DIR_FLOW_TOSERVER:
481  if ((PKT_IS_TOSERVER(p))) {
482  if (PKT_IS_IPV4(p)) {
483  PrintInet(AF_INET, (const void *)GET_IPV4_SRC_ADDR_PTR(p),
484  srcip, sizeof(srcip));
485  PrintInet(AF_INET, (const void *)GET_IPV4_DST_ADDR_PTR(p),
486  dstip, sizeof(dstip));
487  } else if (PKT_IS_IPV6(p)) {
488  PrintInet(AF_INET6, (const void *)GET_IPV6_SRC_ADDR(p),
489  srcip, sizeof(srcip));
490  PrintInet(AF_INET6, (const void *)GET_IPV6_DST_ADDR(p),
491  dstip, sizeof(dstip));
492  }
493  sp = p->sp;
494  dp = p->dp;
495  } else {
496  if (PKT_IS_IPV4(p)) {
497  PrintInet(AF_INET, (const void *)GET_IPV4_DST_ADDR_PTR(p),
498  srcip, sizeof(srcip));
499  PrintInet(AF_INET, (const void *)GET_IPV4_SRC_ADDR_PTR(p),
500  dstip, sizeof(dstip));
501  } else if (PKT_IS_IPV6(p)) {
502  PrintInet(AF_INET6, (const void *)GET_IPV6_DST_ADDR(p),
503  srcip, sizeof(srcip));
504  PrintInet(AF_INET6, (const void *)GET_IPV6_SRC_ADDR(p),
505  dstip, sizeof(dstip));
506  }
507  sp = p->dp;
508  dp = p->sp;
509  }
510  break;
511  case LOG_DIR_FLOW_TOCLIENT:
512  if ((PKT_IS_TOCLIENT(p))) {
513  if (PKT_IS_IPV4(p)) {
514  PrintInet(AF_INET, (const void *)GET_IPV4_SRC_ADDR_PTR(p),
515  srcip, sizeof(srcip));
516  PrintInet(AF_INET, (const void *)GET_IPV4_DST_ADDR_PTR(p),
517  dstip, sizeof(dstip));
518  } else if (PKT_IS_IPV6(p)) {
519  PrintInet(AF_INET6, (const void *)GET_IPV6_SRC_ADDR(p),
520  srcip, sizeof(srcip));
521  PrintInet(AF_INET6, (const void *)GET_IPV6_DST_ADDR(p),
522  dstip, sizeof(dstip));
523  }
524  sp = p->sp;
525  dp = p->dp;
526  } else {
527  if (PKT_IS_IPV4(p)) {
528  PrintInet(AF_INET, (const void *)GET_IPV4_DST_ADDR_PTR(p),
529  srcip, sizeof(srcip));
530  PrintInet(AF_INET, (const void *)GET_IPV4_SRC_ADDR_PTR(p),
531  dstip, sizeof(dstip));
532  } else if (PKT_IS_IPV6(p)) {
533  PrintInet(AF_INET6, (const void *)GET_IPV6_DST_ADDR(p),
534  srcip, sizeof(srcip));
535  PrintInet(AF_INET6, (const void *)GET_IPV6_SRC_ADDR(p),
536  dstip, sizeof(dstip));
537  }
538  sp = p->dp;
539  dp = p->sp;
540  }
541  break;
542  default:
544  return;
545  }
546 
547  if (SCProtoNameValid(IP_GET_IPPROTO(p)) == TRUE) {
548  strlcpy(proto, known_proto[IP_GET_IPPROTO(p)], sizeof(proto));
549  } else {
550  snprintf(proto, sizeof(proto), "%03" PRIu32, IP_GET_IPPROTO(p));
551  }
552 
553  json_object_set_new(js, "src_ip", json_string(srcip));
554 
555  switch(p->proto) {
556  case IPPROTO_ICMP:
557  break;
558  case IPPROTO_UDP:
559  case IPPROTO_TCP:
560  case IPPROTO_SCTP:
561  json_object_set_new(js, "src_port", json_integer(sp));
562  break;
563  }
564 
565  json_object_set_new(js, "dest_ip", json_string(dstip));
566 
567  switch(p->proto) {
568  case IPPROTO_ICMP:
569  break;
570  case IPPROTO_UDP:
571  case IPPROTO_TCP:
572  case IPPROTO_SCTP:
573  json_object_set_new(js, "dest_port", json_integer(dp));
574  break;
575  }
576 
577  json_object_set_new(js, "proto", json_string(proto));
578 }
579 
580 static void CreateJSONCommunityFlowIdv4(json_t *js, const Flow *f,
581  const uint16_t seed)
582 {
583  struct {
584  uint16_t seed;
585  uint32_t src;
586  uint32_t dst;
587  uint8_t proto;
588  uint8_t pad0;
589  uint16_t sp;
590  uint16_t dp;
591  } __attribute__((__packed__)) ipv4;
592 
593  uint32_t src = f->src.addr_data32[0];
594  uint32_t dst = f->dst.addr_data32[0];
595  uint16_t sp = f->sp;
596  if (f->proto == IPPROTO_ICMP)
597  sp = f->icmp_s.type;
598  sp = htons(sp);
599  uint16_t dp = f->dp;
600  if (f->proto == IPPROTO_ICMP)
601  dp = f->icmp_d.type;
602  dp = htons(dp);
603 
604  ipv4.seed = htons(seed);
605  if (ntohl(src) < ntohl(dst) || (src == dst && sp < dp)) {
606  ipv4.src = src;
607  ipv4.dst = dst;
608  ipv4.sp = sp;
609  ipv4.dp = dp;
610  } else {
611  ipv4.src = dst;
612  ipv4.dst = src;
613  ipv4.sp = dp;
614  ipv4.dp = sp;
615  }
616  ipv4.proto = f->proto;
617  ipv4.pad0 = 0;
618 
619  uint8_t hash[20];
620  if (ComputeSHA1((const uint8_t *)&ipv4, sizeof(ipv4), hash, sizeof(hash)) == 1) {
621  unsigned char base64buf[64] = "1:";
622  unsigned long out_len = sizeof(base64buf) - 2;
623  if (Base64Encode(hash, sizeof(hash), base64buf+2, &out_len) == SC_BASE64_OK) {
624  json_object_set_new(js, "community_id", json_string((const char *)base64buf));
625  }
626  }
627 }
628 
629 static inline bool FlowHashRawAddressIPv6LtU32(const uint32_t *a, const uint32_t *b)
630 {
631  for (int i = 0; i < 4; i++) {
632  if (a[i] < b[i])
633  return true;
634  if (a[i] > b[i])
635  break;
636  }
637 
638  return false;
639 }
640 
641 static void CreateJSONCommunityFlowIdv6(json_t *js, const Flow *f,
642  const uint16_t seed)
643 {
644  struct {
645  uint16_t seed;
646  uint32_t src[4];
647  uint32_t dst[4];
648  uint8_t proto;
649  uint8_t pad0;
650  uint16_t sp;
651  uint16_t dp;
652  } __attribute__((__packed__)) ipv6;
653 
654  uint16_t sp = f->sp;
655  if (f->proto == IPPROTO_ICMPV6)
656  sp = f->icmp_s.type;
657  sp = htons(sp);
658  uint16_t dp = f->dp;
659  if (f->proto == IPPROTO_ICMPV6)
660  dp = f->icmp_d.type;
661  dp = htons(dp);
662 
663  ipv6.seed = htons(seed);
664  if (FlowHashRawAddressIPv6LtU32(f->src.addr_data32, f->dst.addr_data32) ||
665  ((memcmp(&f->src, &f->dst, sizeof(f->src)) == 0) && sp < dp))
666  {
667  memcpy(&ipv6.src, &f->src.addr_data32, 16);
668  memcpy(&ipv6.dst, &f->dst.addr_data32, 16);
669  ipv6.sp = sp;
670  ipv6.dp = dp;
671  } else {
672  memcpy(&ipv6.src, &f->dst.addr_data32, 16);
673  memcpy(&ipv6.dst, &f->src.addr_data32, 16);
674  ipv6.sp = dp;
675  ipv6.dp = sp;
676  }
677  ipv6.proto = f->proto;
678  ipv6.pad0 = 0;
679 
680  uint8_t hash[20];
681  if (ComputeSHA1((const uint8_t *)&ipv6, sizeof(ipv6), hash, sizeof(hash)) == 1) {
682  unsigned char base64buf[64] = "1:";
683  unsigned long out_len = sizeof(base64buf) - 2;
684  if (Base64Encode(hash, sizeof(hash), base64buf+2, &out_len) == SC_BASE64_OK) {
685  json_object_set_new(js, "community_id", json_string((const char *)base64buf));
686  }
687  }
688 }
689 
690 static void CreateJSONCommunityFlowId(json_t *js, const Flow *f, const uint16_t seed)
691 {
692  if (f->flags & FLOW_IPV4)
693  return CreateJSONCommunityFlowIdv4(js, f, seed);
694  else if (f->flags & FLOW_IPV6)
695  return CreateJSONCommunityFlowIdv6(js, f, seed);
696 }
697 
698 void CreateJSONFlowId(json_t *js, const Flow *f)
699 {
700  if (f == NULL)
701  return;
702  int64_t flow_id = FlowGetId(f);
703  json_object_set_new(js, "flow_id", json_integer(flow_id));
704  if (f->parent_id) {
705  json_object_set_new(js, "parent_id", json_integer(f->parent_id));
706  }
707 }
708 
709 json_t *CreateJSONHeader(const Packet *p, enum OutputJsonLogDirection dir,
710  const char *event_type)
711 {
712  char timebuf[64];
713  const Flow *f = (const Flow *)p->flow;
714 
715  json_t *js = json_object();
716  if (unlikely(js == NULL))
717  return NULL;
718 
719  CreateIsoTimeString(&p->ts, timebuf, sizeof(timebuf));
720 
721  /* time & tx */
722  json_object_set_new(js, "timestamp", json_string(timebuf));
723 
724  CreateJSONFlowId(js, f);
725 
726  /* sensor id */
727  if (sensor_id >= 0)
728  json_object_set_new(js, "sensor_id", json_integer(sensor_id));
729 
730  /* input interface */
731  if (p->livedev) {
732  json_object_set_new(js, "in_iface", json_string(p->livedev->dev));
733  }
734 
735  /* pcap_cnt */
736  if (p->pcap_cnt != 0) {
737  json_object_set_new(js, "pcap_cnt", json_integer(p->pcap_cnt));
738  }
739 
740  if (event_type) {
741  json_object_set_new(js, "event_type", json_string(event_type));
742  }
743 
744  /* vlan */
745  if (p->vlan_idx > 0) {
746  json_t *js_vlan = json_array();
747  if (js_vlan) {
748  json_array_append_new(js_vlan, json_integer(p->vlan_id[0]));
749  if (p->vlan_idx > 1) {
750  json_array_append_new(js_vlan, json_integer(p->vlan_id[1]));
751  }
752  json_object_set_new(js, "vlan", js_vlan);
753  }
754  }
755 
756  /* 5-tuple */
757  JsonFiveTuple(p, dir, js);
758 
759  /* icmp */
760  switch (p->proto) {
761  case IPPROTO_ICMP:
762  if (p->icmpv4h) {
763  json_object_set_new(js, "icmp_type",
764  json_integer(p->icmpv4h->type));
765  json_object_set_new(js, "icmp_code",
766  json_integer(p->icmpv4h->code));
767  }
768  break;
769  case IPPROTO_ICMPV6:
770  if (p->icmpv6h) {
771  json_object_set_new(js, "icmp_type",
772  json_integer(p->icmpv6h->type));
773  json_object_set_new(js, "icmp_code",
774  json_integer(p->icmpv6h->code));
775  }
776  break;
777  }
778 
779  return js;
780 }
781 
782 json_t *CreateJSONHeaderWithTxId(const Packet *p, enum OutputJsonLogDirection dir,
783  const char *event_type, uint64_t tx_id)
784 {
785  json_t *js = CreateJSONHeader(p, dir, event_type);
786  if (unlikely(js == NULL))
787  return NULL;
788 
789  /* tx id for correlation with other events */
790  json_object_set_new(js, "tx_id", json_integer(tx_id));
791 
792  return js;
793 }
794 
795 int OutputJSONMemBufferCallback(const char *str, size_t size, void *data)
796 {
797  OutputJSONMemBufferWrapper *wrapper = data;
798  MemBuffer **memb = wrapper->buffer;
799 
800  if (MEMBUFFER_OFFSET(*memb) + size >= MEMBUFFER_SIZE(*memb)) {
801  MemBufferExpand(memb, wrapper->expand_by);
802  }
803 
804  MemBufferWriteRaw((*memb), str, size);
805  return 0;
806 }
807 
808 int OutputJSONBuffer(json_t *js, LogFileCtx *file_ctx, MemBuffer **buffer)
809 {
810  if (file_ctx->sensor_name) {
811  json_object_set_new(js, "host",
812  json_string(file_ctx->sensor_name));
813  }
814 
815  if (file_ctx->is_pcap_offline) {
816  json_object_set_new(js, "pcap_filename", json_string(PcapFileGetFilename()));
817  }
818 
819  if (file_ctx->prefix) {
820  MemBufferWriteRaw((*buffer), file_ctx->prefix, file_ctx->prefix_len);
821  }
822 
823  OutputJSONMemBufferWrapper wrapper = {
824  .buffer = buffer,
825  .expand_by = OUTPUT_BUFFER_SIZE
826  };
827 
828  int r = json_dump_callback(js, OutputJSONMemBufferCallback, &wrapper,
829  file_ctx->json_flags);
830  if (r != 0)
831  return TM_ECODE_OK;
832 
833  LogFileWrite(file_ctx, *buffer);
834  return 0;
835 }
836 
837 /**
838  * \brief Create a new LogFileCtx for "fast" output style.
839  * \param conf The configuration node for this output.
840  * \return A LogFileCtx pointer on success, NULL on failure.
841  */
842 OutputInitResult OutputJsonInitCtx(ConfNode *conf)
843 {
844  OutputInitResult result = { NULL, false };
845 
846  OutputJsonCtx *json_ctx = SCCalloc(1, sizeof(OutputJsonCtx));
847  if (unlikely(json_ctx == NULL)) {
848  SCLogDebug("could not create new OutputJsonCtx");
849  return result;
850  }
851 
852  /* First lookup a sensor-name value in this outputs configuration
853  * node (deprecated). If that fails, lookup the global one. */
854  const char *sensor_name = ConfNodeLookupChildValue(conf, "sensor-name");
855  if (sensor_name != NULL) {
857  "Found deprecated eve-log setting \"sensor-name\". "
858  "Please set sensor-name globally.");
859  }
860  else {
861  (void)ConfGet("sensor-name", &sensor_name);
862  }
863 
864  json_ctx->file_ctx = LogFileNewCtx();
865  if (unlikely(json_ctx->file_ctx == NULL)) {
866  SCLogDebug("AlertJsonInitCtx: Could not create new LogFileCtx");
867  SCFree(json_ctx);
868  return result;
869  }
870 
871  if (sensor_name) {
872  json_ctx->file_ctx->sensor_name = SCStrdup(sensor_name);
873  if (json_ctx->file_ctx->sensor_name == NULL) {
874  LogFileFreeCtx(json_ctx->file_ctx);
875  SCFree(json_ctx);
876  return result;
877  }
878  } else {
879  json_ctx->file_ctx->sensor_name = NULL;
880  }
881 
882  OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx));
883  if (unlikely(output_ctx == NULL)) {
884  LogFileFreeCtx(json_ctx->file_ctx);
885  SCFree(json_ctx);
886  return result;
887  }
888 
889  output_ctx->data = json_ctx;
890  output_ctx->DeInit = OutputJsonDeInitCtx;
891 
892  if (conf) {
893  const char *output_s = ConfNodeLookupChildValue(conf, "filetype");
894 
895  // Backwards compatibility
896  if (output_s == NULL) {
897  output_s = ConfNodeLookupChildValue(conf, "type");
898  }
899 
900  if (output_s != NULL) {
901  if (strcmp(output_s, "file") == 0 ||
902  strcmp(output_s, "regular") == 0) {
903  json_ctx->json_out = LOGFILE_TYPE_FILE;
904  } else if (strcmp(output_s, "syslog") == 0) {
905  json_ctx->json_out = LOGFILE_TYPE_SYSLOG;
906  } else if (strcmp(output_s, "unix_dgram") == 0) {
907  json_ctx->json_out = LOGFILE_TYPE_UNIX_DGRAM;
908  } else if (strcmp(output_s, "unix_stream") == 0) {
909  json_ctx->json_out = LOGFILE_TYPE_UNIX_STREAM;
910  } else if (strcmp(output_s, "redis") == 0) {
911 #ifdef HAVE_LIBHIREDIS
912  SCLogRedisInit();
913  json_ctx->json_out = LOGFILE_TYPE_REDIS;
914 #else
916  "redis JSON output option is not compiled");
917  exit(EXIT_FAILURE);
918 #endif
919  } else {
921  "Invalid JSON output option: %s", output_s);
922  exit(EXIT_FAILURE);
923  }
924  }
925 
926  const char *prefix = ConfNodeLookupChildValue(conf, "prefix");
927  if (prefix != NULL)
928  {
929  SCLogInfo("Using prefix '%s' for JSON messages", prefix);
930  json_ctx->file_ctx->prefix = SCStrdup(prefix);
931  if (json_ctx->file_ctx->prefix == NULL)
932  {
934  "Failed to allocate memory for eve-log.prefix setting.");
935  exit(EXIT_FAILURE);
936  }
937  json_ctx->file_ctx->prefix_len = strlen(prefix);
938  }
939 
940  if (json_ctx->json_out == LOGFILE_TYPE_FILE ||
941  json_ctx->json_out == LOGFILE_TYPE_UNIX_DGRAM ||
942  json_ctx->json_out == LOGFILE_TYPE_UNIX_STREAM)
943  {
944  if (SCConfLogOpenGeneric(conf, json_ctx->file_ctx, DEFAULT_LOG_FILENAME, 1) < 0) {
945  LogFileFreeCtx(json_ctx->file_ctx);
946  SCFree(json_ctx);
947  SCFree(output_ctx);
948  return result;
949  }
950  OutputRegisterFileRotationFlag(&json_ctx->file_ctx->rotation_flag);
951  }
952 #ifndef OS_WIN32
953  else if (json_ctx->json_out == LOGFILE_TYPE_SYSLOG) {
954  const char *facility_s = ConfNodeLookupChildValue(conf, "facility");
955  if (facility_s == NULL) {
957  }
958 
959  int facility = SCMapEnumNameToValue(facility_s, SCSyslogGetFacilityMap());
960  if (facility == -1) {
961  SCLogWarning(SC_ERR_INVALID_ARGUMENT, "Invalid syslog facility: \"%s\","
962  " now using \"%s\" as syslog facility", facility_s,
965  }
966 
967  const char *level_s = ConfNodeLookupChildValue(conf, "level");
968  if (level_s != NULL) {
969  int level = SCMapEnumNameToValue(level_s, SCSyslogGetLogLevelMap());
970  if (level != -1) {
971  json_ctx->file_ctx->syslog_setup.alert_syslog_level = level;
972  }
973  }
974 
975  const char *ident = ConfNodeLookupChildValue(conf, "identity");
976  /* if null we just pass that to openlog, which will then
977  * figure it out by itself. */
978 
979  openlog(ident, LOG_PID|LOG_NDELAY, facility);
980  }
981 #endif
982 #ifdef HAVE_LIBHIREDIS
983  else if (json_ctx->json_out == LOGFILE_TYPE_REDIS) {
984  ConfNode *redis_node = ConfNodeLookupChild(conf, "redis");
985  if (!json_ctx->file_ctx->sensor_name) {
986  char hostname[1024];
987  gethostname(hostname, 1023);
988  json_ctx->file_ctx->sensor_name = SCStrdup(hostname);
989  }
990  if (json_ctx->file_ctx->sensor_name == NULL) {
991  LogFileFreeCtx(json_ctx->file_ctx);
992  SCFree(json_ctx);
993  SCFree(output_ctx);
994  return result;
995  }
996 
997  if (SCConfLogOpenRedis(redis_node, json_ctx->file_ctx) < 0) {
998  LogFileFreeCtx(json_ctx->file_ctx);
999  SCFree(json_ctx);
1000  SCFree(output_ctx);
1001  return result;
1002  }
1003  }
1004 #endif
1005 
1006  const char *sensor_id_s = ConfNodeLookupChildValue(conf, "sensor-id");
1007  if (sensor_id_s != NULL) {
1008  if (ByteExtractStringUint64((uint64_t *)&sensor_id, 10, 0, sensor_id_s) == -1) {
1010  "Failed to initialize JSON output, "
1011  "invalid sensor-id: %s", sensor_id_s);
1012  exit(EXIT_FAILURE);
1013  }
1014  }
1015 
1016  /* Check if top-level metadata should be logged. */
1017  const ConfNode *metadata = ConfNodeLookupChild(conf, "metadata");
1018  if (metadata && metadata->val && ConfValIsFalse(metadata->val)) {
1019  SCLogConfig("Disabling eve metadata logging.");
1020  json_ctx->cfg.include_metadata = false;
1021  } else {
1022  json_ctx->cfg.include_metadata = true;
1023  }
1024 
1025  /* See if we want to enable the community id */
1026  const ConfNode *community_id = ConfNodeLookupChild(conf, "community-id");
1027  if (community_id && community_id->val && ConfValIsTrue(community_id->val)) {
1028  SCLogConfig("Enabling eve community_id logging.");
1029  json_ctx->cfg.include_community_id = true;
1030  } else {
1031  json_ctx->cfg.include_community_id = false;
1032  }
1033  const char *cid_seed = ConfNodeLookupChildValue(conf, "community-id-seed");
1034  if (cid_seed != NULL) {
1035  if (ByteExtractStringUint16(&json_ctx->cfg.community_id_seed,
1036  10, 0, cid_seed) == -1)
1037  {
1039  "Failed to initialize JSON output, "
1040  "invalid community-id-seed: %s", cid_seed);
1041  exit(EXIT_FAILURE);
1042  }
1043  }
1044 
1045  /* Do we have a global eve xff configuration? */
1046  const ConfNode *xff = ConfNodeLookupChild(conf, "xff");
1047  if (xff != NULL) {
1048  json_ctx->xff_cfg = SCCalloc(1, sizeof(HttpXFFCfg));
1049  if (likely(json_ctx->xff_cfg != NULL)) {
1050  HttpXFFGetCfg(conf, json_ctx->xff_cfg);
1051  }
1052  }
1053 
1054  const char *pcapfile_s = ConfNodeLookupChildValue(conf, "pcap-file");
1055  if (pcapfile_s != NULL && ConfValIsTrue(pcapfile_s)) {
1056  json_ctx->file_ctx->is_pcap_offline =
1058  }
1059 
1060  json_ctx->file_ctx->type = json_ctx->json_out;
1061  }
1062 
1063 
1064  SCLogDebug("returning output_ctx %p", output_ctx);
1065 
1066  result.ctx = output_ctx;
1067  result.ok = true;
1068  return result;
1069 }
1070 
1071 static void OutputJsonDeInitCtx(OutputCtx *output_ctx)
1072 {
1073  OutputJsonCtx *json_ctx = (OutputJsonCtx *)output_ctx->data;
1074  LogFileCtx *logfile_ctx = json_ctx->file_ctx;
1075  if (logfile_ctx->dropped) {
1077  "%"PRIu64" events were dropped due to slow or "
1078  "disconnected socket", logfile_ctx->dropped);
1079  }
1080  if (json_ctx->xff_cfg != NULL) {
1081  SCFree(json_ctx->xff_cfg);
1082  }
1083  LogFileFreeCtx(logfile_ctx);
1084  SCFree(json_ctx);
1085  SCFree(output_ctx);
1086 }
1087 
1088 #endif
void OutputJsonRegister(void)
Definition: output-json.c:77
struct Flow_::@116::@120 icmp_s
#define GET_IPV4_SRC_ADDR_PTR(p)
Definition: decode.h:212
char * known_proto[256]
uint16_t flags
uint8_t type
Definition: util-var.h:49
#define FLOWVAR_TYPE_STR
Definition: flow-var.h:33
uint8_t SCProtoNameValid(uint16_t proto)
Function to check if the received protocol number is valid and do we have corresponding name entry fo...
#define SCLogDebug(...)
Definition: util-debug.h:335
#define MemBufferWriteRaw(dst, raw_buffer, raw_buffer_len)
Write a raw buffer to the MemBuffer dst.
Definition: util-buffer.h:133
uint32_t idx
Definition: flow-var.h:52
#define FLOW_IPV6
Definition: flow.h:96
uint16_t value_len
Definition: flow-var.h:39
struct Flow_ * flow
Definition: decode.h:443
struct PktVar_ * next
Definition: decode.h:310
#define MEMBUFFER_SIZE(mem_buffer)
Get the MemBuffers current size.
Definition: util-buffer.h:60
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: util-strlcpyu.c:43
uint32_t event_type
uint8_t proto
Definition: flow.h:344
int ComputeSHA1(const uint8_t *inbuf, size_t inbuf_len, uint8_t *outbuf, size_t outbuf_size)
calculate SHA1 hash
Definition: util-crypt.c:230
#define PKT_IS_TOCLIENT(p)
Definition: decode.h:256
Port sp
Definition: flow.h:331
void HttpXFFGetCfg(ConfNode *conf, HttpXFFCfg *result)
Function to return XFF configuration from a configuration node.
#define unlikely(expr)
Definition: util-optimize.h:35
#define GET_IPV4_DST_ADDR_PTR(p)
Definition: decode.h:213
Port sp
Definition: decode.h:413
uint8_t * key
Definition: flow-var.h:60
Port dp
Definition: decode.h:421
ICMPV4Hdr * icmpv4h
Definition: decode.h:526
#define TH_RST
Definition: decode-tcp.h:37
uint8_t code
#define TH_FIN
Definition: decode-tcp.h:35
uint64_t offset
int LogFileWrite(LogFileCtx *file_ctx, MemBuffer *buffer)
#define PKT_IS_IPV6(p)
Definition: decode.h:250
SCEnumCharMap * SCSyslogGetFacilityMap(void)
returns the syslog facility enum map
Definition: util-syslog.c:57
uint16_t src
void(* DeInit)(struct OutputCtx_ *)
Definition: tm-modules.h:84
uint64_t pcap_cnt
Definition: decode.h:561
int SCMapEnumNameToValue(const char *enum_name, SCEnumCharMap *table)
Maps a string name to an enum value from the supplied table. Please specify the last element of any m...
Definition: util-enum.c:41
uint16_t key_len
Definition: decode.h:313
char * val
Definition: conf.h:34
ConfNode * ConfNodeLookupChild(const ConfNode *node, const char *name)
Lookup a child configuration node by name.
Definition: conf.c:815
#define TRUE
#define PKT_IS_IPV4(p)
Definition: decode.h:249
int ConfGet(const char *name, const char **vptr)
Retrieve the value of a configuration node.
Definition: conf.c:331
uint16_t vlan_id[2]
Definition: decode.h:433
FlowVarTypeStr fv_str
Definition: flow-var.h:57
FlowAddress dst
Definition: flow.h:329
char * dev
Definition: util-device.h:41
int ByteExtractStringUint16(uint16_t *res, int base, uint16_t len, const char *str)
Definition: util-byte.c:264
uint8_t datatype
Definition: flow-var.h:50
int ByteExtractStringUint64(uint64_t *res, int base, uint16_t len, const char *str)
Definition: util-byte.c:239
typedef __attribute__
DNP3 application header.
struct GenericVar_ * next
Definition: util-var.h:52
PktVar * pktvar
Definition: decode.h:488
#define str(s)
uint16_t dst
#define SCCalloc(nm, a)
Definition: util-mem.h:197
#define openlog(__ident, __option, __facility)
Definition: win32-syslog.h:76
const char * ConfNodeLookupChildValue(const ConfNode *node, const char *name)
Lookup the value of a child configuration node by name.
Definition: conf.c:843
void OutputRegisterFileRotationFlag(int *flag)
Register a flag for file rotation notification.
Definition: output.c:868
void CreateIsoTimeString(const struct timeval *ts, char *str, size_t size)
Definition: util-time.c:179
ICMPV6Hdr * icmpv6h
Definition: decode.h:528
uint16_t value_len
Definition: decode.h:314
int datalink
Definition: decode.h:574
uint8_t proto
Definition: decode.h:428
#define GET_IPV6_DST_ADDR(p)
Definition: decode.h:218
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:294
#define PrintBufferData(buf, buf_offset_ptr, buf_size,...)
Definition: util-print.h:29
uint32_t idx
Definition: flow-bit.h:33
uint32_t value
Definition: flow-var.h:44
#define TH_URG
Definition: decode-tcp.h:40
int OutputJsonOpenFileCtx(LogFileCtx *, char *)
#define TH_ACK
Definition: decode-tcp.h:39
#define MODULE_NAME
int ConfValIsFalse(const char *val)
Check if a value is false.
Definition: conf.c:591
LogFileCtx * LogFileNewCtx(void)
LogFileNewCtx() Get a new LogFileCtx.
uint8_t * buffer
Definition: util-buffer.h:28
#define PKT_IS_TOSERVER(p)
Definition: decode.h:255
#define TH_PUSH
Definition: decode-tcp.h:38
#define DEFAULT_ALERT_SYSLOG_FACILITY
Definition: alert-syslog.c:56
#define TH_ECN
Definition: decode-tcp.h:42
int SCConfLogOpenGeneric(ConfNode *conf, LogFileCtx *log_ctx, const char *default_filename, int rotate)
open a generic output "log file", which may be a regular file or a socket
const char * PrintInet(int af, const void *src, char *dst, socklen_t size)
Definition: util-print.c:267
char * sensor_name
void PrintStringsToBuffer(uint8_t *dst_buf, uint32_t *dst_buf_offset_ptr, uint32_t dst_buf_size, const uint8_t *src_buf, const uint32_t src_buf_len)
Definition: util-print.c:224
union FlowVar_::@112 data
uint8_t proto
uint16_t Port
Definition: decode.h:233
GenericVar * flowvar
Definition: flow.h:448
#define SCLogWarning(err_code,...)
Macro used to log WARNING messages.
Definition: util-debug.h:281
int ConfValIsTrue(const char *val)
Check if a value is true.
Definition: conf.c:566
FlowVarTypeInt fv_int
Definition: flow-var.h:58
uint8_t vlan_idx
Definition: decode.h:434
uint8_t * value
Definition: flow-var.h:38
uint32_t id
Definition: decode.h:309
Definition: conf.h:32
OutputCtx * ctx
Definition: output.h:42
#define DEFAULT_LOG_FILENAME
#define GET_IPV6_SRC_ADDR(p)
Definition: decode.h:217
int LogFileFreeCtx(LogFileCtx *lf_ctx)
LogFileFreeCtx() Destroy a LogFileCtx (Close the file and free memory)
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:254
#define TH_SYN
Definition: decode-tcp.h:36
#define SCFree(a)
Definition: util-mem.h:228
uint8_t * key
Definition: decode.h:315
Port dp
Definition: flow.h:338
uint8_t * value
Definition: decode.h:316
uint16_t tx_id
SCEnumCharMap * SCSyslogGetLogLevelMap(void)
returns the syslog facility enum map
Definition: util-syslog.c:75
uint8_t type
#define MEMBUFFER_OFFSET(mem_buffer)
Get the MemBuffers current offset.
Definition: util-buffer.h:55
const char * VarNameStoreLookupById(const uint32_t id, const enum VarTypes type)
const char * PcapFileGetFilename(void)
void * data
Definition: tm-modules.h:81
int64_t parent_id
Definition: flow.h:389
int RunmodeGetCurrent(void)
Definition: suricata.c:269
#define IP_GET_IPPROTO(p)
Definition: decode.h:261
struct Flow_::@118::@121 icmp_d
#define GET_PKT_DATA(p)
Definition: decode.h:223
int Base64Encode(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen)
Definition: util-crypt.c:272
#define DEFAULT_ALERT_SYSLOG_FACILITY_STR
Definition: alert-syslog.c:55
#define SCStrdup(a)
Definition: util-mem.h:212
FlowAddress src
Definition: flow.h:329
uint16_t keylen
Definition: flow-var.h:51
struct LiveDevice_ * livedev
Definition: decode.h:553
uint8_t len
struct timeval ts
Definition: decode.h:449
#define GET_PKT_LEN(p)
Definition: decode.h:222
#define FLOWVAR_TYPE_INT
Definition: flow-var.h:34
struct SCLogConfig_ SCLogConfig
Holds the config state used by the logging api.
#define likely(expr)
Definition: util-optimize.h:32
uint8_t pad0
#define TH_CWR
Definition: decode-tcp.h:44
#define OUTPUT_BUFFER_SIZE
Definition: log-httplog.c:58
int MemBufferExpand(MemBuffer **buffer, uint32_t expand_by)
expand membuffer by size of &#39;expand_by&#39;
Definition: util-buffer.c:60
Flow data structure.
Definition: flow.h:325
#define FLOW_IPV4
Definition: flow.h:94
uint32_t flags
Definition: flow.h:379
#define DEBUG_VALIDATE_BUG_ON(exp)
void OutputRegisterModule(const char *, const char *, OutputInitFunc)