diff --git a/dhcppython/packet.py b/dhcppython/packet.py index 6579de0..77f97b9 100644 --- a/dhcppython/packet.py +++ b/dhcppython/packet.py @@ -135,19 +135,36 @@ def from_bytes(cls, packet: bytes): options_list = options.OptionList() read_pos = cls.cookie_offset_end - code = 0 - while read_pos < len(packet) and code != 255: - code = packet[read_pos] - if code in [0, 255]: - data_read_size = 1 - else: - length = packet[read_pos + 1] + end_maker = False + while read_pos < len(packet): + if end_maker: + raise MalformedPacketError("Data after END option/marker") + + option_bytes = code = packet[read_pos] + if code == options.End.code: + end_maker = True + read_pos += 1 + continue + + if code != options.Pad.code: + try: + length = packet[read_pos + 1] + except IndexError: + length = 0 data_read_size = 1 + 1 + length + option_bytes = packet[read_pos:read_pos + data_read_size] + if data_read_size < len(option_bytes): + raise MalformedPacketError( + "Insufficient data, attempt to read {} bytes at offset " + "{}, but got only {}".format( + data_read_size, read_pos, len(option_bytes))) - option_bytes = packet[read_pos : read_pos + data_read_size] options_object = OPTIONS_INTERFACE.bytes_to_object(option_bytes) options_list.append(options_object) - read_pos += data_read_size + read_pos += len(option_bytes) + + if not end_maker and len(options_list): + raise MalformedPacketError("Missing END option") decoded_packet.append(options_list) # Decode the op code diff --git a/tests/test_packet.py b/tests/test_packet.py index 30a2020..55d2cb2 100644 --- a/tests/test_packet.py +++ b/tests/test_packet.py @@ -50,6 +50,10 @@ def test_parse_ack1(self): ack_linux ) + def test_parse_exclude_end_option(self): + parsed_packet = packet.DHCPPacket.from_bytes(discover_linux) + self.assertIsNone(parsed_packet.options.by_code(255)) + request_android: List[int] = [ 0x01, 0x01, 0x06, 0x00, 0xea, 0xbe,