xref: /openbsd-src/regress/sys/kern/kqueue/kqueue-fdpass.c (revision bd35765dfde630203782d36f741b7bde1f9f8a3e)
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