Source code for dhcpkit.ipv6.utils

"""
Utility functions for IPv6 DHCP
"""
import logging
from ipaddress import IPv6Address, IPv6Network
from typing import Iterable, List, Optional, Tuple

from dhcpkit.ipv6.messages import ClientServerMessage, Message, RelayForwardMessage, UnknownMessage

logger = logging.getLogger(__name__)


[docs]def split_relay_chain(message: Message) -> Tuple[Optional[ClientServerMessage], List[RelayForwardMessage]]: """ Separate the relay chain from the actual request message. :param message: The incoming message :returns: The request and the chain of relay messages starting with the one closest to the client """ relay_messages = [] while isinstance(message, RelayForwardMessage): relay_messages.insert(0, message) message = message.relayed_message # Check if we could actually read the message if isinstance(message, UnknownMessage): logger.warning("Received an unrecognised message of type {}".format(message.message_type)) return None, [] # Check that this message is a client->server message if not isinstance(message, ClientServerMessage) or not message.from_client_to_server: logger.warning("A server should not receive {} from a client".format(message.__class__.__name__)) return None, [] # Save it as the request return message, relay_messages
[docs]def address_in_prefixes(address: IPv6Address, prefixes: Iterable[IPv6Network]) -> bool: """ Check whether the given address is part of one of the given prefixes :param address: The IPv6 address to check :param prefixes: The list of IPv6 prefixes :type prefixes: list[IPv6Network] :return: Whether the address is part of one of the prefixes """ for prefix in prefixes: if address in prefix: return True return False
[docs]def prefix_overlaps_prefixes(prefix: IPv6Network, prefixes: Iterable[IPv6Network]) -> bool: """ Check whether the given address is part of one of the given prefixes :param prefix: The IPv6 prefix to check :param prefixes: The list of IPv6 prefixes :type prefixes: list[IPv6Network] :return: Whether the address is part of one of the prefixes """ for other_prefix in prefixes: if prefix.overlaps(other_prefix): return True return False
[docs]def is_global_unicast(address: IPv6Address) -> bool: """ Check if an address is a global unicast address according to :rfc:`4291`. :param address: The address to check :return: Whether it is a global unicast address """ return not (address == IPv6Address('::') or address == IPv6Address('::1') or address in IPv6Network('ff00::/8') or address in IPv6Network('fe80::/10'))