@birdcc/linter 0.0.1-alpha.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.
Files changed (60) hide show
  1. package/.oxfmtrc.json +16 -0
  2. package/LICENSE +674 -0
  3. package/README.md +210 -0
  4. package/dist/index.d.ts +21 -0
  5. package/dist/index.d.ts.map +1 -0
  6. package/dist/index.js +93 -0
  7. package/dist/index.js.map +1 -0
  8. package/dist/rules/bgp.d.ts +5 -0
  9. package/dist/rules/bgp.d.ts.map +1 -0
  10. package/dist/rules/bgp.js +131 -0
  11. package/dist/rules/bgp.js.map +1 -0
  12. package/dist/rules/catalog.d.ts +14 -0
  13. package/dist/rules/catalog.d.ts.map +1 -0
  14. package/dist/rules/catalog.js +61 -0
  15. package/dist/rules/catalog.js.map +1 -0
  16. package/dist/rules/cfg.d.ts +5 -0
  17. package/dist/rules/cfg.d.ts.map +1 -0
  18. package/dist/rules/cfg.js +264 -0
  19. package/dist/rules/cfg.js.map +1 -0
  20. package/dist/rules/net.d.ts +5 -0
  21. package/dist/rules/net.d.ts.map +1 -0
  22. package/dist/rules/net.js +140 -0
  23. package/dist/rules/net.js.map +1 -0
  24. package/dist/rules/normalize.d.ts +6 -0
  25. package/dist/rules/normalize.d.ts.map +1 -0
  26. package/dist/rules/normalize.js +65 -0
  27. package/dist/rules/normalize.js.map +1 -0
  28. package/dist/rules/ospf.d.ts +5 -0
  29. package/dist/rules/ospf.d.ts.map +1 -0
  30. package/dist/rules/ospf.js +136 -0
  31. package/dist/rules/ospf.js.map +1 -0
  32. package/dist/rules/shared.d.ts +46 -0
  33. package/dist/rules/shared.d.ts.map +1 -0
  34. package/dist/rules/shared.js +184 -0
  35. package/dist/rules/shared.js.map +1 -0
  36. package/dist/rules/sym.d.ts +5 -0
  37. package/dist/rules/sym.d.ts.map +1 -0
  38. package/dist/rules/sym.js +188 -0
  39. package/dist/rules/sym.js.map +1 -0
  40. package/dist/rules/type.d.ts +5 -0
  41. package/dist/rules/type.d.ts.map +1 -0
  42. package/dist/rules/type.js +130 -0
  43. package/dist/rules/type.js.map +1 -0
  44. package/package.json +41 -0
  45. package/src/index.ts +155 -0
  46. package/src/rules/bgp.ts +239 -0
  47. package/src/rules/catalog.ts +80 -0
  48. package/src/rules/cfg.ts +562 -0
  49. package/src/rules/net.ts +262 -0
  50. package/src/rules/normalize.ts +90 -0
  51. package/src/rules/ospf.ts +221 -0
  52. package/src/rules/shared.ts +354 -0
  53. package/src/rules/sym.ts +342 -0
  54. package/src/rules/type.ts +210 -0
  55. package/test/linter.bgp-ospf.test.ts +129 -0
  56. package/test/linter.migration.test.ts +66 -0
  57. package/test/linter.net-type.test.ts +132 -0
  58. package/test/linter.sym-cfg.test.ts +224 -0
  59. package/test/linter.test.ts +21 -0
  60. package/tsconfig.json +8 -0
