Class: PacketGen::Header::IP

Inherits:
Base
  • Object
show all
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:

Examples:

Create a IP header

# standalone
ip = PacketGen::Header::IP.new
# in a packet
pkt = PacketGen.gen('IP')
# access to IP header
pkt.ip.class   # => PacketGen::Header::IP

IP attributes

ip = PacketGen::Header::IP.new
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?  # => false
ip.flag_df?   # => false
ip.flag_mf?   # => true

ip.ttl = 0x40
ip.protocol = 6
ip.checksum = 0xffff
ip.src = '127.0.0.1'
ip.src                # => "127.0.0.1"
ip[:src].class        # => PacketGen::Header::IP::Addr
ip.dst = '127.0.0.2'
ip.body = 'this is a body'

Add IP options

pkt = PacketGen.gen('IP')
# add option from class
pkt.ip.options << PacketGen::Header::IP::RA.new
# or use a hash
pkt.ip.options << { type: 'RR', data: ['192.168.16.4']}

Author:

  • Sylvain Daubert

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

Class Method Summary collapse

Instance Method Summary collapse

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

Constructor Details

This class inherits a constructor from PacketGen::Header::Base

Instance Attribute Details

#bodyBinStruct::String, Headerable

IP body

Returns:



166
# File 'lib/packetgen/header/ip.rb', line 166

define_attr :body, BinStruct::String

#checksumInteger

16-bit IP header checksum

Returns:

  • (Integer)


148
# File 'lib/packetgen/header/ip.rb', line 148

define_attr :checksum, BinStruct::Int16, default: 0

#dstAddr

destination IP address

Returns:



156
# File 'lib/packetgen/header/ip.rb', line 156

define_attr :dst, Addr, default: '127.0.0.1'

#flag_dfBoolean

Don’t Fragment flag

Returns:

  • (Boolean)


136
# File 'lib/packetgen/header/ip.rb', line 136

define_bit_attr :frag, flag_rsv: 1, flag_df: 1, flag_mf: 1, fragment_offset: 13

#flag_mfBoolean

More Fragment flags

Returns:

  • (Boolean)


136
# File 'lib/packetgen/header/ip.rb', line 136

define_bit_attr :frag, flag_rsv: 1, flag_df: 1, flag_mf: 1, fragment_offset: 13

#flag_rsvBoolean

reserved bit from flags

Returns:

  • (Boolean)


136
# File 'lib/packetgen/header/ip.rb', line 136

define_bit_attr :frag, flag_rsv: 1, flag_df: 1, flag_mf: 1, fragment_offset: 13

#fragInteger

16-bit frag word

Returns:

  • (Integer)


136
# File 'lib/packetgen/header/ip.rb', line 136

define_bit_attr :frag, flag_rsv: 1, flag_df: 1, flag_mf: 1, fragment_offset: 13

#fragment_offsetInteger

13-bit fragment offset

Returns:

  • (Integer)


136
# File 'lib/packetgen/header/ip.rb', line 136

define_bit_attr :frag, flag_rsv: 1, flag_df: 1, flag_mf: 1, fragment_offset: 13

#idInteger

Returns 16-bit ID.

Returns:

  • (Integer)

    16-bit ID



120
# File 'lib/packetgen/header/ip.rb', line 120

define_attr :id, BinStruct::Int16, default: ->(_) { rand(65_535) }

#ihlInteger

4-bit IP header length attribute, as 32-bit word count. Default to 5 (IP header without option).

Returns:

  • (Integer)


110
# File 'lib/packetgen/header/ip.rb', line 110

define_bit_attr :u8, default: 0x45, version: 4, ihl: 4

#lengthInteger

16-bit IP total length, including this header.

Returns:

  • (Integer)


117
# File 'lib/packetgen/header/ip.rb', line 117

define_attr :length, BinStruct::Int16, default: 20

#optionsOptions

IP options

Returns:

