Date: Mon, 10 Aug 2020 16:55:30 +0000 From: bugzilla-noreply@freebsd.org To: bugs@FreeBSD.org Subject: [Bug 248579] PRoblem with accept(2) and dual IPv4/IPv6 TCP servers Message-ID: <bug-248579-227@https.bugs.freebsd.org/bugzilla/>
next in thread | raw e-mail | index | archive | help
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=3D248579 Bug ID: 248579 Summary: PRoblem with accept(2) and dual IPv4/IPv6 TCP servers Product: Base System Version: 12.1-RELEASE Hardware: Any OS: Any Status: New Severity: Affects Some People Priority: --- Component: kern Assignee: bugs@FreeBSD.org Reporter: rec@rcousins.com While writing a TCP server designed to accept both IPv4 and IPv6 connection= s, I've found that the recommended way fails, but the same code runs under Lin= ux perfectly. The failure is that IPv6 connections succeed and IPv4 connections always fail. Way to exercise bug: - Compile code below (cc -o foo foo.c will work) - run command ("./foo") in one window - In another window try to connect to port 5000 for example: telnet ::1 5000 <-- should work telnet 127.0.0.1 5000 <-- should work but fails 100% of the time. Repeating this test under modern Linux results in both telnet sessions connecting. Code to exercise bug: #include <stdio.h> #include <string.h> #include <unistd.h> #include <err.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include <netinet/in.h> #include <arpa/inet.h> int make_listen(char *port) { struct addrinfo hints, *res, *res0; int error; int s; const char *cause =3D NULL; memset(&hints, 0, sizeof(hints)); // hints.ai_family =3D PF_UNSPEC; hints.ai_family =3D AF_INET6;=20=20 hints.ai_socktype =3D SOCK_STREAM; hints.ai_protocol =3D IPPROTO_TCP; hints.ai_flags =3D AI_PASSIVE; if ((error =3D getaddrinfo(NULL, port, &hints, &res0))) errx(1, "%s", gai_strerror(error)); for (res =3D res0; res; res =3D res->ai_next) { printf("Trying Family=3D%d, Socktype=3D%d, Protocol=3D%d\n", res->ai_family,=20 res->ai_socktype, res->ai_protocol); if ((s =3D socket(res->ai_family,=20 res->ai_socktype, res->ai_protocol)) < 0) { cause =3D "socket"; continue; } int yes =3D 1; if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) errx(1,"Setsockopt(SO_REUSEADDR) failed."); if (bind(s, res->ai_addr, res->ai_addrlen) < 0) { cause =3D "bind"; close(s); continue; } listen(s, 5); freeaddrinfo(res0); return s; } err(1, "%s", cause); freeaddrinfo(res0); return -1; } int main(int argc, char *argv[]) { int listen_fd =3D make_listen("5000"); while (1) { char addr[80]; struct sockaddr_storage client_addr; socklen_t client_addr_len =3D sizeof(client_addr); int fc =3D accept(listen_fd, (struct sockaddr *)&client_addr, &client_addr_len); if (fc < 0) { warn("Accept()"); continue; } if (client_addr.ss_family =3D=3D AF_INET) { struct sockaddr_in *p =3D (struct sockaddr_in *)&client_addr; inet_ntop(p->sin_family, &p->sin_addr, addr,sizeof(addr)); } else { struct sockaddr_in6 *p =3D (struct sockaddr_in6 *)&client_addr; inet_ntop(p->sin6_family, &p->sin6_addr, addr,sizeof(addr)); } printf("Connection from (%d) %s\n", client_addr_len, addr); (void)write(fc,"Hello\n",6); close(fc); } } --=20 You are receiving this mail because: You are the assignee for the bug.=
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?bug-248579-227>