Class: PacketGen::Header::IPv6

Inherits:
Struct
  • Object
show all
Extended by:
HeaderClassMethods
Includes:
HeaderMethods, StructFu
Defined in:
lib/packetgen/header/ipv6.rb

Overview

A IPv6 header consists of:

Create a IPv6 header

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

IPv6 attributes

ipv6.u32 = 0x60280001
# the same as
ipv6.version = 6
ipv6.traffic_class = 2
ipv6.flow_label = 0x80001

ipv6.length = 0x43
ipv6.hop = 0x40
ipv6.next = 6
ipv6.src = '::1'
ipv6.src                # => "::1"
ipv6[:src]              # => PacketGen::Header::IPv6::Addr
ipv6.dst = '2001:1234:5678:abcd::123'
ipv6.body.read 'this is a body'

Author:

  • Sylvain Daubert

Defined Under Namespace

Classes: Addr

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from HeaderClassMethods

bind_header, define_bit_fields_on, known_headers

Methods included from HeaderMethods

#header_id, #ip_header, #packet, #packet=, #protocol_name

Methods included from StructFu

#clone, #set_endianness, #sz, #to_s, #typecast

Methods inherited from Struct

#force_binary

Constructor Details

#initialize(options = {}) ⇒ IPv6

Returns a new instance of IPv6.

Parameters:

  • options (Hash) (defaults to: {})

Options Hash (options):

  • :version (Integer)
  • :traffic_class (Integer)
  • :flow_label (Integer)
  • :length (Integer)

    payload length

  • :next (Integer)
  • :hop (Integer)
  • :src (String)

    colon-delimited source address

  • :dst (String)

    colon-delimited destination address

  • :body (String)

    binary string



133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/packetgen/header/ipv6.rb', line 133

def initialize(options={})
  super Int32.new(0x60000000),
        Int16.new(options[:length]),
        Int8.new(options[:next]),
        Int8.new(options[:hop] || 64),
        Addr.new.from_human(options[:src] || '::1'),
        Addr.new.from_human(options[:dst] || '::1'),
        StructFu::String.new.read(options[:body])
  self.version = options[:version] if options[:version]
  self.traffic_class = options[:traffic_class] if options[:traffic_class]
  self.flow_label = options[:flow_label] if options[:flow_label]
end

Instance Attribute Details

#bodyObject

Returns the value of attribute body

Returns:

  • (Object)

    the current value of body



46
47
48
# File 'lib/packetgen/header/ipv6.rb', line 46

def body
  @body
end

#dstString Also known as: destination

Getter for dst attribute

Returns:



46
47
48
# File 'lib/packetgen/header/ipv6.rb', line 46

def dst
  @dst
end

#flow_labelInteger

Returns 20-bit flow_label attribute.

Returns:

  • (Integer)

    20-bit flow_label attribute



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

define_bit_fields_on :u32, :version, 4, :traffic_class, 8, :flow_label, 20

#hopInteger

Getter for hop attribute

Returns:

  • (Integer)


46
47
48
# File 'lib/packetgen/header/ipv6.rb', line 46

def hop
  @hop
end

#lengthObject



46
47
48
# File 'lib/packetgen/header/ipv6.rb', line 46

def length
  @length
end

#nextInteger

Getter for next attribute

Returns:

  • (Integer)


46
47
48
# File 'lib/packetgen/header/ipv6.rb', line 46

def next
  @next
end

#srcString Also known as: source

Getter for src attribute

Returns:



46
47
48
# File 'lib/packetgen/header/ipv6.rb', line 46

def src
  @src
end

#traffic_classInteger

Returns 8-bit traffic_class attribute.

Returns:

  • (Integer)

    8-bit traffic_class attribute



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

define_bit_fields_on :u32, :version, 4, :traffic_class, 8, :flow_label, 20

#u32Object

Returns the value of attribute u32

Returns:

  • (Object)

    the current value of u32



46
47
48
# File 'lib/packetgen/header/ipv6.rb', line 46

def u32
  @u32
end

#versionInteger

