/* * Copyright 2009-2014 Jagornet Technologies, LLC. All Rights Reserved. * * This software is the proprietary information of Jagornet Technologies, LLC. * Use is subject to license terms. * */ /* * This file ReverseDdnsUpdate.java is part of Jagornet DHCP. * * Jagornet DHCP is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Jagornet DHCP is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Jagornet DHCP. If not, see <http://www.gnu.org/licenses/>. * */ package com.jagornet.dhcp.server.request.ddns; import java.io.IOException; import java.net.Inet6Address; import java.net.InetAddress; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.xbill.DNS.DClass; import org.xbill.DNS.Message; import org.xbill.DNS.Name; import org.xbill.DNS.PTRRecord; import org.xbill.DNS.Rcode; import org.xbill.DNS.Resolver; import org.xbill.DNS.TextParseException; import org.xbill.DNS.Update; /** * The Class ReverseDdnsUpdate. * * @author A. Gregory Rabil */ public class ReverseDdnsUpdate extends DdnsUpdate { /** The log. */ private static Logger log = LoggerFactory.getLogger(ReverseDdnsUpdate.class); /** The rev zone bit length. */ protected int revZoneBitLength = 64; // default protected int v4RevZoneBitLength = 24; /** * Instantiates a new reverse ddns update. * * @param fqdn the fqdn * @param inetAddr the inet addr * @param duid the duid */ public ReverseDdnsUpdate(String fqdn, InetAddress inetAddr, byte[] duid) { super(fqdn, inetAddr, duid); } /* (non-Javadoc) * @see com.jagornet.dhcpv6.server.request.ddns.DdnsUpdate#sendAdd() */ public boolean sendAdd() throws TextParseException, IOException { boolean rc = false; Resolver res = createResolver(); String revIp = buildReverseIpString(); Name owner = new Name(revIp.toString()); PTRRecord ptr = new PTRRecord(owner, DClass.IN, ttl, new Name(fqdn)); Name _zone = buildZoneName(revIp); Update update = new Update(_zone); update.delete(owner); update.add(ptr); if (log.isDebugEnabled()) { log.debug("Sending reverse DDNS update (replace) to server=" + server + ":\n" + update.toString()); } else if (log.isInfoEnabled()) { log.info("Sending reverse DDNS update (replace): " + ptr.toString()); } Message response = res.send(update); if (response.getRcode() == Rcode.NOERROR) { log.info("Reverse DDNS update (replace) succeeded: " + ptr.toString()); rc = true; } else { log.error("Reverse DDNS update (replace) failed (rcode=" + Rcode.string(response.getRcode()) + "): " + ptr.toString()); } return rc; } /* (non-Javadoc) * @see com.jagornet.dhcpv6.server.request.ddns.DdnsUpdate#sendDelete() */ public boolean sendDelete() throws TextParseException, IOException { boolean rc = false; Resolver res = createResolver(); String revIp = buildReverseIpString(); Name owner = new Name(revIp); PTRRecord ptr = new PTRRecord(owner, DClass.IN, 0, new Name(fqdn)); Name _zone = buildZoneName(revIp); Update update = new Update(_zone); update.delete(ptr); if (log.isDebugEnabled()) { log.debug("Sending reverse DDNS update (delete) to server=" + server + ":\n" + update.toString()); } else if (log.isInfoEnabled()) { log.info("Sending reverse DDNS update (delete): " + ptr.toString()); } Message response = res.send(update); if (response.getRcode() == Rcode.NOERROR) { log.info("Reverse DDNS update (delete) succeeded: " + ptr.toString()); rc = true; } else { log.error("Reverse DDNS update (delete) failed (rcode=" + Rcode.string(response.getRcode()) + "): " + ptr.toString()); } return rc; } /** * Builds the reverse ip string. * * @return the string */ protected String buildReverseIpString() { if (inetAddr instanceof Inet6Address) { String[] flds = inetAddr.getHostAddress().split(":"); if (flds.length != 8) { throw new IllegalStateException("Invalid IPv6 Address: " + inetAddr.getHostAddress()); } StringBuilder expanded = new StringBuilder(); for (int i=0; i<8; i++) { StringBuilder sb = new StringBuilder(); if (flds[i].length() < 4) { for (int j=0; j<4-flds[i].length(); j++) { sb.append('0'); } } sb.append(flds[i]); expanded.append(sb); } StringBuilder reversed = expanded.reverse(); StringBuilder revIp = new StringBuilder(); for (int i=0; i<reversed.length(); i++) { revIp.append(reversed.substring(i, i+1)); revIp.append('.'); } revIp.append("ip6.arpa."); return revIp.toString(); } else { String[] flds = inetAddr.getHostAddress().split("\\."); if (flds.length != 4) { throw new IllegalStateException("Invalid IPv4 Address: " + inetAddr.getHostAddress()); } StringBuilder revIp = new StringBuilder(); for (int i=3; i>=0; i--) { revIp.append(flds[i]); revIp.append('.'); } revIp.append("in-addr.arpa."); return revIp.toString(); } } /** * Builds the zone name. * * @param revIp the rev ip * * @return the name * * @throws TextParseException the text parse exception */ private Name buildZoneName(String revIp) throws TextParseException { Name _zone = null; if (zone != null) { _zone = new Name(zone); } else { if (inetAddr instanceof Inet6Address) { int p = 64 - (revZoneBitLength/2); if (p < 0) p = 64; _zone = new Name(revIp.substring(p)); } else { _zone = new Name(revIp); int c = 0; if (v4RevZoneBitLength <= 8) c = 3; else if (v4RevZoneBitLength <= 16) c = 2; else c = 1; for (int i=0; i<c; i++) { int p = _zone.toString().indexOf('.'); _zone = new Name(_zone.toString().substring(p+1)); } } } return _zone; } /** * Gets the rev zone bit length. * * @return the rev zone bit length */ public int getRevZoneBitLength() { return revZoneBitLength; } /** * Sets the rev zone bit length. * * @param revZoneBitLength the new rev zone bit length */ public void setRevZoneBitLength(int revZoneBitLength) { this.revZoneBitLength = revZoneBitLength; } public int getV4RevZoneBitLength() { return v4RevZoneBitLength; } public void setV4RevZoneBitLength(int v4RevZoneBitLength) { this.v4RevZoneBitLength = v4RevZoneBitLength; } }