@takodotid/circuit 0.26.0 → 0.26.1
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/README.md +4 -4
- package/dist/types/schema/common.d.ts +1 -1
- package/dist/types/schema/device.d.ts +1 -1
- package/dist/types/schema/firewall.d.ts +3 -3
- package/dist/types/schema/interfaces.d.ts +13 -13
- package/dist/types/schema/policy.d.ts +3 -3
- package/dist/types/schema/routing.d.ts +7 -7
- package/dist/types/schema/system.d.ts +7 -7
- package/package.json +1 -1
- package/src/adapters/devices/fortios/TRAPS.md +8 -8
- package/src/adapters/devices/junos/TRAPS.md +2 -2
- package/src/adapters/devices/raisecom-ros/TRAPS.md +2 -2
- package/src/adapters/devices/routeros/TRAPS.md +5 -5
- package/src/adapters/devices/vrp/TRAPS.md +4 -4
- package/src/schema/common.ts +1 -1
- package/src/schema/device.ts +1 -1
- package/src/schema/firewall.ts +3 -3
- package/src/schema/interfaces.ts +13 -13
- package/src/schema/policy.ts +3 -3
- package/src/schema/routing.ts +7 -7
- package/src/schema/system.ts +7 -7
package/README.md
CHANGED
|
@@ -11,13 +11,13 @@ Documentation: [circuit.tako.id](https://circuit.tako.id)
|
|
|
11
11
|
|
|
12
12
|
- **One file per device.** VLANs, ports, addresses, routing, firewall, users and services, written in TypeScript. Your editor checks every name you refer to as you type.
|
|
13
13
|
- **The same words for every vendor.** MikroTik RouterOS 7, Huawei VRP, Raisecom ROS, Juniper Junos and Fortinet FortiOS each get their own commands. What a device cannot do is an error before anything is sent.
|
|
14
|
-
- **The file is the whole truth.** A port, user or service the file does not mention is removed or turned off, so nothing set by hand
|
|
14
|
+
- **The file is the whole truth.** A port, user or service the file does not mention is removed or turned off, so nothing set by hand stays behind.
|
|
15
15
|
- **See every change first.** `diff` shows it offline, `apply` plans it against the live device, and nothing is sent without `--confirm`. On RouterOS, Junos and FortiOS, a change undoes itself if Circuit cannot log in again afterwards.
|
|
16
16
|
- **History in git.** Each device's last snapshot is kept in `.circuit/state/`, so the repository's history is the network's history.
|
|
17
17
|
- **Rules of your own.** Checks run on every change, and presets give ready-made filters, BGP policies and checks.
|
|
18
18
|
- **Secrets stay out of the repository.** They come from `.env` or 1Password, and never appear in a plan or a snapshot.
|
|
19
|
-
- **See the network.** Circuit Studio, started with `circuit studio`, draws the cables, VLANs, addresses, BGP sessions, OSPF neighbors and tunnels in your browser, and marks what is broken or differs from the device. Its tables list everything each device
|
|
20
|
-
- **Keeps the rest
|
|
19
|
+
- **See the network.** Circuit Studio, started with `circuit studio`, draws the cables, VLANs, addresses, BGP sessions, OSPF neighbors and tunnels in your browser, and marks what is broken or differs from the device. Its tables list everything each device has, for anyone who does not read TypeScript, and it can run on a server for the whole team. `circuit graph` prints the drawing as Mermaid, DOT or JSON.
|
|
20
|
+
- **Keeps the rest up to date.** Prefix lists fetched from a registry, your PeeringDB record, devices in LibreNMS, targets for Prometheus, WireGuard client configs, and your BGP communities for a looking glass.
|
|
21
21
|
- **Safe with AI agents.** Every project gets an `AGENTS.md` that tells an agent what it may run, and the last step stays yours.
|
|
22
22
|
|
|
23
23
|
<picture>
|
|
@@ -27,7 +27,7 @@ Documentation: [circuit.tako.id](https://circuit.tako.id)
|
|
|
27
27
|
|
|
28
28
|
## Circuit Academy
|
|
29
29
|
|
|
30
|
-
New to networking? [Circuit Academy](https://circuit.tako.id/academy/) teaches it from the very start, in lessons you try in the browser rather than only read: packets, addresses, switches and routers first, then VLANs, DHCP, NAT and firewalls written down in Circuit,
|
|
30
|
+
New to networking? [Circuit Academy](https://circuit.tako.id/academy/) teaches it from the very start, in lessons you try in the browser rather than only read: packets, addresses, switches and routers first, then VLANs, DHCP, NAT and firewalls written down in Circuit, BGP and an edge router of your own, and on to running a provider network. A certification is coming.
|
|
31
31
|
|
|
32
32
|
<picture>
|
|
33
33
|
<source media="(prefers-color-scheme: dark)" srcset="docs/public/screenshots/academy-dark.png">
|
|
@@ -7,7 +7,7 @@ export type Secret = {
|
|
|
7
7
|
/** Name of the value in the environment or in `.env`. */
|
|
8
8
|
readonly secret: string;
|
|
9
9
|
} | {
|
|
10
|
-
/** Path of
|
|
10
|
+
/** Path of the file with the value, relative to the config file. */
|
|
11
11
|
readonly secret_file: string;
|
|
12
12
|
};
|
|
13
13
|
/** An address without a length, IPv4 or IPv6, for example `10.0.0.1`. */
|
|
@@ -26,7 +26,7 @@ export type Vrf = {
|
|
|
26
26
|
export type Device<Pl extends string = string, M extends string = string, N extends string = string, V extends string = string, I extends string = string, P extends string = string, S extends string = string, G extends string = string, A extends string = string, AS extends string = string, U extends string = string, F extends string = string, C extends string = string> = {
|
|
27
27
|
/** Hostname. */
|
|
28
28
|
name: string;
|
|
29
|
-
/** Operating system
|
|
29
|
+
/** Operating system. It decides which adapter renders and applies the device. */
|
|
30
30
|
platform: Pl;
|
|
31
31
|
/** Hardware model. Decides which port names exist. */
|
|
32
32
|
model: M;
|
|
@@ -12,7 +12,7 @@ export type PortRange = {
|
|
|
12
12
|
export type Ports = number | PortRange | readonly (number | PortRange)[];
|
|
13
13
|
/** A TCP header flag. */
|
|
14
14
|
export type TcpFlag = "fin" | "syn" | "rst" | "psh" | "ack" | "urg";
|
|
15
|
-
/** Conditions on a packet. All must
|
|
15
|
+
/** Conditions on a packet. All must be true. A rule with addresses of one family applies to that family only. */
|
|
16
16
|
export type FilterMatch<I extends string, AS extends string> = {
|
|
17
17
|
/** Only packets of this family. */
|
|
18
18
|
family?: Family;
|
|
@@ -50,7 +50,7 @@ export type FilterRule<I extends string, AS extends string> = {
|
|
|
50
50
|
match?: FilterMatch<I, AS>;
|
|
51
51
|
/** What happens to a matching packet. `reject` answers the sender, `drop` does not. */
|
|
52
52
|
action: "accept" | "drop" | "reject";
|
|
53
|
-
/**
|
|
53
|
+
/** Send the rest of an accepted flow through the fast path, skipping the remaining rules. */
|
|
54
54
|
offload?: true;
|
|
55
55
|
};
|
|
56
56
|
/** Rules evaluated in order, first match wins, then `default`. */
|
|
@@ -117,7 +117,7 @@ export type AclRule<V extends string> = {
|
|
|
117
117
|
src_port?: Ports;
|
|
118
118
|
/** Destination port, or any of several. */
|
|
119
119
|
dst_port?: Ports;
|
|
120
|
-
/**
|
|
120
|
+
/** In this VLAN. */
|
|
121
121
|
vlan?: V;
|
|
122
122
|
};
|
|
123
123
|
/** What happens to a matching packet. */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Address, IP, Prefix, Secret } from "./common";
|
|
2
|
-
/** A VLAN.
|
|
2
|
+
/** A VLAN. Its key in `vlans` is its name. */
|
|
3
3
|
export type Vlan = {
|
|
4
|
-
/** The number
|
|
4
|
+
/** The VLAN's number on the wire, 1 to 4094. */
|
|
5
5
|
id: number;
|
|
6
6
|
/** What the VLAN is for. */
|
|
7
7
|
description?: string;
|
|
@@ -25,7 +25,7 @@ export type Vrrp = {
|
|
|
25
25
|
/** Seconds between advertisements. 1 when absent. */
|
|
26
26
|
interval?: number;
|
|
27
27
|
};
|
|
28
|
-
/** Layer 3 settings shared by every interface that can
|
|
28
|
+
/** Layer 3 settings shared by every interface that can have an address. */
|
|
29
29
|
export type Routed<F extends string> = {
|
|
30
30
|
/** Addresses with their length. Use `{ address, peer }` for a point-to-point address whose far end is outside its own prefix. */
|
|
31
31
|
addresses?: readonly (Address | {
|
|
@@ -36,7 +36,7 @@ export type Routed<F extends string> = {
|
|
|
36
36
|
ipv6_ra?: boolean;
|
|
37
37
|
/** Overrides the device's `hardware_offload` for traffic routed through this interface. Software forwarding is what makes the firewall apply. */
|
|
38
38
|
hardware_offload?: boolean;
|
|
39
|
-
/** Virtual router addresses
|
|
39
|
+
/** Virtual router addresses on this interface. */
|
|
40
40
|
vrrp?: readonly Vrrp[];
|
|
41
41
|
/** The VRF this interface routes in. The default table when absent. */
|
|
42
42
|
vrf?: F;
|
|
@@ -63,11 +63,11 @@ export type PortStp = {
|
|
|
63
63
|
};
|
|
64
64
|
/** Layer 2 membership. A port or LAG with none of these is routed. */
|
|
65
65
|
export type Switched<V extends string> = {
|
|
66
|
-
/**
|
|
66
|
+
/** The one VLAN this port or LAG is in, untagged. */
|
|
67
67
|
access_vlan?: V;
|
|
68
|
-
/**
|
|
68
|
+
/** The VLANs this port or LAG carries, tagged. */
|
|
69
69
|
trunk_vlans?: readonly V[];
|
|
70
|
-
/** Untagged frames on a trunk
|
|
70
|
+
/** Untagged frames on a trunk are in this VLAN. Only with `trunk_vlans`. */
|
|
71
71
|
native_vlan?: V;
|
|
72
72
|
/** Overrides the device's `stp` for this port. `false` stops it sending or acting on BPDUs. */
|
|
73
73
|
stp?: boolean | PortStp;
|
|
@@ -97,7 +97,7 @@ export type Port<V extends string, A extends string, L extends string, F extends
|
|
|
97
97
|
lldp?: boolean;
|
|
98
98
|
/** Hardware ACL applied to traffic arriving on this port. */
|
|
99
99
|
acl?: A;
|
|
100
|
-
/**
|
|
100
|
+
/** The LAG this port is in. Every other setting goes on the LAG. */
|
|
101
101
|
lag?: L;
|
|
102
102
|
/** Another of our devices at the other end of the cable. */
|
|
103
103
|
link?: Link;
|
|
@@ -112,19 +112,19 @@ type Base<F extends string> = Routed<F> & {
|
|
|
112
112
|
/** A layer 3 interface on a VLAN. */
|
|
113
113
|
export type VlanInterface<V extends string, F extends string> = Base<F> & {
|
|
114
114
|
type: "vlan";
|
|
115
|
-
/** The VLAN it
|
|
115
|
+
/** The VLAN it is on. */
|
|
116
116
|
vlan: V;
|
|
117
117
|
};
|
|
118
|
-
/** An interface that is always up and
|
|
118
|
+
/** An interface that is always up and is on no link, for addresses that must not depend on one. */
|
|
119
119
|
export type Loopback<F extends string> = Base<F> & {
|
|
120
120
|
type: "loopback";
|
|
121
121
|
};
|
|
122
|
-
/** A link aggregation.
|
|
122
|
+
/** A link aggregation. Each member port points to it with `lag`. */
|
|
123
123
|
export type Lag<V extends string, F extends string> = Base<F> & Switched<V> & {
|
|
124
124
|
type: "lag";
|
|
125
|
-
/** LACP negotiates membership with the far end; static
|
|
125
|
+
/** LACP negotiates membership with the far end; `static` joins the ports without asking. LACP when absent. */
|
|
126
126
|
mode?: "lacp" | "static";
|
|
127
|
-
/** Number on platforms
|
|
127
|
+
/** Number, on platforms where a LAG has a number instead of a name. Its position among the device's LAGs when absent. */
|
|
128
128
|
id?: number;
|
|
129
129
|
};
|
|
130
130
|
/** A GRE tunnel. */
|
|
@@ -15,7 +15,7 @@ export type PrefixSet = {
|
|
|
15
15
|
family: Family;
|
|
16
16
|
};
|
|
17
17
|
};
|
|
18
|
-
/** Conditions on a route. All must
|
|
18
|
+
/** Conditions on a route. All must be true. An empty match is true for every route. */
|
|
19
19
|
export type Match<S extends string> = {
|
|
20
20
|
/** Only routes of this family. */
|
|
21
21
|
family?: Family;
|
|
@@ -35,9 +35,9 @@ export type Match<S extends string> = {
|
|
|
35
35
|
};
|
|
36
36
|
/** The route's origin validation state. */
|
|
37
37
|
rpki?: "valid" | "invalid" | "not-found";
|
|
38
|
-
/**
|
|
38
|
+
/** Has this standard community, `asn:value`. */
|
|
39
39
|
community?: string;
|
|
40
|
-
/**
|
|
40
|
+
/** Has this large community, `asn:function:parameter`. */
|
|
41
41
|
large_community?: string;
|
|
42
42
|
};
|
|
43
43
|
/** Changes to a route. In community lists to remove, `*` stands for any value of a field, as in `64500:*:*`. */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Family, IP, Prefix, Secret } from "./common";
|
|
2
|
-
/** A route the device
|
|
2
|
+
/** A route the device has without learning it. */
|
|
3
3
|
export type StaticRoute<I extends string, F extends string> = {
|
|
4
4
|
/** Destination. */
|
|
5
5
|
prefix: Prefix;
|
|
@@ -11,7 +11,7 @@ export type StaticRoute<I extends string, F extends string> = {
|
|
|
11
11
|
blackhole?: true;
|
|
12
12
|
/** Preference against other routes to the same prefix. Lower wins. 1 when absent. */
|
|
13
13
|
distance?: number;
|
|
14
|
-
/** The VRF the route
|
|
14
|
+
/** The VRF the route is in. The default table when absent. */
|
|
15
15
|
vrf?: F;
|
|
16
16
|
/** Why the route exists. */
|
|
17
17
|
description?: string;
|
|
@@ -20,7 +20,7 @@ export type StaticRoute<I extends string, F extends string> = {
|
|
|
20
20
|
* What a BGP neighbor is to us, with the roles RFC 9234 defines: `provider`, a transit we buy from; `customer`, one we sell transit to; `peer`, one we exchange our own routes with; `rs`, an exchange's route server; `rs-client`, a network using our route server.
|
|
21
21
|
*/
|
|
22
22
|
export type BgpRole = "provider" | "customer" | "peer" | "rs" | "rs-client";
|
|
23
|
-
/** Settings a BGP neighbor can
|
|
23
|
+
/** Settings a BGP neighbor can set itself or take from its group. */
|
|
24
24
|
export type NeighborSettings<P extends string> = {
|
|
25
25
|
/** The neighbor's AS. Our own AS makes the session internal. */
|
|
26
26
|
remote_as?: number;
|
|
@@ -32,7 +32,7 @@ export type NeighborSettings<P extends string> = {
|
|
|
32
32
|
import?: P;
|
|
33
33
|
/** Policy for routes announced. Nothing is announced when absent. */
|
|
34
34
|
export?: P;
|
|
35
|
-
/** What the neighbor is to us, such as `provider` for a transit. Both sides then reject a route leak,
|
|
35
|
+
/** What the neighbor is to us, such as `provider` for a transit. Both sides then reject a route leak, as RFC 9234 describes. */
|
|
36
36
|
role?: BgpRole;
|
|
37
37
|
/** The neighbor is more than one hop away. */
|
|
38
38
|
multihop?: boolean;
|
|
@@ -51,11 +51,11 @@ export type NeighborSettings<P extends string> = {
|
|
|
51
51
|
/** Detect a dead link in under a second with BFD. */
|
|
52
52
|
bfd?: boolean;
|
|
53
53
|
};
|
|
54
|
-
/** One BGP session. Settings it does not
|
|
54
|
+
/** One BGP session. Settings it does not set come from its group. */
|
|
55
55
|
export type Neighbor<P extends string, G extends string> = NeighborSettings<P> & {
|
|
56
56
|
/** The neighbor's address. */
|
|
57
57
|
address: IP;
|
|
58
|
-
/**
|
|
58
|
+
/** The group this neighbor takes a setting from when it does not set that setting itself. */
|
|
59
59
|
group?: NoInfer<G>;
|
|
60
60
|
};
|
|
61
61
|
/** BGP on this device. */
|
|
@@ -104,7 +104,7 @@ export type Ospf<I extends string> = {
|
|
|
104
104
|
export type Routing<P extends string, G extends string, I extends string, F extends string> = {
|
|
105
105
|
/** Identifies this router to its neighbors. */
|
|
106
106
|
router_id?: IP;
|
|
107
|
-
/** Routes the device
|
|
107
|
+
/** Routes the device has without learning them. */
|
|
108
108
|
static?: readonly StaticRoute<I, F>[];
|
|
109
109
|
/** BGP sessions and what they exchange. */
|
|
110
110
|
bgp?: Bgp<P, G>;
|
|
@@ -12,7 +12,7 @@ export type System = {
|
|
|
12
12
|
/** Answer queries from others. Off when absent. */
|
|
13
13
|
serve?: boolean;
|
|
14
14
|
};
|
|
15
|
-
/**
|
|
15
|
+
/** How the device keeps time. */
|
|
16
16
|
ntp?: {
|
|
17
17
|
/** Time sources, by address or name. */
|
|
18
18
|
servers: readonly string[];
|
|
@@ -82,7 +82,7 @@ export type SnmpUser = {
|
|
|
82
82
|
};
|
|
83
83
|
/** How the device is reached and managed. */
|
|
84
84
|
export type Management<I extends string, C extends string> = {
|
|
85
|
-
/** Sources allowed to every service that does not
|
|
85
|
+
/** Sources allowed to every service that does not set its own. */
|
|
86
86
|
allow?: readonly Prefix[];
|
|
87
87
|
/** Secure shell. */
|
|
88
88
|
ssh?: Service & {
|
|
@@ -139,11 +139,11 @@ export type DhcpServer<I extends string> = {
|
|
|
139
139
|
interface: I;
|
|
140
140
|
/** The network it serves. */
|
|
141
141
|
network: Prefix;
|
|
142
|
-
/** Default gateway
|
|
142
|
+
/** Default gateway given to clients. */
|
|
143
143
|
gateway: IP;
|
|
144
|
-
/** Resolvers
|
|
144
|
+
/** Resolvers given to clients. */
|
|
145
145
|
dns?: readonly IP[];
|
|
146
|
-
/** First and last address
|
|
146
|
+
/** First and last address given to clients. */
|
|
147
147
|
pool: readonly [IP, IP];
|
|
148
148
|
/** Seconds a lease lasts. */
|
|
149
149
|
lease_time?: number;
|
|
@@ -164,9 +164,9 @@ export type DhcpRelay<I extends string> = {
|
|
|
164
164
|
};
|
|
165
165
|
/** A certificate the device presents or trusts. */
|
|
166
166
|
export type Certificate = {
|
|
167
|
-
/** The certificate, PEM. Public, so it
|
|
167
|
+
/** The certificate, PEM. Public, so it is kept in the repository. */
|
|
168
168
|
certificate: string;
|
|
169
|
-
/** Its private key: a PEM file through `secretFile`, or PEM base64-encoded as one line through `secret`. A certificate only
|
|
169
|
+
/** Its private key: a PEM file through `secretFile`, or PEM base64-encoded as one line through `secret`. A certificate the device only trusts, such as a CA, has none. */
|
|
170
170
|
private_key?: Secret;
|
|
171
171
|
};
|
|
172
172
|
/** Export flow records or packet samples to collectors. */
|
package/package.json
CHANGED
|
@@ -5,32 +5,32 @@ Behaviour that looks like something else. Each one has been hit on a FortiGate 3
|
|
|
5
5
|
- A change applies at `next` or `end`, and with `cfg-save automatic`, the factory setting, it is saved at once. `abort` discards the changes of the one object being edited, and only there: inside a table it is `Unknown action 0`, and the entries already left with `next` are applied.
|
|
6
6
|
- `cfg-save revert` keeps changes running but unsaved, and `cfg-revert-timeout` seconds after a change the device announces `System will reload` and reloads its saved configuration. The reload restarts the configuration, not the hardware, and takes about two minutes. `execute cfg reload` does the same at once, without asking, and says `no config to be reloaded` when nothing is unsaved. `execute cfg save` saves; setting `cfg-save automatic` again saves too.
|
|
7
7
|
- `cfg-save revert` set while saving is automatic is saved itself. After a reload the device is still in revert mode, and from then on every change made by hand is undone after the timeout until someone saves it or sets `cfg-save automatic`. Circuit sets it back at the end of every apply.
|
|
8
|
-
- `execute config-transaction start N` opens a candidate that `commit` applies and `abort` discards, but Circuit does not use it on 6.2.2. Inside one, deleting an entry does not release what its lists
|
|
8
|
+
- `execute config-transaction start N` opens a candidate that `commit` applies and `abort` discards, but Circuit does not use it on 6.2.2. Inside one, deleting an entry does not release what its lists point to, so deleting a policy and then the address it used is refused: `The entry is used by other 1 entries`. A transaction whose session is cut off keeps every object it touched locked until its N minutes run out: `Can not config the object since it's being configured by another transaction`. Editing a `firewall policy6` entry after `unset central-nat` ends the session at `edit`. Deleting the user you are logged in as ends the session with `cmdb_txn_cache_data ... failed` and breaks every later transaction until the device restarts. `show` prints a new static route or policy with the comment of the last new one, which the commit corrects. OSPF's `config redistribute` is refused, `config child object 'redistribute' is not handled in transaction`, and a certificate added in one cannot be used by name until the commit. None of these happen outside a transaction.
|
|
9
9
|
- The CLI pages long output with `--More--`, and erases the prompt with spaces and a carriage return once it is answered.
|
|
10
10
|
- A `?` typed anywhere shows help at once and is never sent. Ctrl-V before it types it literally.
|
|
11
11
|
- The idle timeout, `admintimeout`, is 5 minutes by default; the session then returns to `login:`.
|
|
12
12
|
- With `pre-login-banner` on, the console shows the banner and waits on `(Press 'a' to accept):` before `login:`. Circuit answers `a`.
|
|
13
13
|
- `grep` after a pipe takes no `-E`, and a command ending in `| grep` reports `Command fail. Return code -27` after printing its matches.
|
|
14
14
|
- `show` prints a setting only when it differs from its default, and prints keys in its own order, not the order they were set. A new aggregate is given `device-identification enable` and `lldp-transmission enable`, a new VLAN interface `device-identification enable` and `role lan`, without being asked. Circuit unsets them.
|
|
15
|
-
- A port joins an aggregate only while nothing
|
|
15
|
+
- A port joins an aggregate only while nothing points to it, such as a static route, `entry not found in datasource`, and its speed cannot change while it is in one, not even back to `auto`: `Interface speed cannot be set for aggregated interfaces`. Circuit frees ports first: what points to a port that joins is deleted and created again after, a port whose speed changes leaves its aggregate and joins again, and an aggregate that goes, or is left with no port, goes before anything else with what points to it.
|
|
16
16
|
- `unset secondary-IP` hides the list of secondary addresses and drops it. NTP's `unset type` hides its servers but keeps them: `set type custom` brings them back. NTP refuses to delete its last server while `ntpsync` is on, and to empty the interfaces it serves on while `server-mode` is on, `There aren't any interfaces with NTP server enabled`; `unset server-mode` hides that list and lets go of the interfaces in it. The plan deletes a nested list before the setting that hides it, except `ntpsync`, which goes first.
|
|
17
|
-
- A DHCP server prints `dns-server1` only while `dns-service` is `specify`, the default, which `show` does not print. The factory server on `mgmt1` uses `default`, so the render
|
|
17
|
+
- A DHCP server prints `dns-server1` only while `dns-service` is `specify`, the default, which `show` does not print. The factory server on `mgmt1` uses `default`, so the render writes `specify` before its resolvers.
|
|
18
18
|
- The timezone is a number of the platform's own, such as `53` for Jakarta, Bangkok and Hanoi. The default is `00`, Eniwetok, at UTC+12; UTC is `80`.
|
|
19
19
|
- Global `alias` is set again at every start, whatever was saved.
|
|
20
20
|
- `log memory setting` prints its `status` whether on or off, and `unset status` turns memory logging on.
|
|
21
|
-
- Two interfaces that are up cannot
|
|
21
|
+
- Two interfaces that are up cannot have overlapping subnets, `Subnets overlap between ...`, so an address moving from one to another must leave the first before it joins the second.
|
|
22
22
|
- A static route identical to another is refused, `Duplicated entry`. An IPv4 route's destination is not printed when it is the default route; neither is IPv6's.
|
|
23
|
-
- A deny policy is given `logtraffic disable`, and its action is not printed, since deny is the default. `send-deny-packet` exists only while a policy denies: set before `action deny` or unset after `action accept`, it is `command parse error`.
|
|
24
|
-
- `show` prints `unset` in two places: an ICMP service's `unset icmptype`, and a prefix list rule's `unset ge` and `unset le` for a bound it does not
|
|
23
|
+
- A deny policy is given `logtraffic disable`, and its action is not printed, since deny is the default. `send-deny-packet` exists only while a policy denies: set before `action deny` or unset after `action accept`, it is `command parse error`. So the render writes `action deny` before `send-deny-packet`, and a plan removes the settings that go before it sets the ones that come: `send-deny-packet` is unset while the policy still denies, and set only once it does.
|
|
24
|
+
- `show` prints `unset` in two places: an ICMP service's `unset icmptype`, and a prefix list rule's `unset ge` and `unset le` for a bound it does not have.
|
|
25
25
|
- An SNMPv3 user authenticates with MD5 or SHA1 only, and has no list of sources: only a community has hosts. Circuit decides who reaches every service with local-in policies instead.
|
|
26
26
|
- The console ignores a user's trusted hosts.
|
|
27
27
|
- A tunnel's interface takes an IPv4 address only as a host, with the far end in `remote-ip`: `set ip 10.0.0.1 255.255.255.252` on one is dropped without a word.
|
|
28
|
-
- A GRE or VXLAN tunnel creates an interface of its own, named after it, which goes when the tunnel goes. VXLAN has no local address: it leaves from the address of the interface it
|
|
28
|
+
- A GRE or VXLAN tunnel creates an interface of its own, named after it, which goes when the tunnel goes. VXLAN has no local address: it leaves from the address of the interface it points to.
|
|
29
29
|
- A static route has no VRF of its own. It lands in the VRF of the interface it leaves through, as `get router info routing-table all` shows, so a blackhole route cannot go in a VRF. OSPF and BGP have no VRF setting.
|
|
30
30
|
- The stateless ACL, `firewall acl` and `acl6`, only drops: it has no action.
|
|
31
31
|
- A route map stops at the first rule that matches, with no way to go on to the next, and its rules permit unless told to deny.
|
|
32
32
|
- `show vpn certificate local` prints a certificate without its text or key. `show full-configuration` prints both, the key encrypted.
|
|
33
|
-
-
|
|
33
|
+
- The device answers a private key it cannot read with `Invalid private key, password may be required`, with no `Command fail`, and the session goes on. A key whose lines end in CR LF gets the same answer, because the CLI takes each CR as a line of its own. The certificate fails only at `end`: `Attribute 'private-key' MUST be set`.
|
|
34
34
|
- A GRE or VXLAN interface takes no flow sampler, and says so without `Command fail`: `Netflow sampler isn't supported on Tunnel interface..`, and the same for sFlow and for VXLAN.
|
|
35
35
|
- A port in an aggregate has no `icmp-send-redirect`, `command parse error`, and loses it when it joins one.
|
|
36
36
|
- `purge` empties a table after asking `(y/n)`.
|
|
@@ -17,10 +17,10 @@ Behaviour that looks like something else. Each one has been hit on a QFX5100-48S
|
|
|
17
17
|
- An SNMP community prints in clear, and its value is also its name, so a new value is a second community. A new value is sent after the old communities are deleted, each by its name, which Circuit looks up during the apply and never prints.
|
|
18
18
|
- A firewall filter name is unique across families. The filter guarding the device's services is `circuit-services` for IPv4 and `circuit-services-v6` for IPv6.
|
|
19
19
|
- A VLAN interface's MTU above what its ports carry commits with only a warning, `mtu 9000 is bigger than member link`.
|
|
20
|
-
- There is no `protocols stp`. Plain STP is RSTP
|
|
20
|
+
- There is no `protocols stp`. Plain STP is RSTP limited with `force-version stp`.
|
|
21
21
|
- sFlow interfaces print with their unit, `xe-0/0/0.0`.
|
|
22
22
|
- The factory VLAN `default` can be deleted.
|
|
23
|
-
- BGP without a licence commits with only a warning, `requires 'bgp' license`, and sessions establish. The same
|
|
23
|
+
- BGP without a licence commits with only a warning, `requires 'bgp' license`, and sessions establish. The same is true for the other licensed features.
|
|
24
24
|
- Junos accepts and announces every route over eBGP unless a policy says otherwise: `Default eBGP mode: advertise - accept, receive - accept`. A session without a policy is given `circuit-reject-all`.
|
|
25
25
|
- An export policy sees every active route, not only BGP's. Every export starts with `circuit-bgp-origin`, which passes on BGP's routes and the prefixes in `routing.bgp.networks` and rejects the rest.
|
|
26
26
|
- A policy's or a filter's terms are kept in order, and `set` adds a new term at the end. A change to one rewrites it whole.
|
|
@@ -6,7 +6,7 @@ Behaviour that looks like something else. Each one has been hit on a RAX721 runn
|
|
|
6
6
|
- The SSH server offers only an `ssh-rsa` host key. The adapter allows it for this platform alone; key exchange, cipher and MAC still negotiate modern ones.
|
|
7
7
|
- `show running-config` stops about halfway with no error unless `terminal page-break disable` is sent first and the read waits several seconds of silence.
|
|
8
8
|
- A `?` sent by a script is executed. Once it applied an address with a /8 mask.
|
|
9
|
-
- An access-list cannot change while any service
|
|
9
|
+
- An access-list cannot change while any service uses it: `ACL 1000 is in use`. Every service that uses it is unbound first and bound again after. `no ssh2 access-list` needs the list number.
|
|
10
10
|
- `portswitch`, `switchport trunk allowed vlan` and `switchport mode` ask for `y` and do nothing without it, except when they need no confirming: `switchport mode trunk` on a port leaving access mode answers `Set successfully` at once, and a `y` sent after it is refused, `Error input`.
|
|
11
11
|
- A VLAN is removed with `no vlan <id>`, not `no create vlan`.
|
|
12
12
|
- The factory account `raisecom` cannot be removed and its service type cannot change. Only its password is ours.
|
|
@@ -18,5 +18,5 @@ Behaviour that looks like something else. Each one has been hit on a RAX721 runn
|
|
|
18
18
|
- An SNMPv3 user prints as localized keys, `authkey sha <hex> privkey aes128 <hex>`, which authenticate as well as the passphrase. The read redacts them. An access group prints a `notify internet` it was not given. A user's group is removed with `no snmp-server group user <user> usm`.
|
|
19
19
|
- A VRRP group is enabled once it has an address and preempts unless `no vrrp N preempt`. `no vrrp N ip <address>` removes the whole group.
|
|
20
20
|
- OSPF settings for an interface sit on the interface, `ip ospf cost`, `ip ospf network ptp`, `ip ospf passive-interface enable`; passive is undone with `... disable`, not `no`.
|
|
21
|
-
- `create vlan <list> active`
|
|
21
|
+
- `create vlan <list> active` has every VLAN on one line. A change creates only the new VLANs and removes each one that is gone with `no vlan <id>`.
|
|
22
22
|
- An access-list rule is not replaced by one with the same number: the device answers `Set unsuccessfully.` and keeps the old rule. The old one is removed first. `no rule N` answers slowly, after a second or more.
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
Behaviour that looks like something else. Each one has been hit on a real device.
|
|
4
4
|
|
|
5
5
|
- Every command takes effect as it arrives; there is no candidate configuration. `apply` saves a backup, arms a scheduler that restores it, and restores at once if a command is refused.
|
|
6
|
-
- A `/32` address gives no connected route, so a session over it never opens.
|
|
6
|
+
- A `/32` address gives no connected route, so a session over it never opens. Give the far end: `{ address, peer }` renders `network=<peer>`.
|
|
7
7
|
- `[find address=X/Y]` unquoted matches nothing, silently. Every selector the plan builds is quoted.
|
|
8
8
|
- `~` in `find` has no anchors. Match exactly.
|
|
9
9
|
- A property of the same group is printed as a bare suffix, `output.filter-chain=X .network=Y`, which only reads back inside that command. The parser expands it before building a `set`.
|
|
10
|
-
- `/routing bgp connection add` without `local.role` is refused, so the render always
|
|
10
|
+
- `/routing bgp connection add` without `local.role` is refused, so the render always writes one. On 7.23 one without `instance` is refused too, `missing value(s) of argument(s) instance`, although the export never prints `instance=default`.
|
|
11
11
|
- A connection without `input.filter` accepts everything. A neighbor without a policy is given `REJECT-ALL`.
|
|
12
12
|
- A session edited repeatedly can stick: SYN both ways, no RST, no log. Remove the connection and add it again.
|
|
13
13
|
- A session that never established is missing from `/routing bgp session print`; look at `/routing bgp connection print`.
|
|
@@ -27,17 +27,17 @@ Behaviour that looks like something else. Each one has been hit on a real device
|
|
|
27
27
|
- `mac-server` and `mac-winbox` work at layer 2 and ignore the IP firewall; they are limited by interface list.
|
|
28
28
|
- `time-zone-autodetect` is on by default and wins after a restart. The render turns it off.
|
|
29
29
|
- The SSH client drops a password sent together with its newline. Send the password, wait, then the newline.
|
|
30
|
-
- A serial console login redraws lines unless the user name
|
|
30
|
+
- A serial console login redraws lines unless the user name has `+cwt`.
|
|
31
31
|
- Narrowing a subnet is a change in several places: the address, the DHCP network, and every switch on the LAN. A mismatch breaks only the return path, so a test from the router passes.
|
|
32
32
|
- In `find`, a quoted `"yes"` is a string and matches no boolean, silently. Plain words go bare; only values with a slash or a space are quoted.
|
|
33
|
-
- `:put [:parse "..."]` compiles a command without running it and
|
|
33
|
+
- `:put [:parse "..."]` compiles a command without running it and reports a syntax error or an unknown property. `apply` checks every command this way before the backup is taken.
|
|
34
34
|
- A refused command restores the backup, which restarts the router. Expect every session to re-establish over a minute or two.
|
|
35
35
|
- `strong-crypto=yes` also hardens the device's own SSH client, which then fails silently toward devices that only speak older algorithms.
|
|
36
36
|
- SNMPv3 authenticates with MD5 or SHA1 only on 7.23.
|
|
37
37
|
- In a quoted string `$` starts a variable. The adapter escapes it.
|
|
38
38
|
- A script sent over SSH exec runs as one line; a multi-line script fails with `expected closing brace`.
|
|
39
39
|
- `:find` on an array returns a number or `nil`. Globals persist between exec commands of one login.
|
|
40
|
-
- A fixed port speed is named by medium, `speed=10G-baseSR-LR` for an optic or `speed=1G-baseT-full` for copper, and only
|
|
40
|
+
- A fixed port speed is named by medium, `speed=10G-baseSR-LR` for an optic or `speed=1G-baseT-full` for copper, and only stays set with `auto-negotiation=no`. With auto-negotiation back on, the export no longer prints the speed, so the plan resets only auto-negotiation. `speed=""` is refused as ambiguous and `unset speed` does not exist.
|
|
41
41
|
- `bgp-path-len` counts every AS in the path, prepends included, and takes the same strict comparisons as `dst-len`.
|
|
42
42
|
- `:parse` checks the command, not the text inside `rule=`. A routing filter rule is only checked when it is added.
|
|
43
43
|
- `/routing/filter/filter-wizard` adds the rule it builds; it is not a dry run. `set blackhole yes` was proved this way on 7.23, in an unused chain removed right after.
|
|
@@ -14,10 +14,10 @@ Behaviour that looks like something else. Each one has been hit on a CE6855 runn
|
|
|
14
14
|
- LLDP is off by default. A port setting for LLDP is refused until it is on globally.
|
|
15
15
|
- A trunk forwards its native VLAN's untagged frames only when that VLAN is also allowed; the adapter adds it.
|
|
16
16
|
- The name `admin` is refused for a local user.
|
|
17
|
-
- A port joins an Eth-Trunk only while it
|
|
17
|
+
- A port joins an Eth-Trunk only while it has no other setting, including a description.
|
|
18
18
|
- An empty block such as `bfd` enters its view; the next line sent goes into it unless the view is left.
|
|
19
19
|
- SNMPv3 passwords are asked for interactively, twice. `authentication-mode` must come before `privacy-mode`.
|
|
20
20
|
- `abort` is not a command here. `clear configuration candidate` discards uncommitted changes.
|
|
21
|
-
- sFlow samples per port, `sflow sampling rate N`, N from 4096; the default is 8192 and an explicit 8192 is kept as written. A port
|
|
22
|
-
- `vlan batch`
|
|
23
|
-
- A VLAN name is unique across VLANs: a new VLAN cannot take a name another still
|
|
21
|
+
- sFlow samples per port, `sflow sampling rate N`, N from 4096; the default is 8192 and an explicit 8192 is kept as written. A port can point to a collector only once the collector exists globally; until then it is refused with "collector does not exist".
|
|
22
|
+
- `vlan batch` has every VLAN on one line, and undoing a list that includes a VLAN with an L3 interface is refused. A change sends only the VLANs added and `undo vlan batch` for the ones removed.
|
|
23
|
+
- A VLAN name is unique across VLANs: a new VLAN cannot take a name another still has. VLANs no longer used, and their VLAN interfaces, are removed first, in the same candidate.
|
package/src/schema/common.ts
CHANGED
package/src/schema/device.ts
CHANGED
|
@@ -43,7 +43,7 @@ export type Device<
|
|
|
43
43
|
> = {
|
|
44
44
|
/** Hostname. */
|
|
45
45
|
name: string;
|
|
46
|
-
/** Operating system
|
|
46
|
+
/** Operating system. It decides which adapter renders and applies the device. */
|
|
47
47
|
platform: Pl;
|
|
48
48
|
/** Hardware model. Decides which port names exist. */
|
|
49
49
|
model: M;
|
package/src/schema/firewall.ts
CHANGED
|
@@ -15,7 +15,7 @@ export type Ports = number | PortRange | readonly (number | PortRange)[];
|
|
|
15
15
|
/** A TCP header flag. */
|
|
16
16
|
export type TcpFlag = "fin" | "syn" | "rst" | "psh" | "ack" | "urg";
|
|
17
17
|
|
|
18
|
-
/** Conditions on a packet. All must
|
|
18
|
+
/** Conditions on a packet. All must be true. A rule with addresses of one family applies to that family only. */
|
|
19
19
|
export type FilterMatch<I extends string, AS extends string> = {
|
|
20
20
|
/** Only packets of this family. */
|
|
21
21
|
family?: Family;
|
|
@@ -51,7 +51,7 @@ export type FilterRule<I extends string, AS extends string> = {
|
|
|
51
51
|
match?: FilterMatch<I, AS>;
|
|
52
52
|
/** What happens to a matching packet. `reject` answers the sender, `drop` does not. */
|
|
53
53
|
action: "accept" | "drop" | "reject";
|
|
54
|
-
/**
|
|
54
|
+
/** Send the rest of an accepted flow through the fast path, skipping the remaining rules. */
|
|
55
55
|
offload?: true;
|
|
56
56
|
};
|
|
57
57
|
|
|
@@ -126,7 +126,7 @@ export type AclRule<V extends string> = {
|
|
|
126
126
|
src_port?: Ports;
|
|
127
127
|
/** Destination port, or any of several. */
|
|
128
128
|
dst_port?: Ports;
|
|
129
|
-
/**
|
|
129
|
+
/** In this VLAN. */
|
|
130
130
|
vlan?: V;
|
|
131
131
|
};
|
|
132
132
|
/** What happens to a matching packet. */
|
package/src/schema/interfaces.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { Address, IP, Prefix, Secret } from "./common";
|
|
2
2
|
|
|
3
|
-
/** A VLAN.
|
|
3
|
+
/** A VLAN. Its key in `vlans` is its name. */
|
|
4
4
|
export type Vlan = {
|
|
5
|
-
/** The number
|
|
5
|
+
/** The VLAN's number on the wire, 1 to 4094. */
|
|
6
6
|
id: number;
|
|
7
7
|
/** What the VLAN is for. */
|
|
8
8
|
description?: string;
|
|
@@ -25,7 +25,7 @@ export type Vrrp = {
|
|
|
25
25
|
interval?: number;
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
-
/** Layer 3 settings shared by every interface that can
|
|
28
|
+
/** Layer 3 settings shared by every interface that can have an address. */
|
|
29
29
|
export type Routed<F extends string> = {
|
|
30
30
|
/** Addresses with their length. Use `{ address, peer }` for a point-to-point address whose far end is outside its own prefix. */
|
|
31
31
|
addresses?: readonly (Address | { address: Address; peer: IP })[];
|
|
@@ -33,7 +33,7 @@ export type Routed<F extends string> = {
|
|
|
33
33
|
ipv6_ra?: boolean;
|
|
34
34
|
/** Overrides the device's `hardware_offload` for traffic routed through this interface. Software forwarding is what makes the firewall apply. */
|
|
35
35
|
hardware_offload?: boolean;
|
|
36
|
-
/** Virtual router addresses
|
|
36
|
+
/** Virtual router addresses on this interface. */
|
|
37
37
|
vrrp?: readonly Vrrp[];
|
|
38
38
|
/** The VRF this interface routes in. The default table when absent. */
|
|
39
39
|
vrf?: F;
|
|
@@ -63,11 +63,11 @@ export type PortStp = {
|
|
|
63
63
|
|
|
64
64
|
/** Layer 2 membership. A port or LAG with none of these is routed. */
|
|
65
65
|
export type Switched<V extends string> = {
|
|
66
|
-
/**
|
|
66
|
+
/** The one VLAN this port or LAG is in, untagged. */
|
|
67
67
|
access_vlan?: V;
|
|
68
|
-
/**
|
|
68
|
+
/** The VLANs this port or LAG carries, tagged. */
|
|
69
69
|
trunk_vlans?: readonly V[];
|
|
70
|
-
/** Untagged frames on a trunk
|
|
70
|
+
/** Untagged frames on a trunk are in this VLAN. Only with `trunk_vlans`. */
|
|
71
71
|
native_vlan?: V;
|
|
72
72
|
/** Overrides the device's `stp` for this port. `false` stops it sending or acting on BPDUs. */
|
|
73
73
|
stp?: boolean | PortStp;
|
|
@@ -100,7 +100,7 @@ export type Port<V extends string, A extends string, L extends string, F extends
|
|
|
100
100
|
lldp?: boolean;
|
|
101
101
|
/** Hardware ACL applied to traffic arriving on this port. */
|
|
102
102
|
acl?: A;
|
|
103
|
-
/**
|
|
103
|
+
/** The LAG this port is in. Every other setting goes on the LAG. */
|
|
104
104
|
lag?: L;
|
|
105
105
|
/** Another of our devices at the other end of the cable. */
|
|
106
106
|
link?: Link;
|
|
@@ -117,20 +117,20 @@ type Base<F extends string> = Routed<F> & {
|
|
|
117
117
|
/** A layer 3 interface on a VLAN. */
|
|
118
118
|
export type VlanInterface<V extends string, F extends string> = Base<F> & {
|
|
119
119
|
type: "vlan";
|
|
120
|
-
/** The VLAN it
|
|
120
|
+
/** The VLAN it is on. */
|
|
121
121
|
vlan: V;
|
|
122
122
|
};
|
|
123
123
|
|
|
124
|
-
/** An interface that is always up and
|
|
124
|
+
/** An interface that is always up and is on no link, for addresses that must not depend on one. */
|
|
125
125
|
export type Loopback<F extends string> = Base<F> & { type: "loopback" };
|
|
126
126
|
|
|
127
|
-
/** A link aggregation.
|
|
127
|
+
/** A link aggregation. Each member port points to it with `lag`. */
|
|
128
128
|
export type Lag<V extends string, F extends string> = Base<F> &
|
|
129
129
|
Switched<V> & {
|
|
130
130
|
type: "lag";
|
|
131
|
-
/** LACP negotiates membership with the far end; static
|
|
131
|
+
/** LACP negotiates membership with the far end; `static` joins the ports without asking. LACP when absent. */
|
|
132
132
|
mode?: "lacp" | "static";
|
|
133
|
-
/** Number on platforms
|
|
133
|
+
/** Number, on platforms where a LAG has a number instead of a name. Its position among the device's LAGs when absent. */
|
|
134
134
|
id?: number;
|
|
135
135
|
};
|
|
136
136
|
|
package/src/schema/policy.ts
CHANGED
|
@@ -20,7 +20,7 @@ export type PrefixSet =
|
|
|
20
20
|
};
|
|
21
21
|
};
|
|
22
22
|
|
|
23
|
-
/** Conditions on a route. All must
|
|
23
|
+
/** Conditions on a route. All must be true. An empty match is true for every route. */
|
|
24
24
|
export type Match<S extends string> = {
|
|
25
25
|
/** Only routes of this family. */
|
|
26
26
|
family?: Family;
|
|
@@ -34,9 +34,9 @@ export type Match<S extends string> = {
|
|
|
34
34
|
as_path_length?: { min?: number; max?: number };
|
|
35
35
|
/** The route's origin validation state. */
|
|
36
36
|
rpki?: "valid" | "invalid" | "not-found";
|
|
37
|
-
/**
|
|
37
|
+
/** Has this standard community, `asn:value`. */
|
|
38
38
|
community?: string;
|
|
39
|
-
/**
|
|
39
|
+
/** Has this large community, `asn:function:parameter`. */
|
|
40
40
|
large_community?: string;
|
|
41
41
|
};
|
|
42
42
|
|
package/src/schema/routing.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Family, IP, Prefix, Secret } from "./common";
|
|
2
2
|
|
|
3
|
-
/** A route the device
|
|
3
|
+
/** A route the device has without learning it. */
|
|
4
4
|
export type StaticRoute<I extends string, F extends string> = {
|
|
5
5
|
/** Destination. */
|
|
6
6
|
prefix: Prefix;
|
|
@@ -12,7 +12,7 @@ export type StaticRoute<I extends string, F extends string> = {
|
|
|
12
12
|
blackhole?: true;
|
|
13
13
|
/** Preference against other routes to the same prefix. Lower wins. 1 when absent. */
|
|
14
14
|
distance?: number;
|
|
15
|
-
/** The VRF the route
|
|
15
|
+
/** The VRF the route is in. The default table when absent. */
|
|
16
16
|
vrf?: F;
|
|
17
17
|
/** Why the route exists. */
|
|
18
18
|
description?: string;
|
|
@@ -23,7 +23,7 @@ export type StaticRoute<I extends string, F extends string> = {
|
|
|
23
23
|
*/
|
|
24
24
|
export type BgpRole = "provider" | "customer" | "peer" | "rs" | "rs-client";
|
|
25
25
|
|
|
26
|
-
/** Settings a BGP neighbor can
|
|
26
|
+
/** Settings a BGP neighbor can set itself or take from its group. */
|
|
27
27
|
export type NeighborSettings<P extends string> = {
|
|
28
28
|
/** The neighbor's AS. Our own AS makes the session internal. */
|
|
29
29
|
remote_as?: number;
|
|
@@ -35,7 +35,7 @@ export type NeighborSettings<P extends string> = {
|
|
|
35
35
|
import?: P;
|
|
36
36
|
/** Policy for routes announced. Nothing is announced when absent. */
|
|
37
37
|
export?: P;
|
|
38
|
-
/** What the neighbor is to us, such as `provider` for a transit. Both sides then reject a route leak,
|
|
38
|
+
/** What the neighbor is to us, such as `provider` for a transit. Both sides then reject a route leak, as RFC 9234 describes. */
|
|
39
39
|
role?: BgpRole;
|
|
40
40
|
/** The neighbor is more than one hop away. */
|
|
41
41
|
multihop?: boolean;
|
|
@@ -55,11 +55,11 @@ export type NeighborSettings<P extends string> = {
|
|
|
55
55
|
bfd?: boolean;
|
|
56
56
|
};
|
|
57
57
|
|
|
58
|
-
/** One BGP session. Settings it does not
|
|
58
|
+
/** One BGP session. Settings it does not set come from its group. */
|
|
59
59
|
export type Neighbor<P extends string, G extends string> = NeighborSettings<P> & {
|
|
60
60
|
/** The neighbor's address. */
|
|
61
61
|
address: IP;
|
|
62
|
-
/**
|
|
62
|
+
/** The group this neighbor takes a setting from when it does not set that setting itself. */
|
|
63
63
|
group?: NoInfer<G>;
|
|
64
64
|
};
|
|
65
65
|
|
|
@@ -111,7 +111,7 @@ export type Ospf<I extends string> = {
|
|
|
111
111
|
export type Routing<P extends string, G extends string, I extends string, F extends string> = {
|
|
112
112
|
/** Identifies this router to its neighbors. */
|
|
113
113
|
router_id?: IP;
|
|
114
|
-
/** Routes the device
|
|
114
|
+
/** Routes the device has without learning them. */
|
|
115
115
|
static?: readonly StaticRoute<I, F>[];
|
|
116
116
|
/** BGP sessions and what they exchange. */
|
|
117
117
|
bgp?: Bgp<P, G>;
|
package/src/schema/system.ts
CHANGED
|
@@ -13,7 +13,7 @@ export type System = {
|
|
|
13
13
|
/** Answer queries from others. Off when absent. */
|
|
14
14
|
serve?: boolean;
|
|
15
15
|
};
|
|
16
|
-
/**
|
|
16
|
+
/** How the device keeps time. */
|
|
17
17
|
ntp?: {
|
|
18
18
|
/** Time sources, by address or name. */
|
|
19
19
|
servers: readonly string[];
|
|
@@ -87,7 +87,7 @@ export type SnmpUser = {
|
|
|
87
87
|
|
|
88
88
|
/** How the device is reached and managed. */
|
|
89
89
|
export type Management<I extends string, C extends string> = {
|
|
90
|
-
/** Sources allowed to every service that does not
|
|
90
|
+
/** Sources allowed to every service that does not set its own. */
|
|
91
91
|
allow?: readonly Prefix[];
|
|
92
92
|
/** Secure shell. */
|
|
93
93
|
ssh?: Service & {
|
|
@@ -141,11 +141,11 @@ export type DhcpServer<I extends string> = {
|
|
|
141
141
|
interface: I;
|
|
142
142
|
/** The network it serves. */
|
|
143
143
|
network: Prefix;
|
|
144
|
-
/** Default gateway
|
|
144
|
+
/** Default gateway given to clients. */
|
|
145
145
|
gateway: IP;
|
|
146
|
-
/** Resolvers
|
|
146
|
+
/** Resolvers given to clients. */
|
|
147
147
|
dns?: readonly IP[];
|
|
148
|
-
/** First and last address
|
|
148
|
+
/** First and last address given to clients. */
|
|
149
149
|
pool: readonly [IP, IP];
|
|
150
150
|
/** Seconds a lease lasts. */
|
|
151
151
|
lease_time?: number;
|
|
@@ -168,9 +168,9 @@ export type DhcpRelay<I extends string> = {
|
|
|
168
168
|
|
|
169
169
|
/** A certificate the device presents or trusts. */
|
|
170
170
|
export type Certificate = {
|
|
171
|
-
/** The certificate, PEM. Public, so it
|
|
171
|
+
/** The certificate, PEM. Public, so it is kept in the repository. */
|
|
172
172
|
certificate: string;
|
|
173
|
-
/** Its private key: a PEM file through `secretFile`, or PEM base64-encoded as one line through `secret`. A certificate only
|
|
173
|
+
/** Its private key: a PEM file through `secretFile`, or PEM base64-encoded as one line through `secret`. A certificate the device only trusts, such as a CA, has none. */
|
|
174
174
|
private_key?: Secret;
|
|
175
175
|
};
|
|
176
176
|
|