class PacketFu::IPHeader
IPHeader
is a complete IP struct, used in IPPacket
. Most traffic on most networks today is IP-based.
For more on IP packets, see www.networksorcery.com/enp/protocol/ip.htm
Header Definition¶ ↑
Integer (4 bits) :ip_v, Default: 4 Integer (4 bits) :ip_hl, Default: 5 Int8 :ip_tos, Default: 0 # TODO: Break out the bits Int16 :ip_len, Default: calculated Int16 :ip_id, Default: calculated # IRL, hardly random. Int16 :ip_frag, Default: 0 # TODO: Break out the bits Int8 :ip_ttl, Default: 0xff # Changes per flavor Int8 :ip_proto, Default: 0x01 # TCP: 0x06, UDP 0x11, ICMP 0x01 Int16 :ip_sum, Default: calculated Octets :ip_src Octets :ip_dst String :body
Note that IPPackets will always be somewhat incorrect upon initalization, and want an IPHeader#recalc() to become correct before a Packet#to_f
or Packet#to_w
.
Public Class Methods
# File lib/packetfu/protos/ip/header.rb, line 124 def initialize(args={}) @random_id = rand(0xffff) super( (args[:ip_v] || 4), (args[:ip_hl] || 5), Int8.new(args[:ip_tos]), Int16.new(args[:ip_len] || 20), Int16.new(args[:ip_id] || ip_calc_id), Int16.new(args[:ip_frag]), Int8.new(args[:ip_ttl] || 32), Int8.new(args[:ip_proto]), Int16.new(args[:ip_sum] || ip_calc_sum), Octets.new.read(args[:ip_src] || "\x00\x00\x00\x00"), Octets.new.read(args[:ip_dst] || "\x00\x00\x00\x00"), StructFu::String.new.read(args[:body]) ) end
Translate various formats of IPv4 Addresses to an array of digits.
# File lib/packetfu/protos/ip/header.rb, line 285 def self.octet_array(addr) if addr.class == String oa = addr.split('.').collect {|x| x.to_i} elsif addr.kind_of? Integer oa = IPAddr.new(addr, Socket::AF_INET).to_s.split('.') elsif addr.kind_of? Array oa = addr else raise ArgumentError, "IP Address should be a dotted quad string, an array of ints, or a bignum" end end
Public Instance Methods
Retrieve the IP ID
# File lib/packetfu/protos/ip/header.rb, line 258 def ip_calc_id @random_id end
Calulcate the true length of the packet.
# File lib/packetfu/protos/ip/header.rb, line 231 def ip_calc_len (ip_hl * 4) + body.to_s.length end
Calculate the true checksum of the packet. (Yes, this is the long way to do it, but it's e-z-2-read for mathtards like me.)
# File lib/packetfu/protos/ip/header.rb, line 242 def ip_calc_sum checksum = (((self.ip_v << 4) + self.ip_hl) << 8) + self.ip_tos checksum += self.ip_len checksum += self.ip_id checksum += self.ip_frag checksum += (self.ip_ttl << 8) + self.ip_proto checksum += (self.ip_src >> 16) checksum += (self.ip_src & 0xffff) checksum += (self.ip_dst >> 16) checksum += (self.ip_dst & 0xffff) checksum = checksum % 0xffff checksum = 0xffff - checksum checksum == 0 ? 0xffff : checksum end
Returns a more readable IP destination address.
# File lib/packetfu/protos/ip/header.rb, line 280 def ip_daddr self[:ip_dst].to_x end
Sets a more readable IP address.
# File lib/packetfu/protos/ip/header.rb, line 275 def ip_daddr=(addr) self[:ip_dst].read_quad(addr) end
Getter for the destination IP address.
# File lib/packetfu/protos/ip/header.rb, line 228 def ip_dst; self[:ip_dst].to_i; end
Setter for the destination IP address.
# File lib/packetfu/protos/ip/header.rb, line 217 def ip_dst=(i) case i when Numeric self[:ip_dst] = Octets.new.read([i].pack("N")) when Octets self[:ip_dst] = i else typecast i end end
Getter for the fragmentation ID.
# File lib/packetfu/protos/ip/header.rb, line 190 def ip_frag; self[:ip_frag].to_i; end
Setter for the fragmentation ID.
# File lib/packetfu/protos/ip/header.rb, line 188 def ip_frag=(i); typecast i; end
Getter for the header length (multiply by 4)
# File lib/packetfu/protos/ip/header.rb, line 174 def ip_hl; self[:ip_hl].to_i; end
Setter for the header length (divide by 4)
# File lib/packetfu/protos/ip/header.rb, line 172 def ip_hl=(i); self[:ip_hl] = i.to_i; end
Return the claimed header length
# File lib/packetfu/protos/ip/header.rb, line 236 def ip_hlen (ip_hl * 4) end
Getter for the identication number.
# File lib/packetfu/protos/ip/header.rb, line 186 def ip_id; self[:ip_id].to_i; end
Setter for the identication number.
# File lib/packetfu/protos/ip/header.rb, line 184 def ip_id=(i); typecast i; end
# File lib/packetfu/protos/ip/header.rb, line 324 def ip_id_readable "0x%04x" % ip_id end
Getter for total length.
# File lib/packetfu/protos/ip/header.rb, line 182 def ip_len; self[:ip_len].to_i; end
Setter for total length.
# File lib/packetfu/protos/ip/header.rb, line 180 def ip_len=(i); typecast i; end
Getter for the protocol number.
# File lib/packetfu/protos/ip/header.rb, line 198 def ip_proto; self[:ip_proto].to_i; end
Setter for the protocol number.
# File lib/packetfu/protos/ip/header.rb, line 196 def ip_proto=(i); typecast i; end
Recalculate the calculated IP fields. Valid arguments are:
:all :ip_len :ip_sum :ip_id
# File lib/packetfu/protos/ip/header.rb, line 302 def ip_recalc(arg=:all) case arg when :ip_len self.ip_len=ip_calc_len when :ip_sum self.ip_sum=ip_calc_sum when :ip_id @random_id = rand(0xffff) when :all self.ip_id= ip_calc_id self.ip_len= ip_calc_len self.ip_sum= ip_calc_sum else raise ArgumentError, "No such field `#{arg}'" end end
Returns a more readable IP source address.
# File lib/packetfu/protos/ip/header.rb, line 270 def ip_saddr self[:ip_src].to_x end
Sets a more readable IP address. If you wants to manipulate individual octets, (eg, for host scanning in one network), it would be better use ip_src.o1 through ip_src.o4 instead.
# File lib/packetfu/protos/ip/header.rb, line 265 def ip_saddr=(addr) self[:ip_src].read_quad(addr) end
Getter for the source IP address.
# File lib/packetfu/protos/ip/header.rb, line 215 def ip_src; self[:ip_src].to_i; end
Setter for the source IP address.
# File lib/packetfu/protos/ip/header.rb, line 204 def ip_src=(i) case i when Numeric self[:ip_src] = Octets.new.read([i].pack("N")) when Octets self[:ip_src] = i else typecast i end end
Getter for the checksum.
# File lib/packetfu/protos/ip/header.rb, line 202 def ip_sum; self[:ip_sum].to_i; end
Setter for the checksum.
# File lib/packetfu/protos/ip/header.rb, line 200 def ip_sum=(i); typecast i; end
# File lib/packetfu/protos/ip/header.rb, line 328 def ip_sum_readable "0x%04x" % ip_sum end
Getter for the differentiated services
# File lib/packetfu/protos/ip/header.rb, line 178 def ip_tos; self[:ip_tos].to_i; end
Setter for the differentiated services
# File lib/packetfu/protos/ip/header.rb, line 176 def ip_tos=(i); typecast i; end
Getter for the time to live.
# File lib/packetfu/protos/ip/header.rb, line 194 def ip_ttl; self[:ip_ttl].to_i; end
Setter for the time to live.
# File lib/packetfu/protos/ip/header.rb, line 192 def ip_ttl=(i); typecast i; end
Getter for the version.
# File lib/packetfu/protos/ip/header.rb, line 170 def ip_v; self[:ip_v].to_i; end
Setter for the version.
# File lib/packetfu/protos/ip/header.rb, line 168 def ip_v=(i); self[:ip_v] = i.to_i; end
Reads a string to populate the object.
# File lib/packetfu/protos/ip/header.rb, line 149 def read(str) force_binary(str) return self if str.nil? self[:ip_v] = str[0,1].unpack("C").first >> 4 self[:ip_hl] = str[0,1].unpack("C").first.to_i & 0x0f self[:ip_tos].read(str[1,1]) self[:ip_len].read(str[2,2]) self[:ip_id].read(str[4,2]) self[:ip_frag].read(str[6,2]) self[:ip_ttl].read(str[8,1]) self[:ip_proto].read(str[9,1]) self[:ip_sum].read(str[10,2]) self[:ip_src].read(str[12,4]) self[:ip_dst].read(str[16,4]) self[:body].read(str[20,str.size]) if str.size > 20 self end
Returns the object in string form.
# File lib/packetfu/protos/ip/header.rb, line 143 def to_s byte_v_hl = [(self.ip_v << 4) + self.ip_hl].pack("C") byte_v_hl + (self.to_a[2,10].map {|x| x.to_s}.join) end