1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
// shunt - active resolution
//
// Collects the resolvable names from the policies and turns query results
// into set writes, following CNAME chains from the queried name.
//
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 Dirk Brenken <dev@brenken.org>
import { normalize } from 'shunt.match';
import { set_name } from 'shunt.nft';
export function names(policies) {
let seen = {}, out = [];
for (let p in (policies ?? [])) {
for (let raw in (p?.domains ?? [])) {
let n = normalize(raw);
if (!length(n) || index(n, '*') >= 0)
continue;
if (seen[n])
continue;
seen[n] = true;
push(out, n);
}
}
return out;
};
const CHAIN_MAX = 8;
// resolv keys records by their own owner name, so a CNAME answer hides the
// address under the canonical name. Walk from the name that was asked for.
export function addresses(by_name, name) {
let seen = {};
let cur = normalize(name);
let a = [], aaaa = [];
for (let hop = 0; hop < CHAIN_MAX; hop++) {
if (!length(cur ?? '') || seen[cur])
break;
seen[cur] = true;
let e = by_name[cur];
if (!e)
break;
for (let v in (e.A ?? []))
push(a, v);
for (let v in (e.AAAA ?? []))
push(aaaa, v);
cur = normalize((e.CNAME ?? [])[0] ?? '');
}
return { a, aaaa };
};
export function index_results(results) {
let by = {};
for (let k in (results ?? {})) {
let n = normalize(k);
if (length(n))
by[n] = results[k];
}
return by;
};
export function plan(results, matcher, names) {
let writes = [];
let by = index_results(results);
for (let raw in (names ?? [])) {
let name = normalize(raw);
let policies = matcher.test(name);
if (policies == null)
continue;
let got = addresses(by, name);
for (let policy in policies) {
for (let a in got.a)
push(writes, { set: set_name('d', 4, policy), addr: a });
for (let a in got.aaaa)
push(writes, { set: set_name('d', 6, policy), addr: a });
}
}
return writes;
};
|