Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 #include <stdio.h>
0003 #include <stdlib.h>
0004 #include <sys/socket.h>
0005 #include <arpa/inet.h>
0006 #include <unistd.h>
0007 #include <string.h>
0008 #include <fcntl.h>
0009 #include <sys/ioctl.h>
0010 #include <errno.h>
0011 #include <netinet/tcp.h>
0012 #include <sys/un.h>
0013 #include <sys/signal.h>
0014 #include <sys/poll.h>
0015 
0016 static int pipefd[2];
0017 static int signal_recvd;
0018 static pid_t producer_id;
0019 static char sock_name[32];
0020 
0021 static void sig_hand(int sn, siginfo_t *si, void *p)
0022 {
0023     signal_recvd = sn;
0024 }
0025 
0026 static int set_sig_handler(int signal)
0027 {
0028     struct sigaction sa;
0029 
0030     sa.sa_sigaction = sig_hand;
0031     sigemptyset(&sa.sa_mask);
0032     sa.sa_flags = SA_SIGINFO | SA_RESTART;
0033 
0034     return sigaction(signal, &sa, NULL);
0035 }
0036 
0037 static void set_filemode(int fd, int set)
0038 {
0039     int flags = fcntl(fd, F_GETFL, 0);
0040 
0041     if (set)
0042         flags &= ~O_NONBLOCK;
0043     else
0044         flags |= O_NONBLOCK;
0045     fcntl(fd, F_SETFL, flags);
0046 }
0047 
0048 static void signal_producer(int fd)
0049 {
0050     char cmd;
0051 
0052     cmd = 'S';
0053     write(fd, &cmd, sizeof(cmd));
0054 }
0055 
0056 static void wait_for_signal(int fd)
0057 {
0058     char buf[5];
0059 
0060     read(fd, buf, 5);
0061 }
0062 
0063 static void die(int status)
0064 {
0065     fflush(NULL);
0066     unlink(sock_name);
0067     kill(producer_id, SIGTERM);
0068     exit(status);
0069 }
0070 
0071 int is_sioctatmark(int fd)
0072 {
0073     int ans = -1;
0074 
0075     if (ioctl(fd, SIOCATMARK, &ans, sizeof(ans)) < 0) {
0076 #ifdef DEBUG
0077         perror("SIOCATMARK Failed");
0078 #endif
0079     }
0080     return ans;
0081 }
0082 
0083 void read_oob(int fd, char *c)
0084 {
0085 
0086     *c = ' ';
0087     if (recv(fd, c, sizeof(*c), MSG_OOB) < 0) {
0088 #ifdef DEBUG
0089         perror("Reading MSG_OOB Failed");
0090 #endif
0091     }
0092 }
0093 
0094 int read_data(int pfd, char *buf, int size)
0095 {
0096     int len = 0;
0097 
0098     memset(buf, size, '0');
0099     len = read(pfd, buf, size);
0100 #ifdef DEBUG
0101     if (len < 0)
0102         perror("read failed");
0103 #endif
0104     return len;
0105 }
0106 
0107 static void wait_for_data(int pfd, int event)
0108 {
0109     struct pollfd pfds[1];
0110 
0111     pfds[0].fd = pfd;
0112     pfds[0].events = event;
0113     poll(pfds, 1, -1);
0114 }
0115 
0116 void producer(struct sockaddr_un *consumer_addr)
0117 {
0118     int cfd;
0119     char buf[64];
0120     int i;
0121 
0122     memset(buf, 'x', sizeof(buf));
0123     cfd = socket(AF_UNIX, SOCK_STREAM, 0);
0124 
0125     wait_for_signal(pipefd[0]);
0126     if (connect(cfd, (struct sockaddr *)consumer_addr,
0127              sizeof(struct sockaddr)) != 0) {
0128         perror("Connect failed");
0129         kill(0, SIGTERM);
0130         exit(1);
0131     }
0132 
0133     for (i = 0; i < 2; i++) {
0134         /* Test 1: Test for SIGURG and OOB */
0135         wait_for_signal(pipefd[0]);
0136         memset(buf, 'x', sizeof(buf));
0137         buf[63] = '@';
0138         send(cfd, buf, sizeof(buf), MSG_OOB);
0139 
0140         wait_for_signal(pipefd[0]);
0141 
0142         /* Test 2: Test for OOB being overwitten */
0143         memset(buf, 'x', sizeof(buf));
0144         buf[63] = '%';
0145         send(cfd, buf, sizeof(buf), MSG_OOB);
0146 
0147         memset(buf, 'x', sizeof(buf));
0148         buf[63] = '#';
0149         send(cfd, buf, sizeof(buf), MSG_OOB);
0150 
0151         wait_for_signal(pipefd[0]);
0152 
0153         /* Test 3: Test for SIOCATMARK */
0154         memset(buf, 'x', sizeof(buf));
0155         buf[63] = '@';
0156         send(cfd, buf, sizeof(buf), MSG_OOB);
0157 
0158         memset(buf, 'x', sizeof(buf));
0159         buf[63] = '%';
0160         send(cfd, buf, sizeof(buf), MSG_OOB);
0161 
0162         memset(buf, 'x', sizeof(buf));
0163         send(cfd, buf, sizeof(buf), 0);
0164 
0165         wait_for_signal(pipefd[0]);
0166 
0167         /* Test 4: Test for 1byte OOB msg */
0168         memset(buf, 'x', sizeof(buf));
0169         buf[0] = '@';
0170         send(cfd, buf, 1, MSG_OOB);
0171     }
0172 }
0173 
0174 int
0175 main(int argc, char **argv)
0176 {
0177     int lfd, pfd;
0178     struct sockaddr_un consumer_addr, paddr;
0179     socklen_t len = sizeof(consumer_addr);
0180     char buf[1024];
0181     int on = 0;
0182     char oob;
0183     int flags;
0184     int atmark;
0185     char *tmp_file;
0186 
0187     lfd = socket(AF_UNIX, SOCK_STREAM, 0);
0188     memset(&consumer_addr, 0, sizeof(consumer_addr));
0189     consumer_addr.sun_family = AF_UNIX;
0190     sprintf(sock_name, "unix_oob_%d", getpid());
0191     unlink(sock_name);
0192     strcpy(consumer_addr.sun_path, sock_name);
0193 
0194     if ((bind(lfd, (struct sockaddr *)&consumer_addr,
0195           sizeof(consumer_addr))) != 0) {
0196         perror("socket bind failed");
0197         exit(1);
0198     }
0199 
0200     pipe(pipefd);
0201 
0202     listen(lfd, 1);
0203 
0204     producer_id = fork();
0205     if (producer_id == 0) {
0206         producer(&consumer_addr);
0207         exit(0);
0208     }
0209 
0210     set_sig_handler(SIGURG);
0211     signal_producer(pipefd[1]);
0212 
0213     pfd = accept(lfd, (struct sockaddr *) &paddr, &len);
0214     fcntl(pfd, F_SETOWN, getpid());
0215 
0216     signal_recvd = 0;
0217     signal_producer(pipefd[1]);
0218 
0219     /* Test 1:
0220      * veriyf that SIGURG is
0221      * delivered, 63 bytes are
0222      * read, oob is '@', and POLLPRI works.
0223      */
0224     wait_for_data(pfd, POLLPRI);
0225     read_oob(pfd, &oob);
0226     len = read_data(pfd, buf, 1024);
0227     if (!signal_recvd || len != 63 || oob != '@') {
0228         fprintf(stderr, "Test 1 failed sigurg %d len %d %c\n",
0229              signal_recvd, len, oob);
0230             die(1);
0231     }
0232 
0233     signal_recvd = 0;
0234     signal_producer(pipefd[1]);
0235 
0236     /* Test 2:
0237      * Verify that the first OOB is over written by
0238      * the 2nd one and the first OOB is returned as
0239      * part of the read, and sigurg is received.
0240      */
0241     wait_for_data(pfd, POLLIN | POLLPRI);
0242     len = 0;
0243     while (len < 70)
0244         len = recv(pfd, buf, 1024, MSG_PEEK);
0245     len = read_data(pfd, buf, 1024);
0246     read_oob(pfd, &oob);
0247     if (!signal_recvd || len != 127 || oob != '#') {
0248         fprintf(stderr, "Test 2 failed, sigurg %d len %d OOB %c\n",
0249         signal_recvd, len, oob);
0250         die(1);
0251     }
0252 
0253     signal_recvd = 0;
0254     signal_producer(pipefd[1]);
0255 
0256     /* Test 3:
0257      * verify that 2nd oob over writes
0258      * the first one and read breaks at
0259      * oob boundary returning 127 bytes
0260      * and sigurg is received and atmark
0261      * is set.
0262      * oob is '%' and second read returns
0263      * 64 bytes.
0264      */
0265     len = 0;
0266     wait_for_data(pfd, POLLIN | POLLPRI);
0267     while (len < 150)
0268         len = recv(pfd, buf, 1024, MSG_PEEK);
0269     len = read_data(pfd, buf, 1024);
0270     atmark = is_sioctatmark(pfd);
0271     read_oob(pfd, &oob);
0272 
0273     if (!signal_recvd || len != 127 || oob != '%' || atmark != 1) {
0274         fprintf(stderr,
0275             "Test 3 failed, sigurg %d len %d OOB %c atmark %d\n",
0276             signal_recvd, len, oob, atmark);
0277         die(1);
0278     }
0279 
0280     signal_recvd = 0;
0281 
0282     len = read_data(pfd, buf, 1024);
0283     if (len != 64) {
0284         fprintf(stderr, "Test 3.1 failed, sigurg %d len %d OOB %c\n",
0285             signal_recvd, len, oob);
0286         die(1);
0287     }
0288 
0289     signal_recvd = 0;
0290     signal_producer(pipefd[1]);
0291 
0292     /* Test 4:
0293      * verify that a single byte
0294      * oob message is delivered.
0295      * set non blocking mode and
0296      * check proper error is
0297      * returned and sigurg is
0298      * received and correct
0299      * oob is read.
0300      */
0301 
0302     set_filemode(pfd, 0);
0303 
0304     wait_for_data(pfd, POLLIN | POLLPRI);
0305     len = read_data(pfd, buf, 1024);
0306     if ((len == -1) && (errno == 11))
0307         len = 0;
0308 
0309     read_oob(pfd, &oob);
0310 
0311     if (!signal_recvd || len != 0 || oob != '@') {
0312         fprintf(stderr, "Test 4 failed, sigurg %d len %d OOB %c\n",
0313              signal_recvd, len, oob);
0314         die(1);
0315     }
0316 
0317     set_filemode(pfd, 1);
0318 
0319     /* Inline Testing */
0320 
0321     on = 1;
0322     if (setsockopt(pfd, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on))) {
0323         perror("SO_OOBINLINE");
0324         die(1);
0325     }
0326 
0327     signal_recvd = 0;
0328     signal_producer(pipefd[1]);
0329 
0330     /* Test 1 -- Inline:
0331      * Check that SIGURG is
0332      * delivered and 63 bytes are
0333      * read and oob is '@'
0334      */
0335 
0336     wait_for_data(pfd, POLLIN | POLLPRI);
0337     len = read_data(pfd, buf, 1024);
0338 
0339     if (!signal_recvd || len != 63) {
0340         fprintf(stderr, "Test 1 Inline failed, sigurg %d len %d\n",
0341             signal_recvd, len);
0342         die(1);
0343     }
0344 
0345     len = read_data(pfd, buf, 1024);
0346 
0347     if (len != 1) {
0348         fprintf(stderr,
0349              "Test 1.1 Inline failed, sigurg %d len %d oob %c\n",
0350              signal_recvd, len, oob);
0351         die(1);
0352     }
0353 
0354     signal_recvd = 0;
0355     signal_producer(pipefd[1]);
0356 
0357     /* Test 2 -- Inline:
0358      * Verify that the first OOB is over written by
0359      * the 2nd one and read breaks correctly on
0360      * 2nd OOB boundary with the first OOB returned as
0361      * part of the read, and sigurg is delivered and
0362      * siocatmark returns true.
0363      * next read returns one byte, the oob byte
0364      * and siocatmark returns false.
0365      */
0366     len = 0;
0367     wait_for_data(pfd, POLLIN | POLLPRI);
0368     while (len < 70)
0369         len = recv(pfd, buf, 1024, MSG_PEEK);
0370     len = read_data(pfd, buf, 1024);
0371     atmark = is_sioctatmark(pfd);
0372     if (len != 127 || atmark != 1 || !signal_recvd) {
0373         fprintf(stderr, "Test 2 Inline failed, len %d atmark %d\n",
0374              len, atmark);
0375         die(1);
0376     }
0377 
0378     len = read_data(pfd, buf, 1024);
0379     atmark = is_sioctatmark(pfd);
0380     if (len != 1 || buf[0] != '#' || atmark == 1) {
0381         fprintf(stderr, "Test 2.1 Inline failed, len %d data %c atmark %d\n",
0382             len, buf[0], atmark);
0383         die(1);
0384     }
0385 
0386     signal_recvd = 0;
0387     signal_producer(pipefd[1]);
0388 
0389     /* Test 3 -- Inline:
0390      * verify that 2nd oob over writes
0391      * the first one and read breaks at
0392      * oob boundary returning 127 bytes
0393      * and sigurg is received and siocatmark
0394      * is true after the read.
0395      * subsequent read returns 65 bytes
0396      * because of oob which should be '%'.
0397      */
0398     len = 0;
0399     wait_for_data(pfd, POLLIN | POLLPRI);
0400     while (len < 126)
0401         len = recv(pfd, buf, 1024, MSG_PEEK);
0402     len = read_data(pfd, buf, 1024);
0403     atmark = is_sioctatmark(pfd);
0404     if (!signal_recvd || len != 127 || !atmark) {
0405         fprintf(stderr,
0406              "Test 3 Inline failed, sigurg %d len %d data %c\n",
0407              signal_recvd, len, buf[0]);
0408         die(1);
0409     }
0410 
0411     len = read_data(pfd, buf, 1024);
0412     atmark = is_sioctatmark(pfd);
0413     if (len != 65 || buf[0] != '%' || atmark != 0) {
0414         fprintf(stderr,
0415              "Test 3.1 Inline failed, len %d oob %c atmark %d\n",
0416              len, buf[0], atmark);
0417         die(1);
0418     }
0419 
0420     signal_recvd = 0;
0421     signal_producer(pipefd[1]);
0422 
0423     /* Test 4 -- Inline:
0424      * verify that a single
0425      * byte oob message is delivered
0426      * and read returns one byte, the oob
0427      * byte and sigurg is received
0428      */
0429     wait_for_data(pfd, POLLIN | POLLPRI);
0430     len = read_data(pfd, buf, 1024);
0431     if (!signal_recvd || len != 1 || buf[0] != '@') {
0432         fprintf(stderr,
0433             "Test 4 Inline failed, signal %d len %d data %c\n",
0434         signal_recvd, len, buf[0]);
0435         die(1);
0436     }
0437     die(0);
0438 }