132115b10SPawel Jakub Dawidek /*- 232115b10SPawel Jakub Dawidek * Copyright (c) 2009-2010 The FreeBSD Foundation 332115b10SPawel Jakub Dawidek * All rights reserved. 432115b10SPawel Jakub Dawidek * 532115b10SPawel Jakub Dawidek * This software was developed by Pawel Jakub Dawidek under sponsorship from 632115b10SPawel Jakub Dawidek * the FreeBSD Foundation. 732115b10SPawel Jakub Dawidek * 832115b10SPawel Jakub Dawidek * Redistribution and use in source and binary forms, with or without 932115b10SPawel Jakub Dawidek * modification, are permitted provided that the following conditions 1032115b10SPawel Jakub Dawidek * are met: 1132115b10SPawel Jakub Dawidek * 1. Redistributions of source code must retain the above copyright 1232115b10SPawel Jakub Dawidek * notice, this list of conditions and the following disclaimer. 1332115b10SPawel Jakub Dawidek * 2. Redistributions in binary form must reproduce the above copyright 1432115b10SPawel Jakub Dawidek * notice, this list of conditions and the following disclaimer in the 1532115b10SPawel Jakub Dawidek * documentation and/or other materials provided with the distribution. 1632115b10SPawel Jakub Dawidek * 1732115b10SPawel Jakub Dawidek * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 1832115b10SPawel Jakub Dawidek * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1932115b10SPawel Jakub Dawidek * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2032115b10SPawel Jakub Dawidek * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 2132115b10SPawel Jakub Dawidek * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2232115b10SPawel Jakub Dawidek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2332115b10SPawel Jakub Dawidek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2432115b10SPawel Jakub Dawidek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2532115b10SPawel Jakub Dawidek * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2632115b10SPawel Jakub Dawidek * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2732115b10SPawel Jakub Dawidek * SUCH DAMAGE. 2832115b10SPawel Jakub Dawidek */ 2932115b10SPawel Jakub Dawidek 3032115b10SPawel Jakub Dawidek #include <sys/cdefs.h> 3132115b10SPawel Jakub Dawidek __FBSDID("$FreeBSD$"); 3232115b10SPawel Jakub Dawidek 3332115b10SPawel Jakub Dawidek #include <sys/types.h> 3432115b10SPawel Jakub Dawidek #include <sys/socket.h> 3532115b10SPawel Jakub Dawidek 3632115b10SPawel Jakub Dawidek #include <assert.h> 3732115b10SPawel Jakub Dawidek #include <errno.h> 3832115b10SPawel Jakub Dawidek #include <stdbool.h> 3932115b10SPawel Jakub Dawidek #include <stdint.h> 4032115b10SPawel Jakub Dawidek #include <stdio.h> 4132115b10SPawel Jakub Dawidek #include <string.h> 4232115b10SPawel Jakub Dawidek #include <unistd.h> 4332115b10SPawel Jakub Dawidek 4432115b10SPawel Jakub Dawidek #include "hast.h" 4532115b10SPawel Jakub Dawidek #include "proto_impl.h" 4632115b10SPawel Jakub Dawidek 4732115b10SPawel Jakub Dawidek #define SP_CTX_MAGIC 0x50c3741 4832115b10SPawel Jakub Dawidek struct sp_ctx { 4932115b10SPawel Jakub Dawidek int sp_magic; 5032115b10SPawel Jakub Dawidek int sp_fd[2]; 5132115b10SPawel Jakub Dawidek int sp_side; 5232115b10SPawel Jakub Dawidek #define SP_SIDE_UNDEF 0 5332115b10SPawel Jakub Dawidek #define SP_SIDE_CLIENT 1 5432115b10SPawel Jakub Dawidek #define SP_SIDE_SERVER 2 5532115b10SPawel Jakub Dawidek }; 5632115b10SPawel Jakub Dawidek 5732115b10SPawel Jakub Dawidek static void sp_close(void *ctx); 5832115b10SPawel Jakub Dawidek 5932115b10SPawel Jakub Dawidek static int 6032115b10SPawel Jakub Dawidek sp_client(const char *addr, void **ctxp) 6132115b10SPawel Jakub Dawidek { 6232115b10SPawel Jakub Dawidek struct sp_ctx *spctx; 6332115b10SPawel Jakub Dawidek int ret; 6432115b10SPawel Jakub Dawidek 6532115b10SPawel Jakub Dawidek if (strcmp(addr, "socketpair://") != 0) 6632115b10SPawel Jakub Dawidek return (-1); 6732115b10SPawel Jakub Dawidek 6832115b10SPawel Jakub Dawidek spctx = malloc(sizeof(*spctx)); 6932115b10SPawel Jakub Dawidek if (spctx == NULL) 7032115b10SPawel Jakub Dawidek return (errno); 7132115b10SPawel Jakub Dawidek 7232115b10SPawel Jakub Dawidek if (socketpair(PF_UNIX, SOCK_STREAM, 0, spctx->sp_fd) < 0) { 7332115b10SPawel Jakub Dawidek ret = errno; 7432115b10SPawel Jakub Dawidek free(spctx); 7532115b10SPawel Jakub Dawidek return (ret); 7632115b10SPawel Jakub Dawidek } 7732115b10SPawel Jakub Dawidek 7832115b10SPawel Jakub Dawidek spctx->sp_side = SP_SIDE_UNDEF; 7932115b10SPawel Jakub Dawidek spctx->sp_magic = SP_CTX_MAGIC; 8032115b10SPawel Jakub Dawidek *ctxp = spctx; 8132115b10SPawel Jakub Dawidek 8232115b10SPawel Jakub Dawidek return (0); 8332115b10SPawel Jakub Dawidek } 8432115b10SPawel Jakub Dawidek 8532115b10SPawel Jakub Dawidek static int 8632115b10SPawel Jakub Dawidek sp_connect(void *ctx __unused) 8732115b10SPawel Jakub Dawidek { 8832115b10SPawel Jakub Dawidek 8932115b10SPawel Jakub Dawidek assert(!"proto_connect() not supported on socketpairs"); 9032115b10SPawel Jakub Dawidek abort(); 9132115b10SPawel Jakub Dawidek } 9232115b10SPawel Jakub Dawidek 9332115b10SPawel Jakub Dawidek static int 942e1facf9SPawel Jakub Dawidek sp_server(const char *addr, void **ctxp __unused) 9532115b10SPawel Jakub Dawidek { 9632115b10SPawel Jakub Dawidek 972e1facf9SPawel Jakub Dawidek if (strcmp(addr, "socketpair://") != 0) 982e1facf9SPawel Jakub Dawidek return (-1); 992e1facf9SPawel Jakub Dawidek 10032115b10SPawel Jakub Dawidek assert(!"proto_server() not supported on socketpairs"); 10132115b10SPawel Jakub Dawidek abort(); 10232115b10SPawel Jakub Dawidek } 10332115b10SPawel Jakub Dawidek 10432115b10SPawel Jakub Dawidek static int 10532115b10SPawel Jakub Dawidek sp_accept(void *ctx __unused, void **newctxp __unused) 10632115b10SPawel Jakub Dawidek { 10732115b10SPawel Jakub Dawidek 10832115b10SPawel Jakub Dawidek assert(!"proto_server() not supported on socketpairs"); 10932115b10SPawel Jakub Dawidek abort(); 11032115b10SPawel Jakub Dawidek } 11132115b10SPawel Jakub Dawidek 11232115b10SPawel Jakub Dawidek static int 11332115b10SPawel Jakub Dawidek sp_send(void *ctx, const unsigned char *data, size_t size) 11432115b10SPawel Jakub Dawidek { 11532115b10SPawel Jakub Dawidek struct sp_ctx *spctx = ctx; 11632115b10SPawel Jakub Dawidek int fd; 11732115b10SPawel Jakub Dawidek 11832115b10SPawel Jakub Dawidek assert(spctx != NULL); 11932115b10SPawel Jakub Dawidek assert(spctx->sp_magic == SP_CTX_MAGIC); 12032115b10SPawel Jakub Dawidek 12132115b10SPawel Jakub Dawidek switch (spctx->sp_side) { 12232115b10SPawel Jakub Dawidek case SP_SIDE_UNDEF: 12332115b10SPawel Jakub Dawidek /* 12432115b10SPawel Jakub Dawidek * If the first operation done by the caller is proto_send(), 12532115b10SPawel Jakub Dawidek * we assume this the client. 12632115b10SPawel Jakub Dawidek */ 12732115b10SPawel Jakub Dawidek /* FALLTHROUGH */ 12832115b10SPawel Jakub Dawidek spctx->sp_side = SP_SIDE_CLIENT; 12932115b10SPawel Jakub Dawidek /* Close other end. */ 13032115b10SPawel Jakub Dawidek close(spctx->sp_fd[1]); 13132115b10SPawel Jakub Dawidek case SP_SIDE_CLIENT: 13232115b10SPawel Jakub Dawidek assert(spctx->sp_fd[0] >= 0); 13332115b10SPawel Jakub Dawidek fd = spctx->sp_fd[0]; 13432115b10SPawel Jakub Dawidek break; 13532115b10SPawel Jakub Dawidek case SP_SIDE_SERVER: 13632115b10SPawel Jakub Dawidek assert(spctx->sp_fd[1] >= 0); 13732115b10SPawel Jakub Dawidek fd = spctx->sp_fd[1]; 13832115b10SPawel Jakub Dawidek break; 13932115b10SPawel Jakub Dawidek default: 14032115b10SPawel Jakub Dawidek abort(); 14132115b10SPawel Jakub Dawidek } 14232115b10SPawel Jakub Dawidek 143*eea2deaaSPawel Jakub Dawidek /* Someone is just trying to decide about side. */ 144*eea2deaaSPawel Jakub Dawidek if (data == NULL) 145*eea2deaaSPawel Jakub Dawidek return (0); 146*eea2deaaSPawel Jakub Dawidek 14732115b10SPawel Jakub Dawidek return (proto_common_send(fd, data, size)); 14832115b10SPawel Jakub Dawidek } 14932115b10SPawel Jakub Dawidek 15032115b10SPawel Jakub Dawidek static int 15132115b10SPawel Jakub Dawidek sp_recv(void *ctx, unsigned char *data, size_t size) 15232115b10SPawel Jakub Dawidek { 15332115b10SPawel Jakub Dawidek struct sp_ctx *spctx = ctx; 15432115b10SPawel Jakub Dawidek int fd; 15532115b10SPawel Jakub Dawidek 15632115b10SPawel Jakub Dawidek assert(spctx != NULL); 15732115b10SPawel Jakub Dawidek assert(spctx->sp_magic == SP_CTX_MAGIC); 15832115b10SPawel Jakub Dawidek 15932115b10SPawel Jakub Dawidek switch (spctx->sp_side) { 16032115b10SPawel Jakub Dawidek case SP_SIDE_UNDEF: 16132115b10SPawel Jakub Dawidek /* 16232115b10SPawel Jakub Dawidek * If the first operation done by the caller is proto_recv(), 16332115b10SPawel Jakub Dawidek * we assume this the server. 16432115b10SPawel Jakub Dawidek */ 16532115b10SPawel Jakub Dawidek /* FALLTHROUGH */ 16632115b10SPawel Jakub Dawidek spctx->sp_side = SP_SIDE_SERVER; 16732115b10SPawel Jakub Dawidek /* Close other end. */ 16832115b10SPawel Jakub Dawidek close(spctx->sp_fd[0]); 16932115b10SPawel Jakub Dawidek case SP_SIDE_SERVER: 17032115b10SPawel Jakub Dawidek assert(spctx->sp_fd[1] >= 0); 17132115b10SPawel Jakub Dawidek fd = spctx->sp_fd[1]; 17232115b10SPawel Jakub Dawidek break; 17332115b10SPawel Jakub Dawidek case SP_SIDE_CLIENT: 17432115b10SPawel Jakub Dawidek assert(spctx->sp_fd[0] >= 0); 17532115b10SPawel Jakub Dawidek fd = spctx->sp_fd[0]; 17632115b10SPawel Jakub Dawidek break; 17732115b10SPawel Jakub Dawidek default: 17832115b10SPawel Jakub Dawidek abort(); 17932115b10SPawel Jakub Dawidek } 18032115b10SPawel Jakub Dawidek 181*eea2deaaSPawel Jakub Dawidek /* Someone is just trying to decide about side. */ 182*eea2deaaSPawel Jakub Dawidek if (data == NULL) 183*eea2deaaSPawel Jakub Dawidek return (0); 184*eea2deaaSPawel Jakub Dawidek 18532115b10SPawel Jakub Dawidek return (proto_common_recv(fd, data, size)); 18632115b10SPawel Jakub Dawidek } 18732115b10SPawel Jakub Dawidek 18832115b10SPawel Jakub Dawidek static int 18932115b10SPawel Jakub Dawidek sp_descriptor(const void *ctx) 19032115b10SPawel Jakub Dawidek { 19132115b10SPawel Jakub Dawidek const struct sp_ctx *spctx = ctx; 19232115b10SPawel Jakub Dawidek 19332115b10SPawel Jakub Dawidek assert(spctx != NULL); 19432115b10SPawel Jakub Dawidek assert(spctx->sp_magic == SP_CTX_MAGIC); 19532115b10SPawel Jakub Dawidek assert(spctx->sp_side == SP_SIDE_CLIENT || 19632115b10SPawel Jakub Dawidek spctx->sp_side == SP_SIDE_SERVER); 19732115b10SPawel Jakub Dawidek 19832115b10SPawel Jakub Dawidek switch (spctx->sp_side) { 19932115b10SPawel Jakub Dawidek case SP_SIDE_CLIENT: 20032115b10SPawel Jakub Dawidek assert(spctx->sp_fd[0] >= 0); 20132115b10SPawel Jakub Dawidek return (spctx->sp_fd[0]); 20232115b10SPawel Jakub Dawidek case SP_SIDE_SERVER: 20332115b10SPawel Jakub Dawidek assert(spctx->sp_fd[1] >= 0); 20432115b10SPawel Jakub Dawidek return (spctx->sp_fd[1]); 20532115b10SPawel Jakub Dawidek } 20632115b10SPawel Jakub Dawidek 20732115b10SPawel Jakub Dawidek abort(); 20832115b10SPawel Jakub Dawidek } 20932115b10SPawel Jakub Dawidek 21032115b10SPawel Jakub Dawidek static bool 21132115b10SPawel Jakub Dawidek sp_address_match(const void *ctx __unused, const char *addr __unused) 21232115b10SPawel Jakub Dawidek { 21332115b10SPawel Jakub Dawidek 21432115b10SPawel Jakub Dawidek assert(!"proto_address_match() not supported on socketpairs"); 21532115b10SPawel Jakub Dawidek abort(); 21632115b10SPawel Jakub Dawidek } 21732115b10SPawel Jakub Dawidek 21832115b10SPawel Jakub Dawidek static void 21932115b10SPawel Jakub Dawidek sp_local_address(const void *ctx __unused, char *addr __unused, 22032115b10SPawel Jakub Dawidek size_t size __unused) 22132115b10SPawel Jakub Dawidek { 22232115b10SPawel Jakub Dawidek 22332115b10SPawel Jakub Dawidek assert(!"proto_local_address() not supported on socketpairs"); 22432115b10SPawel Jakub Dawidek abort(); 22532115b10SPawel Jakub Dawidek } 22632115b10SPawel Jakub Dawidek 22732115b10SPawel Jakub Dawidek static void 22832115b10SPawel Jakub Dawidek sp_remote_address(const void *ctx __unused, char *addr __unused, 22932115b10SPawel Jakub Dawidek size_t size __unused) 23032115b10SPawel Jakub Dawidek { 23132115b10SPawel Jakub Dawidek 23232115b10SPawel Jakub Dawidek assert(!"proto_remote_address() not supported on socketpairs"); 23332115b10SPawel Jakub Dawidek abort(); 23432115b10SPawel Jakub Dawidek } 23532115b10SPawel Jakub Dawidek 23632115b10SPawel Jakub Dawidek static void 23732115b10SPawel Jakub Dawidek sp_close(void *ctx) 23832115b10SPawel Jakub Dawidek { 23932115b10SPawel Jakub Dawidek struct sp_ctx *spctx = ctx; 24032115b10SPawel Jakub Dawidek 24132115b10SPawel Jakub Dawidek assert(spctx != NULL); 24232115b10SPawel Jakub Dawidek assert(spctx->sp_magic == SP_CTX_MAGIC); 24332115b10SPawel Jakub Dawidek 24432115b10SPawel Jakub Dawidek switch (spctx->sp_side) { 24532115b10SPawel Jakub Dawidek case SP_SIDE_UNDEF: 24632115b10SPawel Jakub Dawidek close(spctx->sp_fd[0]); 24732115b10SPawel Jakub Dawidek close(spctx->sp_fd[1]); 24832115b10SPawel Jakub Dawidek break; 24932115b10SPawel Jakub Dawidek case SP_SIDE_CLIENT: 25032115b10SPawel Jakub Dawidek close(spctx->sp_fd[0]); 25132115b10SPawel Jakub Dawidek break; 25232115b10SPawel Jakub Dawidek case SP_SIDE_SERVER: 25332115b10SPawel Jakub Dawidek close(spctx->sp_fd[1]); 25432115b10SPawel Jakub Dawidek break; 25532115b10SPawel Jakub Dawidek default: 25632115b10SPawel Jakub Dawidek abort(); 25732115b10SPawel Jakub Dawidek } 25832115b10SPawel Jakub Dawidek 25932115b10SPawel Jakub Dawidek spctx->sp_magic = 0; 26032115b10SPawel Jakub Dawidek free(spctx); 26132115b10SPawel Jakub Dawidek } 26232115b10SPawel Jakub Dawidek 26332115b10SPawel Jakub Dawidek static struct hast_proto sp_proto = { 26432115b10SPawel Jakub Dawidek .hp_name = "socketpair", 26532115b10SPawel Jakub Dawidek .hp_client = sp_client, 26632115b10SPawel Jakub Dawidek .hp_connect = sp_connect, 26732115b10SPawel Jakub Dawidek .hp_server = sp_server, 26832115b10SPawel Jakub Dawidek .hp_accept = sp_accept, 26932115b10SPawel Jakub Dawidek .hp_send = sp_send, 27032115b10SPawel Jakub Dawidek .hp_recv = sp_recv, 27132115b10SPawel Jakub Dawidek .hp_descriptor = sp_descriptor, 27232115b10SPawel Jakub Dawidek .hp_address_match = sp_address_match, 27332115b10SPawel Jakub Dawidek .hp_local_address = sp_local_address, 27432115b10SPawel Jakub Dawidek .hp_remote_address = sp_remote_address, 27532115b10SPawel Jakub Dawidek .hp_close = sp_close 27632115b10SPawel Jakub Dawidek }; 27732115b10SPawel Jakub Dawidek 27832115b10SPawel Jakub Dawidek static __constructor void 27932115b10SPawel Jakub Dawidek sp_ctor(void) 28032115b10SPawel Jakub Dawidek { 28132115b10SPawel Jakub Dawidek 28250692f84SPawel Jakub Dawidek proto_register(&sp_proto, false); 28332115b10SPawel Jakub Dawidek } 284