fdleak_cmsg.c revision b32f58018498ea2225959b0ba11c18f0c433deef
14e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
24e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
34e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
44e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
54e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
64e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
74e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
84e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
94e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include <sys/socket.h>
104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include <string.h>
224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include <sys/types.h>
234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include <sys/wait.h>
244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include <sys/un.h>
254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include <stdio.h>
264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include <fcntl.h>
274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include <unistd.h>
284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include <stdlib.h>
294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include <errno.h>
30#include "fdleak.h"
31
32char filea[24];
33char fileb[24];
34char sock[24];
35
36void 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   DO( bind(s, (struct sockaddr *)&addr, sizeof(addr)) );
51   DO( listen(s, 5) );
52
53   {
54      int x;
55      int 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      DO( sendmsg(x, &msg, 0) );
81   }
82}
83
84void 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
147int 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   DO( unlink(filea) );
168   DO( unlink(fileb) );
169   DO( unlink(sock) );
170   return 0;
171}
172