proto_socketpair.c revision 212036
1204076Spjd/*- 2204076Spjd * Copyright (c) 2009-2010 The FreeBSD Foundation 3204076Spjd * All rights reserved. 4204076Spjd * 5204076Spjd * This software was developed by Pawel Jakub Dawidek under sponsorship from 6204076Spjd * the FreeBSD Foundation. 7204076Spjd * 8204076Spjd * Redistribution and use in source and binary forms, with or without 9204076Spjd * modification, are permitted provided that the following conditions 10204076Spjd * are met: 11204076Spjd * 1. Redistributions of source code must retain the above copyright 12204076Spjd * notice, this list of conditions and the following disclaimer. 13204076Spjd * 2. Redistributions in binary form must reproduce the above copyright 14204076Spjd * notice, this list of conditions and the following disclaimer in the 15204076Spjd * documentation and/or other materials provided with the distribution. 16204076Spjd * 17204076Spjd * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 18204076Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19204076Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20204076Spjd * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 21204076Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22204076Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23204076Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24204076Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25204076Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26204076Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27204076Spjd * SUCH DAMAGE. 28204076Spjd */ 29204076Spjd 30204076Spjd#include <sys/cdefs.h> 31204076Spjd__FBSDID("$FreeBSD: head/sbin/hastd/proto_socketpair.c 212036 2010-08-30 23:16:45Z pjd $"); 32204076Spjd 33204076Spjd#include <sys/types.h> 34204076Spjd#include <sys/socket.h> 35204076Spjd 36204076Spjd#include <assert.h> 37204076Spjd#include <errno.h> 38204076Spjd#include <stdbool.h> 39204076Spjd#include <stdint.h> 40204076Spjd#include <stdio.h> 41204076Spjd#include <string.h> 42204076Spjd#include <unistd.h> 43204076Spjd 44204076Spjd#include "hast.h" 45204076Spjd#include "proto_impl.h" 46204076Spjd 47204076Spjd#define SP_CTX_MAGIC 0x50c3741 48204076Spjdstruct sp_ctx { 49204076Spjd int sp_magic; 50204076Spjd int sp_fd[2]; 51204076Spjd int sp_side; 52204076Spjd#define SP_SIDE_UNDEF 0 53204076Spjd#define SP_SIDE_CLIENT 1 54204076Spjd#define SP_SIDE_SERVER 2 55204076Spjd}; 56204076Spjd 57204076Spjdstatic void sp_close(void *ctx); 58204076Spjd 59204076Spjdstatic int 60204076Spjdsp_client(const char *addr, void **ctxp) 61204076Spjd{ 62204076Spjd struct sp_ctx *spctx; 63204076Spjd int ret; 64204076Spjd 65204076Spjd if (strcmp(addr, "socketpair://") != 0) 66204076Spjd return (-1); 67204076Spjd 68204076Spjd spctx = malloc(sizeof(*spctx)); 69204076Spjd if (spctx == NULL) 70204076Spjd return (errno); 71204076Spjd 72204076Spjd if (socketpair(PF_UNIX, SOCK_STREAM, 0, spctx->sp_fd) < 0) { 73204076Spjd ret = errno; 74204076Spjd free(spctx); 75204076Spjd return (ret); 76204076Spjd } 77204076Spjd 78204076Spjd spctx->sp_side = SP_SIDE_UNDEF; 79204076Spjd spctx->sp_magic = SP_CTX_MAGIC; 80204076Spjd *ctxp = spctx; 81204076Spjd 82204076Spjd return (0); 83204076Spjd} 84204076Spjd 85204076Spjdstatic int 86204076Spjdsp_connect(void *ctx __unused) 87204076Spjd{ 88204076Spjd 89204076Spjd assert(!"proto_connect() not supported on socketpairs"); 90204076Spjd abort(); 91204076Spjd} 92204076Spjd 93204076Spjdstatic int 94204177Spjdsp_server(const char *addr, void **ctxp __unused) 95204076Spjd{ 96204076Spjd 97204177Spjd if (strcmp(addr, "socketpair://") != 0) 98204177Spjd return (-1); 99204177Spjd 100204076Spjd assert(!"proto_server() not supported on socketpairs"); 101204076Spjd abort(); 102204076Spjd} 103204076Spjd 104204076Spjdstatic int 105204076Spjdsp_accept(void *ctx __unused, void **newctxp __unused) 106204076Spjd{ 107204076Spjd 108204076Spjd assert(!"proto_server() not supported on socketpairs"); 109204076Spjd abort(); 110204076Spjd} 111204076Spjd 112204076Spjdstatic int 113204076Spjdsp_send(void *ctx, const unsigned char *data, size_t size) 114204076Spjd{ 115204076Spjd struct sp_ctx *spctx = ctx; 116204076Spjd int fd; 117204076Spjd 118204076Spjd assert(spctx != NULL); 119204076Spjd assert(spctx->sp_magic == SP_CTX_MAGIC); 120204076Spjd 121204076Spjd switch (spctx->sp_side) { 122204076Spjd case SP_SIDE_UNDEF: 123204076Spjd /* 124204076Spjd * If the first operation done by the caller is proto_send(), 125204076Spjd * we assume this the client. 126204076Spjd */ 127204076Spjd /* FALLTHROUGH */ 128204076Spjd spctx->sp_side = SP_SIDE_CLIENT; 129204076Spjd /* Close other end. */ 130204076Spjd close(spctx->sp_fd[1]); 131204076Spjd case SP_SIDE_CLIENT: 132204076Spjd assert(spctx->sp_fd[0] >= 0); 133204076Spjd fd = spctx->sp_fd[0]; 134204076Spjd break; 135204076Spjd case SP_SIDE_SERVER: 136204076Spjd assert(spctx->sp_fd[1] >= 0); 137204076Spjd fd = spctx->sp_fd[1]; 138204076Spjd break; 139204076Spjd default: 140204076Spjd abort(); 141204076Spjd } 142204076Spjd 143212036Spjd /* Someone is just trying to decide about side. */ 144212036Spjd if (data == NULL) 145212036Spjd return (0); 146212036Spjd 147204076Spjd return (proto_common_send(fd, data, size)); 148204076Spjd} 149204076Spjd 150204076Spjdstatic int 151204076Spjdsp_recv(void *ctx, unsigned char *data, size_t size) 152204076Spjd{ 153204076Spjd struct sp_ctx *spctx = ctx; 154204076Spjd int fd; 155204076Spjd 156204076Spjd assert(spctx != NULL); 157204076Spjd assert(spctx->sp_magic == SP_CTX_MAGIC); 158204076Spjd 159204076Spjd switch (spctx->sp_side) { 160204076Spjd case SP_SIDE_UNDEF: 161204076Spjd /* 162204076Spjd * If the first operation done by the caller is proto_recv(), 163204076Spjd * we assume this the server. 164204076Spjd */ 165204076Spjd /* FALLTHROUGH */ 166204076Spjd spctx->sp_side = SP_SIDE_SERVER; 167204076Spjd /* Close other end. */ 168204076Spjd close(spctx->sp_fd[0]); 169204076Spjd case SP_SIDE_SERVER: 170204076Spjd assert(spctx->sp_fd[1] >= 0); 171204076Spjd fd = spctx->sp_fd[1]; 172204076Spjd break; 173204076Spjd case SP_SIDE_CLIENT: 174204076Spjd assert(spctx->sp_fd[0] >= 0); 175204076Spjd fd = spctx->sp_fd[0]; 176204076Spjd break; 177204076Spjd default: 178204076Spjd abort(); 179204076Spjd } 180204076Spjd 181212036Spjd /* Someone is just trying to decide about side. */ 182212036Spjd if (data == NULL) 183212036Spjd return (0); 184212036Spjd 185204076Spjd return (proto_common_recv(fd, data, size)); 186204076Spjd} 187204076Spjd 188204076Spjdstatic int 189204076Spjdsp_descriptor(const void *ctx) 190204076Spjd{ 191204076Spjd const struct sp_ctx *spctx = ctx; 192204076Spjd 193204076Spjd assert(spctx != NULL); 194204076Spjd assert(spctx->sp_magic == SP_CTX_MAGIC); 195204076Spjd assert(spctx->sp_side == SP_SIDE_CLIENT || 196204076Spjd spctx->sp_side == SP_SIDE_SERVER); 197204076Spjd 198204076Spjd switch (spctx->sp_side) { 199204076Spjd case SP_SIDE_CLIENT: 200204076Spjd assert(spctx->sp_fd[0] >= 0); 201204076Spjd return (spctx->sp_fd[0]); 202204076Spjd case SP_SIDE_SERVER: 203204076Spjd assert(spctx->sp_fd[1] >= 0); 204204076Spjd return (spctx->sp_fd[1]); 205204076Spjd } 206204076Spjd 207204076Spjd abort(); 208204076Spjd} 209204076Spjd 210204076Spjdstatic bool 211204076Spjdsp_address_match(const void *ctx __unused, const char *addr __unused) 212204076Spjd{ 213204076Spjd 214204076Spjd assert(!"proto_address_match() not supported on socketpairs"); 215204076Spjd abort(); 216204076Spjd} 217204076Spjd 218204076Spjdstatic void 219204076Spjdsp_local_address(const void *ctx __unused, char *addr __unused, 220204076Spjd size_t size __unused) 221204076Spjd{ 222204076Spjd 223204076Spjd assert(!"proto_local_address() not supported on socketpairs"); 224204076Spjd abort(); 225204076Spjd} 226204076Spjd 227204076Spjdstatic void 228204076Spjdsp_remote_address(const void *ctx __unused, char *addr __unused, 229204076Spjd size_t size __unused) 230204076Spjd{ 231204076Spjd 232204076Spjd assert(!"proto_remote_address() not supported on socketpairs"); 233204076Spjd abort(); 234204076Spjd} 235204076Spjd 236204076Spjdstatic void 237204076Spjdsp_close(void *ctx) 238204076Spjd{ 239204076Spjd struct sp_ctx *spctx = ctx; 240204076Spjd 241204076Spjd assert(spctx != NULL); 242204076Spjd assert(spctx->sp_magic == SP_CTX_MAGIC); 243204076Spjd 244204076Spjd switch (spctx->sp_side) { 245204076Spjd case SP_SIDE_UNDEF: 246204076Spjd close(spctx->sp_fd[0]); 247204076Spjd close(spctx->sp_fd[1]); 248204076Spjd break; 249204076Spjd case SP_SIDE_CLIENT: 250204076Spjd close(spctx->sp_fd[0]); 251204076Spjd break; 252204076Spjd case SP_SIDE_SERVER: 253204076Spjd close(spctx->sp_fd[1]); 254204076Spjd break; 255204076Spjd default: 256204076Spjd abort(); 257204076Spjd } 258204076Spjd 259204076Spjd spctx->sp_magic = 0; 260204076Spjd free(spctx); 261204076Spjd} 262204076Spjd 263204076Spjdstatic struct hast_proto sp_proto = { 264204076Spjd .hp_name = "socketpair", 265204076Spjd .hp_client = sp_client, 266204076Spjd .hp_connect = sp_connect, 267204076Spjd .hp_server = sp_server, 268204076Spjd .hp_accept = sp_accept, 269204076Spjd .hp_send = sp_send, 270204076Spjd .hp_recv = sp_recv, 271204076Spjd .hp_descriptor = sp_descriptor, 272204076Spjd .hp_address_match = sp_address_match, 273204076Spjd .hp_local_address = sp_local_address, 274204076Spjd .hp_remote_address = sp_remote_address, 275204076Spjd .hp_close = sp_close 276204076Spjd}; 277204076Spjd 278204076Spjdstatic __constructor void 279204076Spjdsp_ctor(void) 280204076Spjd{ 281204076Spjd 282210869Spjd proto_register(&sp_proto, false); 283204076Spjd} 284