xref: /freebsd-src/contrib/openbsm/bin/auditdistd/proto_socketpair.c (revision b626f5a73a48f44a31a200291b141e1da408a2ff)
1*aa772005SRobert Watson /*-
2*aa772005SRobert Watson  * Copyright (c) 2009-2010 The FreeBSD Foundation
3*aa772005SRobert Watson  * All rights reserved.
4*aa772005SRobert Watson  *
5*aa772005SRobert Watson  * This software was developed by Pawel Jakub Dawidek under sponsorship from
6*aa772005SRobert Watson  * the FreeBSD Foundation.
7*aa772005SRobert Watson  *
8*aa772005SRobert Watson  * Redistribution and use in source and binary forms, with or without
9*aa772005SRobert Watson  * modification, are permitted provided that the following conditions
10*aa772005SRobert Watson  * are met:
11*aa772005SRobert Watson  * 1. Redistributions of source code must retain the above copyright
12*aa772005SRobert Watson  *    notice, this list of conditions and the following disclaimer.
13*aa772005SRobert Watson  * 2. Redistributions in binary form must reproduce the above copyright
14*aa772005SRobert Watson  *    notice, this list of conditions and the following disclaimer in the
15*aa772005SRobert Watson  *    documentation and/or other materials provided with the distribution.
16*aa772005SRobert Watson  *
17*aa772005SRobert Watson  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
18*aa772005SRobert Watson  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19*aa772005SRobert Watson  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20*aa772005SRobert Watson  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
21*aa772005SRobert Watson  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22*aa772005SRobert Watson  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23*aa772005SRobert Watson  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24*aa772005SRobert Watson  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25*aa772005SRobert Watson  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26*aa772005SRobert Watson  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27*aa772005SRobert Watson  * SUCH DAMAGE.
28*aa772005SRobert Watson  */
29*aa772005SRobert Watson 
30*aa772005SRobert Watson #include <sys/types.h>
31*aa772005SRobert Watson #include <sys/socket.h>
32*aa772005SRobert Watson 
33*aa772005SRobert Watson #include <errno.h>
34*aa772005SRobert Watson #include <stdbool.h>
35*aa772005SRobert Watson #include <stdint.h>
36*aa772005SRobert Watson #include <stdio.h>
37*aa772005SRobert Watson #include <string.h>
38*aa772005SRobert Watson #include <unistd.h>
39*aa772005SRobert Watson 
40*aa772005SRobert Watson #include "pjdlog.h"
41*aa772005SRobert Watson #include "proto_impl.h"
42*aa772005SRobert Watson 
43*aa772005SRobert Watson #define	SP_CTX_MAGIC	0x50c3741
44*aa772005SRobert Watson struct sp_ctx {
45*aa772005SRobert Watson 	int			sp_magic;
46*aa772005SRobert Watson 	int			sp_fd[2];
47*aa772005SRobert Watson 	int			sp_side;
48*aa772005SRobert Watson #define	SP_SIDE_UNDEF		0
49*aa772005SRobert Watson #define	SP_SIDE_CLIENT		1
50*aa772005SRobert Watson #define	SP_SIDE_SERVER		2
51*aa772005SRobert Watson };
52*aa772005SRobert Watson 
53*aa772005SRobert Watson static void sp_close(void *ctx);
54*aa772005SRobert Watson 
55*aa772005SRobert Watson static int
sp_connect(const char * srcaddr,const char * dstaddr,int timeout,void ** ctxp)56*aa772005SRobert Watson sp_connect(const char *srcaddr, const char *dstaddr, int timeout, void **ctxp)
57*aa772005SRobert Watson {
58*aa772005SRobert Watson 	struct sp_ctx *spctx;
59*aa772005SRobert Watson 	int error;
60*aa772005SRobert Watson 
61*aa772005SRobert Watson 	PJDLOG_ASSERT(dstaddr != NULL);
62*aa772005SRobert Watson 	PJDLOG_ASSERT(timeout >= -1);
63*aa772005SRobert Watson 
64*aa772005SRobert Watson 	if (strcmp(dstaddr, "socketpair://") != 0)
65*aa772005SRobert Watson 		return (-1);
66*aa772005SRobert Watson 
67*aa772005SRobert Watson 	PJDLOG_ASSERT(srcaddr == NULL);
68*aa772005SRobert Watson 
69*aa772005SRobert Watson 	spctx = malloc(sizeof(*spctx));
70*aa772005SRobert Watson 	if (spctx == NULL)
71*aa772005SRobert Watson 		return (errno);
72*aa772005SRobert Watson 
73*aa772005SRobert Watson 	if (socketpair(PF_UNIX, SOCK_STREAM, 0, spctx->sp_fd) == -1) {
74*aa772005SRobert Watson 		error = errno;
75*aa772005SRobert Watson 		free(spctx);
76*aa772005SRobert Watson 		return (error);
77*aa772005SRobert Watson 	}
78*aa772005SRobert Watson 
79*aa772005SRobert Watson 	spctx->sp_side = SP_SIDE_UNDEF;
80*aa772005SRobert Watson 	spctx->sp_magic = SP_CTX_MAGIC;
81*aa772005SRobert Watson 	*ctxp = spctx;
82*aa772005SRobert Watson 
83*aa772005SRobert Watson 	return (0);
84*aa772005SRobert Watson }
85*aa772005SRobert Watson 
86*aa772005SRobert Watson static int
sp_wrap(int fd,bool client,void ** ctxp)87*aa772005SRobert Watson sp_wrap(int fd, bool client, void **ctxp)
88*aa772005SRobert Watson {
89*aa772005SRobert Watson 	struct sp_ctx *spctx;
90*aa772005SRobert Watson 
91*aa772005SRobert Watson 	PJDLOG_ASSERT(fd >= 0);
92*aa772005SRobert Watson 
93*aa772005SRobert Watson 	spctx = malloc(sizeof(*spctx));
94*aa772005SRobert Watson 	if (spctx == NULL)
95*aa772005SRobert Watson 		return (errno);
96*aa772005SRobert Watson 
97*aa772005SRobert Watson 	if (client) {
98*aa772005SRobert Watson 		spctx->sp_side = SP_SIDE_CLIENT;
99*aa772005SRobert Watson 		spctx->sp_fd[0] = fd;
100*aa772005SRobert Watson 		spctx->sp_fd[1] = -1;
101*aa772005SRobert Watson 	} else {
102*aa772005SRobert Watson 		spctx->sp_side = SP_SIDE_SERVER;
103*aa772005SRobert Watson 		spctx->sp_fd[0] = -1;
104*aa772005SRobert Watson 		spctx->sp_fd[1] = fd;
105*aa772005SRobert Watson 	}
106*aa772005SRobert Watson 	spctx->sp_magic = SP_CTX_MAGIC;
107*aa772005SRobert Watson 	*ctxp = spctx;
108*aa772005SRobert Watson 
109*aa772005SRobert Watson 	return (0);
110*aa772005SRobert Watson }
111*aa772005SRobert Watson 
112*aa772005SRobert Watson static int
sp_send(void * ctx,const unsigned char * data,size_t size,int fd)113*aa772005SRobert Watson sp_send(void *ctx, const unsigned char *data, size_t size, int fd)
114*aa772005SRobert Watson {
115*aa772005SRobert Watson 	struct sp_ctx *spctx = ctx;
116*aa772005SRobert Watson 	int sock;
117*aa772005SRobert Watson 
118*aa772005SRobert Watson 	PJDLOG_ASSERT(spctx != NULL);
119*aa772005SRobert Watson 	PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC);
120*aa772005SRobert Watson 
121*aa772005SRobert Watson 	switch (spctx->sp_side) {
122*aa772005SRobert Watson 	case SP_SIDE_UNDEF:
123*aa772005SRobert Watson 		/*
124*aa772005SRobert Watson 		 * If the first operation done by the caller is proto_send(),
125*aa772005SRobert Watson 		 * we assume this is the client.
126*aa772005SRobert Watson 		 */
127*aa772005SRobert Watson 		/* FALLTHROUGH */
128*aa772005SRobert Watson 		spctx->sp_side = SP_SIDE_CLIENT;
129*aa772005SRobert Watson 		/* Close other end. */
130*aa772005SRobert Watson 		close(spctx->sp_fd[1]);
131*aa772005SRobert Watson 		spctx->sp_fd[1] = -1;
132*aa772005SRobert Watson 	case SP_SIDE_CLIENT:
133*aa772005SRobert Watson 		PJDLOG_ASSERT(spctx->sp_fd[0] >= 0);
134*aa772005SRobert Watson 		sock = spctx->sp_fd[0];
135*aa772005SRobert Watson 		break;
136*aa772005SRobert Watson 	case SP_SIDE_SERVER:
137*aa772005SRobert Watson 		PJDLOG_ASSERT(spctx->sp_fd[1] >= 0);
138*aa772005SRobert Watson 		sock = spctx->sp_fd[1];
139*aa772005SRobert Watson 		break;
140*aa772005SRobert Watson 	default:
141*aa772005SRobert Watson 		PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side);
142*aa772005SRobert Watson 	}
143*aa772005SRobert Watson 
144*aa772005SRobert Watson 	/* Someone is just trying to decide about side. */
145*aa772005SRobert Watson 	if (data == NULL)
146*aa772005SRobert Watson 		return (0);
147*aa772005SRobert Watson 
148*aa772005SRobert Watson 	return (proto_common_send(sock, data, size, fd));
149*aa772005SRobert Watson }
150*aa772005SRobert Watson 
151*aa772005SRobert Watson static int
sp_recv(void * ctx,unsigned char * data,size_t size,int * fdp)152*aa772005SRobert Watson sp_recv(void *ctx, unsigned char *data, size_t size, int *fdp)
153*aa772005SRobert Watson {
154*aa772005SRobert Watson 	struct sp_ctx *spctx = ctx;
155*aa772005SRobert Watson 	int sock;
156*aa772005SRobert Watson 
157*aa772005SRobert Watson 	PJDLOG_ASSERT(spctx != NULL);
158*aa772005SRobert Watson 	PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC);
159*aa772005SRobert Watson 
160*aa772005SRobert Watson 	switch (spctx->sp_side) {
161*aa772005SRobert Watson 	case SP_SIDE_UNDEF:
162*aa772005SRobert Watson 		/*
163*aa772005SRobert Watson 		 * If the first operation done by the caller is proto_recv(),
164*aa772005SRobert Watson 		 * we assume this is the server.
165*aa772005SRobert Watson 		 */
166*aa772005SRobert Watson 		/* FALLTHROUGH */
167*aa772005SRobert Watson 		spctx->sp_side = SP_SIDE_SERVER;
168*aa772005SRobert Watson 		/* Close other end. */
169*aa772005SRobert Watson 		close(spctx->sp_fd[0]);
170*aa772005SRobert Watson 		spctx->sp_fd[0] = -1;
171*aa772005SRobert Watson 	case SP_SIDE_SERVER:
172*aa772005SRobert Watson 		PJDLOG_ASSERT(spctx->sp_fd[1] >= 0);
173*aa772005SRobert Watson 		sock = spctx->sp_fd[1];
174*aa772005SRobert Watson 		break;
175*aa772005SRobert Watson 	case SP_SIDE_CLIENT:
176*aa772005SRobert Watson 		PJDLOG_ASSERT(spctx->sp_fd[0] >= 0);
177*aa772005SRobert Watson 		sock = spctx->sp_fd[0];
178*aa772005SRobert Watson 		break;
179*aa772005SRobert Watson 	default:
180*aa772005SRobert Watson 		PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side);
181*aa772005SRobert Watson 	}
182*aa772005SRobert Watson 
183*aa772005SRobert Watson 	/* Someone is just trying to decide about side. */
184*aa772005SRobert Watson 	if (data == NULL)
185*aa772005SRobert Watson 		return (0);
186*aa772005SRobert Watson 
187*aa772005SRobert Watson 	return (proto_common_recv(sock, data, size, fdp));
188*aa772005SRobert Watson }
189*aa772005SRobert Watson 
190*aa772005SRobert Watson static int
sp_descriptor(const void * ctx)191*aa772005SRobert Watson sp_descriptor(const void *ctx)
192*aa772005SRobert Watson {
193*aa772005SRobert Watson 	const struct sp_ctx *spctx = ctx;
194*aa772005SRobert Watson 
195*aa772005SRobert Watson 	PJDLOG_ASSERT(spctx != NULL);
196*aa772005SRobert Watson 	PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC);
197*aa772005SRobert Watson 	PJDLOG_ASSERT(spctx->sp_side == SP_SIDE_CLIENT ||
198*aa772005SRobert Watson 	    spctx->sp_side == SP_SIDE_SERVER);
199*aa772005SRobert Watson 
200*aa772005SRobert Watson 	switch (spctx->sp_side) {
201*aa772005SRobert Watson 	case SP_SIDE_CLIENT:
202*aa772005SRobert Watson 		PJDLOG_ASSERT(spctx->sp_fd[0] >= 0);
203*aa772005SRobert Watson 		return (spctx->sp_fd[0]);
204*aa772005SRobert Watson 	case SP_SIDE_SERVER:
205*aa772005SRobert Watson 		PJDLOG_ASSERT(spctx->sp_fd[1] >= 0);
206*aa772005SRobert Watson 		return (spctx->sp_fd[1]);
207*aa772005SRobert Watson 	}
208*aa772005SRobert Watson 
209*aa772005SRobert Watson 	PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side);
210*aa772005SRobert Watson }
211*aa772005SRobert Watson 
212*aa772005SRobert Watson static void
sp_close(void * ctx)213*aa772005SRobert Watson sp_close(void *ctx)
214*aa772005SRobert Watson {
215*aa772005SRobert Watson 	struct sp_ctx *spctx = ctx;
216*aa772005SRobert Watson 
217*aa772005SRobert Watson 	PJDLOG_ASSERT(spctx != NULL);
218*aa772005SRobert Watson 	PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC);
219*aa772005SRobert Watson 
220*aa772005SRobert Watson 	switch (spctx->sp_side) {
221*aa772005SRobert Watson 	case SP_SIDE_UNDEF:
222*aa772005SRobert Watson 		PJDLOG_ASSERT(spctx->sp_fd[0] >= 0);
223*aa772005SRobert Watson 		close(spctx->sp_fd[0]);
224*aa772005SRobert Watson 		spctx->sp_fd[0] = -1;
225*aa772005SRobert Watson 		PJDLOG_ASSERT(spctx->sp_fd[1] >= 0);
226*aa772005SRobert Watson 		close(spctx->sp_fd[1]);
227*aa772005SRobert Watson 		spctx->sp_fd[1] = -1;
228*aa772005SRobert Watson 		break;
229*aa772005SRobert Watson 	case SP_SIDE_CLIENT:
230*aa772005SRobert Watson 		PJDLOG_ASSERT(spctx->sp_fd[0] >= 0);
231*aa772005SRobert Watson 		close(spctx->sp_fd[0]);
232*aa772005SRobert Watson 		spctx->sp_fd[0] = -1;
233*aa772005SRobert Watson 		PJDLOG_ASSERT(spctx->sp_fd[1] == -1);
234*aa772005SRobert Watson 		break;
235*aa772005SRobert Watson 	case SP_SIDE_SERVER:
236*aa772005SRobert Watson 		PJDLOG_ASSERT(spctx->sp_fd[1] >= 0);
237*aa772005SRobert Watson 		close(spctx->sp_fd[1]);
238*aa772005SRobert Watson 		spctx->sp_fd[1] = -1;
239*aa772005SRobert Watson 		PJDLOG_ASSERT(spctx->sp_fd[0] == -1);
240*aa772005SRobert Watson 		break;
241*aa772005SRobert Watson 	default:
242*aa772005SRobert Watson 		PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side);
243*aa772005SRobert Watson 	}
244*aa772005SRobert Watson 
245*aa772005SRobert Watson 	spctx->sp_magic = 0;
246*aa772005SRobert Watson 	free(spctx);
247*aa772005SRobert Watson }
248*aa772005SRobert Watson 
249*aa772005SRobert Watson static struct proto sp_proto = {
250*aa772005SRobert Watson 	.prt_name = "socketpair",
251*aa772005SRobert Watson 	.prt_connect = sp_connect,
252*aa772005SRobert Watson 	.prt_wrap = sp_wrap,
253*aa772005SRobert Watson 	.prt_send = sp_send,
254*aa772005SRobert Watson 	.prt_recv = sp_recv,
255*aa772005SRobert Watson 	.prt_descriptor = sp_descriptor,
256*aa772005SRobert Watson 	.prt_close = sp_close
257*aa772005SRobert Watson };
258*aa772005SRobert Watson 
259*aa772005SRobert Watson static __constructor void
sp_ctor(void)260*aa772005SRobert Watson sp_ctor(void)
261*aa772005SRobert Watson {
262*aa772005SRobert Watson 
263*aa772005SRobert Watson 	proto_register(&sp_proto, false);
264*aa772005SRobert Watson }
265