Skip to content

Commit 6469eac

Browse files
author
BiffoBear
committed
Completed tests for parse_dhcp_message. Fixed an off-by-one error in parse_dhcp_message and simplified MAGIC_COOKIE. Fixed router IP assignment to allow for multiple routers. Updated type hints.
1 parent b55bdd2 commit 6469eac

File tree

2 files changed

+116
-11
lines changed

2 files changed

+116
-11
lines changed

adafruit_wiznet5k/adafruit_wiznet5k_dhcp.py

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@
6565
DHCP_HLENETHERNET = const(0x06)
6666
DHCP_HOPS = const(0x00)
6767

68-
MAGIC_COOKIE = const(0x63825363)
68+
MAGIC_COOKIE = b"c\x82Sc" # Four bytes 99.130.83.99
6969
MAX_DHCP_OPT = const(0x10)
7070

7171
# Default DHCP Server port
@@ -203,10 +203,7 @@ def send_dhcp_message(
203203
# NOTE: 192 octets of 0's, BOOTP legacy
204204

205205
# Magic Cookie
206-
_BUFF[236] = (MAGIC_COOKIE >> 24) & 0xFF
207-
_BUFF[237] = (MAGIC_COOKIE >> 16) & 0xFF
208-
_BUFF[238] = (MAGIC_COOKIE >> 8) & 0xFF
209-
_BUFF[239] = MAGIC_COOKIE & 0xFF
206+
_BUFF[236:240] = MAGIC_COOKIE
210207

211208
# Option - DHCP Message Type
212209
_BUFF[240] = 53
@@ -262,10 +259,10 @@ def send_dhcp_message(
262259
# pylint: disable=too-many-branches, too-many-statements
263260
def parse_dhcp_response(
264261
self,
265-
) -> Union[Tuple[int, bytes], Tuple[int, int]]:
262+
) -> Union[Tuple[int, bytearray], Tuple[int, int]]:
266263
"""Parse DHCP response from DHCP server.
267264
268-
:return Union[Tuple[int, bytes], Tuple[int, int]]: DHCP packet type.
265+
:return Union[Tuple[int, bytearray], Tuple[int, int]]: DHCP packet type.
269266
"""
270267
# store packet in buffer
271268
_BUFF = self._sock.recv()
@@ -288,7 +285,7 @@ def parse_dhcp_response(
288285
if _BUFF[28:34] == 0:
289286
return 0, 0
290287

291-
if int.from_bytes(_BUFF[235:240], "big") != MAGIC_COOKIE:
288+
if _BUFF[236:240] != MAGIC_COOKIE:
292289
return 0, 0
293290

294291
# -- Parse Packet, VARIABLE -- #
@@ -322,8 +319,8 @@ def parse_dhcp_response(
322319
ptr += 1
323320
opt_len = _BUFF[ptr]
324321
ptr += 1
325-
self.gateway_ip = tuple(_BUFF[ptr : ptr + opt_len])
326-
ptr += opt_len
322+
self.gateway_ip = tuple(_BUFF[ptr : ptr + 4])
323+
ptr += opt_len # still increment even though we only read 1 addr.
327324
elif _BUFF[ptr] == DNS_SERVERS:
328325
ptr += 1
329326
opt_len = _BUFF[ptr]

tests/test_dhcp.py

Lines changed: 109 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ def test_constants(self):
6060
assert wiz_dhcp.DHCP_HLENETHERNET == const(0x06)
6161
assert wiz_dhcp.DHCP_HOPS == const(0x00)
6262

63-
assert wiz_dhcp.MAGIC_COOKIE == const(0x63825363)
63+
assert wiz_dhcp.MAGIC_COOKIE == b"c\x82Sc"
6464
assert wiz_dhcp.MAX_DHCP_OPT == const(0x10)
6565

6666
# Default DHCP Server port
@@ -274,3 +274,111 @@ def test_send_dhcp_message(
274274
dhcp_client.send_dhcp_message(state, time_elapsed, renew=renew)
275275
dhcp_client._sock.send.assert_called_once_with(result)
276276
assert len(wiz_dhcp._BUFF) == 318
277+
278+
279+
class TestParseDhcpMessage:
280+
281+
GOOD_DATA_01 = bytearray(
282+
b"\x02\x00\x00\x00\xff\xff\xff\x7f\x00\x00\x00\x00\x00\x00\x00\x00\xc0"
283+
b"\xa8\x05\x16\x00\x00\x00\x00\x00\x00\x00\x00\x01\x03\x05\x07\t\x0b\x00"
284+
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
285+
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
286+
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
287+
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
288+
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
289+
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
290+
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
291+
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
292+
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
293+
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
294+
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
295+
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00c\x82Sc5\x01"
296+
b"\x02\x01\x04\xc0\xa8\x06\x026\x04\xeao\xde{3\x04\x00\x01\x01\x00\x03"
297+
b'\x04yy\x04\x05\x06\x04\x05\x06\x07\x08:\x04\x00""\x00;\x04\x0033\x00'
298+
b"\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
299+
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
300+
)
301+
GOOD_DATA_02 = bytearray(
302+
b"\x02\x00\x00\x00\x9axV4\x00\x00\x00\x00\x00\x00\x00\x00\x12$@\n\x00\x00"
303+
b"\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
304+
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
305+
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
306+
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
307+
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
308+
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
309+
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
310+
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
311+
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
312+
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
313+
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
314+
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00c\x82Sc5"
315+
b"\x01\x05<\x05\x01\x02\x03\x04\x05\x01\x04\n\x0b\x07\xde6\x04zN\x91\x03\x03"
316+
b"\x08\n\x0b\x0e\x0f\xff\x00\xff\x00\x06\x08\x13\x11\x0b\x07****3\x04\x00\x00"
317+
b"=;:\x04\x00\x0e\x17@;\x04\x02\x92]\xde\xff\x00\x00\x00\x00\x00\x00\x00\x00"
318+
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00"
319+
)
320+
321+
@pytest.mark.parametrize(
322+
"xid, local_ip, msg_type, subnet, dhcp_ip, gate_ip, dns_ip, lease, t1, t2, response",
323+
(
324+
(
325+
0x7FFFFFFF,
326+
(192, 168, 5, 22),
327+
2,
328+
(192, 168, 6, 2),
329+
(234, 111, 222, 123),
330+
(121, 121, 4, 5),
331+
(5, 6, 7, 8),
332+
65792,
333+
2236928,
334+
3355392,
335+
GOOD_DATA_01,
336+
),
337+
(
338+
0x3456789A,
339+
(18, 36, 64, 10),
340+
5,
341+
(10, 11, 7, 222),
342+
(122, 78, 145, 3),
343+
(10, 11, 14, 15),
344+
(19, 17, 11, 7),
345+
15675,
346+
923456,
347+
43146718,
348+
GOOD_DATA_02,
349+
),
350+
),
351+
)
352+
# pylint: disable=too-many-locals
353+
def test_parse_good_data(
354+
self,
355+
wiznet,
356+
wrench,
357+
xid,
358+
local_ip,
359+
msg_type,
360+
subnet,
361+
dhcp_ip,
362+
gate_ip,
363+
dns_ip,
364+
lease,
365+
t1,
366+
t2,
367+
response,
368+
):
369+
dhcp_client = wiz_dhcp.DHCP(wiznet, (1, 2, 3, 4, 5, 6))
370+
dhcp_client._sock = wrench.socket(type=wrench.SOCK_DGRAM)
371+
dhcp_client._transaction_id = xid
372+
dhcp_client._initial_xid = dhcp_client._transaction_id.to_bytes(4, "little")
373+
dhcp_client._sock.recv.return_value = response
374+
response_type, response_id = dhcp_client.parse_dhcp_response()
375+
assert response_type == msg_type
376+
assert response_id == bytearray(xid.to_bytes(4, "little"))
377+
assert dhcp_client.local_ip == local_ip
378+
assert dhcp_client.subnet_mask == subnet
379+
assert dhcp_client.dhcp_server_ip == dhcp_ip
380+
assert dhcp_client.gateway_ip == gate_ip
381+
assert dhcp_client.dns_server_ip == dns_ip
382+
assert dhcp_client._lease_time == lease
383+
assert dhcp_client._t1 == t1
384+
assert dhcp_client._t2 == t2

0 commit comments

Comments
 (0)