1 /* 2 * Test for the regression introduced by 3 * 4 * b9470c27607b ("inet: kill smallest_size and smallest_port") 5 * 6 * If we open an ipv4 socket on a port with reuseaddr we shouldn't reset the tb 7 * when we open the ipv6 conterpart, which is what was happening previously. 8 */ 9 #include <errno.h> 10 #include <error.h> 11 #include <arpa/inet.h> 12 #include <netinet/in.h> 13 #include <stdbool.h> 14 #include <stdio.h> 15 #include <sys/socket.h> 16 #include <sys/types.h> 17 #include <unistd.h> 18 19 #define PORT 9999 20 21 int open_port(int ipv6, int any) 22 { 23 int fd = -1; 24 int reuseaddr = 1; 25 int v6only = 1; 26 int addrlen; 27 int ret = -1; 28 struct sockaddr *addr; 29 int family = ipv6 ? AF_INET6 : AF_INET; 30 31 struct sockaddr_in6 addr6 = { 32 .sin6_family = AF_INET6, 33 .sin6_port = htons(PORT), 34 .sin6_addr = in6addr_any 35 }; 36 struct sockaddr_in addr4 = { 37 .sin_family = AF_INET, 38 .sin_port = htons(PORT), 39 .sin_addr.s_addr = any ? htonl(INADDR_ANY) : inet_addr("127.0.0.1"), 40 }; 41 42 43 if (ipv6) { 44 addr = (struct sockaddr*)&addr6; 45 addrlen = sizeof(addr6); 46 } else { 47 addr = (struct sockaddr*)&addr4; 48 addrlen = sizeof(addr4); 49 } 50 51 if ((fd = socket(family, SOCK_STREAM, IPPROTO_TCP)) < 0) { 52 perror("socket"); 53 goto out; 54 } 55 56 if (ipv6 && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&v6only, 57 sizeof(v6only)) < 0) { 58 perror("setsockopt IPV6_V6ONLY"); 59 goto out; 60 } 61 62 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, 63 sizeof(reuseaddr)) < 0) { 64 perror("setsockopt SO_REUSEADDR"); 65 goto out; 66 } 67 68 if (bind(fd, addr, addrlen) < 0) { 69 perror("bind"); 70 goto out; 71 } 72 73 if (any) 74 return fd; 75 76 if (listen(fd, 1) < 0) { 77 perror("listen"); 78 goto out; 79 } 80 return fd; 81 out: 82 close(fd); 83 return ret; 84 } 85 86 int main(void) 87 { 88 int listenfd; 89 int fd1, fd2; 90 91 fprintf(stderr, "Opening 127.0.0.1:%d\n", PORT); 92 listenfd = open_port(0, 0); 93 if (listenfd < 0) 94 error(1, errno, "Couldn't open listen socket"); 95 fprintf(stderr, "Opening INADDR_ANY:%d\n", PORT); 96 fd1 = open_port(0, 1); 97 if (fd1 >= 0) 98 error(1, 0, "Was allowed to create an ipv4 reuseport on a already bound non-reuseport socket"); 99 fprintf(stderr, "Opening in6addr_any:%d\n", PORT); 100 fd1 = open_port(1, 1); 101 if (fd1 < 0) 102 error(1, errno, "Couldn't open ipv6 reuseport"); 103 fprintf(stderr, "Opening INADDR_ANY:%d\n", PORT); 104 fd2 = open_port(0, 1); 105 if (fd2 >= 0) 106 error(1, 0, "Was allowed to create an ipv4 reuseport on a already bound non-reuseport socket"); 107 close(fd1); 108 fprintf(stderr, "Opening INADDR_ANY:%d after closing ipv6 socket\n", PORT); 109 fd1 = open_port(0, 1); 110 if (fd1 >= 0) 111 error(1, 0, "Was allowed to create an ipv4 reuseport on an already bound non-reuseport socket with no ipv6"); 112 fprintf(stderr, "Success"); 113 return 0; 114 } 115