Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Test for the regression introduced by
0003  *
0004  * b9470c27607b ("inet: kill smallest_size and smallest_port")
0005  *
0006  * If we open an ipv4 socket on a port with reuseaddr we shouldn't reset the tb
0007  * when we open the ipv6 conterpart, which is what was happening previously.
0008  */
0009 #include <errno.h>
0010 #include <error.h>
0011 #include <arpa/inet.h>
0012 #include <netinet/in.h>
0013 #include <stdbool.h>
0014 #include <stdio.h>
0015 #include <sys/socket.h>
0016 #include <sys/types.h>
0017 #include <unistd.h>
0018 
0019 #define PORT 9999
0020 
0021 int open_port(int ipv6, int any)
0022 {
0023     int fd = -1;
0024     int reuseaddr = 1;
0025     int v6only = 1;
0026     int addrlen;
0027     int ret = -1;
0028     struct sockaddr *addr;
0029     int family = ipv6 ? AF_INET6 : AF_INET;
0030 
0031     struct sockaddr_in6 addr6 = {
0032         .sin6_family = AF_INET6,
0033         .sin6_port = htons(PORT),
0034         .sin6_addr = in6addr_any
0035     };
0036     struct sockaddr_in addr4 = {
0037         .sin_family = AF_INET,
0038         .sin_port = htons(PORT),
0039         .sin_addr.s_addr = any ? htonl(INADDR_ANY) : inet_addr("127.0.0.1"),
0040     };
0041 
0042 
0043     if (ipv6) {
0044         addr = (struct sockaddr*)&addr6;
0045         addrlen = sizeof(addr6);
0046     } else {
0047         addr = (struct sockaddr*)&addr4;
0048         addrlen = sizeof(addr4);
0049     }
0050 
0051     if ((fd = socket(family, SOCK_STREAM, IPPROTO_TCP)) < 0) {
0052         perror("socket");
0053         goto out;
0054     }
0055 
0056     if (ipv6 && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&v6only,
0057                    sizeof(v6only)) < 0) {
0058         perror("setsockopt IPV6_V6ONLY");
0059         goto out;
0060     }
0061 
0062     if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr,
0063                sizeof(reuseaddr)) < 0) {
0064         perror("setsockopt SO_REUSEADDR");
0065         goto out;
0066     }
0067 
0068     if (bind(fd, addr, addrlen) < 0) {
0069         perror("bind");
0070         goto out;
0071     }
0072 
0073     if (any)
0074         return fd;
0075 
0076     if (listen(fd, 1) < 0) {
0077         perror("listen");
0078         goto out;
0079     }
0080     return fd;
0081 out:
0082     close(fd);
0083     return ret;
0084 }
0085 
0086 int main(void)
0087 {
0088     int listenfd;
0089     int fd1, fd2;
0090 
0091     fprintf(stderr, "Opening 127.0.0.1:%d\n", PORT);
0092     listenfd = open_port(0, 0);
0093     if (listenfd < 0)
0094         error(1, errno, "Couldn't open listen socket");
0095     fprintf(stderr, "Opening INADDR_ANY:%d\n", PORT);
0096     fd1 = open_port(0, 1);
0097     if (fd1 >= 0)
0098         error(1, 0, "Was allowed to create an ipv4 reuseport on a already bound non-reuseport socket");
0099     fprintf(stderr, "Opening in6addr_any:%d\n", PORT);
0100     fd1 = open_port(1, 1);
0101     if (fd1 < 0)
0102         error(1, errno, "Couldn't open ipv6 reuseport");
0103     fprintf(stderr, "Opening INADDR_ANY:%d\n", PORT);
0104     fd2 = open_port(0, 1);
0105     if (fd2 >= 0)
0106         error(1, 0, "Was allowed to create an ipv4 reuseport on a already bound non-reuseport socket");
0107     close(fd1);
0108     fprintf(stderr, "Opening INADDR_ANY:%d after closing ipv6 socket\n", PORT);
0109     fd1 = open_port(0, 1);
0110     if (fd1 >= 0)
0111         error(1, 0, "Was allowed to create an ipv4 reuseport on an already bound non-reuseport socket with no ipv6");
0112     fprintf(stderr, "Success");
0113     return 0;
0114 }