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