/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* or packager/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
public class NetUtils {
private final static boolean asDebug =
if (asDebug) {
}
}
public enum PortAvailability {
};
private NetUtils() {
}
/**
* Return true if hostname represents the current machine.
* A null or empty hostname is considered local, as is the
* name "localhost". Otherwise, all the IP addresses
* corresponding to hostname are compared with all the IP addresses
* corresponding to "localhost", as well as all the IP addresses
* for all the network interfaces on this machine. Note that
* hostname can also be an IP address in string form.
*
* @return true if hostname is the local host
*/
// optimize common cases
return true;
// now check all the addresses of "localhost"
try {
// any address that's a loopback address is a local address
if (ia.isLoopbackAddress())
return true;
}
}
// are any of our addresses the same as any address of "localhost"?
// XXX - redundant with the above check?
return true;
}
}
}
}
catch (UnknownHostException ex) {
// ignore it
}
// it's not localhost, perhaps it's one of the addresses of this host?
try {
}
catch (SocketException ex) {
// ignore it
}
while (eni.hasMoreElements()) {
return true;
}
}
}
}
return false; // nothing matched, not local
/*
* For reference, here's the old code...
*
// come on JDK! Why is this so #$@% difficult!?!
// if you can think of something better -- go for it!!!
// use IP addresses because one hostname can have more than one IP address!
List<String> host_ips = new ArrayList<String>();
List<String> local_ips = new ArrayList<String>();
String myCanonicalHostName = System.getProperty(SystemPropertyConstants.HOST_NAME_PROPERTY);
try {
if (!StringUtils.ok(myCanonicalHostName))
myCanonicalHostName = getCanonicalHostName();
InetAddress[] adds = InetAddress.getAllByName(hostname);
if (adds == null || adds.length <= 0)
return false;
for (InetAddress ia : adds)
host_ips.add(ia.getHostAddress());
adds = InetAddress.getAllByName(myCanonicalHostName);
for (int i = 0; adds != null && i < adds.length; i++) {
String ip = adds[i].getHostAddress();
if (!local_ips.contains(ip))
local_ips.add(ip);
}
adds = InetAddress.getAllByName("localhost");
for (int i = 0; adds != null && i < adds.length; i++) {
String ip = adds[i].getHostAddress();
if (!local_ips.contains(ip))
local_ips.add(ip);
}
adds = InetAddress.getAllByName(null);
for (int i = 0; adds != null && i < adds.length; i++) {
String ip = adds[i].getHostAddress();
if (!local_ips.contains(ip))
local_ips.add(ip);
}
}
catch (UnknownHostException ex) {
return false;
}
// if any hostAddress matches any localAddress -- then the host is local...
for (String hip : host_ips)
for (String lip : local_ips)
if (hip.equals(lip))
return true;
return false;
*/
}
/**
* Painfully thorough error-handling. Some would say over-engineered but I
* plan on never looking at this code again!
* @param host1
* @param host2
* @return
*/
try {
return true; // edge case ==> both are null or empty
return false; // just one of them is null or empty
boolean adds1Empty = false; // readability. You'll see why below!
boolean adds2Empty = false;
adds1Empty = true;
adds2Empty = true;
// I told you!
return true;
return false;
return true;
return false;
}
catch (UnknownHostException ex) {
return false;
}
}
class SocketFetcher implements Runnable {
public void run() {
try {
}
catch (Exception e) {
}
}
return socket;
}
}
;
t.start();
try {
t.join(msecTimeout);
}
catch (InterruptedException ex) {
// It's probably not running at all
}
}
///////////////////////////////////////////////////////////////////////////
try {
}
catch (Exception e) {
return null;
}
}
///////////////////////////////////////////////////////////////////////////
/**
* This method returns the fully qualified name of the host. If
* the name can't be resolved (on windows if there isn't a domain specified), just
* host name is returned
*
* @throws UnknownHostException so it can be handled on a case by case basis
*/
// short-circuit out if user has reverse-DNS issues
return defaultHostname;
}
// look for full name
// check to see if ip returned or canonical hostname is different than hostname
// It is possible for dhcp connected computers to have an erroneous name returned
// that is created by the dhcp server. If that happens, return just the default hostname
// don't want IP or canonical hostname, this will cause a lot of problems for dhcp users
// get just plan host name instead
}
return hostname;
}
///////////////////////////////////////////////////////////////////////////
try {
return null;
}
}
catch (Exception e) {
return null;
}
}
///////////////////////////////////////////////////////////////////////////
try {
return null;
}
}
return ips;
}
catch (Exception e) {
return null;
}
}
///////////////////////////////////////////////////////////////////////////
return ip;
}
if (index >= 0) {
}
return ip;
}
///////////////////////////////////////////////////////////////////////////
try {
// possibilities: "1.1.1.1", "frodo/1.1.1.1", "frodo.foo.com/1.1.1.1"
//System.out.println("token: " + inum);
}
return bytes;
}
catch (NumberFormatException nfe) {
return null;
}
}
///////////////////////////////////////////////////////////////////////////
return false;
}
}
///////////////////////////////////////////////////////////////////////////
return false;
}
if (isLocalHost(ip)) {
return true;
}
return false;
}
return true;
}
}
return false;
}
///////////////////////////////////////////////////////////////////////////
}
/**
* Get the next free port (incrementing by 1)
* @param hostName The host name on which the port is to be obtained
* @param port The port number
* @return The next incremental port number or 0 if a port cannot be found.
*/
return port;
}
}
return 0;
}
/**
* Returns a random port in the specified range
* @param hostName The host on which the port is to be obtained.
* @param startingPort starting port in the range
* @param endingPort ending port in the range
* @return the new port or 0 if the range is invalid.
*/
int port = 0;
if (range > 0) {
while (true) {
break;
}
}
}
return port;
}
return true;
}
else {
return false;
}
}
try {
}
catch (NumberFormatException ex) {
return false;
}
}
///////////////////////////////////////////////////////////////////////////
return false;
}
return isPortFreeServer(portNumber);
}
else {
}
}
/**
* There are 4 possibilities when you want to setup a server socket on a port:
* 1. The port is already in use
* 2. The user does not have permission to open up shop on that port
* An example of (2) is a non-root user on UNIX trying to use port 80
* 3. The port number is not in the legal range
* 4. OK -- you can use it!
*
* @param portNumber
* @return one of the 4 possibilities for this port
*/
if (!isPortValid(portNumber))
return PortAvailability.illegalNumber;
// if we can setup a server socket on that port then it must be free.
if (isPortFreeServer(portNumber))
return PortAvailability.OK;
// can not setup a server socket and can not connect as a client
// that means we don't have permission...
return PortAvailability.noPermission;
}
return PortAvailability.inUse;
}
}
try {
// WBN - I have no idea why I'm messing with these streams!
// I lifted the code from installer. Apparently if you just
// open a socket on a free port and catch the exception something
// will go wrong in Windows.
// Feel free to change it if you know EXACTLY what you're doing
//If the host name is null, assume localhost
hostName = getHostName();
}
}
catch (Exception e) {
// Nobody is listening on this port
return true;
}
return false;
}
// check 3 different ip-port combinations.
// Amazingly I have seen all 3 possibilities -- so just checking on 0.0.0.0
// is not good enough.
// Usually it is the 0.0.0.0 -- but JMS (default:7676)
// only returns false from the "localhost":port combination.
// We want to be aggressively disqualifying ports rather than the other
// way around
try {
return false; // return immediately on "not-free"
return false; // return immediately on "not-free"
}
catch (Exception e) {
// If we can't get an IP address then we can't check
return false;
}
}
try {
return true;
}
catch (Exception e) {
return false;
}
}
/**
Gets a free port at the time of call to this method.
The logic leverages the built in java.net.ServerSocket implementation
which binds a server socket to a free port when instantiated with
a port <code> 0 </code>.
<P> Note that this method guarantees the availability of the port
only at the time of call. The method does not bind to this port.
<p> Checking for free port can fail for several reasons which may
indicate potential problems with the system. This method acknowledges
the fact and following is the general contract:
<li> Best effort is made to find a port which can be bound to. All
the exceptional conditions in the due course are considered SEVERE.
<li> If any exceptional condition is experienced, <code> 0 </code>
is returned, indicating that the method failed for some reasons and
the callers should take the corrective action. (The method need not
always throw an exception for this).
<li> Method is synchronized on this class.
@return integer depicting the free port number available at this time
0 otherwise.
*/
public static int getFreePort() {
int freePort = 0;
boolean portFound = false;
synchronized (NetUtils.class) {
try {
/*following call normally returns the free port,
to which the ServerSocket is bound. */
portFound = true;
}
catch (Exception e) {
//squelch the exception
}
finally {
if (!portFound) {
freePort = 0;
}
try {
if (serverSocket != null) {
if (!serverSocket.isClosed()) {
throw new Exception("local exception ...");
}
}
}
catch (Exception e) {
//squelch the exception
freePort = 0;
}
}
return freePort;
}
}
/**
* This method accepts a hostname and port #. It uses this information
* to attempt to connect to the port, send a test query, analyze the
* result to determine if the port is secure or unsecure (currently only
* http / https is supported).
* @param hostname - String name of the host where the connections has to be made
* @param port - int name of the port where the connections has to be made
* @return admin password
* @throws IOException if an error occurs during the connection
* @throws ConnectException if an error occurred while attempting to connect a socket to a remote address and port.
* @throws SocketTimeoutException if timeout(4s) expires before connecting
*/
public static boolean isSecurePort(String hostname, int port) throws IOException, ConnectException, SocketTimeoutException {
// Open the socket w/ a 4 second timeout
// Send an https query (w/ trailing http query)
// Get the result
int count = 0;
while (count < 20) {
// Wait up to 4 seconds
try {
break;
}
}
catch (InterruptedException ex) {
}
count++;
}
// Close the socket
// Determine protocol from result
// Can't read https response w/ OpenSSL (or equiv), so use as
// default & try to detect an http response.
boolean isSecure = true;
isSecure = false;
}
isSecure = false;
}
isSecure = false;
}
isSecure = false;
}
return isSecure;
}
/**
* There is sometimes a need for subclasses to know if a
* <code> local domain </code> is running. An example of such a command is
* change-master-password command. The stop-domain command also needs to
* know if a domain is running <i> without </i> having to provide user
* name and password on command line (this is the case when I own a domain
* that has non-default admin user and password) and want to stop it
* without providing it.
* <p>
* In such cases, we need to know if the domain is running and this method
* provides a way to do that.
*
* @return boolean indicating whether the server is running
*/
try {
return true;
}
return false;
}
finally {
try {
}
catch (IOException ex) {
}
}
}
}
/**
* convenience method for the local machine
*/
}
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
try {
if (theiradds[i].isLoopbackAddress()) {
return true;
}
return true;
}
}
}
}
catch (Exception e) {
}
return false;
}
///////////////////////////////////////////////////////////////////////////
}
/**
* This is the test query used to ping the server in an attempt to
* determine if it is secure or not.
*/
private static byte[] TEST_QUERY = new byte[]{
// The following SSL query is from nmap (http://www.insecure.org)
// This HTTPS request should work for most (all?) https servers
(byte) 0x16, (byte) 0x03, (byte) 0x00, (byte) 0x00, (byte) 'S', (byte) 0x01,
(byte) 0x00, (byte) 0x00, (byte) 'O', (byte) 0x03, (byte) 0x00, (byte) '?',
(byte) 'G', (byte) 0xd7, (byte) 0xf7, (byte) 0xba, (byte) ',', (byte) 0xee,
(byte) 0xea, (byte) 0xb2, (byte) '`', (byte) '~', (byte) 0xf3, (byte) 0x00,
(byte) 0xfd, (byte) 0x82, (byte) '{', (byte) 0xb9, (byte) 0xd5, (byte) 0x96,
(byte) 0xc8, (byte) 'w', (byte) 0x9b, (byte) 0xe6, (byte) 0xc4, (byte) 0xdb,
(byte) '<', (byte) '=', (byte) 0xdb, (byte) 'o', (byte) 0xef, (byte) 0x10,
(byte) 'n', (byte) 0x00, (byte) 0x00, (byte) '(', (byte) 0x00, (byte) 0x16,
(byte) 0x00, (byte) 0x13, (byte) 0x00, (byte) 0x0a, (byte) 0x00, (byte) 'f',
(byte) 0x00, (byte) 0x05, (byte) 0x00, (byte) 0x04, (byte) 0x00, (byte) 'e',
(byte) 0x00, (byte) 'd', (byte) 0x00, (byte) 'c', (byte) 0x00, (byte) 'b',
(byte) 0x00, (byte) 'a', (byte) 0x00, (byte) '`', (byte) 0x00, (byte) 0x15,
(byte) 0x00, (byte) 0x12, (byte) 0x00, (byte) 0x09, (byte) 0x00, (byte) 0x14,
(byte) 0x00, (byte) 0x11, (byte) 0x00, (byte) 0x08, (byte) 0x00, (byte) 0x06,
(byte) 0x00, (byte) 0x03, (byte) 0x01, (byte) 0x00,
// The following is a HTTP request, some HTTP servers won't
// respond unless the following is also sent
(byte) 'G', (byte) 'E', (byte) 'T', (byte) ' ', (byte) '/', (byte) ' ',
(byte) 'H', (byte) 'T', (byte) 'T', (byte) 'P', (byte) '/', (byte) '1',
(byte) '.', (byte) '0', (byte) '\n', (byte) '\n'
};
}