Réseau · Section 2
bind(2)
Assigne une adresse locale à une socket.
Signature
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr * addr, socklen_t addrlen);- sockfd
- Descripteur retourné par socket() ; ne doit pas déjà être lié.
- addr
- Pointeur vers une struct sockaddr_* assortie à la famille de la socket (sockaddr_in pour AF_INET, sockaddr_in6, sockaddr_un, sockaddr_ll pour AF_PACKET, etc.).
- addrlen
- Taille de la struct pointée par addr. Utiliser sizeof(struct sockaddr_in) etc. ; pas strlen().
Description
bind() assigne l'adresse indiquée par addr à la socket désignée par sockfd. Pour les sockets AF_INET / AF_INET6 c'est l'IP + port local sur lequel la socket recevra (ou, pour une socket TCP qui se connecte, l'IP/port source ; généralement le noyau les choisit automatiquement). Pour AF_UNIX c'est le chemin du système de fichiers ou le nom en espace abstrait. Un serveur appelle typiquement socket() → bind() → listen() → accept() ; un client saute bind() et laisse le noyau choisir un port source éphémère au connect(). Lier un port privilégié (< 1024 en INET) requiert CAP_NET_BIND_SERVICE.
Numéros par architecture
| Architecture | Numéro | ABI | Point d'entrée |
|---|---|---|---|
| x86 (i386) | 361 | i386 | sys_bind |
| x64 (x86_64) | 49 | common | sys_bind |
| ARM64 (aarch64) | 200 | — | sys_bind |
Historique noyau
Introduit dans Linux 1.0.
1.0
bind() est présent dans Linux depuis 1.0 avec la sémantique BSD.
3.9
SO_REUSEPORT a été ajouté pour permettre à plusieurs sockets dans des processus différents de se lier au même port, le noyau hashant les connexions entrantes entre elles. Utilisé par nginx et HAProxy pour passer à l'échelle sur plusieurs cœurs sans goulot accept() unique.
seccomp & conteneurs
Docker default profile
Autorisé
Podman default profile
Autorisé
bind() est autorisé par les profils Docker / Podman. Le filtrage d'arguments par famille sockaddr n'en vaut généralement pas la complexité — le filtre socket() amont (n'autoriser que AF_INET / AF_UNIX) borne déjà la surface. La restriction intéressante est au niveau IP : les programmes BPF cgroup (BPF_CGROUP_INET4_BIND, BPF_CGROUP_INET6_BIND) peuvent refuser le bind sur des ports précis — les network policies Kubernetes et Cilium s'en servent pour un contrôle fin.
libseccomp
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(bind), 0);Exemple strace
$ strace -e socket,bind,listen python3 -c 'import socket;s=socket.socket();s.bind(("127.0.0.1",0));s.listen(1)'
socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) = 3
bind(3, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("127.0.0.1")}, 16) = 0
listen(3, 1) = 0strace décode sockaddr_in / sockaddr_in6 / sockaddr_un complètement : sa_family, sin_addr, sin_port via htons(). Un bind() retournant -1 EADDRINUSE au démarrage d'un service est le diagnostic classique de « port déjà utilisé » — strace l'affiche immédiatement. -e network filtre les appels liés aux sockets.
Sécurité & observabilité
bind() sur un port privilégié (< 1024) est la raison canonique pour laquelle les démons tournent en root ou détiennent CAP_NET_BIND_SERVICE ; auditer quelles capacités sont abandonnées après bind() est une étape de durcissement standard. Un bind() AF_UNIX vers un emplacement inattendu peut être une porte dérobée ; sur les hôtes systemd, comparer aux sockets listées. Un bind() AF_PACKET épingle une socket brute à une interface — presque toujours un signe de sniff hors d'outils légitimes type tcpdump. Le tracepoint eBPF syscalls:sys_enter_bind plus le hook BPF cgroup inet_bind donnent une observabilité complète.
Erreurs
- EACCES
- Adresse protégée et appelant sans la capacité requise — typiquement CAP_NET_BIND_SERVICE pour les ports INET sous 1024, ou permissions sur le chemin AF_UNIX.
- EADDRINUSE
- Adresse déjà utilisée. Avec SO_REUSEADDR c'est relâché pour les sockets en TIME_WAIT ; avec SO_REUSEPORT, plusieurs sockets peuvent se lier simultanément pour répartir la charge.
- EADDRNOTAVAIL
- Adresse locale inexistante (par ex. IP non assignée à une interface).
- EAFNOSUPPORT
- Discordance de famille entre socket et addr.
- EBADF
- sockfd n'est pas un descripteur valide.
- EINVAL
- Socket déjà liée, ou addrlen incorrect pour la famille.
- ENOTSOCK
- sockfd n'est pas une socket.
- EROFS
- —