1 /* $OpenBSD: kqueue-fdpass.c,v 1.2 2015/08/13 10:14:41 uebayasi 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 <stdlib.h> 13 #include <stdio.h> 14 #include <string.h> 15 #include <err.h> 16 #include <errno.h> 17 #include <unistd.h> 18 #include <signal.h> 19 20 #define ASS(cond, mess) do { if (!(cond)) { mess; return 1; } } while (0) 21 22 #define ASSX(cond) ASS(cond, warnx("assertion " #cond " failed on line %d", __LINE__)) 23 24 25 int do_fdpass(void); 26 27 int 28 do_fdpass(void) 29 { 30 struct msghdr msg; 31 union { 32 struct cmsghdr hdr; 33 char buf[CMSG_SPACE(sizeof(int))]; 34 } cmsgbuf; 35 struct kevent ke; 36 struct cmsghdr *cmp; 37 pid_t pid; 38 int pfd[2], fd, status; 39 40 ASS(socketpair(PF_LOCAL, SOCK_STREAM, 0, pfd) == 0, 41 warn("socketpair")); 42 43 pid = fork(); 44 if (pid == -1) 45 err(1, "fork"); 46 if (pid == 0) { 47 close(pfd[0]); 48 49 /* a kqueue with event to pass */ 50 fd = kqueue(); 51 EV_SET(&ke, SIGHUP, EVFILT_SIGNAL, EV_ADD|EV_ENABLE, 52 0, 0, NULL); 53 if (kevent(fd, &ke, 1, NULL, 0, NULL) != 0) 54 err(1, "can't register events on kqueue"); 55 56 memset(&cmsgbuf.buf, 0, sizeof cmsgbuf.buf); 57 memset(&msg, 0, sizeof msg); 58 msg.msg_control = &cmsgbuf.buf; 59 msg.msg_controllen = sizeof(cmsgbuf); 60 61 cmp = CMSG_FIRSTHDR(&msg); 62 cmp->cmsg_len = CMSG_LEN(sizeof(int)); 63 cmp->cmsg_level = SOL_SOCKET; 64 cmp->cmsg_type = SCM_RIGHTS; 65 66 *(int *)CMSG_DATA(cmp) = fd; 67 68 if (sendmsg(pfd[1], &msg, 0) == 0) 69 errx(1, "sendmsg succeeded when it shouldn't"); 70 if (errno != EINVAL) 71 err(1, "child sendmsg"); 72 printf("sendmsg failed with EINVAL as expected\n"); 73 close(pfd[1]); 74 exit(0); 75 } 76 77 close(pfd[1]); 78 wait(&status); 79 close(pfd[0]); 80 81 return (0); 82 } 83 84