1243730Srwatson/*- 2243730Srwatson * Copyright (c) 2009-2010 The FreeBSD Foundation 3243730Srwatson * All rights reserved. 4243730Srwatson * 5243730Srwatson * This software was developed by Pawel Jakub Dawidek under sponsorship from 6243730Srwatson * the FreeBSD Foundation. 7243730Srwatson * 8243730Srwatson * Redistribution and use in source and binary forms, with or without 9243730Srwatson * modification, are permitted provided that the following conditions 10243730Srwatson * are met: 11243730Srwatson * 1. Redistributions of source code must retain the above copyright 12243730Srwatson * notice, this list of conditions and the following disclaimer. 13243730Srwatson * 2. Redistributions in binary form must reproduce the above copyright 14243730Srwatson * notice, this list of conditions and the following disclaimer in the 15243730Srwatson * documentation and/or other materials provided with the distribution. 16243730Srwatson * 17243730Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 18243730Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19243730Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20243730Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 21243730Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22243730Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23243730Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24243730Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25243730Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26243730Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27243730Srwatson * SUCH DAMAGE. 28243730Srwatson * 29243730Srwatson * $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/proto_socketpair.c#1 $ 30243730Srwatson */ 31243730Srwatson 32243730Srwatson#include <sys/types.h> 33243730Srwatson#include <sys/socket.h> 34243730Srwatson 35243730Srwatson#include <errno.h> 36243730Srwatson#include <stdbool.h> 37243730Srwatson#include <stdint.h> 38243730Srwatson#include <stdio.h> 39243730Srwatson#include <string.h> 40243730Srwatson#include <unistd.h> 41243730Srwatson 42243730Srwatson#include "pjdlog.h" 43243730Srwatson#include "proto_impl.h" 44243730Srwatson 45243730Srwatson#define SP_CTX_MAGIC 0x50c3741 46243730Srwatsonstruct sp_ctx { 47243730Srwatson int sp_magic; 48243730Srwatson int sp_fd[2]; 49243730Srwatson int sp_side; 50243730Srwatson#define SP_SIDE_UNDEF 0 51243730Srwatson#define SP_SIDE_CLIENT 1 52243730Srwatson#define SP_SIDE_SERVER 2 53243730Srwatson}; 54243730Srwatson 55243730Srwatsonstatic void sp_close(void *ctx); 56243730Srwatson 57243730Srwatsonstatic int 58243730Srwatsonsp_connect(const char *srcaddr, const char *dstaddr, int timeout, void **ctxp) 59243730Srwatson{ 60243730Srwatson struct sp_ctx *spctx; 61243730Srwatson int error; 62243730Srwatson 63243730Srwatson PJDLOG_ASSERT(dstaddr != NULL); 64243730Srwatson PJDLOG_ASSERT(timeout >= -1); 65243730Srwatson 66243730Srwatson if (strcmp(dstaddr, "socketpair://") != 0) 67243730Srwatson return (-1); 68243730Srwatson 69243730Srwatson PJDLOG_ASSERT(srcaddr == NULL); 70243730Srwatson 71243730Srwatson spctx = malloc(sizeof(*spctx)); 72243730Srwatson if (spctx == NULL) 73243730Srwatson return (errno); 74243730Srwatson 75243730Srwatson if (socketpair(PF_UNIX, SOCK_STREAM, 0, spctx->sp_fd) == -1) { 76243730Srwatson error = errno; 77243730Srwatson free(spctx); 78243730Srwatson return (error); 79243730Srwatson } 80243730Srwatson 81243730Srwatson spctx->sp_side = SP_SIDE_UNDEF; 82243730Srwatson spctx->sp_magic = SP_CTX_MAGIC; 83243730Srwatson *ctxp = spctx; 84243730Srwatson 85243730Srwatson return (0); 86243730Srwatson} 87243730Srwatson 88243730Srwatsonstatic int 89243730Srwatsonsp_wrap(int fd, bool client, void **ctxp) 90243730Srwatson{ 91243730Srwatson struct sp_ctx *spctx; 92243730Srwatson 93243730Srwatson PJDLOG_ASSERT(fd >= 0); 94243730Srwatson 95243730Srwatson spctx = malloc(sizeof(*spctx)); 96243730Srwatson if (spctx == NULL) 97243730Srwatson return (errno); 98243730Srwatson 99243730Srwatson if (client) { 100243730Srwatson spctx->sp_side = SP_SIDE_CLIENT; 101243730Srwatson spctx->sp_fd[0] = fd; 102243730Srwatson spctx->sp_fd[1] = -1; 103243730Srwatson } else { 104243730Srwatson spctx->sp_side = SP_SIDE_SERVER; 105243730Srwatson spctx->sp_fd[0] = -1; 106243730Srwatson spctx->sp_fd[1] = fd; 107243730Srwatson } 108243730Srwatson spctx->sp_magic = SP_CTX_MAGIC; 109243730Srwatson *ctxp = spctx; 110243730Srwatson 111243730Srwatson return (0); 112243730Srwatson} 113243730Srwatson 114243730Srwatsonstatic int 115243730Srwatsonsp_send(void *ctx, const unsigned char *data, size_t size, int fd) 116243730Srwatson{ 117243730Srwatson struct sp_ctx *spctx = ctx; 118243730Srwatson int sock; 119243730Srwatson 120243730Srwatson PJDLOG_ASSERT(spctx != NULL); 121243730Srwatson PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC); 122243730Srwatson 123243730Srwatson switch (spctx->sp_side) { 124243730Srwatson case SP_SIDE_UNDEF: 125243730Srwatson /* 126243730Srwatson * If the first operation done by the caller is proto_send(), 127243730Srwatson * we assume this is the client. 128243730Srwatson */ 129243730Srwatson /* FALLTHROUGH */ 130243730Srwatson spctx->sp_side = SP_SIDE_CLIENT; 131243730Srwatson /* Close other end. */ 132243730Srwatson close(spctx->sp_fd[1]); 133243730Srwatson spctx->sp_fd[1] = -1; 134243730Srwatson case SP_SIDE_CLIENT: 135243730Srwatson PJDLOG_ASSERT(spctx->sp_fd[0] >= 0); 136243730Srwatson sock = spctx->sp_fd[0]; 137243730Srwatson break; 138243730Srwatson case SP_SIDE_SERVER: 139243730Srwatson PJDLOG_ASSERT(spctx->sp_fd[1] >= 0); 140243730Srwatson sock = spctx->sp_fd[1]; 141243730Srwatson break; 142243730Srwatson default: 143243730Srwatson PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side); 144243730Srwatson } 145243730Srwatson 146243730Srwatson /* Someone is just trying to decide about side. */ 147243730Srwatson if (data == NULL) 148243730Srwatson return (0); 149243730Srwatson 150243730Srwatson return (proto_common_send(sock, data, size, fd)); 151243730Srwatson} 152243730Srwatson 153243730Srwatsonstatic int 154243730Srwatsonsp_recv(void *ctx, unsigned char *data, size_t size, int *fdp) 155243730Srwatson{ 156243730Srwatson struct sp_ctx *spctx = ctx; 157243730Srwatson int sock; 158243730Srwatson 159243730Srwatson PJDLOG_ASSERT(spctx != NULL); 160243730Srwatson PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC); 161243730Srwatson 162243730Srwatson switch (spctx->sp_side) { 163243730Srwatson case SP_SIDE_UNDEF: 164243730Srwatson /* 165243730Srwatson * If the first operation done by the caller is proto_recv(), 166243730Srwatson * we assume this is the server. 167243730Srwatson */ 168243730Srwatson /* FALLTHROUGH */ 169243730Srwatson spctx->sp_side = SP_SIDE_SERVER; 170243730Srwatson /* Close other end. */ 171243730Srwatson close(spctx->sp_fd[0]); 172243730Srwatson spctx->sp_fd[0] = -1; 173243730Srwatson case SP_SIDE_SERVER: 174243730Srwatson PJDLOG_ASSERT(spctx->sp_fd[1] >= 0); 175243730Srwatson sock = spctx->sp_fd[1]; 176243730Srwatson break; 177243730Srwatson case SP_SIDE_CLIENT: 178243730Srwatson PJDLOG_ASSERT(spctx->sp_fd[0] >= 0); 179243730Srwatson sock = spctx->sp_fd[0]; 180243730Srwatson break; 181243730Srwatson default: 182243730Srwatson PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side); 183243730Srwatson } 184243730Srwatson 185243730Srwatson /* Someone is just trying to decide about side. */ 186243730Srwatson if (data == NULL) 187243730Srwatson return (0); 188243730Srwatson 189243730Srwatson return (proto_common_recv(sock, data, size, fdp)); 190243730Srwatson} 191243730Srwatson 192243730Srwatsonstatic int 193243730Srwatsonsp_descriptor(const void *ctx) 194243730Srwatson{ 195243730Srwatson const struct sp_ctx *spctx = ctx; 196243730Srwatson 197243730Srwatson PJDLOG_ASSERT(spctx != NULL); 198243730Srwatson PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC); 199243730Srwatson PJDLOG_ASSERT(spctx->sp_side == SP_SIDE_CLIENT || 200243730Srwatson spctx->sp_side == SP_SIDE_SERVER); 201243730Srwatson 202243730Srwatson switch (spctx->sp_side) { 203243730Srwatson case SP_SIDE_CLIENT: 204243730Srwatson PJDLOG_ASSERT(spctx->sp_fd[0] >= 0); 205243730Srwatson return (spctx->sp_fd[0]); 206243730Srwatson case SP_SIDE_SERVER: 207243730Srwatson PJDLOG_ASSERT(spctx->sp_fd[1] >= 0); 208243730Srwatson return (spctx->sp_fd[1]); 209243730Srwatson } 210243730Srwatson 211243730Srwatson PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side); 212243730Srwatson} 213243730Srwatson 214243730Srwatsonstatic void 215243730Srwatsonsp_close(void *ctx) 216243730Srwatson{ 217243730Srwatson struct sp_ctx *spctx = ctx; 218243730Srwatson 219243730Srwatson PJDLOG_ASSERT(spctx != NULL); 220243730Srwatson PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC); 221243730Srwatson 222243730Srwatson switch (spctx->sp_side) { 223243730Srwatson case SP_SIDE_UNDEF: 224243730Srwatson PJDLOG_ASSERT(spctx->sp_fd[0] >= 0); 225243730Srwatson close(spctx->sp_fd[0]); 226243730Srwatson spctx->sp_fd[0] = -1; 227243730Srwatson PJDLOG_ASSERT(spctx->sp_fd[1] >= 0); 228243730Srwatson close(spctx->sp_fd[1]); 229243730Srwatson spctx->sp_fd[1] = -1; 230243730Srwatson break; 231243730Srwatson case SP_SIDE_CLIENT: 232243730Srwatson PJDLOG_ASSERT(spctx->sp_fd[0] >= 0); 233243730Srwatson close(spctx->sp_fd[0]); 234243730Srwatson spctx->sp_fd[0] = -1; 235243730Srwatson PJDLOG_ASSERT(spctx->sp_fd[1] == -1); 236243730Srwatson break; 237243730Srwatson case SP_SIDE_SERVER: 238243730Srwatson PJDLOG_ASSERT(spctx->sp_fd[1] >= 0); 239243730Srwatson close(spctx->sp_fd[1]); 240243730Srwatson spctx->sp_fd[1] = -1; 241243730Srwatson PJDLOG_ASSERT(spctx->sp_fd[0] == -1); 242243730Srwatson break; 243243730Srwatson default: 244243730Srwatson PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side); 245243730Srwatson } 246243730Srwatson 247243730Srwatson spctx->sp_magic = 0; 248243730Srwatson free(spctx); 249243730Srwatson} 250243730Srwatson 251243730Srwatsonstatic struct proto sp_proto = { 252243730Srwatson .prt_name = "socketpair", 253243730Srwatson .prt_connect = sp_connect, 254243730Srwatson .prt_wrap = sp_wrap, 255243730Srwatson .prt_send = sp_send, 256243730Srwatson .prt_recv = sp_recv, 257243730Srwatson .prt_descriptor = sp_descriptor, 258243730Srwatson .prt_close = sp_close 259243730Srwatson}; 260243730Srwatson 261243730Srwatsonstatic __constructor void 262243730Srwatsonsp_ctor(void) 263243730Srwatson{ 264243730Srwatson 265243730Srwatson proto_register(&sp_proto, false); 266243730Srwatson} 267