]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tools/regression/sockets/unix_cmsg/t_sockcred.c
MFC r309554 and r309631 which breaks down overly long monolithic
[FreeBSD/FreeBSD.git] / tools / regression / sockets / unix_cmsg / t_sockcred.c
1 /*-
2  * Copyright (c) 2005 Andrey Simonenko
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 #include <sys/types.h>
31 #include <sys/socket.h>
32 #include <sys/un.h>
33 #include <inttypes.h>
34 #include <stdarg.h>
35 #include <stdbool.h>
36 #include <stdlib.h>
37
38 #include "uc_common.h"
39 #include "t_generic.h"
40 #include "t_sockcred.h"
41
42 static int
43 t_sockcred_client(int type, int fd)
44 {
45         struct msghdr msghdr;
46         struct iovec iov[1];
47         int rv;
48
49         if (uc_sync_recv() < 0)
50                 return (-2);
51
52         rv = -2;
53
54         uc_msghdr_init_client(&msghdr, iov, NULL, 0, 0, 0);
55
56         if (uc_socket_connect(fd) < 0)
57                 goto done;
58
59         if (type == 2)
60                 if (uc_sync_recv() < 0)
61                         goto done;
62
63         if (uc_message_sendn(fd, &msghdr) < 0)
64                 goto done;
65
66         rv = 0;
67 done:
68         return (rv);
69 }
70
71 static int
72 t_sockcred_server(int type, int fd1)
73 {
74         struct msghdr msghdr;
75         struct iovec iov[1];
76         struct cmsghdr *cmsghdr;
77         void *cmsg_data;
78         size_t cmsg_size;
79         u_int i;
80         int fd2, rv, val;
81
82         fd2 = -1;
83         rv = -2;
84
85         cmsg_size = CMSG_SPACE(SOCKCREDSIZE(uc_cfg.proc_cred.gid_num));
86         cmsg_data = malloc(cmsg_size);
87         if (cmsg_data == NULL) {
88                 uc_logmsg("malloc");
89                 goto done;
90         }
91
92         if (type == 1) {
93                 uc_dbgmsg("setting LOCAL_CREDS");
94                 val = 1;
95                 if (setsockopt(fd1, 0, LOCAL_CREDS, &val, sizeof(val)) < 0) {
96                         uc_logmsg("setsockopt(LOCAL_CREDS)");
97                         goto done;
98                 }
99         }
100
101         if (uc_sync_send() < 0)
102                 goto done;
103
104         if (uc_cfg.sock_type == SOCK_STREAM) {
105                 fd2 = uc_socket_accept(fd1);
106                 if (fd2 < 0)
107                         goto done;
108         } else
109                 fd2 = fd1;
110
111         if (type == 2) {
112                 uc_dbgmsg("setting LOCAL_CREDS");
113                 val = 1;
114                 if (setsockopt(fd2, 0, LOCAL_CREDS, &val, sizeof(val)) < 0) {
115                         uc_logmsg("setsockopt(LOCAL_CREDS)");
116                         goto done;
117                 }
118                 if (uc_sync_send() < 0)
119                         goto done;
120         }
121
122         rv = -1;
123         for (i = 1; i <= uc_cfg.ipc_msg.msg_num; ++i) {
124                 uc_dbgmsg("message #%u", i);
125
126                 uc_msghdr_init_server(&msghdr, iov, cmsg_data, cmsg_size);
127                 if (uc_message_recv(fd2, &msghdr) < 0) {
128                         rv = -2;
129                         break;
130                 }
131
132                 if (i > 1 && uc_cfg.sock_type == SOCK_STREAM) {
133                         if (uc_check_msghdr(&msghdr, 0) < 0)
134                                 break;
135                 } else {
136                         if (uc_check_msghdr(&msghdr, sizeof(*cmsghdr)) < 0)
137                                 break;
138
139                         cmsghdr = CMSG_FIRSTHDR(&msghdr);
140                         if (uc_check_scm_creds_sockcred(cmsghdr) < 0)
141                                 break;
142                 }
143         }
144         if (i > uc_cfg.ipc_msg.msg_num)
145                 rv = 0;
146 done:
147         free(cmsg_data);
148         if (uc_cfg.sock_type == SOCK_STREAM && fd2 >= 0)
149                 if (uc_socket_close(fd2) < 0)
150                         rv = -2;
151         return (rv);
152 }
153
154 int
155 t_sockcred_1(void)
156 {
157         u_int i;
158         int fd, rv, rv_client;
159
160         switch (uc_client_fork()) {
161         case 0:
162                 for (i = 1; i <= 2; ++i) {
163                         uc_dbgmsg("client #%u", i);
164                         fd = uc_socket_create();
165                         if (fd < 0)
166                                 rv = -2;
167                         else {
168                                 rv = t_sockcred_client(1, fd);
169                                 if (uc_socket_close(fd) < 0)
170                                         rv = -2;
171                         }
172                         if (rv != 0)
173                                 break;
174                 }
175                 uc_client_exit(rv);
176                 break;
177         case 1:
178                 fd = uc_socket_create();
179                 if (fd < 0)
180                         rv = -2;
181                 else {
182                         rv = t_sockcred_server(1, fd);
183                         if (rv == 0)
184                                 rv = t_sockcred_server(3, fd);
185                         rv_client = uc_client_wait();
186                         if (rv == 0 || (rv == -2 && rv_client != 0))
187                                 rv = rv_client;
188                         if (uc_socket_close(fd) < 0)
189                                 rv = -2;
190                 }
191                 break;
192         default:
193                 rv = -2;
194         }
195
196         return (rv);
197 }
198
199 static int
200 t_sockcred_2_client(int fd)
201 {
202         return (t_sockcred_client(2, fd));
203 }
204
205 static int
206 t_sockcred_2_server(int fd)
207 {
208         return (t_sockcred_server(2, fd));
209 }
210
211 int
212 t_sockcred_2(void)
213 {
214         return (t_generic(t_sockcred_2_client, t_sockcred_2_server));
215 }