2 * Copyright (c) 2009-2010 The FreeBSD Foundation
5 * This software was developed by Pawel Jakub Dawidek under sponsorship from
6 * the FreeBSD Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/proto_socketpair.c#1 $
32 #include <sys/types.h>
33 #include <sys/socket.h>
43 #include "proto_impl.h"
45 #define SP_CTX_MAGIC 0x50c3741
50 #define SP_SIDE_UNDEF 0
51 #define SP_SIDE_CLIENT 1
52 #define SP_SIDE_SERVER 2
55 static void sp_close(void *ctx);
58 sp_connect(const char *srcaddr, const char *dstaddr, int timeout, void **ctxp)
63 PJDLOG_ASSERT(dstaddr != NULL);
64 PJDLOG_ASSERT(timeout >= -1);
66 if (strcmp(dstaddr, "socketpair://") != 0)
69 PJDLOG_ASSERT(srcaddr == NULL);
71 spctx = malloc(sizeof(*spctx));
75 if (socketpair(PF_UNIX, SOCK_STREAM, 0, spctx->sp_fd) == -1) {
81 spctx->sp_side = SP_SIDE_UNDEF;
82 spctx->sp_magic = SP_CTX_MAGIC;
89 sp_wrap(int fd, bool client, void **ctxp)
93 PJDLOG_ASSERT(fd >= 0);
95 spctx = malloc(sizeof(*spctx));
100 spctx->sp_side = SP_SIDE_CLIENT;
101 spctx->sp_fd[0] = fd;
102 spctx->sp_fd[1] = -1;
104 spctx->sp_side = SP_SIDE_SERVER;
105 spctx->sp_fd[0] = -1;
106 spctx->sp_fd[1] = fd;
108 spctx->sp_magic = SP_CTX_MAGIC;
115 sp_send(void *ctx, const unsigned char *data, size_t size, int fd)
117 struct sp_ctx *spctx = ctx;
120 PJDLOG_ASSERT(spctx != NULL);
121 PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC);
123 switch (spctx->sp_side) {
126 * If the first operation done by the caller is proto_send(),
127 * we assume this is the client.
130 spctx->sp_side = SP_SIDE_CLIENT;
131 /* Close other end. */
132 close(spctx->sp_fd[1]);
133 spctx->sp_fd[1] = -1;
135 PJDLOG_ASSERT(spctx->sp_fd[0] >= 0);
136 sock = spctx->sp_fd[0];
139 PJDLOG_ASSERT(spctx->sp_fd[1] >= 0);
140 sock = spctx->sp_fd[1];
143 PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side);
146 /* Someone is just trying to decide about side. */
150 return (proto_common_send(sock, data, size, fd));
154 sp_recv(void *ctx, unsigned char *data, size_t size, int *fdp)
156 struct sp_ctx *spctx = ctx;
159 PJDLOG_ASSERT(spctx != NULL);
160 PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC);
162 switch (spctx->sp_side) {
165 * If the first operation done by the caller is proto_recv(),
166 * we assume this is the server.
169 spctx->sp_side = SP_SIDE_SERVER;
170 /* Close other end. */
171 close(spctx->sp_fd[0]);
172 spctx->sp_fd[0] = -1;
174 PJDLOG_ASSERT(spctx->sp_fd[1] >= 0);
175 sock = spctx->sp_fd[1];
178 PJDLOG_ASSERT(spctx->sp_fd[0] >= 0);
179 sock = spctx->sp_fd[0];
182 PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side);
185 /* Someone is just trying to decide about side. */
189 return (proto_common_recv(sock, data, size, fdp));
193 sp_descriptor(const void *ctx)
195 const struct sp_ctx *spctx = ctx;
197 PJDLOG_ASSERT(spctx != NULL);
198 PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC);
199 PJDLOG_ASSERT(spctx->sp_side == SP_SIDE_CLIENT ||
200 spctx->sp_side == SP_SIDE_SERVER);
202 switch (spctx->sp_side) {
204 PJDLOG_ASSERT(spctx->sp_fd[0] >= 0);
205 return (spctx->sp_fd[0]);
207 PJDLOG_ASSERT(spctx->sp_fd[1] >= 0);
208 return (spctx->sp_fd[1]);
211 PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side);
217 struct sp_ctx *spctx = ctx;
219 PJDLOG_ASSERT(spctx != NULL);
220 PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC);
222 switch (spctx->sp_side) {
224 PJDLOG_ASSERT(spctx->sp_fd[0] >= 0);
225 close(spctx->sp_fd[0]);
226 spctx->sp_fd[0] = -1;
227 PJDLOG_ASSERT(spctx->sp_fd[1] >= 0);
228 close(spctx->sp_fd[1]);
229 spctx->sp_fd[1] = -1;
232 PJDLOG_ASSERT(spctx->sp_fd[0] >= 0);
233 close(spctx->sp_fd[0]);
234 spctx->sp_fd[0] = -1;
235 PJDLOG_ASSERT(spctx->sp_fd[1] == -1);
238 PJDLOG_ASSERT(spctx->sp_fd[1] >= 0);
239 close(spctx->sp_fd[1]);
240 spctx->sp_fd[1] = -1;
241 PJDLOG_ASSERT(spctx->sp_fd[0] == -1);
244 PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side);
251 static struct proto sp_proto = {
252 .prt_name = "socketpair",
253 .prt_connect = sp_connect,
257 .prt_descriptor = sp_descriptor,
258 .prt_close = sp_close
261 static __constructor void
265 proto_register(&sp_proto, false);