nfrb 0.0.1.alpha

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,102 @@
1
+ /* minilzo.h -- mini subset of the LZO real-time data compression library
2
+
3
+ This file is part of the LZO real-time data compression library.
4
+
5
+ Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
6
+ Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
7
+ Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
8
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
9
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
10
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
11
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
12
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
13
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
14
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
15
+ All Rights Reserved.
16
+
17
+ The LZO library is free software; you can redistribute it and/or
18
+ modify it under the terms of the GNU General Public License,
19
+ version 2, as published by the Free Software Foundation.
20
+
21
+ The LZO library is distributed in the hope that it will be useful,
22
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
23
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24
+ GNU General Public License for more details.
25
+
26
+ You should have received a copy of the GNU General Public License
27
+ along with the LZO library; see the file COPYING.
28
+ If not, write to the Free Software Foundation, Inc.,
29
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
30
+
31
+ Markus F.X.J. Oberhumer
32
+ <markus@oberhumer.com>
33
+ http://www.oberhumer.com/opensource/lzo/
34
+ */
35
+
36
+ /*
37
+ * NOTE:
38
+ * the full LZO package can be found at
39
+ * http://www.oberhumer.com/opensource/lzo/
40
+ */
41
+
42
+
43
+ #ifndef __MINILZO_H
44
+ #define __MINILZO_H 1
45
+
46
+ #define MINILZO_VERSION 0x2020
47
+
48
+ #ifdef __LZOCONF_H
49
+ # error "you cannot use both LZO and miniLZO"
50
+ #endif
51
+
52
+ #undef LZO_HAVE_CONFIG_H
53
+ #include "lzoconf.h"
54
+
55
+ #if !defined(LZO_VERSION) || (LZO_VERSION != MINILZO_VERSION)
56
+ # error "version mismatch in header files"
57
+ #endif
58
+
59
+
60
+ #ifdef __cplusplus
61
+ extern "C" {
62
+ #endif
63
+
64
+
65
+ /***********************************************************************
66
+ //
67
+ ************************************************************************/
68
+
69
+ /* Memory required for the wrkmem parameter.
70
+ * When the required size is 0, you can also pass a NULL pointer.
71
+ */
72
+
73
+ #define LZO1X_MEM_COMPRESS LZO1X_1_MEM_COMPRESS
74
+ #define LZO1X_1_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t))
75
+ #define LZO1X_MEM_DECOMPRESS (0)
76
+
77
+
78
+ /* compression */
79
+ LZO_EXTERN(int)
80
+ lzo1x_1_compress ( const lzo_bytep src, lzo_uint src_len,
81
+ lzo_bytep dst, lzo_uintp dst_len,
82
+ lzo_voidp wrkmem );
83
+
84
+ /* decompression */
85
+ LZO_EXTERN(int)
86
+ lzo1x_decompress ( const lzo_bytep src, lzo_uint src_len,
87
+ lzo_bytep dst, lzo_uintp dst_len,
88
+ lzo_voidp wrkmem /* NOT USED */ );
89
+
90
+ /* safe decompression with overrun testing */
91
+ LZO_EXTERN(int)
92
+ lzo1x_decompress_safe ( const lzo_bytep src, lzo_uint src_len,
93
+ lzo_bytep dst, lzo_uintp dst_len,
94
+ lzo_voidp wrkmem /* NOT USED */ );
95
+
96
+
97
+ #ifdef __cplusplus
98
+ } /* extern "C" */
99
+ #endif
100
+
101
+ #endif /* already included */
102
+
@@ -0,0 +1,117 @@
1
+ /*
2
+ * Copyright (c) 2009, Peter Haag
3
+ * Copyright (c) 2004-2008, SWITCH - Teleinformatikdienste fuer Lehre und Forschung
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ *
9
+ * * Redistributions of source code must retain the above copyright notice,
10
+ * this list of conditions and the following disclaimer.
11
+ * * Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ * * Neither the name of SWITCH nor the names of its contributors may be
15
+ * used to endorse or promote products derived from this software without
16
+ * specific prior written permission.
17
+ *
18
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28
+ * POSSIBILITY OF SUCH DAMAGE.
29
+ *
30
+ * $Author: haag $
31
+ *
32
+ * $Id: nf_common.h 39 2009-11-25 08:11:15Z haag $
33
+ *
34
+ * $LastChangedRevision: 39 $
35
+ *
36
+ *
37
+ */
38
+
39
+ #ifndef _NF_COMMON_H
40
+ #define _NF_COMMON_H 1
41
+
42
+
43
+ typedef void (*printer_t)(void *, char **, int);
44
+
45
+ #if ( SIZEOF_VOID_P == 8 )
46
+ typedef uint64_t pointer_addr_t;
47
+ #else
48
+ typedef uint32_t pointer_addr_t;
49
+ #endif
50
+
51
+ typedef struct msec_time_s {
52
+ time_t sec;
53
+ uint16_t msec;
54
+ } msec_time_tt;
55
+
56
+ /* common minimum netflow header for all versions */
57
+ typedef struct common_flow_header {
58
+ uint16_t version;
59
+ uint16_t count;
60
+ } common_flow_header_t;
61
+
62
+
63
+ /* prototypes */
64
+
65
+ int InitSymbols(void);
66
+
67
+ void Setv6Mode(int mode);
68
+
69
+ int Getv6Mode(void);
70
+
71
+ int Proto_num(char *protostr);
72
+
73
+ void format_file_block_header(void *header, char **s, int tag);
74
+
75
+ char *format_csv_header(void);
76
+
77
+ char *get_record_header(void);
78
+
79
+ void set_record_header(void);
80
+
81
+ void format_file_block_record(void *record, char **s, int tag);
82
+
83
+ void flow_record_to_pipe(void *record, char ** s, int tag);
84
+
85
+ void flow_record_to_csv(void *record, char ** s, int tag);
86
+
87
+ int ParseOutputFormat(char *format, int plain_numbers);
88
+
89
+ void format_special(void *record, char ** s, int tag);
90
+
91
+
92
+ uint32_t Get_fwd_status_id(char *status);
93
+
94
+ char *Get_fwd_status_name(uint32_t id);
95
+
96
+ #define FIXED_WIDTH 1
97
+ #define VAR_LENGTH 0
98
+
99
+ #ifdef __SUNPRO_C
100
+ extern
101
+ #endif
102
+ inline void Proto_string(uint8_t protonum, char *protostr);
103
+
104
+ #ifdef __SUNPRO_C
105
+ extern
106
+ #endif
107
+ inline void format_number(uint64_t num, char *s, int fixed_width);
108
+
109
+ #ifdef __SUNPRO_C
110
+ extern
111
+ #endif
112
+ inline void condense_v6(char *s);
113
+
114
+ #define TAG_CHAR ''
115
+
116
+ #endif //_NF_COMMON_H
117
+
@@ -0,0 +1,1167 @@
1
+ /*
2
+ * Copyright (c) 2011, Peter Haag
3
+ * Copyright (c) 2004-2008, SWITCH - Teleinformatikdienste fuer Lehre und Forschung
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ *
9
+ * * Redistributions of source code must retain the above copyright notice,
10
+ * this list of conditions and the following disclaimer.
11
+ * * Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ * * Neither the name of SWITCH nor the names of its contributors may be
15
+ * used to endorse or promote products derived from this software without
16
+ * specific prior written permission.
17
+ *
18
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28
+ * POSSIBILITY OF SUCH DAMAGE.
29
+ *
30
+ * $Author: haag $
31
+ *
32
+ * $Id: nffile.c 41 2009-12-31 14:46:28Z haag $
33
+ *
34
+ * $LastChangedRevision: 41 $
35
+ *
36
+ */
37
+
38
+ #include "config.h"
39
+
40
+ #include <sys/types.h>
41
+ #include <sys/uio.h>
42
+ #include <unistd.h>
43
+ #include <string.h>
44
+ #include <fcntl.h>
45
+ #include <sys/stat.h>
46
+ #include <sys/param.h>
47
+ #include <stdio.h>
48
+ #include <errno.h>
49
+ #include <unistd.h>
50
+ #include <stdlib.h>
51
+
52
+ #ifdef HAVE_STDINT_H
53
+ #include <stdint.h>
54
+ #endif
55
+
56
+ #include "minilzo.h"
57
+ #include "nf_common.h"
58
+ #include "nffile.h"
59
+ #include "util.h"
60
+
61
+ /* global vars */
62
+
63
+ // required for idet filter in nftree.c
64
+ char *CurrentIdent;
65
+
66
+ /* local vars */
67
+ static file_header_t FileHeader;
68
+
69
+ #define READ_FILE 1
70
+ #define WRITE_FILE 1
71
+
72
+ // LZO params
73
+ #define LZO_BUFFSIZE ((BUFFSIZE + BUFFSIZE / 16 + 64 + 3) + sizeof(data_block_header_t))
74
+ #define HEAP_ALLOC(var,size) \
75
+ lzo_align_t __LZO_MMODEL var [ ((size) + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t) ]
76
+
77
+ static HEAP_ALLOC(wrkmem,LZO1X_1_MEM_COMPRESS);
78
+ static void *lzo_buff;
79
+ static int lzo_initialized = 0;
80
+
81
+ #define ERR_SIZE 256
82
+ static char error_string[ERR_SIZE];
83
+
84
+ static int LZO_initialize(void);
85
+
86
+ extern char *nf_error;
87
+
88
+ /* function prototypes */
89
+ static nffile_t *NewFile(void);
90
+
91
+ /* function definitions */
92
+
93
+ void SumStatRecords(stat_record_t *s1, stat_record_t *s2) {
94
+
95
+ s1->numflows += s2->numflows;
96
+ s1->numbytes += s2->numbytes;
97
+ s1->numpackets += s2->numpackets;
98
+ s1->numflows_tcp += s2->numflows_tcp;
99
+ s1->numflows_udp += s2->numflows_udp;
100
+ s1->numflows_icmp += s2->numflows_icmp;
101
+ s1->numflows_other += s2->numflows_other;
102
+ s1->numbytes_tcp += s2->numbytes_tcp;
103
+ s1->numbytes_udp += s2->numbytes_udp;
104
+ s1->numbytes_icmp += s2->numbytes_icmp;
105
+ s1->numbytes_other += s2->numbytes_other;
106
+ s1->numpackets_tcp += s2->numpackets_tcp;
107
+ s1->numpackets_udp += s2->numpackets_udp;
108
+ s1->numpackets_icmp += s2->numpackets_icmp;
109
+ s1->numpackets_other += s2->numpackets_other;
110
+ s1->sequence_failure += s2->sequence_failure;
111
+
112
+ if ( s2->first_seen < s1->first_seen ) {
113
+ s1->first_seen = s2->first_seen;
114
+ s1->msec_first = s2->msec_first;
115
+ }
116
+ if ( s2->first_seen == s1->first_seen &&
117
+ s2->msec_first < s1->msec_first )
118
+ s1->msec_first = s2->msec_first;
119
+
120
+ if ( s2->last_seen > s1->last_seen ) {
121
+ s1->last_seen = s2->last_seen;
122
+ s1->msec_last = s2->msec_last;
123
+ }
124
+ if ( s2->last_seen == s1->last_seen &&
125
+ s2->msec_last > s1->msec_last )
126
+ s1->msec_last = s2->msec_last;
127
+
128
+ } // End of SumStatRecords
129
+
130
+
131
+ static int LZO_initialize(void) {
132
+
133
+ if (lzo_init() != LZO_E_OK) {
134
+ // this usually indicates a compiler bug - try recompiling
135
+ // without optimizations, and enable `-DLZO_DEBUG' for diagnostics
136
+ LogError("Compression lzo_init() failed.\n");
137
+ return 0;
138
+ }
139
+ lzo_buff = malloc(BUFFSIZE+ sizeof(data_block_header_t));
140
+ if ( !lzo_buff ) {
141
+ LogError("malloc() error in %s line %d: %s\n", __FILE__, __LINE__, strerror(errno) );
142
+ return 0;
143
+ }
144
+ lzo_initialized = 1;
145
+
146
+ return 1;
147
+
148
+ } // End of LZO_initialize
149
+
150
+
151
+ nffile_t *OpenFile(char *filename, nffile_t *nffile){
152
+ struct stat stat_buf;
153
+ int ret, allocated;
154
+
155
+ if ( !nffile ) {
156
+ nffile = NewFile();
157
+ if ( nffile == NULL ) {
158
+ return NULL;
159
+ }
160
+ allocated = 1;
161
+ } else
162
+ allocated = 0;
163
+
164
+
165
+ if ( filename == NULL ) {
166
+ // stdin
167
+ // Zero Stat
168
+ nffile->fd = STDIN_FILENO;
169
+ } else {
170
+ // regular file
171
+ if ( stat(filename, &stat_buf) ) {
172
+ LogError("Can't stat '%s': %s\n", filename, strerror(errno));
173
+ if ( allocated ) {
174
+ DisposeFile(nffile);
175
+ return NULL;
176
+ }
177
+ }
178
+
179
+ if (!S_ISREG(stat_buf.st_mode) ) {
180
+ LogError("'%s' is not a file\n", filename);
181
+ if ( allocated ) {
182
+ DisposeFile(nffile);
183
+ return NULL;
184
+ }
185
+ }
186
+
187
+ // printf("Statfile %s\n",filename);
188
+ nffile->fd = open(filename, O_RDONLY);
189
+ if ( nffile->fd < 0 ) {
190
+ LogError("Error open file: %s\n", strerror(errno));
191
+ if ( allocated ) {
192
+ DisposeFile(nffile);
193
+ return NULL;
194
+ }
195
+ }
196
+
197
+ }
198
+
199
+ ret = read(nffile->fd, (void *)nffile->file_header, sizeof(file_header_t));
200
+ if ( nffile->file_header->magic != MAGIC ) {
201
+ LogError("Open file '%s': bad magic: 0x%X\n", filename ? filename : "<stdin>", FileHeader.magic );
202
+ CloseFile(nffile);
203
+ if ( allocated ) {
204
+ DisposeFile(nffile);
205
+ return NULL;
206
+ }
207
+ }
208
+
209
+ if ( nffile->file_header->version != LAYOUT_VERSION_1 ) {
210
+ LogError("Open file %s: bad version: %u\n", filename, FileHeader.version );
211
+ CloseFile(nffile);
212
+ if ( allocated ) {
213
+ DisposeFile(nffile);
214
+ return NULL;
215
+ }
216
+ }
217
+
218
+ ret = read(nffile->fd, (void *)nffile->stat_record, sizeof(stat_record_t));
219
+ if ( ret < 0 ) {
220
+ LogError("read() error in %s line %d: %s\n", __FILE__, __LINE__, strerror(errno) );
221
+ CloseFile(nffile);
222
+ if ( allocated ) {
223
+ DisposeFile(nffile);
224
+ return NULL;
225
+ }
226
+ }
227
+
228
+ CurrentIdent = nffile->file_header->ident;
229
+
230
+ if ( FILE_IS_COMPRESSED(nffile) && !lzo_initialized && !LZO_initialize() ) {
231
+ if ( allocated ) {
232
+ DisposeFile(nffile);
233
+ return NULL;
234
+ }
235
+ }
236
+
237
+ return nffile;
238
+
239
+ } // End of OpenFile
240
+
241
+ void CloseFile(nffile_t *nffile){
242
+
243
+ if ( !nffile )
244
+ return;
245
+
246
+ // do not close stdout
247
+ if ( nffile->fd )
248
+ close(nffile->fd);
249
+
250
+ } // End of CloseFile
251
+
252
+ int ChangeIdent(char *filename, char *Ident) {
253
+ struct stat stat_buf;
254
+ int fd, ret;
255
+
256
+ if ( filename == NULL )
257
+ return 0;
258
+
259
+ if ( stat(filename, &stat_buf) ) {
260
+ LogError("Can't stat '%s': %s\n", filename, strerror(errno));
261
+ return -1;
262
+ }
263
+
264
+ if (!S_ISREG(stat_buf.st_mode) ) {
265
+ LogError("'%s' is not a file\n", filename);
266
+ return -1;
267
+ }
268
+
269
+ fd = open(filename, O_RDWR);
270
+ if ( fd < 0 ) {
271
+ LogError("Error open file: %s\n", strerror(errno));
272
+ return fd;
273
+ }
274
+
275
+ ret = read(fd, (void *)&FileHeader, sizeof(FileHeader));
276
+ if ( FileHeader.magic != MAGIC ) {
277
+ LogError("Open file '%s': bad magic: 0x%X\n", filename, FileHeader.magic );
278
+ close(fd);
279
+ return -1;
280
+ }
281
+ if ( FileHeader.version != LAYOUT_VERSION_1 ) {
282
+ LogError("Open file %s: bad version: %u\n", filename, FileHeader.version );
283
+ close(fd);
284
+ return -1;
285
+ }
286
+
287
+ strncpy(FileHeader.ident, Ident, IDENTLEN);
288
+ FileHeader.ident[IDENTLEN - 1] = 0;
289
+
290
+ if ( lseek(fd, 0, SEEK_SET) < 0 ) {
291
+ LogError("lseek() error in %s line %d: %s\n", __FILE__, __LINE__, strerror(errno) );
292
+ close(fd);
293
+ return -1;
294
+ }
295
+
296
+ if ( write(fd, (void *)&FileHeader, sizeof(file_header_t)) <= 0 ) {
297
+ LogError("write() error in %s line %d: %s\n", __FILE__, __LINE__, strerror(errno) );
298
+ }
299
+
300
+ if ( close(fd) < 0 ) {
301
+ LogError("close() error in %s line %d: %s\n", __FILE__, __LINE__, strerror(errno) );
302
+ return -1;
303
+ }
304
+
305
+ return 0;
306
+
307
+ } // End of ChangeIdent
308
+
309
+
310
+ void PrintStat(stat_record_t *s) {
311
+
312
+ if ( s == NULL )
313
+ return;
314
+
315
+ // format info: make compiler happy with conversion to (unsigned long long),
316
+ // which does not change the size of the parameter
317
+ printf("Ident: %s\n", FileHeader.ident);
318
+ printf("Flows: %llu\n", (unsigned long long)s->numflows);
319
+ printf("Flows_tcp: %llu\n", (unsigned long long)s->numflows_tcp);
320
+ printf("Flows_udp: %llu\n", (unsigned long long)s->numflows_udp);
321
+ printf("Flows_icmp: %llu\n", (unsigned long long)s->numflows_icmp);
322
+ printf("Flows_other: %llu\n", (unsigned long long)s->numflows_other);
323
+ printf("Packets: %llu\n", (unsigned long long)s->numpackets);
324
+ printf("Packets_tcp: %llu\n", (unsigned long long)s->numpackets_tcp);
325
+ printf("Packets_udp: %llu\n", (unsigned long long)s->numpackets_udp);
326
+ printf("Packets_icmp: %llu\n", (unsigned long long)s->numpackets_icmp);
327
+ printf("Packets_other: %llu\n", (unsigned long long)s->numpackets_other);
328
+ printf("Bytes: %llu\n", (unsigned long long)s->numbytes);
329
+ printf("Bytes_tcp: %llu\n", (unsigned long long)s->numbytes_tcp);
330
+ printf("Bytes_udp: %llu\n", (unsigned long long)s->numbytes_udp);
331
+ printf("Bytes_icmp: %llu\n", (unsigned long long)s->numbytes_icmp);
332
+ printf("Bytes_other: %llu\n", (unsigned long long)s->numbytes_other);
333
+ printf("First: %u\n", s->first_seen);
334
+ printf("Last: %u\n", s->last_seen);
335
+ printf("msec_first: %u\n", s->msec_first);
336
+ printf("msec_last: %u\n", s->msec_last);
337
+ printf("Sequence failures: %u\n", s->sequence_failure);
338
+ } // End of PrintStat
339
+
340
+ static nffile_t *NewFile(void) {
341
+ nffile_t *nffile;
342
+
343
+ // Create struct
344
+ nffile = calloc(1, sizeof(nffile_t));
345
+ if ( !nffile ) {
346
+ LogError("malloc() error in %s line %d: %s\n", __FILE__, __LINE__, strerror(errno) );
347
+ return NULL;
348
+ }
349
+ nffile->buff_ptr = NULL;
350
+ nffile->fd = 0;
351
+
352
+ // Init file header
353
+ nffile->file_header = calloc(1, sizeof(file_header_t));
354
+ if ( !nffile->file_header ) {
355
+ LogError("malloc() error in %s line %d: %s\n", __FILE__, __LINE__, strerror(errno) );
356
+ return NULL;
357
+ }
358
+ nffile->file_header->magic = MAGIC;
359
+ nffile->file_header->version = LAYOUT_VERSION_1;
360
+ nffile->file_header->flags = 0;
361
+ nffile->file_header->NumBlocks = 0;
362
+
363
+ nffile->stat_record = calloc(1, sizeof(stat_record_t));
364
+ if ( !nffile->stat_record ) {
365
+ LogError("malloc() error in %s line %d: %s\n", __FILE__, __LINE__, strerror(errno) );
366
+ return NULL;
367
+ }
368
+
369
+ // init data buffer
370
+ nffile->block_header = malloc(BUFFSIZE + sizeof(data_block_header_t));
371
+ if ( !nffile->block_header ) {
372
+ LogError("malloc() error in %s line %d: %s\n", __FILE__, __LINE__, strerror(errno) );
373
+ return NULL;
374
+ }
375
+ nffile->block_header->size = 0;
376
+ nffile->block_header->NumRecords = 0;
377
+ nffile->block_header->id = DATA_BLOCK_TYPE_2;
378
+ nffile->block_header->pad = 0;
379
+
380
+ nffile->buff_ptr = (void *)((pointer_addr_t)nffile->block_header + sizeof(data_block_header_t));
381
+
382
+ return nffile;
383
+
384
+ } // End of NewFile
385
+
386
+ nffile_t *DisposeFile(nffile_t *nffile) {
387
+ free(nffile->file_header);
388
+ free(nffile->stat_record);
389
+ if (nffile->block_header)
390
+ free(nffile->block_header);
391
+ free(nffile);
392
+ return NULL;
393
+ } // End of DisposeFile
394
+
395
+ nffile_t *OpenNewFile(char *filename, nffile_t *nffile, int compressed, int anonymized, char *ident) {
396
+ size_t len;
397
+ int flags;
398
+
399
+ // Allocate new struct if not given
400
+ if ( nffile == NULL ) {
401
+ nffile = NewFile();
402
+ if ( nffile == NULL ) {
403
+ return NULL;
404
+ }
405
+ }
406
+
407
+ flags = compressed ? FLAG_COMPRESSED : 0;
408
+ if ( anonymized )
409
+ SetFlag(flags, FLAG_ANONYMIZED);
410
+
411
+ nffile->file_header->flags = flags;
412
+
413
+ if ( strcmp(filename, "-") == 0 ) { // output to stdout
414
+ nffile->fd = STDOUT_FILENO;
415
+ } else {
416
+ nffile->fd = open(filename, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH );
417
+ if ( nffile->fd < 0 ) {
418
+ LogError("Failed to open file %s: '%s'" , filename, strerror(errno));
419
+ return NULL;
420
+ }
421
+ }
422
+
423
+ memset((void *)nffile->stat_record, 0, sizeof(stat_record_t));
424
+ nffile->stat_record->first_seen = 0x7fffffff;
425
+ nffile->stat_record->msec_first = 999;
426
+
427
+ if ( ident ) {
428
+ strncpy(nffile->file_header->ident, ident, IDENTLEN);
429
+ nffile->file_header->ident[IDENTLEN - 1] = 0;
430
+ }
431
+
432
+
433
+ if ( TestFlag(flags, FLAG_COMPRESSED) ) {
434
+ if ( !lzo_initialized && !LZO_initialize() ) {
435
+ LogError("Failed to initialize compression");
436
+ close(nffile->fd);
437
+ return NULL;
438
+ }
439
+ }
440
+
441
+ nffile->file_header->NumBlocks = 0;
442
+ len = sizeof(file_header_t);
443
+ if ( write(nffile->fd, (void *)nffile->file_header, len) < len ) {
444
+ LogError("write() error in %s line %d: %s\n", __FILE__, __LINE__, strerror(errno) );
445
+ close(nffile->fd);
446
+ return NULL;
447
+ }
448
+
449
+ // write empty stat record - ist updated when file gets closed
450
+ len = sizeof(stat_record_t);
451
+ if ( write(nffile->fd, (void *)nffile->stat_record, len) < len ) {
452
+ LogError("write() error in %s line %d: %s\n", __FILE__, __LINE__, strerror(errno) );
453
+ close(nffile->fd);
454
+ return NULL;
455
+ }
456
+
457
+ return nffile;
458
+
459
+ } /* End of OpenNewFile */
460
+
461
+ nffile_t *AppendFile(char *filename) {
462
+ nffile_t *nffile;
463
+
464
+ // try to open the existing file
465
+ nffile = OpenFile(filename, NULL);
466
+ if ( !nffile )
467
+ return NULL;
468
+
469
+ // file is valid - re-open the file mode RDWR
470
+ close(nffile->fd);
471
+ nffile->fd = open(filename, O_RDWR | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH );
472
+ if ( nffile->fd < 0 ) {
473
+ LogError("Failed to open file %s: '%s'" , filename, strerror(errno));
474
+ DisposeFile(nffile);
475
+ return NULL;
476
+ }
477
+
478
+ // init output data buffer
479
+ nffile->block_header = malloc(BUFFSIZE + sizeof(data_block_header_t));
480
+ if ( !nffile->block_header ) {
481
+ LogError("malloc() error in %s line %d: %s\n", __FILE__, __LINE__, strerror(errno) );
482
+ close(nffile->fd);
483
+ DisposeFile(nffile);
484
+ return NULL;
485
+ }
486
+ nffile->block_header->size = 0;
487
+ nffile->block_header->NumRecords = 0;
488
+ nffile->block_header->id = DATA_BLOCK_TYPE_2;
489
+ nffile->block_header->pad = 0;
490
+ nffile->buff_ptr = (void *)((pointer_addr_t)nffile->block_header + sizeof(data_block_header_t));
491
+
492
+ // initialize output lzo buffer
493
+ if ( FILE_IS_COMPRESSED(nffile) ) {
494
+ if ( !lzo_initialized && !LZO_initialize() ) {
495
+ LogError("Failed to initialize compression");
496
+ close(nffile->fd);
497
+ DisposeFile(nffile);
498
+ return NULL;
499
+ }
500
+ }
501
+
502
+ return nffile;
503
+
504
+ } /* End of AppendFile */
505
+
506
+ int CloseUpdateFile(nffile_t *nffile, char *ident) {
507
+ file_header_t file_header;
508
+
509
+ if ( nffile->block_header->size ) {
510
+ int ret = WriteBlock(nffile);
511
+ if ( ret < 0 ) {
512
+ LogError("Failed to flush output buffer");
513
+ return 0;
514
+ }
515
+ }
516
+
517
+ if ( lseek(nffile->fd, 0, SEEK_SET) < 0 ) {
518
+ // lseek on stdout works if output redirected:
519
+ // e.g. -w - > outfile
520
+ // but fails on pipe e.g. -w - | ./nfdump ....
521
+ if ( nffile->fd == STDOUT_FILENO ) {
522
+ return 1;
523
+ } else {
524
+ LogError("lseek() error in %s line %d: %s\n", __FILE__, __LINE__, strerror(errno) );
525
+ close(nffile->fd);
526
+ return 0;
527
+ }
528
+ }
529
+
530
+ if ( ident ) {
531
+ strncpy(nffile->file_header->ident, ident, IDENTLEN);
532
+ } else {
533
+ if ( strlen(nffile->file_header->ident) == 0 )
534
+ strncpy(nffile->file_header->ident, IDENTNONE, IDENTLEN);
535
+ }
536
+ file_header.ident[IDENTLEN - 1] = 0;
537
+
538
+ if ( write(nffile->fd, (void *)nffile->file_header, sizeof(file_header_t)) <= 0 ) {
539
+ LogError("write() error in %s line %d: %s\n", __FILE__, __LINE__, strerror(errno) );
540
+ }
541
+ if ( write(nffile->fd, (void *)nffile->stat_record, sizeof(stat_record_t)) <= 0 ) {
542
+ LogError("write() error in %s line %d: %s\n", __FILE__, __LINE__, strerror(errno) );
543
+ }
544
+ if ( close(nffile->fd) < 0 ) {
545
+ LogError("close() error in %s line %d: %s\n", __FILE__, __LINE__, strerror(errno) );
546
+ return 0;
547
+ }
548
+
549
+ nffile->file_header->NumBlocks = 0;
550
+
551
+ return 1;
552
+
553
+ } /* End of CloseUpdateFile */
554
+
555
+ int ReadBlock(nffile_t *nffile) {
556
+ ssize_t ret, read_bytes, buff_bytes, request_size;
557
+ void *read_ptr, *buff;
558
+
559
+ ret = read(nffile->fd, nffile->block_header, sizeof(data_block_header_t));
560
+ if ( ret == 0 ) // EOF
561
+ return NF_EOF;
562
+
563
+ if ( ret == -1 ) // ERROR
564
+ return NF_ERROR;
565
+
566
+ // Check for sane buffer size
567
+ if ( ret != sizeof(data_block_header_t) ) {
568
+ // this is most likely a corrupt file
569
+ LogError("Corrupt data file: Read %i bytes, requested %u\n", ret, sizeof(data_block_header_t));
570
+ return NF_CORRUPT;
571
+ }
572
+
573
+ // block header read successfully
574
+ read_bytes = ret;
575
+
576
+ // Check for sane buffer size
577
+ if ( nffile->block_header->size > BUFFSIZE ) {
578
+ // this is most likely a corrupt file
579
+ LogError("Corrupt data file: Requested buffer size %u exceeds max. buffer size.\n", nffile->block_header->size);
580
+ return NF_CORRUPT;
581
+ }
582
+
583
+ buff = FILE_IS_COMPRESSED(nffile) ? lzo_buff : nffile->buff_ptr;
584
+
585
+ ret = read(nffile->fd, buff, nffile->block_header->size);
586
+ if ( ret == nffile->block_header->size ) {
587
+ lzo_uint new_len;
588
+ // we have the whole record and are done for now
589
+ if ( FILE_IS_COMPRESSED(nffile) ) {
590
+ int r;
591
+ r = lzo1x_decompress(lzo_buff,nffile->block_header->size,nffile->buff_ptr,&new_len,NULL);
592
+ if (r != LZO_E_OK ) {
593
+ /* this should NEVER happen */
594
+ LogError("ReadBlock() error decompression failed in %s line %d: LZO error: %d\n", __FILE__, __LINE__, r);
595
+ return NF_CORRUPT;
596
+ }
597
+ nffile->block_header->size = new_len;
598
+ return read_bytes + new_len;
599
+ } else
600
+ return read_bytes + ret;
601
+ }
602
+
603
+ if ( ret == 0 ) {
604
+ // EOF not expected here - this should never happen, file may be corrupt
605
+ LogError("ReadBlock() Corrupt data file: Unexpected EOF while reading data block.\n");
606
+ return NF_CORRUPT;
607
+ }
608
+
609
+ if ( ret == -1 ) { // ERROR
610
+ LogError("read() error in %s line %d: %s\n", __FILE__, __LINE__, strerror(errno) );
611
+ return NF_ERROR;
612
+ }
613
+
614
+ // Ups! - ret is != block_header->size
615
+ // this was a short read - most likely reading from the stdin pipe
616
+ // loop until we have requested size
617
+
618
+ buff_bytes = ret; // already in buffer
619
+ request_size = nffile->block_header->size - buff_bytes; // still to go for this amount of data
620
+
621
+ read_ptr = (void *)((pointer_addr_t)buff + buff_bytes);
622
+ do {
623
+ ret = read(nffile->fd, read_ptr, request_size);
624
+ if ( ret < 0 )
625
+ // -1: Error - not expected
626
+ LogError("read() error in %s line %d: %s\n", __FILE__, __LINE__, strerror(errno) );
627
+ return NF_ERROR;
628
+
629
+ if ( ret == 0 ) {
630
+ // 0: EOF - not expected
631
+ LogError(error_string, ERR_SIZE, "Corrupt data file: Unexpected EOF. Short read of data block.\n");
632
+ return NF_CORRUPT;
633
+ }
634
+
635
+ buff_bytes += ret;
636
+ request_size = nffile->block_header->size - buff_bytes;
637
+
638
+ if ( request_size > 0 ) {
639
+ // still a short read - continue in read loop
640
+ read_ptr = (void *)((pointer_addr_t)buff + buff_bytes);
641
+ }
642
+ } while ( request_size > 0 );
643
+
644
+ if ( FILE_IS_COMPRESSED(nffile) ) {
645
+ int r;
646
+ lzo_uint new_len;
647
+ r = lzo1x_decompress(lzo_buff, nffile->block_header->size, nffile->buff_ptr, &new_len, NULL);
648
+ if (r != LZO_E_OK ) {
649
+ /* this should NEVER happen */
650
+ LogError("ReadBlock() error decompression failed in %s line %d: LZO error: %d\n", __FILE__, __LINE__, r);
651
+ return NF_CORRUPT;
652
+ }
653
+ nffile->block_header->size = new_len;
654
+ return read_bytes + new_len;
655
+
656
+ } else {
657
+ // finally - we are done for now
658
+ return read_bytes + buff_bytes;
659
+ }
660
+
661
+ /* not reached */
662
+
663
+ } // End of ReadBlock
664
+
665
+ int WriteBlock(nffile_t *nffile) {
666
+ data_block_header_t *out_block_header;
667
+ int r, ret;
668
+ unsigned char __LZO_MMODEL *in;
669
+ unsigned char __LZO_MMODEL *out;
670
+ lzo_uint in_len;
671
+ lzo_uint out_len;
672
+
673
+ // empty blocks need not to be stored
674
+ if ( nffile->block_header->size == 0 )
675
+ return 1;
676
+
677
+ if ( !TestFlag(nffile->file_header->flags, FLAG_COMPRESSED) ) {
678
+ ret = write(nffile->fd, (void *)nffile->block_header, sizeof(data_block_header_t) + nffile->block_header->size);
679
+ if ( ret > 0 ) {
680
+ nffile->block_header->size = 0;
681
+ nffile->block_header->NumRecords = 0;
682
+ nffile->buff_ptr = (void *)((pointer_addr_t)nffile->block_header + sizeof(data_block_header_t) );
683
+ nffile->file_header->NumBlocks++;
684
+ }
685
+ return ret;
686
+ }
687
+
688
+ out_block_header = (data_block_header_t *)lzo_buff;
689
+ *out_block_header = *(nffile->block_header);
690
+
691
+ in = (unsigned char __LZO_MMODEL *)((pointer_addr_t)nffile->block_header + sizeof(data_block_header_t));
692
+ out = (unsigned char __LZO_MMODEL *)((pointer_addr_t)out_block_header + sizeof(data_block_header_t));
693
+ in_len = nffile->block_header->size;
694
+ r = lzo1x_1_compress(in,in_len,out,&out_len,wrkmem);
695
+
696
+ if (r != LZO_E_OK) {
697
+ snprintf(error_string, ERR_SIZE,"compression failed: %d" , r);
698
+ error_string[ERR_SIZE-1] = 0;
699
+ return -2;
700
+ }
701
+
702
+ out_block_header->size = out_len;
703
+ ret = write(nffile->fd, (void *)out_block_header, sizeof(data_block_header_t) + out_block_header->size);
704
+ if ( ret > 0 ) {
705
+ nffile->block_header->size = 0;
706
+ nffile->block_header->NumRecords = 0;
707
+ nffile->buff_ptr = (void *)((pointer_addr_t)nffile->block_header + sizeof(data_block_header_t) );
708
+ nffile->file_header->NumBlocks++;
709
+ }
710
+
711
+ return ret;
712
+
713
+ } // End of WriteBlock
714
+
715
+ int WriteExtraBlock(nffile_t *nffile, data_block_header_t *block_header) {
716
+ data_block_header_t *out_block_header;
717
+ int r, ret;
718
+ unsigned char __LZO_MMODEL *in;
719
+ unsigned char __LZO_MMODEL *out;
720
+ lzo_uint in_len;
721
+ lzo_uint out_len;
722
+
723
+ if ( !TestFlag(nffile->file_header->flags, FLAG_COMPRESSED) ) {
724
+ ret = write(nffile->fd, (void *)block_header, sizeof(data_block_header_t) + block_header->size);
725
+ if ( ret > 0 ) {
726
+ nffile->file_header->NumBlocks++;
727
+ }
728
+ return ret;
729
+ }
730
+
731
+ out_block_header = (data_block_header_t *)lzo_buff;
732
+ *out_block_header = *(block_header);
733
+
734
+ in = (unsigned char __LZO_MMODEL *)((pointer_addr_t)block_header + sizeof(data_block_header_t));
735
+ out = (unsigned char __LZO_MMODEL *)((pointer_addr_t)out_block_header + sizeof(data_block_header_t));
736
+ in_len = block_header->size;
737
+ r = lzo1x_1_compress(in,in_len,out,&out_len,wrkmem);
738
+
739
+ if (r != LZO_E_OK) {
740
+ snprintf(error_string, ERR_SIZE,"compression failed: %d" , r);
741
+ error_string[ERR_SIZE-1] = 0;
742
+ return -2;
743
+ }
744
+
745
+ out_block_header->size = out_len;
746
+ ret = write(nffile->fd, (void *)out_block_header, sizeof(data_block_header_t) + out_block_header->size);
747
+ if ( ret > 0 ) {
748
+ nffile->file_header->NumBlocks++;
749
+ }
750
+
751
+ return ret;
752
+
753
+ } // End of WriteExtraBlock
754
+
755
+
756
+ inline void ExpandRecord_v1(common_record_t *input_record, master_record_t *output_record ) {
757
+ uint32_t *u;
758
+ size_t size;
759
+ void *p = (void *)input_record;
760
+
761
+ // Copy common data block
762
+ size = sizeof(common_record_t) - sizeof(uint8_t[4]);
763
+ memcpy((void *)output_record, p, size);
764
+ p = (void *)input_record->data;
765
+
766
+ if ( (input_record->flags & FLAG_IPV6_ADDR) != 0 ) { // IPv6
767
+ // IPv6
768
+ memcpy((void *)output_record->v6.srcaddr, p, 4 * sizeof(uint64_t));
769
+ p = (void *)((pointer_addr_t)p + 4 * sizeof(uint64_t));
770
+ } else {
771
+ // IPv4
772
+ u = (uint32_t *)p;
773
+ output_record->v6.srcaddr[0] = 0;
774
+ output_record->v6.srcaddr[1] = 0;
775
+ output_record->v4.srcaddr = u[0];
776
+
777
+ output_record->v6.dstaddr[0] = 0;
778
+ output_record->v6.dstaddr[1] = 0;
779
+ output_record->v4.dstaddr = u[1];
780
+ p = (void *)((pointer_addr_t)p + 2 * sizeof(uint32_t));
781
+ }
782
+
783
+ // packet counter
784
+ if ( (input_record->flags & FLAG_PKG_64 ) != 0 ) {
785
+ // 64bit packet counter
786
+ value64_t l, *v = (value64_t *)p;
787
+ l.val.val32[0] = v->val.val32[0];
788
+ l.val.val32[1] = v->val.val32[1];
789
+ output_record->dPkts = l.val.val64;
790
+ p = (void *)((pointer_addr_t)p + sizeof(uint64_t));
791
+ } else {
792
+ // 32bit packet counter
793
+ output_record->dPkts = *((uint32_t *)p);
794
+ p = (void *)((pointer_addr_t)p + sizeof(uint32_t));
795
+ }
796
+
797
+ // byte counter
798
+ if ( (input_record->flags & FLAG_BYTES_64 ) != 0 ) {
799
+ // 64bit byte counter
800
+ value64_t l, *v = (value64_t *)p;
801
+ l.val.val32[0] = v->val.val32[0];
802
+ l.val.val32[1] = v->val.val32[1];
803
+ output_record->dOctets = l.val.val64;
804
+ p = (void *)((pointer_addr_t)p + sizeof(uint64_t));
805
+ } else {
806
+ // 32bit bytes counter
807
+ output_record->dOctets = *((uint32_t *)p);
808
+ p = (void *)((pointer_addr_t)p + sizeof(uint32_t));
809
+ }
810
+
811
+ } // End of ExpandRecord_v1
812
+
813
+ void UnCompressFile(char * filename) {
814
+ int i, flags, compressed, anonymized;
815
+ ssize_t ret;
816
+ nffile_t *nffile_r, *nffile_w;
817
+ stat_record_t *_s;
818
+ char outfile[MAXPATHLEN];
819
+ void *tmp;
820
+
821
+ nffile_r = OpenFile(filename, NULL);
822
+ if ( !nffile_r ) {
823
+ return;
824
+ }
825
+
826
+ // tmp filename for new output file
827
+ snprintf(outfile, MAXPATHLEN, "%s-tmp", filename);
828
+ outfile[MAXPATHLEN-1] = '\0';
829
+
830
+ flags = nffile_r->file_header->flags;
831
+ if ( FILE_IS_COMPRESSED(nffile_r) ) {
832
+ printf("Uncompress file %s ..\n", filename);
833
+ compressed = 0;
834
+ } else {
835
+ printf("Compress file %s .. \n", filename);
836
+ compressed = 1;
837
+ }
838
+ anonymized = IP_ANONYMIZED(nffile_r);
839
+
840
+ // allocate output file
841
+ nffile_w = OpenNewFile(outfile, NULL, compressed, anonymized, NULL);
842
+ if ( !nffile_w ) {
843
+ CloseFile(nffile_r);
844
+ DisposeFile(nffile_r);
845
+ return;
846
+ }
847
+
848
+ // Use same buffer for read/write
849
+ tmp = nffile_r->block_header;
850
+ nffile_r->block_header = nffile_w->block_header;
851
+ nffile_r->buff_ptr = nffile_w->buff_ptr;
852
+
853
+ // swap stat records :)
854
+ _s = nffile_r->stat_record;
855
+ nffile_r->stat_record = nffile_w->stat_record;
856
+ nffile_w->stat_record = _s;
857
+
858
+ for ( i=0; i < nffile_r->file_header->NumBlocks; i++ ) {
859
+ ret = ReadBlock(nffile_r);
860
+ if ( ret < 0 ) {
861
+ LogError("Error while reading data block. Abort.\n");
862
+ nffile_r->block_header = tmp;
863
+ CloseFile(nffile_r);
864
+ DisposeFile(nffile_r);
865
+ CloseFile(nffile_w);
866
+ DisposeFile(nffile_w);
867
+ unlink(outfile);
868
+ return;
869
+ }
870
+ if ( WriteBlock(nffile_w) <= 0 ) {
871
+ LogError("Failed to write output buffer to disk: '%s'" , strerror(errno));
872
+ nffile_r->block_header = tmp;
873
+ CloseFile(nffile_r);
874
+ DisposeFile(nffile_r);
875
+ CloseFile(nffile_w);
876
+ DisposeFile(nffile_w);
877
+ unlink(outfile);
878
+ return;
879
+ }
880
+ }
881
+
882
+ // file processed
883
+ nffile_r->block_header = tmp;
884
+ CloseFile(nffile_r);
885
+
886
+ if ( !CloseUpdateFile(nffile_w, nffile_r->file_header->ident) ) {
887
+ unlink(outfile);
888
+ LogError("Failed to close file: '%s'" , strerror(errno));
889
+ } else {
890
+ unlink(filename);
891
+ rename(outfile, filename);
892
+ }
893
+
894
+ DisposeFile(nffile_r);
895
+ DisposeFile(nffile_w);
896
+
897
+ } // End of UnCompressFile
898
+
899
+ void QueryFile(char *filename) {
900
+ int i;
901
+ nffile_t *nffile;
902
+ uint32_t num_records, type1, type2, type3;
903
+ struct stat stat_buf;
904
+ ssize_t ret;
905
+ off_t fsize;
906
+
907
+ if ( stat(filename, &stat_buf) ) {
908
+ LogError("Can't stat '%s': %s\n", filename, strerror(errno));
909
+ return;
910
+ }
911
+
912
+ nffile = OpenFile(filename, NULL);
913
+ if ( !nffile ) {
914
+ return;
915
+ }
916
+
917
+ num_records = 0;
918
+ // set file size to current position ( file header )
919
+ fsize = lseek(nffile->fd, 0, SEEK_CUR);
920
+ type1 = 0;
921
+ type2 = 0;
922
+ type3 = 0;
923
+ printf("File : %s\n", filename);
924
+ printf("Version : %u - %s\n", nffile->file_header->version, FILE_IS_COMPRESSED(nffile) ? "compressed" : "not compressed");
925
+ printf("Blocks : %u\n", nffile->file_header->NumBlocks);
926
+ for ( i=0; i < nffile->file_header->NumBlocks; i++ ) {
927
+ if ( (fsize + sizeof(data_block_header_t)) > stat_buf.st_size ) {
928
+ LogError("Unexpected read beyond EOF! File corrupted. Abort.\n");
929
+ LogError("Expected %u blocks, counted %i\n", nffile->file_header->NumBlocks, i);
930
+ break;
931
+ }
932
+ ret = read(nffile->fd, (void *)nffile->block_header, sizeof(data_block_header_t));
933
+ if ( ret < 0 ) {
934
+ LogError("Error reading block %i: %s\n", i, strerror(errno));
935
+ break;
936
+ }
937
+
938
+ // Should never happen, as catched already in first check, but test it anyway ..
939
+ if ( ret == 0 ) {
940
+ LogError("Unexpected end of file reached. Expected %u blocks, counted %i\n", nffile->file_header->NumBlocks, i);
941
+ break;
942
+ }
943
+ if ( ret < sizeof(data_block_header_t) ) {
944
+ LogError("Short read: Expected %u bytes, read: %i\n", sizeof(data_block_header_t), ret);
945
+ break;
946
+ }
947
+ fsize += sizeof(data_block_header_t);
948
+
949
+ num_records += nffile->block_header->NumRecords;
950
+ switch ( nffile->block_header->id) {
951
+ case DATA_BLOCK_TYPE_1:
952
+ type1++;
953
+ break;
954
+ case DATA_BLOCK_TYPE_2:
955
+ type2++;
956
+ break;
957
+ case Large_BLOCK_Type:
958
+ type3++;
959
+ break;
960
+ default:
961
+ printf("block %i has unknown type %u\n", i, nffile->block_header->id);
962
+ }
963
+
964
+ if ( (fsize + nffile->block_header->size ) > stat_buf.st_size ) {
965
+ LogError("Expected to seek beyond EOF! File corrupted. Abort.\n");
966
+ break;
967
+ }
968
+ fsize += nffile->block_header->size;
969
+
970
+ ret = lseek(nffile->fd, nffile->block_header->size, SEEK_CUR);
971
+ if ( ret < 0 ) {
972
+ LogError("Error seeking block %i: %s\n", i, strerror(errno));
973
+ break;
974
+ }
975
+ if ( fsize != ret ) {
976
+ LogError("Expected seek: Expected: %u, got: %u\n", fsize, ret);
977
+ break;
978
+ }
979
+ }
980
+
981
+ if ( fsize < stat_buf.st_size ) {
982
+ LogError("Extra data detected after regular blocks: %i bytes\n", stat_buf.st_size-fsize);
983
+ }
984
+
985
+ printf(" Type 1 : %u\n", type1);
986
+ printf(" Type 2 : %u\n", type2);
987
+ printf(" Type 3 : %u\n", type3);
988
+ printf("Records : %u\n", num_records);
989
+
990
+ CloseFile(nffile);
991
+ DisposeFile(nffile);
992
+
993
+ } // End of QueryFile
994
+
995
+ // simple interface to get a statrecord from a file without nffile overhead
996
+ stat_record_t *GetStatRecord(char *filename, stat_record_t *stat_record) {
997
+ file_header_t file_header;
998
+ int fd, ret;
999
+
1000
+ fd = open(filename, O_RDONLY);
1001
+ if ( fd < 0 ) {
1002
+ LogError("open() error in %s line %d: %s\n", __FILE__, __LINE__, strerror(errno) );
1003
+ return NULL;
1004
+ }
1005
+
1006
+ ret = read(fd, (void *)&file_header, sizeof(file_header_t));
1007
+ if ( ret < 0 ) {
1008
+ LogError("read() error in %s line %d: %s\n", __FILE__, __LINE__, strerror(errno) );
1009
+ close(fd);
1010
+ return NULL;
1011
+ }
1012
+
1013
+ if ( file_header.magic != MAGIC ) {
1014
+ LogError("Open file '%s': bad magic: 0x%X\n", filename ? filename : "<stdin>", FileHeader.magic );
1015
+ close(fd);
1016
+ return NULL;
1017
+ }
1018
+
1019
+ if ( file_header.version != LAYOUT_VERSION_1 ) {
1020
+ LogError("Open file %s: bad version: %u\n", filename, FileHeader.version );
1021
+ close(fd);
1022
+ return NULL;
1023
+ }
1024
+
1025
+ ret = read(fd, (void *)stat_record, sizeof(stat_record_t));
1026
+ if ( ret < 0 ) {
1027
+ LogError("read() error in %s line %d: %s\n", __FILE__, __LINE__, strerror(errno) );
1028
+ close(fd);
1029
+ return NULL;
1030
+ }
1031
+
1032
+ close(fd);
1033
+ return stat_record;
1034
+
1035
+ } // End of GetStatRecord
1036
+
1037
+ #ifdef COMPAT15
1038
+ /*
1039
+ * v1 -> v2 record conversion:
1040
+ * A netflow record in v1 block format has the same size as in v2 block format.
1041
+ * Therefore, the conversion rearranges the v1 layout into v2 layout
1042
+ *
1043
+ * old record size = new record size = 36bytes + x, where x is the sum of
1044
+ * IP address block (IPv4 or IPv6) + packet counter + byte counter ( 4/8 bytes)
1045
+ *
1046
+ * v1 v2
1047
+ *
1048
+ * 0 uint32_t flags; uint16_t type;
1049
+ * uint16_t size;
1050
+ *
1051
+ * 1 uint16_t size; uint8_t flags;
1052
+ * uint8_t exporter_ref;
1053
+ * uint16_t exporter_ref; => 0 uint16_t ext_map;
1054
+ *
1055
+ * 2 uint16_t msec_first; uint16_t msec_first;
1056
+ * uint16_t msec_last; uint16_t msec_last;
1057
+ *
1058
+ * 3 uint32_t first; uint32_t first;
1059
+ * 4 uint32_t last; uint32_t last;
1060
+ *
1061
+ * 5 uint8_t dir; uint8_t fwd_status;
1062
+ * uint8_t tcp_flags; uint8_t tcp_flags;
1063
+ * uint8_t prot; uint8_t prot;
1064
+ * uint8_t tos; uint8_t tos;
1065
+ *
1066
+ * 6 uint16_t input; uint16_t srcport;
1067
+ * uint16_t output; uint16_t dstport;
1068
+ *
1069
+ * 7 uint16_t srcport; x bytes IP/pkts/bytes
1070
+ * uint16_t dstport;
1071
+ *
1072
+ * 8 uint16_t srcas;
1073
+ * uint16_t dstas;
1074
+ * uint16_t input;
1075
+ * uint16_t output;
1076
+ *
1077
+ * uint16_t srcas;
1078
+ * 9 x bytes IP/pkts/byte uint16_t dstas;
1079
+ *
1080
+ *
1081
+ */
1082
+
1083
+ void Convert_v1_to_v2(void *mem) {
1084
+ common_record_t *v2 = (common_record_t *)mem;
1085
+ common_record_v1_t *v1 = (common_record_v1_t *)mem;
1086
+ uint32_t *index = (uint32_t *)mem;
1087
+ uint16_t tmp1, tmp2, srcas, dstas, *tmp3;
1088
+ size_t cplen;
1089
+
1090
+ // index 0
1091
+ tmp1 = v1->flags;
1092
+ v2->type = CommonRecordType;
1093
+ v2->size = v1->size;
1094
+
1095
+ // index 1
1096
+ v2->flags = tmp1;
1097
+ v2->exporter_ref = 0;
1098
+ v2->ext_map = 0;
1099
+
1100
+ // index 2, 3, 4 already in sync
1101
+
1102
+ // index 5
1103
+ v2->fwd_status = 0;
1104
+
1105
+ // index 6
1106
+ tmp1 = v1->input;
1107
+ tmp2 = v1->output;
1108
+ v2->srcport = v1->srcport;
1109
+ v2->dstport = v1->dstport;
1110
+
1111
+ // save AS numbers
1112
+ srcas = v1->srcas;
1113
+ dstas = v1->dstas;
1114
+
1115
+ cplen = 0;
1116
+ switch (v2->flags) {
1117
+ case 0:
1118
+ // IPv4 8 byte + 2 x 4 byte counter
1119
+ cplen = 16;
1120
+ break;
1121
+ case 1:
1122
+ // IPv6 32 byte + 2 x 4 byte counter
1123
+ cplen = 40;
1124
+ break;
1125
+ case 2:
1126
+ // IPv4 8 byte + 1 x 4 + 1 x 8 byte counter
1127
+ cplen = 20;
1128
+ break;
1129
+ case 3:
1130
+ // IPv6 32 byte + 1 x 4 + 1 x 8 byte counter
1131
+ cplen = 44;
1132
+ break;
1133
+ case 4:
1134
+ // IPv4 8 byte + 1 x 8 + 1 x 4 byte counter
1135
+ cplen = 20;
1136
+ break;
1137
+ case 5:
1138
+ // IPv6 32 byte + 1 x 8 + 1 x 4 byte counter
1139
+ cplen = 44;
1140
+ break;
1141
+ case 6:
1142
+ // IPv4 8 byte + 2 x 8 byte counter
1143
+ cplen = 24;
1144
+ break;
1145
+ case 7:
1146
+ // IPv6 32 byte + 2 x 8 byte counter
1147
+ cplen = 48;
1148
+ break;
1149
+ default:
1150
+ // this should never happen - catch it anyway
1151
+ cplen = 0;
1152
+ }
1153
+ // copy IP/pkts/bytes block
1154
+ memcpy((void *)&index[7], (void *)&index[9], cplen );
1155
+
1156
+ // hook 16 bit array at the end of copied block
1157
+ tmp3 = (uint16_t *)&index[7+(cplen>>2)];
1158
+ // 2 byte I/O interfaces
1159
+ tmp3[0] = tmp1;
1160
+ tmp3[1] = tmp2;
1161
+ // AS numbers
1162
+ tmp3[2] = srcas;
1163
+ tmp3[3] = dstas;
1164
+
1165
+ } // End of Convert_v1_to_v2
1166
+ #endif
1167
+