Пример #1
0
    def wrap_response(self,
                      response: ClientServerMessage) -> RelayReplyMessage:
        """
        The incoming message was wrapped in this RelayForwardMessage. Let this RelayForwardMessage then create a
        RelayReplyMessage with the correct options and wrap the reply .

        :param response: The response that is going to be sent to the client
        :return: The RelayReplyMessage wrapping the response
        :rtype: RelayReplyMessage
        """
        from dhcpkit.ipv6.options import RelayMessageOption

        my_response = RelayReplyMessage(self.hop_count, self.link_address,
                                        self.peer_address)

        my_relayed_message = self.relayed_message
        if isinstance(my_relayed_message, RelayForwardMessage):
            # Our relayed message is another relay message: let it create its own reply
            my_response.options.append(
                RelayMessageOption(relayed_message=my_relayed_message.
                                   wrap_response(response)))
        elif isinstance(my_relayed_message, ClientServerMessage):
            # Our relayed message is a ClientServerMessage, so place the response here in the RelayReplyMessage
            my_response.options.append(
                RelayMessageOption(relayed_message=response))

        return my_response
Пример #2
0
 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'))),
         ],
     )
Пример #3
0
    def test_bad_message_length(self):
        # Add a fake message type to the registry
        message_registry[254] = WeirdLengthMessage

        with self.assertRaisesRegex(ValueError, 'different length'):
            RelayMessageOption.parse(bytes.fromhex('00090006fe1234567890'))

        # And clean it up again
        del message_registry[254]
    def test_bad_message_length(self):
        # Add a fake message type to the registry
        message_registry[254] = WeirdLengthMessage

        with self.assertRaisesRegex(ValueError, 'different length'):
            RelayMessageOption.parse(bytes.fromhex('00090006fe1234567890'))

        # And clean it up again
        del message_registry[254]
Пример #5
0
    def setUp(self):
        # The following attributes must be overruled by child classes
        # The basics are tested with nested RelayForwardMessages
        self.packet_fixture = bytes.fromhex(
            '0c'  # message_type: MSG_RELAY_FORW
            '02'  # hop_count
            '20010db8000000000000000000020001'  # link_address
            '20010db8000000000000000000020002'  # peer_address
            '0009'  # option_type: OPTION_RELAY_MSG
            '0051'  # option_length
            '0c'  # message_type: MSG_RELAY_FORW
            '01'  # hop_count
            '20010db8000000000000000000010001'  # link_address
            '20010db8000000000000000000010002'  # peer_address
            '0009'  # option_type: OPTION_RELAY_MSG
            '002b'  # option_length
            '0c'  # message_type: MSG_RELAY_FORW
            '00'  # hop_count
            '20010db8000000000000000000000001'  # link_address
            '20010db8000000000000000000000002'  # peer_address
            '0009'  # option_type: OPTION_RELAY_MSG
            '0005'  # option_length
            'ff'  # some unknown  message_type: 255
            '41424344')  # some random message_data: 'ABCD'

        self.message_fixture = RelayForwardMessage(
            hop_count=2,
            link_address=IPv6Address('2001:db8::2:1'),
            peer_address=IPv6Address('2001:db8::2:2'),
            options=[
                RelayMessageOption(relayed_message=RelayForwardMessage(
                    hop_count=1,
                    link_address=IPv6Address('2001:db8::1:1'),
                    peer_address=IPv6Address('2001:db8::1:2'),
                    options=[
                        RelayMessageOption(relayed_message=RelayForwardMessage(
                            hop_count=0,
                            link_address=IPv6Address('2001:db8::1'),
                            peer_address=IPv6Address('2001:db8::2'),
                            options=[
                                RelayMessageOption(
                                    relayed_message=UnknownMessage(
                                        255, b'ABCD'))
                            ]))
                    ]))
            ])

        self.parse_packet()
    def test_absent_option_echo_request(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=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')),
                    ],
                )),
                EchoRequestOption(requested_options=[OPTION_SUBSCRIBER_ID]),
                UnknownOption(option_type=65535),
                InterfaceIdOption(interface_id=b'Fa2/3'),
                RemoteIdOption(enterprise_number=9,
                               remote_id=bytes.fromhex('020023000001000a0003000100211c7d486e')),
            ]
        )

        bundle = TransactionBundle(incoming_message=relayed_solicit_message, received_over_multicast=True)
        self.message_handler.handle(bundle, StatisticsSet())

        self.assertIsInstance(bundle.outgoing_message, RelayReplyMessage)
        self.assertEqual(len(bundle.outgoing_message.options), 2)
        self.assertIsInstance(bundle.outgoing_message.options[0], InterfaceIdOption)
        self.assertIsInstance(bundle.outgoing_message.options[1], RelayMessageOption)
