def test_afi_65535(self): ''' AFI 65535 is reserved ''' afi_address_hex = 'ffffabcdabcdabcd' bitstream = ConstBitStream(hex=afi_address_hex) with self.assertRaisesRegexp(ValueError, 'AFI'): afi.read_afi_address_from_bitstream(bitstream)
def from_bytes(cls, bitstream): ''' 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 type type_nr = bitstream.read('uint:4') if type_nr != packet.message_type: msg = 'Invalid bitstream for a {0} packet' class_name = packet.__class__.__name__ raise ValueError(msg.format(class_name)) # Read if this is a reply packet.is_reply = bitstream.read('bool') # Skip reserved bits packet._reserved1 = bitstream.read(27) # Read the nonce packet.nonce = bitstream.read('bytes:8') # Read the key id packet.key_id = bitstream.read('uint:16') # Read the authentication data data_length = bitstream.read('uint:16') packet.authentication_data = bitstream.read('bytes:%d' % data_length) # Read the TTL packet.ttl = bitstream.read('uint:32') # Skip reserved bits packet._reserved2 = bitstream.read(8) # Store the EID prefix mask length until we need it eid_prefix_len = bitstream.read('uint:8') # Read the EID prefix packet.eid_prefix = read_afi_address_from_bitstream(bitstream, eid_prefix_len) # Read the reply packet.reply = read_afi_address_from_bitstream(bitstream) # Verify that the properties make sense packet.sanitize() return packet
def test_afi_0_with_prefixlen(self): ''' Specifying a prefix length for an empty AFI address is invalid ''' bitstream = ConstBitStream(hex='0000') with self.assertRaisesRegexp(ValueError, r'prefix'): afi.read_afi_address_from_bitstream(bitstream, 16) self.assertEqual(bitstream.pos, bitstream.len, 'unprocessed bits remaining in bitstream')
def test_afi_2_with_bad_prefixlen(self): ''' Test decoding of AFI 2 (IPv6) prefixes with a bad prefix length ''' afi_address_hex = '000220010db80102abcd000000000000cafe' bitstream = ConstBitStream(hex=afi_address_hex) with self.assertRaisesRegexp(ValueError, 'invalid.prefix.length'): afi.read_afi_address_from_bitstream(bitstream, 64) self.assertEqual(bitstream.pos, bitstream.len, 'unprocessed bits remaining in bitstream')
def _from_data_bytes(cls, data, prefix_len=None, rsvd1=None, flags=None, rsvd2=None): (north, latitude_degrees, latitude_minutes, latitude_seconds) = data.readlist('bool, uint:15, 2*uint:8') (east, longitude_degrees, longitude_minutes, longitude_seconds) = data.readlist('bool, uint:15, 2*uint:8') altitude = data.read('int:32') address = read_afi_address_from_bitstream(data) if prefix_len is not None: orig_address = address address = ip_network(address).supernet(new_prefix=prefix_len) if address[0] != orig_address: raise ValueError("invalid prefix length %s for %r" % (prefix_len, address)) lcaf = cls(north=north, latitude_degrees=latitude_degrees, latitude_minutes=latitude_minutes, latitude_seconds=latitude_seconds, east=east, longitude_degrees=longitude_degrees, longitude_minutes=longitude_minutes, longitude_seconds=longitude_seconds, altitude=altitude, address=address) lcaf.sanitize() return lcaf
def from_bytes(cls, bitstream): """ Parse the given record and update properties accordingly """ record = 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 record TTL record.ttl = bitstream.read("uint:32") # Store the locator record count until we need it referral_count = bitstream.read("uint:8") # Store the EID prefix mask length until we need it eid_prefix_len = bitstream.read("uint:8") # Read the Negative Map_Reply action record.action = bitstream.read("uint:3") # Read the flags (record.authoritative, record.incomplete) = bitstream.readlist("2*bool") # Read reserved bits record._reserved1 = bitstream.read(11) # Read the signature count sig_count = bitstream.read("uint:4") # Read the map version record.map_version = bitstream.read("uint:12") # Read the EID prefix record.eid_prefix = read_afi_address_from_bitstream(bitstream, eid_prefix_len) # Read the locator records for dummy in range(referral_count): locator_record = LocatorRecord.from_bytes(bitstream) record.locator_records.append(locator_record) # TODO: Can't handle signatures yet! [LISP-Security] if sig_count: raise NotImplementedError("Cannot handle signatures yet") # Verify that the properties make sense record.sanitize() return record
def _from_data_bytes(cls, data, prefix_len=None, rsvd1=None, flags=None, rsvd2=None): # These are fixed map_server_port, etr_port = data.readlist('2*uint:16') global_etr_rloc = read_afi_address_from_bitstream(data) map_server_rloc = read_afi_address_from_bitstream(data) private_etr_rloc = read_afi_address_from_bitstream(data) # The rest of the data is RTR RLOCs rtr_rlocs = [] while data.pos != data.len: rtr_rlocs.append(read_afi_address_from_bitstream(data)) # Build the object lcaf = cls(map_server_port=map_server_port, etr_port=etr_port, global_etr_rloc=global_etr_rloc, map_server_rloc=map_server_rloc, private_etr_rloc=private_etr_rloc, rtr_rlocs=rtr_rlocs) lcaf.sanitize() return lcaf
def _from_data_bytes(cls, data, prefix_len=None, rsvd1=None, flags=None, rsvd2=None): asn = data.read('uint:32') address = read_afi_address_from_bitstream(data) if prefix_len is not None: orig_address = address address = ip_network(address).supernet(new_prefix=prefix_len) if address[0] != orig_address: raise ValueError("invalid prefix length %s for %r" % (prefix_len, address)) lcaf = cls(asn=asn, address=address) lcaf.sanitize() return lcaf
def test_afi_1_with_prefixlen(self): ''' Test decoding of AFI 1 (IPv4) prefixes ''' afi_address_hex = '0001c0000200' bitstream = ConstBitStream(hex=afi_address_hex) address = afi.read_afi_address_from_bitstream(bitstream, 24) self.assertEqual(address, IPv4Network(u'192.0.2.0/24')) self.assertEqual(bitstream.pos, bitstream.len, 'unprocessed bits remaining in bitstream') new_bitstream = afi.get_bitstream_for_afi_address(address) self.assertEqual(new_bitstream.tobytes(), bitstream.tobytes())
def test_afi_0_without_prefixlen(self): ''' Test en/decoding of empty AFI addresses ''' afi_address_hex = '0000' bitstream = ConstBitStream(hex=afi_address_hex) address = afi.read_afi_address_from_bitstream(bitstream) self.assertIsNone(address, 'wrong address') self.assertEqual(bitstream.pos, bitstream.len, 'unprocessed bits remaining in bitstream') new_bitstream = afi.get_bitstream_for_afi_address(address) self.assertEqual(new_bitstream.tobytes(), bitstream.tobytes())
def test_afi_2_with_prefixlen(self): ''' Test decoding of AFI 2 (IPv6) prefixes ''' afi_address_hex = '000220010db80102abcd0000000000000000' bitstream = ConstBitStream(hex=afi_address_hex) address = afi.read_afi_address_from_bitstream(bitstream, 64) self.assertEqual(address, IPv6Network(u'2001:db8:102:abcd::/64')) self.assertEqual(bitstream.pos, bitstream.len, 'unprocessed bits remaining in bitstream') new_bitstream = afi.get_bitstream_for_afi_address(address) self.assertEqual(new_bitstream.tobytes(), bitstream.tobytes())
def from_bytes(cls, bitstream): ''' Parse the given record and update properties accordingly ''' record = 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 record TTL record.ttl = bitstream.read('uint:32') # Store the locator record count until we need it locator_record_count = bitstream.read('uint:8') # Store the EID prefix mask length until we need it eid_prefix_len = bitstream.read('uint:8') # Read the Negative Map_Reply action record.action = bitstream.read('uint:3') # Read the flag record.authoritative = bitstream.read('bool') # Read reserved bits record._reserved1 = bitstream.read(12 + 4) # Read the map version record.map_version = bitstream.read('uint:12') # Read the EID prefix record.eid_prefix = read_afi_address_from_bitstream(bitstream, eid_prefix_len) # Read the locator records for dummy in range(locator_record_count): locator_record = LocatorRecord.from_bytes(bitstream) record.locator_records.append(locator_record) # Verify that the properties make sense record.sanitize() return record
def test_afi_0_with_prefixlen_0(self): ''' Although a prefix length of 0 is allowed (since that is how many implementations transmit it on the wire) ''' afi_address_hex = '0000' bitstream = ConstBitStream(hex=afi_address_hex) address = afi.read_afi_address_from_bitstream(bitstream, 0) self.assertIsNone(address, 'wrong address') self.assertEqual(bitstream.pos, bitstream.len, 'unprocessed bits remaining in bitstream') new_bitstream = afi.get_bitstream_for_afi_address(address) self.assertEqual(new_bitstream.tobytes(), bitstream.tobytes())
def from_bytes(cls, bitstream): r''' Parse the given packet and update properties accordingly >>> data_hex = ('13000001ae92b5574f849cd00001ac10' ... '1f0300015cfe1cbd00200001ac101f01') >>> data = data_hex.decode('hex') >>> message = ControlMessage.from_bytes(data) >>> message.message_type 1 >>> message.authoritative False >>> message.probe True >>> message.smr True >>> message.pitr False >>> message.smr_invoked False >>> message.nonce '\xae\x92\xb5WO\x84\x9c\xd0' >>> message.source_eid IPv4Address(u'172.16.31.3') >>> message.itr_rlocs [IPv4Address(u'92.254.28.189')] >>> message.eid_prefixes [IPv4Network(u'172.16.31.1/32')] >>> message.map_reply ''' 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 message type type_nr = bitstream.read('uint:4') if type_nr != packet.message_type: msg = 'Invalid bitstream for a {0} packet' class_name = packet.__class__.__name__ raise ValueError(msg.format(class_name)) # Read the flags (packet.authoritative, map_data_present, packet.probe, packet.smr, packet.pitr, packet.smr_invoked) = bitstream.readlist('6*bool') # Skip over reserved bits packet._reserved1 = bitstream.read(9) # Save the IRC until we reach the actual data irc = bitstream.read('uint:5') # Save the record count until we reach the actual data record_count = bitstream.read('uint:8') # Read the nonce packet.nonce = bitstream.read('bytes:8') # Read the source EID packet.source_eid = read_afi_address_from_bitstream(bitstream) # Read the ITR RLOCs for dummy in range(irc + 1): itr_rloc = read_afi_address_from_bitstream(bitstream) packet.itr_rlocs.append(itr_rloc) # Read the EIDs for dummy in range(record_count): # A records begins with 8 reserved bits: skip bitstream.read(8) # Read 8 bits for the prefix length prefix_len = bitstream.read('uint:8') # Then an AFI style prefix eid_prefix = read_afi_address_from_bitstream(bitstream, prefix_len) packet.eid_prefixes.append(eid_prefix) # Read the map-reply record if present if map_data_present: packet.map_reply = MapReplyRecord.from_bytes(bitstream) # Verify that the properties make sense packet.sanitize() return packet