1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright Amazon.com Inc. or its affiliates. */ 3 4 #include <fcntl.h> 5 #include <string.h> 6 #include <unistd.h> 7 8 #include <netinet/in.h> 9 #include <sys/socket.h> 10 11 #include "../../kselftest_harness.h" 12 13 #define BUF_SZ 32 14 15 FIXTURE(msg_oob) 16 { 17 int fd[4]; /* 0: AF_UNIX sender 18 * 1: AF_UNIX receiver 19 * 2: TCP sender 20 * 3: TCP receiver 21 */ 22 }; 23 24 FIXTURE_VARIANT(msg_oob) 25 { 26 bool peek; 27 }; 28 29 FIXTURE_VARIANT_ADD(msg_oob, no_peek) 30 { 31 .peek = false, 32 }; 33 34 FIXTURE_VARIANT_ADD(msg_oob, peek) 35 { 36 .peek = true 37 }; 38 39 static void create_unix_socketpair(struct __test_metadata *_metadata, 40 FIXTURE_DATA(msg_oob) *self) 41 { 42 int ret; 43 44 ret = socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0, self->fd); 45 ASSERT_EQ(ret, 0); 46 } 47 48 static void create_tcp_socketpair(struct __test_metadata *_metadata, 49 FIXTURE_DATA(msg_oob) *self) 50 { 51 struct sockaddr_in addr; 52 socklen_t addrlen; 53 int listen_fd; 54 int ret; 55 56 listen_fd = socket(AF_INET, SOCK_STREAM, 0); 57 ASSERT_GE(listen_fd, 0); 58 59 ret = listen(listen_fd, -1); 60 ASSERT_EQ(ret, 0); 61 62 addrlen = sizeof(addr); 63 ret = getsockname(listen_fd, (struct sockaddr *)&addr, &addrlen); 64 ASSERT_EQ(ret, 0); 65 66 self->fd[2] = socket(AF_INET, SOCK_STREAM, 0); 67 ASSERT_GE(self->fd[2], 0); 68 69 ret = connect(self->fd[2], (struct sockaddr *)&addr, addrlen); 70 ASSERT_EQ(ret, 0); 71 72 self->fd[3] = accept(listen_fd, (struct sockaddr *)&addr, &addrlen); 73 ASSERT_GE(self->fd[3], 0); 74 75 ret = fcntl(self->fd[3], F_SETFL, O_NONBLOCK); 76 ASSERT_EQ(ret, 0); 77 } 78 79 static void close_sockets(FIXTURE_DATA(msg_oob) *self) 80 { 81 int i; 82 83 for (i = 0; i < 4; i++) 84 close(self->fd[i]); 85 } 86 87 FIXTURE_SETUP(msg_oob) 88 { 89 create_unix_socketpair(_metadata, self); 90 create_tcp_socketpair(_metadata, self); 91 } 92 93 FIXTURE_TEARDOWN(msg_oob) 94 { 95 close_sockets(self); 96 } 97 98 static void __sendpair(struct __test_metadata *_metadata, 99 FIXTURE_DATA(msg_oob) *self, 100 const void *buf, size_t len, int flags) 101 { 102 int i, ret[2]; 103 104 for (i = 0; i < 2; i++) 105 ret[i] = send(self->fd[i * 2], buf, len, flags); 106 107 ASSERT_EQ(ret[0], len); 108 ASSERT_EQ(ret[0], ret[1]); 109 } 110 111 static void __recvpair(struct __test_metadata *_metadata, 112 FIXTURE_DATA(msg_oob) *self, 113 const void *expected_buf, int expected_len, 114 int buf_len, int flags) 115 { 116 int i, ret[2], recv_errno[2], expected_errno = 0; 117 char recv_buf[2][BUF_SZ] = {}; 118 119 ASSERT_GE(BUF_SZ, buf_len); 120 121 errno = 0; 122 123 for (i = 0; i < 2; i++) { 124 ret[i] = recv(self->fd[i * 2 + 1], recv_buf[i], buf_len, flags); 125 recv_errno[i] = errno; 126 } 127 128 if (expected_len < 0) { 129 expected_errno = -expected_len; 130 expected_len = -1; 131 } 132 133 if (ret[0] != expected_len || recv_errno[0] != expected_errno) { 134 TH_LOG("AF_UNIX :%s", ret[0] < 0 ? strerror(recv_errno[0]) : recv_buf[0]); 135 TH_LOG("Expected:%s", expected_errno ? strerror(expected_errno) : expected_buf); 136 137 ASSERT_EQ(ret[0], expected_len); 138 ASSERT_EQ(recv_errno[0], expected_errno); 139 } 140 141 if (ret[0] != ret[1] || recv_errno[0] != recv_errno[1]) { 142 TH_LOG("AF_UNIX :%s", ret[0] < 0 ? strerror(recv_errno[0]) : recv_buf[0]); 143 TH_LOG("TCP :%s", ret[1] < 0 ? strerror(recv_errno[1]) : recv_buf[1]); 144 145 ASSERT_EQ(ret[0], ret[1]); 146 ASSERT_EQ(recv_errno[0], recv_errno[1]); 147 } 148 149 if (expected_len >= 0) { 150 int cmp; 151 152 cmp = strncmp(expected_buf, recv_buf[0], expected_len); 153 if (cmp) { 154 TH_LOG("AF_UNIX :%s", ret[0] < 0 ? strerror(recv_errno[0]) : recv_buf[0]); 155 TH_LOG("Expected:%s", expected_errno ? strerror(expected_errno) : expected_buf); 156 157 ASSERT_EQ(cmp, 0); 158 } 159 160 cmp = strncmp(recv_buf[0], recv_buf[1], expected_len); 161 if (cmp) { 162 TH_LOG("AF_UNIX :%s", ret[0] < 0 ? strerror(recv_errno[0]) : recv_buf[0]); 163 TH_LOG("TCP :%s", ret[1] < 0 ? strerror(recv_errno[1]) : recv_buf[1]); 164 165 ASSERT_EQ(cmp, 0); 166 } 167 } 168 } 169 170 #define sendpair(buf, len, flags) \ 171 __sendpair(_metadata, self, buf, len, flags) 172 173 #define recvpair(expected_buf, expected_len, buf_len, flags) \ 174 do { \ 175 if (variant->peek) \ 176 __recvpair(_metadata, self, \ 177 expected_buf, expected_len, \ 178 buf_len, (flags) | MSG_PEEK); \ 179 __recvpair(_metadata, self, \ 180 expected_buf, expected_len, buf_len, flags); \ 181 } while (0) 182 183 TEST_F(msg_oob, non_oob) 184 { 185 sendpair("x", 1, 0); 186 187 recvpair("", -EINVAL, 1, MSG_OOB); 188 } 189 190 TEST_F(msg_oob, oob) 191 { 192 sendpair("x", 1, MSG_OOB); 193 194 recvpair("x", 1, 1, MSG_OOB); 195 } 196 197 TEST_F(msg_oob, oob_drop) 198 { 199 sendpair("x", 1, MSG_OOB); 200 201 recvpair("", -EAGAIN, 1, 0); /* Drop OOB. */ 202 recvpair("", -EINVAL, 1, MSG_OOB); 203 } 204 205 TEST_F(msg_oob, oob_ahead) 206 { 207 sendpair("hello", 5, MSG_OOB); 208 209 recvpair("o", 1, 1, MSG_OOB); 210 recvpair("hell", 4, 4, 0); 211 } 212 213 TEST_F(msg_oob, oob_break) 214 { 215 sendpair("hello", 5, MSG_OOB); 216 217 recvpair("hell", 4, 5, 0); /* Break at OOB even with enough buffer. */ 218 recvpair("o", 1, 1, MSG_OOB); 219 } 220 221 TEST_F(msg_oob, oob_ahead_break) 222 { 223 sendpair("hello", 5, MSG_OOB); 224 sendpair("world", 5, 0); 225 226 recvpair("o", 1, 1, MSG_OOB); 227 recvpair("hell", 4, 9, 0); /* Break at OOB even after it's recv()ed. */ 228 recvpair("world", 5, 5, 0); 229 } 230 231 TEST_F(msg_oob, oob_break_drop) 232 { 233 sendpair("hello", 5, MSG_OOB); 234 sendpair("world", 5, 0); 235 236 recvpair("hell", 4, 10, 0); /* Break at OOB even with enough buffer. */ 237 recvpair("world", 5, 10, 0); /* Drop OOB and recv() the next skb. */ 238 recvpair("", -EINVAL, 1, MSG_OOB); 239 } 240 241 TEST_HARNESS_MAIN 242