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);
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);
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 
1284  LogFileCtx* file_ctx = LogFileNewCtx();
1285  if (file_ctx == NULL) {
1286  SCLogError(SC_ERR_UNIFIED2_ALERT_GENERIC, "Couldn't create new file_ctx");
1287  return result;
1288  }
1289 
1290  const char *filename = NULL;
1291  if (conf != NULL) { /* To faciliate unit tests. */
1292  filename = ConfNodeLookupChildValue(conf, "filename");
1293  }
1294  if (filename == NULL)
1295  filename = DEFAULT_LOG_FILENAME;
1296  file_ctx->prefix = SCStrdup(filename);
1297  if (unlikely(file_ctx->prefix == NULL)) {
1298  SCLogError(SC_ERR_MEM_ALLOC, "Failed to allocate file prefix");
1299  exit(EXIT_FAILURE);
1300  }
1301 
1302  const char *s_limit = NULL;
1303  file_ctx->size_limit = DEFAULT_LIMIT;
1304  if (conf != NULL) {
1305  s_limit = ConfNodeLookupChildValue(conf, "limit");
1306  if (s_limit != NULL) {
1307  if (ParseSizeStringU64(s_limit, &file_ctx->size_limit) < 0) {
1309  "Failed to initialize unified2 output, invalid limit: %s",
1310  s_limit);
1311  exit(EXIT_FAILURE);
1312  }
1313  if (file_ctx->size_limit < 4096) {
1314  SCLogInfo("unified2-alert \"limit\" value of %"PRIu64" assumed to be pre-1.2 "
1315  "style: setting limit to %"PRIu64"mb", file_ctx->size_limit, file_ctx->size_limit);
1316  uint64_t size = file_ctx->size_limit * 1024 * 1024;
1317  file_ctx->size_limit = size;
1318  } else if (file_ctx->size_limit < MIN_LIMIT) {
1320  "Failed to initialize unified2 output, limit less than "
1321  "allowed minimum: %d.", MIN_LIMIT);
1322  exit(EXIT_FAILURE);
1323  }
1324  }
1325  }
1326 
1327  if (conf != NULL) {
1328  const char *sensor_id_s = NULL;
1329  sensor_id_s = ConfNodeLookupChildValue(conf, "sensor-id");
1330  if (sensor_id_s != NULL) {
1331  if (ByteExtractStringUint32(&sensor_id, 10, 0, sensor_id_s) == -1) {
1332  SCLogError(SC_ERR_INVALID_ARGUMENT, "Failed to initialize unified2 output, invalid sensor-id: %s", sensor_id_s);
1333  exit(EXIT_FAILURE);
1334  }
1335  }
1336 
1337  if (ConfGetChildValueBool(conf, "nostamp", &nostamp)) {
1338  if (nostamp) {
1339  SCLogConfig("Disabling unified2 timestamp.");
1340  file_ctx->nostamp = true;
1341  }
1342  }
1343  }
1344 
1346  if (conf != NULL) {
1347  const char *payload = NULL;
1348  payload = ConfNodeLookupChildValue(conf, "payload");
1349  if (payload) {
1350  if (ConfValIsFalse(payload)) {
1352  } else if (!ConfValIsTrue(payload)) {
1353  SCLogError(SC_ERR_INVALID_ARGUMENT, "Failed to initialize unified2 output, invalid payload: %s", payload);
1354  exit(EXIT_FAILURE);
1355  }
1356  }
1357  }
1358 
1359  ret = Unified2AlertOpenFileCtx(file_ctx, filename, false);
1360  if (ret < 0)
1361  goto error;
1362 
1363  /* Only register for file rotation if theout is non-timestamped. */
1364  if (nostamp) {
1366  }
1367 
1368  output_ctx = SCCalloc(1, sizeof(OutputCtx));
1369  if (unlikely(output_ctx == NULL))
1370  goto error;
1371 
1372  xff_cfg = SCMalloc(sizeof(HttpXFFCfg));
1373  if (unlikely(xff_cfg == NULL)) {
1374  goto error;
1375  }
1376  memset(xff_cfg, 0x00, sizeof(HttpXFFCfg));
1377 
1378  if (conf != NULL) {
1379  HttpXFFGetCfg(conf, xff_cfg);
1380  }
1381 
1382  Unified2AlertFileCtx *unified2alert_ctx = SCMalloc(sizeof(Unified2AlertFileCtx));
1383  if (unlikely(unified2alert_ctx == NULL)) {
1384  goto error;
1385  }
1386  memset(unified2alert_ctx, 0x00, sizeof(Unified2AlertFileCtx));
1387 
1388  unified2alert_ctx->file_ctx = file_ctx;
1389  unified2alert_ctx->xff_cfg = xff_cfg;
1390  unified2alert_ctx->flags = flags;
1391  output_ctx->data = unified2alert_ctx;
1392  output_ctx->DeInit = Unified2AlertDeInitCtx;
1393 
1394  SCLogInfo("Unified2-alert initialized: filename %s, limit %"PRIu64" MB",
1395  filename, file_ctx->size_limit / (1024*1024));
1396 
1397  SC_ATOMIC_INIT(unified2_event_id);
1398 
1399  result.ctx = output_ctx;
1400  result.ok = true;
1401  return result;
1402 
1403 error:
1404  LogFileFreeCtx(file_ctx);
1405 
1406  if (xff_cfg != NULL) {
1407  SCFree(xff_cfg);
1408  }
1409  if (output_ctx != NULL) {
1410  SCFree(output_ctx);
1411  }
1412 
1413  return result;
1414 }
1415 
1416 static void Unified2AlertDeInitCtx(OutputCtx *output_ctx)
1417 {
1418  if (output_ctx != NULL) {
1419  Unified2AlertFileCtx *unified2alert_ctx = (Unified2AlertFileCtx *) output_ctx->data;
1420  if (unified2alert_ctx != NULL) {
1421  LogFileCtx *logfile_ctx = unified2alert_ctx->file_ctx;
1422  if (logfile_ctx != NULL) {
1423  LogFileFreeCtx(logfile_ctx);
1424  }
1425  HttpXFFCfg *xff_cfg = unified2alert_ctx->xff_cfg;
1426  if (xff_cfg != NULL) {
1427  SCFree(xff_cfg);
1428  }
1429  SCFree(unified2alert_ctx);
1430  }
1431  SCFree(output_ctx);
1432  }
1433 }
1434 
1435 /** \brief Read the config set the file pointer, open the file
1436  * \param file_ctx pointer to a created LogFileCtx using LogFileNewCtx()
1437  * \param prefix Prefix of the log file.
1438  * \return -1 if failure, 0 if succesful
1439  * */
1440 static int Unified2AlertOpenFileCtx(LogFileCtx *file_ctx, const char *prefix,
1441  bool truncate)
1442 {
1443  int ret = 0;
1444  char *filename = NULL;
1445  if (file_ctx->filename != NULL)
1446  filename = file_ctx->filename;
1447  else {
1448  filename = SCMalloc(PATH_MAX); /* XXX some sane default? */
1449  if (unlikely(filename == NULL))
1450  return -1;
1451  file_ctx->filename = filename;
1452 
1453  memset(filename, 0x00, PATH_MAX);
1454  }
1455 
1456  /** get the time so we can have a filename with seconds since epoch */
1457  struct timeval ts;
1458  memset(&ts, 0x00, sizeof(struct timeval));
1459 
1460  extern int run_mode;
1461  if (run_mode == RUNMODE_UNITTEST)
1462  TimeGet(&ts);
1463  else
1464  gettimeofday(&ts, NULL);
1465 
1466  /* create the filename to use */
1467  const char *log_dir;
1468  log_dir = ConfigGetLogDirectory();
1469 
1470  if (file_ctx->nostamp) {
1471  snprintf(filename, PATH_MAX, "%s/%s", log_dir, prefix);
1472  } else {
1473  snprintf(filename, PATH_MAX, "%s/%s.%" PRIu32, log_dir, prefix, (uint32_t)ts.tv_sec);
1474  }
1475 
1476  if (truncate) {
1477  file_ctx->fp = fopen(filename, "wb");
1478  } else {
1479  file_ctx->fp = fopen(filename, "ab");
1480  }
1481  if (file_ctx->fp == NULL) {
1482  SCLogError(SC_ERR_FOPEN, "failed to open %s: %s", filename,
1483  strerror(errno));
1484  ret = -1;
1485  }
1486 
1487  return ret;
1488 }
1489 
1490 
1491 #ifdef UNITTESTS
1492 
1493 /**
1494  * \test Test the ethernet+ipv4+tcp unified2 test
1495  *
1496  * \retval 1 on succces
1497  * \retval 0 on failure
1498  */
1499 
1500 static int Unified2Test01(void)
1501 {
1502  ThreadVars tv;
1503  DecodeThreadVars dtv;
1504  PacketQueue pq;
1505  void *data = NULL;
1506  OutputInitResult oc;
1507  LogFileCtx *lf;
1508  Unified2AlertFileCtx *uaf = NULL;
1509  Signature s;
1510 
1511  uint8_t raw_ipv4_tcp[] = {
1512  0x00, 0x14, 0xbf, 0xe8, 0xcb, 0x26, 0xaa, 0x00,
1513  0x04, 0x00, 0x0a, 0x04, 0x08, 0x00, 0x45, 0x00,
1514  0x00, 0x3c, 0x8c, 0x55, 0x40, 0x00, 0x40, 0x06,
1515  0x69, 0x86, 0xc0, 0xa8, 0x0a, 0x68, 0x4a, 0x7d,
1516  0x2f, 0x53, 0xc2, 0x40, 0x00, 0x50, 0x1f, 0x00,
1517  0xa4, 0xd4, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x02,
1518  0x16, 0xd0, 0x3d, 0x4e, 0x00, 0x00, 0x02, 0x04,
1519  0x05, 0xb4, 0x04, 0x02, 0x08, 0x0a, 0x00, 0x1c,
1520  0x28, 0x81, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03,
1521  0x03, 0x06};
1522  Packet *p = PacketGetFromAlloc();
1523  if (unlikely(p == NULL))
1524  return 0;
1525  int ret;
1526 
1527  memset(&dtv, 0, sizeof(DecodeThreadVars));
1528  memset(&tv, 0, sizeof(ThreadVars));
1529  memset(&pq, 0, sizeof(PacketQueue));
1530  memset(&s, 0, sizeof(Signature));
1531 
1532  p->alerts.cnt++;
1533  s.id = 1;
1534  s.gid = 1;
1535  s.rev = 1;
1536  p->alerts.alerts[p->alerts.cnt-1].s = &s;
1537  SET_PKT_LEN(p, sizeof(raw_ipv4_tcp));
1538 
1540 
1541  DecodeEthernet(&tv, &dtv, p, raw_ipv4_tcp, sizeof(raw_ipv4_tcp), &pq);
1542 
1543 
1544  oc = Unified2AlertInitCtx(NULL);
1545  if (oc.ctx == NULL) {
1546  goto end;
1547  }
1548  uaf = oc.ctx->data;
1549  if (uaf == NULL)
1550  return 0;
1551  lf = uaf->file_ctx;
1552  if(lf == NULL) {
1553  goto end;
1554  }
1555  ret = Unified2AlertThreadInit(&tv, oc.ctx, &data);
1556  if(ret == TM_ECODE_FAILED) {
1557  goto end;
1558  }
1559  ret = Unified2Logger(&tv, data, p);
1560  if(ret == TM_ECODE_FAILED) {
1561  goto end;
1562  }
1563  ret = Unified2AlertThreadDeinit(&tv, data);
1564  if(ret == -1) {
1565  goto end;
1566  }
1567 
1568  Unified2AlertDeInitCtx(oc.ctx);
1569 
1570  PACKET_RECYCLE(p);
1571  SCFree(p);
1572  FlowShutdown();
1573  return 1;
1574 
1575 end:
1576  PACKET_RECYCLE(p);
1577  SCFree(p);
1578  FlowShutdown();
1579  return 0;
1580 }
1581 
1582 /**
1583  * \test Test the ethernet+ipv6+tcp unified2 test
1584  *
1585  * \retval 1 on succces
1586  * \retval 0 on failure
1587  */
1588 
1589 static int Unified2Test02(void)
1590 {
1591  ThreadVars tv;
1592  DecodeThreadVars dtv;
1593  PacketQueue pq;
1594  void *data = NULL;
1595  OutputInitResult oc;
1596  LogFileCtx *lf;
1597  Unified2AlertFileCtx *uaf = NULL;
1598  Signature s;
1599 
1600  uint8_t raw_ipv6_tcp[] = {
1601  0x00, 0x11, 0x25, 0x82, 0x95, 0xb5, 0x00, 0xd0,
1602  0x09, 0xe3, 0xe8, 0xde, 0x86, 0xdd, 0x60, 0x00,
1603  0x00, 0x00, 0x00, 0x28, 0x06, 0x40, 0x20, 0x01,
1604  0x06, 0xf8, 0x10, 0x2d, 0x00, 0x00, 0x02, 0xd0,
1605  0x09, 0xff, 0xfe, 0xe3, 0xe8, 0xde, 0x20, 0x01,
1606  0x06, 0xf8, 0x09, 0x00, 0x07, 0xc0, 0x00, 0x00,
1607  0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xe7, 0x41,
1608  0x00, 0x50, 0xab, 0xdc, 0xd6, 0x60, 0x00, 0x00,
1609  0x00, 0x00, 0xa0, 0x02, 0x16, 0x80, 0x41, 0xa2,
1610  0x00, 0x00, 0x02, 0x04, 0x05, 0xa0, 0x04, 0x02,
1611  0x08, 0x0a, 0x00, 0x0a, 0x22, 0xa8, 0x00, 0x00,
1612  0x00, 0x00, 0x01, 0x03, 0x03, 0x05 };
1613  Packet *p = PacketGetFromAlloc();
1614  if (unlikely(p == NULL))
1615  return 0;
1616  int ret;
1617 
1618  memset(&dtv, 0, sizeof(DecodeThreadVars));
1619  memset(&tv, 0, sizeof(ThreadVars));
1620  memset(&pq, 0, sizeof(PacketQueue));
1621  memset(&s, 0, sizeof(Signature));
1622 
1623  p->alerts.cnt++;
1624  s.id = 1;
1625  s.gid = 1;
1626  s.rev = 1;
1627  p->alerts.alerts[p->alerts.cnt-1].s = &s;
1628  SET_PKT_LEN(p, sizeof(raw_ipv6_tcp));
1629 
1631 
1632  DecodeEthernet(&tv, &dtv, p, raw_ipv6_tcp, sizeof(raw_ipv6_tcp), &pq);
1633 
1634  oc = Unified2AlertInitCtx(NULL);
1635  if (oc.ctx == NULL) {
1636  goto end;
1637  }
1638  uaf = oc.ctx->data;
1639  if (uaf == NULL)
1640  return 0;
1641  lf = uaf->file_ctx;
1642  if(lf == NULL) {
1643  goto end;
1644  }
1645  ret = Unified2AlertThreadInit(&tv, oc.ctx, &data);
1646  if(ret == -1) {
1647  goto end;
1648  }
1649  ret = Unified2Logger(&tv, data, p);
1650  if(ret == TM_ECODE_FAILED) {
1651  goto end;
1652  }
1653  ret = Unified2AlertThreadDeinit(&tv, data);
1654  if(ret == -1) {
1655  goto end;
1656  }
1657 
1658  Unified2AlertDeInitCtx(oc.ctx);
1659 
1660  PACKET_RECYCLE(p);
1661  SCFree(p);
1662  FlowShutdown();
1663  return 1;
1664 
1665 end:
1666  PACKET_RECYCLE(p);
1667  SCFree(p);
1668  FlowShutdown();
1669  return 0;
1670 }
1671 
1672 
1673 /**
1674  * \test Test the GRE unified2 test
1675  *
1676  * \retval 1 on succces
1677  * \retval 0 on failure
1678  */
1679 
1680 static int Unified2Test03(void)
1681 {
1682  ThreadVars tv;
1683  DecodeThreadVars dtv;
1684  PacketQueue pq;
1685  void *data = NULL;
1686  OutputInitResult oc;
1687  LogFileCtx *lf;
1688  Unified2AlertFileCtx *uaf = NULL;
1689  Signature s;
1690 
1691  uint8_t raw_gre[] = {
1692  0x00, 0x0e, 0x50, 0x06, 0x42, 0x96, 0xaa, 0x00,
1693  0x04, 0x00, 0x0a, 0x04, 0x08, 0x00, 0x45, 0x00,
1694  0x00, 0x74, 0x35, 0xa2, 0x40, 0x00, 0x40, 0x2f,
1695  0xef, 0xcb, 0x0a, 0x00, 0x00, 0x64, 0x0a, 0x00,
1696  0x00, 0x8a, 0x30, 0x01, 0x88, 0x0b, 0x00, 0x54,
1697  0x00, 0x00, 0x00, 0x18, 0x29, 0x5f, 0xff, 0x03,
1698  0x00, 0x21, 0x45, 0x00, 0x00, 0x50, 0xf4, 0x05,
1699  0x40, 0x00, 0x3f, 0x06, 0x20, 0xb8, 0x50, 0x7e,
1700  0x2b, 0x2d, 0xd4, 0xcc, 0xd6, 0x72, 0x0a, 0x92,
1701  0x1a, 0x0b, 0xc9, 0xaf, 0x24, 0x02, 0x8c, 0xdd,
1702  0x45, 0xf6, 0x80, 0x18, 0x21, 0xfc, 0x10, 0x7c,
1703  0x00, 0x00, 0x01, 0x01, 0x08, 0x0a, 0x08, 0x19,
1704  0x1a, 0xda, 0x84, 0xd6, 0xda, 0x3e, 0x50, 0x49,
1705  0x4e, 0x47, 0x20, 0x73, 0x74, 0x65, 0x72, 0x6c,
1706  0x69, 0x6e, 0x67, 0x2e, 0x66, 0x72, 0x65, 0x65,
1707  0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, 0x65, 0x74,
1708  0x0d, 0x0a};
1709  Packet *p = PacketGetFromAlloc();
1710  Packet *pkt;
1711  if (unlikely(p == NULL))
1712  return 0;
1713  int ret;
1714 
1715  memset(&dtv, 0, sizeof(DecodeThreadVars));
1716  memset(&tv, 0, sizeof(ThreadVars));
1717  memset(&pq, 0, sizeof(PacketQueue));
1718  memset(&s, 0, sizeof(Signature));
1719 
1720  p->alerts.cnt++;
1721  s.id = 1;
1722  s.gid = 1;
1723  s.rev = 1;
1724  p->alerts.alerts[p->alerts.cnt-1].s = &s;
1725  SET_PKT_LEN(p, sizeof(raw_gre));
1726 
1728 
1729  DecodeEthernet(&tv, &dtv, p, raw_gre, sizeof(raw_gre), &pq);
1730 
1731  oc = Unified2AlertInitCtx(NULL);
1732  if (oc.ctx == NULL) {
1733  goto end;
1734  }
1735  uaf = oc.ctx->data;
1736  if (uaf == NULL)
1737  return 0;
1738  lf = uaf->file_ctx;
1739  if(lf == NULL) {
1740  goto end;
1741  }
1742  ret = Unified2AlertThreadInit(&tv, oc.ctx, &data);
1743  if(ret == -1) {
1744  goto end;
1745  }
1746  ret = Unified2Logger(&tv, data, p);
1747  if(ret == TM_ECODE_FAILED) {
1748  goto end;
1749  }
1750  ret = Unified2AlertThreadDeinit(&tv, data);
1751  if(ret == -1) {
1752  goto end;
1753  }
1754 
1755  Unified2AlertDeInitCtx(oc.ctx);
1756 
1757  pkt = PacketDequeue(&pq);
1758  while (pkt != NULL) {
1759  PACKET_RECYCLE(pkt);
1760  SCFree(pkt);
1761  pkt = PacketDequeue(&pq);
1762  }
1763 
1764  PACKET_RECYCLE(p);
1765  SCFree(p);
1766  FlowShutdown();
1767  return 1;
1768 
1769 end:
1770  pkt = PacketDequeue(&pq);
1771  while (pkt != NULL) {
1772  PACKET_RECYCLE(pkt);
1773  SCFree(pkt);
1774  pkt = PacketDequeue(&pq);
1775  }
1776  PACKET_RECYCLE(p);
1777  SCFree(p);
1778  FlowShutdown();
1779  return 0;
1780 }
1781 
1782 /**
1783  * \test Test the PPP unified2 test
1784  *
1785  * \retval 1 on succces
1786  * \retval 0 on failure
1787  */
1788 
1789 static int Unified2Test04(void)
1790 {
1791  ThreadVars tv;
1792  DecodeThreadVars dtv;
1793  PacketQueue pq;
1794  void *data = NULL;
1795  OutputInitResult oc;
1796  LogFileCtx *lf;
1797  Unified2AlertFileCtx *uaf = NULL;
1798  Signature s;
1799 
1800  uint8_t raw_ppp[] = {
1801  0xff, 0x03, 0x00, 0x21, 0x45, 0xc0, 0x00, 0x2c,
1802  0x4d, 0xed, 0x00, 0x00, 0xff, 0x06, 0xd5, 0x17,
1803  0xbf, 0x01, 0x0d, 0x01, 0xbf, 0x01, 0x0d, 0x03,
1804  0xea, 0x37, 0x00, 0x17, 0x6d, 0x0b, 0xba, 0xc3,
1805  0x00, 0x00, 0x00, 0x00, 0x60, 0x02, 0x10, 0x20,
1806  0xdd, 0xe1, 0x00, 0x00, 0x02, 0x04, 0x05, 0xb4};
1807  Packet *p = PacketGetFromAlloc();
1808  if (unlikely(p == NULL))
1809  return 0;
1810  int ret;
1811 
1812  memset(&dtv, 0, sizeof(DecodeThreadVars));
1813  memset(&tv, 0, sizeof(ThreadVars));
1814  memset(&pq, 0, sizeof(PacketQueue));
1815  memset(&s, 0, sizeof(Signature));
1816 
1817  p->alerts.cnt++;
1818  s.id = 1;
1819  s.gid = 1;
1820  s.rev = 1;
1821  p->alerts.alerts[p->alerts.cnt-1].s = &s;
1822  SET_PKT_LEN(p, sizeof(raw_ppp));
1823 
1825 
1826  DecodePPP(&tv, &dtv, p, raw_ppp, sizeof(raw_ppp), &pq);
1827 
1828  oc = Unified2AlertInitCtx(NULL);
1829  if (oc.ctx == NULL) {
1830  goto end;
1831  }
1832  uaf = oc.ctx->data;
1833  if (uaf == NULL)
1834  return 0;
1835  lf = uaf->file_ctx;
1836  if(lf == NULL) {
1837  goto end;
1838  }
1839  ret = Unified2AlertThreadInit(&tv, oc.ctx, &data);
1840  if(ret == -1) {
1841  goto end;
1842  }
1843  ret = Unified2Logger(&tv, data, p);
1844  if(ret == TM_ECODE_FAILED) {
1845  goto end;
1846  }
1847  ret = Unified2AlertThreadDeinit(&tv, data);
1848  if(ret == -1) {
1849  goto end;
1850  }
1851 
1852  Unified2AlertDeInitCtx(oc.ctx);
1853 
1854  PACKET_RECYCLE(p);
1855  SCFree(p);
1856  FlowShutdown();
1857  return 1;
1858 
1859 end:
1860  PACKET_RECYCLE(p);
1861  SCFree(p);
1862  FlowShutdown();
1863  return 0;
1864 }
1865 
1866 /**
1867  * \test Test the ethernet+ipv4+tcp droped unified2 test
1868  *
1869  * \retval 1 on succces
1870  * \retval 0 on failure
1871  */
1872 
1873 static int Unified2Test05(void)
1874 {
1875  ThreadVars tv;
1876  DecodeThreadVars dtv;
1877  PacketQueue pq;
1878  void *data = NULL;
1879  OutputInitResult oc;
1880  LogFileCtx *lf;
1881  Unified2AlertFileCtx *uaf = NULL;
1882  Signature s;
1883 
1884  uint8_t raw_ipv4_tcp[] = {
1885  0x00, 0x14, 0xbf, 0xe8, 0xcb, 0x26, 0xaa, 0x00,
1886  0x04, 0x00, 0x0a, 0x04, 0x08, 0x00, 0x45, 0x00,
1887  0x00, 0x3c, 0x8c, 0x55, 0x40, 0x00, 0x40, 0x06,
1888  0x69, 0x86, 0xc0, 0xa8, 0x0a, 0x68, 0x4a, 0x7d,
1889  0x2f, 0x53, 0xc2, 0x40, 0x00, 0x50, 0x1f, 0x00,
1890  0xa4, 0xd4, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x02,
1891  0x16, 0xd0, 0x3d, 0x4e, 0x00, 0x00, 0x02, 0x04,
1892  0x05, 0xb4, 0x04, 0x02, 0x08, 0x0a, 0x00, 0x1c,
1893  0x28, 0x81, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03,
1894  0x03, 0x06};
1895  Packet *p = PacketGetFromAlloc();
1896  if (unlikely(p == NULL))
1897  return 0;
1898  int ret;
1899 
1900  memset(&dtv, 0, sizeof(DecodeThreadVars));
1901  memset(&tv, 0, sizeof(ThreadVars));
1902  memset(&pq, 0, sizeof(PacketQueue));
1903  memset(&s, 0, sizeof(Signature));
1904 
1905  p->alerts.cnt++;
1906  s.id = 1;
1907  s.gid = 1;
1908  s.rev = 1;
1909  p->alerts.alerts[p->alerts.cnt-1].s = &s;
1910  SET_PKT_LEN(p, sizeof(raw_ipv4_tcp));
1911 
1913 
1914  DecodeEthernet(&tv, &dtv, p, raw_ipv4_tcp, sizeof(raw_ipv4_tcp), &pq);
1915 
1916  p->action = ACTION_DROP;
1917 
1918  oc = Unified2AlertInitCtx(NULL);
1919  if (oc.ctx == NULL) {
1920  goto end;
1921  }
1922  uaf = oc.ctx->data;
1923  if (uaf == NULL)
1924  return 0;
1925  lf = uaf->file_ctx;
1926  if(lf == NULL) {
1927  goto end;
1928  }
1929  ret = Unified2AlertThreadInit(&tv, oc.ctx, &data);
1930  if(ret == -1) {
1931  goto end;
1932  }
1933  ret = Unified2Logger(&tv, data, p);
1934  if(ret == TM_ECODE_FAILED) {
1935  goto end;
1936  }
1937  ret = Unified2AlertThreadDeinit(&tv, data);
1938  if(ret == TM_ECODE_FAILED) {
1939  goto end;
1940  }
1941 
1942  Unified2AlertDeInitCtx(oc.ctx);
1943 
1944  PACKET_RECYCLE(p);
1945  SCFree(p);
1946  FlowShutdown();
1947  return 1;
1948 
1949 end:
1950  PACKET_RECYCLE(p);
1951  SCFree(p);
1952  FlowShutdown();
1953  return 0;
1954 }
1955 
1956 /**
1957  * \test Test the Rotate process
1958  *
1959  * \retval 1 on succces
1960  * \retval 0 on failure
1961  */
1962 static int Unified2TestRotate01(void)
1963 {
1964  int ret = 0;
1965  int r = 0;
1966  ThreadVars tv;
1967  OutputInitResult oc;
1968  LogFileCtx *lf;
1969  Unified2AlertFileCtx *uaf = NULL;
1970  void *data = NULL;
1971  char *filename = NULL;
1972 
1973  oc = Unified2AlertInitCtx(NULL);
1974  if (oc.ctx == NULL)
1975  return 0;
1976  uaf = oc.ctx->data;
1977  if (uaf == NULL)
1978  return 0;
1979  lf = uaf->file_ctx;
1980  if (lf == NULL)
1981  return 0;
1982  filename = SCStrdup(lf->filename);
1983  if (unlikely(filename == NULL))
1984  return 0;
1985 
1986  memset(&tv, 0, sizeof(ThreadVars));
1987 
1988  ret = Unified2AlertThreadInit(&tv, oc.ctx, &data);
1989  if (ret == TM_ECODE_FAILED) {
1990  LogFileFreeCtx(lf);
1991  if (filename != NULL)
1992  SCFree(filename);
1993  return 0;
1994  }
1995 
1997 
1998  ret = Unified2AlertRotateFile(data, false);
1999  if (ret == -1)
2000  goto error;
2001 
2002  if (strcmp(filename, lf->filename) == 0) {
2004  "filename \"%s\" == \"%s\": ", filename, lf->filename);
2005  goto error;
2006  }
2007 
2008  r = 1;
2009 
2010 error:
2011  ret = Unified2AlertThreadDeinit(&tv, data);
2012  if(ret == TM_ECODE_FAILED) {
2013  printf("Unified2AlertThreadDeinit error");
2014  }
2015  if (oc.ctx != NULL)
2016  Unified2AlertDeInitCtx(oc.ctx);
2017  if (filename != NULL)
2018  SCFree(filename);
2019  return r;
2020 }
2021 #endif
2022 
2023 /**
2024  * \brief this function registers unit tests for Unified2
2025  */
2027 {
2028 #ifdef UNITTESTS
2029  UtRegisterTest("Unified2Test01 -- Ipv4 test", Unified2Test01);
2030  UtRegisterTest("Unified2Test02 -- Ipv6 test", Unified2Test02);
2031  UtRegisterTest("Unified2Test03 -- GRE test", Unified2Test03);
2032  UtRegisterTest("Unified2Test04 -- PPP test", Unified2Test04);
2033  UtRegisterTest("Unified2Test05 -- Inline test", Unified2Test05);
2034  UtRegisterTest("Unified2TestRotate01 -- Rotate File",
2035  Unified2TestRotate01);
2036 #endif /* UNITTESTS */
2037 }
int Unified2Logger(ThreadVars *tv, void *data, const Packet *p)
Unified2 main entry function.
EthernetHdr * ethh
Definition: decode.h:493
#define PACKET_ALERT_FLAG_STREAM_MATCH
Definition: decode.h:284
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:445
#define PACKET_ALERT_FLAG_TX
Definition: decode.h:286
int DecodePPP(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint32_t len, PacketQueue *pq)
Definition: decode-ppp.c:43
#define BUG_ON(x)
#define PACKET_TEST_ACTION(p, a)
Definition: decode.h:857
uint32_t id
Definition: detect.h:550
#define FALSE
#define SET_PKT_LEN(p, len)
Definition: decode.h:229
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:217
Unified2ExtraData
Port sp
Definition: decode.h:415
uint8_t class
Definition: detect.h:537
#define UNIFIED2_ALERT_XFF_IPV6
int prio
Definition: detect.h:553
int Unified2Condition(ThreadVars *tv, const Packet *p)
Port dp
Definition: decode.h:423
ICMPV4Hdr * icmpv4h
Definition: decode.h:528
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:252
#define PACKET_RECYCLE(p)
Definition: decode.h:814
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:1060
#define DEFAULT_LOG_FILENAME
TCPHdr * tcph
Definition: decode.h:522
struct _FakeIPv4Hdr FakeIPv4Hdr
Signature container.
Definition: detect.h:517
#define TRUE
#define SCMutexLock(mut)
#define PKT_IS_IPV4(p)
Definition: decode.h:251
#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:294
const struct Signature_ * s
Definition: decode.h:273
#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:161
#define SCMutexUnlock(mut)
void OutputRegisterFileRotationFlag(int *flag)
Register a flag for file rotation notification.
Definition: output.c:869
IPV6Hdr * ip6h
Definition: decode.h:502
ICMPV6Hdr * icmpv6h
Definition: decode.h:530
PacketAlert * PacketAlertGetTag(void)
int datalink
Definition: decode.h:574
uint8_t proto
Definition: decode.h:430
#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 DecodeEthernet(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint32_t len, PacketQueue *pq)
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:632
#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:439
#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:551
struct AlertIPv6Unified2_ AlertIPv6Unified2
uint64_t tx_id
Definition: decode.h:274
Unified2AlertFileCtx * unified2alert_ctx
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:500
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:272
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:667
void * data
Definition: tm-modules.h:81
#define PKT_HAS_TAG
Definition: decode.h:1086
uint32_t rev
Definition: detect.h:552
void Unified2RegisterTests(void)
this function registers unit tests for Unified2
PacketAlerts alerts
Definition: decode.h:555
#define GET_PKT_DATA(p)
Definition: decode.h:225
Packet * PacketDequeue(PacketQueue *q)
Definition: packet-queue.c:167
#define XFF_DISABLED
#define PACKET_ALERT_FLAG_STATE_MATCH
Definition: decode.h:282
#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
#define UNIFIED2_EXTRADATA_CLIENT_IPV4_TYPE
uint16_t cnt
Definition: decode.h:293
uint8_t len
Per thread variable structure.
Definition: threadvars.h:57
struct timeval ts
Definition: decode.h:451
#define FLOW_PKT_TOCLIENT
Definition: flow.h:202
#define GET_PKT_LEN(p)
Definition: decode.h:224
Unified2AlertFileHeader * hdr
#define ACTION_DROP
#define ETHERNET_TYPE_IPV6
uint32_t flags
Definition: decode.h:443
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
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:544
void FlowInitConfig(char quiet)
initialize the configuration
Definition: flow.c:512
#define UNIFIED2_EXTRADATA_TYPE_EXTRA_DATA