Skip to content
Jennifer Programming Language

ipnet API reference

IP addresses and CIDR networks, IPv4 and IPv6. Parse an address or a address/prefix block, test membership, and compute netmask / broadcast - for allow-lists and subnet math. An Address holds its raw bytes (4 for IPv4, 16 for IPv6, network byte order); a Network pairs a base address with a prefix length. Pure Jennifer over strings + convert and the bitwise operators; both binaries. parseAddress folds an IPv4-mapped IPv6 literal (::ffff:a.b.c.d) down to a v4 Address so it can't slip past a v4 allow-list (see unmap).

Import with import "ipnet.j" as ipnet;. See the ipnet guide for prose and examples.

Functions

ipnet.aggregate(nets as list of Network)

Collapse a list of networks into the minimal equivalent set: contained blocks are dropped and adjacent sibling pairs are merged into their shorter parent (e.g. 192.168.0.0/25 + 192.168.0.128/25 -> 192.168.0.0/24). IPv4 and IPv6 entries are aggregated independently; the result is sorted ascending.

Parameters

  • nets {list of Network} - the networks to aggregate

Returns {list of Network} - the minimal covering set

ipnet.broadcast(net as Network)

The broadcast (last) address of a network - every host bit set. For IPv4 this is the broadcast address; for IPv6 it is the last address in the block.

Parameters

  • net {Network} - the network

Returns {Address} - the last address in the network

ipnet.compare(a as Address, b as Address)

Order two addresses: -1 if a < b, 0 if equal, 1 if a > b. Different versions order v4 before v6 (a stable, if arbitrary, total order for sorting).

Parameters

  • a {Address} - the first address
  • b {Address} - the second address

Returns {int} - -1, 0, or 1

ipnet.contains(net as Network, addr as Address)

Whether an address falls within a network (same version and matching prefix bits). A version mismatch is simply false.

Parameters

  • net {Network} - the network
  • addr {Address} - the address to test

Returns {bool} - true if the address is in the network

ipnet.equal(a as Address, b as Address)

Whether two addresses are equal (same version and bytes).

Parameters

  • a {Address} - the first address
  • b {Address} - the second address

Returns {bool} - true if equal

ipnet.firstUsable(net as Network)

The first usable host address of a network. For IPv4 this is the address after the network base (the base is the network address), except a /31 (RFC 3021 point-to-point, both addresses usable) and a /32 (single host), where it is the base itself. For IPv6 it is the base + 1 (skipping the subnet-router anycast), except /127 and /128 where it is the base.

Parameters

  • net {Network} - the network

Returns {Address} - the first usable address

ipnet.hostCount(net as Network)

The total number of addresses in a network (2 ^ host-bits). Throws when the block is too large to hold in an int (an IPv4 prefix is always fine; an IPv6 prefix must be >= 66). For usable-host semantics see firstUsable / lastUsable.

Parameters

  • net {Network} - the network

Returns {int} - the count of addresses in the block

Throws

  • {Error} - kind "ipnet" when the block exceeds the int range

ipnet.hosts(net as Network)

Every usable host address of a network, in ascending order (from firstUsable to lastUsable inclusive). Capped at 65536 addresses - a larger block throws, so materializing a whole /8 cannot exhaust memory; walk those with next instead.

Parameters

  • net {Network} - the network

Returns {list of Address} - the usable host addresses

Throws

  • {Error} - kind "ipnet" when the block has more than 65536 addresses

ipnet.isGlobal(addr as Address)

Whether an address is a normal globally-routable unicast address - i.e. its scope is Global (not private, loopback, link-local, multicast, unspecified, or a reserved / documentation range). Best-effort, per the well-known special-purpose registries.

Parameters

  • addr {Address} - the address

Returns {bool} - true if globally routable

ipnet.isLinkLocal(addr as Address)

Whether an address is link-local (169.254.0.0/16 or fe80::/10).

Parameters

  • addr {Address} - the address

Returns {bool} - true if link-local

ipnet.isLoopback(addr as Address)

Whether an address is a loopback address (127.0.0.0/8 or ::1).

Parameters

  • addr {Address} - the address

Returns {bool} - true if loopback

ipnet.isMulticast(addr as Address)

Whether an address is multicast (224.0.0.0/4 or ff00::/8).

Parameters

  • addr {Address} - the address

Returns {bool} - true if multicast

ipnet.isPrivate(addr as Address)

Whether an address is in private (RFC 1918) or IPv6 unique-local (fc00::/7) space.

Parameters

  • addr {Address} - the address

Returns {bool} - true if private / ULA

ipnet.isUnspecified(addr as Address)

Whether an address is the unspecified address (0.0.0.0 or ::).

Parameters

  • addr {Address} - the address

Returns {bool} - true if unspecified

ipnet.lastUsable(net as Network)

The last usable host address of a network. For IPv4 this is the address before the broadcast address, except a /31 or /32 (where the last address is usable). IPv6 has no broadcast address, so the last address of the block is usable.

Parameters

  • net {Network} - the network

Returns {Address} - the last usable address

ipnet.netmask(net as Network)

The netmask of a network as an address (e.g. 255.255.255.0 for a /24).

