10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7298SMark.J.Nelson@Sun.COM * Common Development and Distribution License (the "License"). 6*7298SMark.J.Nelson@Sun.COM * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 220Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate * 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 27*7298SMark.J.Nelson@Sun.COM // sldp.java : The service location daemon. 280Sstevel@tonic-gate // Author: Erik Guttman 290Sstevel@tonic-gate // 300Sstevel@tonic-gate 310Sstevel@tonic-gate package com.sun.slp; 320Sstevel@tonic-gate 330Sstevel@tonic-gate import java.io.*; 340Sstevel@tonic-gate import java.util.*; 350Sstevel@tonic-gate import java.net.*; 360Sstevel@tonic-gate import java.lang.reflect.*; 370Sstevel@tonic-gate import java.awt.*; 380Sstevel@tonic-gate 390Sstevel@tonic-gate /** 400Sstevel@tonic-gate * The slpd class is the main class for the slpd directory agent/ 410Sstevel@tonic-gate * service agent server of SLP. Slpd can run in two possible modes, 420Sstevel@tonic-gate * depending on the configuration of the classes with which it was shipped 430Sstevel@tonic-gate * and information read from the optional configuration file argument: 440Sstevel@tonic-gate * 450Sstevel@tonic-gate * <ol> 460Sstevel@tonic-gate * <li> <b> Service Agent server </b> 470Sstevel@tonic-gate * In this mode, slpd functions as a service agent server only. 480Sstevel@tonic-gate * Directory agent functionality is disabled. Service agent 490Sstevel@tonic-gate * clients on the local machine register and deregister services 500Sstevel@tonic-gate * with slpd, and slpd responds to multicast requests for 510Sstevel@tonic-gate * services. It passively and actively listens for directory agent 520Sstevel@tonic-gate * advertisements, caches them, and forwards them to both 530Sstevel@tonic-gate * user agent and service agent clients. A file of serialized 540Sstevel@tonic-gate * proxy registrations can be read at startup. 550Sstevel@tonic-gate * This mode is normally default. 560Sstevel@tonic-gate * 570Sstevel@tonic-gate * <li> <b> Directory Agent/Service Agent server </b> 580Sstevel@tonic-gate * In this mode, slpd functions as a directory agent 590Sstevel@tonic-gate * for port 427 on the local machine. The directory agent 600Sstevel@tonic-gate * caches service advertisements, makes directory agent 610Sstevel@tonic-gate * advertisements of its services, and responds to requests 620Sstevel@tonic-gate * for TCP connections with service agents and user agents. 630Sstevel@tonic-gate * In addition, slpd functions in the first mode, as a 640Sstevel@tonic-gate * service agent server, for SAs and UAs on the local host. 650Sstevel@tonic-gate * 660Sstevel@tonic-gate * </ol> 670Sstevel@tonic-gate * 680Sstevel@tonic-gate * The slpd is invoked as follows:<br> 690Sstevel@tonic-gate *<blockquote> 700Sstevel@tonic-gate * 710Sstevel@tonic-gate * java com.sun.slpd [monitor] [stop] [-f <config file name>] 720Sstevel@tonic-gate * 730Sstevel@tonic-gate *</blockquote> 740Sstevel@tonic-gate * 750Sstevel@tonic-gate * The optional monitor argument specifies that a GUI monitor should be 760Sstevel@tonic-gate * brought up. The optional stop argument indicates that slpd should 770Sstevel@tonic-gate * signal a running slpd to stop. The optional <config file name> argument 780Sstevel@tonic-gate * specifies that the named file should be used as the configuration file. 790Sstevel@tonic-gate * <p> 800Sstevel@tonic-gate * See <a href="slpd.conf.html">slpd.conf</a> for more information on 810Sstevel@tonic-gate * configuration file syntax and <a href="slpd.reg.html">slpd.reg</a> 820Sstevel@tonic-gate * for more information on proxy registration file syntax. 830Sstevel@tonic-gate * 840Sstevel@tonic-gate * @author Erik Guttman, James Kempf 850Sstevel@tonic-gate */ 860Sstevel@tonic-gate 870Sstevel@tonic-gate // Note that the inheritance is *only* so slpd can initialize the 880Sstevel@tonic-gate // internals of SLP config. 890Sstevel@tonic-gate 900Sstevel@tonic-gate public class slpd extends SLPConfig { 910Sstevel@tonic-gate 920Sstevel@tonic-gate private static final String SERVER_BUNDLE_NAME = "com/sun/slp/Server"; 930Sstevel@tonic-gate 940Sstevel@tonic-gate // Server bundle. Set the parent. 950Sstevel@tonic-gate 960Sstevel@tonic-gate static class ServerBundle extends ResourceBundle { 970Sstevel@tonic-gate 980Sstevel@tonic-gate private ResourceBundle bundle = null; 990Sstevel@tonic-gate 1000Sstevel@tonic-gate static ResourceBundle getBundle(ResourceBundle parent, Locale locale)1010Sstevel@tonic-gate getBundle(ResourceBundle parent, Locale locale) 1020Sstevel@tonic-gate throws MissingResourceException { 1030Sstevel@tonic-gate 1040Sstevel@tonic-gate return new ServerBundle(parent, locale); 1050Sstevel@tonic-gate 1060Sstevel@tonic-gate } 1070Sstevel@tonic-gate ServerBundle(ResourceBundle parent, Locale locale)1080Sstevel@tonic-gate private ServerBundle(ResourceBundle parent, Locale locale) 1090Sstevel@tonic-gate throws MissingResourceException { 1100Sstevel@tonic-gate 1110Sstevel@tonic-gate if (parent != null) { 1120Sstevel@tonic-gate this.parent = parent; 1130Sstevel@tonic-gate 1140Sstevel@tonic-gate } 1150Sstevel@tonic-gate 1160Sstevel@tonic-gate try { 1170Sstevel@tonic-gate URL[] urls = null; 1180Sstevel@tonic-gate urls = new URL[] {new URL("file:/usr/share/lib/locale/")}; 1190Sstevel@tonic-gate URLClassLoader ld = new URLClassLoader(urls); 1200Sstevel@tonic-gate 1210Sstevel@tonic-gate bundle = 1220Sstevel@tonic-gate ResourceBundle.getBundle(SERVER_BUNDLE_NAME, locale, ld); 1230Sstevel@tonic-gate 1240Sstevel@tonic-gate } catch (MalformedURLException e) { 1250Sstevel@tonic-gate // fallthru to default location 1260Sstevel@tonic-gate } // No locales in slpd.jar, so propagate the 1270Sstevel@tonic-gate // MissingResourceException 1280Sstevel@tonic-gate 1290Sstevel@tonic-gate bundle = bundle != null ? 1300Sstevel@tonic-gate bundle : 1310Sstevel@tonic-gate ResourceBundle.getBundle(SERVER_BUNDLE_NAME, locale); 1320Sstevel@tonic-gate 1330Sstevel@tonic-gate } 1340Sstevel@tonic-gate handleGetObject(String key)1350Sstevel@tonic-gate protected Object handleGetObject(String key) 1360Sstevel@tonic-gate throws MissingResourceException { 1370Sstevel@tonic-gate Object ret = null; 1380Sstevel@tonic-gate 1390Sstevel@tonic-gate try { 1400Sstevel@tonic-gate 1410Sstevel@tonic-gate ret = bundle.getObject(key); 1420Sstevel@tonic-gate 1430Sstevel@tonic-gate } catch (MissingResourceException ex) { 1440Sstevel@tonic-gate ret = parent.getObject(key); 1450Sstevel@tonic-gate 1460Sstevel@tonic-gate } 1470Sstevel@tonic-gate 1480Sstevel@tonic-gate return ret; 1490Sstevel@tonic-gate 1500Sstevel@tonic-gate } 1510Sstevel@tonic-gate getKeys()1520Sstevel@tonic-gate public Enumeration getKeys() { 1530Sstevel@tonic-gate return bundle.getKeys(); 1540Sstevel@tonic-gate 1550Sstevel@tonic-gate } 1560Sstevel@tonic-gate 1570Sstevel@tonic-gate } 1580Sstevel@tonic-gate 1590Sstevel@tonic-gate /** 1600Sstevel@tonic-gate * Log object for SLP to write to GUI. This class follows the 1610Sstevel@tonic-gate * semantics of the other SLP logging classes: 1620Sstevel@tonic-gate * 1630Sstevel@tonic-gate * This class does not actually write anything until the flush() method 1640Sstevel@tonic-gate * in invoked; this will write the concatenation of all messages 1650Sstevel@tonic-gate * passed to the write() method since the last invocation of flush(). 1660Sstevel@tonic-gate * 1670Sstevel@tonic-gate * The actual logging class used can be controlled via the 1680Sstevel@tonic-gate * sun.net.slp.loggerClass property. 1690Sstevel@tonic-gate * 1700Sstevel@tonic-gate * See also the StderrLog and Syslog classes. 1710Sstevel@tonic-gate */ 1720Sstevel@tonic-gate 1730Sstevel@tonic-gate static class SLPLog extends Writer { 1740Sstevel@tonic-gate 1750Sstevel@tonic-gate private TextArea taLog = null; 1760Sstevel@tonic-gate private StringBuffer buf; 1770Sstevel@tonic-gate SLPLog(TextArea nta)1780Sstevel@tonic-gate SLPLog(TextArea nta) { 1790Sstevel@tonic-gate taLog = nta; 1800Sstevel@tonic-gate buf = new StringBuffer(); 1810Sstevel@tonic-gate 1820Sstevel@tonic-gate } 1830Sstevel@tonic-gate 1840Sstevel@tonic-gate // Write to the StringBuffer 1850Sstevel@tonic-gate write(char[] cbuf, int off, int len)1860Sstevel@tonic-gate public void write(char[] cbuf, int off, int len) 1870Sstevel@tonic-gate throws IOException { 1880Sstevel@tonic-gate buf.append(cbuf, off, len); 1890Sstevel@tonic-gate 1900Sstevel@tonic-gate } 1910Sstevel@tonic-gate 1920Sstevel@tonic-gate // Write to the Frame. 1930Sstevel@tonic-gate flush()1940Sstevel@tonic-gate public void flush() throws IOException { 1950Sstevel@tonic-gate String date = SLPConfig.getDateString(); 1960Sstevel@tonic-gate 1970Sstevel@tonic-gate taLog.append( 1980Sstevel@tonic-gate "********" + 1990Sstevel@tonic-gate date + "\n" + 2000Sstevel@tonic-gate buf.toString() + "\n" + 2010Sstevel@tonic-gate "********\n"); 2020Sstevel@tonic-gate buf = new StringBuffer(); 2030Sstevel@tonic-gate 2040Sstevel@tonic-gate } 2050Sstevel@tonic-gate 2060Sstevel@tonic-gate // These is a no-op 2070Sstevel@tonic-gate close()2080Sstevel@tonic-gate public void close() throws IOException {} 2090Sstevel@tonic-gate 2100Sstevel@tonic-gate } 2110Sstevel@tonic-gate 2120Sstevel@tonic-gate // 2130Sstevel@tonic-gate // slpd definition. 2140Sstevel@tonic-gate // 2150Sstevel@tonic-gate 2160Sstevel@tonic-gate private static String configFile; // name of configuration file 2170Sstevel@tonic-gate private static SLPDgui slpdgui; // GUI monitor, if desired 2180Sstevel@tonic-gate private static SLPConfig config; // handles system properties 2190Sstevel@tonic-gate private static ServerDATable daTable; // handle recording of DAs 2200Sstevel@tonic-gate 2210Sstevel@tonic-gate // Called by the slpd and subclasses only. 2220Sstevel@tonic-gate slpd()2230Sstevel@tonic-gate protected slpd() { 2240Sstevel@tonic-gate super(); 2250Sstevel@tonic-gate } 2260Sstevel@tonic-gate usage()2270Sstevel@tonic-gate private static void usage() { 2280Sstevel@tonic-gate ResourceBundle bundle = 2290Sstevel@tonic-gate getMessageBundleInternal(Locale.getDefault(), null); 2300Sstevel@tonic-gate System.err.println(formatMessageInternal("slpd_usage", 2310Sstevel@tonic-gate new Object[0], 2320Sstevel@tonic-gate bundle)); 2330Sstevel@tonic-gate System.exit(1); 2340Sstevel@tonic-gate } 2350Sstevel@tonic-gate 2360Sstevel@tonic-gate /** 2370Sstevel@tonic-gate * Usage: slpd [monitor] [stop] [-f config-file name]<br> 2380Sstevel@tonic-gate * <br> 2390Sstevel@tonic-gate * String arguments are: 2400Sstevel@tonic-gate * <br> 2410Sstevel@tonic-gate * <b> monitor </b> Puts up a rudimentary GUI for the slpd.<br> 2420Sstevel@tonic-gate * <b>stop <b> Bring down a running slpd and exit. 2430Sstevel@tonic-gate * <b> config-file name </b> Reads the specified configuration file.<br> 2440Sstevel@tonic-gate * 2450Sstevel@tonic-gate * The default running mode is to have no GUI and to use SLP 2460Sstevel@tonic-gate * defined configuration. 2470Sstevel@tonic-gate */ 2480Sstevel@tonic-gate main(String args[])2490Sstevel@tonic-gate public static void main(String args[]) { 2500Sstevel@tonic-gate boolean bMon = false; 2510Sstevel@tonic-gate boolean bStop = false; 2520Sstevel@tonic-gate configFile = null; 2530Sstevel@tonic-gate 2540Sstevel@tonic-gate Thread.currentThread().setName("slpd"); 2550Sstevel@tonic-gate 2560Sstevel@tonic-gate // Process args. 2570Sstevel@tonic-gate 2580Sstevel@tonic-gate if (args.length > 3) { 2590Sstevel@tonic-gate usage(); 2600Sstevel@tonic-gate 2610Sstevel@tonic-gate } 2620Sstevel@tonic-gate 2630Sstevel@tonic-gate int i, n = args.length; 2640Sstevel@tonic-gate 2650Sstevel@tonic-gate for (i = 0; i < n; i++) { 2660Sstevel@tonic-gate 2670Sstevel@tonic-gate // Argument is a config file. 2680Sstevel@tonic-gate 2690Sstevel@tonic-gate if (args[i].equals("-f")) { 2700Sstevel@tonic-gate 2710Sstevel@tonic-gate if (configFile != null) { 2720Sstevel@tonic-gate usage(); 2730Sstevel@tonic-gate 2740Sstevel@tonic-gate } 2750Sstevel@tonic-gate 2760Sstevel@tonic-gate // Make sure we can open it. 2770Sstevel@tonic-gate 2780Sstevel@tonic-gate try { 2790Sstevel@tonic-gate File f = new File(args[++i]); 2800Sstevel@tonic-gate configFile = args[i]; 2810Sstevel@tonic-gate 2820Sstevel@tonic-gate } catch (Exception ex) { 2830Sstevel@tonic-gate usage(); 2840Sstevel@tonic-gate 2850Sstevel@tonic-gate } 2860Sstevel@tonic-gate } else if (args[i].equals("monitor")) { 2870Sstevel@tonic-gate bMon = true; 2880Sstevel@tonic-gate 2890Sstevel@tonic-gate } else if (args[i].equals("stop")) { 2900Sstevel@tonic-gate bStop = true; 2910Sstevel@tonic-gate 2920Sstevel@tonic-gate } else { 2930Sstevel@tonic-gate usage(); 2940Sstevel@tonic-gate 2950Sstevel@tonic-gate } 2960Sstevel@tonic-gate } 2970Sstevel@tonic-gate 2980Sstevel@tonic-gate // Read message bundle file, load config file into properties. 2990Sstevel@tonic-gate 3000Sstevel@tonic-gate ResourceBundle bundle = 3010Sstevel@tonic-gate getMessageBundleInternal(Locale.getDefault(), null); 3020Sstevel@tonic-gate 3030Sstevel@tonic-gate try { 3040Sstevel@tonic-gate if (configFile != null) { 3050Sstevel@tonic-gate Properties props = System.getProperties(); 3060Sstevel@tonic-gate props.setProperty("sun.net.slp.configURL", 3070Sstevel@tonic-gate "file:" + configFile); 3080Sstevel@tonic-gate 3090Sstevel@tonic-gate } 3100Sstevel@tonic-gate 3110Sstevel@tonic-gate // Create a new SLP Config object from the config file. 3120Sstevel@tonic-gate config = initializeSLPConfig(); 3130Sstevel@tonic-gate 3140Sstevel@tonic-gate // Create a GUI if the user asked for one. 3150Sstevel@tonic-gate 3160Sstevel@tonic-gate if (bMon) { 3170Sstevel@tonic-gate 3180Sstevel@tonic-gate try { 3190Sstevel@tonic-gate slpdgui = new SLPDgui(configFile); 3200Sstevel@tonic-gate SLPLog log = new SLPLog(slpdgui.getTALog()); 3210Sstevel@tonic-gate 3220Sstevel@tonic-gate synchronized (config) { 3230Sstevel@tonic-gate config.log = log; 3240Sstevel@tonic-gate } 3250Sstevel@tonic-gate 3260Sstevel@tonic-gate slpdgui.setVisible(true); 3270Sstevel@tonic-gate 3280Sstevel@tonic-gate } catch (Exception ex) { 3290Sstevel@tonic-gate System.err.println(formatMessageInternal("slpd_no_gui", 3300Sstevel@tonic-gate new Object[0], 3310Sstevel@tonic-gate bundle)); 3320Sstevel@tonic-gate } 3330Sstevel@tonic-gate } 3340Sstevel@tonic-gate 3350Sstevel@tonic-gate // Either start or stop the server, depending on what was 3360Sstevel@tonic-gate // requested. 3370Sstevel@tonic-gate 3380Sstevel@tonic-gate if (!bStop) { 3390Sstevel@tonic-gate start(); 3400Sstevel@tonic-gate 3410Sstevel@tonic-gate } else { 3420Sstevel@tonic-gate stop(); 3430Sstevel@tonic-gate 3440Sstevel@tonic-gate } 3450Sstevel@tonic-gate } catch (ServiceLocationException ex) { 3460Sstevel@tonic-gate 3470Sstevel@tonic-gate errorExit(bundle, ex); 3480Sstevel@tonic-gate 3490Sstevel@tonic-gate } 3500Sstevel@tonic-gate 3510Sstevel@tonic-gate } 3520Sstevel@tonic-gate 3530Sstevel@tonic-gate /** 3540Sstevel@tonic-gate * Start the slpd. 3550Sstevel@tonic-gate * 3560Sstevel@tonic-gate * @param bMon True if initializing with GUI monitor. 3570Sstevel@tonic-gate * @exception ServiceLocationException Internal error or network 3580Sstevel@tonic-gate * initialization error or 3590Sstevel@tonic-gate * internal networking error. 3600Sstevel@tonic-gate * 3610Sstevel@tonic-gate */ 3620Sstevel@tonic-gate start()3630Sstevel@tonic-gate static void start() throws ServiceLocationException { 3640Sstevel@tonic-gate 3650Sstevel@tonic-gate // Initialize the service table. 3660Sstevel@tonic-gate 3670Sstevel@tonic-gate ServiceTable table = ServiceTable.getServiceTable(); 3680Sstevel@tonic-gate 3690Sstevel@tonic-gate // Initialize the class name for the DA table to the Sun-specific 3700Sstevel@tonic-gate // DA table. 3710Sstevel@tonic-gate 3720Sstevel@tonic-gate Properties props = System.getProperties(); 3730Sstevel@tonic-gate props.put(DATable.DA_TABLE_CLASS_PROP, "com.sun.slp.SunServerDATable"); 3740Sstevel@tonic-gate 3750Sstevel@tonic-gate // If there is a request on stdin, process it now 3760Sstevel@tonic-gate try { 3770Sstevel@tonic-gate if (System.in.available() > 0) { 3780Sstevel@tonic-gate RequestHandler rh = 3790Sstevel@tonic-gate new RequestHandler(System.in, System.out, config); 3800Sstevel@tonic-gate rh.start(); 3810Sstevel@tonic-gate } 3820Sstevel@tonic-gate } catch (IOException e) {} 3830Sstevel@tonic-gate 3840Sstevel@tonic-gate // Start a StreamListener on loopback to start accepting locals regs 3850Sstevel@tonic-gate 3860Sstevel@tonic-gate StreamListener.initializeStreamListenerOnInterface( 3870Sstevel@tonic-gate config.getLoopback()); 3880Sstevel@tonic-gate 3890Sstevel@tonic-gate // Create a ServerDATable from the class. This will initialize 3900Sstevel@tonic-gate // active discovery. Note that we need to record our own presence 3910Sstevel@tonic-gate // in the DA table because we are not yet listening for requests. 3920Sstevel@tonic-gate // We do this after deserialization so that if we discover any 3930Sstevel@tonic-gate // DAs, we can perform registrations of the serialized advertisements. 3940Sstevel@tonic-gate 3950Sstevel@tonic-gate daTable = ServerDATable.getServerDATable(); 3960Sstevel@tonic-gate 3970Sstevel@tonic-gate // Deserialize any serialized advertisements and do them now. 3980Sstevel@tonic-gate // Waiting until here allows any error messages to appear in 3990Sstevel@tonic-gate // the GUI log, if any, and at this point the DA table is ready. 4000Sstevel@tonic-gate 4010Sstevel@tonic-gate table.deserializeTable(); 4020Sstevel@tonic-gate 4030Sstevel@tonic-gate // Need to create datagram and stream listeners, and a 4040Sstevel@tonic-gate // DAAdvertiser on all network interfaces. 4050Sstevel@tonic-gate 4060Sstevel@tonic-gate Vector interfaces = config.getInterfaces(); 4070Sstevel@tonic-gate int i, n = interfaces.size(); 4080Sstevel@tonic-gate 4090Sstevel@tonic-gate for (i = 0; i < n; i++) { 4100Sstevel@tonic-gate InetAddress interfac = (InetAddress)interfaces.elementAt(i); 4110Sstevel@tonic-gate 4120Sstevel@tonic-gate // Initialize the complex of listener/sender objects on the 4130Sstevel@tonic-gate // interface. This includes a datagram listener, a DAAdvertiser 4140Sstevel@tonic-gate // (which shares the same socket as the datagram listener), and 4150Sstevel@tonic-gate // a stream listener. 4160Sstevel@tonic-gate 4170Sstevel@tonic-gate Listener.initializeInterfaceManagers(interfac); 4180Sstevel@tonic-gate 4190Sstevel@tonic-gate } 4200Sstevel@tonic-gate 4210Sstevel@tonic-gate // If we've been configured as a DA, then create a DA advertiser to 4220Sstevel@tonic-gate // periodically advertise our presence on this interface. This 4230Sstevel@tonic-gate // is only done on the default interface. 4240Sstevel@tonic-gate 4250Sstevel@tonic-gate if (config.isDA()) { 4260Sstevel@tonic-gate DAAdvertiser.initializeDAAdvertiserOnInterface( 4270Sstevel@tonic-gate config.getLocalHost()); 4280Sstevel@tonic-gate 4290Sstevel@tonic-gate } 4300Sstevel@tonic-gate 4310Sstevel@tonic-gate // Report scopes and whether DA or SA. 4320Sstevel@tonic-gate 4330Sstevel@tonic-gate Vector discoveredScopes = daTable.findScopes(); 4340Sstevel@tonic-gate Vector serverScopes = config.getSAConfiguredScopes(); 4350Sstevel@tonic-gate Vector daAttributes = config.getDAAttributes(); 4360Sstevel@tonic-gate Vector saAttributes = config.getSAAttributes(); 4370Sstevel@tonic-gate 4380Sstevel@tonic-gate // Report that we are running if tracing is on 4390Sstevel@tonic-gate 4400Sstevel@tonic-gate if (config.regTest() || 4410Sstevel@tonic-gate config.traceMsg() || 4420Sstevel@tonic-gate config.traceDrop() || 4430Sstevel@tonic-gate config.traceDATraffic()) { 4440Sstevel@tonic-gate 4450Sstevel@tonic-gate config.writeLog((config.isDA() ? "hello_da":"hello"), 4460Sstevel@tonic-gate new Object[] {interfaces, 4470Sstevel@tonic-gate serverScopes, 4480Sstevel@tonic-gate discoveredScopes, 4490Sstevel@tonic-gate (config.isDA() ? 4500Sstevel@tonic-gate daAttributes:saAttributes)}); 4510Sstevel@tonic-gate } 4520Sstevel@tonic-gate 4530Sstevel@tonic-gate // If V1 is supported, crank up V1 support as well. 4540Sstevel@tonic-gate 4550Sstevel@tonic-gate if (config.isV1Supported()) { 4560Sstevel@tonic-gate SLPV1Manager.start(config, daTable, table); 4570Sstevel@tonic-gate 4580Sstevel@tonic-gate } 4590Sstevel@tonic-gate } 4600Sstevel@tonic-gate 4610Sstevel@tonic-gate // Stop a running server by sending a DAAdvert or SAAdvert. 4620Sstevel@tonic-gate stop()4630Sstevel@tonic-gate static void stop() throws ServiceLocationException { 4640Sstevel@tonic-gate 4650Sstevel@tonic-gate if (daemonIsDA()) { 4660Sstevel@tonic-gate stopDA(); 4670Sstevel@tonic-gate 4680Sstevel@tonic-gate } else { 4690Sstevel@tonic-gate stopSA(); 4700Sstevel@tonic-gate 4710Sstevel@tonic-gate } 4720Sstevel@tonic-gate } 4730Sstevel@tonic-gate 4740Sstevel@tonic-gate // Determine whether the daemon running on this machine is a DA 4750Sstevel@tonic-gate // or not. 4760Sstevel@tonic-gate daemonIsDA()4770Sstevel@tonic-gate static boolean daemonIsDA() throws ServiceLocationException { 4780Sstevel@tonic-gate 4790Sstevel@tonic-gate // Get a DA table with available DAs. 4800Sstevel@tonic-gate 4810Sstevel@tonic-gate DATable table = 4820Sstevel@tonic-gate DATable.getDATable(); 4830Sstevel@tonic-gate 4840Sstevel@tonic-gate // Get DAs. 4850Sstevel@tonic-gate 4860Sstevel@tonic-gate Hashtable das = 4870Sstevel@tonic-gate table.findDAScopes(config.getSAConfiguredScopes()); 4880Sstevel@tonic-gate Vector daRecs = (Vector)das.get(DATable.UNICAST_KEY); 4890Sstevel@tonic-gate Vector interfaces = config.getInterfaces(); 4900Sstevel@tonic-gate 4910Sstevel@tonic-gate // If no DAs, then simply return. 4920Sstevel@tonic-gate 4930Sstevel@tonic-gate if (daRecs == null) { 4940Sstevel@tonic-gate return false; 4950Sstevel@tonic-gate 4960Sstevel@tonic-gate } 4970Sstevel@tonic-gate 4980Sstevel@tonic-gate // Find our address in the list, if it exists. 4990Sstevel@tonic-gate 5000Sstevel@tonic-gate int i, n = daRecs.size(); 5010Sstevel@tonic-gate 5020Sstevel@tonic-gate for (i = 0; i < n; i++) { 5030Sstevel@tonic-gate DATable.DARecord rec = 5040Sstevel@tonic-gate (DATable.DARecord)daRecs.elementAt(i); 5050Sstevel@tonic-gate Vector daAddresses = rec.daAddresses; 5060Sstevel@tonic-gate 5070Sstevel@tonic-gate int j, m = interfaces.size(); 5080Sstevel@tonic-gate 5090Sstevel@tonic-gate for (j = 0; j < m; j++) { 5100Sstevel@tonic-gate if (daAddresses.contains(interfaces.elementAt(i))) { 5110Sstevel@tonic-gate return true; 5120Sstevel@tonic-gate 5130Sstevel@tonic-gate } 5140Sstevel@tonic-gate } 5150Sstevel@tonic-gate } 5160Sstevel@tonic-gate 5170Sstevel@tonic-gate return false; 5180Sstevel@tonic-gate } 5190Sstevel@tonic-gate 5200Sstevel@tonic-gate // Stop a DA by multicasting the DAAdvert with boot timestamp 0. 5210Sstevel@tonic-gate stopDA()5220Sstevel@tonic-gate private static void stopDA() throws ServiceLocationException { 5230Sstevel@tonic-gate 5240Sstevel@tonic-gate // Make the DA URL and the DAAdvert. Note that we only need signal 5250Sstevel@tonic-gate // on the default local host interface because that is the only 5260Sstevel@tonic-gate // one on which the server is listening. 5270Sstevel@tonic-gate 5280Sstevel@tonic-gate ServiceURL url = 5290Sstevel@tonic-gate new ServiceURL(Defaults.DA_SERVICE_TYPE + 5300Sstevel@tonic-gate "://" + 5310Sstevel@tonic-gate config.getLocalHost().getHostAddress(), 5320Sstevel@tonic-gate ServiceURL.LIFETIME_DEFAULT); 5330Sstevel@tonic-gate 5340Sstevel@tonic-gate SDAAdvert advert = 5350Sstevel@tonic-gate new SDAAdvert(new SLPServerHeaderV2(), 5360Sstevel@tonic-gate (short)0x0, // sez we're unsolicited... 5370Sstevel@tonic-gate 0L, // sez we're going down... 5380Sstevel@tonic-gate url, 5390Sstevel@tonic-gate config.getSAConfiguredScopes(), 5400Sstevel@tonic-gate new Vector()); // no attributes needed to go down... 5410Sstevel@tonic-gate 5420Sstevel@tonic-gate // Make the DAAdvertiser. 5430Sstevel@tonic-gate 5440Sstevel@tonic-gate DAAdvertiser daadv = new DAAdvertiser(config.getLocalHost(), 5450Sstevel@tonic-gate advert.getHeader()); 5460Sstevel@tonic-gate 5470Sstevel@tonic-gate // Send out unsolicted "going down" message. 5480Sstevel@tonic-gate 5490Sstevel@tonic-gate daadv.sendAdvert(); 5500Sstevel@tonic-gate 5510Sstevel@tonic-gate // That's it! No need for any messages here. 5520Sstevel@tonic-gate 5530Sstevel@tonic-gate System.exit(0); 5540Sstevel@tonic-gate 5550Sstevel@tonic-gate } 5560Sstevel@tonic-gate 5570Sstevel@tonic-gate // Stop an SA server by unicasting an SA advert with xid 0. 5580Sstevel@tonic-gate stopSA()5590Sstevel@tonic-gate private static void stopSA() throws ServiceLocationException { 5600Sstevel@tonic-gate 5610Sstevel@tonic-gate // We signal for stop on the local host, which is guaranteed 5620Sstevel@tonic-gate // to have an SA listener. 5630Sstevel@tonic-gate 5640Sstevel@tonic-gate ServiceURL url = 5650Sstevel@tonic-gate new ServiceURL(Defaults.SA_SERVICE_TYPE + "://" + 5660Sstevel@tonic-gate config.getLocalHost().getHostAddress(), 5670Sstevel@tonic-gate ServiceURL.LIFETIME_DEFAULT); 5680Sstevel@tonic-gate 5690Sstevel@tonic-gate SSAAdvert advert = new SSAAdvert(Defaults.version, 5700Sstevel@tonic-gate (short)0x0, // sez we're going down... 5710Sstevel@tonic-gate config.getLocale(), 5720Sstevel@tonic-gate url, 5730Sstevel@tonic-gate config.getSAConfiguredScopes(), 5740Sstevel@tonic-gate new Vector()); 5750Sstevel@tonic-gate // don't care about attrs.., 5760Sstevel@tonic-gate 5770Sstevel@tonic-gate // Send it TCP. We ignore NETWORK_ERROR because it only means 5780Sstevel@tonic-gate // that the daemon didn't send us a reply, which is expected. 5790Sstevel@tonic-gate 5800Sstevel@tonic-gate try { 5810Sstevel@tonic-gate 5820Sstevel@tonic-gate SrvLocMsg msg = 5830Sstevel@tonic-gate Transact.transactTCPMsg(config.getLoopback(), advert, false); 5840Sstevel@tonic-gate 5850Sstevel@tonic-gate if (msg.getErrorCode() != ServiceLocationException.OK) { 5860Sstevel@tonic-gate config.writeLog("slpd_sa_stop_failure", 5870Sstevel@tonic-gate new Object[] { 5880Sstevel@tonic-gate new Integer(msg.getErrorCode())}); 5890Sstevel@tonic-gate 5900Sstevel@tonic-gate } 5910Sstevel@tonic-gate 5920Sstevel@tonic-gate } catch (ServiceLocationException ex) { 5930Sstevel@tonic-gate 5940Sstevel@tonic-gate if (ex.getErrorCode() != ServiceLocationException.NETWORK_ERROR) { 5950Sstevel@tonic-gate config.writeLog("slpd_sa_stop_failure", 5960Sstevel@tonic-gate new Object[] {new Integer(ex.getErrorCode())}); 5970Sstevel@tonic-gate 5980Sstevel@tonic-gate } 5990Sstevel@tonic-gate 6000Sstevel@tonic-gate } 6010Sstevel@tonic-gate 6020Sstevel@tonic-gate // That's it! 6030Sstevel@tonic-gate 6040Sstevel@tonic-gate System.exit(0); 6050Sstevel@tonic-gate } 6060Sstevel@tonic-gate 6070Sstevel@tonic-gate // Print error message, exit. 6080Sstevel@tonic-gate errorExit(ResourceBundle bundle, ServiceLocationException ex)6090Sstevel@tonic-gate static void errorExit(ResourceBundle bundle, ServiceLocationException ex) { 6100Sstevel@tonic-gate 6110Sstevel@tonic-gate switch (ex.getErrorCode()) { 6120Sstevel@tonic-gate 6130Sstevel@tonic-gate case ServiceLocationException.INTERNAL_SYSTEM_ERROR: 6140Sstevel@tonic-gate System.err.println(formatMessageInternal("slpd_int_err", 6150Sstevel@tonic-gate new Object[] { 6160Sstevel@tonic-gate ex.getMessage()}, 6170Sstevel@tonic-gate bundle)); 6180Sstevel@tonic-gate break; 6190Sstevel@tonic-gate 6200Sstevel@tonic-gate case ServiceLocationException.NETWORK_INIT_FAILED: 6210Sstevel@tonic-gate System.err.println(formatMessageInternal("slpd_intnet_err", 6220Sstevel@tonic-gate new Object[] { 6230Sstevel@tonic-gate ex.getMessage()}, 6240Sstevel@tonic-gate bundle)); 6250Sstevel@tonic-gate break; 6260Sstevel@tonic-gate 6270Sstevel@tonic-gate case ServiceLocationException.NETWORK_ERROR: 6280Sstevel@tonic-gate System.err.println(formatMessageInternal("slpd_net_err", 6290Sstevel@tonic-gate new Object[] { 6300Sstevel@tonic-gate ex.getMessage()}, 6310Sstevel@tonic-gate bundle)); 6320Sstevel@tonic-gate break; 6330Sstevel@tonic-gate 6340Sstevel@tonic-gate default: 6350Sstevel@tonic-gate System.err.println(formatMessageInternal("slpd_err", 6360Sstevel@tonic-gate new Object[] { 6370Sstevel@tonic-gate new Integer(ex.getErrorCode()), 6380Sstevel@tonic-gate ex.getMessage()}, 6390Sstevel@tonic-gate bundle)); 6400Sstevel@tonic-gate 6410Sstevel@tonic-gate } 6420Sstevel@tonic-gate 6430Sstevel@tonic-gate ex.printStackTrace(); 6440Sstevel@tonic-gate System.err.println(formatMessageInternal("exiting_msg", 6450Sstevel@tonic-gate new Object[0], 6460Sstevel@tonic-gate bundle)); 6470Sstevel@tonic-gate 6480Sstevel@tonic-gate System.exit(1); 6490Sstevel@tonic-gate 6500Sstevel@tonic-gate } 6510Sstevel@tonic-gate 6520Sstevel@tonic-gate // Make a new SLPConfig object of the right class type. 6530Sstevel@tonic-gate initializeSLPConfig()6540Sstevel@tonic-gate private static SLPConfig initializeSLPConfig() { 6550Sstevel@tonic-gate 6560Sstevel@tonic-gate // The server *always* runs as an SA. It may also run as a DA. 6570Sstevel@tonic-gate 6580Sstevel@tonic-gate config.isSA = true; 6590Sstevel@tonic-gate 6600Sstevel@tonic-gate // set default logging class for slpd to syslog 6610Sstevel@tonic-gate 6620Sstevel@tonic-gate if (System.getProperty("sun.net.slp.loggerClass") == null) { 6630Sstevel@tonic-gate Properties props = System.getProperties(); 6640Sstevel@tonic-gate props.setProperty("sun.net.slp.loggerClass", "com.sun.slp.Syslog"); 6650Sstevel@tonic-gate System.setProperties(props); 6660Sstevel@tonic-gate 6670Sstevel@tonic-gate } 6680Sstevel@tonic-gate 6690Sstevel@tonic-gate // slpd is the server side config. 6700Sstevel@tonic-gate 6710Sstevel@tonic-gate theSLPConfig = new slpd(); 6720Sstevel@tonic-gate 6730Sstevel@tonic-gate return theSLPConfig; 6740Sstevel@tonic-gate 6750Sstevel@tonic-gate } 6760Sstevel@tonic-gate 6770Sstevel@tonic-gate // 6780Sstevel@tonic-gate // Extensions to sldp for server side only. 6790Sstevel@tonic-gate // 6800Sstevel@tonic-gate isDA()6810Sstevel@tonic-gate boolean isDA() { 6820Sstevel@tonic-gate return Boolean.getBoolean("net.slp.isDA"); 6830Sstevel@tonic-gate } 6840Sstevel@tonic-gate 6850Sstevel@tonic-gate // Determine whether V1 is supported. Default is no. 6860Sstevel@tonic-gate isV1Supported()6870Sstevel@tonic-gate boolean isV1Supported() { 6880Sstevel@tonic-gate 6890Sstevel@tonic-gate if (!isDA() || super.getSLPv1NotSupported()) { 6900Sstevel@tonic-gate return false; 6910Sstevel@tonic-gate 6920Sstevel@tonic-gate } 6930Sstevel@tonic-gate 6940Sstevel@tonic-gate boolean v1Supported = false; 6950Sstevel@tonic-gate 6960Sstevel@tonic-gate try { 6970Sstevel@tonic-gate 6980Sstevel@tonic-gate Class.forName("com.sun.slp.SLPV1Manager"); 6990Sstevel@tonic-gate v1Supported = true; 7000Sstevel@tonic-gate 7010Sstevel@tonic-gate } catch (ClassNotFoundException ex) { 7020Sstevel@tonic-gate 7030Sstevel@tonic-gate // Not there. 7040Sstevel@tonic-gate 7050Sstevel@tonic-gate } 7060Sstevel@tonic-gate 7070Sstevel@tonic-gate return v1Supported; 7080Sstevel@tonic-gate 7090Sstevel@tonic-gate } 7100Sstevel@tonic-gate 7110Sstevel@tonic-gate // Load server message bundle. 7120Sstevel@tonic-gate 7130Sstevel@tonic-gate private static final String serverMsgBundle = "Server"; 7140Sstevel@tonic-gate getMessageBundle(Locale locale)7150Sstevel@tonic-gate ResourceBundle getMessageBundle(Locale locale) { 7160Sstevel@tonic-gate 7170Sstevel@tonic-gate // Get the parent bundle first. 7180Sstevel@tonic-gate 7190Sstevel@tonic-gate ResourceBundle parentBundle = super.getMessageBundle(locale); 7200Sstevel@tonic-gate 7210Sstevel@tonic-gate return getMessageBundleInternal(locale, parentBundle); 7220Sstevel@tonic-gate 7230Sstevel@tonic-gate } 7240Sstevel@tonic-gate 7250Sstevel@tonic-gate // We need this in case we get an error before the config object is 7260Sstevel@tonic-gate // created. 7270Sstevel@tonic-gate getMessageBundleInternal( Locale locale, ResourceBundle parentBundle)7280Sstevel@tonic-gate static private ResourceBundle getMessageBundleInternal( 7290Sstevel@tonic-gate Locale locale, 7300Sstevel@tonic-gate ResourceBundle parentBundle) { 7310Sstevel@tonic-gate 7320Sstevel@tonic-gate // Now create a server subclass. 7330Sstevel@tonic-gate 7340Sstevel@tonic-gate ResourceBundle msgBundle = null; 7350Sstevel@tonic-gate 7360Sstevel@tonic-gate try { 7370Sstevel@tonic-gate msgBundle = ServerBundle.getBundle(parentBundle, locale); 7380Sstevel@tonic-gate 7390Sstevel@tonic-gate } catch (MissingResourceException ex) { // can't localize this one! 7400Sstevel@tonic-gate 7410Sstevel@tonic-gate // We can't print out to the log, because we may be in the 7420Sstevel@tonic-gate // process of trying to. 7430Sstevel@tonic-gate 7440Sstevel@tonic-gate System.out.println("Missing resource bundle ``"+ 7450Sstevel@tonic-gate SERVER_BUNDLE_NAME+ 7460Sstevel@tonic-gate "'' for locale ``"+ 7470Sstevel@tonic-gate locale+ 7480Sstevel@tonic-gate "''"); 7490Sstevel@tonic-gate // Hosed if the default locale is missing. 7500Sstevel@tonic-gate 7510Sstevel@tonic-gate if (locale.equals(Defaults.locale)) { 7520Sstevel@tonic-gate 7530Sstevel@tonic-gate System.out.println("Exiting..."); 7540Sstevel@tonic-gate System.exit(1); 7550Sstevel@tonic-gate } 7560Sstevel@tonic-gate 7570Sstevel@tonic-gate // Otherwise, return the default locale. 7580Sstevel@tonic-gate 7590Sstevel@tonic-gate System.out.println("Using SLP default locale ``" + 7600Sstevel@tonic-gate Defaults.locale+"''"); 7610Sstevel@tonic-gate 7620Sstevel@tonic-gate msgBundle = 7630Sstevel@tonic-gate getMessageBundleInternal(Defaults.locale, parentBundle); 7640Sstevel@tonic-gate 7650Sstevel@tonic-gate } 7660Sstevel@tonic-gate 7670Sstevel@tonic-gate return msgBundle; 7680Sstevel@tonic-gate } 7690Sstevel@tonic-gate 7700Sstevel@tonic-gate } 771