pmcf 2.1.3 → 2.3.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.1.3",
3
+ "version": "2.3.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
package/src/dns-utils.mjs CHANGED
@@ -1,11 +1,29 @@
1
- import { asArray, asIterator } from "./utils.mjs";
1
+ import {
2
+ asIterator,
3
+ decodeIPv6,
4
+ encodeIPv6,
5
+ normalizeIPAddress
6
+ } from "./utils.mjs";
2
7
 
3
8
  export function dnsFullName(name) {
4
9
  return name.endsWith(".") ? name : name + ".";
5
10
  }
6
11
 
7
12
  export function DNSRecord(key, type, ...values) {
8
- const pad = type === "MX" ? " " : "";
13
+ let pad = "";
14
+
15
+ switch (type) {
16
+ case "MX":
17
+ pad = " ";
18
+ break;
19
+
20
+ case "A":
21
+ values[0] = normalizeIPAddress(values[0]);
22
+ break;
23
+ case "AAAA":
24
+ values[0] = decodeIPv6(encodeIPv6(values[0]));
25
+ break;
26
+ }
9
27
 
10
28
  values = values.map(v =>
11
29
  typeof v === "number" ? String(v).padStart(3) + pad : v
@@ -13,7 +31,7 @@ export function DNSRecord(key, type, ...values) {
13
31
 
14
32
  return {
15
33
  key,
16
- toString: (maxKeyLength, ttl) =>
34
+ toString: (maxKeyLength = 0, ttl = "1W") =>
17
35
  `${key.padEnd(maxKeyLength, " ")} ${ttl} IN ${type.padEnd(
18
36
  5,
19
37
  " "
package/src/service.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Base } from "./base.mjs";
2
2
  import { addType } from "./types.mjs";
3
- import { asArray,isLocalhost } from "./utils.mjs";
3
+ import { asArray, isLocalhost } from "./utils.mjs";
4
4
  import { networkAddressProperties } from "./network-support.mjs";
5
5
  import {
6
6
  DNSRecord,
@@ -11,38 +11,43 @@ import {
11
11
  import { DHCPService, DNSService, NTPService } from "./module.mjs";
12
12
 
13
13
  const ServiceTypes = {
14
- ntp: { protocol: "udp", port: 123, tls: false },
15
- dns: { protocol: "udp", port: 53, tls: false },
16
- ldap: { protocol: "tcp", port: 389, tls: false },
17
- ldaps: { protocol: "tcp", port: 636, tls: true },
18
- http: { protocol: "tcp", port: 80, tls: false },
14
+ ntp: { endpoints: [{ protocol: "udp", port: 123, tls: false }] },
15
+ dns: { endpoints: [{ protocol: "udp", port: 53, tls: false }] },
16
+ ldap: { endpoints: [{ protocol: "tcp", port: 389, tls: false }] },
17
+ ldaps: { endpoints: [{ protocol: "tcp", port: 636, tls: true }] },
18
+ http: { endpoints: [{ protocol: "tcp", port: 80, tls: false }] },
19
19
  https: {
20
- protocol: "tcp",
21
- port: 443,
22
- tls: true,
20
+ endpoints: [{ protocol: "tcp", port: 443, tls: true }],
23
21
  dnsRecord: { type: "HTTPS", parameters: { alpn: "h2" } }
24
22
  },
25
23
  http3: {
26
24
  type: "https",
27
- protocol: "tcp",
28
- port: 443,
29
- tls: true,
25
+ endpoints: [{ protocol: "tcp", port: 443, tls: true }],
30
26
  dnsRecord: {
31
27
  type: "HTTPS",
32
28
  parameters: { "no-default-alpn": undefined, alpn: "h3" }
33
29
  }
34
30
  },
35
- rtsp: { protocol: "tcp", port: 554, tls: false },
36
- smtp: { protocol: "tcp", port: 25, tls: false, dnsRecord: { type: "MX" } },
37
- ssh: { protocol: "tcp", port: 22, tls: false },
38
- imap: { protocol: "tcp", port: 143, tls: false },
39
- imaps: { protocol: "tcp", port: 993, tls: true },
40
- dhcp: { tls: false },
41
- smb: { protocol: "tcp", port: 445, tls: false },
31
+ rtsp: { endpoints: [{ protocol: "tcp", port: 554, tls: false }] },
32
+ smtp: {
33
+ endpoints: [{ protocol: "tcp", port: 25, tls: false }],
34
+ dnsRecord: { type: "MX" }
35
+ },
36
+ ssh: { endpoints: [{ protocol: "tcp", port: 22, tls: false }] },
37
+ imap: { endpoints: [{ protocol: "tcp", port: 143, tls: false }] },
38
+ imaps: { endpoints: [{ protocol: "tcp", port: 993, tls: true }] },
39
+ dhcp: { endpoints: [{ port: 547, tls: false }] },
40
+ "dhcpv6-client": {
41
+ endpoints: [
42
+ { protocol: "tcp", port: 546, tls: false },
43
+ { protocol: "udp", port: 546, tls: false }
44
+ ]
45
+ },
46
+ "dhcpv6-server": { endpoints: [{ port: 547, tls: false }] },
47
+ smb: { endpoints: [{ protocol: "tcp", port: 445, tls: false }] },
42
48
  timemachine: {
43
49
  type: "adisk",
44
- protocol: "tcp",
45
- tls: false,
50
+ endpoints: [{ protocol: "tcp", tls: false }],
46
51
  dnsRecord: {
47
52
  type: "TXT",
48
53
  parameters: {
@@ -86,7 +91,6 @@ export const ServiceTypeDefinition = {
86
91
  alias: { type: "string", collection: false, writeable: true },
87
92
  type: { type: "string", collection: false, writeable: true },
88
93
  weight: { type: "number", collection: false, writeable: true },
89
- srvPrefix: { type: "string", collection: false, writeable: false },
90
94
  tls: { type: "string", collection: false, writeable: false },
91
95
  systemd: { type: "string", collection: true, writeable: true }
92
96
  }
@@ -145,12 +149,22 @@ export class Service extends Base {
145
149
  return this.rawAddresses.map(a => `${a}:${this.port}`);
146
150
  }
147
151
 
152
+ get endpoints() {
153
+ if (this._port !== undefined) {
154
+ return [
155
+ { protocol: this.protocol, address: this.rawAddress, port: this._port }
156
+ ];
157
+ }
158
+
159
+ return ServiceTypes[this.type]?.endpoints || [];
160
+ }
161
+
148
162
  set port(value) {
149
163
  this._port = value;
150
164
  }
151
165
 
152
166
  get port() {
153
- return this._port || ServiceTypes[this.type]?.port;
167
+ return this._port || ServiceTypes[this.type]?.endpoints[0].port;
154
168
  }
155
169
 
156
170
  set weight(value) {
@@ -178,7 +192,7 @@ export class Service extends Base {
178
192
  }
179
193
 
180
194
  get protocol() {
181
- return ServiceTypes[this.type]?.protocol;
195
+ return ServiceTypes[this.type]?.endpoints[0].protocol;
182
196
  }
183
197
 
184
198
  get tls() {
@@ -189,30 +203,29 @@ export class Service extends Base {
189
203
  return this._systemd;
190
204
  }
191
205
 
192
- get srvPrefix() {
193
- const st = ServiceTypes[this.type];
194
- if (st?.protocol) {
195
- return `_${st.type || this.type}._${st.protocol}`;
196
- }
197
- }
198
-
199
206
  dnsRecordsForDomainName(domainName, hasSVRRecords) {
200
207
  const records = [];
201
208
  if (this.priority <= 1 && this.alias) {
202
209
  records.push(DNSRecord(this.alias, "CNAME", dnsFullName(domainName)));
203
210
  }
204
211
 
205
- if (hasSVRRecords && this.srvPrefix) {
206
- records.push(
207
- DNSRecord(
208
- dnsFullName(`${this.srvPrefix}.${domainName}`),
209
- "SRV",
210
- this.priority || 10,
211
- this.weight,
212
- this.port,
213
- dnsFullName(this.domainName)
214
- )
215
- );
212
+ if (hasSVRRecords) {
213
+ for (const ep of this.endpoints.filter(e => e.protocol)) {
214
+ records.push(
215
+ DNSRecord(
216
+ dnsFullName(
217
+ `_${ServiceTypes[this.type]?.type || this.type}._${
218
+ ep.protocol
219
+ }.${domainName}`
220
+ ),
221
+ "SRV",
222
+ this.priority === undefined ? 10 : this.priority,
223
+ this.weight,
224
+ ep.port,
225
+ dnsFullName(this.domainName)
226
+ )
227
+ );
228
+ }
216
229
  }
217
230
 
218
231
  const dnsRecord = ServiceTypes[this.type]?.dnsRecord;
@@ -234,7 +247,7 @@ export class Service extends Base {
234
247
  DNSRecord(
235
248
  dnsFullName(domainName),
236
249
  dnsRecord.type,
237
- this.priority || 10,
250
+ this.priority === undefined ? 10 : this.priority,
238
251
  ".",
239
252
  dnsFormatParameters(parameters)
240
253
  )
@@ -256,12 +269,13 @@ export function serviceAddresses(
256
269
  sources,
257
270
  filter,
258
271
  addressType = "rawAddresses",
259
- addressFilter = a=>!isLocalhost(a)
272
+ addressFilter = a => !isLocalhost(a)
260
273
  ) {
261
274
  return asArray(sources)
262
275
  .map(ft => Array.from(ft.findServices(filter)))
263
276
  .flat()
264
277
  .sort(sortByPriority)
265
278
  .map(s => s[addressType])
266
- .flat().filter(addressFilter);
279
+ .flat()
280
+ .filter(addressFilter);
267
281
  }
@@ -5,16 +5,16 @@ import {
5
5
  writeLines,
6
6
  isIPv6Address,
7
7
  normalizeIPAddress,
8
- isLinkLocal
8
+ isLinkLocal,
9
+ isLocalhost
9
10
  } from "../utils.mjs";
10
11
  import { DNSRecord, dnsFullName } from "../dns-utils.mjs";
11
12
  import { addType } from "../types.mjs";
13
+ import { ServiceTypeDefinition, serviceAddresses } from "../service.mjs";
12
14
  import {
13
- Service,
14
- ServiceTypeDefinition,
15
- serviceAddresses
16
- } from "../service.mjs";
17
- import { ExtraSourceService, ExtraSourceServiceTypeDefinition } from "../extra-source-service.mjs";
15
+ ExtraSourceService,
16
+ ExtraSourceServiceTypeDefinition
17
+ } from "../extra-source-service.mjs";
18
18
  import { subnets } from "../subnet.mjs";
19
19
 
20
20
  const DNSServiceTypeDefinition = {
@@ -262,15 +262,14 @@ async function generateZoneDefs(dns, location, packageData) {
262
262
  };
263
263
  configs.push(config);
264
264
 
265
+ zone.records.add(DNSRecord("location", "TXT", host.location.name));
266
+
265
267
  for (const address of host.rawAddresses) {
266
- zone.records.add(
267
- DNSRecord(
268
- "@",
269
- isIPv6Address(address) ? "AAAA" : "A",
270
- normalizeIPAddress(address)
271
- )
272
- );
273
- zone.records.add(DNSRecord("location", "TXT", host.location.name));
268
+ if (!isLocalhost(address)) {
269
+ zone.records.add(
270
+ DNSRecord("@", isIPv6Address(address) ? "AAAA" : "A", address)
271
+ );
272
+ }
274
273
  }
275
274
  }
276
275
  }
@@ -335,7 +334,7 @@ async function generateZoneDefs(dns, location, packageData) {
335
334
  DNSRecord(
336
335
  dnsFullName(domainName),
337
336
  isIPv6Address(address) ? "AAAA" : "A",
338
- normalizeIPAddress(address)
337
+ address
339
338
  )
340
339
  );
341
340
  }
package/src/utils.mjs CHANGED
@@ -96,7 +96,15 @@ export function isIPv6Address(address) {
96
96
  }
97
97
 
98
98
  export function isLinkLocal(address) {
99
- return address.startsWith("fe80");
99
+ switch (typeof address) {
100
+ case "string":
101
+ return address.startsWith("fe80");
102
+
103
+ case "bigint":
104
+ return ((address >> 112n) & 0xffffn) === 0xfe80n;
105
+ }
106
+
107
+ return false;
100
108
  }
101
109
 
102
110
  export function isLocalhost(address) {
@@ -136,6 +144,10 @@ const ipv6 = {
136
144
  };
137
145
 
138
146
  function _decode(definition, address, length = definition.length) {
147
+ if (typeof address === "string") {
148
+ return address;
149
+ }
150
+
139
151
  let result = "";
140
152
  let compressed = 0;
141
153
  let shift = definition.length;
@@ -1,7 +1,7 @@
1
1
  export function dnsFullName(name: any): any;
2
2
  export function DNSRecord(key: any, type: any, ...values: any[]): {
3
3
  key: any;
4
- toString: (maxKeyLength: any, ttl: any) => string;
4
+ toString: (maxKeyLength?: number, ttl?: string) => string;
5
5
  };
6
6
  export function dnsFormatParameters(parameters: any): string;
7
7
  export function dnsMergeParameters(a: any, b: any): {
@@ -98,11 +98,6 @@ export class ExtraSourceService extends Service {
98
98
  collection: boolean;
99
99
  writeable: boolean;
100
100
  };
101
- srvPrefix: {
102
- type: string;
103
- collection: boolean;
104
- writeable: boolean;
105
- };
106
101
  tls: {
107
102
  type: string;
108
103
  collection: boolean;
@@ -83,11 +83,6 @@ export namespace ServiceTypeDefinition {
83
83
  collection: boolean;
84
84
  writeable: boolean;
85
85
  };
86
- srvPrefix: {
87
- type: string;
88
- collection: boolean;
89
- writeable: boolean;
90
- };
91
86
  tls: {
92
87
  type: string;
93
88
  collection: boolean;
@@ -209,11 +204,6 @@ export class Service extends Base {
209
204
  collection: boolean;
210
205
  writeable: boolean;
211
206
  };
212
- srvPrefix: {
213
- type: string;
214
- collection: boolean;
215
- writeable: boolean;
216
- };
217
207
  tls: {
218
208
  type: string;
219
209
  collection: boolean;
@@ -264,6 +254,7 @@ export class Service extends Base {
264
254
  get rawAddress(): any;
265
255
  set ipAddresses(value: any);
266
256
  get addresses(): any;
257
+ get endpoints(): any;
267
258
  set port(value: any);
268
259
  get port(): any;
269
260
  set weight(value: any);
@@ -273,10 +264,9 @@ export class Service extends Base {
273
264
  get protocol(): any;
274
265
  get tls(): any;
275
266
  get systemdServices(): any;
276
- get srvPrefix(): string;
277
267
  dnsRecordsForDomainName(domainName: any, hasSVRRecords: any): {
278
268
  key: any;
279
- toString: (maxKeyLength: any, ttl: any) => string;
269
+ toString: (maxKeyLength?: number, ttl?: string) => string;
280
270
  }[];
281
271
  }
282
272
  export function sortByPriority(a: any, b: any): number;
@@ -85,11 +85,6 @@ export class DHCPService extends Service {
85
85
  collection: boolean;
86
86
  writeable: boolean;
87
87
  };
88
- srvPrefix: {
89
- type: string;
90
- collection: boolean;
91
- writeable: boolean;
92
- };
93
88
  tls: {
94
89
  type: string;
95
90
  collection: boolean;
@@ -58,7 +58,7 @@ export class DNSService extends ExtraSourceService {
58
58
  };
59
59
  };
60
60
  };
61
- factoryFor(value: any): typeof Service | typeof DNSService | typeof import("./ntp.mjs").NTPService | typeof import("./dhcp.mjs").DHCPService;
61
+ factoryFor(value: any): typeof import("../service.mjs").Service | typeof DNSService | typeof import("./ntp.mjs").NTPService | typeof import("./dhcp.mjs").DHCPService;
62
62
  properties: {
63
63
  ipAddresses: {
64
64
  type: string;
@@ -90,11 +90,6 @@ export class DNSService extends ExtraSourceService {
90
90
  collection: boolean;
91
91
  writeable: boolean;
92
92
  };
93
- srvPrefix: {
94
- type: string;
95
- collection: boolean;
96
- writeable: boolean;
97
- };
98
93
  tls: {
99
94
  type: string;
100
95
  collection: boolean;
@@ -264,4 +259,3 @@ export class DNSService extends ExtraSourceService {
264
259
  }, void, unknown>;
265
260
  }
266
261
  import { ExtraSourceService } from "../extra-source-service.mjs";
267
- import { Service } from "../service.mjs";
@@ -88,11 +88,6 @@ export class NTPService extends ExtraSourceService {
88
88
  collection: boolean;
89
89
  writeable: boolean;
90
90
  };
91
- srvPrefix: {
92
- type: string;
93
- collection: boolean;
94
- writeable: boolean;
95
- };
96
91
  tls: {
97
92
  type: string;
98
93
  collection: boolean;
@@ -27,7 +27,7 @@ export class Subnet extends Base {
27
27
  networks: Set<any>;
28
28
  get fullName(): string;
29
29
  matchesAddress(address: any): any;
30
- get isLinkLocal(): any;
30
+ get isLinkLocal(): boolean;
31
31
  get prefix(): string;
32
32
  get prefixLength(): number;
33
33
  get address(): string;
package/types/utils.d.mts CHANGED
@@ -8,7 +8,7 @@ export function asIterator(value: any): any;
8
8
  export function isIPv4Address(address: any): boolean;
9
9
  export function generateEU64(mac: any): void;
10
10
  export function isIPv6Address(address: any): boolean;
11
- export function isLinkLocal(address: any): any;
11
+ export function isLinkLocal(address: any): boolean;
12
12
  export function isLocalhost(address: any): boolean;
13
13
  export function normalizeIPAddress(address: any): any;
14
14
  export function _encode(definition: any, address: any): any;
@@ -28,7 +28,7 @@ export function normalizeCIDR(address: any): {
28
28
  prefixLength: any;
29
29
  cidr: string;
30
30
  };
31
- export function hasWellKnownSubnet(address: any): any;
31
+ export function hasWellKnownSubnet(address: any): boolean;
32
32
  export const IPV4_LOCALHOST: any;
33
33
  export const IPV6_LOCALHOST: any;
34
34
  export const IPV6_LINK_LOCAL_BROADCAST: any;