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 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#)activate.c 8.3 (Berkeley) 4/28/95 34 */ 35 36#include <sys/cdefs.h> 37__FBSDID("$FreeBSD$"); 38 39#include <errno.h> 40#include <string.h> 41#include <unistd.h> 42#include <sys/types.h> 43#include <sys/param.h> 44#include <sys/socket.h> 45#include <sys/syslog.h> 46#include <sys/uio.h> 47 48#include "portald.h" 49 50/* 51 * Scan the providers list and call the 52 * appropriate function. 53 */ 54static int activate_argv(struct portal_cred *pcr, char *key, char **v, int so, 55 int *fdp) 56{ 57 provider *pr; 58 59 for (pr = providers; pr->pr_match; pr++) 60 if (strcmp(v[0], pr->pr_match) == 0) 61 return ((*pr->pr_func)(pcr, key, v, so, fdp)); 62 63 return (ENOENT); 64} 65 66static int get_request(int so, struct portal_cred *pcr, char *key, int klen) 67{ 68 struct iovec iov[2]; 69 struct msghdr msg; 70 int n; 71 72 iov[0].iov_base = (caddr_t) pcr; 73 iov[0].iov_len = sizeof(*pcr); 74 iov[1].iov_base = key; 75 iov[1].iov_len = klen; 76 77 memset(&msg, 0, sizeof(msg)); 78 msg.msg_iov = iov; 79 msg.msg_iovlen = 2; 80 81 n = recvmsg(so, &msg, 0); 82 if (n < 0) 83 return (errno); 84 85 if (n <= (int)sizeof(*pcr)) 86 return (EINVAL); 87 88 n -= sizeof(*pcr); 89 key[n] = '\0'; 90 91 return (0); 92} 93 94static void send_reply(int so, int fd, int error) 95{ 96 int n; 97 struct iovec iov; 98 struct msghdr msg; 99 union { 100 struct cmsghdr cmsg; 101 char control[CMSG_SPACE(sizeof(int))]; 102 } ctl; 103 104 /* 105 * Line up error code. Don't worry about byte ordering 106 * because we must be sending to the local machine. 107 */ 108 iov.iov_base = (caddr_t) &error; 109 iov.iov_len = sizeof(error); 110 111 /* 112 * Build a msghdr 113 */ 114 memset(&msg, 0, sizeof(msg)); 115 msg.msg_iov = &iov; 116 msg.msg_iovlen = 1; 117 118 /* 119 * If there is a file descriptor to send then 120 * construct a suitable rights control message. 121 */ 122 if (fd >= 0) { 123 ctl.cmsg.cmsg_len = CMSG_LEN(sizeof(int)); 124 ctl.cmsg.cmsg_level = SOL_SOCKET; 125 ctl.cmsg.cmsg_type = SCM_RIGHTS; 126 *((int *)CMSG_DATA(&ctl.cmsg)) = fd; 127 msg.msg_control = (caddr_t) &ctl; 128 msg.msg_controllen = ctl.cmsg.cmsg_len; 129 } 130 131 /* 132 * Send to kernel... 133 */ 134 if ((n = sendmsg(so, &msg, 0)) < 0) 135 syslog(LOG_ERR, "send: %s", strerror(errno)); 136#ifdef DEBUG 137 fprintf(stderr, "sent %d bytes\n", n); 138#endif 139 sleep(1); /*XXX*/ 140#ifdef notdef 141 if (shutdown(so, SHUT_RDWR) < 0) 142 syslog(LOG_ERR, "shutdown: %s", strerror(errno)); 143#endif 144 /* 145 * Throw away the open file descriptor 146 */ 147 (void) close(fd); 148} 149 150void activate(qelem *q, int so) 151{ 152 struct portal_cred pcred; 153 char key[MAXPATHLEN+1]; 154 int error; 155 char **v; 156 int fd = -1; 157 158 /* 159 * Read the key from the socket 160 */ 161 error = get_request(so, &pcred, key, sizeof(key)); 162 if (error) { 163 syslog(LOG_ERR, "activate: recvmsg: %s", strerror(error)); 164 goto drop; 165 } 166 167#ifdef DEBUG 168 fprintf(stderr, "lookup key %s\n", key); 169#endif 170 171 /* 172 * Find a match in the configuration file 173 */ 174 v = conf_match(q, key); 175 176 /* 177 * If a match existed, then find an appropriate portal 178 * otherwise simply return ENOENT. 179 */ 180 if (v) { 181 error = activate_argv(&pcred, key, v, so, &fd); 182 if (error) 183 fd = -1; 184 else if (fd < 0) 185 error = -1; 186 } else { 187 error = ENOENT; 188 } 189 190 if (error >= 0) 191 send_reply(so, fd, error); 192 193drop:; 194 close(so); 195} 196