Documentation
¶
Overview ¶
Package config persists ndscan's TUI state: last-used scan settings, named profiles, and previous scan results (for change detection). Everything lives under ~/.config/ndscan/ as plain JSON.
Index ¶
- func DeleteProfile(name string) error
- func Diff(prev []HostSnapshot, cur []HostSnapshot) map[string]HostDiff
- func Dir() string
- func HistoryModTime(k ScanKey) (time.Time, bool)
- func Save(f File) error
- func SaveEligible(cancelled bool, failed int, hosts int) bool
- func SaveHistory(k ScanKey, snaps []HostSnapshot) error
- func SaveLast(s Settings) error
- func UpsertProfile(name string, s Settings) error
- func WriteFileAtomic(path string, data []byte, perm os.FileMode) error
- type File
- type HostDiff
- type HostSnapshot
- type Profile
- type ScanKey
- type Settings
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func DeleteProfile ¶
DeleteProfile removes a named profile if present.
func Diff ¶
func Diff(prev []HostSnapshot, cur []HostSnapshot) map[string]HostDiff
Diff compares the current scan against the previous snapshot, keyed by IP. The returned map includes an entry for every changed host, including hosts that disappeared (Gone=true).
func Dir ¶ added in v0.2.7
func Dir() string
Dir is the directory ndscan keeps its state in.
Exported so sibling packages store their data alongside config and history rather than each re-deriving the location. Three copies of this resolution would drift the first time the override rules change, and the symptom would be state silently written somewhere nobody looks.
func HistoryModTime ¶ added in v0.2.15
HistoryModTime reports when the baseline for this scan signature was last written, without loading it.
History filenames are one-way hashes of the key, so the store cannot be enumerated back into keys. A caller that wants to point the user at history filed under a *neighbouring* key — ndscan diff, when the exact key it was asked for has no baseline — can therefore only probe candidate signatures, and this is the read-only primitive for that probe. LoadHistory would answer the same question, but at the cost of reading and parsing every candidate file when all the caller needs is "does this exist, and how old is it".
func SaveEligible ¶ added in v0.2.4
SaveEligible reports whether a finished scan may become the new baseline.
The three front ends each answered this question separately and gave three different answers — the web saved unconditionally, including on cancellation, which corrupted history for every later run. Centralising the rule is what keeps them from drifting apart again.
An empty result set is rejected even when the scan reported success: finding zero hosts almost always means the machine lost its network (VPN dropped, Wi-Fi roamed) rather than that the network emptied out, and treating it as truth discards a good baseline in favour of a useless one.
func SaveHistory ¶
func SaveHistory(k ScanKey, snaps []HostSnapshot) error
SaveHistory stores the snapshot for this scan signature.
Callers must not reach here with the results of a cancelled, failed, or partial scan: an incomplete run looks exactly like a network where everything disappeared, and persisting it as the baseline makes the *next* scan report the whole network as new. Eligibility is the caller's decision because only it knows how the run terminated; SaveEligible states the rule in one place.
func UpsertProfile ¶
UpsertProfile adds or replaces a named profile.
func WriteFileAtomic ¶ added in v0.2.7
WriteFileAtomic writes data to path via a temp file and a rename, skipping the write entirely when the contents already match.
Exported for sibling packages that persist state alongside config: the same-contents check is what keeps watch mode from rewriting files every interval, and the rename is what stops an interrupted write from leaving truncated JSON behind.
Types ¶
type File ¶
type File struct {
Last *Settings `json:"last,omitempty"`
Profiles []Profile `json:"profiles,omitempty"`
}
File is the on-disk layout of config.json.
type HostDiff ¶
type HostDiff struct {
New bool // host wasn't in the previous scan
Gone bool // host was in the previous scan but not this one
PortsOpened []string // port numbers newly open
PortsClosed []string // port numbers no longer open
}
HostDiff describes how one host changed between two scans.
type HostSnapshot ¶
type HostSnapshot struct {
IP string `json:"ip"`
Host string `json:"host,omitempty"`
Up bool `json:"up"`
Ports []string `json:"ports,omitempty"` // bare port labels, e.g. "22/tcp ssh"
}
HostSnapshot is the minimal per-host state we remember between scans.
Up is recorded explicitly because a host that stopped responding is a different event from a host whose ports all closed. Without it, a machine that went offline diffs as "every port closed" while the host itself appears to still be there — the opposite of what happened.
func LoadHistory ¶
func LoadHistory(k ScanKey) []HostSnapshot
LoadHistory returns the previous snapshot for this scan signature, or nil.
type ScanKey ¶ added in v0.2.4
type ScanKey struct {
Targets []string
Ports string
Preset string
// Fast records whether this was the native ARP+TCP sweep rather than an
// nmap scan. The two probe different things and legitimately find different
// hosts, so mixing them under one key manufactures phantom
// appeared/disappeared events on every alternation.
Fast bool
}
ScanKey identifies "the same scan" across runs. Two scans are comparable only when every field matches, because each one changes which hosts or ports the scan could possibly have found.
This is a struct rather than a positional argument list on purpose. It was previously three bare strings, and the front ends drifted: the web passed "" for Ports while the TUI passed the real value, so the two never shared a baseline and neither could see the other's history. A named field per input makes an omission visible at the call site instead of silent.
func (ScanKey) Scope ¶ added in v0.2.10
Scope is a stable identifier for "the same scan", suitable for tagging records in other stores so they can be filtered back to the scan that produced them.
It is derived from the same canonical signature the history filename uses, so a second store cannot drift into its own interpretation of what makes two scans comparable — the timeline previously had no scope at all, and `ndscan diff` consequently reported changes from whichever network happened to be scanned last.
type Settings ¶
type Settings struct {
Targets string `json:"targets"`
Preset string `json:"preset"`
Ports string `json:"ports"`
ShowMac bool `json:"show_mac"`
ShowVendors bool `json:"show_vendors"`
RootScan bool `json:"root_scan"`
Concurrency string `json:"concurrency"`
HostTimeout string `json:"host_timeout"`
}
Settings mirrors the TUI form fields.