proto_socketpair.c revision 210869
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 210869 2010-08-05 17:56:41Z 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 143204076Spjd return (proto_common_send(fd, data, size)); 144204076Spjd} 145204076Spjd 146204076Spjdstatic int 147204076Spjdsp_recv(void *ctx, unsigned char *data, size_t size) 148204076Spjd{ 149204076Spjd struct sp_ctx *spctx = ctx; 150204076Spjd int fd; 151204076Spjd 152204076Spjd assert(spctx != NULL); 153204076Spjd assert(spctx->sp_magic == SP_CTX_MAGIC); 154204076Spjd 155204076Spjd switch (spctx->sp_side) { 156204076Spjd case SP_SIDE_UNDEF: 157204076Spjd /* 158204076Spjd * If the first operation done by the caller is proto_recv(), 159204076Spjd * we assume this the server. 160204076Spjd */ 161204076Spjd /* FALLTHROUGH */ 162204076Spjd spctx->sp_side = SP_SIDE_SERVER; 163204076Spjd /* Close other end. */ 164204076Spjd close(spctx->sp_fd[0]); 165204076Spjd case SP_SIDE_SERVER: 166204076Spjd assert(spctx->sp_fd[1] >= 0); 167204076Spjd fd = spctx->sp_fd[1]; 168204076Spjd break; 169204076Spjd case SP_SIDE_CLIENT: 170204076Spjd assert(spctx->sp_fd[0] >= 0); 171204076Spjd fd = spctx->sp_fd[0]; 172204076Spjd break; 173204076Spjd default: 174204076Spjd abort(); 175204076Spjd } 176204076Spjd 177204076Spjd return (proto_common_recv(fd, data, size)); 178204076Spjd} 179204076Spjd 180204076Spjdstatic int 181204076Spjdsp_descriptor(const void *ctx) 182204076Spjd{ 183204076Spjd const struct sp_ctx *spctx = ctx; 184204076Spjd 185204076Spjd assert(spctx != NULL); 186204076Spjd assert(spctx->sp_magic == SP_CTX_MAGIC); 187204076Spjd assert(spctx->sp_side == SP_SIDE_CLIENT || 188204076Spjd spctx->sp_side == SP_SIDE_SERVER); 189204076Spjd 190204076Spjd switch (spctx->sp_side) { 191204076Spjd case SP_SIDE_CLIENT: 192204076Spjd assert(spctx->sp_fd[0] >= 0); 193204076Spjd return (spctx->sp_fd[0]); 194204076Spjd case SP_SIDE_SERVER: 195204076Spjd assert(spctx->sp_fd[1] >= 0); 196204076Spjd return (spctx->sp_fd[1]); 197204076Spjd } 198204076Spjd 199204076Spjd abort(); 200204076Spjd} 201204076Spjd 202204076Spjdstatic bool 203204076Spjdsp_address_match(const void *ctx __unused, const char *addr __unused) 204204076Spjd{ 205204076Spjd 206204076Spjd assert(!"proto_address_match() not supported on socketpairs"); 207204076Spjd abort(); 208204076Spjd} 209204076Spjd 210204076Spjdstatic void 211204076Spjdsp_local_address(const void *ctx __unused, char *addr __unused, 212204076Spjd size_t size __unused) 213204076Spjd{ 214204076Spjd 215204076Spjd assert(!"proto_local_address() not supported on socketpairs"); 216204076Spjd abort(); 217204076Spjd} 218204076Spjd 219204076Spjdstatic void 220204076Spjdsp_remote_address(const void *ctx __unused, char *addr __unused, 221204076Spjd size_t size __unused) 222204076Spjd{ 223204076Spjd 224204076Spjd assert(!"proto_remote_address() not supported on socketpairs"); 225204076Spjd abort(); 226204076Spjd} 227204076Spjd 228204076Spjdstatic void 229204076Spjdsp_close(void *ctx) 230204076Spjd{ 231204076Spjd struct sp_ctx *spctx = ctx; 232204076Spjd 233204076Spjd assert(spctx != NULL); 234204076Spjd assert(spctx->sp_magic == SP_CTX_MAGIC); 235204076Spjd 236204076Spjd switch (spctx->sp_side) { 237204076Spjd case SP_SIDE_UNDEF: 238204076Spjd close(spctx->sp_fd[0]); 239204076Spjd close(spctx->sp_fd[1]); 240204076Spjd break; 241204076Spjd case SP_SIDE_CLIENT: 242204076Spjd close(spctx->sp_fd[0]); 243204076Spjd break; 244204076Spjd case SP_SIDE_SERVER: 245204076Spjd close(spctx->sp_fd[1]); 246204076Spjd break; 247204076Spjd default: 248204076Spjd abort(); 249204076Spjd } 250204076Spjd 251204076Spjd spctx->sp_magic = 0; 252204076Spjd free(spctx); 253204076Spjd} 254204076Spjd 255204076Spjdstatic struct hast_proto sp_proto = { 256204076Spjd .hp_name = "socketpair", 257204076Spjd .hp_client = sp_client, 258204076Spjd .hp_connect = sp_connect, 259204076Spjd .hp_server = sp_server, 260204076Spjd .hp_accept = sp_accept, 261204076Spjd .hp_send = sp_send, 262204076Spjd .hp_recv = sp_recv, 263204076Spjd .hp_descriptor = sp_descriptor, 264204076Spjd .hp_address_match = sp_address_match, 265204076Spjd .hp_local_address = sp_local_address, 266204076Spjd .hp_remote_address = sp_remote_address, 267204076Spjd .hp_close = sp_close 268204076Spjd}; 269204076Spjd 270204076Spjdstatic __constructor void 271204076Spjdsp_ctor(void) 272204076Spjd{ 273204076Spjd 274210869Spjd proto_register(&sp_proto, false); 275204076Spjd} 276