proto_socketpair.c revision 219873
11590Srgrimes/*- 21590Srgrimes * Copyright (c) 2009-2010 The FreeBSD Foundation 31590Srgrimes * All rights reserved. 41590Srgrimes * 51590Srgrimes * This software was developed by Pawel Jakub Dawidek under sponsorship from 61590Srgrimes * the FreeBSD Foundation. 71590Srgrimes * 81590Srgrimes * Redistribution and use in source and binary forms, with or without 91590Srgrimes * modification, are permitted provided that the following conditions 101590Srgrimes * are met: 111590Srgrimes * 1. Redistributions of source code must retain the above copyright 121590Srgrimes * notice, this list of conditions and the following disclaimer. 131590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141590Srgrimes * notice, this list of conditions and the following disclaimer in the 151590Srgrimes * documentation and/or other materials provided with the distribution. 161590Srgrimes * 171590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 181590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 211590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271590Srgrimes * SUCH DAMAGE. 281590Srgrimes */ 291590Srgrimes 301590Srgrimes#include <sys/cdefs.h> 311590Srgrimes__FBSDID("$FreeBSD: head/sbin/hastd/proto_socketpair.c 219873 2011-03-22 16:21:11Z pjd $"); 321590Srgrimes 331590Srgrimes#include <sys/types.h> 341590Srgrimes#include <sys/socket.h> 351590Srgrimes 361590Srgrimes#include <errno.h> 3762833Swsanchez#include <stdbool.h> 3862833Swsanchez#include <stdint.h> 391590Srgrimes#include <stdio.h> 401590Srgrimes#include <string.h> 4162833Swsanchez#include <unistd.h> 4294587Sobrien 431590Srgrimes#include "pjdlog.h" 44141104Sharti#include "proto_impl.h" 45141104Sharti 461590Srgrimes#define SP_CTX_MAGIC 0x50c3741 47141133Shartistruct sp_ctx { 48141104Sharti int sp_magic; 49141104Sharti int sp_fd[2]; 50141104Sharti int sp_side; 51146345Sharti#define SP_SIDE_UNDEF 0 52146345Sharti#define SP_SIDE_CLIENT 1 53228992Suqs#define SP_SIDE_SERVER 2 54146345Sharti}; 55146345Sharti 56228992Suqsstatic void sp_close(void *ctx); 57146345Sharti 58146543Shartistatic int 59146345Shartisp_client(const char *srcaddr, const char *dstaddr, void **ctxp) 60146345Sharti{ 615814Sjkh struct sp_ctx *spctx; 62146345Sharti int ret; 63146345Sharti 64146345Sharti if (strcmp(dstaddr, "socketpair://") != 0) 65146345Sharti return (-1); 66146345Sharti 67146345Sharti PJDLOG_ASSERT(srcaddr == NULL); 68146345Sharti 69146345Sharti spctx = malloc(sizeof(*spctx)); 70146345Sharti if (spctx == NULL) 71146345Sharti return (errno); 725814Sjkh 735814Sjkh if (socketpair(PF_UNIX, SOCK_STREAM, 0, spctx->sp_fd) < 0) { 74146345Sharti ret = errno; 755814Sjkh free(spctx); 76138232Sharti return (ret); 77146345Sharti } 78146345Sharti 79146345Sharti spctx->sp_side = SP_SIDE_UNDEF; 80146345Sharti spctx->sp_magic = SP_CTX_MAGIC; 81146345Sharti *ctxp = spctx; 82146345Sharti 83146345Sharti return (0); 84146345Sharti} 85146345Sharti 86146345Shartistatic int 87146345Shartisp_send(void *ctx, const unsigned char *data, size_t size, int fd) 88146345Sharti{ 89146345Sharti struct sp_ctx *spctx = ctx; 90146345Sharti int sock; 91146345Sharti 92146345Sharti PJDLOG_ASSERT(spctx != NULL); 93146345Sharti PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC); 94146345Sharti 955814Sjkh switch (spctx->sp_side) { 965814Sjkh case SP_SIDE_UNDEF: 971590Srgrimes /* 981590Srgrimes * If the first operation done by the caller is proto_send(), 99138547Sharti * we assume this is the client. 1001590Srgrimes */ 1011590Srgrimes /* FALLTHROUGH */ 1021590Srgrimes spctx->sp_side = SP_SIDE_CLIENT; 1031590Srgrimes /* Close other end. */ 1041590Srgrimes close(spctx->sp_fd[1]); 105138547Sharti spctx->sp_fd[1] = -1; 1061590Srgrimes case SP_SIDE_CLIENT: 10794584Sobrien PJDLOG_ASSERT(spctx->sp_fd[0] >= 0); 10894584Sobrien sock = spctx->sp_fd[0]; 1091590Srgrimes break; 1101590Srgrimes case SP_SIDE_SERVER: 11194638Sobrien PJDLOG_ASSERT(spctx->sp_fd[1] >= 0); 11294638Sobrien sock = spctx->sp_fd[1]; 1131590Srgrimes break; 1141590Srgrimes default: 115138264Sharti PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side); 1161590Srgrimes } 1171590Srgrimes 11894638Sobrien /* Someone is just trying to decide about side. */ 1191590Srgrimes if (data == NULL) 1201590Srgrimes return (0); 12194638Sobrien 12294638Sobrien return (proto_common_send(sock, data, size, fd)); 12394638Sobrien} 12494638Sobrien 12594638Sobrienstatic int 12694638Sobriensp_recv(void *ctx, unsigned char *data, size_t size, int *fdp) 1271590Srgrimes{ 1281590Srgrimes struct sp_ctx *spctx = ctx; 12994638Sobrien int fd; 13094638Sobrien 1311590Srgrimes PJDLOG_ASSERT(spctx != NULL); 132138232Sharti PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC); 1331590Srgrimes 1341590Srgrimes switch (spctx->sp_side) { 135146345Sharti case SP_SIDE_UNDEF: 136146345Sharti /* 137146345Sharti * If the first operation done by the caller is proto_recv(), 138146345Sharti * we assume this is the server. 1391590Srgrimes */ 140146345Sharti /* FALLTHROUGH */ 141146345Sharti spctx->sp_side = SP_SIDE_SERVER; 1421590Srgrimes /* Close other end. */ 143146345Sharti close(spctx->sp_fd[0]); 144146345Sharti spctx->sp_fd[0] = -1; 145146345Sharti case SP_SIDE_SERVER: 1461590Srgrimes PJDLOG_ASSERT(spctx->sp_fd[1] >= 0); 1471590Srgrimes fd = spctx->sp_fd[1]; 1481590Srgrimes break; 1491590Srgrimes case SP_SIDE_CLIENT: 1501590Srgrimes PJDLOG_ASSERT(spctx->sp_fd[0] >= 0); 151146345Sharti fd = spctx->sp_fd[0]; 1521590Srgrimes break; 153209951Semaste default: 154146345Sharti PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side); 155146345Sharti } 156146345Sharti 157146345Sharti /* Someone is just trying to decide about side. */ 158146345Sharti if (data == NULL) 1591590Srgrimes return (0); 1601590Srgrimes 1611590Srgrimes return (proto_common_recv(fd, data, size, fdp)); 1621590Srgrimes} 163146345Sharti 164146345Shartistatic int 1651590Srgrimessp_descriptor(const void *ctx) 1661590Srgrimes{ 167146345Sharti const struct sp_ctx *spctx = ctx; 168146345Sharti 169146345Sharti PJDLOG_ASSERT(spctx != NULL); 1701590Srgrimes PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC); 171146345Sharti PJDLOG_ASSERT(spctx->sp_side == SP_SIDE_CLIENT || 172146345Sharti spctx->sp_side == SP_SIDE_SERVER); 173146345Sharti 174124966Sru switch (spctx->sp_side) { 175124966Sru case SP_SIDE_CLIENT: 176146345Sharti PJDLOG_ASSERT(spctx->sp_fd[0] >= 0); 177146345Sharti return (spctx->sp_fd[0]); 178146345Sharti case SP_SIDE_SERVER: 179146345Sharti PJDLOG_ASSERT(spctx->sp_fd[1] >= 0); 180146345Sharti return (spctx->sp_fd[1]); 181146345Sharti } 182146345Sharti 183146345Sharti PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side); 184146345Sharti} 185146345Sharti 186124840Srustatic void 1871590Srgrimessp_close(void *ctx) 1881590Srgrimes{ 1895814Sjkh struct sp_ctx *spctx = ctx; 190146345Sharti 191146345Sharti PJDLOG_ASSERT(spctx != NULL); 192146345Sharti PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC); 193146345Sharti 1941590Srgrimes switch (spctx->sp_side) { 195146345Sharti case SP_SIDE_UNDEF: 196146345Sharti PJDLOG_ASSERT(spctx->sp_fd[0] >= 0); 197146345Sharti close(spctx->sp_fd[0]); 1981590Srgrimes spctx->sp_fd[0] = -1; 1991590Srgrimes PJDLOG_ASSERT(spctx->sp_fd[1] >= 0); 2001590Srgrimes close(spctx->sp_fd[1]); 2011590Srgrimes spctx->sp_fd[1] = -1; 2021590Srgrimes break; 2031590Srgrimes case SP_SIDE_CLIENT: 204146345Sharti PJDLOG_ASSERT(spctx->sp_fd[0] >= 0); 205146345Sharti close(spctx->sp_fd[0]); 206146345Sharti spctx->sp_fd[0] = -1; 207146345Sharti PJDLOG_ASSERT(spctx->sp_fd[1] == -1); 208146345Sharti break; 2095814Sjkh case SP_SIDE_SERVER: 210146345Sharti PJDLOG_ASSERT(spctx->sp_fd[1] >= 0); 211146345Sharti close(spctx->sp_fd[1]); 212146345Sharti spctx->sp_fd[1] = -1; 213146345Sharti PJDLOG_ASSERT(spctx->sp_fd[0] == -1); 2141590Srgrimes break; 215146345Sharti default: 216146345Sharti PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side); 217146345Sharti } 218146345Sharti 219146345Sharti spctx->sp_magic = 0; 220146345Sharti free(spctx); 221146345Sharti} 2225814Sjkh 2235814Sjkhstatic struct proto sp_proto = { 224146345Sharti .prt_name = "socketpair", 225146345Sharti .prt_client = sp_client, 226146345Sharti .prt_send = sp_send, 227146345Sharti .prt_recv = sp_recv, 228146345Sharti .prt_descriptor = sp_descriptor, 229146345Sharti .prt_close = sp_close 230146345Sharti}; 231146345Sharti 232146345Shartistatic __constructor void 233146345Shartisp_ctor(void) 234146345Sharti{ 235146345Sharti 236146345Sharti proto_register(&sp_proto, false); 237146345Sharti} 238146345Sharti