Class: FFI::PCap::Packet

Inherits:
Object
  • Object
show all
Defined in:
lib/ffi/pcap/packet.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(hdr, body, opts = {}) ⇒ Packet

Returns a new instance of Packet.

Parameters:

  • hdr (PacketHeader, nil)

    The pcap pkthdr struct for this packet or nil. hdr may only be nil if a string is supplied for the body. A header will be created automatically and #set_body called with opts.

  • body (FFI::Pointer, String)

    A string or pointer for the body of the packet. A String may only be specified if hdr is set to nil.

  • opts (optional, Hash) (defaults to: {})

    Specifies additional options at creation time. Only those below are applicable for all initiatialization styles. All other options are sent to #set_body, but only if the header is nil and body is a String. See #set_body for more info.

Options Hash (opts):

  • :time, (optional, Time)

    :timestamp Sets the timestamp in the header.

Raises:

  • (ArgumentError, TypeError)

    An exception is raised if any of the parameter rules described are not followed.



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/ffi/pcap/packet.rb', line 61

def initialize(hdr, body, opts={})
  o = opts.dup
  ts = (o.delete(:time) || o.delete(:timestamp))

  case hdr
  when PacketHeader
    if hdr.to_ptr.null?
      raise(ArgumentError,"NULL header pointer",caller)
    end

    @header = hdr
  when ::FFI::Pointer
    if hdr.null?
      raise(ArgumentError, "NULL header pointer",caller)
    end

    @header = PacketHeader.new(hdr)
  when nil 
    if body.is_a?(String)
      set_body(body, o)
    else
      raise(TypeError,"invalid body with nil header: #{body.class}",caller)
    end
  else
    raise(TypeError,"invalid header: #{hdr.class}",caller)
  end

  @header.ts.time = ts if ts

  unless @body_ptr
    if (body.is_a?(FFI::Pointer) && !(body.null?))
      @body_ptr = body
    else
      raise(TypeError,"invalid body for header: #{body.class}",caller)
    end
  end
end

Instance Attribute Details

#body_ptrObject (readonly)

Returns the value of attribute body_ptr.



7
8
9
# File 'lib/ffi/pcap/packet.rb', line 7

def body_ptr
  @body_ptr
end

#headerObject (readonly)

Returns the value of attribute header.



7
8
9
# File 'lib/ffi/pcap/packet.rb', line 7

def header
  @header
end

Class Method Details

._load(s) ⇒ Object

Unmarshall a marshalled FFI::PCap::Packet



10
11
12
13
# File 'lib/ffi/pcap/packet.rb', line 10

def self._load(s)
  time, body = Marshal.load(s)
  self.from_string(body, :timestamp => time)
end

.allocate(phdr, buf) ⇒ Object

Allocates a FFI::PCap::Packet using new memory. Used primarily for pcap_loop and pcap_dispatch to retain packets after new ones have been received or a pcap device is closed.



34
35
36
# File 'lib/ffi/pcap/packet.rb', line 34

def self.allocate(phdr, buf)
  new(phdr, buf).copy()
end

.from_string(body, opts = {}) ⇒ Object

Creates a FFI::PCap::Packet from a Ruby string object.

See Also:

  • new


25
26
27
# File 'lib/ffi/pcap/packet.rb', line 25

def self.from_string(body, opts={})
  new(nil, body, opts)
end

Instance Method Details

#_dump(lv) ⇒ Object

Marshal this FFI::PCap::Packet



16
17
18
# File 'lib/ffi/pcap/packet.rb', line 16

def _dump(lv)
  Marshal.dump([self.time, self.body])
end

#bodyString

Returns A String representation of the packet data. The reference to the string is not kept by the object and changes won't affect the data in this packet.

Returns:

  • (String)

    A String representation of the packet data. The reference to the string is not kept by the object and changes won't affect the data in this packet.



144
145
146
# File 'lib/ffi/pcap/packet.rb', line 144

def body
  @body_ptr.read_string(@header.caplen)
end

#caplenObject Also known as: captured



165
166
167
# File 'lib/ffi/pcap/packet.rb', line 165

def caplen
  @header.caplen
end

#copyObject

An optimized copy which allocates new memory for a FFI::PCap::PacketHeader and body.

DANGEROUS: This method uses direct FFI bindings for the copy and may crash Ruby if the packet header or body is incorrect.

Raises:

  • (StandardError)

    An exception is raised if the header or body is a NULL pointer.



187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/ffi/pcap/packet.rb', line 187

def copy
  if @header.to_ptr.null?
    raise(StandardError,"header is a NULL pointer",caller)
  end

  if body_ptr.null?
    raise(StandardError,"body is a NULL pointer",caller)
  end

  cpy_hdr = PacketHeader.new
  cpy_buf = FFI::MemoryPointer.new(@header.caplen)

  CRT.memcpy(cpy_hdr, @header, PacketHeader.size)
  CRT.memcpy(cpy_buf, @body_ptr, @header.caplen)

  return self.class.new( cpy_hdr, cpy_buf )
end

#lenObject Also known as: length



171
172
173
# File 'lib/ffi/pcap/packet.rb', line 171

def len
  @header.len
end

#set_body(data, opts = {}) ⇒ String Also known as: body=

Sets the body from a string. A pointer is automatically derived from.

Parameters:

  • data (String)

    The body to set

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

    Body length options.

Options Hash (opts):

  • :caplen, (optional, Integer)

    :captured The captured length (or snaplen) for this packet. Length of data portion present. Defaults to body.size(). If caplen is larger than the body, then it is overridden with body.size.

  • :len, (optional, Integer)

    :length The total length of the packet (off wire). Defaults to caplen. If :length is less than the :caplen, it is overridden as :caplen.

Returns:

  • (String)

    Returns the data as supplied per attr_writer convention.



122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/ffi/pcap/packet.rb', line 122

def set_body(data, opts={})
  cl = (opts[:caplen] || opts[:captured] || data.size)
  l = (opts[:length] || opts[:len] || cl)

  clen = [cl, data.size].min
  len  = [l, clen].max

  @header ||= PacketHeader.new
  @header.caplen = len || @header.caplen
  @header.len = len || @header.caplen
  @body_ptr = MemoryPointer.from_string(data)
  return self
end

#timeTime Also known as: timestamp

Returns the pcap timestamp as a Time object

Returns:

  • (Time)

    Returns the pcap timestamp as a Time object



152
153
154
# File 'lib/ffi/pcap/packet.rb', line 152

def time
  @header.ts.time
end

#time=(t) ⇒ Object

Sets the pcap timestamp.



161
162
163
# File 'lib/ffi/pcap/packet.rb', line 161

def time=(t)
  @header.ts.time = t
end