FreeBSD WiFi management — Apple stack research RESEARCH

What macOS uses for WiFi (it's not wpa_supplicant), what's open source vs closed, why we use wpa_supplicant from ports anyway, and what a hypothetical Apple-shaped WiFi management daemon for FreeBSD would look like. Companion to the IPConfiguration porting plan.

TL;DR

1. Apple's WiFi stack

Multiple components, layered. From hardware up:

ComponentRoleSource
IO80211Family.kext + per-vendor drivers (AirPortBrcmNIC, AppleBCMWLANCore, etc.) Kernel WiFi driver framework. Hardware-specific drivers attach here. Provides the IEEE 802.11 MAC/PHY layer to userspace. Closed
wifid (binary at /usr/libexec/wifid) The main WiFi management daemon. Runs as a launchd job (com.apple.wifid.plist). Owns: AP scanning, BSS selection, association, WPA2/WPA3 4-way handshake, key management, autojoin policy, profile management, fast-roam (802.11r/k/v) coordination. Closed
eapolclient (binary at /usr/libexec/eapolclient) Per-iface 802.1X authentication daemon. wifid spawns one per WiFi iface that needs EAP. Implements EAP-TLS, EAP-PEAP, EAP-TTLS, EAP-FAST, EAP-SIM, EAP-AKA, LEAP. Talks to wifid via Mach IPC for key delivery. Openapple-oss-distributions/eap8021x
EAPOLController.bundle configd plugin coordinating EAP state across services. Acts as the dispatcher between configd's dynamic store and per-iface eapolclient processes. Partial — interfaces in eap8021x repo, controller plugin closed
Apple80211.framework Private 802.11 API the system uses internally. Wraps Mach IPC to wifid. Header in /System/Library/PrivateFrameworks/Apple80211.framework/Headers/Apple80211API.h. Closed
CoreWLAN.framework Public API for third-party apps. Wraps Apple80211. CWInterface, CWNetwork, CWWiFiClient classes. The airport(8) CLI tool is built on this. Headers public, impl closed
AirPort.framework Older WiFi API; mostly superseded by CoreWLAN. Still present for compatibility. Closed
networksetup(8) / airport(8) CLIs User-facing tools for WiFi config. networksetup for general network, airport for WiFi-specific (scan, info, sniff). Both are CoreWLAN clients. Closed
SecKeychain integration WiFi passwords stored in the user's keychain via Security.framework. Per-network credentials, per-user. Security.framework partial open

Net: only the EAP authentication piece is published. The 802.11 association layer, scanning, key management, profile storage — all closed.

1.1 The architecture diagram

+----------------------+ +-----------------------+ | WiFi prefs UI | | Third-party apps | | (System Settings) | | (CWInterface, etc.) | +-----------+----------+ +-----------+-----------+ | | v v +-----------+--------------------------+-----------+ | CoreWLAN.framework (public API) | +-----------+--------------------------+-----------+ | v Mach IPC +-----------+----------+ | Apple80211.framework | +-----------+----------+ | v Mach IPC (com.apple.wifi.client) +-----------+----------+ +--------------------+ | wifid | | eapolclient (per | | (.plist as launchd |<---->| wifi iface) | | job; closed src) | | (eap8021x repo, | +-----------+----------+ | open src) | | +---------+----------+ v | +-----------+----------+ | | IO80211 user client | | | (IOKit Mach port) | | +-----------+----------+ | | | v v +-----------+----------+ +---------+----------+ | IO80211Family.kext | | Keys via Mach back | | + vendor drivers |<-----| to wifid for kernel| | (closed src) | | install | +----------------------+ +--------------------+

2. Open source status — what's actually published

RepoWhat's in itUseful for FreeBSD?
apple-oss-distributions/eap8021x The eapolclient binary source, libeap.a (EAP method library), the EAP-TLS/PEAP/TTLS/FAST/SIM/AKA implementations, EAPOL state machine. Yes, partially. If we ever need EAP methods wpa_supplicant lacks (rare — wpa_supplicant covers all the standard ones). Would need glue to wpa_supplicant or its own supplicant layer.
(no repo) — wifid The main WiFi management daemon n/a — closed source
(no repo) — Apple80211.framework Private 802.11 API n/a — closed source. But the Apple80211API.h header is technically published (via dump tools); reverse-engineered Mach IPC shape is documented in projects like HelloWifid (HelloSystem's exploratory wifid replacement).
(no repo) — IO80211Family.kext Kernel WiFi driver framework n/a — closed source. FreeBSD has its own (net80211(4)); architecturally different.
apple-oss-distributions/IOKitTools kextd, kextload, kextstat — kext loading infrastructure For kmodloader plan, yes (referenced for design). For WiFi, no.
apple-oss-distributions/Security Security.framework — Keychain Services, code signing, certificate handling Maybe long-term for keychain-equivalent; not for WiFi specifically.

So when people say "Apple uses eapolclient" — that's true for the 802.1X piece, and that piece IS open source. But "Apple's WiFi" as a whole is overwhelmingly closed.

3. macOS WiFi stack vs wpa_supplicant

Function-by-function comparison.

FunctionmacOSwpa_supplicant (FreeBSD/Linux)
WPA2-PSK 4-way handshake wifid (closed) wpa_supplicant (open, BSD)
WPA3-SAE association wifid (closed) wpa_supplicant (open) — full RFC 7664 SAE
OWE (Opportunistic Wireless Encryption) wifid (closed) wpa_supplicant (open) — RFC 8110
Open / WEP (legacy) wifid wpa_supplicant — though WEP is mostly removed/deprecated
EAP-TLS / EAP-PEAP / EAP-TTLS eapolclient (semi-open via eap8021x) wpa_supplicant (built-in)
EAP-FAST eapolclient (open via eap8021x) wpa_supplicant (built-in, less-tested than Apple's)
EAP-SIM / EAP-AKA eapolclient (open via eap8021x) wpa_supplicant (built-in but needs SIM card hardware integration)
AP scanning wifid (closed) wpa_supplicant + cfg80211/net80211 (open)
BSS selection / autojoin wifid (closed; uses Apple's signal-strength + history heuristics) wpa_supplicant (configurable; defaults to first match)
802.11r fast roaming wifid (closed) wpa_supplicant (open)
802.11k / 802.11v (radio resource mgmt) wifid (closed) wpa_supplicant (open, partial)
P2P / Wi-Fi Direct wifid (closed; AirDrop is built on this) wpa_supplicant (open, full P2P stack)
AP mode (host the network) wifid (Internet Sharing) hostapd (separate daemon, open)
Profile / credential storage SecKeychain (per-network, per-user) /etc/wpa_supplicant.conf (system-wide) or per-iface configs
User control CLI networksetup, airport(8) wpa_cli
User control GUI System Settings WiFi pane (CoreWLAN client) NetworkManager-applet, iwd, wpa_gui, etc.
DHCP coordination wifid → IPConfiguration via configd dynamic store wpa_supplicant ASSOCIATED state → dhcpcd hook → DHCP attempt

Conclusion: wpa_supplicant covers everything that matters functionally. Apple's wifid has more sophisticated autojoin heuristics and tighter integration with proprietary features (AirDrop, Continuity), but the protocol coverage is essentially equal.

4. What this project ships today

Already in place from the launchd Phase 1 + configd Phase 1d work:

Pragmatic answer for FreeBSD WiFi today: wpa_supplicant + wpa_cli. Battle-tested across many BSDs and Linux distros. Full WPA3 / SAE / OWE / EAP coverage. Coordinates cleanly with dhcpcd. The "not Apple-shaped" critique is real but the alternative (porting Apple's stack) is closed-source-blocked. wpa_supplicant is what every other FreeBSD-based desktop uses (GhostBSD, NomadBSD, HelloSystem, MidnightBSD — all of them).

5. Hypothetical: a wifid-shaped daemon for FreeBSD

If we ever wanted Apple-shape WiFi management on FreeBSD — exposing a CoreWLAN-equivalent API to apps — the realistic shape would be a thin daemon (call it wifid-fbsd or org.freebsd.wifid) that:

  1. Talks to wpa_supplicant via its UNIX control socket (/var/run/wpa_supplicant/<iface>). Standard protocol: STATUS, SCAN, SCAN_RESULTS, LIST_NETWORKS, ADD_NETWORK, SET_NETWORK, ENABLE_NETWORK, SELECT_NETWORK, plus event monitoring (ATTACH + async events: CTRL-EVENT-CONNECTED, CTRL-EVENT-DISCONNECTED, CTRL-EVENT-SSID-TEMP-DISABLED).
  2. Exposes a CoreWLAN-equivalent API over DO IPC (consistent with the project's Mach-IPC-replacement choice). ObjC @protocol sketch:
    @protocol NCWiFiClient
    - (NSArray<NCWiFiInterface *> *)interfaces;
    @end
    
    @protocol NCWiFiInterface
    - (NSString *)ssid;
    - (NSString *)bssid;
    - (NSNumber *)rssi;
    - (NSNumber *)txRate;
    - (NSString *)hardwareAddress;
    - (BOOL)powerOn;
    - (NCStatus)setPower:(BOOL)on;
    
    - (NSArray<NCWiFiNetwork *> *)scanForNetworksAndReturnError:(NSError **)err;
    - (NCStatus)associateToNetwork:(NCWiFiNetwork *)net
                          password:(NSString *)pwd;
    - (NCStatus)disassociate;
    @end
    
    @protocol NCWiFiNetwork
    - (NSString *)ssid;
    - (NSString *)bssid;
    - (NSNumber *)rssi;
    - (NSNumber *)channel;
    - (NCSecurityType)securityType;  // open, WPA2-PSK, WPA3-SAE, EAP, etc.
    @end
  3. Stores credentials in /Local/Library/Preferences/Network.plist (eventually keychain-backed when we have one). Translates user intent into wpa_supplicant SET_NETWORK calls. Persists across reboots.
  4. Coordinates with dhcpcd via the SCDynamicStore-equivalent. Publishes State:/Network/Interface/<wlan>/AirPort with SSID_STR, BSSID, CHANNEL, SecurityType. dhcpcd's hook reads this and times its DHCP attempts after associate.
  5. Optionally pulls in Apple's eap8021x source for EAP methods wpa_supplicant lacks or implements differently. Only if needed; wpa_supplicant covers the standard ones.

Effort estimate: ~3-4k LOC of ObjC, ~2 person-months. Way smaller than the IPConfiguration port because we're not reimplementing the protocol layer — wpa_supplicant stays as the protocol implementation. We're just wrapping it in an Apple-shape API.

Would we do this? Only if Gershwin's WiFi-config UI explicitly wants the CoreWLAN API surface for code symmetry with Mac apps. Today, users using wpa_cli + a launchd plist for wpa_supplicant works fine; nothing is functionally broken. This is a cosmetic / API-symmetry investment, not a functional one.

5.1 Prior art

6. Open questions

Q1. Should we ship a launchd plist for wpa_supplicant? Today wpa_supplicant runs only when user-initiated. A plist (org.freebsd.wpa_supplicant.plist) running per wifi iface at boot would auto-associate to known SSIDs from /etc/wpa_supplicant.conf. Trivial to add — just hasn't been a priority given Phase 1 was wired-network focused.
Q2. Where do WiFi credentials live in the eventual netconfigd Phase 5+? Inline in Network.plist (plaintext, like wpa_supplicant.conf today) or a keychain-equivalent layer? Apple did inline initially, added keychain later. Probably the same path for us. Keychain port itself is its own multi-month project (Security.framework dependencies).
Q3. Would integrating eap8021x add value over wpa_supplicant? Apple's EAP-FAST and EAP-AKA implementations are reportedly more battle-tested in carrier (cellular) deployments. But we don't ship cellular hardware support, so this is academic. Defer.
Q4. P2P / Wi-Fi Direct support? Apple uses this for AirDrop. wpa_supplicant has full P2P stack. Wiring it up needs a discovery + transfer layer above (Apple has the AWDL/Bonjour layer). Punt to a future Bonjour / mDNSResponder phase.

7. References