proto_socketpair.c revision 204076
11539Srgrimes/*- 21539Srgrimes * Copyright (c) 2009-2010 The FreeBSD Foundation 31539Srgrimes * All rights reserved. 41539Srgrimes * 51539Srgrimes * This software was developed by Pawel Jakub Dawidek under sponsorship from 61539Srgrimes * the FreeBSD Foundation. 71539Srgrimes * 81539Srgrimes * Redistribution and use in source and binary forms, with or without 91539Srgrimes * modification, are permitted provided that the following conditions 101539Srgrimes * are met: 111539Srgrimes * 1. Redistributions of source code must retain the above copyright 121539Srgrimes * notice, this list of conditions and the following disclaimer. 131539Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141539Srgrimes * notice, this list of conditions and the following disclaimer in the 151539Srgrimes * documentation and/or other materials provided with the distribution. 161539Srgrimes * 171539Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 181539Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191539Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201539Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 211539Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221539Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231539Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241539Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251539Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261539Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271539Srgrimes * SUCH DAMAGE. 281539Srgrimes */ 291539Srgrimes 301539Srgrimes#include <sys/cdefs.h> 311539Srgrimes__FBSDID("$FreeBSD: head/sbin/hastd/proto_socketpair.c 204076 2010-02-18 23:16:19Z pjd $"); 321539Srgrimes 331539Srgrimes#include <sys/types.h> 341539Srgrimes#include <sys/socket.h> 351539Srgrimes 3623655Speter#include <assert.h> 3750473Speter#include <errno.h> 381539Srgrimes#include <stdbool.h> 391539Srgrimes#include <stdint.h> 401539Srgrimes#include <stdio.h> 411539Srgrimes#include <string.h> 421539Srgrimes#include <unistd.h> 431539Srgrimes 4424897Sbde#include "hast.h" 451539Srgrimes#include "proto_impl.h" 461539Srgrimes 471539Srgrimes#define SP_CTX_MAGIC 0x50c3741 481539Srgrimesstruct sp_ctx { 491539Srgrimes int sp_magic; 501539Srgrimes int sp_fd[2]; 511539Srgrimes int sp_side; 521539Srgrimes#define SP_SIDE_UNDEF 0 531539Srgrimes#define SP_SIDE_CLIENT 1 541539Srgrimes#define SP_SIDE_SERVER 2 5524897Sbde}; 561539Srgrimes 571539Srgrimesstatic void sp_close(void *ctx); 581539Srgrimes 591539Srgrimesstatic int 601539Srgrimessp_client(const char *addr, void **ctxp) 611539Srgrimes{ 621539Srgrimes struct sp_ctx *spctx; 631539Srgrimes int ret; 641539Srgrimes 651539Srgrimes if (strcmp(addr, "socketpair://") != 0) 661539Srgrimes return (-1); 671539Srgrimes 681539Srgrimes spctx = malloc(sizeof(*spctx)); 691539Srgrimes if (spctx == NULL) 701539Srgrimes return (errno); 7172529Simp 7273254Sdeischen if (socketpair(PF_UNIX, SOCK_STREAM, 0, spctx->sp_fd) < 0) { 7372529Simp ret = errno; 741539Srgrimes free(spctx); 751539Srgrimes return (ret); 761539Srgrimes } 771539Srgrimes 781539Srgrimes spctx->sp_side = SP_SIDE_UNDEF; 791539Srgrimes spctx->sp_magic = SP_CTX_MAGIC; 801539Srgrimes *ctxp = spctx; 811539Srgrimes 821539Srgrimes return (0); 831539Srgrimes} 841539Srgrimes 851539Srgrimesstatic int 861539Srgrimessp_connect(void *ctx __unused) 871539Srgrimes{ 881539Srgrimes 891539Srgrimes assert(!"proto_connect() not supported on socketpairs"); 901539Srgrimes abort(); 911539Srgrimes} 921539Srgrimes 931539Srgrimesstatic int 941539Srgrimessp_server(const char *addr __unused, void **ctxp __unused) 951539Srgrimes{ 961539Srgrimes 971539Srgrimes assert(!"proto_server() not supported on socketpairs"); 981539Srgrimes abort(); 991539Srgrimes} 1001539Srgrimes 1011539Srgrimesstatic int 1021539Srgrimessp_accept(void *ctx __unused, void **newctxp __unused) 1031539Srgrimes{ 1041539Srgrimes 1051539Srgrimes assert(!"proto_server() not supported on socketpairs"); 1061539Srgrimes abort(); 1071539Srgrimes} 1081539Srgrimes 1091539Srgrimesstatic int 1101539Srgrimessp_send(void *ctx, const unsigned char *data, size_t size) 11193032Simp{ 11293032Simp struct sp_ctx *spctx = ctx; 11393032Simp int fd; 11493032Simp 1151539Srgrimes assert(spctx != NULL); 1161539Srgrimes assert(spctx->sp_magic == SP_CTX_MAGIC); 1171539Srgrimes 11872529Simp switch (spctx->sp_side) { 1191539Srgrimes case SP_SIDE_UNDEF: 1201539Srgrimes /* 1211539Srgrimes * If the first operation done by the caller is proto_send(), 1221539Srgrimes * we assume this the client. 1231539Srgrimes */ 1241539Srgrimes /* FALLTHROUGH */ 1251539Srgrimes spctx->sp_side = SP_SIDE_CLIENT; 1261539Srgrimes /* Close other end. */ 1271539Srgrimes close(spctx->sp_fd[1]); 1281539Srgrimes case SP_SIDE_CLIENT: 1291539Srgrimes assert(spctx->sp_fd[0] >= 0); 1301539Srgrimes fd = spctx->sp_fd[0]; 1311539Srgrimes break; 1321539Srgrimes case SP_SIDE_SERVER: 1331539Srgrimes assert(spctx->sp_fd[1] >= 0); 13472529Simp fd = spctx->sp_fd[1]; 13581600Speter break; 13681600Speter default: 13781600Speter abort(); 1381539Srgrimes } 1391539Srgrimes 1401539Srgrimes return (proto_common_send(fd, data, size)); 1411539Srgrimes} 1421539Srgrimes 1431539Srgrimesstatic int 1441539Srgrimessp_recv(void *ctx, unsigned char *data, size_t size) 1451539Srgrimes{ 1461539Srgrimes struct sp_ctx *spctx = ctx; 1471539Srgrimes int fd; 1481539Srgrimes 1491539Srgrimes assert(spctx != NULL); 1501539Srgrimes assert(spctx->sp_magic == SP_CTX_MAGIC); 15113771Smpp 15213771Smpp switch (spctx->sp_side) { 1531539Srgrimes case SP_SIDE_UNDEF: 1541539Srgrimes /* 15537489Speter * If the first operation done by the caller is proto_recv(), 15672372Sdeischen * we assume this the server. 1571539Srgrimes */ 1581539Srgrimes /* FALLTHROUGH */ 1591539Srgrimes spctx->sp_side = SP_SIDE_SERVER; 1601539Srgrimes /* Close other end. */ 1611539Srgrimes close(spctx->sp_fd[0]); 1621539Srgrimes case SP_SIDE_SERVER: 1631539Srgrimes assert(spctx->sp_fd[1] >= 0); 1641539Srgrimes fd = spctx->sp_fd[1]; 1651539Srgrimes break; 1661539Srgrimes case SP_SIDE_CLIENT: 1671539Srgrimes assert(spctx->sp_fd[0] >= 0); 1681539Srgrimes fd = spctx->sp_fd[0]; 1691539Srgrimes break; 1701539Srgrimes default: 1711539Srgrimes abort(); 1721539Srgrimes } 1731539Srgrimes 1741539Srgrimes return (proto_common_recv(fd, data, size)); 1751539Srgrimes} 1761539Srgrimes 1771539Srgrimesstatic int 1781539Srgrimessp_descriptor(const void *ctx) 1791539Srgrimes{ 1801539Srgrimes const struct sp_ctx *spctx = ctx; 1811539Srgrimes 1821539Srgrimes assert(spctx != NULL); 1831539Srgrimes assert(spctx->sp_magic == SP_CTX_MAGIC); 184100133Swollman assert(spctx->sp_side == SP_SIDE_CLIENT || 1851539Srgrimes spctx->sp_side == SP_SIDE_SERVER); 1861539Srgrimes 1871539Srgrimes switch (spctx->sp_side) { 1881539Srgrimes case SP_SIDE_CLIENT: 1891539Srgrimes assert(spctx->sp_fd[0] >= 0); 1901539Srgrimes return (spctx->sp_fd[0]); 1911539Srgrimes case SP_SIDE_SERVER: 1921539Srgrimes assert(spctx->sp_fd[1] >= 0); 1931539Srgrimes return (spctx->sp_fd[1]); 1941539Srgrimes } 1951539Srgrimes 1961539Srgrimes abort(); 1971539Srgrimes} 1981539Srgrimes 1991539Srgrimesstatic bool 20081600Spetersp_address_match(const void *ctx __unused, const char *addr __unused) 20183712Speter{ 20272529Simp 20372529Simp assert(!"proto_address_match() not supported on socketpairs"); 20472529Simp abort(); 20581600Speter} 20681600Speter 20781600Speterstatic void 20881600Spetersp_local_address(const void *ctx __unused, char *addr __unused, 20981600Speter size_t size __unused) 2101539Srgrimes{ 211100133Swollman 2121539Srgrimes assert(!"proto_local_address() not supported on socketpairs"); 2131539Srgrimes abort(); 2141539Srgrimes} 21593032Simp 21693032Simpstatic void 21793032Simpsp_remote_address(const void *ctx __unused, char *addr __unused, 21893032Simp size_t size __unused) 21993032Simp{ 22093032Simp 22193032Simp assert(!"proto_remote_address() not supported on socketpairs"); 22293032Simp abort(); 22393032Simp} 22493032Simp 22593032Simpstatic void 22693032Simpsp_close(void *ctx) 22793032Simp{ 22893032Simp struct sp_ctx *spctx = ctx; 22993032Simp 23093032Simp assert(spctx != NULL); 23193032Simp assert(spctx->sp_magic == SP_CTX_MAGIC); 23293032Simp 23393032Simp switch (spctx->sp_side) { 23493032Simp case SP_SIDE_UNDEF: 23593032Simp close(spctx->sp_fd[0]); 23693032Simp close(spctx->sp_fd[1]); 23793032Simp break; 23893032Simp case SP_SIDE_CLIENT: 23993032Simp close(spctx->sp_fd[0]); 24093032Simp break; 24193032Simp case SP_SIDE_SERVER: 24293032Simp close(spctx->sp_fd[1]); 24393032Simp break; 24493032Simp default: 24593032Simp abort(); 24693032Simp } 24793032Simp 24893032Simp spctx->sp_magic = 0; 24993032Simp free(spctx); 25093032Simp} 25193032Simp 25293032Simpstatic struct hast_proto sp_proto = { 25393032Simp .hp_name = "socketpair", 25493032Simp .hp_client = sp_client, 25593032Simp .hp_connect = sp_connect, 2561539Srgrimes .hp_server = sp_server, 257100133Swollman .hp_accept = sp_accept, 258100133Swollman .hp_send = sp_send, 259100133Swollman .hp_recv = sp_recv, 260100133Swollman .hp_descriptor = sp_descriptor, 261100133Swollman .hp_address_match = sp_address_match, 262100133Swollman .hp_local_address = sp_local_address, 2631539Srgrimes .hp_remote_address = sp_remote_address, 264100133Swollman .hp_close = sp_close 2651539Srgrimes}; 266100133Swollman 26719211Swoschstatic __constructor void 26823260Sachesp_ctor(void) 2691539Srgrimes{ 27019211Swosch 27119211Swosch proto_register(&sp_proto); 27293032Simp} 27393032Simp