Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow DNSServerLookupMechanism to specify ports for the servers #82

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.minidns.DnsClient;
import org.minidns.dnsserverlookup.AbstractDnsServerLookupMechanism;
import org.minidns.dnsserverlookup.AndroidUsingExec;
import org.minidns.dnsserverlookup.IPPortPair;

/**
* A DNS server lookup mechanism using Android's Link Properties method available on Android API 21 or higher. Use
Expand Down Expand Up @@ -61,7 +62,7 @@ public boolean isAvailable() {

@Override
@TargetApi(21)
public List<String> getDnsServerAddresses() {
public List<IPPortPair> getDnsServerAddresses() {
Network[] networks = connectivityManager.getAllNetworks();
if (networks == null) {
return null;
Expand All @@ -86,7 +87,7 @@ public List<String> getDnsServerAddresses() {
return null;
}

return servers;
return stringCollectionToListOfIPPortPairs(servers);
}

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
Expand Down
82 changes: 51 additions & 31 deletions minidns-client/src/main/java/org/minidns/DnsClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.minidns.dnsserverlookup.AndroidUsingExec;
import org.minidns.dnsserverlookup.AndroidUsingReflection;
import org.minidns.dnsserverlookup.DnsServerLookupMechanism;
import org.minidns.dnsserverlookup.IPPortPair;
import org.minidns.dnsserverlookup.UnixUsingEtcResolvConf;
import org.minidns.util.CollectionsUtil;
import org.minidns.util.ExceptionCallback;
Expand Down Expand Up @@ -99,8 +100,8 @@ protected DnsMessage.Builder newQuestion(DnsMessage.Builder message) {
return message;
}

private List<InetAddress> getServerAddresses() {
List<InetAddress> dnsServerAddresses = findDnsAddresses();
private List<UpstreamDNSServer> getServerAddresses() {
List<UpstreamDNSServer> dnsServerAddresses = findDnsAddresses();

InetAddress[] selectedHardcodedDnsServerAddresses = new InetAddress[2];
if (useHardcodedDnsServers) {
Expand All @@ -126,7 +127,7 @@ private List<InetAddress> getServerAddresses() {
}
for (InetAddress selectedHardcodedDnsServerAddress : selectedHardcodedDnsServerAddresses) {
if (selectedHardcodedDnsServerAddress == null) continue;
dnsServerAddresses.add(selectedHardcodedDnsServerAddress);
dnsServerAddresses.add(new UpstreamDNSServer(selectedHardcodedDnsServerAddress, IPPortPair.DEFAULT_PORT));
}

return dnsServerAddresses;
Expand All @@ -145,25 +146,25 @@ public DnsQueryResult query(DnsMessage.Builder queryBuilder) throws IOException
return dnsQueryResult;
}

List<InetAddress> dnsServerAddresses = getServerAddresses();
List<UpstreamDNSServer> dnsServerAddresses = getServerAddresses();

List<IOException> ioExceptions = new ArrayList<>(dnsServerAddresses.size());
for (InetAddress dns : dnsServerAddresses) {
if (nonRaServers.contains(dns)) {
for (UpstreamDNSServer dns : dnsServerAddresses) {
if (nonRaServers.contains(dns.getServer())) {
LOGGER.finer("Skipping " + dns + " because it was marked as \"recursion not available\"");
continue;
}

try {
dnsQueryResult = query(q, dns);
dnsQueryResult = query(q, dns.getServer(), dns.getPort());
} catch (IOException ioe) {
ioExceptions.add(ioe);
continue;
}

DnsMessage responseMessage = dnsQueryResult.response;
if (!responseMessage.recursionAvailable) {
boolean newRaServer = nonRaServers.add(dns);
boolean newRaServer = nonRaServers.add(dns.getServer());
if (newRaServer) {
LOGGER.warning("The DNS server " + dns
+ " returned a response without the \"recursion available\" (RA) flag set. This likely indicates a misconfiguration because the server is not suitable for DNS resolution");
Expand Down Expand Up @@ -215,16 +216,16 @@ protected MiniDnsFuture<DnsQueryResult, IOException> queryAsync(DnsMessage.Build
return MiniDnsFuture.from(responseMessage);
}

final List<InetAddress> dnsServerAddresses = getServerAddresses();
final List<UpstreamDNSServer> dnsServerAddresses = getServerAddresses();

final InternalMiniDnsFuture<DnsQueryResult, IOException> future = new InternalMiniDnsFuture<>();
final List<IOException> exceptions = Collections.synchronizedList(new ArrayList<IOException>(dnsServerAddresses.size()));

// Filter loop.
Iterator<InetAddress> it = dnsServerAddresses.iterator();
Iterator<UpstreamDNSServer> it = dnsServerAddresses.iterator();
while (it.hasNext()) {
InetAddress dns = it.next();
if (nonRaServers.contains(dns)) {
UpstreamDNSServer dns = it.next();
if (nonRaServers.contains(dns.getServer())) {
it.remove();
LOGGER.finer("Skipping " + dns + " because it was marked as \"recursion not available\"");
continue;
Expand All @@ -233,15 +234,15 @@ protected MiniDnsFuture<DnsQueryResult, IOException> queryAsync(DnsMessage.Build

List<MiniDnsFuture<DnsQueryResult, IOException>> futures = new ArrayList<>(dnsServerAddresses.size());
// "Main" loop.
for (InetAddress dns : dnsServerAddresses) {
for (UpstreamDNSServer dns : dnsServerAddresses) {
if (future.isDone()) {
for (MiniDnsFuture<DnsQueryResult, IOException> futureToCancel : futures) {
futureToCancel.cancel(true);
}
break;
}

MiniDnsFuture<DnsQueryResult, IOException> f = queryAsync(q, dns);
MiniDnsFuture<DnsQueryResult, IOException> f = queryAsync(q, dns.getServer(), dns.getPort());
f.onSuccess(new SuccessCallback<DnsQueryResult>() {
@Override
public void onSuccess(DnsQueryResult result) {
Expand Down Expand Up @@ -272,8 +273,8 @@ public void processException(IOException exception) {
*
* @return A list of DNS server IP addresses configured for this system.
*/
public static List<String> findDNS() {
List<String> res = null;
public static List<IPPortPair> findDNS() {
List<IPPortPair> res = null;
for (DnsServerLookupMechanism mechanism : LOOKUP_MECHANISMS) {
res = mechanism.getDnsServerAddresses();
if (res == null) {
Expand All @@ -289,14 +290,14 @@ public static List<String> findDNS() {
// especially a valid DNS name is returned, as this would cause the following String to InetAddress conversation using
// getByName(String) to cause a DNS lookup, which would be performed outside of the realm of MiniDNS and therefore also outside
// of its DNSSEC guarantees.
Iterator<String> it = res.iterator();
Iterator<IPPortPair> it = res.iterator();
while (it.hasNext()) {
String potentialDnsServer = it.next();
if (!InetAddressUtil.isIpAddress(potentialDnsServer)) {
IPPortPair potentialDnsServer = it.next();
if (!InetAddressUtil.isIpAddress(potentialDnsServer.getIp())) {
LOGGER.warning("The DNS server lookup mechanism '" + mechanism.getName()
+ "' returned an invalid non-IP address result: '" + potentialDnsServer + "'");
it.remove();
} else if (blacklistedDnsServers.contains(potentialDnsServer)) {
} else if (blacklistedDnsServers.contains(potentialDnsServer.getIp())) {
LOGGER.fine("The DNS server lookup mechanism '" + mechanism.getName()
+ "' returned a blacklisted result: '" + potentialDnsServer + "'");
it.remove();
Expand Down Expand Up @@ -325,56 +326,57 @@ public static List<String> findDNS() {
* @return A list of DNS server addresses.
* @see #findDNS()
*/
public static List<InetAddress> findDnsAddresses() {
public static List<UpstreamDNSServer> findDnsAddresses() {
// The findDNS() method contract guarantees that only IP addresses will be returned.
List<String> res = findDNS();
List<IPPortPair> res = findDNS();

if (res == null) {
return new ArrayList<>();
}

final IpVersionSetting setting = DEFAULT_IP_VERSION_SETTING;

List<Inet4Address> ipv4DnsServer = null;
List<Inet6Address> ipv6DnsServer = null;
List<UpstreamDNSServer> ipv4DnsServer = null;
List<UpstreamDNSServer> ipv6DnsServer = null;
if (setting.v4) {
ipv4DnsServer = new ArrayList<>(res.size());
}
if (setting.v6) {
ipv6DnsServer = new ArrayList<>(res.size());
}

for (String dnsServerString : res) {
for (IPPortPair dnsServer : res) {
// The following invariant must hold: "dnsServerString is a IP address". Therefore findDNS() must only return a List of Strings
// representing IP addresses. Otherwise the following call of getByName(String) may perform a DNS lookup without MiniDNS being
// involved. Something we want to avoid.
assert (InetAddressUtil.isIpAddress(dnsServerString));
assert (InetAddressUtil.isIpAddress(dnsServer.getIp()));
assert (dnsServer.getPort() >= 1 && dnsServer.getPort() <= 65535);

InetAddress dnsServerAddress;
try {
dnsServerAddress = InetAddress.getByName(dnsServerString);
dnsServerAddress = InetAddress.getByName(dnsServer.getIp());
} catch (UnknownHostException e) {
LOGGER.log(Level.SEVERE, "Could not transform '" + dnsServerString + "' to InetAddress", e);
LOGGER.log(Level.SEVERE, "Could not transform '" + dnsServer + "' to InetAddress", e);
continue;
}
if (dnsServerAddress instanceof Inet4Address) {
if (!setting.v4) {
continue;
}
Inet4Address ipv4DnsServerAddress = (Inet4Address) dnsServerAddress;
ipv4DnsServer.add(ipv4DnsServerAddress);
ipv4DnsServer.add(new UpstreamDNSServer(ipv4DnsServerAddress, dnsServer.getPort()));
} else if (dnsServerAddress instanceof Inet6Address) {
if (!setting.v6) {
continue;
}
Inet6Address ipv6DnsServerAddress = (Inet6Address) dnsServerAddress;
ipv6DnsServer.add(ipv6DnsServerAddress);
ipv6DnsServer.add(new UpstreamDNSServer(ipv6DnsServerAddress, dnsServer.getPort()));
} else {
throw new AssertionError("The address '" + dnsServerAddress + "' is neither of type Inet(4|6)Address");
}
}

List<InetAddress> dnsServers = new LinkedList<>();
List<UpstreamDNSServer> dnsServers = new LinkedList<>();

switch (setting) {
case v4v6:
Expand Down Expand Up @@ -462,4 +464,22 @@ public InetAddress getRandomHardcodedIpv4DnsServer() {
public InetAddress getRandomHarcodedIpv6DnsServer() {
return CollectionsUtil.getRandomFrom(STATIC_IPV6_DNS_SERVERS, insecureRandom);
}

public static class UpstreamDNSServer {
private InetAddress server;
private int port;

public UpstreamDNSServer(InetAddress server, int port) {
this.server = server;
this.port = port;
}

public InetAddress getServer() {
return server;
}

public int getPort() {
return port;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public final int compareTo(DnsServerLookupMechanism other) {
}

@Override
public abstract List<String> getDnsServerAddresses();
public abstract List<IPPortPair> getDnsServerAddresses();

protected static List<String> toListOfStrings(Collection<? extends InetAddress> inetAddresses) {
List<String> result = new ArrayList<>(inetAddresses.size());
Expand All @@ -54,4 +54,21 @@ protected static List<String> toListOfStrings(Collection<? extends InetAddress>
}
return result;
}

protected static List<IPPortPair> inetAddressCollectionToListOfIPPortPairs(Collection<? extends InetAddress> inetAddresses){
List<IPPortPair> result = new ArrayList<>(inetAddresses.size());
for (InetAddress inetAddress : inetAddresses) {
String address = inetAddress.getHostAddress();
result.add(new IPPortPair(address, IPPortPair.DEFAULT_PORT));
}
return result;
}

protected static List<IPPortPair> stringCollectionToListOfIPPortPairs(Collection<String> serverAddresses){
List<IPPortPair> result = new ArrayList<>(serverAddresses.size());
for (String address : serverAddresses) {
result.add(new IPPortPair(address, IPPortPair.DEFAULT_PORT));
}
return result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ private AndroidUsingExec() {
}

@Override
public List<String> getDnsServerAddresses() {
public List<IPPortPair> getDnsServerAddresses() {
try {
Process process = Runtime.getRuntime().exec("getprop");
InputStream inputStream = process.getInputStream();
Expand All @@ -48,7 +48,7 @@ public List<String> getDnsServerAddresses() {
if (server.size() > 0) {
List<String> res = new ArrayList<>(server.size());
res.addAll(server);
return res;
return stringCollectionToListOfIPPortPairs(res);
}
} catch (IOException e) {
LOGGER.log(Level.WARNING, "Exception in findDNSByExec", e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ protected AndroidUsingReflection() {
}

@Override
public List<String> getDnsServerAddresses() {
public List<IPPortPair> getDnsServerAddresses() {
try {
Class<?> SystemProperties =
Class.forName("android.os.SystemProperties");
Expand Down Expand Up @@ -63,7 +63,7 @@ public List<String> getDnsServerAddresses() {
}

if (servers.size() > 0) {
return servers;
return stringCollectionToListOfIPPortPairs(servers);
}
} catch (Exception e) {
// we might trigger some problems this way
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ public interface DnsServerLookupMechanism extends Comparable<DnsServerLookupMech
* when using {@link org.minidns.DnsClient#findDNS()}.
* </p>
*
* @return a List of Strings presenting hopefully IP addresses.
* @return a List of IPPortPairs presenting hopefully IP addresses with their respective ports.
*/
public List<String> getDnsServerAddresses();
public List<IPPortPair> getDnsServerAddresses();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright 2015-2018 the original author or authors
*
* This software is licensed under the Apache License, Version 2.0,
* the GNU Lesser General Public License version 2 or later ("LGPL")
* and the WTFPL.
* You may choose either license to govern your use of this software only
* upon the condition that you accept all of the terms of either
* the Apache License 2.0, the LGPL 2.1+ or the WTFPL.
*/
package org.minidns.dnsserverlookup;

import java.io.Serializable;

public class IPPortPair implements Serializable {
private static final long serialVersionUID = 7354713072355023750L;
public static final int DEFAULT_PORT = 53;
private int port;
private String ip;

public IPPortPair(String ip) {
this(ip, DEFAULT_PORT);
}

public IPPortPair(String ip, int port) {
this.port = port;
this.ip = ip;
}

public int getPort() {
return port;
}

public String getIp() {
return ip;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,15 @@ public class UnixUsingEtcResolvConf extends AbstractDnsServerLookupMechanism {
private static final String RESOLV_CONF_FILE = "/etc/resolv.conf";
private static final Pattern NAMESERVER_PATTERN = Pattern.compile("^nameserver\\s+(.*)$");

private static List<String> cached;
private static List<IPPortPair> cached;
private static long lastModified;

private UnixUsingEtcResolvConf() {
super(UnixUsingEtcResolvConf.class.getSimpleName(), PRIORITY);
}

@Override
public List<String> getDnsServerAddresses() {
public List<IPPortPair> getDnsServerAddresses() {
File file = new File(RESOLV_CONF_FILE);
if (!file.exists()) {
// Not very unixoid systems
Expand Down Expand Up @@ -81,7 +81,7 @@ public List<String> getDnsServerAddresses() {
return null;
}

cached = servers;
cached = stringCollectionToListOfIPPortPairs(servers);
lastModified = currentLastModified;

return cached;
Expand Down
Loading