A container's command line, as reported by podman, may comtain environment
variables, which the current regexp (added in ed4fe58) does not support.
Extend the regexp to allow environment variables and add an operational,
config false, 'cmdline' leaf node to allow any characters to be reported
for the full command line in the operational output.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Unfortunatly the fix was entered in 25.10, but confd was not stepped
up until 25.11, so this should be for 25.10 but now it is for confd
version 1.6 (infix 25.11), as close as we can get.
this is a follwup for commit 7e37fc49a3
confd: prevent IP addresses on bridge ports
Bridge ports should not have IP addresses configured. The IP address
should be configured on the bridge interface itself, not its member ports.
Add YANG must expression to enforce this rule at configuration time.
Fixes#1122
The setting 'stratumweight 0.0' disables stratum in Chrony source
selection (pure distance-based), making client_stratum_selection
non-deterministic on a LAN. Setting it to 1.0 gives srv1 a 1-second
effective advantage per stratum level, which no realistic distance
fluctuation can overcome.
Also correct the YANG descriptions in infix-system and infix-ntp which
had the semantics backwards — claiming 0.0 "ensures lower stratum is
always preferred" when in fact higher values do that.
Fixes#1361
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
After a successful bootstrap confd writes a sentinel to /run/confd.boot
If Finit restarts confd — whether after a crash or a clean exit — the
sentinel is found and the destructive bootstrap phases are skipped:
- gen-config fork (factory/failure configs already exist)
- wipe_sysrepo_shm() (other daemons, e.g. statd, are live)
- sr_install_factory_config() (datastores are already initialised)
- sr_replace_config(NULL, NULL) (running datastore is consistent)
- bootstrap_config() / load startup-config (not needed; sysrepo has
the right state; plugins resync via SR_EV_ENABLED on re-subscribe)
On restart confd reconnects to sysrepo, re-initialises plugins (which
re-subscribe and receive SR_EV_ENABLED to resync with the live running
datastore), then enters the steady-state event loop.
The sentinel lives on tmpfs so a real reboot always produces a clean
slate. Crash-loop protection is delegated to Finit's max-restarts (10).
As a side-effect this also enables a future "run-once" mode for resource
constrained systems: confd can exit after bootstrap and the sentinel
ensures any later restart just re-attaches without re-bootstrapping.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Add a finit_enable/disable/reload() family in core.c that directly
manipulates Finit's service state without fork+exec overhead:
finit_enable(svc) -- create symlink in /etc/finit.d/enabled/
finit_disable(svc) -- remove symlink from /etc/finit.d/enabled/
finit_delete(svc) -- remove both symlink and service entirely
finit_reload(svc) -- utimensat() on .conf to schedule reload
Printf-style variants (finit_enablef/disablef/reloadf) handle
template instance names such as container@foo and hostapd@wlan0.
All systemf("initctl ... enable/disable/touch ...") call sites across
containers, dhcp-server, firewall, hardware, ntp, routing, services,
syslog, and system are converted to the new API.
As a related cleanup in services.c, drop the remaining srx_enabled()
calls in favour of reading the already-fetched config tree directly
via lydx_is_enabled(lydx_get_xpathf(config, ...)), eliminating the
last sysrepo round-trips from that module.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Previously svc_enadis() would call 'initctl enable + touch' for every
config change event, even when the service's enabled state was unchanged.
This caused rousette to be unnecessarily restarted on every test_reset(),
racing with the active RESTCONF connection on slow hardware.
Replace svc_enadis() and svc_change() with svc_enable() which only
manages nginx symlinks and calls 'initctl enable/disable' -- never touch.
Each handler now checks the diff for the specific leaf that changed:
- If /enabled appears in diff: call svc_enable() to start or stop it
- If other config leaves changed with service already enabled: touch only
This ensures rousette, ttyd, netbrowse, avahi, sshd, and lldpd are only
restarted when their configuration actually requires it.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Save a few CPU cycles by skipping a new dagger generation when no
interfaces have been modified/added/deleted.
Uses d->next_fp as the sentinel: NULL means no claim was made for this
transaction. dagger_evolve() and dagger_abandon() now NULL it after
fclose, so subsequent unclaimed transactions also get the clean early
return.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
- Use same log frameworks as reset of confd
- Use existing primitives from libite + libsrx
- Drop remaining pthreads
- Coding style fixes
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Only install the keys on CHANGE event, fixes this annoying issue:
Nov 5 01:32:10 ix confd[2011]: Installing HTTPS gencert certificate "self-signed"
Nov 5 01:32:10 ix confd[2011]: Installing SSH host key "genkey".
Nov 5 01:32:11 ix confd[2011]: Installing HTTPS gencert certificate "self-signed
Nov 5 01:32:11 ix confd[2011]: Installing SSH host key "genkey".
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Use SR_SUBSCR_NO_THREAD for all subscriptions and integrate sysrepo
event pipes into a libev event loop. This eliminates approximately 30
per-subscription threads, reducing overhead on embedded ARM hardware.
A temporary poll-based "event pump" thread handles callback dispatch
during bootstrap (where sr_replace_config blocks waiting for callbacks),
then exits. After bootstrap, the single-threaded libev loop takes over
for steady-state event processing.
Note, the confd-test-mode plugin still requires use of threads so we do
not create deadlocks when calling sr_replace_config().
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
- Add x509-public-key-format identity to crypto-types
- Add certificate node to web services container
- Use certificate from ietf-keystore as web cert
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Relocate probe of wifi radios from gen-hardware to 00-probe. This saves
one python invocation and some precious CPU cycles at boot.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Allow confd to start even earlier at boot and call 'gen-config' as a
background task, pending on it to complete before we load the sysrepo
factory datastore.
Also, add Finit style progress to console so users can see the phases
of the bootstrap process.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
On single-core Cortex-A7, the YANG bootstrap and config loading is the
dominant boot bottleneck. The current sequence spawns three serial
phases (bootstrap, sysrepo-plugind, load), each performing independent
sr_connect()/sr_disconnect() cycles, and every sysrepoctl/sysrepocfg
invocation is a fork+exec that rebuilds SHM from scratch.
Replace all three with a single confd binary that does one sr_connect()
and performs all datastore operations in-process:
- Wipe stale /dev/shm/sr_* for a clean slate
- sr_install_factory_config() from the generated JSON
- Smart migration: compare config version via libjansson, only
fork+exec the migrate script when versions actually differ
- Load startup-config (or test-config) via lyd_parse_data() +
sr_replace_config(), mirroring what sysrepocfg -I does internally
- On failure: revert to factory-default, load failure-config, set
login banners (Fail Secure mode)
- On first boot: copy factory-default to running, export to file
- dlopen plugins and enter event loop
The bootstrap shell script is split: config generation (gen-hostname,
gen-interfaces, etc.) stays in the new gen-config script, while all
sysrepo operations move into the C daemon. The finit boot sequence
collapses from 5 stanzas to 2 (gen-config -> confd).
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Replace ERROR() with ERRNO() in all error paths following POSIX API
calls (fopen, rename, realloc, fmkpath, etc.), removing redundant
manual strerror(errno) formatting where present.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Ensure we translate the hostname before we generate the udhcpc command
line options, otherwise we'll send '-x hostname:rpi-%m' to udhcpc.
Also update all board specific factory configs with the missing setting
'"value": "auto"' for the DHCP hostname option. This to match what we
already do when we infer options when enabling a DHCP client in the CLI.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Two races could prevent DHCP-learned default routes from being installed
at boot:
1. The signal from the DHCP client script could be lost leaving conf.d
updated but frr.conf stale.
2. Even when the signal was received, 'vtysh -b' could fail because the
FRR daemon chain (mgmtd→zebra→staticd) writes PID files before being
fully operational, causing netd to give up with no retry.
Fix both by refactoring netd to use libev:
- Use an inotify watch of CONF_DIR, so netd reacts directly to file
changes without depending on signal delivery.
- On backend_apply() failure, schedule a retry in 5s and call pidfile()
unconditionally so dependent services are not blocked waiting for the
Finit condition 'pid/netd' to be satisfied.
We also take this opportunity to rename /etc/netd/conf.d/ to /etc/net.d/
The extra /etc/netd/ directory level served no purpose — nothing else
lives there. Flatten to /etc/net.d/ which reads more naturally as the
drop-in directory for network configuration snippets.
Also, reduce logging a bit since each netd backend already logs success
or fail which is sufficient to know that a configuration change has been
applied or not.
Finally, with the new inotify processing in netd it's redundant to call
'initctl reload netd' from the udhcpc script, in fact it will only cause
unnecessary overhead, so we drop it.
Fixes#1438
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Add a must expression to ensure users do not set static neighbors when
the interface type is not point-to-multipoint or non-broadcast.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Two related problems prevented devices behind an intermediate hub (e.g.
the VIA Labs hub on the RPi 400's VL805 xHCI) from being authorized
when confd unlocks a USB bus:
1. Cascade ordering: usb_authorize() ran nftw() with FTW_DEPTH, which
visits children before the root-hub entry. The hub was authorized
while authorized_default was still 2, so when the kernel probed the
hub's children it immediately denied them. Fix: write
authorized_default=1 on the bus before entering nftw.
2. Slow/async probe: hub port enumeration is asynchronous — devices
behind a hub may appear in sysfs after nftw has already finished.
Fix: add a udev rule that catches usb_device add events on buses
where authorized_default=1 is already set on any ancestor root hub
and authorizes them immediately.
The ATTRS{} matcher in udev walks the full sysfs parent chain, so
authorized_default=1 on the root hub is visible even for devices several
hubs deep. Buses still locked at authorized_default=0 are left alone.
Also expand the docstring in generic_usb_ports() to document the
design: each root hub gets its own uniquely-named entry (USB, or USB1/
USB2/... when multiple) so buses can be individually controlled, and
boards needing finer control should use DT usb-ports annotations.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Add a `hostname` leaf to the `mdns` YANG container with default `"%h"`,
allowing operators to override the avahi host-name used for mDNS A/AAAA
records without reflashing. The default expands to DEFAULT_HOSTNAME from
os-release, preserving existing behaviour for unconfigured deployments.
Format specifiers %h/%i/%m are supported via the existing hostnamefmt()
infrastructure, which is also fixed to copy the const fmt argument to a
local buffer before modification (UB when called with a libyang-owned
string).
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Use avahi's %h wildcard in service names so each device's hostname is
included, avoiding collision suffixes (#2, #3) when multiple Infix
devices are on the same network.
Skip TXT records whose JSON value is null rather than emitting empty
key= fields. Add _workstation._tcp (with chassis MAC) and
_device-info._tcp (with model= from product-name) as always-on records
tied to mDNS being active.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Simplify and consolidate generation of mdns service records from an
external script to C. This reduces fork + exec and saves two seconds
of boot time on single core Cortex-A7 systems.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Instead of publishing A/AAAA records for $(hostname).loocal with a CNAME
infix.local, we flip it around to take advantage of the mDNS conflict
resolution rules. This gives us infix.local for one device ont the LAN
and infix-2.local for the next.
Update all service records to *not* advertise hostname, but instead to
let Avahi imply that from the advertised A/AAAA and CNAME records.
Fixes#1387
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This patch adds support for chronyd's stratumpweight both in the NTP
client (ietf-system) and client+server (ietf-ntp) should fix the flaky
NTP stratum test.
Also, make sure to *not* 'rm -rf /etc/chrony/conf.d/*' in system.c to
prevent clobbering settings potentially made in ntp.c
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This is a follow-up to c559b8f2 (new-frr) where netd now is responsible
for funneling static routes, as well as routes from DHCP clients, into
the kernel via Frr.
For this to work, in particular at boot, any DHCP client must wait for
netd to have started or any default routes learned will be lost.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Add input validation patterns to string-type leaves in container,
firewall, DHCP, and interface YANG models. Also use mkdtemp() for
temporary key files in keystore.
Signed-off-by: Mattias Walström <lazzer@gmail.com>
This is a simpler approach than both grpc and watchfrr. Since we only
really need dynamic handling of static routes (for DHCP), we can track
changes made and maintain a "diff engine" for the resulting frr.conf.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This includes adding a netd-daemon since FRR has gone towards all
daemons should be configured from mgmtd using YANG, netd uses gRPC to
reconfigure in mgmtd
Signed-off-by: Enable grpc
This patch adds a background gps monitor to statd because the gpspipe
program, normally used to interface with gpsd, slows down access to the
operational datastore with *seconds*.
This background monitor is not load bearing for how chrony accesses the
gps + nmea information from gpsd, this is handled separately in SHM.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Add documentation noting that at least one side of a VETH pair must
remain in the host namespace. Both ends cannot be assigned to different
containers.
Updates:
- container.md: Added IMPORTANT note in Container Host Interface section
- infix-if-veth.yang: Added note in module description
- infix-if-container.yang: Added note in host identity description
Fixes: #947
Related: #941
Co-authored-by: troglobit <183517+troglobit@users.noreply.github.com>
Infix key format identities now derive from the IETF bases, so the standard
identityref accepts them without any need for deviations. This also preserves
the nacm default rules, which were inadvertently dropped before.
Also rename format identities for generality:
- wifi-preshared-key-format -> renamed: 'passphrase-key-format'
- wireguard-symmetric-key-format -> use IETF 'octet-string-key-format'
Since cleartext-symmetric-key is now type binary (base64-encoded), the
WiFi backends (station and AP) decode values before passing them to
wpa_supplicant and hostapd.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Introduced in Linux 6.17, the force_forwding flag corresponds to the
ipv4 forwarding flag, which maps perfectly to the ietf-ip.yang model.
Fixes#515
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>