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.
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
- 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.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.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.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
- 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 thealc.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
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)