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]);