1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * This is a proxy daemon for the real Java slpd. This deamon starts 29 * at boot time, and listens for any incoming SLP messages only on 30 * loopback -- this way, only local processes can start the real 31 * daemon. When a message comes in, the proxy daemon dups the message 32 * fds onto fds 0, 1, and 2, and execs the real Java slpd. The purpose 33 * of this approach is for performance: boot time performance is 34 * not degraded by cranking off the (huge) JVM, and systems take 35 * the JVM resource hit only if they actually use SLP. 36 */ 37 38 #include <stdio.h> 39 #include <sys/types.h> 40 #include <sys/socket.h> 41 #include <string.h> 42 #include <errno.h> 43 #include <sys/byteorder.h> 44 #include <sys/resource.h> 45 #include <netinet/in.h> 46 #include <unistd.h> 47 #include <slp.h> 48 #include <fcntl.h> 49 #include <stdlib.h> 50 #include <syslog.h> 51 52 /* This is an index which points into the args array at the conf file arg */ 53 #define CONF_INDEX 6 54 55 /* Location of the Java Virtual Machine */ 56 #define JAVA_VM "/usr/java/jre/bin/java" 57 58 static char *slpd_args[] = { 59 JAVA_VM, 60 "-Xmx128m", 61 "-classpath", 62 "/usr/share/lib/slp/slpd.jar", 63 "com.sun.slp.slpd", 64 "-f", 65 "/etc/inet/slp.conf", 66 0 67 }; 68 69 /* 70 * These are global so they can be easily accessed from a signal 71 * handler for cleanup. 72 */ 73 74 static void 75 run_slpd(void) 76 { 77 closelog(); 78 79 if (execv(*slpd_args, slpd_args) == -1) { 80 openlog("slpd", LOG_PID, LOG_DAEMON); 81 syslog(LOG_ERR, "execv failed: %s", strerror(errno)); 82 closelog(); 83 } 84 } 85 86 /* 87 * If an alternate config file was specified with -f, make sure slpd 88 * uses that config file. Also, force libslp.so to use that new config 89 * file when checking to see if slpd is a DA. If any other arguments 90 * are given, they are ignored. 91 */ 92 static void 93 do_args(int argc, char *const *argv) 94 { 95 int c; 96 char *conf = NULL; 97 98 while ((c = getopt(argc, argv, "f:")) != EOF) 99 switch (c) { 100 case 'f': 101 conf = optarg; 102 break; 103 default: 104 break; 105 } 106 107 if (conf != NULL) { 108 char *prefix = "SLP_CONF_FILE="; 109 int env_size; 110 char *conf_env; 111 112 env_size = strlen(prefix) + strlen(conf) + 1; 113 if ((conf_env = malloc(env_size)) == NULL) { 114 syslog(LOG_ERR, "no memory"); 115 exit(1); 116 } 117 (void) strlcpy(conf_env, prefix, env_size); 118 (void) strlcat(conf_env, conf, env_size); 119 120 (void) putenv(conf_env); 121 122 slpd_args[CONF_INDEX] = conf; 123 } 124 } 125 126 static void 127 detachfromtty(void) { 128 switch (fork()) { 129 case -1: 130 perror("slpd: can not fork"); 131 exit(1); 132 /*NOTREACHED*/ 133 case 0: 134 break; 135 default: 136 exit(0); 137 } 138 139 /* 140 * Close existing file descriptors, open "/dev/null" as 141 * standard input, output, and error, and detach from 142 * controlling terminal. 143 */ 144 closefrom(0); 145 (void) open("/dev/null", O_RDONLY); 146 (void) open("/dev/null", O_WRONLY); 147 (void) dup(1); 148 (void) setsid(); 149 } 150 151 static void 152 cleanup_and_exit(int retval) 153 { 154 closelog(); 155 exit(retval); 156 } 157 158 int 159 main(int argc, char *const *argv) 160 { 161 struct sockaddr_in bindaddr; 162 socklen_t addrlen; 163 const char *isDA; 164 const char *proxyReg; 165 int connfd; 166 int lfd; 167 const int on = 1; 168 169 detachfromtty(); 170 171 openlog("slpd", LOG_PID, LOG_DAEMON); 172 173 do_args(argc, argv); 174 175 /* If slpd has been configured to run as a DA, start it and exit */ 176 isDA = SLPGetProperty("net.slp.isDA"); 177 proxyReg = SLPGetProperty("net.slp.serializedRegURL"); 178 if ((isDA && (strcasecmp(isDA, "true") == 0)) || proxyReg) { 179 run_slpd(); 180 return (1); 181 } 182 183 if ((lfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 184 syslog(LOG_ERR, "socket failed: %s", strerror(errno)); 185 cleanup_and_exit(1); 186 } 187 188 (void) setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)); 189 190 (void) memset((void *)&bindaddr, 0, sizeof (bindaddr)); 191 bindaddr.sin_family = AF_INET; 192 bindaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 193 bindaddr.sin_port = htons(427); 194 195 if (bind(lfd, (const struct sockaddr *)&bindaddr, sizeof (bindaddr)) 196 < 0) { 197 syslog(LOG_ERR, "bind failed: %s", strerror(errno)); 198 cleanup_and_exit(1); 199 } 200 201 if (listen(lfd, 1) < 0) { 202 syslog(LOG_ERR, "listen failed: %s", strerror(errno)); 203 cleanup_and_exit(1); 204 } 205 206 addrlen = sizeof (bindaddr); 207 if ((connfd = accept(lfd, (struct sockaddr *)&bindaddr, &addrlen)) 208 < 0) { 209 syslog(LOG_ERR, "accept failed: %s", strerror(errno)); 210 cleanup_and_exit(1); 211 } 212 213 (void) close(lfd); 214 215 (void) dup2(connfd, 0); 216 (void) close(connfd); 217 (void) dup2(0, 1); 218 (void) dup2(0, 2); 219 220 run_slpd(); 221 222 return (1); 223 } 224