Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

ADR-070 — Descellement additif couche-0 : codec sockaddr public pour la face libc (socket_addr_from_bytes / socket_addr_to_bytes)

Statut : Accepté (2026-07-06, décision BDFL — exposition du codec sockaddr existant plutôt que duplication côté libc ; sous la délégation des re-sceaux additifs du superviseur, ADR-065, et dans le cadre du descellement couche 0 pour la libc ADR-051). RFC d’extension de couches scellées (ADR-015). Sert l’implémentation du jalon M4 réseau (ADR-069, Lot 2). Conventions : ADR-021.

Catégorie : Descellement additif de la couche 0 scellée (couche-0-v1.9couche-0-v1.10). Aucune rupture ; aucun symbole existant modifié ; jalons antérieurs conservés. Tag couche-0-v1.10 DIFFÉRÉ (groupé avec le re-sceau couche-1-v1.6, décision d’ordonnancement BDFL).

Contexte

La libc C-ABI d’Air doit convertir, aux frontières bind/connect/getsockname/ getpeername/accept, entre le struct sockaddr brut que présente un programme C (octets + socklen_t) et le SocketAddr typé qu’utilisent le moteur socket (ADR-069) et la couche 0.

Or la couche 0 possède déjà ce codec, dans les deux sens, mais en pub(crate) :

  • socket_addr_to_raw(&SocketAddr) -> (RawSockaddrStorage, u32) (sérialisation) ;
  • raw_to_socket_addr(&[u8], u32) -> Option<SocketAddr> (désérialisation, validante : famille connue + longueur suffisante).

Deux options se présentaient (cf. décision BDFL) :

  1. Réimplémenter le layout sockaddr_in/sockaddr_in6/sockaddr_un dans la libc (air-libc-socket) — dupliquerait la connaissance du layout kernel, avec un risque de divergence à maintenir en phase.
  2. Exposer le codec couche 0 existant — une seule autorité de layout (doctrine kernel = bible), zéro duplication.

Décision

Option 2. La couche 0 expose deux fines fonctions publiques, qui délèguent aux codecs internes inchangés (aucune logique nouvelle, aucun unsafe) :

#![allow(unused)]
fn main() {
// crates/air-sys-syscall/src/net.rs
pub fn socket_addr_from_bytes(bytes: &[u8], length: u32) -> Option<SocketAddr>;
pub fn socket_addr_to_bytes(address: &SocketAddr, out: &mut [u8]) -> Option<u32>;
}
  • socket_addr_from_bytes = exposition de raw_to_socket_addr (le sens hostile : octets non fiables venus du C → adresse typée, validée ou None).
  • socket_addr_to_bytes = exposition de socket_addr_to_raw sans fuiter le type de stockage interne (RawSockaddrStorage reste pub(crate)) : copie bornée dans le buffer de l’appelant, rend la socklen_t effective ou None si le buffer est trop court.

Les shims C bind/connect/getsockname/… (Lot 3) appellent ces fonctions directement ; il n’y a pas de couche de re-hébergement du codec dans air-libc-socket (qui ne porte que inet_pton/inet_ntop + byte-order, Lot 2.a).

Conséquences

  • Positif : une seule implémentation du layout sockaddr, testée et fuzzée (fuzz_air_sockaddr_decode — octets + socklen_t arbitraires, invariants no-panic + round-trip IP). Couverture 100 % des deux fonctions.
  • ABI : purement additif — les symboles air-stable existants sont intacts ; aucune garantie ABI n’est rompue. Re-sceau couche-0-v1.10 (tag différé).
  • Limitation connue (héritée, hors périmètre) : raw_to_socket_addr accepte un nom Unix abstrait plus long que sun_path (107 octets) que socket_addr_to_raw borne — asymétrie pré-existante du codec couche 0 (déjà employée par getsockname/getpeername). Le fuzz restreint donc son invariant de round-trip aux familles IP (layout fixe). Durcissement éventuel = descellement additif ultérieur.

Alternatives rejetées

  • Réimplémenter le codec dans air-libc-socket : duplication du layout kernel, divergence possible (rejetée — cf. Contexte option 1).
  • Rendre RawSockaddrStorage public : fuiterait un détail de représentation ([u8; 128] aligné) dans la surface stable, sans bénéfice — l’API par tranche (&mut [u8]) est plus sûre et suffit à la libc.