1*bd35765dSbluhm /* $OpenBSD: kqueue-fdpass.c,v 1.3 2016/09/20 23:05:27 bluhm Exp $ */
26897c9b5Sguenther /*
36897c9b5Sguenther * Written by Philip Guenther <guenther@openbsd.org> 2011 Public Domain
46897c9b5Sguenther */
56897c9b5Sguenther
66897c9b5Sguenther #include <sys/types.h>
76897c9b5Sguenther #include <sys/event.h>
86897c9b5Sguenther #include <sys/socket.h>
96897c9b5Sguenther #include <sys/un.h>
106897c9b5Sguenther #include <sys/wait.h>
116897c9b5Sguenther
126897c9b5Sguenther #include <err.h>
136897c9b5Sguenther #include <errno.h>
146897c9b5Sguenther #include <signal.h>
15*bd35765dSbluhm #include <stdio.h>
16*bd35765dSbluhm #include <stdlib.h>
17*bd35765dSbluhm #include <string.h>
18*bd35765dSbluhm #include <unistd.h>
196897c9b5Sguenther
20*bd35765dSbluhm #include "main.h"
216897c9b5Sguenther
226897c9b5Sguenther int
do_fdpass(void)236897c9b5Sguenther do_fdpass(void)
246897c9b5Sguenther {
256897c9b5Sguenther struct msghdr msg;
266897c9b5Sguenther union {
276897c9b5Sguenther struct cmsghdr hdr;
286897c9b5Sguenther char buf[CMSG_SPACE(sizeof(int))];
296897c9b5Sguenther } cmsgbuf;
306897c9b5Sguenther struct kevent ke;
316897c9b5Sguenther struct cmsghdr *cmp;
326897c9b5Sguenther pid_t pid;
336897c9b5Sguenther int pfd[2], fd, status;
346897c9b5Sguenther
356897c9b5Sguenther ASS(socketpair(PF_LOCAL, SOCK_STREAM, 0, pfd) == 0,
366897c9b5Sguenther warn("socketpair"));
376897c9b5Sguenther
386897c9b5Sguenther pid = fork();
396897c9b5Sguenther if (pid == -1)
406897c9b5Sguenther err(1, "fork");
416897c9b5Sguenther if (pid == 0) {
426897c9b5Sguenther close(pfd[0]);
436897c9b5Sguenther
446897c9b5Sguenther /* a kqueue with event to pass */
456897c9b5Sguenther fd = kqueue();
466897c9b5Sguenther EV_SET(&ke, SIGHUP, EVFILT_SIGNAL, EV_ADD|EV_ENABLE,
476897c9b5Sguenther 0, 0, NULL);
486897c9b5Sguenther if (kevent(fd, &ke, 1, NULL, 0, NULL) != 0)
496897c9b5Sguenther err(1, "can't register events on kqueue");
506897c9b5Sguenther
51a3dcdeb8Suebayasi memset(&cmsgbuf.buf, 0, sizeof cmsgbuf.buf);
526897c9b5Sguenther memset(&msg, 0, sizeof msg);
536897c9b5Sguenther msg.msg_control = &cmsgbuf.buf;
546897c9b5Sguenther msg.msg_controllen = sizeof(cmsgbuf);
556897c9b5Sguenther
566897c9b5Sguenther cmp = CMSG_FIRSTHDR(&msg);
576897c9b5Sguenther cmp->cmsg_len = CMSG_LEN(sizeof(int));
586897c9b5Sguenther cmp->cmsg_level = SOL_SOCKET;
596897c9b5Sguenther cmp->cmsg_type = SCM_RIGHTS;
606897c9b5Sguenther
616897c9b5Sguenther *(int *)CMSG_DATA(cmp) = fd;
626897c9b5Sguenther
636897c9b5Sguenther if (sendmsg(pfd[1], &msg, 0) == 0)
646897c9b5Sguenther errx(1, "sendmsg succeeded when it shouldn't");
656897c9b5Sguenther if (errno != EINVAL)
666897c9b5Sguenther err(1, "child sendmsg");
676897c9b5Sguenther printf("sendmsg failed with EINVAL as expected\n");
68a3dcdeb8Suebayasi close(pfd[1]);
696897c9b5Sguenther exit(0);
706897c9b5Sguenther }
716897c9b5Sguenther
726897c9b5Sguenther close(pfd[1]);
736897c9b5Sguenther wait(&status);
74a3dcdeb8Suebayasi close(pfd[0]);
756897c9b5Sguenther
766897c9b5Sguenther return (0);
776897c9b5Sguenther }
78