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
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
33 #include <sys/types.h>
34 #include <sys/socket.h>
45 #include "proto_impl.h"
47 #define SP_CTX_MAGIC 0x50c3741
52 #define SP_SIDE_UNDEF 0
53 #define SP_SIDE_CLIENT 1
54 #define SP_SIDE_SERVER 2
57 static void sp_close(void *ctx);
60 sp_client(const char *addr, void **ctxp)
65 if (strcmp(addr, "socketpair://") != 0)
68 spctx = malloc(sizeof(*spctx));
72 if (socketpair(PF_UNIX, SOCK_STREAM, 0, spctx->sp_fd) < 0) {
78 spctx->sp_side = SP_SIDE_UNDEF;
79 spctx->sp_magic = SP_CTX_MAGIC;
86 sp_connect(void *ctx __unused)
89 assert(!"proto_connect() not supported on socketpairs");
94 sp_server(const char *addr, void **ctxp __unused)
97 if (strcmp(addr, "socketpair://") != 0)
100 assert(!"proto_server() not supported on socketpairs");
105 sp_accept(void *ctx __unused, void **newctxp __unused)
108 assert(!"proto_server() not supported on socketpairs");
113 sp_send(void *ctx, const unsigned char *data, size_t size)
115 struct sp_ctx *spctx = ctx;
118 assert(spctx != NULL);
119 assert(spctx->sp_magic == SP_CTX_MAGIC);
121 switch (spctx->sp_side) {
124 * If the first operation done by the caller is proto_send(),
125 * we assume this the client.
128 spctx->sp_side = SP_SIDE_CLIENT;
129 /* Close other end. */
130 close(spctx->sp_fd[1]);
132 assert(spctx->sp_fd[0] >= 0);
133 fd = spctx->sp_fd[0];
136 assert(spctx->sp_fd[1] >= 0);
137 fd = spctx->sp_fd[1];
143 /* Someone is just trying to decide about side. */
147 return (proto_common_send(fd, data, size));
151 sp_recv(void *ctx, unsigned char *data, size_t size)
153 struct sp_ctx *spctx = ctx;
156 assert(spctx != NULL);
157 assert(spctx->sp_magic == SP_CTX_MAGIC);
159 switch (spctx->sp_side) {
162 * If the first operation done by the caller is proto_recv(),
163 * we assume this the server.
166 spctx->sp_side = SP_SIDE_SERVER;
167 /* Close other end. */
168 close(spctx->sp_fd[0]);
170 assert(spctx->sp_fd[1] >= 0);
171 fd = spctx->sp_fd[1];
174 assert(spctx->sp_fd[0] >= 0);
175 fd = spctx->sp_fd[0];
181 /* Someone is just trying to decide about side. */
185 return (proto_common_recv(fd, data, size));
189 sp_descriptor(const void *ctx)
191 const struct sp_ctx *spctx = ctx;
193 assert(spctx != NULL);
194 assert(spctx->sp_magic == SP_CTX_MAGIC);
195 assert(spctx->sp_side == SP_SIDE_CLIENT ||
196 spctx->sp_side == SP_SIDE_SERVER);
198 switch (spctx->sp_side) {
200 assert(spctx->sp_fd[0] >= 0);
201 return (spctx->sp_fd[0]);
203 assert(spctx->sp_fd[1] >= 0);
204 return (spctx->sp_fd[1]);
211 sp_address_match(const void *ctx __unused, const char *addr __unused)
214 assert(!"proto_address_match() not supported on socketpairs");
219 sp_local_address(const void *ctx __unused, char *addr __unused,
220 size_t size __unused)
223 assert(!"proto_local_address() not supported on socketpairs");
228 sp_remote_address(const void *ctx __unused, char *addr __unused,
229 size_t size __unused)
232 assert(!"proto_remote_address() not supported on socketpairs");
239 struct sp_ctx *spctx = ctx;
241 assert(spctx != NULL);
242 assert(spctx->sp_magic == SP_CTX_MAGIC);
244 switch (spctx->sp_side) {
246 close(spctx->sp_fd[0]);
247 close(spctx->sp_fd[1]);
250 close(spctx->sp_fd[0]);
253 close(spctx->sp_fd[1]);
263 static struct hast_proto sp_proto = {
264 .hp_name = "socketpair",
265 .hp_client = sp_client,
266 .hp_connect = sp_connect,
267 .hp_server = sp_server,
268 .hp_accept = sp_accept,
271 .hp_descriptor = sp_descriptor,
272 .hp_address_match = sp_address_match,
273 .hp_local_address = sp_local_address,
274 .hp_remote_address = sp_remote_address,
278 static __constructor void
282 proto_register(&sp_proto, false);