proto_common.c revision 218139
153813Simp/*- 2180314Simp * Copyright (c) 2009-2010 The FreeBSD Foundation 3100213Simp * All rights reserved. 452506Simp * 552506Simp * This software was developed by Pawel Jakub Dawidek under sponsorship from 6140752Simp * the FreeBSD Foundation. 752506Simp * 852506Simp * Redistribution and use in source and binary forms, with or without 952506Simp * modification, are permitted provided that the following conditions 1052506Simp * are met: 1152506Simp * 1. Redistributions of source code must retain the above copyright 1252506Simp * notice, this list of conditions and the following disclaimer. 1352506Simp * 2. Redistributions in binary form must reproduce the above copyright 1452506Simp * notice, this list of conditions and the following disclaimer in the 1552506Simp * documentation and/or other materials provided with the distribution. 1652506Simp * 1752506Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 1852506Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1952506Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2052506Simp * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 2152506Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2252506Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2352506Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2452506Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2552506Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2652506Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2752506Simp * SUCH DAMAGE. 2852506Simp */ 2952506Simp 3052506Simp#include <sys/cdefs.h> 3152506Simp__FBSDID("$FreeBSD: head/sbin/hastd/proto_common.c 218139 2011-01-31 18:35:17Z pjd $"); 3252506Simp 3352506Simp#include <sys/types.h> 34140752Simp#include <sys/socket.h> 35140752Simp 36140752Simp#include <errno.h> 37140752Simp#include <stdlib.h> 38140752Simp#include <strings.h> 39140752Simp 40140752Simp#include "pjdlog.h" 41140752Simp#include "proto_impl.h" 42140752Simp 43140752Simp/* Maximum size of packet we want to use when sending data. */ 44140752Simp#ifndef MAX_SEND_SIZE 45140752Simp#define MAX_SEND_SIZE 32768 46140752Simp#endif 47140752Simp 48140752Simpint 49140752Simpproto_common_send(int sock, const unsigned char *data, size_t size) 50140752Simp{ 51140752Simp ssize_t done; 52140752Simp size_t sendsize; 53140752Simp 54140752Simp PJDLOG_ASSERT(sock >= 0); 55140752Simp PJDLOG_ASSERT(data != NULL); 56140752Simp PJDLOG_ASSERT(size > 0); 57140752Simp 58140752Simp do { 59140752Simp sendsize = size < MAX_SEND_SIZE ? size : MAX_SEND_SIZE; 60140752Simp done = send(sock, data, sendsize, MSG_NOSIGNAL); 6152506Simp if (done == 0) 62140749Simp return (ENOTCONN); 63166788Simp else if (done < 0) { 64140749Simp if (errno == EINTR) 65140749Simp continue; 66140749Simp return (errno); 67149869Simp } 68149869Simp data += done; 69149561Simp size -= done; 70166787Simp } while (size > 0); 71166787Simp 72166787Simp return (0); 73166787Simp} 74149869Simp 75149869Simpint 7652506Simpproto_common_recv(int sock, unsigned char *data, size_t size) 77140793Simp{ 78189680Simp ssize_t done; 79140793Simp 8058545Simp PJDLOG_ASSERT(sock >= 0); 8152506Simp PJDLOG_ASSERT(data != NULL); 8265039Simp PJDLOG_ASSERT(size > 0); 8365039Simp 84149869Simp do { 8552506Simp done = recv(sock, data, size, MSG_WAITALL); 86140793Simp } while (done == -1 && errno == EINTR); 87149869Simp if (done == 0) 88149869Simp return (ENOTCONN); 89149869Simp else if (done < 0) 90149869Simp return (errno); 91149869Simp return (0); 92149869Simp} 93149869Simp 94149869Simpint 95149869Simpproto_common_descriptor_send(int sock, int fd) 96140793Simp{ 9752506Simp unsigned char ctrl[CMSG_SPACE(sizeof(fd))]; 9852506Simp struct msghdr msg; 9952506Simp struct cmsghdr *cmsg; 10052506Simp 10158545Simp PJDLOG_ASSERT(sock >= 0); 10252506Simp PJDLOG_ASSERT(fd >= 0); 10386455Simp 10479270Simp bzero(&msg, sizeof(msg)); 105107359Snon bzero(&ctrl, sizeof(ctrl)); 10652506Simp 10786269Simp msg.msg_iov = NULL; 10886455Simp msg.msg_iovlen = 0; 109119225Simp msg.msg_control = ctrl; 11052506Simp msg.msg_controllen = sizeof(ctrl); 111140749Simp 11286455Simp cmsg = CMSG_FIRSTHDR(&msg); 11358545Simp cmsg->cmsg_level = SOL_SOCKET; 114104854Simp cmsg->cmsg_type = SCM_RIGHTS; 115140886Simp cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); 11652506Simp *((int *)CMSG_DATA(cmsg)) = fd; 11786455Simp 11852506Simp if (sendmsg(sock, &msg, 0) == -1) 11986455Simp return (errno); 12053813Simp 121148141Simp return (0); 122100213Simp} 12358545Simp 12489945Simpint 12584514Simpproto_common_descriptor_recv(int sock, int *fdp) 126147872Simp{ 12758545Simp unsigned char ctrl[CMSG_SPACE(sizeof(*fdp))]; 128119234Simp struct msghdr msg; 12969138Speter struct cmsghdr *cmsg; 130118634Simp 131149561Simp PJDLOG_ASSERT(sock >= 0); 132172572Sremko PJDLOG_ASSERT(fdp != NULL); 13352506Simp 13458545Simp bzero(&msg, sizeof(msg)); 135140837Simp bzero(&ctrl, sizeof(ctrl)); 136140793Simp 137140793Simp msg.msg_iov = NULL; 138147872Simp msg.msg_iovlen = 0; 139140793Simp msg.msg_control = ctrl; 140176868Srink msg.msg_controllen = sizeof(ctrl); 14158545Simp 14265039Simp if (recvmsg(sock, &msg, 0) == -1) 14392471Simp return (errno); 144140793Simp 145116207Simp for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; 14684514Simp cmsg = CMSG_NXTHDR(&msg, cmsg)) { 14779270Simp if (cmsg->cmsg_level == SOL_SOCKET && 148140793Simp cmsg->cmsg_type == SCM_RIGHTS) { 14979270Simp *fdp = *((int *)CMSG_DATA(cmsg)); 150180314Simp return (0); 151117438Simp } 152117602Simp } 153148141Simp 154118895Simp return (ENOENT); 155119240Simp} 156119240Simp