Functional Weave
Code in Python

net.ip-classify@1.0.0

impl/python.py

1,657 bytes · the Python implementation · view raw

Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.

from .net_cidr import cidr_contains  ← from net.cidr ^1.0.0 · built alongside by fune
from .net_ip_classify_data import SPECIAL_BLOCKS  ← this capability’s own data, compiled from data/special-purpose.json into the same file by fune build
from .net_ip_classify_types import IpClassification
from .net_ipv4 import is_ipv4  ← from net.ipv4 ^1.0.0 · built alongside by fune
from .net_ipv6 import format_ipv6, is_ipv6, parse_ipv6  ← from net.ipv6 ^1.0.0 · built alongside by fune


def classify_ip(address: str) -> IpClassification:
    """Which special-purpose block an address is in.

    From the IANA IPv4 and IPv6 Special-Purpose Address Registries (RFC 6890)
    plus the multicast ranges. The most specific block wins: 192.0.0.9 is Port
    Control Protocol Anycast (globally reachable), not the /24 of IETF
    assignments around it (not). An address in no block is "global".
    """
    if is_ipv4(address):
        version = 4
        canonical = address
    elif is_ipv6(address):
        version = 6
        canonical = format_ipv6(parse_ipv6(address))
    else:
        raise ValueError('"%s" is not an IPv4 or IPv6 address' % (address,))
    best = None
    best_prefix = -1
    for row in SPECIAL_BLOCKS:
        if (":" in row.block) != (version == 6):
            continue
        if not cidr_contains(row.block, canonical):
            continue
        prefix = int(row.block[row.block.index("/") + 1:])
        if prefix > best_prefix:
            best, best_prefix = row, prefix
    if best is None:
        return IpClassification(
            address=canonical, version=version, category="global", name="Global unicast",
            block=None, rfc=None, globally_reachable=True,
        )
    return IpClassification(
        address=canonical, version=version, category=best.category, name=best.name,
        block=best.block, rfc=best.rfc, globally_reachable=best.globally_reachable,
    )