proto_socketpair.c revision 219818
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 219818 2011-03-21 08:54:59Z pjd $"); 32204076Spjd 33204076Spjd#include <sys/types.h> 34204076Spjd#include <sys/socket.h> 35204076Spjd 36204076Spjd#include <errno.h> 37204076Spjd#include <stdbool.h> 38204076Spjd#include <stdint.h> 39204076Spjd#include <stdio.h> 40204076Spjd#include <string.h> 41204076Spjd#include <unistd.h> 42204076Spjd 43204076Spjd#include "hast.h" 44218138Spjd#include "pjdlog.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 60219818Spjdsp_client(const char *srcaddr, const char *dstaddr, void **ctxp) 61204076Spjd{ 62204076Spjd struct sp_ctx *spctx; 63204076Spjd int ret; 64204076Spjd 65219818Spjd if (strcmp(dstaddr, "socketpair://") != 0) 66204076Spjd return (-1); 67204076Spjd 68219818Spjd PJDLOG_ASSERT(srcaddr == NULL); 69219818Spjd 70204076Spjd spctx = malloc(sizeof(*spctx)); 71204076Spjd if (spctx == NULL) 72204076Spjd return (errno); 73204076Spjd 74204076Spjd if (socketpair(PF_UNIX, SOCK_STREAM, 0, spctx->sp_fd) < 0) { 75204076Spjd ret = errno; 76204076Spjd free(spctx); 77204076Spjd return (ret); 78204076Spjd } 79204076Spjd 80204076Spjd spctx->sp_side = SP_SIDE_UNDEF; 81204076Spjd spctx->sp_magic = SP_CTX_MAGIC; 82204076Spjd *ctxp = spctx; 83204076Spjd 84204076Spjd return (0); 85204076Spjd} 86204076Spjd 87204076Spjdstatic int 88218194Spjdsp_send(void *ctx, const unsigned char *data, size_t size, int fd) 89204076Spjd{ 90204076Spjd struct sp_ctx *spctx = ctx; 91218194Spjd int sock; 92204076Spjd 93218138Spjd PJDLOG_ASSERT(spctx != NULL); 94218138Spjd PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC); 95204076Spjd 96204076Spjd switch (spctx->sp_side) { 97204076Spjd case SP_SIDE_UNDEF: 98204076Spjd /* 99204076Spjd * If the first operation done by the caller is proto_send(), 100218194Spjd * we assume this is the client. 101204076Spjd */ 102204076Spjd /* FALLTHROUGH */ 103204076Spjd spctx->sp_side = SP_SIDE_CLIENT; 104204076Spjd /* Close other end. */ 105204076Spjd close(spctx->sp_fd[1]); 106218138Spjd spctx->sp_fd[1] = -1; 107204076Spjd case SP_SIDE_CLIENT: 108218138Spjd PJDLOG_ASSERT(spctx->sp_fd[0] >= 0); 109218194Spjd sock = spctx->sp_fd[0]; 110204076Spjd break; 111204076Spjd case SP_SIDE_SERVER: 112218138Spjd PJDLOG_ASSERT(spctx->sp_fd[1] >= 0); 113218194Spjd sock = spctx->sp_fd[1]; 114204076Spjd break; 115204076Spjd default: 116218138Spjd PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side); 117204076Spjd } 118204076Spjd 119212036Spjd /* Someone is just trying to decide about side. */ 120212036Spjd if (data == NULL) 121212036Spjd return (0); 122212036Spjd 123218194Spjd return (proto_common_send(sock, data, size, fd)); 124204076Spjd} 125204076Spjd 126204076Spjdstatic int 127218194Spjdsp_recv(void *ctx, unsigned char *data, size_t size, int *fdp) 128204076Spjd{ 129204076Spjd struct sp_ctx *spctx = ctx; 130204076Spjd int fd; 131204076Spjd 132218138Spjd PJDLOG_ASSERT(spctx != NULL); 133218138Spjd PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC); 134204076Spjd 135204076Spjd switch (spctx->sp_side) { 136204076Spjd case SP_SIDE_UNDEF: 137204076Spjd /* 138204076Spjd * If the first operation done by the caller is proto_recv(), 139218194Spjd * we assume this is the server. 140204076Spjd */ 141204076Spjd /* FALLTHROUGH */ 142204076Spjd spctx->sp_side = SP_SIDE_SERVER; 143204076Spjd /* Close other end. */ 144204076Spjd close(spctx->sp_fd[0]); 145218138Spjd spctx->sp_fd[0] = -1; 146204076Spjd case SP_SIDE_SERVER: 147218138Spjd PJDLOG_ASSERT(spctx->sp_fd[1] >= 0); 148204076Spjd fd = spctx->sp_fd[1]; 149204076Spjd break; 150204076Spjd case SP_SIDE_CLIENT: 151218138Spjd PJDLOG_ASSERT(spctx->sp_fd[0] >= 0); 152204076Spjd fd = spctx->sp_fd[0]; 153204076Spjd break; 154204076Spjd default: 155218138Spjd PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side); 156204076Spjd } 157204076Spjd 158212036Spjd /* Someone is just trying to decide about side. */ 159212036Spjd if (data == NULL) 160212036Spjd return (0); 161212036Spjd 162218194Spjd return (proto_common_recv(fd, data, size, fdp)); 163204076Spjd} 164204076Spjd 165204076Spjdstatic int 166204076Spjdsp_descriptor(const void *ctx) 167204076Spjd{ 168204076Spjd const struct sp_ctx *spctx = ctx; 169204076Spjd 170218138Spjd PJDLOG_ASSERT(spctx != NULL); 171218138Spjd PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC); 172218138Spjd PJDLOG_ASSERT(spctx->sp_side == SP_SIDE_CLIENT || 173204076Spjd spctx->sp_side == SP_SIDE_SERVER); 174204076Spjd 175204076Spjd switch (spctx->sp_side) { 176204076Spjd case SP_SIDE_CLIENT: 177218138Spjd PJDLOG_ASSERT(spctx->sp_fd[0] >= 0); 178204076Spjd return (spctx->sp_fd[0]); 179204076Spjd case SP_SIDE_SERVER: 180218138Spjd PJDLOG_ASSERT(spctx->sp_fd[1] >= 0); 181204076Spjd return (spctx->sp_fd[1]); 182204076Spjd } 183204076Spjd 184218138Spjd PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side); 185204076Spjd} 186204076Spjd 187204076Spjdstatic void 188204076Spjdsp_close(void *ctx) 189204076Spjd{ 190204076Spjd struct sp_ctx *spctx = ctx; 191204076Spjd 192218138Spjd PJDLOG_ASSERT(spctx != NULL); 193218138Spjd PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC); 194204076Spjd 195204076Spjd switch (spctx->sp_side) { 196204076Spjd case SP_SIDE_UNDEF: 197218138Spjd PJDLOG_ASSERT(spctx->sp_fd[0] >= 0); 198204076Spjd close(spctx->sp_fd[0]); 199218138Spjd spctx->sp_fd[0] = -1; 200218138Spjd PJDLOG_ASSERT(spctx->sp_fd[1] >= 0); 201204076Spjd close(spctx->sp_fd[1]); 202218138Spjd spctx->sp_fd[1] = -1; 203204076Spjd break; 204204076Spjd case SP_SIDE_CLIENT: 205218138Spjd PJDLOG_ASSERT(spctx->sp_fd[0] >= 0); 206204076Spjd close(spctx->sp_fd[0]); 207218138Spjd spctx->sp_fd[0] = -1; 208218138Spjd PJDLOG_ASSERT(spctx->sp_fd[1] == -1); 209204076Spjd break; 210204076Spjd case SP_SIDE_SERVER: 211218138Spjd PJDLOG_ASSERT(spctx->sp_fd[1] >= 0); 212204076Spjd close(spctx->sp_fd[1]); 213218138Spjd spctx->sp_fd[1] = -1; 214218138Spjd PJDLOG_ASSERT(spctx->sp_fd[0] == -1); 215204076Spjd break; 216204076Spjd default: 217218138Spjd PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side); 218204076Spjd } 219204076Spjd 220204076Spjd spctx->sp_magic = 0; 221204076Spjd free(spctx); 222204076Spjd} 223204076Spjd 224204076Spjdstatic struct hast_proto sp_proto = { 225204076Spjd .hp_name = "socketpair", 226204076Spjd .hp_client = sp_client, 227204076Spjd .hp_send = sp_send, 228204076Spjd .hp_recv = sp_recv, 229204076Spjd .hp_descriptor = sp_descriptor, 230204076Spjd .hp_close = sp_close 231204076Spjd}; 232204076Spjd 233204076Spjdstatic __constructor void 234204076Spjdsp_ctor(void) 235204076Spjd{ 236204076Spjd 237210869Spjd proto_register(&sp_proto, false); 238204076Spjd} 239