use of org.xbill.DNS.SetResponse in project GNS by MobilityFirst.
the class NameResolution method lookupDnsCache.
/**
* Look up the local dns server cache.
* Returns a {@link Message}.
*
* @param query
* @param dnsCache
* @return a Message
*/
public static Message lookupDnsCache(Message query, Cache dnsCache) {
// check for queries we can't handle
int type = query.getQuestion().getType();
// Was the query legitimate or implemented?
if (!Type.isRR(type) && type != Type.ANY) {
return errorMessage(query, Rcode.NOTIMP);
}
// extract the domain (guid) and field from the query
final Name requestedName = query.getQuestion().getName();
final byte[] rawName = requestedName.toWire();
final String lookupName = querytoStringForGNS(rawName);
NameResolution.getLogger().log(Level.FINER, "Looking up name in cache: {0}", lookupName);
SetResponse lookupresult = dnsCache.lookupRecords(requestedName, Type.ANY, Credibility.NORMAL);
if (lookupresult.isSuccessful()) {
Message response = new Message(query.getHeader().getID());
response.getHeader().setFlag(Flags.QR);
if (query.getHeader().getFlag(Flags.RD)) {
response.getHeader().setFlag(Flags.RA);
}
response.addRecord(query.getQuestion(), Section.QUESTION);
response.getHeader().setFlag(Flags.AA);
ArrayList<Name> cnameNames = new ArrayList<>();
// Write the response
for (RRset rrset : lookupresult.answers()) {
NameResolution.getLogger().log(Level.FINE, "{0}\n", rrset.toString());
Iterator<?> rrItr = rrset.rrs();
while (rrItr.hasNext()) {
Record curRecord = (Record) rrItr.next();
response.addRecord(curRecord, Section.ANSWER);
if (curRecord.getType() == Type.CNAME) {
cnameNames.add(((CNAMERecord) curRecord).getAlias());
}
}
}
if (cnameNames.isEmpty()) {
return response;
}
// For all CNAMES in the response, add their A records
for (Name cname : cnameNames) {
NameResolution.getLogger().log(Level.FINE, "Looking up CNAME in cache: {0}", cname.toString());
SetResponse lookUpResult = dnsCache.lookupRecords(cname, Type.ANY, Credibility.NORMAL);
if (lookUpResult.isSuccessful()) {
for (RRset rrset : lookUpResult.answers()) {
NameResolution.getLogger().log(Level.FINE, "{0}\n", rrset.toString());
Iterator<?> rrItr = rrset.rrs();
while (rrItr.hasNext()) {
Record curRecord = (Record) rrItr.next();
response.addRecord(curRecord, Section.ANSWER);
}
}
}
}
return response;
} else {
return errorMessage(query, Rcode.NOTIMP);
}
}
use of org.xbill.DNS.SetResponse in project GNS by MobilityFirst.
the class LookupWorker method generateReply.
/**
* Queries DNS and/or GNS servers for DNS records.
*
* Note: a null return value means that the caller doesn't need to do
* anything. Currently this only happens if this is an AXFR request over TCP.
*/
private Message generateReply(Message query) {
long startTime = System.currentTimeMillis();
NameResolution.getLogger().log(Level.FINE, "Incoming request:\n {0}", query.toString());
// If it's not a query we just ignore it.
if (query.getHeader().getFlag(Flags.QR)) {
return null;
}
long checkStart = System.currentTimeMillis();
// Check for wierd queries we can't handle.
Message errorMessage;
if ((errorMessage = NameResolution.checkForErroneousQueries(query)) != null) {
return errorMessage;
}
DelayProfiler.updateDelay("checkForErroneousQueries", checkStart);
// If we're not consulting the DNS server as well just send the query to GNS.
if (dnsServer == null) {
Message result = NameResolution.lookupGnsServer(incomingPacket.getAddress(), query, handler);
DelayProfiler.updateDelay("generateReply", startTime);
return result;
}
// Otherwise as a first step before performing GNS/DNS lookup we check our own local cache.
if (dnsCache != null) {
Message tempQuery = (Message) query.clone();
Message result = NameResolution.lookupDnsCache(tempQuery, dnsCache);
if (result.getHeader().getRcode() == Rcode.NOERROR) {
NameResolution.getLogger().log(Level.FINE, "Responding the request from cache {0}", NameResolution.queryAndResponseToString(query, result));
return result;
}
}
// Create a clone of the query for duplicating the request to GNS and DNS
Message dnsQuery = (Message) query.clone();
List<LookupTask> tasks;
if (gnsServer == null) {
// We make two tasks to check the DNS and GNS in parallel
tasks = Arrays.asList(// Create GNS lookup task
new LookupTask(query, handler), // Create DNS lookup task
new LookupTask(dnsQuery, dnsServer, handler));
} else {
tasks = Arrays.asList(// Create GNS lookup task
new LookupTask(query, gnsServer, true, /* isGNS */
handler), // Create DNS lookup task
new LookupTask(dnsQuery, dnsServer, false, /* isGNS */
handler));
}
// A little bit of overkill for two tasks, but it's really not that much longer (if any) than
// the altenative. Plus it's cool and trendy to use futures.
ExecutorService executor = Executors.newFixedThreadPool(2);
ExecutorCompletionService<Message> completionService = new ExecutorCompletionService<>(executor);
List<Future<Message>> futures = new ArrayList<>(2);
for (Callable<Message> task : tasks) {
futures.add(completionService.submit(task));
}
Message successResponse = null;
Message errorResponse = null;
// loop throught the tasks getting results as they complete
for (LookupTask task : tasks) {
// this is just doing things twice btw
try {
Message result = completionService.take().get();
if (result.getHeader().getRcode() == Rcode.NOERROR) {
successResponse = result;
break;
} else {
// squirrel this away for later in case we get no successes
errorResponse = result;
}
} catch (ExecutionException e) {
NameResolution.getLogger().log(Level.WARNING, "Problem handling lookup task: {0}", e);
} catch (InterruptedException e) {
NameResolution.getLogger().log(Level.WARNING, "Lookup task interrupted: {0}", e);
}
}
// Shutdown the executor threadpool
executor.shutdown();
if (successResponse != null) {
// Cache the successful response
try {
SetResponse addMsgResponse = dnsCache.addMessage(successResponse);
if (!addMsgResponse.isSuccessful()) {
RRset[] answers = successResponse.getSectionRRsets(Section.ANSWER);
boolean isAuth = successResponse.getHeader().getFlag(Flags.AA);
int qClass = successResponse.getQuestion().getDClass();
for (int i = 0; i < answers.length; i++) {
if (answers[i].getDClass() != qClass) {
continue;
}
int cred = getCred(Section.ANSWER, isAuth);
dnsCache.addRRset(answers[i], cred);
NameResolution.getLogger().log(Level.FINE, "Records added to cache {0}", answers[i].toString());
}
}
} catch (NullPointerException e) {
NameResolution.getLogger().log(Level.WARNING, "Failed to add a dns response to cache{0}", e);
}
return successResponse;
} else if (errorResponse != null) {
// currently this is returning the second error response... do we care?
return errorResponse;
} else {
return NameResolution.errorMessage(query, Rcode.NXDOMAIN);
}
}
use of org.xbill.DNS.SetResponse in project opennms by OpenNMS.
the class DNSServer method addCacheNS.
private final void addCacheNS(final Message response, final Cache cache, final Name name) {
final SetResponse sr = cache.lookupRecords(name, Type.NS, Credibility.HINT);
if (!sr.isDelegation())
return;
final RRset nsRecords = sr.getNS();
@SuppressWarnings("unchecked") final Iterator<Record> it = nsRecords.rrs();
while (it.hasNext()) {
final Record r = it.next();
response.addRecord(r, Section.AUTHORITY);
}
}
use of org.xbill.DNS.SetResponse in project opennms by OpenNMS.
the class DNSServer method addAnswer.
byte addAnswer(final Message response, final Name name, int type, int dclass, int iterations, int flags) {
SetResponse sr;
byte rcode = Rcode.NOERROR;
if (iterations > 6)
return Rcode.NOERROR;
if (type == Type.SIG || type == Type.RRSIG) {
type = Type.ANY;
flags |= FLAG_SIGONLY;
}
final Zone zone = findBestZone(name);
if (zone != null)
sr = zone.findRecords(name, type);
else {
sr = getCache(dclass).lookupRecords(name, type, Credibility.NORMAL);
}
if (sr.isUnknown()) {
addCacheNS(response, getCache(dclass), name);
}
if (sr.isNXDOMAIN()) {
response.getHeader().setRcode(Rcode.NXDOMAIN);
if (zone != null) {
addSOA(response, zone);
if (iterations == 0)
response.getHeader().setFlag(Flags.AA);
}
rcode = Rcode.NXDOMAIN;
} else if (sr.isNXRRSET()) {
if (zone != null) {
addSOA(response, zone);
if (iterations == 0)
response.getHeader().setFlag(Flags.AA);
}
} else if (sr.isDelegation()) {
final RRset nsRecords = sr.getNS();
addRRset(nsRecords.getName(), response, nsRecords, Section.AUTHORITY, flags);
} else if (sr.isCNAME()) {
final CNAMERecord cname = sr.getCNAME();
addRRset(name, response, new RRset(cname), Section.ANSWER, flags);
if (zone != null && iterations == 0)
response.getHeader().setFlag(Flags.AA);
rcode = addAnswer(response, cname.getTarget(), type, dclass, iterations + 1, flags);
} else if (sr.isDNAME()) {
final DNAMERecord dname = sr.getDNAME();
RRset rrset = new RRset(dname);
addRRset(name, response, rrset, Section.ANSWER, flags);
final Name newname;
try {
newname = name.fromDNAME(dname);
} catch (final NameTooLongException e) {
return Rcode.YXDOMAIN;
}
rrset = new RRset(new CNAMERecord(name, dclass, 0, newname));
addRRset(name, response, rrset, Section.ANSWER, flags);
if (zone != null && iterations == 0)
response.getHeader().setFlag(Flags.AA);
rcode = addAnswer(response, newname, type, dclass, iterations + 1, flags);
} else if (sr.isSuccessful()) {
final RRset[] rrsets = sr.answers();
for (int i = 0; i < rrsets.length; i++) addRRset(name, response, rrsets[i], Section.ANSWER, flags);
if (zone != null) {
addNS(response, zone, flags);
if (iterations == 0)
response.getHeader().setFlag(Flags.AA);
} else
addCacheNS(response, getCache(dclass), name);
}
return rcode;
}
Aggregations