Files
fips/packaging/openwrt-ipk/Makefile
T
ArjenandJohnathan Corgan 054d17aac5 feat(openwrt): 802.11s open-mesh backhaul support
Router-to-router radio backhaul over an open 802.11s mesh interface,
with FIPS providing all encryption (Noise IK), authentication, and
routing on top of bare L2 neighbor links. The mesh runs OPEN with
mesh_fwding 0 — SAE would duplicate the Noise layer and force ath10k
raw mode, and FIPS is the routing layer — so the Noise handshake is the
real auth/encryption boundary and FIPS's spanning tree does the routing.

fips-mesh-setup: an opt-in UCI helper that creates a per-radio
mesh-point interface (radio0 -> fips-mesh0, radio1 -> fips-mesh1;
trailing-digit derivation with a free-index fallback and a collision
guard). Radio setup stays opt-in — a package must not commandeer radios
on install. 'remove' takes an optional radio and otherwise removes all
instances. Dual-band routers get one instance per radio; FIPS treats the
two backhaul paths as failover, not multipath: it keeps one active link
per peer (cross-connection resolution picks a single winner), and the
second band stands by, re-establishing the peer after keepalive timeout —
traffic never uses both bands at once.

fips.yaml ships the mesh0/mesh1 Ethernet-transport entries commented
out, so a stock install that never creates fips-mesh* logs no per-boot
"interface missing" bind warning. fips-mesh-setup uncomments the matching
meshN block when it creates the interface and re-comments it on remove,
so the flash-and-drop-in flow needs no manual config edit. The file is
rewritten 0600-first (it may hold an inline nsec) via an atomic replace.

Two field-found silent non-peering causes are surfaced by the helper and
the guide:

- Same channel: mesh points only peer on a shared channel, and 'auto'
  lets each radio pick its own. The helper prints the radio's
  band/channel and warns loudly on 'auto' with the exact uci command to
  pin one; the how-to gains an ordered no-peers triage (channel mismatch,
  on-air scan check, DFS CAC wait, regdomain).
- STA channel capture: a client (sta) interface drags the whole radio to
  its upstream AP's channel, so a mesh pinned elsewhere never joins and
  does not recover until the STA disconnects. The helper warns when the
  target radio carries a STA; the guide documents the incompatibility of a
  roaming uplink with a fixed-channel mesh on the same radio.

Both the create and remove paths run 'wifi reload', which briefly drops
every client AP on all radios; the how-to sets that expectation.

Regression test: the shipped OpenWrt fips.yaml must parse via the real
Config deserializer in both states — as shipped (mesh inactive) and after
the uncomment the helper performs.

Packaging: the helper is installed across the ipk/apk/buildroot paths
(three synced copies), with the CI structural checks and shellcheck
targets extended to cover it. Full guide in
docs/how-to/set-up-80211s-mesh-backhaul.md.
2026-07-16 05:48:04 +00:00

137 lines
5.1 KiB
Makefile

