0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020 #include <arpa/inet.h>
0021 #include <netinet/in.h>
0022 #include <sys/socket.h>
0023 #include <sys/types.h>
0024 #include <unistd.h>
0025 #include "../kselftest_harness.h"
0026
0027 struct reuse_opts {
0028 int reuseaddr[2];
0029 int reuseport[2];
0030 };
0031
0032 struct reuse_opts unreusable_opts[12] = {
0033 {{0, 0}, {0, 0}},
0034 {{0, 0}, {0, 1}},
0035 {{0, 0}, {1, 0}},
0036 {{0, 0}, {1, 1}},
0037 {{0, 1}, {0, 0}},
0038 {{0, 1}, {0, 1}},
0039 {{0, 1}, {1, 0}},
0040 {{0, 1}, {1, 1}},
0041 {{1, 0}, {0, 0}},
0042 {{1, 0}, {0, 1}},
0043 {{1, 0}, {1, 0}},
0044 {{1, 0}, {1, 1}},
0045 };
0046
0047 struct reuse_opts reusable_opts[4] = {
0048 {{1, 1}, {0, 0}},
0049 {{1, 1}, {0, 1}},
0050 {{1, 1}, {1, 0}},
0051 {{1, 1}, {1, 1}},
0052 };
0053
0054 int bind_port(struct __test_metadata *_metadata, int reuseaddr, int reuseport)
0055 {
0056 struct sockaddr_in local_addr;
0057 int len = sizeof(local_addr);
0058 int fd, ret;
0059
0060 fd = socket(AF_INET, SOCK_STREAM, 0);
0061 ASSERT_NE(-1, fd) TH_LOG("failed to open socket.");
0062
0063 ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(int));
0064 ASSERT_EQ(0, ret) TH_LOG("failed to setsockopt: SO_REUSEADDR.");
0065
0066 ret = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &reuseport, sizeof(int));
0067 ASSERT_EQ(0, ret) TH_LOG("failed to setsockopt: SO_REUSEPORT.");
0068
0069 local_addr.sin_family = AF_INET;
0070 local_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
0071 local_addr.sin_port = 0;
0072
0073 if (bind(fd, (struct sockaddr *)&local_addr, len) == -1) {
0074 close(fd);
0075 return -1;
0076 }
0077
0078 return fd;
0079 }
0080
0081 TEST(reuseaddr_ports_exhausted_unreusable)
0082 {
0083 struct reuse_opts *opts;
0084 int i, j, fd[2];
0085
0086 for (i = 0; i < 12; i++) {
0087 opts = &unreusable_opts[i];
0088
0089 for (j = 0; j < 2; j++)
0090 fd[j] = bind_port(_metadata, opts->reuseaddr[j], opts->reuseport[j]);
0091
0092 ASSERT_NE(-1, fd[0]) TH_LOG("failed to bind.");
0093 EXPECT_EQ(-1, fd[1]) TH_LOG("should fail to bind.");
0094
0095 for (j = 0; j < 2; j++)
0096 if (fd[j] != -1)
0097 close(fd[j]);
0098 }
0099 }
0100
0101 TEST(reuseaddr_ports_exhausted_reusable_same_euid)
0102 {
0103 struct reuse_opts *opts;
0104 int i, j, fd[2];
0105
0106 for (i = 0; i < 4; i++) {
0107 opts = &reusable_opts[i];
0108
0109 for (j = 0; j < 2; j++)
0110 fd[j] = bind_port(_metadata, opts->reuseaddr[j], opts->reuseport[j]);
0111
0112 ASSERT_NE(-1, fd[0]) TH_LOG("failed to bind.");
0113
0114 if (opts->reuseport[0] && opts->reuseport[1]) {
0115 EXPECT_EQ(-1, fd[1]) TH_LOG("should fail to bind because both sockets succeed to be listened.");
0116 } else {
0117 EXPECT_NE(-1, fd[1]) TH_LOG("should succeed to bind to connect to different destinations.");
0118 }
0119
0120 for (j = 0; j < 2; j++)
0121 if (fd[j] != -1)
0122 close(fd[j]);
0123 }
0124 }
0125
0126 TEST(reuseaddr_ports_exhausted_reusable_different_euid)
0127 {
0128 struct reuse_opts *opts;
0129 int i, j, ret, fd[2];
0130 uid_t euid[2] = {10, 20};
0131
0132 for (i = 0; i < 4; i++) {
0133 opts = &reusable_opts[i];
0134
0135 for (j = 0; j < 2; j++) {
0136 ret = seteuid(euid[j]);
0137 ASSERT_EQ(0, ret) TH_LOG("failed to seteuid: %d.", euid[j]);
0138
0139 fd[j] = bind_port(_metadata, opts->reuseaddr[j], opts->reuseport[j]);
0140
0141 ret = seteuid(0);
0142 ASSERT_EQ(0, ret) TH_LOG("failed to seteuid: 0.");
0143 }
0144
0145 ASSERT_NE(-1, fd[0]) TH_LOG("failed to bind.");
0146 EXPECT_NE(-1, fd[1]) TH_LOG("should succeed to bind because one socket can be bound in each euid.");
0147
0148 if (fd[1] != -1) {
0149 ret = listen(fd[0], 5);
0150 ASSERT_EQ(0, ret) TH_LOG("failed to listen.");
0151
0152 ret = listen(fd[1], 5);
0153 EXPECT_EQ(-1, ret) TH_LOG("should fail to listen because only one uid reserves the port in TCP_LISTEN.");
0154 }
0155
0156 for (j = 0; j < 2; j++)
0157 if (fd[j] != -1)
0158 close(fd[j]);
0159 }
0160 }
0161
0162 TEST_HARNESS_MAIN