Skip to content

Commit 83f8bc4

Browse files
DHCPv6: add RFC9686 support (#4694)
This adds 2 new DHCPv6 messages and 1 new DHCPv6 option - ADDR-REG-INFORM message added - ADDR-REG-REPLY message added - ADDR-REG option added - Flake8 appeased - Unit-tests added
1 parent f8f35a6 commit 83f8bc4

File tree

2 files changed

+96
-2
lines changed

2 files changed

+96
-2
lines changed

scapy/layers/dhcp6.py

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,10 @@ def get_cls(name, fallback_cls):
5757
10: "DHCP6_Reconf",
5858
11: "DHCP6_InfoRequest",
5959
12: "DHCP6_RelayForward",
60-
13: "DHCP6_RelayReply"}
60+
13: "DHCP6_RelayReply",
61+
36: "DHCP6_AddrRegInform",
62+
37: "DHCP6_AddrRegReply",
63+
}
6164

6265

6366
def _dhcp6_dispatcher(x, *args, **kargs):
@@ -128,6 +131,7 @@ def _dhcp6_dispatcher(x, *args, **kargs):
128131
79: "OPTION_CLIENT_LINKLAYER_ADDR", # RFC6939
129132
103: "OPTION_CAPTIVE_PORTAL", # RFC8910
130133
112: "OPTION_MUD_URL", # RFC8520
134+
148: "OPTION_ADDR_REG_ENABLE", # RFC9686
131135
}
132136

133137
dhcp6opts_by_code = {1: "DHCP6OptClientId",
@@ -187,10 +191,12 @@ def _dhcp6_dispatcher(x, *args, **kargs):
187191
79: "DHCP6OptClientLinkLayerAddr", # RFC6939
188192
103: "DHCP6OptCaptivePortal", # RFC8910
189193
112: "DHCP6OptMudUrl", # RFC8520
194+
148: "DHCP6OptAddrRegEnable", # RFC9686
190195
}
191196

192197

193198
# sect 7.3 RFC 8415 : DHCP6 Messages types
199+
# also RFC 9686
194200
dhcp6types = {1: "SOLICIT",
195201
2: "ADVERTISE",
196202
3: "REQUEST",
@@ -203,7 +209,10 @@ def _dhcp6_dispatcher(x, *args, **kargs):
203209
10: "RECONFIGURE",
204210
11: "INFORMATION-REQUEST",
205211
12: "RELAY-FORW",
206-
13: "RELAY-REPL"}
212+
13: "RELAY-REPL",
213+
36: "ADDR-REG-INFORM",
214+
37: "ADDR-REG-REPLY",
215+
}
207216

208217

209218
#####################################################################
@@ -1103,6 +1112,12 @@ class DHCP6OptMudUrl(_DHCP6OptGuessPayload): # RFC8520
11031112
)]
11041113

11051114

1115+
class DHCP6OptAddrRegEnable(_DHCP6OptGuessPayload): # RFC 9686 sect 4.1
1116+
name = "DHCP6 Address Registration Option"
1117+
fields_desc = [ShortEnumField("optcode", 148, dhcp6opts),
1118+
ShortField("optlen", 0)]
1119+
1120+
11061121
#####################################################################
11071122
# DHCPv6 messages #
11081123
#####################################################################
@@ -1437,6 +1452,24 @@ def answers(self, other):
14371452
self.peeraddr == other.peeraddr)
14381453

14391454

1455+
#####################################################################
1456+
# Address Registration-Inform Message (RFC 9686)
1457+
# - sent by clients who generated their own address and need it registered
1458+
1459+
class DHCP6_AddrRegInform(DHCP6):
1460+
name = "DHCPv6 Information Request Message"
1461+
msgtype = 36
1462+
1463+
#####################################################################
1464+
# Address Registration-Reply Message (RFC 9686)
1465+
# - sent by servers who respond to the address registration-inform message
1466+
1467+
1468+
class DHCP6_AddrRegReply(DHCP6):
1469+
name = "DHCPv6 Information Reply Message"
1470+
msgtype = 37
1471+
1472+
14401473
bind_bottom_up(UDP, _dhcp6_dispatcher, {"dport": 547})
14411474
bind_bottom_up(UDP, _dhcp6_dispatcher, {"dport": 546})
14421475

