class Scriptroute::IPv4

Constants

IPPROTO_ICMP

Attributes

ip_dst[R]

@return [IPaddress]

ip_hl[R]

@return [Fixnum]

ip_id[RW]

@return [Fixnum]

ip_len[R]

@return [Fixnum]

ip_off[RW]

@return [Fixnum]

ip_options[RW]

@return [Array<IPv4option>]

ip_p[R]

@return [Fixnum]

ip_src[R]

@return [IPaddress]

ip_sum[RW]

@return [Fixnum]

ip_tos[RW]

@return [Fixnum]

ip_ttl[RW]

@return [Fixnum]

ip_v[R]

@return [Fixnum]

Public Class Methods

creator(str) click to toggle source

invoke a factory(?) to create a TCP/UDP/ICMP as appropriate, then unmarshal the IPv4 header contents. @param [String] str the bytes of the packet to unpack.

# File lib/scriptroute/packets.rb, line 355
def IPv4.creator(str) 
  ip_vhl, ip_tos, ip_len,
    ip_id, ip_off,
    ip_ttl, ip_p, ip_sum,
    ip_src, ip_dst = str.unpack("ccn" + "nn" + "ccn" + "N" + "N");
  ip_v = ((ip_vhl & 0xf0) >> 4)
  if(ip_v == 4) then
    ip_hl = ip_vhl & 0xf;
    if(@@creators[ip_p]) then
      pkt = (@@creators[ip_p]).call(str[(ip_hl * 4) .. ip_len])
      pkt.ipv4_unmarshal(str)
      pkt
    else
      raise "unknown IPv4 protocol #%d in %s" % [ ip_p, str.unpack("C*").map { |c| "%x" % c }.join(' ') ]
    end
  elsif(ip_v == 6) then
    # probably should do this someplace above IPv4 creator.
    puts "received v6 packet %s" % [ str.unpack("H*") ]
    str
  else
    raise "unknown IP version #%d in %s" % [ ip_v, str.unpack("C*").map { |c| "%x" % c }.join(' ') ]
  end
end
new(p) click to toggle source

This method is probably only useful for calling from subclasses. @param p [Fixnum] the protocol, either Scriptroute::IPv4::IPPROTO_ICMP, IPPROTO_TCP, or IPPROTO_UDP

# File lib/scriptroute/packets.rb, line 331
def initialize(p) 
  if(p.is_a?(Fixnum)) then
    @ip_v = 4
    @ip_tos = 0
    @ip_id = 11 
    @ip_off = 0
    @ip_ttl = 64
    @ip_p = p
    @ip_sum = 0
    @ip_src = 0
    @ip_dst = 0
    @ip_options = Array.new
    calculate_packet_len
  else
    raise "need a protocol number to instantiate an ipv4 packet"
  end
end

Public Instance Methods

add_option(opt) click to toggle source

@param opt [IPv4option] add a record route or timestamp option. @return [void]

# File lib/scriptroute/packets.rb, line 324
def add_option(opt)
  opt.is_a?(IPv4option) or raise "can add only IPv4options"
  @ip_options.push(opt)
  calculate_header_len
end
calculate_header_len() click to toggle source

sets ip_hl, should not be necessary to call this explicitly. @return [void]

# File lib/scriptroute/packets.rb, line 313
def calculate_header_len 
  @ip_hl = [ 5 + ((ip_options.map { |o| o.ipt_len }.sum)/4.0).ceil, 15 ].min # at most 15
end
calculate_packet_len() click to toggle source

@return [void]

# File lib/scriptroute/packets.rb, line 317
def calculate_packet_len 
  calculate_header_len # ensures @ip_hl is set properly
  raise "ip_payload_len not calculated" unless ip_payload_len
  @ip_len = ip_payload_len + (@ip_hl * 4)
end
ip_dst=(destination_address) click to toggle source

@param [String,IPaddress] destination_address the destination of this packet.

# File lib/scriptroute/packets.rb, line 292
def ip_dst=(destination_address)
  @ip_dst = IPaddress.new(destination_address)
end
ip_payload_len() click to toggle source

@return [Fixnum] the length of the payload, intended to be implemented by subclasses. @raise [RuntimeError] if invoked directly instead of being overloaded.

# File lib/scriptroute/packets.rb, line 308
def ip_payload_len
  raise  "ip_payload_len is a pure virtual function in IPv4"
end
ipv4_unmarshal(str) click to toggle source

unpack the ipv4 component of the packet, even if we’re unmarshaling an instance of a subclass. @param [String] str The string from which to unpack. @return [void]

# File lib/scriptroute/packets.rb, line 383
def ipv4_unmarshal(str)
  ip_vhl, @ip_tos, @ip_len,
    @ip_id, @ip_off,
    @ip_ttl, @ip_p, @ip_sum,
    ip_src, ip_dst = str.unpack("CCn" + "nn" + "CCn" + "N" + "N");
  @ip_src, @ip_dst = [ip_src, ip_dst].map { |addr| IPaddress.new(addr) }
  @ip_hl = ip_vhl & 0xf;
  @ip_v = (ip_vhl & 0xf0) >> 4;
  @ip_options = Array.new
  if(@ip_hl > 5) then
    add_option(IPv4option.creator(str[20 .. (@ip_hl*4)]))
  end
end
to_s() click to toggle source

@return [String]

# File lib/scriptroute/packets.rb, line 398
def to_s
  "%s > %s ttl%d" % [ @ip_src, @ip_dst, @ip_ttl ] + 
    @ip_options.map { |o| o.to_s }.join(", ")
end

Private Instance Methods

marshal() click to toggle source

@return [String] The packet in string form

# File lib/scriptroute/packets.rb, line 297
def marshal
  calculate_packet_len
  [ (@ip_v << 4) + @ip_hl, @ip_tos, @ip_len, 
    @ip_id, @ip_off, 
    @ip_ttl, @ip_p, @ip_sum,
    @ip_src.to_i, 
    @ip_dst.to_i ].pack("ccn" + "nn" + "ccn" + "N" + "N") + 
    @ip_options.map { |o| o.marshal }.join
end