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 classalc.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.
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 |
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
- set_iana(opdl, /)
Sets the IA_NA(3) option as an OPDL data structure.
- Parameters
value (OPDL) – IA_NA option to be set
- set_iata(opdl, /)
Sets the IA_TA(3) option as an OPDL data structure.
- Parameters
value (OPDL) – IA_TA option to be set
- set_iapd(opdl, /)
Sets the IA_PD(3) option as an OPDL data structure.
- Parameters
value (OPDL) – IA_PD option to be set
- 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 theset_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
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)