NextBSD IPConfiguration — porting plan Filed under: freebsd-launchd-mach (v2) effort SHIPPED through iter 8

A phased plan to replace dhcpcd in this project with a port of Apple's IPConfiguration daemon. Targets freebsd-launchd-mach (v2) — the Mach IPC + libxpc + libdispatch track. Shipped through iter 8 as a standalone Mach daemon at src/IPConfiguration/, NOT as a configd plugin (this repo's configd has no plugin loader). DHCPv4 INIT→BOUND, RFC 5227 ARP probe, IPv6 RA/SLAAC, SCDynamicStore publish, MIG service worker, and the Apple-shape ipconfig(8) CLI are live.

Revision 2026-05-23 — architecture pivot + status update. This plan originally targeted the sibling freebsd-launchd (AF_UNIX/DO) repo as a netconfigd plugin. Refactored 2026-05-23 to target freebsd-launchd-mach (v2): standalone Mach daemon (this repo's configd has no plugin loader), Mach service com.apple.IPConfiguration, ipconfig.defs MIG IDL retained. SHIPPED through iter 8 — PRs #42–#51 merged covering daemon skeleton, full DHCPv4 INIT→BOUND, ARP probe (RFC 5227), IPv6 RA/SLAAC, SCDynamicStore publish, MIG service worker thread, IPCONFIGD_FAST_LEASE renewal gate, and the Apple-shape ipconfig(8) CLI at /usr/sbin/ipconfig. iter 7b (DHCPv6 stateful) deferred indefinitely — SLAAC covers the common case; Apple's DHCPv6Client.c is 3717 LOC with no CI validation path (QEMU SLIRP doesn't run a DHCPv6 server). Future iters grow the MIG surface as real consumers need it (Apple's ipconfig.defs has 21+ routines; this repo has 2).

TL;DR

1. Goal & non-goals

1.1 Goal

Replace dhcpcd in the freebsd-launchd-mach (v2) project with a port of Apple's IPConfiguration. End state (now reached through iter 8): a standalone Mach daemon /usr/sbin/ipconfigd owns DHCPv4 / RA-SLAAC / ARP processing for the first non-loopback Ethernet; state lands in this repo's SCDynamicStore (via Mach RPC to configd at com.apple.SystemConfiguration) under the canonical Apple key namespace (State:/Network/Service/<UUID>/IPv4 + /IPv6); client tools (scutil, ipconfig(8)) reach the daemon via MIG over mach_msg on service name com.apple.IPConfiguration.

1.2 Non-goals

2. Apple source overview (reference)

For context: Apple's bootp repo total scope. This repo's port is much smaller — a fresh-written thin daemon at src/IPConfiguration/ that draws on Apple's protocol cores rather than re-shaping Apple's plugin tree wholesale.

ComponentApple LOCThis repo's approach
IPConfiguration.bproj/ (Apple's daemon-as-plugin)39,722Fresh thin standalone daemon; protocol cores referenced as Apple-shape oracles.
bootplib/ (shared protocol library)26,997Reference for option tables + RA parser + DHCP packet structs.
IPConfiguration_framework/ (Mach client API library)5,228Not built. CLI talks MIG directly via stubs from ipconfig.defs.
IPConfigurationHelper/ (XPC helper for PvD HTTPS fetch)1,250Not built. PvD deferred indefinitely.
ipconfig.tproj/ (CLI tool)1,630Fresh Apple-shape ipconfig(8) in iter 8 (ipconfig.c).
Total Apple scope~74,827This repo: a few thousand LOC of fresh-written daemon code.
Out-of-scope siblings (bootpd, bsdpd, dhcp6d, rtadvd, BSDPClient, netbootdisk, tests)~24,000Not imported.

Largest single Apple files (for orientation):

3. Architecture (shipped)

+------------------------------------+ | scutil / ipconfig(8) / consumers | +------------------+-----------------+ | MIG over mach_msg | (com.apple.IPConfiguration) v +--------------------+ +--------+----------+ | configd | Mach RPC | ipconfigd | | (SCDynamicStore) |<------------>| /usr/sbin/ | | com.apple. | publish | ipconfigd | | SystemConfig. | IPv4/IPv6 | | +--------------------+ | - dhcp_discover | | - apply_lease | +--------------------+ BPF / | - apply_lease_v6 | | kernel | PF_ROUTE / | - arp_probe | | (BPF, route, |<------------>| - ra_listen | | ifconfig, SLAAC) | ICMPv6 RA | - lease_loop | +--------------------+ sockets | - sc_publish | | - mach_service | | - bound_state | +-------------------+

Standalone Mach daemon (NOT a configd plugin — this repo's configd has no plugin loader). The two daemons live in separate address spaces and communicate exclusively over Mach RPC. ipconfigd registers Mach service com.apple.IPConfiguration; it publishes to com.apple.SystemConfiguration via sc_publish.c. Subscribes to nothing yet — DHCP fires once at boot on the first non-loopback Ethernet. Hot-plug / multi-interface deferred.

4. Shipped files (file-by-file)

Source tree lives at src/IPConfiguration/ in the freebsd-launchd-mach repo. Translation units below are what's on disk through iter 8 (PRs #42–#51).

FileRoleIter
src/IPConfiguration/ipconfigd.cMain daemon loop. Wires DHCPv4 + RA + lease loop. Boot-time first-Ethernet selection.1 → 7a
src/IPConfiguration/dhcp_discover.cDHCPv4 state machine (DISCOVER / OFFER / REQUEST / ACK) over BPF.2 → 3
src/IPConfiguration/apply_lease.cSIOCAIFADDR (assign IPv4 address) + RTM_ADD (default route).3
src/IPConfiguration/apply_lease_v6.cEUI-64 SLAAC + IFDISABLED clear + SIOCAIFADDR_IN6 + RTM_ADD ::/0.7a
src/IPConfiguration/arp_probe.cRFC 5227 ARP probe + announce over BPF. BIOCGBLEN = 4096 rxbuf.6
src/IPConfiguration/ra_listen.cICMPv6 Router Advertisement listener (RFC 4861).7a
src/IPConfiguration/sc_publish.cSCDynamicStore publish over Mach RPC (CF translation unit) — State:/Network/Service/<UUID>/IPv4 + /IPv6.4, 7a
src/IPConfiguration/mach_service.cMIG service worker thread; bootstrap_check_in + mach_msg_server loop on com.apple.IPConfiguration.5a
src/IPConfiguration/lease_loop.cRFC 2131 RENEWING/REBINDING timers; IPCONFIGD_FAST_LEASE env var collapses the T1/T2 wait for CI.4, 5b
src/IPConfiguration/bound_state.cShared lease state readable by the MIG worker (ifname / IP / lease metadata).5a
src/IPConfiguration/ipconfig.citer 8 CLI at /usr/sbin/ipconfig — Apple-shape command-table dispatch with getifaddr + ifcount subcommands.8
src/IPConfiguration/ipconfig.defsMIG IDL — this repo's slim subset. 2 routines today: ipconfig_if_count + ipconfig_if_addr. (Apple's has 21+.)5a
src/IPConfiguration/ipconfigtest.cTest binary exercising the lease pipeline directly.3+
src/IPConfiguration/ipconfigrpctest.cTest binary exercising the MIG client-server path end-to-end.5a+

4.1 Deleted on import (Apple subtrees out of scope)

4.2 Fresh-written for this repo (Apple shapes, Mach-IPC track)

Rather than line-for-line reshape Apple's ipconfigd.c (10k LOC of plugin shell + power events + service lifecycle + Mach RPC server), iter 1–8 wrote a thin daemon from scratch that reuses Apple's protocol cores (DHCPv4 state machine, DHCP option tables, RA parser, ARP packet build) and replaces everything Darwin-specific with native FreeBSD code.

FileApple LOC (origin)What changed in our port
mach_service.cserver.c (654)Fresh-written Mach service: bootstrap_check_in + worker thread running mach_msg_server on com.apple.IPConfiguration. No BSM audit-token entitlement check (no Apple entitlement system in this repo); identity gating deferred.
ipconfigd.cipconfigd.c (10,312)Fresh thin daemon main loop. First-Ethernet selection + DHCPv4 launch + RA listener thread + lease loop. Power-event handlers (IORegisterForSystemPower) dropped entirely. No plugin shell — runs as a regular launchd-managed daemon at /usr/sbin/ipconfigd.
sc_publish.c(scattered in ipconfigd.c)Fresh CF translation unit. Builds the IPv4 / IPv6 dictionaries and publishes via Mach RPC to com.apple.SystemConfiguration. Avoids the plugin model entirely.
ipconfig.cipconfig.tproj/client.c (1,630)Fresh Apple-shape CLI. Command-table dispatch (getifaddr, ifcount) calling the MIG client stubs generated from ipconfig.defs. Same Mach-IPC shape as Apple — different (smaller) routine set.
ipconfig.defsbootplib/ipconfig.defs (196, 21+ routines)Slim 2-routine subset: ipconfig_if_count + ipconfig_if_addr. Grows as real consumers arrive.
ifutil.c (Darwin-specific ioctls)ifutil.c (2,211)Replaced by direct ioctl calls in apply_lease.c + apply_lease_v6.c. SIOCAUTOADDR / SIOCSIFL4S / SIOCCLAT46_* / SIOCPROTOATTACH not used. CLAT46 + L4S features unavailable by design.
HostUUIDHostUUID.c (56)Use sysctlbyname("kern.hostuuid", ...). ISO first-boot seeds kern.hostuuid if blank.
IPHXPCServer.m + IPHPvDInfoRequestServer.m (PvD helper)1,167Not built. PvD support deferred indefinitely; RFC 8801 deployment is rare.
os_log wiringthroughoutMapped to syslog(3), same shape as the launchd-mach mylog.h.

4.3 Apple protocol-core inventory (reference)

Files in Apple's tree that would be portable verbatim (or near) on a future expansion. Today this repo's fresh-written daemon uses these as reference oracles rather than importing them directly — the iter 1–8 codebase is much smaller. Listed here for orientation when growing the surface in future iters.

FileApple LOCNotes
IPConfiguration.bproj/dhcp.c4,660DHCPv4 state machine. One MobileGestalt call at line 447 to stub.
IPConfiguration.bproj/DHCPv6Client.c3,717DHCPv6 state machine. RFC 8415 retry constants in bootplib/DHCPv6.h:79-94 — no source changes.
IPConfiguration.bproj/arp_session.c2,505ARP probe/announce/conflict via BPF. bpflib is BSD-portable.
IPConfiguration.bproj/rtadv.c2,133RA consumer; PIO/RDNSS/DNSSL/PvD state.
IPConfiguration.bproj/bootp_session.c827Raw IP/UDP DHCPv4 socket on port 68.
IPConfiguration.bproj/RTADVSocket.c801ICMPv6 RS sender / RA receiver via <netinet6/nd6.h>.
IPConfiguration.bproj/CGA.c711RFC 3972 Cryptographically Generated Addresses.
IPConfiguration.bproj/DHCPv6Socket.c685UDP socket on port 546.
IPConfiguration.bproj/linklocal.c577IPv4LL (RFC 3927).
IPConfiguration.bproj/manual.c + manual_v6.c742Static IP config method.
IPConfiguration.bproj/DHCPDUIDIAID.c371DUID/IAID generation, persisted to DUID_IA.plist.
IPConfiguration.bproj/timer.c + FDSet.c494libdispatch-source timers + FD wrappers.
bootplib/RouterAdvertisement.c1,788RA parser/builder.
bootplib/dhcp_options.c1,716DHCPv4 option parse/build.
bootplib/DHCPv6Options.c1,637DHCPv6 option parse/build.
bootplib/DNSEncryptedServers.c + DNSNameList.c2,868RFC 1035 DNS-name compression + DDR.
bootplib/interfaces.c1,589getifaddrs + SIOCGIFMEDIA; few Darwin-only IFEF_/IFXNAMSIZ usages.
bootplib/cfutil.c1,068CFPropertyList helpers — corebase already provides.
bootplib/IPv4ClasslessRoute.c651Option 121 parser.
bootplib/NICache.c646DHCPv4 binding cache.
bootplib/arp.c633ARP packet build/parse.
bootplib/{ptrlist,dynarray,util}.c~700Utility types.
bootplib/DHCPDUID.c283DUID factory.
bootplib/inetroute.c263Route table reader.
bootplib/udp_transmit.c245Raw UDP send.
bootplib/bpflib.c204BPF socket open/filter.

5. MIG IDL (Mach-IPC track)

Apple's bootplib/ipconfig.defs is 196 LOC, 21+ routines. This repo retains the same MIG-over-mach_msg shape but ships a slim 2-routine subset as src/IPConfiguration/ipconfig.defs. The MIG-generated stubs link into both the daemon (mach_service.c) and the CLI (ipconfig.c).

subsystem ipconfig 17000;

#include <mach/std_types.defs>
#include <mach/mach_types.defs>

/* Iter 5a — 2 routines. */
routine ipconfig_if_count(
        server          : mach_port_t;
    out  count           : int);

routine ipconfig_if_addr(
        server          : mach_port_t;
     in  ifname          : (string_t);
    out  ipv4            : (string_t);
    out  result          : int);

Future routines (Apple's full surface) grow the IDL as real consumers arrive — see §12 Future iters. Caller-identity gating on these MIG entry points is currently TODO; no BSM audit-token / Apple entitlement system exists in this repo. Production hardening would gate on the Mach audit-token PID + uid via set_security_token already used elsewhere in the launchd-mach kernel module (cf. fork_bsport).

6. Kernel events: publish-only today

Apple's ipconfigd subscribes to seven SCDynamicStore key suffixes (kSCEntNetLink, kSCEntNetAirPort, kSCEntNetRefreshConfiguration, kSCEntNetIPv6, kSCEntNetIPv4ARPCollision, kSCEntNetIPv6RouterExpired, kSCEntNetNAT64) translated from kernel events by the sibling KernelEventMonitor.bundle configd plugin. This repo's ipconfigd currently subscribes to none of them — it fires DHCPv4 once at boot on the first non-loopback Ethernet interface, runs the ARP probe, then publishes the resulting lease.

Concretely, today (iter 8):

Hot-plug, multi-interface, link-flap handling, and ARP-collision recovery all wait on a KEM-equivalent. The future-iters plan calls for hwregd-driven subscription rather than a configd KEM plugin (this repo has no plugin loader). PF_ROUTE → publish mapping is the same on FreeBSD vs. Darwin:

FreeBSD PF_ROUTE messageSC key suffix (when wired)
RTM_IFINFO (link state from if_data.ifi_link_state)State:/Network/Interface/<bsd>/Link
RTM_NEWADDR (AF_INET)State:/Network/Interface/<bsd>/IPv4
RTM_NEWADDR (AF_INET6)State:/Network/Interface/<bsd>/IPv6
RTM_DELADDRsame keys, recomputed
RTM_IFANNOUNCE (IFAN_ARRIVAL/IFAN_DEPARTURE)recompute interface list

7. Apple-specific dependencies

DependencyWhereFreeBSD plan
IORegisterForSystemPower + IOPMConnectionCreateipconfigd.c:8469, 8530Drop in v1; FreeBSD has no pmset-equivalent. Sleep-coordinated lease renewal not supported. Future: bridge from devd ACPI events.
IOPMCopyScheduledPowerEvents / IOPMCancelScheduledPowerEventipconfigd.c:1515, 1531Drop. No scheduled-wake support.
gethostuuid(3)HostUUID.c:52Replace with sysctlbyname("kern.hostuuid", ...). Caveat: ISO first-boot needs to seed kern.hostuuid if blank.
MGCopyAnswer(kMGQProductType, ...)dhcp.c:447One-line stub: return "FreeBSD".
IO80211/Apple80211API.hwireless.c:178Replace with wpa_supplicant control-socket consumer (/var/run/wpa_supplicant/<ifname>, STATUS command).
SymptomReporter.frameworkreport_symptoms.c, DHCPv6Client.c:2692Delete entirely. Apple wireless-diag telemetry.
os_log familythroughoutMap to syslog(3) via opaque handle wrapper. Keep call-sites unchanged.
bsm/libbsm.h audit_token_to_au32()server.c:79-115Not used today; MIG entry points are ungated. Future: gate via Mach audit token set_security_token path already used in fork_bsport.
IODeviceTree:/chosen NetBoot blobipconfigd.c:2933 via ioregpath.cDeleted (NetBoot out of scope).
Darwin-only ioctls (SIOCAUTOADDR, SIOCSIFL4S, SIOCCLAT46_*, SIOCPROTOATTACH)ifutil.c (~12 ioctls)Not used in fresh-written apply_lease.c / apply_lease_v6.c. CLAT46 (464XLAT) and L4S features unavailable by design.
SCPreferences watcherthroughout for tunables fileNot used. IPCONFIGD_FAST_LEASE env var is the only tunable today; future tunables can ride configd SCPreferences once the watcher is exposed over Mach RPC.

8. The hard parts (what bit in iter 1–8)

  1. BPF rxbuf sizing for ARP probe (iter 6). arp_probe.c initially undersized the BPF rxbuf; BIOCGBLEN returns 4096 by default. Fixed in commit e790468 — match the kernel's reported buffer size, not a guessed-smaller value. The exact failure mode was probe responses getting truncated silently.
  2. SCDynamicStore publish from a non-plugin daemon (iter 4). Apple's pattern is "publish from inside configd's address space." This repo's sc_publish.c instead bundles up the CF dictionary and ships it as a Mach RPC to configd's com.apple.SystemConfiguration port. CF lifetime + key-shape symmetry both had to be right or scutil would not see the value.
  3. MIG worker thread coexistence with the main DHCP loop (iter 5a). The worker runs mach_msg_server blocking on the registered port while the main thread runs select() over BPF / PF_ROUTE / RA sockets. Shared lease state lives in bound_state.c behind locks. Bootstrap_check_in must happen before the MIG service can be reached.
  4. RFC 2131 RENEWING/REBINDING timer accuracy under CI (iter 5b). Real T1/T2 timers are minutes-to-hours; CI must observe the renewal without sleeping for hours. Solution: IPCONFIGD_FAST_LEASE=1 env var collapses T1/T2 to seconds; the IPCFG-RENEW-OK boot marker gates CI on observing one full renew cycle.
  5. SLAAC vs. FreeBSD's accept_rtadv flag (iter 7a). The kernel's net.inet6.ip6.accept_rtadv=0 default plus per-iface IFDISABLED meant SLAAC silently did nothing until apply_lease_v6.c explicitly cleared IFDISABLED and called SIOCAIFADDR_IN6 with the EUI-64 we derived ourselves. RTM_ADD for ::/0 goes through the standard route socket.
  6. Apple-shape ipconfig(8) command-table dispatch (iter 8). The CLI is structurally identical to Apple's — a static table of {name, handler, min_args, help} rows that the main dispatcher matches against argv[1]. Built fresh against our MIG client stubs.
  7. DHCPv6 not built (iter 7b deferred indefinitely). Apple's DHCPv6Client.c is 3717 LOC. QEMU SLIRP doesn't run a DHCPv6 server, so there's no CI validation path. SLAAC covers home / SOHO / most enterprise. Build when a real consumer needs it.
  8. Caller-identity gating is currently TODO. MIG entry points are ungated. Production hardening should gate on the Mach audit-token PID + uid via the set_security_token path already in mach.ko (cf. fork_bsport).
  9. Subscribes to nothing yet. Hot-plug / link-flap / multi-interface / ARP-collision-recovery handling all wait on a kernel-event-subscription path. Future iters plan a hwregd-driven subscription (see §12).

9. The DHCPv6-spam-on-broken-networks problem

Confirmed: IPConfiguration has the same problem as dhcpcd. Both implement RFC 8415 verbatim. RFC 8415 says DHCPv6 Solicit has no max retransmission count (SOL_MAX_RC = 0 = infinite). Both clients retry Solicit forever on networks where the router advertises the M-flag but the DHCPv6 server returns "No Addresses Available." Both cap at one Solicit per hour with random jitter (SOL_MAX_RT = 3600).

Source citations:

The Apple-vs-FreeBSD difference is purely logging policy:

Knob to disable in IPConfiguration: DHCPv6Enabled boolean in Embedded-Info.plist (default true upstream). Per-service: set kSCNetworkProtocolTypeIPv6 ConfigMethod to Manual or LinkLocal.

Conclusion (iter 8 resolution): this repo's ipconfigd doesn't build the DHCPv6 stateful path at all (iter 7b deferred indefinitely). The spam problem is sidestepped entirely. SLAAC handles the IPv6 case. If someone later builds DHCPv6 here, they'll need to default it to off and require per-service opt-in.

10. Comparison with dhcpcd

FeatureIPConfigurationdhcpcd
DHCPv4 (RFC 2131)
DHCPv4 rapid commit (RFC 4039)✗ (yes for v6)
BOOTP (RFC 951)✓ (separate ConfigMethod)partial (frame layout shared)
IPv4LL (RFC 3927)✓ (linklocal.c)✓ (src/ipv4ll.c)
DHCPv6 stateful (RFC 8415)
DHCPv6 IA_PD prefix delegation
DHCPv6 Information-Request (RFC 3736)
DHCPv6 Reconfigure (RFC 8415 §18)partial (option codes, no full handler)
RS/RA (RFC 4861)
RDNSS / DNSSL (RFC 8106)
DHCP authentication (RFC 3118)
Dynamic SOL_MAX_RT learning✗ (fixed 3600)
Bonjour Sleep Proxy coordination✓ (Apple-only)
IOKit power-management awareness✓ (Apple-only)
CGA (RFC 3972)
RFC 7217 stable IIDs✓ (slaac private)
Captive portal URL option (RFC 8910)✓ (DHCPv6 code 103)partial
Hook-script framework✗ (publishes to SCDynamicStore instead)✓ (/lib/dhcpcd/dhcpcd-hooks/)
resolvconf(8) integrationwrites /etc/resolv.conf directly via configd plugin chain✓ via hook
WLAN association coordinationvia Apple80211 (wireless.c)via the AirPort key wland publishes (not a wpa_supplicant hook — NextBSD has no dhcpcd, so no such hook exists)
Bridge / lagg / vlan layeringpartial (Apple's interface model)
Per-iface profiles✓ (each Service has its own UUID)
Privsep✗ (runs in configd as root)✓ (src/privsep*.c)
Cross-platformmacOS onlyNetBSD, FreeBSD, OpenBSD, DragonFly, Linux, Solaris, Haiku
SCDynamicStore publication✓ (canonical Apple keys)✗ (lease file + hooks)
Native ObjC client API (IPConfigurationServiceCreate)✗ (control socket protocol)

What IPConfiguration gave us (iter 1–8): SCDynamicStore-keyed publication (cleaner integration with the rest of the Mach-IPC track), Apple-shape ipconfig(8) CLI with MIG-stub dispatch, RFC 5227 ARP probe + announce, IPv6 RA listener + SLAAC, RFC 2131 lease loop. CGA + Bonjour Sleep Proxy + IOKit power coordination remain Apple-only (no FreeBSD equivalents — out of scope by design).

What dhcpcd had that we gave up: RFC 3118 authentication (rare in real deployments), DHCPv6 Reconfigure handler (deferred — iter 7b), dynamic SOL_MAX_RT learning (DHCPv6 not built), hook-script ecosystem (replaced by SCDynamicStore publish), bridge/lagg/vlan layering recognition (deferred — multi-interface future iter), privilege separation (daemon runs as root under launchd), RFC 7217 stable IIDs (deferred), cross-platform maintenance burden shared with NetBSD/Linux/etc. (intentional — this is an Apple-track port).

11. Locked architectural decisions

DecisionChoice
Repo / trackfreebsd-launchd-mach (v2) — the Mach IPC + libxpc + libdispatch track. The sibling freebsd-launchd (AF_UNIX/DO) track is a separate effort.
Deployment shapeStandalone Mach daemon at /usr/sbin/ipconfigd — NOT a configd plugin. This repo's configd has no plugin loader; the two daemons live in separate address spaces.
Source repo (Apple)apple-oss-distributions/bootp at the latest tag (currently bootp-534.100.6). Used as reference + protocol-core source; the daemon shell is fresh-written.
IPCMIG over mach_msg. Mach service name com.apple.IPConfiguration. IDL src/IPConfiguration/ipconfig.defs — slim 2-routine subset (ipconfig_if_count, ipconfig_if_addr); grows as real consumers arrive.
SCDynamicStorePublish-only via Mach RPC to configd at com.apple.SystemConfiguration. Subscribes to nothing yet.
Power managementDropped. No FreeBSD equivalent for IOPMConnection. Sleep-coordinated renew unsupported.
WLAN coordinationNot built in iter 1–8 (Ethernet only). Next: the ~70-LOC sc_link_watch.c gate requiring Link{Active} and AirPort{Authenticated}, key-absent meaning ready so wired NICs are untouched. WLAN plan §1.4.
EAPOL / 802.1XSkipped. Route through wpa_supplicant if needed later.
NetBoot / BSDPOut of scope.
Loggingsyslog(3) wrapper around the os_log macros, matching the launchd-mach mylog.h.
PrivsepRuns as root under launchd. No separate sandboxing.
LicenseBSD-2-Clause for new code; preserve Apple OSReference 2.0 (Apache) headers on imported files.
DHCPv6 (iter 7b)Deferred indefinitely. SLAAC covers the common case; Apple's DHCPv6Client.c is 3717 LOC with no CI validation path (QEMU SLIRP doesn't run a DHCPv6 server). Build when a real consumer needs it.
CLI shapeApple-shape ipconfig(8) at /usr/sbin/ipconfig. Command-table dispatch with getifaddr + ifcount so far (iter 8).

12. Iter history (shipped)

Iter 1 — Daemon skeleton + Mach service registration SHIPPED (PR #42)

Iter 2 — DHCPDISCOVER/OFFER over BPF SHIPPED (PR #43)

Iter 3 — Full DHCPv4 INIT→BOUND SHIPPED (PR #44)

Iter 4 — SCDynamicStore publish + RENEWING/REBINDING SHIPPED (PR #45)

Iter 5a — MIG service (worker thread, 2-routine surface) SHIPPED (PR #46)

Iter 5b — IPCONFIGD_FAST_LEASE + IPCFG-RENEW-OK CI gate SHIPPED (PR #47)

Iter 6 — RFC 5227 ARP probe + announce SHIPPED (PR #49)

Iter 7a — IPv6 RA listener + SLAAC + ::/0 + State:/.../IPv6 SHIPPED (PR #50)

Iter 7b — DHCPv6 stateful DEFERRED INDEFINITELY

Iter 8 — Apple-shape ipconfig(8) CLI SHIPPED (PR #51)

13. Future iters

Grow the MIG surface FUTURE

Multi-interface + per-interface workers FUTURE

BPF → kqueue FUTURE

Hot-plug via hwregd subscription FUTURE

14. Open questions / deferred features

Deferred-by-design (per the iter plan):

Q1. When to grow the MIG IDL? Resolved policy: grow when a real consumer arrives. Apple's 21+ routines stay aspirational; don't gold-plate.
Q2. Caller-identity gating on MIG entry points. Currently ungated. Production hardening should gate on the Mach audit-token PID + uid via set_security_token (already used in mach.ko's fork_bsport path). No urgency — the daemon runs as root and the queries are read-only.
Q3. Hot-plug subscription path. hwregd interface-arrival events vs. a configd KEM-equivalent. Lean toward hwregd subscription (Phase K hardware-registry daemon already ships interface enrichment). Decide when the first multi-interface consumer arrives.
Q4. Power-management integration. Apple's IORegisterForSystemPower + scheduled wake events let IPConfiguration coordinate lease renewal across sleep. FreeBSD has no pmset-equivalent. Build a bridge from devd ACPI events later, or live without sleep coordination on laptops.
Q5. Bonjour Sleep Proxy support. Apple's ipconfigd coordinates with mDNSResponder so a sleep proxy answers ARP/ND while the host sleeps. Useful on a Mac; less useful on a desktop. Requires freebsd-mdnsresponder shipped first.

15. References


Revision 2026-05-23. Refactored from a deferred netconfigd-plugin plan (sibling AF_UNIX/DO track) to a shipped freebsd-launchd-mach (v2) standalone Mach daemon. Iter 1–8 (PRs #42–#51) merged: daemon skeleton, DHCPv4 INIT→BOUND, SCDynamicStore publish, RFC 2131 RENEW/REBIND with IPCONFIGD_FAST_LEASE CI gate, MIG service worker (2-routine surface), RFC 5227 ARP probe + announce, IPv6 RA listener + EUI-64 SLAAC + ::/0 route + State:/.../IPv6 publish, Apple-shape ipconfig(8) CLI. iter 7b (DHCPv6 stateful) deferred indefinitely. Future iters grow the MIG surface, add multi-interface workers, swap select() for kqueue, and subscribe to hwregd for hot-plug.