include $(TOPDIR)/rules.mk
PKG_NAME:=fips
PKG_VERSION:=0.1.0
PKG_RELEASE:=1
# Pin to a specific commit for reproducible builds.
# Update PKG_SOURCE_VERSION and PKG_MIRROR_HASH when upgrading.
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://github.com/jmcorgan/fips.git
PKG_SOURCE_VERSION:=master
PKG_MIRROR_HASH:=skip
PKG_MAINTAINER:=FIPS Network
PKG_LICENSE:=MIT
PKG_LICENSE_FILES:=LICENSE
# Rust host toolchain must be present in the build system.
# In the OpenWrt build system, enable via: make menuconfig → Advanced → Rust
PKG_BUILD_DEPENDS:=rust/host
PKG_BUILD_PARALLEL:=1
include $(INCLUDE_DIR)/package.mk
# ---------------------------------------------------------------------------
# Map OpenWrt ARCH to Rust target triple.
# All OpenWrt targets use musl libc.
# ---------------------------------------------------------------------------
ifeq ($(ARCH),aarch64)
RUST_TARGET:=aarch64-unknown-linux-musl
else ifeq ($(ARCH),x86_64)
RUST_TARGET:=x86_64-unknown-linux-musl
else ifeq ($(ARCH),mipsel)
RUST_TARGET:=mipsel-unknown-linux-musl
else ifeq ($(ARCH),mips)
RUST_TARGET:=mips-unknown-linux-musl
else ifeq ($(ARCH),arm)
# OpenWrt ARM targets predominantly use hardfloat ABI.
# Override RUST_TARGET in your build if your target uses softfloat.
RUST_TARGET:=arm-unknown-linux-musleabihf
else
$(error Unsupported architecture: $(ARCH). Add a RUST_TARGET mapping in packaging/openwrt/Makefile.)
endif
RUST_RELEASE_DIR:=$(PKG_BUILD_DIR)/target/$(RUST_TARGET)/release
define Package/fips
SECTION:=net
CATEGORY:=Network
TITLE:=FIPS Mesh Network Daemon
URL:=https://github.com/jmcorgan/fips
DEPENDS:=+kmod-tun +kmod-br-netfilter +kmod-nft-nat \
+kmod-nf-conntrack +ip-full
endef
define Package/fips/description
FIPS is a distributed, decentralized mesh networking daemon. It routes
traffic across nodes connected over UDP, TCP, or raw Ethernet (EtherType
0x2121). Provides a TUN interface (fips0) with ULA IPv6 mesh addressing
and a local DNS responder for .fips name resolution.
Four binaries are installed:
fips — mesh daemon
fipsctl — CLI control and inspection tool
fipstop — live TUI dashboard (requires a terminal)
fips-gateway — outbound LAN gateway (not started by default)
endef
# ---------------------------------------------------------------------------
# Build
#
# We write a temporary .cargo/config.toml to set the cross-linker without
# polluting the source tree. CARGO_HOME is scoped to the staging directory
# to avoid touching the developer's ~/.cargo during SDK builds.
# ---------------------------------------------------------------------------
define Build/Compile
mkdir -p $(PKG_BUILD_DIR)/.cargo
printf '[target.$(RUST_TARGET)]\nlinker = "$(TARGET_CC)"\n' \
> $(PKG_BUILD_DIR)/.cargo/config.toml
cd $(PKG_BUILD_DIR) && \
CARGO_HOME=$(STAGING_DIR_HOST)/share/cargo \
cargo build \
--release \
--target $(RUST_TARGET) \
--bin fips \
--bin fipsctl \
--bin fipstop \
--bin fips-gateway
endef
define Package/fips/install
# Binaries
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(RUST_RELEASE_DIR)/fips $(1)/usr/bin/fips
$(INSTALL_BIN) $(RUST_RELEASE_DIR)/fipsctl $(1)/usr/bin/fipsctl
$(INSTALL_BIN) $(RUST_RELEASE_DIR)/fipstop $(1)/usr/bin/fipstop
$(INSTALL_BIN) $(RUST_RELEASE_DIR)/fips-gateway $(1)/usr/bin/fips-gateway
# 802.11s mesh backhaul setup helper
$(INSTALL_BIN) $(CURDIR)/files/usr/bin/fips-mesh-setup $(1)/usr/bin/fips-mesh-setup
# procd init script
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_BIN) $(CURDIR)/files/etc/init.d/fips $(1)/etc/init.d/fips
$(INSTALL_BIN) $(CURDIR)/files/etc/init.d/fips-gateway $(1)/etc/init.d/fips-gateway
# Default config — installed as CONF so opkg will not overwrite it on upgrade
$(INSTALL_DIR) $(1)/etc/fips
$(INSTALL_CONF) $(CURDIR)/files/etc/fips/fips.yaml $(1)/etc/fips/fips.yaml
# Firewall helper script (called by UCI include and hotplug)
$(INSTALL_BIN) $(CURDIR)/files/etc/fips/firewall.sh $(1)/etc/fips/firewall.sh
# dnsmasq drop-in: forward .fips queries to the FIPS DNS responder
$(INSTALL_DIR) $(1)/etc/dnsmasq.d
$(INSTALL_DATA) $(CURDIR)/files/etc/dnsmasq.d/fips.conf $(1)/etc/dnsmasq.d/fips.conf
# sysctl: enable br_netfilter so AF_PACKET sees frames on bridge member ports
$(INSTALL_DIR) $(1)/etc/sysctl.d
$(INSTALL_DATA) $(CURDIR)/files/etc/sysctl.d/fips-bridge.conf $(1)/etc/sysctl.d/fips-bridge.conf
$(INSTALL_DATA) $(CURDIR)/files/etc/sysctl.d/fips-gateway.conf $(1)/etc/sysctl.d/fips-gateway.conf
# Hotplug: apply firewall rules when the FIPS TUN interface comes up
$(INSTALL_DIR) $(1)/etc/hotplug.d/net
$(INSTALL_BIN) $(CURDIR)/files/etc/hotplug.d/net/99-fips $(1)/etc/hotplug.d/net/99-fips
# UCI defaults: one-time first-boot firewall and module setup
$(INSTALL_DIR) $(1)/etc/uci-defaults
$(INSTALL_BIN) $(CURDIR)/files/etc/uci-defaults/90-fips-setup $(1)/etc/uci-defaults/90-fips-setup
# sysupgrade: preserve /etc/fips/ (config + identity key) across firmware upgrades
$(INSTALL_DIR) $(1)/lib/upgrade/keep.d
$(INSTALL_DATA) $(CURDIR)/files/lib/upgrade/keep.d/fips $(1)/lib/upgrade/keep.d/fips
endef
$(eval $(call BuildPackage,fips))