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.

Author:

  • Sylvain Daubert

Constant Summary collapse

{
  LINKTYPE_ETHERNET => 'Eth',
  LINKTYPE_IEEE802_11 => 'Dot11',
  LINKTYPE_IEEE802_11_RADIOTAP => 'RadioTap',
  LINKTYPE_PPI => 'PPI',
  LINKTYPE_IPV4 => 'IP',
  LINKTYPE_IPV6 => 'IPv6'
}.freeze
BLOCK_TYPES =
PcapNG.constants(false).select { |c| c.to_s.include?('_TYPE') }.to_h do |c|
  type_value = PcapNG.const_get(c).to_i
  klass = PcapNG.const_get(c.to_s.delete_suffix('_TYPE'))
  [type_value, klass]
end.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeFile

Returns a new instance of File.



35
36
37
# File 'lib/packetgen/pcapng/file.rb', line 35

def initialize
  @sections = []
end

Instance Attribute Details

#sectionsArray

Get file sections

Returns:

  • (Array)


33
34
35
# File 'lib/packetgen/pcapng/file.rb', line 33

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



222
223
224
# File 'lib/packetgen/pcapng/file.rb', line 222

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

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

Deprecated.

Prefer use of #read_array or #read_hash.

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):

    • :file (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



244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
# File 'lib/packetgen/pcapng/file.rb', line 244

def array_to_file(options={})
  filename, ary, ts, ts_inc, append = array_to_file_options(options)

  section = create_new_shb_section

  ary.each do |pkt|
    classify_block(section, epb_from_pkt(pkt, section, ts))
    ts += ts_inc
  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.



139
140
141
# File 'lib/packetgen/pcapng/file.rb', line 139

def clear
  @sections.clear
end

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

Deprecated.

Prefer use of #to_a or #to_h.

Translates a PacketGen::PcapNG::File into an array of packets.

Parameters:

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

Options Hash (options):

  • :file (String)

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

  • :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.

Returns:

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


153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/packetgen/pcapng/file.rb', line 153

def file_to_array(options={})
  Deprecation.deprecated(self.class, __method__)

  file = options[:file] || options[:filename]
  reread file

  ary = []
  blk = if options[:keep_timestamps] || options[:keep_ts]
          proc { |pkt| { pkt.timestamp => pkt.data.to_s } }
        else
          proc { |pkt| pkt.data.to_s }
        end
  each_packet_with_interface do |pkt, _itf|
    ary << blk.call(pkt)
  end

  ary
end

#inspectString

Returns:

  • (String)

Since:

  • 3.1.6



296
297
298
299
300
301
302
303
304
305
306
307
# File 'lib/packetgen/pcapng/file.rb', line 296

def inspect
  str = +''
  sections.each do |section|
    str << section.inspect
    section.interfaces.each do |itf|
      str << itf.inspect
      itf.packets.each { |block| str << block.inspect }
    end
  end

  str
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)


43
44
45
46
47
48
# File 'lib/packetgen/pcapng/file.rb', line 43

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)


55
56
57
58
# File 'lib/packetgen/pcapng/file.rb', line 55

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

#read_array(packets, timestamp: nil, ts_inc: nil) ⇒ self

Note:

if timestamp and/or ts_inc are nil, SPB sections are created for each packet, else EPB ones are used

Update current object from an array of packets

Parameters:

  • packets (Array<Packet>)
  • timestamp (Time, nil) (defaults to: nil)

    initial timestamp, used for first packet

  • ts_inc (Numeric, nil) (defaults to: nil)

    timestamp increment, in seconds, to increment initial timestamp for each packet

Returns:

  • (self)

Since:

  • 3.1.6



270
271
272
273
274
275
276
277
278
279
# File 'lib/packetgen/pcapng/file.rb', line 270

def read_array(packets, timestamp: nil, ts_inc: nil)
  ts = timestamp
  section = create_new_shb_section
  packets.each do |pkt|
    block = create_block_from_pkt(pkt, section, ts, ts_inc)
    classify_block(section, block)
    ts = update_ts(ts, ts_inc)
  end
  self
end

#read_hash(hsh) ⇒ self

Update current object from a hash of packets and timestamps

Parameters:

Returns:

  • (self)

Since:

  • 3.1.6



285
286
287
288
289
290
291
292
# File 'lib/packetgen/pcapng/file.rb', line 285

def read_hash(hsh)
  section = create_new_shb_section
  hsh.each do |ts, pkt|
    block = create_block_from_pkt(pkt, section, ts, 0)
    classify_block(section, block)
  end
  self
end

#read_packet_bytes(fname) ⇒ Array #read_packet_bytes(fname) {|raw, interface's| ... } ⇒ Integer

Give an array of raw 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, interface's| ... } ⇒ Integer

    Returns number of packets.

    Parameters:

    • fname (String)

      pcapng file name

    Yield Parameters:

    • raw (String)

      packet raw data

    • interface's (Integer)

      link_type from which packet was captured

    Returns:

    • (Integer)

      number of packets

Raises:

  • (ArgumentError)

    cannot read fname



92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/packetgen/pcapng/file.rb', line 92

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

  count = readfile(fname) do |packet|
    if blk
      yield packet.data.to_s, packet.interface.link_type
    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



116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/packetgen/pcapng/file.rb', line 116

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

  count = read_packet_bytes(fname) do |packet, link_type|
    parsed_pkt = parse_packet(packet, link_type)
    if blk
      yield parsed_pkt
    else
      packets << parsed_pkt
    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



67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/packetgen/pcapng/file.rb', line 67

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

  ::File.open(fname, 'rb') { |f| parse_section(f) until f.eof? }
  return unless blk

  count = 0
  each_packet_with_interface do |pkt, _itf|
    count += 1
    yield pkt
  end
  count
end

#to_aArray<Packet>

Translates a PacketGen::PcapNG::File into an array of packets.

Returns:

Since:

  • 3.1.6



175
176
177
178
179
180
181
182
# File 'lib/packetgen/pcapng/file.rb', line 175

def to_a
  ary = []
  each_packet_with_interface do |pkt, itf|
    ary << parse_packet(pkt.data.to_s, itf.link_type)
  end

  ary
end

#to_file(filename, options = {}) ⇒ Array Also known as: to_f

TODO:

for 4.0, replace options by append kwarg

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



205
206
207
208
209
# File 'lib/packetgen/pcapng/file.rb', line 205

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

#to_hHash{Time => Packet}

Note:

Only packets from EPB sections are extracted, as SPB ones do not have timestamp.

Translates a PacketGen::PcapNG::File into a hash with timestamps as keys.

Returns:

Since:

  • 3.1.6



188
189
190
191
192
193
194
195
196
197
# File 'lib/packetgen/pcapng/file.rb', line 188

def to_h
  hsh = {}
  each_packet_with_interface do |pkt, itf|
    next if pkt.is_a?(SPB)

    hsh[pkt.timestamp] = parse_packet(pkt.data.to_s, itf.link_type)
  end

  hsh
end

#to_sString

Return the object as a String

Returns:

  • (String)


133
134
135
# File 'lib/packetgen/pcapng/file.rb', line 133

def to_s
  @sections.map(&: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



215
216
217
# File 'lib/packetgen/pcapng/file.rb', line 215

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