Class: PacketGen::Header::IP
- Inherits:
-
Base
- Object
- Types::Fields
- Base
- PacketGen::Header::IP
- Defined in:
- lib/packetgen/header/ip.rb,
lib/packetgen/header/ip.rb,
lib/packetgen/header/ip/addr.rb,
lib/packetgen/header/ip/option.rb,
lib/packetgen/header/ip/options.rb
Overview
A IP header consists of:
-
a first byte (#u8 of Types::Int8 type) composed of:
-
a Type of Service field (#tos, Types::Int8 type),
-
a total length (#length, Types::Int16 type),
-
a ID (#id,
Int16type), -
a #frag worg (
Int16) composed of:-
a 13-bit #fragment_offset field,
-
a Time-to-Live (#ttl) field (
Int8), -
a #protocol field (
Int8), -
a #checksum field (
Int16), -
a destination IP address (#dst,
Addrtype), -
an optional #options field (Types::String type),
-
and a #body (Types::String type).
Create a IP header
# standalone
ip = PacketGen::Header::IP.new
# in a packet
pkt = PacketGen.gen('IP')
# access to IP header
pkt.ip # => PacketGen::Header::IP
IP attributes
ip.u8 = 0x45
# the same as
ip.version = 4
ip.ihl = 5
ip.length = 0x43
ip.id = 0x1234
ip.frag = 0x2031
# the same as:
ip.flag_mf = true
ip.fragment_offset = 0x31
ip.flag_rsv? # => Boolean
ip.flag_df? # => Boolean
ip.flag_mf? # => Boolean
ip.ttl = 0x40
ip.protocol = 6
ip.checksum = 0xffff
ip.src = '127.0.0.1'
ip.src # => "127.0.0.1"
ip[:src] # => PacketGen::Header::IP::Addr
ip.dst = '127.0.0.2'
ip.body.read 'this is a body'
Defined Under Namespace
Classes: Addr, ArrayOfAddr, EOL, LSRR, NOP, Option, Options, RA, RR, SI, SSRR
Constant Summary collapse
- ETHERTYPE =
IP Ether type
0x0800
Instance Attribute Summary collapse
- #body ⇒ Types::String, Header::Base
-
#checksum ⇒ Integer
16-bit IP header checksum.
-
#dst ⇒ Addr
Destination IP address.
-
#flag_df ⇒ Boolean
Don’t Fragment flag.
-
#flag_mf ⇒ Boolean
More Fragment flags.
-
#flag_rsv ⇒ Boolean
Reserved bit from flags.
-
#frag ⇒ Integer
16-bit frag word.
-
#fragment_offset ⇒ Integer
13-bit fragment offset.
-
#id ⇒ Integer
16-bit ID.
-
#ihl ⇒ Integer
4-bit IP header length attribute.
-
#length ⇒ Integer
16-bit IP total length.
- #options ⇒ Types::String
-
#protocol ⇒ Integer
8-bit upper protocol self.
-
#src ⇒ Addr
Source IP address.
-
#tos ⇒ Integer
8-bit Type of Service self.
-
#ttl ⇒ Integer
8-bit Time To Live self.
-
#u8 ⇒ Integer
First byte of IP header.
-
#version ⇒ Integer
4-bit version attribute.
Attributes inherited from Base
Class Method Summary collapse
-
.reduce_checksum(checksum) ⇒ Integer
Helper method to reduce an IP checksum.
-
.sum16(hdr) ⇒ Integer
Helper method to compute sum of 16-bit words.
Instance Method Summary collapse
-
#calc_checksum ⇒ Integer
Compute checksum and set
checksumfield. -
#calc_length ⇒ Integer
Compute length and set
lengthfield. - #inspect ⇒ String
-
#parse? ⇒ Boolean
Check version field.
-
#pseudo_header_checksum ⇒ Integer
Get IP part of pseudo header checksum.
-
#read(str) ⇒ Fields
Populate object from a binary string.
-
#reply! ⇒ self
Invert source and destination addresses.
-
#to_s ⇒ Object
Get binary string.
-
#to_w(_iface = nil) ⇒ void
Send IP packet on wire.
Methods inherited from Base
#added_to_packet, bind, bind_header, calculate_and_set_length, #header_id, inherited, #initialize, #ip_header, known_headers, #ll_header, #method_name, #protocol_name, protocol_name
Methods inherited from Types::Fields
#[], #[]=, #bits_on, define_bit_fields_on, define_field, define_field_after, define_field_before, delete_field, fields, #fields, #force_binary, inherited, #initialize, #is_optional?, #is_present?, #offset_of, #optional?, #optional_fields, #present?, remove_bit_fields_on, remove_field, #sz, #to_h, update_field
Constructor Details
This class inherits a constructor from PacketGen::Header::Base
Instance Attribute Details
#body ⇒ Types::String, Header::Base
112 |
# File 'lib/packetgen/header/ip.rb', line 112 define_field :body, Types::String |
#checksum ⇒ Integer
Returns 16-bit IP header checksum.
99 |
# File 'lib/packetgen/header/ip.rb', line 99 define_field :checksum, Types::Int16, default: 0 |
#dst ⇒ Addr
Returns destination IP address.
105 |
# File 'lib/packetgen/header/ip.rb', line 105 define_field :dst, Addr, default: '127.0.0.1' |
#flag_df ⇒ Boolean
Returns Don’t Fragment flag.
128 |
# File 'lib/packetgen/header/ip.rb', line 128 define_bit_fields_on :frag, :flag_rsv, :flag_df, :flag_mf, :fragment_offset, 13 |
#flag_mf ⇒ Boolean
Returns More Fragment flags.
128 |
# File 'lib/packetgen/header/ip.rb', line 128 define_bit_fields_on :frag, :flag_rsv, :flag_df, :flag_mf, :fragment_offset, 13 |
#flag_rsv ⇒ Boolean
Returns reserved bit from flags.
128 |
# File 'lib/packetgen/header/ip.rb', line 128 define_bit_fields_on :frag, :flag_rsv, :flag_df, :flag_mf, :fragment_offset, 13 |
#frag ⇒ Integer
Returns 16-bit frag word.
90 |
# File 'lib/packetgen/header/ip.rb', line 90 define_field :frag, Types::Int16, default: 0 |
#fragment_offset ⇒ Integer
Returns 13-bit fragment offset.
128 |
# File 'lib/packetgen/header/ip.rb', line 128 define_bit_fields_on :frag, :flag_rsv, :flag_df, :flag_mf, :fragment_offset, 13 |
#id ⇒ Integer
Returns 16-bit ID.
87 |
# File 'lib/packetgen/header/ip.rb', line 87 define_field :id, Types::Int16, default: ->(h) { rand(65_535) } |
#ihl ⇒ Integer
Returns 4-bit IP header length attribute.
118 |
# File 'lib/packetgen/header/ip.rb', line 118 define_bit_fields_on :u8, :version, 4, :ihl, 4 |
#length ⇒ Integer
Returns 16-bit IP total length.
84 |
# File 'lib/packetgen/header/ip.rb', line 84 define_field :length, Types::Int16, default: 20 |
#options ⇒ Types::String
109 |
# File 'lib/packetgen/header/ip.rb', line 109 define_field :options, Options, optional: ->(h) { h.ihl > 5 } |
#protocol ⇒ Integer
Returns 8-bit upper protocol self.
96 |
# File 'lib/packetgen/header/ip.rb', line 96 define_field :protocol, Types::Int8 |
#src ⇒ Addr
Returns source IP address.
102 |
# File 'lib/packetgen/header/ip.rb', line 102 define_field :src, Addr, default: '127.0.0.1' |
#tos ⇒ Integer
Returns 8-bit Type of Service self.
81 |
# File 'lib/packetgen/header/ip.rb', line 81 define_field :tos, Types::Int8, default: 0 |
#ttl ⇒ Integer
Returns 8-bit Time To Live self.
93 |
# File 'lib/packetgen/header/ip.rb', line 93 define_field :ttl, Types::Int8, default: 64 |
#u8 ⇒ Integer
78 |
# File 'lib/packetgen/header/ip.rb', line 78 define_field :u8, Types::Int8, default: 0x45 |
#version ⇒ Integer
Returns 4-bit version attribute.
118 |
# File 'lib/packetgen/header/ip.rb', line 118 define_bit_fields_on :u8, :version, 4, :ihl, 4 |
Class Method Details
.reduce_checksum(checksum) ⇒ Integer
159 160 161 162 163 164 165 |
# File 'lib/packetgen/header/ip.rb', line 159 def self.reduce_checksum(checksum) while checksum > 0xffff checksum = (checksum & 0xffff) + (checksum >> 16) end checksum = ~checksum & 0xffff checksum.zero? ? 0xffff : checksum end |
.sum16(hdr) ⇒ Integer
Helper method to compute sum of 16-bit words. Used to compute IP-style checksums.
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/packetgen/header/ip.rb', line 135 def self.sum16(hdr) old_checksum = nil if hdr.respond_to? :checksum= old_checksum = hdr.checksum hdr.checksum = 0 end data = hdr.to_s data << "\x00" if data.size.odd? sum = data.unpack('n*').reduce(:+) hdr.checksum = old_checksum if old_checksum sum end |
Instance Method Details
#calc_checksum ⇒ Integer
Compute checksum and set checksum field
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 |
# File 'lib/packetgen/header/ip.rb', line 194 def calc_checksum # Checksum is only on header, so cannot use IP.sum16, # which also calcultes checksum on #body. checksum = (self[:u8].to_i << 8) | self.tos checksum += self.length checksum += self.id checksum += self.frag checksum += (self.ttl << 8) | self.protocol checksum += (self[:src].to_i >> 16) checksum += (self[:src].to_i & 0xffff) checksum += self[:dst].to_i >> 16 checksum += self[:dst].to_i & 0xffff .to_s.unpack('n*').each { |x| checksum += x } self[:checksum].value = IP.reduce_checksum(checksum) end |
#calc_length ⇒ Integer
Compute length and set length field
212 213 214 |
# File 'lib/packetgen/header/ip.rb', line 212 def calc_length Base.calculate_and_set_length self end |
#inspect ⇒ String
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 |
# File 'lib/packetgen/header/ip.rb', line 237 def inspect str = Inspect.dashed_line(self.class, 1) shift = Inspect.shift_level(1) fields.each do |attr| next if attr == :body str << Inspect.inspect_attribute(attr, self[attr], 1) if attr == :u8 str << shift + Inspect::FMT_ATTR % ['', 'version', version] str << shift + Inspect::FMT_ATTR % ['', 'ihl', ihl] elsif attr == :frag flags = flag_rsv? ? %w[RSV] : [] flags << 'DF' if flag_df? flags << 'MF' if flag_mf? flags_str = flags.empty? ? 'none' : flags.join(',') str << shift + Inspect::FMT_ATTR % ['', 'flags', flags_str] foff = Inspect.int_dec_hex(fragment_offset, 4) str << shift + Inspect::FMT_ATTR % ['', 'frag_offset', foff] end end str end |
#parse? ⇒ Boolean
Check version field
262 263 264 |
# File 'lib/packetgen/header/ip.rb', line 262 def parse? (version == 4) && (ihl >= 5) end |
#pseudo_header_checksum ⇒ Integer
Get IP part of pseudo header checksum.
218 219 220 221 |
# File 'lib/packetgen/header/ip.rb', line 218 def pseudo_header_checksum checksum = self[:src].to_i + self[:dst].to_i (checksum >> 16) + (checksum & 0xffff) end |
#read(str) ⇒ Fields
Populate object from a binary string
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
# File 'lib/packetgen/header/ip.rb', line 170 def read(str) return self if str.nil? force_binary str self[:u8].read str[0, 1] self[:tos].read str[1, 1] self[:length].read str[2, 2] self[:id].read str[4, 2] self[:frag].read str[6, 2] self[:ttl].read str[8, 1] self[:protocol].read str[9, 1] self[:checksum].read str[10, 2] self[:src].read str[12, 4] self[:dst].read str[16, 4] opt_size = 0 if self.ihl > 5 opt_size = (self.ihl - 5) * 4 self[:options].read str[20, opt_size] end self[:body].read str[20 + opt_size..-1] self end |
#reply! ⇒ self
Invert source and destination addresses
276 277 278 279 |
# File 'lib/packetgen/header/ip.rb', line 276 def reply! self[:src], self[:dst] = self[:dst], self[:src] self end |
#to_s ⇒ Object
Get binary string. Fixup IHL if needed (IP header has options, and IHL was not set by user).
268 269 270 271 |
# File 'lib/packetgen/header/ip.rb', line 268 def to_s self.ihl = 5 + .sz / 4 if self.ihl == 5 super end |
#to_w(_iface = nil) ⇒ void
This method returns an undefined value.
Send IP packet on wire.
When sending packet at IP level, checksum and length fields are set by kernel, so bad IP packets cannot be sent this way. To do so, use Eth#to_w.
229 230 231 232 233 234 |
# File 'lib/packetgen/header/ip.rb', line 229 def to_w(_iface=nil) sock = Socket.new(Socket::AF_INET, Socket::SOCK_RAW, Socket::IPPROTO_RAW) sockaddrin = Socket.sockaddr_in(0, dst) sock.send to_s, 0, sockaddrin sock.close end |