Since:

  • 2.2.0



161
162
# File 'lib/packetgen/header/ip.rb', line 161

define_attr :options, Options, optional: ->(h) { h.ihl > 5 },
builder: ->(h, t) { t.new(length_from: -> { (h.ihl - 5) * 4 }) }

#protocolInteger

8-bit upper protocol

Returns:

  • (Integer)


144
# File 'lib/packetgen/header/ip.rb', line 144

define_attr :protocol, BinStruct::Int8

#srcAddr

source IP address

Returns:



152
# File 'lib/packetgen/header/ip.rb', line 152

define_attr :src, Addr, default: '127.0.0.1'

#tosInteger

Returns 8-bit Type of Service self.

Returns:

  • (Integer)

    8-bit Type of Service self



113
# File 'lib/packetgen/header/ip.rb', line 113

define_attr :tos, BinStruct::Int8, default: 0

#ttlInteger

8-bit Time To Live

Returns:

  • (Integer)


140
# File 'lib/packetgen/header/ip.rb', line 140

define_attr :ttl, BinStruct::Int8, default: 64

#u8Integer

First byte of IP header. May be accessed through #version and #ihl.

Returns:

  • (Integer)

    first byte of IP header.



110
# File 'lib/packetgen/header/ip.rb', line 110

define_bit_attr :u8, default: 0x45, version: 4, ihl: 4

#versionInteger

4-bit version attribute

Returns:

  • (Integer)


110
# File 'lib/packetgen/header/ip.rb', line 110

define_bit_attr :u8, default: 0x45, version: 4, ihl: 4

Class Method Details

.reduce_checksum(checksum) ⇒ Integer

Helper method to reduce an IP checksum. This method:

  • checks a checksum is not greater than 0xffff. If it is, reduces it.

  • inverts reduced checksum.

  • forces checksum to 0xffff if computed checksum is 0.

Parameters:

  • checksum (Integer)

    checksum to reduce

Returns:

  • (Integer)

    reduced checksum



197
198
199
200
201
# File 'lib/packetgen/header/ip.rb', line 197

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.

Parameters:

  • hdr (#to_s)

    header or other object on which calculates a sum of 16-bit words.

Returns:

  • (Integer)


173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/packetgen/header/ip.rb', line 173

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_checksumInteger

Compute checksum and set checksum field

Returns:

  • (Integer)


205
206
207
208
209
210
211
212
# File 'lib/packetgen/header/ip.rb', line 205

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_lengthInteger

Compute and set length and ihl field

Returns:

  • (Integer)

Since:

  • 3.0.0 add ihl calculation



217
218
219
220
# File 'lib/packetgen/header/ip.rb', line 217

def calc_length
  Base.calculate_and_set_length(self)
  self.ihl = 5 + self[:options].sz / 4
end

#parse?Boolean

Check version field

Returns:

  • (Boolean)

See Also:



245
246
247
# File 'lib/packetgen/header/ip.rb', line 245

def parse?
  (version == 4) && (ihl >= 5)
end

#pseudo_header_checksumInteger

Get IP part of pseudo header checksum.

Returns:

  • (Integer)


224
225
226
227
# File 'lib/packetgen/header/ip.rb', line 224

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

Returns:

  • (self)

Since:

  • 2.7.0



259
260
261
262
# File 'lib/packetgen/header/ip.rb', line 259

def reply!
  self[:src], self[:dst] = self[:dst], self[:src]
  self
end

#to_sObject

Get binary string. Fixup IHL if needed (IP header has options, and IHL was not set by user).



251
252
253
254
# File 'lib/packetgen/header/ip.rb', line 251

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 attributes are set by kernel, so bad IP packets cannot be sent this way. To do so, use Eth#to_w.

Parameters:

  • _iface (String, nil) (defaults to: nil)

    interface name. Not used



235
236
237
238
239
240
# File 'lib/packetgen/header/ip.rb', line 235

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