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. It provides methods to:

  • read and write PcapNG files,

  • process packets from such files.

Examples:

Writing a file

pkt1 = PacketGen.gen('IP', id: 1).add('TCP')
pkt2 = PacketGen.gen('IP', id: 2).add('UDP')
file = PacketGen::PcapNG::File.new
file.read_array([pkt1, pkt2])
file.write('/tmp/file.pcapng')

Reading a file

file = PacketGen::PcapNG::File.new
pkts = file.read_packets('/tmp/file.pcapng')

Author:

  • Sylvain Daubert

  • LemonTree55

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.



50
51
52
# File 'lib/packetgen/pcapng/file.rb', line 50

def initialize
  @sections = []
end

Instance Attribute Details

#sectionsArray<SHB>

Get file sections

Returns:



48
49
50
# File 'lib/packetgen/pcapng/file.rb', line 48

def sections
  @sections
end

Instance Method Details

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

Shorthand method for appending to a file.

Parameters:

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

Returns:

  • (Array(String, Integer))

See Also:



220
221
222
# File 'lib/packetgen/pcapng/file.rb', line 220

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

#clearvoid

This method returns an undefined value.

Clear the contents of the Pcapng::File.



162
163
164
# File 'lib/packetgen/pcapng/file.rb', line 162

def clear
  @sections.clear
end

#inspectString

Returns:

  • (String)

Since:

  • 3.1.6



259
260
261
262
263
264
265
266
267
268
269
270
# File 'lib/packetgen/pcapng/file.rb', line 259

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 binary string to populate the object. Note that this appends new blocks to the Pcapng::File object.

Parameters:

  • str (String)

Returns:

  • (self)


58
59
60
61
62
63
# File 'lib/packetgen/pcapng/file.rb', line 58

def read(str)
  str = str.b unless str.encoding == Encoding::BINARY
  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)


70
71
72
73
# File 'lib/packetgen/pcapng/file.rb', line 70

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



233
234
235
236
237
238
239
240
241
242
# File 'lib/packetgen/pcapng/file.rb', line 233

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



248
249
250
251
252
253
254
255
# File 'lib/packetgen/pcapng/file.rb', line 248

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



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

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



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

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 (via EPB#timestamp).

Examples:

Parse packets and get their timestamp

hsh = {}
file = PacketGen::PcapNG::File.new
file.readfile('/tmp/file.pcapng') do |xpb|
  ts = xpb.is_a?(PacketGen::PcapNG::EPB) ? xpb.timestamp : nil
  pkt = PacketGen.parse(xpb.data)
  hsh[pkt] = ts
end

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



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

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



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

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, append: false) ⇒ Array(String, Integer) Also known as: to_f

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

Parameters:

  • filename (String)

    file name to write

  • append (Boolean) (defaults to: false)

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

Returns:

  • (Array(String, Integer))

    array of 2 elements: filename and size written

See Also:

Since:

  • 4.1.0 Options hash with single :append option is replaced by append keyword argument.



201
202
203
204
205
# File 'lib/packetgen/pcapng/file.rb', line 201

def to_file(filename, append: false)
  mode = 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



182
183
184
185
186
187
188
189
190
191
# File 'lib/packetgen/pcapng/file.rb', line 182

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)


156
157
158
# File 'lib/packetgen/pcapng/file.rb', line 156

def to_s
  @sections.map(&:to_s).join
end

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

Shorthand method for writing to a file.

Parameters:

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

Returns:

  • (Array(String, Integer))

See Also:



212
213
214
# File 'lib/packetgen/pcapng/file.rb', line 212

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