linux/tools/testing/selftests/net/af_unix/test_unix_oob.c
<<
>>
Prefs
   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(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
 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 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,
 275                        "Test 3 failed, sigurg %d len %d OOB %c atmark %d\n",
 276                        signal_recvd, len, oob, atmark);
 277                die(1);
 278        }
 279
 280        signal_recvd = 0;
 281
 282        len = read_data(pfd, buf, 1024);
 283        if (len != 64) {
 284                fprintf(stderr, "Test 3.1 failed, sigurg %d len %d OOB %c\n",
 285                        signal_recvd, len, oob);
 286                die(1);
 287        }
 288
 289        signal_recvd = 0;
 290        signal_producer(pipefd[1]);
 291
 292        /* Test 4:
 293         * verify that a single byte
 294         * oob message is delivered.
 295         * set non blocking mode and
 296         * check proper error is
 297         * returned and sigurg is
 298         * received and correct
 299         * oob is read.
 300         */
 301
 302        set_filemode(pfd, 0);
 303
 304        wait_for_data(pfd, POLLIN | POLLPRI);
 305        len = read_data(pfd, buf, 1024);
 306        if ((len == -1) && (errno == 11))
 307                len = 0;
 308
 309        read_oob(pfd, &oob);
 310
 311        if (!signal_recvd || len != 0 || oob != '@') {
 312                fprintf(stderr, "Test 4 failed, sigurg %d len %d OOB %c\n",
 313                         signal_recvd, len, oob);
 314                die(1);
 315        }
 316
 317        set_filemode(pfd, 1);
 318
 319        /* Inline Testing */
 320
 321        on = 1;
 322        if (setsockopt(pfd, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on))) {
 323                perror("SO_OOBINLINE");
 324                die(1);
 325        }
 326
 327        signal_recvd = 0;
 328        signal_producer(pipefd[1]);
 329
 330        /* Test 1 -- Inline:
 331         * Check that SIGURG is
 332         * delivered and 63 bytes are
 333         * read and oob is '@'
 334         */
 335
 336        wait_for_data(pfd, POLLIN | POLLPRI);
 337        len = read_data(pfd, buf, 1024);
 338
 339        if (!signal_recvd || len != 63) {
 340                fprintf(stderr, "Test 1 Inline failed, sigurg %d len %d\n",
 341                        signal_recvd, len);
 342                die(1);
 343        }
 344
 345        len = read_data(pfd, buf, 1024);
 346
 347        if (len != 1) {
 348                fprintf(stderr,
 349                         "Test 1.1 Inline failed, sigurg %d len %d oob %c\n",
 350                         signal_recvd, len, oob);
 351                die(1);
 352        }
 353
 354        signal_recvd = 0;
 355        signal_producer(pipefd[1]);
 356
 357        /* Test 2 -- Inline:
 358         * Verify that the first OOB is over written by
 359         * the 2nd one and read breaks correctly on
 360         * 2nd OOB boundary with the first OOB returned as
 361         * part of the read, and sigurg is delivered and
 362         * siocatmark returns true.
 363         * next read returns one byte, the oob byte
 364         * and siocatmark returns false.
 365         */
 366        len = 0;
 367        wait_for_data(pfd, POLLIN | POLLPRI);
 368        while (len < 70)
 369                len = recv(pfd, buf, 1024, MSG_PEEK);
 370        len = read_data(pfd, buf, 1024);
 371        atmark = is_sioctatmark(pfd);
 372        if (len != 127 || atmark != 1 || !signal_recvd) {
 373                fprintf(stderr, "Test 2 Inline failed, len %d atmark %d\n",
 374                         len, atmark);
 375                die(1);
 376        }
 377
 378        len = read_data(pfd, buf, 1024);
 379        atmark = is_sioctatmark(pfd);
 380        if (len != 1 || buf[0] != '#' || atmark == 1) {
 381                fprintf(stderr, "Test 2.1 Inline failed, len %d data %c atmark %d\n",
 382                        len, buf[0], atmark);
 383                die(1);
 384        }
 385
 386        signal_recvd = 0;
 387        signal_producer(pipefd[1]);
 388
 389        /* Test 3 -- Inline:
 390         * verify that 2nd oob over writes
 391         * the first one and read breaks at
 392         * oob boundary returning 127 bytes
 393         * and sigurg is received and siocatmark
 394         * is true after the read.
 395         * subsequent read returns 65 bytes
 396         * because of oob which should be '%'.
 397         */
 398        len = 0;
 399        wait_for_data(pfd, POLLIN | POLLPRI);
 400        while (len < 126)
 401                len = recv(pfd, buf, 1024, MSG_PEEK);
 402        len = read_data(pfd, buf, 1024);
 403        atmark = is_sioctatmark(pfd);
 404        if (!signal_recvd || len != 127 || !atmark) {
 405                fprintf(stderr,
 406                         "Test 3 Inline failed, sigurg %d len %d data %c\n",
 407                         signal_recvd, len, buf[0]);
 408                die(1);
 409        }
 410
 411        len = read_data(pfd, buf, 1024);
 412        atmark = is_sioctatmark(pfd);
 413        if (len != 65 || buf[0] != '%' || atmark != 0) {
 414                fprintf(stderr,
 415                         "Test 3.1 Inline failed, len %d oob %c atmark %d\n",
 416                         len, buf[0], atmark);
 417                die(1);
 418        }
 419
 420        signal_recvd = 0;
 421        signal_producer(pipefd[1]);
 422
 423        /* Test 4 -- Inline:
 424         * verify that a single
 425         * byte oob message is delivered
 426         * and read returns one byte, the oob
 427         * byte and sigurg is received
 428         */
 429        wait_for_data(pfd, POLLIN | POLLPRI);
 430        len = read_data(pfd, buf, 1024);
 431        if (!signal_recvd || len != 1 || buf[0] != '@') {
 432                fprintf(stderr,
 433                        "Test 4 Inline failed, signal %d len %d data %c\n",
 434                signal_recvd, len, buf[0]);
 435                die(1);
 436        }
 437        die(0);
 438}
 439