Class: Caper::Packet

Inherits:
Object
  • Object
show all
Defined in:
lib/caper/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.



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/caper/packet.rb', line 42

def initialize(hdr, body, opts={})
  o = opts.dup
  ts = o.delete(:time) || o.delete(:timestamp)
  case hdr
  when PacketHeader
    raise(ArgumentError, "NULL header pointer") if hdr.to_ptr.null?
    @header = hdr
  when ::FFI::Pointer
    raise(ArgumentError, "NULL header pointer") if hdr.null?
    @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}")
    end
  else
    raise(TypeError, "invalid header: #{hdr.class}")
  end
    
  @header.ts.time = ts if ts

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

Instance Attribute Details

#body_ptrObject (readonly)

Returns the value of attribute body_ptr.



4
5
6
# File 'lib/caper/packet.rb', line 4

def body_ptr
  @body_ptr
end

#headerObject (readonly)

Returns the value of attribute header.



4
5
6
# File 'lib/caper/packet.rb', line 4

def header
  @header
end

Class Method Details

.allocate(phdr, buf) ⇒ Object

Allocates a 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.



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

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

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

Creates a Packet from a Ruby string object.

see new() for more information about the arguments.



9
10
11
# File 'lib/caper/packet.rb', line 9

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

Instance Method Details

#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.



113
114
115
# File 'lib/caper/packet.rb', line 113

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

#caplenObject Also known as: captured



130
131
132
# File 'lib/caper/packet.rb', line 130

def caplen
  @header.caplen
end

#copyObject

An optimized copy which allocates new memory for a 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.



151
152
153
154
155
156
157
158
159
# File 'lib/caper/packet.rb', line 151

def copy
  raise(StandardError, "header is a NULL pointer") if @header.to_ptr.null?
  raise(StandardError, "body is a NULL pointer") if body_ptr.null?
  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)
  self.class.new( cpy_hdr, cpy_buf )
end

#lenObject Also known as: length



136
137
138
# File 'lib/caper/packet.rb', line 136

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 If :length is less than the :caplen, it is overridden as :caplen.

Returns:

  • (String)

    Returns the data as supplied per attr_writer convention.



94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/caper/packet.rb', line 94

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

  @header ||= PacketHeader.new
  @header.caplen = len || @header.caplen
  @header.len = len || @header.caplen
  @body_ptr = FFI::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



119
120
121
# File 'lib/caper/packet.rb', line 119

def time
  @header.ts.time
end

#time=(t) ⇒ Object

Sets the pcap timestamp.



126
127
128
# File 'lib/caper/packet.rb', line 126

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