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 @@ -23,6 +23,7 @@

import org.minidns.dnsserverlookup.AbstractDNSServerLookupMechanism;
import org.minidns.dnsserverlookup.AndroidUsingExec;
import org.minidns.dnsserverlookup.IPPortPair;

/**
* Requires the ACCESS_NETWORK_STATE permission.
Expand All @@ -44,7 +45,7 @@ public boolean isAvailable() {

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

return servers;
return stringCollectionToListOfIPPortPairs(servers);
}

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
Expand Down
84 changes: 52 additions & 32 deletions minidns-client/src/main/java/org/minidns/DNSClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,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 @@ -96,8 +97,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 @@ -123,7 +124,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 @@ -142,23 +143,23 @@ public DNSMessage query(DNSMessage.Builder queryBuilder) throws IOException {
return responseMessage;
}

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 {
responseMessage = query(q, dns);
responseMessage = query(q, dns.getServer(), dns.getPort());
if (responseMessage == null) {
continue;
}

if (!responseMessage.recursionAvailable) {
boolean newRaServer = nonRaServers.add(dns);
boolean newRaServer = nonRaServers.add(dns.getServer());
if (newRaServer) {
LOGGER.warning("The DNS server "
+ dns
Expand Down Expand Up @@ -211,16 +212,16 @@ protected MiniDnsFuture<DNSMessage, IOException> queryAsync(DNSMessage.Builder q
return MiniDnsFuture.from(responseMessage);
}

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

final InternalMiniDnsFuture<DNSMessage, 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 @@ -229,15 +230,15 @@ protected MiniDnsFuture<DNSMessage, IOException> queryAsync(DNSMessage.Builder q

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

MiniDnsFuture<DNSMessage, IOException> f = queryAsync(q, dns);
MiniDnsFuture<DNSMessage, IOException> f = queryAsync(q, dns.getServer(), dns.getPort());
f.onSuccess(new SuccessCallback<DNSMessage>() {
@Override
public void onSuccess(DNSMessage result) {
Expand Down Expand Up @@ -268,10 +269,10 @@ 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();
res = mechanism.getDnsServerAddressesWithPorts();
if (res == null) {
continue;
}
Expand All @@ -285,14 +286,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 @@ -321,56 +322,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 @@ -458,4 +460,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> getDnsServerAddressesWithPorts();

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> getDnsServerAddressesWithPorts() {
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> getDnsServerAddressesWithPorts() {
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 @@ -29,6 +29,6 @@ public interface DNSServerLookupMechanism extends Comparable<DNSServerLookupMech
*
* @return a List of Strings presenting hopefully IP addresses.
*/
public List<String> getDnsServerAddresses();
public List<IPPortPair> getDnsServerAddressesWithPorts();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no need to rename the method, just changing the return type is fine.


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* 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;

/**
* Copyright Daniel Wolf 2018
* All rights reserved.
* Code may NOT be used without proper permission, neither in binary nor in source form.
* All redistributions of this software in source code must retain this copyright header
* All redistributions of this software in binary form must visibly inform users about usage of this software
* <p>
* [email protected]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this added by accident? If so, please remove it.

Copy link
Author

@Ch4t4r Ch4t4r Apr 26, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah it was. I'm removing it.

*/
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> getDnsServerAddressesWithPorts() {
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