proto_socketpair.c revision 218138
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 218138 2011-01-31 18:32:17Z 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 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_send(void *ctx, const unsigned char *data, size_t size) 87204076Spjd{ 88204076Spjd struct sp_ctx *spctx = ctx; 89204076Spjd int fd; 90204076Spjd 91218138Spjd PJDLOG_ASSERT(spctx != NULL); 92218138Spjd PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC); 93204076Spjd 94204076Spjd switch (spctx->sp_side) { 95204076Spjd case SP_SIDE_UNDEF: 96204076Spjd /* 97204076Spjd * If the first operation done by the caller is proto_send(), 98204076Spjd * we assume this the client. 99204076Spjd */ 100204076Spjd /* FALLTHROUGH */ 101204076Spjd spctx->sp_side = SP_SIDE_CLIENT; 102204076Spjd /* Close other end. */ 103204076Spjd close(spctx->sp_fd[1]); 104218138Spjd spctx->sp_fd[1] = -1; 105204076Spjd case SP_SIDE_CLIENT: 106218138Spjd PJDLOG_ASSERT(spctx->sp_fd[0] >= 0); 107204076Spjd fd = spctx->sp_fd[0]; 108204076Spjd break; 109204076Spjd case SP_SIDE_SERVER: 110218138Spjd PJDLOG_ASSERT(spctx->sp_fd[1] >= 0); 111204076Spjd fd = spctx->sp_fd[1]; 112204076Spjd break; 113204076Spjd default: 114218138Spjd PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side); 115204076Spjd } 116204076Spjd 117212036Spjd /* Someone is just trying to decide about side. */ 118212036Spjd if (data == NULL) 119212036Spjd return (0); 120212036Spjd 121204076Spjd return (proto_common_send(fd, data, size)); 122204076Spjd} 123204076Spjd 124204076Spjdstatic int 125204076Spjdsp_recv(void *ctx, unsigned char *data, size_t size) 126204076Spjd{ 127204076Spjd struct sp_ctx *spctx = ctx; 128204076Spjd int fd; 129204076Spjd 130218138Spjd PJDLOG_ASSERT(spctx != NULL); 131218138Spjd PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC); 132204076Spjd 133204076Spjd switch (spctx->sp_side) { 134204076Spjd case SP_SIDE_UNDEF: 135204076Spjd /* 136204076Spjd * If the first operation done by the caller is proto_recv(), 137204076Spjd * we assume this the server. 138204076Spjd */ 139204076Spjd /* FALLTHROUGH */ 140204076Spjd spctx->sp_side = SP_SIDE_SERVER; 141204076Spjd /* Close other end. */ 142204076Spjd close(spctx->sp_fd[0]); 143218138Spjd spctx->sp_fd[0] = -1; 144204076Spjd case SP_SIDE_SERVER: 145218138Spjd PJDLOG_ASSERT(spctx->sp_fd[1] >= 0); 146204076Spjd fd = spctx->sp_fd[1]; 147204076Spjd break; 148204076Spjd case SP_SIDE_CLIENT: 149218138Spjd PJDLOG_ASSERT(spctx->sp_fd[0] >= 0); 150204076Spjd fd = spctx->sp_fd[0]; 151204076Spjd break; 152204076Spjd default: 153218138Spjd PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side); 154204076Spjd } 155204076Spjd 156212036Spjd /* Someone is just trying to decide about side. */ 157212036Spjd if (data == NULL) 158212036Spjd return (0); 159212036Spjd 160204076Spjd return (proto_common_recv(fd, data, size)); 161204076Spjd} 162204076Spjd 163204076Spjdstatic int 164204076Spjdsp_descriptor(const void *ctx) 165204076Spjd{ 166204076Spjd const struct sp_ctx *spctx = ctx; 167204076Spjd 168218138Spjd PJDLOG_ASSERT(spctx != NULL); 169218138Spjd PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC); 170218138Spjd PJDLOG_ASSERT(spctx->sp_side == SP_SIDE_CLIENT || 171204076Spjd spctx->sp_side == SP_SIDE_SERVER); 172204076Spjd 173204076Spjd switch (spctx->sp_side) { 174204076Spjd case SP_SIDE_CLIENT: 175218138Spjd PJDLOG_ASSERT(spctx->sp_fd[0] >= 0); 176204076Spjd return (spctx->sp_fd[0]); 177204076Spjd case SP_SIDE_SERVER: 178218138Spjd PJDLOG_ASSERT(spctx->sp_fd[1] >= 0); 179204076Spjd return (spctx->sp_fd[1]); 180204076Spjd } 181204076Spjd 182218138Spjd PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side); 183204076Spjd} 184204076Spjd 185204076Spjdstatic void 186204076Spjdsp_close(void *ctx) 187204076Spjd{ 188204076Spjd struct sp_ctx *spctx = ctx; 189204076Spjd 190218138Spjd PJDLOG_ASSERT(spctx != NULL); 191218138Spjd PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC); 192204076Spjd 193204076Spjd switch (spctx->sp_side) { 194204076Spjd case SP_SIDE_UNDEF: 195218138Spjd PJDLOG_ASSERT(spctx->sp_fd[0] >= 0); 196204076Spjd close(spctx->sp_fd[0]); 197218138Spjd spctx->sp_fd[0] = -1; 198218138Spjd PJDLOG_ASSERT(spctx->sp_fd[1] >= 0); 199204076Spjd close(spctx->sp_fd[1]); 200218138Spjd spctx->sp_fd[1] = -1; 201204076Spjd break; 202204076Spjd case SP_SIDE_CLIENT: 203218138Spjd PJDLOG_ASSERT(spctx->sp_fd[0] >= 0); 204204076Spjd close(spctx->sp_fd[0]); 205218138Spjd spctx->sp_fd[0] = -1; 206218138Spjd PJDLOG_ASSERT(spctx->sp_fd[1] == -1); 207204076Spjd break; 208204076Spjd case SP_SIDE_SERVER: 209218138Spjd PJDLOG_ASSERT(spctx->sp_fd[1] >= 0); 210204076Spjd close(spctx->sp_fd[1]); 211218138Spjd spctx->sp_fd[1] = -1; 212218138Spjd PJDLOG_ASSERT(spctx->sp_fd[0] == -1); 213204076Spjd break; 214204076Spjd default: 215218138Spjd PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side); 216204076Spjd } 217204076Spjd 218204076Spjd spctx->sp_magic = 0; 219204076Spjd free(spctx); 220204076Spjd} 221204076Spjd 222204076Spjdstatic struct hast_proto sp_proto = { 223204076Spjd .hp_name = "socketpair", 224204076Spjd .hp_client = sp_client, 225204076Spjd .hp_send = sp_send, 226204076Spjd .hp_recv = sp_recv, 227204076Spjd .hp_descriptor = sp_descriptor, 228204076Spjd .hp_close = sp_close 229204076Spjd}; 230204076Spjd 231204076Spjdstatic __constructor void 232204076Spjdsp_ctor(void) 233204076Spjd{ 234204076Spjd 235210869Spjd proto_register(&sp_proto, false); 236204076Spjd} 237