1d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen// Copyright (c) 2005 Brian Wellington (bwelling@xbill.org) 2d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 3d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpackage org.xbill.DNS.spi; 4d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 5d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.lang.reflect.InvocationHandler; 6d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.lang.reflect.Method; 7d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.net.InetAddress; 8d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.net.UnknownHostException; 9d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.StringTokenizer; 10d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 11d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.xbill.DNS.AAAARecord; 12d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.xbill.DNS.ARecord; 13d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.xbill.DNS.ExtendedResolver; 14d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.xbill.DNS.Lookup; 15d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.xbill.DNS.Name; 16d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.xbill.DNS.PTRRecord; 17d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.xbill.DNS.Record; 18d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.xbill.DNS.Resolver; 19d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.xbill.DNS.ReverseMap; 20d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.xbill.DNS.TextParseException; 21d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.xbill.DNS.Type; 22d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 23d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 24d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * This class implements a Name Service Provider, which Java can use 25d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * (starting with version 1.4), to perform DNS resolutions instead of using 26d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * the standard calls. 27d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <p> 28d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * This Name Service Provider uses dnsjava. 29d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <p> 30d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * To use this provider, you must set the following system property: 31d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <b>sun.net.spi.nameservice.provider.1=dns,dnsjava</b> 32d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 33d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @author Brian Wellington 34d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @author Paul Cowan (pwc21@yahoo.com) 35d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 36d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 37d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic class DNSJavaNameService implements InvocationHandler { 38d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 39d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate static final String nsProperty = "sun.net.spi.nameservice.nameservers"; 40d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate static final String domainProperty = "sun.net.spi.nameservice.domain"; 41d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate static final String v6Property = "java.net.preferIPv6Addresses"; 42d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 43d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate boolean preferV6 = false; 44d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 45d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 46d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates a DNSJavaNameService instance. 47d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <p> 48d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Uses the 49d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <b>sun.net.spi.nameservice.nameservers</b>, 50d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <b>sun.net.spi.nameservice.domain</b>, and 51d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <b>java.net.preferIPv6Addresses</b> properties for configuration. 52d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 53d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprotected 54d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenDNSJavaNameService() { 55d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String nameServers = System.getProperty(nsProperty); 56d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String domain = System.getProperty(domainProperty); 57d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String v6 = System.getProperty(v6Property); 58d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 59d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (nameServers != null) { 60d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen StringTokenizer st = new StringTokenizer(nameServers, ","); 61d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String [] servers = new String[st.countTokens()]; 62d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int n = 0; 63d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen while (st.hasMoreTokens()) 64d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen servers[n++] = st.nextToken(); 65d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 66d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Resolver res = new ExtendedResolver(servers); 67d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Lookup.setDefaultResolver(res); 68d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 69d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen catch (UnknownHostException e) { 70d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen System.err.println("DNSJavaNameService: invalid " + 71d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen nsProperty); 72d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 73d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 74d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 75d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (domain != null) { 76d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 77d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Lookup.setDefaultSearchPath(new String[] {domain}); 78d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 79d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen catch (TextParseException e) { 80d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen System.err.println("DNSJavaNameService: invalid " + 81d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen domainProperty); 82d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 83d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 84d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 85d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (v6 != null && v6.equalsIgnoreCase("true")) 86d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen preferV6 = true; 87d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 88d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 89d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 90d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic Object 91d7955ce24d294fb2014c59d11fca184471056f44Shuyi Cheninvoke(Object proxy, Method method, Object[] args) throws Throwable { 92d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 93d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (method.getName().equals("getHostByAddr")) { 94d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return this.getHostByAddr((byte[]) args[0]); 95d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else if (method.getName().equals("lookupAllHostAddr")) { 96d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen InetAddress[] addresses; 97d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen addresses = this.lookupAllHostAddr((String) args[0]); 98d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Class returnType = method.getReturnType(); 99d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (returnType.equals(InetAddress[].class)) { 100d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // method for Java >= 1.6 101d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return addresses; 102d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else if (returnType.equals(byte[][].class)) { 103d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // method for Java <= 1.5 104d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int naddrs = addresses.length; 105d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen byte [][] byteAddresses = new byte[naddrs][]; 106d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen byte [] addr; 107d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (int i = 0; i < naddrs; i++) { 108d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen addr = addresses[i].getAddress(); 109d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen byteAddresses[i] = addr; 110d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 111d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return byteAddresses; 112d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 113d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 114d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } catch (Throwable e) { 115d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen System.err.println("DNSJavaNameService: Unexpected error."); 116d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen e.printStackTrace(); 117d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw e; 118d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 119d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new IllegalArgumentException( 120d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen "Unknown function name or arguments."); 121d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 122d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 123d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 124d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Performs a forward DNS lookup for the host name. 125d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param host The host name to resolve. 126d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return All the ip addresses found for the host name. 127d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 128d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic InetAddress [] 129d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenlookupAllHostAddr(String host) throws UnknownHostException { 130d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Name name = null; 131d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 132d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try { 133d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen name = new Name(host); 134d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 135d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen catch (TextParseException e) { 136d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new UnknownHostException(host); 137d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 138d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 139d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Record [] records = null; 140d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (preferV6) 141d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen records = new Lookup(name, Type.AAAA).run(); 142d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (records == null) 143d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen records = new Lookup(name, Type.A).run(); 144d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (records == null && !preferV6) 145d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen records = new Lookup(name, Type.AAAA).run(); 146d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (records == null) 147d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new UnknownHostException(host); 148d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 149d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen InetAddress[] array = new InetAddress[records.length]; 150d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (int i = 0; i < records.length; i++) { 151d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Record record = records[i]; 152d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (records[i] instanceof ARecord) { 153d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ARecord a = (ARecord) records[i]; 154d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen array[i] = a.getAddress(); 155d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else { 156d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen AAAARecord aaaa = (AAAARecord) records[i]; 157d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen array[i] = aaaa.getAddress(); 158d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 159d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 160d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return array; 161d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 162d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 163d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 164d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Performs a reverse DNS lookup. 165d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param addr The ip address to lookup. 166d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The host name found for the ip address. 167d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 168d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic String 169d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetHostByAddr(byte [] addr) throws UnknownHostException { 170d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Name name = ReverseMap.fromAddress(InetAddress.getByAddress(addr)); 171d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Record [] records = new Lookup(name, Type.PTR).run(); 172d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (records == null) 173d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new UnknownHostException(); 174d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return ((PTRRecord) records[0]).getTarget().toString(); 175d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 176d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 177