1 /* $NetBSD: activate.c,v 1.13 2005/02/09 13:57:57 xtraeme 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.13 2005/02/09 13:57:57 xtraeme 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 activate_argv(struct portal_cred *, char *, char **, 59 int, int *); 60 static int get_request(int, struct portal_cred *, char *, int); 61 static void send_reply(int, int, int); 62 63 /* 64 * Scan the providers list and call the 65 * appropriate function. 66 */ 67 static int 68 activate_argv(struct portal_cred *pcr, char *key, char **v, int so, int *fdp) 69 { 70 provider *pr; 71 72 for (pr = providers; pr->pr_match; pr++) 73 if (strcmp(v[0], pr->pr_match) == 0) 74 return ((*pr->pr_func)(pcr, key, v, so, fdp)); 75 76 return (ENOENT); 77 } 78 79 static int 80 get_request(int so, struct portal_cred *pcr, char *key, int klen) 81 { 82 struct iovec iov[2]; 83 struct msghdr msg; 84 int n; 85 86 iov[0].iov_base = (caddr_t) pcr; 87 iov[0].iov_len = sizeof(*pcr); 88 iov[1].iov_base = key; 89 iov[1].iov_len = klen; 90 91 memset(&msg, 0, sizeof(msg)); 92 msg.msg_iov = iov; 93 msg.msg_iovlen = 2; 94 95 n = recvmsg(so, &msg, 0); 96 if (n < 0) 97 return (errno); 98 99 if (n <= sizeof(*pcr)) 100 return (EINVAL); 101 102 n -= sizeof(*pcr); 103 key[n] = '\0'; 104 105 return (0); 106 } 107 108 static void 109 send_reply(int so, int fd, int error) 110 { 111 int n; 112 struct iovec iov; 113 struct msghdr msg; 114 void *ctl = NULL; 115 struct cmsghdr *cmsg; 116 int *files; 117 socklen_t cmsgsize; 118 119 /* 120 * Line up error code. Don't worry about byte ordering 121 * because we must be sending to the local machine. 122 */ 123 iov.iov_base = (caddr_t) &error; 124 iov.iov_len = sizeof(error); 125 126 /* 127 * Build a msghdr 128 */ 129 memset(&msg, 0, sizeof(msg)); 130 msg.msg_iov = &iov; 131 msg.msg_iovlen = 1; 132 133 /* 134 * If there is a file descriptor to send then 135 * construct a suitable rights control message. 136 */ 137 if (fd >= 0) { 138 cmsgsize = CMSG_LEN(sizeof(*files)); 139 140 ctl = malloc(cmsgsize); 141 if (ctl == NULL) { 142 syslog(LOG_WARNING, "malloc control message: %m"); 143 return; 144 } 145 memset(ctl, 0, cmsgsize); 146 147 cmsg = (struct cmsghdr *) ctl; 148 cmsg->cmsg_len = CMSG_LEN(sizeof(int)); 149 cmsg->cmsg_level = SOL_SOCKET; 150 cmsg->cmsg_type = SCM_RIGHTS; 151 152 files = (int *)CMSG_DATA(cmsg); 153 files[0] = fd; 154 155 msg.msg_control = ctl; 156 msg.msg_controllen = cmsgsize; 157 } 158 159 /* 160 * Send to kernel... 161 */ 162 if ((n = sendmsg(so, &msg, MSG_EOR)) < 0) 163 syslog(LOG_WARNING, "send: %m"); 164 #ifdef DEBUG 165 fprintf(stderr, "sent %d bytes\n", n); 166 #endif 167 sleep(1); /*XXX*/ 168 #ifdef notdef 169 if (shutdown(so, 2) < 0) 170 syslog(LOG_WARNING, "shutdown: %m"); 171 #endif 172 /* 173 * Throw away the open file descriptor and control 174 * message buffer. 175 */ 176 if (fd >= 0) 177 (void) close(fd); 178 if (ctl != NULL) 179 free(ctl); 180 } 181 182 void 183 activate(qelem *q, int so) 184 { 185 struct portal_cred pcred; 186 char key[MAXPATHLEN+1]; 187 int error; 188 char **v; 189 int fd = -1; 190 191 /* 192 * Read the key from the socket 193 */ 194 error = get_request(so, &pcred, key, sizeof(key)); 195 if (error) { 196 syslog(LOG_WARNING, "activate: recvmsg: %m"); 197 goto drop; 198 } 199 200 #ifdef DEBUG 201 fprintf(stderr, "lookup key %s\n", key); 202 #endif 203 204 /* 205 * Find a match in the configuration file 206 */ 207 v = conf_match(q, key); 208 209 /* 210 * If a match existed, then find an appropriate portal 211 * otherwise simply return ENOENT. 212 */ 213 if (v) { 214 error = activate_argv(&pcred, key, v, so, &fd); 215 if (error) 216 fd = -1; 217 else if (fd < 0) 218 error = -1; 219 } else 220 error = ENOENT; 221 222 if (error >= 0) 223 send_reply(so, fd, error); 224 225 drop:; 226 close(so); 227 } 228