001/* 002 * Copyright 2015-2018 the original author or authors 003 * 004 * This software is licensed under the Apache License, Version 2.0, 005 * the GNU Lesser General Public License version 2 or later ("LGPL") 006 * and the WTFPL. 007 * You may choose either license to govern your use of this software only 008 * upon the condition that you accept all of the terms of either 009 * the Apache License 2.0, the LGPL 2.1+ or the WTFPL. 010 */ 011package org.minidns.dnsserverlookup; 012 013import org.minidns.util.PlatformDetection; 014 015import java.io.BufferedReader; 016import java.io.IOException; 017import java.io.InputStream; 018import java.io.InputStreamReader; 019import java.io.LineNumberReader; 020import java.net.InetAddress; 021import java.net.UnknownHostException; 022import java.util.ArrayList; 023import java.util.HashSet; 024import java.util.List; 025import java.util.Set; 026import java.util.logging.Level; 027 028/** 029 * Try to retrieve the list of DNS server by executing getprop. 030 */ 031public class AndroidUsingExec extends AbstractDnsServerLookupMechanism { 032 033 public static final DnsServerLookupMechanism INSTANCE = new AndroidUsingExec(); 034 public static final int PRIORITY = AndroidUsingReflection.PRIORITY - 1; 035 036 private AndroidUsingExec() { 037 super(AndroidUsingExec.class.getSimpleName(), PRIORITY); 038 } 039 040 @Override 041 public List<String> getDnsServerAddresses() { 042 try { 043 Process process = Runtime.getRuntime().exec("getprop"); 044 InputStream inputStream = process.getInputStream(); 045 LineNumberReader lnr = new LineNumberReader( 046 new InputStreamReader(inputStream)); 047 Set<String> server = parseProps(lnr, true); 048 if (server.size() > 0) { 049 List<String> res = new ArrayList<>(server.size()); 050 res.addAll(server); 051 return res; 052 } 053 } catch (IOException e) { 054 LOGGER.log(Level.WARNING, "Exception in findDNSByExec", e); 055 } 056 return null; 057 } 058 059 @Override 060 public boolean isAvailable() { 061 return PlatformDetection.isAndroid(); 062 } 063 064 private static final String PROP_DELIM = "]: ["; 065 protected static Set<String> parseProps(BufferedReader lnr, boolean logWarning) throws UnknownHostException, IOException { 066 String line = null; 067 Set<String> server = new HashSet<String>(6); 068 069 while ((line = lnr.readLine()) != null) { 070 int split = line.indexOf(PROP_DELIM); 071 if (split == -1) { 072 continue; 073 } 074 String property = line.substring(1, split); 075 076 int valueStart = split + PROP_DELIM.length(); 077 int valueEnd = line.length() - 1; 078 if (valueEnd < valueStart) { 079 // This can happen if a newline sneaks in as the first character of the property value. For example 080 // "[propName]: [\n…]". 081 if (logWarning) { 082 LOGGER.warning("Malformed property detected: \"" + line + '"'); 083 } 084 continue; 085 } 086 087 String value = line.substring(valueStart, valueEnd); 088 089 if (value.isEmpty()) { 090 continue; 091 } 092 093 if (property.endsWith(".dns") || property.endsWith(".dns1") || 094 property.endsWith(".dns2") || property.endsWith(".dns3") || 095 property.endsWith(".dns4")) { 096 097 // normalize the address 098 099 InetAddress ip = InetAddress.getByName(value); 100 101 if (ip == null) continue; 102 103 value = ip.getHostAddress(); 104 105 if (value == null) continue; 106 if (value.length() == 0) continue; 107 108 server.add(value); 109 } 110 } 111 112 return server; 113 } 114}