Пример #7
0
 def setUp(self):
     self.bundle = TransactionBundle(relayed_solicit_message,
                                     received_over_multicast=False)
     self.shallow_bundle = TransactionBundle(solicit_message,
                                             received_over_multicast=True)
     self.deep_bundle = TransactionBundle(RelayForwardMessage(
         hop_count=0,
         link_address=IPv6Address('2001:db8:ffff:2::1'),
         peer_address=IPv6Address('fe80::3631:c4ff:fe3c:b2f1'),
         options=[
             RelayMessageOption(relayed_message=relayed_solicit_message),
         ]),
                                          received_over_multicast=False,
                                          marks=['some', 'marks'])
     self.ia_bundle = TransactionBundle(SolicitMessage(options=[
         IANAOption(b'0001'),
         IANAOption(b'0002'),
         IATAOption(b'0003'),
         IATAOption(b'0004'),
         IAPDOption(b'0005'),
         IAPDOption(b'0006'),
     ]),
                                        received_over_multicast=False)
     self.option_handlers = [
         InterfaceIdOptionHandler(),
     ]
Пример #8
0
    def relayed_message(self, message):
        """
        Utility method to easily set the relayed message inside this RelayServerMessage.

        :param message: The new message
        """
        from dhcpkit.ipv6.options import RelayMessageOption

        relay_message_option = self.get_option_of_type(RelayMessageOption)
        if relay_message_option:
            # Overwrite the existing message
            relay_message_option.relayed_message = message
        else:
            # Add a new one
            relay_message_option = RelayMessageOption(relayed_message=message)
            self.options.append(relay_message_option)
Пример #9
0
def parse_incoming_request(
        incoming_packet: IncomingPacketBundle) -> TransactionBundle:
    """
    Parse the incoming packet and add a RelayServerMessage around it containing the meta-data received from the
    listener.

    :param incoming_packet: The received packet
    :return: The parsed message in a transaction bundle
    """
    # Parse message and validate
    length, incoming_message = Message.parse(incoming_packet.data)
    incoming_message.validate()

    # Determine the next hop count and construct useful log messages
    if isinstance(incoming_message, RelayForwardMessage):
        next_hop_count = incoming_message.hop_count + 1
    else:
        next_hop_count = 0

    # Collect the relay options
    relay_options = []
    """:type: List[Option]"""

    relay_options.append(
        InterfaceIdOption(
            interface_id=incoming_packet.interface_name.encode('utf-8')))
    relay_options.extend(incoming_packet.extra_options)
    relay_options.append(RelayMessageOption(relayed_message=incoming_message))

    # Pretend to be an internal relay and wrap the message like a relay would
    wrapped_message = RelayForwardMessage(
        hop_count=next_hop_count,
        link_address=incoming_packet.link_address,
        peer_address=incoming_packet.sender,
        options=relay_options)

    # Create the transaction bundle
    return TransactionBundle(
        incoming_message=wrapped_message,
        received_over_multicast=incoming_packet.received_over_multicast,
        marks=incoming_packet.marks)
