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