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.
wpa_supplicant. macOS has its own proprietary WiFi stack centered on wifid (the WiFi management daemon), Apple80211.framework (private 802.11 API), and CoreWLAN.framework (public app API).wifid talking to a closed-source IO80211Family kernel framework. Nobody outside Apple has visibility into it.eapolclient. Apple publishes the EAP / 802.1X authentication code as apple-oss-distributions/eap8021x — handles EAP-TLS, EAP-PEAP, EAP-FAST, EAP-SIM, EAP-AKA. But this only covers the authentication side; it doesn't do 802.11 association.wpa_supplicant from ports. Already in pkglist.txt alongside dhcpcd. Battle-tested, portable, full WPA3-SAE / OWE / EAP coverage, well-maintained upstream. Same client every Linux distro and FreeBSD-based system uses.wifid — it's closed source, depends on closed-source IO80211Family kernel framework that doesn't exist on FreeBSD. But Apple's API surface (CoreWLAN, the airport(8)-equivalent) could be replicated in a FreeBSD-side daemon that talks to wpa_supplicant over its control socket. That's the only realistic Apple-shape WiFi path on FreeBSD. Out of scope for now; documented here so we don't relitigate.Multiple components, layered. From hardware up:
| Component | Role | Source |
|---|---|---|
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. | Open — apple-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.
| Repo | What's in it | Useful 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.
wpa_supplicantFunction-by-function comparison.
| Function | macOS | wpa_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.
Already in place from the launchd Phase 1 + configd Phase 1d work:
security/wpa_supplicant from ports — supersedes the base FreeBSD wpa_supplicant. Newer WPA3-SAE / OWE coverage, current EAP methods, more aggressive CVE backports. Listed in pkglist.txt.wpa_supplicant hook detects the control socket on a wifi iface and gates DHCP behind ASSOCIATED state. Out-of-the-box pairing, no extra glue./etc/wpa_supplicant.conf or wpa_cli. A Phase 2+ enhancement (in the configd plan) is to introduce a netconfigd-managed flow where Network.plist declares wpa_supplicant config and netconfigd materializes it per wifi iface.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).
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:
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).@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
/Local/Library/Preferences/Network.plist (eventually keychain-backed when we have one). Translates user intent into wpa_supplicant SET_NETWORK calls. Persists across reboots.State:/Network/Interface/<wlan>/AirPort with SSID_STR, BSSID, CHANNEL, SecurityType. dhcpcd's hook reads this and times its DHCP attempts after associate.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.
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.
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).
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.
net80211(4): man 4 net80211