1*54851Spendry /*
2*54851Spendry  * Copyright (c) 1992 The Regents of the University of California
3*54851Spendry  * Copyright (c) 1990, 1992 Jan-Simon Pendry
4*54851Spendry  * All rights reserved.
5*54851Spendry  *
6*54851Spendry  * This code is derived from software donated to Berkeley by
7*54851Spendry  * Jan-Simon Pendry.
8*54851Spendry  *
9*54851Spendry  * %sccs.include.redist.c%
10*54851Spendry  *
11*54851Spendry  *	@(#)activate.c	1.1 (Berkeley) 07/09/92
12*54851Spendry  *
13*54851Spendry  * $Id: activate.c,v 1.2 1992/05/27 07:09:27 jsp Exp jsp $
14*54851Spendry  */
15*54851Spendry 
16*54851Spendry #include <stdio.h>
17*54851Spendry #include <stdlib.h>
18*54851Spendry #include <unistd.h>
19*54851Spendry #include <string.h>
20*54851Spendry #include <errno.h>
21*54851Spendry #include <signal.h>
22*54851Spendry #include <sys/types.h>
23*54851Spendry #include <sys/param.h>
24*54851Spendry #include <sys/socket.h>
25*54851Spendry #include <sys/un.h>
26*54851Spendry #include <sys/syslog.h>
27*54851Spendry #include <sys/uio.h>
28*54851Spendry 
29*54851Spendry #include "portald.h"
30*54851Spendry 
31*54851Spendry /*
32*54851Spendry  * Scan the providers list and call the
33*54851Spendry  * appropriate function.
34*54851Spendry  */
35*54851Spendry static int activate_argv(pcr, key, v, so, fdp)
36*54851Spendry struct portal_cred *pcr;
37*54851Spendry char *key;
38*54851Spendry char **v;
39*54851Spendry int so;
40*54851Spendry int *fdp;
41*54851Spendry {
42*54851Spendry 	provider *pr;
43*54851Spendry 
44*54851Spendry 	for (pr = providers; pr->pr_match; pr++)
45*54851Spendry 		if (strcmp(v[0], pr->pr_match) == 0)
46*54851Spendry 			return ((*pr->pr_func)(pcr, key, v, so, fdp));
47*54851Spendry 
48*54851Spendry 	return (ENOENT);
49*54851Spendry }
50*54851Spendry 
51*54851Spendry static int get_request(so, pcr, key, klen)
52*54851Spendry int so;
53*54851Spendry struct portal_cred *pcr;
54*54851Spendry char *key;
55*54851Spendry int klen;
56*54851Spendry {
57*54851Spendry 	struct iovec iov[2];
58*54851Spendry 	struct msghdr msg;
59*54851Spendry 	int n;
60*54851Spendry 
61*54851Spendry 	iov[0].iov_base = (caddr_t) pcr;
62*54851Spendry 	iov[0].iov_len = sizeof(*pcr);
63*54851Spendry 	iov[1].iov_base = key;
64*54851Spendry 	iov[1].iov_len = klen;
65*54851Spendry 
66*54851Spendry 	bzero((char *) &msg, sizeof(msg));
67*54851Spendry 	msg.msg_iov = iov;
68*54851Spendry 	msg.msg_iovlen = 2;
69*54851Spendry 
70*54851Spendry 	n = recvmsg(so, &msg, 0);
71*54851Spendry 	if (n < 0)
72*54851Spendry 		return (errno);
73*54851Spendry 
74*54851Spendry 	if (n <= sizeof(*pcr))
75*54851Spendry 		return (EINVAL);
76*54851Spendry 
77*54851Spendry 	n -= sizeof(*pcr);
78*54851Spendry 	key[n] = '\0';
79*54851Spendry 
80*54851Spendry 	return (0);
81*54851Spendry }
82*54851Spendry 
83*54851Spendry static void send_reply(so, fd, error)
84*54851Spendry int so;
85*54851Spendry int fd;
86*54851Spendry int error;
87*54851Spendry {
88*54851Spendry 	int n;
89*54851Spendry 	struct iovec iov;
90*54851Spendry 	struct msghdr msg;
91*54851Spendry 	struct {
92*54851Spendry 		struct cmsghdr cmsg;
93*54851Spendry 		int fd;
94*54851Spendry 	} ctl;
95*54851Spendry 
96*54851Spendry 	/*
97*54851Spendry 	 * Line up error code.  Don't worry about byte ordering
98*54851Spendry 	 * because we must be sending to the local machine.
99*54851Spendry 	 */
100*54851Spendry 	iov.iov_base = (caddr_t) &error;
101*54851Spendry 	iov.iov_len = sizeof(error);
102*54851Spendry 
103*54851Spendry 	/*
104*54851Spendry 	 * Build a msghdr
105*54851Spendry 	 */
106*54851Spendry 	bzero((char *) &msg, sizeof(msg));
107*54851Spendry 	msg.msg_iov = &iov;
108*54851Spendry 	msg.msg_iovlen = 1;
109*54851Spendry 
110*54851Spendry 	/*
111*54851Spendry 	 * If there is a file descriptor to send then
112*54851Spendry 	 * construct a suitable rights control message.
113*54851Spendry 	 */
114*54851Spendry 	if (fd >= 0) {
115*54851Spendry 		ctl.fd = fd;
116*54851Spendry 		ctl.cmsg.cmsg_len = sizeof(ctl);
117*54851Spendry 		ctl.cmsg.cmsg_level = SOL_SOCKET;
118*54851Spendry 		ctl.cmsg.cmsg_type = SCM_RIGHTS;
119*54851Spendry 		msg.msg_control = (caddr_t) &ctl;
120*54851Spendry 		msg.msg_controllen = ctl.cmsg.cmsg_len;
121*54851Spendry 	}
122*54851Spendry 
123*54851Spendry 	/*
124*54851Spendry 	 * Send to kernel...
125*54851Spendry 	 */
126*54851Spendry 	if ((n = sendmsg(so, &msg, MSG_EOR)) < 0)
127*54851Spendry 		syslog(LOG_ERR, "send: %s", strerror(errno));
128*54851Spendry #ifdef DEBUG
129*54851Spendry 	fprintf(stderr, "sent %d bytes\n", n);
130*54851Spendry #endif
131*54851Spendry 	sleep(1);	/*XXX*/
132*54851Spendry #ifdef notdef
133*54851Spendry 	if (shutdown(so, 2) < 0)
134*54851Spendry 		syslog(LOG_ERR, "shutdown: %s", strerror(errno));
135*54851Spendry #endif
136*54851Spendry 	/*
137*54851Spendry 	 * Throw away the open file descriptor
138*54851Spendry 	 */
139*54851Spendry 	(void) close(fd);
140*54851Spendry }
141*54851Spendry 
142*54851Spendry void activate(q, so)
143*54851Spendry qelem *q;
144*54851Spendry int so;
145*54851Spendry {
146*54851Spendry 	struct portal_cred pcred;
147*54851Spendry 	char key[MAXPATHLEN+1];
148*54851Spendry 	int n;
149*54851Spendry 	int error;
150*54851Spendry 	char **v;
151*54851Spendry 	int fd = -1;
152*54851Spendry 
153*54851Spendry 	/*
154*54851Spendry 	 * Read the key from the socket
155*54851Spendry 	 */
156*54851Spendry 	error = get_request(so, &pcred, key, sizeof(key));
157*54851Spendry 	if (error) {
158*54851Spendry 		syslog(LOG_ERR, "activate: recvmsg: %s", strerror(error));
159*54851Spendry 		goto drop;
160*54851Spendry 	}
161*54851Spendry 
162*54851Spendry 	fprintf(stderr, "lookup key %s\n", key);
163*54851Spendry 
164*54851Spendry 	/*
165*54851Spendry 	 * Find a match in the configuration file
166*54851Spendry 	 */
167*54851Spendry 	v = conf_match(q, key);
168*54851Spendry 
169*54851Spendry 	/*
170*54851Spendry 	 * If a match existed, then find an appropriate portal
171*54851Spendry 	 * otherwise simply return ENOENT.
172*54851Spendry 	 */
173*54851Spendry 	if (v) {
174*54851Spendry 		error = activate_argv(&pcred, key, v, so, &fd);
175*54851Spendry 		if (error)
176*54851Spendry 			fd = -1;
177*54851Spendry 		else if (fd < 0)
178*54851Spendry 			error = -1;
179*54851Spendry 	} else {
180*54851Spendry 		error = ENOENT;
181*54851Spendry 	}
182*54851Spendry 
183*54851Spendry 	if (error >= 0)
184*54851Spendry 		send_reply(so, fd, error);
185*54851Spendry 
186*54851Spendry drop:;
187*54851Spendry 	close(so);
188*54851Spendry }
189