mirror of
https://github.com/Control-D-Inc/ctrld.git
synced 2026-10-12 01:58:46 +02:00
The journal records the network state of the host and each change of that state. The support team reads one file to see the interfaces, the routes, the resolvers, and the recoveries around an incident. The same file shows the health of the query path. A change that touches only AirDrop or virtual interfaces runs no DNS work.
83 lines
2.3 KiB
Go
83 lines
2.3 KiB
Go
package cli
|
|
|
|
import (
|
|
"bufio"
|
|
"io"
|
|
"maps"
|
|
"slices"
|
|
"strings"
|
|
)
|
|
|
|
// parsePFAnchorNames returns the anchor names that the running ruleset refers to,
|
|
// unique and sorted. It takes both pfctl show commands because each one holds half
|
|
// of the list: "pfctl -sr" the scrub and filter anchors, "pfctl -sn" the
|
|
// translation anchors.
|
|
func parsePFAnchorNames(rules, nat io.Reader) []string {
|
|
unique := make(map[string]struct{})
|
|
// A read that stopped early gives a shorter list, and a shorter list reads
|
|
// as an anchor that went away.
|
|
if !collectPFAnchorNames(rules, unique) || !collectPFAnchorNames(nat, unique) {
|
|
return nil
|
|
}
|
|
return slices.Sorted(maps.Keys(unique))
|
|
}
|
|
|
|
// collectPFAnchorNames reports whether it read the whole output.
|
|
func collectPFAnchorNames(r io.Reader, into map[string]struct{}) bool {
|
|
if r == nil {
|
|
return true
|
|
}
|
|
scanner := bufio.NewScanner(r)
|
|
for scanner.Scan() {
|
|
name := pfAnchorNameOf(scanner.Text())
|
|
if name == "" {
|
|
continue
|
|
}
|
|
into[name] = struct{}{}
|
|
}
|
|
return scanner.Err() == nil
|
|
}
|
|
|
|
// pfAnchorNameOf returns the anchor name of one pfctl rule line. The rule verb is
|
|
// anchor, nat-anchor, rdr-anchor, scrub-anchor or dummynet-anchor, and the quoted
|
|
// name follows it. Every other line, including the merged ALTQ warnings, gives "".
|
|
func pfAnchorNameOf(line string) string {
|
|
verb, rest, ok := strings.Cut(strings.TrimSpace(line), " ")
|
|
if !ok || !strings.HasSuffix(verb, "anchor") {
|
|
return ""
|
|
}
|
|
_, quoted, ok := strings.Cut(rest, `"`)
|
|
if !ok {
|
|
return ""
|
|
}
|
|
name, _, ok := strings.Cut(quoted, `"`)
|
|
if !ok {
|
|
return ""
|
|
}
|
|
return name
|
|
}
|
|
|
|
// parsePFStatus reads "pfctl -si" output and reports whether pf runs, with the
|
|
// uptime text that pfctl prints beside it.
|
|
func parsePFStatus(r io.Reader) (enabled bool, since string) {
|
|
if r == nil {
|
|
return false, ""
|
|
}
|
|
scanner := bufio.NewScanner(r)
|
|
for scanner.Scan() {
|
|
status, ok := strings.CutPrefix(strings.TrimSpace(scanner.Text()), "Status:")
|
|
if !ok {
|
|
continue
|
|
}
|
|
// pfctl pads the status into a column and prints the debug level next to it.
|
|
status, _, _ = strings.Cut(status, "Debug:")
|
|
state, uptime, _ := strings.Cut(strings.TrimSpace(status), " for ")
|
|
if state != "Enabled" {
|
|
return false, ""
|
|
}
|
|
return true, strings.TrimSpace(uptime)
|
|
}
|
|
// A read that stopped early may have stopped before the status line.
|
|
return false, ""
|
|
}
|