Пример #10
0
 def setUp(self):
     self.option_bytes = bytes.fromhex(
         '00090017ff') + b'ThisIsAnUnknownMessage'
     self.option_object = RelayMessageOption(
         relayed_message=UnknownMessage(255, b'ThisIsAnUnknownMessage'))
     self.parse_option()
Пример #11
0
"""
import unittest

from dhcpkit.ipv6.message_registry import message_registry
from dhcpkit.ipv6.messages import ClientServerMessage, UnknownMessage
from dhcpkit.ipv6.options import RelayMessageOption
from dhcpkit.tests.ipv6.options import test_option


# A dummy option that may not be in a RelayMessageOption
class NonRelayableMessage(UnknownMessage):
    pass


# Add the constraint to disallow putting it in a RelayMessageOption
RelayMessageOption.add_may_contain(NonRelayableMessage, max_occurrence=0)


# A dummy message that has the wrong length
class WeirdLengthMessage(ClientServerMessage):
    message_type = 254

    def load_from(self, buffer: bytes, offset: int = 0, length: int = None):
        return 4


class RelayMessageOptionTestCase(test_option.OptionTestCase):
    def setUp(self):
        self.option_bytes = bytes.fromhex(
            '00090017ff') + b'ThisIsAnUnknownMessage'
        self.option_object = RelayMessageOption(
"""
import unittest

from dhcpkit.ipv6.message_registry import message_registry
from dhcpkit.ipv6.messages import UnknownMessage, ClientServerMessage
from dhcpkit.ipv6.options import RelayMessageOption
from tests.ipv6.options import test_option


# A dummy option that may not be in a RelayMessageOption
class NonRelayableMessage(UnknownMessage):
    pass


# Add the constraint to disallow putting it in a RelayMessageOption
RelayMessageOption.add_may_contain(NonRelayableMessage, max_occurrence=0)


# A dummy message that has the wrong length
class WeirdLengthMessage(ClientServerMessage):
    message_type = 254

    def load_from(self, buffer: bytes, offset: int = 0, length: int = None):
        return 4


class RelayMessageOptionTestCase(test_option.OptionTestCase):
    def setUp(self):
        self.option_bytes = bytes.fromhex('00090017ff') + b'ThisIsAnUnknownMessage'
        self.option_object = RelayMessageOption(relayed_message=UnknownMessage(255, b'ThisIsAnUnknownMessage'))
        self.parse_option()
Пример #13
0
 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'))),
                 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')),
     ])),
 RelayMessageOption(relayed_message=RelayReplyMessage(
     hop_count=0,
     link_address=IPv6Address('::'),
     peer_address=IPv6Address('fe80::3631:c4ff:fe3c:b2f1'),
     options=[
         InterfaceIdOption(interface_id=b'Fa2/3'),
         RelayMessageOption(relayed_message=AdvertiseMessage(
             transaction_id=bytes.fromhex('f350d6'),
             options=[
                 IANAOption(iaid=bytes.fromhex('c43cb2f1'),
                            options=[
                                IAAddressOption(address=IPv6Address(
                                    '2001:db8:ffff:1:c::e09c'),
                                                preferred_lifetime=375,
                                                valid_lifetime=600),
                            ]),
                 IAPDOption(iaid=bytes.fromhex('c43cb2f1'),
                            options=[
                                IAPrefixOption(prefix=IPv6Network(
                                    '2001:db8:ffcc:fe00::/56'),
                                               preferred_lifetime=375,
                                               valid_lifetime=600),
                            ]),
                 ClientIdOption(duid=LinkLayerDUID(
                     hardware_type=1,
                     link_layer_address=bytes.fromhex('3431c43cb2f1'))),
                 ServerIdOption(duid=LinkLayerTimeDUID(
                     hardware_type=1,
                     time=488458703,
                     link_layer_address=bytes.fromhex('00137265ca42'))),
                 ReconfigureAcceptOption(),
                 RecursiveNameServersOption(
                     dns_servers=[IPv6Address('2001:4860:4860::8888')]),
             ],
         ))
     ],
 ))