// Copyright (c) 2003-2004 Brian Wellington (bwelling@xbill.org) package io.milton.dns.record; import io.milton.dns.Address; import io.milton.dns.Name; import io.milton.dns.TextParseException; import java.net.*; /** * A set functions designed to deal with DNS names used in reverse mappings. * For the IPv4 address a.b.c.d, the reverse map name is d.c.b.a.in-addr.arpa. * For an IPv6 address, the reverse map name is ...ip6.arpa. * * @author Brian Wellington */ public final class ReverseMap { private static final Name inaddr4 = Name.fromConstantString("in-addr.arpa."); private static final Name inaddr6 = Name.fromConstantString("ip6.arpa."); /* Otherwise the class could be instantiated */ private ReverseMap() {} /** * Creates a reverse map name corresponding to an address contained in * an array of 4 bytes (for an IPv4 address) or 16 bytes (for an IPv6 address). * @param addr The address from which to build a name. * @return The name corresponding to the address in the reverse map. */ public static Name fromAddress(byte [] addr) { if (addr.length != 4 && addr.length != 16) throw new IllegalArgumentException("array must contain " + "4 or 16 elements"); StringBuilder sb = new StringBuilder(); if (addr.length == 4) { for (int i = addr.length - 1; i >= 0; i--) { sb.append(addr[i] & 0xFF); if (i > 0) sb.append("."); } } else { int [] nibbles = new int[2]; for (int i = addr.length - 1; i >= 0; i--) { nibbles[0] = (addr[i] & 0xFF) >> 4; nibbles[1] = (addr[i] & 0xFF) & 0xF; for (int j = nibbles.length - 1; j >= 0; j--) { sb.append(Integer.toHexString(nibbles[j])); if (i > 0 || j > 0) sb.append("."); } } } try { if (addr.length == 4) return Name.fromString(sb.toString(), inaddr4); else return Name.fromString(sb.toString(), inaddr6); } catch (TextParseException e) { throw new IllegalStateException("name cannot be invalid"); } } /** * Creates a reverse map name corresponding to an address contained in * an array of 4 integers between 0 and 255 (for an IPv4 address) or 16 * integers between 0 and 255 (for an IPv6 address). * @param addr The address from which to build a name. * @return The name corresponding to the address in the reverse map. */ public static Name fromAddress(int [] addr) { byte [] bytes = new byte[addr.length]; for (int i = 0; i < addr.length; i++) { if (addr[i] < 0 || addr[i] > 0xFF) throw new IllegalArgumentException("array must " + "contain values " + "between 0 and 255"); bytes[i] = (byte) addr[i]; } return fromAddress(bytes); } /** * Creates a reverse map name corresponding to an address contained in * an InetAddress. * @param addr The address from which to build a name. * @return The name corresponding to the address in the reverse map. */ public static Name fromAddress(InetAddress addr) { return fromAddress(addr.getAddress()); } /** * Creates a reverse map name corresponding to an address contained in * a String. * @param addr The address from which to build a name. * @return The name corresponding to the address in the reverse map. * @throws UnknownHostException The string does not contain a valid address. */ public static Name fromAddress(String addr, int family) throws UnknownHostException { byte [] array = Address.toByteArray(addr, family); if (array == null) throw new UnknownHostException("Invalid IP address"); return fromAddress(array); } /** * Creates a reverse map name corresponding to an address contained in * a String. * @param addr The address from which to build a name. * @return The name corresponding to the address in the reverse map. * @throws UnknownHostException The string does not contain a valid address. */ public static Name fromAddress(String addr) throws UnknownHostException { byte [] array = Address.toByteArray(addr, Address.IPv4); if (array == null) array = Address.toByteArray(addr, Address.IPv6); if (array == null) throw new UnknownHostException("Invalid IP address"); return fromAddress(array); } }