Can some explain Context.list() in DNS terms?
Hi all,
First question: using nmap 10.101.40.200 shows port 53 and dns running
so why would DirContext.list() throw "OperationNotSupportedException:
DNS service refused" ? The goal: Find all hosts that are known to a
nameserver. If one of the hosts is a NS record, search that server as
well. I can switch - as the commented out code shows - to use the
public dns server via calculateDNS("bee.uspnet.usp.br", "usp.br") and
the code works fine. Why I can't connect to 10.101.40.200 completely
baffles me - what exactly is DirContext.list() trying to look for in
the DNS service ? I tried DNSJava as well with the same problem.
Second question: Can someone explain the equivalent DIG or NSLOOKUP
commands that and the subsequent:
NamingEnumeration hostEnumeration = DirContext.list()
String host = ((NameClassPair) hostEnumeration.next())
.getNameInNamespace();
I want to post the DNS parts of the question to the approriate
newsgroup, but I'm having a hard time using DIG and NSLOOKUP to repeat
the results.
Here's my code - there are a few sockets open, already cancelled,
waiting to timeout which is ok. Not sure about the recursion part -
still thinking about it.
package org;
import java.util.concurrent.*;
public class RecursionLatch {
private final CountDownLatch done = new CountDownLatch(1);
public boolean isSet() {
return (done.getCount() == 0);
}
public synchronized void setCompleted() {
if (!isSet()) {
done.countDown();
}
}
public void taskCompleted() throws InterruptedException {
done.await();
}
}
package org;
import static java.lang.System.out;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Hashtable;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
import javax.naming.NameClassPair;
import javax.naming.NamingEnumeration;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.NamingException;
public class DNS
{
private static final AtomicInteger taskCount = new AtomicInteger(0);
private static final RecursionLatch solution = new RecursionLatch();
public static void main(String[] args) throws Exception {
helloDNS();
}
/*******************************************************************
Use this method to test dns
*******************************************************************/
private static void helloDNS() throws Exception {
//calculateDNS("10.101.40.200", "atlantico.com.br");
calculateDNS("bee.uspnet.usp.br", "usp.br");
out.println("calculateDNS returned, waiting for cancelled
sockets to timeout...");
}
private static List<String> calculateDNS(final String ipDNS, final
String domain)
throws Exception {
final Hashtable<String, String> env = new Hashtable<String,
String>();
env.put("java.naming.factory.initial",
"com.sun.jndi.dns.DnsContextFactory");
env.put("java.naming.provider.url", "dns://" + ipDNS + "/");
final DirContext ictx;
ictx = new InitialDirContext(env);
ExecutorService exec = Executors.newCachedThreadPool();
NamingEnumeration hostEnumeration = null;
boolean gotList = false;
Callable <NamingEnumeration> listTask =
new Callable<NamingEnumeration>() {
public NamingEnumeration call() {
try {
return ictx.list(domain);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
};
Future <NamingEnumeration> future = exec.submit(listTask);
try {
hostEnumeration = future.get(10L, TimeUnit.SECONDS);
if (hostEnumeration != null) {
gotList = true;
}
} catch (Exception ex) {
ex.printStackTrace();
} finally {
future.cancel(true);
}
try {
if (!gotList) {
throw new Exception("Can't connect to DNS server");
}
// skip those already found
Queue <String> domainsVisitedQueue = new
ConcurrentLinkedQueue<String>();
domainsVisitedQueue.add(domain);
Queue <String> resultQueue = new
ConcurrentLinkedQueue<String>();
parallelRecursiveDNS(exec, ictx, hostEnumeration,
domainsVisitedQueue, resultQueue );
// wait for latch
solution.taskCompleted();
out.println("latch returned, waiting for shutdown");
for (String s : resultQueue) {
out.println("WTF: " + s);
}
return new ArrayList<String>(resultQueue);
} catch (Exception ex) {
ex.printStackTrace();
throw new Exception (ex);
} finally {
out.println("shutting down DirContext");
long ictxStart = System.currentTimeMillis();
if (ictx != null) {
try {
ictx.close();
} catch (NamingException ex) {
ex.printStackTrace();
}
}
long ictxEnd = System.currentTimeMillis();
out.println("runnable execution time was "
+ (ictxStart - ictxStart) / 1000 + " seconds ");
// may have some sockets still open that have been cancelled
- that's ok
exec.shutdownNow();
out.println("termination complete");
}
}
private static void parallelRecursiveDNS(final ExecutorService exec,
final DirContext ictx,
final NamingEnumeration hostEnumeration, final
Collection<String> domainsVisitedQueue,
final Collection<String> results)
throws Exception {
while (hostEnumeration.hasMore()) {
taskCount.incrementAndGet();
exec.execute(new Runnable() {
public void run() {
long runStart = System.currentTimeMillis();
try {
String host = null;
host = ((NameClassPair) hostEnumeration.next())
.getNameInNamespace();
if (results.contains(host)) {
return;
}
results.add(host);
out.println("Found host: " + host);
Attributes aDNS = ictx.getAttributes(host,
new String[] { "NS" });
NamingEnumeration allDNS = aDNS.getAll();
while (allDNS.hasMore()) {
out.println("Entering allDNS: ");
Attribute attr = (Attribute) allDNS.next();
NamingEnumeration values = attr.getAll();
final String dns = values.next().toString();
if (domainsVisitedQueue.contains(dns)) {
continue;
}
domainsVisitedQueue.add(dns);
NamingEnumeration newEnumeration = null;
boolean gotList = false;
Callable <NamingEnumeration> listTask =
new Callable<NamingEnumeration>() {
public NamingEnumeration call() {
try {
out.println("doing future on
ictx.list()");
return ictx.list(dns);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
};
Future <NamingEnumeration> future =
exec.submit(listTask);
try {
newEnumeration = future.get(10L,
TimeUnit.SECONDS);
if (newEnumeration != null) {
gotList = true;
}
} catch (Exception ex) {
ex.printStackTrace();
} finally {
future.cancel(true);
}
if (!gotList) {
continue;
}
parallelRecursiveDNS(exec, ictx,
newEnumeration, domainsVisitedQueue, results);
}
} catch (Exception ex) {
ex.printStackTrace();
} finally {
long runEnd = System.currentTimeMillis();
out.println("runnable execution time was "
+ (runEnd - runStart) / 1000 + " seconds ");
if (taskCount.decrementAndGet() == 0) {
out.println("\n\nparallelRecursiveDNS
finished\n\n");
solution.setCompleted();
}
}
}
});
}
}
}