1*1fab62b1SMaxim Sobolev /*-
2*1fab62b1SMaxim Sobolev * Copyright (c) 2005 Andrey Simonenko
3*1fab62b1SMaxim Sobolev * All rights reserved.
4*1fab62b1SMaxim Sobolev *
5*1fab62b1SMaxim Sobolev * Redistribution and use in source and binary forms, with or without
6*1fab62b1SMaxim Sobolev * modification, are permitted provided that the following conditions
7*1fab62b1SMaxim Sobolev * are met:
8*1fab62b1SMaxim Sobolev * 1. Redistributions of source code must retain the above copyright
9*1fab62b1SMaxim Sobolev * notice, this list of conditions and the following disclaimer.
10*1fab62b1SMaxim Sobolev * 2. Redistributions in binary form must reproduce the above copyright
11*1fab62b1SMaxim Sobolev * notice, this list of conditions and the following disclaimer in the
12*1fab62b1SMaxim Sobolev * documentation and/or other materials provided with the distribution.
13*1fab62b1SMaxim Sobolev *
14*1fab62b1SMaxim Sobolev * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15*1fab62b1SMaxim Sobolev * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16*1fab62b1SMaxim Sobolev * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*1fab62b1SMaxim Sobolev * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18*1fab62b1SMaxim Sobolev * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*1fab62b1SMaxim Sobolev * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*1fab62b1SMaxim Sobolev * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*1fab62b1SMaxim Sobolev * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22*1fab62b1SMaxim Sobolev * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23*1fab62b1SMaxim Sobolev * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24*1fab62b1SMaxim Sobolev * SUCH DAMAGE.
25*1fab62b1SMaxim Sobolev */
26*1fab62b1SMaxim Sobolev
27*1fab62b1SMaxim Sobolev #include <sys/cdefs.h>
28*1fab62b1SMaxim Sobolev #include <sys/socket.h>
29*1fab62b1SMaxim Sobolev #include <sys/un.h>
30*1fab62b1SMaxim Sobolev #include <err.h>
31*1fab62b1SMaxim Sobolev #include <fcntl.h>
32*1fab62b1SMaxim Sobolev #include <errno.h>
33*1fab62b1SMaxim Sobolev #include <inttypes.h>
34*1fab62b1SMaxim Sobolev #include <stdarg.h>
35*1fab62b1SMaxim Sobolev #include <stdbool.h>
36*1fab62b1SMaxim Sobolev #include <stdlib.h>
37*1fab62b1SMaxim Sobolev #include <stdio.h>
38*1fab62b1SMaxim Sobolev #include <string.h>
39*1fab62b1SMaxim Sobolev #include <unistd.h>
40*1fab62b1SMaxim Sobolev #include <sys/wait.h>
41*1fab62b1SMaxim Sobolev
42*1fab62b1SMaxim Sobolev #include "uc_common.h"
43*1fab62b1SMaxim Sobolev
44*1fab62b1SMaxim Sobolev #ifndef LISTENQ
45*1fab62b1SMaxim Sobolev # define LISTENQ 1
46*1fab62b1SMaxim Sobolev #endif
47*1fab62b1SMaxim Sobolev
48*1fab62b1SMaxim Sobolev #ifndef TIMEOUT
49*1fab62b1SMaxim Sobolev # define TIMEOUT 2
50*1fab62b1SMaxim Sobolev #endif
51*1fab62b1SMaxim Sobolev
52*1fab62b1SMaxim Sobolev #define SYNC_SERVER 0
53*1fab62b1SMaxim Sobolev #define SYNC_CLIENT 1
54*1fab62b1SMaxim Sobolev #define SYNC_RECV 0
55*1fab62b1SMaxim Sobolev #define SYNC_SEND 1
56*1fab62b1SMaxim Sobolev
57*1fab62b1SMaxim Sobolev #define LOGMSG_SIZE 128
58*1fab62b1SMaxim Sobolev
59*1fab62b1SMaxim Sobolev void
uc_output(const char * format,...)60*1fab62b1SMaxim Sobolev uc_output(const char *format, ...)
61*1fab62b1SMaxim Sobolev {
62*1fab62b1SMaxim Sobolev char buf[LOGMSG_SIZE];
63*1fab62b1SMaxim Sobolev va_list ap;
64*1fab62b1SMaxim Sobolev
65*1fab62b1SMaxim Sobolev va_start(ap, format);
66*1fab62b1SMaxim Sobolev if (vsnprintf(buf, sizeof(buf), format, ap) < 0)
67*1fab62b1SMaxim Sobolev err(EXIT_FAILURE, "output: vsnprintf failed");
68*1fab62b1SMaxim Sobolev write(STDOUT_FILENO, buf, strlen(buf));
69*1fab62b1SMaxim Sobolev va_end(ap);
70*1fab62b1SMaxim Sobolev }
71*1fab62b1SMaxim Sobolev
72*1fab62b1SMaxim Sobolev void
uc_logmsg(const char * format,...)73*1fab62b1SMaxim Sobolev uc_logmsg(const char *format, ...)
74*1fab62b1SMaxim Sobolev {
75*1fab62b1SMaxim Sobolev char buf[LOGMSG_SIZE];
76*1fab62b1SMaxim Sobolev va_list ap;
77*1fab62b1SMaxim Sobolev int errno_save;
78*1fab62b1SMaxim Sobolev
79*1fab62b1SMaxim Sobolev errno_save = errno;
80*1fab62b1SMaxim Sobolev va_start(ap, format);
81*1fab62b1SMaxim Sobolev if (vsnprintf(buf, sizeof(buf), format, ap) < 0)
82*1fab62b1SMaxim Sobolev err(EXIT_FAILURE, "logmsg: vsnprintf failed");
83*1fab62b1SMaxim Sobolev if (errno_save == 0)
84*1fab62b1SMaxim Sobolev uc_output("%s: %s\n", uc_cfg.proc_name, buf);
85*1fab62b1SMaxim Sobolev else
86*1fab62b1SMaxim Sobolev uc_output("%s: %s: %s\n", uc_cfg.proc_name, buf,
87*1fab62b1SMaxim Sobolev strerror(errno_save));
88*1fab62b1SMaxim Sobolev va_end(ap);
89*1fab62b1SMaxim Sobolev errno = errno_save;
90*1fab62b1SMaxim Sobolev }
91*1fab62b1SMaxim Sobolev
92*1fab62b1SMaxim Sobolev void
uc_vlogmsgx(const char * format,va_list ap)93*1fab62b1SMaxim Sobolev uc_vlogmsgx(const char *format, va_list ap)
94*1fab62b1SMaxim Sobolev {
95*1fab62b1SMaxim Sobolev char buf[LOGMSG_SIZE];
96*1fab62b1SMaxim Sobolev
97*1fab62b1SMaxim Sobolev if (vsnprintf(buf, sizeof(buf), format, ap) < 0)
98*1fab62b1SMaxim Sobolev err(EXIT_FAILURE, "uc_logmsgx: vsnprintf failed");
99*1fab62b1SMaxim Sobolev uc_output("%s: %s\n", uc_cfg.proc_name, buf);
100*1fab62b1SMaxim Sobolev }
101*1fab62b1SMaxim Sobolev
102*1fab62b1SMaxim Sobolev void
uc_logmsgx(const char * format,...)103*1fab62b1SMaxim Sobolev uc_logmsgx(const char *format, ...)
104*1fab62b1SMaxim Sobolev {
105*1fab62b1SMaxim Sobolev va_list ap;
106*1fab62b1SMaxim Sobolev
107*1fab62b1SMaxim Sobolev va_start(ap, format);
108*1fab62b1SMaxim Sobolev uc_vlogmsgx(format, ap);
109*1fab62b1SMaxim Sobolev va_end(ap);
110*1fab62b1SMaxim Sobolev }
111*1fab62b1SMaxim Sobolev
112*1fab62b1SMaxim Sobolev void
uc_dbgmsg(const char * format,...)113*1fab62b1SMaxim Sobolev uc_dbgmsg(const char *format, ...)
114*1fab62b1SMaxim Sobolev {
115*1fab62b1SMaxim Sobolev va_list ap;
116*1fab62b1SMaxim Sobolev
117*1fab62b1SMaxim Sobolev if (uc_cfg.debug) {
118*1fab62b1SMaxim Sobolev va_start(ap, format);
119*1fab62b1SMaxim Sobolev uc_vlogmsgx(format, ap);
120*1fab62b1SMaxim Sobolev va_end(ap);
121*1fab62b1SMaxim Sobolev }
122*1fab62b1SMaxim Sobolev }
123*1fab62b1SMaxim Sobolev
124*1fab62b1SMaxim Sobolev int
uc_socket_create(void)125*1fab62b1SMaxim Sobolev uc_socket_create(void)
126*1fab62b1SMaxim Sobolev {
127*1fab62b1SMaxim Sobolev struct timeval tv;
128*1fab62b1SMaxim Sobolev int fd;
129*1fab62b1SMaxim Sobolev
130*1fab62b1SMaxim Sobolev fd = socket(PF_LOCAL, uc_cfg.sock_type, 0);
131*1fab62b1SMaxim Sobolev if (fd < 0) {
132*1fab62b1SMaxim Sobolev uc_logmsg("socket_create: socket(PF_LOCAL, %s, 0)", uc_cfg.sock_type_str);
133*1fab62b1SMaxim Sobolev return (-1);
134*1fab62b1SMaxim Sobolev }
135*1fab62b1SMaxim Sobolev if (uc_cfg.server_flag)
136*1fab62b1SMaxim Sobolev uc_cfg.serv_sock_fd = fd;
137*1fab62b1SMaxim Sobolev
138*1fab62b1SMaxim Sobolev tv.tv_sec = TIMEOUT;
139*1fab62b1SMaxim Sobolev tv.tv_usec = 0;
140*1fab62b1SMaxim Sobolev if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0 ||
141*1fab62b1SMaxim Sobolev setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0) {
142*1fab62b1SMaxim Sobolev uc_logmsg("socket_create: setsockopt(SO_RCVTIMEO/SO_SNDTIMEO)");
143*1fab62b1SMaxim Sobolev goto failed;
144*1fab62b1SMaxim Sobolev }
145*1fab62b1SMaxim Sobolev
146*1fab62b1SMaxim Sobolev if (uc_cfg.server_flag) {
147*1fab62b1SMaxim Sobolev if (bind(fd, (struct sockaddr *)&uc_cfg.serv_addr_sun,
148*1fab62b1SMaxim Sobolev uc_cfg.serv_addr_sun.sun_len) < 0) {
149*1fab62b1SMaxim Sobolev uc_logmsg("socket_create: bind(%s)",
150*1fab62b1SMaxim Sobolev uc_cfg.serv_addr_sun.sun_path);
151*1fab62b1SMaxim Sobolev goto failed;
152*1fab62b1SMaxim Sobolev }
153*1fab62b1SMaxim Sobolev if (uc_cfg.sock_type == SOCK_STREAM) {
154*1fab62b1SMaxim Sobolev int val;
155*1fab62b1SMaxim Sobolev
156*1fab62b1SMaxim Sobolev if (listen(fd, LISTENQ) < 0) {
157*1fab62b1SMaxim Sobolev uc_logmsg("socket_create: listen");
158*1fab62b1SMaxim Sobolev goto failed;
159*1fab62b1SMaxim Sobolev }
160*1fab62b1SMaxim Sobolev val = fcntl(fd, F_GETFL, 0);
161*1fab62b1SMaxim Sobolev if (val < 0) {
162*1fab62b1SMaxim Sobolev uc_logmsg("socket_create: fcntl(F_GETFL)");
163*1fab62b1SMaxim Sobolev goto failed;
164*1fab62b1SMaxim Sobolev }
165*1fab62b1SMaxim Sobolev if (fcntl(fd, F_SETFL, val | O_NONBLOCK) < 0) {
166*1fab62b1SMaxim Sobolev uc_logmsg("socket_create: fcntl(F_SETFL)");
167*1fab62b1SMaxim Sobolev goto failed;
168*1fab62b1SMaxim Sobolev }
169*1fab62b1SMaxim Sobolev }
170*1fab62b1SMaxim Sobolev }
171*1fab62b1SMaxim Sobolev
172*1fab62b1SMaxim Sobolev return (fd);
173*1fab62b1SMaxim Sobolev
174*1fab62b1SMaxim Sobolev failed:
175*1fab62b1SMaxim Sobolev if (close(fd) < 0)
176*1fab62b1SMaxim Sobolev uc_logmsg("socket_create: close");
177*1fab62b1SMaxim Sobolev if (uc_cfg.server_flag)
178*1fab62b1SMaxim Sobolev if (unlink(uc_cfg.serv_addr_sun.sun_path) < 0)
179*1fab62b1SMaxim Sobolev uc_logmsg("socket_close: unlink(%s)",
180*1fab62b1SMaxim Sobolev uc_cfg.serv_addr_sun.sun_path);
181*1fab62b1SMaxim Sobolev return (-1);
182*1fab62b1SMaxim Sobolev }
183*1fab62b1SMaxim Sobolev
184*1fab62b1SMaxim Sobolev int
uc_socket_close(int fd)185*1fab62b1SMaxim Sobolev uc_socket_close(int fd)
186*1fab62b1SMaxim Sobolev {
187*1fab62b1SMaxim Sobolev int rv;
188*1fab62b1SMaxim Sobolev
189*1fab62b1SMaxim Sobolev rv = 0;
190*1fab62b1SMaxim Sobolev if (close(fd) < 0) {
191*1fab62b1SMaxim Sobolev uc_logmsg("socket_close: close");
192*1fab62b1SMaxim Sobolev rv = -1;
193*1fab62b1SMaxim Sobolev }
194*1fab62b1SMaxim Sobolev if (uc_cfg.server_flag && fd == uc_cfg.serv_sock_fd)
195*1fab62b1SMaxim Sobolev if (unlink(uc_cfg.serv_addr_sun.sun_path) < 0) {
196*1fab62b1SMaxim Sobolev uc_logmsg("socket_close: unlink(%s)",
197*1fab62b1SMaxim Sobolev uc_cfg.serv_addr_sun.sun_path);
198*1fab62b1SMaxim Sobolev rv = -1;
199*1fab62b1SMaxim Sobolev }
200*1fab62b1SMaxim Sobolev return (rv);
201*1fab62b1SMaxim Sobolev }
202*1fab62b1SMaxim Sobolev
203*1fab62b1SMaxim Sobolev int
uc_socket_connect(int fd)204*1fab62b1SMaxim Sobolev uc_socket_connect(int fd)
205*1fab62b1SMaxim Sobolev {
206*1fab62b1SMaxim Sobolev uc_dbgmsg("connect");
207*1fab62b1SMaxim Sobolev
208*1fab62b1SMaxim Sobolev if (connect(fd, (struct sockaddr *)&uc_cfg.serv_addr_sun,
209*1fab62b1SMaxim Sobolev uc_cfg.serv_addr_sun.sun_len) < 0) {
210*1fab62b1SMaxim Sobolev uc_logmsg("socket_connect: connect(%s)", uc_cfg.serv_addr_sun.sun_path);
211*1fab62b1SMaxim Sobolev return (-1);
212*1fab62b1SMaxim Sobolev }
213*1fab62b1SMaxim Sobolev return (0);
214*1fab62b1SMaxim Sobolev }
215*1fab62b1SMaxim Sobolev
216*1fab62b1SMaxim Sobolev int
uc_sync_recv(void)217*1fab62b1SMaxim Sobolev uc_sync_recv(void)
218*1fab62b1SMaxim Sobolev {
219*1fab62b1SMaxim Sobolev ssize_t ssize;
220*1fab62b1SMaxim Sobolev int fd;
221*1fab62b1SMaxim Sobolev char buf;
222*1fab62b1SMaxim Sobolev
223*1fab62b1SMaxim Sobolev uc_dbgmsg("sync: wait");
224*1fab62b1SMaxim Sobolev
225*1fab62b1SMaxim Sobolev fd = uc_cfg.sync_fd[uc_cfg.server_flag ? SYNC_SERVER : SYNC_CLIENT][SYNC_RECV];
226*1fab62b1SMaxim Sobolev
227*1fab62b1SMaxim Sobolev ssize = read(fd, &buf, 1);
228*1fab62b1SMaxim Sobolev if (ssize < 0) {
229*1fab62b1SMaxim Sobolev uc_logmsg("sync_recv: read");
230*1fab62b1SMaxim Sobolev return (-1);
231*1fab62b1SMaxim Sobolev }
232*1fab62b1SMaxim Sobolev if (ssize < 1) {
233*1fab62b1SMaxim Sobolev uc_logmsgx("sync_recv: read %zd of 1 byte", ssize);
234*1fab62b1SMaxim Sobolev return (-1);
235*1fab62b1SMaxim Sobolev }
236*1fab62b1SMaxim Sobolev
237*1fab62b1SMaxim Sobolev uc_dbgmsg("sync: received");
238*1fab62b1SMaxim Sobolev
239*1fab62b1SMaxim Sobolev return (0);
240*1fab62b1SMaxim Sobolev }
241*1fab62b1SMaxim Sobolev
242*1fab62b1SMaxim Sobolev int
uc_sync_send(void)243*1fab62b1SMaxim Sobolev uc_sync_send(void)
244*1fab62b1SMaxim Sobolev {
245*1fab62b1SMaxim Sobolev ssize_t ssize;
246*1fab62b1SMaxim Sobolev int fd;
247*1fab62b1SMaxim Sobolev
248*1fab62b1SMaxim Sobolev uc_dbgmsg("sync: send");
249*1fab62b1SMaxim Sobolev
250*1fab62b1SMaxim Sobolev fd = uc_cfg.sync_fd[uc_cfg.server_flag ? SYNC_CLIENT : SYNC_SERVER][SYNC_SEND];
251*1fab62b1SMaxim Sobolev
252*1fab62b1SMaxim Sobolev ssize = write(fd, "", 1);
253*1fab62b1SMaxim Sobolev if (ssize < 0) {
254*1fab62b1SMaxim Sobolev uc_logmsg("uc_sync_send: write");
255*1fab62b1SMaxim Sobolev return (-1);
256*1fab62b1SMaxim Sobolev }
257*1fab62b1SMaxim Sobolev if (ssize < 1) {
258*1fab62b1SMaxim Sobolev uc_logmsgx("uc_sync_send: sent %zd of 1 byte", ssize);
259*1fab62b1SMaxim Sobolev return (-1);
260*1fab62b1SMaxim Sobolev }
261*1fab62b1SMaxim Sobolev
262*1fab62b1SMaxim Sobolev return (0);
263*1fab62b1SMaxim Sobolev }
264*1fab62b1SMaxim Sobolev
265*1fab62b1SMaxim Sobolev int
uc_message_send(int fd,const struct msghdr * msghdr)266*1fab62b1SMaxim Sobolev uc_message_send(int fd, const struct msghdr *msghdr)
267*1fab62b1SMaxim Sobolev {
268*1fab62b1SMaxim Sobolev const struct cmsghdr *cmsghdr;
269*1fab62b1SMaxim Sobolev size_t size;
270*1fab62b1SMaxim Sobolev ssize_t ssize;
271*1fab62b1SMaxim Sobolev
272*1fab62b1SMaxim Sobolev size = msghdr->msg_iov != 0 ? msghdr->msg_iov->iov_len : 0;
273*1fab62b1SMaxim Sobolev uc_dbgmsg("send: data size %zu", size);
274*1fab62b1SMaxim Sobolev uc_dbgmsg("send: msghdr.msg_controllen %u",
275*1fab62b1SMaxim Sobolev (u_int)msghdr->msg_controllen);
276*1fab62b1SMaxim Sobolev cmsghdr = CMSG_FIRSTHDR(msghdr);
277*1fab62b1SMaxim Sobolev if (cmsghdr != NULL)
278*1fab62b1SMaxim Sobolev uc_dbgmsg("send: cmsghdr.cmsg_len %u",
279*1fab62b1SMaxim Sobolev (u_int)cmsghdr->cmsg_len);
280*1fab62b1SMaxim Sobolev
281*1fab62b1SMaxim Sobolev ssize = sendmsg(fd, msghdr, 0);
282*1fab62b1SMaxim Sobolev if (ssize < 0) {
283*1fab62b1SMaxim Sobolev uc_logmsg("message_send: sendmsg");
284*1fab62b1SMaxim Sobolev return (-1);
285*1fab62b1SMaxim Sobolev }
286*1fab62b1SMaxim Sobolev if ((size_t)ssize != size) {
287*1fab62b1SMaxim Sobolev uc_logmsgx("message_send: sendmsg: sent %zd of %zu bytes",
288*1fab62b1SMaxim Sobolev ssize, size);
289*1fab62b1SMaxim Sobolev return (-1);
290*1fab62b1SMaxim Sobolev }
291*1fab62b1SMaxim Sobolev
292*1fab62b1SMaxim Sobolev if (!uc_cfg.send_data_flag)
293*1fab62b1SMaxim Sobolev if (uc_sync_send() < 0)
294*1fab62b1SMaxim Sobolev return (-1);
295*1fab62b1SMaxim Sobolev
296*1fab62b1SMaxim Sobolev return (0);
297*1fab62b1SMaxim Sobolev }
298*1fab62b1SMaxim Sobolev
299*1fab62b1SMaxim Sobolev int
uc_message_sendn(int fd,struct msghdr * msghdr)300*1fab62b1SMaxim Sobolev uc_message_sendn(int fd, struct msghdr *msghdr)
301*1fab62b1SMaxim Sobolev {
302*1fab62b1SMaxim Sobolev u_int i;
303*1fab62b1SMaxim Sobolev
304*1fab62b1SMaxim Sobolev for (i = 1; i <= uc_cfg.ipc_msg.msg_num; ++i) {
305*1fab62b1SMaxim Sobolev uc_dbgmsg("message #%u", i);
306*1fab62b1SMaxim Sobolev if (uc_message_send(fd, msghdr) < 0)
307*1fab62b1SMaxim Sobolev return (-1);
308*1fab62b1SMaxim Sobolev }
309*1fab62b1SMaxim Sobolev return (0);
310*1fab62b1SMaxim Sobolev }
311*1fab62b1SMaxim Sobolev
312*1fab62b1SMaxim Sobolev int
uc_message_recv(int fd,struct msghdr * msghdr)313*1fab62b1SMaxim Sobolev uc_message_recv(int fd, struct msghdr *msghdr)
314*1fab62b1SMaxim Sobolev {
315*1fab62b1SMaxim Sobolev const struct cmsghdr *cmsghdr;
316*1fab62b1SMaxim Sobolev size_t size;
317*1fab62b1SMaxim Sobolev ssize_t ssize;
318*1fab62b1SMaxim Sobolev
319*1fab62b1SMaxim Sobolev if (!uc_cfg.send_data_flag)
320*1fab62b1SMaxim Sobolev if (uc_sync_recv() < 0)
321*1fab62b1SMaxim Sobolev return (-1);
322*1fab62b1SMaxim Sobolev
323*1fab62b1SMaxim Sobolev size = msghdr->msg_iov != NULL ? msghdr->msg_iov->iov_len : 0;
324*1fab62b1SMaxim Sobolev ssize = recvmsg(fd, msghdr, MSG_WAITALL);
325*1fab62b1SMaxim Sobolev if (ssize < 0) {
326*1fab62b1SMaxim Sobolev uc_logmsg("message_recv: recvmsg");
327*1fab62b1SMaxim Sobolev return (-1);
328*1fab62b1SMaxim Sobolev }
329*1fab62b1SMaxim Sobolev if ((size_t)ssize != size) {
330*1fab62b1SMaxim Sobolev uc_logmsgx("message_recv: recvmsg: received %zd of %zu bytes",
331*1fab62b1SMaxim Sobolev ssize, size);
332*1fab62b1SMaxim Sobolev return (-1);
333*1fab62b1SMaxim Sobolev }
334*1fab62b1SMaxim Sobolev
335*1fab62b1SMaxim Sobolev uc_dbgmsg("recv: data size %zd", ssize);
336*1fab62b1SMaxim Sobolev uc_dbgmsg("recv: msghdr.msg_controllen %u",
337*1fab62b1SMaxim Sobolev (u_int)msghdr->msg_controllen);
338*1fab62b1SMaxim Sobolev cmsghdr = CMSG_FIRSTHDR(msghdr);
339*1fab62b1SMaxim Sobolev if (cmsghdr != NULL)
340*1fab62b1SMaxim Sobolev uc_dbgmsg("recv: cmsghdr.cmsg_len %u",
341*1fab62b1SMaxim Sobolev (u_int)cmsghdr->cmsg_len);
342*1fab62b1SMaxim Sobolev
343*1fab62b1SMaxim Sobolev if (memcmp(uc_cfg.ipc_msg.buf_recv, uc_cfg.ipc_msg.buf_send, size) != 0) {
344*1fab62b1SMaxim Sobolev uc_logmsgx("message_recv: received message has wrong content");
345*1fab62b1SMaxim Sobolev return (-1);
346*1fab62b1SMaxim Sobolev }
347*1fab62b1SMaxim Sobolev
348*1fab62b1SMaxim Sobolev return (0);
349*1fab62b1SMaxim Sobolev }
350*1fab62b1SMaxim Sobolev
351*1fab62b1SMaxim Sobolev int
uc_socket_accept(int listenfd)352*1fab62b1SMaxim Sobolev uc_socket_accept(int listenfd)
353*1fab62b1SMaxim Sobolev {
354*1fab62b1SMaxim Sobolev fd_set rset;
355*1fab62b1SMaxim Sobolev struct timeval tv;
356*1fab62b1SMaxim Sobolev int fd, rv, val;
357*1fab62b1SMaxim Sobolev
358*1fab62b1SMaxim Sobolev uc_dbgmsg("accept");
359*1fab62b1SMaxim Sobolev
360*1fab62b1SMaxim Sobolev FD_ZERO(&rset);
361*1fab62b1SMaxim Sobolev FD_SET(listenfd, &rset);
362*1fab62b1SMaxim Sobolev tv.tv_sec = TIMEOUT;
363*1fab62b1SMaxim Sobolev tv.tv_usec = 0;
364*1fab62b1SMaxim Sobolev rv = select(listenfd + 1, &rset, (fd_set *)NULL, (fd_set *)NULL, &tv);
365*1fab62b1SMaxim Sobolev if (rv < 0) {
366*1fab62b1SMaxim Sobolev uc_logmsg("socket_accept: select");
367*1fab62b1SMaxim Sobolev return (-1);
368*1fab62b1SMaxim Sobolev }
369*1fab62b1SMaxim Sobolev if (rv == 0) {
370*1fab62b1SMaxim Sobolev uc_logmsgx("socket_accept: select timeout");
371*1fab62b1SMaxim Sobolev return (-1);
372*1fab62b1SMaxim Sobolev }
373*1fab62b1SMaxim Sobolev
374*1fab62b1SMaxim Sobolev fd = accept(listenfd, (struct sockaddr *)NULL, (socklen_t *)NULL);
375*1fab62b1SMaxim Sobolev if (fd < 0) {
376*1fab62b1SMaxim Sobolev uc_logmsg("socket_accept: accept");
377*1fab62b1SMaxim Sobolev return (-1);
378*1fab62b1SMaxim Sobolev }
379*1fab62b1SMaxim Sobolev
380*1fab62b1SMaxim Sobolev val = fcntl(fd, F_GETFL, 0);
381*1fab62b1SMaxim Sobolev if (val < 0) {
382*1fab62b1SMaxim Sobolev uc_logmsg("socket_accept: fcntl(F_GETFL)");
383*1fab62b1SMaxim Sobolev goto failed;
384*1fab62b1SMaxim Sobolev }
385*1fab62b1SMaxim Sobolev if (fcntl(fd, F_SETFL, val & ~O_NONBLOCK) < 0) {
386*1fab62b1SMaxim Sobolev uc_logmsg("socket_accept: fcntl(F_SETFL)");
387*1fab62b1SMaxim Sobolev goto failed;
388*1fab62b1SMaxim Sobolev }
389*1fab62b1SMaxim Sobolev
390*1fab62b1SMaxim Sobolev return (fd);
391*1fab62b1SMaxim Sobolev
392*1fab62b1SMaxim Sobolev failed:
393*1fab62b1SMaxim Sobolev if (close(fd) < 0)
394*1fab62b1SMaxim Sobolev uc_logmsg("socket_accept: close");
395*1fab62b1SMaxim Sobolev return (-1);
396*1fab62b1SMaxim Sobolev }
397*1fab62b1SMaxim Sobolev
398*1fab62b1SMaxim Sobolev int
uc_check_msghdr(const struct msghdr * msghdr,size_t size)399*1fab62b1SMaxim Sobolev uc_check_msghdr(const struct msghdr *msghdr, size_t size)
400*1fab62b1SMaxim Sobolev {
401*1fab62b1SMaxim Sobolev if (msghdr->msg_flags & MSG_TRUNC) {
402*1fab62b1SMaxim Sobolev uc_logmsgx("msghdr.msg_flags has MSG_TRUNC");
403*1fab62b1SMaxim Sobolev return (-1);
404*1fab62b1SMaxim Sobolev }
405*1fab62b1SMaxim Sobolev if (msghdr->msg_flags & MSG_CTRUNC) {
406*1fab62b1SMaxim Sobolev uc_logmsgx("msghdr.msg_flags has MSG_CTRUNC");
407*1fab62b1SMaxim Sobolev return (-1);
408*1fab62b1SMaxim Sobolev }
409*1fab62b1SMaxim Sobolev if (msghdr->msg_controllen < size) {
410*1fab62b1SMaxim Sobolev uc_logmsgx("msghdr.msg_controllen %u < %zu",
411*1fab62b1SMaxim Sobolev (u_int)msghdr->msg_controllen, size);
412*1fab62b1SMaxim Sobolev return (-1);
413*1fab62b1SMaxim Sobolev }
414*1fab62b1SMaxim Sobolev if (msghdr->msg_controllen > 0 && size == 0) {
415*1fab62b1SMaxim Sobolev uc_logmsgx("msghdr.msg_controllen %u > 0",
416*1fab62b1SMaxim Sobolev (u_int)msghdr->msg_controllen);
417*1fab62b1SMaxim Sobolev return (-1);
418*1fab62b1SMaxim Sobolev }
419*1fab62b1SMaxim Sobolev return (0);
420*1fab62b1SMaxim Sobolev }
421*1fab62b1SMaxim Sobolev
422*1fab62b1SMaxim Sobolev int
uc_check_cmsghdr(const struct cmsghdr * cmsghdr,int type,size_t size)423*1fab62b1SMaxim Sobolev uc_check_cmsghdr(const struct cmsghdr *cmsghdr, int type, size_t size)
424*1fab62b1SMaxim Sobolev {
425*1fab62b1SMaxim Sobolev if (cmsghdr == NULL) {
426*1fab62b1SMaxim Sobolev uc_logmsgx("cmsghdr is NULL");
427*1fab62b1SMaxim Sobolev return (-1);
428*1fab62b1SMaxim Sobolev }
429*1fab62b1SMaxim Sobolev if (cmsghdr->cmsg_level != SOL_SOCKET) {
430*1fab62b1SMaxim Sobolev uc_logmsgx("cmsghdr.cmsg_level %d != SOL_SOCKET",
431*1fab62b1SMaxim Sobolev cmsghdr->cmsg_level);
432*1fab62b1SMaxim Sobolev return (-1);
433*1fab62b1SMaxim Sobolev }
434*1fab62b1SMaxim Sobolev if (cmsghdr->cmsg_type != type) {
435*1fab62b1SMaxim Sobolev uc_logmsgx("cmsghdr.cmsg_type %d != %d",
436*1fab62b1SMaxim Sobolev cmsghdr->cmsg_type, type);
437*1fab62b1SMaxim Sobolev return (-1);
438*1fab62b1SMaxim Sobolev }
439*1fab62b1SMaxim Sobolev if (cmsghdr->cmsg_len != CMSG_LEN(size)) {
440*1fab62b1SMaxim Sobolev uc_logmsgx("cmsghdr.cmsg_len %u != %zu",
441*1fab62b1SMaxim Sobolev (u_int)cmsghdr->cmsg_len, CMSG_LEN(size));
442*1fab62b1SMaxim Sobolev return (-1);
443*1fab62b1SMaxim Sobolev }
444*1fab62b1SMaxim Sobolev return (0);
445*1fab62b1SMaxim Sobolev }
446*1fab62b1SMaxim Sobolev
447*1fab62b1SMaxim Sobolev static void
uc_msghdr_init_generic(struct msghdr * msghdr,struct iovec * iov,void * cmsg_data)448*1fab62b1SMaxim Sobolev uc_msghdr_init_generic(struct msghdr *msghdr, struct iovec *iov, void *cmsg_data)
449*1fab62b1SMaxim Sobolev {
450*1fab62b1SMaxim Sobolev msghdr->msg_name = NULL;
451*1fab62b1SMaxim Sobolev msghdr->msg_namelen = 0;
452*1fab62b1SMaxim Sobolev if (uc_cfg.send_data_flag) {
453*1fab62b1SMaxim Sobolev iov->iov_base = uc_cfg.server_flag ?
454*1fab62b1SMaxim Sobolev uc_cfg.ipc_msg.buf_recv : uc_cfg.ipc_msg.buf_send;
455*1fab62b1SMaxim Sobolev iov->iov_len = uc_cfg.ipc_msg.buf_size;
456*1fab62b1SMaxim Sobolev msghdr->msg_iov = iov;
457*1fab62b1SMaxim Sobolev msghdr->msg_iovlen = 1;
458*1fab62b1SMaxim Sobolev } else {
459*1fab62b1SMaxim Sobolev msghdr->msg_iov = NULL;
460*1fab62b1SMaxim Sobolev msghdr->msg_iovlen = 0;
461*1fab62b1SMaxim Sobolev }
462*1fab62b1SMaxim Sobolev msghdr->msg_control = cmsg_data;
463*1fab62b1SMaxim Sobolev msghdr->msg_flags = 0;
464*1fab62b1SMaxim Sobolev }
465*1fab62b1SMaxim Sobolev
466*1fab62b1SMaxim Sobolev void
uc_msghdr_init_server(struct msghdr * msghdr,struct iovec * iov,void * cmsg_data,size_t cmsg_size)467*1fab62b1SMaxim Sobolev uc_msghdr_init_server(struct msghdr *msghdr, struct iovec *iov,
468*1fab62b1SMaxim Sobolev void *cmsg_data, size_t cmsg_size)
469*1fab62b1SMaxim Sobolev {
470*1fab62b1SMaxim Sobolev uc_msghdr_init_generic(msghdr, iov, cmsg_data);
471*1fab62b1SMaxim Sobolev msghdr->msg_controllen = cmsg_size;
472*1fab62b1SMaxim Sobolev uc_dbgmsg("init: data size %zu", msghdr->msg_iov != NULL ?
473*1fab62b1SMaxim Sobolev msghdr->msg_iov->iov_len : (size_t)0);
474*1fab62b1SMaxim Sobolev uc_dbgmsg("init: msghdr.msg_controllen %u",
475*1fab62b1SMaxim Sobolev (u_int)msghdr->msg_controllen);
476*1fab62b1SMaxim Sobolev }
477*1fab62b1SMaxim Sobolev
478*1fab62b1SMaxim Sobolev void
uc_msghdr_init_client(struct msghdr * msghdr,struct iovec * iov,void * cmsg_data,size_t cmsg_size,int type,size_t arr_size)479*1fab62b1SMaxim Sobolev uc_msghdr_init_client(struct msghdr *msghdr, struct iovec *iov,
480*1fab62b1SMaxim Sobolev void *cmsg_data, size_t cmsg_size, int type, size_t arr_size)
481*1fab62b1SMaxim Sobolev {
482*1fab62b1SMaxim Sobolev struct cmsghdr *cmsghdr;
483*1fab62b1SMaxim Sobolev
484*1fab62b1SMaxim Sobolev uc_msghdr_init_generic(msghdr, iov, cmsg_data);
485*1fab62b1SMaxim Sobolev if (cmsg_data != NULL) {
486*1fab62b1SMaxim Sobolev if (uc_cfg.send_array_flag)
487*1fab62b1SMaxim Sobolev uc_dbgmsg("sending an array");
488*1fab62b1SMaxim Sobolev else
489*1fab62b1SMaxim Sobolev uc_dbgmsg("sending a scalar");
490*1fab62b1SMaxim Sobolev msghdr->msg_controllen = uc_cfg.send_array_flag ?
491*1fab62b1SMaxim Sobolev cmsg_size : CMSG_SPACE(0);
492*1fab62b1SMaxim Sobolev cmsghdr = CMSG_FIRSTHDR(msghdr);
493*1fab62b1SMaxim Sobolev cmsghdr->cmsg_level = SOL_SOCKET;
494*1fab62b1SMaxim Sobolev cmsghdr->cmsg_type = type;
495*1fab62b1SMaxim Sobolev cmsghdr->cmsg_len = CMSG_LEN(uc_cfg.send_array_flag ? arr_size : 0);
496*1fab62b1SMaxim Sobolev } else
497*1fab62b1SMaxim Sobolev msghdr->msg_controllen = 0;
498*1fab62b1SMaxim Sobolev }
499*1fab62b1SMaxim Sobolev
500*1fab62b1SMaxim Sobolev int
uc_client_fork(void)501*1fab62b1SMaxim Sobolev uc_client_fork(void)
502*1fab62b1SMaxim Sobolev {
503*1fab62b1SMaxim Sobolev int fd1, fd2;
504*1fab62b1SMaxim Sobolev
505*1fab62b1SMaxim Sobolev if (pipe(uc_cfg.sync_fd[SYNC_SERVER]) < 0 ||
506*1fab62b1SMaxim Sobolev pipe(uc_cfg.sync_fd[SYNC_CLIENT]) < 0) {
507*1fab62b1SMaxim Sobolev uc_logmsg("client_fork: pipe");
508*1fab62b1SMaxim Sobolev return (-1);
509*1fab62b1SMaxim Sobolev }
510*1fab62b1SMaxim Sobolev uc_cfg.client_pid = fork();
511*1fab62b1SMaxim Sobolev if (uc_cfg.client_pid == (pid_t)-1) {
512*1fab62b1SMaxim Sobolev uc_logmsg("client_fork: fork");
513*1fab62b1SMaxim Sobolev return (-1);
514*1fab62b1SMaxim Sobolev }
515*1fab62b1SMaxim Sobolev if (uc_cfg.client_pid == 0) {
516*1fab62b1SMaxim Sobolev uc_cfg.proc_name = "CLIENT";
517*1fab62b1SMaxim Sobolev uc_cfg.server_flag = false;
518*1fab62b1SMaxim Sobolev fd1 = uc_cfg.sync_fd[SYNC_SERVER][SYNC_RECV];
519*1fab62b1SMaxim Sobolev fd2 = uc_cfg.sync_fd[SYNC_CLIENT][SYNC_SEND];
520*1fab62b1SMaxim Sobolev } else {
521*1fab62b1SMaxim Sobolev fd1 = uc_cfg.sync_fd[SYNC_SERVER][SYNC_SEND];
522*1fab62b1SMaxim Sobolev fd2 = uc_cfg.sync_fd[SYNC_CLIENT][SYNC_RECV];
523*1fab62b1SMaxim Sobolev }
524*1fab62b1SMaxim Sobolev if (close(fd1) < 0 || close(fd2) < 0) {
525*1fab62b1SMaxim Sobolev uc_logmsg("client_fork: close");
526*1fab62b1SMaxim Sobolev return (-1);
527*1fab62b1SMaxim Sobolev }
528*1fab62b1SMaxim Sobolev return (uc_cfg.client_pid != 0);
529*1fab62b1SMaxim Sobolev }
530*1fab62b1SMaxim Sobolev
531*1fab62b1SMaxim Sobolev void
uc_client_exit(int rv)532*1fab62b1SMaxim Sobolev uc_client_exit(int rv)
533*1fab62b1SMaxim Sobolev {
534*1fab62b1SMaxim Sobolev if (close(uc_cfg.sync_fd[SYNC_SERVER][SYNC_SEND]) < 0 ||
535*1fab62b1SMaxim Sobolev close(uc_cfg.sync_fd[SYNC_CLIENT][SYNC_RECV]) < 0) {
536*1fab62b1SMaxim Sobolev uc_logmsg("client_exit: close");
537*1fab62b1SMaxim Sobolev rv = -1;
538*1fab62b1SMaxim Sobolev }
539*1fab62b1SMaxim Sobolev rv = rv == 0 ? EXIT_SUCCESS : -rv;
540*1fab62b1SMaxim Sobolev uc_dbgmsg("exit: code %d", rv);
541*1fab62b1SMaxim Sobolev _exit(rv);
542*1fab62b1SMaxim Sobolev }
543*1fab62b1SMaxim Sobolev
544*1fab62b1SMaxim Sobolev int
uc_client_wait(void)545*1fab62b1SMaxim Sobolev uc_client_wait(void)
546*1fab62b1SMaxim Sobolev {
547*1fab62b1SMaxim Sobolev int status;
548*1fab62b1SMaxim Sobolev pid_t pid;
549*1fab62b1SMaxim Sobolev
550*1fab62b1SMaxim Sobolev uc_dbgmsg("waiting for client");
551*1fab62b1SMaxim Sobolev
552*1fab62b1SMaxim Sobolev if (close(uc_cfg.sync_fd[SYNC_SERVER][SYNC_RECV]) < 0 ||
553*1fab62b1SMaxim Sobolev close(uc_cfg.sync_fd[SYNC_CLIENT][SYNC_SEND]) < 0) {
554*1fab62b1SMaxim Sobolev uc_logmsg("client_wait: close");
555*1fab62b1SMaxim Sobolev return (-1);
556*1fab62b1SMaxim Sobolev }
557*1fab62b1SMaxim Sobolev
558*1fab62b1SMaxim Sobolev pid = waitpid(uc_cfg.client_pid, &status, 0);
559*1fab62b1SMaxim Sobolev if (pid == (pid_t)-1) {
560*1fab62b1SMaxim Sobolev uc_logmsg("client_wait: waitpid");
561*1fab62b1SMaxim Sobolev return (-1);
562*1fab62b1SMaxim Sobolev }
563*1fab62b1SMaxim Sobolev
564*1fab62b1SMaxim Sobolev if (WIFEXITED(status)) {
565*1fab62b1SMaxim Sobolev if (WEXITSTATUS(status) != EXIT_SUCCESS) {
566*1fab62b1SMaxim Sobolev uc_logmsgx("client exit status is %d",
567*1fab62b1SMaxim Sobolev WEXITSTATUS(status));
568*1fab62b1SMaxim Sobolev return (-WEXITSTATUS(status));
569*1fab62b1SMaxim Sobolev }
570*1fab62b1SMaxim Sobolev } else {
571*1fab62b1SMaxim Sobolev if (WIFSIGNALED(status))
572*1fab62b1SMaxim Sobolev uc_logmsgx("abnormal termination of client, signal %d%s",
573*1fab62b1SMaxim Sobolev WTERMSIG(status), WCOREDUMP(status) ?
574*1fab62b1SMaxim Sobolev " (core file generated)" : "");
575*1fab62b1SMaxim Sobolev else
576*1fab62b1SMaxim Sobolev uc_logmsgx("termination of client, unknown status");
577*1fab62b1SMaxim Sobolev return (-1);
578*1fab62b1SMaxim Sobolev }
579*1fab62b1SMaxim Sobolev
580*1fab62b1SMaxim Sobolev return (0);
581*1fab62b1SMaxim Sobolev }
582*1fab62b1SMaxim Sobolev
583*1fab62b1SMaxim Sobolev int
uc_check_groups(const char * gid_arr_str,const gid_t * gid_arr,const char * gid_num_str,int gid_num,bool all_gids)584*1fab62b1SMaxim Sobolev uc_check_groups(const char *gid_arr_str, const gid_t *gid_arr,
585*1fab62b1SMaxim Sobolev const char *gid_num_str, int gid_num, bool all_gids)
586*1fab62b1SMaxim Sobolev {
587*1fab62b1SMaxim Sobolev int i;
588*1fab62b1SMaxim Sobolev
589*1fab62b1SMaxim Sobolev for (i = 0; i < gid_num; ++i)
590*1fab62b1SMaxim Sobolev uc_dbgmsg("%s[%d] %lu", gid_arr_str, i, (u_long)gid_arr[i]);
591*1fab62b1SMaxim Sobolev
592*1fab62b1SMaxim Sobolev if (all_gids) {
593*1fab62b1SMaxim Sobolev if (gid_num != uc_cfg.proc_cred.gid_num) {
594*1fab62b1SMaxim Sobolev uc_logmsgx("%s %d != %d", gid_num_str, gid_num,
595*1fab62b1SMaxim Sobolev uc_cfg.proc_cred.gid_num);
596*1fab62b1SMaxim Sobolev return (-1);
597*1fab62b1SMaxim Sobolev }
598*1fab62b1SMaxim Sobolev } else {
599*1fab62b1SMaxim Sobolev if (gid_num > uc_cfg.proc_cred.gid_num) {
600*1fab62b1SMaxim Sobolev uc_logmsgx("%s %d > %d", gid_num_str, gid_num,
601*1fab62b1SMaxim Sobolev uc_cfg.proc_cred.gid_num);
602*1fab62b1SMaxim Sobolev return (-1);
603*1fab62b1SMaxim Sobolev }
604*1fab62b1SMaxim Sobolev }
605*1fab62b1SMaxim Sobolev if (memcmp(gid_arr, uc_cfg.proc_cred.gid_arr,
606*1fab62b1SMaxim Sobolev gid_num * sizeof(*gid_arr)) != 0) {
607*1fab62b1SMaxim Sobolev uc_logmsgx("%s content is wrong", gid_arr_str);
608*1fab62b1SMaxim Sobolev for (i = 0; i < gid_num; ++i)
609*1fab62b1SMaxim Sobolev if (gid_arr[i] != uc_cfg.proc_cred.gid_arr[i]) {
610*1fab62b1SMaxim Sobolev uc_logmsgx("%s[%d] %lu != %lu",
611*1fab62b1SMaxim Sobolev gid_arr_str, i, (u_long)gid_arr[i],
612*1fab62b1SMaxim Sobolev (u_long)uc_cfg.proc_cred.gid_arr[i]);
613*1fab62b1SMaxim Sobolev break;
614*1fab62b1SMaxim Sobolev }
615*1fab62b1SMaxim Sobolev return (-1);
616*1fab62b1SMaxim Sobolev }
617*1fab62b1SMaxim Sobolev return (0);
618*1fab62b1SMaxim Sobolev }
619*1fab62b1SMaxim Sobolev
620*1fab62b1SMaxim Sobolev int
uc_check_scm_creds_cmsgcred(struct cmsghdr * cmsghdr)621*1fab62b1SMaxim Sobolev uc_check_scm_creds_cmsgcred(struct cmsghdr *cmsghdr)
622*1fab62b1SMaxim Sobolev {
623*1fab62b1SMaxim Sobolev const struct cmsgcred *cmcred;
624*1fab62b1SMaxim Sobolev int rc;
625*1fab62b1SMaxim Sobolev
626*1fab62b1SMaxim Sobolev if (uc_check_cmsghdr(cmsghdr, SCM_CREDS, sizeof(struct cmsgcred)) < 0)
627*1fab62b1SMaxim Sobolev return (-1);
628*1fab62b1SMaxim Sobolev
629*1fab62b1SMaxim Sobolev cmcred = (struct cmsgcred *)CMSG_DATA(cmsghdr);
630*1fab62b1SMaxim Sobolev
631*1fab62b1SMaxim Sobolev uc_dbgmsg("cmsgcred.cmcred_pid %ld", (long)cmcred->cmcred_pid);
632*1fab62b1SMaxim Sobolev uc_dbgmsg("cmsgcred.cmcred_uid %lu", (u_long)cmcred->cmcred_uid);
633*1fab62b1SMaxim Sobolev uc_dbgmsg("cmsgcred.cmcred_euid %lu", (u_long)cmcred->cmcred_euid);
634*1fab62b1SMaxim Sobolev uc_dbgmsg("cmsgcred.cmcred_gid %lu", (u_long)cmcred->cmcred_gid);
635*1fab62b1SMaxim Sobolev uc_dbgmsg("cmsgcred.cmcred_ngroups %d", cmcred->cmcred_ngroups);
636*1fab62b1SMaxim Sobolev
637*1fab62b1SMaxim Sobolev rc = 0;
638*1fab62b1SMaxim Sobolev
639*1fab62b1SMaxim Sobolev if (cmcred->cmcred_pid != uc_cfg.client_pid) {
640*1fab62b1SMaxim Sobolev uc_logmsgx("cmsgcred.cmcred_pid %ld != %ld",
641*1fab62b1SMaxim Sobolev (long)cmcred->cmcred_pid, (long)uc_cfg.client_pid);
642*1fab62b1SMaxim Sobolev rc = -1;
643*1fab62b1SMaxim Sobolev }
644*1fab62b1SMaxim Sobolev if (cmcred->cmcred_uid != uc_cfg.proc_cred.uid) {
645*1fab62b1SMaxim Sobolev uc_logmsgx("cmsgcred.cmcred_uid %lu != %lu",
646*1fab62b1SMaxim Sobolev (u_long)cmcred->cmcred_uid, (u_long)uc_cfg.proc_cred.uid);
647*1fab62b1SMaxim Sobolev rc = -1;
648*1fab62b1SMaxim Sobolev }
649*1fab62b1SMaxim Sobolev if (cmcred->cmcred_euid != uc_cfg.proc_cred.euid) {
650*1fab62b1SMaxim Sobolev uc_logmsgx("cmsgcred.cmcred_euid %lu != %lu",
651*1fab62b1SMaxim Sobolev (u_long)cmcred->cmcred_euid, (u_long)uc_cfg.proc_cred.euid);
652*1fab62b1SMaxim Sobolev rc = -1;
653*1fab62b1SMaxim Sobolev }
654*1fab62b1SMaxim Sobolev if (cmcred->cmcred_gid != uc_cfg.proc_cred.gid) {
655*1fab62b1SMaxim Sobolev uc_logmsgx("cmsgcred.cmcred_gid %lu != %lu",
656*1fab62b1SMaxim Sobolev (u_long)cmcred->cmcred_gid, (u_long)uc_cfg.proc_cred.gid);
657*1fab62b1SMaxim Sobolev rc = -1;
658*1fab62b1SMaxim Sobolev }
659*1fab62b1SMaxim Sobolev if (cmcred->cmcred_ngroups == 0) {
660*1fab62b1SMaxim Sobolev uc_logmsgx("cmsgcred.cmcred_ngroups == 0");
661*1fab62b1SMaxim Sobolev rc = -1;
662*1fab62b1SMaxim Sobolev }
663*1fab62b1SMaxim Sobolev if (cmcred->cmcred_ngroups < 0) {
664*1fab62b1SMaxim Sobolev uc_logmsgx("cmsgcred.cmcred_ngroups %d < 0",
665*1fab62b1SMaxim Sobolev cmcred->cmcred_ngroups);
666*1fab62b1SMaxim Sobolev rc = -1;
667*1fab62b1SMaxim Sobolev }
668*1fab62b1SMaxim Sobolev if (cmcred->cmcred_ngroups > CMGROUP_MAX) {
669*1fab62b1SMaxim Sobolev uc_logmsgx("cmsgcred.cmcred_ngroups %d > %d",
670*1fab62b1SMaxim Sobolev cmcred->cmcred_ngroups, CMGROUP_MAX);
671*1fab62b1SMaxim Sobolev rc = -1;
672*1fab62b1SMaxim Sobolev }
673*1fab62b1SMaxim Sobolev if (cmcred->cmcred_groups[0] != uc_cfg.proc_cred.egid) {
674*1fab62b1SMaxim Sobolev uc_logmsgx("cmsgcred.cmcred_groups[0] %lu != %lu (EGID)",
675*1fab62b1SMaxim Sobolev (u_long)cmcred->cmcred_groups[0], (u_long)uc_cfg.proc_cred.egid);
676*1fab62b1SMaxim Sobolev rc = -1;
677*1fab62b1SMaxim Sobolev }
678*1fab62b1SMaxim Sobolev if (uc_check_groups("cmsgcred.cmcred_groups", cmcred->cmcred_groups,
679*1fab62b1SMaxim Sobolev "cmsgcred.cmcred_ngroups", cmcred->cmcred_ngroups, false) < 0)
680*1fab62b1SMaxim Sobolev rc = -1;
681*1fab62b1SMaxim Sobolev return (rc);
682*1fab62b1SMaxim Sobolev }
683*1fab62b1SMaxim Sobolev
684*1fab62b1SMaxim Sobolev int
uc_check_scm_creds_sockcred(struct cmsghdr * cmsghdr)685*1fab62b1SMaxim Sobolev uc_check_scm_creds_sockcred(struct cmsghdr *cmsghdr)
686*1fab62b1SMaxim Sobolev {
687*1fab62b1SMaxim Sobolev const struct sockcred *sc;
688*1fab62b1SMaxim Sobolev int rc;
689*1fab62b1SMaxim Sobolev
690*1fab62b1SMaxim Sobolev if (uc_check_cmsghdr(cmsghdr, SCM_CREDS,
691*1fab62b1SMaxim Sobolev SOCKCREDSIZE(uc_cfg.proc_cred.gid_num)) < 0)
692*1fab62b1SMaxim Sobolev return (-1);
693*1fab62b1SMaxim Sobolev
694*1fab62b1SMaxim Sobolev sc = (struct sockcred *)CMSG_DATA(cmsghdr);
695*1fab62b1SMaxim Sobolev
696*1fab62b1SMaxim Sobolev rc = 0;
697*1fab62b1SMaxim Sobolev
698*1fab62b1SMaxim Sobolev uc_dbgmsg("sockcred.sc_uid %lu", (u_long)sc->sc_uid);
699*1fab62b1SMaxim Sobolev uc_dbgmsg("sockcred.sc_euid %lu", (u_long)sc->sc_euid);
700*1fab62b1SMaxim Sobolev uc_dbgmsg("sockcred.sc_gid %lu", (u_long)sc->sc_gid);
701*1fab62b1SMaxim Sobolev uc_dbgmsg("sockcred.sc_egid %lu", (u_long)sc->sc_egid);
702*1fab62b1SMaxim Sobolev uc_dbgmsg("sockcred.sc_ngroups %d", sc->sc_ngroups);
703*1fab62b1SMaxim Sobolev
704*1fab62b1SMaxim Sobolev if (sc->sc_uid != uc_cfg.proc_cred.uid) {
705*1fab62b1SMaxim Sobolev uc_logmsgx("sockcred.sc_uid %lu != %lu",
706*1fab62b1SMaxim Sobolev (u_long)sc->sc_uid, (u_long)uc_cfg.proc_cred.uid);
707*1fab62b1SMaxim Sobolev rc = -1;
708*1fab62b1SMaxim Sobolev }
709*1fab62b1SMaxim Sobolev if (sc->sc_euid != uc_cfg.proc_cred.euid) {
710*1fab62b1SMaxim Sobolev uc_logmsgx("sockcred.sc_euid %lu != %lu",
711*1fab62b1SMaxim Sobolev (u_long)sc->sc_euid, (u_long)uc_cfg.proc_cred.euid);
712*1fab62b1SMaxim Sobolev rc = -1;
713*1fab62b1SMaxim Sobolev }
714*1fab62b1SMaxim Sobolev if (sc->sc_gid != uc_cfg.proc_cred.gid) {
715*1fab62b1SMaxim Sobolev uc_logmsgx("sockcred.sc_gid %lu != %lu",
716*1fab62b1SMaxim Sobolev (u_long)sc->sc_gid, (u_long)uc_cfg.proc_cred.gid);
717*1fab62b1SMaxim Sobolev rc = -1;
718*1fab62b1SMaxim Sobolev }
719*1fab62b1SMaxim Sobolev if (sc->sc_egid != uc_cfg.proc_cred.egid) {
720*1fab62b1SMaxim Sobolev uc_logmsgx("sockcred.sc_egid %lu != %lu",
721*1fab62b1SMaxim Sobolev (u_long)sc->sc_egid, (u_long)uc_cfg.proc_cred.egid);
722*1fab62b1SMaxim Sobolev rc = -1;
723*1fab62b1SMaxim Sobolev }
724*1fab62b1SMaxim Sobolev if (sc->sc_ngroups == 0) {
725*1fab62b1SMaxim Sobolev uc_logmsgx("sockcred.sc_ngroups == 0");
726*1fab62b1SMaxim Sobolev rc = -1;
727*1fab62b1SMaxim Sobolev }
728*1fab62b1SMaxim Sobolev if (sc->sc_ngroups < 0) {
729*1fab62b1SMaxim Sobolev uc_logmsgx("sockcred.sc_ngroups %d < 0",
730*1fab62b1SMaxim Sobolev sc->sc_ngroups);
731*1fab62b1SMaxim Sobolev rc = -1;
732*1fab62b1SMaxim Sobolev }
733*1fab62b1SMaxim Sobolev if (sc->sc_ngroups != uc_cfg.proc_cred.gid_num) {
734*1fab62b1SMaxim Sobolev uc_logmsgx("sockcred.sc_ngroups %d != %u",
735*1fab62b1SMaxim Sobolev sc->sc_ngroups, uc_cfg.proc_cred.gid_num);
736*1fab62b1SMaxim Sobolev rc = -1;
737*1fab62b1SMaxim Sobolev }
738*1fab62b1SMaxim Sobolev if (uc_check_groups("sockcred.sc_groups", sc->sc_groups,
739*1fab62b1SMaxim Sobolev "sockcred.sc_ngroups", sc->sc_ngroups, true) < 0)
740*1fab62b1SMaxim Sobolev rc = -1;
741*1fab62b1SMaxim Sobolev return (rc);
742*1fab62b1SMaxim Sobolev }
743