1 /* $OpenBSD: kqueue-fdpass.c,v 1.3 2016/09/20 23:05:27 bluhm Exp $ */
2 /*
3 * Written by Philip Guenther <guenther@openbsd.org> 2011 Public Domain
4 */
5
6 #include <sys/types.h>
7 #include <sys/event.h>
8 #include <sys/socket.h>
9 #include <sys/un.h>
10 #include <sys/wait.h>
11
12 #include <err.h>
13 #include <errno.h>
14 #include <signal.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <unistd.h>
19
20 #include "main.h"
21
22 int
do_fdpass(void)23 do_fdpass(void)
24 {
25 struct msghdr msg;
26 union {
27 struct cmsghdr hdr;
28 char buf[CMSG_SPACE(sizeof(int))];
29 } cmsgbuf;
30 struct kevent ke;
31 struct cmsghdr *cmp;
32 pid_t pid;
33 int pfd[2], fd, status;
34
35 ASS(socketpair(PF_LOCAL, SOCK_STREAM, 0, pfd) == 0,
36 warn("socketpair"));
37
38 pid = fork();
39 if (pid == -1)
40 err(1, "fork");
41 if (pid == 0) {
42 close(pfd[0]);
43
44 /* a kqueue with event to pass */
45 fd = kqueue();
46 EV_SET(&ke, SIGHUP, EVFILT_SIGNAL, EV_ADD|EV_ENABLE,
47 0, 0, NULL);
48 if (kevent(fd, &ke, 1, NULL, 0, NULL) != 0)
49 err(1, "can't register events on kqueue");
50
51 memset(&cmsgbuf.buf, 0, sizeof cmsgbuf.buf);
52 memset(&msg, 0, sizeof msg);
53 msg.msg_control = &cmsgbuf.buf;
54 msg.msg_controllen = sizeof(cmsgbuf);
55
56 cmp = CMSG_FIRSTHDR(&msg);
57 cmp->cmsg_len = CMSG_LEN(sizeof(int));
58 cmp->cmsg_level = SOL_SOCKET;
59 cmp->cmsg_type = SCM_RIGHTS;
60
61 *(int *)CMSG_DATA(cmp) = fd;
62
63 if (sendmsg(pfd[1], &msg, 0) == 0)
64 errx(1, "sendmsg succeeded when it shouldn't");
65 if (errno != EINVAL)
66 err(1, "child sendmsg");
67 printf("sendmsg failed with EINVAL as expected\n");
68 close(pfd[1]);
69 exit(0);
70 }
71
72 close(pfd[1]);
73 wait(&status);
74 close(pfd[0]);
75
76 return (0);
77 }
78