1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
"""
the Dynamic Host Configuration Protocol (DHCP) for IPv6
http://www.networksorcery.com/enp/rfc/rfc3315.txt
"""
from construct import *
from ipv6 import Ipv6Address
import six
dhcp_option = Struct("dhcp_option",
Enum(UBInt16("code"),
OPTION_CLIENTID = 1,
OPTION_SERVERID = 2,
OPTION_IA_NA = 3,
OPTION_IA_TA = 4,
OPTION_IAADDR = 5,
OPTION_ORO = 6,
OPTION_PREFERENCE = 7,
OPTION_ELAPSED_TIME = 8,
OPTION_RELAY_MSG = 9,
OPTION_AUTH = 11,
OPTION_UNICAST = 12,
OPTION_STATUS_CODE = 13,
OPTION_RAPID_COMMIT = 14,
OPTION_USER_CLASS = 15,
OPTION_VENDOR_CLASS = 16,
OPTION_VENDOR_OPTS = 17,
OPTION_INTERFACE_ID = 18,
OPTION_RECONF_MSG = 19,
OPTION_RECONF_ACCEPT = 20,
SIP_SERVERS_DOMAIN_NAME_LIST = 21,
SIP_SERVERS_IPV6_ADDRESS_LIST = 22,
DNS_RECURSIVE_NAME_SERVER = 23,
DOMAIN_SEARCH_LIST = 24,
OPTION_IA_PD = 25,
OPTION_IAPREFIX = 26,
OPTION_NIS_SERVERS = 27,
OPTION_NISP_SERVERS = 28,
OPTION_NIS_DOMAIN_NAME = 29,
OPTION_NISP_DOMAIN_NAME = 30,
SNTP_SERVER_LIST = 31,
INFORMATION_REFRESH_TIME = 32,
BCMCS_CONTROLLER_DOMAIN_NAME_LIST = 33,
BCMCS_CONTROLLER_IPV6_ADDRESS_LIST = 34,
OPTION_GEOCONF_CIVIC = 36,
OPTION_REMOTE_ID = 37,
RELAY_AGENT_SUBSCRIBER_ID = 38,
OPTION_CLIENT_FQDN = 39,
),
UBInt16("length"),
Field("data", lambda ctx: ctx.length),
)
client_message = Struct("client_message",
Bitwise(BitField("transaction_id", 24)),
)
relay_message = Struct("relay_message",
Byte("hop_count"),
Ipv6Address("linkaddr"),
Ipv6Address("peeraddr"),
)
dhcp_message = Struct("dhcp_message",
Enum(Byte("msgtype"),
# these are client-server messages
SOLICIT = 1,
ADVERTISE = 2,
REQUEST = 3,
CONFIRM = 4,
RENEW = 5,
REBIND = 6,
REPLY = 7,
RELEASE_ = 8,
DECLINE_ = 9,
RECONFIGURE = 10,
INFORMATION_REQUEST = 11,
# these two are relay messages
RELAY_FORW = 12,
RELAY_REPL = 13,
),
# relay messages have a different structure from client-server messages
Switch("params", lambda ctx: ctx.msgtype,
{
"RELAY_FORW" : relay_message,
"RELAY_REPL" : relay_message,
},
default = client_message,
),
Rename("options", GreedyRange(dhcp_option)),
)
if __name__ == "__main__":
test1 = six.b("\x03\x11\x22\x33\x00\x17\x00\x03ABC\x00\x05\x00\x05HELLO")
test2 = six.b("\x0c\x040123456789abcdef0123456789abcdef\x00\x09\x00\x0bhello world\x00\x01\x00\x00")
print (dhcp_message.parse(test1))
print (dhcp_message.parse(test2))
|