1 2 3 4 5 6 7 8 9 #include <sys/socket.h> 10 11 12 13 14 15 16 17 18 19 20 21 #include <string.h> 22 #include <sys/types.h> 23 #include <sys/wait.h> 24 #include <sys/un.h> 25 #include <stdio.h> 26 #include <fcntl.h> 27 #include <unistd.h> 28 #include <stdlib.h> 29 #include <errno.h> 30 #include "fdleak.h" 31 32 char filea[24]; 33 char fileb[24]; 34 char sock[24]; 35 36 void server (void) 37 { 38 int s, fd1, fd2; 39 struct sockaddr_un addr; 40 41 fd1 = DO( open(filea, O_RDWR | O_CREAT | O_TRUNC, 0750) ); 42 fd2 = DO( open(fileb, O_RDWR | O_CREAT | O_TRUNC, 0750) ); 43 s = DO( socket(PF_UNIX, SOCK_STREAM, 0) ); 44 45 memset(&addr, 0, sizeof(addr)); 46 addr.sun_family = AF_UNIX; 47 sprintf(addr.sun_path, "%s", sock); 48 49 unlink(sock); 50 (void) DO( bind(s, (struct sockaddr *)&addr, sizeof(addr)) ); 51 (void) DO( listen(s, 5) ); 52 53 { 54 int x; 55 unsigned baddrsize = 0; 56 struct sockaddr_un baddr; 57 struct msghdr msg = {NULL, 0, NULL, 0, 0, 0, 0}; 58 struct cmsghdr *cmsg; 59 char buf[CMSG_SPACE(sizeof(int) * 2)]; 60 struct iovec iov[1]; 61 62 memset(&baddr, 0, sizeof(baddr)); 63 x = DO( accept(s, (struct sockaddr *)&baddr, &baddrsize) ); 64 65 msg.msg_control = buf; 66 msg.msg_controllen = sizeof(buf); 67 cmsg = CMSG_FIRSTHDR(&msg); 68 cmsg->cmsg_level = SOL_SOCKET; 69 cmsg->cmsg_type = SCM_RIGHTS; 70 cmsg->cmsg_len = CMSG_LEN(sizeof(int) * 2); 71 ((int *)CMSG_DATA(cmsg))[0] = fd1; 72 ((int *)CMSG_DATA(cmsg))[1] = fd2; 73 74 iov[0].iov_base = "hello"; 75 iov[0].iov_len = 6; 76 77 msg.msg_iov = iov; 78 msg.msg_iovlen = 1; 79 80 (void) DO( sendmsg(x, &msg, 0) ); 81 } 82 } 83 84 void client (void) 85 { 86 int s, fd1 = -1, fd2 = -1, size, count = 0, ret; 87 struct sockaddr_un addr; 88 struct iovec iov[1]; 89 union { 90 struct cmsghdr cm; 91 char control[CMSG_SPACE(sizeof(int) * 2)]; 92 } control_un; 93 struct msghdr msg = { NULL, 0, iov, 1, control_un.control, 94 sizeof(control_un), 0 }; 95 struct cmsghdr *cmsg = &control_un.cm; 96 char buf[1024]; 97 98 iov[0].iov_base = buf; 99 iov[0].iov_len = sizeof(buf); 100 101 s = socket(PF_UNIX, SOCK_STREAM, 0); 102 if (s == -1) { 103 perror("socket"); 104 exit(1); 105 } 106 107 addr.sun_family = AF_UNIX; 108 sprintf(addr.sun_path, "%s", sock); 109 110 do { 111 count++; 112 ret = connect(s, (struct sockaddr *)&addr, sizeof(addr)); 113 if (ret == -1) sleep(1); 114 } while (count < 10 && ret == -1); 115 116 if (ret == -1) { 117 perror("connect"); 118 exit(1); 119 } 120 121 again: 122 if ((size = recvmsg(s, &msg, 0)) == -1) { 123 if (errno == EINTR) 124 goto again; /* SIGCHLD from server exiting could interrupt */ 125 perror("recvmsg"); 126 exit(1); 127 } 128 129 130 cmsg = CMSG_FIRSTHDR(&msg); 131 while (cmsg) { 132 if (cmsg->cmsg_level == SOL_SOCKET && 133 cmsg->cmsg_type == SCM_RIGHTS && 134 cmsg->cmsg_len == CMSG_LEN(sizeof(int) * 2)) { 135 fd1 = ((int *)CMSG_DATA(cmsg))[0]; 136 fd2 = ((int *)CMSG_DATA(cmsg))[1]; 137 } 138 139 cmsg = CMSG_NXTHDR(&msg, cmsg); 140 } 141 142 if (fd1 != -1) write(fd1, "Yeah 1\n", 8); 143 if (fd2 != -1) write(fd2, "Yeah 2\n", 8); 144 } 145 146 147 int main (int argc, char **argv) 148 { 149 int pid, status; 150 151 CLOSE_INHERITED_FDS; 152 153 pid = getpid(); 154 sprintf(filea, "/tmp/data1.%d", pid); 155 sprintf(fileb, "/tmp/data2.%d", pid); 156 sprintf(sock, "/tmp/sock.%d", pid); 157 158 if ((pid = fork()) == 0) { 159 server(); 160 return 0; 161 } 162 163 client(); 164 165 wait(&status); 166 167 (void) DO( unlink(filea) ); 168 (void) DO( unlink(fileb) ); 169 (void) DO( unlink(sock) ); 170 return 0; 171 } 172