154851Spendry /*
261515Sbostic  * Copyright (c) 1992, 1993
361515Sbostic  *	The Regents of the University of California.  All rights reserved.
454851Spendry  * All rights reserved.
554851Spendry  *
654851Spendry  * This code is derived from software donated to Berkeley by
754851Spendry  * Jan-Simon Pendry.
854851Spendry  *
954851Spendry  * %sccs.include.redist.c%
1054851Spendry  *
11*68995Sbostic  *	@(#)activate.c	8.3 (Berkeley) 04/28/95
1254851Spendry  *
1354851Spendry  * $Id: activate.c,v 1.2 1992/05/27 07:09:27 jsp Exp jsp $
1454851Spendry  */
1554851Spendry 
1654851Spendry #include <stdio.h>
1754851Spendry #include <stdlib.h>
1854851Spendry #include <unistd.h>
1954851Spendry #include <string.h>
2054851Spendry #include <errno.h>
2154851Spendry #include <signal.h>
2254851Spendry #include <sys/types.h>
2354851Spendry #include <sys/param.h>
2454851Spendry #include <sys/socket.h>
2554851Spendry #include <sys/un.h>
2654851Spendry #include <sys/syslog.h>
2754851Spendry #include <sys/uio.h>
2854851Spendry 
2954851Spendry #include "portald.h"
3054851Spendry 
3154851Spendry /*
3254851Spendry  * Scan the providers list and call the
3354851Spendry  * appropriate function.
3454851Spendry  */
activate_argv(pcr,key,v,so,fdp)3554851Spendry static int activate_argv(pcr, key, v, so, fdp)
3654851Spendry struct portal_cred *pcr;
3754851Spendry char *key;
3854851Spendry char **v;
3954851Spendry int so;
4054851Spendry int *fdp;
4154851Spendry {
4254851Spendry 	provider *pr;
4354851Spendry 
4454851Spendry 	for (pr = providers; pr->pr_match; pr++)
4554851Spendry 		if (strcmp(v[0], pr->pr_match) == 0)
4654851Spendry 			return ((*pr->pr_func)(pcr, key, v, so, fdp));
4754851Spendry 
4854851Spendry 	return (ENOENT);
4954851Spendry }
5054851Spendry 
get_request(so,pcr,key,klen)5154851Spendry static int get_request(so, pcr, key, klen)
5254851Spendry int so;
5354851Spendry struct portal_cred *pcr;
5454851Spendry char *key;
5554851Spendry int klen;
5654851Spendry {
5754851Spendry 	struct iovec iov[2];
5854851Spendry 	struct msghdr msg;
5954851Spendry 	int n;
6054851Spendry 
6154851Spendry 	iov[0].iov_base = (caddr_t) pcr;
6254851Spendry 	iov[0].iov_len = sizeof(*pcr);
6354851Spendry 	iov[1].iov_base = key;
6454851Spendry 	iov[1].iov_len = klen;
6554851Spendry 
66*68995Sbostic 	memset(&msg, 0, sizeof(msg));
6754851Spendry 	msg.msg_iov = iov;
6854851Spendry 	msg.msg_iovlen = 2;
6954851Spendry 
7054851Spendry 	n = recvmsg(so, &msg, 0);
7154851Spendry 	if (n < 0)
7254851Spendry 		return (errno);
7354851Spendry 
7454851Spendry 	if (n <= sizeof(*pcr))
7554851Spendry 		return (EINVAL);
7654851Spendry 
7754851Spendry 	n -= sizeof(*pcr);
7854851Spendry 	key[n] = '\0';
7954851Spendry 
8054851Spendry 	return (0);
8154851Spendry }
8254851Spendry 
send_reply(so,fd,error)8354851Spendry static void send_reply(so, fd, error)
8454851Spendry int so;
8554851Spendry int fd;
8654851Spendry int error;
8754851Spendry {
8854851Spendry 	int n;
8954851Spendry 	struct iovec iov;
9054851Spendry 	struct msghdr msg;
9154851Spendry 	struct {
9254851Spendry 		struct cmsghdr cmsg;
9354851Spendry 		int fd;
9454851Spendry 	} ctl;
9554851Spendry 
9654851Spendry 	/*
9754851Spendry 	 * Line up error code.  Don't worry about byte ordering
9854851Spendry 	 * because we must be sending to the local machine.
9954851Spendry 	 */
10054851Spendry 	iov.iov_base = (caddr_t) &error;
10154851Spendry 	iov.iov_len = sizeof(error);
10254851Spendry 
10354851Spendry 	/*
10454851Spendry 	 * Build a msghdr
10554851Spendry 	 */
106*68995Sbostic 	memset(&msg, 0, sizeof(msg));
10754851Spendry 	msg.msg_iov = &iov;
10854851Spendry 	msg.msg_iovlen = 1;
10954851Spendry 
11054851Spendry 	/*
11154851Spendry 	 * If there is a file descriptor to send then
11254851Spendry 	 * construct a suitable rights control message.
11354851Spendry 	 */
11454851Spendry 	if (fd >= 0) {
11554851Spendry 		ctl.fd = fd;
11654851Spendry 		ctl.cmsg.cmsg_len = sizeof(ctl);
11754851Spendry 		ctl.cmsg.cmsg_level = SOL_SOCKET;
11854851Spendry 		ctl.cmsg.cmsg_type = SCM_RIGHTS;
11954851Spendry 		msg.msg_control = (caddr_t) &ctl;
12054851Spendry 		msg.msg_controllen = ctl.cmsg.cmsg_len;
12154851Spendry 	}
12254851Spendry 
12354851Spendry 	/*
12454851Spendry 	 * Send to kernel...
12554851Spendry 	 */
12654851Spendry 	if ((n = sendmsg(so, &msg, MSG_EOR)) < 0)
12754851Spendry 		syslog(LOG_ERR, "send: %s", strerror(errno));
12854851Spendry #ifdef DEBUG
12954851Spendry 	fprintf(stderr, "sent %d bytes\n", n);
13054851Spendry #endif
13154851Spendry 	sleep(1);	/*XXX*/
13254851Spendry #ifdef notdef
13354851Spendry 	if (shutdown(so, 2) < 0)
13454851Spendry 		syslog(LOG_ERR, "shutdown: %s", strerror(errno));
13554851Spendry #endif
13654851Spendry 	/*
13754851Spendry 	 * Throw away the open file descriptor
13854851Spendry 	 */
13954851Spendry 	(void) close(fd);
14054851Spendry }
14154851Spendry 
activate(q,so)14254851Spendry void activate(q, so)
14354851Spendry qelem *q;
14454851Spendry int so;
14554851Spendry {
14654851Spendry 	struct portal_cred pcred;
14754851Spendry 	char key[MAXPATHLEN+1];
14854851Spendry 	int error;
14954851Spendry 	char **v;
15054851Spendry 	int fd = -1;
15154851Spendry 
15254851Spendry 	/*
15354851Spendry 	 * Read the key from the socket
15454851Spendry 	 */
15554851Spendry 	error = get_request(so, &pcred, key, sizeof(key));
15654851Spendry 	if (error) {
15754851Spendry 		syslog(LOG_ERR, "activate: recvmsg: %s", strerror(error));
15854851Spendry 		goto drop;
15954851Spendry 	}
16054851Spendry 
16154979Spendry #ifdef DEBUG
16254851Spendry 	fprintf(stderr, "lookup key %s\n", key);
16354979Spendry #endif
16454851Spendry 
16554851Spendry 	/*
16654851Spendry 	 * Find a match in the configuration file
16754851Spendry 	 */
16854851Spendry 	v = conf_match(q, key);
16954851Spendry 
17054851Spendry 	/*
17154851Spendry 	 * If a match existed, then find an appropriate portal
17254851Spendry 	 * otherwise simply return ENOENT.
17354851Spendry 	 */
17454851Spendry 	if (v) {
17554851Spendry 		error = activate_argv(&pcred, key, v, so, &fd);
17654851Spendry 		if (error)
17754851Spendry 			fd = -1;
17854851Spendry 		else if (fd < 0)
17954851Spendry 			error = -1;
18054851Spendry 	} else {
18154851Spendry 		error = ENOENT;
18254851Spendry 	}
18354851Spendry 
18454851Spendry 	if (error >= 0)
18554851Spendry 		send_reply(so, fd, error);
18654851Spendry 
18754851Spendry drop:;
18854851Spendry 	close(so);
18954851Spendry }
190