1/* $NetBSD: activate.c,v 1.14 2007/07/02 18:07:44 pooka 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.14 2007/07/02 18:07:44 pooka 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 58static int get_request(int, struct portal_cred *, char *, size_t); 59static void send_reply(int, int, int); 60 61/* 62 * Scan the providers list and call the 63 * appropriate function. 64 */ 65int 66activate_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 77static int 78get_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 106static void 107send_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 180void 181activate(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 223drop:; 224 close(so); 225} 226