https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=248579
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: b...@freebsd.org Reporter: r...@rcousins.com While writing a TCP server designed to accept both IPv4 and IPv6 connections, I've found that the recommended way fails, but the same code runs under Linux 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 = NULL; memset(&hints, 0, sizeof(hints)); // hints.ai_family = PF_UNSPEC; hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; hints.ai_flags = AI_PASSIVE; if ((error = getaddrinfo(NULL, port, &hints, &res0))) errx(1, "%s", gai_strerror(error)); for (res = res0; res; res = res->ai_next) { printf("Trying Family=%d, Socktype=%d, Protocol=%d\n", res->ai_family, res->ai_socktype, res->ai_protocol); if ((s = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) < 0) { cause = "socket"; continue; } int yes = 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 = "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 = make_listen("5000"); while (1) { char addr[80]; struct sockaddr_storage client_addr; socklen_t client_addr_len = sizeof(client_addr); int fc = accept(listen_fd, (struct sockaddr *)&client_addr, &client_addr_len); if (fc < 0) { warn("Accept()"); continue; } if (client_addr.ss_family == AF_INET) { struct sockaddr_in *p = (struct sockaddr_in *)&client_addr; inet_ntop(p->sin_family, &p->sin_addr, addr,sizeof(addr)); } else { struct sockaddr_in6 *p = (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); } } -- You are receiving this mail because: You are the assignee for the bug. _______________________________________________ freebsd-bugs@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/freebsd-bugs To unsubscribe, send any mail to "freebsd-bugs-unsubscr...@freebsd.org"