fdleak_cmsg.c revision 436e89c602e787e7a27dd6624b09beed41a0da8a
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
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   (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
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   (void) DO( unlink(filea) );
168   (void) DO( unlink(fileb) );
169   (void) DO( unlink(sock) );
170   return 0;
171}
172