1223637Sbz/*	$OpenBSD: privsep_fdpass.c,v 1.5 2008/03/24 16:11:08 deraadt Exp $	*/
2130614Smlaier
3130614Smlaier/*
4130614Smlaier * Copyright 2001 Niels Provos <provos@citi.umich.edu>
5130614Smlaier * All rights reserved.
6130614Smlaier *
7130614Smlaier * Copyright (c) 2002 Matthieu Herrb
8130614Smlaier * All rights reserved.
9130614Smlaier *
10130614Smlaier * Redistribution and use in source and binary forms, with or without
11130614Smlaier * modification, are permitted provided that the following conditions
12130614Smlaier * are met:
13130614Smlaier *
14130614Smlaier *    - Redistributions of source code must retain the above copyright
15130614Smlaier *      notice, this list of conditions and the following disclaimer.
16130614Smlaier *    - Redistributions in binary form must reproduce the above
17130614Smlaier *      copyright notice, this list of conditions and the following
18130614Smlaier *      disclaimer in the documentation and/or other materials provided
19130614Smlaier *      with the distribution.
20130614Smlaier *
21130614Smlaier * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22130614Smlaier * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23130614Smlaier * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24130614Smlaier * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25130614Smlaier * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26130614Smlaier * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27130614Smlaier * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28130614Smlaier * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29130614Smlaier * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30130614Smlaier * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31130614Smlaier * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32130614Smlaier * POSSIBILITY OF SUCH DAMAGE.
33130614Smlaier */
34130614Smlaier#include <sys/param.h>
35130614Smlaier#include <sys/uio.h>
36130614Smlaier#include <sys/types.h>
37130614Smlaier#include <sys/socket.h>
38130614Smlaier#include <sys/stat.h>
39130614Smlaier#include <err.h>
40130614Smlaier#include <errno.h>
41130614Smlaier#include <fcntl.h>
42130614Smlaier#include <signal.h>
43130614Smlaier#include <stdio.h>
44130614Smlaier#include <stdlib.h>
45130614Smlaier#include <string.h>
46130614Smlaier#include <unistd.h>
47130614Smlaier#include "pflogd.h"
48130614Smlaier
49130614Smlaiervoid
50130614Smlaiersend_fd(int sock, int fd)
51130614Smlaier{
52130614Smlaier	struct msghdr msg;
53223637Sbz	union {
54223637Sbz		struct cmsghdr hdr;
55223637Sbz		char buf[CMSG_SPACE(sizeof(int))];
56223637Sbz	} cmsgbuf;
57130614Smlaier	struct cmsghdr *cmsg;
58130614Smlaier	struct iovec vec;
59130614Smlaier	int result = 0;
60130614Smlaier	ssize_t n;
61130614Smlaier
62130614Smlaier	memset(&msg, 0, sizeof(msg));
63130614Smlaier
64130614Smlaier	if (fd >= 0) {
65223637Sbz		msg.msg_control = (caddr_t)&cmsgbuf.buf;
66223637Sbz		msg.msg_controllen = sizeof(cmsgbuf.buf);
67130614Smlaier		cmsg = CMSG_FIRSTHDR(&msg);
68130614Smlaier		cmsg->cmsg_len = CMSG_LEN(sizeof(int));
69130614Smlaier		cmsg->cmsg_level = SOL_SOCKET;
70130614Smlaier		cmsg->cmsg_type = SCM_RIGHTS;
71130614Smlaier		*(int *)CMSG_DATA(cmsg) = fd;
72130614Smlaier	} else {
73130614Smlaier		result = errno;
74130614Smlaier	}
75130614Smlaier
76130614Smlaier	vec.iov_base = &result;
77130614Smlaier	vec.iov_len = sizeof(int);
78130614Smlaier	msg.msg_iov = &vec;
79130614Smlaier	msg.msg_iovlen = 1;
80130614Smlaier
81130614Smlaier	if ((n = sendmsg(sock, &msg, 0)) == -1)
82130614Smlaier		warn("%s: sendmsg(%d)", __func__, sock);
83130614Smlaier	if (n != sizeof(int))
84130614Smlaier		warnx("%s: sendmsg: expected sent 1 got %ld",
85130614Smlaier		    __func__, (long)n);
86130614Smlaier}
87130614Smlaier
88130614Smlaierint
89130614Smlaierreceive_fd(int sock)
90130614Smlaier{
91130614Smlaier	struct msghdr msg;
92223637Sbz	union {
93223637Sbz		struct cmsghdr hdr;
94223637Sbz		char buf[CMSG_SPACE(sizeof(int))];
95223637Sbz	} cmsgbuf;
96130614Smlaier	struct cmsghdr *cmsg;
97130614Smlaier	struct iovec vec;
98130614Smlaier	ssize_t n;
99130614Smlaier	int result;
100130614Smlaier	int fd;
101130614Smlaier
102130614Smlaier	memset(&msg, 0, sizeof(msg));
103130614Smlaier	vec.iov_base = &result;
104130614Smlaier	vec.iov_len = sizeof(int);
105130614Smlaier	msg.msg_iov = &vec;
106130614Smlaier	msg.msg_iovlen = 1;
107223637Sbz	msg.msg_control = &cmsgbuf.buf;
108223637Sbz	msg.msg_controllen = sizeof(cmsgbuf.buf);
109130614Smlaier
110130614Smlaier	if ((n = recvmsg(sock, &msg, 0)) == -1)
111130614Smlaier		warn("%s: recvmsg", __func__);
112130614Smlaier	if (n != sizeof(int))
113130614Smlaier		warnx("%s: recvmsg: expected received 1 got %ld",
114130614Smlaier		    __func__, (long)n);
115130614Smlaier	if (result == 0) {
116130614Smlaier		cmsg = CMSG_FIRSTHDR(&msg);
117145837Smlaier		if (cmsg == NULL) {
118145837Smlaier			warnx("%s: no message header", __func__);
119145837Smlaier			return -1;
120145837Smlaier		}
121130614Smlaier		if (cmsg->cmsg_type != SCM_RIGHTS)
122130614Smlaier			warnx("%s: expected type %d got %d", __func__,
123130614Smlaier			    SCM_RIGHTS, cmsg->cmsg_type);
124130614Smlaier		fd = (*(int *)CMSG_DATA(cmsg));
125130614Smlaier		return fd;
126130614Smlaier	} else {
127130614Smlaier		errno = result;
128130614Smlaier		return -1;
129130614Smlaier	}
130130614Smlaier}
131