DHCPv6

The system provides a Python object alc.dhcpv6, which is an instance of class alc.Dhcpv6, to inspect and modify DHCPv6 packets.

Note

Only the pre-provided alc.dhcpv6 object should be used in script, the class alc.Dhcpv6 should not be used directly.

The alc.Dhcpv6 class

Instance Attributes

DHCPv6 header fields are exposed as instance attributes on the object. Depending on the message-type (client-server or relay), different attributes are supported. Trying to fetch an attribute from a different message-type raises an AttributeError.

Attributes defined on client-server messages

Attribute

Field

Access

Type

pkt_len

total length, in bytes, of the original DHCPv6-layer

ro

int

msg_type

msg-type

ro

bytes

transaction_id

transaction-id

ro

bytes

Attributes defined on relay messages

Attribute

Field

Access

Type

pkt_len

total length, in bytes, of the original DHCPv6-layer

ro

int

msg_type

msg-type

ro

bytes

hop_count

hop-count

rw

bytes

link_addr

link-address

rw

bytes

peer_addr

peer-address

rw

bytes

Methods

drop()

Drops the packet.

getOptionList()

Returns a tuple of option-codes that are present in the top-level packet.

  • The order of the elements is the same as they appear in the packet.

  • If there are multiple instances of the same option, the option-code also appears multiple times in the tuple.

# for a c/s packet with options
# Elapsed Time/Client Identifier/IANA/FQDN/Vendor Class/Option Request
print(alc.dhcpv6.getOptionList())
# (8, 1, 3, 39, 16, 6)
get(op_code, /)

Returns a tuple of all values of options with the specified option-code. The values are returned as the exact bytestrings as they appear in the packet.

  • If the specified option does not exist, the result is an empty tuple: ()

  • If a specific instance has zero length or no values, the corresponding bytestring in the result tuple is an empty bytestring: b””

param int option_code

option-code to fetch

rtype

tuple of bytestrings

# For a packet with status-code option (code=0, msg="Address Assigned"):
print(alc.dhcpv6.get(13))
# (b‘\x00\x00Address Assigned’,)
set(op_code, value, /)

Deletes existing options of the specified code and inserts new options with the specified code and value. Multiple values can be specified in a tuple, in which case an option is added for each item in the tuple.

param int option_code

option-code to set

param bytes|tuple(bytes) value

value of the option; the length is computed from this value

# To insert an address lease time option(51) with value 60:
alc.dhcpv6.set(51, b'\x00\x00\x00\x3c')
clear(op_code, /)

Removes all options with specified option-code.

Parameters

option_code (int) – option-code to clear

get_iana()

Retrieves the IA_NA(3) option as an OPDL data structure.

Return type

OPDL

set_iana(opdl, /)

Sets the IA_NA(3) option as an OPDL data structure.

Parameters

value (OPDL) – IA_NA option to be set

get_iata()

Retrieves the IA_TA(4) option as an OPDL data structure.

Return type

OPDL

set_iata(opdl, /)

Sets the IA_TA(3) option as an OPDL data structure.

Parameters

value (OPDL) – IA_TA option to be set

get_iapd()

Retrieves the IA_PD(25) option as an OPDL data structure.

Return type

OPDL

set_iapd(opdl, /)

Sets the IA_PD(3) option as an OPDL data structure.

Parameters

value (OPDL) – IA_PD option to be set

get_vendoropts()

Retrieves the vendor_opts(17) option as an OPDL data structure.

Return type

OPDL

set_vendoropts(opdl, /)

Sets the vendor_opts(17) option as an OPDL data structure.

Parameters

value (OPDL) – vendor specific option to set

get_relaymsg()

Returns the embedded relay-message.

Return type

alc.Dhcpv6

Raises

RuntimeError – when invoked on a client-server message

Note

The embedded packet returned from get_relaymsg() can also be modified in-place. However, these changes do not automatically propagate to the outer packet. This occurs only when the set_relaymsg() method is called on the outer packet with the modified embedded packet as the argument.

set_relaymsg(msg, /)

Replaces the current relay-message option with the specified message.

Parameters

msg (alc.Dhcpv6) – DHCPv6 message to set as the relay-message

Raises

RuntimeError – when invoked on a client-server message

Option Datastructure List (OPDL)

The OPDL is a nested data structure which represents the value of some DHCPv6 options.

  • An OPDL is a list where each element represents an instance of that option (referred to as an OPD). The elements are ordered as they appear in the packet.

  • An OPD is a list where each element represents one field in the option. The elements are ordered as they appear in the packet.

  • There are two types of fields in the OPD:

    • The first fields (if any) are bytestrings and correspond to fixed fields. The number and meaning are specific to the option.

    • The last field is a dictionary which contains the sub-options, where

      • the keys are the sub-option codes

      • the values are themselves an OPDL if the sub-options are supported, or a bytestring of the whole sub-option if not supported.

      • if there are no sub-options, the dictionary is empty.

In summary:

  • OPDL := [OPD, OPD, …]

  • OPD := [field, field, …, sub-options]

  • field := bytestring

  • sub-options := {sub-opt-code: sub-opt-value, …}

  • sub-opt-code := int

  • sub-opt-value := bytestring or OPDL

