package com.netifera.platform.net.dns.tools;
import java.io.IOException;
import java.net.UnknownHostException;
import java.util.List;
import org.xbill.DNS.AAAARecord;
import org.xbill.DNS.ARecord;
import org.xbill.DNS.Lookup;
import org.xbill.DNS.MXRecord;
import org.xbill.DNS.NSRecord;
import org.xbill.DNS.Name;
import org.xbill.DNS.PTRRecord;
import org.xbill.DNS.Record;
import org.xbill.DNS.TextParseException;
import org.xbill.DNS.Type;
import com.netifera.platform.api.probe.IProbe;
import com.netifera.platform.api.tools.ITool;
import com.netifera.platform.api.tools.IToolContext;
import com.netifera.platform.api.tools.ToolException;
import com.netifera.platform.net.dns.internal.tools.Activator;
import com.netifera.platform.net.dns.model.DomainEntity;
import com.netifera.platform.net.dns.model.MXRecordEntity;
import com.netifera.platform.net.dns.model.NSRecordEntity;
import com.netifera.platform.net.dns.service.DNS;
import com.netifera.platform.net.dns.service.nameresolver.INameResolver;
import com.netifera.platform.net.model.ServiceEntity;
import com.netifera.platform.tools.RequiredOptionMissingException;
import com.netifera.platform.util.addresses.inet.IPv4Address;
import com.netifera.platform.util.addresses.inet.IPv6Address;
import com.netifera.platform.util.addresses.inet.InternetAddress;
import com.netifera.platform.util.locators.TCPSocketLocator;
import com.netifera.platform.util.locators.UDPSocketLocator;
public class AddDomain implements ITool {
private DNS dns;
private Name domain;
private INameResolver resolver;
private IToolContext context;
private long realm;
public void toolRun(IToolContext context) throws ToolException {
this.context = context;
// XXX hardcode local probe as realm
IProbe probe = Activator.getInstance().getProbeManager().getLocalProbe();
realm = probe.getEntity().getId();
setupToolOptions();
context.setTitle("Lookup NS records for "+domain);
try {
if (dns != null)
resolver = dns.createNameResolver(Activator.getInstance().getSocketEngine());
else
resolver = Activator.getInstance().getNameResolver();
getNS();
} catch (IOException e) {
context.exception("I/O Exception", e);
} finally {
context.done();
}
}
private boolean getNS() {
context.setStatus("Querying for authoritative name servers");
Lookup lookup = new Lookup(domain, Type.NS);
lookup.setResolver(resolver.getExtendedResolver());
lookup.setSearchPath((Name[])null);
Record [] records = lookup.run();
if (records == null) {
context.info("No NS records found for "+domain);
return false;
}
// if the domain has ns records, it exists
DomainEntity entity = Activator.getInstance().getDomainEntityFactory().createDomain(realm, context.getSpaceId(), domain.toString());
entity.addTag("Target");
entity.addToSpace(context.getSpaceId());
entity.update();
for (Record record: records)
processRecord(record);
return true;
}
private void processRecord(Record o) {
context.info(o.toString());
if (o instanceof ARecord) {
ARecord a = (ARecord) o;
Activator.getInstance().getDomainEntityFactory().createARecord(realm, context.getSpaceId(), a.getName().toString(), IPv4Address.fromInetAddress(a.getAddress()));
} else if (o instanceof AAAARecord) {
AAAARecord aaaa = (AAAARecord) o;
Activator.getInstance().getDomainEntityFactory().createAAAARecord(realm, context.getSpaceId(), aaaa.getName().toString(), IPv6Address.fromInetAddress(aaaa.getAddress()));
} else if (o instanceof PTRRecord) {
PTRRecord ptr = (PTRRecord) o;
// Activator.getInstance().getDomainEntityFactory().createARecord(realm, a.getName().toString(), InternetAddress.fromInetAddress(o..getAddress()));
context.warning("unhandled record: "+ptr);
} else if (o instanceof MXRecord) {
processMXRecord((MXRecord) o);
} else if (o instanceof NSRecord) {
processNSRecord((NSRecord) o);
} else {
context.warning("Unhandled DNS record: "+o);
}
}
private void processNSRecord(NSRecord ns) {
NSRecordEntity entity = Activator.getInstance().getDomainEntityFactory().createNSRecord(realm, context.getSpaceId(), domain.toString(), ns.getTarget().toString());
try {
List<InternetAddress> addresses = resolver.getAddressesByName(ns.getTarget().toString());
for (InternetAddress address: addresses) {
if (address instanceof IPv4Address) {
Activator.getInstance().getDomainEntityFactory().createARecord(realm, context.getSpaceId(), ns.getTarget().toString(), (IPv4Address)address);
} else {
Activator.getInstance().getDomainEntityFactory().createAAAARecord(realm, context.getSpaceId(), ns.getTarget().toString(), (IPv6Address)address);
}
UDPSocketLocator locator = new UDPSocketLocator(address,53);
ServiceEntity service = Activator.getInstance().getNetworkEntityFactory().createService(realm, context.getSpaceId(), locator, "DNS", null);
entity.setService(service); //XXX just the last one will be kept as default service when accessing it from the NS record entity
}
entity.save();
} catch (UnknownHostException e) {
context.warning("Could not resolve NS record target "+ns.getTarget());
} catch (TextParseException e) {
context.warning("Malformed host name as NS record target: "+ns.getTarget());
}
}
private void processMXRecord(MXRecord mx) {
MXRecordEntity entity = Activator.getInstance().getDomainEntityFactory().createMXRecord(realm, context.getSpaceId(), domain.toString(), mx.getTarget().toString(), mx.getPriority());
try {
List<InternetAddress> addresses = resolver.getAddressesByName(mx.getTarget().toString());
for (InternetAddress address: addresses) {
if (address instanceof IPv4Address) {
Activator.getInstance().getDomainEntityFactory().createARecord(realm, context.getSpaceId(), mx.getTarget().toString(), (IPv4Address)address);
} else {
Activator.getInstance().getDomainEntityFactory().createAAAARecord(realm, context.getSpaceId(), mx.getTarget().toString(), (IPv6Address)address);
}
TCPSocketLocator locator = new TCPSocketLocator(address,25);
ServiceEntity service = Activator.getInstance().getNetworkEntityFactory().createService(realm, context.getSpaceId(), locator, "SMTP", null);
entity.setService(service); //XXX just the last one will be kept as default service when accessing it from the MX record entity
}
entity.save();
} catch (UnknownHostException e) {
context.warning("Could not resolve MX record target "+mx.getTarget());
} catch (TextParseException e) {
context.warning("Malformed host name as MX record target: "+mx.getTarget());
}
}
private void setupToolOptions() throws ToolException {
dns = (DNS) context.getConfiguration().get("dns");
String domainString = (String) context.getConfiguration().get("domain");
if (domainString == null || domainString.length() == 0) {
throw new RequiredOptionMissingException("domain");
}
if (domainString.endsWith(".")) {
domainString = domainString.substring(0,domainString.length()-1);
}
try {
domain = new Name(domainString);
} catch (TextParseException e) {
throw new ToolException("Malformed host name: '"+domainString+"'");
}
}
}