1// SPDX-License-Identifier: GPL-2.0-or-later 2#include <stdio.h> 3#include <stdlib.h> 4#include <sys/socket.h> 5#include <arpa/inet.h> 6#include <unistd.h> 7#include <string.h> 8#include <fcntl.h> 9#include <sys/ioctl.h> 10#include <errno.h> 11#include <netinet/tcp.h> 12#include <sys/un.h> 13#include <sys/signal.h> 14#include <sys/poll.h> 15 16static int pipefd[2]; 17static int signal_recvd; 18static pid_t producer_id; 19static char sock_name[32]; 20 21static void sig_hand(int sn, siginfo_t *si, void *p) 22{ 23 signal_recvd = sn; 24} 25 26static int set_sig_handler(int signal) 27{ 28 struct sigaction sa; 29 30 sa.sa_sigaction = sig_hand; 31 sigemptyset(&sa.sa_mask); 32 sa.sa_flags = SA_SIGINFO | SA_RESTART; 33 34 return sigaction(signal, &sa, NULL); 35} 36 37static void set_filemode(int fd, int set) 38{ 39 int flags = fcntl(fd, F_GETFL, 0); 40 41 if (set) 42 flags &= ~O_NONBLOCK; 43 else 44 flags |= O_NONBLOCK; 45 fcntl(fd, F_SETFL, flags); 46} 47 48static void signal_producer(int fd) 49{ 50 char cmd; 51 52 cmd = 'S'; 53 write(fd, &cmd, sizeof(cmd)); 54} 55 56static void wait_for_signal(int fd) 57{ 58 char buf[5]; 59 60 read(fd, buf, 5); 61} 62 63static void die(int status) 64{ 65 fflush(NULL); 66 unlink(sock_name); 67 kill(producer_id, SIGTERM); 68 exit(status); 69} 70 71int is_sioctatmark(int fd) 72{ 73 int ans = -1; 74 75 if (ioctl(fd, SIOCATMARK, &ans, sizeof(ans)) < 0) { 76#ifdef DEBUG 77 perror("SIOCATMARK Failed"); 78#endif 79 } 80 return ans; 81} 82 83void read_oob(int fd, char *c) 84{ 85 86 *c = ' '; 87 if (recv(fd, c, sizeof(*c), MSG_OOB) < 0) { 88#ifdef DEBUG 89 perror("Reading MSG_OOB Failed"); 90#endif 91 } 92} 93 94int read_data(int pfd, char *buf, int size) 95{ 96 int len = 0; 97 98 memset(buf, size, '0'); 99 len = read(pfd, buf, size); 100#ifdef DEBUG 101 if (len < 0) 102 perror("read failed"); 103#endif 104 return len; 105} 106 107static void wait_for_data(int pfd, int event) 108{ 109 struct pollfd pfds[1]; 110 111 pfds[0].fd = pfd; 112 pfds[0].events = event; 113 poll(pfds, 1, -1); 114} 115 116void producer(struct sockaddr_un *consumer_addr) 117{ 118 int cfd; 119 char buf[64]; 120 int i; 121 122 memset(buf, 'x', sizeof(buf)); 123 cfd = socket(AF_UNIX, SOCK_STREAM, 0); 124 125 wait_for_signal(pipefd[0]); 126 if (connect(cfd, (struct sockaddr *)consumer_addr, 127 sizeof(*consumer_addr)) != 0) { 128 perror("Connect failed"); 129 kill(0, SIGTERM); 130 exit(1); 131 } 132 133 for (i = 0; i < 2; i++) { 134 /* Test 1: Test for SIGURG and OOB */ 135 wait_for_signal(pipefd[0]); 136 memset(buf, 'x', sizeof(buf)); 137 buf[63] = '@'; 138 send(cfd, buf, sizeof(buf), MSG_OOB); 139 140 wait_for_signal(pipefd[0]); 141 142 /* Test 2: Test for OOB being overwitten */ 143 memset(buf, 'x', sizeof(buf)); 144 buf[63] = '%'; 145 send(cfd, buf, sizeof(buf), MSG_OOB); 146 147 memset(buf, 'x', sizeof(buf)); 148 buf[63] = '#'; 149 send(cfd, buf, sizeof(buf), MSG_OOB); 150 151 wait_for_signal(pipefd[0]); 152 153 /* Test 3: Test for SIOCATMARK */ 154 memset(buf, 'x', sizeof(buf)); 155 buf[63] = '@'; 156 send(cfd, buf, sizeof(buf), MSG_OOB); 157 158 memset(buf, 'x', sizeof(buf)); 159 buf[63] = '%'; 160 send(cfd, buf, sizeof(buf), MSG_OOB); 161 162 memset(buf, 'x', sizeof(buf)); 163 send(cfd, buf, sizeof(buf), 0); 164 165 wait_for_signal(pipefd[0]); 166 167 /* Test 4: Test for 1byte OOB msg */ 168 memset(buf, 'x', sizeof(buf)); 169 buf[0] = '@'; 170 send(cfd, buf, 1, MSG_OOB); 171 } 172} 173 174int 175main(int argc, char **argv) 176{ 177 int lfd, pfd; 178 struct sockaddr_un consumer_addr, paddr; 179 socklen_t len = sizeof(consumer_addr); 180 char buf[1024]; 181 int on = 0; 182 char oob; 183 int atmark; 184 185 lfd = socket(AF_UNIX, SOCK_STREAM, 0); 186 memset(&consumer_addr, 0, sizeof(consumer_addr)); 187 consumer_addr.sun_family = AF_UNIX; 188 sprintf(sock_name, "unix_oob_%d", getpid()); 189 unlink(sock_name); 190 strcpy(consumer_addr.sun_path, sock_name); 191 192 if ((bind(lfd, (struct sockaddr *)&consumer_addr, 193 sizeof(consumer_addr))) != 0) { 194 perror("socket bind failed"); 195 exit(1); 196 } 197 198 pipe(pipefd); 199 200 listen(lfd, 1); 201 202 producer_id = fork(); 203 if (producer_id == 0) { 204 producer(&consumer_addr); 205 exit(0); 206 } 207 208 set_sig_handler(SIGURG); 209 signal_producer(pipefd[1]); 210 211 pfd = accept(lfd, (struct sockaddr *) &paddr, &len); 212 fcntl(pfd, F_SETOWN, getpid()); 213 214 signal_recvd = 0; 215 signal_producer(pipefd[1]); 216 217 /* Test 1: 218 * veriyf that SIGURG is 219 * delivered, 63 bytes are 220 * read, oob is '@', and POLLPRI works. 221 */ 222 wait_for_data(pfd, POLLPRI); 223 read_oob(pfd, &oob); 224 len = read_data(pfd, buf, 1024); 225 if (!signal_recvd || len != 63 || oob != '@') { 226 fprintf(stderr, "Test 1 failed sigurg %d len %d %c\n", 227 signal_recvd, len, oob); 228 die(1); 229 } 230 231 signal_recvd = 0; 232 signal_producer(pipefd[1]); 233 234 /* Test 2: 235 * Verify that the first OOB is over written by 236 * the 2nd one and the first OOB is returned as 237 * part of the read, and sigurg is received. 238 */ 239 wait_for_data(pfd, POLLIN | POLLPRI); 240 len = 0; 241 while (len < 70) 242 len = recv(pfd, buf, 1024, MSG_PEEK); 243 len = read_data(pfd, buf, 1024); 244 read_oob(pfd, &oob); 245 if (!signal_recvd || len != 127 || oob != '#') { 246 fprintf(stderr, "Test 2 failed, sigurg %d len %d OOB %c\n", 247 signal_recvd, len, oob); 248 die(1); 249 } 250 251 signal_recvd = 0; 252 signal_producer(pipefd[1]); 253 254 /* Test 3: 255 * verify that 2nd oob over writes 256 * the first one and read breaks at 257 * oob boundary returning 127 bytes 258 * and sigurg is received and atmark 259 * is set. 260 * oob is '%' and second read returns 261 * 64 bytes. 262 */ 263 len = 0; 264 wait_for_data(pfd, POLLIN | POLLPRI); 265 while (len < 150) 266 len = recv(pfd, buf, 1024, MSG_PEEK); 267 len = read_data(pfd, buf, 1024); 268 atmark = is_sioctatmark(pfd); 269 read_oob(pfd, &oob); 270 271 if (!signal_recvd || len != 127 || oob != '%' || atmark != 1) { 272 fprintf(stderr, 273 "Test 3 failed, sigurg %d len %d OOB %c atmark %d\n", 274 signal_recvd, len, oob, atmark); 275 die(1); 276 } 277 278 signal_recvd = 0; 279 280 len = read_data(pfd, buf, 1024); 281 if (len != 64) { 282 fprintf(stderr, "Test 3.1 failed, sigurg %d len %d OOB %c\n", 283 signal_recvd, len, oob); 284 die(1); 285 } 286 287 signal_recvd = 0; 288 signal_producer(pipefd[1]); 289 290 /* Test 4: 291 * verify that a single byte 292 * oob message is delivered. 293 * set non blocking mode and 294 * check proper error is 295 * returned and sigurg is 296 * received and correct 297 * oob is read. 298 */ 299 300 set_filemode(pfd, 0); 301 302 wait_for_data(pfd, POLLIN | POLLPRI); 303 len = read_data(pfd, buf, 1024); 304 if ((len == -1) && (errno == 11)) 305 len = 0; 306 307 read_oob(pfd, &oob); 308 309 if (!signal_recvd || len != 0 || oob != '@') { 310 fprintf(stderr, "Test 4 failed, sigurg %d len %d OOB %c\n", 311 signal_recvd, len, oob); 312 die(1); 313 } 314 315 set_filemode(pfd, 1); 316 317 /* Inline Testing */ 318 319 on = 1; 320 if (setsockopt(pfd, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on))) { 321 perror("SO_OOBINLINE"); 322 die(1); 323 } 324 325 signal_recvd = 0; 326 signal_producer(pipefd[1]); 327 328 /* Test 1 -- Inline: 329 * Check that SIGURG is 330 * delivered and 63 bytes are 331 * read and oob is '@' 332 */ 333 334 wait_for_data(pfd, POLLIN | POLLPRI); 335 len = read_data(pfd, buf, 1024); 336 337 if (!signal_recvd || len != 63) { 338 fprintf(stderr, "Test 1 Inline failed, sigurg %d len %d\n", 339 signal_recvd, len); 340 die(1); 341 } 342 343 len = read_data(pfd, buf, 1024); 344 345 if (len != 1) { 346 fprintf(stderr, 347 "Test 1.1 Inline failed, sigurg %d len %d oob %c\n", 348 signal_recvd, len, oob); 349 die(1); 350 } 351 352 signal_recvd = 0; 353 signal_producer(pipefd[1]); 354 355 /* Test 2 -- Inline: 356 * Verify that the first OOB is over written by 357 * the 2nd one and read breaks correctly on 358 * 2nd OOB boundary with the first OOB returned as 359 * part of the read, and sigurg is delivered and 360 * siocatmark returns true. 361 * next read returns one byte, the oob byte 362 * and siocatmark returns false. 363 */ 364 len = 0; 365 wait_for_data(pfd, POLLIN | POLLPRI); 366 while (len < 70) 367 len = recv(pfd, buf, 1024, MSG_PEEK); 368 len = read_data(pfd, buf, 1024); 369 atmark = is_sioctatmark(pfd); 370 if (len != 127 || atmark != 1 || !signal_recvd) { 371 fprintf(stderr, "Test 2 Inline failed, len %d atmark %d\n", 372 len, atmark); 373 die(1); 374 } 375 376 len = read_data(pfd, buf, 1024); 377 atmark = is_sioctatmark(pfd); 378 if (len != 1 || buf[0] != '#' || atmark == 1) { 379 fprintf(stderr, "Test 2.1 Inline failed, len %d data %c atmark %d\n", 380 len, buf[0], atmark); 381 die(1); 382 } 383 384 signal_recvd = 0; 385 signal_producer(pipefd[1]); 386 387 /* Test 3 -- Inline: 388 * verify that 2nd oob over writes 389 * the first one and read breaks at 390 * oob boundary returning 127 bytes 391 * and sigurg is received and siocatmark 392 * is true after the read. 393 * subsequent read returns 65 bytes 394 * because of oob which should be '%'. 395 */ 396 len = 0; 397 wait_for_data(pfd, POLLIN | POLLPRI); 398 while (len < 126) 399 len = recv(pfd, buf, 1024, MSG_PEEK); 400 len = read_data(pfd, buf, 1024); 401 atmark = is_sioctatmark(pfd); 402 if (!signal_recvd || len != 127 || !atmark) { 403 fprintf(stderr, 404 "Test 3 Inline failed, sigurg %d len %d data %c\n", 405 signal_recvd, len, buf[0]); 406 die(1); 407 } 408 409 len = read_data(pfd, buf, 1024); 410 atmark = is_sioctatmark(pfd); 411 if (len != 65 || buf[0] != '%' || atmark != 0) { 412 fprintf(stderr, 413 "Test 3.1 Inline failed, len %d oob %c atmark %d\n", 414 len, buf[0], atmark); 415 die(1); 416 } 417 418 signal_recvd = 0; 419 signal_producer(pipefd[1]); 420 421 /* Test 4 -- Inline: 422 * verify that a single 423 * byte oob message is delivered 424 * and read returns one byte, the oob 425 * byte and sigurg is received 426 */ 427 wait_for_data(pfd, POLLIN | POLLPRI); 428 len = read_data(pfd, buf, 1024); 429 if (!signal_recvd || len != 1 || buf[0] != '@') { 430 fprintf(stderr, 431 "Test 4 Inline failed, signal %d len %d data %c\n", 432 signal_recvd, len, buf[0]); 433 die(1); 434 } 435 die(0); 436} 437