Spec couche 5 — air-dhcp (client DHCPv4/DHCPv6, patron sans-IO)
Spécification technique — Version 0.1 (proposition). Couche 5 « Services système ».
Cadrage.
air-dhcp= client de configuration réseau automatique : DHCPv4 (RFC 2131), DHCPv6 (RFC 8415), et RA/SLAAC IPv6 (RFC 4861/4862). Maison, pur Rust, zéro-C, zérounsafe. Crate-lib (cœur sans-IO) + daemon.airservice(note réseau §1 : DHCP = L5, UDP broadcast). Serveur DHCP hors périmètre (client only).
Position et méthode
Protocole filaire → cœur sans-IO (les 9 composants) + pilote I/O (air-socket UDP
broadcast/multicast). Le daemon applique le bail obtenu : adresses/routes via
air-netlink (rtnetlink), DNS via air-config (resolv.conf). Consomme
air-runtime (async/timers), air-base-core.
Périmètre — moderne, borné
- DHCPv4 (DISCOVER/OFFER/REQUEST/ACK, RENEW/REBIND) ; DHCPv6 (SOLICIT/ADVERTISE/ REQUEST/REPLY, IA_NA/IA_PD) ; RA/SLAAC (autoconfiguration IPv6 sans état).
- Options bornées (surface hostile : le serveur DHCP est sur le LAN) — jamais d’exécution, jamais d’alloc non bornée ; option 43/121 (routes) parsées prudemment.
- Omis : serveur DHCP ; options legacy inutiles (NIS…) ; BOOTP legacy.
Anatomie : les 9 composants
| # | Composant | air-dhcp | Pur ? |
|---|---|---|---|
| 1 | Framer | // TRIVIAL : un datagramme UDP = un message DHCP | ✅ triv. |
| 2 | Codec | DhcpV4Codec/DhcpV6Codec — en-tête fixe + options TLV bornées | ✅ |
| 3 | StateMachine | LeaseStateMachine — DISCOVER→…→BOUND, RENEW/REBIND/EXPIRE (RFC 2131 §4.4) | ✅ |
| 4 | Handshaker | // NO : pas d'auth (DHCP authentication RFC 3118 = hors périmètre) | — |
| 5 | Flow Controller | // NO | — |
| 6 | Multiplexer | // NO | — |
| 7 | Timer Manager | LeaseTimers — T1/T2/expiry, retransmit backoff (RFC 2131 §4.1) ; horloge injectée | ✅ |
| 8 | Session Context | Lease — adresse, masque, routeurs, DNS, durée, xid | ✅ |
| 9 | Extension hooks | options connues (SLAAC/RA en variante) | ✅ |
Inventaire — ~12 objets
Surface (~8) : DhcpV4Client, DhcpV6Client, SlaacClient, Lease (+ LeaseV6),
DhcpOption, DhcpEvent (Bound/Renewed/Expired/Lost), DhcpConfig, DhcpError.
Cœur sans-IO (~4) : DhcpV4Codec, DhcpV6Codec, LeaseStateMachine, LeaseTimers.
#![allow(unused)]
fn main() {
pub enum DhcpEvent { Bound(Lease), Renewed(Lease), Expired, Lost, WantsTransmit }
impl DhcpV4Client {
pub fn new(interface: AirInterfaceRef) -> AirResult<Self>;
pub fn recv(&mut self, now: AirInstant, datagram: &[u8]) -> AirResult<Vec<DhcpEvent>>;
pub fn poll_transmit(&mut self, now: AirInstant) -> Option<Vec<u8>>; // broadcast
pub fn handle_timeout(&mut self, now: AirInstant) -> AirResult<Vec<DhcpEvent>>;
}
}
Dépendances
air-socket (L1, UDP broadcast/multicast — additif SO_BROADCAST typé si besoin),
air-netlink (L1, appliquer adresses/routes), air-config (L1, DNS/resolv.conf),
air-runtime/air-base-core (L1). Zéro-C, zéro tierce. ICMPv6 (RA/SLAAC) : le
socket brut est déjà possible en couche 0 (SocketType::Raw + socket générique) ;
il faut seulement un wrapper air-socket typé (Raw/Ipv6 + ICMP6_FILTER via
setsockopt_bytes, ADR-080) — pas d’additif couche 0 (ADR-083).
Sécurité & tests
- Parsing d’options borné + fuzzé (LAN hostile) ; bail plafonné ; jamais de route/
DNS appliqués sans validation. Rogue-DHCP : hors scope crypto (DHCP n’authentifie
pas), le daemon peut exiger une politique (
air-config). - Tests : codec fuzzé, StateMachine property (transitions bail), timers virtual clock,
interop
isc-dhcp/dnsmasqen loopback.
Travail à reprendre
- Wrappers
air-socket(couche 1) : ICMPv6 brut typé (SLAAC — socle couche 0 déjà présent, ADR-083) +SO_BROADCASTtypé (sockopt entier existant, ADR-071). Aucun additif couche 0. - Daemon
.airservice(L5) : intégrationair-config/air-netlink, politique. - DHCPv6 IA_PD (délégation de préfixe) ; ABI C différée.
Licence : MPL 2.0. Statut : spec air-dhcp (L5) v0.1 — client DHCPv4/v6 + SLAAC, sans-IO.