root/tools/testing/selftests/net/reuseaddr_conflict.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. open_port
  2. main

   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 }

/* [<][>][^][v][top][bottom][index][help] */