proto_socketpair.c revision 231017
1132744Skan/*- 290285Sobrien * Copyright (c) 2009-2010 The FreeBSD Foundation 3132744Skan * All rights reserved. 418334Speter * 5132744Skan * This software was developed by Pawel Jakub Dawidek under sponsorship from 618334Speter * the FreeBSD Foundation. 7132744Skan * 818334Speter * Redistribution and use in source and binary forms, with or without 918334Speter * modification, are permitted provided that the following conditions 1018334Speter * are met: 1118334Speter * 1. Redistributions of source code must retain the above copyright 12132744Skan * notice, this list of conditions and the following disclaimer. 1318334Speter * 2. Redistributions in binary form must reproduce the above copyright 1418334Speter * notice, this list of conditions and the following disclaimer in the 1518334Speter * documentation and/or other materials provided with the distribution. 1618334Speter * 1718334Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 18132744Skan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1918334Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2090285Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 2118334Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2218334Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2318334Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2418334Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2518334Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2618334Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2718334Speter * SUCH DAMAGE. 2818334Speter */ 2918334Speter 3018334Speter#include <sys/cdefs.h> 3118334Speter__FBSDID("$FreeBSD: stable/9/sbin/hastd/proto_socketpair.c 231017 2012-02-05 15:51:19Z trociny $"); 3218334Speter 3390285Sobrien#include <sys/types.h> 3490285Sobrien#include <sys/socket.h> 3590285Sobrien 3618334Speter#include <errno.h> 3750654Sobrien#include <stdbool.h> 3850654Sobrien#include <stdint.h> 3950654Sobrien#include <stdio.h> 4090285Sobrien#include <string.h> 4190285Sobrien#include <unistd.h> 4290285Sobrien 4390285Sobrien#include "pjdlog.h" 44132744Skan#include "proto_impl.h" 45132744Skan 4690285Sobrien#define SP_CTX_MAGIC 0x50c3741 47132744Skanstruct sp_ctx { 48132744Skan int sp_magic; 4990285Sobrien int sp_fd[2]; 5090285Sobrien int sp_side; 5190285Sobrien#define SP_SIDE_UNDEF 0 5290285Sobrien#define SP_SIDE_CLIENT 1 5390285Sobrien#define SP_SIDE_SERVER 2 5490285Sobrien}; 5590285Sobrien 5690285Sobrienstatic void sp_close(void *ctx); 5790285Sobrien 5890285Sobrienstatic int 5990285Sobriensp_client(const char *srcaddr, const char *dstaddr, void **ctxp) 6090285Sobrien{ 6190285Sobrien struct sp_ctx *spctx; 6290285Sobrien int ret; 6390285Sobrien 6490285Sobrien if (strcmp(dstaddr, "socketpair://") != 0) 6590285Sobrien return (-1); 6690285Sobrien 6790285Sobrien PJDLOG_ASSERT(srcaddr == NULL); 6890285Sobrien 6990285Sobrien spctx = malloc(sizeof(*spctx)); 7090285Sobrien if (spctx == NULL) 7190285Sobrien return (errno); 7290285Sobrien 7390285Sobrien if (socketpair(PF_UNIX, SOCK_STREAM, 0, spctx->sp_fd) == -1) { 7490285Sobrien ret = errno; 7590285Sobrien free(spctx); 7690285Sobrien return (ret); 7790285Sobrien } 7890285Sobrien 7990285Sobrien spctx->sp_side = SP_SIDE_UNDEF; 80132744Skan spctx->sp_magic = SP_CTX_MAGIC; 81117407Skan *ctxp = spctx; 82117407Skan 83117407Skan return (0); 84117407Skan} 85117407Skan 86117407Skanstatic int 8750654Sobriensp_send(void *ctx, const unsigned char *data, size_t size, int fd) 8850654Sobrien{ 8990285Sobrien struct sp_ctx *spctx = ctx; 9050654Sobrien int sock; 9118334Speter 9218334Speter PJDLOG_ASSERT(spctx != NULL); 9318334Speter PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC); 9418334Speter 9518334Speter switch (spctx->sp_side) { 9618334Speter case SP_SIDE_UNDEF: 9718334Speter /* 9890285Sobrien * If the first operation done by the caller is proto_send(), 9918334Speter * we assume this is the client. 100132744Skan */ 101132744Skan /* FALLTHROUGH */ 102132744Skan spctx->sp_side = SP_SIDE_CLIENT; 10318334Speter /* Close other end. */ 10418334Speter close(spctx->sp_fd[1]); 105132744Skan spctx->sp_fd[1] = -1; 10618334Speter case SP_SIDE_CLIENT: 10718334Speter PJDLOG_ASSERT(spctx->sp_fd[0] >= 0); 10890285Sobrien sock = spctx->sp_fd[0]; 10990285Sobrien break; 11090285Sobrien case SP_SIDE_SERVER: 11190285Sobrien PJDLOG_ASSERT(spctx->sp_fd[1] >= 0); 11290285Sobrien sock = spctx->sp_fd[1]; 11390285Sobrien break; 11490285Sobrien default: 11590285Sobrien PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side); 11690285Sobrien } 11790285Sobrien 11890285Sobrien /* Someone is just trying to decide about side. */ 11990285Sobrien if (data == NULL) 12090285Sobrien return (0); 121117407Skan 122117407Skan return (proto_common_send(sock, data, size, fd)); 123117407Skan} 124132744Skan 125122193Skanstatic int 126122193Skansp_recv(void *ctx, unsigned char *data, size_t size, int *fdp) 127122193Skan{ 128122193Skan struct sp_ctx *spctx = ctx; 129132744Skan int fd; 130132744Skan 131117407Skan PJDLOG_ASSERT(spctx != NULL); 132132744Skan PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC); 133117407Skan 13490285Sobrien switch (spctx->sp_side) { 13590285Sobrien case SP_SIDE_UNDEF: 13697911Sobrien /* 13718334Speter * If the first operation done by the caller is proto_recv(), 13818334Speter * we assume this is the server. 13918334Speter */ 14018334Speter /* FALLTHROUGH */ 14118334Speter spctx->sp_side = SP_SIDE_SERVER; 14218334Speter /* Close other end. */ 143117407Skan close(spctx->sp_fd[0]); 14418334Speter spctx->sp_fd[0] = -1; 14518334Speter case SP_SIDE_SERVER: 14618334Speter PJDLOG_ASSERT(spctx->sp_fd[1] >= 0); 14718334Speter fd = spctx->sp_fd[1]; 14818334Speter break; 14918334Speter case SP_SIDE_CLIENT: 15018334Speter PJDLOG_ASSERT(spctx->sp_fd[0] >= 0); 15190285Sobrien fd = spctx->sp_fd[0]; 15290285Sobrien break; 15390285Sobrien default: 15490285Sobrien PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side); 15590285Sobrien } 15690285Sobrien 15790285Sobrien /* Someone is just trying to decide about side. */ 15818334Speter if (data == NULL) 15918334Speter return (0); 16018334Speter 16118334Speter return (proto_common_recv(fd, data, size, fdp)); 16218334Speter} 16318334Speter 16418334Speterstatic int 16518334Spetersp_descriptor(const void *ctx) 16618334Speter{ 16718334Speter const struct sp_ctx *spctx = ctx; 16818334Speter 16990285Sobrien PJDLOG_ASSERT(spctx != NULL); 17018334Speter PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC); 17118334Speter PJDLOG_ASSERT(spctx->sp_side == SP_SIDE_CLIENT || 17290285Sobrien spctx->sp_side == SP_SIDE_SERVER); 17390285Sobrien 17490285Sobrien switch (spctx->sp_side) { 17590285Sobrien case SP_SIDE_CLIENT: 17690285Sobrien PJDLOG_ASSERT(spctx->sp_fd[0] >= 0); 17718334Speter return (spctx->sp_fd[0]); 17818334Speter case SP_SIDE_SERVER: 17918334Speter PJDLOG_ASSERT(spctx->sp_fd[1] >= 0); 18018334Speter return (spctx->sp_fd[1]); 18150654Sobrien } 18290285Sobrien 18390285Sobrien PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side); 18450654Sobrien} 18518334Speter 18690285Sobrienstatic void 18718334Spetersp_close(void *ctx) 18818334Speter{ 18990285Sobrien struct sp_ctx *spctx = ctx; 19018334Speter 191117407Skan PJDLOG_ASSERT(spctx != NULL); 192117407Skan PJDLOG_ASSERT(spctx->sp_magic == SP_CTX_MAGIC); 193117407Skan 194117407Skan switch (spctx->sp_side) { 195117407Skan case SP_SIDE_UNDEF: 196117407Skan PJDLOG_ASSERT(spctx->sp_fd[0] >= 0); 197117407Skan close(spctx->sp_fd[0]); 198117407Skan spctx->sp_fd[0] = -1; 199117407Skan PJDLOG_ASSERT(spctx->sp_fd[1] >= 0); 20090285Sobrien close(spctx->sp_fd[1]); 20190285Sobrien spctx->sp_fd[1] = -1; 20290285Sobrien break; 203117407Skan case SP_SIDE_CLIENT: 20490285Sobrien PJDLOG_ASSERT(spctx->sp_fd[0] >= 0); 20590285Sobrien close(spctx->sp_fd[0]); 20690285Sobrien spctx->sp_fd[0] = -1; 20790285Sobrien PJDLOG_ASSERT(spctx->sp_fd[1] == -1); 20890285Sobrien break; 209117407Skan case SP_SIDE_SERVER: 21018334Speter PJDLOG_ASSERT(spctx->sp_fd[1] >= 0); 211132744Skan close(spctx->sp_fd[1]); 212132744Skan spctx->sp_fd[1] = -1; 21352295Sobrien PJDLOG_ASSERT(spctx->sp_fd[0] == -1); 214132744Skan break; 215132744Skan default: 216132744Skan PJDLOG_ABORT("Invalid socket side (%d).", spctx->sp_side); 217132744Skan } 218132744Skan 219132744Skan spctx->sp_magic = 0; 220132744Skan free(spctx); 221132744Skan} 222132744Skan 223132744Skanstatic struct proto sp_proto = { 224132744Skan .prt_name = "socketpair", 22552295Sobrien .prt_client = sp_client, 22652295Sobrien .prt_send = sp_send, 22790285Sobrien .prt_recv = sp_recv, 22890285Sobrien .prt_descriptor = sp_descriptor, 22990285Sobrien .prt_close = sp_close 23090285Sobrien}; 23190285Sobrien 232117407Skanstatic __constructor void 23390285Sobriensp_ctor(void) 23490285Sobrien{ 23590285Sobrien 23690285Sobrien proto_register(&sp_proto, false); 23790285Sobrien} 23890285Sobrien