1*8e2fe698Slukem /* $NetBSD: activate.c,v 1.15 2009/04/11 07:36:43 lukem Exp $ */
20114e805Scgd
3b8b85029Scgd /*
4b8b85029Scgd * Copyright (c) 1992, 1993
5b8b85029Scgd * The Regents of the University of California. All rights reserved.
6b8b85029Scgd *
7b8b85029Scgd * This code is derived from software donated to Berkeley by
8b8b85029Scgd * Jan-Simon Pendry.
9b8b85029Scgd *
10b8b85029Scgd * Redistribution and use in source and binary forms, with or without
11b8b85029Scgd * modification, are permitted provided that the following conditions
12b8b85029Scgd * are met:
13b8b85029Scgd * 1. Redistributions of source code must retain the above copyright
14b8b85029Scgd * notice, this list of conditions and the following disclaimer.
15b8b85029Scgd * 2. Redistributions in binary form must reproduce the above copyright
16b8b85029Scgd * notice, this list of conditions and the following disclaimer in the
17b8b85029Scgd * documentation and/or other materials provided with the distribution.
18276d62f6Sagc * 3. Neither the name of the University nor the names of its contributors
19b8b85029Scgd * may be used to endorse or promote products derived from this software
20b8b85029Scgd * without specific prior written permission.
21b8b85029Scgd *
22b8b85029Scgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23b8b85029Scgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24b8b85029Scgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25b8b85029Scgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26b8b85029Scgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27b8b85029Scgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28b8b85029Scgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29b8b85029Scgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30b8b85029Scgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31b8b85029Scgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32b8b85029Scgd * SUCH DAMAGE.
33b8b85029Scgd *
345922d844Smycroft * from: Id: activate.c,v 1.2 1992/05/27 07:09:27 jsp Exp
354b0b1ba8Slukem * @(#)activate.c 8.3 (Berkeley) 4/28/95
36b8b85029Scgd */
37b8b85029Scgd
384eb9f40aSlukem #include <sys/cdefs.h>
394eb9f40aSlukem #ifndef lint
40*8e2fe698Slukem __RCSID("$NetBSD: activate.c,v 1.15 2009/04/11 07:36:43 lukem Exp $");
414eb9f40aSlukem #endif /* not lint */
424eb9f40aSlukem
43b8b85029Scgd #include <stdio.h>
44b8b85029Scgd #include <stdlib.h>
45b8b85029Scgd #include <unistd.h>
46b8b85029Scgd #include <string.h>
47b8b85029Scgd #include <errno.h>
48b8b85029Scgd #include <signal.h>
49b8b85029Scgd #include <sys/types.h>
50b8b85029Scgd #include <sys/param.h>
51b8b85029Scgd #include <sys/socket.h>
52b8b85029Scgd #include <sys/un.h>
53b8b85029Scgd #include <sys/syslog.h>
54b8b85029Scgd #include <sys/uio.h>
55b8b85029Scgd
56b8b85029Scgd #include "portald.h"
57b8b85029Scgd
58*8e2fe698Slukem static int get_request(int, struct portal_cred *, char *, size_t);
59a8d83732Sxtraeme static void send_reply(int, int, int);
604eb9f40aSlukem
61b8b85029Scgd /*
62b8b85029Scgd * Scan the providers list and call the
63b8b85029Scgd * appropriate function.
64b8b85029Scgd */
6501d79aaeSpooka int
activate_argv(struct portal_cred * pcr,char * key,char ** v,int * fdp)6601d79aaeSpooka activate_argv(struct portal_cred *pcr, char *key, char **v, int *fdp)
67b8b85029Scgd {
68b8b85029Scgd provider *pr;
69b8b85029Scgd
70b8b85029Scgd for (pr = providers; pr->pr_match; pr++)
71b8b85029Scgd if (strcmp(v[0], pr->pr_match) == 0)
7201d79aaeSpooka return ((*pr->pr_func)(pcr, key, v, fdp));
73b8b85029Scgd
74b8b85029Scgd return (ENOENT);
75b8b85029Scgd }
76b8b85029Scgd
774eb9f40aSlukem static int
get_request(int so,struct portal_cred * pcr,char * key,size_t klen)78*8e2fe698Slukem get_request(int so, struct portal_cred *pcr, char *key, size_t klen)
79b8b85029Scgd {
80b8b85029Scgd struct iovec iov[2];
81b8b85029Scgd struct msghdr msg;
82*8e2fe698Slukem ssize_t n;
83b8b85029Scgd
84b8b85029Scgd iov[0].iov_base = (caddr_t) pcr;
85b8b85029Scgd iov[0].iov_len = sizeof(*pcr);
86b8b85029Scgd iov[1].iov_base = key;
87b8b85029Scgd iov[1].iov_len = klen;
88b8b85029Scgd
89ea7b5d4eSmycroft memset(&msg, 0, sizeof(msg));
90b8b85029Scgd msg.msg_iov = iov;
91b8b85029Scgd msg.msg_iovlen = 2;
92b8b85029Scgd
93b8b85029Scgd n = recvmsg(so, &msg, 0);
94b8b85029Scgd if (n < 0)
95b8b85029Scgd return (errno);
96b8b85029Scgd
97*8e2fe698Slukem if (n <= (ssize_t)sizeof(*pcr))
98b8b85029Scgd return (EINVAL);
99b8b85029Scgd
100b8b85029Scgd n -= sizeof(*pcr);
101b8b85029Scgd key[n] = '\0';
102b8b85029Scgd
103b8b85029Scgd return (0);
104b8b85029Scgd }
105b8b85029Scgd
1064eb9f40aSlukem static void
send_reply(int so,int fd,int error)107a8d83732Sxtraeme send_reply(int so, int fd, int error)
108b8b85029Scgd {
109b8b85029Scgd int n;
110b8b85029Scgd struct iovec iov;
111b8b85029Scgd struct msghdr msg;
1120ffb5bb9Sthorpej void *ctl = NULL;
1130ffb5bb9Sthorpej struct cmsghdr *cmsg;
1140ffb5bb9Sthorpej int *files;
1150ffb5bb9Sthorpej socklen_t cmsgsize;
116b8b85029Scgd
117b8b85029Scgd /*
118b8b85029Scgd * Line up error code. Don't worry about byte ordering
119b8b85029Scgd * because we must be sending to the local machine.
120b8b85029Scgd */
121b8b85029Scgd iov.iov_base = (caddr_t) &error;
122b8b85029Scgd iov.iov_len = sizeof(error);
123b8b85029Scgd
124b8b85029Scgd /*
125b8b85029Scgd * Build a msghdr
126b8b85029Scgd */
127ea7b5d4eSmycroft memset(&msg, 0, sizeof(msg));
128b8b85029Scgd msg.msg_iov = &iov;
129b8b85029Scgd msg.msg_iovlen = 1;
130b8b85029Scgd
131b8b85029Scgd /*
132b8b85029Scgd * If there is a file descriptor to send then
133b8b85029Scgd * construct a suitable rights control message.
134b8b85029Scgd */
135b8b85029Scgd if (fd >= 0) {
136a63801edSatatat cmsgsize = CMSG_LEN(sizeof(*files));
1370ffb5bb9Sthorpej
1380ffb5bb9Sthorpej ctl = malloc(cmsgsize);
1390ffb5bb9Sthorpej if (ctl == NULL) {
140415d1abdSlukem syslog(LOG_WARNING, "malloc control message: %m");
1410ffb5bb9Sthorpej return;
1420ffb5bb9Sthorpej }
1430ffb5bb9Sthorpej memset(ctl, 0, cmsgsize);
1440ffb5bb9Sthorpej
1450ffb5bb9Sthorpej cmsg = (struct cmsghdr *) ctl;
1460ffb5bb9Sthorpej cmsg->cmsg_len = CMSG_LEN(sizeof(int));
1470ffb5bb9Sthorpej cmsg->cmsg_level = SOL_SOCKET;
1480ffb5bb9Sthorpej cmsg->cmsg_type = SCM_RIGHTS;
1490ffb5bb9Sthorpej
1500ffb5bb9Sthorpej files = (int *)CMSG_DATA(cmsg);
1510ffb5bb9Sthorpej files[0] = fd;
1520ffb5bb9Sthorpej
1530ffb5bb9Sthorpej msg.msg_control = ctl;
1540ffb5bb9Sthorpej msg.msg_controllen = cmsgsize;
155b8b85029Scgd }
156b8b85029Scgd
157b8b85029Scgd /*
158b8b85029Scgd * Send to kernel...
159b8b85029Scgd */
160b8b85029Scgd if ((n = sendmsg(so, &msg, MSG_EOR)) < 0)
161415d1abdSlukem syslog(LOG_WARNING, "send: %m");
162b8b85029Scgd #ifdef DEBUG
163b8b85029Scgd fprintf(stderr, "sent %d bytes\n", n);
164b8b85029Scgd #endif
165b8b85029Scgd sleep(1); /*XXX*/
166b8b85029Scgd #ifdef notdef
167b8b85029Scgd if (shutdown(so, 2) < 0)
168415d1abdSlukem syslog(LOG_WARNING, "shutdown: %m");
169b8b85029Scgd #endif
170b8b85029Scgd /*
1710ffb5bb9Sthorpej * Throw away the open file descriptor and control
1720ffb5bb9Sthorpej * message buffer.
173b8b85029Scgd */
1740ffb5bb9Sthorpej if (fd >= 0)
175b8b85029Scgd (void) close(fd);
1760ffb5bb9Sthorpej if (ctl != NULL)
1770ffb5bb9Sthorpej free(ctl);
178b8b85029Scgd }
179b8b85029Scgd
1804eb9f40aSlukem void
activate(qelem * q,int so)181a8d83732Sxtraeme activate(qelem *q, int so)
182b8b85029Scgd {
183b8b85029Scgd struct portal_cred pcred;
184b8b85029Scgd char key[MAXPATHLEN+1];
185b8b85029Scgd int error;
186b8b85029Scgd char **v;
187b8b85029Scgd int fd = -1;
188b8b85029Scgd
189b8b85029Scgd /*
190b8b85029Scgd * Read the key from the socket
191b8b85029Scgd */
192b8b85029Scgd error = get_request(so, &pcred, key, sizeof(key));
193b8b85029Scgd if (error) {
194415d1abdSlukem syslog(LOG_WARNING, "activate: recvmsg: %m");
195b8b85029Scgd goto drop;
196b8b85029Scgd }
197b8b85029Scgd
198b8b85029Scgd #ifdef DEBUG
199b8b85029Scgd fprintf(stderr, "lookup key %s\n", key);
200b8b85029Scgd #endif
201b8b85029Scgd
202b8b85029Scgd /*
203b8b85029Scgd * Find a match in the configuration file
204b8b85029Scgd */
205b8b85029Scgd v = conf_match(q, key);
206b8b85029Scgd
207b8b85029Scgd /*
208b8b85029Scgd * If a match existed, then find an appropriate portal
209b8b85029Scgd * otherwise simply return ENOENT.
210b8b85029Scgd */
211b8b85029Scgd if (v) {
21201d79aaeSpooka error = activate_argv(&pcred, key, v, &fd);
213b8b85029Scgd if (error)
214b8b85029Scgd fd = -1;
215b8b85029Scgd else if (fd < 0)
216b8b85029Scgd error = -1;
2170ac5bcaaSenami } else
218b8b85029Scgd error = ENOENT;
219b8b85029Scgd
220b8b85029Scgd if (error >= 0)
221b8b85029Scgd send_reply(so, fd, error);
222b8b85029Scgd
223b8b85029Scgd drop:;
224b8b85029Scgd close(so);
225b8b85029Scgd }
226