test/scapy/layers/dhcp6.uts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1310,6 +1310,19 @@ p = DHCP6OptVSS(s)
13101310
assert p.type == 255
13111311

13121312

1313+
############
1314+
############
1315+
+ Test DHCP6 Option - Address Registration Enabled
1316+
1317+
= DHCP6OptAddrRegEnable - Basic Instantiation
1318+
raw(DHCP6OptAddrRegEnable()) == b'\x00\x94\x00\x00'
1319+
1320+
= DHCP6OptAddrRegEnable - Basic Dissection
1321+
a=DHCP6OptAddrRegEnable(b'\x00\x94\x00\x00')
1322+
a.optcode == 148 and a.optlen == 0
1323+
1324+
1325+
13131326
############
13141327
############
13151328
+ Test DHCP6 Messages - DHCP6_Solicit
@@ -1564,4 +1577,52 @@ raw(DHCP6_RelayReply()) == b'\r\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
15641577
a=DHCP6_RelayReply(b'\r\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
15651578
a.msgtype == 13 and a.hopcount == 0 and a.linkaddr == "::" and a.peeraddr == "::"
15661579

1580+
############
1581+
############
1582+
+ Test DHCP6 Messages - DHCP6_AddrRegInform
1583+
1584+
= DHCP6_AddrRegInform - Basic Instantiation
1585+
raw(DHCP6_AddrRegInform()) == b'\x24\x00\x00\x00'
1586+
1587+
= DHCP6_AddrRegInform - Basic Dissection
1588+
a = DHCP6_AddrRegInform(b'\x24\x00\x00\x00')
1589+
a.msgtype == 36 and a.trid == 0
1590+
1591+
= DHCP6_AddrRegInform - Basic test of DHCP6_addrreginform.hashret()
1592+
DHCP6_AddrRegInform().hashret() == b'\x00\x00\x00'
1593+
1594+
= DHCP6_AddrRegInform - Test of DHCP6_addrreginform.hashret() with specific values
1595+
DHCP6_AddrRegInform(trid=0xbbccdd).hashret() == b'\xbb\xcc\xdd'
1596+
1597+
= DHCP6_AddrRegInform - UDP ports overload
1598+
a=UDP()/DHCP6_AddrRegInform()
1599+
a.sport == 546 and a.dport == 547
1600+
1601+
= DHCP6_AddrRegInform - Dispatch based on UDP port
1602+
a=UDP(raw(UDP()/DHCP6_AddrRegInform()))
1603+
isinstance(a.payload, DHCP6_AddrRegInform)
1604+
1605+
############
1606+
############
1607+
+ Test DHCP6 Messages - DHCP6_AddrRegReply
1608+
1609+
= DHCP6_AddrRegReply - Basic Instantiation
1610+
raw(DHCP6_AddrRegReply()) == b'\x25\x00\x00\x00'
1611+
1612+
= DHCP6_AddrRegReply - Basic Dissection
1613+
a = DHCP6_AddrRegReply(b'\x25\x00\x00\x00')
1614+
a.msgtype == 37 and a.trid == 0
1615+
1616+
= DHCP6_AddrRegReply - Basic test of DHCP6_addrregreply.hashret()
1617+
DHCP6_AddrRegReply().hashret() == b'\x00\x00\x00'
1618+
1619+
= DHCP6_AddrRegReply - Test of DHCP6_addrregreply.hashret() with specific values
1620+
DHCP6_AddrRegReply(trid=0xbbccdd).hashret() == b'\xbb\xcc\xdd'
1621+
1622+
= DHCP6_AddrRegReply - UDP ports overload
1623+
a=UDP()/DHCP6_AddrRegReply()
1624+
a.sport == 546 and a.dport == 547
15671625

1626+
= DHCP6_AddrRegReply - Dispatch based on UDP port
1627+
a=UDP(raw(UDP()/DHCP6_AddrRegReply()))
1628+
isinstance(a.payload, DHCP6_AddrRegReply)

0 commit comments

Comments
 (0)