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