11558Srgrimes/*
21558Srgrimes * Copyright (c) 1992, 1993
31558Srgrimes *	The Regents of the University of California.  All rights reserved.
41558Srgrimes * All rights reserved.
51558Srgrimes *
61558Srgrimes * This code is derived from software donated to Berkeley by
71558Srgrimes * Jan-Simon Pendry.
81558Srgrimes *
91558Srgrimes * Redistribution and use in source and binary forms, with or without
101558Srgrimes * modification, are permitted provided that the following conditions
111558Srgrimes * are met:
121558Srgrimes * 1. Redistributions of source code must retain the above copyright
131558Srgrimes *    notice, this list of conditions and the following disclaimer.
141558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
151558Srgrimes *    notice, this list of conditions and the following disclaimer in the
161558Srgrimes *    documentation and/or other materials provided with the distribution.
171558Srgrimes * 4. Neither the name of the University nor the names of its contributors
181558Srgrimes *    may be used to endorse or promote products derived from this software
191558Srgrimes *    without specific prior written permission.
201558Srgrimes *
211558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
221558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241558Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
251558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
301558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311558Srgrimes * SUCH DAMAGE.
321558Srgrimes *
3323680Speter *	@(#)activate.c	8.3 (Berkeley) 4/28/95
341558Srgrimes */
351558Srgrimes
36129862Sstefanf#include <sys/cdefs.h>
37129862Sstefanf__FBSDID("$FreeBSD$");
3837429Scharnier
3937429Scharnier#include <errno.h>
4037429Scharnier#include <string.h>
411558Srgrimes#include <unistd.h>
421558Srgrimes#include <sys/types.h>
431558Srgrimes#include <sys/param.h>
441558Srgrimes#include <sys/socket.h>
451558Srgrimes#include <sys/syslog.h>
461558Srgrimes#include <sys/uio.h>
471558Srgrimes
481558Srgrimes#include "portald.h"
491558Srgrimes
501558Srgrimes/*
511558Srgrimes * Scan the providers list and call the
521558Srgrimes * appropriate function.
531558Srgrimes */
54166157Srodrigcstatic int activate_argv(struct portal_cred *pcr, char *key, char **v, int so,
55166157Srodrigc    int *fdp)
561558Srgrimes{
571558Srgrimes	provider *pr;
581558Srgrimes
591558Srgrimes	for (pr = providers; pr->pr_match; pr++)
601558Srgrimes		if (strcmp(v[0], pr->pr_match) == 0)
611558Srgrimes			return ((*pr->pr_func)(pcr, key, v, so, fdp));
621558Srgrimes
631558Srgrimes	return (ENOENT);
641558Srgrimes}
651558Srgrimes
66166157Srodrigcstatic int get_request(int so, struct portal_cred *pcr, char *key, int klen)
671558Srgrimes{
681558Srgrimes	struct iovec iov[2];
691558Srgrimes	struct msghdr msg;
701558Srgrimes	int n;
711558Srgrimes
721558Srgrimes	iov[0].iov_base = (caddr_t) pcr;
731558Srgrimes	iov[0].iov_len = sizeof(*pcr);
741558Srgrimes	iov[1].iov_base = key;
751558Srgrimes	iov[1].iov_len = klen;
761558Srgrimes
7723680Speter	memset(&msg, 0, sizeof(msg));
781558Srgrimes	msg.msg_iov = iov;
791558Srgrimes	msg.msg_iovlen = 2;
801558Srgrimes
811558Srgrimes	n = recvmsg(so, &msg, 0);
821558Srgrimes	if (n < 0)
831558Srgrimes		return (errno);
841558Srgrimes
85166157Srodrigc	if (n <= (int)sizeof(*pcr))
861558Srgrimes		return (EINVAL);
871558Srgrimes
881558Srgrimes	n -= sizeof(*pcr);
891558Srgrimes	key[n] = '\0';
901558Srgrimes
911558Srgrimes	return (0);
921558Srgrimes}
931558Srgrimes
94166157Srodrigcstatic void send_reply(int so, int fd, int error)
951558Srgrimes{
961558Srgrimes	int n;
971558Srgrimes	struct iovec iov;
981558Srgrimes	struct msghdr msg;
9984472Sdwmalone	union {
1001558Srgrimes		struct cmsghdr cmsg;
10184472Sdwmalone		char control[CMSG_SPACE(sizeof(int))];
1021558Srgrimes	} ctl;
1031558Srgrimes
1041558Srgrimes	/*
1051558Srgrimes	 * Line up error code.  Don't worry about byte ordering
1061558Srgrimes	 * because we must be sending to the local machine.
1071558Srgrimes	 */
1081558Srgrimes	iov.iov_base = (caddr_t) &error;
1091558Srgrimes	iov.iov_len = sizeof(error);
1101558Srgrimes
1111558Srgrimes	/*
1121558Srgrimes	 * Build a msghdr
1131558Srgrimes	 */
11423680Speter	memset(&msg, 0, sizeof(msg));
1151558Srgrimes	msg.msg_iov = &iov;
1161558Srgrimes	msg.msg_iovlen = 1;
1171558Srgrimes
1181558Srgrimes	/*
1191558Srgrimes	 * If there is a file descriptor to send then
1201558Srgrimes	 * construct a suitable rights control message.
1211558Srgrimes	 */
1221558Srgrimes	if (fd >= 0) {
12384472Sdwmalone		ctl.cmsg.cmsg_len = CMSG_LEN(sizeof(int));
1241558Srgrimes		ctl.cmsg.cmsg_level = SOL_SOCKET;
1251558Srgrimes		ctl.cmsg.cmsg_type = SCM_RIGHTS;
12684472Sdwmalone		*((int *)CMSG_DATA(&ctl.cmsg)) = fd;
1271558Srgrimes		msg.msg_control = (caddr_t) &ctl;
1281558Srgrimes		msg.msg_controllen = ctl.cmsg.cmsg_len;
1291558Srgrimes	}
1301558Srgrimes
1311558Srgrimes	/*
1321558Srgrimes	 * Send to kernel...
1331558Srgrimes	 */
13441701Sdillon	if ((n = sendmsg(so, &msg, 0)) < 0)
1351558Srgrimes		syslog(LOG_ERR, "send: %s", strerror(errno));
1361558Srgrimes#ifdef DEBUG
1371558Srgrimes	fprintf(stderr, "sent %d bytes\n", n);
1381558Srgrimes#endif
1391558Srgrimes	sleep(1);	/*XXX*/
1401558Srgrimes#ifdef notdef
141146077Sjmallett	if (shutdown(so, SHUT_RDWR) < 0)
1421558Srgrimes		syslog(LOG_ERR, "shutdown: %s", strerror(errno));
1431558Srgrimes#endif
1441558Srgrimes	/*
1451558Srgrimes	 * Throw away the open file descriptor
1461558Srgrimes	 */
1471558Srgrimes	(void) close(fd);
1481558Srgrimes}
1491558Srgrimes
150166157Srodrigcvoid activate(qelem *q, int so)
1511558Srgrimes{
1521558Srgrimes	struct portal_cred pcred;
1531558Srgrimes	char key[MAXPATHLEN+1];
1541558Srgrimes	int error;
1551558Srgrimes	char **v;
1561558Srgrimes	int fd = -1;
1571558Srgrimes
1581558Srgrimes	/*
1591558Srgrimes	 * Read the key from the socket
1601558Srgrimes	 */
1611558Srgrimes	error = get_request(so, &pcred, key, sizeof(key));
1621558Srgrimes	if (error) {
1631558Srgrimes		syslog(LOG_ERR, "activate: recvmsg: %s", strerror(error));
1641558Srgrimes		goto drop;
1651558Srgrimes	}
1661558Srgrimes
1671558Srgrimes#ifdef DEBUG
1681558Srgrimes	fprintf(stderr, "lookup key %s\n", key);
1691558Srgrimes#endif
1701558Srgrimes
1711558Srgrimes	/*
1721558Srgrimes	 * Find a match in the configuration file
1731558Srgrimes	 */
1741558Srgrimes	v = conf_match(q, key);
1751558Srgrimes
1761558Srgrimes	/*
1771558Srgrimes	 * If a match existed, then find an appropriate portal
1781558Srgrimes	 * otherwise simply return ENOENT.
1791558Srgrimes	 */
1801558Srgrimes	if (v) {
1811558Srgrimes		error = activate_argv(&pcred, key, v, so, &fd);
1821558Srgrimes		if (error)
1831558Srgrimes			fd = -1;
1841558Srgrimes		else if (fd < 0)
1851558Srgrimes			error = -1;
1861558Srgrimes	} else {
1871558Srgrimes		error = ENOENT;
1881558Srgrimes	}
1891558Srgrimes
1901558Srgrimes	if (error >= 0)
1911558Srgrimes		send_reply(so, fd, error);
1921558Srgrimes
1931558Srgrimesdrop:;
1941558Srgrimes	close(so);
1951558Srgrimes}
196