Class: PacketGen::Header::IP

Inherits:
Base 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

A IP header consists of:

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'

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

Attributes inherited from Base

#packet

Class Method Summary collapse

Instance Method Summary collapse

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

#bodyTypes::String, Header::Base



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

define_field :body, Types::String

#checksumInteger

Returns 16-bit IP header checksum.

Returns:

  • (Integer)

    16-bit IP header checksum



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

define_field :checksum, Types::Int16, default: 0

#dstAddr

Returns destination IP address.

Returns:

  • (Addr)

    destination IP address



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

define_field :dst, Addr, default: '127.0.0.1'

#flag_dfBoolean

Returns Don’t Fragment flag.

Returns:

  • (Boolean)

    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_mfBoolean

Returns More Fragment flags.

Returns:

  • (Boolean)

    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_rsvBoolean

Returns reserved bit from flags.

Returns:

  • (Boolean)

    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

#fragInteger

Returns 16-bit frag word.

Returns:

  • (Integer)

    16-bit frag word



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

define_field :frag, Types::Int16, default: 0

#fragment_offsetInteger

Returns 13-bit fragment offset.

Returns:

  • (Integer)

    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

#idInteger

Returns 16-bit ID.

Returns:

  • (Integer)

    16-bit ID



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

define_field :id, Types::Int16, default: ->(h) { rand(65_535) }

#ihlInteger

Returns 4-bit IP header length attribute.

Returns:

  • (Integer)

    4-bit IP header length attribute



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

define_bit_fields_on :u8, :version, 4, :ihl, 4

#lengthInteger

Returns 16-bit IP total length.

Returns:

  • (Integer)

    16-bit IP total length



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

define_field :length, Types::Int16, default: 20

#optionsTypes::String

Returns:

Since:

  • 2.2.0



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

define_field :options, Options, optional: ->(h) { h.ihl > 5 }

#protocolInteger

Returns 8-bit upper protocol self.

Returns:

  • (Integer)

    8-bit upper protocol self



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

define_field :protocol, Types::Int8

#srcAddr

Returns source IP address.

Returns:

  • (Addr)

    source IP address



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

define_field :src, Addr, default: '127.0.0.1'

#tosInteger

Returns 8-bit Type of Service self.

Returns:

  • (Integer)

    8-bit Type of Service self



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

define_field :tos, Types::Int8, default: 0

#ttlInteger

Returns 8-bit Time To Live self.

Returns:

  • (Integer)

    8-bit Time To Live self



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

define_field :ttl, Types::Int8, default: 64

#u8Integer

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

Returns:

  • (Integer)

    first byte of IP header.



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

define_field :u8, Types::Int8, default: 0x45

#versionInteger

Returns 4-bit version attribute.

Returns:

  • (Integer)

    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

Helper method to reduce an IP checksum. This method:

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

  • inverts reduced self.

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

Parameters:

  • checksum (Integer)

    checksum to reduce

Returns:

  • (Integer)

    reduced checksum



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.

Parameters:

  • hdr (#to_s)

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

Returns:

  • (Integer)


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_checksumInteger

Compute checksum and set checksum field

Returns:

  • (Integer)


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
  options.to_s.unpack('n*').each { |x| checksum += x }
  self[:checksum].value = IP.reduce_checksum(checksum)
end

#calc_lengthInteger

Compute length and set length field

Returns:

  • (Integer)


212
213
214
# File 'lib/packetgen/header/ip.rb', line 212

def calc_length
  Base.calculate_and_set_length self
end

#inspectString

Returns:

  • (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

Returns:

  • (Boolean)

See Also:

  • PacketGen::Header::IP.[Base[Base#parse?]


262
263
264
# File 'lib/packetgen/header/ip.rb', line 262

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

#pseudo_header_checksumInteger

Get IP part of pseudo header checksum.

Returns:

  • (Integer)


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

Parameters:

  • str (String)

Returns:

  • (Fields)

    self



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

Returns:

  • (self)

Since:

  • 2.7.0



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_sObject

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 + 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.

Parameters:

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

    interface name. Not used



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