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 2001-2002 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate * 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate // RequestHandler.java: Handle an incoming request in a separate thread. 287c478bd9Sstevel@tonic-gate // Author: James Kempf 297c478bd9Sstevel@tonic-gate // Created On: Mon May 18 14:00:27 1998 307c478bd9Sstevel@tonic-gate // Last Modified By: James Kempf 317c478bd9Sstevel@tonic-gate // Last Modified On: Mon Mar 8 16:12:13 1999 327c478bd9Sstevel@tonic-gate // Update Count: 173 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.net.*; 397c478bd9Sstevel@tonic-gate import java.util.*; 407c478bd9Sstevel@tonic-gate 417c478bd9Sstevel@tonic-gate /** 427c478bd9Sstevel@tonic-gate * Handle an incoming request in a separate thread. The request 437c478bd9Sstevel@tonic-gate * may have arrived via datagram, or it may have arrived via 447c478bd9Sstevel@tonic-gate * stream. 457c478bd9Sstevel@tonic-gate * 467c478bd9Sstevel@tonic-gate * @author James Kempf, Erik Guttman 477c478bd9Sstevel@tonic-gate */ 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate class RequestHandler extends Thread { 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate private SLPConfig config; // Config for system properties. 537c478bd9Sstevel@tonic-gate private ServerDATable daTable; // DA table in server for reg and dereg 547c478bd9Sstevel@tonic-gate private InetAddress interfac = null; // Interface on which request came in. 557c478bd9Sstevel@tonic-gate private Socket sock = null; // Socket for incoming stream request. 567c478bd9Sstevel@tonic-gate private DatagramPacket packet = null; // Packet for datagram requests. 577c478bd9Sstevel@tonic-gate private InetAddress clientAddr = null; // Internet address of the client. 587c478bd9Sstevel@tonic-gate private int port = 0; // Port to use. 597c478bd9Sstevel@tonic-gate private ServiceTable serviceTable = null; 607c478bd9Sstevel@tonic-gate private SrvLocMsg toForward = null; // Reg or dereg to forward. 617c478bd9Sstevel@tonic-gate private InputStream inStream = null; 627c478bd9Sstevel@tonic-gate private OutputStream outStream = null; 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate static private Hashtable inProgress = new Hashtable(); 657c478bd9Sstevel@tonic-gate // Keeps track of in progress requests 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate // When a request handler gets GC'd, make sure it's open socket is closed. 687c478bd9Sstevel@tonic-gate // We simply let the exception propagate, because it is ignored. 697c478bd9Sstevel@tonic-gate finalize()707c478bd9Sstevel@tonic-gate protected void finalize() throws IOException { 717c478bd9Sstevel@tonic-gate if (sock != null) sock.close(); 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate } 747c478bd9Sstevel@tonic-gate RequestHandler(InputStream in, OutputStream out, SLPConfig config_in)757c478bd9Sstevel@tonic-gate RequestHandler(InputStream in, OutputStream out, SLPConfig config_in) { 767c478bd9Sstevel@tonic-gate config = config_in; 777c478bd9Sstevel@tonic-gate sock = null; 787c478bd9Sstevel@tonic-gate inStream = in; 797c478bd9Sstevel@tonic-gate outStream = out; 807c478bd9Sstevel@tonic-gate clientAddr = config.getLoopback(); 817c478bd9Sstevel@tonic-gate port = 427; 827c478bd9Sstevel@tonic-gate interfac = clientAddr; 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate try { 857c478bd9Sstevel@tonic-gate serviceTable = ServiceTable.getServiceTable(); 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate } catch (ServiceLocationException ex) { 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate // Taken care of in initialization code. 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate } 927c478bd9Sstevel@tonic-gate } 937c478bd9Sstevel@tonic-gate 947c478bd9Sstevel@tonic-gate // Request arrived via stream. Set the incoming socket, spawn 957c478bd9Sstevel@tonic-gate // a separate thread in which to run. 967c478bd9Sstevel@tonic-gate RequestHandler(Socket sock_in, InetAddress interfac, SLPConfig config_in)977c478bd9Sstevel@tonic-gate RequestHandler(Socket sock_in, InetAddress interfac, SLPConfig config_in) { 987c478bd9Sstevel@tonic-gate 997c478bd9Sstevel@tonic-gate Assert.slpassert((sock_in != null), 1007c478bd9Sstevel@tonic-gate "rh_null_sock", 1017c478bd9Sstevel@tonic-gate new Object[0]); 1027c478bd9Sstevel@tonic-gate Assert.slpassert((config_in != null), 1037c478bd9Sstevel@tonic-gate "ls_null_config", 1047c478bd9Sstevel@tonic-gate new Object[0]); 1057c478bd9Sstevel@tonic-gate 1067c478bd9Sstevel@tonic-gate config = config_in; 1077c478bd9Sstevel@tonic-gate sock = sock_in; 1087c478bd9Sstevel@tonic-gate clientAddr = sock.getInetAddress(); 1097c478bd9Sstevel@tonic-gate port = sock.getPort(); 1107c478bd9Sstevel@tonic-gate this.interfac = interfac; 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate try { 1137c478bd9Sstevel@tonic-gate serviceTable = ServiceTable.getServiceTable(); 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate } catch (ServiceLocationException ex) { 1167c478bd9Sstevel@tonic-gate 1177c478bd9Sstevel@tonic-gate // Taken care of in initialization code. 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate } 1207c478bd9Sstevel@tonic-gate } 1217c478bd9Sstevel@tonic-gate 1227c478bd9Sstevel@tonic-gate // Request arrived via datagram. Set the incoming packet, spawn 1237c478bd9Sstevel@tonic-gate // a separate thread in which to run. 1247c478bd9Sstevel@tonic-gate RequestHandler(DatagramPacket packet_in, InetAddress interfac, SLPConfig config_in)1257c478bd9Sstevel@tonic-gate RequestHandler(DatagramPacket packet_in, 1267c478bd9Sstevel@tonic-gate InetAddress interfac, 1277c478bd9Sstevel@tonic-gate SLPConfig config_in) { 1287c478bd9Sstevel@tonic-gate 1297c478bd9Sstevel@tonic-gate Assert.slpassert((packet_in != null), 1307c478bd9Sstevel@tonic-gate "rh_null_packy", 1317c478bd9Sstevel@tonic-gate new Object[0]); 1327c478bd9Sstevel@tonic-gate Assert.slpassert((config_in != null), 1337c478bd9Sstevel@tonic-gate "ls_null_config", 1347c478bd9Sstevel@tonic-gate new Object[0]); 1357c478bd9Sstevel@tonic-gate 1367c478bd9Sstevel@tonic-gate config = config_in; 1377c478bd9Sstevel@tonic-gate packet = packet_in; 1387c478bd9Sstevel@tonic-gate clientAddr = packet.getAddress(); 1397c478bd9Sstevel@tonic-gate port = packet.getPort(); 1407c478bd9Sstevel@tonic-gate this.interfac = interfac; 1417c478bd9Sstevel@tonic-gate 1427c478bd9Sstevel@tonic-gate try { 1437c478bd9Sstevel@tonic-gate serviceTable = ServiceTable.getServiceTable(); 1447c478bd9Sstevel@tonic-gate daTable = ServerDATable.getServerDATable(); 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate } catch (ServiceLocationException ex) { 1477c478bd9Sstevel@tonic-gate 1487c478bd9Sstevel@tonic-gate // Taken care of in initialziation code. 1497c478bd9Sstevel@tonic-gate 1507c478bd9Sstevel@tonic-gate } 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gate } 1537c478bd9Sstevel@tonic-gate 1547c478bd9Sstevel@tonic-gate /** 1557c478bd9Sstevel@tonic-gate * Return a stringified buffer, suitable for printing, for 1567c478bd9Sstevel@tonic-gate * debugging. 1577c478bd9Sstevel@tonic-gate * 1587c478bd9Sstevel@tonic-gate * @param bytes The byte buffer. 1597c478bd9Sstevel@tonic-gate * @return A string with the ASCII characters as characters, otherwise 1607c478bd9Sstevel@tonic-gate * convert to escape notation. 1617c478bd9Sstevel@tonic-gate */ 1627c478bd9Sstevel@tonic-gate stringifyBuffer(byte[] bytes)1637c478bd9Sstevel@tonic-gate static String stringifyBuffer(byte[] bytes) { 1647c478bd9Sstevel@tonic-gate 1657c478bd9Sstevel@tonic-gate StringBuffer buf = new StringBuffer(); 1667c478bd9Sstevel@tonic-gate int i, n = bytes.length; 1677c478bd9Sstevel@tonic-gate 1687c478bd9Sstevel@tonic-gate for (i = 0; i < n; i++) { 1697c478bd9Sstevel@tonic-gate byte b = bytes[i]; 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate if ((b >= 0x21) && (b < 0x7e)) { 1727c478bd9Sstevel@tonic-gate buf.append((char)b); 1737c478bd9Sstevel@tonic-gate } else { 1747c478bd9Sstevel@tonic-gate buf.append("\\"+Integer.toHexString(((int)b) & 0xFF)); 1757c478bd9Sstevel@tonic-gate } 1767c478bd9Sstevel@tonic-gate } 1777c478bd9Sstevel@tonic-gate 1787c478bd9Sstevel@tonic-gate return buf.toString(); 1797c478bd9Sstevel@tonic-gate } 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate // If a stream thread, then get the request first. Process the 1827c478bd9Sstevel@tonic-gate // request and reply to client. 1837c478bd9Sstevel@tonic-gate run()1847c478bd9Sstevel@tonic-gate public void run() { 1857c478bd9Sstevel@tonic-gate 1867c478bd9Sstevel@tonic-gate // Is this a stream or datagram thread? 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate if (sock != null || inStream != null) { 1897c478bd9Sstevel@tonic-gate 1907c478bd9Sstevel@tonic-gate // Label appropriately. 1917c478bd9Sstevel@tonic-gate 1927c478bd9Sstevel@tonic-gate setName("Stream Request Handler "+clientAddr+":"+port); 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate if (sock != null) { 1957c478bd9Sstevel@tonic-gate // Set the socket to block until there are bytes to read. 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate try { 1987c478bd9Sstevel@tonic-gate sock.setSoTimeout(0); 1997c478bd9Sstevel@tonic-gate 2007c478bd9Sstevel@tonic-gate } catch (SocketException ex) { 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate } 2037c478bd9Sstevel@tonic-gate 2047c478bd9Sstevel@tonic-gate } 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate // get DA Table 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate try { 2097c478bd9Sstevel@tonic-gate daTable = ServerDATable.getServerDATable(); 2107c478bd9Sstevel@tonic-gate } catch (ServiceLocationException e) { 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate // Taken care of in initialziation code. 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate } 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate // Stream needs to loop through until requests are completed. 2177c478bd9Sstevel@tonic-gate 2187c478bd9Sstevel@tonic-gate handleStream(); 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate if (sock != null) { 2217c478bd9Sstevel@tonic-gate try { 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate sock.close(); 2247c478bd9Sstevel@tonic-gate sock = null; 2257c478bd9Sstevel@tonic-gate 2267c478bd9Sstevel@tonic-gate } catch (IOException ex) { 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate } 2297c478bd9Sstevel@tonic-gate } 2307c478bd9Sstevel@tonic-gate 2317c478bd9Sstevel@tonic-gate } else { 2327c478bd9Sstevel@tonic-gate 2337c478bd9Sstevel@tonic-gate // Label appropriately. 2347c478bd9Sstevel@tonic-gate 2357c478bd9Sstevel@tonic-gate setName("Datagram Request Handler "+clientAddr+":"+port); 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate byte[] inbuf = packet.getData(); 2387c478bd9Sstevel@tonic-gate 2397c478bd9Sstevel@tonic-gate // Copy xid for use in hash key. 2407c478bd9Sstevel@tonic-gate 2417c478bd9Sstevel@tonic-gate byte[] xidBuf = new byte[2]; 2427c478bd9Sstevel@tonic-gate System.arraycopy(inbuf, SrvLocHeader.XID_OFFSET, xidBuf, 0, 2); 2437c478bd9Sstevel@tonic-gate 2447c478bd9Sstevel@tonic-gate // If this request is already in progress, drop new request. 2457c478bd9Sstevel@tonic-gate 2467c478bd9Sstevel@tonic-gate int xid = 0; 2477c478bd9Sstevel@tonic-gate xid = (int)((char)xidBuf[0] & 0xFF) << 8; 2487c478bd9Sstevel@tonic-gate xid += (int)((char)xidBuf[1] & 0xFF); 2497c478bd9Sstevel@tonic-gate String syncTableKey = 2507c478bd9Sstevel@tonic-gate (new Integer(xid)).toString() + clientAddr.getHostAddress(); 2517c478bd9Sstevel@tonic-gate boolean there = false; 2527c478bd9Sstevel@tonic-gate 2537c478bd9Sstevel@tonic-gate synchronized (inProgress) { 2547c478bd9Sstevel@tonic-gate 2557c478bd9Sstevel@tonic-gate there = (inProgress.get(syncTableKey) != null); 2567c478bd9Sstevel@tonic-gate 2577c478bd9Sstevel@tonic-gate if (!there) { 2587c478bd9Sstevel@tonic-gate inProgress.put(syncTableKey, this); 2597c478bd9Sstevel@tonic-gate 2607c478bd9Sstevel@tonic-gate } 2617c478bd9Sstevel@tonic-gate } 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate // Drop if we are processing it already. 2647c478bd9Sstevel@tonic-gate 2657c478bd9Sstevel@tonic-gate if (there) { 2667c478bd9Sstevel@tonic-gate if (config.traceDrop()) { 2677c478bd9Sstevel@tonic-gate config.writeLog("rh_rqst_in_progress", 2687c478bd9Sstevel@tonic-gate new Object[] {clientAddr, 2697c478bd9Sstevel@tonic-gate new Integer(port), 2707c478bd9Sstevel@tonic-gate interfac}); 2717c478bd9Sstevel@tonic-gate } 2727c478bd9Sstevel@tonic-gate return; 2737c478bd9Sstevel@tonic-gate 2747c478bd9Sstevel@tonic-gate } 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate // We can simply cut to the chase and process the datagram 2777c478bd9Sstevel@tonic-gate // request. 2787c478bd9Sstevel@tonic-gate 2797c478bd9Sstevel@tonic-gate DataInputStream dis = 2807c478bd9Sstevel@tonic-gate new DataInputStream(new ByteArrayInputStream(inbuf)); 2817c478bd9Sstevel@tonic-gate ByteArrayOutputStream baos = new ByteArrayOutputStream(); 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gate try { 2847c478bd9Sstevel@tonic-gate 2857c478bd9Sstevel@tonic-gate handleRequest(dis, baos, false); 2867c478bd9Sstevel@tonic-gate 2877c478bd9Sstevel@tonic-gate byte[] outbuf = baos.toByteArray(); 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate // Open a data output stream for the outgoing request. There 2907c478bd9Sstevel@tonic-gate // is no buffer for reply or it is empty, the request was 2917c478bd9Sstevel@tonic-gate // multicast and nothing was sent back. 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate if (outbuf != null && outbuf.length > 0) { 2947c478bd9Sstevel@tonic-gate sendDatagramReply(outbuf); 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate } 2977c478bd9Sstevel@tonic-gate 2987c478bd9Sstevel@tonic-gate } catch (IOException ex) { 2997c478bd9Sstevel@tonic-gate 3007c478bd9Sstevel@tonic-gate // No excuse for an EOF exception here. 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate if (config.traceDrop()) { 3037c478bd9Sstevel@tonic-gate config.writeLog("rh_datagram_ioe", 3047c478bd9Sstevel@tonic-gate new Object[] {clientAddr, 3057c478bd9Sstevel@tonic-gate new Integer(port), 3067c478bd9Sstevel@tonic-gate interfac, 3077c478bd9Sstevel@tonic-gate ex.getMessage()}); 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate } 3107c478bd9Sstevel@tonic-gate } 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate // Remove the lock for this request. We do this just before the 3137c478bd9Sstevel@tonic-gate // run() method exits and the thread expires to reduce the 3147c478bd9Sstevel@tonic-gate // window in which a new copy of the request could come in. 3157c478bd9Sstevel@tonic-gate // We need to be sure that we only remove if it is this 3167c478bd9Sstevel@tonic-gate // request handler. 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate synchronized (inProgress) { 3197c478bd9Sstevel@tonic-gate RequestHandler rh = 3207c478bd9Sstevel@tonic-gate (RequestHandler)inProgress.get(syncTableKey); 3217c478bd9Sstevel@tonic-gate 3227c478bd9Sstevel@tonic-gate if (rh == this) { 3237c478bd9Sstevel@tonic-gate inProgress.remove(syncTableKey); 3247c478bd9Sstevel@tonic-gate 3257c478bd9Sstevel@tonic-gate } 3267c478bd9Sstevel@tonic-gate 3277c478bd9Sstevel@tonic-gate } 3287c478bd9Sstevel@tonic-gate 3297c478bd9Sstevel@tonic-gate } 3307c478bd9Sstevel@tonic-gate 3317c478bd9Sstevel@tonic-gate } 3327c478bd9Sstevel@tonic-gate 3337c478bd9Sstevel@tonic-gate // Handle an incoming stream. 3347c478bd9Sstevel@tonic-gate handleStream()3357c478bd9Sstevel@tonic-gate private void handleStream() { 3367c478bd9Sstevel@tonic-gate 3377c478bd9Sstevel@tonic-gate try { 3387c478bd9Sstevel@tonic-gate 3397c478bd9Sstevel@tonic-gate DataInputStream dis = null; 3407c478bd9Sstevel@tonic-gate DataOutputStream dos = null; 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate if (inStream != null) { 3437c478bd9Sstevel@tonic-gate dis = new DataInputStream(inStream); 3447c478bd9Sstevel@tonic-gate dos = new DataOutputStream(outStream); 3457c478bd9Sstevel@tonic-gate } else { 3467c478bd9Sstevel@tonic-gate // use the socket 3477c478bd9Sstevel@tonic-gate 3487c478bd9Sstevel@tonic-gate dis = new DataInputStream(sock.getInputStream()); 3497c478bd9Sstevel@tonic-gate dos = new DataOutputStream(sock.getOutputStream()); 3507c478bd9Sstevel@tonic-gate } 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate // Loop while the client still wants to send something. But we 3537c478bd9Sstevel@tonic-gate // only read one SLP message at a time on the connection, 3547c478bd9Sstevel@tonic-gate // returning if it there are no more bytes to read. Note that 3557c478bd9Sstevel@tonic-gate // we have to use a do/while loop here so that the read hangs 3567c478bd9Sstevel@tonic-gate // until something shows up. 3577c478bd9Sstevel@tonic-gate 3587c478bd9Sstevel@tonic-gate do { 3597c478bd9Sstevel@tonic-gate 3607c478bd9Sstevel@tonic-gate // Handle the new request. 3617c478bd9Sstevel@tonic-gate 3627c478bd9Sstevel@tonic-gate ByteArrayOutputStream baos = new ByteArrayOutputStream(); 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate boolean parseError = handleRequest(dis, baos, true); 3657c478bd9Sstevel@tonic-gate 3667c478bd9Sstevel@tonic-gate dos.write(baos.toByteArray(), 0, baos.size()); 3677c478bd9Sstevel@tonic-gate 3687c478bd9Sstevel@tonic-gate // Forward reg or dereg to foreign DAs that need to know 3697c478bd9Sstevel@tonic-gate // about it. 3707c478bd9Sstevel@tonic-gate 3717c478bd9Sstevel@tonic-gate if (toForward != null) { 3727c478bd9Sstevel@tonic-gate 3737c478bd9Sstevel@tonic-gate try { 3747c478bd9Sstevel@tonic-gate daTable.forwardSAMessage(toForward, clientAddr); 3757c478bd9Sstevel@tonic-gate toForward = null; 3767c478bd9Sstevel@tonic-gate 3777c478bd9Sstevel@tonic-gate } catch (ServiceLocationException ex) { 3787c478bd9Sstevel@tonic-gate config.writeLog("sa_forwarding_exception", 3797c478bd9Sstevel@tonic-gate new Object[] { 3807c478bd9Sstevel@tonic-gate new Short(ex.getErrorCode()), 3817c478bd9Sstevel@tonic-gate Integer.toHexString(toForward.getHeader().xid), 3827c478bd9Sstevel@tonic-gate ex.getMessage()}); 3837c478bd9Sstevel@tonic-gate } 3847c478bd9Sstevel@tonic-gate } 3857c478bd9Sstevel@tonic-gate 3867c478bd9Sstevel@tonic-gate // If there was a parse error, then break out and close the 3877c478bd9Sstevel@tonic-gate // stream, because it may have lingering bytes. 3887c478bd9Sstevel@tonic-gate 3897c478bd9Sstevel@tonic-gate if (parseError && config.traceMsg()) { 3907c478bd9Sstevel@tonic-gate 3917c478bd9Sstevel@tonic-gate config.writeLog("rh_tcp_error", 3927c478bd9Sstevel@tonic-gate new Object[] {clientAddr, 3937c478bd9Sstevel@tonic-gate new Integer(port), 3947c478bd9Sstevel@tonic-gate interfac}); 3957c478bd9Sstevel@tonic-gate 3967c478bd9Sstevel@tonic-gate break; 3977c478bd9Sstevel@tonic-gate 3987c478bd9Sstevel@tonic-gate } 3997c478bd9Sstevel@tonic-gate 4007c478bd9Sstevel@tonic-gate } while (true); 4017c478bd9Sstevel@tonic-gate 4027c478bd9Sstevel@tonic-gate } catch (EOFException ex) { 4037c478bd9Sstevel@tonic-gate 4047c478bd9Sstevel@tonic-gate if (config.traceMsg()) { 4057c478bd9Sstevel@tonic-gate config.writeLog("rh_socket_closed", 4067c478bd9Sstevel@tonic-gate new Object[] {clientAddr, 4077c478bd9Sstevel@tonic-gate new Integer(port), 4087c478bd9Sstevel@tonic-gate interfac}); 4097c478bd9Sstevel@tonic-gate } 4107c478bd9Sstevel@tonic-gate 4117c478bd9Sstevel@tonic-gate 4127c478bd9Sstevel@tonic-gate } catch (IOException ex) { 4137c478bd9Sstevel@tonic-gate 4147c478bd9Sstevel@tonic-gate // An error occured during input. 4157c478bd9Sstevel@tonic-gate 4167c478bd9Sstevel@tonic-gate if (config.traceDrop()) { 4177c478bd9Sstevel@tonic-gate config.writeLog("ioexception_server_stream", 4187c478bd9Sstevel@tonic-gate new Object[] {clientAddr, 4197c478bd9Sstevel@tonic-gate new Integer(port), 4207c478bd9Sstevel@tonic-gate interfac, 4217c478bd9Sstevel@tonic-gate ex.getMessage()}); 4227c478bd9Sstevel@tonic-gate } 4237c478bd9Sstevel@tonic-gate 4247c478bd9Sstevel@tonic-gate } 4257c478bd9Sstevel@tonic-gate } 4267c478bd9Sstevel@tonic-gate 4277c478bd9Sstevel@tonic-gate // Send a byte buffer reply through a datagram socket. 4287c478bd9Sstevel@tonic-gate sendDatagramReply(byte[] outbuf)4297c478bd9Sstevel@tonic-gate private void sendDatagramReply(byte[] outbuf) { 4307c478bd9Sstevel@tonic-gate 4317c478bd9Sstevel@tonic-gate DatagramSocket ds = null; 4327c478bd9Sstevel@tonic-gate 4337c478bd9Sstevel@tonic-gate try { 4347c478bd9Sstevel@tonic-gate 4357c478bd9Sstevel@tonic-gate // Open the socket. 4367c478bd9Sstevel@tonic-gate 4377c478bd9Sstevel@tonic-gate ds = new DatagramSocket(); 4387c478bd9Sstevel@tonic-gate 4397c478bd9Sstevel@tonic-gate // Format the outgoing packet. 4407c478bd9Sstevel@tonic-gate 4417c478bd9Sstevel@tonic-gate DatagramPacket dpOut = 4427c478bd9Sstevel@tonic-gate new DatagramPacket(outbuf, outbuf.length, clientAddr, port); 4437c478bd9Sstevel@tonic-gate 4447c478bd9Sstevel@tonic-gate // Send the reply. 4457c478bd9Sstevel@tonic-gate 4467c478bd9Sstevel@tonic-gate ds.send(dpOut); 4477c478bd9Sstevel@tonic-gate 4487c478bd9Sstevel@tonic-gate // Forward reg or dereg to foreign DAs that need to know about it. 4497c478bd9Sstevel@tonic-gate 4507c478bd9Sstevel@tonic-gate if (toForward != null) { 4517c478bd9Sstevel@tonic-gate 4527c478bd9Sstevel@tonic-gate try { 4537c478bd9Sstevel@tonic-gate daTable.forwardSAMessage(toForward, clientAddr); 4547c478bd9Sstevel@tonic-gate toForward = null; 4557c478bd9Sstevel@tonic-gate 4567c478bd9Sstevel@tonic-gate } catch (ServiceLocationException ex) { 4577c478bd9Sstevel@tonic-gate config.writeLog("sle_forward_error", 4587c478bd9Sstevel@tonic-gate new Object[] { 4597c478bd9Sstevel@tonic-gate new Integer(ex.getErrorCode()), 4607c478bd9Sstevel@tonic-gate Integer.toHexString(toForward.getHeader().xid), 4617c478bd9Sstevel@tonic-gate ex.getMessage()}); 4627c478bd9Sstevel@tonic-gate } 4637c478bd9Sstevel@tonic-gate } 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate } catch (SocketException ex) { 4667c478bd9Sstevel@tonic-gate 4677c478bd9Sstevel@tonic-gate // Failure in reply. 4687c478bd9Sstevel@tonic-gate 4697c478bd9Sstevel@tonic-gate if (config.traceDrop()) { 4707c478bd9Sstevel@tonic-gate config.writeLog("rh_socket_error", 4717c478bd9Sstevel@tonic-gate new Object[] {clientAddr, 4727c478bd9Sstevel@tonic-gate new Integer(port), 4737c478bd9Sstevel@tonic-gate interfac, 4747c478bd9Sstevel@tonic-gate ex.getMessage()}); 4757c478bd9Sstevel@tonic-gate } 4767c478bd9Sstevel@tonic-gate } catch (IOException ex) { 4777c478bd9Sstevel@tonic-gate 4787c478bd9Sstevel@tonic-gate // Failure in reply. 4797c478bd9Sstevel@tonic-gate 4807c478bd9Sstevel@tonic-gate if (config.traceDrop()) { 4817c478bd9Sstevel@tonic-gate config.writeLog( 4827c478bd9Sstevel@tonic-gate "rh_ioexception_reply", 4837c478bd9Sstevel@tonic-gate new Object[] {clientAddr, 4847c478bd9Sstevel@tonic-gate new Integer(port), 4857c478bd9Sstevel@tonic-gate interfac, 4867c478bd9Sstevel@tonic-gate ex.getMessage()}); 4877c478bd9Sstevel@tonic-gate } 4887c478bd9Sstevel@tonic-gate 4897c478bd9Sstevel@tonic-gate } finally { 4907c478bd9Sstevel@tonic-gate 4917c478bd9Sstevel@tonic-gate if (ds != null) { 4927c478bd9Sstevel@tonic-gate ds.close(); 4937c478bd9Sstevel@tonic-gate 4947c478bd9Sstevel@tonic-gate } 4957c478bd9Sstevel@tonic-gate 4967c478bd9Sstevel@tonic-gate } 4977c478bd9Sstevel@tonic-gate 4987c478bd9Sstevel@tonic-gate } 4997c478bd9Sstevel@tonic-gate 5007c478bd9Sstevel@tonic-gate // Handle an incoming stream containing an SLP request. 5017c478bd9Sstevel@tonic-gate 5027c478bd9Sstevel@tonic-gate private boolean handleRequest(DataInputStream dis, ByteArrayOutputStream baos, boolean isTCP)5037c478bd9Sstevel@tonic-gate handleRequest(DataInputStream dis, 5047c478bd9Sstevel@tonic-gate ByteArrayOutputStream baos, 5057c478bd9Sstevel@tonic-gate boolean isTCP) 5067c478bd9Sstevel@tonic-gate throws IOException { 5077c478bd9Sstevel@tonic-gate 5087c478bd9Sstevel@tonic-gate boolean parseError = false; 5097c478bd9Sstevel@tonic-gate 5107c478bd9Sstevel@tonic-gate // Decode the message. 5117c478bd9Sstevel@tonic-gate 5127c478bd9Sstevel@tonic-gate SrvLocMsg msg = internalize(dis, isTCP); 5137c478bd9Sstevel@tonic-gate 5147c478bd9Sstevel@tonic-gate // If there was an error converting the request, then don't 5157c478bd9Sstevel@tonic-gate // process further. 5167c478bd9Sstevel@tonic-gate 5177c478bd9Sstevel@tonic-gate SrvLocMsg rply = msg; 5187c478bd9Sstevel@tonic-gate 5197c478bd9Sstevel@tonic-gate if (msg != null) { 5207c478bd9Sstevel@tonic-gate SrvLocHeader hdr = msg.getHeader(); 5217c478bd9Sstevel@tonic-gate 5227c478bd9Sstevel@tonic-gate if (hdr.errCode == ServiceLocationException.OK) { 5237c478bd9Sstevel@tonic-gate 5247c478bd9Sstevel@tonic-gate if (config.traceMsg()) { 5257c478bd9Sstevel@tonic-gate config.writeLog("rh_rqst_in", 5267c478bd9Sstevel@tonic-gate new Object[] {Integer.toHexString(hdr.xid), 5277c478bd9Sstevel@tonic-gate clientAddr, 5287c478bd9Sstevel@tonic-gate new Integer(port), 5297c478bd9Sstevel@tonic-gate interfac, 5307c478bd9Sstevel@tonic-gate msg.getHeader()}); 5317c478bd9Sstevel@tonic-gate } 5327c478bd9Sstevel@tonic-gate 5337c478bd9Sstevel@tonic-gate 5347c478bd9Sstevel@tonic-gate // Dispatch the message to the service table. 5357c478bd9Sstevel@tonic-gate 5367c478bd9Sstevel@tonic-gate rply = dispatch(msg); 5377c478bd9Sstevel@tonic-gate 5387c478bd9Sstevel@tonic-gate // If no reply, then simply return. 5397c478bd9Sstevel@tonic-gate 5407c478bd9Sstevel@tonic-gate if (rply == null) { 5417c478bd9Sstevel@tonic-gate 5427c478bd9Sstevel@tonic-gate if (config.traceMsg()) { 5437c478bd9Sstevel@tonic-gate config.writeLog("rh_rply_null", 5447c478bd9Sstevel@tonic-gate new Object[] { 5457c478bd9Sstevel@tonic-gate Integer.toHexString(hdr.xid), 5467c478bd9Sstevel@tonic-gate clientAddr, 5477c478bd9Sstevel@tonic-gate new Integer(port), 5487c478bd9Sstevel@tonic-gate interfac}); 5497c478bd9Sstevel@tonic-gate 5507c478bd9Sstevel@tonic-gate } 5517c478bd9Sstevel@tonic-gate 5527c478bd9Sstevel@tonic-gate return parseError; 5537c478bd9Sstevel@tonic-gate 5547c478bd9Sstevel@tonic-gate } 5557c478bd9Sstevel@tonic-gate } else { 5567c478bd9Sstevel@tonic-gate 5577c478bd9Sstevel@tonic-gate // Drop if multicast. 5587c478bd9Sstevel@tonic-gate 5597c478bd9Sstevel@tonic-gate if (msg.getHeader().mcast) { 5607c478bd9Sstevel@tonic-gate rply = null; 5617c478bd9Sstevel@tonic-gate 5627c478bd9Sstevel@tonic-gate if (config.traceDrop()) { 5637c478bd9Sstevel@tonic-gate config.writeLog("rh_multi_error", 5647c478bd9Sstevel@tonic-gate new Object[] { 5657c478bd9Sstevel@tonic-gate msg.getClass().getName(), 5667c478bd9Sstevel@tonic-gate Integer.toHexString(hdr.xid), 5677c478bd9Sstevel@tonic-gate clientAddr, 5687c478bd9Sstevel@tonic-gate new Integer(port), 5697c478bd9Sstevel@tonic-gate interfac}); 5707c478bd9Sstevel@tonic-gate 5717c478bd9Sstevel@tonic-gate 5727c478bd9Sstevel@tonic-gate } 5737c478bd9Sstevel@tonic-gate } else if (isTCP) { 5747c478bd9Sstevel@tonic-gate 5757c478bd9Sstevel@tonic-gate // Set the parse error flag so that the stream gets closed. 5767c478bd9Sstevel@tonic-gate // It's easier than trying to keep track of the number of 5777c478bd9Sstevel@tonic-gate // bytes read. Otherwise, the remnents of the message 5787c478bd9Sstevel@tonic-gate // hang around. 5797c478bd9Sstevel@tonic-gate 5807c478bd9Sstevel@tonic-gate parseError = true; 5817c478bd9Sstevel@tonic-gate 5827c478bd9Sstevel@tonic-gate } 5837c478bd9Sstevel@tonic-gate } 5847c478bd9Sstevel@tonic-gate } 5857c478bd9Sstevel@tonic-gate 5867c478bd9Sstevel@tonic-gate // Reply to the client if necessary. Note that if the reply is null 5877c478bd9Sstevel@tonic-gate // here, there was a problem parsing the message in and so formulating 5887c478bd9Sstevel@tonic-gate // a reply may be impossible (for example, the message may not 5897c478bd9Sstevel@tonic-gate // be parsable beyond the function code. 5907c478bd9Sstevel@tonic-gate 5917c478bd9Sstevel@tonic-gate if (rply != null) { 5927c478bd9Sstevel@tonic-gate SrvLocHeader hdr = rply.getHeader(); 5937c478bd9Sstevel@tonic-gate ServiceLocationException ex = null; 5947c478bd9Sstevel@tonic-gate 5957c478bd9Sstevel@tonic-gate // Parse out the message. 5967c478bd9Sstevel@tonic-gate 5977c478bd9Sstevel@tonic-gate try { 5987c478bd9Sstevel@tonic-gate hdr.externalize(baos, false, isTCP); 5997c478bd9Sstevel@tonic-gate } catch (ServiceLocationException sle) { 6007c478bd9Sstevel@tonic-gate ex = sle; 6017c478bd9Sstevel@tonic-gate } 6027c478bd9Sstevel@tonic-gate 6037c478bd9Sstevel@tonic-gate if (config.traceMsg()) { 6047c478bd9Sstevel@tonic-gate config.writeLog("rh_rply_out", 6057c478bd9Sstevel@tonic-gate new Object[] {Integer.toHexString(hdr.xid), 6067c478bd9Sstevel@tonic-gate clientAddr, 6077c478bd9Sstevel@tonic-gate new Integer(port), 6087c478bd9Sstevel@tonic-gate interfac, 6097c478bd9Sstevel@tonic-gate rply.getHeader()}); 6107c478bd9Sstevel@tonic-gate } 6117c478bd9Sstevel@tonic-gate 6127c478bd9Sstevel@tonic-gate if (ex != null) { 6137c478bd9Sstevel@tonic-gate baos.reset(); 6147c478bd9Sstevel@tonic-gate rply = hdr.makeErrorReply(ex); 6157c478bd9Sstevel@tonic-gate 6167c478bd9Sstevel@tonic-gate Assert.slpassert(msg != null, 6177c478bd9Sstevel@tonic-gate "rh_header_class_error", 6187c478bd9Sstevel@tonic-gate new Object[] {ex.getMessage()}); 6197c478bd9Sstevel@tonic-gate 6207c478bd9Sstevel@tonic-gate hdr = rply.getHeader(); 6217c478bd9Sstevel@tonic-gate 6227c478bd9Sstevel@tonic-gate try { 6237c478bd9Sstevel@tonic-gate hdr.externalize(baos, false, isTCP); 6247c478bd9Sstevel@tonic-gate 6257c478bd9Sstevel@tonic-gate } catch (ServiceLocationException exx) { 6267c478bd9Sstevel@tonic-gate 6277c478bd9Sstevel@tonic-gate } 6287c478bd9Sstevel@tonic-gate } 6297c478bd9Sstevel@tonic-gate } else if (config.traceMsg()) { 6307c478bd9Sstevel@tonic-gate 6317c478bd9Sstevel@tonic-gate // Print error message. 6327c478bd9Sstevel@tonic-gate 6337c478bd9Sstevel@tonic-gate String xidStr = "<null message>"; 6347c478bd9Sstevel@tonic-gate 6357c478bd9Sstevel@tonic-gate if (msg != null) { 6367c478bd9Sstevel@tonic-gate SrvLocHeader hdr = msg.getHeader(); 6377c478bd9Sstevel@tonic-gate xidStr = Integer.toHexString(hdr.xid); 6387c478bd9Sstevel@tonic-gate 6397c478bd9Sstevel@tonic-gate } 6407c478bd9Sstevel@tonic-gate 6417c478bd9Sstevel@tonic-gate config.writeLog("rh_rply_null", 6427c478bd9Sstevel@tonic-gate new Object[] {xidStr, 6437c478bd9Sstevel@tonic-gate clientAddr, 6447c478bd9Sstevel@tonic-gate new Integer(port), 6457c478bd9Sstevel@tonic-gate interfac}); 6467c478bd9Sstevel@tonic-gate } 6477c478bd9Sstevel@tonic-gate 6487c478bd9Sstevel@tonic-gate return parseError; 6497c478bd9Sstevel@tonic-gate } 6507c478bd9Sstevel@tonic-gate 6517c478bd9Sstevel@tonic-gate /** 6527c478bd9Sstevel@tonic-gate * Internalize the byte array in the input stream into a SrvLocMsg 6537c478bd9Sstevel@tonic-gate * subclass. It will be an appropriate subclass for the SA/DA. 6547c478bd9Sstevel@tonic-gate * 6557c478bd9Sstevel@tonic-gate * @param dis The input stream containing the packet. 6567c478bd9Sstevel@tonic-gate * @param viaTCP True if the outgoing stream is via TCP. 6577c478bd9Sstevel@tonic-gate * @return The right SrvLocMsg subclass appropriate for the SA/DA. 6587c478bd9Sstevel@tonic-gate * If null is returned, it means that the function code was 6597c478bd9Sstevel@tonic-gate * not recognized. 6607c478bd9Sstevel@tonic-gate * If any error occurs during creation, an error request is 6617c478bd9Sstevel@tonic-gate * returned with the error code set. 6627c478bd9Sstevel@tonic-gate */ 6637c478bd9Sstevel@tonic-gate 6647c478bd9Sstevel@tonic-gate private SrvLocMsg internalize(DataInputStream dis, boolean viaTCP)6657c478bd9Sstevel@tonic-gate internalize(DataInputStream dis, boolean viaTCP) throws IOException { 6667c478bd9Sstevel@tonic-gate 6677c478bd9Sstevel@tonic-gate int ver = 0, fun = 0; 6687c478bd9Sstevel@tonic-gate 6697c478bd9Sstevel@tonic-gate Assert.slpassert((dis != null), 6707c478bd9Sstevel@tonic-gate "rh_null_bais", 6717c478bd9Sstevel@tonic-gate new Object[0]); 6727c478bd9Sstevel@tonic-gate 6737c478bd9Sstevel@tonic-gate try { 6747c478bd9Sstevel@tonic-gate 6757c478bd9Sstevel@tonic-gate // Pull off the version number and function code. 6767c478bd9Sstevel@tonic-gate 6777c478bd9Sstevel@tonic-gate byte[] b = new byte[2]; 6787c478bd9Sstevel@tonic-gate 6797c478bd9Sstevel@tonic-gate dis.readFully(b, 0, 2); 6807c478bd9Sstevel@tonic-gate 6817c478bd9Sstevel@tonic-gate ver = (int) ((char)b[0] & 0XFF); 6827c478bd9Sstevel@tonic-gate fun = (int) ((char)b[1] & 0XFF); 6837c478bd9Sstevel@tonic-gate 6847c478bd9Sstevel@tonic-gate } catch (IOException ex) { 6857c478bd9Sstevel@tonic-gate 6867c478bd9Sstevel@tonic-gate // Print an error message, but only if not EOF. 6877c478bd9Sstevel@tonic-gate 6887c478bd9Sstevel@tonic-gate if (!(ex instanceof EOFException)) { 6897c478bd9Sstevel@tonic-gate printInternalizeErrorMessage(ver, fun, ex); 6907c478bd9Sstevel@tonic-gate 6917c478bd9Sstevel@tonic-gate } 6927c478bd9Sstevel@tonic-gate 6937c478bd9Sstevel@tonic-gate // Throw the exception, so streams can terminate. 6947c478bd9Sstevel@tonic-gate 6957c478bd9Sstevel@tonic-gate throw ex; 6967c478bd9Sstevel@tonic-gate 6977c478bd9Sstevel@tonic-gate } 6987c478bd9Sstevel@tonic-gate 6997c478bd9Sstevel@tonic-gate SrvLocMsg msg = null; 7007c478bd9Sstevel@tonic-gate SrvLocHeader hdr = null; 7017c478bd9Sstevel@tonic-gate 7027c478bd9Sstevel@tonic-gate try { 7037c478bd9Sstevel@tonic-gate 7047c478bd9Sstevel@tonic-gate hdr = SrvLocHeader.newInstance(ver); 7057c478bd9Sstevel@tonic-gate 7067c478bd9Sstevel@tonic-gate // Unrecognized version number if header not returned. 7077c478bd9Sstevel@tonic-gate // We only throw an exception if the version number 7087c478bd9Sstevel@tonic-gate // is greater than the current default version number. 7097c478bd9Sstevel@tonic-gate // otherwise, the packet is from an earlier version 7107c478bd9Sstevel@tonic-gate // of the protocol and should be ignored if we are 7117c478bd9Sstevel@tonic-gate // not operating in compatibility mode. 7127c478bd9Sstevel@tonic-gate 7137c478bd9Sstevel@tonic-gate if (hdr == null) { 7147c478bd9Sstevel@tonic-gate 7157c478bd9Sstevel@tonic-gate if (ver > Defaults.version || 7167c478bd9Sstevel@tonic-gate (config.isV1Supported() && config.isDA())) { 7177c478bd9Sstevel@tonic-gate // code problem... 7187c478bd9Sstevel@tonic-gate throw 7197c478bd9Sstevel@tonic-gate new ServiceLocationException( 7207c478bd9Sstevel@tonic-gate ServiceLocationException.VERSION_NOT_SUPPORTED, 7217c478bd9Sstevel@tonic-gate "rh_version_number_error", 7227c478bd9Sstevel@tonic-gate new Object[] {new Integer(ver), 7237c478bd9Sstevel@tonic-gate clientAddr, 7247c478bd9Sstevel@tonic-gate new Integer(port), 7257c478bd9Sstevel@tonic-gate interfac}); 7267c478bd9Sstevel@tonic-gate } else { 7277c478bd9Sstevel@tonic-gate return null; 7287c478bd9Sstevel@tonic-gate 7297c478bd9Sstevel@tonic-gate } 7307c478bd9Sstevel@tonic-gate } 7317c478bd9Sstevel@tonic-gate 7327c478bd9Sstevel@tonic-gate // If we've come via TCP, clear the packet length so the 7337c478bd9Sstevel@tonic-gate // eventual reply won't be checked for overflow. 7347c478bd9Sstevel@tonic-gate 7357c478bd9Sstevel@tonic-gate if (viaTCP) { 7367c478bd9Sstevel@tonic-gate hdr.setPacketLength(Integer.MAX_VALUE); 7377c478bd9Sstevel@tonic-gate 7387c478bd9Sstevel@tonic-gate } 7397c478bd9Sstevel@tonic-gate 7407c478bd9Sstevel@tonic-gate // Parse the header. 7417c478bd9Sstevel@tonic-gate 7427c478bd9Sstevel@tonic-gate hdr.parseHeader(fun, dis); 7437c478bd9Sstevel@tonic-gate 7447c478bd9Sstevel@tonic-gate // Parse body. 7457c478bd9Sstevel@tonic-gate 7467c478bd9Sstevel@tonic-gate if ((msg = hdr.parseMsg(dis)) != null) { 7477c478bd9Sstevel@tonic-gate 7487c478bd9Sstevel@tonic-gate // Parse options, if any. 7497c478bd9Sstevel@tonic-gate 7507c478bd9Sstevel@tonic-gate hdr.parseOptions(dis); 7517c478bd9Sstevel@tonic-gate 7527c478bd9Sstevel@tonic-gate } 7537c478bd9Sstevel@tonic-gate 7547c478bd9Sstevel@tonic-gate } catch (Exception ex) { 7557c478bd9Sstevel@tonic-gate 7567c478bd9Sstevel@tonic-gate printInternalizeErrorMessage(ver, fun, ex); 7577c478bd9Sstevel@tonic-gate 7587c478bd9Sstevel@tonic-gate msg = null; 7597c478bd9Sstevel@tonic-gate 7607c478bd9Sstevel@tonic-gate // If this is a DAAdvert or an SAAdvert, or there's no header, 7617c478bd9Sstevel@tonic-gate // return null cause we don't need to return anything or 7627c478bd9Sstevel@tonic-gate // can't. 7637c478bd9Sstevel@tonic-gate 7647c478bd9Sstevel@tonic-gate if (fun != SrvLocHeader.DAAdvert && 7657c478bd9Sstevel@tonic-gate fun != SrvLocHeader.SAAdvert && 7667c478bd9Sstevel@tonic-gate hdr != null) { 7677c478bd9Sstevel@tonic-gate 7687c478bd9Sstevel@tonic-gate // Let header create message. 7697c478bd9Sstevel@tonic-gate 7707c478bd9Sstevel@tonic-gate msg = hdr.makeErrorReply(ex); 7717c478bd9Sstevel@tonic-gate 7727c478bd9Sstevel@tonic-gate } 7737c478bd9Sstevel@tonic-gate 7747c478bd9Sstevel@tonic-gate } 7757c478bd9Sstevel@tonic-gate 7767c478bd9Sstevel@tonic-gate return msg; 7777c478bd9Sstevel@tonic-gate } 7787c478bd9Sstevel@tonic-gate 7797c478bd9Sstevel@tonic-gate // Print an error message for errors during internalization. 7807c478bd9Sstevel@tonic-gate printInternalizeErrorMessage(int ver, int fun, Exception ex)7817c478bd9Sstevel@tonic-gate private void printInternalizeErrorMessage(int ver, int fun, Exception ex) { 7827c478bd9Sstevel@tonic-gate 7837c478bd9Sstevel@tonic-gate if (config.traceDrop()) { 7847c478bd9Sstevel@tonic-gate 7857c478bd9Sstevel@tonic-gate StringWriter sw = new StringWriter(); 7867c478bd9Sstevel@tonic-gate PrintWriter pw = new PrintWriter(sw); 7877c478bd9Sstevel@tonic-gate 7887c478bd9Sstevel@tonic-gate ex.printStackTrace(pw); 7897c478bd9Sstevel@tonic-gate 7907c478bd9Sstevel@tonic-gate short errCode = ServiceLocationException.INTERNAL_SYSTEM_ERROR; 7917c478bd9Sstevel@tonic-gate 7927c478bd9Sstevel@tonic-gate if (ex instanceof ServiceLocationException) { 7937c478bd9Sstevel@tonic-gate errCode = ((ServiceLocationException)ex).getErrorCode(); 7947c478bd9Sstevel@tonic-gate 7957c478bd9Sstevel@tonic-gate } else if (ex instanceof IllegalArgumentException) { 7967c478bd9Sstevel@tonic-gate errCode = ServiceLocationException.PARSE_ERROR; 7977c478bd9Sstevel@tonic-gate 7987c478bd9Sstevel@tonic-gate } 7997c478bd9Sstevel@tonic-gate 8007c478bd9Sstevel@tonic-gate String exMsg = "(" + errCode + "):" + ex.getMessage(); 8017c478bd9Sstevel@tonic-gate 8027c478bd9Sstevel@tonic-gate config.writeLog("rh_unparse_exception", 8037c478bd9Sstevel@tonic-gate new Object[] {clientAddr, 8047c478bd9Sstevel@tonic-gate new Integer(port), 8057c478bd9Sstevel@tonic-gate interfac, 8067c478bd9Sstevel@tonic-gate new Integer(ver), 8077c478bd9Sstevel@tonic-gate new Integer(fun), 8087c478bd9Sstevel@tonic-gate exMsg, 8097c478bd9Sstevel@tonic-gate sw.toString()}); 8107c478bd9Sstevel@tonic-gate } 8117c478bd9Sstevel@tonic-gate } 8127c478bd9Sstevel@tonic-gate 8137c478bd9Sstevel@tonic-gate /** 8147c478bd9Sstevel@tonic-gate * Dispatch the service request object to the service table. 8157c478bd9Sstevel@tonic-gate * The SA table is used for the following: 8167c478bd9Sstevel@tonic-gate * 8177c478bd9Sstevel@tonic-gate * @param rqst Service request object. 8187c478bd9Sstevel@tonic-gate * @return A SrvLocMsg object to reply with, or null if no reply. 8197c478bd9Sstevel@tonic-gate */ 8207c478bd9Sstevel@tonic-gate dispatch(SrvLocMsg rqst)8217c478bd9Sstevel@tonic-gate SrvLocMsg dispatch(SrvLocMsg rqst) { 8227c478bd9Sstevel@tonic-gate 8237c478bd9Sstevel@tonic-gate SrvLocHeader hdr = rqst.getHeader(); 8247c478bd9Sstevel@tonic-gate boolean mcast = hdr.mcast; 8257c478bd9Sstevel@tonic-gate 8267c478bd9Sstevel@tonic-gate // Check CDAAdvert and CSAAdvert before we check the previous 8277c478bd9Sstevel@tonic-gate // responders list, because they don't have any. 8287c478bd9Sstevel@tonic-gate 8297c478bd9Sstevel@tonic-gate if (rqst instanceof CDAAdvert) { // DA advert... 8307c478bd9Sstevel@tonic-gate CDAAdvert msg = (CDAAdvert)rqst; 8317c478bd9Sstevel@tonic-gate 8327c478bd9Sstevel@tonic-gate // For V1, V2 messages know. 8337c478bd9Sstevel@tonic-gate 8347c478bd9Sstevel@tonic-gate msg.setIsUnsolicited(true); 8357c478bd9Sstevel@tonic-gate 8367c478bd9Sstevel@tonic-gate // If passive detection is off, ignore it, but only if it wasn't 8377c478bd9Sstevel@tonic-gate // a signal to stop. 8387c478bd9Sstevel@tonic-gate 8397c478bd9Sstevel@tonic-gate if (!config.passiveDADetection() && 8407c478bd9Sstevel@tonic-gate msg.isUnsolicited() && 8417c478bd9Sstevel@tonic-gate !msg.isGoingDown()) { 8427c478bd9Sstevel@tonic-gate if (config.traceDrop()) { 8437c478bd9Sstevel@tonic-gate config.writeLog("rh_passive_drop", 8447c478bd9Sstevel@tonic-gate new Object[] {msg.URL, 8457c478bd9Sstevel@tonic-gate hdr.scopes}); 8467c478bd9Sstevel@tonic-gate 8477c478bd9Sstevel@tonic-gate } 8487c478bd9Sstevel@tonic-gate 8497c478bd9Sstevel@tonic-gate } else if (msg.isGoingDown() && msg.isUnsolicited() && 8507c478bd9Sstevel@tonic-gate isLocalHostURL(msg.URL) && config.isDA()) { 8517c478bd9Sstevel@tonic-gate 8527c478bd9Sstevel@tonic-gate // We've been asked to terminate. 8537c478bd9Sstevel@tonic-gate 8547c478bd9Sstevel@tonic-gate // Check scopes. 8557c478bd9Sstevel@tonic-gate 8567c478bd9Sstevel@tonic-gate Vector scopes = (Vector)hdr.scopes.clone(); 8577c478bd9Sstevel@tonic-gate 8587c478bd9Sstevel@tonic-gate DATable.filterScopes(scopes, 8597c478bd9Sstevel@tonic-gate config.getSAConfiguredScopes(), true); 8607c478bd9Sstevel@tonic-gate 8617c478bd9Sstevel@tonic-gate // If all scopes not equal, it isn't a shutdown message for us. 8627c478bd9Sstevel@tonic-gate 8637c478bd9Sstevel@tonic-gate if (scopes.size() > 0) { 8647c478bd9Sstevel@tonic-gate daTable.handleAdvertIn(msg); 8657c478bd9Sstevel@tonic-gate 8667c478bd9Sstevel@tonic-gate } else { 8677c478bd9Sstevel@tonic-gate 8687c478bd9Sstevel@tonic-gate Vector discoveredScopes = new Vector(); 8697c478bd9Sstevel@tonic-gate 8707c478bd9Sstevel@tonic-gate try { 8717c478bd9Sstevel@tonic-gate discoveredScopes = daTable.findScopes(); 8727c478bd9Sstevel@tonic-gate 8737c478bd9Sstevel@tonic-gate } catch (ServiceLocationException ex) { 8747c478bd9Sstevel@tonic-gate 8757c478bd9Sstevel@tonic-gate // Ignore, we're going down anyway and it's 8767c478bd9Sstevel@tonic-gate // just a report. 8777c478bd9Sstevel@tonic-gate 8787c478bd9Sstevel@tonic-gate } 8797c478bd9Sstevel@tonic-gate 8807c478bd9Sstevel@tonic-gate // It is a shutdown message for us. 8817c478bd9Sstevel@tonic-gate 8827c478bd9Sstevel@tonic-gate Vector serverScopes = config.getSAConfiguredScopes(); 8837c478bd9Sstevel@tonic-gate Vector interfaces = config.getInterfaces(); 8847c478bd9Sstevel@tonic-gate Vector daAttributes = config.getDAAttributes(); 8857c478bd9Sstevel@tonic-gate 8867c478bd9Sstevel@tonic-gate if (config.traceAll() || 8877c478bd9Sstevel@tonic-gate config.traceMsg() || 8887c478bd9Sstevel@tonic-gate config.traceDrop() || 8897c478bd9Sstevel@tonic-gate config.traceDATraffic()) { 8907c478bd9Sstevel@tonic-gate 8917c478bd9Sstevel@tonic-gate config.writeLog("goodby_da", 8927c478bd9Sstevel@tonic-gate new Object[] {interfaces, 8937c478bd9Sstevel@tonic-gate serverScopes, 8947c478bd9Sstevel@tonic-gate discoveredScopes, 8957c478bd9Sstevel@tonic-gate daAttributes}); 8967c478bd9Sstevel@tonic-gate } 897*55fea89dSDan Cross 8987c478bd9Sstevel@tonic-gate 8997c478bd9Sstevel@tonic-gate // We don't reply, which means that the client will 9007c478bd9Sstevel@tonic-gate // time out. 9017c478bd9Sstevel@tonic-gate 9027c478bd9Sstevel@tonic-gate System.exit(0); 9037c478bd9Sstevel@tonic-gate 9047c478bd9Sstevel@tonic-gate } 9057c478bd9Sstevel@tonic-gate } else { 9067c478bd9Sstevel@tonic-gate 9077c478bd9Sstevel@tonic-gate // The implementation specific DA table handles this. 9087c478bd9Sstevel@tonic-gate 9097c478bd9Sstevel@tonic-gate daTable.handleAdvertIn(msg); 9107c478bd9Sstevel@tonic-gate 9117c478bd9Sstevel@tonic-gate } 9127c478bd9Sstevel@tonic-gate 9137c478bd9Sstevel@tonic-gate return null; 9147c478bd9Sstevel@tonic-gate 9157c478bd9Sstevel@tonic-gate } else if (rqst instanceof CSAAdvert) {// SA advert... 9167c478bd9Sstevel@tonic-gate CSAAdvert msg = (CSAAdvert)rqst; 9177c478bd9Sstevel@tonic-gate 9187c478bd9Sstevel@tonic-gate // We are only interested in it if we may be going down. 9197c478bd9Sstevel@tonic-gate 9207c478bd9Sstevel@tonic-gate if ((hdr.xid == 0) && isLocalHostURL(msg.URL) && !config.isDA()) { 9217c478bd9Sstevel@tonic-gate 9227c478bd9Sstevel@tonic-gate // Check scopes. 9237c478bd9Sstevel@tonic-gate 9247c478bd9Sstevel@tonic-gate Vector scopes = (Vector)hdr.scopes.clone(); 9257c478bd9Sstevel@tonic-gate 9267c478bd9Sstevel@tonic-gate DATable.filterScopes(scopes, 9277c478bd9Sstevel@tonic-gate config.getSAConfiguredScopes(), true); 9287c478bd9Sstevel@tonic-gate 9297c478bd9Sstevel@tonic-gate // If all scopes not equal, it isn't a shutdown message for us. 9307c478bd9Sstevel@tonic-gate 9317c478bd9Sstevel@tonic-gate if (scopes.size() <= 0) { 9327c478bd9Sstevel@tonic-gate 9337c478bd9Sstevel@tonic-gate Vector discoveredScopes = new Vector(); 9347c478bd9Sstevel@tonic-gate 9357c478bd9Sstevel@tonic-gate try { 9367c478bd9Sstevel@tonic-gate discoveredScopes = daTable.findScopes(); 9377c478bd9Sstevel@tonic-gate 9387c478bd9Sstevel@tonic-gate } catch (ServiceLocationException ex) { 9397c478bd9Sstevel@tonic-gate 9407c478bd9Sstevel@tonic-gate // Ignore, we're going down anyway and it's just a 9417c478bd9Sstevel@tonic-gate // report. 9427c478bd9Sstevel@tonic-gate 9437c478bd9Sstevel@tonic-gate } 9447c478bd9Sstevel@tonic-gate 9457c478bd9Sstevel@tonic-gate // It is a shutdown message for us. 9467c478bd9Sstevel@tonic-gate 9477c478bd9Sstevel@tonic-gate Vector serverScopes = config.getSAConfiguredScopes(); 9487c478bd9Sstevel@tonic-gate Vector interfaces = config.getInterfaces(); 9497c478bd9Sstevel@tonic-gate Vector saAttributes = config.getSAAttributes(); 9507c478bd9Sstevel@tonic-gate 9517c478bd9Sstevel@tonic-gate if (config.traceAll() || 9527c478bd9Sstevel@tonic-gate config.traceMsg() || 9537c478bd9Sstevel@tonic-gate config.traceDrop() || 9547c478bd9Sstevel@tonic-gate config.traceDATraffic()) { 9557c478bd9Sstevel@tonic-gate 9567c478bd9Sstevel@tonic-gate config.writeLog("goodby", 9577c478bd9Sstevel@tonic-gate new Object[] {interfaces, 9587c478bd9Sstevel@tonic-gate serverScopes, 9597c478bd9Sstevel@tonic-gate discoveredScopes, 9607c478bd9Sstevel@tonic-gate saAttributes}); 9617c478bd9Sstevel@tonic-gate } 9627c478bd9Sstevel@tonic-gate 9637c478bd9Sstevel@tonic-gate System.exit(0); 9647c478bd9Sstevel@tonic-gate } 9657c478bd9Sstevel@tonic-gate } 9667c478bd9Sstevel@tonic-gate 9677c478bd9Sstevel@tonic-gate // Otherwise, drop it for now. 9687c478bd9Sstevel@tonic-gate 9697c478bd9Sstevel@tonic-gate if (config.traceDrop()) { 9707c478bd9Sstevel@tonic-gate config.writeLog("rh_client_sa_advert_drop", 9717c478bd9Sstevel@tonic-gate new Object[] {Integer.toHexString(hdr.xid), 9727c478bd9Sstevel@tonic-gate clientAddr, 9737c478bd9Sstevel@tonic-gate new Integer(port), 9747c478bd9Sstevel@tonic-gate interfac}); 9757c478bd9Sstevel@tonic-gate } 9767c478bd9Sstevel@tonic-gate 9777c478bd9Sstevel@tonic-gate return null; 9787c478bd9Sstevel@tonic-gate 9797c478bd9Sstevel@tonic-gate } 9807c478bd9Sstevel@tonic-gate 9817c478bd9Sstevel@tonic-gate if (rqst instanceof SSrvReg) { // registration... 9827c478bd9Sstevel@tonic-gate 9837c478bd9Sstevel@tonic-gate return dispatchReg((SSrvReg)rqst, 9847c478bd9Sstevel@tonic-gate serviceTable); 9857c478bd9Sstevel@tonic-gate 9867c478bd9Sstevel@tonic-gate } else if (rqst instanceof SSrvDereg) { // deregistration... 9877c478bd9Sstevel@tonic-gate 9887c478bd9Sstevel@tonic-gate return dispatchDereg((SSrvDereg)rqst, 9897c478bd9Sstevel@tonic-gate serviceTable); 9907c478bd9Sstevel@tonic-gate 9917c478bd9Sstevel@tonic-gate } 9927c478bd9Sstevel@tonic-gate 9937c478bd9Sstevel@tonic-gate 9947c478bd9Sstevel@tonic-gate // If we are on the previous responder list, then ignore this 9957c478bd9Sstevel@tonic-gate // request. 9967c478bd9Sstevel@tonic-gate 9977c478bd9Sstevel@tonic-gate if (isPreviousResponder(hdr)) { 9987c478bd9Sstevel@tonic-gate 9997c478bd9Sstevel@tonic-gate if (config.traceDrop()) { 10007c478bd9Sstevel@tonic-gate config.writeLog("rh_prev_resp", 10017c478bd9Sstevel@tonic-gate new Object[] {Integer.toHexString(hdr.xid), 10027c478bd9Sstevel@tonic-gate clientAddr, 10037c478bd9Sstevel@tonic-gate new Integer(port), 10047c478bd9Sstevel@tonic-gate interfac}); 10057c478bd9Sstevel@tonic-gate } 10067c478bd9Sstevel@tonic-gate 10077c478bd9Sstevel@tonic-gate return null; 10087c478bd9Sstevel@tonic-gate 10097c478bd9Sstevel@tonic-gate } 10107c478bd9Sstevel@tonic-gate 10117c478bd9Sstevel@tonic-gate // Now check requests with previous responders. 10127c478bd9Sstevel@tonic-gate 10137c478bd9Sstevel@tonic-gate if (rqst instanceof SSrvTypeMsg) { // service types... 10147c478bd9Sstevel@tonic-gate 10157c478bd9Sstevel@tonic-gate return dispatchSrvType((SSrvTypeMsg)rqst, 10167c478bd9Sstevel@tonic-gate serviceTable); 10177c478bd9Sstevel@tonic-gate 10187c478bd9Sstevel@tonic-gate } else if (rqst instanceof SAttrMsg) { // attributes... 10197c478bd9Sstevel@tonic-gate 10207c478bd9Sstevel@tonic-gate return dispatchAttr((SAttrMsg)rqst, 10217c478bd9Sstevel@tonic-gate serviceTable); 10227c478bd9Sstevel@tonic-gate 10237c478bd9Sstevel@tonic-gate } else if (rqst instanceof SSrvMsg) { // services... 10247c478bd9Sstevel@tonic-gate 10257c478bd9Sstevel@tonic-gate return dispatchSrv((SSrvMsg)rqst, 10267c478bd9Sstevel@tonic-gate serviceTable); 10277c478bd9Sstevel@tonic-gate 10287c478bd9Sstevel@tonic-gate } else { // error... 10297c478bd9Sstevel@tonic-gate 10307c478bd9Sstevel@tonic-gate Assert.slpassert(false, 10317c478bd9Sstevel@tonic-gate "rh_rqst_type_err", 10327c478bd9Sstevel@tonic-gate new Object[] {rqst}); 10337c478bd9Sstevel@tonic-gate 10347c478bd9Sstevel@tonic-gate } 10357c478bd9Sstevel@tonic-gate 10367c478bd9Sstevel@tonic-gate return null; 10377c478bd9Sstevel@tonic-gate 10387c478bd9Sstevel@tonic-gate } 10397c478bd9Sstevel@tonic-gate 10407c478bd9Sstevel@tonic-gate 10417c478bd9Sstevel@tonic-gate // Dispatch a service registration. 10427c478bd9Sstevel@tonic-gate dispatchReg(SSrvReg rqst, ServiceTable serviceTable)10437c478bd9Sstevel@tonic-gate private SrvLocMsg dispatchReg(SSrvReg rqst, 10447c478bd9Sstevel@tonic-gate ServiceTable serviceTable) { 10457c478bd9Sstevel@tonic-gate 10467c478bd9Sstevel@tonic-gate SrvLocHeader hdr = rqst.getHeader(); 10477c478bd9Sstevel@tonic-gate 10487c478bd9Sstevel@tonic-gate // Report error if the message was multicast. 10497c478bd9Sstevel@tonic-gate 10507c478bd9Sstevel@tonic-gate if (hdr.mcast && config.traceDrop()) { 10517c478bd9Sstevel@tonic-gate 10527c478bd9Sstevel@tonic-gate if (config.traceDrop()) { 10537c478bd9Sstevel@tonic-gate config.writeLog("rh_no_multi", 10547c478bd9Sstevel@tonic-gate new Object[] {"SrvReg", 10557c478bd9Sstevel@tonic-gate Integer.toHexString(hdr.xid), 10567c478bd9Sstevel@tonic-gate clientAddr, 10577c478bd9Sstevel@tonic-gate new Integer(port), 10587c478bd9Sstevel@tonic-gate interfac}); 10597c478bd9Sstevel@tonic-gate } 10607c478bd9Sstevel@tonic-gate 10617c478bd9Sstevel@tonic-gate return null; 10627c478bd9Sstevel@tonic-gate 10637c478bd9Sstevel@tonic-gate } 10647c478bd9Sstevel@tonic-gate 10657c478bd9Sstevel@tonic-gate // Register the request. 10667c478bd9Sstevel@tonic-gate 10677c478bd9Sstevel@tonic-gate SrvLocMsg rply = serviceTable.register(rqst); 10687c478bd9Sstevel@tonic-gate 10697c478bd9Sstevel@tonic-gate // Forward to foreign DAs if no error. 10707c478bd9Sstevel@tonic-gate 10717c478bd9Sstevel@tonic-gate if (rply != null) { 10727c478bd9Sstevel@tonic-gate hdr = rply.getHeader(); 10737c478bd9Sstevel@tonic-gate 10747c478bd9Sstevel@tonic-gate if (hdr.errCode == ServiceLocationException.OK) { 10757c478bd9Sstevel@tonic-gate toForward = rqst; 1076*55fea89dSDan Cross 10777c478bd9Sstevel@tonic-gate } 10787c478bd9Sstevel@tonic-gate } 10797c478bd9Sstevel@tonic-gate 10807c478bd9Sstevel@tonic-gate return rply; 10817c478bd9Sstevel@tonic-gate } 10827c478bd9Sstevel@tonic-gate 10837c478bd9Sstevel@tonic-gate // Dispatch a service deregistration. 10847c478bd9Sstevel@tonic-gate dispatchDereg(SSrvDereg rqst, ServiceTable serviceTable)10857c478bd9Sstevel@tonic-gate private SrvLocMsg dispatchDereg(SSrvDereg rqst, 10867c478bd9Sstevel@tonic-gate ServiceTable serviceTable) { 10877c478bd9Sstevel@tonic-gate 10887c478bd9Sstevel@tonic-gate SrvLocHeader hdr = rqst.getHeader(); 10897c478bd9Sstevel@tonic-gate 10907c478bd9Sstevel@tonic-gate // Report error if the message was multicast. 10917c478bd9Sstevel@tonic-gate 10927c478bd9Sstevel@tonic-gate if (hdr.mcast && config.traceDrop()) { 10937c478bd9Sstevel@tonic-gate 10947c478bd9Sstevel@tonic-gate if (config.traceDrop()) { 10957c478bd9Sstevel@tonic-gate config.writeLog("rh_no_multi", 10967c478bd9Sstevel@tonic-gate new Object[] {"SrvDereg", 10977c478bd9Sstevel@tonic-gate Integer.toHexString(hdr.xid), 10987c478bd9Sstevel@tonic-gate clientAddr, 10997c478bd9Sstevel@tonic-gate new Integer(port), 11007c478bd9Sstevel@tonic-gate interfac}); 11017c478bd9Sstevel@tonic-gate } 11027c478bd9Sstevel@tonic-gate 11037c478bd9Sstevel@tonic-gate return null; 11047c478bd9Sstevel@tonic-gate 11057c478bd9Sstevel@tonic-gate } 11067c478bd9Sstevel@tonic-gate 11077c478bd9Sstevel@tonic-gate // If the message came from the local host, use the SA store. 11087c478bd9Sstevel@tonic-gate 11097c478bd9Sstevel@tonic-gate SrvLocMsg rply = serviceTable.deregister(rqst); 11107c478bd9Sstevel@tonic-gate 11117c478bd9Sstevel@tonic-gate // Forward to foreign DAs if no error. 11127c478bd9Sstevel@tonic-gate 11137c478bd9Sstevel@tonic-gate if (rply != null) { 11147c478bd9Sstevel@tonic-gate hdr = rply.getHeader(); 11157c478bd9Sstevel@tonic-gate 11167c478bd9Sstevel@tonic-gate if (hdr.errCode == ServiceLocationException.OK) { 11177c478bd9Sstevel@tonic-gate toForward = rqst; 11187c478bd9Sstevel@tonic-gate 11197c478bd9Sstevel@tonic-gate } 11207c478bd9Sstevel@tonic-gate } 11217c478bd9Sstevel@tonic-gate 11227c478bd9Sstevel@tonic-gate return rply; 11237c478bd9Sstevel@tonic-gate } 11247c478bd9Sstevel@tonic-gate 11257c478bd9Sstevel@tonic-gate // Dispatch a service type message. 11267c478bd9Sstevel@tonic-gate dispatchSrvType(SSrvTypeMsg rqst, ServiceTable serviceTable)11277c478bd9Sstevel@tonic-gate private SrvLocMsg dispatchSrvType(SSrvTypeMsg rqst, 11287c478bd9Sstevel@tonic-gate ServiceTable serviceTable) { 11297c478bd9Sstevel@tonic-gate 11307c478bd9Sstevel@tonic-gate SrvLocHeader hdr = rqst.getHeader(); 11317c478bd9Sstevel@tonic-gate boolean mcast = hdr.mcast; 11327c478bd9Sstevel@tonic-gate 11337c478bd9Sstevel@tonic-gate // Drop if this is a DA and the request was multicast. DAs 11347c478bd9Sstevel@tonic-gate // do not respond to multicast, except for DAAdverts. 11357c478bd9Sstevel@tonic-gate 11367c478bd9Sstevel@tonic-gate if (mcast && config.isDA()) { 11377c478bd9Sstevel@tonic-gate 11387c478bd9Sstevel@tonic-gate if (config.traceDrop()) { 11397c478bd9Sstevel@tonic-gate config.writeLog("rh_drop_da_multi", 11407c478bd9Sstevel@tonic-gate new Object[] {"SrvTypeRqst", 11417c478bd9Sstevel@tonic-gate Integer.toHexString(hdr.xid), 11427c478bd9Sstevel@tonic-gate clientAddr, 11437c478bd9Sstevel@tonic-gate new Integer(port), 11447c478bd9Sstevel@tonic-gate interfac}); 11457c478bd9Sstevel@tonic-gate } 11467c478bd9Sstevel@tonic-gate 11477c478bd9Sstevel@tonic-gate return null; 11487c478bd9Sstevel@tonic-gate 11497c478bd9Sstevel@tonic-gate } 11507c478bd9Sstevel@tonic-gate 11517c478bd9Sstevel@tonic-gate SrvLocMsg rply = serviceTable.findServiceTypes(rqst); 11527c478bd9Sstevel@tonic-gate hdr = rply.getHeader(); 11537c478bd9Sstevel@tonic-gate 11547c478bd9Sstevel@tonic-gate // Filter multicast replies to remove null and error returns. 11557c478bd9Sstevel@tonic-gate 11567c478bd9Sstevel@tonic-gate if (mcast && 11577c478bd9Sstevel@tonic-gate ((hdr.errCode != ServiceLocationException.OK) || 11587c478bd9Sstevel@tonic-gate (hdr.getNumReplies() == 0))) { 11597c478bd9Sstevel@tonic-gate 11607c478bd9Sstevel@tonic-gate if (config.traceDrop()) { 11617c478bd9Sstevel@tonic-gate config.writeLog("rh_multi_error", 11627c478bd9Sstevel@tonic-gate new Object[] {"SrvTypeRqst", 11637c478bd9Sstevel@tonic-gate Integer.toHexString(hdr.xid), 11647c478bd9Sstevel@tonic-gate clientAddr, 11657c478bd9Sstevel@tonic-gate new Integer(port), 11667c478bd9Sstevel@tonic-gate interfac}); 11677c478bd9Sstevel@tonic-gate 11687c478bd9Sstevel@tonic-gate 11697c478bd9Sstevel@tonic-gate } 11707c478bd9Sstevel@tonic-gate 11717c478bd9Sstevel@tonic-gate return null; 11727c478bd9Sstevel@tonic-gate 11737c478bd9Sstevel@tonic-gate } 11747c478bd9Sstevel@tonic-gate 11757c478bd9Sstevel@tonic-gate return rply; 11767c478bd9Sstevel@tonic-gate } 11777c478bd9Sstevel@tonic-gate 11787c478bd9Sstevel@tonic-gate // Dispatch an attribute request. 11797c478bd9Sstevel@tonic-gate dispatchAttr(SAttrMsg rqst, ServiceTable serviceTable)11807c478bd9Sstevel@tonic-gate private SrvLocMsg dispatchAttr(SAttrMsg rqst, 11817c478bd9Sstevel@tonic-gate ServiceTable serviceTable) { 11827c478bd9Sstevel@tonic-gate 11837c478bd9Sstevel@tonic-gate SrvLocHeader hdr = rqst.getHeader(); 11847c478bd9Sstevel@tonic-gate boolean mcast = hdr.mcast; 11857c478bd9Sstevel@tonic-gate 11867c478bd9Sstevel@tonic-gate // Drop if this is a DA and the request was multicast. DAs 11877c478bd9Sstevel@tonic-gate // do not respond to multicast, except for DAAdverts. 11887c478bd9Sstevel@tonic-gate 11897c478bd9Sstevel@tonic-gate if (mcast && config.isDA()) { 11907c478bd9Sstevel@tonic-gate 11917c478bd9Sstevel@tonic-gate if (config.traceDrop()) { 11927c478bd9Sstevel@tonic-gate config.writeLog("rh_drop_da_multi", 11937c478bd9Sstevel@tonic-gate new Object[] {"AttrRqst", 11947c478bd9Sstevel@tonic-gate Integer.toHexString(hdr.xid), 11957c478bd9Sstevel@tonic-gate clientAddr, 11967c478bd9Sstevel@tonic-gate new Integer(port), 11977c478bd9Sstevel@tonic-gate interfac}); 11987c478bd9Sstevel@tonic-gate } 11997c478bd9Sstevel@tonic-gate 12007c478bd9Sstevel@tonic-gate return null; 12017c478bd9Sstevel@tonic-gate 12027c478bd9Sstevel@tonic-gate } 12037c478bd9Sstevel@tonic-gate 12047c478bd9Sstevel@tonic-gate SrvLocMsg rply = serviceTable.findAttributes(rqst); 12057c478bd9Sstevel@tonic-gate hdr = rply.getHeader(); 12067c478bd9Sstevel@tonic-gate 12077c478bd9Sstevel@tonic-gate // Filter multicast replies to remove null and error returns. 12087c478bd9Sstevel@tonic-gate 12097c478bd9Sstevel@tonic-gate if (mcast && 12107c478bd9Sstevel@tonic-gate ((hdr.errCode != ServiceLocationException.OK) || 12117c478bd9Sstevel@tonic-gate (hdr.getNumReplies() == 0))) { 12127c478bd9Sstevel@tonic-gate 12137c478bd9Sstevel@tonic-gate if (config.traceDrop()) { 12147c478bd9Sstevel@tonic-gate config.writeLog("rh_multi_error", 12157c478bd9Sstevel@tonic-gate new Object[] {"AttrRqst", 12167c478bd9Sstevel@tonic-gate Integer.toHexString(hdr.xid), 12177c478bd9Sstevel@tonic-gate clientAddr, 12187c478bd9Sstevel@tonic-gate new Integer(port), 12197c478bd9Sstevel@tonic-gate interfac}); 12207c478bd9Sstevel@tonic-gate 12217c478bd9Sstevel@tonic-gate } 12227c478bd9Sstevel@tonic-gate 12237c478bd9Sstevel@tonic-gate return null; 12247c478bd9Sstevel@tonic-gate 12257c478bd9Sstevel@tonic-gate } 12267c478bd9Sstevel@tonic-gate 12277c478bd9Sstevel@tonic-gate return rply; 12287c478bd9Sstevel@tonic-gate } 12297c478bd9Sstevel@tonic-gate 12307c478bd9Sstevel@tonic-gate // Dispatch a service request. 12317c478bd9Sstevel@tonic-gate dispatchSrv(SSrvMsg rqst, ServiceTable serviceTable)12327c478bd9Sstevel@tonic-gate private SrvLocMsg dispatchSrv(SSrvMsg rqst, 12337c478bd9Sstevel@tonic-gate ServiceTable serviceTable) { 12347c478bd9Sstevel@tonic-gate 12357c478bd9Sstevel@tonic-gate SrvLocHeader hdr = rqst.getHeader(); 12367c478bd9Sstevel@tonic-gate boolean mcast = hdr.mcast; 12377c478bd9Sstevel@tonic-gate String serviceType = rqst.serviceType; 12387c478bd9Sstevel@tonic-gate SrvLocMsg rply = null; 12397c478bd9Sstevel@tonic-gate 12407c478bd9Sstevel@tonic-gate // We need to special case if this is a request for a DAAdvert 12417c478bd9Sstevel@tonic-gate // and we are a DA or an SAAdvert and we are an SA only. 12427c478bd9Sstevel@tonic-gate 12437c478bd9Sstevel@tonic-gate if (serviceType.equals(Defaults.DA_SERVICE_TYPE.toString())) { 12447c478bd9Sstevel@tonic-gate 12457c478bd9Sstevel@tonic-gate // Reply only if a DA. 12467c478bd9Sstevel@tonic-gate 12477c478bd9Sstevel@tonic-gate if (config.isDA()) { 12487c478bd9Sstevel@tonic-gate 12497c478bd9Sstevel@tonic-gate 12507c478bd9Sstevel@tonic-gate // Return a DAAdvert for this DA. 12517c478bd9Sstevel@tonic-gate 12527c478bd9Sstevel@tonic-gate rply = serviceTable.makeDAAdvert(rqst, 12537c478bd9Sstevel@tonic-gate interfac, 12547c478bd9Sstevel@tonic-gate config); 12557c478bd9Sstevel@tonic-gate 12567c478bd9Sstevel@tonic-gate hdr = rply.getHeader(); 12577c478bd9Sstevel@tonic-gate 12587c478bd9Sstevel@tonic-gate if ((hdr.errCode != ServiceLocationException.OK) && 12597c478bd9Sstevel@tonic-gate config.traceMsg()) { 12607c478bd9Sstevel@tonic-gate config.writeLog("rh_advert_error", 12617c478bd9Sstevel@tonic-gate new Object[] { new Integer(hdr.errCode), 12627c478bd9Sstevel@tonic-gate "DAAdvert", 12637c478bd9Sstevel@tonic-gate ""}); 12647c478bd9Sstevel@tonic-gate 12657c478bd9Sstevel@tonic-gate } 12667c478bd9Sstevel@tonic-gate } 12677c478bd9Sstevel@tonic-gate 12687c478bd9Sstevel@tonic-gate // If there was an error and the request was multicast, drop it 12697c478bd9Sstevel@tonic-gate // by returning null. 12707c478bd9Sstevel@tonic-gate 12717c478bd9Sstevel@tonic-gate if (hdr.errCode != ServiceLocationException.OK && 12727c478bd9Sstevel@tonic-gate mcast) { 12737c478bd9Sstevel@tonic-gate 12747c478bd9Sstevel@tonic-gate if (config.traceDrop()) { 12757c478bd9Sstevel@tonic-gate 12767c478bd9Sstevel@tonic-gate config.writeLog("rh_drop_srv", 12777c478bd9Sstevel@tonic-gate new Object[] { 12787c478bd9Sstevel@tonic-gate "DA SrvRqst", 12797c478bd9Sstevel@tonic-gate Integer.toHexString(hdr.xid), 12807c478bd9Sstevel@tonic-gate clientAddr, 12817c478bd9Sstevel@tonic-gate new Integer(port), 12827c478bd9Sstevel@tonic-gate interfac}); 12837c478bd9Sstevel@tonic-gate 12847c478bd9Sstevel@tonic-gate } 12857c478bd9Sstevel@tonic-gate 12867c478bd9Sstevel@tonic-gate return null; 12877c478bd9Sstevel@tonic-gate 12887c478bd9Sstevel@tonic-gate } 12897c478bd9Sstevel@tonic-gate 12907c478bd9Sstevel@tonic-gate return rply; 12917c478bd9Sstevel@tonic-gate 12927c478bd9Sstevel@tonic-gate } else if (serviceType.equals(Defaults.SA_SERVICE_TYPE.toString())) { 12937c478bd9Sstevel@tonic-gate 12947c478bd9Sstevel@tonic-gate // Note that we reply if we are a DA because somebody may want 12957c478bd9Sstevel@tonic-gate // SA attributes. 12967c478bd9Sstevel@tonic-gate 12977c478bd9Sstevel@tonic-gate // We report error for unicast SA service request. 12987c478bd9Sstevel@tonic-gate 12997c478bd9Sstevel@tonic-gate if (!mcast) { 1300*55fea89dSDan Cross 13017c478bd9Sstevel@tonic-gate if (config.traceDrop()) { 13027c478bd9Sstevel@tonic-gate 13037c478bd9Sstevel@tonic-gate config.writeLog("rh_no_srv_uni", 13047c478bd9Sstevel@tonic-gate new Object[] { 13057c478bd9Sstevel@tonic-gate "SA SrvRqst", 13067c478bd9Sstevel@tonic-gate Integer.toHexString(hdr.xid), 13077c478bd9Sstevel@tonic-gate clientAddr, 13087c478bd9Sstevel@tonic-gate new Integer(port), 13097c478bd9Sstevel@tonic-gate interfac}); 13107c478bd9Sstevel@tonic-gate 13117c478bd9Sstevel@tonic-gate } 13127c478bd9Sstevel@tonic-gate 13137c478bd9Sstevel@tonic-gate return null; 13147c478bd9Sstevel@tonic-gate 13157c478bd9Sstevel@tonic-gate } 13167c478bd9Sstevel@tonic-gate 13177c478bd9Sstevel@tonic-gate // Return a SAAdvert for this SA. 13187c478bd9Sstevel@tonic-gate 13197c478bd9Sstevel@tonic-gate try { 13207c478bd9Sstevel@tonic-gate rply = serviceTable.makeSAAdvert(rqst, 13217c478bd9Sstevel@tonic-gate interfac, 13227c478bd9Sstevel@tonic-gate config); 13237c478bd9Sstevel@tonic-gate 13247c478bd9Sstevel@tonic-gate } catch (ServiceLocationException ex) { 13257c478bd9Sstevel@tonic-gate config.writeLog("rh_advert_error", 13267c478bd9Sstevel@tonic-gate new Object [] {new Integer(ex.getErrorCode()), 13277c478bd9Sstevel@tonic-gate "SAAdvert", 13287c478bd9Sstevel@tonic-gate ex.getMessage()}); 13297c478bd9Sstevel@tonic-gate 13307c478bd9Sstevel@tonic-gate } 13317c478bd9Sstevel@tonic-gate 13327c478bd9Sstevel@tonic-gate 13337c478bd9Sstevel@tonic-gate if (rply == null && config.traceDrop()) { 13347c478bd9Sstevel@tonic-gate 13357c478bd9Sstevel@tonic-gate config.writeLog("rh_drop_srv", 13367c478bd9Sstevel@tonic-gate new Object[] {"SA SrvRqst", 13377c478bd9Sstevel@tonic-gate Integer.toHexString(hdr.xid), 13387c478bd9Sstevel@tonic-gate clientAddr, 13397c478bd9Sstevel@tonic-gate new Integer(port), 13407c478bd9Sstevel@tonic-gate interfac}); 13417c478bd9Sstevel@tonic-gate 13427c478bd9Sstevel@tonic-gate } 13437c478bd9Sstevel@tonic-gate 13447c478bd9Sstevel@tonic-gate return rply; 13457c478bd9Sstevel@tonic-gate 13467c478bd9Sstevel@tonic-gate } 13477c478bd9Sstevel@tonic-gate 13487c478bd9Sstevel@tonic-gate // Drop if this is a DA and the request was multicast. DAs 13497c478bd9Sstevel@tonic-gate // do not respond to multicast, except for DAAdverts. 13507c478bd9Sstevel@tonic-gate 13517c478bd9Sstevel@tonic-gate if (mcast && config.isDA()) { 13527c478bd9Sstevel@tonic-gate 13537c478bd9Sstevel@tonic-gate if (config.traceDrop()) { 13547c478bd9Sstevel@tonic-gate config.writeLog("rh_drop_da_multi", 13557c478bd9Sstevel@tonic-gate new Object[] {"SrvRqst", 13567c478bd9Sstevel@tonic-gate Integer.toHexString(hdr.xid), 13577c478bd9Sstevel@tonic-gate clientAddr, 13587c478bd9Sstevel@tonic-gate new Integer(port), 13597c478bd9Sstevel@tonic-gate interfac}); 13607c478bd9Sstevel@tonic-gate } 13617c478bd9Sstevel@tonic-gate 13627c478bd9Sstevel@tonic-gate return null; 13637c478bd9Sstevel@tonic-gate 13647c478bd9Sstevel@tonic-gate } 13657c478bd9Sstevel@tonic-gate 13667c478bd9Sstevel@tonic-gate SrvLocMsg smrply = serviceTable.findServices(rqst); 13677c478bd9Sstevel@tonic-gate hdr = smrply.getHeader(); 13687c478bd9Sstevel@tonic-gate 13697c478bd9Sstevel@tonic-gate // Filter multicast replies to remove null and error returns. 13707c478bd9Sstevel@tonic-gate 13717c478bd9Sstevel@tonic-gate if (mcast && 13727c478bd9Sstevel@tonic-gate ((hdr.errCode != ServiceLocationException.OK) || 13737c478bd9Sstevel@tonic-gate (hdr.getNumReplies() == 0))) { 13747c478bd9Sstevel@tonic-gate 13757c478bd9Sstevel@tonic-gate if (config.traceDrop()) { 13767c478bd9Sstevel@tonic-gate config.writeLog("rh_multi_error", 13777c478bd9Sstevel@tonic-gate new Object[] {"SrvRqst", 13787c478bd9Sstevel@tonic-gate Integer.toHexString(hdr.xid), 13797c478bd9Sstevel@tonic-gate clientAddr, 13807c478bd9Sstevel@tonic-gate new Integer(port), 13817c478bd9Sstevel@tonic-gate interfac}); 13827c478bd9Sstevel@tonic-gate 13837c478bd9Sstevel@tonic-gate } 13847c478bd9Sstevel@tonic-gate 13857c478bd9Sstevel@tonic-gate return null; 13867c478bd9Sstevel@tonic-gate 13877c478bd9Sstevel@tonic-gate } 13887c478bd9Sstevel@tonic-gate 13897c478bd9Sstevel@tonic-gate return smrply; 13907c478bd9Sstevel@tonic-gate } 13917c478bd9Sstevel@tonic-gate 13927c478bd9Sstevel@tonic-gate // Return true if the host address matches one of the local interfaces. 13937c478bd9Sstevel@tonic-gate isLocalHostURL(ServiceURL url)13947c478bd9Sstevel@tonic-gate boolean isLocalHostURL(ServiceURL url) { 13957c478bd9Sstevel@tonic-gate String hostAddr = url.getHost(); 13967c478bd9Sstevel@tonic-gate Vector interfaces = config.getInterfaces(); 13977c478bd9Sstevel@tonic-gate InetAddress addr = null; 13987c478bd9Sstevel@tonic-gate 13997c478bd9Sstevel@tonic-gate try { 14007c478bd9Sstevel@tonic-gate addr = InetAddress.getByName(hostAddr); 14017c478bd9Sstevel@tonic-gate 14027c478bd9Sstevel@tonic-gate } catch (UnknownHostException ex) { 14037c478bd9Sstevel@tonic-gate 14047c478bd9Sstevel@tonic-gate // We simply ignore it. 14057c478bd9Sstevel@tonic-gate 14067c478bd9Sstevel@tonic-gate return false; 14077c478bd9Sstevel@tonic-gate 14087c478bd9Sstevel@tonic-gate } 14097c478bd9Sstevel@tonic-gate 14107c478bd9Sstevel@tonic-gate if (interfaces.contains(addr)) { 14117c478bd9Sstevel@tonic-gate return true; 14127c478bd9Sstevel@tonic-gate 14137c478bd9Sstevel@tonic-gate } 14147c478bd9Sstevel@tonic-gate 14157c478bd9Sstevel@tonic-gate return false; 14167c478bd9Sstevel@tonic-gate } 14177c478bd9Sstevel@tonic-gate 14187c478bd9Sstevel@tonic-gate /** 14197c478bd9Sstevel@tonic-gate * Return whether this was previous responder. Only do so if the 14207c478bd9Sstevel@tonic-gate * request was multicast. 14217c478bd9Sstevel@tonic-gate * 14227c478bd9Sstevel@tonic-gate * @return True if this host was a previous responder. 14237c478bd9Sstevel@tonic-gate */ 14247c478bd9Sstevel@tonic-gate isPreviousResponder(SrvLocHeader hdr)14257c478bd9Sstevel@tonic-gate public boolean isPreviousResponder(SrvLocHeader hdr) { 14267c478bd9Sstevel@tonic-gate 14277c478bd9Sstevel@tonic-gate // If there are no previous responders, then return false, 14287c478bd9Sstevel@tonic-gate // because they aren't used for this message. Also for 14297c478bd9Sstevel@tonic-gate // messages that are not multicast. 14307c478bd9Sstevel@tonic-gate 14317c478bd9Sstevel@tonic-gate if ((hdr.previousResponders == null) || 14327c478bd9Sstevel@tonic-gate (hdr.mcast == false)) { 14337c478bd9Sstevel@tonic-gate return false; 14347c478bd9Sstevel@tonic-gate 14357c478bd9Sstevel@tonic-gate } 14367c478bd9Sstevel@tonic-gate 14377c478bd9Sstevel@tonic-gate Vector previousResponders = hdr.previousResponders; 14387c478bd9Sstevel@tonic-gate Enumeration e = null; 14397c478bd9Sstevel@tonic-gate Vector interfaces = config.getInterfaces(); 14407c478bd9Sstevel@tonic-gate 14417c478bd9Sstevel@tonic-gate // Check for matches against this address. 14427c478bd9Sstevel@tonic-gate 14437c478bd9Sstevel@tonic-gate for (e = previousResponders.elements(); e.hasMoreElements(); ) { 14447c478bd9Sstevel@tonic-gate try { 14457c478bd9Sstevel@tonic-gate String sHost = ((String)e.nextElement()); 14467c478bd9Sstevel@tonic-gate InetAddress iaHost = InetAddress.getByName(sHost); 14477c478bd9Sstevel@tonic-gate 14487c478bd9Sstevel@tonic-gate if (interfaces.contains(iaHost)) { 14497c478bd9Sstevel@tonic-gate return true; 14507c478bd9Sstevel@tonic-gate } 14517c478bd9Sstevel@tonic-gate 14527c478bd9Sstevel@tonic-gate } catch (UnknownHostException ex) { 14537c478bd9Sstevel@tonic-gate 14547c478bd9Sstevel@tonic-gate } 14557c478bd9Sstevel@tonic-gate } 14567c478bd9Sstevel@tonic-gate 14577c478bd9Sstevel@tonic-gate return false; 14587c478bd9Sstevel@tonic-gate } 14597c478bd9Sstevel@tonic-gate 14607c478bd9Sstevel@tonic-gate 14617c478bd9Sstevel@tonic-gate // Initialize the SLPv2 header parser class when we are loaded. 14627c478bd9Sstevel@tonic-gate 14637c478bd9Sstevel@tonic-gate static { 14647c478bd9Sstevel@tonic-gate SrvLocHeader.addHeaderClass(Defaults.DEFAULT_SERVER_HEADER_CLASS, Defaults.version)14657c478bd9Sstevel@tonic-gate SrvLocHeader.addHeaderClass(Defaults.DEFAULT_SERVER_HEADER_CLASS, 14667c478bd9Sstevel@tonic-gate Defaults.version); 14677c478bd9Sstevel@tonic-gate 14687c478bd9Sstevel@tonic-gate } 14697c478bd9Sstevel@tonic-gate 14707c478bd9Sstevel@tonic-gate } 1471