Class: PacketGen::PcapNG::File

Inherits:
Object
  • Object
show all
Defined in:
lib/packetgen/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/packetgen/pcapng/file.rb', line 10

def initialize
  @sections = []
end

Instance Attribute Details

#sectionsArray

Get file sections

Returns:

  • (Array)


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

def sections
  @sections
end

Instance Method Details

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

Shorthand method for appending to a file.

Parameters:

  • filename (#to_s) (defaults to: 'out.pcapng')

Returns:

  • (Array)

    see return value from #to_file



188
189
190
# File 'lib/packetgen/pcapng/file.rb', line 188

def append(filename='out.pcapng')
  self.to_file(filename.to_s, :append => true)
end

#array_to_file(ary) ⇒ self #array_to_file(options = {}) ⇒ Array

Overloads:

  • #array_to_file(ary) ⇒ self

    Update PacketGen::PcapNG::File object with packets.

    Parameters:

    Returns:

    • (self)
  • #array_to_file(options = {}) ⇒ Array

    Update PacketGen::PcapNG::File and/or write it to a file

    Parameters:

    • options (Hash) (defaults to: {})

    Options Hash (options):

    • :filename (String)

      file written on disk only if given

    • :array (Array)

      can either be an array of packet data, or a hash-value pair of timestamp => data.

    • :timestamp (Time)

      set an initial timestamp

    • :ts_inc (Integer)

      set the increment between timestamps. Defaults to 1

    • :append (Boolean)

      if true, append packets to the end of the file

    Returns:

    • (Array)

      see return value from #to_file



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
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'lib/packetgen/pcapng/file.rb', line 209

def array_to_file(options={})
  case options
  when Hash
    filename = options[:filename] || options[:file]
    ary = options[:array] || options[:arr]
    unless ary.kind_of? Array
      raise ArgumentError, ':array parameter needs to be an array'
    end
    ts = options[:timestamp] || options[:ts] || Time.now
    ts_inc = options[:ts_inc] || 1
    append = !!options[:append]
  when Array
    ary = options
    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, :append => append)
  else
    self
  end
end

#clearvoid

This method returns an undefined value.

Clear the contents of the Pcapng::File.



124
125
126
# File 'lib/packetgen/pcapng/file.rb', line 124

def clear
  @sections.clear
end

#file_to_array(options = {}) ⇒ Array<Packet>, Array<Hash>

Translates a PacketGen::PcapNG::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.

Parameters:

  • options (Hash) (defaults to: {})

Options Hash (options):

  • :filename (String)

    if given, object is cleared and filename is analyzed before generating array. Else, array is generated from self

  • :file (String)

    same as :filename

  • :keep_timestamps (Boolean)

    if true (default value: false), generates an array of hashes, each one with timestamp as key and packet as value. There is one hash per packet.

  • :keep_ts (Boolean)

    same as :keep_timestamp

Returns:

  • (Array<Packet>, Array<Hash>)


141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/packetgen/pcapng/file.rb', line 141

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

  ary = []
  @sections.each do |section|
    section.interfaces.each do |itf|
      if options[:keep_timestamps] || options[: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) ⇒ self

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

Parameters:

  • str (String)

Returns:

  • (self)


18
19
20
21
22
23
# File 'lib/packetgen/pcapng/file.rb', line 18

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

#read!(str) ⇒ self

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.

Parameters:

  • str (String)

Returns:

  • (self)


30
31
32
33
# File 'lib/packetgen/pcapng/file.rb', line 30

def read!(str)
  clear
  read(str)
end

#read_packet_bytes(fname) ⇒ Array #read_packet_bytes(fname) {|raw| ... } ⇒ Integer

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

Overloads:

  • #read_packet_bytes(fname) ⇒ Array

    Returns array of packet raw data.

    Parameters:

    • fname (String)

      pcapng file name

    Returns:

    • (Array)

      array of packet raw data

  • #read_packet_bytes(fname) {|raw| ... } ⇒ Integer

    Returns number of packets.

    Parameters:

    • fname (String)

      pcapng file name

    Yield Parameters:

    • raw (String)

      packet raw data

    Returns:

    • (Integer)

      number of packets

Raises:

  • (ArgumentError)

    cannot read fname



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/packetgen/pcapng/file.rb', line 74

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) ⇒ Array<Packet> #read_packets(fname) {|packet| ... } ⇒ Integer

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

Overloads:

  • #read_packets(fname) ⇒ Array<Packet>

    Parameters:

    • fname (String)

      pcapng file name

    Returns:

  • #read_packets(fname) {|packet| ... } ⇒ Integer

    Returns number of packets.

    Parameters:

    • fname (String)

      pcapng file name

    Yield Parameters:

    Returns:

    • (Integer)

      number of packets

Raises:

  • (ArgumentError)

    cannot read fname



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/packetgen/pcapng/file.rb', line 100

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) {|block| ... } ⇒ Integer

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.

Parameters:

  • fname (String)

    pcapng file name

Yield Parameters:

Returns:

  • (Integer)

    return number of yielded blocks (only if a block is given)

Raises:

  • (ArgumentError)

    cannot read fname



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/packetgen/pcapng/file.rb', line 42

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(filename, options = {}) ⇒ Array Also known as: to_f

Writes the PacketGen::PcapNG::File to a file.

Parameters:

  • options (Hash) (defaults to: {})

Options Hash (options):

  • :append (Boolean) — default: default: +false+

    if set to true, the packets are appended to the file, rather than overwriting it

Returns:

  • (Array)

    array of 2 elements: filename and size written



166
167
168
169
170
171
172
173
174
175
# File 'lib/packetgen/pcapng/file.rb', line 166

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

#to_sString

Return the object as a String

Returns:

  • (String)


118
119
120
# File 'lib/packetgen/pcapng/file.rb', line 118

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

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

Shorthand method for writing to a file.

Parameters:

  • filename (#to_s) (defaults to: 'out.pcapng')

Returns:

  • (Array)

    see return value from #to_file



181
182
183
# File 'lib/packetgen/pcapng/file.rb', line 181

def write(filename='out.pcapng')
  self.to_file(filename.to_s, :append => false)
end