Vflow 1.0.3
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.
- data/README +95 -0
- data/Rakefile +72 -0
- data/ext/Vflow.c +522 -0
- data/ext/extconf.rb +38 -0
- data/tests/vfprofile.rb +32 -0
- data/tests/vftest.rb +73 -0
- metadata +63 -0
data/README
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
$Id: README,v 1.5 2004/12/13 11:13:18 jeffm Exp $
|
2
|
+
|
3
|
+
vflow is an attempt at a ruby replacement for the perl Cflow or python pyflowtool
|
4
|
+
modules. This is beta and should be safe for limited use it passes testing by the
|
5
|
+
vftest.rb script.
|
6
|
+
|
7
|
+
Installation
|
8
|
+
============
|
9
|
+
To install do the following, when installing from gem,
|
10
|
+
|
11
|
+
gem install vflow
|
12
|
+
|
13
|
+
If installing manually from tar.gz file,
|
14
|
+
|
15
|
+
cd ext
|
16
|
+
ruby extconf.rb
|
17
|
+
make
|
18
|
+
make install
|
19
|
+
|
20
|
+
If your flow-tools headers and libraries are not in a common path you can use
|
21
|
+
|
22
|
+
--with-ft-include-dir=<include file directory>
|
23
|
+
and
|
24
|
+
--with-ft-lib-dir=<library directory>
|
25
|
+
|
26
|
+
as arguments to extconf.rb to specify the paths.
|
27
|
+
|
28
|
+
vftest.rb prints flow data from testdata/dummy_flow file
|
29
|
+
vfprofile.rb profiles vflow processing the dummy_flow file
|
30
|
+
|
31
|
+
The following methods are defined as part of vflow
|
32
|
+
new()
|
33
|
+
Creates and returns a vflow object
|
34
|
+
open(filename)
|
35
|
+
Open file of filename which has been created by flow-tools for reading.
|
36
|
+
If a block is given, the file will be automatically closed at the end of the block
|
37
|
+
close()
|
38
|
+
Close the current file
|
39
|
+
currentfile()
|
40
|
+
return the name of the current file being read from.
|
41
|
+
next()
|
42
|
+
Returns a vflowrec object containing the values of the next entry in the file.
|
43
|
+
each()
|
44
|
+
This loops over all entries from the current position calling the associated
|
45
|
+
block. See the example below.
|
46
|
+
|
47
|
+
Example 1
|
48
|
+
=========
|
49
|
+
require 'Vflow'
|
50
|
+
vf = Vflow.new()
|
51
|
+
vf.open('aflowfile')
|
52
|
+
vf.each() { |r|
|
53
|
+
# do something
|
54
|
+
}
|
55
|
+
vf.close()
|
56
|
+
|
57
|
+
Example 2
|
58
|
+
=========
|
59
|
+
require 'Vflow'
|
60
|
+
vf = Vflow.new()
|
61
|
+
vf.open('aflowfile') {
|
62
|
+
vf.each { |r|
|
63
|
+
#do something
|
64
|
+
}
|
65
|
+
}
|
66
|
+
|
67
|
+
To Do
|
68
|
+
=====
|
69
|
+
modify open() to take an array of filenames and automatically interate from
|
70
|
+
the end of one to the start of annother.
|
71
|
+
modify open() to take directory names and iterate over each file in the given
|
72
|
+
a directory.
|
73
|
+
add method to extract header info
|
74
|
+
add method to get flow version
|
75
|
+
|
76
|
+
|
77
|
+
Changes
|
78
|
+
=======
|
79
|
+
0.3a
|
80
|
+
Patched Vflow.c so #open will take blocks (jeffw@globaldial.com)
|
81
|
+
Altered extconf.rb to use arbitrary paths for ft-lib (jeffw@globaldial.com)
|
82
|
+
Altered extconf.rb to give errors on missing libraries (jeffw@globaldial.com)
|
83
|
+
Altered extconf.rb to use flow-tools from path /usr/local/netflow automatically.
|
84
|
+
Created vflow.gemspec and gem file.
|
85
|
+
|
86
|
+
Thanks
|
87
|
+
======
|
88
|
+
Thanks go to the following people,
|
89
|
+
|
90
|
+
jpietsch@amazon.com for complaining about it not working. So I know at least one other person is using
|
91
|
+
this library ;-).
|
92
|
+
|
93
|
+
jeffw@globaldial.com for his patch so #open could use blocks and altering extconf.rb to give error
|
94
|
+
messages and work with the flow-tools library and includes not being in the library path.
|
95
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'rake/gempackagetask'
|
2
|
+
#require 'rake/contrib/rubyforgepublisher'
|
3
|
+
require 'rake/clean'
|
4
|
+
require 'rake/rdoctask'
|
5
|
+
require "benchmark"
|
6
|
+
|
7
|
+
PKG_NAME = "Vflow"
|
8
|
+
PKG_VERSION = "1.0.3"
|
9
|
+
PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
|
10
|
+
PKG_FILES = FileList[
|
11
|
+
'[A-Z]*',
|
12
|
+
'lib/**/*.rb',
|
13
|
+
'spec/**/*.rb',
|
14
|
+
'tests/*.rb',
|
15
|
+
'ext/*.c',
|
16
|
+
'ext/*.h',
|
17
|
+
'ext/*.rb'
|
18
|
+
]
|
19
|
+
CLEAN.include(
|
20
|
+
"ext/*.o",
|
21
|
+
"ext/*.bundle",
|
22
|
+
"ext/*.so"
|
23
|
+
)
|
24
|
+
CLOBBER.include(
|
25
|
+
"doc/coverage"
|
26
|
+
)
|
27
|
+
|
28
|
+
task :default => [:compile]
|
29
|
+
|
30
|
+
desc 'Generate RDoc'
|
31
|
+
rd = Rake::RDocTask.new do |rdoc|
|
32
|
+
rdoc.rdoc_dir = 'doc/rdoc'
|
33
|
+
rdoc.options << '--title' << 'bcrypt-ruby' << '--line-numbers' << '--inline-source' << '--main' << 'README'
|
34
|
+
rdoc.template = ENV['TEMPLATE'] if ENV['TEMPLATE']
|
35
|
+
rdoc.rdoc_files.include('README')
|
36
|
+
end
|
37
|
+
|
38
|
+
spec = Gem::Specification.new do |s|
|
39
|
+
s.name = PKG_NAME
|
40
|
+
s.version = PKG_VERSION
|
41
|
+
s.summary = "Flowtools binding"
|
42
|
+
s.description = <<-EOF
|
43
|
+
Ruby bindings for VFlow
|
44
|
+
EOF
|
45
|
+
|
46
|
+
s.files = PKG_FILES.to_a
|
47
|
+
s.require_path = 'lib'
|
48
|
+
|
49
|
+
s.has_rdoc = true
|
50
|
+
s.rdoc_options = rd.options
|
51
|
+
s.extra_rdoc_files = rd.rdoc_files.to_a
|
52
|
+
|
53
|
+
s.extensions = FileList["ext/extconf.rb"].to_a
|
54
|
+
|
55
|
+
s.authors = ["HZ, gem packed by Antti"]
|
56
|
+
s.email = "hz@hz.com"
|
57
|
+
s.homepage = "http://rubyforge.org"
|
58
|
+
end
|
59
|
+
|
60
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
61
|
+
pkg.need_zip = true
|
62
|
+
pkg.need_tar = true
|
63
|
+
end
|
64
|
+
|
65
|
+
desc "Clean, then compile the extension."
|
66
|
+
task :compile => [:clean] do
|
67
|
+
Dir.chdir('./ext')
|
68
|
+
sh "ruby extconf.rb"
|
69
|
+
sh "make"
|
70
|
+
Dir.chdir('..')
|
71
|
+
end
|
72
|
+
|
data/ext/Vflow.c
ADDED
@@ -0,0 +1,522 @@
|
|
1
|
+
/*
|
2
|
+
* $Id: Vflow.c,v 1.5 2004/12/13 11:13:18 jeffm Exp $
|
3
|
+
*
|
4
|
+
* Example script,
|
5
|
+
* vf = vflow.new()
|
6
|
+
* vf.open(afile)
|
7
|
+
* vf.find() { |r|
|
8
|
+
* # do something with entry.
|
9
|
+
* }
|
10
|
+
* vf.close()
|
11
|
+
*
|
12
|
+
*
|
13
|
+
*/
|
14
|
+
#include "ruby.h"
|
15
|
+
#include <sys/types.h>
|
16
|
+
#include <fcntl.h>
|
17
|
+
#include <sys/stat.h>
|
18
|
+
#include <ftconfig.h>
|
19
|
+
#include <ftlib.h>
|
20
|
+
#include <strings.h>
|
21
|
+
|
22
|
+
typedef struct vf_data_struct {
|
23
|
+
char *current_file;
|
24
|
+
int fd;
|
25
|
+
struct ftio ftio_data;
|
26
|
+
struct ftver ftv;
|
27
|
+
struct fts3rec_offsets ftoffsets;
|
28
|
+
} vf_type;
|
29
|
+
|
30
|
+
static VALUE vf_info_free(void *p) {
|
31
|
+
xfree(((vf_type *)p)->current_file);
|
32
|
+
xfree(p);
|
33
|
+
}
|
34
|
+
|
35
|
+
/* Mapping acsii string to values.
|
36
|
+
* Should have been able to use
|
37
|
+
* struct ftxfield_table ftxfield_table[]
|
38
|
+
* from flow-tools lib/ftxfield.c but this is not
|
39
|
+
* in the same order as
|
40
|
+
* struct fts3rec_offsets
|
41
|
+
* in flow-tool's ftlib.h which make calculation
|
42
|
+
* for converstions difficult see
|
43
|
+
* vfr_init() and vfr_fts3rec_to_vfrec below
|
44
|
+
*/
|
45
|
+
struct vfr_mapfields {
|
46
|
+
char *name;
|
47
|
+
u_int64 val;
|
48
|
+
VALUE (*getter)();
|
49
|
+
VALUE (*setter)();
|
50
|
+
};
|
51
|
+
|
52
|
+
// needed by libft.a
|
53
|
+
int debug = 0;
|
54
|
+
|
55
|
+
// Are these type identifiers?
|
56
|
+
VALUE vflow;
|
57
|
+
VALUE vflowrec;
|
58
|
+
|
59
|
+
/********* vflowrec ************
|
60
|
+
* vflowrec is a pure ruby object to hold
|
61
|
+
* the infomation normally held by
|
62
|
+
* struct fts3rec_all in flow-tools
|
63
|
+
*/
|
64
|
+
|
65
|
+
/* private function to create a vfrec
|
66
|
+
* input:
|
67
|
+
* struct ftio
|
68
|
+
* struct fts3rec_offsets
|
69
|
+
*
|
70
|
+
* returns:
|
71
|
+
* ruby object vfrec
|
72
|
+
*/
|
73
|
+
|
74
|
+
/*********** vflowrec ******/
|
75
|
+
typedef struct vfr_data_struct {
|
76
|
+
char *rec;
|
77
|
+
struct ftio ftio_data;
|
78
|
+
struct fts3rec_offsets offsets;
|
79
|
+
} vfr_type;
|
80
|
+
|
81
|
+
void vfr_copy_data(VALUE vfr_obj, char *r, struct ftio *fdata, struct fts3rec_offsets *o) {
|
82
|
+
vfr_type *info;
|
83
|
+
Data_Get_Struct(vfr_obj, vfr_type, info);
|
84
|
+
info->rec = xmalloc(fdata->rec_size);
|
85
|
+
memcpy(info->rec,r, fdata->rec_size);
|
86
|
+
memcpy(&info->ftio_data,fdata,sizeof(struct ftio));
|
87
|
+
memcpy(&info->offsets, o, sizeof(struct fts3rec_offsets));
|
88
|
+
}
|
89
|
+
|
90
|
+
static VALUE vfr_info_free(void *p) {
|
91
|
+
xfree(((vfr_type *)p)->rec);
|
92
|
+
xfree(p);
|
93
|
+
}
|
94
|
+
|
95
|
+
//initialize()
|
96
|
+
static VALUE vfr_init(VALUE rbself) {
|
97
|
+
return rbself;
|
98
|
+
}
|
99
|
+
|
100
|
+
static VALUE vfr_alloc(VALUE klass) {
|
101
|
+
vfr_type *info = xmalloc(sizeof(vfr_type));
|
102
|
+
VALUE vfr_info = Data_Wrap_Struct(klass, NULL, vfr_info_free, info);
|
103
|
+
return vfr_info;
|
104
|
+
}
|
105
|
+
|
106
|
+
// new()
|
107
|
+
static VALUE vfr_new(VALUE klass) {
|
108
|
+
VALUE obj = rb_funcall2(klass, rb_intern("allocate"), 0, 0);
|
109
|
+
rb_obj_call_init(obj, 0, NULL);
|
110
|
+
return obj;
|
111
|
+
}
|
112
|
+
|
113
|
+
#define VFR_EXTRACT8(INFO,XFIELD,NAME) Data_Get_Struct(rbself, vfr_type, INFO);\
|
114
|
+
if (!ftio_check_xfield(&INFO->ftio_data, XFIELD)) {\
|
115
|
+
return INT2NUM(*(u_int8*)(INFO->rec + (INFO->offsets).NAME));\
|
116
|
+
}\
|
117
|
+
return Qnil;\
|
118
|
+
|
119
|
+
#define VFR_EXTRACT16(INFO,XFIELD,NAME) Data_Get_Struct(rbself, vfr_type, INFO);\
|
120
|
+
if (!ftio_check_xfield(&INFO->ftio_data, XFIELD))\
|
121
|
+
return INT2NUM(*(u_int16*)(INFO->rec + (INFO->offsets).NAME));\
|
122
|
+
return Qnil;\
|
123
|
+
|
124
|
+
#define VFR_EXTRACT32(INFO,XFIELD,NAME) Data_Get_Struct(rbself, vfr_type, INFO);\
|
125
|
+
if (!ftio_check_xfield(&INFO->ftio_data, XFIELD)) {\
|
126
|
+
u_int64 tmp64 = *(u_int32*)(INFO->rec + (INFO->offsets).NAME);\
|
127
|
+
return INT2NUM(tmp64);\
|
128
|
+
}\
|
129
|
+
return Qnil;\
|
130
|
+
|
131
|
+
#define VFR_EXTRACTADDR(INFO,XFIELD,NAME) Data_Get_Struct(rbself, vfr_type, INFO);\
|
132
|
+
if (!ftio_check_xfield(&INFO->ftio_data, XFIELD)) {\
|
133
|
+
return INT2NUM(*(u_int32*)(INFO->rec + (INFO->offsets).NAME));\
|
134
|
+
}\
|
135
|
+
return Qnil;\
|
136
|
+
|
137
|
+
|
138
|
+
// vfr_unix_secs
|
139
|
+
static VALUE vfr_unix_secs(VALUE rbself) {
|
140
|
+
vfr_type *info;
|
141
|
+
VFR_EXTRACT32(info,FT_XFIELD_UNIX_SECS,unix_secs)
|
142
|
+
}
|
143
|
+
|
144
|
+
// vfr_unix_nsecs
|
145
|
+
static VALUE vfr_unix_nsecs(VALUE rbself) {
|
146
|
+
vfr_type *info;
|
147
|
+
VFR_EXTRACT32(info,FT_XFIELD_UNIX_NSECS,unix_nsecs);
|
148
|
+
}
|
149
|
+
|
150
|
+
// vfr_sysuptime
|
151
|
+
static VALUE vfr_sysuptime(VALUE rbself) {
|
152
|
+
vfr_type *info;
|
153
|
+
VFR_EXTRACT32(info,FT_XFIELD_SYSUPTIME,sysUpTime);
|
154
|
+
}
|
155
|
+
|
156
|
+
static VALUE vfr_exaddr(VALUE rbself) {
|
157
|
+
vfr_type *info;
|
158
|
+
VFR_EXTRACTADDR(info,FT_XFIELD_EXADDR,exaddr)
|
159
|
+
}
|
160
|
+
|
161
|
+
static VALUE vfr_srcaddr(VALUE rbself) {
|
162
|
+
vfr_type *info;
|
163
|
+
VFR_EXTRACTADDR(info,FT_XFIELD_SRCADDR,srcaddr)
|
164
|
+
}
|
165
|
+
|
166
|
+
static VALUE vfr_dstaddr(VALUE rbself) {
|
167
|
+
vfr_type *info;
|
168
|
+
VFR_EXTRACTADDR(info,FT_XFIELD_DSTADDR,dstaddr)
|
169
|
+
}
|
170
|
+
static VALUE vfr_nexthop(VALUE rbself) {
|
171
|
+
vfr_type *info;
|
172
|
+
VFR_EXTRACTADDR(info,FT_XFIELD_NEXTHOP,nexthop)
|
173
|
+
}
|
174
|
+
|
175
|
+
static VALUE vfr_input(VALUE rbself) {
|
176
|
+
vfr_type *info;
|
177
|
+
VFR_EXTRACT16(info, FT_XFIELD_INPUT,input)
|
178
|
+
}
|
179
|
+
|
180
|
+
static VALUE vfr_output(VALUE rbself) {
|
181
|
+
vfr_type *info;
|
182
|
+
VFR_EXTRACT16(info, FT_XFIELD_OUTPUT,output)
|
183
|
+
}
|
184
|
+
|
185
|
+
static VALUE vfr_dflows(VALUE rbself) {
|
186
|
+
vfr_type *info;
|
187
|
+
VFR_EXTRACT32(info, FT_XFIELD_DFLOWS, dFlows)
|
188
|
+
}
|
189
|
+
|
190
|
+
static VALUE vfr_dpkts(VALUE rbself) {
|
191
|
+
vfr_type *info;
|
192
|
+
VFR_EXTRACT32(info, FT_XFIELD_DPKTS, dPkts);
|
193
|
+
}
|
194
|
+
|
195
|
+
static VALUE vfr_doctets(VALUE rbself) {
|
196
|
+
vfr_type *info;
|
197
|
+
VFR_EXTRACT32(info, FT_XFIELD_DPKTS, dOctets);
|
198
|
+
}
|
199
|
+
|
200
|
+
static VALUE vfr_first(VALUE rbself) {
|
201
|
+
vfr_type *info;
|
202
|
+
VFR_EXTRACT32(info, FT_XFIELD_FIRST, First);
|
203
|
+
}
|
204
|
+
|
205
|
+
static VALUE vfr_last(VALUE rbself) {
|
206
|
+
vfr_type *info;
|
207
|
+
VFR_EXTRACT32(info, FT_XFIELD_LAST, Last);
|
208
|
+
}
|
209
|
+
|
210
|
+
static VALUE vfr_srcport(VALUE rbself) {
|
211
|
+
vfr_type *info;
|
212
|
+
VFR_EXTRACT16(info, FT_XFIELD_SRCPORT, srcport);
|
213
|
+
}
|
214
|
+
|
215
|
+
static VALUE vfr_dstport(VALUE rbself) {
|
216
|
+
vfr_type *info;
|
217
|
+
VFR_EXTRACT16(info, FT_XFIELD_DSTPORT, dstport);
|
218
|
+
}
|
219
|
+
|
220
|
+
static VALUE vfr_prot(VALUE rbself) {
|
221
|
+
vfr_type *info;
|
222
|
+
VFR_EXTRACT8(info, FT_XFIELD_PROT, prot);
|
223
|
+
}
|
224
|
+
|
225
|
+
static VALUE vfr_tos(VALUE rbself) {
|
226
|
+
vfr_type *info;
|
227
|
+
VFR_EXTRACT8(info, FT_XFIELD_TOS, tos);
|
228
|
+
}
|
229
|
+
|
230
|
+
static VALUE vfr_tcp_flags(VALUE rbself) {
|
231
|
+
vfr_type *info;
|
232
|
+
VFR_EXTRACT8(info, FT_XFIELD_TCP_FLAGS, tcp_flags);
|
233
|
+
}
|
234
|
+
|
235
|
+
static VALUE vfr_engine_type(VALUE rbself) {
|
236
|
+
vfr_type *info;
|
237
|
+
VFR_EXTRACT8(info, FT_XFIELD_ENGINE_TYPE, engine_type);
|
238
|
+
}
|
239
|
+
|
240
|
+
static VALUE vfr_engine_id(VALUE rbself) {
|
241
|
+
vfr_type *info;
|
242
|
+
VFR_EXTRACT8(info, FT_XFIELD_ENGINE_ID, engine_id);
|
243
|
+
}
|
244
|
+
|
245
|
+
static VALUE vfr_src_mask(VALUE rbself) {
|
246
|
+
vfr_type *info;
|
247
|
+
VFR_EXTRACT8(info, FT_XFIELD_SRC_MASK, src_mask);
|
248
|
+
}
|
249
|
+
|
250
|
+
static VALUE vfr_dst_mask(VALUE rbself) {
|
251
|
+
vfr_type *info;
|
252
|
+
VFR_EXTRACT8(info, FT_XFIELD_DST_MASK, dst_mask);
|
253
|
+
}
|
254
|
+
|
255
|
+
static VALUE vfr_src_as(VALUE rbself) {
|
256
|
+
vfr_type *info;
|
257
|
+
VFR_EXTRACT16(info, FT_XFIELD_SRC_AS, src_as);
|
258
|
+
}
|
259
|
+
|
260
|
+
static VALUE vfr_dst_as(VALUE rbself) {
|
261
|
+
vfr_type *info;
|
262
|
+
VFR_EXTRACT16(info, FT_XFIELD_DST_AS, dst_as);
|
263
|
+
}
|
264
|
+
|
265
|
+
static VALUE vfr_in_encaps(VALUE rbself) {
|
266
|
+
vfr_type *info;
|
267
|
+
VFR_EXTRACT8(info, FT_XFIELD_IN_ENCAPS, in_encaps);
|
268
|
+
}
|
269
|
+
|
270
|
+
static VALUE vfr_out_encaps(VALUE rbself) {
|
271
|
+
vfr_type *info;
|
272
|
+
VFR_EXTRACT8(info, FT_XFIELD_OUT_ENCAPS, out_encaps);
|
273
|
+
}
|
274
|
+
|
275
|
+
static VALUE vfr_peer_nexthop(VALUE rbself) {
|
276
|
+
vfr_type *info;
|
277
|
+
VFR_EXTRACTADDR(info, FT_XFIELD_PEER_NEXTHOP, peer_nexthop);
|
278
|
+
}
|
279
|
+
|
280
|
+
static VALUE vfr_router_sc(VALUE rbself) {
|
281
|
+
vfr_type *info;
|
282
|
+
VFR_EXTRACT32(info, FT_XFIELD_ROUTER_SC, router_sc);
|
283
|
+
}
|
284
|
+
|
285
|
+
static VALUE vfr_src_tag(VALUE rbself) {
|
286
|
+
vfr_type *info;
|
287
|
+
VFR_EXTRACT32(info, FT_XFIELD_SRC_TAG, src_tag);
|
288
|
+
}
|
289
|
+
|
290
|
+
static VALUE vfr_dst_tag(VALUE rbself) {
|
291
|
+
vfr_type *info;
|
292
|
+
VFR_EXTRACT32(info, FT_XFIELD_DST_TAG, dst_tag);
|
293
|
+
}
|
294
|
+
|
295
|
+
static VALUE vfr_extra_pkts(VALUE rbself) {
|
296
|
+
vfr_type *info;
|
297
|
+
VFR_EXTRACT32(info, FT_XFIELD_EXTRA_PKTS, extra_pkts);
|
298
|
+
}
|
299
|
+
|
300
|
+
static VALUE vfr_marked_tos(VALUE rbself) {
|
301
|
+
vfr_type *info;
|
302
|
+
VFR_EXTRACT8(info, FT_XFIELD_MARKED_TOS, marked_tos);
|
303
|
+
}
|
304
|
+
|
305
|
+
static VALUE vfr_start_time(VALUE rbself) {
|
306
|
+
vfr_type *info;
|
307
|
+
|
308
|
+
Data_Get_Struct(rbself, vfr_type, info);
|
309
|
+
|
310
|
+
if (!ftio_check_xfield(&info->ftio_data,
|
311
|
+
FT_XFIELD_SYSUPTIME |
|
312
|
+
FT_XFIELD_UNIX_SECS)) {
|
313
|
+
struct fttime ftt = ftltime(*(u_int32*)(info->rec + (info->offsets).sysUpTime),
|
314
|
+
*(u_int32*)(info->rec + (info->offsets).unix_secs),
|
315
|
+
*(u_int32*)(info->rec + (info->offsets).unix_nsecs),
|
316
|
+
*(u_int32*)(info->rec + (info->offsets).First));
|
317
|
+
return INT2NUM(ftt.secs);
|
318
|
+
}
|
319
|
+
return Qnil;
|
320
|
+
}
|
321
|
+
|
322
|
+
static VALUE vfr_end_time(VALUE rbself) {
|
323
|
+
vfr_type *info;
|
324
|
+
|
325
|
+
Data_Get_Struct(rbself, vfr_type, info);
|
326
|
+
|
327
|
+
if (!ftio_check_xfield(&info->ftio_data,
|
328
|
+
FT_XFIELD_SYSUPTIME |
|
329
|
+
FT_XFIELD_UNIX_SECS)) {
|
330
|
+
struct fttime ftt = ftltime(*(u_int32*)(info->rec + (info->offsets).sysUpTime),
|
331
|
+
*(u_int32*)(info->rec + (info->offsets).unix_secs),
|
332
|
+
*(u_int32*)(info->rec + (info->offsets).unix_nsecs),
|
333
|
+
*(u_int32*)(info->rec + (info->offsets).First));
|
334
|
+
return INT2NUM(ftt.secs);
|
335
|
+
}
|
336
|
+
return Qnil;
|
337
|
+
}
|
338
|
+
|
339
|
+
|
340
|
+
// declare methods to ruby
|
341
|
+
void Init_Vflowrec() {
|
342
|
+
vflowrec = rb_define_class("Vflowrec", rb_cObject);
|
343
|
+
#if HAVE_RB_DEFINE_ALLOC_FUNC
|
344
|
+
rb_define_alloc_func(vflowrec, vfr_alloc);
|
345
|
+
#else
|
346
|
+
rb_define_singleton_method(vflowrec, "allocate", vfr_alloc, 0);
|
347
|
+
#endif
|
348
|
+
rb_define_singleton_method(vflowrec, "new", vfr_new, 0);
|
349
|
+
rb_define_method(vflowrec, "initialize", vfr_init, 0);
|
350
|
+
rb_define_method(vflowrec, "unix_secs", vfr_unix_secs, 0);
|
351
|
+
rb_define_method(vflowrec, "unix_nsecs", vfr_unix_nsecs, 0);
|
352
|
+
rb_define_method(vflowrec, "sysuptime", vfr_sysuptime, 0);
|
353
|
+
rb_define_method(vflowrec, "exaddr", vfr_exaddr, 0);
|
354
|
+
rb_define_method(vflowrec, "srcaddr", vfr_srcaddr, 0);
|
355
|
+
rb_define_method(vflowrec, "dstaddr", vfr_dstaddr, 0);
|
356
|
+
rb_define_method(vflowrec, "nexthop", vfr_nexthop, 0);
|
357
|
+
rb_define_method(vflowrec, "input", vfr_input, 0);
|
358
|
+
rb_define_method(vflowrec, "output", vfr_output, 0);
|
359
|
+
rb_define_method(vflowrec, "dflows", vfr_dflows, 0);
|
360
|
+
rb_define_method(vflowrec, "dpkts", vfr_dpkts, 0);
|
361
|
+
rb_define_method(vflowrec, "doctets", vfr_doctets, 0);
|
362
|
+
rb_define_method(vflowrec, "first", vfr_first, 0);
|
363
|
+
rb_define_method(vflowrec, "last", vfr_last, 0);
|
364
|
+
rb_define_method(vflowrec, "srcport", vfr_srcport, 0);
|
365
|
+
rb_define_method(vflowrec, "dstport", vfr_dstport, 0);
|
366
|
+
rb_define_method(vflowrec, "prot", vfr_prot, 0);
|
367
|
+
rb_define_method(vflowrec, "tos", vfr_tos, 0);
|
368
|
+
rb_define_method(vflowrec, "tcp_flags", vfr_tcp_flags, 0);
|
369
|
+
rb_define_method(vflowrec, "engine_type", vfr_engine_type, 0);
|
370
|
+
rb_define_method(vflowrec, "engine_id", vfr_engine_id, 0);
|
371
|
+
rb_define_method(vflowrec, "src_mask", vfr_src_mask, 0);
|
372
|
+
rb_define_method(vflowrec, "dst_mask", vfr_dst_mask, 0);
|
373
|
+
rb_define_method(vflowrec, "src_as", vfr_src_as, 0);
|
374
|
+
rb_define_method(vflowrec, "dst_as", vfr_dst_as, 0);
|
375
|
+
rb_define_method(vflowrec, "in_encaps", vfr_in_encaps, 0);
|
376
|
+
rb_define_method(vflowrec, "out_encaps", vfr_out_encaps, 0);
|
377
|
+
rb_define_method(vflowrec, "peer_nexthop", vfr_peer_nexthop, 0);
|
378
|
+
rb_define_method(vflowrec, "router_sc", vfr_router_sc, 0);
|
379
|
+
rb_define_method(vflowrec, "src_tag", vfr_src_tag, 0);
|
380
|
+
rb_define_method(vflowrec, "dst_tag", vfr_dst_tag, 0);
|
381
|
+
rb_define_method(vflowrec, "extra_pkts", vfr_extra_pkts, 0);
|
382
|
+
rb_define_method(vflowrec, "marked_tos", vfr_marked_tos, 0);
|
383
|
+
rb_define_method(vflowrec, "start_time", vfr_start_time, 0);
|
384
|
+
rb_define_method(vflowrec, "end_time", vfr_end_time, 0);
|
385
|
+
|
386
|
+
}
|
387
|
+
|
388
|
+
/*********** vflow ********/
|
389
|
+
// initialize()
|
390
|
+
static VALUE vf_init(VALUE rbself) {
|
391
|
+
return rbself;
|
392
|
+
}
|
393
|
+
|
394
|
+
static VALUE vf_alloc(VALUE klass) {
|
395
|
+
VALUE vf_info;
|
396
|
+
vf_type *info = xmalloc(sizeof(vf_type));
|
397
|
+
info->current_file = NULL; /* set to sensible defaults */
|
398
|
+
vf_info = Data_Wrap_Struct(klass, NULL, vf_info_free, info);
|
399
|
+
return vf_info;
|
400
|
+
}
|
401
|
+
|
402
|
+
// new()
|
403
|
+
static VALUE vf_new(VALUE klass) {
|
404
|
+
VALUE obj = rb_funcall2(klass, rb_intern("allocate"), 0, 0);
|
405
|
+
rb_obj_call_init(obj, 0, NULL);
|
406
|
+
return obj;
|
407
|
+
}
|
408
|
+
|
409
|
+
// header() - return header of current file
|
410
|
+
static VALUE vf_header(VALUE rbself) {
|
411
|
+
|
412
|
+
}
|
413
|
+
|
414
|
+
// currentfile()
|
415
|
+
static VALUE vf_currentfile(VALUE rbself) {
|
416
|
+
vf_type *info;
|
417
|
+
Data_Get_Struct(rbself, vf_type, info);
|
418
|
+
return rb_str_new2(info->current_file);
|
419
|
+
}
|
420
|
+
|
421
|
+
// close one file
|
422
|
+
static VALUE vf_close(VALUE rbself) {
|
423
|
+
vf_type *info;
|
424
|
+
|
425
|
+
Data_Get_Struct(rbself, vf_type, info);
|
426
|
+
ftio_close(&info->ftio_data); // FIXME: should check return code
|
427
|
+
close(info->fd);
|
428
|
+
free(info->current_file);
|
429
|
+
info->fd = 0;
|
430
|
+
}
|
431
|
+
|
432
|
+
/* open(string)
|
433
|
+
* opens a single file for reading
|
434
|
+
*/
|
435
|
+
static VALUE vf_open(VALUE rbself, VALUE file) {
|
436
|
+
struct stat statdata;
|
437
|
+
int fd;
|
438
|
+
vf_type *info;
|
439
|
+
|
440
|
+
Data_Get_Struct(rbself, vf_type, info);
|
441
|
+
if (rb_type(file) == T_STRING) {
|
442
|
+
info->current_file = STR2CSTR(file);
|
443
|
+
|
444
|
+
/* determine file type */
|
445
|
+
if ((fd = open(info->current_file, O_RDONLY, 0)) < 0)
|
446
|
+
rb_raise(rb_eIOError, "Cannot open file: %s", info->current_file);
|
447
|
+
info->fd = fd;
|
448
|
+
if (fstat(fd, & statdata) < 0)
|
449
|
+
rb_raise(rb_eIOError, "Cannot stat file: %s", info->current_file);
|
450
|
+
|
451
|
+
if (!S_ISREG(statdata.st_mode)) {
|
452
|
+
rb_raise(rb_eIOError, "File Type (0x%x) not handled for file %s",
|
453
|
+
statdata.st_mode, info->current_file);
|
454
|
+
}
|
455
|
+
|
456
|
+
if (ftio_init(&info->ftio_data, fd, FT_IO_FLAG_READ) < 0)
|
457
|
+
rb_raise(rb_eIOError, "ftio_init() error");
|
458
|
+
|
459
|
+
// store values needed to make calls to ftio_read and alike
|
460
|
+
ftio_get_ver(&info->ftio_data, &info->ftv);
|
461
|
+
fts3rec_compute_offsets(&info->ftoffsets, &info->ftv);
|
462
|
+
|
463
|
+
/* If we have a block, yield and close after */
|
464
|
+
if (rb_block_given_p())
|
465
|
+
return rb_ensure(rb_yield, rbself, vf_close, rbself);
|
466
|
+
else
|
467
|
+
return rbself;
|
468
|
+
}
|
469
|
+
rb_raise(rb_eTypeError,"Not a string");
|
470
|
+
}
|
471
|
+
|
472
|
+
// next() - return next entry in file
|
473
|
+
static VALUE vf_next(VALUE rbself) {
|
474
|
+
char *ent;
|
475
|
+
struct fts3rec_all cur;
|
476
|
+
vf_type *info;
|
477
|
+
VALUE vfr;
|
478
|
+
|
479
|
+
Data_Get_Struct(rbself, vf_type, info);
|
480
|
+
|
481
|
+
if ((ent = ftio_read(&info->ftio_data)) == NULL)
|
482
|
+
return Qnil;
|
483
|
+
// create flow record object
|
484
|
+
// return vfr_fts3rec_to_vfrec(ent, &info->ftio_data, &info->ftoffsets);
|
485
|
+
vfr = rb_funcall2(vflowrec,rb_intern("new"),0,0);
|
486
|
+
vfr_copy_data(vfr, ent, &info->ftio_data, &info->ftoffsets);
|
487
|
+
return vfr;
|
488
|
+
}
|
489
|
+
|
490
|
+
|
491
|
+
/* for each recoard call block
|
492
|
+
* Examples,
|
493
|
+
* each() {|flowrec| ....}
|
494
|
+
*/
|
495
|
+
static VALUE vf_each(VALUE rbself) {
|
496
|
+
VALUE vfr_rec;
|
497
|
+
|
498
|
+
// debugging
|
499
|
+
//ftio_header_print(&info->ftio_data, stdout, 'f');
|
500
|
+
while ((vfr_rec = vf_next(rbself)) != Qnil) {
|
501
|
+
rb_yield(vfr_rec); // call block
|
502
|
+
}
|
503
|
+
return Qnil;
|
504
|
+
}
|
505
|
+
|
506
|
+
|
507
|
+
void Init_Vflow() {
|
508
|
+
Init_Vflowrec();
|
509
|
+
vflow = rb_define_class("Vflow", rb_cObject);
|
510
|
+
#if HAVE_RB_DEFINE_ALLOC_FUNC
|
511
|
+
rb_define_alloc_func(vflow, vf_alloc);
|
512
|
+
#else
|
513
|
+
rb_define_singleton_method(vflow, "allocate", vf_alloc, 0);
|
514
|
+
#endif
|
515
|
+
rb_define_singleton_method(vflow, "new", vf_new, 0);
|
516
|
+
rb_define_method(vflow, "initialize", vf_init, 0);
|
517
|
+
rb_define_method(vflow, "currentfile", vf_currentfile, 0);
|
518
|
+
rb_define_method(vflow, "open", vf_open, 1);
|
519
|
+
rb_define_method(vflow, "close", vf_close, 0);
|
520
|
+
rb_define_method(vflow, "next", vf_next, 0);
|
521
|
+
rb_define_method(vflow, "each", vf_each, 0);
|
522
|
+
}
|
data/ext/extconf.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'mkmf'
|
2
|
+
|
3
|
+
$CFLAGS="-O3 -pipe"
|
4
|
+
|
5
|
+
#default location for netflow flowtools library and includes
|
6
|
+
NETFLOW_DIR='/usr/local'
|
7
|
+
|
8
|
+
if File.directory?(NETFLOW_DIR)
|
9
|
+
dir_config("ft", "#{NETFLOW_DIR}/include/", "#{NETFLOW_DIR}/lib/")
|
10
|
+
$CFLAGS += " -I#{NETFLOW_DIR}/include/"
|
11
|
+
$LDFLAGS += " -L#{NETFLOW_DIR}/lib/"
|
12
|
+
end
|
13
|
+
|
14
|
+
# check for special include and lib dirs
|
15
|
+
incdir = with_config("ft-include-dir")
|
16
|
+
if incdir
|
17
|
+
$CFLAGS += " -I#{incdir}"
|
18
|
+
puts "Using include dir: #{incdir}"
|
19
|
+
end
|
20
|
+
|
21
|
+
libdir = with_config("ft-lib-dir")
|
22
|
+
if libdir
|
23
|
+
$LDFLAGS += " -L#{libdir}"
|
24
|
+
puts "Using lib dir: #{libdir}"
|
25
|
+
end
|
26
|
+
|
27
|
+
# check for our libraries
|
28
|
+
unless have_library("z")
|
29
|
+
puts "You must have libz!"
|
30
|
+
exit 1
|
31
|
+
end
|
32
|
+
unless have_library("ft")
|
33
|
+
puts "You must have libft!"
|
34
|
+
exit 1
|
35
|
+
end
|
36
|
+
|
37
|
+
# make the Makefile
|
38
|
+
create_makefile('Vflow')
|
data/tests/vfprofile.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
#
|
3
|
+
# $Id: vfprofile.rb,v 1.1 2004/12/13 11:13:18 jeffm Exp $
|
4
|
+
#
|
5
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), "..","ext")
|
6
|
+
require 'Vflow'
|
7
|
+
require 'socket'
|
8
|
+
require 'profile'
|
9
|
+
|
10
|
+
TESTFILE='testdata/dummy_flow'
|
11
|
+
|
12
|
+
puts "+++ get new()"
|
13
|
+
x = Vflow.new()
|
14
|
+
|
15
|
+
puts "+++ open a file"
|
16
|
+
x.open(TESTFILE) do
|
17
|
+
|
18
|
+
puts "+++ each"
|
19
|
+
count = 0
|
20
|
+
total_pkts, total_flows, total_octets = 0,0,0
|
21
|
+
x.each() {|r|
|
22
|
+
count += 1
|
23
|
+
# do some realistic-ish calculations
|
24
|
+
r.dpkts and total_pkts += r.dpkts
|
25
|
+
r.dflows and total_flows += r.dflows
|
26
|
+
r.doctets and total_octets += r.doctets
|
27
|
+
}
|
28
|
+
|
29
|
+
puts "pkts: #{total_pkts} flows: #{total_flows} octets: #{total_octets}"
|
30
|
+
end
|
31
|
+
|
32
|
+
puts "=== End of Tests ===";
|
data/tests/vftest.rb
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
#
|
3
|
+
# $Id: vftest.rb,v 1.6 2004/12/13 11:13:18 jeffm Exp $
|
4
|
+
#
|
5
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), "..","ext")
|
6
|
+
require 'Vflow'
|
7
|
+
require 'socket'
|
8
|
+
|
9
|
+
TESTFILE='testdata/dummy_flow'
|
10
|
+
|
11
|
+
def dumpvflowrec(r)
|
12
|
+
puts "=============="
|
13
|
+
puts "have #{r.class}"
|
14
|
+
puts "start_time: #{Time.at(r.start_time)} end_time: #{Time.at(r.end_time)}"
|
15
|
+
puts "unix_secs #{Time.at(r.unix_secs)} unix_nsecs #{r.unix_nsecs}"
|
16
|
+
puts "sysuptime #{r.sysuptime}"
|
17
|
+
puts "exaddr #{IPSocket.getaddress(r.exaddr)}"
|
18
|
+
print "srcaddr #{IPSocket.getaddress(r.srcaddr)} -> "
|
19
|
+
puts "dstaddr #{IPSocket.getaddress(r.dstaddr)}"
|
20
|
+
puts "nexthop #{IPSocket.getaddress(r.nexthop)}"
|
21
|
+
puts "input #{r.input} output #{r.output}"
|
22
|
+
puts "dflows #{r.dflows}"
|
23
|
+
puts "dpkts #{r.dpkts} doctets #{r.doctets}"
|
24
|
+
puts "first #{r.first} last #{r.last}"
|
25
|
+
puts "srcport #{r.srcport} dstport #{r.dstport}"
|
26
|
+
puts "prot #{r.prot} tos #{r.tos}"
|
27
|
+
puts "engine_type #{r.engine_type} engine_id #{r.engine_id}"
|
28
|
+
puts "src_mask #{r.src_mask} dst_mask #{r.dst_mask}"
|
29
|
+
puts "src_as #{r.src_as} dst_as #{r.dst_as}"
|
30
|
+
puts "in_encaps #{r.in_encaps}"
|
31
|
+
puts "out_encaps #{r.out_encaps}"
|
32
|
+
if r.peer_nexthop then
|
33
|
+
puts "peer_nexthop #{IPSocket.getaddress(r.peer_nexthop)}"
|
34
|
+
else
|
35
|
+
puts "peer_nexthop nil"
|
36
|
+
end
|
37
|
+
puts "router_sc #{r.router_sc}"
|
38
|
+
puts "src_tag #{r.src_tag} dst_tag #{r.dst_tag}"
|
39
|
+
puts "extra_pkts #{r.extra_pkts} marked_tos #{r.marked_tos}"
|
40
|
+
end
|
41
|
+
|
42
|
+
puts "+++ get new()"
|
43
|
+
x = Vflow.new()
|
44
|
+
|
45
|
+
puts "+++ open a file"
|
46
|
+
x.open(TESTFILE)
|
47
|
+
|
48
|
+
puts "+++ currentfile"
|
49
|
+
puts x.currentfile()
|
50
|
+
|
51
|
+
puts "+++ next"
|
52
|
+
dumpvflowrec(x.next)
|
53
|
+
puts "+++ next (again)"
|
54
|
+
dumpvflowrec(x.next)
|
55
|
+
|
56
|
+
puts "+++ each"
|
57
|
+
count = 0
|
58
|
+
x.each() {|r|
|
59
|
+
dumpvflowrec(r)
|
60
|
+
count += 1
|
61
|
+
puts count
|
62
|
+
}
|
63
|
+
|
64
|
+
puts "+++ close a file"
|
65
|
+
x.close()
|
66
|
+
|
67
|
+
print "---- bad call to open "
|
68
|
+
begin
|
69
|
+
x.open(1)
|
70
|
+
rescue TypeError => detail
|
71
|
+
puts "received expected error(TypeError) good"
|
72
|
+
end
|
73
|
+
puts "=== End of Tests ===";
|
metadata
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: Vflow
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- HZ, gem packed by Antti
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-02-11 00:00:00 +02:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Ruby bindings for VFlow
|
17
|
+
email: hz@hz.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions:
|
21
|
+
- ext/extconf.rb
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README
|
24
|
+
files:
|
25
|
+
- Rakefile
|
26
|
+
- README
|
27
|
+
- tests/vftest.rb
|
28
|
+
- tests/vfprofile.rb
|
29
|
+
- ext/Vflow.c
|
30
|
+
- ext/extconf.rb
|
31
|
+
has_rdoc: true
|
32
|
+
homepage: http://rubyforge.org
|
33
|
+
post_install_message:
|
34
|
+
rdoc_options:
|
35
|
+
- --title
|
36
|
+
- bcrypt-ruby
|
37
|
+
- --line-numbers
|
38
|
+
- --inline-source
|
39
|
+
- --main
|
40
|
+
- README
|
41
|
+
require_paths:
|
42
|
+
- lib
|
43
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: "0"
|
48
|
+
version:
|
49
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: "0"
|
54
|
+
version:
|
55
|
+
requirements: []
|
56
|
+
|
57
|
+
rubyforge_project:
|
58
|
+
rubygems_version: 1.3.1
|
59
|
+
signing_key:
|
60
|
+
specification_version: 2
|
61
|
+
summary: Flowtools binding
|
62
|
+
test_files: []
|
63
|
+
|