@chainsafe/netmask
Version:
Typescript implementation of netmask filtering
51 lines (48 loc) • 1.32 kB
text/typescript
import { parseIPv4, parseIPv6 } from "@chainsafe/is-ip/parse";
import { IPv4Len, IPv6Len, maskIp } from "./ip.js";
export function parseCidr(s: string): {
network: Uint8Array;
mask: Uint8Array;
} {
const [address, maskString] = s.split("/");
if (!address || !maskString)
throw new Error("Failed to parse given CIDR: " + s);
let ipLength = IPv4Len;
let ip = parseIPv4(address);
if (ip == null) {
ipLength = IPv6Len;
ip = parseIPv6(address);
if (ip == null) throw new Error("Failed to parse given CIDR: " + s);
}
const m = parseInt(maskString, 10);
if (
Number.isNaN(m) ||
String(m).length !== maskString.length ||
m < 0 ||
m > ipLength * 8
) {
throw new Error("Failed to parse given CIDR: " + s);
}
const mask = cidrMask(m, 8 * ipLength);
return {
network: maskIp(ip, mask),
mask,
};
}
export function cidrMask(ones: number, bits: number): Uint8Array {
if (bits !== 8 * IPv4Len && bits !== 8 * IPv6Len)
throw new Error("Invalid CIDR mask");
if (ones < 0 || ones > bits) throw new Error("Invalid CIDR mask");
const l = bits / 8;
const m = new Uint8Array(l);
for (let i = 0; i < l; i++) {
if (ones >= 8) {
m[i] = 0xff;
ones -= 8;
continue;
}
m[i] = 255 - (0xff >> ones);
ones = 0;
}
return m;
}