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