proto_socketpair.c revision 204076
11539Srgrimes/*-
21539Srgrimes * Copyright (c) 2009-2010 The FreeBSD Foundation
31539Srgrimes * All rights reserved.
41539Srgrimes *
51539Srgrimes * This software was developed by Pawel Jakub Dawidek under sponsorship from
61539Srgrimes * the FreeBSD Foundation.
71539Srgrimes *
81539Srgrimes * Redistribution and use in source and binary forms, with or without
91539Srgrimes * modification, are permitted provided that the following conditions
101539Srgrimes * are met:
111539Srgrimes * 1. Redistributions of source code must retain the above copyright
121539Srgrimes *    notice, this list of conditions and the following disclaimer.
131539Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
141539Srgrimes *    notice, this list of conditions and the following disclaimer in the
151539Srgrimes *    documentation and/or other materials provided with the distribution.
161539Srgrimes *
171539Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
181539Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
191539Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
201539Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
211539Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
221539Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
231539Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
241539Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
251539Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
261539Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
271539Srgrimes * SUCH DAMAGE.
281539Srgrimes */
291539Srgrimes
301539Srgrimes#include <sys/cdefs.h>
311539Srgrimes__FBSDID("$FreeBSD: head/sbin/hastd/proto_socketpair.c 204076 2010-02-18 23:16:19Z pjd $");
321539Srgrimes
331539Srgrimes#include <sys/types.h>
341539Srgrimes#include <sys/socket.h>
351539Srgrimes
3623655Speter#include <assert.h>
3750473Speter#include <errno.h>
381539Srgrimes#include <stdbool.h>
391539Srgrimes#include <stdint.h>
401539Srgrimes#include <stdio.h>
411539Srgrimes#include <string.h>
421539Srgrimes#include <unistd.h>
431539Srgrimes
4424897Sbde#include "hast.h"
451539Srgrimes#include "proto_impl.h"
461539Srgrimes
471539Srgrimes#define	SP_CTX_MAGIC	0x50c3741
481539Srgrimesstruct sp_ctx {
491539Srgrimes	int			sp_magic;
501539Srgrimes	int			sp_fd[2];
511539Srgrimes	int			sp_side;
521539Srgrimes#define	SP_SIDE_UNDEF		0
531539Srgrimes#define	SP_SIDE_CLIENT		1
541539Srgrimes#define	SP_SIDE_SERVER		2
5524897Sbde};
561539Srgrimes
571539Srgrimesstatic void sp_close(void *ctx);
581539Srgrimes
591539Srgrimesstatic int
601539Srgrimessp_client(const char *addr, void **ctxp)
611539Srgrimes{
621539Srgrimes	struct sp_ctx *spctx;
631539Srgrimes	int ret;
641539Srgrimes
651539Srgrimes	if (strcmp(addr, "socketpair://") != 0)
661539Srgrimes		return (-1);
671539Srgrimes
681539Srgrimes	spctx = malloc(sizeof(*spctx));
691539Srgrimes	if (spctx == NULL)
701539Srgrimes		return (errno);
7172529Simp
7273254Sdeischen	if (socketpair(PF_UNIX, SOCK_STREAM, 0, spctx->sp_fd) < 0) {
7372529Simp		ret = errno;
741539Srgrimes		free(spctx);
751539Srgrimes		return (ret);
761539Srgrimes	}
771539Srgrimes
781539Srgrimes	spctx->sp_side = SP_SIDE_UNDEF;
791539Srgrimes	spctx->sp_magic = SP_CTX_MAGIC;
801539Srgrimes	*ctxp = spctx;
811539Srgrimes
821539Srgrimes	return (0);
831539Srgrimes}
841539Srgrimes
851539Srgrimesstatic int
861539Srgrimessp_connect(void *ctx __unused)
871539Srgrimes{
881539Srgrimes
891539Srgrimes	assert(!"proto_connect() not supported on socketpairs");
901539Srgrimes	abort();
911539Srgrimes}
921539Srgrimes
931539Srgrimesstatic int
941539Srgrimessp_server(const char *addr __unused, void **ctxp __unused)
951539Srgrimes{
961539Srgrimes
971539Srgrimes	assert(!"proto_server() not supported on socketpairs");
981539Srgrimes	abort();
991539Srgrimes}
1001539Srgrimes
1011539Srgrimesstatic int
1021539Srgrimessp_accept(void *ctx __unused, void **newctxp __unused)
1031539Srgrimes{
1041539Srgrimes
1051539Srgrimes	assert(!"proto_server() not supported on socketpairs");
1061539Srgrimes	abort();
1071539Srgrimes}
1081539Srgrimes
1091539Srgrimesstatic int
1101539Srgrimessp_send(void *ctx, const unsigned char *data, size_t size)
11193032Simp{
11293032Simp	struct sp_ctx *spctx = ctx;
11393032Simp	int fd;
11493032Simp
1151539Srgrimes	assert(spctx != NULL);
1161539Srgrimes	assert(spctx->sp_magic == SP_CTX_MAGIC);
1171539Srgrimes
11872529Simp	switch (spctx->sp_side) {
1191539Srgrimes	case SP_SIDE_UNDEF:
1201539Srgrimes		/*
1211539Srgrimes		 * If the first operation done by the caller is proto_send(),
1221539Srgrimes		 * we assume this the client.
1231539Srgrimes		 */
1241539Srgrimes		/* FALLTHROUGH */
1251539Srgrimes		spctx->sp_side = SP_SIDE_CLIENT;
1261539Srgrimes		/* Close other end. */
1271539Srgrimes		close(spctx->sp_fd[1]);
1281539Srgrimes	case SP_SIDE_CLIENT:
1291539Srgrimes		assert(spctx->sp_fd[0] >= 0);
1301539Srgrimes		fd = spctx->sp_fd[0];
1311539Srgrimes		break;
1321539Srgrimes	case SP_SIDE_SERVER:
1331539Srgrimes		assert(spctx->sp_fd[1] >= 0);
13472529Simp		fd = spctx->sp_fd[1];
13581600Speter		break;
13681600Speter	default:
13781600Speter		abort();
1381539Srgrimes	}
1391539Srgrimes
1401539Srgrimes	return (proto_common_send(fd, data, size));
1411539Srgrimes}
1421539Srgrimes
1431539Srgrimesstatic int
1441539Srgrimessp_recv(void *ctx, unsigned char *data, size_t size)
1451539Srgrimes{
1461539Srgrimes	struct sp_ctx *spctx = ctx;
1471539Srgrimes	int fd;
1481539Srgrimes
1491539Srgrimes	assert(spctx != NULL);
1501539Srgrimes	assert(spctx->sp_magic == SP_CTX_MAGIC);
15113771Smpp
15213771Smpp	switch (spctx->sp_side) {
1531539Srgrimes	case SP_SIDE_UNDEF:
1541539Srgrimes		/*
15537489Speter		 * If the first operation done by the caller is proto_recv(),
15672372Sdeischen		 * we assume this the server.
1571539Srgrimes		 */
1581539Srgrimes		/* FALLTHROUGH */
1591539Srgrimes		spctx->sp_side = SP_SIDE_SERVER;
1601539Srgrimes		/* Close other end. */
1611539Srgrimes		close(spctx->sp_fd[0]);
1621539Srgrimes	case SP_SIDE_SERVER:
1631539Srgrimes		assert(spctx->sp_fd[1] >= 0);
1641539Srgrimes		fd = spctx->sp_fd[1];
1651539Srgrimes		break;
1661539Srgrimes	case SP_SIDE_CLIENT:
1671539Srgrimes		assert(spctx->sp_fd[0] >= 0);
1681539Srgrimes		fd = spctx->sp_fd[0];
1691539Srgrimes		break;
1701539Srgrimes	default:
1711539Srgrimes		abort();
1721539Srgrimes	}
1731539Srgrimes
1741539Srgrimes	return (proto_common_recv(fd, data, size));
1751539Srgrimes}
1761539Srgrimes
1771539Srgrimesstatic int
1781539Srgrimessp_descriptor(const void *ctx)
1791539Srgrimes{
1801539Srgrimes	const struct sp_ctx *spctx = ctx;
1811539Srgrimes
1821539Srgrimes	assert(spctx != NULL);
1831539Srgrimes	assert(spctx->sp_magic == SP_CTX_MAGIC);
184100133Swollman	assert(spctx->sp_side == SP_SIDE_CLIENT ||
1851539Srgrimes	    spctx->sp_side == SP_SIDE_SERVER);
1861539Srgrimes
1871539Srgrimes	switch (spctx->sp_side) {
1881539Srgrimes	case SP_SIDE_CLIENT:
1891539Srgrimes		assert(spctx->sp_fd[0] >= 0);
1901539Srgrimes		return (spctx->sp_fd[0]);
1911539Srgrimes	case SP_SIDE_SERVER:
1921539Srgrimes		assert(spctx->sp_fd[1] >= 0);
1931539Srgrimes		return (spctx->sp_fd[1]);
1941539Srgrimes	}
1951539Srgrimes
1961539Srgrimes	abort();
1971539Srgrimes}
1981539Srgrimes
1991539Srgrimesstatic bool
20081600Spetersp_address_match(const void *ctx __unused, const char *addr __unused)
20183712Speter{
20272529Simp
20372529Simp	assert(!"proto_address_match() not supported on socketpairs");
20472529Simp	abort();
20581600Speter}
20681600Speter
20781600Speterstatic void
20881600Spetersp_local_address(const void *ctx __unused, char *addr __unused,
20981600Speter    size_t size __unused)
2101539Srgrimes{
211100133Swollman
2121539Srgrimes	assert(!"proto_local_address() not supported on socketpairs");
2131539Srgrimes	abort();
2141539Srgrimes}
21593032Simp
21693032Simpstatic void
21793032Simpsp_remote_address(const void *ctx __unused, char *addr __unused,
21893032Simp    size_t size __unused)
21993032Simp{
22093032Simp
22193032Simp	assert(!"proto_remote_address() not supported on socketpairs");
22293032Simp	abort();
22393032Simp}
22493032Simp
22593032Simpstatic void
22693032Simpsp_close(void *ctx)
22793032Simp{
22893032Simp	struct sp_ctx *spctx = ctx;
22993032Simp
23093032Simp	assert(spctx != NULL);
23193032Simp	assert(spctx->sp_magic == SP_CTX_MAGIC);
23293032Simp
23393032Simp	switch (spctx->sp_side) {
23493032Simp	case SP_SIDE_UNDEF:
23593032Simp		close(spctx->sp_fd[0]);
23693032Simp		close(spctx->sp_fd[1]);
23793032Simp		break;
23893032Simp	case SP_SIDE_CLIENT:
23993032Simp		close(spctx->sp_fd[0]);
24093032Simp		break;
24193032Simp	case SP_SIDE_SERVER:
24293032Simp		close(spctx->sp_fd[1]);
24393032Simp		break;
24493032Simp	default:
24593032Simp		abort();
24693032Simp	}
24793032Simp
24893032Simp	spctx->sp_magic = 0;
24993032Simp	free(spctx);
25093032Simp}
25193032Simp
25293032Simpstatic struct hast_proto sp_proto = {
25393032Simp	.hp_name = "socketpair",
25493032Simp	.hp_client = sp_client,
25593032Simp	.hp_connect = sp_connect,
2561539Srgrimes	.hp_server = sp_server,
257100133Swollman	.hp_accept = sp_accept,
258100133Swollman	.hp_send = sp_send,
259100133Swollman	.hp_recv = sp_recv,
260100133Swollman	.hp_descriptor = sp_descriptor,
261100133Swollman	.hp_address_match = sp_address_match,
262100133Swollman	.hp_local_address = sp_local_address,
2631539Srgrimes	.hp_remote_address = sp_remote_address,
264100133Swollman	.hp_close = sp_close
2651539Srgrimes};
266100133Swollman
26719211Swoschstatic __constructor void
26823260Sachesp_ctor(void)
2691539Srgrimes{
27019211Swosch
27119211Swosch	proto_register(&sp_proto);
27293032Simp}
27393032Simp