supported options and fields

Option

Fields

Sub-options

IA-NA(3)

[IAID, T1, T2]

IAADDR(5), Status Code(13)

IA-TA(4)

[IAID]

IA Address(5), Status Code(13)

IA-PD(25)

[IAID, T1, T2]

IA Prefix(26), Status Code(13)

Vendor Options(17)

[enterprise-number]

IA Address(5)

[ipv6addr, preferred-lifetime, valid-lifetime]

Status Code(13)

Status Code(13)

[status-code, status-message]

IA Prefix(26)

[preferred-lifetime, valid-lifetime, prefix-length, ipv6-prefix]

Status Code(13)

Note

The OPDL data structures that have been extracted from a alc.Dhcpv6 packet can be modified in-place. However, these changes do not automatically propagate to packet options. This occurs only when the corresponding set_xxx() method is called with the modified OPDL as the argument.

Example 1: Extract address from IA_NA option

With an IA_NA option as in the following:

Identity Association for Non-temporary Address
  Option: Identity Association for the Non-temporary Address (3)
  Length: 40
  Value:  0ff0def10002a30000043800000500182001055860450047...
  IAID:   0ff0def1
  T1:     172800
  T2:     276480
  IA Address: 2001:558:6045:47:45cc:d9f2:5727:eae0
    Option:             IA Address (5)
    Length:             24
    Value:              200105586045004745ccd9f25727eae00005460000054600
    IPv6 address:       2001:558:6045:47:45cc:d9f2:5727:eae0
    Preferred lifetime: 345600
    Valid lifetime:     345600

The following extracts the address from the IA_NA option:

opdl = alc.dhcpv6.get_iana()
# opdl: [[b'\x0f\xf0\xde\xf1', b'\x00\x02\xa3\x00', b'\x00\x048\x00', {5: [[b" \x01\x05X`E\x00GE\xcc\xd9\xf2W'\xea\xe0", b'\x00\x05F\x00', b'\x00\x05F\x00', {}]]}]]
addresses = [hexlify(sub_opd[0]) for opd in opdl for sub_opd in opd[3][5]]
# addresses: [b'200105586045004745ccd9f25727eae0']

Example 2: Extract information from IA_PD option

With an IA_PD option as in the following:

Identity Association for Prefix Delegation
  Option: Identity Association for Prefix Delegation (25)
  Length:  41
  Value:  000000010000070800000b40001a001900000e1000015180...
  IAID:  00000001
  T1:  1800
  T2:  2880
  IA  Prefix
    Option: IA Prefix (26)
    Length:  25
    Value:  00000e10000151803820010db80002000000000000000000...
    Preferred lifetime: 3600
    Valid lifetime: 86400
    Prefix length: 56
    Prefix address: 2001:db8:2::

The following code extracts the IAID, T1, and T2:

opdl = alc.dhcpv6.get_iapd()
# opdl: [[b'\x00\x00\x00\x01', b'\x00\x00\x07\x08', b'\x00\x00\x0b@', {26: [[b'\x00\x00\x0e\x10', b'\x00\x01Q\x80', b'8', b' \x01\r\xb8\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', {}]]}]]
iaid,t1,t2 = (int.from_bytes(x, 'big') for x in opdl[0][0:3])
# iaid,t1,t2 = (1, 1800, 2880)

Example 3: Extract Enterprise ID from Vendor Option

With a Vendor Option as in the following:

Vendor-specific Information
  Option: Vendor-specific Information (17)
  Length:  40
  Value:  0000197f0001000969612d6e615f3030310002000969612d...
  Enterprise ID: Panthera Networks, Inc. (6527)
  option
    option code: 1
    option length: 9
    option-data
  option
    option code: 2
    option length: 9
    option-data
  option
    option code: 3
    option length: 1
    option-data
  option
    option code: 4
    option length: 1
    option-data

The following code extracts the vendor ID:

opdl = alc.dhcpv6.get_vendoropts()
# opdl: [[b'\x00\x00\x19\x7f', {4: [b'@'], 1: [b'ia-na_001'], 2: [b'ia-pd_001'], 3: [b'8']}]]
vendor = int.from_bytes(opdl[0][0], 'big')
# vendor: 6527

Example 4: Change T1 of IA_NA option in relayed message

embed_dhcpv6_packet = alc.dhcpv6.get_relaymsg()
iana_list = embed_dhcpv6_packet.get_iana()
iana_list[0][1] = b'\x00\x00\x04\xb0' # change T1 to 1200
embed_dhcpv6_packet.set_iana(iana_list) #update the IA_NA of the embedded packet
alc.dhcpv6.set_relaymsg(embed_dhcpv6_packet) #update the Relay Message option

Example 5: Change T1 of IA_NA option in double relayed message

embed_lv1_packet = alc.dhcpv6.get_relaymsg()
embed_lv2_packet = embed_lv1_packet.get_relaymsg()
iana_list = embed_dhcpv6_packet.get_iana()
iana_list[0][1] = b'\x00\x00\x04\xb0' # change T1 to 1200
embed_lv2_packet.set_iana(iana_list)
embed_lv1_packet.set_relaymsg(embed_lv2_packet)
alc.dhcpv6.set_relaymsg(embed_lv1_packet)