def from_bytes(cls, bitstream): packet = cls() # Convert to ConstBitStream (if not already provided) if not isinstance(bitstream, ConstBitStream): if isinstance(bitstream, Bits): bitstream = ConstBitStream(auto=bitstream) else: bitstream = ConstBitStream(bytes=bitstream) # Read the next header type packet.next_header = bitstream.read('uint:8') # Read the header length, given in multiples of 8 octets header_length = bitstream.read('uint:8') + 1 # Read the options options_length = (header_length * 8) - 2 packet.options = bitstream.read('bytes:%d' % options_length) # And the rest is payload remaining = bitstream[bitstream.pos:] packet.payload = remaining.bytes payload_class = protocol_registry.get_type_class(packet.next_header) if payload_class: packet.payload = payload_class.from_bytes(packet.payload) # Verify that the properties make sense packet.sanitize() return packet
def from_bytes(cls, bitstream, decode_payload=True): """ Parse the given packet and update properties accordingly """ packet = cls() # Convert to ConstBitStream (if not already provided) if not isinstance(bitstream, ConstBitStream): if isinstance(bitstream, Bits): bitstream = ConstBitStream(auto=bitstream) else: bitstream = ConstBitStream(bytes=bitstream) # Read the version version = bitstream.read("uint:4") if version != packet.version: raise ValueError("Provided bytes do not contain an IPv6 packet") # Read the traffic class packet.traffic_class = bitstream.read("uint:8") # Read the flow label packet.flow_label = bitstream.read("uint:20") # Read the payload length payload_length = bitstream.read("uint:16") # Read the next header type packet.next_header = bitstream.read("uint:8") # Read the hop limit packet.hop_limit = bitstream.read("uint:8") # Read the source and destination addresses packet.source = IPv6Address(bitstream.read("uint:128")) packet.destination = IPv6Address(bitstream.read("uint:128")) # And the rest is payload packet.payload = bitstream.read("bytes:%d" % payload_length) if decode_payload: payload_class = protocol_registry.get_type_class(packet.next_header) if payload_class: packet.payload = payload_class.from_bytes(packet.payload) # There should be no remaining bits if bitstream.pos != bitstream.len: raise ValueError("Bits remaining after processing packet") # Verify that the properties make sense packet.sanitize() return packet
def from_bytes(cls, bitstream, decode_payload=True): ''' Parse the given packet and update properties accordingly ''' packet = cls() # Convert to ConstBitStream (if not already provided) if not isinstance(bitstream, ConstBitStream): if isinstance(bitstream, Bits): bitstream = ConstBitStream(auto=bitstream) else: bitstream = ConstBitStream(bytes=bitstream) # Read the version version = bitstream.read('uint:4') if version != packet.version: raise ValueError('Provided bytes do not contain an IPv4 packet') # Read the header length ihl = bitstream.read('uint:4') if ihl < 5: raise ValueError('Invalid IPv4 header length') # Now that we know the length of the header we store it to be able # to easily recalculate the header checksum later remaining_header_bits = (ihl * 32) - 8 header = (BitStream('uint:4=4, uint:4=%d' % ihl) + bitstream.peek(remaining_header_bits)) # Read the type of service packet.tos = bitstream.read('uint:8') # Read the total length total_length = bitstream.read('uint:16') if total_length < ihl * 4: raise ValueError('Total length is shorter than the header') # Read the identification packet.identification = bitstream.read('uint:16') # Read the flags (reserved, packet.dont_fragment, packet.more_fragments) = bitstream.readlist('3*bool') if reserved: raise ValueError('Reserved flag must be 0') # Read the fragment offset packet.fragment_offset = bitstream.read('uint:13') # Read the TTL packet.ttl = bitstream.read('uint:8') # Read the protocol number packet.protocol = bitstream.read('uint:8') # Read the header checksum header_checksum = bitstream.read('uint:16') # Set the checksum bits in the header to 0 and re-calculate header[80:96] = BitStream(16) my_checksum = checksum.ones_complement(header.bytes) if my_checksum != header_checksum: raise ValueError('Header checksum does not match') # Read the source and destination addresses packet.source = IPv4Address(bitstream.read('uint:32')) packet.destination = IPv4Address(bitstream.read('uint:32')) # Read the options option_len = (ihl - 5) * 4 packet.options = bitstream.read('bytes:%d' % option_len) # And the rest is payload payload_bytes = (total_length) - (ihl * 4) packet.payload = bitstream.read('bytes:%d' % payload_bytes) if decode_payload: payload_class = protocol_registry.get_type_class(packet.protocol) if payload_class: packet.payload = payload_class.from_bytes(packet.payload) # There should be no remaining bits if bitstream.pos != bitstream.len: raise ValueError('Bits remaining after processing packet') # Verify that the properties make sense packet.sanitize() return packet