jdk/src/java.base/share/classes/java/net/InetAddress.java
changeset 36967 d041d2e80712
parent 33675 7d9d372a41df
child 37363 329dba26ffd2
equal deleted inserted replaced
36966:4209c9e19c45 36967:d041d2e80712
     1 /*
     1 /*
     2  * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    28 import java.util.NavigableSet;
    28 import java.util.NavigableSet;
    29 import java.util.Iterator;
    29 import java.util.Iterator;
    30 import java.util.List;
    30 import java.util.List;
    31 import java.util.ArrayList;
    31 import java.util.ArrayList;
    32 import java.util.Objects;
    32 import java.util.Objects;
    33 import java.util.ServiceLoader;
    33 import java.util.Scanner;
    34 import java.security.AccessController;
    34 import java.security.AccessController;
       
    35 import java.io.File;
       
    36 import java.io.FileNotFoundException;
    35 import java.io.ObjectStreamException;
    37 import java.io.ObjectStreamException;
    36 import java.io.ObjectStreamField;
    38 import java.io.ObjectStreamField;
    37 import java.io.IOException;
    39 import java.io.IOException;
    38 import java.io.ObjectInputStream;
    40 import java.io.ObjectInputStream;
    39 import java.io.ObjectInputStream.GetField;
    41 import java.io.ObjectInputStream.GetField;
    47 import jdk.internal.misc.JavaNetInetAddressAccess;
    49 import jdk.internal.misc.JavaNetInetAddressAccess;
    48 import jdk.internal.misc.SharedSecrets;
    50 import jdk.internal.misc.SharedSecrets;
    49 import sun.security.action.*;
    51 import sun.security.action.*;
    50 import sun.net.InetAddressCachePolicy;
    52 import sun.net.InetAddressCachePolicy;
    51 import sun.net.util.IPAddressUtil;
    53 import sun.net.util.IPAddressUtil;
    52 import sun.net.spi.nameservice.*;
       
    53 
    54 
    54 /**
    55 /**
    55  * This class represents an Internet Protocol (IP) address.
    56  * This class represents an Internet Protocol (IP) address.
    56  *
    57  *
    57  * <p> An IP address is either a 32-bit or 128-bit unsigned number
    58  * <p> An IP address is either a 32-bit or 128-bit unsigned number
   205     static final int IPv6 = 2;
   206     static final int IPv6 = 2;
   206 
   207 
   207     /* Specify address family preference */
   208     /* Specify address family preference */
   208     static transient boolean preferIPv6Address = false;
   209     static transient boolean preferIPv6Address = false;
   209 
   210 
       
   211 
   210     static class InetAddressHolder {
   212     static class InetAddressHolder {
   211         /**
   213         /**
   212          * Reserve the original application specified hostname.
   214          * Reserve the original application specified hostname.
   213          *
   215          *
   214          * The original hostname is useful for domain-based endpoint
   216          * The original hostname is useful for domain-based endpoint
   277     InetAddressHolder holder() {
   279     InetAddressHolder holder() {
   278         return holder;
   280         return holder;
   279     }
   281     }
   280 
   282 
   281     /* Used to store the name service provider */
   283     /* Used to store the name service provider */
   282     private static List<NameService> nameServices = null;
   284     private static transient NameService nameService = null;
   283 
   285 
   284     /* Used to store the best available hostname */
   286     /* Used to store the best available hostname */
   285     private transient String canonicalHostName = null;
   287     private transient String canonicalHostName = null;
   286 
   288 
   287     /** use serialVersionUID from JDK 1.0.2 for interoperability */
   289     /** use serialVersionUID from JDK 1.0.2 for interoperability */
   621      *
   623      *
   622      * @see SecurityManager#checkConnect
   624      * @see SecurityManager#checkConnect
   623      */
   625      */
   624     private static String getHostFromNameService(InetAddress addr, boolean check) {
   626     private static String getHostFromNameService(InetAddress addr, boolean check) {
   625         String host = null;
   627         String host = null;
   626         for (NameService nameService : nameServices) {
       
   627             try {
   628             try {
   628                 // first lookup the hostname
   629                 // first lookup the hostname
   629                 host = nameService.getHostByAddr(addr.getAddress());
   630                 host = nameService.getHostByAddr(addr.getAddress());
   630 
   631 
   631                 /* check to see if calling code is allowed to know
   632                 /* check to see if calling code is allowed to know
   655                 //XXX: if it looks a spoof just return the address?
   656                 //XXX: if it looks a spoof just return the address?
   656                 if (!ok) {
   657                 if (!ok) {
   657                     host = addr.getHostAddress();
   658                     host = addr.getHostAddress();
   658                     return host;
   659                     return host;
   659                 }
   660                 }
   660 
       
   661                 break;
       
   662 
       
   663             } catch (SecurityException e) {
   661             } catch (SecurityException e) {
   664                 host = addr.getHostAddress();
   662                 host = addr.getHostAddress();
   665                 break;
       
   666             } catch (UnknownHostException e) {
   663             } catch (UnknownHostException e) {
   667                 host = addr.getHostAddress();
   664                 host = addr.getHostAddress();
   668                 // let next provider resolve the hostname
   665                 // let next provider resolve the hostname
   669             }
   666             }
   670         }
       
   671 
       
   672         return host;
   667         return host;
   673     }
   668     }
   674 
   669 
   675     /**
   670     /**
   676      * Returns the raw IP address of this {@code InetAddress}
   671      * Returns the raw IP address of this {@code InetAddress}
   858             // but outside of synchronized block to avoid any chance of dead-locking
   853             // but outside of synchronized block to avoid any chance of dead-locking
   859             return addresses.get();
   854             return addresses.get();
   860         }
   855         }
   861     }
   856     }
   862 
   857 
   863     static InetAddressImpl  impl;
   858     /**
   864 
   859      * NameService provides host and address lookup service
   865     private static NameService createNSProvider(String provider) {
   860      *
   866         if (provider == null)
   861      * @since 9
   867             return null;
   862      */
   868 
   863     private interface NameService {
   869         NameService nameService = null;
   864 
   870         if (provider.equals("default")) {
   865         /**
   871             // initialize the default name service
   866          * Lookup a host mapping by name. Retrieve the IP addresses
   872             nameService = new NameService() {
   867          * associated with a host
       
   868          *
       
   869          * @param host the specified hostname
       
   870          * @return array of IP addresses for the requested host
       
   871          * @throws UnknownHostException
       
   872          *             if no IP address for the {@code host} could be found
       
   873          */
       
   874         InetAddress[] lookupAllHostAddr(String host)
       
   875                 throws UnknownHostException;
       
   876 
       
   877         /**
       
   878          * Lookup the host corresponding to the IP address provided
       
   879          *
       
   880          * @param addr byte array representing an IP address
       
   881          * @return {@code String} representing the host name mapping
       
   882          * @throws UnknownHostException
       
   883          *             if no host found for the specified IP address
       
   884          */
       
   885         String getHostByAddr(byte[] addr) throws UnknownHostException;
       
   886 
       
   887     }
       
   888 
       
   889     /**
       
   890      * The default NameService implementation, which delegates to the underlying
       
   891      * OS network libraries to resolve host address mappings.
       
   892      *
       
   893      * @since 9
       
   894      */
       
   895     private static final class PlatformNameService implements NameService {
       
   896 
   873                 public InetAddress[] lookupAllHostAddr(String host)
   897                 public InetAddress[] lookupAllHostAddr(String host)
   874                     throws UnknownHostException {
   898                     throws UnknownHostException {
       
   899 
   875                     return impl.lookupAllHostAddr(host);
   900                     return impl.lookupAllHostAddr(host);
   876                 }
   901 
   877                 public String getHostByAddr(byte[] addr)
   902                             }
   878                     throws UnknownHostException {
   903 
   879                     return impl.getHostByAddr(addr);
   904         public String getHostByAddr(byte[] addr) throws UnknownHostException {
   880                 }
   905 
   881             };
   906             return impl.getHostByAddr(addr);
   882         } else {
   907 
   883             final String providerName = provider;
   908         }
   884             try {
   909 
   885                 nameService = java.security.AccessController.doPrivileged(
   910     }
   886                     new java.security.PrivilegedExceptionAction<>() {
   911 
   887                         public NameService run() {
   912     /**
   888                             Iterator<NameServiceDescriptor> itr =
   913      * The HostsFileNameService provides host address mapping
   889                                 ServiceLoader.load(NameServiceDescriptor.class)
   914      * by reading the entries in a hosts file, which is specified by
   890                                     .iterator();
   915      * {@code jdk.net.hosts.file} system property
   891                             while (itr.hasNext()) {
   916      *
   892                                 NameServiceDescriptor nsd = itr.next();
   917      * <p>The file format is that which corresponds with the /etc/hosts file
   893                                 if (providerName.
   918      * IP Address host alias list.
   894                                     equalsIgnoreCase(nsd.getType()+","
   919      *
   895                                         +nsd.getProviderName())) {
   920      * <p>When the file lookup is enabled it replaces the default NameService
   896                                     try {
   921      * implementation
   897                                         return nsd.createNameService();
   922      *
   898                                     } catch (Exception e) {
   923      * @since 9
   899                                         e.printStackTrace();
   924      */
   900                                         System.err.println(
   925     private static final class HostsFileNameService implements NameService {
   901                                             "Cannot create name service:"
   926 
   902                                              +providerName+": " + e);
   927         private final String hostsFile;
   903                                     }
   928 
       
   929         public HostsFileNameService (String hostsFileName) {
       
   930             this.hostsFile = hostsFileName;
       
   931         }
       
   932 
       
   933         private  String addrToString(byte addr[]) {
       
   934           String stringifiedAddress = null;
       
   935 
       
   936             if (addr.length == Inet4Address.INADDRSZ) {
       
   937                 stringifiedAddress = Inet4Address.numericToTextFormat(addr);
       
   938             } else { // treat as an IPV6 jobby
       
   939                 byte[] newAddr
       
   940                     = IPAddressUtil.convertFromIPv4MappedAddress(addr);
       
   941                 if (newAddr != null) {
       
   942                    stringifiedAddress = Inet4Address.numericToTextFormat(addr);
       
   943                 } else {
       
   944                     stringifiedAddress = Inet6Address.numericToTextFormat(addr);
       
   945                 }
       
   946             }
       
   947             return stringifiedAddress;
       
   948         }
       
   949 
       
   950         /**
       
   951          * Lookup the host name  corresponding to the IP address provided.
       
   952          * Search the configured host file a host name corresponding to
       
   953          * the specified IP address.
       
   954          *
       
   955          * @param addr byte array representing an IP address
       
   956          * @return {@code String} representing the host name mapping
       
   957          * @throws UnknownHostException
       
   958          *             if no host found for the specified IP address
       
   959          */
       
   960         @Override
       
   961         public String getHostByAddr(byte[] addr) throws UnknownHostException {
       
   962             String hostEntry;
       
   963             String host = null;
       
   964 
       
   965             String addrString = addrToString(addr);
       
   966             try (Scanner hostsFileScanner = new Scanner(new File(hostsFile), "UTF-8")) {
       
   967                 while (hostsFileScanner.hasNextLine()) {
       
   968                     hostEntry = hostsFileScanner.nextLine();
       
   969                     if (!hostEntry.startsWith("#")) {
       
   970                         hostEntry = removeComments(hostEntry);
       
   971                         if (hostEntry.contains(addrString)) {
       
   972                             host = extractHost(hostEntry, addrString);
       
   973                             if (host != null) {
       
   974                                 break;
       
   975                             }
       
   976                         }
       
   977                     }
       
   978                 }
       
   979             } catch (FileNotFoundException e) {
       
   980                 throw new UnknownHostException("Unable to resolve address "
       
   981                         + addrString + " as hosts file " + hostsFile
       
   982                         + " not found ");
       
   983             }
       
   984 
       
   985             if ((host == null) || (host.equals("")) || (host.equals(" "))) {
       
   986                 throw new UnknownHostException("Requested address "
       
   987                         + addrString
       
   988                         + " resolves to an invalid entry in hosts file "
       
   989                         + hostsFile);
       
   990             }
       
   991             return host;
       
   992         }
       
   993 
       
   994 
       
   995         /**
       
   996          * <p>Lookup a host mapping by name. Retrieve the IP addresses
       
   997          * associated with a host.
       
   998          *
       
   999          * <p>Search the configured hosts file for the addresses assocaited with
       
  1000          * with the specified host name.
       
  1001          *
       
  1002          * @param host the specified hostname
       
  1003          * @return array of IP addresses for the requested host
       
  1004          * @throws UnknownHostException
       
  1005          *             if no IP address for the {@code host} could be found
       
  1006          */
       
  1007 
       
  1008         public InetAddress[] lookupAllHostAddr(String host)
       
  1009                 throws UnknownHostException {
       
  1010             String hostEntry;
       
  1011             String addrStr = null;
       
  1012             InetAddress[] res = null;
       
  1013             byte addr[] = new byte[4];
       
  1014             ArrayList<InetAddress> inetAddresses = null;
       
  1015 
       
  1016             // lookup the file and create a list InetAddress for the specfied host
       
  1017             try (Scanner hostsFileScanner = new Scanner(new File(hostsFile), "UTF-8")) {
       
  1018                 while (hostsFileScanner.hasNextLine()) {
       
  1019                     hostEntry = hostsFileScanner.nextLine();
       
  1020                     if (!hostEntry.startsWith("#")) {
       
  1021                         hostEntry = removeComments(hostEntry);
       
  1022                         if (hostEntry.contains(host)) {
       
  1023                             addrStr = extractHostAddr(hostEntry, host);
       
  1024                             if ((addrStr != null) && (!addrStr.equals(""))) {
       
  1025                                 addr = createAddressByteArray(addrStr);
       
  1026                                 if (inetAddresses == null) {
       
  1027                                     inetAddresses = new ArrayList<>(1);
       
  1028                                 }
       
  1029                                 if (addr != null) {
       
  1030                                     inetAddresses.add(InetAddress.getByAddress(host, addr));
   904                                 }
  1031                                 }
   905                             }
  1032                             }
   906 
       
   907                             return null;
       
   908                         }
  1033                         }
   909                     }
  1034                     }
   910                 );
  1035                 }
   911             } catch (java.security.PrivilegedActionException e) {
  1036             } catch (FileNotFoundException e) {
   912             }
  1037                 throw new UnknownHostException("Unable to resolve host " + host
   913         }
  1038                         + " as hosts file " + hostsFile + " not found ");
   914 
  1039             }
   915         return nameService;
  1040 
   916     }
  1041             if (inetAddresses != null) {
       
  1042                 res = inetAddresses.toArray(new InetAddress[inetAddresses.size()]);
       
  1043             } else {
       
  1044                 throw new UnknownHostException("Unable to resolve host " + host
       
  1045                         + " in hosts file " + hostsFile);
       
  1046             }
       
  1047             return res;
       
  1048         }
       
  1049 
       
  1050         private String removeComments(String hostsEntry) {
       
  1051             String filteredEntry = hostsEntry;
       
  1052             int hashIndex;
       
  1053 
       
  1054             if ((hashIndex = hostsEntry.indexOf("#")) != -1) {
       
  1055                 filteredEntry = hostsEntry.substring(0, hashIndex);
       
  1056             }
       
  1057             return filteredEntry;
       
  1058         }
       
  1059 
       
  1060         private byte [] createAddressByteArray(String addrStr) {
       
  1061             byte[] addrArray;
       
  1062             // check if IPV4 address - most likely
       
  1063             addrArray = IPAddressUtil.textToNumericFormatV4(addrStr);
       
  1064             if (addrArray == null) {
       
  1065                 addrArray = IPAddressUtil.textToNumericFormatV6(addrStr);
       
  1066             }
       
  1067             return addrArray;
       
  1068         }
       
  1069 
       
  1070         /** host to ip address mapping */
       
  1071         private String extractHostAddr(String hostEntry, String host) {
       
  1072             String[] mapping = hostEntry.split("\\s+");
       
  1073             String hostAddr = null;
       
  1074 
       
  1075             if (mapping.length >= 2) {
       
  1076                 // look at the host aliases
       
  1077                 for (int i = 1; i < mapping.length; i++) {
       
  1078                     if (mapping[i].equalsIgnoreCase(host)) {
       
  1079                         hostAddr = mapping[0];
       
  1080                     }
       
  1081                 }
       
  1082             }
       
  1083             return hostAddr;
       
  1084         }
       
  1085 
       
  1086         /**
       
  1087          * IP Address to host mapping
       
  1088          * use first host alias in list
       
  1089          */
       
  1090         private String extractHost(String hostEntry, String addrString) {
       
  1091             String[] mapping = hostEntry.split("\\s+");
       
  1092             String host = null;
       
  1093 
       
  1094             if (mapping.length >= 2) {
       
  1095                 if (mapping[0].equalsIgnoreCase(addrString)) {
       
  1096                     host = mapping[1];
       
  1097                 }
       
  1098             }
       
  1099             return host;
       
  1100         }
       
  1101     }
       
  1102 
       
  1103     static final InetAddressImpl  impl;
   917 
  1104 
   918     static {
  1105     static {
   919         // create the impl
  1106         // create the impl
   920         impl = InetAddressImplFactory.create();
  1107         impl = InetAddressImplFactory.create();
   921 
  1108 
   922         // get name service if provided and requested
  1109         // create name service
   923         String provider = null;;
  1110         nameService = createNameService();
   924         String propPrefix = "sun.net.spi.nameservice.provider.";
  1111         }
   925         int n = 1;
  1112 
   926         nameServices = new ArrayList<>();
  1113     /**
   927         provider = AccessController.doPrivileged(
  1114      * Create an instance of the NameService interface based on
   928                 new GetPropertyAction(propPrefix + n));
  1115      * the setting of the {@codejdk.net.hosts.file} system property.
   929         while (provider != null) {
  1116      *
   930             NameService ns = createNSProvider(provider);
  1117      * <p>The default NameService is the PlatformNameService, which typically
   931             if (ns != null)
  1118      * delegates name and address resolution calls to the underlying
   932                 nameServices.add(ns);
  1119      * OS network libraries.
   933 
  1120      *
   934             n++;
  1121      * <p> A HostsFileNameService is created if the {@code jdk.net.hosts.file}
   935             provider = AccessController.doPrivileged(
  1122      * system property is set. If the specified file doesn't exist, the name or
   936                     new GetPropertyAction(propPrefix + n));
  1123      * address lookup will result in an UnknownHostException. Thus, non existent
   937         }
  1124      * hosts file is handled as if the file is empty.
   938 
  1125      *
   939         // if not designate any name services provider,
  1126      * @return a NameService
   940         // create a default one
  1127      */
   941         if (nameServices.size() == 0) {
  1128     private static NameService createNameService() {
   942             NameService ns = createNSProvider("default");
  1129 
   943             nameServices.add(ns);
  1130         String hostsFileName = AccessController
   944         }
  1131                 .doPrivileged(new GetPropertyAction("jdk.net.hosts.file"));
       
  1132         NameService theNameService;
       
  1133         if (hostsFileName != null) {
       
  1134             theNameService = new HostsFileNameService(hostsFileName);
       
  1135         } else {
       
  1136             theNameService = new PlatformNameService();
       
  1137         }
       
  1138         return theNameService;
   945     }
  1139     }
   946 
  1140 
   947     /**
  1141     /**
   948      * Creates an InetAddress based on the provided host name and IP address.
  1142      * Creates an InetAddress based on the provided host name and IP address.
   949      * No name service is checked for the validity of the address.
  1143      * No name service is checked for the validity of the address.
  1284         throws UnknownHostException
  1478         throws UnknownHostException
  1285     {
  1479     {
  1286         InetAddress[] addresses = null;
  1480         InetAddress[] addresses = null;
  1287         UnknownHostException ex = null;
  1481         UnknownHostException ex = null;
  1288 
  1482 
  1289         for (NameService nameService : nameServices) {
       
  1290             try {
  1483             try {
  1291                 addresses = nameService.lookupAllHostAddr(host);
  1484                 addresses = nameService.lookupAllHostAddr(host);
  1292                 break;
       
  1293             } catch (UnknownHostException uhe) {
  1485             } catch (UnknownHostException uhe) {
  1294                 if (host.equalsIgnoreCase("localhost")) {
  1486                 if (host.equalsIgnoreCase("localhost")) {
  1295                     addresses = new InetAddress[] { impl.loopbackAddress() };
  1487                     addresses = new InetAddress[] { impl.loopbackAddress() };
  1296                     break;
       
  1297                 }
  1488                 }
  1298                 else {
  1489                 else {
  1299                     ex = uhe;
  1490                     ex = uhe;
  1300                 }
  1491                 }
  1301             }
  1492             }
  1302         }
       
  1303 
  1493 
  1304         if (addresses == null) {
  1494         if (addresses == null) {
  1305             throw ex == null ? new UnknownHostException(host) : ex;
  1495             throw ex == null ? new UnknownHostException(host) : ex;
  1306         }
  1496         }
  1307 
  1497