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 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