Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/dsslib/netflow/flow-tool.c
1810 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 2002-2011 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* *
19
***********************************************************************/
20
#pragma prototyped
21
/*
22
* netflow flowtool type
23
*
24
* Glenn Fowler
25
* AT&T Research
26
*/
27
28
#include "flowlib.h"
29
30
#include <swap.h>
31
32
#define u_int8 Nfbyte_t
33
#define u_int16 Nfshort_t
34
#define u_int32 Nflong_t
35
36
#define FT_MAGIC_1 0xCF
37
#define FT_MAGIC_2 0x10
38
39
#define FT_LE 1
40
#define FT_BE 2
41
42
#define FT_S_VERSION 3
43
44
#define R1(p) ((Rec_1_t*)(p))
45
#define R5(p) ((Rec_5_t*)(p))
46
#define R6(p) ((Rec_6_t*)(p))
47
#define R7(p) ((Rec_7_t*)(p))
48
49
typedef struct ft1header
50
{
51
u_int8 magic1; /* 0xCF */
52
u_int8 magic2; /* 0x10 (cisco flow) */
53
u_int8 byte_order; /* 1 for little endian (VAX) */
54
/* 2 for big endian (Motorolla) */
55
u_int8 s_version; /* flow stream format version 1 or 2 */
56
u_int16 d_version; /* 1 or 5 - stream version 1 */
57
/* 1,5,7,8 - stream version 2 */
58
u_int32 start; /* start time of flow capture */
59
u_int32 end; /* end time of flow capture */
60
u_int32 flags; /* FT_HEADER_FLAG_* */
61
u_int32 rotation; /* rotation schedule */
62
u_int32 nflows; /* # of flows */
63
u_int32 pdu_drops; /* # of dropped pdu's detected */
64
u_int32 pdu_misordered; /* # of detected misordered packets */
65
char hostname[68]; /* 0 terminated name of capture device */
66
char comments[256]; /* 0 terminated ascii comments */
67
} Hdr_t;
68
69
typedef struct fts3rec_v1 {
70
u_int32 unix_secs; /* Current seconds since 0000 UTC 1970 */
71
u_int32 unix_nsecs; /* Residual nanoseconds since 0000 UTC 1970 */
72
u_int32 sysUpTime; /* Current time in millisecs since router booted */
73
u_int32 exaddr; /* Exporter IP address */
74
u_int32 srcaddr; /* Source IP Address */
75
u_int32 dstaddr; /* Destination IP Address */
76
u_int32 nexthop; /* Next hop router's IP Address */
77
u_int16 input; /* Input interface index */
78
u_int16 output; /* Output interface index */
79
u_int32 dPkts; /* Packets sent in Duration */
80
u_int32 dOctets; /* Octets sent in Duration. */
81
u_int32 First; /* SysUptime at start of flow */
82
u_int32 Last; /* and of last packet of flow */
83
u_int16 srcport; /* TCP/UDP source port number or equivalent */
84
u_int16 dstport; /* TCP/UDP destination port number or equiv */
85
u_int8 prot; /* IP protocol, e.g., 6=TCP, 17=UDP, ... */
86
u_int8 tos; /* IP Type-of-Service */
87
u_int8 tcp_flags; /* OR of TCP header bits */
88
u_int8 pad;
89
u_int32 reserved;
90
} Rec_1_t;
91
92
/* note the v5 struct is a subset of v6 and v7. v6 and v7 are assumed
93
* to be in the same order so the engine_* src_mask, dst_mask, src_as and
94
* dst_as are in the same place. v5 is like a generic v5, v6, v7
95
*/
96
typedef struct fts3rec_v5 {
97
u_int32 unix_secs; /* Current seconds since 0000 UTC 1970 */
98
u_int32 unix_nsecs; /* Residual nanoseconds since 0000 UTC 1970 */
99
u_int32 sysUpTime; /* Current time in millisecs since router booted */
100
u_int32 exaddr; /* Exporter IP address */
101
u_int32 srcaddr; /* Source IP Address */
102
u_int32 dstaddr; /* Destination IP Address */
103
u_int32 nexthop; /* Next hop router's IP Address */
104
u_int16 input; /* Input interface index */
105
u_int16 output; /* Output interface index */
106
u_int32 dPkts; /* Packets sent in Duration */
107
u_int32 dOctets; /* Octets sent in Duration. */
108
u_int32 First; /* SysUptime at start of flow */
109
u_int32 Last; /* and of last packet of flow */
110
u_int16 srcport; /* TCP/UDP source port number or equivalent */
111
u_int16 dstport; /* TCP/UDP destination port number or equiv */
112
u_int8 prot; /* IP protocol, e.g., 6=TCP, 17=UDP, ... */
113
u_int8 tos; /* IP Type-of-Service */
114
u_int8 tcp_flags; /* OR of TCP header bits */
115
u_int8 pad;
116
u_int8 engine_type; /* Type of flow switching engine (RP,VIP,etc.) */
117
u_int8 engine_id; /* Slot number of the flow switching engine */
118
u_int8 src_mask; /* mask length of source address */
119
u_int8 dst_mask; /* mask length of destination address */
120
u_int16 src_as; /* AS of source address */
121
u_int16 dst_as; /* AS of destination address */
122
} Rec_5_t;
123
124
typedef struct fts3rec_v6 {
125
u_int32 unix_secs; /* Current seconds since 0000 UTC 1970 */
126
u_int32 unix_nsecs; /* Residual nanoseconds since 0000 UTC 1970 */
127
u_int32 sysUpTime; /* Current time in millisecs since router booted */
128
u_int32 exaddr; /* Exporter IP address */
129
u_int32 srcaddr; /* Source IP Address */
130
u_int32 dstaddr; /* Destination IP Address */
131
u_int32 nexthop; /* Next hop router's IP Address */
132
u_int16 input; /* Input interface index */
133
u_int16 output; /* Output interface index */
134
u_int32 dPkts; /* Packets sent in Duration */
135
u_int32 dOctets; /* Octets sent in Duration. */
136
u_int32 First; /* SysUptime at start of flow */
137
u_int32 Last; /* and of last packet of flow */
138
u_int16 srcport; /* TCP/UDP source port number or equivalent */
139
u_int16 dstport; /* TCP/UDP destination port number or equiv */
140
u_int8 prot; /* IP protocol, e.g., 6=TCP, 17=UDP, ... */
141
u_int8 tos; /* IP Type-of-Service */
142
u_int8 tcp_flags; /* OR of TCP header bits */
143
u_int8 pad;
144
u_int8 engine_type; /* Type of flow switching engine (RP,VIP,etc.) */
145
u_int8 engine_id; /* Slot number of the flow switching engine */
146
u_int8 src_mask; /* mask length of source address */
147
u_int8 dst_mask; /* mask length of destination address */
148
u_int16 src_as; /* AS of source address */
149
u_int16 dst_as; /* AS of destination address */
150
u_int8 in_encaps; /* size in bytes of the input encapsulation */
151
u_int8 out_encaps; /* size in bytes of the output encapsulation */
152
u_int16 pad2;
153
u_int32 peer_nexthop; /* IP address of the next hop within the peer */
154
} Rec_6_t;
155
156
typedef struct fts3rec_v7 {
157
u_int32 unix_secs; /* Current seconds since 0000 UTC 1970 */
158
u_int32 unix_nsecs; /* Residual nanoseconds since 0000 UTC 1970 */
159
u_int32 sysUpTime; /* Current time in millisecs since router booted */
160
u_int32 exaddr; /* Exporter IP address */
161
u_int32 srcaddr; /* Source IP Address */
162
u_int32 dstaddr; /* Destination IP Address */
163
u_int32 nexthop; /* Next hop router's IP Address */
164
u_int16 input; /* Input interface index */
165
u_int16 output; /* Output interface index */
166
u_int32 dPkts; /* Packets sent in Duration */
167
u_int32 dOctets; /* Octets sent in Duration. */
168
u_int32 First; /* SysUptime at start of flow */
169
u_int32 Last; /* and of last packet of flow */
170
u_int16 srcport; /* TCP/UDP source port number or equivalent */
171
u_int16 dstport; /* TCP/UDP destination port number or equiv */
172
u_int8 prot; /* IP protocol, e.g., 6=TCP, 17=UDP, ... */
173
u_int8 tos; /* IP Type-of-Service */
174
u_int8 tcp_flags; /* OR of TCP header bits */
175
u_int8 flags; /* Reason flow discarded, etc */
176
u_int8 engine_type; /* Type of flow switching engine (RP,VIP,etc.) */
177
u_int8 engine_id; /* Slot number of the flow switching engine */
178
u_int8 src_mask; /* mask length of source address */
179
u_int8 dst_mask; /* mask length of destination address */
180
u_int16 src_as; /* AS of source address */
181
u_int16 dst_as; /* AS of destination address */
182
u_int32 router_sc; /* ID of router shortcut by switch */
183
} Rec_7_t;
184
185
typedef struct State_s
186
{
187
Netflow_t record;
188
char* data;
189
char* next;
190
size_t chunk;
191
size_t count;
192
size_t size;
193
int swap;
194
int version;
195
} State_t;
196
197
/*
198
* identf
199
*/
200
201
static int
202
ftident(Dssfile_t* file, void* buf, size_t n, Dssdisc_t* disc)
203
{
204
Hdr_t* h = (Hdr_t*)buf;
205
char* dp;
206
char* ep;
207
int size;
208
int swap;
209
int type;
210
int version;
211
212
if (n < 4)
213
return 0;
214
if (h->magic1 != FT_MAGIC_1 || h->magic2 != FT_MAGIC_2)
215
return 0;
216
switch (h->byte_order)
217
{
218
case FT_BE:
219
swap = 0;
220
break;
221
case FT_LE:
222
swap = 7;
223
break;
224
default:
225
return 0;
226
}
227
switch (h->s_version)
228
{
229
case 1:
230
file->ident = sizeof(Hdr_t);
231
if (n < file->ident)
232
return 0;
233
version = swapget(swap, (char*)buf, 2);
234
break;
235
case 3:
236
if (n < 8)
237
return 0;
238
file->ident = swapget(swap, (char*)buf + 4, 4);
239
if (n < file->ident)
240
return 0;
241
version = 0;
242
dp = (char*)buf + 8;
243
ep = (char*)buf + file->ident;
244
while ((ep - dp) >= 4)
245
{
246
type = swapget(swap, dp, 2);
247
dp += 2;
248
size = swapget(swap, dp, 2);
249
dp += 2;
250
if (size > (ep - dp))
251
break;
252
if (type == 2)
253
{
254
version = swapget(swap, dp, size);
255
break;
256
}
257
dp += size;
258
}
259
break;
260
default:
261
return 0;
262
}
263
switch (version)
264
{
265
case 1:
266
case 5:
267
case 6:
268
case 7:
269
break;
270
default:
271
return 0;
272
}
273
file->ident |= (((swap^int_swap)&3)<<28)|(version<<20);
274
return 1;
275
}
276
277
/*
278
* fopenf
279
*/
280
281
static int
282
ftfopen(Dssfile_t* file, Dssdisc_t* disc)
283
{
284
State_t* state;
285
286
if (!sfreserve(file->io, file->ident & ((1<<20)-1), 0))
287
{
288
if (disc->errorf)
289
(*disc->errorf)(NiL, disc, ERROR_SYSTEM|2, "heaxder read error");
290
return -1;
291
}
292
if (!(state = vmnewof(file->dss->vm, 0, State_t, 1, (file->flags & DSS_FILE_WRITE) ? NETFLOW_PACKET : 0)))
293
{
294
if (disc->errorf)
295
(*disc->errorf)(NiL, disc, ERROR_SYSTEM|2, "out of space");
296
return -1;
297
}
298
file->data = state;
299
state->swap = (file->ident >> 28) & ((1<<4)-1);
300
state->version = (file->ident >> 20) & ((1<<8)-1);
301
switch (state->version)
302
{
303
case 1:
304
state->size = sizeof(Rec_1_t);
305
break;
306
case 5:
307
state->size = sizeof(Rec_5_t);
308
break;
309
case 6:
310
state->size = sizeof(Rec_6_t);
311
break;
312
case 7:
313
state->size = sizeof(Rec_7_t);
314
break;
315
}
316
state->chunk = (1024 * 1024 + state->size - 1) / state->size;
317
if (file->flags & DSS_FILE_WRITE)
318
state->data = (char*)(state + 1);
319
state->record.version = state->version;
320
return 0;
321
}
322
323
/*
324
* freadf
325
*/
326
327
static int
328
ftfread(register Dssfile_t* file, register Dssrecord_t* record, Dssdisc_t* disc)
329
{
330
register State_t* state = (State_t*)file->data;
331
register Netflow_t* rp = &state->record;
332
register char* fp;
333
size_t n;
334
Nftime_t boot;
335
336
while (!state->count--)
337
{
338
if (state->data = (char*)sfreserve(file->io, state->chunk * state->size, 0))
339
{
340
state->count = state->chunk;
341
break;
342
}
343
if (!(n = sfvalue(file->io)))
344
return 0;
345
if (!(state->chunk = n / state->size))
346
{
347
if (disc->errorf)
348
(*disc->errorf)(NiL, disc, 2, "%slast packet incomplete", cxlocation(file->dss->cx, record));
349
return -1;
350
}
351
state->count = 0;
352
}
353
memset(rp, 0, sizeof(*rp));
354
rp->set = NETFLOW_SET_src_addrv4|NETFLOW_SET_dst_addrv4|NETFLOW_SET_hopv4;
355
fp = state->data;
356
state->data += state->size;
357
switch (state->version)
358
{
359
case 1:
360
if (n = state->swap & 3)
361
{
362
swapmem(n, &R1(fp)->unix_secs, &R1(fp)->unix_secs, (char*)&R1(fp)->input - (char*)&R1(fp)->unix_secs);
363
swapmem(n, &R1(fp)->dPkts, &R1(fp)->dPkts, (char*)&R1(fp)->srcport - (char*)&R1(fp)->dPkts);
364
if (n &= 1)
365
{
366
swapmem(n, &R1(fp)->input, &R1(fp)->input, (char*)&R1(fp)->dPkts - (char*)&R1(fp)->input);
367
swapmem(n, &R1(fp)->srcport, &R1(fp)->srcport, (char*)&R1(fp)->prot - (char*)&R1(fp)->srcport);
368
}
369
}
370
rp->src_addrv4 = R1(fp)->srcaddr;
371
rp->dst_addrv4 = R1(fp)->dstaddr;
372
rp->hopv4 = R1(fp)->nexthop;
373
rp->input = R1(fp)->input;
374
rp->output = R1(fp)->output;
375
rp->packets = R1(fp)->dPkts;
376
rp->bytes = R1(fp)->dOctets;
377
rp->first = R1(fp)->First;
378
rp->last = R1(fp)->Last;
379
rp->src_port = R1(fp)->srcport;
380
rp->dst_port = R1(fp)->dstport;
381
rp->flags = 0;
382
rp->tcp_flags = R1(fp)->tcp_flags;
383
rp->protocol = R1(fp)->prot;
384
rp->src_tos = R1(fp)->tos;
385
rp->time = R1(fp)->unix_secs;
386
rp->nsec = R1(fp)->unix_nsecs;
387
rp->uptime = R1(fp)->sysUpTime;
388
break;
389
case 5:
390
if (n = state->swap & 3)
391
{
392
swapmem(n, &R5(fp)->unix_secs, &R5(fp)->unix_secs, (char*)&R5(fp)->input - (char*)&R5(fp)->unix_secs);
393
swapmem(n, &R5(fp)->dPkts, &R5(fp)->dPkts, (char*)&R5(fp)->srcport - (char*)&R5(fp)->dPkts);
394
if (n &= 1)
395
{
396
swapmem(n, &R5(fp)->input, &R5(fp)->input, (char*)&R5(fp)->dPkts - (char*)&R5(fp)->input);
397
swapmem(n, &R5(fp)->srcport, &R5(fp)->srcport, (char*)&R5(fp)->prot - (char*)&R5(fp)->srcport);
398
swapmem(n, &R5(fp)->src_as, &R5(fp)->src_as, (char*)(R5(fp)+1) - (char*)&R5(fp)->src_as);
399
}
400
}
401
rp->src_addrv4 = R5(fp)->srcaddr;
402
rp->dst_addrv4 = R5(fp)->dstaddr;
403
rp->hopv4 = R5(fp)->nexthop;
404
rp->input = R5(fp)->input;
405
rp->output = R5(fp)->output;
406
rp->packets = R5(fp)->dPkts;
407
rp->bytes = R5(fp)->dOctets;
408
rp->first = R5(fp)->First;
409
rp->last = R5(fp)->Last;
410
rp->src_port = R5(fp)->srcport;
411
rp->dst_port = R5(fp)->dstport;
412
rp->flags = 0;
413
rp->tcp_flags = R5(fp)->tcp_flags;
414
rp->protocol = R5(fp)->prot;
415
rp->src_tos = R5(fp)->tos;
416
rp->engine_type = R5(fp)->engine_type;
417
rp->engine_id = R5(fp)->engine_id;
418
rp->src_as16 = R5(fp)->src_as;
419
rp->dst_as16 = R5(fp)->dst_as;
420
rp->src_maskv4 = R5(fp)->src_mask;
421
rp->dst_maskv4 = R5(fp)->dst_mask;
422
rp->time = R5(fp)->unix_secs;
423
rp->nsec = R5(fp)->unix_nsecs;
424
rp->uptime = R5(fp)->sysUpTime;
425
break;
426
case 6:
427
if (n = state->swap & 3)
428
{
429
swapmem(n, &R6(fp)->unix_secs, &R6(fp)->unix_secs, (char*)&R6(fp)->input - (char*)&R6(fp)->unix_secs);
430
swapmem(n, &R6(fp)->dPkts, &R6(fp)->dPkts, (char*)&R6(fp)->srcport - (char*)&R6(fp)->dPkts);
431
if (n &= 1)
432
{
433
swapmem(n, &R6(fp)->input, &R6(fp)->input, (char*)&R6(fp)->dPkts - (char*)&R6(fp)->input);
434
swapmem(n, &R6(fp)->srcport, &R6(fp)->srcport, (char*)&R6(fp)->prot - (char*)&R6(fp)->srcport);
435
swapmem(n, &R6(fp)->src_as, &R6(fp)->src_as, (char*)(R6(fp)+1) - (char*)&R6(fp)->src_as);
436
}
437
}
438
rp->src_addrv4 = R6(fp)->srcaddr;
439
rp->dst_addrv4 = R6(fp)->dstaddr;
440
rp->hopv4 = R6(fp)->nexthop;
441
rp->input = R6(fp)->input;
442
rp->output = R6(fp)->output;
443
rp->packets = R6(fp)->dPkts;
444
rp->bytes = R6(fp)->dOctets;
445
rp->first = R6(fp)->First;
446
rp->last = R6(fp)->Last;
447
rp->src_port = R6(fp)->srcport;
448
rp->dst_port = R6(fp)->dstport;
449
rp->flags = 0;
450
rp->tcp_flags = R6(fp)->tcp_flags;
451
rp->protocol = R6(fp)->prot;
452
rp->src_tos = R6(fp)->tos;
453
rp->engine_type = R6(fp)->engine_type;
454
rp->engine_id = R6(fp)->engine_id;
455
rp->src_as16 = R6(fp)->src_as;
456
rp->dst_as16 = R6(fp)->dst_as;
457
rp->src_maskv4 = R6(fp)->src_mask;
458
rp->dst_maskv4 = R6(fp)->dst_mask;
459
rp->time = R6(fp)->unix_secs;
460
rp->nsec = R6(fp)->unix_nsecs;
461
rp->uptime = R6(fp)->sysUpTime;
462
break;
463
case 7:
464
if (n = state->swap & 3)
465
{
466
swapmem(n, &R7(fp)->unix_secs, &R7(fp)->unix_secs, (char*)&R7(fp)->input - (char*)&R7(fp)->unix_secs);
467
swapmem(n, &R7(fp)->dPkts, &R7(fp)->dPkts, (char*)&R7(fp)->srcport - (char*)&R7(fp)->dPkts);
468
if (n &= 1)
469
{
470
swapmem(n, &R7(fp)->input, &R7(fp)->input, (char*)&R7(fp)->dPkts - (char*)&R7(fp)->input);
471
swapmem(n, &R7(fp)->srcport, &R7(fp)->srcport, (char*)&R7(fp)->prot - (char*)&R7(fp)->srcport);
472
swapmem(n, &R7(fp)->src_as, &R7(fp)->src_as, (char*)(R7(fp)+1) - (char*)&R7(fp)->src_as);
473
}
474
}
475
rp->src_addrv4 = R7(fp)->srcaddr;
476
rp->dst_addrv4 = R7(fp)->dstaddr;
477
rp->hopv4 = R7(fp)->nexthop;
478
rp->input = R7(fp)->input;
479
rp->output = R7(fp)->output;
480
rp->packets = R7(fp)->dPkts;
481
rp->bytes = R7(fp)->dOctets;
482
rp->first = R7(fp)->First;
483
rp->last = R7(fp)->Last;
484
rp->src_port = R7(fp)->srcport;
485
rp->dst_port = R7(fp)->dstport;
486
rp->flags = 0;
487
rp->tcp_flags = R7(fp)->tcp_flags;
488
rp->protocol = R7(fp)->prot;
489
rp->src_tos = R7(fp)->tos;
490
rp->engine_type = R7(fp)->engine_type;
491
rp->engine_id = R7(fp)->engine_id;
492
rp->src_as16 = R7(fp)->src_as;
493
rp->dst_as16 = R7(fp)->dst_as;
494
rp->src_maskv4 = R7(fp)->src_mask;
495
rp->dst_maskv4 = R7(fp)->dst_mask;
496
rp->time = R7(fp)->unix_secs;
497
rp->nsec = R7(fp)->unix_nsecs;
498
rp->uptime = R7(fp)->sysUpTime;
499
break;
500
}
501
boot = ((Nftime_t)rp->time * MS - (Nftime_t)rp->uptime) * US + (Nftime_t)rp->nsec;
502
rp->start = boot + (Nftime_t)rp->first * US;
503
rp->end = boot + (Nftime_t)rp->last * US;
504
record->size = sizeof(*rp);
505
record->data = rp;
506
return 1;
507
}
508
509
/*
510
* fwritef
511
*/
512
513
static int
514
ftfwrite(Dssfile_t* file, Dssrecord_t* record, Dssdisc_t* disc)
515
{
516
register State_t* state = (State_t*)file->data;
517
register Netflow_t* rp = (Netflow_t*)record->data;
518
519
if (disc->errorf)
520
(*disc->errorf)(NiL, disc, 1, "%s: write not implemented", file->format->name);
521
return -1;
522
}
523
524
/*
525
* fclosef
526
*/
527
528
static int
529
ftfclose(Dssfile_t* file, Dssdisc_t* disc)
530
{
531
register State_t* state = (State_t*)file->data;
532
533
if (!state)
534
return -1;
535
vmfree(file->dss->vm, state);
536
return 0;
537
}
538
539
Dssformat_t netflow_tool_format =
540
{
541
"flowtool",
542
"flowtool netflow format (2008-06-21)",
543
CXH,
544
ftident,
545
ftfopen,
546
ftfread,
547
ftfwrite,
548
0,
549
ftfclose,
550
0,
551
0,
552
netflow_tool_next
553
};
554
555