pmcf 2.15.1 → 2.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pmcf",
3
- "version": "2.15.1",
3
+ "version": "2.16.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
package/src/cli.mjs CHANGED
@@ -1,8 +1,9 @@
1
1
  import { parseArgs } from "node:util";
2
+ import { resolve } from "node:path";
2
3
  import { argv, cwd, env } from "node:process";
3
4
  import { Root } from "./module.mjs";
4
5
 
5
- export async function prepare(options={}) {
6
+ export async function prepare(options = {}) {
6
7
  const { values, positionals } = parseArgs({
7
8
  args: argv.slice(2),
8
9
  options: {
@@ -17,7 +18,7 @@ export async function prepare(options={}) {
17
18
  default: false
18
19
  },
19
20
  publish: {
20
- type: "string",
21
+ type: "string"
21
22
  },
22
23
  root: {
23
24
  type: "string",
@@ -32,9 +33,13 @@ export async function prepare(options={}) {
32
33
  allowPositionals: true
33
34
  });
34
35
 
36
+ if (values.output) {
37
+ values.output = resolve(cwd(), values.output);
38
+ }
39
+
35
40
  const root = new Root(values.root);
36
41
 
37
42
  await root.loadAll();
38
-
43
+
39
44
  return { root, options: values, args: positionals };
40
45
  }
package/src/dns-utils.mjs CHANGED
@@ -1,10 +1,5 @@
1
- import {
2
- asIterator,
3
- decodeIPv6,
4
- encodeIPv6,
5
- isIPv6Address,
6
- normalizeIPAddress
7
- } from "./utils.mjs";
1
+ import { asIterator } from "./utils.mjs";
2
+ import { decodeIPv4, decodeIPv6 } from "./ip.mjs";
8
3
 
9
4
  export function dnsFullName(name) {
10
5
  return name.endsWith(".") ? name : name + ".";
@@ -19,10 +14,10 @@ export function DNSRecord(key, type, ...values) {
19
14
  break;
20
15
 
21
16
  case "A":
22
- values[0] = normalizeIPAddress(values[0]);
17
+ values[0] = decodeIPv4(values[0]);
23
18
  break;
24
19
  case "AAAA":
25
- values[0] = decodeIPv6(encodeIPv6(values[0]));
20
+ values[0] = decodeIPv6(values[0]);
26
21
  break;
27
22
  }
28
23
 
@@ -59,22 +54,3 @@ export function dnsMergeParameters(a, b) {
59
54
  ])
60
55
  );
61
56
  }
62
-
63
- export function reverseAddress(address) {
64
- if (isIPv6Address(address)) {
65
- return normalizeIPAddress(address)
66
- .replaceAll(":", "")
67
- .split("")
68
- .reverse()
69
- .join(".");
70
- }
71
-
72
- return address.split(".").reverse().join(".");
73
- }
74
-
75
- export function reverseArpaAddress(address) {
76
- return (
77
- reverseAddress(address) +
78
- (isIPv6Address(address) ? ".ip6.arpa" : ".in-addr.arpa")
79
- );
80
- }
@@ -1,13 +1,5 @@
1
- import {
2
- writeFile,
3
- mkdir,
4
- copyFile,
5
- glob,
6
- chmod,
7
- stat
8
- } from "node:fs/promises";
1
+ import { writeFile, mkdir } from "node:fs/promises";
9
2
  import { join } from "node:path";
10
- import { FileContentProvider } from "npm-pkgbuild";
11
3
  import { writeLines, sectionLines } from "../src/utils.mjs";
12
4
  import { addHook } from "./hooks.mjs";
13
5
 
package/src/host.mjs CHANGED
@@ -6,16 +6,14 @@ import {
6
6
  networkProperties,
7
7
  networkAddressProperties
8
8
  } from "./network-support.mjs";
9
+ import { asArray, domainFromDominName, domainName } from "./utils.mjs";
9
10
  import {
10
- asArray,
11
- isIPv4Address,
12
- isIPv6Address,
13
- normalizeIPAddress,
11
+ isIPv4,
12
+ isIPv6,
14
13
  formatCIDR,
15
14
  hasWellKnownSubnet,
16
- domainFromDominName,
17
- domainName
18
- } from "./utils.mjs";
15
+ normalizeIP
16
+ } from "./ip.mjs";
19
17
  import { objectFilter } from "./filter.mjs";
20
18
  import { addType, types } from "./types.mjs";
21
19
  import { loadHooks } from "./hooks.mjs";
@@ -582,7 +580,7 @@ export class NetworkInterface extends Base {
582
580
  set ipAddresses(value) {
583
581
  for (const address of asArray(value)) {
584
582
  this._ipAddresses.set(
585
- normalizeIPAddress(address),
583
+ normalizeIP(address),
586
584
  this.addSubnet(address)
587
585
  );
588
586
  }
@@ -593,11 +591,11 @@ export class NetworkInterface extends Base {
593
591
  }
594
592
 
595
593
  get rawIPv4Address() {
596
- return this.rawAddresses.filter(a => isIPv4Address(a))[0];
594
+ return this.rawAddresses.filter(a => isIPv4(a))[0];
597
595
  }
598
596
 
599
597
  get rawIPv6Address() {
600
- return this.rawAddresses.filter(a => isIPv6Address(a))[0];
598
+ return this.rawAddresses.filter(a => isIPv6(a))[0];
601
599
  }
602
600
 
603
601
  get rawAddresses() {
@@ -616,13 +614,13 @@ export class NetworkInterface extends Base {
616
614
 
617
615
  get rawIPv4Addresses() {
618
616
  return [...this.ipAddresses]
619
- .filter(([address]) => isIPv4Address(address))
617
+ .filter(([address]) => isIPv4(address))
620
618
  .map(([address]) => address);
621
619
  }
622
620
 
623
621
  get rawIPv6Addresses() {
624
622
  return [...this.ipAddresses]
625
- .filter(([address]) => isIPv6Address(address))
623
+ .filter(([address]) => isIPv6(address))
626
624
  .map(([address]) => address);
627
625
  }
628
626
 
package/src/ip.mjs ADDED
@@ -0,0 +1,298 @@
1
+ const ipv4 = {
2
+ factory: Uint8Array,
3
+ normalize(address) {
4
+ return address;
5
+ },
6
+ separator: ".",
7
+ bitLength: 32,
8
+ byteLength: 4,
9
+ segments: 4,
10
+ segmentLength: 8,
11
+ segmentMask: 0xffn,
12
+ mask: 0xffffffffn,
13
+ base: 10
14
+ };
15
+
16
+ const ipv6 = {
17
+ factory: Uint16Array,
18
+ normalize(address) {
19
+ const parts = address.split(":");
20
+ const i = parts.indexOf("");
21
+ if (i >= 0) {
22
+ parts.splice(i, 1, ..."0".repeat(9 - parts.length));
23
+ }
24
+ return parts /*.map(s => s.padStart(4, "0"))*/
25
+ .join(":");
26
+ },
27
+ separator: ":",
28
+ compressor: "::",
29
+ bitLength: 128,
30
+ byteLength: 8,
31
+ segments: 8,
32
+ segmentLength: 16,
33
+ segmentMask: 0xffffn,
34
+ mask: 0xffffffffffffffffffffffffffffffffn,
35
+ base: 16
36
+ };
37
+
38
+ export function IPV4(...args) {
39
+ return _create(ipv4, ...args);
40
+ }
41
+
42
+ export function IPV6(...args) {
43
+ return _create(ipv6, ...args);
44
+ }
45
+
46
+ function _create(definition, ...args) {
47
+ if (args.length === 1) {
48
+ return _encode(definition, args[0]);
49
+ }
50
+ return new definition.factory(args);
51
+ }
52
+
53
+ export function encodeIP(address) {
54
+ return _encode(isIPv4(address) ? ipv4 : ipv6, address);
55
+ }
56
+
57
+ export function encodeIPv6(address) {
58
+ return _encode(ipv6, address);
59
+ }
60
+
61
+ export function encodeIPv4(address) {
62
+ return _encode(ipv4, address);
63
+ }
64
+
65
+ export function _encode(definition, address) {
66
+ switch (typeof address) {
67
+ case "string":
68
+ const res = new definition.factory(definition.segments);
69
+
70
+ let i = 0;
71
+ for (const segment of definition
72
+ .normalize(address)
73
+ .split(definition.separator)) {
74
+ res[i++] = parseInt(segment, definition.base);
75
+ }
76
+
77
+ return res;
78
+
79
+ case "object":
80
+ if (
81
+ address instanceof definition.factory &&
82
+ address.length === definition.byteLength
83
+ ) {
84
+ return address;
85
+ }
86
+ }
87
+ }
88
+
89
+ function _decode(definition, address, length) {
90
+ switch (typeof address) {
91
+ case "string":
92
+ if (length === undefined) {
93
+ return address;
94
+ }
95
+ address = _encode(definition, address);
96
+ break;
97
+ case "bigint":
98
+ address = _encodeBigInt(definition, address);
99
+ }
100
+
101
+ let result = "";
102
+ let compressed = 0;
103
+ let word;
104
+ let last = address?.length;
105
+
106
+ if (length !== undefined) {
107
+ length /= definition.segmentLength;
108
+
109
+ if (length < last) {
110
+ last = length;
111
+ }
112
+ }
113
+ for (let i = 0, j = 0; i < last; j = j + 1, i = j) {
114
+ for (; j < last; j++) {
115
+ word = address[j];
116
+
117
+ if (word !== 0 || !definition.compressor || compressed > 0) {
118
+ break;
119
+ }
120
+ }
121
+
122
+ if (j > i + 1) {
123
+ compressed++;
124
+ result += definition.compressor;
125
+ } else {
126
+ if (result.length > 0) {
127
+ result += definition.separator;
128
+ }
129
+ }
130
+
131
+ if (j < last) {
132
+ result += word.toString(definition.base);
133
+ }
134
+ }
135
+
136
+ return result;
137
+ }
138
+
139
+ export function decodeIPv6(address, length) {
140
+ return _decode(ipv6, address, length);
141
+ }
142
+
143
+ export function decodeIPv4(address, length) {
144
+ return _decode(ipv4, address, length);
145
+ }
146
+
147
+ export function decodeIP(address, length) {
148
+ return _decode(isIPv4(address) ? ipv4 : ipv6, address, length);
149
+ }
150
+
151
+ export function isIPv4(address) {
152
+ return _is(ipv4, address);
153
+ }
154
+
155
+ export function isIPv6(address) {
156
+ return _is(ipv6, address);
157
+ }
158
+
159
+ export function _is(definition, address) {
160
+ switch (typeof address) {
161
+ case "string":
162
+ return address.indexOf(definition.separator) >= 0;
163
+
164
+ case "object":
165
+ return (
166
+ address instanceof definition.factory &&
167
+ address.length === definition.byteLength
168
+ );
169
+ }
170
+
171
+ return false;
172
+ }
173
+
174
+ export function asBigInt(address) {
175
+ return _asBigInt(isIPv4(address) ? ipv4 : ipv6, address);
176
+ }
177
+
178
+ function _asBigInt(definition, address) {
179
+ if (typeof address === "bigint") {
180
+ return address;
181
+ }
182
+
183
+ const ea = _encode(definition, address);
184
+
185
+ let result = 0n;
186
+
187
+ for (let i = 0; i < ea.length; i++) {
188
+ result = result << BigInt(definition.segmentLength);
189
+ result += BigInt(ea[i]);
190
+ }
191
+
192
+ return result;
193
+ }
194
+
195
+ function _encodeBigInt(definition, address) {
196
+ const segments = [];
197
+
198
+ for (let i = 0; i < definition.segments; i++) {
199
+ segments.push(Number(address & definition.segmentMask));
200
+ address >>= BigInt(definition.segmentLength);
201
+ }
202
+
203
+ return new definition.factory(segments.reverse());
204
+ }
205
+
206
+ export function prefixIP(address, length) {
207
+ const definition = isIPv4(address) ? ipv4 : ipv6;
208
+ return _decode(definition, _prefix(definition, address, length));
209
+ }
210
+
211
+ export function _prefix(definition, address, length) {
212
+ return (
213
+ _asBigInt(definition, address) &
214
+ (definition.mask << BigInt(definition.bitLength - length))
215
+ );
216
+ }
217
+
218
+ export function normalizeCIDR(address) {
219
+ let [prefix, prefixLength] = address.split(/\//);
220
+ let longPrefix;
221
+
222
+ if (!prefixLength && isLinkLocal(address)) {
223
+ prefix = "fe80::";
224
+ longPrefix = prefix;
225
+ prefixLength = 64;
226
+ } else {
227
+ prefixLength = parseInt(prefixLength);
228
+
229
+ const definition = isIPv6(prefix) ? ipv6 : ipv4;
230
+ let n;
231
+
232
+ if (prefixLength) {
233
+ n = _prefix(definition, prefix, prefixLength);
234
+ } else {
235
+ n = _encode(definition, prefix);
236
+
237
+ if (isLocalhost(n)) {
238
+ prefixLength = definition === ipv6 ? 128 : 8;
239
+ } else {
240
+ return {};
241
+ }
242
+ }
243
+ prefix = _decode(definition, n, prefixLength);
244
+ longPrefix = _decode(definition, n);
245
+ }
246
+
247
+ return { longPrefix, prefix, prefixLength, cidr: `${prefix}/${prefixLength}` };
248
+ }
249
+
250
+ export function formatCIDR(address, subnet) {
251
+ return subnet ? `${address}/${subnet.prefixLength}` : address;
252
+ }
253
+
254
+ export function normalizeIP(address) {
255
+ return decodeIP(encodeIP(address));
256
+ }
257
+
258
+ export function reverseArpa(address) {
259
+ if (isIPv6(address)) {
260
+ const ea = encodeIPv6(address);
261
+ let result = [];
262
+ for (let i = 0; i < ea.length; i++) {
263
+ const v = ea[i];
264
+ for (let i = 0; i < 4; i++) {
265
+ result.push(((v >> (12 - 4 * i)) & 0x000f).toString(16));
266
+ }
267
+ }
268
+ return result.reverse().join(".") + ".ip6.arpa";
269
+ }
270
+
271
+ return address.split(".").reverse().join(".") + ".in-addr.arpa";
272
+ }
273
+
274
+ export function isLocalhost(address) {
275
+ const eaddr = encodeIP(address);
276
+
277
+ if (!eaddr) {
278
+ return false;
279
+ }
280
+
281
+ const str = eaddr.toString();
282
+
283
+ return str === IPV4_LOCALHOST.toString() || str === IPV6_LOCALHOST.toString();
284
+ }
285
+
286
+ export function isLinkLocal(address) {
287
+ const eaddr = encodeIP(address);
288
+ return eaddr[0] === 0xfe80;
289
+ }
290
+
291
+ export function hasWellKnownSubnet(address) {
292
+ return isLocalhost(address) || isLinkLocal(address);
293
+ }
294
+
295
+ export const IPV6_LINK_LOCAL_BROADCAST = _encode(ipv6, "ff02::1");
296
+ export const IPV6_ROUTER_BROADCAST = _encode(ipv6, "ff02::2");
297
+ export const IPV4_LOCALHOST = _encode(ipv4, "127.0.0.1");
298
+ export const IPV6_LOCALHOST = _encode(ipv6, "::1");
package/src/owner.mjs CHANGED
@@ -1,8 +1,8 @@
1
- import { asIterator, normalizeCIDR } from "./utils.mjs";
1
+ import { asIterator } from "./utils.mjs";
2
2
  import { Base } from "./base.mjs";
3
3
  import { Subnet } from "./subnet.mjs";
4
4
  import { addType, types } from "./types.mjs";
5
-
5
+ import { normalizeCIDR } from "./ip.mjs";
6
6
  const OwnerTypeDefinition = {
7
7
  name: "owner",
8
8
  owners: ["location", "owner", "root"],
package/src/service.mjs CHANGED
@@ -1,8 +1,9 @@
1
1
  import { Base } from "./base.mjs";
2
2
  import { addType } from "./types.mjs";
3
3
  import { objectFilter } from "./filter.mjs";
4
- import { asArray, isLocalhost } from "./utils.mjs";
4
+ import { asArray } from "./utils.mjs";
5
5
  import { networkAddressProperties } from "./network-support.mjs";
6
+ import { isLocalhost } from "./ip.mjs";
6
7
  import {
7
8
  DNSRecord,
8
9
  dnsFullName,
@@ -7,7 +7,8 @@ import {
7
7
  serviceEndpoints
8
8
  } from "../service.mjs";
9
9
  import { addType } from "../types.mjs";
10
- import { writeLines, isIPv4Address, isIPv6Address } from "../utils.mjs";
10
+ import { writeLines } from "../utils.mjs";
11
+ import { isIPv4, isIPv6 } from "../ip.mjs";
11
12
 
12
13
  const DHCPServiceTypeDefinition = {
13
14
  name: "dhcp",
@@ -145,7 +146,7 @@ export class DHCPService extends Service {
145
146
  return {
146
147
  name: domain,
147
148
  "dns-servers": dnsServerEndpoints
148
- .filter(endpoint => isIPv4Address(endpoint.rawAddress))
149
+ .filter(endpoint => isIPv4(endpoint.rawAddress))
149
150
  .map(endpoint => {
150
151
  return { "ip-address": endpoint.rawAddress };
151
152
  })
@@ -229,7 +230,7 @@ export class DHCPService extends Service {
229
230
  Dhcp4: {
230
231
  ...commonConfig,
231
232
  "interfaces-config": {
232
- interfaces: listenInterfaces(isIPv4Address)
233
+ interfaces: listenInterfaces(isIPv4)
233
234
  },
234
235
  "multi-threading": {
235
236
  "enable-multi-threading": false
@@ -242,7 +243,7 @@ export class DHCPService extends Service {
242
243
  {
243
244
  name: "domain-name-servers",
244
245
  data: dnsServerEndpoints
245
- .filter(endpoint => isIPv4Address(endpoint.rawAddress))
246
+ .filter(endpoint => isIPv4(endpoint.rawAddress))
246
247
  .map(endpoint => endpoint.rawAddress)
247
248
  .join(",")
248
249
  },
@@ -275,7 +276,7 @@ export class DHCPService extends Service {
275
276
  Dhcp6: {
276
277
  ...commonConfig,
277
278
  "interfaces-config": {
278
- interfaces: listenInterfaces(isIPv6Address)
279
+ interfaces: listenInterfaces(isIPv6)
279
280
  },
280
281
  "control-socket": {
281
282
  "socket-type": "unix",
@@ -286,7 +287,7 @@ export class DHCPService extends Service {
286
287
  {
287
288
  name: "dns-servers",
288
289
  data: dnsServerEndpoints
289
- .filter(endpoint => isIPv6Address(endpoint.rawAddress))
290
+ .filter(endpoint => isIPv6(endpoint.rawAddress))
290
291
  .map(endpoint => endpoint.rawAddress)
291
292
  .join(",")
292
293
  }
@@ -1,13 +1,9 @@
1
1
  import { join } from "node:path";
2
2
  import { createHmac } from "node:crypto";
3
3
  import { FileContentProvider } from "npm-pkgbuild";
4
- import {
5
- writeLines,
6
- isIPv6Address,
7
- isLinkLocal,
8
- isLocalhost
9
- } from "../utils.mjs";
10
- import { DNSRecord, dnsFullName, reverseArpaAddress } from "../dns-utils.mjs";
4
+ import { writeLines } from "../utils.mjs";
5
+ import { isIPv6, isLinkLocal, isLocalhost, reverseArpa } from "../ip.mjs";
6
+ import { DNSRecord, dnsFullName } from "../dns-utils.mjs";
11
7
  import { addType } from "../types.mjs";
12
8
  import { ServiceTypeDefinition, serviceAddresses } from "../service.mjs";
13
9
  import {
@@ -211,9 +207,10 @@ export class DNSService extends ExtraSourceService {
211
207
  yield packageData;
212
208
  }
213
209
 
214
- const p2 = (packageData.dir = join(dir, "p2"));
210
+ const p2 = join(dir, "p2");
215
211
 
216
212
  packageData.properties = {
213
+ dir: p2,
217
214
  name: `named-zones-${name}`,
218
215
  description: `zone definitions for ${location.fullName}`,
219
216
  dependencies: ["mf-named"],
@@ -292,7 +289,7 @@ async function generateZoneDefs(dns, location, packageData) {
292
289
  for (const address of host.rawAddresses) {
293
290
  if (!isLocalhost(address)) {
294
291
  zone.records.add(
295
- DNSRecord("@", isIPv6Address(address) ? "AAAA" : "A", address)
292
+ DNSRecord("@", isIPv6(address) ? "AAAA" : "A", address)
296
293
  );
297
294
  }
298
295
  }
@@ -366,7 +363,7 @@ async function generateZoneDefs(dns, location, packageData) {
366
363
  zone.records.add(
367
364
  DNSRecord(
368
365
  dnsFullName(domainName),
369
- isIPv6Address(address) ? "AAAA" : "A",
366
+ isIPv6(address) ? "AAAA" : "A",
370
367
  address
371
368
  )
372
369
  );
@@ -375,11 +372,11 @@ async function generateZoneDefs(dns, location, packageData) {
375
372
  let reverseZone = reverseZones.get(subnet.address);
376
373
 
377
374
  if (!reverseZone) {
378
- const reverseArpa = reverseArpaAddress(subnet.prefix);
375
+ const id = reverseArpa(subnet.prefix);
379
376
  reverseZone = {
380
- id: reverseArpa,
377
+ id,
381
378
  type: "plain",
382
- file: `${locationName}/${reverseArpa}.zone`,
379
+ file: `${locationName}/${id}.zone`,
383
380
  records: new Set([SOARecord, NSRecord])
384
381
  };
385
382
  config.zones.push(reverseZone);
@@ -389,7 +386,7 @@ async function generateZoneDefs(dns, location, packageData) {
389
386
  for (const domainName of host.domainNames) {
390
387
  reverseZone.records.add(
391
388
  DNSRecord(
392
- dnsFullName(reverseArpaAddress(address)),
389
+ dnsFullName(reverseArpa(address)),
393
390
  "PTR",
394
391
  dnsFullName(domainName)
395
392
  )
package/src/subnet.mjs CHANGED
@@ -1,10 +1,4 @@
1
- import {
2
- normalizeCIDR,
3
- isLinkLocal,
4
- isIPv4Address,
5
- isIPv6Address,
6
- addressWithPrefixLength
7
- } from "./utils.mjs";
1
+ import { normalizeCIDR, isLinkLocal, isIPv4, isIPv6, prefixIP } from "./ip.mjs";
8
2
  import { Base } from "./base.mjs";
9
3
  import { addType } from "./types.mjs";
10
4
 
@@ -37,9 +31,13 @@ export class Subnet extends Base {
37
31
  }
38
32
 
39
33
  constructor(owner, address) {
40
- const { cidr } = normalizeCIDR(address);
34
+ const { longPrefix, prefix, prefixLength, cidr } = normalizeCIDR(address);
41
35
  super(owner, cidr);
42
36
  owner.addObject(this);
37
+
38
+ this.prefix = prefix;
39
+ this.prefixLength = prefixLength;
40
+ this.longPrefix = longPrefix;
43
41
  }
44
42
 
45
43
  get fullName() {
@@ -55,36 +53,20 @@ export class Subnet extends Base {
55
53
  }
56
54
 
57
55
  get isIPv4() {
58
- return isIPv4Address(this.address);
56
+ return isIPv4(this.address);
59
57
  }
60
58
 
61
59
  get isIPv6() {
62
- return isIPv6Address(this.address);
60
+ return isIPv6(this.address);
63
61
  }
64
62
 
65
63
  get addressRange() {
66
64
  return [
67
- addressWithPrefixLength(this.prefix, this.prefixLength),
65
+ prefixIP(this.prefix, this.prefixLength),
68
66
  this.prefix + ".255".repeat((32 - this.prefixLength) / 8)
69
67
  ];
70
68
  }
71
69
 
72
- get longPrefix() {
73
- return addressWithPrefixLength(this.prefix, this.prefixLength);
74
- }
75
-
76
- get prefix() {
77
- const [prefix] = this.name.split("/");
78
- return prefix;
79
- }
80
-
81
- get prefixLength() {
82
- const m = this.name.match(/\/(\d+)$/);
83
- if (m) {
84
- return parseInt(m[1]);
85
- }
86
- }
87
-
88
70
  get address() {
89
71
  return this.name;
90
72
  }
package/src/utils.mjs CHANGED
@@ -77,205 +77,3 @@ export function asIterator(value) {
77
77
 
78
78
  return asArray(value);
79
79
  }
80
-
81
- export function isIPv4Address(address) {
82
- switch (typeof address) {
83
- case "string":
84
- return address.indexOf(".") >= 0;
85
- }
86
-
87
- return false;
88
- }
89
-
90
- export function isIPv6Address(address) {
91
- switch (typeof address) {
92
- case "string":
93
- return address.indexOf(":") >= 0;
94
- }
95
-
96
- return false;
97
- }
98
-
99
- export function isLinkLocal(address) {
100
- switch (typeof address) {
101
- case "string":
102
- return address.startsWith("fe80");
103
-
104
- case "bigint":
105
- return ((address >> 112n) & 0xffffn) === 0xfe80n;
106
- }
107
-
108
- return false;
109
- }
110
-
111
- export function generateEU64(mac) {
112
- //TODO
113
- }
114
-
115
- export function isLocalhost(address) {
116
- const eaddr = encodeIP(address);
117
- return eaddr === IPV4_LOCALHOST || eaddr === IPV6_LOCALHOST;
118
- }
119
-
120
- export function normalizeIPAddress(address) {
121
- address = address.replace(/\/\d+$/, "");
122
- if (isIPv4Address(address)) {
123
- return address;
124
- }
125
- const parts = address.split(":");
126
- const i = parts.indexOf("");
127
- if (i >= 0) {
128
- parts.splice(i, 1, ..."0".repeat(9 - parts.length));
129
- }
130
- return parts.map(s => s.padStart(4, "0")).join(":");
131
- }
132
-
133
- const ipv4 = {
134
- separator: ".",
135
- length: 32,
136
- segmentLength: 8,
137
- segmentMask: 0xffn,
138
- mask: 0xffffffffn,
139
- base: 10
140
- };
141
- const ipv6 = {
142
- separator: ":",
143
- compressor: "::",
144
- length: 128,
145
- segmentLength: 16,
146
- segmentMask: 0xffffn,
147
- mask: 0xffffffffffffffffffffffffffffffffn,
148
- base: 16
149
- };
150
-
151
- export function addressWithPrefixLength(address, prefixLength) {
152
- const definition = ipv4;
153
-
154
- return (
155
- address +
156
- ".0".repeat((definition.length - prefixLength) / definition.segmentLength)
157
- );
158
- }
159
-
160
- function _decode(definition, address, length = definition.length) {
161
- if (typeof address === "string") {
162
- return address;
163
- }
164
-
165
- let result = "";
166
- let compressed = 0;
167
- let shift = definition.length;
168
- let word;
169
- const last = length / definition.segmentLength;
170
-
171
- for (let i = 0, j = 0; i < last; j = j + 1, i = j) {
172
- for (; j < last; j++) {
173
- shift -= definition.segmentLength;
174
- word = (address >> BigInt(shift)) & definition.segmentMask;
175
-
176
- if (word !== 0n || !definition.compressor || compressed > 0) {
177
- break;
178
- }
179
- }
180
-
181
- if (j > i + 1) {
182
- compressed++;
183
- result += definition.compressor;
184
- } else {
185
- if (result.length > 0) {
186
- result += definition.separator;
187
- }
188
- }
189
-
190
- if (j < last) {
191
- result += word.toString(definition.base);
192
- }
193
- }
194
-
195
- return result;
196
- }
197
-
198
- export function _encode(definition, address) {
199
- if (typeof address !== "string") {
200
- return address;
201
- }
202
-
203
- let res = 0n;
204
- let shift = BigInt(definition.length);
205
-
206
- for (const word of normalizeIPAddress(address)
207
- .split(definition.separator)
208
- .map(a => parseInt(a, definition.base))) {
209
- shift -= BigInt(definition.segmentLength);
210
- res += BigInt(word) << shift;
211
- }
212
-
213
- return res;
214
- }
215
-
216
- export function decodeIPv6(address, length) {
217
- return _decode(ipv6, address, length);
218
- }
219
-
220
- export function encodeIPv6(address) {
221
- return _encode(ipv6, address);
222
- }
223
-
224
- export function decodeIPv4(address, length) {
225
- return _decode(ipv4, address, length);
226
- }
227
-
228
- export function encodeIPv4(address) {
229
- return _encode(ipv4, address);
230
- }
231
-
232
- export function decodeIP(address, length) {
233
- return _decode(isIPv4Address(address) ? ipv4 : ipv6, address, length);
234
- }
235
-
236
- export function encodeIP(address) {
237
- return _encode(isIPv4Address(address) ? ipv4 : ipv6, address);
238
- }
239
-
240
- export function formatCIDR(address, subnet) {
241
- return subnet ? `${address}/${subnet.prefixLength}` : address;
242
- }
243
-
244
- export function normalizeCIDR(address) {
245
- let [prefix, prefixLength] = address.split(/\//);
246
-
247
- if (!prefixLength && isLinkLocal(address)) {
248
- prefix = "fe80::";
249
- prefixLength = 64;
250
- } else {
251
- const definition = isIPv6Address(prefix) ? ipv6 : ipv4;
252
- let n = _encode(definition, prefix);
253
-
254
- if (prefixLength) {
255
- n = n & (definition.mask << BigInt(definition.length - prefixLength));
256
- prefix = _decode(definition, n, prefixLength);
257
- } else {
258
- if (n === IPV4_LOCALHOST) {
259
- prefixLength = 8;
260
- prefix = _decode(definition, n, prefixLength);
261
- } else if (n === IPV6_LOCALHOST) {
262
- prefixLength = 128;
263
- prefix = _decode(definition, n, prefixLength);
264
- } else {
265
- return {};
266
- }
267
- }
268
- }
269
-
270
- return { prefix, prefixLength, cidr: `${prefix}/${prefixLength}` };
271
- }
272
-
273
- export function hasWellKnownSubnet(address) {
274
- const n = encodeIP(address);
275
- return n === IPV4_LOCALHOST || n === IPV6_LOCALHOST || isLinkLocal(address);
276
- }
277
-
278
- export const IPV4_LOCALHOST = _encode(ipv4, "127.0.0.1");
279
- export const IPV6_LOCALHOST = _encode(ipv6, "::1");
280
- export const IPV6_LINK_LOCAL_BROADCAST = _encode(ipv6, "ff02::1");
281
- export const IPV6_ROUTER_BROADCAST = _encode(ipv6, "ff02::2");
@@ -7,5 +7,3 @@ export function dnsFormatParameters(parameters: any): string;
7
7
  export function dnsMergeParameters(a: any, b: any): {
8
8
  [k: string]: Set<any>;
9
9
  };
10
- export function reverseAddress(address: any): any;
11
- export function reverseArpaAddress(address: any): string;
package/types/ip.d.mts ADDED
@@ -0,0 +1,36 @@
1
+ export function IPV4(...args: any[]): any;
2
+ export function IPV6(...args: any[]): any;
3
+ export function encodeIP(address: any): any;
4
+ export function encodeIPv6(address: any): any;
5
+ export function encodeIPv4(address: any): any;
6
+ export function _encode(definition: any, address: any): any;
7
+ export function decodeIPv6(address: any, length: any): string;
8
+ export function decodeIPv4(address: any, length: any): string;
9
+ export function decodeIP(address: any, length: any): string;
10
+ export function isIPv4(address: any): boolean;
11
+ export function isIPv6(address: any): boolean;
12
+ export function _is(definition: any, address: any): boolean;
13
+ export function asBigInt(address: any): bigint;
14
+ export function prefixIP(address: any, length: any): string;
15
+ export function _prefix(definition: any, address: any, length: any): bigint;
16
+ export function normalizeCIDR(address: any): {
17
+ longPrefix?: undefined;
18
+ prefix?: undefined;
19
+ prefixLength?: undefined;
20
+ cidr?: undefined;
21
+ } | {
22
+ longPrefix: any;
23
+ prefix: any;
24
+ prefixLength: any;
25
+ cidr: string;
26
+ };
27
+ export function formatCIDR(address: any, subnet: any): any;
28
+ export function normalizeIP(address: any): string;
29
+ export function reverseArpa(address: any): string;
30
+ export function isLocalhost(address: any): boolean;
31
+ export function isLinkLocal(address: any): boolean;
32
+ export function hasWellKnownSubnet(address: any): boolean;
33
+ export const IPV6_LINK_LOCAL_BROADCAST: any;
34
+ export const IPV6_ROUTER_BROADCAST: any;
35
+ export const IPV4_LOCALHOST: any;
36
+ export const IPV6_LOCALHOST: any;
@@ -25,15 +25,15 @@ export class Subnet extends Base {
25
25
  };
26
26
  };
27
27
  networks: Set<any>;
28
+ prefix: any;
29
+ prefixLength: any;
30
+ longPrefix: any;
28
31
  get fullName(): string;
29
32
  matchesAddress(address: any): any;
30
33
  get isLinkLocal(): boolean;
31
34
  get isIPv4(): boolean;
32
35
  get isIPv6(): boolean;
33
36
  get addressRange(): string[];
34
- get longPrefix(): string;
35
- get prefix(): string;
36
- get prefixLength(): number;
37
37
  get address(): string;
38
38
  get longAddress(): string;
39
39
  _traverse(...args: any[]): boolean;
package/types/utils.d.mts CHANGED
@@ -5,32 +5,3 @@ export function sectionLines(sectionName: any, values: any): string[];
5
5
  export function bridgeToJSON(bridge: any): any[];
6
6
  export function asArray(value: any): any[];
7
7
  export function asIterator(value: any): any;
8
- export function isIPv4Address(address: any): boolean;
9
- export function isIPv6Address(address: any): boolean;
10
- export function isLinkLocal(address: any): boolean;
11
- export function generateEU64(mac: any): void;
12
- export function isLocalhost(address: any): boolean;
13
- export function normalizeIPAddress(address: any): any;
14
- export function addressWithPrefixLength(address: any, prefixLength: any): string;
15
- export function _encode(definition: any, address: any): any;
16
- export function decodeIPv6(address: any, length: any): string;
17
- export function encodeIPv6(address: any): any;
18
- export function decodeIPv4(address: any, length: any): string;
19
- export function encodeIPv4(address: any): any;
20
- export function decodeIP(address: any, length: any): string;
21
- export function encodeIP(address: any): any;
22
- export function formatCIDR(address: any, subnet: any): any;
23
- export function normalizeCIDR(address: any): {
24
- prefix?: undefined;
25
- prefixLength?: undefined;
26
- cidr?: undefined;
27
- } | {
28
- prefix: any;
29
- prefixLength: any;
30
- cidr: string;
31
- };
32
- export function hasWellKnownSubnet(address: any): boolean;
33
- export const IPV4_LOCALHOST: any;
34
- export const IPV6_LOCALHOST: any;
35
- export const IPV6_LINK_LOCAL_BROADCAST: any;
36
- export const IPV6_ROUTER_BROADCAST: any;