/** * Returns the hostname for this address. * * <p>If there is a security manager, this method first calls its <code>checkConnect</code> method * with the hostname and <code>-1</code> as its arguments to see if the calling code is allowed to * know the hostname for this IP address, i.e., to connect to the host. If the operation is not * allowed, it will return the textual representation of the IP address. * * @return the host name for this IP address, or if the operation is not allowed by the security * check, the textual representation of the IP address. * @param check make security check if true * @see SecurityManager#checkConnect */ private static String getHostFromNameService(InetAddress addr, boolean check) { String host = null; for (NameService nameService : nameServices) { try { // first lookup the hostname host = nameService.getHostByAddr(addr.getAddress()); /* check to see if calling code is allowed to know * the hostname for this IP address, ie, connect to the host */ if (check) { SecurityManager sec = System.getSecurityManager(); if (sec != null) { sec.checkConnect(host, -1); } } /* now get all the IP addresses for this hostname, * and make sure one of them matches the original IP * address. We do this to try and prevent spoofing. */ InetAddress[] arr = InetAddress.getAllByName0(host, check); boolean ok = false; if (arr != null) { for (int i = 0; !ok && i < arr.length; i++) { ok = addr.equals(arr[i]); } } // XXX: if it looks a spoof just return the address? if (!ok) { host = addr.getHostAddress(); return host; } break; } catch (SecurityException e) { host = addr.getHostAddress(); break; } catch (UnknownHostException e) { host = addr.getHostAddress(); // let next provider resolve the hostname } } return host; }
private static Object getAddressFromNameService(String host, InetAddress reqAddr) throws UnknownHostException { Object obj = null; boolean success = false; UnknownHostException ex = null; // Check whether the host is in the lookupTable. // 1) If the host isn't in the lookupTable when // checkLookupTable() is called, checkLookupTable() // would add the host in the lookupTable and // return null. So we will do the lookup. // 2) If the host is in the lookupTable when // checkLookupTable() is called, the current thread // would be blocked until the host is removed // from the lookupTable. Then this thread // should try to look up the addressCache. // i) if it found the address in the // addressCache, checkLookupTable() would // return the address. // ii) if it didn't find the address in the // addressCache for any reason, // it should add the host in the // lookupTable and return null so the // following code would do a lookup itself. if ((obj = checkLookupTable(host)) == null) { // This is the first thread which looks up the address // this host or the cache entry for this host has been // expired so this thread should do the lookup. for (NameService nameService : nameServices) { try { /* * Do not put the call to lookup() inside the * constructor. if you do you will still be * allocating space when the lookup fails. */ obj = nameService.lookupAllHostAddr(host); success = true; break; } catch (UnknownHostException uhe) { if (host.equalsIgnoreCase("localhost")) { InetAddress[] local = new InetAddress[] {impl.loopbackAddress()}; obj = local; success = true; break; } else { obj = unknown_array; success = false; ex = uhe; } } } // More to do? InetAddress[] addrs = (InetAddress[]) obj; if (reqAddr != null && addrs.length > 1 && !addrs[0].equals(reqAddr)) { // Find it? int i = 1; for (; i < addrs.length; i++) { if (addrs[i].equals(reqAddr)) { break; } } // Rotate if (i < addrs.length) { InetAddress tmp, tmp2 = reqAddr; for (int j = 0; j < i; j++) { tmp = addrs[j]; addrs[j] = tmp2; tmp2 = tmp; } addrs[i] = tmp2; } } // Cache the address. cacheAddress(host, obj, success); // Delete the host from the lookupTable, and // notify all threads waiting for the monitor // for lookupTable. updateLookupTable(host); if (!success && ex != null) throw ex; } return obj; }