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
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 |
# File 'lib/packetgen/header/ip.rb', line 184 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.
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*').sum hdr.checksum = old_checksum if old_checksum sum end |
Instance Method Details
#calc_checksum ⇒ Integer
Compute checksum and set checksum
field
192 193 194 195 196 197 198 199 |
# File 'lib/packetgen/header/ip.rb', line 192 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
204 205 206 207 |
# File 'lib/packetgen/header/ip.rb', line 204 def calc_length Base.calculate_and_set_length self self.ihl = 5 + self[:options].sz / 4 end |
#inspect ⇒ String
230 231 232 233 234 235 236 237 238 239 |
# File 'lib/packetgen/header/ip.rb', line 230 def inspect super do |attr| case attr when :u8 inspect_u8 when :frag inspect_frag end end end |
#parse? ⇒ Boolean
Check version field
243 244 245 |
# File 'lib/packetgen/header/ip.rb', line 243 def parse? (version == 4) && (ihl >= 5) end |
#pseudo_header_checksum ⇒ Integer
Get IP part of pseudo header checksum.
211 212 213 214 |
# File 'lib/packetgen/header/ip.rb', line 211 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
257 258 259 260 |
# File 'lib/packetgen/header/ip.rb', line 257 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).
249 250 251 252 |
# File 'lib/packetgen/header/ip.rb', line 249 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.
222 223 224 225 226 227 |
# File 'lib/packetgen/header/ip.rb', line 222 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 |