Parameters

  • net {Network} - the network

Returns {Address} - the netmask address

ipnet.networkString(net as Network)

Render a network as address/prefix.

Parameters

  • net {Network} - the network

Returns {string} - the CIDR text

ipnet.next(addr as Address)

The next address after addr (numerically +1). Throws at the last address of the version (255.255.255.255 / all-ones IPv6) - there is no successor.

Parameters

  • addr {Address} - the address

Returns {Address} - the following address

Throws

  • {Error} - kind "ipnet" at the last address

ipnet.overlaps(a as Network, b as Network)

Whether two networks share any address. Different versions never overlap.

Parameters

  • a {Network} - the first network
  • b {Network} - the second network

Returns {bool} - true if the blocks intersect

ipnet.parse(cidr as string)

Parse a CIDR block address/prefix into a Network with host bits zeroed. The prefix range is taken from the literal, so an IPv6 v4-mapped block (::ffff:0:0/96) is accepted as a /96 and then folded to its v4 equivalent (0.0.0.0/0, i.e. the prefix is translated down by the 96-bit v4-mapped offset) - mirroring how parseAddress folds a v4-mapped address. A block with a prefix shorter than 96 stays a genuine v6 network (it spans beyond the v4-mapped range).

Parameters

  • cidr {string} - the CIDR text (e.g. "10.0.0.0/8" or "2001:db8::/32")

Returns {Network} - the network

Throws

  • {Error} - kind "ipnet" on malformed input or an out-of-range prefix

ipnet.parseAddress(s as string)

Parse a bare IP address (IPv4 dotted-quad or IPv6, with :: compression and embedded IPv4 supported).

Parameters

  • s {string} - the address text

Returns {Address} - the parsed address

Throws

  • {Error} - kind "ipnet" on malformed input

ipnet.prev(addr as Address)

The previous address before addr (numerically -1). Throws at the first address (0.0.0.0 / ::).

Parameters

  • addr {Address} - the address

Returns {Address} - the preceding address

Throws

  • {Error} - kind "ipnet" at the first address

ipnet.scope(addr as Address)

Classify an address into its Scope. A v4-mapped IPv6 address is folded to v4 first (via unmap), so ::ffff:10.0.0.1 classifies as Private.

Parameters

  • addr {Address} - the address

Returns {Scope} - the address's scope

ipnet.split(net as Network, newPrefix as int)

Divide a network into the equal subnets of a longer prefix (e.g. a /24 into four /26s). Returns them in ascending order. Capped at 65536 subnets (a newPrefix no more than 16 bits longer than the network prefix).

Parameters

  • net {Network} - the network to split
  • newPrefix {int} - the subnet prefix length (>= net.prefix, <= version max)

Returns {list of Network} - the subnets

Throws

  • {Error} - kind "ipnet" on a bad prefix or more than 65536 subnets

ipnet.subnetOf(child as Network, parent as Network)

Whether child is wholly contained in parent (a subnet of it, or equal). Different versions are never a subnet.

Parameters

  • child {Network} - the candidate subnet
  • parent {Network} - the enclosing network

Returns {bool} - true if child lies inside parent

ipnet.toString(addr as Address)

Render an address to its canonical string (IPv4 dotted-quad, or RFC 5952 canonical IPv6).

Parameters

  • addr {Address} - the address

Returns {string} - the canonical text

ipnet.unmap(addr as Address)

Fold an IPv4-mapped IPv6 address (::ffff:a.b.c.d, the ::ffff:0:0/96 range) down to the plain IPv4 Address it represents; any other address is returned unchanged. Without this, ::ffff:127.0.0.1 stays a version-6 Address and silently misses a version-4 network in a contains allow-list / deny-list check - a bypass of exactly the kind the leading-zero and embedded-IPv4 guards already close (OM-010). parseAddress applies it, so a v4-mapped literal parses straight to a v4 Address. The deprecated IPv4-compatible form (::a.b.c.d) is intentionally left alone: it is ambiguous with low addresses like ::1 and unmapping it would be wrong.

Parameters

  • addr {Address} - the address to normalize

Returns {Address} - a v4 Address if addr was v4-mapped, else addr unchanged

ipnet.version(addr as Address)

The IP version of an address (4 or 6).

Parameters

  • addr {Address} - the address

Returns {int} - 4 or 6

Structs

ipnet.Address

An IP address as raw bytes.

FieldTypeDescription
versionintthe IP version: 4 or 6
octetsbytesthe address bytes (4 for IPv4, 16 for IPv6), network byte order

ipnet.Network

A CIDR network: a base address (host bits zeroed) plus a prefix length.

FieldTypeDescription
addrAddressthe network base address
prefixintthe prefix length (0..32 for IPv4, 0..128 for IPv6)

Enums

ipnet.Scope

The address scope: which well-known category an address falls in. A total, disjoint classification - every address is exactly one Scope - so the is* predicates are thin wrappers over it and a caller can match on the whole set. Reserved covers the special-purpose ranges that are neither a normal global unicast address nor one of the named categories (documentation, benchmarking, shared CGNAT space, and other reserved blocks).