17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
59a70fc3bSMark J. Nelson  * Common Development and Distribution License (the "License").
69a70fc3bSMark J. Nelson  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
227c478bd9Sstevel@tonic-gate  * Copyright (c) 2001 by Sun Microsystems, Inc.
237c478bd9Sstevel@tonic-gate  * All rights reserved.
247c478bd9Sstevel@tonic-gate  *
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate //  SLPV1Manager.java: Manages V1 Compatibility
287c478bd9Sstevel@tonic-gate //  Author:           James Kempf
297c478bd9Sstevel@tonic-gate //  Created On:       Wed Sep  9 09:51:40 1998
307c478bd9Sstevel@tonic-gate //  Last Modified By: James Kempf
317c478bd9Sstevel@tonic-gate //  Last Modified On: Thu Mar  4 10:39:11 1999
327c478bd9Sstevel@tonic-gate //  Update Count:     46
337c478bd9Sstevel@tonic-gate //
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate package com.sun.slp;
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate import java.io.*;
387c478bd9Sstevel@tonic-gate import java.util.*;
397c478bd9Sstevel@tonic-gate import java.net.*;
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate /**
437c478bd9Sstevel@tonic-gate  * The SLPV1Manager manages access between the DA and the V1 compatibility
447c478bd9Sstevel@tonic-gate  * framework. The DA calls into the SLPV1Manager to initialize
457c478bd9Sstevel@tonic-gate  * active and passive DA advertising, and to decode an incoming V1
467c478bd9Sstevel@tonic-gate  * message. However, the ServiceTable does *not* call into SLPV1Manager
477c478bd9Sstevel@tonic-gate  * to handle an outgoing message, since each individual message type is
487c478bd9Sstevel@tonic-gate  * handled separately. SLPV1Manager also handles V1 defaults.
497c478bd9Sstevel@tonic-gate  *
507c478bd9Sstevel@tonic-gate  * @author James Kempf
517c478bd9Sstevel@tonic-gate  */
527c478bd9Sstevel@tonic-gate 
537c478bd9Sstevel@tonic-gate abstract class SLPV1Manager extends Object {
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate     // V1 Header class.
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate     static final String V1_HEADER_CLASS = "com.sun.slp.SLPHeaderV1";
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate     // V1 multicast addresses.
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate     static final String sGeneralSLPMCAddress = "224.0.1.22";
627c478bd9Sstevel@tonic-gate     static final String sDADiscSLPMCAddress  = "224.0.1.35";
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate     static InetAddress v1SLPGSAddr = null;
657c478bd9Sstevel@tonic-gate     static InetAddress v1SLPDAAddr = null;
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate     /**
687c478bd9Sstevel@tonic-gate      * The SLPV1Advertiser implements the SLPv1 DAAdvert xid incrementing
697c478bd9Sstevel@tonic-gate      * algorithm. In SLPv1, the xid of an unsolicited DAAdvert is only
707c478bd9Sstevel@tonic-gate      * 0 if it came up stateless. If it comes up with preexisting state,
717c478bd9Sstevel@tonic-gate      * it sets the counter to 0x100. Also, when the xid counter wraps,
727c478bd9Sstevel@tonic-gate      * it must wrap to 0x100 and not 0x0.
737c478bd9Sstevel@tonic-gate      */
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate     static class SLPV1Advertiser extends DAAdvertiser {
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate 	// For implementing the V1 xid algorithm.
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate 	private short xid = 0;
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate 	private static final short STATEFUL_XID = 0x100;
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate 	private static final long STATEFUL_TIME_BOUND = 300L;
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate 	// Service table.
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate 	private ServiceTable table = null;
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate 	// Scopes to use. We need to map from V2, so default corresponds to
907c478bd9Sstevel@tonic-gate 	//  the empty scope.
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate 	Vector useScopes = new Vector();
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate 	// Create an SLPv1 Advertiser and start it running.
957c478bd9Sstevel@tonic-gate 
SLPV1Advertiser(InetAddress interfac, InetAddress maddr, ServiceTable table)967c478bd9Sstevel@tonic-gate 	SLPV1Advertiser(InetAddress interfac,
977c478bd9Sstevel@tonic-gate 			InetAddress maddr,
987c478bd9Sstevel@tonic-gate 			ServiceTable table)
997c478bd9Sstevel@tonic-gate 	    throws ServiceLocationException {
1007c478bd9Sstevel@tonic-gate 	    super();
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate 	    this.table = table;
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate 	    initialize();
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate 	    //  There will be NO listener on this multicast address,
1077c478bd9Sstevel@tonic-gate 	    //  so the superclass will simply create a scoket for it.
1087c478bd9Sstevel@tonic-gate 	    //  We don't want to create a new Listener
1097c478bd9Sstevel@tonic-gate 	    //  because we are not interested in multicast requests since
1107c478bd9Sstevel@tonic-gate 	    //  only SAs answer multicast requests.
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate 	    initializeNetworking(interfac, maddr);
1137c478bd9Sstevel@tonic-gate 	}
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate 	// Initialize the xid for passive advertising. We need to determine
1167c478bd9Sstevel@tonic-gate 	//  whether we came up stateless or not. We do this by asking the
1177c478bd9Sstevel@tonic-gate 	//  the service store for the stateless reboot time. If the
1187c478bd9Sstevel@tonic-gate 	//  stateless reboot time is within the last 5 minutes, we
1197c478bd9Sstevel@tonic-gate 	//  assume we came up stateless. Otherwise, we're stateful.
1207c478bd9Sstevel@tonic-gate 	//  We also initialize the URL and scopes.
1217c478bd9Sstevel@tonic-gate 
initialize()1227c478bd9Sstevel@tonic-gate 	private void initialize() throws ServiceLocationException {
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate 	    // Initialize the xid.
1257c478bd9Sstevel@tonic-gate 
1267c478bd9Sstevel@tonic-gate 	    ServiceStore store = ServiceTable.getServiceTable().store;
1277c478bd9Sstevel@tonic-gate 	    long timestamp = store.getStateTimestamp();
1287c478bd9Sstevel@tonic-gate 	    long currentTime = SLPConfig.currentSLPTime();
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate 	    if ((currentTime - timestamp) > STATEFUL_TIME_BOUND) {
1317c478bd9Sstevel@tonic-gate 		xid = STATEFUL_XID;
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate 	    }
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate 	    // Initialize the scopes.
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate 	    useScopes = config.getSAConfiguredScopes();
1387c478bd9Sstevel@tonic-gate 
1397c478bd9Sstevel@tonic-gate 	}
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate 	// Return the output buffer for a passive advert. We need to create
1427c478bd9Sstevel@tonic-gate 	//  the advert, rolling over the xid if necessary for the next one.
1437c478bd9Sstevel@tonic-gate 
getOutbuf()1447c478bd9Sstevel@tonic-gate 	protected byte[] getOutbuf() {
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate 	    SDAAdvert daadvert = null;
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate 	    try {
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate 		SLPHeaderV1 hdr = new SLPHeaderV1();
1517c478bd9Sstevel@tonic-gate 		hdr.functionCode = SrvLocHeader.DAAdvert;
1527c478bd9Sstevel@tonic-gate 		hdr.locale = config.getLocale();
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate 		daadvert = (SDAAdvert)table.makeDAAdvert(hdr,
1557c478bd9Sstevel@tonic-gate 							 interfac,
1567c478bd9Sstevel@tonic-gate 							 xid,
1577c478bd9Sstevel@tonic-gate 							 useScopes,
1587c478bd9Sstevel@tonic-gate 							 config);
1597c478bd9Sstevel@tonic-gate 		hdr = (SLPHeaderV1)daadvert.getHeader();
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate 		ByteArrayOutputStream baos = new ByteArrayOutputStream();
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate 		hdr.externalize(baos, true, false);
1647c478bd9Sstevel@tonic-gate 		byte[] outbuf = baos.toByteArray();
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate 		bumpXid();
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate 		return outbuf;
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate 	    } catch (ServiceLocationException ex) {
1717c478bd9Sstevel@tonic-gate 		Assert.slpassert(false,
1727c478bd9Sstevel@tonic-gate 			      "v1_advert_error",
1737c478bd9Sstevel@tonic-gate 			      new Object[0]);
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate 	    }
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate 	    return null;
1787c478bd9Sstevel@tonic-gate 	}
1797c478bd9Sstevel@tonic-gate 
bumpXid()1807c478bd9Sstevel@tonic-gate 	private void bumpXid() {
1817c478bd9Sstevel@tonic-gate 
1827c478bd9Sstevel@tonic-gate 	    int newXID = (int)xid + 1;
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate 	    if (newXID > Short.MAX_VALUE) {
1857c478bd9Sstevel@tonic-gate 		xid = STATEFUL_XID;
1867c478bd9Sstevel@tonic-gate 
1877c478bd9Sstevel@tonic-gate 	    } else {
1887c478bd9Sstevel@tonic-gate 		xid = (short)newXID;
1897c478bd9Sstevel@tonic-gate 
1907c478bd9Sstevel@tonic-gate 	    }
1917c478bd9Sstevel@tonic-gate 	}
1927c478bd9Sstevel@tonic-gate     }
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate 
1957c478bd9Sstevel@tonic-gate     // Start up listener, active and passive listeners for SLPv1.
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate     static public void
start(SLPConfig config, ServerDATable table, ServiceTable stable)1987c478bd9Sstevel@tonic-gate 	start(SLPConfig config, ServerDATable table, ServiceTable stable) {
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate 	// We do not handle SLPv1 if security is enabled, because SLPv1
2017c478bd9Sstevel@tonic-gate 	//  security is not implemented.
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate 	if (config.getHasSecurity()) {
2047c478bd9Sstevel@tonic-gate 
2057c478bd9Sstevel@tonic-gate 	    if (config.regTest() ||
2067c478bd9Sstevel@tonic-gate 		config.traceMsg() ||
2077c478bd9Sstevel@tonic-gate 		config.traceDrop() ||
2087c478bd9Sstevel@tonic-gate 		config.traceDATraffic()) {
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate 		config.writeLog("v1_security_enabled",
2117c478bd9Sstevel@tonic-gate 				new Object[0]);
2127c478bd9Sstevel@tonic-gate 	    }
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate 	    return;
2157c478bd9Sstevel@tonic-gate 
2167c478bd9Sstevel@tonic-gate 	}
2177c478bd9Sstevel@tonic-gate 
2187c478bd9Sstevel@tonic-gate 	Vector interfaces = config.getInterfaces();
2197c478bd9Sstevel@tonic-gate 	int i = 0, n = interfaces.size();
2207c478bd9Sstevel@tonic-gate 	Vector advs = new Vector();
2217c478bd9Sstevel@tonic-gate 
2227c478bd9Sstevel@tonic-gate 	try {
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate 	    InetAddress v1SLPDAAddr = null;
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate 	    // Get address for DA discovery multicast.
2277c478bd9Sstevel@tonic-gate 
2287c478bd9Sstevel@tonic-gate 	    v1SLPDAAddr = InetAddress.getByName(sDADiscSLPMCAddress);
2297c478bd9Sstevel@tonic-gate 	    v1SLPGSAddr = InetAddress.getByName(sGeneralSLPMCAddress);
2307c478bd9Sstevel@tonic-gate 
2317c478bd9Sstevel@tonic-gate 	    // Add all listeners onto the SLPv1 DA multicast address and
2327c478bd9Sstevel@tonic-gate 	    //  create a DAAdvertiser on all network interfaces for the
2337c478bd9Sstevel@tonic-gate 	    //  general multicast group.
2347c478bd9Sstevel@tonic-gate 
2357c478bd9Sstevel@tonic-gate 	    for (i = 0; i < n; i++) {
2367c478bd9Sstevel@tonic-gate 		InetAddress interfac = (InetAddress)interfaces.elementAt(i);
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate 		// Listen for SLPv1 multicast DA service requests. Only DA
2397c478bd9Sstevel@tonic-gate 		//  service requests are multicast on this address.
2407c478bd9Sstevel@tonic-gate 
2417c478bd9Sstevel@tonic-gate 		Listener.addListenerToMulticastGroup(interfac, v1SLPDAAddr);
2427c478bd9Sstevel@tonic-gate 
2437c478bd9Sstevel@tonic-gate 		// We don't need to listen to the SLPv1 general multicast
2447c478bd9Sstevel@tonic-gate 		//  address because we never want any multicast service
2457c478bd9Sstevel@tonic-gate 		//  requests. But we do need to advertise as an SLPv1 DA.
2467c478bd9Sstevel@tonic-gate 		//  So we have a special DAAdvertiser subclass to do it.
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate 		DAAdvertiser ad =
2497c478bd9Sstevel@tonic-gate 		    new SLPV1Advertiser(interfac, v1SLPGSAddr, stable);
2507c478bd9Sstevel@tonic-gate 		ad.start();
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate 		advs.addElement(ad);
2537c478bd9Sstevel@tonic-gate 
2547c478bd9Sstevel@tonic-gate 	    }
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate 	    // Let admin know we are running in SLPv1 compatibility mode
2577c478bd9Sstevel@tonic-gate 	    //  if tracing is on
2587c478bd9Sstevel@tonic-gate 
2597c478bd9Sstevel@tonic-gate 	    if (config.regTest() ||
2607c478bd9Sstevel@tonic-gate 		config.traceMsg() ||
2617c478bd9Sstevel@tonic-gate 		config.traceDrop() ||
2627c478bd9Sstevel@tonic-gate 		config.traceDATraffic()) {
2637c478bd9Sstevel@tonic-gate 
2647c478bd9Sstevel@tonic-gate 		config.writeLog("v1_hello",
2657c478bd9Sstevel@tonic-gate 				new Object[] {config.getSAConfiguredScopes()});
2667c478bd9Sstevel@tonic-gate 	    }
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate 	    return;
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate 	} catch (ServiceLocationException ex) {
2717c478bd9Sstevel@tonic-gate 
2727c478bd9Sstevel@tonic-gate 	    config.writeLog("v1_init_error",
2737c478bd9Sstevel@tonic-gate 			    new Object[] {ex.getMessage()});
274*55fea89dSDan Cross 
2757c478bd9Sstevel@tonic-gate 	}  catch (UnknownHostException ex) {
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate 	    config.writeLog("v1_init_error",
2787c478bd9Sstevel@tonic-gate 			    new Object[] {ex.getMessage()});
2797c478bd9Sstevel@tonic-gate 
2807c478bd9Sstevel@tonic-gate 	}
2817c478bd9Sstevel@tonic-gate 
2827c478bd9Sstevel@tonic-gate 	// Remove Listeners from multicast group, stop DAAdvertisers.
2837c478bd9Sstevel@tonic-gate 	// An error occured.
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate 	int j;
2867c478bd9Sstevel@tonic-gate 
2877c478bd9Sstevel@tonic-gate 	for (j = 0; j < i; i++) {
2887c478bd9Sstevel@tonic-gate 	    InetAddress interfac = (InetAddress)interfaces.elementAt(i);
2897c478bd9Sstevel@tonic-gate 	    DatagramSocket dss =
2907c478bd9Sstevel@tonic-gate 		Listener.returnListenerSocketOnInterface(interfac);
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate 	    if (dss instanceof MulticastSocket) {
2937c478bd9Sstevel@tonic-gate 		MulticastSocket mss = (MulticastSocket)dss;
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate 		try {
2967c478bd9Sstevel@tonic-gate 		    mss.leaveGroup(v1SLPDAAddr);
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate 		} catch (IOException ex) {
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate 		    // Ignore it.
3017c478bd9Sstevel@tonic-gate 
3027c478bd9Sstevel@tonic-gate 		}
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate 		DAAdvertiser ad = (DAAdvertiser)advs.elementAt(j);
3057c478bd9Sstevel@tonic-gate 
3067c478bd9Sstevel@tonic-gate 		ad.stopThread();
3077c478bd9Sstevel@tonic-gate 	    }
3087c478bd9Sstevel@tonic-gate 	}
3097c478bd9Sstevel@tonic-gate     }
3107c478bd9Sstevel@tonic-gate 
3117c478bd9Sstevel@tonic-gate     // Initialize CSrvReg, CSrvDereg, CSrvMsg, and SDAAdvert classes for SLPv1,
3127c478bd9Sstevel@tonic-gate     //  also V1 header class.
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate     static {
3157c478bd9Sstevel@tonic-gate 
SrvLocHeader.addHeaderClass(V1_HEADER_CLASS, SLPHeaderV1.VERSION)3167c478bd9Sstevel@tonic-gate 	SrvLocHeader.addHeaderClass(V1_HEADER_CLASS, SLPHeaderV1.VERSION);
3177c478bd9Sstevel@tonic-gate 
3187c478bd9Sstevel@tonic-gate     }
3197c478bd9Sstevel@tonic-gate }
320