def parse_ip_address_and_port(addr, default_port=22):
    """
    Return a pair (IP address, port) extracted from string `addr`.

    Different formats are accepted for the address/port string:

    * IPv6 literals in square brackets, with or without an optional
      port specification, as used in URLs::

        >>> parse_ip_address_and_port('[fe80::dead:beef]:1234')
        (IPAddress('fe80::dead:beef'), 1234)

        >>> parse_ip_address_and_port('[fe80::dead:beef]')
        (IPAddress('fe80::dead:beef'), 22)

    * IPv6 literals with a "local interface" specification::

        >>> parse_ip_address_and_port('[fe80::dead:beef%eth0]')
        (IPAddress('fe80::dead:beef'), 22)

        >>> parse_ip_address_and_port('fe80::dead:beef%eth0')
        (IPAddress('fe80::dead:beef'), 22)

    * bare IPv6 addresses::

        >>> parse_ip_address_and_port('fe80::dead:beef')
        (IPAddress('fe80::dead:beef'), 22)

        >>> parse_ip_address_and_port('2001:db8:5ca1:1f0:f816:3eff:fe05:f40f')
        (IPAddress('2001:db8:5ca1:1f0:f816:3eff:fe05:f40f'), 22)

    * IPv4 addresses, with or without an additional port specification::

        >>> parse_ip_address_and_port('192.0.2.123')
        (IPAddress('192.0.2.123'), 22)

        >>> parse_ip_address_and_port('192.0.2.123:999')
        (IPAddress('192.0.2.123'), 999)

    Note that the default port can be changed by passing an additional parameter::

        >>> parse_ip_address_and_port('192.0.2.123', 987)
        (IPAddress('192.0.2.123'), 987)

        >>> parse_ip_address_and_port('fe80::dead:beef', 987)
        (IPAddress('fe80::dead:beef'), 987)

    :raise netaddr.AddrFormatError: Upon parse failure, e.g., syntactically incorrect IP address.
    """
    # we assume one and only one of the regexps will match
    for regexp in _IP_ADDRESS_RE:
        match = regexp.search(addr)
        if not match:
            continue
        # can raise netaddr.AddrFormatError
        ip_addr = netaddr.IPAddress(match.group('ip_addr'))
        try:
            port = match.group('port')
        except IndexError:
            port = None
        if port is not None:
            port = int(port[1:])  # skip leading `:`
        else:
            port = default_port
        return ip_addr, port
    # parse failed
    raise netaddr.AddrFormatError(
        "Could not extract IP address and port from `{1}`"
        .format(addr))