def test_failed_send_relayed(self): multicast_socket = MockSocket(AF_INET6, IPPROTO_UDP, All_DHCP_Relay_Agents_and_Servers, SERVER_PORT, 42, 1608) link_local_socket = MockSocket(AF_INET6, IPPROTO_UDP, 'fe80::1%eth0', SERVER_PORT, 42, 1608) link_local_socket.pretend_sendto_fails = True # noinspection PyTypeChecker listening_socket = ListeningSocket('eth0', multicast_socket, link_local_socket, global_address=IPv6Address('2001:db8::1')) outgoing_message = RelayReplyMessage(hop_count=0, link_address=IPv6Address('2001:db8::1'), peer_address=IPv6Address('fe80::babe'), options=[ InterfaceIdOption(interface_id=b'eth0'), RelayMessageOption(relayed_message=relayed_advertise_message) ]) with self.assertLogs(level=logging.DEBUG) as logged: success = listening_socket.send_reply(outgoing_message) self.assertFalse(success) # Nothing should be sent from a multicast socket with self.assertRaises(IndexError): multicast_socket.read_from_outgoing_queue() # It must be on the link local socket sent_packet, recipient = link_local_socket.read_from_outgoing_queue() self.assertNotEqual(sent_packet, relayed_advertise_packet) log_output = '\n'.join(logged.output) self.assertRegex(log_output, r'AdvertiseMessage') self.assertRegex(log_output, r'to fe80::3631:c4ff:fe3c:b2f1') self.assertRegex(log_output, r"via Fa2/3 of relay fe80::babe")
def test_send_relayed_without_interface_id(self): multicast_socket = MockSocket(AF_INET6, IPPROTO_UDP, All_DHCP_Relay_Agents_and_Servers, SERVER_PORT, 42, 1608) link_local_socket = MockSocket(AF_INET6, IPPROTO_UDP, 'fe80::1%eth0', SERVER_PORT, 42, 1608) # noinspection PyTypeChecker listening_socket = ListeningSocket('eth0', multicast_socket, link_local_socket, global_address=IPv6Address('2001:db8::1')) # Start with a clean parse and then change interface-id new_message = Message.parse(relayed_advertise_packet)[1] interface_id_option = new_message.inner_relay_message.get_option_of_type(InterfaceIdOption) new_message.inner_relay_message.options.remove(interface_id_option) outgoing_message = RelayReplyMessage(hop_count=0, link_address=IPv6Address('2001:db8::1'), peer_address=IPv6Address('fe80::babe'), options=[ InterfaceIdOption(interface_id=b'eth0'), RelayMessageOption(relayed_message=new_message) ]) with self.assertLogs(level=logging.DEBUG) as logged: listening_socket.send_reply(outgoing_message) log_output = '\n'.join(logged.output) self.assertRegex(log_output, r'Sent AdvertiseMessage') self.assertRegex(log_output, r'to fe80::3631:c4ff:fe3c:b2f1') self.assertRegex(log_output, r"via relay fe80::babe")
def test_send_unwrapped(self): multicast_socket = MockSocket(AF_INET6, IPPROTO_UDP, All_DHCP_Relay_Agents_and_Servers, SERVER_PORT, 42, 1608) link_local_socket = MockSocket(AF_INET6, IPPROTO_UDP, 'fe80::1%eth0', SERVER_PORT, 42, 1608) # noinspection PyTypeChecker listening_socket = ListeningSocket('eth0', multicast_socket, link_local_socket, global_address=IPv6Address('2001:db8::1')) with self.assertRaisesRegex(ValueError, r'has to be wrapped'): listening_socket.send_reply(advertise_message)
def test_receive_bad_message(self): multicast_socket = MockSocket(AF_INET6, IPPROTO_UDP, All_DHCP_Relay_Agents_and_Servers, SERVER_PORT, 42, 1608) link_local_socket = MockSocket(AF_INET6, IPPROTO_UDP, 'fe80::1%eth0', SERVER_PORT, 42, 1608) # noinspection PyTypeChecker listening_socket = ListeningSocket('eth0', multicast_socket, link_local_socket, global_address=IPv6Address('2001:db8::1')) multicast_socket.add_to_incoming_queue(b'\x01ThisIsNotAValidDHCPv6Message', ('2001:db8::babe', 546, 0, 42)) with self.assertRaisesRegex(InvalidPacketError, r"Invalid packet from \('2001:db8::babe', 546, 0, 42\)"): listening_socket.recv_request()
def test_constructor_link_local(self): link_local_socket = MockSocket(AF_INET6, IPPROTO_UDP, 'fe80::1%eth0', SERVER_PORT, 42, 1608) # noinspection PyTypeChecker listening_socket = ListeningSocket('eth0', link_local_socket, global_address=IPv6Address('2001:db8::1')) self.assertEqual(listening_socket.interface_name, 'eth0') self.assertEqual(listening_socket.interface_id, b'eth0') self.assertEqual(listening_socket.interface_index, 42) self.assertEqual(listening_socket.listen_socket, link_local_socket) self.assertEqual(listening_socket.listen_address, IPv6Address('fe80::1')) self.assertEqual(listening_socket.reply_socket, link_local_socket) self.assertEqual(listening_socket.reply_address, IPv6Address('fe80::1')) self.assertEqual(listening_socket.global_address, IPv6Address('2001:db8::1')) self.assertEqual(listening_socket.fileno(), 1608)
def test_send_empty_wrapper(self): multicast_socket = MockSocket(AF_INET6, IPPROTO_UDP, All_DHCP_Relay_Agents_and_Servers, SERVER_PORT, 42, 1608) link_local_socket = MockSocket(AF_INET6, IPPROTO_UDP, 'fe80::1%eth0', SERVER_PORT, 42, 1608) # noinspection PyTypeChecker listening_socket = ListeningSocket('eth0', multicast_socket, link_local_socket, global_address=IPv6Address('2001:db8::1')) outgoing_message = RelayReplyMessage(hop_count=0, link_address=IPv6Address('2001:db8::1'), peer_address=IPv6Address('fe80::babe'), options=[ InterfaceIdOption(interface_id=b'eth0'), ]) with self.assertRaisesRegex(ValueError, r'not contain a message'): listening_socket.send_reply(outgoing_message)
def test_receive_unknown_message_type(self): multicast_socket = MockSocket(AF_INET6, IPPROTO_UDP, All_DHCP_Relay_Agents_and_Servers, SERVER_PORT, 42, 1608) link_local_socket = MockSocket(AF_INET6, IPPROTO_UDP, 'fe80::1%eth0', SERVER_PORT, 42, 1608) # noinspection PyTypeChecker listening_socket = ListeningSocket('eth0', multicast_socket, link_local_socket, global_address=IPv6Address('2001:db8::1')) multicast_socket.add_to_incoming_queue(b'\xffThisIsNotAValidDHCPv6Message', ('2001:db8::babe', 546, 0, 42)) received_message = listening_socket.recv_request() self.assertIsInstance(received_message, RelayForwardMessage) self.assertEqual(received_message.hop_count, 0) self.assertEqual(received_message.link_address, IPv6Address('2001:db8::1')) self.assertEqual(received_message.peer_address, IPv6Address('2001:db8::babe')) self.assertEqual(received_message.get_option_of_type(InterfaceIdOption).interface_id, b'eth0') self.assertIsInstance(received_message.relayed_message, UnknownMessage) self.assertEqual(received_message.relayed_message.message_type, 255)
def test_receive_relayed_with_unprintable_interface_id(self): global_unicast_socket = MockSocket(AF_INET6, IPPROTO_UDP, '2001:db8::1', SERVER_PORT, 42, 1608) # noinspection PyTypeChecker listening_socket = ListeningSocket('eth0', global_unicast_socket) # Start with a clean parse and then change interface-id new_message = Message.parse(relayed_solicit_packet)[1] new_message.inner_relay_message.get_option_of_type(InterfaceIdOption).interface_id = b'\x80\x81\x82' global_unicast_socket.add_to_incoming_queue(bytes(new_message.save()), ('2001:db8::babe', 546, 0, 42)) with self.assertLogs(level=logging.DEBUG) as logged: listening_socket.recv_request() log_output = '\n'.join(logged.output) self.assertRegex(log_output, r'Received SolicitMessage') self.assertRegex(log_output, r'from fe80::3631:c4ff:fe3c:b2f1') self.assertRegex(log_output, r"via b'\\x80\\x81\\x82' of relay 2001:db8::babe")
def test_receive_relayed(self): global_unicast_socket = MockSocket(AF_INET6, IPPROTO_UDP, '2001:db8::1', SERVER_PORT, 42, 1608) # noinspection PyTypeChecker listening_socket = ListeningSocket('eth0', global_unicast_socket) global_unicast_socket.add_to_incoming_queue(relayed_solicit_packet, ('2001:db8::babe', 546, 0, 42)) with self.assertLogs(level=logging.DEBUG) as logged: received_message = listening_socket.recv_request() self.assertIsInstance(received_message, RelayForwardMessage) self.assertEqual(received_message.hop_count, 2) self.assertEqual(received_message.link_address, IPv6Address('2001:db8::1')) self.assertEqual(received_message.peer_address, IPv6Address('2001:db8::babe')) self.assertEqual(received_message.get_option_of_type(InterfaceIdOption).interface_id, b'eth0') self.assertEqual(received_message.relayed_message, relayed_solicit_message) log_output = '\n'.join(logged.output) self.assertRegex(log_output, r'Received SolicitMessage') self.assertRegex(log_output, r'from fe80::3631:c4ff:fe3c:b2f1') self.assertRegex(log_output, r'via Fa2/3 of relay 2001:db8::babe')
def test_receive_direct(self): multicast_socket = MockSocket(AF_INET6, IPPROTO_UDP, All_DHCP_Relay_Agents_and_Servers, SERVER_PORT, 42, 1608) link_local_socket = MockSocket(AF_INET6, IPPROTO_UDP, 'fe80::1%eth0', SERVER_PORT, 42, 1608) # noinspection PyTypeChecker listening_socket = ListeningSocket('eth0', multicast_socket, link_local_socket, global_address=IPv6Address('2001:db8::1')) multicast_socket.add_to_incoming_queue(solicit_packet, ('2001:db8::babe', 546, 0, 42)) with self.assertLogs(level=logging.DEBUG) as logged: received_message = listening_socket.recv_request() self.assertIsInstance(received_message, RelayForwardMessage) self.assertEqual(received_message.hop_count, 0) self.assertEqual(received_message.link_address, IPv6Address('2001:db8::1')) self.assertEqual(received_message.peer_address, IPv6Address('2001:db8::babe')) self.assertEqual(received_message.get_option_of_type(InterfaceIdOption).interface_id, b'eth0') self.assertEqual(received_message.relayed_message, solicit_message) log_output = '\n'.join(logged.output) self.assertRegex(log_output, r'Received SolicitMessage') self.assertRegex(log_output, r'from 2001:db8::babe')
def test_send_badly_wrapped(self): multicast_socket = MockSocket(AF_INET6, IPPROTO_UDP, All_DHCP_Relay_Agents_and_Servers, SERVER_PORT, 42, 1608) link_local_socket = MockSocket(AF_INET6, IPPROTO_UDP, 'fe80::1%eth0', SERVER_PORT, 42, 1608) # noinspection PyTypeChecker listening_socket = ListeningSocket('eth0', multicast_socket, link_local_socket, global_address=IPv6Address('2001:db8::1')) with self.assertRaisesRegex(ValueError, r'link-address does not match'): listening_socket.send_reply(relayed_advertise_message) # Fix the link-address so the test continues to the interface-id # noinspection PyTypeChecker listening_socket = ListeningSocket('eth0', multicast_socket, link_local_socket, global_address=IPv6Address('2001:db8:ffff:1::1')) with self.assertRaisesRegex(ValueError, r'interface-id in the reply does not match'): listening_socket.send_reply(relayed_advertise_message)