1 // SPDX-License-Identifier: GPL-2.0-or-later
4 #include <sys/socket.h>
11 #include <netinet/tcp.h>
13 #include <sys/signal.h>
17 static int signal_recvd;
18 static pid_t producer_id;
19 static char sock_name[32];
21 static void sig_hand(int sn, siginfo_t *si, void *p)
26 static int set_sig_handler(int signal)
30 sa.sa_sigaction = sig_hand;
31 sigemptyset(&sa.sa_mask);
32 sa.sa_flags = SA_SIGINFO | SA_RESTART;
34 return sigaction(signal, &sa, NULL);
37 static void set_filemode(int fd, int set)
39 int flags = fcntl(fd, F_GETFL, 0);
45 fcntl(fd, F_SETFL, flags);
48 static void signal_producer(int fd)
53 write(fd, &cmd, sizeof(cmd));
56 static void wait_for_signal(int fd)
63 static void die(int status)
67 kill(producer_id, SIGTERM);
71 int is_sioctatmark(int fd)
75 if (ioctl(fd, SIOCATMARK, &ans, sizeof(ans)) < 0) {
77 perror("SIOCATMARK Failed");
83 void read_oob(int fd, char *c)
87 if (recv(fd, c, sizeof(*c), MSG_OOB) < 0) {
89 perror("Reading MSG_OOB Failed");
94 int read_data(int pfd, char *buf, int size)
98 memset(buf, size, '0');
99 len = read(pfd, buf, size);
102 perror("read failed");
107 static void wait_for_data(int pfd, int event)
109 struct pollfd pfds[1];
112 pfds[0].events = event;
116 void producer(struct sockaddr_un *consumer_addr)
122 memset(buf, 'x', sizeof(buf));
123 cfd = socket(AF_UNIX, SOCK_STREAM, 0);
125 wait_for_signal(pipefd[0]);
126 if (connect(cfd, (struct sockaddr *)consumer_addr,
127 sizeof(struct sockaddr)) != 0) {
128 perror("Connect failed");
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));
138 send(cfd, buf, sizeof(buf), MSG_OOB);
140 wait_for_signal(pipefd[0]);
142 /* Test 2: Test for OOB being overwitten */
143 memset(buf, 'x', sizeof(buf));
145 send(cfd, buf, sizeof(buf), MSG_OOB);
147 memset(buf, 'x', sizeof(buf));
149 send(cfd, buf, sizeof(buf), MSG_OOB);
151 wait_for_signal(pipefd[0]);
153 /* Test 3: Test for SIOCATMARK */
154 memset(buf, 'x', sizeof(buf));
156 send(cfd, buf, sizeof(buf), MSG_OOB);
158 memset(buf, 'x', sizeof(buf));
160 send(cfd, buf, sizeof(buf), MSG_OOB);
162 memset(buf, 'x', sizeof(buf));
163 send(cfd, buf, sizeof(buf), 0);
165 wait_for_signal(pipefd[0]);
167 /* Test 4: Test for 1byte OOB msg */
168 memset(buf, 'x', sizeof(buf));
170 send(cfd, buf, 1, MSG_OOB);
175 main(int argc, char **argv)
178 struct sockaddr_un consumer_addr, paddr;
179 socklen_t len = sizeof(consumer_addr);
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());
192 strcpy(consumer_addr.sun_path, sock_name);
194 if ((bind(lfd, (struct sockaddr *)&consumer_addr,
195 sizeof(consumer_addr))) != 0) {
196 perror("socket bind failed");
204 producer_id = fork();
205 if (producer_id == 0) {
206 producer(&consumer_addr);
210 set_sig_handler(SIGURG);
211 signal_producer(pipefd[1]);
213 pfd = accept(lfd, (struct sockaddr *) &paddr, &len);
214 fcntl(pfd, F_SETOWN, getpid());
217 signal_producer(pipefd[1]);
220 * veriyf that SIGURG is
221 * delivered, 63 bytes are
222 * read, oob is '@', and POLLPRI works.
224 wait_for_data(pfd, POLLPRI);
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);
234 signal_producer(pipefd[1]);
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.
241 wait_for_data(pfd, POLLIN | POLLPRI);
244 len = recv(pfd, buf, 1024, MSG_PEEK);
245 len = read_data(pfd, buf, 1024);
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);
254 signal_producer(pipefd[1]);
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
262 * oob is '%' and second read returns
266 wait_for_data(pfd, POLLIN | POLLPRI);
268 len = recv(pfd, buf, 1024, MSG_PEEK);
269 len = read_data(pfd, buf, 1024);
270 atmark = is_sioctatmark(pfd);
273 if (!signal_recvd || len != 127 || oob != '%' || atmark != 1) {
275 "Test 3 failed, sigurg %d len %d OOB %c atmark %d\n",
276 signal_recvd, len, oob, atmark);
282 len = read_data(pfd, buf, 1024);
284 fprintf(stderr, "Test 3.1 failed, sigurg %d len %d OOB %c\n",
285 signal_recvd, len, oob);
290 signal_producer(pipefd[1]);
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
302 set_filemode(pfd, 0);
304 wait_for_data(pfd, POLLIN | POLLPRI);
305 len = read_data(pfd, buf, 1024);
306 if ((len == -1) && (errno == 11))
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);
317 set_filemode(pfd, 1);
322 if (setsockopt(pfd, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on))) {
323 perror("SO_OOBINLINE");
328 signal_producer(pipefd[1]);
331 * Check that SIGURG is
332 * delivered and 63 bytes are
333 * read and oob is '@'
336 wait_for_data(pfd, POLLIN | POLLPRI);
337 len = read_data(pfd, buf, 1024);
339 if (!signal_recvd || len != 63) {
340 fprintf(stderr, "Test 1 Inline failed, sigurg %d len %d\n",
345 len = read_data(pfd, buf, 1024);
349 "Test 1.1 Inline failed, sigurg %d len %d oob %c\n",
350 signal_recvd, len, oob);
355 signal_producer(pipefd[1]);
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.
367 wait_for_data(pfd, POLLIN | POLLPRI);
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",
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);
387 signal_producer(pipefd[1]);
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 '%'.
399 wait_for_data(pfd, POLLIN | POLLPRI);
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) {
406 "Test 3 Inline failed, sigurg %d len %d data %c\n",
407 signal_recvd, len, buf[0]);
411 len = read_data(pfd, buf, 1024);
412 atmark = is_sioctatmark(pfd);
413 if (len != 65 || buf[0] != '%' || atmark != 0) {
415 "Test 3.1 Inline failed, len %d oob %c atmark %d\n",
416 len, buf[0], atmark);
421 signal_producer(pipefd[1]);
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
429 wait_for_data(pfd, POLLIN | POLLPRI);
430 len = read_data(pfd, buf, 1024);
431 if (!signal_recvd || len != 1 || buf[0] != '@') {
433 "Test 4 Inline failed, signal %d len %d data %c\n",
434 signal_recvd, len, buf[0]);