When an interface has been handed off to a container it lives in
another netns, so `ip neigh/addr flush dev FOO` fails on the host.
The failure aborts dagger, and since interfaces_change() runs before
containers_change() in change_cb(), the container delete path is
never reached -- the stale container keeps the interface trapped in
its netns, breaking the next reconfiguration.
Guard both the neighbor and address flush exit scripts with
`if_nametoindex(ifname)` -- true exactly when the interface is in
the host netns, false for both "in a container" and "already gone".
This replaces the pre-existing `!cni_find(ifname) && if_nametoindex(
ifname)` guard at the addr site: cni_find() added no information
for this check and would popen(container find) for nothing when the
interface had been deleted entirely.
Also harden wrap() in /usr/sbin/container so a stale setup pidfile
doesn't short-circuit Finit's stop attempt -- kill the setup PID and
still ask podman to stop the container.
Fixes#1493
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>
- 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>
Follow-up to 90f619b which first introduced the /etc/hostname.d concept.
This commit moves the setup of /etc/hostname.d to post-build.sh dropping
the initial call to the hostname activation script a bit, since it is
called anyway after bootstrap has finished. The scrip is also given a
bit of a refrehs, reducing overhead and needless log messages.
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>
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>
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>
Replace the costly read-only filter loop (awk+tr per line) with a
stderr redirect, use /sys/class/net/ instead of ip+jq, and batch
all sysctl writes into a single call.
Reduces boot time by ~4s on 32-bit Arm systems.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Calling tune2fs for ext4 partitions at boot costs more than one second
boot time on 32-bit Arm systems, with very little gain. Dropping this
restores the default periodic fsck *and* saves boot time.
Instead of calling sgdisk four times, call it only when resizing and
instead use sysfs to find named paritions. Saves seconds on boards
with weaker CPU and slow media.
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>
The weird `if env | grep -q 'reset-volumes'` construct is due to Klish
not sanitizing names before constructing variables, which leads to env
variables with '-' in them, not allowed in POSIX sh.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
With the latest backported fixes to Finit, we no longer need to remove
/run/netd.pid to trigger a reload (restart) of staticd.
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 update brings new support for editing cleartext-symmetric-keys with
the 'change' command. The cleartext-symmetric-key is of type binary and
its use differs between different key-formats.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Environment variables are stored in a separate .env file from the main
container script. The config SHA256 checksum only covered the script
file, so changes to env vars went undetected -- the container was not
recreated and kept running with stale values.
Include the env file contents in the config checksum calculation so that
any change to environment variables triggers a proper container restart.
Fixes#1313
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
RSSI is a vendor-specific relative index (0-255), while dBm is an
absolute power measurement. Since we report dBm values from iw,
rename the leaf to signal-strength for accuracy.
The trick to starting the scanner mode is to have a dummy network that
cannot associate with anything.
Fixes#1193
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This reverts commit bf1eca0567.
This mess up order if having more than 1 phy, have not been
reproduce the error that got me to introduce this fix from
the beginning.
The sysrepocfg tool does not set up nacm based on $USER, and we now have
the shell 'copy' tool which does. So drop 'cfg' and while we're at it
we also drop the 'edit' alias.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Replace BusyBox udhcpc6 with OpenWrt's odhcp6c for improved DHCPv6
functionality and better integration with Router Advertisements (RA).
The primary motivation is support for a common ISP deployment scenario
where IPv6 addresses are assigned via SLAAC (from Router Advertisements)
and DHCPv6 is used in stateless/information-only mode to provide DNS
servers and other configuration options. This hybrid RA+DHCPv6 setup is
standard practice for many ISPs but was not supported by udhcpc6, which
treats RA and DHCPv6 as separate, non-integrated mechanisms.
Additional benefits of odhcp6c:
- Better IPv6 Prefix Delegation (IA-PD) support with proper handling
of delegated prefix lifetimes and renewal
- Native integration of RA-provided configuration (DNS servers, routes,
addresses) with DHCPv6-provided options
- Support for stateless DHCPv6 via information-only mode
To verify stateless DHCPv6 integration with SLAAC addresses - the ISP
scenario that motivated this migration, a new test case has been added.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Example usage:
./src/statd/python/yanger/yanger -p wifi0 -x "ixll -A ssh enp195s0f0 sudo" ietf-hardware | ./board/common/rootfs/usr/libexec/infix/wifi-channel-map.py
Show the congestion in the 2.4 band.
Signed-off-by: Mattias Walström <lazzer@gmail.com>
* Add support for AP (list connected stations)
* Add scan-mode (Scan without create a fully configured station)
Signed-off-by: Mattias Walström <lazzer@gmail.com>
Add resource-limit and resource-usage containers to YANG model. Podman,
and later conmon, enforce CPU and memory limits in a delegated cgroupsv2
hierarchy managed by Finit.
Resource usage is queried from 'podman inspect', which has more nodes
than what is currently possible to limit.
Requires Finit 4.15, or later.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Validate keys in gen_hostkey() before passing empty keys to shell scripts,
preventing:
Nov 04 2024 10:54:25 confd[2697]: SSH key (genkey) does not exist, generating...
Nov 04 2024 10:54:25 confd[2697]: writing RSA key
Nov 04 2024 10:54:26 confd[2697]: do_convert_from_pkcs8: /tmp/tmp.FH1Hr1 is not a recognised public key format
Also, fix base64 content formatting with proper 64-character line wrapping
using printf+fold instead of echo.
Use PKCS#1 RSA format for public keys as required by netopeer2-server, while
keeping PKCS#8 format for private keys. Use proper ssh-keygen format flag
(PKCS8) for correct conversion.
Fixes#1289
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Simplify fallback MAC detection to return lowest valid MAC address.
This is the easiest to document and explain to end users.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This allows us to gather better product information in /run/system.json
also for x86 based systems. For Qemu x86_64 systems the 'product-name'
changes from 'VM' to 'Standard PC (i440FX + PIIX, 1996)'.
Also, add new 'product-version' field for, e.g., board revisions, and add
missing 'serial-number' value for systems like Rasperry Pi that inject it
in the device tree.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Validate that DHCP options were requested in the parameter request
list before applying them. This prevents malicious or misconfigured
DHCP servers from forcing unwanted configuration changes.
Validates: hostname (12), DNS (6), domain (15), search (119),
router (3), static routes (121), and NTP (42).
Fail-safe behavior: rejects options if config file unavailable.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Resolve race condition between DHCP and configured hostname by introducing
priority-based hostname management using /etc/hostname.d/ directory pattern.
Priority order (highest wins):
90-dhcp-<iface> - DHCP assigned hostname
50-configured - YANG /system/hostname config
10-default - Bootstrap/factory default
The new /usr/libexec/infix/hostname helper reads all sources and applies the
highest priority hostname. It exits early if hostname unchanged, preventing
unnecessary service restarts.
Fixes#1112
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
After some discussion we agreed that this operation is the domain of
confd (or dagger) and any DHCP client should not mess with the admin
state of the interface it runs on.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Basic DHCPv6 support as a per-interface ipv6 setting, not in line with
the IETF YANG model, which has this as a root container.
Note, this also fixes DHCPv4 option inference after the relocation of
/dhcp-client to /interfaces, in 764bd8e.
Fixes#1110
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Check if partition/LABEL is available before trying to run tune2fs and
mount commands on it. This change masks the kernel output:
LABEL=var: Can't lookup blockdev
commne when running `make run` on x86_64 builds.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
In 45efa94 we introduced new mount options for the: 'aux', 'cfg', and
'var' partitions. To save boot time, we also disabled the periodic fsck
check, which does not affect journal replay or other Ext4 safety or
integrity checks. The latter involved calling tune2fs at runtime, but
this caused the following to appear for the 'aux' partition, which is a
reduced ext4 for systems that need to change U-Boot settings, e.g., to
set MAC address on systems without a VPD.
EXT4-fs: Mount option(s) incompatible with ext2
Note, this is a "bogus" warning, setting the fstypt to ext2 in fstab is
not the way around this one. That's been tried.
To make matters worse, the new mount option(s), e.g., 'commit=30', gave
us another set of warnings from the kernel. This was due to the fstype
being 'auto', so the kernel objected to options not being applicable to
every filesystem it tried before ending up with extfs:
squashfs: Unknown parameter 'commit'
vfat: Unknown parameter 'commit'
exfat: Unknown parameter 'commit'
fuseblk: Unknown parameter 'commit'
btrfs: Unknown parameter 'errors'
This commit explicitly sets cfg and var to ext4, leaving mnt as auto, we
also check before calling tune2fs that the partition/disk image is ext4.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>