QuLab 2.10.10__cp313-cp313-macosx_10_13_universal2.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- qulab/__init__.py +33 -0
- qulab/__main__.py +4 -0
- qulab/cli/__init__.py +0 -0
- qulab/cli/commands.py +30 -0
- qulab/cli/config.py +170 -0
- qulab/cli/decorators.py +28 -0
- qulab/dicttree.py +523 -0
- qulab/executor/__init__.py +5 -0
- qulab/executor/analyze.py +188 -0
- qulab/executor/cli.py +434 -0
- qulab/executor/load.py +563 -0
- qulab/executor/registry.py +185 -0
- qulab/executor/schedule.py +543 -0
- qulab/executor/storage.py +615 -0
- qulab/executor/template.py +259 -0
- qulab/executor/utils.py +194 -0
- qulab/expression.py +827 -0
- qulab/fun.cpython-313-darwin.so +0 -0
- qulab/monitor/__init__.py +1 -0
- qulab/monitor/__main__.py +8 -0
- qulab/monitor/config.py +41 -0
- qulab/monitor/dataset.py +77 -0
- qulab/monitor/event_queue.py +54 -0
- qulab/monitor/mainwindow.py +234 -0
- qulab/monitor/monitor.py +115 -0
- qulab/monitor/ploter.py +123 -0
- qulab/monitor/qt_compat.py +16 -0
- qulab/monitor/toolbar.py +265 -0
- qulab/scan/__init__.py +2 -0
- qulab/scan/curd.py +221 -0
- qulab/scan/models.py +554 -0
- qulab/scan/optimize.py +76 -0
- qulab/scan/query.py +387 -0
- qulab/scan/record.py +603 -0
- qulab/scan/scan.py +1166 -0
- qulab/scan/server.py +450 -0
- qulab/scan/space.py +213 -0
- qulab/scan/utils.py +234 -0
- qulab/storage/__init__.py +0 -0
- qulab/storage/__main__.py +51 -0
- qulab/storage/backend/__init__.py +0 -0
- qulab/storage/backend/redis.py +204 -0
- qulab/storage/base_dataset.py +352 -0
- qulab/storage/chunk.py +60 -0
- qulab/storage/dataset.py +127 -0
- qulab/storage/file.py +273 -0
- qulab/storage/models/__init__.py +22 -0
- qulab/storage/models/base.py +4 -0
- qulab/storage/models/config.py +28 -0
- qulab/storage/models/file.py +89 -0
- qulab/storage/models/ipy.py +58 -0
- qulab/storage/models/models.py +88 -0
- qulab/storage/models/record.py +161 -0
- qulab/storage/models/report.py +22 -0
- qulab/storage/models/tag.py +93 -0
- qulab/storage/storage.py +95 -0
- qulab/sys/__init__.py +2 -0
- qulab/sys/chat.py +688 -0
- qulab/sys/device/__init__.py +3 -0
- qulab/sys/device/basedevice.py +255 -0
- qulab/sys/device/loader.py +86 -0
- qulab/sys/device/utils.py +79 -0
- qulab/sys/drivers/FakeInstrument.py +68 -0
- qulab/sys/drivers/__init__.py +0 -0
- qulab/sys/ipy_events.py +125 -0
- qulab/sys/net/__init__.py +0 -0
- qulab/sys/net/bencoder.py +205 -0
- qulab/sys/net/cli.py +169 -0
- qulab/sys/net/dhcp.py +543 -0
- qulab/sys/net/dhcpd.py +176 -0
- qulab/sys/net/kad.py +1142 -0
- qulab/sys/net/kcp.py +192 -0
- qulab/sys/net/nginx.py +194 -0
- qulab/sys/progress.py +190 -0
- qulab/sys/rpc/__init__.py +0 -0
- qulab/sys/rpc/client.py +0 -0
- qulab/sys/rpc/exceptions.py +96 -0
- qulab/sys/rpc/msgpack.py +1052 -0
- qulab/sys/rpc/msgpack.pyi +41 -0
- qulab/sys/rpc/router.py +35 -0
- qulab/sys/rpc/rpc.py +412 -0
- qulab/sys/rpc/serialize.py +139 -0
- qulab/sys/rpc/server.py +29 -0
- qulab/sys/rpc/socket.py +29 -0
- qulab/sys/rpc/utils.py +25 -0
- qulab/sys/rpc/worker.py +0 -0
- qulab/sys/rpc/zmq_socket.py +227 -0
- qulab/tools/__init__.py +0 -0
- qulab/tools/connection_helper.py +39 -0
- qulab/typing.py +2 -0
- qulab/utils.py +95 -0
- qulab/version.py +1 -0
- qulab/visualization/__init__.py +188 -0
- qulab/visualization/__main__.py +71 -0
- qulab/visualization/_autoplot.py +464 -0
- qulab/visualization/plot_circ.py +319 -0
- qulab/visualization/plot_layout.py +408 -0
- qulab/visualization/plot_seq.py +242 -0
- qulab/visualization/qdat.py +152 -0
- qulab/visualization/rot3d.py +23 -0
- qulab/visualization/widgets.py +86 -0
- qulab-2.10.10.dist-info/METADATA +110 -0
- qulab-2.10.10.dist-info/RECORD +107 -0
- qulab-2.10.10.dist-info/WHEEL +5 -0
- qulab-2.10.10.dist-info/entry_points.txt +2 -0
- qulab-2.10.10.dist-info/licenses/LICENSE +21 -0
- qulab-2.10.10.dist-info/top_level.txt +1 -0
qulab/sys/net/dhcp.py
ADDED
@@ -0,0 +1,543 @@
|
|
1
|
+
# Packet format
|
2
|
+
# -------------
|
3
|
+
#
|
4
|
+
# Offset Length Notes
|
5
|
+
# ------ ------ -----
|
6
|
+
#
|
7
|
+
# 0 1 Operation code with 1 being request and 2 being response
|
8
|
+
# 1 1 Hardware type with 1 being "Ethernet 10Mb"
|
9
|
+
# 2 1 Hardware address length with 6 for Ethernet
|
10
|
+
# 3 1 Hops - usually 0 unless DHCP relaying in operation
|
11
|
+
# 4-7 4 Transaction ID (selected randomly by client)
|
12
|
+
# 8-9 2 Seconds - might be used by a server to prioritise requests
|
13
|
+
# 10-11 2 Flags (only most significan bit used for broadcast)
|
14
|
+
# 12-15 4 Client Internet address (might be requested by client)
|
15
|
+
# 16-19 4 Your Internet address (the IP assigned by the server)
|
16
|
+
# 20-23 4 Server Internet address (the IP of the server)
|
17
|
+
# 24-27 4 Gateway Internet address (if DHCP relaying in operation)
|
18
|
+
# 28-43 16 Client hardware address - only first 6 bytes used for Ethernet
|
19
|
+
# 44-107 64 Text name of server (optional)
|
20
|
+
# 108-235 128 Boot file name (optional - used for PXE booting)
|
21
|
+
# 236-239 4 Magic cookie (decimal values 99, 130, 83, 99 )
|
22
|
+
#
|
23
|
+
|
24
|
+
# Dynamic Host Configuration Protocol (DHCP) and Bootstrap Protocol (BOOTP) Parameters
|
25
|
+
# See http://www.iana.org/assignments/bootp-dhcp-parameters
|
26
|
+
|
27
|
+
import base64
|
28
|
+
import logging
|
29
|
+
import socket
|
30
|
+
from enum import Enum
|
31
|
+
from struct import Struct, pack, unpack
|
32
|
+
from typing import NamedTuple
|
33
|
+
|
34
|
+
MAGIC_COOKIE = b'c\x82Sc'
|
35
|
+
|
36
|
+
|
37
|
+
class DHCPOption(Enum):
|
38
|
+
PAD = 0 # 0 [RFC2132] None
|
39
|
+
SUBNET_MASK = 1 # 4 [RFC2132] Subnet Mask Value
|
40
|
+
TIME_OFFSET = 2 # 4 [RFC2132] Time Offset in Seconds from UTC (note: deprecated by 100 and 101)
|
41
|
+
ROUTER = 3 # N [RFC2132] N/4 Router addresses
|
42
|
+
TIME_SERVER = 4 # N [RFC2132] N/4 Timeserver addresses
|
43
|
+
NAME_SERVER = 5 # N [RFC2132] N/4 IEN-116 Server addresses
|
44
|
+
DOMAIN_SERVER = 6 # N [RFC2132] N/4 DNS Server addresses
|
45
|
+
LOG_SERVER = 7 # N [RFC2132] N/4 Logging Server addresses
|
46
|
+
QUOTES_SERVER = 8 # N [RFC2132] N/4 Quotes Server addresses
|
47
|
+
LPR_SERVER = 9 # N [RFC2132] N/4 Printer Server addresses
|
48
|
+
IMPRESS_SERVER = 10 # N [RFC2132] N/4 Impress Server addresses
|
49
|
+
RLP_SERVER = 11 # N [RFC2132] N/4 RLP Server addresses
|
50
|
+
HOSTNAME = 12 # N [RFC2132] Hostname string
|
51
|
+
BOOT_FILE_SIZE = 13 # 2 [RFC2132] Size of boot file in 512 byte chunks
|
52
|
+
MERIT_DUMP_FILE = 14 # N [RFC2132] Client to dump and name the file to dump it to
|
53
|
+
DOMAIN_NAME = 15 # N [RFC2132] The DNS domain name of the client
|
54
|
+
SWAP_SERVER = 16 # N [RFC2132] Swap Server address
|
55
|
+
ROOT_PATH = 17 # N [RFC2132] Path name for root disk
|
56
|
+
EXTENSION_FILE = 18 # N [RFC2132] Path name for more BOOTP info
|
57
|
+
FORWARD = 19 # 1 [RFC2132] Enable/Disable IP Forwarding
|
58
|
+
SRCRTE = 20 # 1 [RFC2132] Enable/Disable Source Routing
|
59
|
+
POLICY_FILTER = 21 # N [RFC2132] Routing Policy Filters
|
60
|
+
MAX_DG_ASSEMBLY = 22 # 2 [RFC2132] Max Datagram Reassembly Size
|
61
|
+
DEFAULT_IP_TTL = 23 # 1 [RFC2132] Default IP Time to Live
|
62
|
+
MTU_TIMEOUT = 24 # 4 [RFC2132] Path MTU Aging Timeout
|
63
|
+
MTU_PLATEAU = 25 # N [RFC2132] Path MTU Plateau Table
|
64
|
+
MTU_INTERFACE = 26 # 2 [RFC2132] Interface MTU Size
|
65
|
+
MTU_SUBNET = 27 # 1 [RFC2132] All Subnets are Local
|
66
|
+
BROADCAST_ADDRESS = 28 # 4 [RFC2132] Broadcast Address
|
67
|
+
MASK_DISCOVERY = 29 # 1 [RFC2132] Perform Mask Discovery
|
68
|
+
MASK_SUPPLIER = 30 # 1 [RFC2132] Provide Mask to Others
|
69
|
+
ROUTER_DISCOVERY = 31 # 1 [RFC2132] Perform Router Discovery
|
70
|
+
ROUTER_REQUEST = 32 # 4 [RFC2132] Router Solicitation Address
|
71
|
+
STATIC_ROUTE = 33 # N [RFC2132] Static Routing Table
|
72
|
+
TRAILERS = 34 # 1 [RFC2132] Trailer Encapsulation
|
73
|
+
ARP_TIMEOUT = 35 # 4 [RFC2132] ARP Cache Timeout
|
74
|
+
ETHERNET = 36 # 1 [RFC2132] Ethernet Encapsulation
|
75
|
+
DEFAULT_TCP_TTL = 37 # 1 [RFC2132] Default TCP Time to Live
|
76
|
+
KEEPALIVE_TIME = 38 # 4 [RFC2132] TCP Keepalive Interval
|
77
|
+
KEEPALIVE_DATA = 39 # 1 [RFC2132] TCP Keepalive Garbage
|
78
|
+
NIS_DOMAIN = 40 # N [RFC2132] NIS Domain Name
|
79
|
+
NIS_SERVERS = 41 # N [RFC2132] NIS Server Addresses
|
80
|
+
NTP_SERVERS = 42 # N [RFC2132] NTP Server Addresses
|
81
|
+
VENDOR_SPECIFIC = 43 # N [RFC2132] Vendor Specific Information
|
82
|
+
NETBIOS_NAME_SRV = 44 # N [RFC2132] NETBIOS Name Servers
|
83
|
+
NETBIOS_DIST_SRV = 45 # N [RFC2132] NETBIOS Datagram Distribution
|
84
|
+
NETBIOS_NODE_TYPE = 46 # 1 [RFC2132] NETBIOS Node Type
|
85
|
+
NETBIOS_SCOPE = 47 # N [RFC2132] NETBIOS Scope
|
86
|
+
X_WINDOW_FONT = 48 # N [RFC2132] X Window Font Server
|
87
|
+
X_WINDOW_MANAGER = 49 # N [RFC2132] X Window Display Manager
|
88
|
+
ADDRESS_REQUEST = 50 # 4 [RFC2132] Requested IP Address
|
89
|
+
IP_LEASE_TIME = 51 # 4 [RFC2132] IP Address Lease Time
|
90
|
+
OVERLOAD = 52 # 1 [RFC2132] Overload "sname" or "file"
|
91
|
+
DHCP_MSG_TYPE = 53 # 1 [RFC2132] DHCP Message Type
|
92
|
+
SERVER_ID = 54 # 4 [RFC2132] DHCP Server Identification
|
93
|
+
PARAMETER_LIST = 55 # N [RFC2132] Parameter Request List
|
94
|
+
DHCP_MESSAGE = 56 # N [RFC2132] DHCP Error Message
|
95
|
+
DHCP_MAX_MSG_SIZE = 57 # 2 [RFC2132] DHCP Maximum Message Size
|
96
|
+
RENEWAL_TIME = 58 # 4 [RFC2132] DHCP Renewal (T1) Time
|
97
|
+
REBINDING_TIME = 59 # 4 [RFC2132] DHCP Rebinding (T2) Time
|
98
|
+
CLASS_ID = 60 # N [RFC2132] Class Identifier
|
99
|
+
CLIENT_ID = 61 # N [RFC2132] Client Identifier
|
100
|
+
NETWARE_IP_DOMAIN = 62 # N [RFC2242] NetWare/IP Domain Name
|
101
|
+
NETWARE_IP_OPTION = 63 # N [RFC2242] NetWare/IP sub Options
|
102
|
+
NIS_DOMAIN_NAME = 64 # N [RFC2132] NIS+ v3 Client Domain Name
|
103
|
+
NIS_SERVER_ADDR = 65 # N [RFC2132] NIS+ v3 Server Addresses
|
104
|
+
SERVER_NAME = 66 # N [RFC2132] TFTP Server Name
|
105
|
+
BOOTFILE_NAME = 67 # N [RFC2132] Boot File Name
|
106
|
+
HOME_AGENT_ADDRS = 68 # N [RFC2132] Home Agent Addresses
|
107
|
+
SMTP_SERVER = 69 # N [RFC2132] Simple Mail Server Addresses
|
108
|
+
POP3_SERVER = 70 # N [RFC2132] Post Office Server Addresses
|
109
|
+
NNTP_SERVER = 71 # N [RFC2132] Network News Server Addresses
|
110
|
+
WWW_SERVER = 72 # N [RFC2132] WWW Server Addresses
|
111
|
+
FINGER_SERVER = 73 # N [RFC2132] Finger Server Addresses
|
112
|
+
IRC_SERVER = 74 # N [RFC2132] Chat Server Addresses
|
113
|
+
STREETTALK_SERVER = 75 # N [RFC2132] StreetTalk Server Addresses
|
114
|
+
STDA_SERVER = 76 # N [RFC2132] ST Directory Assist. Addresses
|
115
|
+
USER_CLASS = 77 # N [RFC3004] User Class Information
|
116
|
+
DIRECTORY_AGENT = 78 # N [RFC2610] directory agent information
|
117
|
+
SERVICE_SCOPE = 79 # N [RFC2610] service location agent scope
|
118
|
+
RAPID_COMMIT = 80 # 0 [RFC4039] Rapid Commit
|
119
|
+
CLIENT_FQDN = 81 # N [RFC4702] Fully Qualified Domain Name
|
120
|
+
RELAY_AGENT_INFORMATION = 82 # N [RFC3046] Relay Agent Information
|
121
|
+
ISNS = 83 # N [RFC4174] Internet Storage Name Service
|
122
|
+
# 84 REMOVED/Unassigned [RFC3679]
|
123
|
+
NDS_SERVERS = 85 # N [RFC2241] Novell Directory Services
|
124
|
+
NDS_TREE_NAME = 86 # N [RFC2241] Novell Directory Services
|
125
|
+
NDS_CONTEXT = 87 # N [RFC2241] Novell Directory Services
|
126
|
+
BCMCS_CONTROLLER_DOMAIN_NAME_LIST = 88 # [RFC4280]
|
127
|
+
BCMCS_CONTROLLER_IPV4_ADDRESS_OPTION = 89 # [RFC4280]
|
128
|
+
AUTHENTICATION = 90 # N [RFC3118] Authentication
|
129
|
+
CLIENT_LAST_TRANSACTION_TIME_OPTION = 91 # [RFC4388]
|
130
|
+
ASSOCIATED_IP_OPTION = 92 # [RFC4388]
|
131
|
+
CLIENT_SYSTEM = 93 # N [RFC4578] Client System Architecture
|
132
|
+
CLIENT_NDI = 94 # N [RFC4578] Client Network Device Interface
|
133
|
+
LDAP = 95 # N [RFC3679] Lightweight Directory Access Protocol
|
134
|
+
# 96 REMOVED/Unassigned [RFC3679]
|
135
|
+
UUID = 97 # N [RFC4578] UUID/GUID-based Client Identifier
|
136
|
+
USER_AUTH = 98 # N [RFC2485] Open Group's User Authentication
|
137
|
+
GEOCONF_CIVIC = 99 # [RFC4776]
|
138
|
+
PCODE = 100 # N [RFC4833] IEEE 1003.1 TZ String
|
139
|
+
TCODE = 101 # N [RFC4833] Reference to the TZ Database
|
140
|
+
# 102-107 REMOVED/Unassigned [RFC3679]
|
141
|
+
IPV6_ONLY_PREFERRED = 108 # 4 [RFC8925] Number of seconds that DHCPv4 should be disabled
|
142
|
+
OPTION_DHCP4O6_S46_SADDR = 109 # 16 [RFC8539] DHCPv4 over DHCPv6 Softwire Source Address Option
|
143
|
+
# 110 REMOVED/Unassigned [RFC3679]
|
144
|
+
# 111 Unassigned [RFC3679]
|
145
|
+
NETINFO_ADDRESS = 112 # N [RFC3679] NetInfo Parent Server Address
|
146
|
+
NETINFO_TAG = 113 # N [RFC3679] NetInfo Parent Server Tag
|
147
|
+
DHCP_CAPTIVE_PORTAL = 114 # N [RFC8910] DHCP Captive-Portal
|
148
|
+
# 115 REMOVED/Unassigned [RFC3679]
|
149
|
+
AUTO_CONFIG = 116 # N [RFC2563] DHCP Auto-Configuration
|
150
|
+
NAME_SERVICE_SEARCH = 117 # N [RFC2937] Name Service Search
|
151
|
+
SUBNET_SELECTION_OPTION = 118 # 4 [RFC3011] Subnet Selection Option
|
152
|
+
DOMAIN_SEARCH = 119 # N [RFC3397] DNS domain search list
|
153
|
+
SIP_SERVERS_DHCP_OPTION = 120 # N [RFC3361] SIP Servers DHCP Option
|
154
|
+
CLASSLESS_STATIC_ROUTE_OPTION = 121 # N [RFC3442] Classless Static Route Option
|
155
|
+
CCC = 122 # N [RFC3495] CableLabs Client Configuration
|
156
|
+
GEOCONF_OPTION = 123 # 16 [RFC6225] GeoConf Option
|
157
|
+
VI_VENDOR_CLASS = 124 # [RFC3925] Vendor-Identifying Vendor Class
|
158
|
+
VI_VENDOR_SPECIFIC_INFORMATION = 125 # [RFC3925] Vendor-Identifying Vendor-Specific Information
|
159
|
+
# 128 PXE - undefined (vendor specific) [RFC4578]
|
160
|
+
# 128 Etherboot signature. 6 bytes: E4:45:74:68:00:00
|
161
|
+
# 128 DOCSIS "full security" server IP address
|
162
|
+
# 128 TFTP Server IP address (for IP Phone software load)
|
163
|
+
# 129 PXE - undefined (vendor specific) [RFC4578]
|
164
|
+
# 129 Kernel options. Variable length string
|
165
|
+
# 129 Call Server IP address
|
166
|
+
# 130 PXE - undefined (vendor specific) [RFC4578]
|
167
|
+
# 130 Ethernet interface. Variable length string.
|
168
|
+
# 130 Discrimination string (to identify vendor)
|
169
|
+
# 131 PXE - undefined (vendor specific) [RFC4578]
|
170
|
+
# 131 Remote statistics server IP address
|
171
|
+
# 132 PXE - undefined (vendor specific) [RFC4578]
|
172
|
+
# 132 IEEE 802.1Q VLAN ID
|
173
|
+
# 133 PXE - undefined (vendor specific) [RFC4578]
|
174
|
+
# 133 IEEE 802.1D/p Layer 2 Priority
|
175
|
+
# 134 PXE - undefined (vendor specific) [RFC4578]
|
176
|
+
# 134 Diffserv Code Point (DSCP) for VoIP signalling and media streams
|
177
|
+
# 135 PXE - undefined (vendor specific) [RFC4578]
|
178
|
+
# 135 HTTP Proxy for phone-specific applications
|
179
|
+
OPTION_PANA_AGENT = 136 # [RFC5192]
|
180
|
+
OPTION_V4_LOST = 137 # [RFC5223]
|
181
|
+
OPTION_CAPWAP_AC_V4 = 138 # N [RFC5417] CAPWAP Access Controller addresses
|
182
|
+
OPTION_IPV4_ADDRESS_MOS = 139 # N [RFC5678] a series of suboptions
|
183
|
+
OPTION_IPV4_FQDN_MOS = 140 # N [RFC5678] a series of suboptions
|
184
|
+
SIP_UA_CONFIGURATION_SERVICE_DOMAINS = 141 # N [RFC6011] List of domain names to search for SIP User Agent Configuration
|
185
|
+
OPTION_IPV4_ADDRESS_ANDSF = 142 # N [RFC6153] ANDSF IPv4 Address Option for DHCPv4
|
186
|
+
OPTION_V4_SZTP_REDIRECT = 143 # N [RFC8572] This option provides a list of URIs for SZTP bootstrap servers
|
187
|
+
GEOLOC = 144 # 16 [RFC6225] Geospatial Location with Uncertainty
|
188
|
+
FORCERENEW_NONCE_CAPABLE = 145 # 1 [RFC6704] Forcerenew Nonce Capable
|
189
|
+
RDNSS_SELECTION = 146 # N [RFC6731] Information for selecting RDNSS
|
190
|
+
OPTION_V4_DOTS_RI = 147 # N [RFC8973] The name of the peer DOTS agent.
|
191
|
+
OPTION_V4_DOTS_ADDRESS = 148 # N (the minimal length is 4) [RFC8973] N/4 IPv4 addresses of peer DOTS agent(s).
|
192
|
+
# 149 Unassigned [RFC3942]
|
193
|
+
TFTP_SERVER_ADDRESS = 150 # [RFC5859]
|
194
|
+
STATUS_CODE = 151 # N+1 [RFC6926] Status code and optional N byte text message describing status.
|
195
|
+
BASE_TIME = 152 # 4 [RFC6926] Absolute time (seconds since Jan 1, 1970) message was sent.
|
196
|
+
START_TIME_OF_STATE = 153 # 4 [RFC6926] Number of seconds in the past when client entered current state.
|
197
|
+
QUERY_START_TIME = 154 # 4 [RFC6926] Absolute time (seconds since Jan 1, 1970) for beginning of query.
|
198
|
+
QUERY_END_TIME = 155 # 4 [RFC6926] Absolute time (seconds since Jan 1, 1970) for end of query.
|
199
|
+
DHCP_STATE = 156 # 1 [RFC6926] State of IP address.
|
200
|
+
DATA_SOURCE = 157 # 1 [RFC6926] Indicates information came from local or remote server.
|
201
|
+
OPTION_V4_PCP_SERVER = 158 # Variable; the minimum length is 5. [RFC7291] Includes one or multiple lists of PCP server IP addresses; each list is treated as a separate PCP server.
|
202
|
+
OPTION_V4_PORTPARAMS = 159 # 4 [RFC7618] This option is used to configure a set of ports bound to a shared IPv4 address.
|
203
|
+
# 160 Unassigned [RFC7710][RFC8910] Previously assigned by [RFC7710]; known to also be used by Polycom.
|
204
|
+
OPTION_MUD_URL_V4 = 161 # N (variable) [RFC8520] Manufacturer Usage Descriptions
|
205
|
+
OPTION_V4_DNR = 162 # N [RFC-ietf-add-dnr-13] Encrypted DNS Server
|
206
|
+
# 163-174 Unassigned [RFC3942]
|
207
|
+
# ETHERBOOT = 175 # Tentatively Assigned - 2005-06-23
|
208
|
+
# IP_TELEPHONE = 176 # Tentatively Assigned - 2005-06-23
|
209
|
+
# ETHERBOOT = 177 # Tentatively Assigned - 2005-06-23
|
210
|
+
# PACKETCABLE_AND_CABLEHOME = 177 # replaced by 122
|
211
|
+
# 178-207 Unassigned [RFC3942]
|
212
|
+
PXELINUX_MAGIC = 208 # 4 [RFC5071][Deprecated] magic string = F1:00:74:7E
|
213
|
+
CONFIGURATION_FILE = 209 # N [RFC5071] Configuration file
|
214
|
+
PATH_PREFIX = 210 # N [RFC5071] Path Prefix Option
|
215
|
+
REBOOT_TIME = 211 # 4 [RFC5071] Reboot Time
|
216
|
+
OPTION_6RD = 212 # 18 + N [RFC5969] OPTION_6RD with N/4 6rd BR addresses
|
217
|
+
OPTION_V4_ACCESS_DOMAIN = 213 # N [RFC5986] Access Network Domain Name
|
218
|
+
# 214-219 Unassigned
|
219
|
+
SUBNET_ALLOCATION_OPTION = 220 # N [RFC6656] Subnet Allocation Option
|
220
|
+
VSS_OPTION = 221 # Virtual Subnet Selection (VSS) Option [RFC6607]
|
221
|
+
# 222-223 Unassigned [RFC3942]
|
222
|
+
# 224-254 Reserved (Private Use)
|
223
|
+
WPAD_PROXY_URL = 252
|
224
|
+
END = 255 # 0 [RFC2132] None
|
225
|
+
|
226
|
+
|
227
|
+
class DHCPMessageType(Enum):
|
228
|
+
# 53 Values
|
229
|
+
DISCOVER = 1 # RFC 2131
|
230
|
+
OFFER = 2 # RFC 2131
|
231
|
+
REQUEST = 3 # RFC 2131
|
232
|
+
DECLINE = 4 # RFC 2131
|
233
|
+
ACK = 5 # RFC 2131
|
234
|
+
NAK = 6 # RFC 2131
|
235
|
+
RELEASE = 7 # RFC 2131
|
236
|
+
INFORM = 8 # RFC 2131
|
237
|
+
FORCERENEW = 9 # RFC 3203
|
238
|
+
LEASEQUERY = 10 # RFC 4388
|
239
|
+
LEASEUNASSIGNED = 11 # RFC 4388
|
240
|
+
LEASEUNKNOWN = 12 # RFC 4388
|
241
|
+
LEASEACTIVE = 13 # RFC 4388
|
242
|
+
BULKLEASEQUERY = 14 # RFC 6926
|
243
|
+
LEASEQUERYDONE = 15 # RFC 6926
|
244
|
+
ACTIVELEASEQUERY = 16 # RFC 7724
|
245
|
+
LEASEQUERYSTATUS = 17 # RFC 7724
|
246
|
+
TLS = 18 # RFC 7724
|
247
|
+
|
248
|
+
|
249
|
+
class DHCPStatusCodeType(Enum):
|
250
|
+
# 151 Values
|
251
|
+
Success = 0 # RFC 6926
|
252
|
+
UnspecFail = 1 # RFC 6926
|
253
|
+
QueryTerminated = 2 # RFC 6926
|
254
|
+
MalformedQuery = 3 # RFC 6926
|
255
|
+
NotAllowed = 4 # RFC 6926
|
256
|
+
DataMissing = 5 # RFC 7724
|
257
|
+
ConnectionActive = 6 # RFC 7724
|
258
|
+
CatchUpComplete = 7 # RFC 7724
|
259
|
+
TLSConnectionRefused = 8 # RFC 7724
|
260
|
+
|
261
|
+
|
262
|
+
def mac_aton(s: str) -> bytes:
|
263
|
+
try:
|
264
|
+
haddr = [int(n, base=16) for n in s.split(':')]
|
265
|
+
if not all(0 <= x <= 0xff for x in haddr):
|
266
|
+
raise ValueError
|
267
|
+
except:
|
268
|
+
raise ValueError(f"Invalid MAC address {s!r}.")
|
269
|
+
return bytes(haddr)
|
270
|
+
|
271
|
+
|
272
|
+
def mac_ntoa(b: bytes) -> str:
|
273
|
+
return ':'.join([f"{x:02X}" for x in b])
|
274
|
+
|
275
|
+
|
276
|
+
def readable_packet(data: bytes) -> str:
|
277
|
+
bpr = 16 # bpr is Bytes Per Row
|
278
|
+
numbytes = len(data)
|
279
|
+
|
280
|
+
if numbytes == 0:
|
281
|
+
return " <empty packet>"
|
282
|
+
else:
|
283
|
+
output = ""
|
284
|
+
i = 0
|
285
|
+
while i < numbytes:
|
286
|
+
if (i % bpr) == 0:
|
287
|
+
output += f" {i:04d} :"
|
288
|
+
|
289
|
+
output += f" {data[i]:02X}"
|
290
|
+
|
291
|
+
if ((i + 1) % bpr) == 0:
|
292
|
+
output += "\n"
|
293
|
+
|
294
|
+
i = i + 1
|
295
|
+
|
296
|
+
if (numbytes % bpr) != 0:
|
297
|
+
output += "\n"
|
298
|
+
|
299
|
+
return output
|
300
|
+
|
301
|
+
|
302
|
+
def buildbytesoption(optnum, ba):
|
303
|
+
lenba = len(ba)
|
304
|
+
|
305
|
+
if (ba) == 0:
|
306
|
+
opt = bytearray(1)
|
307
|
+
opt[0] = optnum
|
308
|
+
else:
|
309
|
+
opt = bytearray(2 + lenba)
|
310
|
+
opt[0] = optnum
|
311
|
+
opt[1] = lenba
|
312
|
+
opt[2:2 + lenba] = ba
|
313
|
+
|
314
|
+
return opt
|
315
|
+
|
316
|
+
|
317
|
+
def build1byteoption(optnum, databyte):
|
318
|
+
return bytearray([optnum, 1, databyte])
|
319
|
+
|
320
|
+
|
321
|
+
def build4byteoption(optnum, d1, d2, d3, d4):
|
322
|
+
optbytes = bytearray(6)
|
323
|
+
optbytes[0] = optnum
|
324
|
+
optbytes[1] = 4
|
325
|
+
optbytes[2] = d1
|
326
|
+
optbytes[3] = d2
|
327
|
+
optbytes[4] = d3
|
328
|
+
optbytes[5] = d4
|
329
|
+
|
330
|
+
return optbytes
|
331
|
+
|
332
|
+
|
333
|
+
def buildstringoption(optnum, string):
|
334
|
+
optbytes = bytearray(2 + len(string))
|
335
|
+
optbytes[0] = optnum
|
336
|
+
optbytes[1] = len(string)
|
337
|
+
d = 2
|
338
|
+
for c in string:
|
339
|
+
optbytes[d] = ord(c)
|
340
|
+
if d == len(string) + 1:
|
341
|
+
if c == "/":
|
342
|
+
optbytes[d] = 0
|
343
|
+
d += 1
|
344
|
+
|
345
|
+
return optbytes
|
346
|
+
|
347
|
+
|
348
|
+
def buildendoption():
|
349
|
+
optbytes = bytearray(1)
|
350
|
+
optbytes[0] = 255
|
351
|
+
|
352
|
+
return optbytes
|
353
|
+
|
354
|
+
|
355
|
+
class DHCPPacket():
|
356
|
+
|
357
|
+
_format = Struct('!BBBBIHH4s4s4s4s16s64s128s4s')
|
358
|
+
|
359
|
+
def __init__(self):
|
360
|
+
self.op = 0
|
361
|
+
self.htype = 1
|
362
|
+
self.hlen = 6
|
363
|
+
self.hops = 0
|
364
|
+
self.xid = 0
|
365
|
+
self.secs = 0
|
366
|
+
self.flags = 0
|
367
|
+
self.ciaddr = '0.0.0.0'
|
368
|
+
self.yiaddr = '0.0.0.0'
|
369
|
+
self.siaddr = '0.0.0.0'
|
370
|
+
self.giaddr = '0.0.0.0'
|
371
|
+
self.chaddr = '00:00:00:00:00:00'
|
372
|
+
self.sname = ''
|
373
|
+
self.file = ''
|
374
|
+
self.options = {}
|
375
|
+
self.data = None
|
376
|
+
|
377
|
+
def encode(self):
|
378
|
+
if self.data is not None:
|
379
|
+
return self.data
|
380
|
+
|
381
|
+
buf = DHCPPacket._format.pack(self.op, self.htype, self.hlen,
|
382
|
+
self.hops, self.xid,
|
383
|
+
self.secs, self.flags,
|
384
|
+
socket.inet_aton(self.ciaddr),
|
385
|
+
socket.inet_aton(self.yiaddr),
|
386
|
+
socket.inet_aton(self.siaddr),
|
387
|
+
socket.inet_aton(self.giaddr),
|
388
|
+
mac_aton(self.chaddr),
|
389
|
+
self.sname.encode(), self.file.encode(),
|
390
|
+
MAGIC_COOKIE)
|
391
|
+
|
392
|
+
ret = [buf]
|
393
|
+
for opt, data in self.options.items():
|
394
|
+
ret.append(bytearray([opt, len(data)]))
|
395
|
+
ret.append(data)
|
396
|
+
ret.append(bytearray([DHCPOption.END.value]))
|
397
|
+
self.data = b''.join(ret)
|
398
|
+
return self.data
|
399
|
+
|
400
|
+
@classmethod
|
401
|
+
def decode(cls, data):
|
402
|
+
if len(data) < DHCPPacket._format.size:
|
403
|
+
raise ValueError("Not enough data to decode")
|
404
|
+
|
405
|
+
packet = cls()
|
406
|
+
packet.data = data
|
407
|
+
|
408
|
+
(packet.op, packet.htype, packet.hlen, packet.hops, packet.xid,
|
409
|
+
packet.secs, packet.flags, ciaddr, yiaddr, siaddr, giaddr, chaddr,
|
410
|
+
sname, file, magic_cookie) = DHCPPacket._format.unpack(
|
411
|
+
data[:DHCPPacket._format.size])
|
412
|
+
|
413
|
+
if magic_cookie != MAGIC_COOKIE:
|
414
|
+
raise ValueError("Invalid message")
|
415
|
+
|
416
|
+
packet.ciaddr = socket.inet_ntoa(ciaddr)
|
417
|
+
packet.yiaddr = socket.inet_ntoa(yiaddr)
|
418
|
+
packet.siaddr = socket.inet_ntoa(siaddr)
|
419
|
+
packet.giaddr = socket.inet_ntoa(giaddr)
|
420
|
+
|
421
|
+
packet.chaddr = mac_ntoa(chaddr[0:packet.hlen])
|
422
|
+
packet.sname = sname.decode('utf-8')
|
423
|
+
packet.file = file.decode('utf-8')
|
424
|
+
|
425
|
+
offset = DHCPPacket._format.size
|
426
|
+
|
427
|
+
while offset < len(data):
|
428
|
+
option = data[offset]
|
429
|
+
offset += 1
|
430
|
+
if option == DHCPOption.PAD.value:
|
431
|
+
continue
|
432
|
+
elif option == DHCPOption.END.value:
|
433
|
+
break
|
434
|
+
optlen = data[offset]
|
435
|
+
offset += 1
|
436
|
+
if (offset + optlen) >= len(data):
|
437
|
+
raise ValueError("Invalid option length")
|
438
|
+
packet.options[option] = data[offset:offset + optlen]
|
439
|
+
offset += optlen
|
440
|
+
|
441
|
+
return packet
|
442
|
+
|
443
|
+
def __str__(self):
|
444
|
+
DHCP_ops = {0: 'ERROR_UNDEF', 1: 'BOOTREQUEST', 2: 'BOOTREPLY'}
|
445
|
+
|
446
|
+
lines = [
|
447
|
+
"###################### Header fields ######################",
|
448
|
+
f" op : {DHCP_ops[self.op]}",
|
449
|
+
f" htype : {self.htype}",
|
450
|
+
f" hlen : {self.hlen}",
|
451
|
+
f" hops : {self.hops}",
|
452
|
+
f" xid : 0x{self.xid:08x}",
|
453
|
+
f" secs : {self.secs}",
|
454
|
+
f" flags : {self.flags}",
|
455
|
+
f" Client IP address : {self.ciaddr}",
|
456
|
+
f" Your IP address : {self.yiaddr}",
|
457
|
+
f" Server IP address : {self.siaddr}",
|
458
|
+
f" Gateway IP address : {self.giaddr}",
|
459
|
+
f" Client hardware address : {self.chaddr}",
|
460
|
+
"##################### Options fields ######################"
|
461
|
+
]
|
462
|
+
for opt, value in self.options.items():
|
463
|
+
if opt == 53:
|
464
|
+
value = DHCPMessageType(value[0]).name
|
465
|
+
elif opt in [50, 54, 1, 3, 6]:
|
466
|
+
value = socket.inet_ntoa(value)
|
467
|
+
elif opt in [51, 58, 59]:
|
468
|
+
value = unpack('!I', value)[0]
|
469
|
+
elif opt in [57]:
|
470
|
+
value = unpack('!H', value)[0]
|
471
|
+
elif opt in [12, 15, 56]:
|
472
|
+
value = value.decode()
|
473
|
+
elif opt in [28, 33, 42]:
|
474
|
+
value = [
|
475
|
+
socket.inet_ntoa(x)
|
476
|
+
for x in [value[i:i + 4] for i in range(0, len(value), 4)]
|
477
|
+
]
|
478
|
+
value = f'{value[0]}\n' + '\n'.join(f"{'':39s} : {x}"
|
479
|
+
for x in value[1:])
|
480
|
+
elif opt in [55]:
|
481
|
+
value = (f"({value[0]:3d}) {DHCPOption(value[0]).name}\n" +
|
482
|
+
'\n'.join(f"{'':39s} : ({x:3d}) {DHCPOption(x).name}"
|
483
|
+
for x in value[1:]))
|
484
|
+
elif opt in [61]:
|
485
|
+
value = f"{value[0]} - {mac_ntoa(value[1:])}"
|
486
|
+
else:
|
487
|
+
value = f"({len(value):2d}) {base64.b16encode(value).decode()}"
|
488
|
+
opt_name = DHCPOption(opt).name
|
489
|
+
lines.append(f" {opt_name:29s} ({opt:3d}) : {value}")
|
490
|
+
|
491
|
+
if self.data is not None:
|
492
|
+
lines.append(
|
493
|
+
"######################## Raw data #########################")
|
494
|
+
lines.append(readable_packet(self.data))
|
495
|
+
lines.append(
|
496
|
+
"###########################################################")
|
497
|
+
return '\n'.join(lines)
|
498
|
+
|
499
|
+
def set_option(self, opt: DHCPOption, value):
|
500
|
+
if opt.value in [0, 255]:
|
501
|
+
raise ValueError("Invalid option")
|
502
|
+
if opt.value == 53:
|
503
|
+
value = bytearray([value.value])
|
504
|
+
elif opt.value in [50, 54, 1, 3, 6]:
|
505
|
+
value = socket.inet_aton(value)
|
506
|
+
elif opt.value in [51, 58, 59]:
|
507
|
+
value = pack('!I', value)
|
508
|
+
elif opt.value in [57]:
|
509
|
+
value = pack('!H', value)
|
510
|
+
elif opt.value in [12, 15, 56]:
|
511
|
+
value = value.encode()
|
512
|
+
elif opt.value in [28, 33, 42]:
|
513
|
+
value = b''.join(socket.inet_aton(x) for x in value)
|
514
|
+
elif opt.value in [55]:
|
515
|
+
value = bytearray([v.value for v in value])
|
516
|
+
elif opt.value in [61]:
|
517
|
+
value = bytearray([1]) + mac_aton(value)
|
518
|
+
else:
|
519
|
+
value = bytearray(value)
|
520
|
+
self.options[opt.value] = value
|
521
|
+
|
522
|
+
def get_option(self, opt: DHCPOption):
|
523
|
+
value = self.options[opt.value]
|
524
|
+
if opt.value == 53:
|
525
|
+
value = DHCPMessageType(value[0])
|
526
|
+
elif opt.value in [50, 54, 1, 3, 6]:
|
527
|
+
value = socket.inet_ntoa(value)
|
528
|
+
elif opt.value in [51, 58, 59]:
|
529
|
+
value = unpack('!I', value)[0]
|
530
|
+
elif opt.value in [57]:
|
531
|
+
value = unpack('!H', value)[0]
|
532
|
+
elif opt.value in [12, 15, 56]:
|
533
|
+
value = value.decode()
|
534
|
+
elif opt.value in [28, 33, 42]:
|
535
|
+
value = [
|
536
|
+
socket.inet_ntoa(x)
|
537
|
+
for x in [value[i:i + 4] for i in range(0, len(value), 4)]
|
538
|
+
]
|
539
|
+
elif opt.value in [55]:
|
540
|
+
value = [DHCPOption(x) for x in value]
|
541
|
+
elif opt.value in [61]:
|
542
|
+
value = mac_ntoa(value[1:])
|
543
|
+
return value
|