1314564Sdim/* $NetBSD: activate.c,v 1.14 2007/07/02 18:07:44 pooka Exp $ */ 2254721Semaste 3353358Sdim/* 4353358Sdim * Copyright (c) 1992, 1993 5353358Sdim * The Regents of the University of California. All rights reserved. 6254721Semaste * 7254721Semaste * This code is derived from software donated to Berkeley by 8254721Semaste * Jan-Simon Pendry. 9254721Semaste * 10254721Semaste * Redistribution and use in source and binary forms, with or without 11254721Semaste * modification, are permitted provided that the following conditions 12254721Semaste * are met: 13254721Semaste * 1. Redistributions of source code must retain the above copyright 14254721Semaste * notice, this list of conditions and the following disclaimer. 15341825Sdim * 2. Redistributions in binary form must reproduce the above copyright 16353358Sdim * notice, this list of conditions and the following disclaimer in the 17321369Sdim * documentation and/or other materials provided with the distribution. 18314564Sdim * 3. Neither the name of the University nor the names of its contributors 19314564Sdim * may be used to endorse or promote products derived from this software 20353358Sdim * without specific prior written permission. 21353358Sdim * 22254721Semaste * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23254721Semaste * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24254721Semaste * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25314564Sdim * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26254721Semaste * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27314564Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28309124Sdim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29360784Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30360784Sdim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31360784Sdim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32360784Sdim * SUCH DAMAGE. 33360784Sdim * 34360784Sdim * from: Id: activate.c,v 1.2 1992/05/27 07:09:27 jsp Exp 35360784Sdim * @(#)activate.c 8.3 (Berkeley) 4/28/95 36360784Sdim */ 37254721Semaste 38314564Sdim#include <sys/cdefs.h> 39254721Semaste#ifndef lint 40314564Sdim__RCSID("$NetBSD: activate.c,v 1.14 2007/07/02 18:07:44 pooka Exp $"); 41254721Semaste#endif /* not lint */ 42314564Sdim 43254721Semaste#include <stdio.h> 44314564Sdim#include <stdlib.h> 45254721Semaste#include <unistd.h> 46314564Sdim#include <string.h> 47296417Sdim#include <errno.h> 48314564Sdim#include <signal.h> 49254721Semaste#include <sys/types.h> 50314564Sdim#include <sys/param.h> 51254721Semaste#include <sys/socket.h> 52360784Sdim#include <sys/un.h> 53360784Sdim#include <sys/syslog.h> 54360784Sdim#include <sys/uio.h> 55360784Sdim 56360784Sdim#include "portald.h" 57353358Sdim 58254721Semastestatic int get_request(int, struct portal_cred *, char *, size_t); 59314564Sdimstatic void send_reply(int, int, int); 60254721Semaste 61314564Sdim/* 62288943Sdim * Scan the providers list and call the 63314564Sdim * appropriate function. 64254721Semaste */ 65314564Sdimint 66254721Semasteactivate_argv(struct portal_cred *pcr, char *key, char **v, int *fdp) 67314564Sdim{ 68254721Semaste provider *pr; 69314564Sdim 70296417Sdim for (pr = providers; pr->pr_match; pr++) 71314564Sdim if (strcmp(v[0], pr->pr_match) == 0) 72254721Semaste return ((*pr->pr_func)(pcr, key, v, fdp)); 73314564Sdim 74254721Semaste return (ENOENT); 75314564Sdim} 76254721Semaste 77314564Sdimstatic int 78254721Semasteget_request(int so, struct portal_cred *pcr, char *key, size_t klen) 79314564Sdim{ 80254721Semaste struct iovec iov[2]; 81314564Sdim struct msghdr msg; 82254721Semaste ssize_t n; 83314564Sdim 84254721Semaste iov[0].iov_base = (caddr_t) pcr; 85314564Sdim iov[0].iov_len = sizeof(*pcr); 86254721Semaste iov[1].iov_base = key; 87314564Sdim iov[1].iov_len = klen; 88254721Semaste 89314564Sdim memset(&msg, 0, sizeof(msg)); 90254721Semaste msg.msg_iov = iov; 91314564Sdim msg.msg_iovlen = 2; 92296417Sdim 93314564Sdim n = recvmsg(so, &msg, 0); 94314564Sdim if (n < 0) 95309124Sdim return (errno); 96321369Sdim 97314564Sdim if (n <= (ssize_t)sizeof(*pcr)) 98314564Sdim return (EINVAL); 99314564Sdim 100314564Sdim n -= sizeof(*pcr); 101360784Sdim key[n] = '\0'; 102360784Sdim 103314564Sdim return (0); 104314564Sdim} 105314564Sdim 106314564Sdimstatic void 107314564Sdimsend_reply(int so, int fd, int error) 108254721Semaste{ 109360784Sdim int n; 110360784Sdim struct iovec iov; 111360784Sdim struct msghdr msg; 112360784Sdim void *ctl = NULL; 113360784Sdim struct cmsghdr *cmsg; 114360784Sdim int *files; 115360784Sdim socklen_t cmsgsize; 116360784Sdim 117360784Sdim /* 118360784Sdim * Line up error code. Don't worry about byte ordering 119360784Sdim * because we must be sending to the local machine. 120360784Sdim */ 121360784Sdim iov.iov_base = (caddr_t) &error; 122360784Sdim iov.iov_len = sizeof(error); 123360784Sdim 124360784Sdim /* 125360784Sdim * Build a msghdr 126360784Sdim */ 127360784Sdim memset(&msg, 0, sizeof(msg)); 128360784Sdim msg.msg_iov = &iov; 129360784Sdim msg.msg_iovlen = 1; 130360784Sdim 131360784Sdim /* 132360784Sdim * If there is a file descriptor to send then 133360784Sdim * construct a suitable rights control message. 134360784Sdim */ 135360784Sdim if (fd >= 0) { 136360784Sdim cmsgsize = CMSG_LEN(sizeof(*files)); 137254721Semaste 138353358Sdim ctl = malloc(cmsgsize); 139353358Sdim if (ctl == NULL) { 140254721Semaste syslog(LOG_WARNING, "malloc control message: %m"); 141254721Semaste return; 142254721Semaste } 143254721Semaste memset(ctl, 0, cmsgsize); 144314564Sdim 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