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
IP protocol (RFC 791)
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Version| IHL |Type of Service| Total Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Identification |Flags| Fragment Offset |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Time to Live | Protocol | Header Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Destination Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
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), -
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'
Add IP options
IP has an #options attribute used to store datagram options.
pkt = PacketGen.gen('IP')
# add option from class
pkt.ip. << PacketGen::Header::IP::RA.new
# or use a hash
pkt.ip. << { type: 'RR', data: ['192.168.16.4']}
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.
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 and set
lengthandihlfield. - #inspect ⇒ String
-
#parse? ⇒ Boolean
Check version field.
-
#pseudo_header_checksum ⇒ Integer
Get IP part of pseudo header checksum.
-
#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
bind, calculate_and_set_length, #header_id, inherited, #initialize, #ip_header, known_headers, #ll_header
Methods included from PacketGen::Headerable
#added_to_packet, included, #method_name, #packet, #packet=, #protocol_name, #read
Methods inherited from Types::Fields
#[], #[]=, #bits_on, define_bit_fields_on, define_field, define_field_after, define_field_before, #fields, fields, inherited, #initialize, #offset_of, #optional?, #optional_fields, #present?, #read, 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
137 |
# File 'lib/packetgen/header/ip.rb', line 137 define_field :body, Types::String |
#checksum ⇒ Integer
Returns 16-bit IP header checksum.
123 |
# File 'lib/packetgen/header/ip.rb', line 123 define_field :checksum, Types::Int16, default: 0 |
#dst ⇒ Addr
Returns destination IP address.
129 |
# File 'lib/packetgen/header/ip.rb', line 129 define_field :dst, Addr, default: '127.0.0.1' |
#flag_df ⇒ Boolean
Returns Don’t Fragment flag.
153 |
# File 'lib/packetgen/header/ip.rb', line 153 define_bit_fields_on :frag, :flag_rsv, :flag_df, :flag_mf, :fragment_offset, 13 |
#flag_mf ⇒ Boolean
Returns More Fragment flags.
153 |
# File 'lib/packetgen/header/ip.rb', line 153 define_bit_fields_on :frag, :flag_rsv, :flag_df, :flag_mf, :fragment_offset, 13 |
#flag_rsv ⇒ Boolean
Returns reserved bit from flags.
153 |
# File 'lib/packetgen/header/ip.rb', line 153 define_bit_fields_on :frag, :flag_rsv, :flag_df, :flag_mf, :fragment_offset, 13 |
#frag ⇒ Integer
Returns 16-bit frag word.
114 |
# File 'lib/packetgen/header/ip.rb', line 114 define_field :frag, Types::Int16, default: 0 |
#fragment_offset ⇒ Integer
Returns 13-bit fragment offset.
153 |
# File 'lib/packetgen/header/ip.rb', line 153 define_bit_fields_on :frag, :flag_rsv, :flag_df, :flag_mf, :fragment_offset, 13 |
#id ⇒ Integer
Returns 16-bit ID.
111 |
# File 'lib/packetgen/header/ip.rb', line 111 define_field :id, Types::Int16, default: ->(_) { rand(65_535) } |
#ihl ⇒ Integer
Returns 4-bit IP header length attribute.
143 |
# File 'lib/packetgen/header/ip.rb', line 143 define_bit_fields_on :u8, :version, 4, :ihl, 4 |
#length ⇒ Integer
Returns 16-bit IP total length.
108 |
# File 'lib/packetgen/header/ip.rb', line 108 define_field :length, Types::Int16, default: 20 |
#options ⇒ Types::String
133 134 |
# File 'lib/packetgen/header/ip.rb', line 133 define_field :options, Options, optional: ->(h) { h.ihl > 5 }, builder: ->(h, t) { t.new(length_from: -> { (h.ihl - 5) * 4 }) } |
#protocol ⇒ Integer
Returns 8-bit upper protocol self.
120 |
# File 'lib/packetgen/header/ip.rb', line 120 define_field :protocol, Types::Int8 |
#src ⇒ Addr
Returns source IP address.
126 |
# File 'lib/packetgen/header/ip.rb', line 126 define_field :src, Addr, default: '127.0.0.1' |
#tos ⇒ Integer
Returns 8-bit Type of Service self.
105 |
# File 'lib/packetgen/header/ip.rb', line 105 define_field :tos, Types::Int8, default: 0 |
#ttl ⇒ Integer
Returns 8-bit Time To Live self.
117 |
# File 'lib/packetgen/header/ip.rb', line 117 define_field :ttl, Types::Int8, default: 64 |
#u8 ⇒ Integer
102 |
# File 'lib/packetgen/header/ip.rb', line 102 define_field :u8, Types::Int8, default: 0x45 |
#version ⇒ Integer
Returns 4-bit version attribute.
143 |
# File 'lib/packetgen/header/ip.rb', line 143 define_bit_fields_on :u8, :version, 4, :ihl, 4 |
Class Method Details
.reduce_checksum(checksum) ⇒ Integer
184 185 186 187 188 189 190 |
# File 'lib/packetgen/header/ip.rb', line 184 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.
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
# File 'lib/packetgen/header/ip.rb', line 160 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 and set length and ihl field
213 214 215 216 |
# File 'lib/packetgen/header/ip.rb', line 213 def calc_length Base.calculate_and_set_length self self.ihl = 5 + self[:options].sz / 4 end |
#inspect ⇒ String
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 |
# File 'lib/packetgen/header/ip.rb', line 239 def inspect super do |attr| case attr when :u8 shift = Inspect.shift_level str = Inspect.inspect_attribute(attr, self[attr]) str << shift << Inspect::FMT_ATTR % ['', 'version', version] str << shift << Inspect::FMT_ATTR % ['', 'ihl', ihl] when :frag shift = Inspect.shift_level str = Inspect.inspect_attribute(attr, self[attr]) 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 end |
#parse? ⇒ Boolean
Check version field
263 264 265 |
# File 'lib/packetgen/header/ip.rb', line 263 def parse? (version == 4) && (ihl >= 5) end |
#pseudo_header_checksum ⇒ Integer
Get IP part of pseudo header checksum.
220 221 222 223 |
# File 'lib/packetgen/header/ip.rb', line 220 def pseudo_header_checksum checksum = self[:src].to_i + self[:dst].to_i (checksum >> 16) + (checksum & 0xffff) end |
#reply! ⇒ self
Invert source and destination addresses
277 278 279 280 |
# File 'lib/packetgen/header/ip.rb', line 277 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).
269 270 271 272 |
# File 'lib/packetgen/header/ip.rb', line 269 def to_s self.ihl = 5 + self[:options].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.
231 232 233 234 235 236 |
# File 'lib/packetgen/header/ip.rb', line 231 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 |