Class: PacketFu::TcpOptions

Inherits:
Array
  • Object
show all
Includes:
StructFu
Defined in:
lib/packetfu/protos/tcp.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.



585
586
587
588
589
590
591
592
593
594
# File 'lib/packetfu/protos/tcp.rb', line 585

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”



615
616
617
618
619
620
621
622
623
624
625
626
# File 'lib/packetfu/protos/tcp.rb', line 615

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.



629
630
631
632
# File 'lib/packetfu/protos/tcp.rb', line 629

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

#read(str) ⇒ Object

Reads a string to populate the object.



550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
# File 'lib/packetfu/protos/tcp.rb', line 550

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; TcpOption::EOL.new
               when 1; TcpOption::NOP.new
               when 2; TcpOption::MSS.new
               when 3; TcpOption::WS.new
               when 4; TcpOption::SACKOK.new
               when 5; TcpOption::SACK.new
               when 6; TcpOption::ECHO.new
               when 7; TcpOption::ECHOREPLY.new
               when 8; TcpOption::TS.new
               else; 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.



539
540
541
542
543
544
545
546
547
# File 'lib/packetfu/protos/tcp.rb', line 539

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