def setUp(self): self.relayed_solicit_message = RelayForwardMessage( hop_count=1, link_address=IPv6Address('2001:db8:ffff:1::1'), peer_address=IPv6Address('fe80::3631:c4ff:fe3c:b2f1'), options=[ RelayMessageOption(relayed_message=RelayForwardMessage( hop_count=0, link_address=IPv6Address('::'), peer_address=IPv6Address('fe80::3631:c4ff:fe3c:b2f1'), options=[ RelayMessageOption(relayed_message=SolicitMessage( transaction_id=bytes.fromhex('f350d6'), options=[ ElapsedTimeOption(elapsed_time=0), ClientIdOption(duid=LinkLayerDUID(hardware_type=1, link_layer_address=bytes.fromhex('3431c43cb2f1'))), IANAOption(iaid=bytes.fromhex('c43cb2f1')), IAPDOption(iaid=bytes.fromhex('c43cb2f1')), OptionRequestOption(requested_options=[ OPTION_DNS_SERVERS, ]), ], )), InterfaceIdOption(interface_id=b'Fa2/3'), RemoteIdOption(enterprise_number=9, remote_id=bytes.fromhex('020023000001000a0003000100211c7d486e')), ]) ), InterfaceIdOption(interface_id=b'Gi0/0/0'), RemoteIdOption(enterprise_number=9, remote_id=bytes.fromhex('020000000000000a0003000124e9b36e8100')), RelayIdOption(duid=LinkLayerDUID(hardware_type=1, link_layer_address=bytes.fromhex('121212121212'))), ], )
def setUp(self): self.packet_fixture = bytes.fromhex( '0e' # Message type LeaseQuery 'e86f0c' # Transaction ID '0001' # Option type 1: OPTION_CLIENT_ID '000a' # Option length: 10 '0003' # DUID type: DUID_LL '0001' # Hardware type: Ethernet '001ee6f77d00' # MAC Address '002c' # Option type 44: OPTION_LQ_QUERY '0017' # Option length: 23 '01' # Query type: QUERY_BY_ADDRESS 'fe800000000000000000000000000001' # Link address: fe80::1 '0006' # Option type: OPTION_ORO '0002' # Option length: 2 '002f' # Requested option: OPTION_LQ_RELAY_DATA ) self.message_fixture = LeaseQueryMessage( transaction_id=bytes.fromhex('e86f0c'), options=[ ClientIdOption(duid=LinkLayerDUID( hardware_type=1, link_layer_address=bytes.fromhex('001ee6f77d00'))), LQQueryOption( query_type=QUERY_BY_ADDRESS, link_address=IPv6Address('fe80::1'), options=[ OptionRequestOption( requested_options=[OPTION_LQ_RELAY_DATA]), ]), ]) self.parse_packet()
def test_query_by_address_with_relay_data(self): bundle = TransactionBundle(self.relayed_solicit_message, received_over_multicast=False) bundle.response = reply_message ia_na_option = bundle.response.get_option_of_type(IANAOption) ia_address = ia_na_option.get_option_of_type(IAAddressOption) query = LQQueryOption(QUERY_BY_ADDRESS, options=[ia_address, OptionRequestOption([OPTION_LQ_RELAY_DATA])]) self.query(bundle, query, [LQRelayDataOption])
def test_query_by_address_with_extra_data(self): bundle = TransactionBundle(self.relayed_solicit_message, received_over_multicast=False) bundle.response = reply_message ia_na_option = bundle.response.get_option_of_type(IANAOption) ia_address = ia_na_option.get_option_of_type(IAAddressOption) query = LQQueryOption(QUERY_BY_ADDRESS, options=[ia_address, OptionRequestOption([OPTION_DNS_SERVERS])]) self.query(bundle, query, [RecursiveNameServersOption])
def setUp(self): self.option_bytes = bytes.fromhex( '002c' # Option type 44: OPTION_LQ_QUERY '0017' # Option length: 23 '01' # Query type: QUERY_BY_ADDRESS 'fe800000000000000000000000000001' # Link address: fe80::1 '0006' # Option type: OPTION_ORO '0002' # Option length: 2 '002f' # Requested option: OPTION_LQ_RELAY_DATA ) self.option_object = LQQueryOption( query_type=QUERY_BY_ADDRESS, link_address=IPv6Address('fe80::1'), options=[ OptionRequestOption(requested_options=[OPTION_LQ_RELAY_DATA]), ]) self.parse_option()
ClientIdOption(duid=LinkLayerDUID( hardware_type=1, link_layer_address=bytes.fromhex('3431c43cb2f1'))), RapidCommitOption(), IANAOption(iaid=bytes.fromhex('c43cb2f1')), IAPDOption(iaid=bytes.fromhex('c43cb2f1'), options=[ IAPrefixOption( prefix=IPv6Network('::/0')), ]), ReconfigureAcceptOption(), OptionRequestOption(requested_options=[ OPTION_DNS_SERVERS, OPTION_NTP_SERVER, OPTION_SNTP_SERVERS, OPTION_IA_PD, OPTION_IA_NA, OPTION_VENDOR_OPTS, OPTION_SOL_MAX_RT, OPTION_INF_MAX_RT, ]), VendorClassOption(enterprise_number=872), ], )), InterfaceIdOption(interface_id=b'Fa2/3'), RemoteIdOption(enterprise_number=9, remote_id=bytes.fromhex( '020023000001000a0003000100211c7d486e')), ])), InterfaceIdOption(interface_id=b'Gi0/0/0'), RemoteIdOption( enterprise_number=9,
def test_bad_option_length(self): with self.assertRaisesRegex(ValueError, 'Invalid option length'): OptionRequestOption.parse(bytes.fromhex('0006000300030004'))
def test_bad_option_length(self): with self.assertRaisesRegex(ValueError, 'Invalid option length'): OptionRequestOption.parse(bytes.fromhex('0006000300030004'))
def setUp(self): self.option_bytes = bytes.fromhex('0006000400030004') self.option_object = OptionRequestOption( requested_options=[OPTION_IA_NA, OPTION_IA_TA]) self.parse_option()
def main(args: Iterable[str]) -> int: """ The main program :param args: Command line arguments :return: The program exit code """ # Handle command line arguments options = handle_args(args) set_verbosity_logger(logger, options.verbosity) query = options.create(options) # Add ORO for relay data if options.relay_data: query.options.append(OptionRequestOption([OPTION_LQ_RELAY_DATA])) # Generate the outgoing message transaction_id = random.getrandbits(24).to_bytes(3, 'big') message_out = LeasequeryMessage( transaction_id, [ClientIdOption(EnterpriseDUID(40208, b'LeaseQueryTester')), query]) # Create client socket if options.tcp: client = TCPClientSocket(options) else: # Check permission if os.getuid() != 0: raise RuntimeError("This tool needs to be run as root") client = UDPClientSocket(options) destination = client.send(message_out) logger.info("Sent to {}:\n{}".format(destination, message_out)) # Wait for responses wait_for_multiple = options.server.is_multicast or options.tcp start = time.time() deadline = start + 3 received = 0 while time.time() < deadline: client.set_timeout(deadline - time.time()) try: sender, message_in = client.recv() received += 1 logger.info("Received from {}:\n{}".format(sender, message_in)) if options.tcp: # Check bulk leasequery ending if isinstance(message_in, LeasequeryReplyMessage): if not message_in.get_option_of_type(ClientDataOption): # Reply without data, the end break if isinstance(message_in, LeasequeryDoneMessage): break if not wait_for_multiple: break except socket.timeout: pass logger.info( gettext.ngettext("{} response received", "{} responses received", received).format(received)) return 0