org.xbill.DNS.Address Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of org.apache.servicemix.bundles.dnsjava
Show all versions of org.apache.servicemix.bundles.dnsjava
This OSGi bundle wraps ${pkgArtifactId} ${pkgVersion} jar file.
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 1999-2004 Brian Wellington ([email protected])
package org.xbill.DNS;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
* Routines dealing with IP addresses. Includes functions similar to those in the
* java.net.InetAddress class.
*
* @author Brian Wellington
*/
public final class Address {
public static final int IPv4 = 1;
public static final int IPv6 = 2;
private Address() {}
private static byte[] parseV4(String s) {
int numDigits;
int currentOctet;
byte[] values = new byte[4];
int currentValue;
int length = s.length();
currentOctet = 0;
currentValue = 0;
numDigits = 0;
for (int i = 0; i < length; i++) {
char c = s.charAt(i);
if (c >= '0' && c <= '9') {
/* Can't have more than 3 digits per octet. */
if (numDigits == 3) {
return null;
}
/* Octets shouldn't start with 0, unless they are 0. */
if (numDigits > 0 && currentValue == 0) {
return null;
}
numDigits++;
currentValue *= 10;
currentValue += c - '0';
/* 255 is the maximum value for an octet. */
if (currentValue > 255) {
return null;
}
} else if (c == '.') {
/* Can't have more than 3 dots. */
if (currentOctet == 3) {
return null;
}
/* Two consecutive dots are bad. */
if (numDigits == 0) {
return null;
}
values[currentOctet++] = (byte) currentValue;
currentValue = 0;
numDigits = 0;
} else {
return null;
}
}
/* Must have 4 octets. */
if (currentOctet != 3) {
return null;
}
/* The fourth octet can't be empty. */
if (numDigits == 0) {
return null;
}
values[currentOctet] = (byte) currentValue;
return values;
}
private static byte[] parseV6(String s) {
int range = -1;
byte[] data = new byte[16];
String[] tokens = s.split(":", -1);
int first = 0;
int last = tokens.length - 1;
if (tokens[0].length() == 0) {
// If the first two tokens are empty, it means the string
// started with ::, which is fine. If only the first is
// empty, the string started with :, which is bad.
if (last - first > 0 && tokens[1].length() == 0) {
first++;
} else {
return null;
}
}
if (tokens[last].length() == 0) {
// If the last two tokens are empty, it means the string
// ended with ::, which is fine. If only the last is
// empty, the string ended with :, which is bad.
if (last - first > 0 && tokens[last - 1].length() == 0) {
last--;
} else {
return null;
}
}
if (last - first + 1 > 8) {
return null;
}
int i, j;
for (i = first, j = 0; i <= last; i++) {
if (tokens[i].length() == 0) {
if (range >= 0) {
return null;
}
range = j;
continue;
}
if (tokens[i].indexOf('.') >= 0) {
// An IPv4 address must be the last component
if (i < last) {
return null;
}
// There can't have been more than 6 components.
if (i > 6) {
return null;
}
byte[] v4addr = Address.toByteArray(tokens[i], IPv4);
if (v4addr == null) {
return null;
}
for (int k = 0; k < 4; k++) {
data[j++] = v4addr[k];
}
break;
}
try {
for (int k = 0; k < tokens[i].length(); k++) {
char c = tokens[i].charAt(k);
if (Character.digit(c, 16) < 0) {
return null;
}
}
int x = Integer.parseInt(tokens[i], 16);
if (x > 0xFFFF || x < 0) {
return null;
}
data[j++] = (byte) (x >>> 8);
data[j++] = (byte) (x & 0xFF);
} catch (NumberFormatException e) {
return null;
}
}
if (j < 16 && range < 0) {
return null;
}
if (range >= 0) {
int empty = 16 - j;
System.arraycopy(data, range, data, range + empty, j - range);
for (i = range; i < range + empty; i++) {
data[i] = 0;
}
}
return data;
}
/**
* Convert a string containing an IP address to an array of 4 or 16 integers.
*
* @param s The address, in text format.
* @param family The address family.
* @return The address
*/
public static int[] toArray(String s, int family) {
byte[] byteArray = toByteArray(s, family);
if (byteArray == null) {
return null;
}
int[] intArray = new int[byteArray.length];
for (int i = 0; i < byteArray.length; i++) {
intArray[i] = byteArray[i] & 0xFF;
}
return intArray;
}
/**
* Convert a string containing an IPv4 address to an array of 4 integers.
*
* @param s The address, in text format.
* @return The address
*/
public static int[] toArray(String s) {
return toArray(s, IPv4);
}
/**
* Convert a string containing an IP address to an array of 4 or 16 bytes.
*
* @param s The address, in text format.
* @param family The address family.
* @return The address
*/
public static byte[] toByteArray(String s, int family) {
if (family == IPv4) {
return parseV4(s);
} else if (family == IPv6) {
return parseV6(s);
} else {
throw new IllegalArgumentException("unknown address family");
}
}
/**
* Determines if a string contains a valid IP address.
*
* @param s The string
* @return Whether the string contains a valid IP address
*/
public static boolean isDottedQuad(String s) {
byte[] address = Address.toByteArray(s, IPv4);
return address != null;
}
/**
* Converts a byte array containing an IPv4 address into a dotted quad string.
*
* @param addr The array
* @return The string representation
*/
public static String toDottedQuad(byte[] addr) {
return (addr[0] & 0xFF)
+ "."
+ (addr[1] & 0xFF)
+ "."
+ (addr[2] & 0xFF)
+ "."
+ (addr[3] & 0xFF);
}
/**
* Converts an int array containing an IPv4 address into a dotted quad string.
*
* @param addr The array
* @return The string representation
*/
public static String toDottedQuad(int[] addr) {
return addr[0] + "." + addr[1] + "." + addr[2] + "." + addr[3];
}
private static Record[] lookupHostName(String name, boolean all) throws UnknownHostException {
try {
Lookup lookup = new Lookup(name, Type.A);
Record[] a = lookup.run();
if (a == null) {
if (lookup.getResult() == Lookup.TYPE_NOT_FOUND) {
Record[] aaaa = new Lookup(name, Type.AAAA).run();
if (aaaa != null) {
return aaaa;
}
}
throw new UnknownHostException(
"<" + name + "> could not be resolved: " + lookup.getErrorString());
}
if (!all) {
return a;
}
Record[] aaaa = new Lookup(name, Type.AAAA).run();
if (aaaa == null) {
return a;
}
Record[] merged = new Record[a.length + aaaa.length];
System.arraycopy(a, 0, merged, 0, a.length);
System.arraycopy(aaaa, 0, merged, a.length, aaaa.length);
return merged;
} catch (TextParseException e) {
throw new UnknownHostException("<" + name + "> is invalid: " + e.getMessage());
}
}
private static InetAddress addrFromRecord(String name, Record r) throws UnknownHostException {
InetAddress addr;
if (r instanceof ARecord) {
addr = ((ARecord) r).getAddress();
} else {
addr = ((AAAARecord) r).getAddress();
}
return InetAddress.getByAddress(name, addr.getAddress());
}
/**
* Determines the IP address of a host
*
* @param name The hostname to look up
* @return The first matching IP address
* @exception UnknownHostException The hostname does not have any addresses
*/
public static InetAddress getByName(String name) throws UnknownHostException {
try {
return getByAddress(name);
} catch (UnknownHostException e) {
Record[] records = lookupHostName(name, false);
return addrFromRecord(name, records[0]);
}
}
/**
* Determines all IP address of a host
*
* @param name The hostname to look up
* @return All matching IP addresses
* @exception UnknownHostException The hostname does not have any addresses
*/
public static InetAddress[] getAllByName(String name) throws UnknownHostException {
try {
InetAddress addr = getByAddress(name);
return new InetAddress[] {addr};
} catch (UnknownHostException e) {
Record[] records = lookupHostName(name, true);
InetAddress[] addrs = new InetAddress[records.length];
for (int i = 0; i < records.length; i++) {
addrs[i] = addrFromRecord(name, records[i]);
}
return addrs;
}
}
/**
* Converts an address from its string representation to an IP address. The address can be either
* IPv4 or IPv6.
*
* @param addr The address, in string form
* @return The IP addresses
* @exception UnknownHostException The address is not a valid IP address.
*/
public static InetAddress getByAddress(String addr) throws UnknownHostException {
byte[] bytes;
bytes = toByteArray(addr, IPv4);
if (bytes != null) {
return InetAddress.getByAddress(addr, bytes);
}
bytes = toByteArray(addr, IPv6);
if (bytes != null) {
return InetAddress.getByAddress(addr, bytes);
}
throw new UnknownHostException("Invalid address: " + addr);
}
/**
* Converts an address from its string representation to an IP address in a particular family.
*
* @param addr The address, in string form
* @param family The address family, either IPv4 or IPv6.
* @return The IP addresses
* @exception UnknownHostException The address is not a valid IP address in the specified address
* family.
*/
public static InetAddress getByAddress(String addr, int family) throws UnknownHostException {
if (family != IPv4 && family != IPv6) {
throw new IllegalArgumentException("unknown address family");
}
byte[] bytes;
bytes = toByteArray(addr, family);
if (bytes != null) {
return InetAddress.getByAddress(addr, bytes);
}
throw new UnknownHostException("Invalid address: " + addr);
}
/**
* Determines the hostname for an address
*
* @param addr The address to look up
* @return The associated host name
* @exception UnknownHostException There is no hostname for the address
*/
public static String getHostName(InetAddress addr) throws UnknownHostException {
Name name = ReverseMap.fromAddress(addr);
Record[] records = new Lookup(name, Type.PTR).run();
if (records == null) {
throw new UnknownHostException("unknown address: " + name);
}
PTRRecord ptr = (PTRRecord) records[0];
return ptr.getTarget().toString();
}
/**
* Returns the family of an InetAddress.
*
* @param address The supplied address.
* @return The family, either IPv4 or IPv6.
*/
public static int familyOf(InetAddress address) {
if (address instanceof Inet4Address) {
return IPv4;
}
if (address instanceof Inet6Address) {
return IPv6;
}
throw new IllegalArgumentException("unknown address family");
}
/**
* Returns the length of an address in a particular family.
*
* @param family The address family, either IPv4 or IPv6.
* @return The length of addresses in that family.
*/
public static int addressLength(int family) {
if (family == IPv4) {
return 4;
}
if (family == IPv6) {
return 16;
}
throw new IllegalArgumentException("unknown address family");
}
/**
* Truncates an address to the specified number of bits. For example, truncating the address
* 10.1.2.3 to 8 bits would yield 10.0.0.0.
*
* @param address The source address
* @param maskLength The number of bits to truncate the address to.
*/
public static InetAddress truncate(InetAddress address, int maskLength) {
int family = familyOf(address);
int maxMaskLength = addressLength(family) * 8;
if (maskLength < 0 || maskLength > maxMaskLength) {
throw new IllegalArgumentException("invalid mask length");
}
if (maskLength == maxMaskLength) {
return address;
}
byte[] bytes = address.getAddress();
for (int i = maskLength / 8 + 1; i < bytes.length; i++) {
bytes[i] = 0;
}
int maskBits = maskLength % 8;
int bitmask = 0;
for (int i = 0; i < maskBits; i++) {
bitmask |= 1 << (7 - i);
}
bytes[maskLength / 8] &= bitmask;
try {
return InetAddress.getByAddress(bytes);
} catch (UnknownHostException e) {
throw new IllegalArgumentException("invalid address");
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy