package com.netifera.platform.net.dns.tools; import java.io.IOException; import java.net.ConnectException; import java.net.SocketTimeoutException; import org.xbill.DNS.AAAARecord; import org.xbill.DNS.ARecord; import org.xbill.DNS.MXRecord; import org.xbill.DNS.NSRecord; import org.xbill.DNS.Name; import org.xbill.DNS.PTRRecord; import org.xbill.DNS.TextParseException; import org.xbill.DNS.ZoneTransferException; 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.service.DNS; 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.patternmatching.HostnameMatcher; public class DNSZoneTransfer implements ITool { private DNS dns; private Name domain; 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(); context.setTitle("Zone transfer"); setupToolOptions(); context.setTitle("Zone transfer of "+domain+" from "+dns.getLocator()); try { // resolver = dns.createResolver(Activator.getInstance().getSocketEngine()); transferZone(); } catch (ConnectException e) { context.error("Cannot connect to "+dns); } catch (SocketTimeoutException e) { context.error("Connection to "+dns+" timed out"); } catch (ZoneTransferException e) { context.error(dns+" doesnt allow zone transfer of "+domain); } catch (IOException e) { context.exception("I/O Exception", e); } finally { context.done(); } } // Transfer a zone from a server and print it private void transferZone() throws IOException, ZoneTransferException { for (Object o: dns.zoneTransfer(domain.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; String reverseName = ptr.getName().toString(); if (!reverseName.endsWith(".in-addr.arpa.")) { context.error("Unknown reverse address format: "+reverseName); continue; } String[] octets = reverseName.split("\\."); InternetAddress address = InternetAddress.fromString(octets[3]+"."+octets[2]+"."+octets[1]+"."+octets[0]); // XXX ipv6 String hostname = ptr.getTarget().toString(); /* verify the hostname is valid before adding it to model * (avoid configuration errors to pollute the model) */ if (HostnameMatcher.matches(hostname)) { Activator.getInstance().getDomainEntityFactory().createPTRRecord(realm, context.getSpaceId(), address, ptr.getTarget().toString()); } } else if (o instanceof MXRecord) { MXRecord mx = (MXRecord) o; Activator.getInstance().getDomainEntityFactory().createMXRecord(realm, context.getSpaceId(), domain.toString(), mx.getTarget().toString(), mx.getPriority()); } else if (o instanceof NSRecord) { NSRecord ns = (NSRecord) o; Activator.getInstance().getDomainEntityFactory().createNSRecord(realm, context.getSpaceId(), domain.toString(), ns.getTarget().toString()); } else { context.warning("Unhandled DNS record: "+o); } if (Thread.currentThread().isInterrupted()) { context.warning("Interrupted"); return; } } } private void setupToolOptions() throws ToolException { dns = (DNS) context.getConfiguration().get("dns"); if (dns == null) throw new RequiredOptionMissingException("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 domain name: '"+domainString+"'", e); } } }