1 /*
2  * Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved.
3  * Copyright (C) 2002-2013 Sourcefire, Inc.
4  * Copyright (C) 1998-2002 Martin Roesch <roesch@sourcefire.com>
5  * Author: Adam Keeton
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License Version 2 as
9  * published by the Free Software Foundation.  You may not use, modify or
10  * distribute this program under any other version of the GNU General
11  * Public License.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21  */
22 
23 
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27 
28 #include <stdio.h>
29 
30 #ifndef WIN32
31 #include <ctype.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <errno.h>
35 
36 #include <sys/types.h>
37 #include <sys/socket.h>
38 #include <netinet/in.h>
39 #include <arpa/inet.h>
40 #endif
41 #ifdef HAVE_UUID_UUID_H
42 #include<uuid/uuid.h>
43 #endif
44 
45 #include "Unified2_common.h"
46 
47 #define SUCCESS 314159265
48 #define STEVE -1
49 #define FAILURE STEVE
50 
51 #ifndef WIN32
52 #ifndef uint32_t
53 typedef unsigned int uint32_t;
54 typedef unsigned short uint16_t;
55 typedef unsigned char uint8_t;
56 #endif
57 #else
inet_ntop(int family,const void * ip_raw,char * buf,int bufsize)58 static void inet_ntop(int family, const void *ip_raw, char *buf, int bufsize) {
59     int i;
60 
61     if(!ip_raw || !buf || !bufsize ||
62        (family != AF_INET && family != AF_INET6) ||
63        /* Make sure if it's IPv6 that the buf is large enough. */
64        /* Need atleast a max of 8 fields of 4 bytes plus 7 for colons in
65         * between.  Need 1 more byte for null. */
66        (family == AF_INET6 && bufsize < 8*4 + 7 + 1) ||
67        /* Make sure if it's IPv4 that the buf is large enough. */
68        /* 4 fields of 3 numbers, plus 3 dots and a null byte */
69        (family == AF_INET && bufsize < 3*4 + 4) )
70     {
71         if(buf && bufsize > 0) buf[0] = 0;
72         return;
73     }
74 
75     /* 4 fields of at most 3 characters each */
76     if(family == AF_INET) {
77         u_int8_t *p = (u_int8_t*)ip_raw;
78 
79         for(i=0; p < ((u_int8_t*)ip_raw) + 4; p++) {
80             i += sprintf(&buf[i], "%d", *p);
81 
82             /* If this is the last iteration, this could technically cause one
83              *  extra byte to be written past the end. */
84             if(i < bufsize && ((p + 1) < ((u_int8_t*)ip_raw+4)))
85                 buf[i] = '.';
86 
87             i++;
88         }
89 
90     /* Check if this is really just an IPv4 address represented as 6,
91      * in compatible format */
92 #if 0
93     }
94     else if(!field[0] && !field[1] && !field[2]) {
95         unsigned char *p = (unsigned char *)(&ip->ip[12]);
96 
97         for(i=0; p < &ip->ip[16]; p++)
98              i += sprintf(&buf[i], "%d.", *p);
99 #endif
100     }
101     else {
102         u_int16_t *p = (u_int16_t*)ip_raw;
103 
104         for(i=0; p < ((u_int16_t*)ip_raw) + 8; p++) {
105             i += sprintf(&buf[i], "%04x", ntohs(*p));
106 
107             /* If this is the last iteration, this could technically cause one
108              *  extra byte to be written past the end. */
109             if(i < bufsize && ((p + 1) < ((u_int16_t*)ip_raw) + 8))
110                 buf[i] = ':';
111 
112             i++;
113         }
114     }
115 }
116 #endif
117 
118 typedef struct _record {
119     uint32_t type;
120     uint32_t length;
121     uint8_t *data;
122 } u2record;
123 
124 typedef struct _u2iterator {
125     FILE *file;
126     char *filename;
127     u2record current;
128 } u2iterator;
129 
130 static long s_pos = 0, s_off = 0;
131 
132 #define TO_IP(x) x >> 24, (x >> 16) & 0xff, (x >> 8) & 0xff, x & 0xff
133 
new_iterator(char * filename)134 static u2iterator *new_iterator(char *filename) {
135     FILE *f = fopen(filename, "rb");
136     u2iterator *ret;
137 
138     if(!f) {
139         printf("new_iterator: Failed to open file: %s\n\tErrno: %s\n",
140           filename, strerror(errno));
141         return NULL;
142     }
143 
144     ret = (u2iterator*)malloc(sizeof(u2iterator));
145 
146     if(!ret) {
147         printf("new_iterator: Failed to malloc %lu bytes.\n", (unsigned long)sizeof(u2iterator));
148         fclose(f);
149         return NULL;
150     }
151 
152     ret->file = f;
153     ret->filename = strdup(filename);
154     return ret;
155 }
156 
free_iterator(u2iterator * it)157 static inline void free_iterator(u2iterator *it) {
158     if(it->file) fclose(it->file);
159     if(it->filename) free(it->filename);
160     if(it) free(it);
161 }
162 
get_record(u2iterator * it,u2record * record)163 static int get_record(u2iterator *it, u2record *record) {
164     uint32_t bytes_read;
165     uint8_t *tmp;
166 
167     if(!it || !it->file) return FAILURE;
168 
169     /* check if the log was rotated */
170     if(feof(it->file)) {
171         /* Get next timestamped file? */
172         puts("Hit the EOF .. and this is not being handled yet.");
173         return FAILURE;
174     }
175 
176     if ( s_off )
177     {
178         if (fseek(it->file, s_pos+s_off, SEEK_SET))
179         {
180             puts("Unable to SEEK on current file .. and this is not being handled yet.");
181             return FAILURE;
182         }
183         s_off = 0;
184     }
185 
186     /* read type and length */
187     bytes_read = fread(record, 1, sizeof(uint32_t) * 2, it->file);
188     /* But they're in network order! */
189     record->type= ntohl(record->type);
190     record->length= ntohl(record->length);
191 
192     //if(record->type == UNIFIED2_PACKET) record->length+=4;
193 
194     if(bytes_read == 0)
195        /* EOF */
196        return FAILURE;
197 
198     if(bytes_read != sizeof(uint32_t)*2) {
199         puts("get_record: (1) Failed to read all of record.");
200         printf("\tRead %u of %lu bytes\n", bytes_read, (unsigned long)sizeof(uint32_t)*2);
201         return FAILURE;
202     }
203 
204     s_pos = ftell(it->file);
205 
206     tmp = (uint8_t *)realloc(record->data, record->length);
207 
208     if (!tmp)
209     {
210         puts("get_record: (2) Failed to allocate memory.");
211         free(record->data);
212         return FAILURE;
213     }
214 
215     record->data = tmp;
216 
217     bytes_read = fread(record->data, 1, record->length, it->file);
218 
219     if(bytes_read != record->length) {
220         puts("get_record: (3) Failed to read all of record data.");
221         printf("\tRead %u of %u bytes\n", bytes_read, record->length);
222 
223         if ( record->type != UNIFIED2_PACKET ||
224             bytes_read < ntohl(((Serial_Unified2Packet*)record->data)->packet_length)
225         )
226             return FAILURE;
227 
228         clearerr(it->file);
229     }
230 
231     return SUCCESS;
232 }
233 
extradata_dump(u2record * record)234 static void extradata_dump(u2record *record) {
235     uint8_t *field, *data;
236     int i;
237     int len = 0;
238     SerialUnified2ExtraData event;
239     Unified2ExtraDataHdr eventHdr;
240     uint32_t ip;
241     char ip6buf[INET6_ADDRSTRLEN+1];
242     struct in6_addr ipAddr;
243 
244     memcpy(&eventHdr, record->data, sizeof(Unified2ExtraDataHdr));
245 
246     memcpy(&event, record->data + sizeof(Unified2ExtraDataHdr) , sizeof(SerialUnified2ExtraData));
247 
248     /* network to host ordering */
249     field = (uint8_t*)&eventHdr;
250     for(i=0; i<2; i++, field+=4) {
251         *(uint32_t*)field = ntohl(*(uint32_t*)field);
252     }
253 
254     field = (uint8_t*)&event;
255     for(i=0; i<6; i++, field+=4) {
256         *(uint32_t*)field = ntohl(*(uint32_t*)field);
257     }
258 
259 
260 
261     printf("\n(ExtraDataHdr)\n"
262             "\tevent type: %u\tevent length: %u\n",
263             eventHdr.event_type, eventHdr.event_length);
264 
265     printf("\n(ExtraData)\n"
266             "\tsensor id: %u\tevent id: %u\tevent second: %u\n"
267             "\ttype: %u\tdatatype: %u\tbloblength: %u\t",
268              event.sensor_id, event.event_id,
269              event.event_second, event.type,
270              event.data_type, event.blob_length);
271 
272     len = event.blob_length - sizeof(event.blob_length) - sizeof(event.data_type);
273 
274     switch(event.type)
275     {
276         case EVENT_INFO_XFF_IPV4:
277             memcpy(&ip, record->data + sizeof(Unified2ExtraDataHdr) + sizeof(SerialUnified2ExtraData), sizeof(uint32_t));
278             ip = ntohl(ip);
279             printf("Original Client IP: %u.%u.%u.%u\n",
280                     TO_IP(ip));
281             break;
282 
283         case EVENT_INFO_XFF_IPV6:
284             memcpy(&ipAddr, record->data + sizeof(Unified2ExtraDataHdr) + sizeof(SerialUnified2ExtraData), sizeof(struct in6_addr));
285             inet_ntop(AF_INET6, &ipAddr, ip6buf, INET6_ADDRSTRLEN);
286             printf("Original Client IP: %s\n",
287                     ip6buf);
288             break;
289 
290         case EVENT_INFO_GZIP_DATA:
291             printf("GZIP Decompressed Data: %.*s\n",
292                 len, record->data + sizeof(Unified2ExtraDataHdr) + sizeof(SerialUnified2ExtraData));
293             break;
294 
295         case EVENT_INFO_JSNORM_DATA:
296             printf("Normalized JavaScript Data: %.*s\n",
297                 len, record->data + sizeof(Unified2ExtraDataHdr) + sizeof(SerialUnified2ExtraData));
298             break;
299 
300         case EVENT_INFO_SMTP_FILENAME:
301             printf("SMTP Attachment Filename: %.*s\n",
302                 len,record->data + sizeof(Unified2ExtraDataHdr) + sizeof(SerialUnified2ExtraData));
303             break;
304 
305         case EVENT_INFO_SMTP_MAILFROM:
306             printf("SMTP MAIL FROM Addresses: %.*s\n",
307                     len,record->data + sizeof(Unified2ExtraDataHdr) + sizeof(SerialUnified2ExtraData));
308             break;
309 
310         case EVENT_INFO_SMTP_RCPTTO:
311             printf("SMTP RCPT TO Addresses: %.*s\n",
312                 len, record->data + sizeof(Unified2ExtraDataHdr) + sizeof(SerialUnified2ExtraData));
313             break;
314 
315         case EVENT_INFO_SMTP_EMAIL_HDRS:
316             printf("SMTP EMAIL HEADERS: \n%.*s\n",
317                 len, record->data + sizeof(Unified2ExtraDataHdr) + sizeof(SerialUnified2ExtraData));
318             break;
319 
320         case EVENT_INFO_HTTP_URI:
321             printf("HTTP URI: %.*s\n",
322                 len, record->data + sizeof(Unified2ExtraDataHdr) + sizeof(SerialUnified2ExtraData));
323             break;
324 
325         case EVENT_INFO_HTTP_HOSTNAME:
326             printf("HTTP Hostname: ");
327             data = record->data + sizeof(Unified2ExtraDataHdr) + sizeof(SerialUnified2ExtraData);
328             for(i=0; i < len; i++)
329             {
330                 if(iscntrl(data[i]))
331                     printf("%c",'.');
332                 else
333                     printf("%c",data[i]);
334             }
335             printf("\n");
336             break;
337 
338         case EVENT_INFO_IPV6_SRC:
339             memcpy(&ipAddr, record->data + sizeof(Unified2ExtraDataHdr) + sizeof(SerialUnified2ExtraData), sizeof(struct in6_addr));
340             inet_ntop(AF_INET6, &ipAddr, ip6buf, INET6_ADDRSTRLEN);
341             printf("IPv6 Source Address: %s\n",
342                     ip6buf);
343             break;
344 
345         case EVENT_INFO_IPV6_DST:
346             memcpy(&ipAddr, record->data + sizeof(Unified2ExtraDataHdr) + sizeof(SerialUnified2ExtraData), sizeof(struct in6_addr));
347             inet_ntop(AF_INET6, &ipAddr, ip6buf, INET6_ADDRSTRLEN);
348             printf("IPv6 Destination Address: %s\n",
349                     ip6buf);
350             break;
351 
352         default :
353             break;
354     }
355 
356 }
357 
event_dump(u2record * record)358 static void event_dump(u2record *record) {
359     uint8_t *field;
360     int i;
361     Serial_Unified2IDSEvent_legacy event;
362 
363     memcpy(&event, record->data, sizeof(Serial_Unified2IDSEvent_legacy));
364 
365     /* network to host ordering */
366     /* In the event structure, only the last 40 bits are not 32 bit fields */
367     /* The first 11 fields need to be convertted */
368     field = (uint8_t*)&event;
369     for(i=0; i<11; i++, field+=4) {
370         *(uint32_t*)field = ntohl(*(uint32_t*)field);
371     }
372 
373     /* last 3 fields, with the exception of the last most since it's just one byte */
374     *(uint16_t*)field = ntohs(*(uint16_t*)field); /* sport_itype */
375     field += 2;
376     *(uint16_t*)field = ntohs(*(uint16_t*)field); /* dport_icode */
377     /* done changing the network ordering */
378 
379 
380     printf("\n(Event)\n"
381             "\tsensor id: %u\tevent id: %u\tevent second: %u\tevent microsecond: %u\n"
382             "\tsig id: %u\tgen id: %u\trevision: %u\t classification: %u\n"
383             "\tpriority: %u\tip source: %u.%u.%u.%u\tip destination: %u.%u.%u.%u\n"
384             "\tsrc port: %u\tdest port: %u\tprotocol: %u\timpact_flag: %u\tblocked: %u\n",
385              event.sensor_id, event.event_id,
386              event.event_second, event.event_microsecond,
387              event.signature_id, event.generator_id,
388              event.signature_revision, event.classification_id,
389              event.priority_id, TO_IP(event.ip_source),
390              TO_IP(event.ip_destination), event.sport_itype,
391              event.dport_icode, event.protocol,
392              event.impact_flag, event.blocked);
393 }
394 
event6_dump(u2record * record)395 static void event6_dump(u2record *record) {
396     uint8_t *field;
397     int i;
398     Serial_Unified2IDSEventIPv6_legacy event;
399     char ip6buf[INET6_ADDRSTRLEN+1];
400 
401     memcpy(&event, record->data, sizeof(Serial_Unified2IDSEventIPv6_legacy));
402 
403     /* network to host ordering */
404     /* In the event structure, only the last 40 bits are not 32 bit fields */
405     /* The first fields need to be convertted */
406     field = (uint8_t*)&event;
407     for(i=0; i<9; i++, field+=4) {
408         *(uint32_t*)field = ntohl(*(uint32_t*)field);
409     }
410 
411     field = field + 2*sizeof(struct in6_addr);
412 
413     /* last 3 fields, with the exception of the last most since it's just one byte */
414     *(uint16_t*)field = ntohs(*(uint16_t*)field); /* sport_itype */
415     field += 2;
416     *(uint16_t*)field = ntohs(*(uint16_t*)field); /* dport_icode */
417     /* done changing the network ordering */
418 
419     inet_ntop(AF_INET6, &event.ip_source, ip6buf, INET6_ADDRSTRLEN);
420 
421     printf("\n(IPv6 Event)\n"
422             "\tsensor id: %u\tevent id: %u\tevent second: %u\tevent microsecond: %u\n"
423             "\tsig id: %u\tgen id: %u\trevision: %u\t classification: %u\n"
424             "\tpriority: %u\tip source: %s\t",
425              event.sensor_id, event.event_id,
426              event.event_second, event.event_microsecond,
427              event.signature_id, event.generator_id,
428              event.signature_revision, event.classification_id,
429              event.priority_id, ip6buf);
430 
431 
432     inet_ntop(AF_INET6, &event.ip_destination, ip6buf, INET6_ADDRSTRLEN);
433     printf("ip destination: %s\n"
434             "\tsrc port: %u\tdest port: %u\tprotocol: %u\timpact_flag: %u\tblocked: %u\n",
435              ip6buf, event.sport_itype,
436              event.dport_icode, event.protocol,
437              event.impact_flag, event.blocked);
438 }
439 
440 
441 
event2_dump(u2record * record)442 static void event2_dump(u2record *record) {
443     uint8_t *field;
444     int i;
445 
446     Serial_Unified2IDSEvent event;
447 
448     memcpy(&event, record->data, sizeof(Serial_Unified2IDSEvent));
449 
450     /* network to host ordering */
451     /* In the event structure, only the last 40 bits are not 32 bit fields */
452     /* The first 11 fields need to be convertted */
453     field = (uint8_t*)&event;
454     for(i=0; i<11; i++, field+=4) {
455         *(uint32_t*)field = ntohl(*(uint32_t*)field);
456     }
457 
458     /* last 3 fields, with the exception of the last most since it's just one byte */
459     *(uint16_t*)field = ntohs(*(uint16_t*)field); /* sport_itype */
460     field += 2;
461     *(uint16_t*)field = ntohs(*(uint16_t*)field); /* dport_icode */
462     field +=6;
463     *(uint32_t*)field = ntohl(*(uint32_t*)field); /* mpls_label */
464     field += 4;
465     /* policy_id and vlanid */
466     for(i=0; i<2; i++, field+=2) {
467         *(uint16_t*)field = ntohs(*(uint16_t*)field);
468     }
469     /* done changing the network ordering */
470 
471 
472     printf("\n(Event)\n"
473             "\tsensor id: %u\tevent id: %u\tevent second: %u\tevent microsecond: %u\n"
474             "\tsig id: %u\tgen id: %u\trevision: %u\t classification: %u\n"
475             "\tpriority: %u\tip source: %u.%u.%u.%u\tip destination: %u.%u.%u.%u\n"
476             "\tsrc port: %u\tdest port: %u\tprotocol: %u\timpact_flag: %u\tblocked: %u\n"
477             "\tmpls label: %u\tvland id: %u\tpolicy id: %u\n",
478              event.sensor_id, event.event_id,
479              event.event_second, event.event_microsecond,
480              event.signature_id, event.generator_id,
481              event.signature_revision, event.classification_id,
482              event.priority_id, TO_IP(event.ip_source),
483              TO_IP(event.ip_destination), event.sport_itype,
484              event.dport_icode, event.protocol,
485              event.impact_flag, event.blocked,
486              event.mpls_label, event.vlanId, event.pad2);
487 
488 }
489 
490 #if defined(FEAT_OPEN_APPID)
event3_dump(u2record * record)491 static void event3_dump(u2record *record)
492 {
493     uint8_t *field;
494     int i;
495 
496     Serial_Unified2IDSEvent event;
497 
498     memcpy(&event, record->data, sizeof(Serial_Unified2IDSEvent));
499 
500     /* network to host ordering */
501     /* In the event structure, only the last 40 bits are not 32 bit fields */
502     /* The first 11 fields need to be convertted */
503     field = (uint8_t*)&event;
504     for(i=0; i<11; i++, field+=4) {
505         *(uint32_t*)field = ntohl(*(uint32_t*)field);
506     }
507 
508     /* last 3 fields, with the exception of the last most since it's just one byte */
509     *(uint16_t*)field = ntohs(*(uint16_t*)field); /* sport_itype */
510     field += 2;
511     *(uint16_t*)field = ntohs(*(uint16_t*)field); /* dport_icode */
512     field +=6;
513     *(uint32_t*)field = ntohl(*(uint32_t*)field); /* mpls_label */
514     field += 4;
515     /* policy_id and vlanid */
516     for(i=0; i<2; i++, field+=2) {
517         *(uint16_t*)field = ntohs(*(uint16_t*)field);
518     }
519     /* done changing the network ordering */
520 
521 
522     printf("\n(Event)\n"
523             "\tsensor id: %u\tevent id: %u\tevent second: %u\tevent microsecond: %u\n"
524             "\tsig id: %u\tgen id: %u\trevision: %u\t classification: %u\n"
525             "\tpriority: %u\tip source: %u.%u.%u.%u\tip destination: %u.%u.%u.%u\n"
526             "\tsrc port: %u\tdest port: %u\tprotocol: %u\timpact_flag: %u\tblocked: %u\n"
527             "\tmpls label: %u\tvland id: %u\tpolicy id: %u\tappid: %s\n",
528              event.sensor_id, event.event_id,
529              event.event_second, event.event_microsecond,
530              event.signature_id, event.generator_id,
531              event.signature_revision, event.classification_id,
532              event.priority_id, TO_IP(event.ip_source),
533              TO_IP(event.ip_destination), event.sport_itype,
534              event.dport_icode, event.protocol,
535              event.impact_flag, event.blocked,
536              event.mpls_label, event.vlanId, event.pad2, event.app_name);
537 
538 }
539 
540 #endif /* defined(FEAT_OPEN_APPID) */
event2_6_dump(u2record * record)541 static void event2_6_dump(u2record *record) {
542     uint8_t *field;
543     int i;
544     char ip6buf[INET6_ADDRSTRLEN+1];
545     Serial_Unified2IDSEventIPv6 event;
546 
547     memcpy(&event, record->data, sizeof(Serial_Unified2IDSEventIPv6));
548 
549     /* network to host ordering */
550     /* In the event structure, only the last 40 bits are not 32 bit fields */
551     /* The first fields need to be convertted */
552     field = (uint8_t*)&event;
553     for(i=0; i<9; i++, field+=4) {
554         *(uint32_t*)field = ntohl(*(uint32_t*)field);
555     }
556 
557     field = field + 2*sizeof(struct in6_addr);
558 
559     /* last 3 fields, with the exception of the last most since it's just one byte */
560     *(uint16_t*)field = ntohs(*(uint16_t*)field); /* sport_itype */
561     field += 2;
562     *(uint16_t*)field = ntohs(*(uint16_t*)field); /* dport_icode */
563     field +=6;
564     *(uint32_t*)field = ntohl(*(uint32_t*)field); /* mpls_label */
565     field += 4;
566     /* policy_id and vlanid */
567     for(i=0; i<2; i++, field+=2) {
568         *(uint16_t*)field = ntohs(*(uint16_t*)field);
569     }
570     /* done changing the network ordering */
571 
572     inet_ntop(AF_INET6, &event.ip_source, ip6buf, INET6_ADDRSTRLEN);
573 
574     printf("\n(IPv6 Event)\n"
575             "\tsensor id: %u\tevent id: %u\tevent second: %u\tevent microsecond: %u\n"
576             "\tsig id: %u\tgen id: %u\trevision: %u\t classification: %u\n"
577             "\tpriority: %u\tip source: %s\t",
578              event.sensor_id, event.event_id,
579              event.event_second, event.event_microsecond,
580              event.signature_id, event.generator_id,
581              event.signature_revision, event.classification_id,
582              event.priority_id, ip6buf);
583 
584 
585     inet_ntop(AF_INET6, &event.ip_destination, ip6buf, INET6_ADDRSTRLEN);
586     printf("ip destination: %s\n"
587             "\tsrc port: %u\tdest port: %u\tprotocol: %u\timpact_flag: %u\tblocked: %u\n"
588             "\tmpls label: %u\tvland id: %u\tpolicy id: %u\n",
589              ip6buf, event.sport_itype,
590              event.dport_icode, event.protocol,
591              event.impact_flag, event.blocked,
592              event.mpls_label, event.vlanId,event.pad2);
593 
594 }
595 
596 #if defined(FEAT_OPEN_APPID)
event3_6_dump(u2record * record)597 static void event3_6_dump(u2record *record) {
598     uint8_t *field;
599     int i;
600     char ip6buf[INET6_ADDRSTRLEN+1];
601     Serial_Unified2IDSEventIPv6 event;
602 
603     memcpy(&event, record->data, sizeof(Serial_Unified2IDSEventIPv6));
604 
605     /* network to host ordering */
606     /* In the event structure, only the last 40 bits are not 32 bit fields */
607     /* The first fields need to be convertted */
608     field = (uint8_t*)&event;
609     for(i=0; i<9; i++, field+=4) {
610         *(uint32_t*)field = ntohl(*(uint32_t*)field);
611     }
612 
613     field = field + 2*sizeof(struct in6_addr);
614 
615     /* last 3 fields, with the exception of the last most since it's just one byte */
616     *(uint16_t*)field = ntohs(*(uint16_t*)field); /* sport_itype */
617     field += 2;
618     *(uint16_t*)field = ntohs(*(uint16_t*)field); /* dport_icode */
619     field +=6;
620     *(uint32_t*)field = ntohl(*(uint32_t*)field); /* mpls_label */
621     field += 4;
622     /* policy_id and vlanid */
623     for(i=0; i<2; i++, field+=2) {
624         *(uint16_t*)field = ntohs(*(uint16_t*)field);
625     }
626     /* done changing the network ordering */
627 
628     inet_ntop(AF_INET6, &event.ip_source, ip6buf, INET6_ADDRSTRLEN);
629 
630     printf("\n(IPv6 Event)\n"
631             "\tsensor id: %u\tevent id: %u\tevent second: %u\tevent microsecond: %u\n"
632             "\tsig id: %u\tgen id: %u\trevision: %u\t classification: %u\n"
633             "\tpriority: %u\tip source: %s\t",
634              event.sensor_id, event.event_id,
635              event.event_second, event.event_microsecond,
636              event.signature_id, event.generator_id,
637              event.signature_revision, event.classification_id,
638              event.priority_id, ip6buf);
639 
640 
641     inet_ntop(AF_INET6, &event.ip_destination, ip6buf, INET6_ADDRSTRLEN);
642     printf("ip destination: %s\n"
643             "\tsrc port: %u\tdest port: %u\tprotocol: %u\timpact_flag: %u\tblocked: %u\n"
644             "\tmpls label: %u\tvland id: %u\tpolicy id: %u\tappid: %s\n",
645              ip6buf, event.sport_itype,
646              event.dport_icode, event.protocol,
647              event.impact_flag, event.blocked,
648              event.mpls_label, event.vlanId,event.pad2, event.app_name);
649 
650 }
651 
appid_dump(u2record * record)652 static void appid_dump(u2record *record) {
653     uint8_t *field = (uint8_t*)record->data;
654     unsigned i;
655     unsigned appCnt;
656     unsigned statTime;
657 
658     /* network to host ordering */
659     /* In the event structure, only the last 40 bits are not 32 bit fields */
660     /* The first fields need to be convertted */
661     statTime = ntohl(*(uint32_t*)field);
662     field += 4;
663     appCnt = ntohl(*(uint32_t*)field);
664     field += 4;
665 
666     printf("\n(AppId Stats)\n"
667             "    event second: %u\tRecordCount: %u\n",
668              statTime, appCnt);
669     for(i=0; i<appCnt; i++)
670     {
671         char appName[MAX_EVENT_APPNAME_LEN];
672         memcpy(appName, field, sizeof(appName));
673         field += MAX_EVENT_APPNAME_LEN;
674 
675         int txBytes = ntohl(*(uint32_t*)field);
676         field += 4;
677         int rxBytes = ntohl(*(uint32_t*)field);
678         field += 4;
679 
680         printf("    -----------\n\tApp:%s\n\tbytes_out: %u\n\tbytes_in: %u\n",
681             appName, txBytes, rxBytes);
682      }
683 }
684 
685 #endif /* defined(FEAT_OPEN_APPID) */
686 
687 #define LOG_CHARS 16
688 
LogBuffer(const uint8_t * p,unsigned n)689 static void LogBuffer (const uint8_t* p, unsigned n)
690 {
691     char hex[(3*LOG_CHARS)+1];
692     char txt[LOG_CHARS+1];
693     unsigned odx = 0, idx = 0, at = 0;
694 
695     for ( idx = 0; idx < n; idx++)
696     {
697         uint8_t byte = p[idx];
698         sprintf(hex + 3*odx, "%2.02X ", byte);
699         txt[odx++] = isprint(byte) ? byte : '.';
700 
701         if ( odx == LOG_CHARS )
702         {
703             txt[odx] = hex[3*odx] = '\0';
704             printf("[%5u] %s %s\n", at, hex, txt);
705             at = idx + 1;
706             odx = 0;
707         }
708     }
709     if ( odx )
710     {
711         txt[odx] = hex[3*odx] = '\0';
712         printf("[%5u] %-48.48s %s\n", at, hex, txt);
713     }
714 }
715 
packet_dump(u2record * record)716 static void packet_dump(u2record *record) {
717     uint32_t counter;
718     uint8_t *field;
719 
720     unsigned offset = sizeof(Serial_Unified2Packet)-4;
721     unsigned reclen = record->length - offset;
722 
723     Serial_Unified2Packet packet;
724     memcpy(&packet, record->data, sizeof(Serial_Unified2Packet));
725 
726     /* network to host ordering */
727     /* The first 7 fields need to be convertted */
728     field = (uint8_t*)&packet;
729     for(counter=0; counter<7; counter++, field+=4) {
730         *(uint32_t*)field = ntohl(*(uint32_t*)field);
731     }
732     /* done changing from network ordering */
733 
734     printf("\nPacket\n"
735             "\tsensor id: %u\tevent id: %u\tevent second: %u\n"
736             "\tpacket second: %u\tpacket microsecond: %u\n"
737             "\tlinktype: %u\tpacket_length: %u\n",
738             packet.sensor_id, packet.event_id, packet.event_second,
739             packet.packet_second, packet.packet_microsecond, packet.linktype,
740             packet.packet_length);
741 
742 
743     if ( record->length <= offset )
744         return;
745 
746     if ( packet.packet_length != reclen )
747     {
748         printf("ERROR: logged %u but packet_length = %u\n",
749             record->length-offset, packet.packet_length);
750 
751         if ( packet.packet_length < reclen )
752         {
753             reclen = packet.packet_length;
754             s_off = reclen + offset;
755         }
756     }
757     LogBuffer(record->data+offset, reclen);
758 }
759 
u2dump(char * file)760 static int u2dump(char *file) {
761     u2record record;
762     u2iterator *it = new_iterator(file);
763 
764     memset(&record, 0, sizeof(record));
765 
766     if(!it) {
767         printf("u2dump: Failed to create new iterator with file: %s\n", file);
768         return -1;
769     }
770 
771     while( get_record(it, &record) == SUCCESS ) {
772         if(record.type == UNIFIED2_IDS_EVENT) event_dump(&record);
773         else if(record.type == UNIFIED2_IDS_EVENT_VLAN) event2_dump(&record);
774         else if(record.type == UNIFIED2_PACKET) packet_dump(&record);
775         else if(record.type == UNIFIED2_IDS_EVENT_IPV6) event6_dump(&record);
776         else if(record.type == UNIFIED2_IDS_EVENT_IPV6_VLAN) event2_6_dump(&record);
777         else if(record.type == UNIFIED2_EXTRA_DATA) extradata_dump(&record);
778 #if defined(FEAT_OPEN_APPID)
779 
780         else if(record.type == UNIFIED2_IDS_EVENT_APPID) event3_dump(&record);
781         else if(record.type == UNIFIED2_IDS_EVENT_APPID_IPV6) event3_6_dump(&record);
782         else if(record.type == UNIFIED2_IDS_EVENT_APPSTAT) appid_dump(&record);
783 #endif /* defined(FEAT_OPEN_APPID) */
784     }
785 
786     free_iterator(it);
787     if(record.data)
788         free(record.data);
789 
790     return 0;
791 }
792 
main(int argc,char ** argv)793 int main(int argc, char **argv) {
794     if(argc != 2) {
795         printf("usage: %s <file>\n",argv[0]);
796         return 1;
797     }
798 
799     return u2dump(argv[1]);
800 }
801