ADR-083 — Additifs couche 0 pour la plomberie réseau : TUN (TUNSETIFF) + adjtimex/clock_adjtime — descellement additif couche-0-v1.x
Statut : Accepté (délégation additive, ADR-065 §Gouvernance — additifs neutres). RFC de structure (ADR-015). Modèle : descellements additifs couche 0
ADR-051/ADR-060/ADR-070/ADR-071.
Consommateurs : air-wireguard (TUN), air-ntp (adjtimex).
Catégorie : Descellement additif de la couche 0 scellée. Aucune rupture ; jalons conservés.
Contexte
Les specs de plomberie (air-dhcp/air-ntp/air-wireguard) ont flagué des « additifs
couche 0 ». Vérification faite sur le socle réel, la plupart existent déjà — seuls
deux manquent réellement :
| Besoin (spec) | État réel couche 0 | Additif ? |
|---|---|---|
| Régler l’horloge (NTP) | clock_settime EXISTE (time.rs) — step possible | adjtimex seul (slew) |
| Socket ICMPv6 brut (SLAAC) | SocketType::Raw EXISTE + socket(domain, ty, protocol: i32) générique | NON (déjà possible) ; ICMP6_FILTER = setsockopt_bytes (ADR-080) |
SO_BROADCAST (DHCPv4) | sockopt entier EXISTE (ADR-071) | NON (wrapper couche 1) |
| Interface TUN (WireGuard) | absent | TUNSETIFF (ioctl dédié) |
⇒ Le périmètre réel est deux additifs : adjtimex (discipline fine d’horloge) et le
TUN (/dev/net/tun + TUNSETIFF).
Décision
(1) Famille time — adjtimex/clock_adjtime (discipline fine)
Ajouter le wrapper adjtimex (via clock_adjtime(2), moderne, par-clock) —
ajustement graduel (slew) de l’horloge, que NTP préfère au saut brut
(clock_settime, déjà présent). Type TimexBuffer (struct timex, #[repr(C)]
identique x86/arm), fonction dédiée typée, Result<TimexState, Errno>, EINTR
remonté. Privilégié (CAP_SYS_TIME — appliqué par le kernel, le wrapper n’élève rien).
(2) TUN — /dev/net/tun + TUNSETIFF (ioctl dédié typé)
Ajouter un wrapper tun_set_iff (ioctl(fd, TUNSETIFF, &ifreq)) — fonction dédiée
typée (ADR-021 conv. 3, jamais d’ioctl générique), sur /dev/net/tun ouvert par
l’open existant. Types InterfaceRequest (ifreq borné : nom d’interface ≤ IFNAMSIZ,
flags TunFlags : IFF_TUN/IFF_NO_PI/IFF_MULTI_QUEUE). RAII sur le FD.
Privilégié (CAP_NET_ADMIN).
Zéro nouveau paradigme : adjtimex = un syscall de plus dans time ; TUN = un ioctl
dédié de plus (comme la famille terminal, ADR-060). Types #[repr(C)] identiques
2 arches (asserts de layout). Option<T> où sentinelle, EINTR remonté, RAII FD.
Gouvernance
- Additifs neutres (le privilège est appliqué par le kernel ; le wrapper ne fait qu’exposer le syscall) → délégation additive (ADR-065), comme ADR-060/070/071.
- Tags après implémentation + barrière 2 arches (ADR-072) :
couche-0-v1.x(séquentiel après les additifs en attentev1.11/v1.12). - Couverture 100 % couche 0 (hors exceptions PRIVILEGE documentées pour les chemins
exigeant
CAP_*, ADR-035) ;// SAFETY:sur chaque blocunsafe;check-syscalls(numérosadjtimex/clock_adjtime, 2 arches).
Conséquences
air-ntp: discipline slew possible (adjtimex) en plus du step (clock_settimedéjà là).air-wireguard: interface tunnel créable (tun_set_iff).- Corrections de specs :
air-dhcp(ICMPv6/SO_BROADCAST ne sont pas des additifs couche 0),air-ntp(clock_settimedéjà présent → seuladjtimexmanque),air-wireguard(TUN = additif couche 0 précis). - ICMPv6 brut (SLAAC) : réalisé en couche 1 (
air-socket: socketRaw/Ipv6typé +ICMP6_FILTERviasetsockopt_bytesADR-080) — sans additif couche 0.
Alternatives rejetées
- Ioctl TUN générique — interdit (ADR-021 conv. 3) ; wrapper dédié typé.
settimeofdaylegacy — remplacé parclock_settime(déjà présent) +clock_adjtime(moderne, par-clock). Rejeté.- Ajouter un socket ICMPv6/
SO_BROADCASTen couche 0 — inutile : le socle générique (Raw+socket+ sockopt entier/structuré) les couvre déjà. Rejeté.
Suite
- Specs
family-time(adjtimex) + une famille/extensiontundocumentées à l’implémentation. Correctionsair-dhcp/air-ntp/air-wireguard. Tagscouche-0-v1.xaprès barrière 2 arches. Câblage registre/SUMMARY.