Returns 4-bit version attribute.

Returns:

  • (Integer)

    4-bit version attribute



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

define_bit_fields_on :u32, :version, 4, :traffic_class, 8, :flow_label, 20

Instance Method Details

#calc_lengthInteger

Compute length and set len field

Returns:

  • (Integer)


177
178
179
# File 'lib/packetgen/header/ipv6.rb', line 177

def calc_length
  self.length = body.sz
end

#inspectString

Returns:



290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
# File 'lib/packetgen/header/ipv6.rb', line 290

def inspect
  str = Inspect.dashed_line(self.class, 2)
  to_h.each do |attr, value|
    next if attr == :body
    str << Inspect.inspect_attribute(attr, value, 2)
    if attr == :u32
      shift = Inspect.shift_level(2)
      str << shift + Inspect::INSPECT_FMT_ATTR % ['', 'version', version]
      tclass = Inspect.int_dec_hex(traffic_class, 2)
      str << shift + Inspect::INSPECT_FMT_ATTR % ['', 'tclass', tclass]
      fl_value = Inspect.int_dec_hex(flow_label, 5)
      str << shift + Inspect::INSPECT_FMT_ATTR % ['', 'flow_label', fl_value]
    end
  end
  str
end

#pseudo_header_checksumInteger

Get IPv6 part of pseudo header checksum.

Returns:

  • (Integer)


252
253
254
255
256
257
# File 'lib/packetgen/header/ipv6.rb', line 252

def pseudo_header_checksum
  sum = 0
  self[:src].each { |word| sum += word.to_i }
  self[:dst].each { |word| sum += word.to_i }
  sum
end

#read(str) ⇒ self

Read a IP header from a string

Parameters:

  • str (String)

    binary string

Returns:

  • (self)

Raises:



157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/packetgen/header/ipv6.rb', line 157

def read(str)
  return self if str.nil?
  raise ParseError, 'string too short for IPv6' if str.size < self.sz
  force_binary str
  first32 = str[0, 4].unpack('N').first
  self.version = first32 >> 28
  self.traffic_class = (first32 >> 20) & 0xff
  self.flow_label = first32 & 0xfffff

  self[:length].read str[4, 2]
  self[:next].read str[6, 1]
  self[:hop].read str[7, 1]
  self[:src].read str[8, 16]
  self[:dst].read str[24, 16]
  self[:body].read str[40..-1]
  self
end

#to_w(iface = nil) ⇒ void

This method returns an undefined value.

Send IPv6 packet on wire.

When sending packet at IPv6 level, version, flow_label and length fields are set by kernel. Source address should be a unicast address assigned to the host. To set any of this fields, use Eth#to_w.

Parameters:

  • iface (String) (defaults to: nil)

    interface name

Raises:



266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
# File 'lib/packetgen/header/ipv6.rb', line 266

def to_w(iface=nil)
  sock = Socket.new(Socket::AF_INET6, Socket::SOCK_RAW, self.next)
  sockaddrin = Socket.sockaddr_in(0, dst)

  # IPv6 RAW sockets don't have IPHDRINCL option to send IPv6 header.
  # So, header must be built using ancillary data.
  # Only src address, traffic_class and hop_limit can be set this way.
  hop_limit = Socket::AncillaryData.int(Socket::AF_INET6,
                                        Socket::IPPROTO_IPV6,
                                        Socket::IPV6_HOPLIMIT, hop)
  tc = Socket::AncillaryData.int(Socket::AF_INET6,
                                 Socket::IPPROTO_IPV6,
                                 Socket::IPV6_TCLASS,
                                 traffic_class)

  # src address is set through PKT_INFO, which needs interface index.
  ifaddr = Socket.getifaddrs.find { |ia| ia.name == iface }
  raise WireError, "unknown #{iface} interface" if ifaddr.nil?
  pkt_info = Socket::AncillaryData.ipv6_pktinfo(Addrinfo.ip(src), ifaddr.ifindex)

  sock.sendmsg body.to_s, 0, sockaddrin, hop_limit, tc, pkt_info
end