Reviewed-on: #40 Co-authored-by: Koda YeenBean <n122330@gmail.com>
7.0 KiB
Agent guide
Use this file as the first-pass context for changes in this package. Read only
the module(s) relevant to the task; the public interfaces in src/*.h usually
provide enough context before opening an implementation.
Project in one paragraph
openUF is a single-process C daemon for OpenWrt. It makes an OpenWrt access
point look like a UniFi AP: main.c periodically sends L2 discovery, LLDP, and
encrypted HTTP inform packets. Controller responses can update persistent
adoption state and apply WiFi configuration through UCI. There is no internal
threading or event framework; the main loop runs once per second.
Source map
| Concern | Start here | Responsibility |
|---|---|---|
| Lifecycle and scheduling | src/main.c |
Load config/state, choose model, run announce/inform/LLDP timers |
| User configuration | src/config.[ch], files/openuf.conf |
Parse static daemon settings and defaults |
| Persistent controller state | src/state.[ch] |
Read/write /etc/openuf/state.json |
| Inform exchange | src/inform/inform.c, src/inform.h |
Orchestrate payload, TNBU, HTTP, and response stages |
| Inform internals | src/inform/{payload,packet,response}.c |
Build telemetry, encode TNBU packets, handle commands |
| Transport and encryption | src/http.[ch], src/crypto.[ch] |
Raw HTTP/1.0 client and AES-CBC/AES-GCM helpers |
| WiFi provisioning | src/wlan/{provision,legacy,radio,uci}.c, src/wlan.h |
Translate controller config to UCI |
| WiFi telemetry/helpers | src/wlan/{telemetry,common}.c |
Report VAP state and share translations |
| Device telemetry | src/sysinfo.[ch], src/clients.[ch] |
Read proc/sysfs/iw/bridge/dnsmasq data |
| Discovery/topology | src/announce.[ch], src/lldp.[ch] |
UniFi UDP announce and LLDP send/read |
| Emulated hardware | src/models.c, src/ufmodel.h |
Model registry, radios, ports, and band-to-radio mapping |
| Packaging/service | Makefile, files/openuf.init |
OpenWrt package recipe and procd service |
Runtime flow: main() -> inform_send() -> build telemetry -> encrypt ->
http_post() -> decrypt response -> inform_handle_response() -> optionally
wlan_apply_config()/wlan_apply_system_cfg() and state_save().
Important invariants
- Treat the TNBU packet layout, byte order, flags, and key selection as protocol
compatibility constraints. An unadopted device must use
DEFAULT_AUTH_KEY. cfgversionmeans successfully applied controller configuration. On an apply failure it is reset to"0"so the controller retries.- Increment
OPENUF_CONFIG_SCHEMAwhen a persisted configuration must be reapplied after an upgrade. - Only WiFi sections managed by this daemon may be removed. Their names start
with
openuf_; preserve unrelated UCI sections. - Keep model-specific radio and port assumptions in
models.c, not scattered across protocol or WLAN code. - Logging is opt-in because persistent writes wear flash. Debug level 2 may log decrypted credentials; never enable it by default or expose full auth keys.
- This daemon runs as root and can change network config, send raw frames, and reboot. Do not run it on a development host as a test.
- The target uses OpenWrt/musl and constrained hardware. Prefer bounded buffers, explicit ownership, no new heavy dependency, and no background thread unless the design requires one.
Build and validation
The primary validation is the package cross-build. From the OpenWrt root (two directories above this package), run:
make package/OpenUniFi/compile
Use V=s when compiler diagnostics need more context. Avoid a top-level
make clean; if a clean rebuild is necessary, use:
make package/OpenUniFi/clean
make package/OpenUniFi/compile
Makefile.standalone is for compiling on an OpenWrt device with development
packages installed; it is not a host-side substitute for the cross-build.
Architecture pages for the Gitea Wiki are generated from the recursive C source tree into a separate checkout. After source or architecture changes, run:
./scripts/docs/generate-wiki.py --output /path/to/openunifi.wiki
./scripts/docs/generate-wiki.py --check --output /path/to/openunifi.wiki
There is currently no automated test suite. For documentation-only changes, check paths and commands against the source and package Makefile. For C changes, the cross-build is the minimum verification; report any device/controller behavior that still needs manual testing.
Change discipline
- Keep headers as the concise contract and implementation detail in
.cfiles. - Update
MakefileandMakefile.standalonetogether when adding/removing a source file or library. - Update
files/openuf.conf,config.[ch], and the README together when changing a user-facing setting. - Update
ufmodel.h, every affected model entry, and telemetry/WLAN consumers together when changing model data. - Preserve controller compatibility unless the task explicitly changes it. Call out changes to payload fields, encryption, adoption, UCI, or persistent state in the handoff.
- Do not commit generated binaries, OpenWrt build output, runtime state, logs, or captured protocol payloads.
Environment pitfalls and shared discoveries
- In this workspace, the Codex
apply_patchhelper is currently unusable. It fails withbwrap: No permissions to create a new namespace, including when invoked from an approved command outside the normal sandbox. Do not spend time retrying it or tracing its symlink after seeing this known error. - For repository edits, use
git apply --recountwith a focused unified diff as the fallback.--recountavoids failures caused by manually miscounted hunk lengths. Review the resultinggit diffand rungit diff --checkafterward. Preserve unrelated worktree changes exactly as with any other editing method. - Ordinary read-only commands may fail with the same
bwrapnamespace error. When the command is safe and required, rerun it using the environment's normal escalation/approval mechanism instead of investigating the namespace setup. - OpenWrt's release SDK host tools and preload libraries are x86-64. When using
them through QEMU on an ARM runner, never export the SDK's fakeroot library as
host
LD_PRELOAD; carry it in a private variable and pass it to the bundled x86 loader with--preload. Validate changes with an emulated build through mbedTLS packaging, where a broken handoff appears as alibrary/...dependency.
Agents must preserve useful environment knowledge for later agents. When a new pitfall or workaround is verified to be deterministic or repeatedly encountered, add a short entry to this section before handoff. Keep these entries actionable and specific: include the recognizable failure, the confirmed workaround, and any validation required afterward.
Do not record transient command failures, guesses, lengthy logs, credentials, auth keys, host secrets, or details that only apply to a single task. If a discovery could weaken safety controls or requires broader permissions, report it to the user instead of documenting a bypass.