proto_socketpair.c revision 204076
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 204076 2010-02-18 23:16:19Z 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 94204076Spjdsp_server(const char *addr __unused, void **ctxp __unused) 95204076Spjd{ 96204076Spjd 97204076Spjd assert(!"proto_server() not supported on socketpairs"); 98204076Spjd abort(); 99204076Spjd} 100204076Spjd 101204076Spjdstatic int 102204076Spjdsp_accept(void *ctx __unused, void **newctxp __unused) 103204076Spjd{ 104204076Spjd 105204076Spjd assert(!"proto_server() not supported on socketpairs"); 106204076Spjd abort(); 107204076Spjd} 108204076Spjd 109204076Spjdstatic int 110204076Spjdsp_send(void *ctx, const unsigned char *data, size_t size) 111204076Spjd{ 112204076Spjd struct sp_ctx *spctx = ctx; 113204076Spjd int fd; 114204076Spjd 115204076Spjd assert(spctx != NULL); 116204076Spjd assert(spctx->sp_magic == SP_CTX_MAGIC); 117204076Spjd 118204076Spjd switch (spctx->sp_side) { 119204076Spjd case SP_SIDE_UNDEF: 120204076Spjd /* 121204076Spjd * If the first operation done by the caller is proto_send(), 122204076Spjd * we assume this the client. 123204076Spjd */ 124204076Spjd /* FALLTHROUGH */ 125204076Spjd spctx->sp_side = SP_SIDE_CLIENT; 126204076Spjd /* Close other end. */ 127204076Spjd close(spctx->sp_fd[1]); 128204076Spjd case SP_SIDE_CLIENT: 129204076Spjd assert(spctx->sp_fd[0] >= 0); 130204076Spjd fd = spctx->sp_fd[0]; 131204076Spjd break; 132204076Spjd case SP_SIDE_SERVER: 133204076Spjd assert(spctx->sp_fd[1] >= 0); 134204076Spjd fd = spctx->sp_fd[1]; 135204076Spjd break; 136204076Spjd default: 137204076Spjd abort(); 138204076Spjd } 139204076Spjd 140204076Spjd return (proto_common_send(fd, data, size)); 141204076Spjd} 142204076Spjd 143204076Spjdstatic int 144204076Spjdsp_recv(void *ctx, unsigned char *data, size_t size) 145204076Spjd{ 146204076Spjd struct sp_ctx *spctx = ctx; 147204076Spjd int fd; 148204076Spjd 149204076Spjd assert(spctx != NULL); 150204076Spjd assert(spctx->sp_magic == SP_CTX_MAGIC); 151204076Spjd 152204076Spjd switch (spctx->sp_side) { 153204076Spjd case SP_SIDE_UNDEF: 154204076Spjd /* 155204076Spjd * If the first operation done by the caller is proto_recv(), 156204076Spjd * we assume this the server. 157204076Spjd */ 158204076Spjd /* FALLTHROUGH */ 159204076Spjd spctx->sp_side = SP_SIDE_SERVER; 160204076Spjd /* Close other end. */ 161204076Spjd close(spctx->sp_fd[0]); 162204076Spjd case SP_SIDE_SERVER: 163204076Spjd assert(spctx->sp_fd[1] >= 0); 164204076Spjd fd = spctx->sp_fd[1]; 165204076Spjd break; 166204076Spjd case SP_SIDE_CLIENT: 167204076Spjd assert(spctx->sp_fd[0] >= 0); 168204076Spjd fd = spctx->sp_fd[0]; 169204076Spjd break; 170204076Spjd default: 171204076Spjd abort(); 172204076Spjd } 173204076Spjd 174204076Spjd return (proto_common_recv(fd, data, size)); 175204076Spjd} 176204076Spjd 177204076Spjdstatic int 178204076Spjdsp_descriptor(const void *ctx) 179204076Spjd{ 180204076Spjd const struct sp_ctx *spctx = ctx; 181204076Spjd 182204076Spjd assert(spctx != NULL); 183204076Spjd assert(spctx->sp_magic == SP_CTX_MAGIC); 184204076Spjd assert(spctx->sp_side == SP_SIDE_CLIENT || 185204076Spjd spctx->sp_side == SP_SIDE_SERVER); 186204076Spjd 187204076Spjd switch (spctx->sp_side) { 188204076Spjd case SP_SIDE_CLIENT: 189204076Spjd assert(spctx->sp_fd[0] >= 0); 190204076Spjd return (spctx->sp_fd[0]); 191204076Spjd case SP_SIDE_SERVER: 192204076Spjd assert(spctx->sp_fd[1] >= 0); 193204076Spjd return (spctx->sp_fd[1]); 194204076Spjd } 195204076Spjd 196204076Spjd abort(); 197204076Spjd} 198204076Spjd 199204076Spjdstatic bool 200204076Spjdsp_address_match(const void *ctx __unused, const char *addr __unused) 201204076Spjd{ 202204076Spjd 203204076Spjd assert(!"proto_address_match() not supported on socketpairs"); 204204076Spjd abort(); 205204076Spjd} 206204076Spjd 207204076Spjdstatic void 208204076Spjdsp_local_address(const void *ctx __unused, char *addr __unused, 209204076Spjd size_t size __unused) 210204076Spjd{ 211204076Spjd 212204076Spjd assert(!"proto_local_address() not supported on socketpairs"); 213204076Spjd abort(); 214204076Spjd} 215204076Spjd 216204076Spjdstatic void 217204076Spjdsp_remote_address(const void *ctx __unused, char *addr __unused, 218204076Spjd size_t size __unused) 219204076Spjd{ 220204076Spjd 221204076Spjd assert(!"proto_remote_address() not supported on socketpairs"); 222204076Spjd abort(); 223204076Spjd} 224204076Spjd 225204076Spjdstatic void 226204076Spjdsp_close(void *ctx) 227204076Spjd{ 228204076Spjd struct sp_ctx *spctx = ctx; 229204076Spjd 230204076Spjd assert(spctx != NULL); 231204076Spjd assert(spctx->sp_magic == SP_CTX_MAGIC); 232204076Spjd 233204076Spjd switch (spctx->sp_side) { 234204076Spjd case SP_SIDE_UNDEF: 235204076Spjd close(spctx->sp_fd[0]); 236204076Spjd close(spctx->sp_fd[1]); 237204076Spjd break; 238204076Spjd case SP_SIDE_CLIENT: 239204076Spjd close(spctx->sp_fd[0]); 240204076Spjd break; 241204076Spjd case SP_SIDE_SERVER: 242204076Spjd close(spctx->sp_fd[1]); 243204076Spjd break; 244204076Spjd default: 245204076Spjd abort(); 246204076Spjd } 247204076Spjd 248204076Spjd spctx->sp_magic = 0; 249204076Spjd free(spctx); 250204076Spjd} 251204076Spjd 252204076Spjdstatic struct hast_proto sp_proto = { 253204076Spjd .hp_name = "socketpair", 254204076Spjd .hp_client = sp_client, 255204076Spjd .hp_connect = sp_connect, 256204076Spjd .hp_server = sp_server, 257204076Spjd .hp_accept = sp_accept, 258204076Spjd .hp_send = sp_send, 259204076Spjd .hp_recv = sp_recv, 260204076Spjd .hp_descriptor = sp_descriptor, 261204076Spjd .hp_address_match = sp_address_match, 262204076Spjd .hp_local_address = sp_local_address, 263204076Spjd .hp_remote_address = sp_remote_address, 264204076Spjd .hp_close = sp_close 265204076Spjd}; 266204076Spjd 267204076Spjdstatic __constructor void 268204076Spjdsp_ctor(void) 269204076Spjd{ 270204076Spjd 271204076Spjd proto_register(&sp_proto); 272204076Spjd} 273