1 /* 2 * Copyright (c) 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * All rights reserved. 5 * 6 * This code is derived from software donated to Berkeley by 7 * Jan-Simon Pendry. 8 * 9 * %sccs.include.redist.c% 10 * 11 * @(#)activate.c 8.3 (Berkeley) 04/28/95 12 * 13 * $Id: activate.c,v 1.2 1992/05/27 07:09:27 jsp Exp jsp $ 14 */ 15 16 #include <stdio.h> 17 #include <stdlib.h> 18 #include <unistd.h> 19 #include <string.h> 20 #include <errno.h> 21 #include <signal.h> 22 #include <sys/types.h> 23 #include <sys/param.h> 24 #include <sys/socket.h> 25 #include <sys/un.h> 26 #include <sys/syslog.h> 27 #include <sys/uio.h> 28 29 #include "portald.h" 30 31 /* 32 * Scan the providers list and call the 33 * appropriate function. 34 */ 35 static int activate_argv(pcr, key, v, so, fdp) 36 struct portal_cred *pcr; 37 char *key; 38 char **v; 39 int so; 40 int *fdp; 41 { 42 provider *pr; 43 44 for (pr = providers; pr->pr_match; pr++) 45 if (strcmp(v[0], pr->pr_match) == 0) 46 return ((*pr->pr_func)(pcr, key, v, so, fdp)); 47 48 return (ENOENT); 49 } 50 51 static int get_request(so, pcr, key, klen) 52 int so; 53 struct portal_cred *pcr; 54 char *key; 55 int klen; 56 { 57 struct iovec iov[2]; 58 struct msghdr msg; 59 int n; 60 61 iov[0].iov_base = (caddr_t) pcr; 62 iov[0].iov_len = sizeof(*pcr); 63 iov[1].iov_base = key; 64 iov[1].iov_len = klen; 65 66 memset(&msg, 0, sizeof(msg)); 67 msg.msg_iov = iov; 68 msg.msg_iovlen = 2; 69 70 n = recvmsg(so, &msg, 0); 71 if (n < 0) 72 return (errno); 73 74 if (n <= sizeof(*pcr)) 75 return (EINVAL); 76 77 n -= sizeof(*pcr); 78 key[n] = '\0'; 79 80 return (0); 81 } 82 83 static void send_reply(so, fd, error) 84 int so; 85 int fd; 86 int error; 87 { 88 int n; 89 struct iovec iov; 90 struct msghdr msg; 91 struct { 92 struct cmsghdr cmsg; 93 int fd; 94 } ctl; 95 96 /* 97 * Line up error code. Don't worry about byte ordering 98 * because we must be sending to the local machine. 99 */ 100 iov.iov_base = (caddr_t) &error; 101 iov.iov_len = sizeof(error); 102 103 /* 104 * Build a msghdr 105 */ 106 memset(&msg, 0, sizeof(msg)); 107 msg.msg_iov = &iov; 108 msg.msg_iovlen = 1; 109 110 /* 111 * If there is a file descriptor to send then 112 * construct a suitable rights control message. 113 */ 114 if (fd >= 0) { 115 ctl.fd = fd; 116 ctl.cmsg.cmsg_len = sizeof(ctl); 117 ctl.cmsg.cmsg_level = SOL_SOCKET; 118 ctl.cmsg.cmsg_type = SCM_RIGHTS; 119 msg.msg_control = (caddr_t) &ctl; 120 msg.msg_controllen = ctl.cmsg.cmsg_len; 121 } 122 123 /* 124 * Send to kernel... 125 */ 126 if ((n = sendmsg(so, &msg, MSG_EOR)) < 0) 127 syslog(LOG_ERR, "send: %s", strerror(errno)); 128 #ifdef DEBUG 129 fprintf(stderr, "sent %d bytes\n", n); 130 #endif 131 sleep(1); /*XXX*/ 132 #ifdef notdef 133 if (shutdown(so, 2) < 0) 134 syslog(LOG_ERR, "shutdown: %s", strerror(errno)); 135 #endif 136 /* 137 * Throw away the open file descriptor 138 */ 139 (void) close(fd); 140 } 141 142 void activate(q, so) 143 qelem *q; 144 int so; 145 { 146 struct portal_cred pcred; 147 char key[MAXPATHLEN+1]; 148 int error; 149 char **v; 150 int fd = -1; 151 152 /* 153 * Read the key from the socket 154 */ 155 error = get_request(so, &pcred, key, sizeof(key)); 156 if (error) { 157 syslog(LOG_ERR, "activate: recvmsg: %s", strerror(error)); 158 goto drop; 159 } 160 161 #ifdef DEBUG 162 fprintf(stderr, "lookup key %s\n", key); 163 #endif 164 165 /* 166 * Find a match in the configuration file 167 */ 168 v = conf_match(q, key); 169 170 /* 171 * If a match existed, then find an appropriate portal 172 * otherwise simply return ENOENT. 173 */ 174 if (v) { 175 error = activate_argv(&pcred, key, v, so, &fd); 176 if (error) 177 fd = -1; 178 else if (fd < 0) 179 error = -1; 180 } else { 181 error = ENOENT; 182 } 183 184 if (error >= 0) 185 send_reply(so, fd, error); 186 187 drop:; 188 close(so); 189 } 190