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,
Int16
type), -
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,
Addr
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'
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
checksum
field. -
#calc_length ⇒ Integer
Compute and set
length
andihl
field. - #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, #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
138 |
# File 'lib/packetgen/header/ip.rb', line 138 define_field :body, Types::String |
#checksum ⇒ Integer
Returns 16-bit IP header checksum.
124 |
# File 'lib/packetgen/header/ip.rb', line 124 define_field :checksum, Types::Int16, default: 0 |
#dst ⇒ Addr
Returns destination IP address.
130 |
# File 'lib/packetgen/header/ip.rb', line 130 define_field :dst, Addr, default: '127.0.0.1' |
#flag_df ⇒ Boolean
Returns Don’t Fragment flag.
154 |
# File 'lib/packetgen/header/ip.rb', line 154 define_bit_fields_on :frag, :flag_rsv, :flag_df, :flag_mf, :fragment_offset, 13 |
#flag_mf ⇒ Boolean
Returns More Fragment flags.
154 |
# File 'lib/packetgen/header/ip.rb', line 154 define_bit_fields_on :frag, :flag_rsv, :flag_df, :flag_mf, :fragment_offset, 13 |
#flag_rsv ⇒ Boolean
Returns reserved bit from flags.
154 |
# File 'lib/packetgen/header/ip.rb', line 154 define_bit_fields_on :frag, :flag_rsv, :flag_df, :flag_mf, :fragment_offset, 13 |
#frag ⇒ Integer
Returns 16-bit frag word.
115 |
# File 'lib/packetgen/header/ip.rb', line 115 define_field :frag, Types::Int16, default: 0 |
#fragment_offset ⇒ Integer
Returns 13-bit fragment offset.
154 |
# File 'lib/packetgen/header/ip.rb', line 154 define_bit_fields_on :frag, :flag_rsv, :flag_df, :flag_mf, :fragment_offset, 13 |
#id ⇒ Integer
Returns 16-bit ID.
112 |
# File 'lib/packetgen/header/ip.rb', line 112 define_field :id, Types::Int16, default: ->(_) { rand(65_535) } |
#ihl ⇒ Integer
Returns 4-bit IP header length attribute.
144 |
# File 'lib/packetgen/header/ip.rb', line 144 define_bit_fields_on :u8, :version, 4, :ihl, 4 |
#length ⇒ Integer
Returns 16-bit IP total length.
109 |
# File 'lib/packetgen/header/ip.rb', line 109 define_field :length, Types::Int16, default: 20 |
#options ⇒ Types::String
134 135 |
# File 'lib/packetgen/header/ip.rb', line 134 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.
121 |
# File 'lib/packetgen/header/ip.rb', line 121 define_field :protocol, Types::Int8 |
#src ⇒ Addr
Returns source IP address.
127 |
# File 'lib/packetgen/header/ip.rb', line 127 define_field :src, Addr, default: '127.0.0.1' |
#tos ⇒ Integer
Returns 8-bit Type of Service self.
106 |
# File 'lib/packetgen/header/ip.rb', line 106 define_field :tos, Types::Int8, default: 0 |
#ttl ⇒ Integer
Returns 8-bit Time To Live self.
118 |
# File 'lib/packetgen/header/ip.rb', line 118 define_field :ttl, Types::Int8, default: 64 |
#u8 ⇒ Integer
103 |
# File 'lib/packetgen/header/ip.rb', line 103 define_field :u8, Types::Int8, default: 0x45 |
#version ⇒ Integer
Returns 4-bit version attribute.
144 |
# File 'lib/packetgen/header/ip.rb', line 144 define_bit_fields_on :u8, :version, 4, :ihl, 4 |
Class Method Details
.reduce_checksum(checksum) ⇒ Integer
185 186 187 188 189 |
# File 'lib/packetgen/header/ip.rb', line 185 def self.reduce_checksum(checksum) checksum = (checksum & 0xffff) + (checksum >> 16) while checksum > 0xffff 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.
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
# File 'lib/packetgen/header/ip.rb', line 161 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*').sum hdr.checksum = old_checksum if old_checksum sum end |
Instance Method Details
#calc_checksum ⇒ Integer
Compute checksum and set checksum
field
193 194 195 196 197 198 199 200 |
# File 'lib/packetgen/header/ip.rb', line 193 def calc_checksum # Checksum is only on header, so cannot use IP.sum16, # which also calculates checksum on #body. nb_words = ihl * 2 self.checksum = 0 checksum = to_s.unpack("n#{nb_words}").sum self[:checksum].value = IP.reduce_checksum(checksum) end |
#calc_length ⇒ Integer
Compute and set length
and ihl
field
205 206 207 208 |
# File 'lib/packetgen/header/ip.rb', line 205 def calc_length Base.calculate_and_set_length self self.ihl = 5 + self[:options].sz / 4 end |
#inspect ⇒ String
231 232 233 234 235 236 237 238 239 240 |
# File 'lib/packetgen/header/ip.rb', line 231 def inspect super do |attr| case attr when :u8 inspect_u8 when :frag inspect_frag end end end |
#parse? ⇒ Boolean
Check version field
244 245 246 |
# File 'lib/packetgen/header/ip.rb', line 244 def parse? (version == 4) && (ihl >= 5) end |
#pseudo_header_checksum ⇒ Integer
Get IP part of pseudo header checksum.
212 213 214 215 |
# File 'lib/packetgen/header/ip.rb', line 212 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
258 259 260 261 |
# File 'lib/packetgen/header/ip.rb', line 258 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).
250 251 252 253 |
# File 'lib/packetgen/header/ip.rb', line 250 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.
223 224 225 226 227 228 |
# File 'lib/packetgen/header/ip.rb', line 223 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 |