package hu.sztaki.ilab.longneck.dns;
import hu.sztaki.ilab.longneck.dns.db.LookupResult;
import hu.sztaki.ilab.longneck.dns.db.ReverseData;
import java.io.IOException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.Calendar;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.InitializingBean;
import org.xbill.DNS.DClass;
import org.xbill.DNS.ExtendedResolver;
import org.xbill.DNS.Message;
import org.xbill.DNS.Name;
import org.xbill.DNS.Record;
import org.xbill.DNS.ReverseMap;
import org.xbill.DNS.Section;
import org.xbill.DNS.Type;
/**
* DNS lookup service.
*
* @author Bendig Loránd <lbendig@ilab.sztaki.hu>
* @author Molnár Péter <molnar.peter@sztaki.mta.hu>
*
*/
public class LookupService implements InitializingBean {
/** The log. */
private final Logger LOG = Logger.getLogger(LookupService.class);
/** Validity of lookup results for reverse dns in days. */
private int reverseValidityDays;
/** Timeout for dns queries in seconds. */
private int queryTimeout;
/** Configured nameservers used for lookup. */
private String[] nameservers;
/** Resolver for dns queries. */
private ExtendedResolver resolver;
@Override
public void afterPropertiesSet() {
try {
resolver = ( nameservers == null || nameservers.length == 0) ?
new ExtendedResolver() : new ExtendedResolver(nameservers);
resolver.setTimeout(queryTimeout);
} catch (UnknownHostException ex) {
throw new RuntimeException("Invalid nameservers configuration.", ex);
}
}
/**
* Looks up reverse dns for the specified ip address.
*
* @param ipAddr The ip address that is looked up.
* @return The reverse dns data.
*/
public ReverseData getReverseDns(String ipAddr) {
try {
Name name = ReverseMap.fromAddress(ipAddr.trim());
Record rec = Record.newRecord(name, Type.PTR, DClass.IN);
// Send query and receive response
Message response = resolver.send(Message.newQuery(rec));
Record[] answers = response.getSectionArray(Section.ANSWER); // fetch authoritative answer?
// Prepare reverse data
ReverseData reverseData = new ReverseData();
reverseData.setResult(LookupResult.OK);
reverseData.setIpAddress(ipAddr);
reverseData.setExpirationDate(Calendar.getInstance().getTimeInMillis() +
reverseValidityDays * 24 * 60 * 60);
// Parse and return answer
if (answers.length > 0) {
for (Record answer : answers) {
if (answer.getType() == Type.PTR &&
!answer.rdataToString().matches("^.*\\.in-addr\\.arpa\\.$")) {
reverseData.setDomain(
answer.rdataToString().replaceAll("^(.+)(?<!\\.)\\.*$", "$1"));
return reverseData;
}
}
} else {
reverseData.setDomain("-");
reverseData.setResult(LookupResult.FAIL);
return reverseData;
}
} catch (UnknownHostException e) {
LOG.warn("Reverse lookup failed, unknown host: " + ipAddr, e);
} catch (SocketTimeoutException e) {
LOG.warn("Reverse dns lookup timed out: " + ipAddr, e);
} catch (IOException e) {
LOG.warn("Error during dns query: " + ipAddr, e);
}
// Return null on failure
return null;
}
public int getReverseValidityDays() {
return reverseValidityDays;
}
public void setReverseValidityDays(int reverseValidityDays) {
this.reverseValidityDays = reverseValidityDays;
}
public int getQueryTimeout() {
return queryTimeout;
}
public void setQueryTimeout(int queryTimeout) {
this.queryTimeout = queryTimeout;
}
public String[] getNameservers() {
return nameservers;
}
public void setNameservers(String[] nameservers) {
this.nameservers = nameservers;
}
}