Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.
import { cidrContains } from "./net_cidr.ts"; ← from net.cidr ^1.0.0 · built alongside by fune
import { isIpv4 } from "./net_ipv4.ts"; ← from net.ipv4 ^1.0.0 · built alongside by fune
import { formatIpv6, isIpv6, parseIpv6 } from "./net_ipv6.ts"; ← from net.ipv6 ^1.0.0 · built alongside by fune
import { SPECIAL_BLOCKS } from "./net_ip_classify_data.ts"; ← this capability’s own data, compiled from data/special-purpose.json into the same file by fune build
import { type IpCategory, type IpClassification } from "./net_ip_classify_types.ts";
/**
* 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".
*/
export function classifyIp(address: string): IpClassification {
let version: number;
let canonical: string;
if (isIpv4(address)) {
version = 4;
canonical = address;
} else if (isIpv6(address)) {
version = 6;
canonical = formatIpv6(parseIpv6(address));
} else {
throw new Error(`"${String(address)}" is not an IPv4 or IPv6 address`);
}
let best: (typeof SPECIAL_BLOCKS)[number] | null = null;
let bestPrefix = -1;
for (const row of SPECIAL_BLOCKS) {
if (row.block.includes(":") !== (version === 6)) continue;
if (!cidrContains(row.block, canonical)) continue;
const prefix = Number(row.block.slice(row.block.indexOf("/") + 1));
if (prefix > bestPrefix) {
best = row;
bestPrefix = prefix;
}
}
if (best === null) {
return { address: canonical, version, category: "global", name: "Global unicast", block: null, rfc: null, globallyReachable: true };
}
return {
address: canonical,
version,
category: best.category as IpCategory,
name: best.name,
block: best.block,
rfc: best.rfc,
globallyReachable: best.globallyReachable,
};
}