suricata
alert-unified2-alert.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2014 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 Breno Silva <breno.silva@gmail.com>
22  * \author Eric Leblond <eric@regit.org>
23  * \author Ignacio Sanchez <sanchezmartin.ji@gmail.com>
24  * \author Duarte Silva <duarte.silva@serializing.me>
25  *
26  * Logs alerts in a format compatible to Snort's unified2 format, so it should
27  * be readable by Barnyard2.
28  */
29 
30 #include "suricata-common.h"
31 #include "runmodes.h"
32 #include "debug.h"
33 #include "detect.h"
34 #include "flow.h"
35 #include "conf.h"
36 #include "pkt-var.h"
37 #include "threads.h"
38 #include "threadvars.h"
39 #include "tm-threads.h"
40 
41 #include "output.h"
42 
43 #include "util-unittest.h"
44 #include "alert-unified2-alert.h"
45 #include "decode-ipv4.h"
46 
47 #include "host.h"
48 #include "util-profiling.h"
49 #include "decode.h"
50 
51 #include "util-error.h"
52 #include "util-debug.h"
53 #include "util-time.h"
54 #include "util-byte.h"
55 #include "util-misc.h"
56 #include "util-logopenfile.h"
57 
58 #include "app-layer-parser.h"
59 #include "app-layer-htp.h"
60 #include "app-layer.h"
61 #include "app-layer-htp-xff.h"
62 
63 #include "util-privs.h"
64 
65 #include "stream.h"
66 #include "stream-tcp-inline.h"
67 
68 #include "util-optimize.h"
69 
70 #ifndef IPPROTO_SCTP
71 #define IPPROTO_SCTP 132
72 #endif
73 
74 #define DEFAULT_LOG_FILENAME "unified2.alert"
75 
76 /**< Default log file limit in MB. */
77 #define DEFAULT_LIMIT 32 * 1024 * 1024
78 
79 /**< Minimum log file limit in MB. */
80 #define MIN_LIMIT 1 * 1024 * 1024
81 
82 /* Default Sensor ID value */
83 static uint32_t sensor_id = 0;
84 
85 /**
86  * Unified2 Extra Data Header
87  *
88  */
89 typedef struct Unified2ExtraDataHdr_ {
90  uint32_t event_type;
91  uint32_t event_length;
92 } __attribute__((__packed__)) Unified2ExtraDataHdr;
93 
94 /**
95  * Unified2 Extra Data (currently used only for XFF)
96  *
97  */
98 typedef struct Unified2ExtraData_ {
99  uint32_t sensor_id;
100  uint32_t event_id;
101  uint32_t event_second;
102  uint32_t type; /* EventInfo */
103  uint32_t data_type; /*EventDataType */
104  uint32_t blob_length; /* Length of the data + sizeof(blob_length) + sizeof(data_type)*/
106 
107 /**
108  * Unified2 file header struct
109  *
110  * Used for storing file header options.
111  */
112 typedef struct Unified2AlertFileHeader_ {
113  uint32_t type; /**< unified2 type header */
114  uint32_t length; /**< unified2 struct size length */
116 
117 /**
118  * Unified2 Ipv4 struct
119  *
120  * Used for storing ipv4 type values.
121  */
122 typedef struct AlertIPv4Unified2_ {
123  uint32_t sensor_id; /**< sendor id */
124  uint32_t event_id; /**< event id */
125  uint32_t event_second; /**< event second */
126  uint32_t event_microsecond; /**< event microsecond */
127  uint32_t signature_id; /**< signature id */
128  uint32_t generator_id; /**< generator id */
129  uint32_t signature_revision; /**< signature revision */
130  uint32_t classification_id; /**< classification id */
131  uint32_t priority_id; /**< priority id */
132  uint32_t src_ip; /**< source ip */
133  uint32_t dst_ip; /**< destination ip */
134  uint16_t sp; /**< source port */
135  uint16_t dp; /**< destination port */
136  uint8_t protocol; /**< protocol */
137  uint8_t packet_action; /**< packet action */
139 
140 /**
141  * Unified2 Ipv6 type struct
142  *
143  * Used for storing ipv6 type values.
144  */
145 typedef struct AlertIPv6Unified2_ {
146  uint32_t sensor_id; /**< sendor id */
147  uint32_t event_id; /**< event id */
148  uint32_t event_second; /**< event second */
149  uint32_t event_microsecond; /**< event microsecond */
150  uint32_t signature_id; /**< signature id */
151  uint32_t generator_id; /**< generator id */
152  uint32_t signature_revision; /**< signature revision */
153  uint32_t classification_id; /**< classification id */
154  uint32_t priority_id; /**< priority id */
155  struct in6_addr src_ip; /**< source ip */
156  struct in6_addr dst_ip; /**< destination ip */
157  uint16_t sp; /**< source port */
158  uint16_t dp; /**< destination port */
159  uint8_t protocol; /**< protocol */
160  uint8_t packet_action; /**< packet action */
162 
163 /**
164  * Unified2 packet type struct
165  *
166  * Used for storing packet type values.
167  */
168 typedef struct AlertUnified2Packet_ {
169  uint32_t sensor_id; /**< sensor id */
170  uint32_t event_id; /**< event id */
171  uint32_t event_second; /**< event second */
172  uint32_t packet_second; /**< packet second */
173  uint32_t packet_microsecond; /**< packet microsecond */
174  uint32_t linktype; /**< link type */
175  uint32_t packet_length; /**< packet length */
176  uint8_t packet_data[4]; /**< packet data */
178 
179 /** Extracted XFF IP is v4 */
180 #define UNIFIED2_ALERT_XFF_IPV4 8
181 /** Extracted XFF IP is v4 */
182 #define UNIFIED2_ALERT_XFF_IPV6 16
183 
184 typedef struct Unified2AlertFileCtx_ {
187  uint32_t flags; /**< flags for all alerts */
189 
190 #define UNIFIED2_ALERT_FLAGS_EMIT_PACKET (1 << 0)
191 
192 /**
193  * Unified2 thread vars
194  *
195  * Used for storing file options.
196  */
197 typedef struct Unified2AlertThread_ {
198  Unified2AlertFileCtx *unified2alert_ctx; /**< LogFileCtx pointer */
199  uint8_t *data; /**< Per function and thread data */
200  /** Pointer to the Unified2AlertFileHeader contained in
201  * the pointer data. */
203  /** Pointer to the Unified2Packet contained in
204  * the pointer data. */
206  /** Pointer to the IPv4 or IPv6 header contained in
207  * the pointer data. */
208  void *iphdr;
209  int datalen; /**< Length of per function and thread data */
210  int offset; /**< Offset used to now where to fill data */
211  int length; /**< Length of data for current alert */
212  uint8_t xff_flags; /**< XFF flags for the current alert */
213  uint32_t xff_ip[4]; /**< The XFF reported IP address for the current alert */
214  uint32_t event_id;
216 
217 #define UNIFIED2_PACKET_SIZE (sizeof(Unified2Packet) - 4)
218 
219 SC_ATOMIC_DECLARE(unsigned int, unified2_event_id); /**< Atomic counter, to link relative event */
220 
221 /** prototypes */
222 TmEcode Unified2AlertThreadInit(ThreadVars *, const void *, void **);
224 static int Unified2IPv4TypeAlert(ThreadVars *, const Packet *, void *);
225 static int Unified2IPv6TypeAlert(ThreadVars *, const Packet *, void *);
226 static int Unified2PacketTypeAlert(Unified2AlertThread *, const Packet *, uint32_t, int);
227 static int Unified2XFFTypeAlert(Unified2AlertThread *, const Packet *, uint32_t);
228 void Unified2RegisterTests(void);
229 static int Unified2AlertOpenFileCtx(LogFileCtx *, const char *, bool);
230 static void Unified2AlertDeInitCtx(OutputCtx *);
231 
232 int Unified2Condition(ThreadVars *tv, const Packet *p);
233 int Unified2Logger(ThreadVars *tv, void *data, const Packet *p);
234 
235 #define MODULE_NAME "Unified2Alert"
236 
238 {
243 }
244 
245 /**
246  * \brief Function to close unified2 file
247  *
248  * \param aun Unified2 thread variable.
249  */
250 static int Unified2AlertCloseFile(Unified2AlertThread *aun)
251 {
252  if (aun->unified2alert_ctx->file_ctx->fp != NULL) {
253  fclose(aun->unified2alert_ctx->file_ctx->fp);
254  }
256 
257  return 0;
258 }
259 
260 /**
261  * \brief Function to rotate unified2 file
262  *
263  * \param aun Unified2 thread variable.
264  * \retval 0 on succces
265  * \retval -1 on failure
266  */
267 static int Unified2AlertRotateFile(Unified2AlertThread *aun, bool truncate)
268 {
269  if (Unified2AlertCloseFile(aun) < 0) {
271  "Error: Unified2AlertCloseFile failed");
272  return -1;
273  }
274  if (Unified2AlertOpenFileCtx(aun->unified2alert_ctx->file_ctx,
275  aun->unified2alert_ctx->file_ctx->prefix, truncate) < 0) {
277  "Error: Unified2AlertOpenFileCtx, open new log file failed");
278  return -1;
279  }
280  return 0;
281 }
282 
283 /**
284  * \brief Wrapper for fwrite
285  *
286  * This function is basically a wrapper for fwrite which take
287  * in charge a size counter.
288  *
289  * \return 1 in case of success
290  */
291 static int Unified2Write(Unified2AlertThread *aun)
292 {
293  int ret;
294 
295  ret = fwrite(aun->data, aun->length, 1, aun->unified2alert_ctx->file_ctx->fp);
296  if (ret != 1) {
297  SCLogError(SC_ERR_FWRITE, "Error: fwrite failed: %s", strerror(errno));
298  return -1;
299  }
300 
302  return 1;
303 }
304 
305 int Unified2Condition(ThreadVars *tv, const Packet *p) {
306  if (likely(p->alerts.cnt == 0 && !(p->flags & PKT_HAS_TAG)))
307  return FALSE;
308  return TRUE;
309 }
310 
311 /**
312  * \brief Unified2 main entry function
313  *
314  * \retval TM_ECODE_OK all is good
315  * \retval TM_ECODE_FAILED serious error
316  */
317 int Unified2Logger(ThreadVars *t, void *data, const Packet *p)
318 {
319  int ret = 0;
321  aun->xff_flags = XFF_DISABLED;
322 
323  HttpXFFCfg *xff_cfg = aun->unified2alert_ctx->xff_cfg;
324 
325  /* overwrite mode can only work per u2 block, not per individual
326  * alert. So we'll look for an XFF record once */
327  if ((xff_cfg->flags & XFF_OVERWRITE) && p->flow != NULL) {
328  char buffer[XFF_MAXLEN];
329  int have_xff_ip = 0;
330 
331  if (FlowGetAppProtocol(p->flow) == ALPROTO_HTTP) {
332  have_xff_ip = HttpXFFGetIP(p->flow, xff_cfg, buffer, XFF_MAXLEN);
333  }
334 
335  if (have_xff_ip) {
336  /** Be sure that we have a nice zeroed buffer */
337  memset(aun->xff_ip, 0, 4 * sizeof(uint32_t));
338 
339  /** We can only have override mode if packet IP version matches
340  * the XFF IP version, otherwise fall-back to extra data */
341  if (inet_pton(AF_INET, buffer, aun->xff_ip) == 1) {
342  if (PKT_IS_IPV4(p)) {
344  } else {
346  }
347  } else if (inet_pton(AF_INET6, buffer, aun->xff_ip) == 1) {
348  if (PKT_IS_IPV6(p)) {
350  } else {
352  }
353  }
354  }
355  }
356 
357  if (PKT_IS_IPV4(p)) {
358  ret = Unified2IPv4TypeAlert (t, p, data);
359  } else if(PKT_IS_IPV6(p)) {
360  ret = Unified2IPv6TypeAlert (t, p, data);
361  } else {
362  /* we're only supporting IPv4 and IPv6 */
363  return TM_ECODE_OK;
364  }
365 
366  if (ret != 0) {
367  return TM_ECODE_FAILED;
368  }
369 
370  return TM_ECODE_OK;
371 }
372 
373 typedef struct _FakeIPv4Hdr {
375  TCPHdr tcph;
376 } FakeIPv4Hdr;
377 
378 static int Unified2ForgeFakeIPv4Header(FakeIPv4Hdr *fakehdr, const Packet *p, int pkt_len, char invert)
379 {
380  fakehdr->ip4h.ip_verhl = p->ip4h->ip_verhl;
381  fakehdr->ip4h.ip_proto = p->ip4h->ip_proto;
382  if (! invert) {
383  fakehdr->ip4h.s_ip_src.s_addr = p->ip4h->s_ip_src.s_addr;
384  fakehdr->ip4h.s_ip_dst.s_addr = p->ip4h->s_ip_dst.s_addr;
385  } else {
386  fakehdr->ip4h.s_ip_dst.s_addr = p->ip4h->s_ip_src.s_addr;
387  fakehdr->ip4h.s_ip_src.s_addr = p->ip4h->s_ip_dst.s_addr;
388  }
389  fakehdr->ip4h.ip_len = htons((uint16_t)pkt_len);
390 
391  if (! invert) {
392  fakehdr->tcph.th_sport = p->tcph->th_sport;
393  fakehdr->tcph.th_dport = p->tcph->th_dport;
394  } else {
395  fakehdr->tcph.th_dport = p->tcph->th_sport;
396  fakehdr->tcph.th_sport = p->tcph->th_dport;
397  }
398  fakehdr->tcph.th_offx2 = 0x50; /* just the TCP header, no options */
399 
400  return 1;
401 }
402 
403 typedef struct _FakeIPv6Hdr {
405  TCPHdr tcph;
406 } FakeIPv6Hdr;
407 
408 /**
409  * \param payload_len length of the payload
410  */
411 static int Unified2ForgeFakeIPv6Header(FakeIPv6Hdr *fakehdr, const Packet *p, int payload_len, char invert)
412 {
413  fakehdr->ip6h.s_ip6_vfc = p->ip6h->s_ip6_vfc;
414  fakehdr->ip6h.s_ip6_nxt = IPPROTO_TCP;
415  fakehdr->ip6h.s_ip6_plen = htons(sizeof(TCPHdr) + payload_len);
416  if (!invert) {
417  memcpy(fakehdr->ip6h.s_ip6_addrs, p->ip6h->s_ip6_addrs, 32);
418  } else {
419  memcpy(fakehdr->ip6h.s_ip6_src, p->ip6h->s_ip6_dst, 16);
420  memcpy(fakehdr->ip6h.s_ip6_dst, p->ip6h->s_ip6_src, 16);
421  }
422  if (! invert) {
423  fakehdr->tcph.th_sport = p->tcph->th_sport;
424  fakehdr->tcph.th_dport = p->tcph->th_dport;
425  } else {
426  fakehdr->tcph.th_dport = p->tcph->th_sport;
427  fakehdr->tcph.th_sport = p->tcph->th_dport;
428  }
429  fakehdr->tcph.th_offx2 = 0x50; /* just the TCP header, no options */
430 
431  return 1;
432 }
433 
434 /**
435  * \brief Write a faked Packet in unified2 file for each stream segment.
436  */
437 static int Unified2PrintStreamSegmentCallback(const Packet *p, void *data, const uint8_t *buf, uint32_t buflen)
438 {
439  int ret = 1;
442  Unified2Packet *phdr = (Unified2Packet *)(hdr + 1);
443 
444  aun->length = 0;
445  aun->offset = 0;
446 
447  int ethh_offset = 0;
448  EthernetHdr ethhdr = { {0,0,0,0,0,0}, {0,0,0,0,0,0}, htons(ETHERNET_TYPE_IPV6) };
449  uint32_t hdr_length = 0;
450 
451  memset(hdr, 0, sizeof(Unified2AlertFileHeader));
452  memset(phdr, 0, sizeof(Unified2Packet));
453 
454  hdr->type = htonl(UNIFIED2_PACKET_TYPE);
455  aun->hdr = hdr;
456 
457  phdr->sensor_id = htonl(sensor_id);
458  phdr->linktype = htonl(p->datalink);
459  phdr->event_id = aun->event_id;
460  phdr->event_second = phdr->packet_second = htonl(p->ts.tv_sec);
461  phdr->packet_microsecond = htonl(p->ts.tv_usec);
462  aun->phdr = phdr;
463 
464  if (p->datalink != DLT_EN10MB) {
465  /* We have raw data here */
466  phdr->linktype = htonl(DLT_RAW);
467  }
468 
471 
472  /* Include Packet header */
473  if (PKT_IS_IPV4(p)) {
474  FakeIPv4Hdr fakehdr;
475  hdr_length = sizeof(FakeIPv4Hdr);
476 
477  if (p->datalink == DLT_EN10MB) {
478  /* Fake this */
479  ethh_offset = 14;
480  phdr->linktype = htonl(DLT_EN10MB);
481  aun->length += ethh_offset;
482 
483  if (aun->length > aun->datalen) {
484  SCLogError(SC_ERR_INVALID_VALUE, "len is too big for thread data");
485  goto error;
486  }
487  ethhdr.eth_type = htons(ETHERNET_TYPE_IP);
488 
489  memcpy(aun->data + aun->offset, &ethhdr, 14);
490  aun->offset += ethh_offset;
491  }
492 
493  memset(&fakehdr, 0, hdr_length);
494  aun->length += hdr_length;
495  Unified2ForgeFakeIPv4Header(&fakehdr, p, hdr_length + buflen, 0);
496  if (aun->length > aun->datalen) {
497  SCLogError(SC_ERR_INVALID_VALUE, "len is too big for thread data");
498  goto error;
499  }
500  /** If XFF is in overwrite mode... */
501  if (aun->xff_flags & XFF_OVERWRITE) {
503 
504  if (p->flowflags & FLOW_PKT_TOCLIENT) {
505  fakehdr.ip4h.s_ip_dst.s_addr = aun->xff_ip[0];
506  } else {
507  fakehdr.ip4h.s_ip_src.s_addr = aun->xff_ip[0];
508  }
509  }
510 
511  memcpy(aun->data + aun->offset, &fakehdr, hdr_length);
512  aun->iphdr = (void *)(aun->data + aun->offset);
513  aun->offset += hdr_length;
514 
515  } else if (PKT_IS_IPV6(p)) {
516  FakeIPv6Hdr fakehdr;
517  hdr_length = sizeof(FakeIPv6Hdr);
518 
519  if (p->datalink == DLT_EN10MB) {
520  /* Fake this */
521  ethh_offset = 14;
522  phdr->linktype = htonl(DLT_EN10MB);
523  aun->length += ethh_offset;
524  if (aun->length > aun->datalen) {
525  SCLogError(SC_ERR_INVALID_VALUE, "len is too big for thread data");
526  goto error;
527  }
528  ethhdr.eth_type = htons(ETHERNET_TYPE_IPV6);
529 
530  memcpy(aun->data + aun->offset, &ethhdr, 14);
531  aun->offset += ethh_offset;
532  }
533 
534  memset(&fakehdr, 0, hdr_length);
535  Unified2ForgeFakeIPv6Header(&fakehdr, p, buflen, 1);
536 
537  aun->length += hdr_length;
538  if (aun->length > aun->datalen) {
539  SCLogError(SC_ERR_INVALID_VALUE, "len is too big for thread data");
540  goto error;
541  }
542  /** If XFF is in overwrite mode... */
543  if (aun->xff_flags & XFF_OVERWRITE) {
545 
546  if (p->flowflags & FLOW_PKT_TOCLIENT) {
547  memcpy(fakehdr.ip6h.s_ip6_dst, aun->xff_ip, 4 * sizeof(uint32_t));
548  } else {
549  memcpy(fakehdr.ip6h.s_ip6_src, aun->xff_ip, 4 * sizeof(uint32_t));
550  }
551  }
552 
553  memcpy(aun->data + aun->offset, &fakehdr, hdr_length);
554  aun->iphdr = (void *)(aun->data + aun->offset);
555  aun->offset += hdr_length;
556  } else {
557  goto error;
558  }
559 
560  /* update unified2 headers for length */
561  aun->hdr->length = htonl(UNIFIED2_PACKET_SIZE + ethh_offset +
562  hdr_length + buflen);
563  aun->phdr->packet_length = htonl(ethh_offset + hdr_length + buflen);
564 
565  /* copy stream segment payload in */
566  aun->length += buflen;
567 
568  if (aun->length > aun->datalen) {
569  SCLogError(SC_ERR_INVALID_VALUE, "len is too big for thread"
570  " data: %d vs %d", aun->length, aun->datalen);
571  goto error;
572  }
573 
574  memcpy(aun->data + aun->offset, buf, buflen);
575  aun->offset += buflen;
576 
577  /* rebuild checksum */
578  if (PKT_IS_IPV6(p)) {
579  FakeIPv6Hdr *fakehdr = (FakeIPv6Hdr *)aun->iphdr;
580 
581  fakehdr->tcph.th_sum = TCPV6Checksum(fakehdr->ip6h.s_ip6_addrs,
582  (uint16_t *)&fakehdr->tcph, buflen + sizeof(TCPHdr), 0);
583  } else {
584  FakeIPv4Hdr *fakehdr = (FakeIPv4Hdr *)aun->iphdr;
585 
586  fakehdr->tcph.th_sum = TCPChecksum(fakehdr->ip4h.s_ip_addrs,
587  (uint16_t *)&fakehdr->tcph, buflen + sizeof(TCPHdr), 0);
588  fakehdr->ip4h.ip_csum = IPV4Checksum((uint16_t *)&fakehdr->ip4h,
589  IPV4_GET_RAW_HLEN(&fakehdr->ip4h), 0);
590  }
591 
592  /* write out */
593  ret = Unified2Write(aun);
594  if (ret != 1) {
595  goto error;
596  }
597  return 1;
598 
599 error:
600  aun->length = 0;
601  aun->offset = 0;
602  return -1;
603 }
604 
605 
606 /**
607  * \brief Function to fill unified2 packet format into the file. If the alert
608  * was generated based on a stream chunk we call the stream function
609  * to generate the record.
610  *
611  * Barnyard2 doesn't like DLT_RAW + IPv6, so if we don't have an ethernet
612  * header, we create a fake one.
613  *
614  * No need to lock here, since it's already locked.
615  *
616  * \param aun thread local data
617  * \param p Packet
618  * \param stream pointer to stream chunk
619  * \param event_id unique event id
620  * \param stream state/stream match, try logging stream segments
621  *
622  * \retval 0 on succces
623  * \retval -1 on failure
624  */
625 static int Unified2PacketTypeAlert(Unified2AlertThread *aun, const Packet *p, uint32_t event_id, int stream)
626 {
627  int ret = 0;
628 
630  return 1;
631 
632  /* try stream logging first */
633  if (stream) {
634  SCLogDebug("logging the state");
635  uint8_t flag;
636 
637  if (p->flowflags & FLOW_PKT_TOSERVER) {
638  flag = FLOW_PKT_TOCLIENT;
639  } else {
640  flag = FLOW_PKT_TOSERVER;
641  }
642 
643  /* make event id available to callback */
644  aun->event_id = event_id;
645 
646  /* run callback for all segments in the stream */
647  ret = StreamSegmentForEach(p, flag, Unified2PrintStreamSegmentCallback, (void *)aun);
648  }
649 
650  /* or no segment could been logged or no segment have been logged */
651  if (ret == 0) {
652  SCLogDebug("no stream, no state: falling back to payload logging");
653 
655  Unified2Packet *phdr = (Unified2Packet *)(hdr + 1);
657  int datalink = p->datalink;
658 #ifdef HAVE_OLD_BARNYARD2
659  int ethh_offset = 0;
660  EthernetHdr ethhdr = { {0,0,0,0,0,0}, {0,0,0,0,0,0}, htons(ETHERNET_TYPE_IPV6) };
661 #endif
662  memset(hdr, 0, sizeof(Unified2AlertFileHeader));
663  memset(phdr, 0, sizeof(Unified2Packet));
664 
665  hdr->type = htonl(UNIFIED2_PACKET_TYPE);
666  aun->hdr = hdr;
667 
668  phdr->sensor_id = htonl(sensor_id);
669  phdr->linktype = htonl(datalink);
670  phdr->event_id = event_id;
671  phdr->event_second = phdr->packet_second = htonl(p->ts.tv_sec);
672  phdr->packet_microsecond = htonl(p->ts.tv_usec);
673  aun->phdr = phdr;
674 
675  /* we need to reset offset and length which could
676  * have been modified by the segment logging */
677  aun->offset = len;
678  len += GET_PKT_LEN(p);
679  aun->length = len;
680 
681  /* Unified 2 packet header is the one of the packet. */
682  phdr->linktype = htonl(p->datalink);
683 #ifdef HAVE_OLD_BARNYARD2
684  /* Fake datalink to avoid bug with old barnyard2 */
685  if (PKT_IS_IPV6(p) && (!p->ethh)) {
686  /* Fake this */
687  ethh_offset = 14;
688  datalink = DLT_EN10MB;
689  phdr->linktype = htonl(datalink);
690  aun->length += ethh_offset;
691  if (aun->length > aun->datalen) {
692  SCLogError(SC_ERR_INVALID_VALUE, "len is too big for thread data: %d vs %d",
693  len, aun->datalen - aun->offset);
694  return -1;
695  }
696  ethhdr.eth_type = htons(ETHERNET_TYPE_IPV6);
697 
698  memcpy(aun->data + aun->offset, &ethhdr, 14);
699  aun->offset += ethh_offset;
700  }
701 #endif
702 
703  if (len > aun->datalen) {
704  SCLogError(SC_ERR_INVALID_VALUE, "len is too big for thread data: %d vs %d",
705  len, aun->datalen - aun->offset);
706  return -1;
707  }
708  hdr->length = htonl(UNIFIED2_PACKET_SIZE + GET_PKT_LEN(p));
709  phdr->packet_length = htonl(GET_PKT_LEN(p));
710  memcpy(aun->data + aun->offset, GET_PKT_DATA(p), GET_PKT_LEN(p));
711 
712  ret = Unified2Write(aun);
713  }
714 
715  if (ret < 1) {
716  return -1;
717  }
718 
719  return 1;
720 }
721 
722 
723 /**
724  * \brief Function to fill unified2 xff extra data into the file.
725  *
726  * No need to lock here, since it's already locked.
727  * Will clear thread local data prior to writing, resetting length and offset
728  *
729  * \param aun thread local data
730  * \param p Packet
731  * \param event_id unique event id
732  *
733  * \retval 0 on succces
734  * \retval -1 on failure
735  */
736 static int Unified2XFFTypeAlert(Unified2AlertThread *aun, const Packet *p, uint32_t event_id)
737 {
738  /* Return immediately if XFF extra-data mode is not enabled */
739  if ( !(aun->xff_flags & XFF_EXTRADATA) ) {
740  return 0;
741  }
742 
743  /* Determine length info for various data fields*/
744  size_t addr_size;
745  unsigned int blob_length;
746  unsigned int dhdr_type;
747 
748  if ( aun->xff_flags & UNIFIED2_ALERT_XFF_IPV4 ) {
749  addr_size = sizeof(uint32_t);
750  blob_length = 3 * sizeof(uint32_t);
752  } else if ( aun->xff_flags & UNIFIED2_ALERT_XFF_IPV6 ) {
753  addr_size = 4*sizeof(uint32_t);
754  blob_length = 6 * sizeof(uint32_t);
756  } else {
757  return -1;
758  }
759 
760  int hdr_length = sizeof(Unified2ExtraDataHdr)
761  + sizeof(Unified2ExtraData)
762  + addr_size;
763  int total_len = sizeof(Unified2AlertFileHeader) + hdr_length;
764 
765  /* Clear aun's data and set new length */
766  memset( aun->data, 0, aun->datalen );
767  if ( total_len > aun->datalen ) {
768  SCLogError( SC_ERR_INVALID_VALUE, "len too big for thread data: %d, %d",
769  total_len, aun->datalen );
770  return -1;
771  }
772 
773  aun->length = total_len;
774  aun->offset = total_len;
775 
776  /* Prepare pointers to file header, extra data header, extra data record,
777  * and the extra data itself */
779  Unified2ExtraDataHdr *ehdr = (Unified2ExtraDataHdr *)(hdr + 1);
780  Unified2ExtraData *dhdr = (Unified2ExtraData *)(ehdr + 1);
781  uint32_t *xff = (uint32_t *) (dhdr + 1);
782 
783  /* Fill in all data structures and write */
784  hdr->type = htonl( UNIFIED2_IDS_EVENT_EXTRADATA_TYPE );
785  hdr->length = htonl( hdr_length );
786 
787  ehdr->event_type = htonl( UNIFIED2_EXTRADATA_TYPE_EXTRA_DATA );
788  ehdr->event_length = hdr->length;
789 
790  dhdr->sensor_id = 0;
791  dhdr->event_id = event_id;
792  dhdr->event_second = htonl( p->ts.tv_sec );
793  dhdr->data_type = htonl( UNIFIED2_EXTRADATA_TYPE_BLOB );
794  dhdr->type = htonl( dhdr_type );
795  dhdr->blob_length = htonl( blob_length );
796 
797  memcpy( xff, aun->xff_ip, addr_size );
798 
799  Unified2Write(aun);
800 
801  return 0;
802 }
803 
804 
805 /**
806  * \brief Function to fill unified2 ipv6 ids type format into the file.
807  *
808  * \param t Thread Variable containing input/output queue, cpu affinity etc.
809  * \param p Packet struct used to decide for ipv4 or ipv6
810  * \param data Unified2 thread data.
811  *
812  * \retval 0 on succces
813  * \retval -1 on failure
814  */
815 static int Unified2IPv6TypeAlert(ThreadVars *t, const Packet *p, void *data)
816 {
818  LogFileCtx *file_ctx = aun->unified2alert_ctx->file_ctx;
820  AlertIPv6Unified2 *phdr;
821  AlertIPv6Unified2 gphdr;
822  const PacketAlert *pa;
823  int offset, length;
824  int ret;
825  unsigned int event_id;
826 
827  if (likely(p->alerts.cnt == 0 && !(p->flags & PKT_HAS_TAG)))
828  return 0;
829 
830  phdr = (AlertIPv6Unified2 *)(aun->data +
831  sizeof(Unified2AlertFileHeader));
832 
833  length = (sizeof(Unified2AlertFileHeader) + sizeof(AlertIPv6Unified2));
834  offset = length;
835 
836  memset(aun->data, 0, aun->datalen);
837 
838  hdr.type = htonl(UNIFIED2_IDS_EVENT_IPV6_TYPE);
839  hdr.length = htonl(sizeof(AlertIPv6Unified2));
840 
841  /* fill the gphdr structure with the data of the packet */
842  memset(&gphdr, 0, sizeof(gphdr));
843  /* FIXME this need to be copied for each alert */
844  gphdr.sensor_id = htonl(sensor_id);
845  gphdr.event_second = htonl(p->ts.tv_sec);
846  gphdr.event_microsecond = htonl(p->ts.tv_usec);
847  gphdr.src_ip = GET_IPV6_SRC_IN6ADDR(p);
848  gphdr.dst_ip = GET_IPV6_SRC_IN6ADDR(p);
849  /** If XFF is in overwrite mode... */
850  if (aun->xff_flags & XFF_OVERWRITE) {
852 
853  struct in6_addr *a = (struct in6_addr*)aun->xff_ip;
854  if (p->flowflags & FLOW_PKT_TOCLIENT) {
855  gphdr.dst_ip = *a;
856  } else {
857  gphdr.src_ip = *a;
858  }
859  }
860  gphdr.protocol = p->proto;
861 
864  else
865  gphdr.packet_action = 0;
866 
867  switch(gphdr.protocol) {
868  case IPPROTO_ICMPV6:
869  if(p->icmpv6h) {
870  gphdr.sp = htons(p->icmpv6h->type);
871  gphdr.dp = htons(p->icmpv6h->code);
872  } else {
873  gphdr.sp = 0;
874  gphdr.dp = 0;
875  }
876  break;
877  case IPPROTO_ICMP:
878  if(p->icmpv4h) {
879  gphdr.sp = htons(p->icmpv4h->type);
880  gphdr.dp = htons(p->icmpv4h->code);
881  } else {
882  gphdr.sp = 0;
883  gphdr.dp = 0;
884  }
885  break;
886  case IPPROTO_UDP:
887  case IPPROTO_TCP:
888  case IPPROTO_SCTP:
889  gphdr.sp = htons(p->sp);
890  gphdr.dp = htons(p->dp);
891  break;
892  default:
893  gphdr.sp = 0;
894  gphdr.dp = 0;
895  break;
896  }
897 
898  uint16_t i = 0;
899  for (; i < p->alerts.cnt + 1; i++) {
900  if (i < p->alerts.cnt)
901  pa = &p->alerts.alerts[i];
902  else {
903  if (!(p->flags & PKT_HAS_TAG))
904  break;
905  pa = PacketAlertGetTag();
906  }
907 
908  if (unlikely(pa->s == NULL))
909  continue;
910 
911  HttpXFFCfg *xff_cfg = aun->unified2alert_ctx->xff_cfg;
912 
913  if ((xff_cfg->flags & XFF_EXTRADATA) && p->flow != NULL) {
914  char buffer[XFF_MAXLEN];
915  int have_xff_ip = 0;
916 
917  if (FlowGetAppProtocol(p->flow) == ALPROTO_HTTP) {
918  if (pa->flags & PACKET_ALERT_FLAG_TX) {
919  have_xff_ip = HttpXFFGetIPFromTx(p->flow, pa->tx_id, xff_cfg, buffer, XFF_MAXLEN);
920  } else {
921  have_xff_ip = HttpXFFGetIP(p->flow, xff_cfg, buffer, XFF_MAXLEN);
922  }
923  }
924 
925  if (have_xff_ip) {
926  memset(aun->xff_ip, 0, 4 * sizeof(uint32_t));
927 
928  if (inet_pton(AF_INET, buffer, aun->xff_ip) == 1) {
930  } else if (inet_pton(AF_INET6, buffer, aun->xff_ip) == 1) {
932  }
933  }
934  }
935 
936  /* reset length and offset */
937  aun->offset = offset;
938  aun->length = length;
939  memset(aun->data + aun->offset, 0, aun->datalen - aun->offset);
940 
941  /* copy the part common to all alerts */
942  memcpy(aun->data, &hdr, sizeof(hdr));
943  memcpy(phdr, &gphdr, sizeof(gphdr));
944 
945  /* fill the header structure with the data of the alert */
946  event_id = htonl(SC_ATOMIC_ADD(unified2_event_id, 1));
947  phdr->event_id = event_id;
948  phdr->generator_id = htonl(pa->s->gid);
949  phdr->signature_id = htonl(pa->s->id);
950  phdr->signature_revision = htonl(pa->s->rev);
951  phdr->classification_id = htonl(pa->s->class_id);
952  phdr->priority_id = htonl(pa->s->prio);
953 
954  SCMutexLock(&file_ctx->fp_mutex);
955 
956  bool truncate = (file_ctx->size_current + length) > file_ctx->size_limit
957  ? true : false;
958  if (truncate || file_ctx->rotation_flag) {
959  if (Unified2AlertRotateFile(aun, truncate) < 0) {
960  SCMutexUnlock(&file_ctx->fp_mutex);
961  return -1;
962  }
963  file_ctx->rotation_flag = 0;
964  }
965 
966  if (Unified2Write(aun) != 1) {
967  SCMutexUnlock(&file_ctx->fp_mutex);
968  return -1;
969  }
970 
971  memset(aun->data, 0, aun->length);
972  aun->length = 0;
973  aun->offset = 0;
974 
975  /* Write the extra data if any (it doesn't lock inside, since we
976  * already locked here for rotation check) */
977  ret = Unified2XFFTypeAlert(aun, p, phdr->event_id);
978  if (ret != 0) {
979  SCLogError(SC_ERR_FWRITE, "Error: fwrite failed: %s", strerror(errno));
980  SCMutexUnlock(&file_ctx->fp_mutex);
981  return -1;
982  }
983 
984  memset(aun->data, 0, aun->length);
985  aun->length = 0;
986  aun->offset = 0;
987 
988  /* stream flag based on state match, but only for TCP */
989  int stream = (gphdr.protocol == IPPROTO_TCP) ?
991  ret = Unified2PacketTypeAlert(aun, p, phdr->event_id, stream);
992  if (ret != 1) {
993  SCLogError(SC_ERR_FWRITE, "Error: fwrite failed: %s", strerror(errno));
994  SCMutexUnlock(&file_ctx->fp_mutex);
995  return -1;
996  }
997  fflush(aun->unified2alert_ctx->file_ctx->fp);
998  SCMutexUnlock(&file_ctx->fp_mutex);
999  }
1000 
1001  return 0;
1002 }
1003 
1004 /**
1005  * \brief Function to fill unified2 ipv4 ids type format into the file.
1006  *
1007  * \param t Thread Variable containing input/output queue, cpu affinity etc.
1008  * \param p Packet struct used to decide for ipv4 or ipv6
1009  * \param data Unified2 thread data.
1010  * \retval 0 on succces
1011  * \retval -1 on failure
1012  */
1013 
1014 static int Unified2IPv4TypeAlert (ThreadVars *tv, const Packet *p, void *data)
1015 {
1017  LogFileCtx *file_ctx = aun->unified2alert_ctx->file_ctx;
1019  AlertIPv4Unified2 *phdr;
1020  AlertIPv4Unified2 gphdr;
1021  const PacketAlert *pa;
1022  int offset, length;
1023  int ret;
1024  unsigned int event_id;
1025 
1026  if (likely(p->alerts.cnt == 0 && !(p->flags & PKT_HAS_TAG)))
1027  return 0;
1028 
1029  phdr = (AlertIPv4Unified2 *)(aun->data +
1030  sizeof(Unified2AlertFileHeader));
1031 
1032  length = (sizeof(Unified2AlertFileHeader) + sizeof(AlertIPv4Unified2));
1033  offset = length;
1034 
1035  memset(aun->data, 0, aun->datalen);
1036 
1037  hdr.type = htonl(UNIFIED2_IDS_EVENT_TYPE);
1038  hdr.length = htonl(sizeof(AlertIPv4Unified2));
1039 
1040  /* fill the gphdr structure with the data of the packet */
1041  memset(&gphdr, 0, sizeof(gphdr));
1042  gphdr.sensor_id = htonl(sensor_id);
1043  gphdr.event_id = 0;
1044  gphdr.event_second = htonl(p->ts.tv_sec);
1045  gphdr.event_microsecond = htonl(p->ts.tv_usec);
1046  gphdr.src_ip = p->ip4h->s_ip_src.s_addr;
1047  gphdr.dst_ip = p->ip4h->s_ip_dst.s_addr;
1048  /** If XFF is in overwrite mode... */
1049  if (aun->xff_flags & XFF_OVERWRITE) {
1051 
1052  if (p->flowflags & FLOW_PKT_TOCLIENT) {
1053  gphdr.dst_ip = aun->xff_ip[0];
1054  } else {
1055  gphdr.src_ip = aun->xff_ip[0];
1056  }
1057  }
1058  gphdr.protocol = IPV4_GET_RAW_IPPROTO(p->ip4h);
1059 
1062  else
1063  gphdr.packet_action = 0;
1064 
1065  /* TODO inverse order if needed, this should be done on a
1066  * alert basis */
1067  switch(gphdr.protocol) {
1068  case IPPROTO_ICMP:
1069  if(p->icmpv4h) {
1070  gphdr.sp = htons(p->icmpv4h->type);
1071  gphdr.dp = htons(p->icmpv4h->code);
1072  }
1073  break;
1074  case IPPROTO_UDP:
1075  case IPPROTO_TCP:
1076  case IPPROTO_SCTP:
1077  gphdr.sp = htons(p->sp);
1078  gphdr.dp = htons(p->dp);
1079  break;
1080  default:
1081  gphdr.sp = 0;
1082  gphdr.dp = 0;
1083  break;
1084  }
1085 
1086  uint16_t i = 0;
1087  for (; i < p->alerts.cnt + 1; i++) {
1088  if (i < p->alerts.cnt)
1089  pa = &p->alerts.alerts[i];
1090  else {
1091  if (!(p->flags & PKT_HAS_TAG))
1092  break;
1093  pa = PacketAlertGetTag();
1094  }
1095 
1096  if (unlikely(pa->s == NULL))
1097  continue;
1098 
1099  HttpXFFCfg *xff_cfg = aun->unified2alert_ctx->xff_cfg;
1100 
1101  if ((xff_cfg->flags & XFF_EXTRADATA) && p->flow != NULL) {
1102  char buffer[XFF_MAXLEN];
1103  int have_xff_ip = 0;
1104 
1105  if (FlowGetAppProtocol(p->flow) == ALPROTO_HTTP) {
1106  if (pa->flags & PACKET_ALERT_FLAG_TX) {
1107  have_xff_ip = HttpXFFGetIPFromTx(p->flow, pa->tx_id, xff_cfg, buffer, XFF_MAXLEN);
1108  } else {
1109  have_xff_ip = HttpXFFGetIP(p->flow, xff_cfg, buffer, XFF_MAXLEN);
1110  }
1111  }
1112 
1113  if (have_xff_ip) {
1114  memset(aun->xff_ip, 0, 4 * sizeof(uint32_t));
1115 
1116  if (inet_pton(AF_INET, buffer, aun->xff_ip) == 1) {
1118  } else if (inet_pton(AF_INET6, buffer, aun->xff_ip) == 1) {
1120  }
1121  }
1122  }
1123 
1124  /* reset length and offset */
1125  aun->offset = offset;
1126  aun->length = length;
1127  memset(aun->data + aun->offset, 0, aun->datalen - aun->offset);
1128 
1129  /* copy the part common to all alerts */
1130  memcpy(aun->data, &hdr, sizeof(hdr));
1131  memcpy(phdr, &gphdr, sizeof(gphdr));
1132 
1133  /* fill the hdr structure with the alert data */
1134  event_id = htonl(SC_ATOMIC_ADD(unified2_event_id, 1));
1135  phdr->event_id = event_id;
1136  phdr->generator_id = htonl(pa->s->gid);
1137  phdr->signature_id = htonl(pa->s->id);
1138  phdr->signature_revision = htonl(pa->s->rev);
1139  phdr->classification_id = htonl(pa->s->class_id);
1140  phdr->priority_id = htonl(pa->s->prio);
1141 
1142  /* check and enforce the filesize limit */
1143  SCMutexLock(&file_ctx->fp_mutex);
1144 
1145  bool truncate = (file_ctx->size_current + length) > file_ctx->size_limit
1146  ? true : false;
1147  if (truncate || file_ctx->rotation_flag) {
1148  if (Unified2AlertRotateFile(aun, truncate) < 0) {
1149  SCMutexUnlock(&file_ctx->fp_mutex);
1150  return -1;
1151  }
1152  file_ctx->rotation_flag = 0;
1153  }
1154 
1155  if (Unified2Write(aun) != 1) {
1156  SCMutexUnlock(&file_ctx->fp_mutex);
1157  return -1;
1158  }
1159 
1160  memset(aun->data, 0, aun->length);
1161  aun->length = 0;
1162  aun->offset = 0;
1163 
1164  /* Write the extra data if any (it doesn't lock inside, since we
1165  * already locked here for rotation check) */
1166  ret = Unified2XFFTypeAlert(aun, p, event_id);
1167  if (ret != 0) {
1168  SCMutexUnlock(&file_ctx->fp_mutex);
1169  return -1;
1170  }
1171 
1172  memset(aun->data, 0, aun->length);
1173  aun->length = 0;
1174  aun->offset = 0;
1175 
1176  /* Write the alert (it doesn't lock inside, since we
1177  * already locked here for rotation check)
1178  */
1179  int stream = (gphdr.protocol == IPPROTO_TCP) ?
1181  ret = Unified2PacketTypeAlert(aun, p, event_id, stream);
1182  if (ret != 1) {
1183  SCMutexUnlock(&file_ctx->fp_mutex);
1184  return -1;
1185  }
1186 
1187  fflush(aun->unified2alert_ctx->file_ctx->fp);
1188  SCMutexUnlock(&file_ctx->fp_mutex);
1189  }
1190 
1191  return 0;
1192 }
1193 
1194 /**
1195  * \brief Thread init function.
1196  *
1197  * \param t Thread Variable containing input/output queue, cpu affinity etc.
1198  * \param initdata Unified2 thread initial data.
1199  * \param data Unified2 thread data.
1200  * \retval TM_ECODE_OK on succces
1201  * \retval TM_ECODE_FAILED on failure
1202  */
1203 
1204 TmEcode Unified2AlertThreadInit(ThreadVars *t, const void *initdata, void **data)
1205 {
1207  if (unlikely(aun == NULL))
1208  return TM_ECODE_FAILED;
1209  memset(aun, 0, sizeof(Unified2AlertThread));
1210  if(initdata == NULL)
1211  {
1212  SCLogDebug("Error getting context for AlertUnified2. \"initdata\" argument NULL");
1213  SCFree(aun);
1214  return TM_ECODE_FAILED;
1215  }
1216  /** Use the Ouptut Context (file pointer and mutex) */
1217  aun->unified2alert_ctx = ((OutputCtx *)initdata)->data;
1218 
1219  aun->data = SCMalloc(sizeof(Unified2AlertFileHeader) + sizeof(Unified2Packet) +
1220  IPV4_MAXPACKET_LEN + sizeof(Unified2ExtraDataHdr) + sizeof (Unified2ExtraData));
1221  if (aun->data == NULL) {
1222  SCFree(aun);
1223  return TM_ECODE_FAILED;
1224  }
1225  aun->datalen = sizeof(Unified2AlertFileHeader) + sizeof(Unified2Packet) +
1226  IPV4_MAXPACKET_LEN + sizeof(Unified2ExtraDataHdr) + sizeof(Unified2ExtraData);
1227 
1228  *data = (void *)aun;
1229 
1230  return TM_ECODE_OK;
1231 }
1232 
1233 /**
1234  * \brief Thread deinit function.
1235  *
1236  * \param t Thread Variable containing input/output queue, cpu affinity etc.
1237  * \param data Unified2 thread data.
1238  * \retval TM_ECODE_OK on succces
1239  * \retval TM_ECODE_FAILED on failure
1240  */
1241 
1243 {
1245  if (aun == NULL) {
1246  goto error;
1247  }
1248 
1250  //SCLogInfo("Alert unified2 module wrote %"PRIu64" alerts",
1251  // aun->unified2alert_ctx->file_ctx->alerts);
1252 
1253  /* Do not print it for each thread */
1255 
1256  }
1257 
1258  if (aun->data != NULL) {
1259  SCFree(aun->data);
1260  aun->data = NULL;
1261  }
1262  aun->datalen = 0;
1263  /* clear memory */
1264  memset(aun, 0, sizeof(Unified2AlertThread));
1265  SCFree(aun);
1266  return TM_ECODE_OK;
1267 
1268 error:
1269  return TM_ECODE_FAILED;
1270 }
1271 
1272 /** \brief Create a new LogFileCtx from the provided ConfNode.
1273  * \param conf The configuration node for this output.
1274  * \return NULL if failure, LogFileCtx* to the file_ctx if succesful
1275  * */
1277 {
1278  OutputInitResult result = { NULL, false };
1279  int ret = 0;
1280  OutputCtx* output_ctx = NULL;
1281  HttpXFFCfg *xff_cfg = NULL;
1282  int nostamp = 0;
1283 
1285  "Unified2 alert has been deprecated and will be removed by "
1286  "December 2019.");
1287 
1288  LogFileCtx* file_ctx = LogFileNewCtx();
1289  if (file_ctx == NULL) {
1290  SCLogError(SC_ERR_UNIFIED2_ALERT_GENERIC, "Couldn't create new file_ctx");
1291  return result;
1292  }
1293 
1294  const char *filename = NULL;
1295  if (conf != NULL) { /* To faciliate unit tests. */
1296  filename = ConfNodeLookupChildValue(conf, "filename");
1297  }
1298  if (filename == NULL)
1299  filename = DEFAULT_LOG_FILENAME;
1300  file_ctx->prefix = SCStrdup(filename);
1301  if (unlikely(file_ctx->prefix == NULL)) {
1302  SCLogError(SC_ERR_MEM_ALLOC, "Failed to allocate file prefix");
1303  exit(EXIT_FAILURE);
1304  }
1305 
1306  const char *s_limit = NULL;
1307  file_ctx->size_limit = DEFAULT_LIMIT;
1308  if (conf != NULL) {
1309  s_limit = ConfNodeLookupChildValue(conf, "limit");
1310  if (s_limit != NULL) {
1311  if (ParseSizeStringU64(s_limit, &file_ctx->size_limit) < 0) {
1313  "Failed to initialize unified2 output, invalid limit: %s",
1314  s_limit);
1315  exit(EXIT_FAILURE);
1316  }
1317  if (file_ctx->size_limit < 4096) {
1318  SCLogInfo("unified2-alert \"limit\" value of %"PRIu64" assumed to be pre-1.2 "
1319  "style: setting limit to %"PRIu64"mb", file_ctx->size_limit, file_ctx->size_limit);
1320  uint64_t size = file_ctx->size_limit * 1024 * 1024;
1321  file_ctx->size_limit = size;
1322  } else if (file_ctx->size_limit < MIN_LIMIT) {
1324  "Failed to initialize unified2 output, limit less than "
1325  "allowed minimum: %d.", MIN_LIMIT);
1326  exit(EXIT_FAILURE);
1327  }
1328  }
1329  }
1330 
1331  if (conf != NULL) {
1332  const char *sensor_id_s = NULL;
1333  sensor_id_s = ConfNodeLookupChildValue(conf, "sensor-id");
1334  if (sensor_id_s != NULL) {
1335  if (ByteExtractStringUint32(&sensor_id, 10, 0, sensor_id_s) == -1) {
1336  SCLogError(SC_ERR_INVALID_ARGUMENT, "Failed to initialize unified2 output, invalid sensor-id: %s", sensor_id_s);
1337  exit(EXIT_FAILURE);
1338  }
1339  }
1340 
1341  if (ConfGetChildValueBool(conf, "nostamp", &nostamp)) {
1342  if (nostamp) {
1343  SCLogConfig("Disabling unified2 timestamp.");
1344  file_ctx->nostamp = true;
1345  }
1346  }
1347  }
1348 
1350  if (conf != NULL) {
1351  const char *payload = NULL;
1352  payload = ConfNodeLookupChildValue(conf, "payload");
1353  if (payload) {
1354  if (ConfValIsFalse(payload)) {
1356  } else if (!ConfValIsTrue(payload)) {
1357  SCLogError(SC_ERR_INVALID_ARGUMENT, "Failed to initialize unified2 output, invalid payload: %s", payload);
1358  exit(EXIT_FAILURE);
1359  }
1360  }
1361  }
1362 
1363  ret = Unified2AlertOpenFileCtx(file_ctx, filename, false);
1364  if (ret < 0)
1365  goto error;
1366 
1367  /* Only register for file rotation if theout is non-timestamped. */
1368  if (nostamp) {
1370  }
1371 
1372  output_ctx = SCCalloc(1, sizeof(OutputCtx));
1373  if (unlikely(output_ctx == NULL))
1374  goto error;
1375 
1376  xff_cfg = SCMalloc(sizeof(HttpXFFCfg));
1377  if (unlikely(xff_cfg == NULL)) {
1378  goto error;
1379  }
1380  memset(xff_cfg, 0x00, sizeof(HttpXFFCfg));
1381 
1382  if (conf != NULL) {
1383  HttpXFFGetCfg(conf, xff_cfg);
1384  }
1385 
1386  Unified2AlertFileCtx *unified2alert_ctx = SCMalloc(sizeof(Unified2AlertFileCtx));
1387  if (unlikely(unified2alert_ctx == NULL)) {
1388  goto error;
1389  }
1390  memset(unified2alert_ctx, 0x00, sizeof(Unified2AlertFileCtx));
1391 
1392  unified2alert_ctx->file_ctx = file_ctx;
1393  unified2alert_ctx->xff_cfg = xff_cfg;
1394  unified2alert_ctx->flags = flags;
1395  output_ctx->data = unified2alert_ctx;
1396  output_ctx->DeInit = Unified2AlertDeInitCtx;
1397 
1398  SCLogInfo("Unified2-alert initialized: filename %s, limit %"PRIu64" MB",
1399  filename, file_ctx->size_limit / (1024*1024));
1400 
1401  SC_ATOMIC_INIT(unified2_event_id);
1402 
1403  result.ctx = output_ctx;
1404  result.ok = true;
1405  return result;
1406 
1407 error:
1408  LogFileFreeCtx(file_ctx);
1409 
1410  if (xff_cfg != NULL) {
1411  SCFree(xff_cfg);
1412  }
1413  if (output_ctx != NULL) {
1414  SCFree(output_ctx);
1415  }
1416 
1417  return result;
1418 }
1419 
1420 static void Unified2AlertDeInitCtx(OutputCtx *output_ctx)
1421 {
1422  if (output_ctx != NULL) {
1423  Unified2AlertFileCtx *unified2alert_ctx = (Unified2AlertFileCtx *) output_ctx->data;
1424  if (unified2alert_ctx != NULL) {
1425  LogFileCtx *logfile_ctx = unified2alert_ctx->file_ctx;
1426  if (logfile_ctx != NULL) {
1427  LogFileFreeCtx(logfile_ctx);
1428  }
1429  HttpXFFCfg *xff_cfg = unified2alert_ctx->xff_cfg;
1430  if (xff_cfg != NULL) {
1431  SCFree(xff_cfg);
1432  }
1433  SCFree(unified2alert_ctx);
1434  }
1435  SCFree(output_ctx);
1436  }
1437 }
1438 
1439 /** \brief Read the config set the file pointer, open the file
1440  * \param file_ctx pointer to a created LogFileCtx using LogFileNewCtx()
1441  * \param prefix Prefix of the log file.
1442  * \return -1 if failure, 0 if succesful
1443  * */
1444 static int Unified2AlertOpenFileCtx(LogFileCtx *file_ctx, const char *prefix,
1445  bool truncate)
1446 {
1447  int ret = 0;
1448  char *filename = NULL;
1449  if (file_ctx->filename != NULL)
1450  filename = file_ctx->filename;
1451  else {
1452  filename = SCMalloc(PATH_MAX); /* XXX some sane default? */
1453  if (unlikely(filename == NULL))
1454  return -1;
1455  file_ctx->filename = filename;
1456 
1457  memset(filename, 0x00, PATH_MAX);
1458  }
1459 
1460  /** get the time so we can have a filename with seconds since epoch */
1461  struct timeval ts;
1462  memset(&ts, 0x00, sizeof(struct timeval));
1463 
1464  extern int run_mode;
1465  if (run_mode == RUNMODE_UNITTEST)
1466  TimeGet(&ts);
1467  else
1468  gettimeofday(&ts, NULL);
1469 
1470  /* create the filename to use */
1471  const char *log_dir;
1472  log_dir = ConfigGetLogDirectory();
1473 
1474  if (file_ctx->nostamp) {
1475  snprintf(filename, PATH_MAX, "%s/%s", log_dir, prefix);
1476  } else {
1477  snprintf(filename, PATH_MAX, "%s/%s.%" PRIu32, log_dir, prefix, (uint32_t)ts.tv_sec);
1478  }
1479 
1480  if (truncate) {
1481  file_ctx->fp = fopen(filename, "wb");
1482  } else {
1483  file_ctx->fp = fopen(filename, "ab");
1484  }
1485  if (file_ctx->fp == NULL) {
1486  SCLogError(SC_ERR_FOPEN, "failed to open %s: %s", filename,
1487  strerror(errno));
1488  ret = -1;
1489  }
1490 
1491  return ret;
1492 }
1493 
1494 
1495 #ifdef UNITTESTS
1496 
1497 /**
1498  * \test Test the ethernet+ipv4+tcp unified2 test
1499  *
1500  * \retval 1 on succces
1501  * \retval 0 on failure
1502  */
1503 
1504 static int Unified2Test01(void)
1505 {
1506  ThreadVars tv;
1507  DecodeThreadVars dtv;
1508  PacketQueue pq;
1509  void *data = NULL;
1510  OutputInitResult oc;
1511  LogFileCtx *lf;
1512  Unified2AlertFileCtx *uaf = NULL;
1513  Signature s;
1514 
1515  uint8_t raw_ipv4_tcp[] = {
1516  0x00, 0x14, 0xbf, 0xe8, 0xcb, 0x26, 0xaa, 0x00,
1517  0x04, 0x00, 0x0a, 0x04, 0x08, 0x00, 0x45, 0x00,
1518  0x00, 0x3c, 0x8c, 0x55, 0x40, 0x00, 0x40, 0x06,
1519  0x69, 0x86, 0xc0, 0xa8, 0x0a, 0x68, 0x4a, 0x7d,
1520  0x2f, 0x53, 0xc2, 0x40, 0x00, 0x50, 0x1f, 0x00,
1521  0xa4, 0xd4, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x02,
1522  0x16, 0xd0, 0x3d, 0x4e, 0x00, 0x00, 0x02, 0x04,
1523  0x05, 0xb4, 0x04, 0x02, 0x08, 0x0a, 0x00, 0x1c,
1524  0x28, 0x81, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03,
1525  0x03, 0x06};
1526  Packet *p = PacketGetFromAlloc();
1527  if (unlikely(p == NULL))
1528  return 0;
1529  int ret;
1530 
1531  memset(&dtv, 0, sizeof(DecodeThreadVars));
1532  memset(&tv, 0, sizeof(ThreadVars));
1533  memset(&pq, 0, sizeof(PacketQueue));
1534  memset(&s, 0, sizeof(Signature));
1535 
1536  p->alerts.cnt++;
1537  s.id = 1;
1538  s.gid = 1;
1539  s.rev = 1;
1540  p->alerts.alerts[p->alerts.cnt-1].s = &s;
1541  SET_PKT_LEN(p, sizeof(raw_ipv4_tcp));
1542 
1544 
1545  DecodeEthernet(&tv, &dtv, p, raw_ipv4_tcp, sizeof(raw_ipv4_tcp), &pq);
1546 
1547 
1548  oc = Unified2AlertInitCtx(NULL);
1549  if (oc.ctx == NULL) {
1550  goto end;
1551  }
1552  uaf = oc.ctx->data;
1553  if (uaf == NULL)
1554  return 0;
1555  lf = uaf->file_ctx;
1556  if(lf == NULL) {
1557  goto end;
1558  }
1559  ret = Unified2AlertThreadInit(&tv, oc.ctx, &data);
1560  if(ret == TM_ECODE_FAILED) {
1561  goto end;
1562  }
1563  ret = Unified2Logger(&tv, data, p);
1564  if(ret == TM_ECODE_FAILED) {
1565  goto end;
1566  }
1567  ret = Unified2AlertThreadDeinit(&tv, data);
1568  if(ret == -1) {
1569  goto end;
1570  }
1571 
1572  Unified2AlertDeInitCtx(oc.ctx);
1573 
1574  PACKET_RECYCLE(p);
1575  SCFree(p);
1576  FlowShutdown();
1577  return 1;
1578 
1579 end:
1580  PACKET_RECYCLE(p);
1581  SCFree(p);
1582  FlowShutdown();
1583  return 0;
1584 }
1585 
1586 /**
1587  * \test Test the ethernet+ipv6+tcp unified2 test
1588  *
1589  * \retval 1 on succces
1590  * \retval 0 on failure
1591  */
1592 
1593 static int Unified2Test02(void)
1594 {
1595  ThreadVars tv;
1596  DecodeThreadVars dtv;
1597  PacketQueue pq;
1598  void *data = NULL;
1599  OutputInitResult oc;
1600  LogFileCtx *lf;
1601  Unified2AlertFileCtx *uaf = NULL;
1602  Signature s;
1603 
1604  uint8_t raw_ipv6_tcp[] = {
1605  0x00, 0x11, 0x25, 0x82, 0x95, 0xb5, 0x00, 0xd0,
1606  0x09, 0xe3, 0xe8, 0xde, 0x86, 0xdd, 0x60, 0x00,
1607  0x00, 0x00, 0x00, 0x28, 0x06, 0x40, 0x20, 0x01,
1608  0x06, 0xf8, 0x10, 0x2d, 0x00, 0x00, 0x02, 0xd0,
1609  0x09, 0xff, 0xfe, 0xe3, 0xe8, 0xde, 0x20, 0x01,
1610  0x06, 0xf8, 0x09, 0x00, 0x07, 0xc0, 0x00, 0x00,
1611  0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xe7, 0x41,
1612  0x00, 0x50, 0xab, 0xdc, 0xd6, 0x60, 0x00, 0x00,
1613  0x00, 0x00, 0xa0, 0x02, 0x16, 0x80, 0x41, 0xa2,
1614  0x00, 0x00, 0x02, 0x04, 0x05, 0xa0, 0x04, 0x02,
1615  0x08, 0x0a, 0x00, 0x0a, 0x22, 0xa8, 0x00, 0x00,
1616  0x00, 0x00, 0x01, 0x03, 0x03, 0x05 };
1617  Packet *p = PacketGetFromAlloc();
1618  if (unlikely(p == NULL))
1619  return 0;
1620  int ret;
1621 
1622  memset(&dtv, 0, sizeof(DecodeThreadVars));
1623  memset(&tv, 0, sizeof(ThreadVars));
1624  memset(&pq, 0, sizeof(PacketQueue));
1625  memset(&s, 0, sizeof(Signature));
1626 
1627  p->alerts.cnt++;
1628  s.id = 1;
1629  s.gid = 1;
1630  s.rev = 1;
1631  p->alerts.alerts[p->alerts.cnt-1].s = &s;
1632  SET_PKT_LEN(p, sizeof(raw_ipv6_tcp));
1633 
1635 
1636  DecodeEthernet(&tv, &dtv, p, raw_ipv6_tcp, sizeof(raw_ipv6_tcp), &pq);
1637 
1638  oc = Unified2AlertInitCtx(NULL);
1639  if (oc.ctx == NULL) {
1640  goto end;
1641  }
1642  uaf = oc.ctx->data;
1643  if (uaf == NULL)
1644  return 0;
1645  lf = uaf->file_ctx;
1646  if(lf == NULL) {
1647  goto end;
1648  }
1649  ret = Unified2AlertThreadInit(&tv, oc.ctx, &data);
1650  if(ret == -1) {
1651  goto end;
1652  }
1653  ret = Unified2Logger(&tv, data, p);
1654  if(ret == TM_ECODE_FAILED) {
1655  goto end;
1656  }
1657  ret = Unified2AlertThreadDeinit(&tv, data);
1658  if(ret == -1) {
1659  goto end;
1660  }
1661 
1662  Unified2AlertDeInitCtx(oc.ctx);
1663 
1664  PACKET_RECYCLE(p);
1665  SCFree(p);
1666  FlowShutdown();
1667  return 1;
1668 
1669 end:
1670  PACKET_RECYCLE(p);
1671  SCFree(p);
1672  FlowShutdown();
1673  return 0;
1674 }
1675 
1676 
1677 /**
1678  * \test Test the GRE unified2 test
1679  *
1680  * \retval 1 on succces
1681  * \retval 0 on failure
1682  */
1683 
1684 static int Unified2Test03(void)
1685 {
1686  ThreadVars tv;
1687  DecodeThreadVars dtv;
1688  PacketQueue pq;
1689  void *data = NULL;
1690  OutputInitResult oc;
1691  LogFileCtx *lf;
1692  Unified2AlertFileCtx *uaf = NULL;
1693  Signature s;
1694 
1695  uint8_t raw_gre[] = {
1696  0x00, 0x0e, 0x50, 0x06, 0x42, 0x96, 0xaa, 0x00,
1697  0x04, 0x00, 0x0a, 0x04, 0x08, 0x00, 0x45, 0x00,
1698  0x00, 0x74, 0x35, 0xa2, 0x40, 0x00, 0x40, 0x2f,
1699  0xef, 0xcb, 0x0a, 0x00, 0x00, 0x64, 0x0a, 0x00,
1700  0x00, 0x8a, 0x30, 0x01, 0x88, 0x0b, 0x00, 0x54,
1701  0x00, 0x00, 0x00, 0x18, 0x29, 0x5f, 0xff, 0x03,
1702  0x00, 0x21, 0x45, 0x00, 0x00, 0x50, 0xf4, 0x05,
1703  0x40, 0x00, 0x3f, 0x06, 0x20, 0xb8, 0x50, 0x7e,
1704  0x2b, 0x2d, 0xd4, 0xcc, 0xd6, 0x72, 0x0a, 0x92,
1705  0x1a, 0x0b, 0xc9, 0xaf, 0x24, 0x02, 0x8c, 0xdd,
1706  0x45, 0xf6, 0x80, 0x18, 0x21, 0xfc, 0x10, 0x7c,
1707  0x00, 0x00, 0x01, 0x01, 0x08, 0x0a, 0x08, 0x19,
1708  0x1a, 0xda, 0x84, 0xd6, 0xda, 0x3e, 0x50, 0x49,
1709  0x4e, 0x47, 0x20, 0x73, 0x74, 0x65, 0x72, 0x6c,
1710  0x69, 0x6e, 0x67, 0x2e, 0x66, 0x72, 0x65, 0x65,
1711  0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, 0x65, 0x74,
1712  0x0d, 0x0a};
1713  Packet *p = PacketGetFromAlloc();
1714  Packet *pkt;
1715  if (unlikely(p == NULL))
1716  return 0;
1717  int ret;
1718 
1719  memset(&dtv, 0, sizeof(DecodeThreadVars));
1720  memset(&tv, 0, sizeof(ThreadVars));
1721  memset(&pq, 0, sizeof(PacketQueue));
1722  memset(&s, 0, sizeof(Signature));
1723 
1724  p->alerts.cnt++;
1725  s.id = 1;
1726  s.gid = 1;
1727  s.rev = 1;
1728  p->alerts.alerts[p->alerts.cnt-1].s = &s;
1729  SET_PKT_LEN(p, sizeof(raw_gre));
1730 
1732 
1733  DecodeEthernet(&tv, &dtv, p, raw_gre, sizeof(raw_gre), &pq);
1734 
1735  oc = Unified2AlertInitCtx(NULL);
1736  if (oc.ctx == NULL) {
1737  goto end;
1738  }
1739  uaf = oc.ctx->data;
1740  if (uaf == NULL)
1741  return 0;
1742  lf = uaf->file_ctx;
1743  if(lf == NULL) {
1744  goto end;
1745  }
1746  ret = Unified2AlertThreadInit(&tv, oc.ctx, &data);
1747  if(ret == -1) {
1748  goto end;
1749  }
1750  ret = Unified2Logger(&tv, data, p);
1751  if(ret == TM_ECODE_FAILED) {
1752  goto end;
1753  }
1754  ret = Unified2AlertThreadDeinit(&tv, data);
1755  if(ret == -1) {
1756  goto end;
1757  }
1758 
1759  Unified2AlertDeInitCtx(oc.ctx);
1760 
1761  pkt = PacketDequeue(&pq);
1762  while (pkt != NULL) {
1763  PACKET_RECYCLE(pkt);
1764  SCFree(pkt);
1765  pkt = PacketDequeue(&pq);
1766  }
1767 
1768  PACKET_RECYCLE(p);
1769  SCFree(p);
1770  FlowShutdown();
1771  return 1;
1772 
1773 end:
1774  pkt = PacketDequeue(&pq);
1775  while (pkt != NULL) {
1776  PACKET_RECYCLE(pkt);
1777  SCFree(pkt);
1778  pkt = PacketDequeue(&pq);
1779  }
1780  PACKET_RECYCLE(p);
1781  SCFree(p);
1782  FlowShutdown();
1783  return 0;
1784 }
1785 
1786 /**
1787  * \test Test the PPP unified2 test
1788  *
1789  * \retval 1 on succces
1790  * \retval 0 on failure
1791  */
1792 
1793 static int Unified2Test04(void)
1794 {
1795  ThreadVars tv;
1796  DecodeThreadVars dtv;
1797  PacketQueue pq;
1798  void *data = NULL;
1799  OutputInitResult oc;
1800  LogFileCtx *lf;
1801  Unified2AlertFileCtx *uaf = NULL;
1802  Signature s;
1803 
1804  uint8_t raw_ppp[] = {
1805  0xff, 0x03, 0x00, 0x21, 0x45, 0xc0, 0x00, 0x2c,
1806  0x4d, 0xed, 0x00, 0x00, 0xff, 0x06, 0xd5, 0x17,
1807  0xbf, 0x01, 0x0d, 0x01, 0xbf, 0x01, 0x0d, 0x03,
1808  0xea, 0x37, 0x00, 0x17, 0x6d, 0x0b, 0xba, 0xc3,
1809  0x00, 0x00, 0x00, 0x00, 0x60, 0x02, 0x10, 0x20,
1810  0xdd, 0xe1, 0x00, 0x00, 0x02, 0x04, 0x05, 0xb4};
1811  Packet *p = PacketGetFromAlloc();
1812  if (unlikely(p == NULL))
1813  return 0;
1814  int ret;
1815 
1816  memset(&dtv, 0, sizeof(DecodeThreadVars));
1817  memset(&tv, 0, sizeof(ThreadVars));
1818  memset(&pq, 0, sizeof(PacketQueue));
1819  memset(&s, 0, sizeof(Signature));
1820 
1821  p->alerts.cnt++;
1822  s.id = 1;
1823  s.gid = 1;
1824  s.rev = 1;
1825  p->alerts.alerts[p->alerts.cnt-1].s = &s;
1826  SET_PKT_LEN(p, sizeof(raw_ppp));
1827 
1829 
1830  DecodePPP(&tv, &dtv, p, raw_ppp, sizeof(raw_ppp), &pq);
1831 
1832  oc = Unified2AlertInitCtx(NULL);
1833  if (oc.ctx == NULL) {
1834  goto end;
1835  }
1836  uaf = oc.ctx->data;
1837  if (uaf == NULL)
1838  return 0;
1839  lf = uaf->file_ctx;
1840  if(lf == NULL) {
1841  goto end;
1842  }
1843  ret = Unified2AlertThreadInit(&tv, oc.ctx, &data);
1844  if(ret == -1) {
1845  goto end;
1846  }
1847  ret = Unified2Logger(&tv, data, p);
1848  if(ret == TM_ECODE_FAILED) {
1849  goto end;
1850  }
1851  ret = Unified2AlertThreadDeinit(&tv, data);
1852  if(ret == -1) {
1853  goto end;
1854  }
1855 
1856  Unified2AlertDeInitCtx(oc.ctx);
1857 
1858  PACKET_RECYCLE(p);
1859  SCFree(p);
1860  FlowShutdown();
1861  return 1;
1862 
1863 end:
1864  PACKET_RECYCLE(p);
1865  SCFree(p);
1866  FlowShutdown();
1867  return 0;
1868 }
1869 
1870 /**
1871  * \test Test the ethernet+ipv4+tcp droped unified2 test
1872  *
1873  * \retval 1 on succces
1874  * \retval 0 on failure
1875  */
1876 
1877 static int Unified2Test05(void)
1878 {
1879  ThreadVars tv;
1880  DecodeThreadVars dtv;
1881  PacketQueue pq;
1882  void *data = NULL;
1883  OutputInitResult oc;
1884  LogFileCtx *lf;
1885  Unified2AlertFileCtx *uaf = NULL;
1886  Signature s;
1887 
1888  uint8_t raw_ipv4_tcp[] = {
1889  0x00, 0x14, 0xbf, 0xe8, 0xcb, 0x26, 0xaa, 0x00,
1890  0x04, 0x00, 0x0a, 0x04, 0x08, 0x00, 0x45, 0x00,
1891  0x00, 0x3c, 0x8c, 0x55, 0x40, 0x00, 0x40, 0x06,
1892  0x69, 0x86, 0xc0, 0xa8, 0x0a, 0x68, 0x4a, 0x7d,
1893  0x2f, 0x53, 0xc2, 0x40, 0x00, 0x50, 0x1f, 0x00,
1894  0xa4, 0xd4, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x02,
1895  0x16, 0xd0, 0x3d, 0x4e, 0x00, 0x00, 0x02, 0x04,
1896  0x05, 0xb4, 0x04, 0x02, 0x08, 0x0a, 0x00, 0x1c,
1897  0x28, 0x81, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03,
1898  0x03, 0x06};
1899  Packet *p = PacketGetFromAlloc();
1900  if (unlikely(p == NULL))
1901  return 0;
1902  int ret;
1903 
1904  memset(&dtv, 0, sizeof(DecodeThreadVars));
1905  memset(&tv, 0, sizeof(ThreadVars));
1906  memset(&pq, 0, sizeof(PacketQueue));
1907  memset(&s, 0, sizeof(Signature));
1908 
1909  p->alerts.cnt++;
1910  s.id = 1;
1911  s.gid = 1;
1912  s.rev = 1;
1913  p->alerts.alerts[p->alerts.cnt-1].s = &s;
1914  SET_PKT_LEN(p, sizeof(raw_ipv4_tcp));
1915 
1917 
1918  DecodeEthernet(&tv, &dtv, p, raw_ipv4_tcp, sizeof(raw_ipv4_tcp), &pq);
1919 
1920  p->action = ACTION_DROP;
1921 
1922  oc = Unified2AlertInitCtx(NULL);
1923  if (oc.ctx == NULL) {
1924  goto end;
1925  }
1926  uaf = oc.ctx->data;
1927  if (uaf == NULL)
1928  return 0;
1929  lf = uaf->file_ctx;
1930  if(lf == NULL) {
1931  goto end;
1932  }
1933  ret = Unified2AlertThreadInit(&tv, oc.ctx, &data);
1934  if(ret == -1) {
1935  goto end;
1936  }
1937  ret = Unified2Logger(&tv, data, p);
1938  if(ret == TM_ECODE_FAILED) {
1939  goto end;
1940  }
1941  ret = Unified2AlertThreadDeinit(&tv, data);
1942  if(ret == TM_ECODE_FAILED) {
1943  goto end;
1944  }
1945 
1946  Unified2AlertDeInitCtx(oc.ctx);
1947 
1948  PACKET_RECYCLE(p);
1949  SCFree(p);
1950  FlowShutdown();
1951  return 1;
1952 
1953 end:
1954  PACKET_RECYCLE(p);
1955  SCFree(p);
1956  FlowShutdown();
1957  return 0;
1958 }
1959 
1960 /**
1961  * \test Test the Rotate process
1962  *
1963  * \retval 1 on succces
1964  * \retval 0 on failure
1965  */
1966 static int Unified2TestRotate01(void)
1967 {
1968  int ret = 0;
1969  int r = 0;
1970  ThreadVars tv;
1971  OutputInitResult oc;
1972  LogFileCtx *lf;
1973  Unified2AlertFileCtx *uaf = NULL;
1974  void *data = NULL;
1975  char *filename = NULL;
1976 
1977  oc = Unified2AlertInitCtx(NULL);
1978  if (oc.ctx == NULL)
1979  return 0;
1980  uaf = oc.ctx->data;
1981  if (uaf == NULL)
1982  return 0;
1983  lf = uaf->file_ctx;
1984  if (lf == NULL)
1985  return 0;
1986  filename = SCStrdup(lf->filename);
1987  if (unlikely(filename == NULL))
1988  return 0;
1989 
1990  memset(&tv, 0, sizeof(ThreadVars));
1991 
1992  ret = Unified2AlertThreadInit(&tv, oc.ctx, &data);
1993  if (ret == TM_ECODE_FAILED) {
1994  LogFileFreeCtx(lf);
1995  if (filename != NULL)
1996  SCFree(filename);
1997  return 0;
1998  }
1999 
2001 
2002  ret = Unified2AlertRotateFile(data, false);
2003  if (ret == -1)
2004  goto error;
2005 
2006  if (strcmp(filename, lf->filename) == 0) {
2008  "filename \"%s\" == \"%s\": ", filename, lf->filename);
2009  goto error;
2010  }
2011 
2012  r = 1;
2013 
2014 error:
2015  ret = Unified2AlertThreadDeinit(&tv, data);
2016  if(ret == TM_ECODE_FAILED) {
2017  printf("Unified2AlertThreadDeinit error");
2018  }
2019  if (oc.ctx != NULL)
2020  Unified2AlertDeInitCtx(oc.ctx);
2021  if (filename != NULL)
2022  SCFree(filename);
2023  return r;
2024 }
2025 #endif
2026 
2027 /**
2028  * \brief this function registers unit tests for Unified2
2029  */
2031 {
2032 #ifdef UNITTESTS
2033  UtRegisterTest("Unified2Test01 -- Ipv4 test", Unified2Test01);
2034  UtRegisterTest("Unified2Test02 -- Ipv6 test", Unified2Test02);
2035  UtRegisterTest("Unified2Test03 -- GRE test", Unified2Test03);
2036  UtRegisterTest("Unified2Test04 -- PPP test", Unified2Test04);
2037  UtRegisterTest("Unified2Test05 -- Inline test", Unified2Test05);
2038  UtRegisterTest("Unified2TestRotate01 -- Rotate File",
2039  Unified2TestRotate01);
2040 #endif /* UNITTESTS */
2041 }
int Unified2Logger(ThreadVars *tv, void *data, const Packet *p)
Unified2 main entry function.
EthernetHdr * ethh
Definition: decode.h:494
#define PACKET_ALERT_FLAG_STREAM_MATCH
Definition: decode.h:285
int DecodePPP(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len, PacketQueue *pq)
Definition: decode-ppp.c:43
uint16_t flags
int StreamSegmentForEach(const Packet *p, uint8_t flag, StreamSegmentCallback CallbackFunc, void *data)
Run callback for all segments.
Definition: stream.c:39
#define SCLogDebug(...)
Definition: util-debug.h:335
uint8_t ip_proto
Definition: decode-ipv4.h:78
int HttpXFFGetIP(const Flow *f, HttpXFFCfg *xff_cfg, char *dstbuf, int dstbuflen)
Function to return XFF IP if any. The caller needs to lock the flow.
struct Flow_ * flow
Definition: decode.h:446
#define PACKET_ALERT_FLAG_TX
Definition: decode.h:287
#define BUG_ON(x)
#define PACKET_TEST_ACTION(p, a)
Definition: decode.h:858
uint32_t id
Definition: detect.h:555
#define FALSE
#define SET_PKT_LEN(p, len)
Definition: decode.h:230
void HttpXFFGetCfg(ConfNode *conf, HttpXFFCfg *result)
Function to return XFF configuration from a configuration node.
#define unlikely(expr)
Definition: util-optimize.h:35
struct Unified2AlertFileCtx_ Unified2AlertFileCtx
#define GET_IPV6_SRC_IN6ADDR(p)
Definition: decode.h:218
Unified2ExtraData
Port sp
Definition: decode.h:416
#define UNIFIED2_ALERT_XFF_IPV6
int prio
Definition: detect.h:558
int Unified2Condition(ThreadVars *tv, const Packet *p)
Port dp
Definition: decode.h:424
ICMPV4Hdr * icmpv4h
Definition: decode.h:529
uint8_t code
#define UNIFIED2_IDS_EVENT_TYPE
#define IPV4_MAXPACKET_LEN
Definition: decode-ipv4.h:30
#define SC_ATOMIC_ADD(name, val)
add a value to our atomic variable
Definition: util-atomic.h:107
#define DEFAULT_LIMIT
uint64_t offset
#define UNIFIED2_BLOCKED_FLAG
uint64_t size_current
#define FLOW_QUIET
Definition: flow.h:38
#define PKT_IS_IPV6(p)
Definition: decode.h:253
#define PACKET_RECYCLE(p)
Definition: decode.h:815
int ByteExtractStringUint32(uint32_t *res, int base, uint16_t len, const char *str)
Definition: util-byte.c:244
void(* DeInit)(struct OutputCtx_ *)
Definition: tm-modules.h:84
struct Unified2AlertThread_ Unified2AlertThread
AppProto FlowGetAppProtocol(const Flow *f)
Definition: flow.c:1063
#define DEFAULT_LOG_FILENAME
TCPHdr * tcph
Definition: decode.h:523
struct _FakeIPv4Hdr FakeIPv4Hdr
Signature container.
Definition: detect.h:522
#define TRUE
#define SCMutexLock(mut)
#define PKT_IS_IPV4(p)
Definition: decode.h:252
#define UNIFIED2_ALERT_FLAGS_EMIT_PACKET
#define XFF_MAXLEN
int ParseSizeStringU64(const char *size, uint64_t *res)
Definition: util-misc.c:203
PacketAlert alerts[PACKET_ALERT_MAX]
Definition: decode.h:295
const struct Signature_ * s
Definition: decode.h:274
#define SC_ATOMIC_INIT(name)
Initialize the previously declared atomic variable and it&#39;s lock.
Definition: util-atomic.h:81
#define SCCalloc(nm, a)
Definition: util-mem.h:253
const char * ConfNodeLookupChildValue(const ConfNode *node, const char *name)
Lookup the value of a child configuration node by name.
Definition: conf.c:843
struct Unified2AlertFileHeader_ Unified2AlertFileHeader
void OutputRegisterPacketModule(LoggerId id, const char *name, const char *conf_name, OutputInitFunc InitFunc, PacketLogger PacketLogFunc, PacketLogCondition PacketConditionFunc, ThreadInitFunc ThreadInit, ThreadDeinitFunc ThreadDeinit, ThreadExitPrintStatsFunc ThreadExitPrintStats)
Register a packet output module.
Definition: output.c:163
#define SCMutexUnlock(mut)
void OutputRegisterFileRotationFlag(int *flag)
Register a flag for file rotation notification.
Definition: output.c:871
IPV6Hdr * ip6h
Definition: decode.h:503
ICMPV6Hdr * icmpv6h
Definition: decode.h:531
PacketAlert * PacketAlertGetTag(void)
int datalink
Definition: decode.h:575
uint8_t proto
Definition: decode.h:431
#define UNIFIED2_ALERT_XFF_IPV4
void TimeGet(struct timeval *tv)
Definition: util-time.c:146
int ConfGetChildValueBool(const ConfNode *base, const char *name, int *val)
Definition: conf.c:530
#define ETHERNET_TYPE_IP
uint8_t type
int HttpXFFGetIPFromTx(const Flow *f, uint64_t tx_id, HttpXFFCfg *xff_cfg, char *dstbuf, int dstbuflen)
Function to return XFF IP if any in the selected transaction. The caller needs to lock the flow...
#define MODULE_NAME
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:294
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Structure to hold thread specific data for all decode modules.
Definition: decode.h:633
#define UNIFIED2_EXTRADATA_CLIENT_IPV6_TYPE
struct _FakeIPv6Hdr FakeIPv6Hdr
#define MIN_LIMIT
SCMutex fp_mutex
#define LOGFILE_ALERTS_PRINTED
#define UNIFIED2_EXTRADATA_TYPE_BLOB
uint8_t flowflags
Definition: decode.h:440
#define UNIFIED2_IDS_EVENT_EXTRADATA_TYPE
int ConfValIsFalse(const char *val)
Check if a value is false.
Definition: conf.c:591
LogFileCtx * LogFileNewCtx(void)
LogFileNewCtx() Get a new LogFileCtx.
#define IPV4_GET_RAW_IPPROTO(ip4h)
Definition: decode-ipv4.h:101
#define FLOW_PKT_TOSERVER
Definition: flow.h:201
uint32_t gid
Definition: detect.h:556
struct AlertIPv6Unified2_ AlertIPv6Unified2
uint64_t tx_id
Definition: decode.h:275
Unified2AlertFileCtx * unified2alert_ctx
#define SCLogWarning(err_code,...)
Macro used to log WARNING messages.
Definition: util-debug.h:281
void Unified2AlertRegister(void)
OutputInitResult Unified2AlertInitCtx(ConfNode *conf)
Create a new LogFileCtx from the provided ConfNode.
int ConfValIsTrue(const char *val)
Check if a value is true.
Definition: conf.c:566
IPV4Hdr * ip4h
Definition: decode.h:501
uint16_t ip_len
Definition: decode-ipv4.h:74
#define IPV4_GET_RAW_HLEN(ip4h)
Definition: decode-ipv4.h:95
Definition: conf.h:32
TmEcode Unified2AlertThreadDeinit(ThreadVars *, void *)
Thread deinit function.
OutputCtx * ctx
Definition: output.h:42
const char * ConfigGetLogDirectory()
Definition: util-conf.c:36
#define SCMalloc(a)
Definition: util-mem.h:222
void TimeSetIncrementTime(uint32_t tv_sec)
increment the time in the engine
Definition: util-time.c:175
int LogFileFreeCtx(LogFileCtx *lf_ctx)
LogFileFreeCtx() Destroy a LogFileCtx (Close the file and free memory)
uint16_t payload_len
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:254
#define XFF_OVERWRITE
#define UNIFIED2_IDS_EVENT_IPV6_TYPE
#define SCFree(a)
Definition: util-mem.h:322
uint8_t flags
Definition: decode.h:273
uint8_t type
TmEcode Unified2AlertThreadInit(ThreadVars *, const void *, void **)
Thread init function.
struct AlertUnified2Packet_ Unified2Packet
void FlowShutdown(void)
shutdown the flow engine
Definition: flow.c:670
void * data
Definition: tm-modules.h:81
#define PKT_HAS_TAG
Definition: decode.h:1090
uint32_t rev
Definition: detect.h:557
void Unified2RegisterTests(void)
this function registers unit tests for Unified2
PacketAlerts alerts
Definition: decode.h:556
#define GET_PKT_DATA(p)
Definition: decode.h:226
Packet * PacketDequeue(PacketQueue *q)
Definition: packet-queue.c:167
#define XFF_DISABLED
#define PACKET_ALERT_FLAG_STATE_MATCH
Definition: decode.h:283
#define SCStrdup(a)
Definition: util-mem.h:268
uint16_t length
uint64_t size_limit
int run_mode
Definition: suricata.c:204
uint16_t ip_csum
Definition: decode-ipv4.h:79
int DecodeEthernet(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len, PacketQueue *pq)
#define UNIFIED2_EXTRADATA_CLIENT_IPV4_TYPE
uint16_t cnt
Definition: decode.h:294
uint8_t len
Per thread variable structure.
Definition: threadvars.h:57
struct timeval ts
Definition: decode.h:452
#define FLOW_PKT_TOCLIENT
Definition: flow.h:202
#define GET_PKT_LEN(p)
Definition: decode.h:225
Unified2AlertFileHeader * hdr
#define ACTION_DROP
#define ETHERNET_TYPE_IPV6
uint32_t flags
Definition: decode.h:444
struct SCLogConfig_ SCLogConfig
Holds the config state used by the logging api.
#define likely(expr)
Definition: util-optimize.h:32
#define UNIFIED2_PACKET_TYPE
struct AlertIPv4Unified2_ AlertIPv4Unified2
#define XFF_EXTRADATA
uint8_t ip_verhl
Definition: decode-ipv4.h:72
uint16_t class_id
Definition: detect.h:542
Packet * PacketGetFromAlloc(void)
Get a malloced packet.
Definition: decode.c:141
#define UNIFIED2_PACKET_SIZE
SC_ATOMIC_DECLARE(unsigned int, unified2_event_id)
struct Unified2ExtraDataHdr_ __attribute__((__packed__))
DNP3 link header.
uint8_t action
Definition: decode.h:545
void FlowInitConfig(char quiet)
initialize the configuration
Definition: flow.c:515
#define UNIFIED2_EXTRADATA_TYPE_EXTRA_DATA