reuseaddr_conflict.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  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. #define PORT 9999
  19. int open_port(int ipv6, int any)
  20. {
  21. int fd = -1;
  22. int reuseaddr = 1;
  23. int v6only = 1;
  24. int addrlen;
  25. int ret = -1;
  26. struct sockaddr *addr;
  27. int family = ipv6 ? AF_INET6 : AF_INET;
  28. struct sockaddr_in6 addr6 = {
  29. .sin6_family = AF_INET6,
  30. .sin6_port = htons(PORT),
  31. .sin6_addr = in6addr_any
  32. };
  33. struct sockaddr_in addr4 = {
  34. .sin_family = AF_INET,
  35. .sin_port = htons(PORT),
  36. .sin_addr.s_addr = any ? htonl(INADDR_ANY) : inet_addr("127.0.0.1"),
  37. };
  38. if (ipv6) {
  39. addr = (struct sockaddr*)&addr6;
  40. addrlen = sizeof(addr6);
  41. } else {
  42. addr = (struct sockaddr*)&addr4;
  43. addrlen = sizeof(addr4);
  44. }
  45. if ((fd = socket(family, SOCK_STREAM, IPPROTO_TCP)) < 0) {
  46. perror("socket");
  47. goto out;
  48. }
  49. if (ipv6 && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&v6only,
  50. sizeof(v6only)) < 0) {
  51. perror("setsockopt IPV6_V6ONLY");
  52. goto out;
  53. }
  54. if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr,
  55. sizeof(reuseaddr)) < 0) {
  56. perror("setsockopt SO_REUSEADDR");
  57. goto out;
  58. }
  59. if (bind(fd, addr, addrlen) < 0) {
  60. perror("bind");
  61. goto out;
  62. }
  63. if (any)
  64. return fd;
  65. if (listen(fd, 1) < 0) {
  66. perror("listen");
  67. goto out;
  68. }
  69. return fd;
  70. out:
  71. close(fd);
  72. return ret;
  73. }
  74. int main(void)
  75. {
  76. int listenfd;
  77. int fd1, fd2;
  78. fprintf(stderr, "Opening 127.0.0.1:%d\n", PORT);
  79. listenfd = open_port(0, 0);
  80. if (listenfd < 0)
  81. error(1, errno, "Couldn't open listen socket");
  82. fprintf(stderr, "Opening INADDR_ANY:%d\n", PORT);
  83. fd1 = open_port(0, 1);
  84. if (fd1 >= 0)
  85. error(1, 0, "Was allowed to create an ipv4 reuseport on a already bound non-reuseport socket");
  86. fprintf(stderr, "Opening in6addr_any:%d\n", PORT);
  87. fd1 = open_port(1, 1);
  88. if (fd1 < 0)
  89. error(1, errno, "Couldn't open ipv6 reuseport");
  90. fprintf(stderr, "Opening INADDR_ANY:%d\n", PORT);
  91. fd2 = open_port(0, 1);
  92. if (fd2 >= 0)
  93. error(1, 0, "Was allowed to create an ipv4 reuseport on a already bound non-reuseport socket");
  94. close(fd1);
  95. fprintf(stderr, "Opening INADDR_ANY:%d after closing ipv6 socket\n", PORT);
  96. fd1 = open_port(0, 1);
  97. if (fd1 >= 0)
  98. error(1, 0, "Was allowed to create an ipv4 reuseport on an already bound non-reuseport socket with no ipv6");
  99. fprintf(stderr, "Success");
  100. return 0;
  101. }