154851Spendry /* 254851Spendry * Copyright (c) 1992 The Regents of the University of California 354851Spendry * Copyright (c) 1990, 1992 Jan-Simon Pendry 454851Spendry * All rights reserved. 554851Spendry * 654851Spendry * This code is derived from software donated to Berkeley by 754851Spendry * Jan-Simon Pendry. 854851Spendry * 954851Spendry * %sccs.include.redist.c% 1054851Spendry * 11*54979Spendry * @(#)activate.c 1.2 (Berkeley) 07/12/92 1254851Spendry * 1354851Spendry * $Id: activate.c,v 1.2 1992/05/27 07:09:27 jsp Exp jsp $ 1454851Spendry */ 1554851Spendry 1654851Spendry #include <stdio.h> 1754851Spendry #include <stdlib.h> 1854851Spendry #include <unistd.h> 1954851Spendry #include <string.h> 2054851Spendry #include <errno.h> 2154851Spendry #include <signal.h> 2254851Spendry #include <sys/types.h> 2354851Spendry #include <sys/param.h> 2454851Spendry #include <sys/socket.h> 2554851Spendry #include <sys/un.h> 2654851Spendry #include <sys/syslog.h> 2754851Spendry #include <sys/uio.h> 2854851Spendry 2954851Spendry #include "portald.h" 3054851Spendry 3154851Spendry /* 3254851Spendry * Scan the providers list and call the 3354851Spendry * appropriate function. 3454851Spendry */ 3554851Spendry static int activate_argv(pcr, key, v, so, fdp) 3654851Spendry struct portal_cred *pcr; 3754851Spendry char *key; 3854851Spendry char **v; 3954851Spendry int so; 4054851Spendry int *fdp; 4154851Spendry { 4254851Spendry provider *pr; 4354851Spendry 4454851Spendry for (pr = providers; pr->pr_match; pr++) 4554851Spendry if (strcmp(v[0], pr->pr_match) == 0) 4654851Spendry return ((*pr->pr_func)(pcr, key, v, so, fdp)); 4754851Spendry 4854851Spendry return (ENOENT); 4954851Spendry } 5054851Spendry 5154851Spendry static int get_request(so, pcr, key, klen) 5254851Spendry int so; 5354851Spendry struct portal_cred *pcr; 5454851Spendry char *key; 5554851Spendry int klen; 5654851Spendry { 5754851Spendry struct iovec iov[2]; 5854851Spendry struct msghdr msg; 5954851Spendry int n; 6054851Spendry 6154851Spendry iov[0].iov_base = (caddr_t) pcr; 6254851Spendry iov[0].iov_len = sizeof(*pcr); 6354851Spendry iov[1].iov_base = key; 6454851Spendry iov[1].iov_len = klen; 6554851Spendry 6654851Spendry bzero((char *) &msg, sizeof(msg)); 6754851Spendry msg.msg_iov = iov; 6854851Spendry msg.msg_iovlen = 2; 6954851Spendry 7054851Spendry n = recvmsg(so, &msg, 0); 7154851Spendry if (n < 0) 7254851Spendry return (errno); 7354851Spendry 7454851Spendry if (n <= sizeof(*pcr)) 7554851Spendry return (EINVAL); 7654851Spendry 7754851Spendry n -= sizeof(*pcr); 7854851Spendry key[n] = '\0'; 7954851Spendry 8054851Spendry return (0); 8154851Spendry } 8254851Spendry 8354851Spendry static void send_reply(so, fd, error) 8454851Spendry int so; 8554851Spendry int fd; 8654851Spendry int error; 8754851Spendry { 8854851Spendry int n; 8954851Spendry struct iovec iov; 9054851Spendry struct msghdr msg; 9154851Spendry struct { 9254851Spendry struct cmsghdr cmsg; 9354851Spendry int fd; 9454851Spendry } ctl; 9554851Spendry 9654851Spendry /* 9754851Spendry * Line up error code. Don't worry about byte ordering 9854851Spendry * because we must be sending to the local machine. 9954851Spendry */ 10054851Spendry iov.iov_base = (caddr_t) &error; 10154851Spendry iov.iov_len = sizeof(error); 10254851Spendry 10354851Spendry /* 10454851Spendry * Build a msghdr 10554851Spendry */ 10654851Spendry bzero((char *) &msg, sizeof(msg)); 10754851Spendry msg.msg_iov = &iov; 10854851Spendry msg.msg_iovlen = 1; 10954851Spendry 11054851Spendry /* 11154851Spendry * If there is a file descriptor to send then 11254851Spendry * construct a suitable rights control message. 11354851Spendry */ 11454851Spendry if (fd >= 0) { 11554851Spendry ctl.fd = fd; 11654851Spendry ctl.cmsg.cmsg_len = sizeof(ctl); 11754851Spendry ctl.cmsg.cmsg_level = SOL_SOCKET; 11854851Spendry ctl.cmsg.cmsg_type = SCM_RIGHTS; 11954851Spendry msg.msg_control = (caddr_t) &ctl; 12054851Spendry msg.msg_controllen = ctl.cmsg.cmsg_len; 12154851Spendry } 12254851Spendry 12354851Spendry /* 12454851Spendry * Send to kernel... 12554851Spendry */ 12654851Spendry if ((n = sendmsg(so, &msg, MSG_EOR)) < 0) 12754851Spendry syslog(LOG_ERR, "send: %s", strerror(errno)); 12854851Spendry #ifdef DEBUG 12954851Spendry fprintf(stderr, "sent %d bytes\n", n); 13054851Spendry #endif 13154851Spendry sleep(1); /*XXX*/ 13254851Spendry #ifdef notdef 13354851Spendry if (shutdown(so, 2) < 0) 13454851Spendry syslog(LOG_ERR, "shutdown: %s", strerror(errno)); 13554851Spendry #endif 13654851Spendry /* 13754851Spendry * Throw away the open file descriptor 13854851Spendry */ 13954851Spendry (void) close(fd); 14054851Spendry } 14154851Spendry 14254851Spendry void activate(q, so) 14354851Spendry qelem *q; 14454851Spendry int so; 14554851Spendry { 14654851Spendry struct portal_cred pcred; 14754851Spendry char key[MAXPATHLEN+1]; 14854851Spendry int n; 14954851Spendry int error; 15054851Spendry char **v; 15154851Spendry int fd = -1; 15254851Spendry 15354851Spendry /* 15454851Spendry * Read the key from the socket 15554851Spendry */ 15654851Spendry error = get_request(so, &pcred, key, sizeof(key)); 15754851Spendry if (error) { 15854851Spendry syslog(LOG_ERR, "activate: recvmsg: %s", strerror(error)); 15954851Spendry goto drop; 16054851Spendry } 16154851Spendry 162*54979Spendry #ifdef DEBUG 16354851Spendry fprintf(stderr, "lookup key %s\n", key); 164*54979Spendry #endif 16554851Spendry 16654851Spendry /* 16754851Spendry * Find a match in the configuration file 16854851Spendry */ 16954851Spendry v = conf_match(q, key); 17054851Spendry 17154851Spendry /* 17254851Spendry * If a match existed, then find an appropriate portal 17354851Spendry * otherwise simply return ENOENT. 17454851Spendry */ 17554851Spendry if (v) { 17654851Spendry error = activate_argv(&pcred, key, v, so, &fd); 17754851Spendry if (error) 17854851Spendry fd = -1; 17954851Spendry else if (fd < 0) 18054851Spendry error = -1; 18154851Spendry } else { 18254851Spendry error = ENOENT; 18354851Spendry } 18454851Spendry 18554851Spendry if (error >= 0) 18654851Spendry send_reply(so, fd, error); 18754851Spendry 18854851Spendry drop:; 18954851Spendry close(so); 19054851Spendry } 191