/* * BastionGuard™ Secure Connection * Copyright (C) 2025–2026 Calogero Scarnà * GPL-3.0 * * Lookup veloce e senza race delle informazioni di un socket usando * NETLINK_SOCK_DIAG (sock_diag). E' l'API che `ss` e `iproute2` usano * internamente: chiede direttamente al kernel il socket e ottiene l' * inode senza scansionare /proc. * * Workflow per risolvere un flow → PID: * 1. Query sock_diag con (family=AF_INET/INET6, proto=TCP/UDP, * saddr:sport, daddr:dport) → il kernel ritorna l'inode del socket * 2. Ricerca dell'inode nei /proc//fd/ (questo passaggio e' * comunque necessario: non c'e' API kernel che mappi socket->PID * senza passare da /proc, ma almeno ora l'inode e' quello GIUSTO) * * Vantaggi rispetto al parsing di /proc/net/tcp: * - Quando NFQUEUE ti consegna il SYN, sock_diag risponde sempre * (il kernel ha l'inode in memoria). /proc/net/tcp invece viene * aggiornato in modo visibile dopo un brief delay. * - Zero parsing di testo. Struttura binaria diretta. * - Filtering su 4-tupla diretto nel kernel. */ #pragma once #include #include #include namespace bsc::net { struct SockInfo { std::uint32_t inode{0}; std::uint32_t uid{0xFFFFFFFFu}; }; /** * Risolve un flow TCP (saddr:sport → daddr:dport) al suo inode + uid * tramite NETLINK_SOCK_DIAG. * * @param src_ip/src_port Endpoint locale (stringa IPv4 o IPv6) * @param dst_ip/dst_port Endpoint remoto * @return SockInfo con inode e uid, o nullopt se il kernel non trova il socket * * Thread-safe. Ogni chiamata crea/chiude il proprio netlink socket * (operazione molto leggera). */ std::optional sockdiag_lookup_tcp(const std::string& src_ip, std::uint16_t src_port, const std::string& dst_ip, std::uint16_t dst_port); std::optional sockdiag_lookup_udp(const std::string& src_ip, std::uint16_t src_port, const std::string& dst_ip, std::uint16_t dst_port); } // namespace bsc::net