DHCPv6

The system provides a Python object alc.dhcpv6 to inspect and modify DHCPv6 packets.

The alc.dhcpv6 object

Attributes

The object exposes the header fields as 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

alc.Dhcp6.drop()

Drops the packet.

alc.Dhcp6.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)
alc.Dhcp6.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’,)
alc.Dhcp6.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')
alc.Dhcp6.clear(op_code, /)

Remove all options with specified option-code.

Parameters

option_code (int) – option-code to clear

alc.Dhcp6.get_iana()

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

Return type

OPDL

alc.Dhcp6.set_iana(opdl, /)

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

Parameters

value (OPDL) – IA_NA option to be set

alc.Dhcp6.get_iata()

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

Return type

OPDL

alc.Dhcp6.set_iata(opdl, /)

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

Parameters

value (OPDL) – IA_TA option to be set

alc.Dhcp6.get_iapd()

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

Return type

OPDL

alc.Dhcp6.set_iapd(opdl, /)

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

Parameters

value (OPDL) – IA_PD option to be set

alc.Dhcp6.get_vendoropts()

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

Return type

OPDL

alc.Dhcp6.set_vendoropts(opdl, /)

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

Parameters

value (OPDL) – vendor specific option to set

alc.Dhcp6.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 alc.Dhcpv6.get_relaymsg() can also be modified in-place. However, these changes do not automatically propagate to the outer packet. This occurs only when the alc.Dhcpv6.set_relaymsg() method is called on the outer packet with the modified embedded packet as the argument.

alc.Dhcp6.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 alc.Dhcpv6.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)