Class: PacketFu::PcapNG::File

Inherits:
Object
  • Object
show all
Defined in:
lib/packetfu/pcapng/file.rb

Overview

PcapNG::File is a complete Pcap-NG file handler.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeFile

Returns a new instance of File.



10
11
12
# File 'lib/packetfu/pcapng/file.rb', line 10

def initialize
  @sections = []
end

Instance Attribute Details

#sectionsObject

Returns the value of attribute sections.



8
9
10
# File 'lib/packetfu/pcapng/file.rb', line 8

def sections
  @sections
end

Instance Method Details

#append(filename = 'out.pcapng') ⇒ Object

Shorthand method for appendong to a file. Can take either :file => ‘name.pcapng’ or simply ‘name.pcapng’



171
172
173
174
175
176
177
178
# File 'lib/packetfu/pcapng/file.rb', line 171

def append(filename='out.pcapng')
  if filename.kind_of?(Hash)
    f = filename[:filename] || filename[:file] || 'out.pcapng'
  else
    f = filename.to_s
  end
  self.to_file(:filename => f.to_s, :append => true)
end

#array_to_file(args = {}) ⇒ Object

Takes an array of packets or a Hash.

Array: as generated by file_to_array or Array of Packet objects.

update Pcapng::File object without writing file on disk

Hash: take packets from args and write them to a file. Valid arguments are:

:filename   # do not write file on disk if not given
:array      # Can either be an array of packet data, or a hash-value pair
            # of timestamp => data.
:timestamp  # Sets an initial timestamp (Time object)
:ts_inc     # Sets the increment between timestamps. Defaults to 1 second.
:append     # If true, then the packets are appended to the end of a file.


191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
# File 'lib/packetfu/pcapng/file.rb', line 191

def array_to_file(args={})
  case args
  when Hash
    filename = args[:filename] || args[:file]
    ary = args[:array] || args[:arr]
    unless ary.kind_of? Array
      raise ArgumentError, ':array parameter needs to be an array'
    end
    ts = args[:timestamp] || args[:ts] || Time.now
    ts_inc = args[:ts_inc] || 1
    append = !!args[:append]
  when Array
    ary = args
    ts = Time.now
    ts_inc = 1
    filename = nil
    append = false
  else
    raise ArgumentError, 'unknown argument. Need either a Hash or Array'
  end

  section = SHB.new
  @sections << section
  itf = IDB.new(:endian => section.endian)
  classify_block section, itf

  ary.each_with_index do |pkt, i|
    case pkt
    when Hash
      this_ts = pkt.keys.first.to_i
      this_cap_len = pkt.values.first.to_s.size
      this_data = pkt.values.first.to_s
    else
      this_ts = (ts + ts_inc * i).to_i
      this_cap_len = pkt.to_s.size
      this_data = pkt.to_s
    end
    this_ts = (this_ts / itf.ts_resol).to_i
    this_tsh = this_ts >> 32
    this_tsl = this_ts & 0xffffffff
    this_pkt = EPB.new(:endian       => section.endian,
                       :interface_id => 0,
                       :tsh          => this_tsh,
                       :tsl          => this_tsl,
                       :cap_len      => this_cap_len,
                       :orig_len     => this_cap_len,
                       :data         => this_data)
    classify_block section, this_pkt
  end

  if filename
    self.to_f(:filename => filename, :append => append)
  else
    self
  end
end

#clearObject

Clear the contents of the Pcapng::File.



99
100
101
# File 'lib/packetfu/pcapng/file.rb', line 99

def clear
  @sections.clear
end

#file_to_array(args = {}) ⇒ Object

#file_to_array translates a Pcap-NG file into an array of packets. Note that this strips out timestamps – if you’d like to retain timestamps and other pcapng file information, you will want to use #read instead.

Valid arguments are:

* :filename           If given, object is cleared and filename is analyzed
                      before generating array. Else, array is generated
                      from self.
* :keep_timestamps    If true, generates an array of hashes, each one with
                      timestamp as key and packet as value. There is one hash
                      per packet.


115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/packetfu/pcapng/file.rb', line 115

