packetfu 1.0.0
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/.document +4 -0
- data/CHANGES +36 -0
- data/INSTALL +40 -0
- data/LICENSE +28 -0
- data/README +25 -0
- data/TODO +25 -0
- data/examples/ackscan.rb +38 -0
- data/examples/arp.rb +60 -0
- data/examples/arphood.rb +56 -0
- data/examples/ethernet.rb +10 -0
- data/examples/examples.rb +3 -0
- data/examples/ids.rb +4 -0
- data/examples/idsv2.rb +6 -0
- data/examples/oui.txt +84177 -0
- data/examples/packetfu-shell.rb +111 -0
- data/examples/simple-stats.rb +42 -0
- data/examples/slammer.rb +33 -0
- data/examples/uniqpcap.rb +15 -0
- data/lib/packetfu.rb +108 -0
- data/lib/packetfu/arp.rb +239 -0
- data/lib/packetfu/capture.rb +169 -0
- data/lib/packetfu/config.rb +55 -0
- data/lib/packetfu/eth.rb +264 -0
- data/lib/packetfu/icmp.rb +153 -0
- data/lib/packetfu/inject.rb +65 -0
- data/lib/packetfu/invalid.rb +41 -0
- data/lib/packetfu/ip.rb +318 -0
- data/lib/packetfu/ipv6.rb +230 -0
- data/lib/packetfu/packet.rb +492 -0
- data/lib/packetfu/pcap.rb +502 -0
- data/lib/packetfu/structfu.rb +274 -0
- data/lib/packetfu/tcp.rb +1061 -0
- data/lib/packetfu/udp.rb +210 -0
- data/lib/packetfu/utils.rb +182 -0
- data/test/all_tests.rb +37 -0
- data/test/ptest.rb +10 -0
- data/test/sample.pcap +0 -0
- data/test/sample2.pcap +0 -0
- data/test/test_arp.rb +135 -0
- data/test/test_eth.rb +90 -0
- data/test/test_icmp.rb +54 -0
- data/test/test_inject.rb +33 -0
- data/test/test_invalid.rb +28 -0
- data/test/test_ip.rb +69 -0
- data/test/test_ip6.rb +68 -0
- data/test/test_octets.rb +37 -0
- data/test/test_packet.rb +41 -0
- data/test/test_pcap.rb +210 -0
- data/test/test_structfu.rb +112 -0
- data/test/test_tcp.rb +327 -0
- data/test/test_udp.rb +73 -0
- metadata +144 -0
@@ -0,0 +1,502 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
module StructFu
|
4
|
+
|
5
|
+
# Set the endianness for the various Int classes. Takes either :little or :big.
|
6
|
+
def set_endianness(e=nil)
|
7
|
+
unless [:little, :big].include? e
|
8
|
+
raise ArgumentError, "Unknown endianness for #{self.class}"
|
9
|
+
end
|
10
|
+
@int32 = e == :little ? Int32le : Int32be
|
11
|
+
@int16 = e == :little ? Int16le : Int16be
|
12
|
+
return e
|
13
|
+
end
|
14
|
+
|
15
|
+
# Instead of returning the "size" of the object, which is usually the
|
16
|
+
# number of elements of the Struct, returns the size of the object after
|
17
|
+
# a to_s. Essentially, a short version of self.to_size.size
|
18
|
+
def sz
|
19
|
+
self.to_s.size
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
module PacketFu
|
25
|
+
|
26
|
+
# PcapHeader represents the header portion of a libpcap file (the packets
|
27
|
+
# themselves are in the PcapPackets array). See
|
28
|
+
# http://wiki.wireshark.org/Development/LibpcapFileFormat for details.
|
29
|
+
#
|
30
|
+
# Depending on the endianness (set with :endian), elements are either
|
31
|
+
# :little endian or :big endian.
|
32
|
+
#
|
33
|
+
# ==== PcapHeader Definition
|
34
|
+
#
|
35
|
+
# Symbol :endian Default: :little
|
36
|
+
# Int32 :magic Default: 0xa1b2c3d4 # :big is 0xd4c3b2a1
|
37
|
+
# Int16 :ver_major Default: 2
|
38
|
+
# Int16 :ver_minor Default: 4
|
39
|
+
# Int32 :thiszone
|
40
|
+
# Int32 :sigfigs
|
41
|
+
# Int32 :snaplen Default: 0xffff
|
42
|
+
# Int32 :network Default: 1
|
43
|
+
class PcapHeader < Struct.new(:endian, :magic, :ver_major, :ver_minor,
|
44
|
+
:thiszone, :sigfigs, :snaplen, :network)
|
45
|
+
include StructFu
|
46
|
+
|
47
|
+
def initialize(args={})
|
48
|
+
set_endianness(args[:endian] ||= :little)
|
49
|
+
init_fields(args)
|
50
|
+
super(args[:endian], args[:magic], args[:ver_major],
|
51
|
+
args[:ver_minor], args[:thiszone], args[:sigfigs],
|
52
|
+
args[:snaplen], args[:network])
|
53
|
+
end
|
54
|
+
|
55
|
+
# Called by initialize to set the initial fields.
|
56
|
+
def init_fields(args={})
|
57
|
+
args[:magic] = @int32.new(args[:magic] || 0xa1b2c3d4)
|
58
|
+
args[:ver_major] = @int16.new(args[:ver_major] || 2)
|
59
|
+
args[:ver_minor] ||= @int16.new(args[:ver_minor] || 4)
|
60
|
+
args[:thiszone] ||= @int32.new(args[:thiszone])
|
61
|
+
args[:sigfigs] ||= @int32.new(args[:sigfigs])
|
62
|
+
args[:snaplen] ||= @int32.new(args[:snaplen] || 0xffff)
|
63
|
+
args[:network] ||= @int32.new(args[:network] || 1)
|
64
|
+
return args
|
65
|
+
end
|
66
|
+
|
67
|
+
# Returns the object in string form.
|
68
|
+
def to_s
|
69
|
+
self.to_a[1,7].map {|x| x.to_s}.join
|
70
|
+
end
|
71
|
+
|
72
|
+
# Reads a string to populate the object.
|
73
|
+
# TODO: Need to test this by getting a hold of a big endian pcap file.
|
74
|
+
# Conversion from big to little shouldn't be that big of a deal.
|
75
|
+
def read(str)
|
76
|
+
force_binary(str)
|
77
|
+
return self if str.nil?
|
78
|
+
str.force_encoding("binary") if str.respond_to? :force_encoding
|
79
|
+
if str[0,4] == self[:magic].to_s || true # TODO: raise if it's not magic.
|
80
|
+
self[:magic].read str[0,4]
|
81
|
+
self[:ver_major].read str[4,2]
|
82
|
+
self[:ver_minor].read str[6,2]
|
83
|
+
self[:thiszone].read str[8,4]
|
84
|
+
self[:sigfigs].read str[12,4]
|
85
|
+
self[:snaplen].read str[16,4]
|
86
|
+
self[:network].read str[20,4]
|
87
|
+
end
|
88
|
+
self
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
# The Timestamp class defines how Timestamps appear in libpcap files.
|
94
|
+
#
|
95
|
+
# ==== Header Definition
|
96
|
+
#
|
97
|
+
# Symbol :endian Default: :little
|
98
|
+
# Int32 :sec
|
99
|
+
# Int32 :usec
|
100
|
+
class Timestamp < Struct.new(:endian, :sec, :usec)
|
101
|
+
include StructFu
|
102
|
+
|
103
|
+
def initialize(args={})
|
104
|
+
set_endianness(args[:endian] ||= :little)
|
105
|
+
init_fields(args)
|
106
|
+
super(args[:endian], args[:sec], args[:usec])
|
107
|
+
end
|
108
|
+
|
109
|
+
# Called by initialize to set the initial fields.
|
110
|
+
def init_fields(args={})
|
111
|
+
args[:sec] = @int32.new(args[:sec])
|
112
|
+
args[:usec] = @int32.new(args[:usec])
|
113
|
+
return args
|
114
|
+
end
|
115
|
+
|
116
|
+
# Returns the object in string form.
|
117
|
+
def to_s
|
118
|
+
self.to_a[1,2].map {|x| x.to_s}.join
|
119
|
+
end
|
120
|
+
|
121
|
+
# Reads a string to populate the object.
|
122
|
+
def read(str)
|
123
|
+
force_binary(str)
|
124
|
+
return self if str.nil?
|
125
|
+
self[:sec].read str[0,4]
|
126
|
+
self[:usec].read str[4,4]
|
127
|
+
self
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
|
132
|
+
# PcapPacket defines how individual packets are stored in a libpcap-formatted
|
133
|
+
# file.
|
134
|
+
#
|
135
|
+
# ==== Header Definition
|
136
|
+
#
|
137
|
+
# Timestamp :timestamp
|
138
|
+
# Int32 :incl_len
|
139
|
+
# Int32 :orig_len
|
140
|
+
# String :data
|
141
|
+
class PcapPacket < Struct.new(:endian, :timestamp, :incl_len,
|
142
|
+
:orig_len, :data)
|
143
|
+
include StructFu
|
144
|
+
def initialize(args={})
|
145
|
+
set_endianness(args[:endian] ||= :little)
|
146
|
+
init_fields(args)
|
147
|
+
super(args[:endian], args[:timestamp], args[:incl_len],
|
148
|
+
args[:orig_len], args[:data])
|
149
|
+
end
|
150
|
+
|
151
|
+
# Called by initialize to set the initial fields.
|
152
|
+
def init_fields(args={})
|
153
|
+
args[:timestamp] = Timestamp.new(:endian => args[:endian]).read(args[:timestamp])
|
154
|
+
args[:incl_len] = args[:incl_len].nil? ? @int32.new(args[:data].to_s.size) : @int32.new(args[:incl_len])
|
155
|
+
args[:orig_len] = @int32.new(args[:orig_len])
|
156
|
+
args[:data] = StructFu::String.new.read(args[:data])
|
157
|
+
end
|
158
|
+
|
159
|
+
# Returns the object in string form.
|
160
|
+
def to_s
|
161
|
+
self.to_a[1,4].map {|x| x.to_s}.join
|
162
|
+
end
|
163
|
+
|
164
|
+
# Reads a string to populate the object.
|
165
|
+
def read(str)
|
166
|
+
force_binary(str)
|
167
|
+
self[:timestamp].read str[0,8]
|
168
|
+
self[:incl_len].read str[8,4]
|
169
|
+
self[:orig_len].read str[12,4]
|
170
|
+
self[:data].read str[16,self[:incl_len].to_i]
|
171
|
+
self
|
172
|
+
end
|
173
|
+
|
174
|
+
end
|
175
|
+
|
176
|
+
# PcapPackets is a collection of PcapPacket objects.
|
177
|
+
class PcapPackets < Array
|
178
|
+
|
179
|
+
include StructFu
|
180
|
+
|
181
|
+
attr_accessor :endian # probably ought to be read-only but who am i.
|
182
|
+
|
183
|
+
def initialize(args={})
|
184
|
+
@endian = args[:endian] || :little
|
185
|
+
end
|
186
|
+
|
187
|
+
def force_binary(str)
|
188
|
+
str.force_encoding "binary" if str.respond_to? :force_encoding
|
189
|
+
end
|
190
|
+
|
191
|
+
# Reads a string to populate the object. Note, this read takes in the
|
192
|
+
# whole pcap file, since we need to see the magic to know what
|
193
|
+
# endianness we're dealing with.
|
194
|
+
def read(str)
|
195
|
+
force_binary(str)
|
196
|
+
return self if str.nil?
|
197
|
+
magic = "\xa1\xb2\xc3\xd4"
|
198
|
+
if str[0,4] == magic
|
199
|
+
@endian = :big
|
200
|
+
elsif str[0,4] == magic.reverse
|
201
|
+
@endian = :little
|
202
|
+
else
|
203
|
+
raise ArgumentError, "Unknown file format for #{self.class}"
|
204
|
+
end
|
205
|
+
body = str[24,str.size]
|
206
|
+
while body.size > 16 # TODO: catch exceptions on malformed packets at end
|
207
|
+
p = PcapPacket.new(:endian => @endian)
|
208
|
+
p.read(body)
|
209
|
+
self<<p
|
210
|
+
body = body[p.sz,body.size]
|
211
|
+
end
|
212
|
+
self
|
213
|
+
end
|
214
|
+
|
215
|
+
def to_s
|
216
|
+
self.join
|
217
|
+
end
|
218
|
+
|
219
|
+
end
|
220
|
+
|
221
|
+
# PcapFile is a complete libpcap file struct, made up of two elements, a
|
222
|
+
# PcapHeader and PcapPackets.
|
223
|
+
#
|
224
|
+
# See http://wiki.wireshark.org/Development/LibpcapFileFormat
|
225
|
+
class PcapFile < Struct.new(:endian, :head, :body)
|
226
|
+
include StructFu
|
227
|
+
|
228
|
+
def initialize(args={})
|
229
|
+
init_fields(args)
|
230
|
+
super(args[:endian], args[:head], args[:body])
|
231
|
+
end
|
232
|
+
|
233
|
+
# Called by initialize to set the initial fields.
|
234
|
+
def init_fields(args={})
|
235
|
+
args[:head] = PcapHeader.new(:endian => args[:endian]).read(args[:head])
|
236
|
+
args[:body] = PcapPackets.new(:endian => args[:endian]).read(args[:body])
|
237
|
+
return args
|
238
|
+
end
|
239
|
+
|
240
|
+
# Returns the object in string form.
|
241
|
+
def to_s
|
242
|
+
self[:head].to_s + self[:body].map {|p| p.to_s}.join
|
243
|
+
end
|
244
|
+
|
245
|
+
# Clears the contents of the PcapFile.
|
246
|
+
def clear
|
247
|
+
self[:body].clear
|
248
|
+
end
|
249
|
+
|
250
|
+
# Reads a string to populate the object. Note that this appends new packets to
|
251
|
+
# any existing packets in the PcapFile.
|
252
|
+
def read(str)
|
253
|
+
force_binary(str)
|
254
|
+
self[:head].read str[0,24]
|
255
|
+
self[:body].read str
|
256
|
+
self
|
257
|
+
end
|
258
|
+
|
259
|
+
# Clears the contents of the PcapFile prior to reading in a new string.
|
260
|
+
def read!(str)
|
261
|
+
clear
|
262
|
+
self.read str
|
263
|
+
end
|
264
|
+
|
265
|
+
# A shorthand method for opening a file and reading in the packets. Note
|
266
|
+
# that readfile clears any existing packets, since that seems to be the
|
267
|
+
# typical use.
|
268
|
+
def readfile(file)
|
269
|
+
f = File.open(file, "rb") {|f| f.read}
|
270
|
+
self.read! f
|
271
|
+
end
|
272
|
+
|
273
|
+
# file_to_array() translates a libpcap file into an array of packets.
|
274
|
+
# Note that this strips out pcap timestamps -- if you'd like to retain
|
275
|
+
# timestamps and other libpcap file information, you will want to
|
276
|
+
# use read() instead.
|
277
|
+
#
|
278
|
+
# Note, invoking this requires the somewhat clumsy sytax of,
|
279
|
+
# PcapFile.new.file_to_array(:f => 'filename.pcap')
|
280
|
+
def file_to_array(args={})
|
281
|
+
filename = args[:filename] || args[:file] || args[:f]
|
282
|
+
if filename
|
283
|
+
self.read! File.open(filename, "rb") {|f| f.read}
|
284
|
+
end
|
285
|
+
if args[:keep_timestamps] || args[:keep_ts] || args[:ts]
|
286
|
+
self[:body].map {|x| {x.timestamp.to_s => x.data.to_s} }
|
287
|
+
else
|
288
|
+
self[:body].map {|x| x.data.to_s}
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
alias_method :f2a, :file_to_array
|
293
|
+
|
294
|
+
# Takes an array of packets (as generated by file_to_array), and writes them
|
295
|
+
# to a file. Valid arguments are:
|
296
|
+
#
|
297
|
+
# :filename
|
298
|
+
# :array # Can either be an array of packet data, or a hash-value pair of timestamp => data.
|
299
|
+
# :timestamp # Sets an initial timestamp
|
300
|
+
# :ts_inc # Sets the increment between timestamps. Defaults to 1 second.
|
301
|
+
# :append # If true, then the packets are appended to the end of a file.
|
302
|
+
def array_to_file(args={})
|
303
|
+
if args.kind_of? Hash
|
304
|
+
filename = args[:filename] || args[:file] || args[:f]
|
305
|
+
arr = args[:array] || args[:arr] || args[:a]
|
306
|
+
ts = args[:timestamp] || args[:ts] || Time.now.to_i
|
307
|
+
ts_inc = args[:timestamp_increment] || args[:ts_inc] || 1
|
308
|
+
append = !!args[:append]
|
309
|
+
elsif args.kind_of? Array
|
310
|
+
arr = args
|
311
|
+
filename = append = nil
|
312
|
+
else
|
313
|
+
raise ArgumentError, "Unknown argument. Need either a Hash or Array."
|
314
|
+
end
|
315
|
+
unless arr.kind_of? Array
|
316
|
+
raise ArgumentError, "Need an array to read packets from"
|
317
|
+
end
|
318
|
+
arr.each_with_index do |p,i|
|
319
|
+
if p.kind_of? Hash # Binary timestamps are included
|
320
|
+
this_ts = p.keys.first
|
321
|
+
this_incl_len = p.values.first.size
|
322
|
+
this_orig_len = this_incl_len
|
323
|
+
this_data = p.values.first
|
324
|
+
else # it's an array
|
325
|
+
this_ts = Timestamp.new(:endian => self[:endian], :sec => ts + (ts_inc * i)).to_s
|
326
|
+
this_incl_len = p.to_s.size
|
327
|
+
this_orig_len = this_incl_len
|
328
|
+
this_data = p.to_s
|
329
|
+
end
|
330
|
+
this_pkt = PcapPacket.new({:endian => self[:endian],
|
331
|
+
:timestamp => this_ts,
|
332
|
+
:incl_len => this_incl_len,
|
333
|
+
:orig_len => this_orig_len,
|
334
|
+
:data => this_data }
|
335
|
+
)
|
336
|
+
self[:body] << this_pkt
|
337
|
+
end
|
338
|
+
if filename
|
339
|
+
self.to_f(:filename => filename, :append => append)
|
340
|
+
else
|
341
|
+
self
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
345
|
+
alias_method :a2f, :array_to_file
|
346
|
+
|
347
|
+
# Just like array_to_file, but clears any existing packets from the array first.
|
348
|
+
def array_to_file!(arr)
|
349
|
+
clear
|
350
|
+
array_to_file(arr)
|
351
|
+
end
|
352
|
+
|
353
|
+
alias_method :a2f!, :array_to_file!
|
354
|
+
|
355
|
+
# Writes the PcapFile to a file. Takes the following arguments:
|
356
|
+
#
|
357
|
+
# :filename # The file to write to.
|
358
|
+
# :append # If set to true, the packets are appended to the file, rather than overwriting.
|
359
|
+
def to_file(args={})
|
360
|
+
filename = args[:filename] || args[:file] || args[:f]
|
361
|
+
unless (!filename.nil? || filename.kind_of?(String))
|
362
|
+
raise ArgumentError, "Need a :filename for #{self.class}"
|
363
|
+
end
|
364
|
+
append = args[:append]
|
365
|
+
if append
|
366
|
+
File.open(filename,'ab') {|file| file.write(self.body.to_s)}
|
367
|
+
else
|
368
|
+
File.open(filename,'wb') {|file| file.write(self.to_s)}
|
369
|
+
end
|
370
|
+
[filename, self.body.sz, self.body.size]
|
371
|
+
end
|
372
|
+
|
373
|
+
alias_method :to_f, :to_file
|
374
|
+
|
375
|
+
# Shorthand method for writing to a file. Can take either :file => 'name.pcap' or
|
376
|
+
# simply 'name.pcap'
|
377
|
+
def write(filename='out.pcap')
|
378
|
+
if filename.kind_of?(Hash)
|
379
|
+
f = filename[:filename] || filename[:file] || filename[:f] || 'out.pcap'
|
380
|
+
else
|
381
|
+
f = filename.to_s
|
382
|
+
end
|
383
|
+
self.to_file(:filename => f.to_s, :append => false)
|
384
|
+
end
|
385
|
+
|
386
|
+
# Shorthand method for appending to a file. Can take either :file => 'name.pcap' or
|
387
|
+
# simply 'name.pcap'
|
388
|
+
def append(filename='out.pcap')
|
389
|
+
if filename.kind_of?(Hash)
|
390
|
+
f = filename[:filename] || filename[:file] || filename[:f] || 'out.pcap'
|
391
|
+
else
|
392
|
+
f = filename.to_s
|
393
|
+
end
|
394
|
+
self.to_file(:filename => f, :append => true)
|
395
|
+
end
|
396
|
+
|
397
|
+
end
|
398
|
+
|
399
|
+
end
|
400
|
+
|
401
|
+
module PacketFu
|
402
|
+
|
403
|
+
# Read is largely deprecated. It was current in PacketFu 0.2.0, but isn't all that useful
|
404
|
+
# in 0.3.0 and beyond. Expect it to go away completely by version 1.0. So, the main use
|
405
|
+
# of this class is to learn how to do exactly the same things using the PcapFile object.
|
406
|
+
class Read
|
407
|
+
|
408
|
+
class << self
|
409
|
+
|
410
|
+
# Reads the magic string of a pcap file, and determines
|
411
|
+
# if it's :little or :big endian.
|
412
|
+
def get_byte_order(pcap_file)
|
413
|
+
byte_order = ((pcap_file[0,4] == "\xd4\xc3\xb2\xa1") ? :little : :big)
|
414
|
+
return byte_order
|
415
|
+
end
|
416
|
+
|
417
|
+
# set_byte_order is pretty much totally deprecated.
|
418
|
+
def set_byte_order(byte_order)
|
419
|
+
PacketFu.instance_variable_set("@byte_order",byte_order)
|
420
|
+
return true
|
421
|
+
end
|
422
|
+
|
423
|
+
# A wrapper for PcapFile#file_to_array, but only returns the array. Actually
|
424
|
+
# using the PcapFile object is going to be more useful.
|
425
|
+
def file_to_array(args={})
|
426
|
+
filename = args[:filename] || args[:file] || args[:out]
|
427
|
+
raise ArgumentError, "Need a :filename in string form to read from." if (filename.nil? || filename.class != String)
|
428
|
+
PcapFile.new.file_to_array(args)
|
429
|
+
end
|
430
|
+
|
431
|
+
alias_method :f2a, :file_to_array
|
432
|
+
|
433
|
+
end
|
434
|
+
|
435
|
+
end
|
436
|
+
|
437
|
+
end
|
438
|
+
|
439
|
+
module PacketFu
|
440
|
+
|
441
|
+
# Write is largely deprecated. It was current in PacketFu 0.2.0, but isn't all that useful
|
442
|
+
# in 0.3.0 and beyond. Expect it to go away completely by version 1.0, as working with
|
443
|
+
# PacketFu::PcapFile directly is generally going to be more rewarding.
|
444
|
+
class Write
|
445
|
+
|
446
|
+
class << self
|
447
|
+
|
448
|
+
# format_packets: Pretty much totally deprecated.
|
449
|
+
def format_packets(args={})
|
450
|
+
arr = args[:arr] || args[:array] || []
|
451
|
+
ts = args[:ts] || args[:timestamp] || Time.now.to_i
|
452
|
+
ts_inc = args[:ts_inc] || args[:timestamp_increment]
|
453
|
+
pkts = PcapFile.new.array_to_file(:endian => PacketFu.instance_variable_get("@byte_order"),
|
454
|
+
:arr => arr,
|
455
|
+
:ts => ts,
|
456
|
+
:ts_inc => ts_inc)
|
457
|
+
pkts.body
|
458
|
+
end
|
459
|
+
|
460
|
+
# array_to_file is a largely deprecated function for writing arrays of pcaps to a file.
|
461
|
+
# Use PcapFile#array_to_file instead.
|
462
|
+
def array_to_file(args={})
|
463
|
+
filename = args[:filename] || args[:file] || args[:out] || :nowrite
|
464
|
+
arr = args[:arr] || args[:array] || []
|
465
|
+
ts = args[:ts] || args[:timestamp] || args[:time_stamp] || Time.now.to_f
|
466
|
+
ts_inc = args[:ts_inc] || args[:timestamp_increment] || args[:time_stamp_increment]
|
467
|
+
byte_order = args[:byte_order] || args[:byteorder] || args[:endian] || args[:endianness] || :little
|
468
|
+
append = args[:append]
|
469
|
+
Read.set_byte_order(byte_order) if [:big, :little].include? byte_order
|
470
|
+
pf = PcapFile.new
|
471
|
+
pf.array_to_file(:endian => PacketFu.instance_variable_get("@byte_order"),
|
472
|
+
:arr => arr,
|
473
|
+
:ts => ts,
|
474
|
+
:ts_inc => ts_inc)
|
475
|
+
if filename && filename != :nowrite
|
476
|
+
if append
|
477
|
+
pf.append(filename)
|
478
|
+
else
|
479
|
+
pf.write(filename)
|
480
|
+
end
|
481
|
+
return [filename,pf.to_s.size,arr.size,ts,ts_inc]
|
482
|
+
else
|
483
|
+
return [nil,pf.to_s.size,arr.size,ts,ts_inc]
|
484
|
+
end
|
485
|
+
|
486
|
+
end
|
487
|
+
|
488
|
+
alias_method :a2f, :array_to_file
|
489
|
+
|
490
|
+
# Shorthand method for appending to a file. Also shouldn't use.
|
491
|
+
def append(args={})
|
492
|
+
array_to_file(args.merge(:append => true))
|
493
|
+
end
|
494
|
+
|
495
|
+
end
|
496
|
+
|
497
|
+
end
|
498
|
+
|
499
|
+
end
|
500
|
+
|
501
|
+
|
502
|
+
# vim: nowrap sw=2 sts=0 ts=2 ff=unix ft=ruby
|