def load_from(self, buffer: bytes, offset: int = 0, length: int = None) -> int: """ Load the internal state of this object from the given buffer. The buffer may contain more data after the structured element is parsed. This data is ignored. :param buffer: The buffer to read data from :param offset: The offset in the buffer where to start reading :param length: The amount of data we are allowed to read from the buffer :return: The number of bytes used from the buffer """ my_offset, option_len = self.parse_option_header(buffer, offset, length, min_length=0) header_offset = my_offset # Parse the options self.options = [] max_offset = option_len + header_offset # The option_len field counts bytes *after* the header fields while max_offset > my_offset: used_buffer, option = Option.parse(buffer, offset=offset + my_offset) self.options.append(option) my_offset += used_buffer if my_offset != max_offset: raise ValueError('Option length does not match the combined length of the parsed options') return my_offset
def load_from(self, buffer: bytes, offset: int = 0, length: int = None) -> int: """ Load the internal state of this object from the given buffer. The buffer may contain more data after the structured element is parsed. This data is ignored. :param buffer: The buffer to read data from :param offset: The offset in the buffer where to start reading :param length: The amount of data we are allowed to read from the buffer :return: The number of bytes used from the buffer """ my_offset = 0 # These message types always begin with a message type and a transaction id message_type = buffer[offset + my_offset] my_offset += 1 if message_type != self.message_type: raise ValueError('The provided buffer does not contain {} data'.format(self.__class__.__name__)) self.transaction_id = buffer[offset + my_offset:offset + my_offset + 3] my_offset += 3 # Parse the options from dhcpkit.ipv6.options import Option max_length = length or (len(buffer) - offset) while max_length > my_offset: used_buffer, option = Option.parse(buffer, offset=offset + my_offset) self.options.append(option) my_offset += used_buffer self.validate() return my_offset
def load_from(self, buffer: bytes, offset: int = 0, length: int = None) -> int: """ Load the internal state of this object from the given buffer. The buffer may contain more data after the structured element is parsed. This data is ignored. :param buffer: The buffer to read data from :param offset: The offset in the buffer where to start reading :param length: The amount of data we are allowed to read from the buffer :return: The number of bytes used from the buffer """ my_offset, option_len = self.parse_option_header(buffer, offset, length, min_length=5) # Parse the options self.options = [] max_offset = option_len + my_offset while max_offset > my_offset: used_buffer, option = Option.parse(buffer, offset=offset + my_offset) self.options.append(option) my_offset += used_buffer if my_offset != max_offset: raise ValueError( 'Option length does not match the combined length of the parsed options' ) return my_offset
def load_from(self, buffer: bytes, offset: int = 0, length: int = None) -> int: """ Load the internal state of this object from the given buffer. The buffer may contain more data after the structured element is parsed. This data is ignored. :param buffer: The buffer to read data from :param offset: The offset in the buffer where to start reading :param length: The amount of data we are allowed to read from the buffer :return: The number of bytes used from the buffer """ my_offset = 0 # These message types always begin with a message type, a hop count, the link address and the peer address self.message_type = buffer[offset + my_offset] my_offset += 1 self.hop_count = buffer[offset + my_offset] my_offset += 1 self.link_address = IPv6Address(buffer[offset + my_offset : offset + my_offset + 16]) my_offset += 16 self.peer_address = IPv6Address(buffer[offset + my_offset : offset + my_offset + 16]) my_offset += 16 # Parse the options from dhcpkit.ipv6.options import Option max_length = length or (len(buffer) - offset) while max_length > my_offset: used_buffer, option = Option.parse(buffer, offset=offset + my_offset) self.options.append(option) my_offset += used_buffer return my_offset
def load_from(self, buffer: bytes, offset: int = 0, length: int = None) -> int: """ Load the internal state of this object from the given buffer. The buffer may contain more data after the structured element is parsed. This data is ignored. :param buffer: The buffer to read data from :param offset: The offset in the buffer where to start reading :param length: The amount of data we are allowed to read from the buffer :return: The number of bytes used from the buffer """ my_offset, option_len = self.parse_option_header(buffer, offset, length, min_length=8) header_offset = my_offset # Flags self.flags = buffer[offset + my_offset] my_offset += 1 # EA-Len self.ea_len = buffer[offset + my_offset] my_offset += 1 # IPv4 prefix ipv4_prefix_length = buffer[offset + my_offset] my_offset += 1 if not (0 <= ipv4_prefix_length <= 32): raise ValueError("IPv4 prefix length must be in range from 0 to 32") ipv4_address = IPv4Address(buffer[offset + my_offset:offset + my_offset + 4]) my_offset += 4 # Combine address and prefix length into prefix self.ipv4_prefix = IPv4Network('{!s}/{:d}'.format(ipv4_address, ipv4_prefix_length), strict=False) # IPv6 prefix ipv6_prefix_length = buffer[offset + my_offset] my_offset += 1 if not (0 <= ipv6_prefix_length <= 128): raise ValueError("IPv6 prefix length must be in range from 0 to 128") included_octets = math.ceil(ipv6_prefix_length / 8) ipv6_address = IPv6Address(buffer[offset + my_offset:offset + my_offset + included_octets].ljust(16, b'\x00')) my_offset += included_octets self.ipv6_prefix = IPv6Network('{!s}/{:d}'.format(ipv6_address, ipv6_prefix_length), strict=False) # Parse the options self.options = [] max_offset = option_len + header_offset # The option_len field counts bytes *after* the header fields while max_offset > my_offset: used_buffer, option = Option.parse(buffer, offset=offset + my_offset) self.options.append(option) my_offset += used_buffer if my_offset != max_offset: raise ValueError('Option length does not match the combined length of the parsed options') return my_offset
def load_from(self, buffer: bytes, offset: int = 0, length: int = None) -> int: """ Load the internal state of this object from the given buffer. The buffer may contain more data after the structured element is parsed. This data is ignored. :param buffer: The buffer to read data from :param offset: The offset in the buffer where to start reading :param length: The amount of data we are allowed to read from the buffer :return: The number of bytes used from the buffer """ my_offset, option_len = self.parse_option_header(buffer, offset, length, min_length=5) header_offset = my_offset # IPv4 address self.ipv4_address = IPv4Address(buffer[offset + my_offset:offset + my_offset + 4]) my_offset += 4 # IPv6 prefix ipv6_prefix_length = buffer[offset + my_offset] my_offset += 1 if not (0 <= ipv6_prefix_length <= 128): raise ValueError( "IPv6 prefix length must be in range from 0 to 128") included_octets = math.ceil(ipv6_prefix_length / 8) ipv6_address = IPv6Address(buffer[offset + my_offset:offset + my_offset + included_octets].ljust( 16, b'\x00')) my_offset += included_octets self.ipv6_prefix = IPv6Network('{!s}/{:d}'.format( ipv6_address, ipv6_prefix_length), strict=False) # Parse the options self.options = [] max_offset = option_len + header_offset # The option_len field counts bytes *after* the header fields while max_offset > my_offset: used_buffer, option = Option.parse(buffer, offset=offset + my_offset) self.options.append(option) my_offset += used_buffer if my_offset != max_offset: raise ValueError( 'Option length does not match the combined length of the parsed options' ) return my_offset
def load_from(self, buffer: bytes, offset: int = 0, length: int = None) -> int: """ Load the internal state of this object from the given buffer. The buffer may contain more data after the structured element is parsed. This data is ignored. :param buffer: The buffer to read data from :param offset: The offset in the buffer where to start reading :param length: The amount of data we are allowed to read from the buffer :return: The number of bytes used from the buffer """ my_offset, option_len = self.parse_option_header(buffer, offset, length, min_length=25) header_offset = my_offset self.preferred_lifetime, self.valid_lifetime = unpack_from( '!II', buffer, offset=offset + my_offset) my_offset += 8 prefix_length = buffer[offset + my_offset] my_offset += 1 address = IPv6Address(buffer[offset + my_offset:offset + my_offset + 16]) my_offset += 16 # Combine address and prefix length into prefix self.prefix = IPv6Network('{!s}/{:d}'.format(address, prefix_length)) # Parse the options self.options = [] max_offset = option_len + header_offset # The option_len field counts bytes *after* the header fields while max_offset > my_offset: used_buffer, option = Option.parse(buffer, offset=offset + my_offset) self.options.append(option) my_offset += used_buffer if my_offset != max_offset: raise ValueError( 'Option length does not match the combined length of the parsed options' ) return my_offset
def decode_options(data: bytes) -> Iterable[Option]: """ Decode a list of options from bytes. :param data: The bytes :return: The list of options """ options = [] max_length = len(data) offset = 0 while max_length > offset: used_buffer, option = Option.parse(data, offset=offset, length=max_length - offset) options.append(option) offset += used_buffer return options
def load_from(self, buffer: bytes, offset: int = 0, length: int = None) -> int: """ Load the internal state of this object from the given buffer. The buffer may contain more data after the structured element is parsed. This data is ignored. :param buffer: The buffer to read data from :param offset: The offset in the buffer where to start reading :param length: The amount of data we are allowed to read from the buffer :return: The number of bytes used from the buffer """ my_offset = 0 # These message types always begin with a message type, a hop count, the link address and the peer address self.message_type = buffer[offset + my_offset] my_offset += 1 self.hop_count = buffer[offset + my_offset] my_offset += 1 self.link_address = IPv6Address(buffer[offset + my_offset:offset + my_offset + 16]) my_offset += 16 self.peer_address = IPv6Address(buffer[offset + my_offset:offset + my_offset + 16]) my_offset += 16 # Parse the options from dhcpkit.ipv6.options import Option max_length = length or (len(buffer) - offset) while max_length > my_offset: used_buffer, option = Option.parse(buffer, offset=offset + my_offset) self.options.append(option) my_offset += used_buffer return my_offset
def load_from(self, buffer: bytes, offset: int = 0, length: int = None) -> int: """ Load the internal state of this object from the given buffer. The buffer may contain more data after the structured element is parsed. This data is ignored. :param buffer: The buffer to read data from :param offset: The offset in the buffer where to start reading :param length: The amount of data we are allowed to read from the buffer :return: The number of bytes used from the buffer """ my_offset = 0 # These message types always begin with a message type and a transaction id message_type = buffer[offset + my_offset] my_offset += 1 if message_type != self.message_type: raise ValueError( 'The provided buffer does not contain {} data'.format( self.__class__.__name__)) self.transaction_id = buffer[offset + my_offset:offset + my_offset + 3] my_offset += 3 # Parse the options from dhcpkit.ipv6.options import Option max_length = length or (len(buffer) - offset) while max_length > my_offset: used_buffer, option = Option.parse(buffer, offset=offset + my_offset) self.options.append(option) my_offset += used_buffer return my_offset
def load_from(self, buffer: bytes, offset: int = 0, length: int = None) -> int: """ Load the internal state of this object from the given buffer. The buffer may contain more data after the structured element is parsed. This data is ignored. :param buffer: The buffer to read data from :param offset: The offset in the buffer where to start reading :param length: The amount of data we are allowed to read from the buffer :return: The number of bytes used from the buffer """ my_offset, option_len = self.parse_option_header(buffer, offset, length) header_offset = my_offset self.preferred_lifetime, self.valid_lifetime = unpack_from('!II', buffer, offset=offset + my_offset) my_offset += 8 prefix_length = buffer[offset + my_offset] my_offset += 1 address = IPv6Address(buffer[offset + my_offset:offset + my_offset + 16]) my_offset += 16 # Combine address and prefix length into prefix self.prefix = IPv6Network('{!s}/{:d}'.format(address, prefix_length)) # Parse the options self.options = [] max_offset = option_len + header_offset # The option_len field counts bytes *after* the header fields while max_offset > my_offset: used_buffer, option = Option.parse(buffer, offset=offset + my_offset) self.options.append(option) my_offset += used_buffer if my_offset != max_offset: raise ValueError('Option length does not match the combined length of the parsed options') self.validate() return my_offset
def parse_option(self): self.length, self.option = Option.parse(self.option_bytes) self.assertIsInstance(self.option, Option) self.option_class = type(self.option)