def file_to_array(args={})
  filename = args[:filename] || args[:file]
  if filename
    clear
    readfile filename
  end

  ary = []
  @sections.each do |section|
    section.interfaces.each do |itf|
      if args[:keep_timestamps] || args[:keep_ts]
        ary.concat itf.packets.map { |pkt| { pkt.timestamp => pkt.data.to_s } }
      else
        ary.concat itf.packets.map { |pkt| pkt.data.to_s}
      end
    end
  end
  ary
end

#read(str) ⇒ Object

Read a string to populate the object. Note that this appends new blocks to the Pcapng::File object.



16
17
18
19
20
21
# File 'lib/packetfu/pcapng/file.rb', line 16

def read(str)
  PacketFu.force_binary(str)
  io = StringIO.new(str)
  parse_section(io)
  self
end

#read!(str) ⇒ Object

Clear the contents of the Pcapng::File prior to reading in a new string. This string should contain a Section Header Block and an Interface Description Block to create a conform pcapng file.



26
27
28
29
30
# File 'lib/packetfu/pcapng/file.rb', line 26

def read!(str)
  clear
  PacketFu.force_binary(str)
  read(str)
end

#read_packet_bytes(fname, &blk) ⇒ Object

Give an array of parsed packets (raw data from packets). If a block is given, yield raw packet data from the given file.



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/packetfu/pcapng/file.rb', line 59

def read_packet_bytes(fname, &blk)
  count = 0
  packets = [] unless blk

  readfile(fname) do |packet|
    if blk
      count += 1
      yield packet.data.to_s
    else
      packets << packet.data.to_s
    end
  end

  blk ? count : packets
end

#read_packets(fname, &blk) ⇒ Object

Return an array of parsed packets. If a block is given, yield parsed packets from the given file.



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/packetfu/pcapng/file.rb', line 77

def read_packets(fname, &blk)
  count = 0
  packets = [] unless blk

  read_packet_bytes(fname) do |packet|
    if blk
      count += 1
      yield Packet.parse(packet)
    else
      packets << Packet.parse(packet)
    end
  end

  blk ? count : packets
end

#readfile(fname, &blk) ⇒ Object

Read a given file and analyze it. If given a block, it will yield PcapNG::EPB or PcapNG::SPB objects. This is the only way to get packet timestamps.



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/packetfu/pcapng/file.rb', line 35

def readfile(fname, &blk)
  unless ::File.readable?(fname)
    raise ArgumentError, "cannot read file #{fname}"
  end

  ::File.open(fname, 'rb') do |f|
    while !f.eof? do
      parse_section(f)
    end
  end

  if blk
    count = 0
    @sections.each do |section|
      section.interfaces.each do |intf|
        intf.packets.each { |pkt| count += 1; yield pkt }
      end
    end
    count
  end
end

#to_file(args = {}) ⇒ Object Also known as: to_f

Writes the Pcapng::File to a file. Takes the following arguments:

:filename # The file to write to.
:append   # If set to true, the packets are appended to the file, rather
          # than overwriting.


139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/packetfu/pcapng/file.rb', line 139

def to_file(args={})
  filename = args[:filename] || args[:file]
  unless (!filename.nil? || filename.kind_of?(String))
    raise ArgumentError, "Need a :filename for #{self.class}"
  end

  append = args[:append]
  mode = ''
  if append and ::File.exist? filename
    mode = 'ab'
  else
    mode = 'wb'
  end
  ::File.open(filename,mode) {|f| f.write(self.to_s)}
  [filename, self.to_s.size]
end

#to_sObject

Return the object as a String



94
95
96
# File 'lib/packetfu/pcapng/file.rb', line 94

def to_s
  @sections.map { |section| section.to_s }.join
end

#write(filename = 'out.pcapng') ⇒ Object

Shorthand method for writing to a file. Can take either :file => ‘name.pcapng’ or simply ‘name.pcapng’



160
161
162
163
164
165
166
167
# File 'lib/packetfu/pcapng/file.rb', line 160

def write(filename='out.pcapng')
  if filename.kind_of?(Hash)
    f = filename[:filename] || filename[:file] || 'out.pcapng'
  else
    f = filename.to_s
  end
  self.to_file(:filename => f.to_s, :append => false)
end