Class: PacketFu::TcpOptions

Inherits:
Array
  • Object
show all
Includes:
StructFu
Defined in:
lib/packetfu/protos/tcp/options.rb

Instance Method Summary collapse

Methods included from StructFu

#body=, #clone, #set_endianness, #sz, #typecast

Instance Method Details

#decodeObject

Decode parses the TcpOptions object's member options, and produces a human-readable string by iterating over each element's decode() function. If TcpOptions elements were not initially created as TcpOptions, an attempt will be made to convert them.

The output of decode is suitable as input for TcpOptions#encode.


58
59
60
61
62
63
64
65
66
67
# File 'lib/packetfu/protos/tcp/options.rb', line 58

def decode
  decoded = self.map do |x| 
    if x.kind_of? TcpOption
      x.decode
    else
      x = TcpOptions.new.read(x).decode
    end
  end
  decoded.join(",")
end

#encode(str) ⇒ Object

Encode takes a human-readable string and appends the corresponding binary options to the TcpOptions object. To completely replace the contents of the object, use TcpOptions#encode! instead.

Options are comma-delimited, and are identical to the output of the TcpOptions#decode function. Note that the syntax can be unforgiving, so it may be easier to create the subclassed TcpOptions themselves directly, but this method can be less typing if you know what you're doing.

Note that by using TcpOptions#encode, strings supplied as values which can be converted to numbers will be converted first.

Example

t = TcpOptions.new
t.encode("MS:1460,WS:6")

t.to_s # => “002004005264002003006” t.encode(“NOP”) t.to_s # => “002004005264002003006001”


88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/packetfu/protos/tcp/options.rb', line 88

def encode(str)
  opts = str.split(/[\s]*,[\s]*/)
  opts.each do |o|
    kind,value = o.split(/[\s]*:[\s]*/)
    klass = TcpOption.const_get(kind.upcase)
    value = value.to_i if value =~ /^[0-9]+$/
    this_opt = klass.new
    this_opt.encode(value)
    self << this_opt
  end
  self
end

#encode!(str) ⇒ Object

Like TcpOption#encode, except the entire contents are replaced.


102
103
104
105
# File 'lib/packetfu/protos/tcp/options.rb', line 102

def encode!(str)
  self.clear if self.size > 0
  encode(str)
end

#read(str) ⇒ Object

Reads a string to populate the object.


23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/packetfu/protos/tcp/options.rb', line 23

def read(str)
  self.clear 
  PacketFu.force_binary(str)
  return self if(!str.respond_to? :to_s || str.nil?)
  i = 0
  while i < str.to_s.size
    this_opt = case str[i,1].unpack("C").first
               when 0; ::PacketFu::TcpOption::EOL.new
               when 1; ::PacketFu::TcpOption::NOP.new
               when 2; ::PacketFu::TcpOption::MSS.new
               when 3; ::PacketFu::TcpOption::WS.new
               when 4; ::PacketFu::TcpOption::SACKOK.new
               when 5; ::PacketFu::TcpOption::SACK.new
               when 6; ::PacketFu::TcpOption::ECHO.new
               when 7; ::PacketFu::TcpOption::ECHOREPLY.new
               when 8; ::PacketFu::TcpOption::TS.new
               else; ::PacketFu::TcpOption.new
               end
    this_opt.read str[i,str.size]
    unless this_opt.has_optlen?
      this_opt.value = nil
      this_opt.optlen = nil
    end
    self << this_opt
    i += this_opt.sz
  end
  self
end

#to_s(args = {}) ⇒ Object

If args is set, the options line is automatically padded out with NOPs.


12
13
14
15
16
17
18
19
20
# File 'lib/packetfu/protos/tcp/options.rb', line 12

def to_s(args={})
  opts = self.map {|x| x.to_s}.join
  if args[:pad]
    unless (opts.size % 4).zero?
      (4 - (opts.size % 4)).times { opts << "\x01" }
    end
  end
  opts
end