0001
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
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
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
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
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
0220
0221
0222
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
0237
0238
0239
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
0257
0258
0259
0260
0261
0262
0263
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
0293
0294
0295
0296
0297
0298
0299
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
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
0331
0332
0333
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
0358
0359
0360
0361
0362
0363
0364
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
0390
0391
0392
0393
0394
0395
0396
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
0424
0425
0426
0427
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 }