@@ -0,0 +1,264 @@
1
+ import { isIP } from "node:net";
2
+ import { channelOtherEntries, createProtocolDiagnostic, createRuleDiagnostic, extractFirstNumberAfterKeyword, hasBooleanValue, isProtocolType, numericValue, protocolDeclarations, pushUniqueDiagnostic, routerIdDeclarations, templateDeclarations, } from "./shared.js";
3
+ const MAX_ASN = 4_294_967_294;
4
+ const MAX_ROUTE_LIMIT = 10_000_000;
5
+ const cfgNoProtocolRule = ({ parsed }) => {
6
+ if (protocolDeclarations(parsed).length > 0) {
7
+ return [];
8
+ }
9
+ return [
10
+ createRuleDiagnostic("cfg/no-protocol", "No protocol is specified in configuration", {
11
+ line: 1,
12
+ column: 1,
13
+ endLine: 1,
14
+ endColumn: 1,
15
+ }),
16
+ ];
17
+ };
18
+ const cfgMissingRouterIdRule = ({ parsed }) => {
19
+ if (routerIdDeclarations(parsed).length > 0) {
20
+ return [];
21
+ }
22
+ return [
23
+ createRuleDiagnostic("cfg/missing-router-id", "Router ID must be configured", {
24
+ line: 1,
25
+ column: 1,
26
+ endLine: 1,
27
+ endColumn: 1,
28
+ }),
29
+ ];
30
+ };
31
+ const diagnoseNumberExpected = (diagnostics, seen, range, declarationName, fieldName, value) => {
32
+ if (value === undefined) {
33
+ return;
34
+ }
35
+ if (numericValue(value) !== null) {
36
+ return;
37
+ }
38
+ pushUniqueDiagnostic(diagnostics, seen, createRuleDiagnostic("cfg/number-expected", `Protocol '${declarationName}' expects numeric value for '${fieldName}'`, range));
39
+ };
40
+ const diagnoseValueOutOfRange = (diagnostics, seen, range, declarationName, fieldName, value, min, max) => {
41
+ if (value === null) {
42
+ return;
43
+ }
44
+ if (value >= min && value <= max) {
45
+ return;
46
+ }
47
+ pushUniqueDiagnostic(diagnostics, seen, createRuleDiagnostic("cfg/value-out-of-range", `Protocol '${declarationName}' has out-of-range value for '${fieldName}': ${value}`, range));
48
+ };
49
+ const cfgNumericRules = ({ parsed }) => {
50
+ const diagnostics = [];
51
+ const seen = new Set();
52
+ for (const declaration of protocolDeclarations(parsed)) {
53
+ for (const statement of declaration.statements) {
54
+ if (statement.kind === "local-as") {
55
+ diagnoseNumberExpected(diagnostics, seen, statement.asnRange, declaration.name, "local as", statement.asn);
56
+ diagnoseValueOutOfRange(diagnostics, seen, statement.asnRange, declaration.name, "local as", numericValue(statement.asn), 1, MAX_ASN);
57
+ }
58
+ if (statement.kind === "neighbor" && statement.asnRange) {
59
+ diagnoseNumberExpected(diagnostics, seen, statement.asnRange, declaration.name, "neighbor as", statement.asn);
60
+ diagnoseValueOutOfRange(diagnostics, seen, statement.asnRange, declaration.name, "neighbor as", numericValue(statement.asn), 1, MAX_ASN);
61
+ }
62
+ if (statement.kind === "other") {
63
+ const lowerText = statement.text.toLowerCase();
64
+ const holdNumber = extractFirstNumberAfterKeyword(lowerText, "hold");
65
+ if (holdNumber === null && /\bhold\b/.test(lowerText)) {
66
+ diagnoseNumberExpected(diagnostics, seen, statement, declaration.name, "hold", "");
67
+ }
68
+ diagnoseValueOutOfRange(diagnostics, seen, statement, declaration.name, "hold", holdNumber, 3, 65_535);
69
+ const keepaliveNumber = extractFirstNumberAfterKeyword(lowerText, "keepalive");
70
+ if (keepaliveNumber === null && /\bkeepalive\b/.test(lowerText)) {
71
+ diagnoseNumberExpected(diagnostics, seen, statement, declaration.name, "keepalive", "");
72
+ }
73
+ diagnoseValueOutOfRange(diagnostics, seen, statement, declaration.name, "keepalive", keepaliveNumber, 1, 65_535);
74
+ const ttlNumber = extractFirstNumberAfterKeyword(lowerText, "ttl");
75
+ if (ttlNumber === null && /\bttl\b/.test(lowerText)) {
76
+ diagnoseNumberExpected(diagnostics, seen, statement, declaration.name, "ttl", "");
77
+ }
78
+ diagnoseValueOutOfRange(diagnostics, seen, statement, declaration.name, "ttl", ttlNumber, 1, 255);
79
+ }
80
+ if (statement.kind !== "channel") {
81
+ continue;
82
+ }
83
+ for (const entry of statement.entries) {
84
+ if (entry.kind === "limit") {
85
+ diagnoseNumberExpected(diagnostics, seen, entry.valueRange, declaration.name, "limit", entry.value);
86
+ diagnoseValueOutOfRange(diagnostics, seen, entry.valueRange, declaration.name, "limit", numericValue(entry.value), 0, MAX_ROUTE_LIMIT);
87
+ }
88
+ if (entry.kind !== "other") {
89
+ continue;
90
+ }
91
+ const maxPrefixMatch = entry.text.match(/\bmax\s+prefix\s+([^;\s]+)/i);
92
+ if (!maxPrefixMatch) {
93
+ continue;
94
+ }
95
+ const token = maxPrefixMatch[1] ?? "";
96
+ diagnoseNumberExpected(diagnostics, seen, entry, declaration.name, "max prefix", token);
97
+ diagnoseValueOutOfRange(diagnostics, seen, entry, declaration.name, "max prefix", numericValue(token), 0, MAX_ROUTE_LIMIT);
98
+ }
99
+ }
100
+ }
101
+ return diagnostics;
102
+ };
103
+ const cfgSwitchValueExpectedRule = ({ parsed }) => {
104
+ const diagnostics = [];
105
+ const seen = new Set();
106
+ const switchPattern = /\b(passive|stub|bfd|enabled|disabled|check\s+link|deterministic\s+med)\b\s+([^;\s]+)/i;
107
+ for (const declaration of protocolDeclarations(parsed)) {
108
+ for (const statement of declaration.statements) {
109
+ if (statement.kind === "other") {
110
+ const matched = statement.text.match(switchPattern);
111
+ if (matched) {
112
+ const token = matched[2] ?? "";
113
+ if (!hasBooleanValue(token)) {
114
+ pushUniqueDiagnostic(diagnostics, seen, createRuleDiagnostic("cfg/switch-value-expected", `Protocol '${declaration.name}' expects boolean value for '${matched[1]}'`, statement));
115
+ }
116
+ }
117
+ }
118
+ if (statement.kind !== "channel") {
119
+ continue;
120
+ }
121
+ for (const entry of statement.entries) {
122
+ if (entry.kind !== "keep-filtered") {
123
+ continue;
124
+ }
125
+ if (hasBooleanValue(entry.value)) {
126
+ continue;
127
+ }
128
+ pushUniqueDiagnostic(diagnostics, seen, createRuleDiagnostic("cfg/switch-value-expected", `Protocol '${declaration.name}' expects boolean value for keep filtered`, entry.valueRange));
129
+ }
130
+ }
131
+ }
132
+ return diagnostics;
133
+ };
134
+ const extractIps = (text) => {
135
+ const parts = text
136
+ .split(/[^0-9A-Fa-f:./]+/)
137
+ .map((item) => item.trim())
138
+ .filter((item) => item.length > 0);
139
+ const values = [];
140
+ for (const part of parts) {
141
+ const candidate = part.includes("/") ? (part.split("/")[0] ?? "") : part;
142
+ if (isIP(candidate) !== 0) {
143
+ values.push(candidate);
144
+ }
145
+ }
146
+ return values;
147
+ };
148
+ const cfgIpNetworkMismatchRule = ({ parsed }) => {
149
+ const diagnostics = [];
150
+ const seen = new Set();
151
+ for (const declaration of protocolDeclarations(parsed)) {
152
+ for (const entry of channelOtherEntries(declaration)) {
153
+ if (entry.channelType !== "ipv4" && entry.channelType !== "ipv6") {
154
+ continue;
155
+ }
156
+ for (const value of extractIps(entry.text)) {
157
+ const family = isIP(value);
158
+ if ((entry.channelType === "ipv4" && family === 4) ||
159
+ (entry.channelType === "ipv6" && family === 6)) {
160
+ continue;
161
+ }
162
+ pushUniqueDiagnostic(diagnostics, seen, createRuleDiagnostic("cfg/ip-network-mismatch", `Protocol '${declaration.name}' channel '${entry.channelType}' contains mismatched address '${value}'`, entry.range));
163
+ }
164
+ }
165
+ }
166
+ return diagnostics;
167
+ };
168
+ const cfgIncompatibleTypeRule = ({ parsed }) => {
169
+ const diagnostics = [];
170
+ const seen = new Set();
171
+ for (const declaration of protocolDeclarations(parsed)) {
172
+ for (const statement of declaration.statements) {
173
+ if (statement.kind === "neighbor" && statement.addressKind !== "ip") {
174
+ pushUniqueDiagnostic(diagnostics, seen, createRuleDiagnostic("cfg/incompatible-type", `Protocol '${declaration.name}' neighbor address must be an IP literal`, statement.addressRange));
175
+ }
176
+ if (statement.kind === "other" &&
177
+ /\brouter\s+id\s+\S+/i.test(statement.text)) {
178
+ const matched = statement.text.match(/\brouter\s+id\s+([^;\s]+)/i);
179
+ const value = matched?.[1] ?? "";
180
+ if (value && isIP(value) !== 4) {
181
+ pushUniqueDiagnostic(diagnostics, seen, createRuleDiagnostic("cfg/incompatible-type", `Router id '${value}' must be IPv4`, statement));
182
+ }
183
+ }
184
+ }
185
+ }
186
+ return diagnostics;
187
+ };
188
+ const hasTemplateCycleFrom = (start, graph) => {
189
+ const path = new Set();
190
+ let current = start;
191
+ let hops = 0;
192
+ const maxHops = graph.size + 1;
193
+ while (current.length > 0) {
194
+ if (path.has(current)) {
195
+ return true;
196
+ }
197
+ path.add(current);
198
+ current = graph.get(current) ?? "";
199
+ hops += 1;
200
+ if (hops > maxHops) {
201
+ return true;
202
+ }
203
+ }
204
+ return false;
205
+ };
206
+ const cfgCircularTemplateRule = ({ parsed }) => {
207
+ const diagnostics = [];
208
+ const seen = new Set();
209
+ const templates = templateDeclarations(parsed);
210
+ if (templates.length === 0) {
211
+ return diagnostics;
212
+ }
213
+ const graph = new Map();
214
+ const ranges = new Map();
215
+ for (const template of templates) {
216
+ const name = template.name.toLowerCase();
217
+ ranges.set(name, template.nameRange);
218
+ if (template.fromTemplate) {
219
+ graph.set(name, template.fromTemplate.toLowerCase());
220
+ }
221
+ }
222
+ for (const template of templates) {
223
+ const name = template.name.toLowerCase();
224
+ if (!hasTemplateCycleFrom(name, graph)) {
225
+ continue;
226
+ }
227
+ const range = ranges.get(name) ?? template.nameRange;
228
+ pushUniqueDiagnostic(diagnostics, seen, createRuleDiagnostic("cfg/circular-template", `Template '${template.name}' is in a circular inheritance chain`, range));
229
+ }
230
+ return diagnostics;
231
+ };
232
+ const cfgProtocolSpecificHintRule = ({ parsed }) => {
233
+ const diagnostics = [];
234
+ const seen = new Set();
235
+ for (const declaration of protocolDeclarations(parsed)) {
236
+ if (!isProtocolType(declaration, "bgp")) {
237
+ continue;
238
+ }
239
+ for (const statement of declaration.statements) {
240
+ if (statement.kind !== "other") {
241
+ continue;
242
+ }
243
+ if (!/\bneighbor\s+\S+\s+as\s+[^0-9\s;]+/i.test(statement.text)) {
244
+ continue;
245
+ }
246
+ pushUniqueDiagnostic(diagnostics, seen, createProtocolDiagnostic("cfg/number-expected", `Protocol '${declaration.name}' expects numeric ASN in neighbor statement`, declaration, "error"));
247
+ }
248
+ }
249
+ return diagnostics;
250
+ };
251
+ export const cfgRules = [
252
+ cfgNoProtocolRule,
253
+ cfgMissingRouterIdRule,
254
+ cfgNumericRules,
255
+ cfgSwitchValueExpectedRule,
256
+ cfgIpNetworkMismatchRule,
257
+ cfgIncompatibleTypeRule,
258
+ cfgCircularTemplateRule,
259
+ cfgProtocolSpecificHintRule,
260
+ ];
261
+ export const collectCfgRuleDiagnostics = (context) => {
262
+ return cfgRules.flatMap((rule) => rule(context));
263
+ };
264
+ //# sourceMappingURL=cfg.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cfg.js","sourceRoot":"","sources":["../../src/rules/cfg.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAGhC,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,oBAAoB,EACpB,8BAA8B,EAC9B,eAAe,EACf,cAAc,EACd,YAAY,EACZ,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,GAErB,MAAM,aAAa,CAAC;AAErB,MAAM,OAAO,GAAG,aAAa,CAAC;AAC9B,MAAM,eAAe,GAAG,UAAU,CAAC;AAEnC,MAAM,iBAAiB,GAAa,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE;IACjD,IAAI,oBAAoB,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5C,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,OAAO;QACL,oBAAoB,CAClB,iBAAiB,EACjB,2CAA2C,EAC3C;YACE,IAAI,EAAE,CAAC;YACP,MAAM,EAAE,CAAC;YACT,OAAO,EAAE,CAAC;YACV,SAAS,EAAE,CAAC;SACb,CACF;KACF,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,sBAAsB,GAAa,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE;IACtD,IAAI,oBAAoB,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5C,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,OAAO;QACL,oBAAoB,CAClB,uBAAuB,EACvB,8BAA8B,EAC9B;YACE,IAAI,EAAE,CAAC;YACP,MAAM,EAAE,CAAC;YACT,OAAO,EAAE,CAAC;YACV,SAAS,EAAE,CAAC;SACb,CACF;KACF,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,sBAAsB,GAAG,CAC7B,WAA6B,EAC7B,IAAiB,EACjB,KAAkB,EAClB,eAAuB,EACvB,SAAiB,EACjB,KAAyB,EACnB,EAAE;IACR,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,OAAO;IACT,CAAC;IAED,IAAI,YAAY,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC;QACjC,OAAO;IACT,CAAC;IAED,oBAAoB,CAClB,WAAW,EACX,IAAI,EACJ,oBAAoB,CAClB,qBAAqB,EACrB,aAAa,eAAe,gCAAgC,SAAS,GAAG,EACxE,KAAK,CACN,CACF,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,uBAAuB,GAAG,CAC9B,WAA6B,EAC7B,IAAiB,EACjB,KAAkB,EAClB,eAAuB,EACvB,SAAiB,EACjB,KAAoB,EACpB,GAAW,EACX,GAAW,EACL,EAAE;IACR,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,OAAO;IACT,CAAC;IAED,IAAI,KAAK,IAAI,GAAG,IAAI,KAAK,IAAI,GAAG,EAAE,CAAC;QACjC,OAAO;IACT,CAAC;IAED,oBAAoB,CAClB,WAAW,EACX,IAAI,EACJ,oBAAoB,CAClB,wBAAwB,EACxB,aAAa,eAAe,iCAAiC,SAAS,MAAM,KAAK,EAAE,EACnF,KAAK,CACN,CACF,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,eAAe,GAAa,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE;IAC/C,MAAM,WAAW,GAAqB,EAAE,CAAC;IACzC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/B,KAAK,MAAM,WAAW,IAAI,oBAAoB,CAAC,MAAM,CAAC,EAAE,CAAC;QACvD,KAAK,MAAM,SAAS,IAAI,WAAW,CAAC,UAAU,EAAE,CAAC;YAC/C,IAAI,SAAS,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;gBAClC,sBAAsB,CACpB,WAAW,EACX,IAAI,EACJ,SAAS,CAAC,QAAQ,EAClB,WAAW,CAAC,IAAI,EAChB,UAAU,EACV,SAAS,CAAC,GAAG,CACd,CAAC;gBACF,uBAAuB,CACrB,WAAW,EACX,IAAI,EACJ,SAAS,CAAC,QAAQ,EAClB,WAAW,CAAC,IAAI,EAChB,UAAU,EACV,YAAY,CAAC,SAAS,CAAC,GAAG,CAAC,EAC3B,CAAC,EACD,OAAO,CACR,CAAC;YACJ,CAAC;YAED,IAAI,SAAS,CAAC,IAAI,KAAK,UAAU,IAAI,SAAS,CAAC,QAAQ,EAAE,CAAC;gBACxD,sBAAsB,CACpB,WAAW,EACX,IAAI,EACJ,SAAS,CAAC,QAAQ,EAClB,WAAW,CAAC,IAAI,EAChB,aAAa,EACb,SAAS,CAAC,GAAG,CACd,CAAC;gBACF,uBAAuB,CACrB,WAAW,EACX,IAAI,EACJ,SAAS,CAAC,QAAQ,EAClB,WAAW,CAAC,IAAI,EAChB,aAAa,EACb,YAAY,CAAC,SAAS,CAAC,GAAG,CAAC,EAC3B,CAAC,EACD,OAAO,CACR,CAAC;YACJ,CAAC;YAED,IAAI,SAAS,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAC/B,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;gBAE/C,MAAM,UAAU,GAAG,8BAA8B,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;gBACrE,IAAI,UAAU,KAAK,IAAI,IAAI,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;oBACtD,sBAAsB,CACpB,WAAW,EACX,IAAI,EACJ,SAAS,EACT,WAAW,CAAC,IAAI,EAChB,MAAM,EACN,EAAE,CACH,CAAC;gBACJ,CAAC;gBACD,uBAAuB,CACrB,WAAW,EACX,IAAI,EACJ,SAAS,EACT,WAAW,CAAC,IAAI,EAChB,MAAM,EACN,UAAU,EACV,CAAC,EACD,MAAM,CACP,CAAC;gBAEF,MAAM,eAAe,GAAG,8BAA8B,CACpD,SAAS,EACT,WAAW,CACZ,CAAC;gBACF,IAAI,eAAe,KAAK,IAAI,IAAI,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;oBAChE,sBAAsB,CACpB,WAAW,EACX,IAAI,EACJ,SAAS,EACT,WAAW,CAAC,IAAI,EAChB,WAAW,EACX,EAAE,CACH,CAAC;gBACJ,CAAC;gBACD,uBAAuB,CACrB,WAAW,EACX,IAAI,EACJ,SAAS,EACT,WAAW,CAAC,IAAI,EAChB,WAAW,EACX,eAAe,EACf,CAAC,EACD,MAAM,CACP,CAAC;gBAEF,MAAM,SAAS,GAAG,8BAA8B,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;gBACnE,IAAI,SAAS,KAAK,IAAI,IAAI,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;oBACpD,sBAAsB,CACpB,WAAW,EACX,IAAI,EACJ,SAAS,EACT,WAAW,CAAC,IAAI,EAChB,KAAK,EACL,EAAE,CACH,CAAC;gBACJ,CAAC;gBACD,uBAAuB,CACrB,WAAW,EACX,IAAI,EACJ,SAAS,EACT,WAAW,CAAC,IAAI,EAChB,KAAK,EACL,SAAS,EACT,CAAC,EACD,GAAG,CACJ,CAAC;YACJ,CAAC;YAED,IAAI,SAAS,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBACjC,SAAS;YACX,CAAC;YAED,KAAK,MAAM,KAAK,IAAI,SAAS,CAAC,OAAO,EAAE,CAAC;gBACtC,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;oBAC3B,sBAAsB,CACpB,WAAW,EACX,IAAI,EACJ,KAAK,CAAC,UAAU,EAChB,WAAW,CAAC,IAAI,EAChB,OAAO,EACP,KAAK,CAAC,KAAK,CACZ,CAAC;oBACF,uBAAuB,CACrB,WAAW,EACX,IAAI,EACJ,KAAK,CAAC,UAAU,EAChB,WAAW,CAAC,IAAI,EAChB,OAAO,EACP,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,EACzB,CAAC,EACD,eAAe,CAChB,CAAC;gBACJ,CAAC;gBAED,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;oBAC3B,SAAS;gBACX,CAAC;gBAED,MAAM,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;gBACvE,IAAI,CAAC,cAAc,EAAE,CAAC;oBACpB,SAAS;gBACX,CAAC;gBAED,MAAM,KAAK,GAAG,cAAc,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;gBACtC,sBAAsB,CACpB,WAAW,EACX,IAAI,EACJ,KAAK,EACL,WAAW,CAAC,IAAI,EAChB,YAAY,EACZ,KAAK,CACN,CAAC;gBACF,uBAAuB,CACrB,WAAW,EACX,IAAI,EACJ,KAAK,EACL,WAAW,CAAC,IAAI,EAChB,YAAY,EACZ,YAAY,CAAC,KAAK,CAAC,EACnB,CAAC,EACD,eAAe,CAChB,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,WAAW,CAAC;AACrB,CAAC,CAAC;AAEF,MAAM,0BAA0B,GAAa,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE;IAC1D,MAAM,WAAW,GAAqB,EAAE,CAAC;IACzC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,aAAa,GACjB,uFAAuF,CAAC;IAE1F,KAAK,MAAM,WAAW,IAAI,oBAAoB,CAAC,MAAM,CAAC,EAAE,CAAC;QACvD,KAAK,MAAM,SAAS,IAAI,WAAW,CAAC,UAAU,EAAE,CAAC;YAC/C,IAAI,SAAS,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAC/B,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;gBACpD,IAAI,OAAO,EAAE,CAAC;oBACZ,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;oBAC/B,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC;wBAC5B,oBAAoB,CAClB,WAAW,EACX,IAAI,EACJ,oBAAoB,CAClB,2BAA2B,EAC3B,aAAa,WAAW,CAAC,IAAI,gCAAgC,OAAO,CAAC,CAAC,CAAC,GAAG,EAC1E,SAAS,CACV,CACF,CAAC;oBACJ,CAAC;gBACH,CAAC;YACH,CAAC;YAED,IAAI,SAAS,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBACjC,SAAS;YACX,CAAC;YAED,KAAK,MAAM,KAAK,IAAI,SAAS,CAAC,OAAO,EAAE,CAAC;gBACtC,IAAI,KAAK,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;oBACnC,SAAS;gBACX,CAAC;gBAED,IAAI,eAAe,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;oBACjC,SAAS;gBACX,CAAC;gBAED,oBAAoB,CAClB,WAAW,EACX,IAAI,EACJ,oBAAoB,CAClB,2BAA2B,EAC3B,aAAa,WAAW,CAAC,IAAI,2CAA2C,EACxE,KAAK,CAAC,UAAU,CACjB,CACF,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,WAAW,CAAC;AACrB,CAAC,CAAC;AAEF,MAAM,UAAU,GAAG,CAAC,IAAY,EAAY,EAAE;IAC5C,MAAM,KAAK,GAAG,IAAI;SACf,KAAK,CAAC,kBAAkB,CAAC;SACzB,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;SAC1B,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAErC,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACzE,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;YAC1B,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF,MAAM,wBAAwB,GAAa,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE;IACxD,MAAM,WAAW,GAAqB,EAAE,CAAC;IACzC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/B,KAAK,MAAM,WAAW,IAAI,oBAAoB,CAAC,MAAM,CAAC,EAAE,CAAC;QACvD,KAAK,MAAM,KAAK,IAAI,mBAAmB,CAAC,WAAW,CAAC,EAAE,CAAC;YACrD,IAAI,KAAK,CAAC,WAAW,KAAK,MAAM,IAAI,KAAK,CAAC,WAAW,KAAK,MAAM,EAAE,CAAC;gBACjE,SAAS;YACX,CAAC;YAED,KAAK,MAAM,KAAK,IAAI,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC3C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;gBAC3B,IACE,CAAC,KAAK,CAAC,WAAW,KAAK,MAAM,IAAI,MAAM,KAAK,CAAC,CAAC;oBAC9C,CAAC,KAAK,CAAC,WAAW,KAAK,MAAM,IAAI,MAAM,KAAK,CAAC,CAAC,EAC9C,CAAC;oBACD,SAAS;gBACX,CAAC;gBAED,oBAAoB,CAClB,WAAW,EACX,IAAI,EACJ,oBAAoB,CAClB,yBAAyB,EACzB,aAAa,WAAW,CAAC,IAAI,cAAc,KAAK,CAAC,WAAW,kCAAkC,KAAK,GAAG,EACtG,KAAK,CAAC,KAAK,CACZ,CACF,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,WAAW,CAAC;AACrB,CAAC,CAAC;AAEF,MAAM,uBAAuB,GAAa,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE;IACvD,MAAM,WAAW,GAAqB,EAAE,CAAC;IACzC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/B,KAAK,MAAM,WAAW,IAAI,oBAAoB,CAAC,MAAM,CAAC,EAAE,CAAC;QACvD,KAAK,MAAM,SAAS,IAAI,WAAW,CAAC,UAAU,EAAE,CAAC;YAC/C,IAAI,SAAS,CAAC,IAAI,KAAK,UAAU,IAAI,SAAS,CAAC,WAAW,KAAK,IAAI,EAAE,CAAC;gBACpE,oBAAoB,CAClB,WAAW,EACX,IAAI,EACJ,oBAAoB,CAClB,uBAAuB,EACvB,aAAa,WAAW,CAAC,IAAI,0CAA0C,EACvE,SAAS,CAAC,YAAY,CACvB,CACF,CAAC;YACJ,CAAC;YAED,IACE,SAAS,CAAC,IAAI,KAAK,OAAO;gBAC1B,sBAAsB,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAC3C,CAAC;gBACD,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC;gBACnE,MAAM,KAAK,GAAG,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;gBACjC,IAAI,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;oBAC/B,oBAAoB,CAClB,WAAW,EACX,IAAI,EACJ,oBAAoB,CAClB,uBAAuB,EACvB,cAAc,KAAK,gBAAgB,EACnC,SAAS,CACV,CACF,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,WAAW,CAAC;AACrB,CAAC,CAAC;AAEF,MAAM,oBAAoB,GAAG,CAC3B,KAAa,EACb,KAA0B,EACjB,EAAE;IACX,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC;IAE/B,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YACtB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAClB,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QACnC,IAAI,IAAI,CAAC,CAAC;QAEV,IAAI,IAAI,GAAG,OAAO,EAAE,CAAC;YACnB,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF,MAAM,uBAAuB,GAAa,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE;IACvD,MAAM,WAAW,GAAqB,EAAE,CAAC;IACzC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,SAAS,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAC/C,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;IACxC,MAAM,MAAM,GAAG,IAAI,GAAG,EAAuB,CAAC;IAE9C,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;QACzC,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC;QACrC,IAAI,QAAQ,CAAC,YAAY,EAAE,CAAC;YAC1B,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,YAAY,CAAC,WAAW,EAAE,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;IAED,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;QACzC,IAAI,CAAC,oBAAoB,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC;YACvC,SAAS;QACX,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC,SAAS,CAAC;QACrD,oBAAoB,CAClB,WAAW,EACX,IAAI,EACJ,oBAAoB,CAClB,uBAAuB,EACvB,aAAa,QAAQ,CAAC,IAAI,sCAAsC,EAChE,KAAK,CACN,CACF,CAAC;IACJ,CAAC;IAED,OAAO,WAAW,CAAC;AACrB,CAAC,CAAC;AAEF,MAAM,2BAA2B,GAAa,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE;IAC3D,MAAM,WAAW,GAAqB,EAAE,CAAC;IACzC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/B,KAAK,MAAM,WAAW,IAAI,oBAAoB,CAAC,MAAM,CAAC,EAAE,CAAC;QACvD,IAAI,CAAC,cAAc,CAAC,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC;YACxC,SAAS;QACX,CAAC;QAED,KAAK,MAAM,SAAS,IAAI,WAAW,CAAC,UAAU,EAAE,CAAC;YAC/C,IAAI,SAAS,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAC/B,SAAS;YACX,CAAC;YAED,IAAI,CAAC,qCAAqC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;gBAChE,SAAS;YACX,CAAC;YAED,oBAAoB,CAClB,WAAW,EACX,IAAI,EACJ,wBAAwB,CACtB,qBAAqB,EACrB,aAAa,WAAW,CAAC,IAAI,6CAA6C,EAC1E,WAAW,EACX,OAAO,CACR,CACF,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,WAAW,CAAC;AACrB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,QAAQ,GAAe;IAClC,iBAAiB;IACjB,sBAAsB;IACtB,eAAe;IACf,0BAA0B;IAC1B,wBAAwB;IACxB,uBAAuB;IACvB,uBAAuB;IACvB,2BAA2B;CAC5B,CAAC;AAEF,MAAM,CAAC,MAAM,yBAAyB,GAAG,CACvC,OAAgC,EACd,EAAE;IACpB,OAAO,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;AACnD,CAAC,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { BirdDiagnostic } from "@birdcc/core";
2
+ import { type BirdRule } from "./shared.js";
3
+ export declare const netRules: BirdRule[];
4
+ export declare const collectNetRuleDiagnostics: (context: Parameters<BirdRule>[0]) => BirdDiagnostic[];
5
+ //# sourceMappingURL=net.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"net.d.ts","sourceRoot":"","sources":["../../src/rules/net.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnD,OAAO,EAKL,KAAK,QAAQ,EACd,MAAM,aAAa,CAAC;AAsPrB,eAAO,MAAM,QAAQ,EAAE,QAAQ,EAAuC,CAAC;AAEvE,eAAO,MAAM,yBAAyB,GACpC,SAAS,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAC/B,cAAc,EAEhB,CAAC"}
@@ -0,0 +1,140 @@
1
+ import { isIP } from "node:net";
2
+ import { createRuleDiagnostic, filterAndFunctionDeclarations, protocolDeclarations, pushUniqueDiagnostic, } from "./shared.js";
3
+ const PREFIX_PATTERN_SOURCE = "([0-9A-Za-z:.]+\\/[^\\s,;{}[\\]]+)";
4
+ const extractPrefixes = (text) => {
5
+ const prefixes = [];
6
+ const prefixPattern = new RegExp(PREFIX_PATTERN_SOURCE, "g");
7
+ let matched = prefixPattern.exec(text);
8
+ while (matched) {
9
+ const raw = matched[1] ?? "";
10
+ const [address, lengthText] = raw.split("/");
11
+ if (!address || !lengthText) {
12
+ matched = prefixPattern.exec(text);
13
+ continue;
14
+ }
15
+ const normalizedLength = lengthText.trim();
16
+ const length = /^\d+$/.test(normalizedLength)
17
+ ? Number.parseInt(normalizedLength, 10)
18
+ : null;
19
+ prefixes.push({ address: address.trim(), length, raw });
20
+ matched = prefixPattern.exec(text);
21
+ }
22
+ return prefixes;
23
+ };
24
+ const statementText = (statement) => {
25
+ if (statement.kind === "expression") {
26
+ return statement.expressionText;
27
+ }
28
+ if (statement.kind === "other") {
29
+ return statement.text;
30
+ }
31
+ if (statement.kind === "if") {
32
+ return statement.conditionText ?? "";
33
+ }
34
+ if (statement.kind === "return") {
35
+ return statement.valueText ?? "";
36
+ }
37
+ if (statement.kind === "case") {
38
+ return statement.subjectText ?? "";
39
+ }
40
+ return "";
41
+ };
42
+ const analyzePrefix = (diagnostics, seen, prefix, range) => {
43
+ const family = isIP(prefix.address);
44
+ if (prefix.length === null || prefix.length < 0 || prefix.length > 128) {
45
+ pushUniqueDiagnostic(diagnostics, seen, createRuleDiagnostic("net/invalid-prefix-length", `Invalid prefix length in '${prefix.raw}'`, range));
46
+ return;
47
+ }
48
+ if (prefix.address.includes(".")) {
49
+ if (family !== 4) {
50
+ pushUniqueDiagnostic(diagnostics, seen, createRuleDiagnostic("net/invalid-ipv4-prefix", `Invalid IPv4 prefix '${prefix.raw}'`, range));
51
+ return;
52
+ }
53
+ if (prefix.length > 32) {
54
+ pushUniqueDiagnostic(diagnostics, seen, createRuleDiagnostic("net/max-prefix-length", `Invalid max prefix length ${prefix.length} for IPv4 prefix '${prefix.raw}'`, range));
55
+ }
56
+ return;
57
+ }
58
+ if (prefix.address.includes(":")) {
59
+ if (family !== 6) {
60
+ pushUniqueDiagnostic(diagnostics, seen, createRuleDiagnostic("net/invalid-ipv6-prefix", `Invalid IPv6 prefix '${prefix.raw}'`, range));
61
+ return;
62
+ }
63
+ if (prefix.length > 128) {
64
+ pushUniqueDiagnostic(diagnostics, seen, createRuleDiagnostic("net/max-prefix-length", `Invalid max prefix length ${prefix.length} for IPv6 prefix '${prefix.raw}'`, range));
65
+ }
66
+ return;
67
+ }
68
+ pushUniqueDiagnostic(diagnostics, seen, createRuleDiagnostic("net/invalid-ipv4-prefix", `Invalid IP prefix '${prefix.raw}'`, range));
69
+ };
70
+ const netPrefixRules = ({ parsed }) => {
71
+ const diagnostics = [];
72
+ const seen = new Set();
73
+ for (const declaration of filterAndFunctionDeclarations(parsed)) {
74
+ for (const statement of declaration.statements) {
75
+ const text = statementText(statement);
76
+ if (!text) {
77
+ continue;
78
+ }
79
+ for (const prefix of extractPrefixes(text)) {
80
+ analyzePrefix(diagnostics, seen, prefix, statement);
81
+ }
82
+ }
83
+ for (const match of declaration.matches) {
84
+ for (const prefix of extractPrefixes(match.right)) {
85
+ analyzePrefix(diagnostics, seen, prefix, match);
86
+ }
87
+ }
88
+ for (const literal of declaration.literals) {
89
+ if (literal.kind !== "prefix") {
90
+ continue;
91
+ }
92
+ for (const prefix of extractPrefixes(literal.value)) {
93
+ analyzePrefix(diagnostics, seen, prefix, literal);
94
+ }
95
+ }
96
+ }
97
+ return diagnostics;
98
+ };
99
+ const netMaxPrefixRule = ({ parsed }) => {
100
+ const diagnostics = [];
101
+ const seen = new Set();
102
+ for (const declaration of protocolDeclarations(parsed)) {
103
+ for (const statement of declaration.statements) {
104
+ if (statement.kind !== "channel") {
105
+ continue;
106
+ }
107
+ if (statement.channelType !== "ipv4" &&
108
+ statement.channelType !== "ipv6") {
109
+ continue;
110
+ }
111
+ const channelText = statement.entries
112
+ .filter((entry) => entry.kind === "other")
113
+ .map((entry) => entry.text)
114
+ .join(" ");
115
+ const matched = channelText.match(/\bmax\s+prefix\s+([^;\s]+)/i);
116
+ if (!matched) {
117
+ continue;
118
+ }
119
+ const token = (matched[1] ?? "").trim();
120
+ if (!/^\d+$/.test(token)) {
121
+ pushUniqueDiagnostic(diagnostics, seen, createRuleDiagnostic("net/invalid-prefix-length", `Invalid prefix length in 'max prefix ${token}'`, statement));
122
+ continue;
123
+ }
124
+ const length = Number.parseInt(token, 10);
125
+ if (Number.isNaN(length)) {
126
+ continue;
127
+ }
128
+ const maxAllowed = statement.channelType === "ipv4" ? 32 : 128;
129
+ if (length > maxAllowed) {
130
+ pushUniqueDiagnostic(diagnostics, seen, createRuleDiagnostic("net/max-prefix-length", `Invalid max prefix length ${length} for ${statement.channelType}`, statement));
131
+ }
132
+ }
133
+ }
134
+ return diagnostics;
135
+ };
136
+ export const netRules = [netPrefixRules, netMaxPrefixRule];
137
+ export const collectNetRuleDiagnostics = (context) => {
138
+ return netRules.flatMap((rule) => rule(context));
139
+ };
140
+ //# sourceMappingURL=net.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"net.js","sourceRoot":"","sources":["../../src/rules/net.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { BirdDiagnostic } from "@birdcc/core";
2
+ import type { ParsedBirdDocument } from "@birdcc/parser";
3
+ export declare const normalizeBaseDiagnostics: (parsed: ParsedBirdDocument, coreDiagnostics: BirdDiagnostic[], options?: {
4
+ uri?: string;
5
+ }) => BirdDiagnostic[];
6
+ //# sourceMappingURL=normalize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../src/rules/normalize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAkEzD,eAAO,MAAM,wBAAwB,GACnC,QAAQ,kBAAkB,EAC1B,iBAAiB,cAAc,EAAE,EACjC,UAAS;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAO,KAC7B,cAAc,EAkBhB,CAAC"}
@@ -0,0 +1,65 @@
1
+ import { isRuleCode, RULE_SEVERITY } from "./catalog.js";
2
+ const CORE_CODE_MAP = {
3
+ "semantic/duplicate-definition": "sym/duplicate",
4
+ "semantic/undefined-reference": "sym/undefined",
5
+ "semantic/circular-template": "cfg/circular-template",
6
+ "type/mismatch": "type/mismatch",
7
+ "type/undefined-variable": "sym/variable-scope",
8
+ "type/unknown-expression": "cfg/incompatible-type",
9
+ "semantic/invalid-router-id": "cfg/incompatible-type",
10
+ "semantic/invalid-neighbor-address": "cfg/incompatible-type",
11
+ "semantic/invalid-cidr": "net/invalid-prefix-length",
12
+ "semantic/missing-include": "sym/undefined",
13
+ };
14
+ const PARSER_TO_CFG_SYNTAX = new Set([
15
+ "syntax/missing-semicolon",
16
+ "syntax/unbalanced-brace",
17
+ "parser/syntax-error",
18
+ "parser/missing-symbol",
19
+ "parser/runtime-error",
20
+ ]);
21
+ const normalizeCode = (code) => {
22
+ if (isRuleCode(code)) {
23
+ return code;
24
+ }
25
+ if (code in CORE_CODE_MAP) {
26
+ return CORE_CODE_MAP[code];
27
+ }
28
+ if (PARSER_TO_CFG_SYNTAX.has(code)) {
29
+ return "cfg/syntax-error";
30
+ }
31
+ return "cfg/incompatible-type";
32
+ };
33
+ const normalizeMessage = (code, mappedCode, message) => {
34
+ if (code === mappedCode) {
35
+ return message;
36
+ }
37
+ return `[${code}] ${message}`;
38
+ };
39
+ const toNormalizedDiagnostic = (diagnostic, fallbackUri) => {
40
+ const mappedCode = normalizeCode(diagnostic.code);
41
+ return {
42
+ ...diagnostic,
43
+ code: mappedCode,
44
+ severity: RULE_SEVERITY[mappedCode],
45
+ message: normalizeMessage(diagnostic.code, mappedCode, diagnostic.message),
46
+ uri: diagnostic.uri ?? fallbackUri,
47
+ };
48
+ };
49
+ export const normalizeBaseDiagnostics = (parsed, coreDiagnostics, options = {}) => {
50
+ const parserDiagnostics = parsed.issues.map((issue) => ({
51
+ code: issue.code,
52
+ message: issue.message,
53
+ severity: "error",
54
+ source: "parser",
55
+ uri: options.uri,
56
+ range: {
57
+ line: issue.line,
58
+ column: issue.column,
59
+ endLine: issue.endLine,
60
+ endColumn: issue.endColumn,
61
+ },
62
+ }));
63
+ return [...parserDiagnostics, ...coreDiagnostics].map((diagnostic) => toNormalizedDiagnostic(diagnostic, options.uri));
64
+ };
65
+ //# sourceMappingURL=normalize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalize.js","sourceRoot":"","sources":["../../src/rules/normalize.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAiB,aAAa,EAAE,MAAM,cAAc,CAAC;AAExE,MAAM,aAAa,GAA6B;IAC9C,+BAA+B,EAAE,eAAe;IAChD,8BAA8B,EAAE,eAAe;IAC/C,4BAA4B,EAAE,uBAAuB;IACrD,eAAe,EAAE,eAAe;IAChC,yBAAyB,EAAE,oBAAoB;IAC/C,yBAAyB,EAAE,uBAAuB;IAClD,4BAA4B,EAAE,uBAAuB;IACrD,mCAAmC,EAAE,uBAAuB;IAC5D,uBAAuB,EAAE,2BAA2B;IACpD,0BAA0B,EAAE,eAAe;CAC5C,CAAC;AAEF,MAAM,oBAAoB,GAAG,IAAI,GAAG,CAAC;IACnC,0BAA0B;IAC1B,yBAAyB;IACzB,qBAAqB;IACrB,uBAAuB;IACvB,sBAAsB;CACvB,CAAC,CAAC;AAEH,MAAM,aAAa,GAAG,CAAC,IAAY,EAAY,EAAE;IAC/C,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,IAAI,IAAI,aAAa,EAAE,CAAC;QAC1B,OAAO,aAAa,CAAC,IAAI,CAAa,CAAC;IACzC,CAAC;IAED,IAAI,oBAAoB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,OAAO,kBAAkB,CAAC;IAC5B,CAAC;IAED,OAAO,uBAAuB,CAAC;AACjC,CAAC,CAAC;AAEF,MAAM,gBAAgB,GAAG,CACvB,IAAY,EACZ,UAAoB,EACpB,OAAe,EACP,EAAE;IACV,IAAI,IAAI,KAAK,UAAU,EAAE,CAAC;QACxB,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,OAAO,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;AAChC,CAAC,CAAC;AAEF,MAAM,sBAAsB,GAAG,CAC7B,UAA0B,EAC1B,WAAoB,EACJ,EAAE;IAClB,MAAM,UAAU,GAAG,aAAa,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IAClD,OAAO;QACL,GAAG,UAAU;QACb,IAAI,EAAE,UAAU;QAChB,QAAQ,EAAE,aAAa,CAAC,UAAU,CAAC;QACnC,OAAO,EAAE,gBAAgB,CAAC,UAAU,CAAC,IAAI,EAAE,UAAU,EAAE,UAAU,CAAC,OAAO,CAAC;QAC1E,GAAG,EAAE,UAAU,CAAC,GAAG,IAAI,WAAW;KACnC,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,wBAAwB,GAAG,CACtC,MAA0B,EAC1B,eAAiC,EACjC,UAA4B,EAAE,EACZ,EAAE;IACpB,MAAM,iBAAiB,GAAqB,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACxE,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,QAAQ,EAAE,OAAO;QACjB,MAAM,EAAE,QAAQ;QAChB,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,KAAK,EAAE;YACL,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,SAAS,EAAE,KAAK,CAAC,SAAS;SAC3B;KACF,CAAC,CAAC,CAAC;IAEJ,OAAO,CAAC,GAAG,iBAAiB,EAAE,GAAG,eAAe,CAAC,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CACnE,sBAAsB,CAAC,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,CAChD,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { BirdDiagnostic } from "@birdcc/core";
2
+ import { type BirdRule } from "./shared.js";
3
+ export declare const ospfRules: BirdRule[];
4
+ export declare const collectOspfRuleDiagnostics: (context: Parameters<BirdRule>[0]) => BirdDiagnostic[];
5
+ //# sourceMappingURL=ospf.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ospf.d.ts","sourceRoot":"","sources":["../../src/rules/ospf.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnD,OAAO,EAML,KAAK,QAAQ,EACd,MAAM,aAAa,CAAC;AAwMrB,eAAO,MAAM,SAAS,EAAE,QAAQ,EAK/B,CAAC;AAEF,eAAO,MAAM,0BAA0B,GACrC,SAAS,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAC/B,cAAc,EAEhB,CAAC"}