IPv4 and IPv6 address parsing, stringifying, and CIDR utilities.
Reject a fetch target that resolves inside your own network
Reject a fetch target that resolves inside your own network
import { assertEquals } from "@std/assert"; import { classifyAddress } from "@hertzg/ip"; // A guard that only checks loopback and link-local misses private, CGNAT, // and multicast ranges; classification is one label from a closed set, so // there's no list of booleans to keep in sync function isSafeToFetch(host: string): boolean { const { classification } = classifyAddress(host); // v4, v6, or mapped, one call return classification === "public" || classification === "global-unicast"; } assertEquals(isSafeToFetch("8.8.8.8"), true); assertEquals(isSafeToFetch("2001:4860:4860::8888"), true); assertEquals(isSafeToFetch("127.0.0.1"), false); assertEquals(isSafeToFetch("10.0.0.1"), false); assertEquals(isSafeToFetch("169.254.169.254"), false); // cloud metadata endpoint assertEquals(isSafeToFetch("::ffff:127.0.0.1"), false); // mapped, unwrapped first
Trusted Network Allowlist
Check if a client IP is in a set of trusted CIDR blocks
Check if a client IP is in a set of trusted CIDR blocks
import { assert, assertEquals } from "@std/assert"; import { cidrContains, parseCidr, parseAddress } from "@hertzg/ip"; // The list may mix IP versions; each entry is only ever compared against an // address of its own version, and a mismatch is a miss rather than an error const trustedRanges = [ "10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16", "fd00::/8", ].map((s) => parseCidr(s)); function isTrusted(ip: string): boolean { const address = parseAddress(ip).address; return trustedRanges.some((cidr) => cidrContains(cidr, address)); } assert(isTrusted("192.168.1.100")); assert(isTrusted("10.0.0.1")); assert(isTrusted("::ffff:172.16.5.1")); // parseAddress unwrapped this to IPv4 first assert(isTrusted("fd00::1")); // matched the IPv6 entry, no conversion involved assertEquals(isTrusted("8.8.8.8"), false); assertEquals(isTrusted("2001:db8::1"), false);
Dual-Stack Server
Normalize client addresses from a dual-stack server
Normalize client addresses from a dual-stack server
import { assertEquals } from "@std/assert"; import { classifyAddress, parseAddress, stringifyAddress } from "@hertzg/ip"; // Dual-stack servers (Deno, Node) report IPv4 clients as ::ffff:x.x.x.x // parseAddress auto-unwraps mapped addresses to their IPv4 form const remote1 = parseAddress("::ffff:192.168.1.50").address; assertEquals(stringifyAddress(remote1), "192.168.1.50"); // Native IPv6 clients pass through unchanged const remote2 = parseAddress("2001:db8::1").address; assertEquals(stringifyAddress(remote2), "2001:db8::1"); // Classification works on both assertEquals(classifyAddress(remote1).classification, "private"); assertEquals(classifyAddress(remote2).classification, "documentation");
IP Classification
Classify addresses for logging, analytics, or input validation
Classify addresses for logging, analytics, or input validation
import { assertEquals } from "@std/assert"; import { classifyAddress } from "@hertzg/ip"; // Classify any IP — result includes kind, numeric value, and label const result = classifyAddress("192.168.1.1"); assertEquals(result.kind, "ipv4"); assertEquals(result.classification, "private"); assertEquals(classifyAddress("127.0.0.1").classification, "loopback"); assertEquals(classifyAddress("8.8.8.8").classification, "public"); assertEquals(classifyAddress("169.254.1.1").classification, "link-local"); // Works with IPv6 too assertEquals(classifyAddress("::1").classification, "loopback"); assertEquals(classifyAddress("fe80::1").classification, "link-local"); assertEquals(classifyAddress("fd00::1").classification, "unique-local"); // Use with Zod as a custom validator that accepts allowed classifications: // // import { type Classificationv4, type Classificationv6, // classifyAddress } from "@hertzg/ip"; // // function ipClassification( // ...allowed: (Classificationv4 | Classificationv6)[] // ) { // const set = new Set(allowed); // return z.string().refine( // (val) => set.has(classifyAddress(val).classification), // { message: `IP must be: ${allowed.join(", ")}` }, // ); // } // // const publicIp = ipClassification("public", "global-unicast"); // publicIp.parse("8.8.8.8"); // ok // publicIp.parse("192.168.1.1"); // throws: private // // const internalIp = ipClassification("private", "loopback"); // internalIp.parse("10.0.0.1"); // ok // internalIp.parse("8.8.8.8"); // throws: public
Sorting
Sort a mixed dual-stack list of addresses and CIDR blocks
Sort a mixed dual-stack list of addresses and CIDR blocks
import { assertEquals } from "@std/assert"; import { compareCidr, compareAddress, parseCidr, parseAddress, stringifyAddress, stringifyCidr } from "@hertzg/ip"; // All IPv4 sorts before all IPv6, numerically ascending within each version const clients = ["2001:db8::1", "10.0.0.10", "::1", "10.0.0.2"].map((s) => parseAddress(s).address); assertEquals(clients.toSorted(compareAddress).map(stringifyAddress), [ "10.0.0.2", "10.0.0.10", "::1", "2001:db8::1", ]); // CIDR blocks tie-break on prefix length: the larger block comes first const ranges = ["10.0.0.0/16", "2001:db8::/32", "10.0.0.0/8"].map((s) => parseCidr(s)); assertEquals(ranges.toSorted(compareCidr).map(stringifyCidr), [ "10.0.0.0/8", "10.0.0.0/16", "2001:db8::/32", ]);
Parsing and Stringifying
Parse and stringify IPv4 and IPv6 addresses
Parse and stringify IPv4 and IPv6 addresses
import { assertEquals } from "@std/assert"; import { parseAddressv4, parseAddressv6, stringifyAddressv4, stringifyAddressv6 } from "@hertzg/ip"; // IPv4: string <-> 32-bit number const v4 = parseAddressv4("192.168.1.1").address; assertEquals(v4, 3232235777); assertEquals(stringifyAddressv4(v4), "192.168.1.1"); assertEquals(stringifyAddressv4(v4 + 1), "192.168.1.2"); // IPv6: string <-> 128-bit bigint const v6 = parseAddressv6("2001:db8::1").address; assertEquals(v6, 42540766411282592856903984951653826561n); assertEquals(stringifyAddressv6(v6), "2001:db8::1"); assertEquals(stringifyAddressv6(v6 + 1n), "2001:db8::2");
CIDR Network Boundaries
Compute network and broadcast addresses from CIDR
Compute network and broadcast addresses from CIDR
import { assertEquals } from "@std/assert"; import { cidrv4BroadcastAddress, cidrv4NetworkAddress, cidrv4Size, parseCidrv4, stringifyAddressv4, } from "@hertzg/ip"; const cidr = parseCidrv4("192.168.1.0/24"); assertEquals(stringifyAddressv4(cidrv4NetworkAddress(cidr)), "192.168.1.0"); assertEquals(stringifyAddressv4(cidrv4BroadcastAddress(cidr)), "192.168.1.255"); assertEquals(cidrv4Size(cidr), 256);
Containment Checking
Check if IPs fall within a CIDR block
Check if IPs fall within a CIDR block
import { assert, assertEquals } from "@std/assert"; import { cidrv4Contains, parseCidrv4, parseAddressv4 } from "@hertzg/ip"; const cidr = parseCidrv4("10.0.0.0/8"); assert(cidrv4Contains(cidr, parseAddressv4("10.0.0.1").address)); assert(cidrv4Contains(cidr, parseAddressv4("10.255.255.255").address)); assertEquals(cidrv4Contains(cidr, parseAddressv4("11.0.0.0").address), false);
Address Enumeration
Generate addresses in a CIDR block
Generate addresses in a CIDR block
import { assertEquals } from "@std/assert"; import { cidrv4Addresses, parseCidrv4, stringifyAddressv4 } from "@hertzg/ip"; const cidr = parseCidrv4("10.0.0.0/29"); // 8 addresses // Iterate all addresses const all = Array.from(cidrv4Addresses(cidr)); assertEquals(all.map(stringifyAddressv4), [ "10.0.0.0", "10.0.0.1", "10.0.0.2", "10.0.0.3", "10.0.0.4", "10.0.0.5", "10.0.0.6", "10.0.0.7", ]); // Skip network address, take first 3 usable const usable = Array.from(cidrv4Addresses(cidr, { offset: 1, count: 3 })); assertEquals(usable.map(stringifyAddressv4), ["10.0.0.1", "10.0.0.2", "10.0.0.3"]);
Wire Bytes
Decode addresses straight out of a packet buffer
Decode addresses straight out of a packet buffer
import { assertEquals } from "@std/assert"; import { addressv4FromBytes, addressv4ToBytes, stringifyAddressv4 } from "@hertzg/ip"; // deno-fmt-ignore const packet = new Uint8Array([ 0x45, 0x00, 0x00, 0x54, 0x1c, 0x46, 0x40, 0x00, 0x40, 0x06, 0x00, 0x00, 10, 0, 0, 1, 192, 168, 1, 1, ]); // Read the source and destination fields in place assertEquals(stringifyAddressv4(addressv4FromBytes(packet, 12)), "10.0.0.1"); assertEquals(stringifyAddressv4(addressv4FromBytes(packet, 16)), "192.168.1.1"); // Rewrite the destination in place; the return is only the bytes written const written = addressv4ToBytes(addressv4FromBytes(packet, 12), packet, 16); assertEquals(written, new Uint8Array([10, 0, 0, 1])); assertEquals(stringifyAddressv4(addressv4FromBytes(packet, 16)), "10.0.0.1");
Reverse DNS
The names are relative -- no trailing dot. Append "." if a resolver
requires an absolute name.
Build the name a PTR record lives at
Build the name a PTR record lives at
import { assertEquals } from "@std/assert"; import { addressToArpa, parseAddress } from "@hertzg/ip"; assertEquals(addressToArpa(parseAddress("192.168.0.1").address), "1.0.168.192.in-addr.arpa"); assertEquals( addressToArpa(parseAddress("2001:db8::1").address), "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa", );
API Reference
Universal (auto-detect IPv4/IPv6)
- Address: An IP address of either version (
numberorbigint) - ParsedAddress: What
parseAddressreturns, the address plus an optional zone ID - ParseOptions: Options for the universal parsers,
unmapToV4 - parseAddress: Parse any IP address string, with an optional zone ID, to number (IPv4) or bigint (IPv6)
- stringifyAddress: Convert an address, bare or parsed, to IP address string
- Cidr: A CIDR block of either version, in either dialect (prefix length or mask)
- ParsedCidr: What
parseCidrreturns, the block plus an optional zone ID - Mask: A network mask of either version (
numberorbigint) - PrefixLength: A prefix length of either version
- parseCidr: Parse any CIDR notation string, in either dialect and with an optional zone ID
- stringifyCidr: Convert a Cidr, parse result or address to CIDR notation string, in the dialect it stores
- cidrSize: Get total number of addresses in a CIDR block
- cidrFirstAddress: Get the first address of a CIDR block
- cidrLastAddress: Get the last address of a CIDR block
- cidrAddresses: Generate IP addresses in a CIDR block
- cidrContains: Check if a CIDR block contains an address
- cidrContainsCidr: Check if one CIDR fully contains another
- cidrOverlaps: Check if two CIDRs share at least one address
- cidrIntersect: Return the overlapping CIDR block, or null
- cidrSubtract: Return CIDR blocks in A but not in B
- cidrMerge: Merge CIDR blocks into the minimal covering set
- compareAddress: Compare two IP addresses of either version for sorting
- compareCidr: Compare two CIDR blocks of either version for sorting
- isValidAddress: Check if a string is a valid plain IP address (IPv4 or IPv6)
- isValidCidr: Check if a string is valid CIDR notation (IPv4 or IPv6)
- addressVersion: Report which IP version an address string is written in, or undefined
- cidrVersion: Report which IP version a CIDR string is written in, or undefined
- IpVersion: An IP version number, 4 or 6
- classifyAddress: Classify an IPv4 (number) or IPv6 (bigint) address
- ClassifiedAddress: Discriminated union result with kind, value, and classification
- ClassifiedAddressv4: Result type for IPv4 classification
- ClassifiedAddressv6: Result type for IPv6 classification
Notation
- splitNotation: Split
address[%zoneId][/prefix]into its three slots without reading them - Notation: The three slots as slices
- ZoneId: The zone ID after
%, a string
IPv4
- Addressv4: An IPv4 address as a 32-bit unsigned integer
- ParsedAddressv4: What
parseAddressv4returns, the address plus an optional zone ID - parseAddressv4: Parse dotted decimal notation, with an optional zone ID, to number
- stringifyAddressv4: Convert an IPv4 address, bare or parsed, to dotted decimal notation
- compareAddressv4: Compare two IPv4 addresses for sorting
- isValidAddressv4: Check if a string is a valid IPv4 address
IPv4 CIDR
- Cidrv4: Type representing an IPv4 CIDR block, PrefixedCidrv4 or MaskedCidrv4
- Maskv4: An IPv4 network mask as a 32-bit unsigned integer
- PrefixLengthv4: An IPv4 prefix length, 0 to 32
- ParsedCidrv4: What
parseCidrv4returns, the block plus an optional zone ID - parseCidrv4: Parse IPv4 CIDR notation, in either dialect and with an optional zone ID
- stringifyCidrv4: Convert a Cidrv4, parse result or address to CIDR notation string, in the dialect it stores
- cidrv4Mask: Get the network mask of a CIDR block or prefix length (0-32)
- cidrv4PrefixLength: Get the prefix length of a CIDR block or network mask, as a number or notation string
- cidrv4Contains: Check if IP is within CIDR block
- cidrv4ContainsCidr: Check if one IPv4 CIDR fully contains another
- cidrv4Overlaps: Check if two IPv4 CIDRs share at least one address
- cidrv4Intersect: Return the overlapping IPv4 CIDR block, or null
- cidrv4Subtract: Return IPv4 CIDR blocks in A but not in B
- cidrv4Merge: Merge IPv4 CIDR blocks into the minimal covering set
- cidrv4FirstAddress: Get first address in CIDR block
- cidrv4LastAddress: Get last address in CIDR block
- cidrv4NetworkAddress: Get the network address (first address) of a CIDR block
- cidrv4BroadcastAddress: Get the directed broadcast address (last address) of a CIDR block
- cidrv4FirstUsableAddress: Get first assignable address in CIDR block (RFC 3021 aware)
- cidrv4LastUsableAddress: Get last assignable address in CIDR block (RFC 3021 aware)
- cidrv4Size: Get total number of addresses in CIDR block
- cidrv4UsableSize: Get number of assignable addresses in CIDR block
- cidrv4Addresses: Generate IP addresses in CIDR block
- cidrv4UsableAddresses: Generate every assignable address in CIDR block
- compareCidrv4: Compare two IPv4 CIDR blocks for sorting
- isValidCidrv4: Check if a string is valid IPv4 CIDR notation
IPv6
- Addressv6: An IPv6 address as a 128-bit unsigned bigint
- ParsedAddressv6: What
parseAddressv6returns, the address plus an optional zone ID - parseAddressv6: Parse colon-hexadecimal notation, with an optional zone ID, to bigint
- stringifyAddressv6: Convert an IPv6 address, bare or parsed, to compressed colon-hexadecimal
- stringifyAddressv6Expanded: Convert an IPv6 address, bare or parsed, to full uncompressed colon-hexadecimal
- compareAddressv6: Compare two IPv6 addresses for sorting
- isValidAddressv6: Check if a string is a valid IPv6 address
IPv6 CIDR
- Cidrv6: Type representing an IPv6 CIDR block, PrefixedCidrv6 or MaskedCidrv6
- Maskv6: An IPv6 network mask as a 128-bit unsigned bigint
- PrefixLengthv6: An IPv6 prefix length, 0 to 128
- ParsedCidrv6: What
parseCidrv6returns, the block plus an optional zone ID - parseCidrv6: Parse IPv6 CIDR notation, in either dialect and with an optional zone ID
- stringifyCidrv6: Convert a Cidrv6, parse result or address to CIDR notation string, compressed, in the dialect it stores
- stringifyCidrv6Expanded: The same with the address written in full
- cidrv6Mask: Get the network mask of a CIDR block or prefix length (0-128)
- cidrv6PrefixLength: Get the prefix length of a CIDR block or network mask, as a bigint or notation string
- cidrv6Contains: Check if IP is within CIDR block
- cidrv6ContainsCidr: Check if one IPv6 CIDR fully contains another
- cidrv6Overlaps: Check if two IPv6 CIDRs share at least one address
- cidrv6Intersect: Return the overlapping IPv6 CIDR block, or null
- cidrv6Subtract: Return IPv6 CIDR blocks in A but not in B
- cidrv6Merge: Merge IPv6 CIDR blocks into the minimal covering set
- cidrv6FirstAddress: Get first address in CIDR block
- cidrv6LastAddress: Get last address in CIDR block
- cidrv6Size: Get total number of addresses in CIDR block
- cidrv6Addresses: Generate IP addresses in CIDR block
- compareCidrv6: Compare two IPv6 CIDR blocks for sorting
- isValidCidrv6: Check if a string is valid IPv6 CIDR notation
IPv4 Classification
- Classificationv4: Type for all IPv4 classification labels
- classifyAddressv4: Classify an IPv4 address into its well-known range
- isAddressv4Private: Check if address is private (RFC 1918)
- isAddressv4Loopback: Check if address is loopback (127.0.0.0/8)
- isAddressv4LinkLocal: Check if address is link-local (169.254.0.0/16)
- isAddressv4Multicast: Check if address is multicast (224.0.0.0/4)
- isAddressv4Reserved: Check if address is reserved (240.0.0.0/4)
- isAddressv4Broadcast: Check if address is broadcast (255.255.255.255)
- isAddressv4ThisNetwork: Check if address is "this network" (0.0.0.0/8)
- isAddressv4CgNat: Check if address is Carrier-Grade NAT (100.64.0.0/10)
- isAddressv4Benchmarking: Check if address is benchmarking (198.18.0.0/15)
- isAddressv4Documentation: Check if address is documentation (RFC 5737)
- isAddressv4Public: Check if address is publicly routable
IPv6 Classification
- Classificationv6: Type for all IPv6 classification labels
- classifyAddressv6: Classify an IPv6 address into its well-known range
- isAddressv6Loopback: Check if address is loopback (::1)
- isAddressv6Unspecified: Check if address is unspecified (::)
- isAddressv6LinkLocal: Check if address is link-local (fe80::/10)
- isAddressv6Multicast: Check if address is multicast (ff00::/8)
- isAddressv6UniqueLocal: Check if address is unique local (fc00::/7)
- isAddressv6GlobalUnicast: Check if address is global unicast (2000::/3)
- isAddressv6Mapped: Check if address is IPv4-mapped (::ffff:0:0/96)
- isAddressv6Translated: Check if address is IPv4-translated (64:ff9b::/96)
- isAddressv6Documentation: Check if address is documentation (2001:db8::/32)
- isAddressv6Teredo: Check if address is Teredo (2001::/32)
- isAddressv6Benchmarking: Check if address is benchmarking (2001:2::/48)
- isAddressv6Orchidv2: Check if address is ORCHIDv2 (2001:20::/28)
IPv4-Mapped IPv6 Conversion (addressv6, cidrv6)
- mapFromAddressv4: Convert IPv4 number to IPv4-mapped IPv6 bigint
- unmapToAddressv4: Extract IPv4 number from IPv4-mapped IPv6 bigint
- mapFromCidrv4: Convert IPv4 CIDR to IPv4-mapped IPv6 CIDR
- unmapToCidrv4: Convert IPv4-mapped IPv6 CIDR to IPv4 CIDR
Universal Wire Byte Conversion (bytes)
- addressFromBytes: Read a 4- or 16-byte address, version from its length
- addressToBytes: Write an address as its wire bytes, width from its type
IPv4 Wire Byte Conversion (bytesv4)
- addressv4FromBytes: Read a 4-byte IPv4 address from a buffer
- addressv4ToBytes: Write a 4-byte IPv4 address to a buffer
IPv6 Wire Byte Conversion (bytesv6)
- addressv6FromBytes: Read a 16-byte IPv6 address from a buffer
- addressv6ToBytes: Write a 16-byte IPv6 address to a buffer
Universal Reverse DNS Pointer Names (arpa)
- addressToArpa: Build the pointer name of an address of either version
IPv4 Reverse DNS Pointer Names (arpav4)
- addressv4ToArpa: Build the
in-addr.arpapointer name of an IPv4 address
IPv6 Reverse DNS Pointer Names (arpav6)
- addressv6ToArpa: Build the
ip6.arpapointer name of an IPv6 address
Submodules
notation: The structural layer of notation via splitNotationaddress: Universal IP parsing via parseAddress, stringifyAddress, compareAddresscidr: Universal CIDR parsing via parseCidr, stringifyCidr, compareCidraddressv4: IPv4 parsing, sorting, and validationcidrv4: IPv4 CIDR utilities, sorting, and validationaddressv6: IPv6 parsing, sorting, validation, and IPv4-mapped conversioncidrv6: IPv6 CIDR utilities, sorting, validation, and IPv4-mapped conversionclassify: Universal classifier via classifyAddressclassifyv4: IPv4 classification via classifyAddressv4, isAddressv4Private, etc.classifyv6: IPv6 classification via classifyAddressv6, isAddressv6Loopback, etc.validate: Universal validation via isValidAddress, isValidCidrversion: IP version detection via addressVersion, cidrVersionbytes: Universal wire byte conversion via addressFromBytes, addressToBytesbytesv4: IPv4 wire byte conversion via addressv4FromBytes, addressv4ToBytesbytesv6: IPv6 wire byte conversion via addressv6FromBytes, addressv6ToBytesarpa: Universal reverse DNS pointer names via addressToArpaarpav4: IPv4 reverse DNS pointer names via addressv4ToArpaarpav6: IPv6 reverse DNS pointer names via addressv6ToArpa
Reads an IPv4 or IPv6 address from a buffer, picking the version from its length.
Builds the reverse DNS pointer name of an IP address of either version.
Writes an IPv4 or IPv6 address, either into a fresh buffer or into one you supply.
Reads a 4-byte IPv4 address from a buffer.
Builds the reverse DNS pointer name of an IPv4 address.
Writes a 4-byte IPv4 address, either into a fresh buffer or into one you supply.
Reads a 16-byte IPv6 address from a buffer.
Builds the reverse DNS pointer name of an IPv6 address.
Writes a 16-byte IPv6 address, either into a fresh buffer or into one you supply.
Reports which IP version a plain address string is written in.
Generates all addresses in an IPv4 CIDR block.
Checks if a CIDR block contains an address.
Checks if one CIDR block fully contains another.
Returns the first address of a CIDR block.
Returns the intersection of two CIDR blocks.
Returns the last address of a CIDR block.
Merges CIDR blocks into the minimal covering set.
Checks if two CIDR blocks overlap (share at least one address).
Returns the total number of addresses in a CIDR block.
Subtracts one CIDR block from another.
Generates a range of IP addresses from a CIDR block.
Returns the directed broadcast address of a CIDR block.
Checks if an IPv4 address is contained within a CIDR block.
Checks if one IPv4 CIDR block fully contains another.
Returns the first address of a CIDR block (network address).
Returns the first assignable address of a CIDR block.
Returns the intersection of two IPv4 CIDR blocks.
Returns the last address of a CIDR block (broadcast address for IPv4).
Returns the last assignable address of a CIDR block.
Creates a network mask from an IPv4 prefix length.
Merges IPv4 CIDR blocks into the minimal covering set.
Returns the network address of a CIDR block.
Checks if two IPv4 CIDR blocks overlap (share at least one address).
Recovers the prefix length from an IPv4 network mask given as a 32-bit unsigned integer.
Returns the total number of IP addresses in a CIDR block.
Subtracts one IPv4 CIDR block from another.
Generates every assignable address in a CIDR block, in ascending order.
Returns the number of assignable addresses in a CIDR block.
Generates a range of IP addresses from a CIDR block.
Checks if an IPv6 address is contained within a CIDR block.
Checks if one IPv6 CIDR block fully contains another.
Returns the first address of a CIDR block.
Returns the intersection of two IPv6 CIDR blocks.
Returns the last address of a CIDR block.
Creates a network mask from an IPv6 prefix length.
Merges IPv6 CIDR blocks into the minimal covering set.
Checks if two IPv6 CIDR blocks overlap (share at least one address).
Recovers the prefix length from an IPv6 network mask given as a bigint.
Returns the total number of IP addresses in a CIDR block.
Subtracts one IPv6 CIDR block from another.
Reports which IP version a CIDR notation string is written in.
Classifies an IPv4 address into its well-known range.
Classifies an IPv4 address into its well-known range.
Classifies an IPv6 address into its well-known range.
Compares two IP addresses of either version for sorting.
Compares two IPv4 addresses for sorting, numerically ascending.
Compares two IPv6 addresses for sorting, numerically ascending.
Compares two CIDR blocks of either version for sorting.
Compares two IPv4 CIDR blocks for sorting.
Compares two IPv6 CIDR blocks for sorting.
Checks if an IPv4 address is in the benchmarking range (RFC 2544).
Checks if an IPv4 address is the limited broadcast address.
Checks if an IPv4 address is in the Carrier-Grade NAT range (RFC 6598).
Checks if an IPv4 address is in a documentation range (RFC 5737).
Checks if an IPv4 address is a link-local address (RFC 3927).
Checks if an IPv4 address is a loopback address (RFC 1122).
Checks if an IPv4 address is a multicast address (RFC 5771).
Checks if an IPv4 address is in a private range (RFC 1918).
Checks if an IPv4 address is a public (globally routable) address.
Checks if an IPv4 address is in the reserved range (RFC 1112).
Checks if an IPv4 address is in the "this network" range (RFC 791).
Checks if an IPv6 address is in the benchmarking range (RFC 5180).
Checks if an IPv6 address is in the documentation range (RFC 3849).
Checks if an IPv6 address is a global unicast address (RFC 4291).
Checks if an IPv6 address is a link-local address (RFC 4291).
Checks if an IPv6 address is the loopback address (RFC 4291).
Checks if an IPv6 address is an IPv4-mapped address (RFC 4291).
Checks if an IPv6 address is a multicast address (RFC 4291).
Checks if an IPv6 address is an ORCHIDv2 address (RFC 7343).
Checks if an IPv6 address is a Teredo address (RFC 4380).
Checks if an IPv6 address is an IPv4-translated address (RFC 6052).
Checks if an IPv6 address is a unique local address (RFC 4193).
Checks if an IPv6 address is the unspecified address (RFC 4291).
Type guard that checks whether a Cidr is an IPv4 CIDR block.
Type guard that checks whether a Cidr is an IPv6 CIDR block.
Checks if a string is a valid plain IP address (IPv4 or IPv6).
Checks if a string is a valid IPv4 address in dotted decimal notation.
Checks if a string is a valid IPv6 address in colon-hexadecimal notation.
Checks if a string is valid IPv4 or IPv6 CIDR notation.
Checks if a string is valid IPv4 CIDR notation.
Checks if a string is valid IPv6 CIDR notation.
Converts an IPv4 address to its IPv4-mapped IPv6 representation.
Converts an IPv4 CIDR block with a prefix length to its IPv4-mapped IPv6 CIDR representation.
Parses an IPv4 or IPv6 address string, with an optional zone ID, to its numeric value.
Parses an IPv4 address in dotted decimal notation, with an optional zone ID, to its numeric value.
Parses an IPv6 address in colon-hexadecimal notation, with an optional zone ID, to its numeric value.
Parses IPv4 or IPv6 CIDR notation, in either dialect and with an optional zone ID.
Parses IPv4 CIDR notation, in either dialect and with an optional zone ID, to a ParsedCidrv4.
Parses IPv6 CIDR notation, in either dialect and with an optional zone ID, to a ParsedCidrv6.
Splits an IP notation string into its address, zone ID and prefix slots.
Stringifies an IPv4 (number) or IPv6 (bigint) address, bare or
parsed, to its standard notation.
Stringifies an IPv4 address to dotted decimal notation.
Stringifies an IPv6 address to compressed colon-hexadecimal notation.
Stringifies an IPv6 address to full uncompressed colon-hexadecimal notation.
Stringifies a CIDR block of either version, or an address, to CIDR notation.
Stringifies an IPv4 CIDR block, or an address, to CIDR notation.
Stringifies an IPv6 CIDR block, or an address, to CIDR notation with the address compressed.
Stringifies an IPv6 CIDR block, or an address, to CIDR notation with the address written in full uncompressed colon-hexadecimal.
Extracts the IPv4 address from an IPv4-mapped IPv6 address.
Converts an IPv4-mapped IPv6 CIDR block with a prefix length to its IPv4 CIDR representation.
A plain IP address of either IP version.
An IPv4 address as a 32-bit unsigned integer, 0 to 4294967295. The
primitive type is what carries the version: a number is IPv4, a
bigint is IPv6 (ADR 0001).
An IPv6 address as a 128-bit unsigned bigint, 0n to 2n ** 128n - 1n.
The primitive type is what carries the version: a bigint is IPv6, a
number is IPv4 (ADR 0001).
A CIDR block of either IP version.
Represents an IPv4 CIDR block.
Represents an IPv6 CIDR block.
| "this-network"
| "loopback"
| "link-local"
| "documentation"
| "benchmarking"
| "cg-nat"
| "private"
| "multicast"
| "reserved"
| "public"
All possible IPv4 address classification labels.
Result of classifying an IP address with version information and parsed value.
An IP version number: 4 for IPv4, 6 for IPv6.
A network mask of either IP version: a number for IPv4, a bigint
for IPv6, the same split as Address.
An IPv4 CIDR block written with a network mask, as in
10.0.0.0/255.0.0.0.
-
address: Addressv4
The IPv4 address from the CIDR notation
-
mask: Maskv4
The network mask, stored as given
-
prefixLength: never
Absent: the prefix length dialect is PrefixedCidrv4
An IPv6 CIDR block written with a network mask, as in
2001:db8::/ffff:ffff::.
-
address: Addressv6
The IPv6 address from the CIDR notation
-
mask: Maskv6
The network mask, stored as given
-
prefixLength: never
Absent: the prefix length dialect is PrefixedCidrv6
An IPv4 network mask as a 32-bit unsigned integer, e.g. 0xFFFFFF00
for /24.
An IPv6 network mask as a 128-bit unsigned bigint, e.g.
0xFFFFFFFFFFFFFFFF0000000000000000n for /64.
The three slots of an IP notation string, as slices of it, before any of
them is read. Absent slots are absent, not empty: splitNotation
rejects an empty slot rather than returning "".
-
address: string
The address slot, everything before the first
%or/ -
prefix: string
The prefix slot, everything after
/: a prefix length or a mask -
zoneId: ZoneId
The zone ID slot, between
%and the/or the end of the string
What parseAddress returns and what stringifyAddress
accepts: a ParsedAddressv4 or a ParsedAddressv6. Read
.address for the bare Address and narrow with typeof; the
zone never touches the value, and no operation in this package reads it.
What parseAddressv4 returns and what stringifyAddressv4
accepts: the address, plus the zone ID if the notation had one. Read
.address for the bare Addressv4; the zone never touches the
value, and no operation in this package reads it.
-
address: Addressv4
The address as a 32-bit unsigned integer
-
zoneId: ZoneId
The zone ID after
%, verbatim, when the notation had one
What parseAddressv6 returns and what stringifyAddressv6
accepts: the address, plus the zone ID if the notation had one. Read
.address for the bare Addressv6; the zone never touches the
value, and no operation in this package reads it.
-
address: Addressv6
The address as a 128-bit unsigned bigint
-
zoneId: ZoneId
The zone ID after
%, verbatim, when the notation had one
What parseCidr returns and what stringifyCidr accepts: a
ParsedCidrv4 or a ParsedCidrv6, the block in the dialect
it was written in plus an optional zone ID. Assignable to Cidr,
so a parse result goes straight into every cidr* operation; none of
them reads the zone.
What parseCidrv4 returns and what stringifyCidrv4
accepts: a Cidrv4 in the dialect it was written in, plus the zone
ID if the notation had one (fe80::%ether1/64 has one; RouterOS emits
that form for connected routes). Assignable to Cidrv4, so a parse
result goes straight into every cidrv4* operation; none of them reads
the zone.
What parseCidrv6 returns and what stringifyCidrv6
accepts: a Cidrv6 in the dialect it was written in, plus the zone
ID if the notation had one (fe80::%ether1/64, the form RouterOS and
netstat -rn emit for link-local routes). Assignable to Cidrv6,
so a parse result goes straight into every cidrv6* operation; none of
them reads the zone.
Options for the universal parsers, parseAddress and parseCidr. The version-specific parsers take none: they return their own version and nothing else.
-
unmapToV4: boolean
Whether an IPv4-mapped IPv6 address (
::ffff:a.b.c.d) is returned as the IPv4 value it carries. Defaults totrue(ADR 0004): dual-stack listeners report IPv4 clients in the mapped form, and almost every caller wants the IPv4 view. Set tofalseto keep thebigint.
An IPv4 CIDR block written with a prefix length, as in 10.0.0.0/8.
-
address: Addressv4
The IPv4 address from the CIDR notation
-
mask: never
Absent: the mask dialect is MaskedCidrv4
-
prefixLength: PrefixLengthv4
The prefix length (0-32)
An IPv6 CIDR block written with a prefix length, as in 2001:db8::/32.
-
address: Addressv6
The IPv6 address from the CIDR notation
-
mask: never
Absent: the mask dialect is MaskedCidrv6
-
prefixLength: PrefixLengthv6
The prefix length (0-128)
A prefix length of either IP version. Being a bare number it cannot
say which version it belongs to, which is why there is no universal
mask-from-prefix-length function: 24 is /24 in both, and the masks
differ.
An IPv4 prefix length, the 24 in /24. The range is 0 to 32; it is
documented rather than encoded in the type, so prefixLength + 1 stays
a PrefixLengthv4 (ADR 0002).
An IPv6 prefix length, the 64 in /64. The range is 0 to 128; it is
documented rather than encoded in the type, so prefixLength + 1 stays
a PrefixLengthv6 (ADR 0002).
The zone ID of an address, the interface tail after % in
fe80::1%eth0 (RFC 4007 section 11). Carried verbatim by the Parsed*
types; never percent-decoded, so %25eth0 is the zone 25eth0.
The structural layer of IP notation: splitting a string into its address, zone ID and prefix slots without reading any of them.
Splitting the three slots
Splitting the three slots
import { assertEquals } from "@std/assert"; import { splitNotation } from "@hertzg/ip/notation"; assertEquals(splitNotation("fe80::%ether1/64"), { address: "fe80::", zoneId: "ether1", prefix: "64", }); assertEquals(splitNotation("10.0.0.0/255.0.0.0"), { address: "10.0.0.0", prefix: "255.0.0.0", }); assertEquals(splitNotation("192.168.1.1%ether1"), { address: "192.168.1.1", zoneId: "ether1", });
Splits an IP notation string into its address, zone ID and prefix slots.
The three slots of an IP notation string, as slices of it, before any of
them is read. Absent slots are absent, not empty: splitNotation
rejects an empty slot rather than returning "".
-
address: string
The address slot, everything before the first
%or/ -
prefix: string
The prefix slot, everything after
/: a prefix length or a mask -
zoneId: ZoneId
The zone ID slot, between
%and the/or the end of the string
The zone ID of an address, the interface tail after % in
fe80::1%eth0 (RFC 4007 section 11). Carried verbatim by the Parsed*
types; never percent-decoded, so %25eth0 is the zone 25eth0.
Universal IP address parsing and stringifying.
Parse and stringify any IP address
Parse and stringify any IP address
import { assertEquals } from "@std/assert"; import { parseAddress, stringifyAddress } from "@hertzg/ip/address"; // IPv4 const v4 = parseAddress("192.168.1.1"); assertEquals(v4, { address: 3232235777 }); assertEquals(stringifyAddress(v4), "192.168.1.1"); // IPv6 const v6 = parseAddress("2001:db8::1"); assertEquals(v6, { address: 42540766411282592856903984951653826561n }); assertEquals(stringifyAddress(v6), "2001:db8::1"); // A zone ID rides along const linkLocal = parseAddress("fe80::1%eth0"); assertEquals(linkLocal, { address: 0xfe800000000000000000000000000001n, zoneId: "eth0" }); assertEquals(stringifyAddress(linkLocal), "fe80::1%eth0");
Compares two IP addresses of either version for sorting.
Parses an IPv4 or IPv6 address string, with an optional zone ID, to its numeric value.
Stringifies an IPv4 (number) or IPv6 (bigint) address, bare or
parsed, to its standard notation.
A plain IP address of either IP version.
An IPv4 address as a 32-bit unsigned integer, 0 to 4294967295. The
primitive type is what carries the version: a number is IPv4, a
bigint is IPv6 (ADR 0001).
An IPv6 address as a 128-bit unsigned bigint, 0n to 2n ** 128n - 1n.
The primitive type is what carries the version: a bigint is IPv6, a
number is IPv4 (ADR 0001).
What parseAddress returns and what stringifyAddress
accepts: a ParsedAddressv4 or a ParsedAddressv6. Read
.address for the bare Address and narrow with typeof; the
zone never touches the value, and no operation in this package reads it.
What parseAddressv4 returns and what stringifyAddressv4
accepts: the address, plus the zone ID if the notation had one. Read
.address for the bare Addressv4; the zone never touches the
value, and no operation in this package reads it.
-
address: Addressv4
The address as a 32-bit unsigned integer
-
zoneId: ZoneId
The zone ID after
%, verbatim, when the notation had one
What parseAddressv6 returns and what stringifyAddressv6
accepts: the address, plus the zone ID if the notation had one. Read
.address for the bare Addressv6; the zone never touches the
value, and no operation in this package reads it.
-
address: Addressv6
The address as a 128-bit unsigned bigint
-
zoneId: ZoneId
The zone ID after
%, verbatim, when the notation had one
Options for the universal parsers, parseAddress and parseCidr. The version-specific parsers take none: they return their own version and nothing else.
-
unmapToV4: boolean
Whether an IPv4-mapped IPv6 address (
::ffff:a.b.c.d) is returned as the IPv4 value it carries. Defaults totrue(ADR 0004): dual-stack listeners report IPv4 clients in the mapped form, and almost every caller wants the IPv4 view. Set tofalseto keep thebigint.
The zone ID of an address, the interface tail after % in
fe80::1%eth0 (RFC 4007 section 11). Carried verbatim by the Parsed*
types; never percent-decoded, so %25eth0 is the zone 25eth0.
IPv4 address parsing and stringifying utilities.
Basic IPv4 operations
Basic IPv4 operations
import { assertEquals } from "@std/assert"; import { parseAddressv4, stringifyAddressv4 } from "@hertzg/ip/addressv4"; const { address } = parseAddressv4("192.168.1.1"); assertEquals(address, 3232235777); const next = address + 1; assertEquals(stringifyAddressv4(next), "192.168.1.2");
Zone IDs are carried, not applied
Zone IDs are carried, not applied
import { assertEquals } from "@std/assert"; import { parseAddressv4, stringifyAddressv4 } from "@hertzg/ip/addressv4"; const gateway = parseAddressv4("10.155.101.1%ether1"); assertEquals(gateway, { address: 177956097, zoneId: "ether1" }); assertEquals(stringifyAddressv4(gateway), "10.155.101.1%ether1"); assertEquals(stringifyAddressv4(gateway.address), "10.155.101.1");
Bitwise operations on IPv4 addresses
Bitwise operations on IPv4 addresses
Since IPv4 addresses are plain numbers, you can use standard JavaScript
bitwise operators directly instead of library functions. Use >>> 0 to
keep results as unsigned 32-bit integers.
import { assertEquals } from "@std/assert"; import { parseAddressv4, stringifyAddressv4 } from "@hertzg/ip/addressv4"; import { cidrv4Mask } from "@hertzg/ip/cidrv4"; const ip = parseAddressv4("192.168.1.100").address; const mask = cidrv4Mask(24); // Bitwise NOT (invert all bits) const inverted = (~ip >>> 0); assertEquals(stringifyAddressv4(inverted), "63.87.254.155"); // Bitwise AND (apply network mask to get network address) const network = ((ip & mask) >>> 0); assertEquals(stringifyAddressv4(network), "192.168.1.0"); // Bitwise OR (combine network with host bits for broadcast) const broadcast = ((network | (~mask >>> 0)) >>> 0); assertEquals(stringifyAddressv4(broadcast), "192.168.1.255"); // Direct comparison (no isEqual() needed) assertEquals(parseAddressv4("10.0.0.1").address === parseAddressv4("10.0.0.1").address, true); assertEquals(parseAddressv4("10.0.0.1").address === parseAddressv4("10.0.0.2").address, false);
Compares two IPv4 addresses for sorting, numerically ascending.
Parses an IPv4 address in dotted decimal notation, with an optional zone ID, to its numeric value.
Stringifies an IPv4 address to dotted decimal notation.
An IPv4 address as a 32-bit unsigned integer, 0 to 4294967295. The
primitive type is what carries the version: a number is IPv4, a
bigint is IPv6 (ADR 0001).
What parseAddressv4 returns and what stringifyAddressv4
accepts: the address, plus the zone ID if the notation had one. Read
.address for the bare Addressv4; the zone never touches the
value, and no operation in this package reads it.
-
address: Addressv4
The address as a 32-bit unsigned integer
-
zoneId: ZoneId
The zone ID after
%, verbatim, when the notation had one
The zone ID of an address, the interface tail after % in
fe80::1%eth0 (RFC 4007 section 11). Carried verbatim by the Parsed*
types; never percent-decoded, so %25eth0 is the zone 25eth0.
Universal CIDR notation parsing, stringifying, and validation.
Parse and stringify any CIDR block
Parse and stringify any CIDR block
import { assertEquals } from "@std/assert"; import { parseCidr, stringifyCidr } from "@hertzg/ip/cidr"; // IPv4 const v4 = parseCidr("192.168.1.0/24"); assertEquals(v4, { address: 3232235776, prefixLength: 24 }); assertEquals(stringifyCidr(v4), "192.168.1.0/24"); // IPv6, with a zone ID const v6 = parseCidr("fe80::%ether1/64"); assertEquals(v6, { address: 0xfe80n << 112n, prefixLength: 64, zoneId: "ether1" }); assertEquals(stringifyCidr(v6), "fe80::%ether1/64"); // The mask dialect is kept as written const masked = parseCidr("10.0.0.0/255.0.0.0"); assertEquals(masked, { address: 167772160, mask: 0xFF000000 }); assertEquals(stringifyCidr(masked), "10.0.0.0/255.0.0.0");
Generates all addresses in an IPv4 CIDR block.
Checks if a CIDR block contains an address.
Checks if one CIDR block fully contains another.
Returns the first address of a CIDR block.
Returns the intersection of two CIDR blocks.
Returns the last address of a CIDR block.
Merges CIDR blocks into the minimal covering set.
Checks if two CIDR blocks overlap (share at least one address).
Returns the total number of addresses in a CIDR block.
Subtracts one CIDR block from another.
Compares two CIDR blocks of either version for sorting.
Type guard that checks whether a Cidr is an IPv4 CIDR block.
Type guard that checks whether a Cidr is an IPv6 CIDR block.
Parses IPv4 or IPv6 CIDR notation, in either dialect and with an optional zone ID.
Stringifies a CIDR block of either version, or an address, to CIDR notation.
A plain IP address of either IP version.
An IPv4 address as a 32-bit unsigned integer, 0 to 4294967295. The
primitive type is what carries the version: a number is IPv4, a
bigint is IPv6 (ADR 0001).
An IPv6 address as a 128-bit unsigned bigint, 0n to 2n ** 128n - 1n.
The primitive type is what carries the version: a bigint is IPv6, a
number is IPv4 (ADR 0001).
A CIDR block of either IP version.
Represents an IPv4 CIDR block.
Represents an IPv6 CIDR block.
A network mask of either IP version: a number for IPv4, a bigint
for IPv6, the same split as Address.
An IPv4 CIDR block written with a network mask, as in
10.0.0.0/255.0.0.0.
-
address: Addressv4
The IPv4 address from the CIDR notation
-
mask: Maskv4
The network mask, stored as given
-
prefixLength: never
Absent: the prefix length dialect is PrefixedCidrv4
An IPv6 CIDR block written with a network mask, as in
2001:db8::/ffff:ffff::.
-
address: Addressv6
The IPv6 address from the CIDR notation
-
mask: Maskv6
The network mask, stored as given
-
prefixLength: never
Absent: the prefix length dialect is PrefixedCidrv6
An IPv4 network mask as a 32-bit unsigned integer, e.g. 0xFFFFFF00
for /24.
An IPv6 network mask as a 128-bit unsigned bigint, e.g.
0xFFFFFFFFFFFFFFFF0000000000000000n for /64.
What parseAddress returns and what stringifyAddress
accepts: a ParsedAddressv4 or a ParsedAddressv6. Read
.address for the bare Address and narrow with typeof; the
zone never touches the value, and no operation in this package reads it.
What parseAddressv4 returns and what stringifyAddressv4
accepts: the address, plus the zone ID if the notation had one. Read
.address for the bare Addressv4; the zone never touches the
value, and no operation in this package reads it.
-
address: Addressv4
The address as a 32-bit unsigned integer
-
zoneId: ZoneId
The zone ID after
%, verbatim, when the notation had one
What parseAddressv6 returns and what stringifyAddressv6
accepts: the address, plus the zone ID if the notation had one. Read
.address for the bare Addressv6; the zone never touches the
value, and no operation in this package reads it.
-
address: Addressv6
The address as a 128-bit unsigned bigint
-
zoneId: ZoneId
The zone ID after
%, verbatim, when the notation had one
What parseCidr returns and what stringifyCidr accepts: a
ParsedCidrv4 or a ParsedCidrv6, the block in the dialect
it was written in plus an optional zone ID. Assignable to Cidr,
so a parse result goes straight into every cidr* operation; none of
them reads the zone.
What parseCidrv4 returns and what stringifyCidrv4
accepts: a Cidrv4 in the dialect it was written in, plus the zone
ID if the notation had one (fe80::%ether1/64 has one; RouterOS emits
that form for connected routes). Assignable to Cidrv4, so a parse
result goes straight into every cidrv4* operation; none of them reads
the zone.
What parseCidrv6 returns and what stringifyCidrv6
accepts: a Cidrv6 in the dialect it was written in, plus the zone
ID if the notation had one (fe80::%ether1/64, the form RouterOS and
netstat -rn emit for link-local routes). Assignable to Cidrv6,
so a parse result goes straight into every cidrv6* operation; none of
them reads the zone.
Options for the universal parsers, parseAddress and parseCidr. The version-specific parsers take none: they return their own version and nothing else.
-
unmapToV4: boolean
Whether an IPv4-mapped IPv6 address (
::ffff:a.b.c.d) is returned as the IPv4 value it carries. Defaults totrue(ADR 0004): dual-stack listeners report IPv4 clients in the mapped form, and almost every caller wants the IPv4 view. Set tofalseto keep thebigint.
An IPv4 CIDR block written with a prefix length, as in 10.0.0.0/8.
-
address: Addressv4
The IPv4 address from the CIDR notation
-
mask: never
Absent: the mask dialect is MaskedCidrv4
-
prefixLength: PrefixLengthv4
The prefix length (0-32)
An IPv6 CIDR block written with a prefix length, as in 2001:db8::/32.
-
address: Addressv6
The IPv6 address from the CIDR notation
-
mask: never
Absent: the mask dialect is MaskedCidrv6
-
prefixLength: PrefixLengthv6
The prefix length (0-128)
A prefix length of either IP version. Being a bare number it cannot
say which version it belongs to, which is why there is no universal
mask-from-prefix-length function: 24 is /24 in both, and the masks
differ.
An IPv4 prefix length, the 24 in /24. The range is 0 to 32; it is
documented rather than encoded in the type, so prefixLength + 1 stays
a PrefixLengthv4 (ADR 0002).
An IPv6 prefix length, the 64 in /64. The range is 0 to 128; it is
documented rather than encoded in the type, so prefixLength + 1 stays
a PrefixLengthv6 (ADR 0002).
The zone ID of an address, the interface tail after % in
fe80::1%eth0 (RFC 4007 section 11). Carried verbatim by the Parsed*
types; never percent-decoded, so %25eth0 is the zone 25eth0.
IPv4 CIDR notation parsing and utilities.
Both dialects parse, and write back the way they came
Both dialects parse, and write back the way they came
import { assertEquals } from "@std/assert"; import { cidrv4Size, parseCidrv4, stringifyCidrv4 } from "@hertzg/ip/cidrv4"; const prefixed = parseCidrv4("10.0.0.0/8"); const masked = parseCidrv4("10.0.0.0/255.0.0.0"); assertEquals(cidrv4Size(prefixed), cidrv4Size(masked)); assertEquals(stringifyCidrv4(prefixed), "10.0.0.0/8"); assertEquals(stringifyCidrv4(masked), "10.0.0.0/255.0.0.0");
CIDR operations
CIDR operations
import { assert, assertEquals } from "@std/assert"; import { cidrv4Contains, parseCidrv4 } from "@hertzg/ip/cidrv4"; import { parseAddressv4 } from "@hertzg/ip/addressv4"; const cidr = parseCidrv4("192.168.1.0/24"); assert(cidrv4Contains(cidr, parseAddressv4("192.168.1.1").address)); assertEquals(cidrv4Contains(cidr, parseAddressv4("192.168.2.1").address), false);
Handing out assignable addresses
Handing out assignable addresses
import { assertEquals } from "@std/assert"; import { cidrv4UsableAddresses, cidrv4UsableSize, parseCidrv4, } from "@hertzg/ip/cidrv4"; import { stringifyAddressv4 } from "@hertzg/ip/addressv4"; const pool = parseCidrv4("192.168.1.0/24"); const assigned = Array.from(cidrv4UsableAddresses(pool), stringifyAddressv4); assertEquals(assigned.length, cidrv4UsableSize(pool)); assertEquals(assigned[0], "192.168.1.1"); assertEquals(assigned.at(-1), "192.168.1.254");
Generates a range of IP addresses from a CIDR block.
Returns the directed broadcast address of a CIDR block.
Checks if an IPv4 address is contained within a CIDR block.
Checks if one IPv4 CIDR block fully contains another.
Returns the first address of a CIDR block (network address).
Returns the first assignable address of a CIDR block.
Returns the intersection of two IPv4 CIDR blocks.
Returns the last address of a CIDR block (broadcast address for IPv4).
Returns the last assignable address of a CIDR block.
Creates a network mask from an IPv4 prefix length.
Merges IPv4 CIDR blocks into the minimal covering set.
Returns the network address of a CIDR block.
Checks if two IPv4 CIDR blocks overlap (share at least one address).
Recovers the prefix length from an IPv4 network mask given as a 32-bit unsigned integer.
Returns the total number of IP addresses in a CIDR block.
Subtracts one IPv4 CIDR block from another.
Generates every assignable address in a CIDR block, in ascending order.
Returns the number of assignable addresses in a CIDR block.
Compares two IPv4 CIDR blocks for sorting.
Parses IPv4 CIDR notation, in either dialect and with an optional zone ID, to a ParsedCidrv4.
Stringifies an IPv4 CIDR block, or an address, to CIDR notation.
An IPv4 address as a 32-bit unsigned integer, 0 to 4294967295. The
primitive type is what carries the version: a number is IPv4, a
bigint is IPv6 (ADR 0001).
Represents an IPv4 CIDR block.
An IPv4 CIDR block written with a network mask, as in
10.0.0.0/255.0.0.0.
-
address: Addressv4
The IPv4 address from the CIDR notation
-
mask: Maskv4
The network mask, stored as given
-
prefixLength: never
Absent: the prefix length dialect is PrefixedCidrv4
An IPv4 network mask as a 32-bit unsigned integer, e.g. 0xFFFFFF00
for /24.
What parseAddressv4 returns and what stringifyAddressv4
accepts: the address, plus the zone ID if the notation had one. Read
.address for the bare Addressv4; the zone never touches the
value, and no operation in this package reads it.
-
address: Addressv4
The address as a 32-bit unsigned integer
-
zoneId: ZoneId
The zone ID after
%, verbatim, when the notation had one
What parseCidrv4 returns and what stringifyCidrv4
accepts: a Cidrv4 in the dialect it was written in, plus the zone
ID if the notation had one (fe80::%ether1/64 has one; RouterOS emits
that form for connected routes). Assignable to Cidrv4, so a parse
result goes straight into every cidrv4* operation; none of them reads
the zone.
An IPv4 CIDR block written with a prefix length, as in 10.0.0.0/8.
-
address: Addressv4
The IPv4 address from the CIDR notation
-
mask: never
Absent: the mask dialect is MaskedCidrv4
-
prefixLength: PrefixLengthv4
The prefix length (0-32)
An IPv4 prefix length, the 24 in /24. The range is 0 to 32; it is
documented rather than encoded in the type, so prefixLength + 1 stays
a PrefixLengthv4 (ADR 0002).
The zone ID of an address, the interface tail after % in
fe80::1%eth0 (RFC 4007 section 11). Carried verbatim by the Parsed*
types; never percent-decoded, so %25eth0 is the zone 25eth0.
IPv6 address parsing and stringifying utilities.
Basic IPv6 operations
Basic IPv6 operations
import { assertEquals } from "@std/assert"; import { parseAddressv6, stringifyAddressv6 } from "@hertzg/ip/addressv6"; const { address } = parseAddressv6("2001:db8::1"); assertEquals(address, 42540766411282592856903984951653826561n); const next = address + 1n; assertEquals(stringifyAddressv6(next), "2001:db8::2");
Zone IDs are carried, not applied
Zone IDs are carried, not applied
import { assertEquals } from "@std/assert"; import { parseAddressv6, stringifyAddressv6 } from "@hertzg/ip/addressv6"; const linkLocal = parseAddressv6("fe80::1%eth0"); assertEquals(linkLocal, { address: 0xfe800000000000000000000000000001n, zoneId: "eth0" }); assertEquals(stringifyAddressv6(linkLocal), "fe80::1%eth0"); assertEquals(stringifyAddressv6(linkLocal.address), "fe80::1");
Bitwise operations on IPv6 addresses
Bitwise operations on IPv6 addresses
Since IPv6 addresses are plain bigints, you can use standard JavaScript bitwise operators directly. For NOT, mask the result with the maximum 128-bit value to stay within range.
import { assertEquals } from "@std/assert"; import { parseAddressv6, stringifyAddressv6 } from "@hertzg/ip/addressv6"; const ip = parseAddressv6("2001:db8::1").address; const MAX_IPV6 = (1n << 128n) - 1n; // Bitwise NOT (invert all bits, mask to 128 bits) const inverted = ~ip & MAX_IPV6; assertEquals(stringifyAddressv6(inverted), "dffe:f247:ffff:ffff:ffff:ffff:ffff:fffe"); // Bitwise AND (apply network mask to get network address) const mask = (MAX_IPV6 << 96n) & MAX_IPV6; // /32 mask const network = ip & mask; assertEquals(stringifyAddressv6(network), "2001:db8::"); // Bitwise OR (set host bits) const result = network | 0xFFn; assertEquals(stringifyAddressv6(result), "2001:db8::ff"); // Direct comparison (no isEqual() needed) assertEquals(parseAddressv6("::1").address === parseAddressv6("::1").address, true); assertEquals(parseAddressv6("::1").address === parseAddressv6("::2").address, false);
Compares two IPv6 addresses for sorting, numerically ascending.
Converts an IPv4 address to its IPv4-mapped IPv6 representation.
Parses an IPv6 address in colon-hexadecimal notation, with an optional zone ID, to its numeric value.
Stringifies an IPv6 address to compressed colon-hexadecimal notation.
Stringifies an IPv6 address to full uncompressed colon-hexadecimal notation.
Extracts the IPv4 address from an IPv4-mapped IPv6 address.
An IPv4 address as a 32-bit unsigned integer, 0 to 4294967295. The
primitive type is what carries the version: a number is IPv4, a
bigint is IPv6 (ADR 0001).
An IPv6 address as a 128-bit unsigned bigint, 0n to 2n ** 128n - 1n.
The primitive type is what carries the version: a bigint is IPv6, a
number is IPv4 (ADR 0001).
What parseAddressv6 returns and what stringifyAddressv6
accepts: the address, plus the zone ID if the notation had one. Read
.address for the bare Addressv6; the zone never touches the
value, and no operation in this package reads it.
-
address: Addressv6
The address as a 128-bit unsigned bigint
-
zoneId: ZoneId
The zone ID after
%, verbatim, when the notation had one
The zone ID of an address, the interface tail after % in
fe80::1%eth0 (RFC 4007 section 11). Carried verbatim by the Parsed*
types; never percent-decoded, so %25eth0 is the zone 25eth0.
IPv6 CIDR notation parsing and utilities.
Both dialects parse, a zone rides along, and each writes back as it came
Both dialects parse, a zone rides along, and each writes back as it came
import { assertEquals } from "@std/assert"; import { cidrv6Size, parseCidrv6, stringifyCidrv6 } from "@hertzg/ip/cidrv6"; const prefixed = parseCidrv6("fe80::%ether1/64"); const masked = parseCidrv6("fe80::/ffff:ffff:ffff:ffff::"); assertEquals(cidrv6Size(prefixed), cidrv6Size(masked)); assertEquals(stringifyCidrv6(prefixed), "fe80::%ether1/64"); assertEquals(stringifyCidrv6(masked), "fe80::/ffff:ffff:ffff:ffff::");
CIDR operations
CIDR operations
import { assert, assertEquals } from "@std/assert"; import { cidrv6Contains, cidrv6FirstAddress, cidrv6LastAddress, parseCidrv6, } from "@hertzg/ip/cidrv6"; import { parseAddressv6, stringifyAddressv6 } from "@hertzg/ip/addressv6"; const cidr = parseCidrv6("2001:db8:ffff:ffff:ffff:ffff::/120"); let currentIp = cidrv6FirstAddress(cidr) + 1n; while (cidrv6Contains(cidr, currentIp)) { const assigned = stringifyAddressv6(currentIp); currentIp = currentIp + 1n; if (currentIp > cidrv6LastAddress(cidr)) break; } assert(cidrv6Contains(cidr, parseAddressv6("2001:db8:ffff:ffff:ffff:ffff::1").address)); assertEquals(cidrv6Contains(cidr, parseAddressv6("2001:db9::1").address), false);
Generates a range of IP addresses from a CIDR block.
Checks if an IPv6 address is contained within a CIDR block.
Checks if one IPv6 CIDR block fully contains another.
Returns the first address of a CIDR block.
Returns the intersection of two IPv6 CIDR blocks.
Returns the last address of a CIDR block.
Creates a network mask from an IPv6 prefix length.
Merges IPv6 CIDR blocks into the minimal covering set.
Checks if two IPv6 CIDR blocks overlap (share at least one address).
Recovers the prefix length from an IPv6 network mask given as a bigint.
Returns the total number of IP addresses in a CIDR block.
Subtracts one IPv6 CIDR block from another.
Compares two IPv6 CIDR blocks for sorting.
Converts an IPv4 CIDR block with a prefix length to its IPv4-mapped IPv6 CIDR representation.
Parses IPv6 CIDR notation, in either dialect and with an optional zone ID, to a ParsedCidrv6.
Stringifies an IPv6 CIDR block, or an address, to CIDR notation with the address compressed.
Stringifies an IPv6 CIDR block, or an address, to CIDR notation with the address written in full uncompressed colon-hexadecimal.
Converts an IPv4-mapped IPv6 CIDR block with a prefix length to its IPv4 CIDR representation.
An IPv4 address as a 32-bit unsigned integer, 0 to 4294967295. The
primitive type is what carries the version: a number is IPv4, a
bigint is IPv6 (ADR 0001).
An IPv6 address as a 128-bit unsigned bigint, 0n to 2n ** 128n - 1n.
The primitive type is what carries the version: a bigint is IPv6, a
number is IPv4 (ADR 0001).
Represents an IPv4 CIDR block.
Represents an IPv6 CIDR block.
An IPv4 CIDR block written with a network mask, as in
10.0.0.0/255.0.0.0.
-
address: Addressv4
The IPv4 address from the CIDR notation
-
mask: Maskv4
The network mask, stored as given
-
prefixLength: never
Absent: the prefix length dialect is PrefixedCidrv4
An IPv6 CIDR block written with a network mask, as in
2001:db8::/ffff:ffff::.
-
address: Addressv6
The IPv6 address from the CIDR notation
-
mask: Maskv6
The network mask, stored as given
-
prefixLength: never
Absent: the prefix length dialect is PrefixedCidrv6
An IPv4 network mask as a 32-bit unsigned integer, e.g. 0xFFFFFF00
for /24.
An IPv6 network mask as a 128-bit unsigned bigint, e.g.
0xFFFFFFFFFFFFFFFF0000000000000000n for /64.
What parseAddressv6 returns and what stringifyAddressv6
accepts: the address, plus the zone ID if the notation had one. Read
.address for the bare Addressv6; the zone never touches the
value, and no operation in this package reads it.
-
address: Addressv6
The address as a 128-bit unsigned bigint
-
zoneId: ZoneId
The zone ID after
%, verbatim, when the notation had one
What parseCidrv6 returns and what stringifyCidrv6
accepts: a Cidrv6 in the dialect it was written in, plus the zone
ID if the notation had one (fe80::%ether1/64, the form RouterOS and
netstat -rn emit for link-local routes). Assignable to Cidrv6,
so a parse result goes straight into every cidrv6* operation; none of
them reads the zone.
An IPv4 CIDR block written with a prefix length, as in 10.0.0.0/8.
-
address: Addressv4
The IPv4 address from the CIDR notation
-
mask: never
Absent: the mask dialect is MaskedCidrv4
-
prefixLength: PrefixLengthv4
The prefix length (0-32)
An IPv6 CIDR block written with a prefix length, as in 2001:db8::/32.
-
address: Addressv6
The IPv6 address from the CIDR notation
-
mask: never
Absent: the mask dialect is MaskedCidrv6
-
prefixLength: PrefixLengthv6
The prefix length (0-128)
An IPv4 prefix length, the 24 in /24. The range is 0 to 32; it is
documented rather than encoded in the type, so prefixLength + 1 stays
a PrefixLengthv4 (ADR 0002).
An IPv6 prefix length, the 64 in /64. The range is 0 to 128; it is
documented rather than encoded in the type, so prefixLength + 1 stays
a PrefixLengthv6 (ADR 0002).
The zone ID of an address, the interface tail after % in
fe80::1%eth0 (RFC 4007 section 11). Carried verbatim by the Parsed*
types; never percent-decoded, so %25eth0 is the zone 25eth0.
Universal IP address classification.
Classify any IP address
Classify any IP address
import { assertEquals } from "@std/assert"; import { classifyAddress } from "@hertzg/ip/classify"; import { parseAddressv4 } from "@hertzg/ip/addressv4"; import { parseAddressv6 } from "@hertzg/ip/addressv6"; // IPv4 from parsed value const v4 = classifyAddress(parseAddressv4("192.168.1.1").address); assertEquals(v4.kind, "ipv4"); assertEquals(v4.value, 3232235777); assertEquals(v4.classification, "private"); // IPv6 from parsed value const v6 = classifyAddress(parseAddressv6("::1").address); assertEquals(v6.kind, "ipv6"); assertEquals(v6.value, 1n); assertEquals(v6.classification, "loopback"); // From string directly const str4 = classifyAddress("127.0.0.1"); assertEquals(str4.kind, "ipv4"); assertEquals(str4.classification, "loopback"); const str6 = classifyAddress("2001:db8::1"); assertEquals(str6.kind, "ipv6"); assertEquals(str6.classification, "documentation");
Classifies an IPv4 address into its well-known range.
A plain IP address of either IP version.
An IPv4 address as a 32-bit unsigned integer, 0 to 4294967295. The
primitive type is what carries the version: a number is IPv4, a
bigint is IPv6 (ADR 0001).
An IPv6 address as a 128-bit unsigned bigint, 0n to 2n ** 128n - 1n.
The primitive type is what carries the version: a bigint is IPv6, a
number is IPv4 (ADR 0001).
| "this-network"
| "loopback"
| "link-local"
| "documentation"
| "benchmarking"
| "cg-nat"
| "private"
| "multicast"
| "reserved"
| "public"
All possible IPv4 address classification labels.
Result of classifying an IP address with version information and parsed value.
IPv4 address classification utilities.
Classify an IPv4 address
Classify an IPv4 address
import { assertEquals } from "@std/assert"; import { classifyAddressv4 } from "@hertzg/ip/classifyv4"; import { parseAddressv4 } from "@hertzg/ip/addressv4"; assertEquals(classifyAddressv4(parseAddressv4("192.168.1.1").address), "private"); assertEquals(classifyAddressv4(parseAddressv4("8.8.8.8").address), "public"); assertEquals(classifyAddressv4(parseAddressv4("127.0.0.1").address), "loopback"); assertEquals(classifyAddressv4(parseAddressv4("224.0.0.1").address), "multicast");
Check specific ranges
Check specific ranges
import { assert, assertEquals } from "@std/assert"; import { isAddressv4Loopback, isAddressv4Private, isAddressv4Public } from "@hertzg/ip/classifyv4"; import { parseAddressv4 } from "@hertzg/ip/addressv4"; assert(isAddressv4Loopback(parseAddressv4("127.0.0.1").address)); assert(isAddressv4Private(parseAddressv4("10.0.0.1").address)); assertEquals(isAddressv4Public(parseAddressv4("10.0.0.1").address), false); assert(isAddressv4Public(parseAddressv4("8.8.8.8").address));
Classifies an IPv4 address into its well-known range.
Checks if an IPv4 address is in the benchmarking range (RFC 2544).
Checks if an IPv4 address is the limited broadcast address.
Checks if an IPv4 address is in the Carrier-Grade NAT range (RFC 6598).
Checks if an IPv4 address is in a documentation range (RFC 5737).
Checks if an IPv4 address is a link-local address (RFC 3927).
Checks if an IPv4 address is a loopback address (RFC 1122).
Checks if an IPv4 address is a multicast address (RFC 5771).
Checks if an IPv4 address is in a private range (RFC 1918).
Checks if an IPv4 address is a public (globally routable) address.
Checks if an IPv4 address is in the reserved range (RFC 1112).
Checks if an IPv4 address is in the "this network" range (RFC 791).
| "this-network"
| "loopback"
| "link-local"
| "documentation"
| "benchmarking"
| "cg-nat"
| "private"
| "multicast"
| "reserved"
| "public"
All possible IPv4 address classification labels.
IPv6 address classification utilities.
Classify an IPv6 address
Classify an IPv6 address
import { assertEquals } from "@std/assert"; import { classifyAddressv6 } from "@hertzg/ip/classifyv6"; import { parseAddressv6 } from "@hertzg/ip/addressv6"; assertEquals(classifyAddressv6(parseAddressv6("::1").address), "loopback"); assertEquals(classifyAddressv6(parseAddressv6("2001:db8::1").address), "documentation"); assertEquals(classifyAddressv6(parseAddressv6("fe80::1").address), "link-local"); assertEquals(classifyAddressv6(parseAddressv6("2607:f8b0:4004:800::200e").address), "global-unicast");
Check specific ranges
Check specific ranges
import { assert, assertEquals } from "@std/assert"; import { isAddressv6Loopback, isAddressv6UniqueLocal } from "@hertzg/ip/classifyv6"; import { parseAddressv6 } from "@hertzg/ip/addressv6"; assert(isAddressv6Loopback(parseAddressv6("::1").address)); assert(isAddressv6UniqueLocal(parseAddressv6("fd00::1").address)); assertEquals(isAddressv6Loopback(parseAddressv6("::2").address), false);
Classifies an IPv6 address into its well-known range.
Checks if an IPv6 address is in the benchmarking range (RFC 5180).
Checks if an IPv6 address is in the documentation range (RFC 3849).
Checks if an IPv6 address is a global unicast address (RFC 4291).
Checks if an IPv6 address is a link-local address (RFC 4291).
Checks if an IPv6 address is the loopback address (RFC 4291).
Checks if an IPv6 address is an IPv4-mapped address (RFC 4291).
Checks if an IPv6 address is a multicast address (RFC 4291).
Checks if an IPv6 address is an ORCHIDv2 address (RFC 7343).
Checks if an IPv6 address is a Teredo address (RFC 4380).
Checks if an IPv6 address is an IPv4-translated address (RFC 6052).
Checks if an IPv6 address is a unique local address (RFC 4193).
Checks if an IPv6 address is the unspecified address (RFC 4291).
Universal IP address and CIDR validation utilities.
Universal validation
Universal validation
import { assert, assertEquals } from "@std/assert"; import { isValidCidr, isValidAddress } from "@hertzg/ip/validate"; assert(isValidAddress("192.168.1.1")); assert(isValidAddress("::1")); assertEquals(isValidAddress("10.0.0.0/8"), false); assertEquals(isValidAddress("garbage"), false); assert(isValidCidr("10.0.0.0/8")); assert(isValidCidr("2001:db8::/32")); assertEquals(isValidCidr("192.168.1.1"), false);
Checks if a string is a valid plain IP address (IPv4 or IPv6).
Checks if a string is valid IPv4 or IPv6 CIDR notation.
IP version detection for address and CIDR strings.
Dispatching on the IP version
Dispatching on the IP version
import { assertEquals } from "@std/assert"; import { addressVersion } from "@hertzg/ip/version"; import { parseAddressv4 } from "@hertzg/ip/addressv4"; import { parseAddressv6 } from "@hertzg/ip/addressv6"; const describe = (input: string): string => { switch (addressVersion(input)) { case 4: return `v4:${parseAddressv4(input).address}`; case 6: return `v6:${parseAddressv6(input).address}`; default: return "not an address"; } }; assertEquals(describe("10.0.0.1"), "v4:167772161"); assertEquals(describe("::1"), "v6:1"); assertEquals(describe("nonsense"), "not an address");
Reports which IP version a plain address string is written in.
Reports which IP version a CIDR notation string is written in.
An IP version number: 4 for IPv4, 6 for IPv6.
IPv4 address and CIDR validation utilities.
Checks if a string is a valid IPv4 address in dotted decimal notation.
Checks if a string is valid IPv4 CIDR notation.
IPv6 address and CIDR validation utilities.
Example 1
Example 1
import { assert, assertEquals } from "@std/assert"; import { isValidCidrv6, isValidAddressv6 } from "@hertzg/ip"; assert(isValidAddressv6("::1")); assertEquals(isValidAddressv6("192.168.1.1"), false); assert(isValidCidrv6("2001:db8::/32")); assertEquals(isValidCidrv6("2001:db8::/129"), false);
Checks if a string is a valid IPv6 address in colon-hexadecimal notation.
Checks if a string is valid IPv6 CIDR notation.
Universal conversion between IP addresses and their network-order wire bytes.
Read and write without knowing the version up front
Read and write without knowing the version up front
import { assertEquals } from "@std/assert"; import { addressFromBytes, addressToBytes } from "@hertzg/ip/bytes"; import { stringifyAddress } from "@hertzg/ip/address"; const field = new Uint8Array([10, 0, 0, 1]); assertEquals(stringifyAddress(addressFromBytes(field)), "10.0.0.1"); // The width comes back out unchanged assertEquals(addressToBytes(addressFromBytes(field)), field);
Reads an IPv4 or IPv6 address from a buffer, picking the version from its length.
Writes an IPv4 or IPv6 address, either into a fresh buffer or into one you supply.
Conversion between IPv4 addresses and their network-order wire bytes.
Decode both addresses out of an IPv4 header
Decode both addresses out of an IPv4 header
import { assertEquals } from "@std/assert"; import { addressv4FromBytes } from "@hertzg/ip/bytesv4"; import { stringifyAddressv4 } from "@hertzg/ip/addressv4"; // deno-fmt-ignore const packet = new Uint8Array([ 0x45, 0x00, 0x00, 0x54, 0x1c, 0x46, 0x40, 0x00, 0x40, 0x06, 0x00, 0x00, 10, 0, 0, 1, 192, 168, 1, 1, ]); assertEquals(stringifyAddressv4(addressv4FromBytes(packet, 12)), "10.0.0.1"); assertEquals(stringifyAddressv4(addressv4FromBytes(packet, 16)), "192.168.1.1");
Assemble an IPv4 header in place
Assemble an IPv4 header in place
import { assertEquals } from "@std/assert"; import { addressv4ToBytes } from "@hertzg/ip/bytesv4"; import { parseAddressv4 } from "@hertzg/ip/addressv4"; const frame = new Uint8Array(20); addressv4ToBytes(parseAddressv4("10.0.0.1").address, frame, 12); addressv4ToBytes(parseAddressv4("192.168.1.1").address, frame, 16); assertEquals(frame.slice(12), new Uint8Array([10, 0, 0, 1, 192, 168, 1, 1]));
Reads a 4-byte IPv4 address from a buffer.
Writes a 4-byte IPv4 address, either into a fresh buffer or into one you supply.
Conversion between IPv6 addresses and their network-order wire bytes.
Decode an address out of an IPv6 header
Decode an address out of an IPv6 header
import { assertEquals } from "@std/assert"; import { addressv6FromBytes } from "@hertzg/ip/bytesv6"; import { stringifyAddressv6 } from "@hertzg/ip/addressv6"; // deno-fmt-ignore const packet = new Uint8Array([ 0x60, 0x00, 0x00, 0x00, 0x00, 0x14, 0x06, 0x40, 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, ]); assertEquals(stringifyAddressv6(addressv6FromBytes(packet, 8)), "2001:db8::1");
Assemble an IPv6 header in place
Assemble an IPv6 header in place
import { assertEquals } from "@std/assert"; import { addressv6FromBytes, addressv6ToBytes } from "@hertzg/ip/bytesv6"; import { parseAddressv6 } from "@hertzg/ip/addressv6"; const frame = new Uint8Array(40); addressv6ToBytes(parseAddressv6("2001:db8::1").address, frame, 8); addressv6ToBytes(parseAddressv6("2001:db8::2").address, frame, 24); assertEquals(addressv6FromBytes(frame, 24), parseAddressv6("2001:db8::2").address);
Reads a 16-byte IPv6 address from a buffer.
Writes a 16-byte IPv6 address, either into a fresh buffer or into one you supply.
Universal reverse DNS pointer names for IP addresses.
Look up the PTR record of an address
Look up the PTR record of an address
import { assertEquals } from "@std/assert"; import { addressToArpa } from "@hertzg/ip/arpa"; import { parseAddress } from "@hertzg/ip/address"; assertEquals(addressToArpa(parseAddress("8.8.8.8").address), "8.8.8.8.in-addr.arpa"); assertEquals( addressToArpa(parseAddress("2001:4860:4860::8888").address), "8.8.8.8.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.6.8.4.0.6.8.4.1.0.0.2.ip6.arpa", );
Builds the reverse DNS pointer name of an IP address of either version.
IPv4 reverse DNS pointer names.
Builds the reverse DNS pointer name of an IPv4 address.
IPv6 reverse DNS pointer names.
Build the name a PTR record lives at
Build the name a PTR record lives at
import { assertEquals } from "@std/assert"; import { addressv6ToArpa } from "@hertzg/ip/arpav6"; import { parseAddressv6 } from "@hertzg/ip/addressv6"; assertEquals( addressv6ToArpa(parseAddressv6("2001:db8::1").address), "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa", );
Builds the reverse DNS pointer name of an IPv6 address.