diff options
author | Shuyi Chen <shuyichen@google.com> | 2013-05-22 14:51:55 -0700 |
---|---|---|
committer | Shuyi Chen <shuyichen@google.com> | 2013-05-22 17:19:30 -0700 |
commit | d7955ce24d294fb2014c59d11fca184471056f44 (patch) | |
tree | e260500b0b7639127038495d46a0ad6dcbb6d96c /src/org/xbill/DNS/ResolverConfig.java | |
parent | 8f4ce9ea0de51fee918bffe19c434612d6bbb2d7 (diff) | |
download | smack-d7955ce24d294fb2014c59d11fca184471056f44.tar.gz |
Add android smack source.HEADandroid-wear-5.0.0_r1android-sdk-4.4.2_r1.0.1android-sdk-4.4.2_r1android-l-preview_r2android-cts-5.1_r9android-cts-5.1_r8android-cts-5.1_r7android-cts-5.1_r6android-cts-5.1_r5android-cts-5.1_r4android-cts-5.1_r3android-cts-5.1_r28android-cts-5.1_r27android-cts-5.1_r26android-cts-5.1_r25android-cts-5.1_r24android-cts-5.1_r23android-cts-5.1_r22android-cts-5.1_r21android-cts-5.1_r20android-cts-5.1_r2android-cts-5.1_r19android-cts-5.1_r18android-cts-5.1_r17android-cts-5.1_r16android-cts-5.1_r15android-cts-5.1_r14android-cts-5.1_r13android-cts-5.1_r10android-cts-5.1_r1android-cts-5.0_r9android-cts-5.0_r8android-cts-5.0_r7android-cts-5.0_r6android-cts-5.0_r5android-cts-5.0_r4android-cts-5.0_r3android-cts-4.4_r4android-cts-4.4_r1android-5.1.1_r9android-5.1.1_r8android-5.1.1_r7android-5.1.1_r6android-5.1.1_r5android-5.1.1_r4android-5.1.1_r38android-5.1.1_r37android-5.1.1_r36android-5.1.1_r35android-5.1.1_r34android-5.1.1_r33android-5.1.1_r30android-5.1.1_r3android-5.1.1_r29android-5.1.1_r28android-5.1.1_r26android-5.1.1_r25android-5.1.1_r24android-5.1.1_r23android-5.1.1_r22android-5.1.1_r20android-5.1.1_r2android-5.1.1_r19android-5.1.1_r18android-5.1.1_r17android-5.1.1_r16android-5.1.1_r15android-5.1.1_r14android-5.1.1_r13android-5.1.1_r12android-5.1.1_r10android-5.1.1_r1android-5.1.0_r5android-5.1.0_r4android-5.1.0_r3android-5.1.0_r1android-5.0.2_r3android-5.0.2_r1android-5.0.1_r1android-5.0.0_r7android-5.0.0_r6android-5.0.0_r5.1android-5.0.0_r5android-5.0.0_r4android-5.0.0_r3android-5.0.0_r2android-5.0.0_r1android-4.4w_r1android-4.4_r1.2.0.1android-4.4_r1.2android-4.4_r1.1.0.1android-4.4_r1.1android-4.4_r1.0.1android-4.4_r1android-4.4_r0.9android-4.4_r0.8android-4.4_r0.7android-4.4.4_r2.0.1android-4.4.4_r2android-4.4.4_r1.0.1android-4.4.4_r1android-4.4.3_r1.1.0.1android-4.4.3_r1.1android-4.4.3_r1.0.1android-4.4.3_r1android-4.4.2_r2.0.1android-4.4.2_r2android-4.4.2_r1.0.1android-4.4.2_r1android-4.4.1_r1.0.1android-4.4.1_r1android-4.3_r3.1android-4.3_r3android-4.3_r2.3android-4.3_r2.2android-4.3_r2.1android-4.3_r2android-4.3_r1.1android-4.3_r1android-4.3_r0.9.1android-4.3_r0.9android-4.3.1_r1tools_r22.2mastermainlollipop-wear-releaselollipop-releaselollipop-mr1-wfc-releaselollipop-mr1-releaselollipop-mr1-fi-releaselollipop-mr1-devlollipop-mr1-cts-releaselollipop-devlollipop-cts-releasel-previewkitkat-wearkitkat-releasekitkat-mr2.2-releasekitkat-mr2.1-releasekitkat-mr2-releasekitkat-mr1.1-releasekitkat-mr1-releasekitkat-devkitkat-cts-releasekitkat-cts-devjb-mr2.0.0-releasejb-mr2.0-releasejb-mr2-releasejb-mr2-devidea133-weekly-releaseidea133
Change-Id: I49ce97136c17173c4ae3965c694af6e7bc49897d
Diffstat (limited to 'src/org/xbill/DNS/ResolverConfig.java')
-rw-r--r-- | src/org/xbill/DNS/ResolverConfig.java | 509 |
1 files changed, 509 insertions, 0 deletions
diff --git a/src/org/xbill/DNS/ResolverConfig.java b/src/org/xbill/DNS/ResolverConfig.java new file mode 100644 index 0000000..7b09daf --- /dev/null +++ b/src/org/xbill/DNS/ResolverConfig.java @@ -0,0 +1,509 @@ +// Copyright (c) 1999-2004 Brian Wellington (bwelling@xbill.org) + +package org.xbill.DNS; + +import java.io.*; +import java.lang.reflect.*; +import java.util.*; + +/** + * A class that tries to locate name servers and the search path to + * be appended to unqualified names. + * + * The following are attempted, in order, until one succeeds. + * <UL> + * <LI>The properties 'dns.server' and 'dns.search' (comma delimited lists) + * are checked. The servers can either be IP addresses or hostnames + * (which are resolved using Java's built in DNS support). + * <LI>The sun.net.dns.ResolverConfiguration class is queried. + * <LI>On Unix, /etc/resolv.conf is parsed. + * <LI>On Windows, ipconfig/winipcfg is called and its output parsed. This + * may fail for non-English versions on Windows. + * <LI>"localhost" is used as the nameserver, and the search path is empty. + * </UL> + * + * These routines will be called internally when creating Resolvers/Lookups + * without explicitly specifying server names, and can also be called + * directly if desired. + * + * @author Brian Wellington + * @author <a href="mailto:yannick@meudal.net">Yannick Meudal</a> + * @author <a href="mailto:arnt@gulbrandsen.priv.no">Arnt Gulbrandsen</a> + */ + +public class ResolverConfig { + +private String [] servers = null; +private Name [] searchlist = null; +private int ndots = -1; + +private static ResolverConfig currentConfig; + +static { + refresh(); +} + +public +ResolverConfig() { + if (findProperty()) + return; + if (findSunJVM()) + return; + if (servers == null || searchlist == null) { + String OS = System.getProperty("os.name"); + String vendor = System.getProperty("java.vendor"); + if (OS.indexOf("Windows") != -1) { + if (OS.indexOf("95") != -1 || + OS.indexOf("98") != -1 || + OS.indexOf("ME") != -1) + find95(); + else + findNT(); + } else if (OS.indexOf("NetWare") != -1) { + findNetware(); + } else if (vendor.indexOf("Android") != -1) { + findAndroid(); + } else { + findUnix(); + } + } +} + +private void +addServer(String server, List list) { + if (list.contains(server)) + return; + if (Options.check("verbose")) + System.out.println("adding server " + server); + list.add(server); +} + +private void +addSearch(String search, List list) { + Name name; + if (Options.check("verbose")) + System.out.println("adding search " + search); + try { + name = Name.fromString(search, Name.root); + } + catch (TextParseException e) { + return; + } + if (list.contains(name)) + return; + list.add(name); +} + +private int +parseNdots(String token) { + token = token.substring(6); + try { + int ndots = Integer.parseInt(token); + if (ndots >= 0) { + if (Options.check("verbose")) + System.out.println("setting ndots " + token); + return ndots; + } + } + catch (NumberFormatException e) { + } + return -1; +} + +private void +configureFromLists(List lserver, List lsearch) { + if (servers == null && lserver.size() > 0) + servers = (String []) lserver.toArray(new String[0]); + if (searchlist == null && lsearch.size() > 0) + searchlist = (Name []) lsearch.toArray(new Name[0]); +} + +private void +configureNdots(int lndots) { + if (ndots < 0 && lndots > 0) + ndots = lndots; +} + +/** + * Looks in the system properties to find servers and a search path. + * Servers are defined by dns.server=server1,server2... + * The search path is defined by dns.search=domain1,domain2... + */ +private boolean +findProperty() { + String prop; + List lserver = new ArrayList(0); + List lsearch = new ArrayList(0); + StringTokenizer st; + + prop = System.getProperty("dns.server"); + if (prop != null) { + st = new StringTokenizer(prop, ","); + while (st.hasMoreTokens()) + addServer(st.nextToken(), lserver); + } + + prop = System.getProperty("dns.search"); + if (prop != null) { + st = new StringTokenizer(prop, ","); + while (st.hasMoreTokens()) + addSearch(st.nextToken(), lsearch); + } + configureFromLists(lserver, lsearch); + return (servers != null && searchlist != null); +} + +/** + * Uses the undocumented Sun DNS implementation to determine the configuration. + * This doesn't work or even compile with all JVMs (gcj, for example). + */ +private boolean +findSunJVM() { + List lserver = new ArrayList(0); + List lserver_tmp; + List lsearch = new ArrayList(0); + List lsearch_tmp; + + try { + Class [] noClasses = new Class[0]; + Object [] noObjects = new Object[0]; + String resConfName = "sun.net.dns.ResolverConfiguration"; + Class resConfClass = Class.forName(resConfName); + Object resConf; + + // ResolverConfiguration resConf = ResolverConfiguration.open(); + Method open = resConfClass.getDeclaredMethod("open", noClasses); + resConf = open.invoke(null, noObjects); + + // lserver_tmp = resConf.nameservers(); + Method nameservers = resConfClass.getMethod("nameservers", + noClasses); + lserver_tmp = (List) nameservers.invoke(resConf, noObjects); + + // lsearch_tmp = resConf.searchlist(); + Method searchlist = resConfClass.getMethod("searchlist", + noClasses); + lsearch_tmp = (List) searchlist.invoke(resConf, noObjects); + } + catch (Exception e) { + return false; + } + + if (lserver_tmp.size() == 0) + return false; + + if (lserver_tmp.size() > 0) { + Iterator it = lserver_tmp.iterator(); + while (it.hasNext()) + addServer((String) it.next(), lserver); + } + + if (lsearch_tmp.size() > 0) { + Iterator it = lsearch_tmp.iterator(); + while (it.hasNext()) + addSearch((String) it.next(), lsearch); + } + configureFromLists(lserver, lsearch); + return true; +} + +/** + * Looks in /etc/resolv.conf to find servers and a search path. + * "nameserver" lines specify servers. "domain" and "search" lines + * define the search path. + */ +private void +findResolvConf(String file) { + InputStream in = null; + try { + in = new FileInputStream(file); + } + catch (FileNotFoundException e) { + return; + } + InputStreamReader isr = new InputStreamReader(in); + BufferedReader br = new BufferedReader(isr); + List lserver = new ArrayList(0); + List lsearch = new ArrayList(0); + int lndots = -1; + try { + String line; + while ((line = br.readLine()) != null) { + if (line.startsWith("nameserver")) { + StringTokenizer st = new StringTokenizer(line); + st.nextToken(); /* skip nameserver */ + addServer(st.nextToken(), lserver); + } + else if (line.startsWith("domain")) { + StringTokenizer st = new StringTokenizer(line); + st.nextToken(); /* skip domain */ + if (!st.hasMoreTokens()) + continue; + if (lsearch.isEmpty()) + addSearch(st.nextToken(), lsearch); + } + else if (line.startsWith("search")) { + if (!lsearch.isEmpty()) + lsearch.clear(); + StringTokenizer st = new StringTokenizer(line); + st.nextToken(); /* skip search */ + while (st.hasMoreTokens()) + addSearch(st.nextToken(), lsearch); + } + else if(line.startsWith("options")) { + StringTokenizer st = new StringTokenizer(line); + st.nextToken(); /* skip options */ + while (st.hasMoreTokens()) { + String token = st.nextToken(); + if (token.startsWith("ndots:")) { + lndots = parseNdots(token); + } + } + } + } + br.close(); + } + catch (IOException e) { + } + + configureFromLists(lserver, lsearch); + configureNdots(lndots); +} + +private void +findUnix() { + findResolvConf("/etc/resolv.conf"); +} + +private void +findNetware() { + findResolvConf("sys:/etc/resolv.cfg"); +} + +/** + * Parses the output of winipcfg or ipconfig. + */ +private void +findWin(InputStream in, Locale locale) { + String packageName = ResolverConfig.class.getPackage().getName(); + String resPackageName = packageName + ".windows.DNSServer"; + ResourceBundle res; + if (locale != null) + res = ResourceBundle.getBundle(resPackageName, locale); + else + res = ResourceBundle.getBundle(resPackageName); + + String host_name = res.getString("host_name"); + String primary_dns_suffix = res.getString("primary_dns_suffix"); + String dns_suffix = res.getString("dns_suffix"); + String dns_servers = res.getString("dns_servers"); + + BufferedReader br = new BufferedReader(new InputStreamReader(in)); + try { + List lserver = new ArrayList(); + List lsearch = new ArrayList(); + String line = null; + boolean readingServers = false; + boolean readingSearches = false; + while ((line = br.readLine()) != null) { + StringTokenizer st = new StringTokenizer(line); + if (!st.hasMoreTokens()) { + readingServers = false; + readingSearches = false; + continue; + } + String s = st.nextToken(); + if (line.indexOf(":") != -1) { + readingServers = false; + readingSearches = false; + } + + if (line.indexOf(host_name) != -1) { + while (st.hasMoreTokens()) + s = st.nextToken(); + Name name; + try { + name = Name.fromString(s, null); + } + catch (TextParseException e) { + continue; + } + if (name.labels() == 1) + continue; + addSearch(s, lsearch); + } else if (line.indexOf(primary_dns_suffix) != -1) { + while (st.hasMoreTokens()) + s = st.nextToken(); + if (s.equals(":")) + continue; + addSearch(s, lsearch); + readingSearches = true; + } else if (readingSearches || + line.indexOf(dns_suffix) != -1) + { + while (st.hasMoreTokens()) + s = st.nextToken(); + if (s.equals(":")) + continue; + addSearch(s, lsearch); + readingSearches = true; + } else if (readingServers || + line.indexOf(dns_servers) != -1) + { + while (st.hasMoreTokens()) + s = st.nextToken(); + if (s.equals(":")) + continue; + addServer(s, lserver); + readingServers = true; + } + } + + configureFromLists(lserver, lsearch); + } + catch (IOException e) { + } + return; +} + +private void +findWin(InputStream in) { + String property = "org.xbill.DNS.windows.parse.buffer"; + final int defaultBufSize = 8 * 1024; + int bufSize = Integer.getInteger(property, defaultBufSize).intValue(); + BufferedInputStream b = new BufferedInputStream(in, bufSize); + b.mark(bufSize); + findWin(b, null); + if (servers == null) { + try { + b.reset(); + } + catch (IOException e) { + return; + } + findWin(b, new Locale("", "")); + } +} + +/** + * Calls winipcfg and parses the result to find servers and a search path. + */ +private void +find95() { + String s = "winipcfg.out"; + try { + Process p; + p = Runtime.getRuntime().exec("winipcfg /all /batch " + s); + p.waitFor(); + File f = new File(s); + findWin(new FileInputStream(f)); + new File(s).delete(); + } + catch (Exception e) { + return; + } +} + +/** + * Calls ipconfig and parses the result to find servers and a search path. + */ +private void +findNT() { + try { + Process p; + p = Runtime.getRuntime().exec("ipconfig /all"); + findWin(p.getInputStream()); + p.destroy(); + } + catch (Exception e) { + return; + } +} + +/** + * Parses the output of getprop, which is the only way to get DNS + * info on Android. getprop might disappear in future releases, so + * this code comes with a use-by date. + */ +private void +findAndroid() { + // This originally looked for all lines containing .dns; but + // http://code.google.com/p/android/issues/detail?id=2207#c73 + // indicates that net.dns* should always be the active nameservers, so + // we use those. + String re1 = "^\\d+(\\.\\d+){3}$"; + String re2 = "^[0-9a-f]+(:[0-9a-f]*)+:[0-9a-f]+$"; + try { + ArrayList lserver = new ArrayList(); + ArrayList lsearch = new ArrayList(); + String line; + Process p = Runtime.getRuntime().exec("getprop"); + InputStream in = p.getInputStream(); + InputStreamReader isr = new InputStreamReader(in); + BufferedReader br = new BufferedReader(isr); + while ((line = br.readLine()) != null ) { + StringTokenizer t = new StringTokenizer(line, ":"); + String name = t.nextToken(); + if (name.indexOf( "net.dns" ) > -1) { + String v = t.nextToken(); + v = v.replaceAll("[ \\[\\]]", ""); + if ((v.matches(re1) || v.matches(re2)) && + !lserver.contains(v)) + lserver.add(v); + } + } + configureFromLists(lserver, lsearch); + } catch ( Exception e ) { + // ignore resolutely + } +} + +/** Returns all located servers */ +public String [] +servers() { + return servers; +} + +/** Returns the first located server */ +public String +server() { + if (servers == null) + return null; + return servers[0]; +} + +/** Returns all entries in the located search path */ +public Name [] +searchPath() { + return searchlist; +} + +/** + * Returns the located ndots value, or the default (1) if not configured. + * Note that ndots can only be configured in a resolv.conf file, and will only + * take effect if ResolverConfig uses resolv.conf directly (that is, if the + * JVM does not include the sun.net.dns.ResolverConfiguration class). + */ +public int +ndots() { + if (ndots < 0) + return 1; + return ndots; +} + +/** Gets the current configuration */ +public static synchronized ResolverConfig +getCurrentConfig() { + return currentConfig; +} + +/** Gets the current configuration */ +public static void +refresh() { + ResolverConfig newConfig = new ResolverConfig(); + synchronized (ResolverConfig.class) { + currentConfig = newConfig; + } +} + +} |