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 16 static int pipefd[2]; 17 static int signal_recvd; 18 static pid_t producer_id; 19 static char sock_name[32]; 20 21 static void sig_hand(int sn, siginfo_t *si, void *p) 22 { 23 signal_recvd = sn; 24 } 25 26 static 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 37 static 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 48 static void signal_producer(int fd) 49 { 50 char cmd; 51 52 cmd = 'S'; 53 write(fd, &cmd, sizeof(cmd)); 54 } 55 56 static void wait_for_signal(int fd) 57 { 58 char buf[5]; 59 60 read(fd, buf, 5); 61 } 62 63 static void die(int status) 64 { 65 fflush(NULL); 66 unlink(sock_name); 67 kill(producer_id, SIGTERM); 68 exit(status); 69 } 70 71 int 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 83 void 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 94 int 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 107 static 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 116 void 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(struct sockaddr)) != 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 174 int 175 main(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 flags; 184 int atmark; 185 char *tmp_file; 186 187 lfd = socket(AF_UNIX, SOCK_STREAM, 0); 188 memset(&consumer_addr, 0, sizeof(consumer_addr)); 189 consumer_addr.sun_family = AF_UNIX; 190 sprintf(sock_name, "unix_oob_%d", getpid()); 191 unlink(sock_name); 192 strcpy(consumer_addr.sun_path, sock_name); 193 194 if ((bind(lfd, (struct sockaddr *)&consumer_addr, 195 sizeof(consumer_addr))) != 0) { 196 perror("socket bind failed"); 197 exit(1); 198 } 199 200 pipe(pipefd); 201 202 listen(lfd, 1); 203 204 producer_id = fork(); 205 if (producer_id == 0) { 206 producer(&consumer_addr); 207 exit(0); 208 } 209 210 set_sig_handler(SIGURG); 211 signal_producer(pipefd[1]); 212 213 pfd = accept(lfd, (struct sockaddr *) &paddr, &len); 214 fcntl(pfd, F_SETOWN, getpid()); 215 216 signal_recvd = 0; 217 signal_producer(pipefd[1]); 218 219 /* Test 1: 220 * veriyf that SIGURG is 221 * delivered and 63 bytes are 222 * read and oob is '@' 223 */ 224 wait_for_data(pfd, POLLIN | POLLPRI); 225 read_oob(pfd, &oob); 226 len = read_data(pfd, buf, 1024); 227 if (!signal_recvd || len != 63 || oob != '@') { 228 fprintf(stderr, "Test 1 failed sigurg %d len %d %c\n", 229 signal_recvd, len, oob); 230 die(1); 231 } 232 233 signal_recvd = 0; 234 signal_producer(pipefd[1]); 235 236 /* Test 2: 237 * Verify that the first OOB is over written by 238 * the 2nd one and the first OOB is returned as 239 * part of the read, and sigurg is received. 240 */ 241 wait_for_data(pfd, POLLIN | POLLPRI); 242 len = 0; 243 while (len < 70) 244 len = recv(pfd, buf, 1024, MSG_PEEK); 245 len = read_data(pfd, buf, 1024); 246 read_oob(pfd, &oob); 247 if (!signal_recvd || len != 127 || oob != '#') { 248 fprintf(stderr, "Test 2 failed, sigurg %d len %d OOB %c\n", 249 signal_recvd, len, oob); 250 die(1); 251 } 252 253 signal_recvd = 0; 254 signal_producer(pipefd[1]); 255 256 /* Test 3: 257 * verify that 2nd oob over writes 258 * the first one and read breaks at 259 * oob boundary returning 127 bytes 260 * and sigurg is received and atmark 261 * is set. 262 * oob is '%' and second read returns 263 * 64 bytes. 264 */ 265 len = 0; 266 wait_for_data(pfd, POLLIN | POLLPRI); 267 while (len < 150) 268 len = recv(pfd, buf, 1024, MSG_PEEK); 269 len = read_data(pfd, buf, 1024); 270 atmark = is_sioctatmark(pfd); 271 read_oob(pfd, &oob); 272 273 if (!signal_recvd || len != 127 || oob != '%' || atmark != 1) { 274 fprintf(stderr, "Test 3 failed, sigurg %d len %d OOB %c ", 275 "atmark %d\n", signal_recvd, len, oob, atmark); 276 die(1); 277 } 278 279 signal_recvd = 0; 280 281 len = read_data(pfd, buf, 1024); 282 if (len != 64) { 283 fprintf(stderr, "Test 3.1 failed, sigurg %d len %d OOB %c\n", 284 signal_recvd, len, oob); 285 die(1); 286 } 287 288 signal_recvd = 0; 289 signal_producer(pipefd[1]); 290 291 /* Test 4: 292 * verify that a single byte 293 * oob message is delivered. 294 * set non blocking mode and 295 * check proper error is 296 * returned and sigurg is 297 * received and correct 298 * oob is read. 299 */ 300 301 set_filemode(pfd, 0); 302 303 wait_for_data(pfd, POLLIN | POLLPRI); 304 len = read_data(pfd, buf, 1024); 305 if ((len == -1) && (errno == 11)) 306 len = 0; 307 308 read_oob(pfd, &oob); 309 310 if (!signal_recvd || len != 0 || oob != '@') { 311 fprintf(stderr, "Test 4 failed, sigurg %d len %d OOB %c\n", 312 signal_recvd, len, oob); 313 die(1); 314 } 315 316 set_filemode(pfd, 1); 317 318 /* Inline Testing */ 319 320 on = 1; 321 if (setsockopt(pfd, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on))) { 322 perror("SO_OOBINLINE"); 323 die(1); 324 } 325 326 signal_recvd = 0; 327 signal_producer(pipefd[1]); 328 329 /* Test 1 -- Inline: 330 * Check that SIGURG is 331 * delivered and 63 bytes are 332 * read and oob is '@' 333 */ 334 335 wait_for_data(pfd, POLLIN | POLLPRI); 336 len = read_data(pfd, buf, 1024); 337 338 if (!signal_recvd || len != 63) { 339 fprintf(stderr, "Test 1 Inline failed, sigurg %d len %d\n", 340 signal_recvd, len); 341 die(1); 342 } 343 344 len = read_data(pfd, buf, 1024); 345 346 if (len != 1) { 347 fprintf(stderr, 348 "Test 1.1 Inline failed, sigurg %d len %d oob %c\n", 349 signal_recvd, len, oob); 350 die(1); 351 } 352 353 signal_recvd = 0; 354 signal_producer(pipefd[1]); 355 356 /* Test 2 -- Inline: 357 * Verify that the first OOB is over written by 358 * the 2nd one and read breaks correctly on 359 * 2nd OOB boundary with the first OOB returned as 360 * part of the read, and sigurg is delivered and 361 * siocatmark returns true. 362 * next read returns one byte, the oob byte 363 * and siocatmark returns false. 364 */ 365 len = 0; 366 wait_for_data(pfd, POLLIN | POLLPRI); 367 while (len < 70) 368 len = recv(pfd, buf, 1024, MSG_PEEK); 369 len = read_data(pfd, buf, 1024); 370 atmark = is_sioctatmark(pfd); 371 if (len != 127 || atmark != 1 || !signal_recvd) { 372 fprintf(stderr, "Test 2 Inline failed, len %d atmark %d\n", 373 len, atmark); 374 die(1); 375 } 376 377 len = read_data(pfd, buf, 1024); 378 atmark = is_sioctatmark(pfd); 379 if (len != 1 || buf[0] != '#' || atmark == 1) { 380 fprintf(stderr, "Test 2.1 Inline failed, len %d data %c atmark %d\n", 381 len, buf[0], atmark); 382 die(1); 383 } 384 385 signal_recvd = 0; 386 signal_producer(pipefd[1]); 387 388 /* Test 3 -- Inline: 389 * verify that 2nd oob over writes 390 * the first one and read breaks at 391 * oob boundary returning 127 bytes 392 * and sigurg is received and siocatmark 393 * is true after the read. 394 * subsequent read returns 65 bytes 395 * because of oob which should be '%'. 396 */ 397 len = 0; 398 wait_for_data(pfd, POLLIN | POLLPRI); 399 while (len < 126) 400 len = recv(pfd, buf, 1024, MSG_PEEK); 401 len = read_data(pfd, buf, 1024); 402 atmark = is_sioctatmark(pfd); 403 if (!signal_recvd || len != 127 || !atmark) { 404 fprintf(stderr, 405 "Test 3 Inline failed, sigurg %d len %d data %c\n", 406 signal_recvd, len, buf[0]); 407 die(1); 408 } 409 410 len = read_data(pfd, buf, 1024); 411 atmark = is_sioctatmark(pfd); 412 if (len != 65 || buf[0] != '%' || atmark != 0) { 413 fprintf(stderr, 414 "Test 3.1 Inline failed, len %d oob %c atmark %d\n", 415 len, buf[0], atmark); 416 die(1); 417 } 418 419 signal_recvd = 0; 420 signal_producer(pipefd[1]); 421 422 /* Test 4 -- Inline: 423 * verify that a single 424 * byte oob message is delivered 425 * and read returns one byte, the oob 426 * byte and sigurg is received 427 */ 428 wait_for_data(pfd, POLLIN | POLLPRI); 429 len = read_data(pfd, buf, 1024); 430 if (!signal_recvd || len != 1 || buf[0] != '@') { 431 fprintf(stderr, 432 "Test 4 Inline failed, signal %d len %d data %c\n", 433 signal_recvd, len, buf[0]); 434 die(1); 435 } 436 die(0); 437 } 438