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