1d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen// Copyright (c) 1999-2004 Brian Wellington (bwelling@xbill.org)
2d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
3d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpackage org.xbill.DNS;
4d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
5d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.net.*;
6d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.net.Inet6Address;
7d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
8d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
9d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Routines dealing with IP addresses.  Includes functions similar to
10d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * those in the java.net.InetAddress class.
11d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *
12d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @author Brian Wellington
13d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
14d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
15d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic final class Address {
16d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
17d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static final int IPv4 = 1;
18d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static final int IPv6 = 2;
19d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
20d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate
21d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenAddress() {}
22d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
23d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate static byte []
24d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenparseV4(String s) {
25d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	int numDigits;
26d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	int currentOctet;
27d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	byte [] values = new byte[4];
28d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	int currentValue;
29d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	int length = s.length();
30d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
31d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	currentOctet = 0;
32d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	currentValue = 0;
33d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	numDigits = 0;
34d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	for (int i = 0; i < length; i++) {
35d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		char c = s.charAt(i);
36d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (c >= '0' && c <= '9') {
37d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			/* Can't have more than 3 digits per octet. */
38d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			if (numDigits == 3)
39d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				return null;
40d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			/* Octets shouldn't start with 0, unless they are 0. */
41d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			if (numDigits > 0 && currentValue == 0)
42d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				return null;
43d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			numDigits++;
44d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			currentValue *= 10;
45d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			currentValue += (c - '0');
46d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			/* 255 is the maximum value for an octet. */
47d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			if (currentValue > 255)
48d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				return null;
49d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		} else if (c == '.') {
50d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			/* Can't have more than 3 dots. */
51d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			if (currentOctet == 3)
52d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				return null;
53d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			/* Two consecutive dots are bad. */
54d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			if (numDigits == 0)
55d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				return null;
56d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			values[currentOctet++] = (byte) currentValue;
57d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			currentValue = 0;
58d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			numDigits = 0;
59d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		} else
60d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			return null;
61d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
62d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	/* Must have 4 octets. */
63d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (currentOctet != 3)
64d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return null;
65d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	/* The fourth octet can't be empty. */
66d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (numDigits == 0)
67d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return null;
68d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	values[currentOctet] = (byte) currentValue;
69d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return values;
70d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
71d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
72d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate static byte []
73d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenparseV6(String s) {
74d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	int range = -1;
75d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	byte [] data = new byte[16];
76d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
77d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	String [] tokens = s.split(":", -1);
78d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
79d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	int first = 0;
80d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	int last = tokens.length - 1;
81d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
82d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (tokens[0].length() == 0) {
83d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		// If the first two tokens are empty, it means the string
84d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		// started with ::, which is fine.  If only the first is
85d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		// empty, the string started with :, which is bad.
86d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (last - first > 0 && tokens[1].length() == 0)
87d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			first++;
88d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		else
89d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			return null;
90d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
91d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
92d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (tokens[last].length() == 0) {
93d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		// If the last two tokens are empty, it means the string
94d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		// ended with ::, which is fine.  If only the last is
95d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		// empty, the string ended with :, which is bad.
96d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (last - first > 0 && tokens[last - 1].length() == 0)
97d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			last--;
98d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		else
99d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			return null;
100d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
101d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
102d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (last - first + 1 > 8)
103d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return null;
104d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
105d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	int i, j;
106d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	for (i = first, j = 0; i <= last; i++) {
107d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (tokens[i].length() == 0) {
108d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			if (range >= 0)
109d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				return null;
110d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			range = j;
111d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			continue;
112d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		}
113d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
114d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (tokens[i].indexOf('.') >= 0) {
115d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			// An IPv4 address must be the last component
116d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			if (i < last)
117d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				return null;
118d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			// There can't have been more than 6 components.
119d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			if (i > 6)
120d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				return null;
121d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			byte [] v4addr = Address.toByteArray(tokens[i], IPv4);
122d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			if (v4addr == null)
123d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				return null;
124d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			for (int k = 0; k < 4; k++)
125d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				data[j++] = v4addr[k];
126d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			break;
127d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		}
128d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
129d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		try {
130d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			for (int k = 0; k < tokens[i].length(); k++) {
131d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				char c = tokens[i].charAt(k);
132d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				if (Character.digit(c, 16) < 0)
133d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen					return null;
134d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			}
135d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			int x = Integer.parseInt(tokens[i], 16);
136d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			if (x > 0xFFFF || x < 0)
137d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				return null;
138d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			data[j++] = (byte)(x >>> 8);
139d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			data[j++] = (byte)(x & 0xFF);
140d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		}
141d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		catch (NumberFormatException e) {
142d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			return null;
143d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		}
144d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
145d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
146d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (j < 16 && range < 0)
147d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return null;
148d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
149d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (range >= 0) {
150d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		int empty = 16 - j;
151d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		System.arraycopy(data, range, data, range + empty, j - range);
152d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		for (i = range; i < range + empty; i++)
153d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			data[i] = 0;
154d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
155d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
156d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return data;
157d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
158d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
159d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
160d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Convert a string containing an IP address to an array of 4 or 16 integers.
161d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param s The address, in text format.
162d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param family The address family.
163d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The address
164d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
165d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static int []
166d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChentoArray(String s, int family) {
167d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	byte [] byteArray = toByteArray(s, family);
168d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (byteArray == null)
169d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return null;
170d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	int [] intArray = new int[byteArray.length];
171d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	for (int i = 0; i < byteArray.length; i++)
172d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		intArray[i] = byteArray[i] & 0xFF;
173d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return intArray;
174d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
175d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
176d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
177d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Convert a string containing an IPv4 address to an array of 4 integers.
178d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param s The address, in text format.
179d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The address
180d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
181d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static int []
182d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChentoArray(String s) {
183d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return toArray(s, IPv4);
184d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
185d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
186d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
187d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Convert a string containing an IP address to an array of 4 or 16 bytes.
188d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param s The address, in text format.
189d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param family The address family.
190d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The address
191d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
192d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static byte []
193d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChentoByteArray(String s, int family) {
194d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (family == IPv4)
195d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return parseV4(s);
196d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	else if (family == IPv6)
197d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return parseV6(s);
198d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	else
199d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		throw new IllegalArgumentException("unknown address family");
200d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
201d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
202d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
203d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Determines if a string contains a valid IP address.
204d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param s The string
205d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return Whether the string contains a valid IP address
206d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
207d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static boolean
208d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenisDottedQuad(String s) {
209d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	byte [] address = Address.toByteArray(s, IPv4);
210d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return (address != null);
211d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
212d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
213d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
214d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Converts a byte array containing an IPv4 address into a dotted quad string.
215d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param addr The array
216d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The string representation
217d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
218d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static String
219d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChentoDottedQuad(byte [] addr) {
220d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return ((addr[0] & 0xFF) + "." + (addr[1] & 0xFF) + "." +
221d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		(addr[2] & 0xFF) + "." + (addr[3] & 0xFF));
222d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
223d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
224d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
225d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Converts an int array containing an IPv4 address into a dotted quad string.
226d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param addr The array
227d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The string representation
228d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
229d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static String
230d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChentoDottedQuad(int [] addr) {
231d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return (addr[0] + "." + addr[1] + "." + addr[2] + "." + addr[3]);
232d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
233d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
234d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate static Record []
235d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenlookupHostName(String name) throws UnknownHostException {
236d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	try {
237d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		Record [] records = new Lookup(name).run();
238d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (records == null)
239d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			throw new UnknownHostException("unknown host");
240d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return records;
241d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
242d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	catch (TextParseException e) {
243d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		throw new UnknownHostException("invalid name");
244d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
245d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
246d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
247d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate static InetAddress
248d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenaddrFromRecord(String name, Record r) throws UnknownHostException {
249d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	ARecord a = (ARecord) r;
250d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return InetAddress.getByAddress(name, a.getAddress().getAddress());
251d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
252d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
253d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
254d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Determines the IP address of a host
255d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param name The hostname to look up
256d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The first matching IP address
257d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @exception UnknownHostException The hostname does not have any addresses
258d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
259d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static InetAddress
260d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetByName(String name) throws UnknownHostException {
261d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	try {
262d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return getByAddress(name);
263d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	} catch (UnknownHostException e) {
264d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		Record [] records = lookupHostName(name);
265d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return addrFromRecord(name, records[0]);
266d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
267d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
268d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
269d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
270d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Determines all IP address of a host
271d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param name The hostname to look up
272d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return All matching IP addresses
273d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @exception UnknownHostException The hostname does not have any addresses
274d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
275d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static InetAddress []
276d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetAllByName(String name) throws UnknownHostException {
277d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	try {
278d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		InetAddress addr = getByAddress(name);
279d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return new InetAddress[] {addr};
280d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	} catch (UnknownHostException e) {
281d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		Record [] records = lookupHostName(name);
282d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		InetAddress [] addrs = new InetAddress[records.length];
283d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		for (int i = 0; i < records.length; i++)
284d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			addrs[i] = addrFromRecord(name, records[i]);
285d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return addrs;
286d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
287d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
288d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
289d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
290d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Converts an address from its string representation to an IP address.
291d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * The address can be either IPv4 or IPv6.
292d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param addr The address, in string form
293d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The IP addresses
294d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @exception UnknownHostException The address is not a valid IP address.
295d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
296d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static InetAddress
297d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetByAddress(String addr) throws UnknownHostException {
298d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	byte [] bytes;
299d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	bytes = toByteArray(addr, IPv4);
300d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (bytes != null)
301d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return InetAddress.getByAddress(addr, bytes);
302d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	bytes = toByteArray(addr, IPv6);
303d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (bytes != null)
304d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return InetAddress.getByAddress(addr, bytes);
305d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	throw new UnknownHostException("Invalid address: " + addr);
306d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
307d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
308d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
309d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Converts an address from its string representation to an IP address in
310d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * a particular family.
311d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param addr The address, in string form
312d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param family The address family, either IPv4 or IPv6.
313d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The IP addresses
314d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @exception UnknownHostException The address is not a valid IP address in
315d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * the specified address family.
316d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
317d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static InetAddress
318d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetByAddress(String addr, int family) throws UnknownHostException {
319d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (family != IPv4 && family != IPv6)
320d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		throw new IllegalArgumentException("unknown address family");
321d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	byte [] bytes;
322d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	bytes = toByteArray(addr, family);
323d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (bytes != null)
324d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return InetAddress.getByAddress(addr, bytes);
325d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	throw new UnknownHostException("Invalid address: " + addr);
326d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
327d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
328d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
329d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Determines the hostname for an address
330d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param addr The address to look up
331d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The associated host name
332d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @exception UnknownHostException There is no hostname for the address
333d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
334d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static String
335d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetHostName(InetAddress addr) throws UnknownHostException {
336d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	Name name = ReverseMap.fromAddress(addr);
337d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	Record [] records = new Lookup(name, Type.PTR).run();
338d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (records == null)
339d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		throw new UnknownHostException("unknown address");
340d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	PTRRecord ptr = (PTRRecord) records[0];
341d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return ptr.getTarget().toString();
342d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
343d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
344d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
345d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the family of an InetAddress.
346d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param address The supplied address.
347d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The family, either IPv4 or IPv6.
348d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
349d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static int
350d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenfamilyOf(InetAddress address) {
351d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (address instanceof Inet4Address)
352d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return IPv4;
353d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (address instanceof Inet6Address)
354d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return IPv6;
355d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	throw new IllegalArgumentException("unknown address family");
356d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
357d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
358d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
359d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the length of an address in a particular family.
360d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param family The address family, either IPv4 or IPv6.
361d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The length of addresses in that family.
362d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
363d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static int
364d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenaddressLength(int family) {
365d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (family == IPv4)
366d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return 4;
367d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (family == IPv6)
368d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return 16;
369d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	throw new IllegalArgumentException("unknown address family");
370d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
371d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
372d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
373d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Truncates an address to the specified number of bits.  For example,
374d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * truncating the address 10.1.2.3 to 8 bits would yield 10.0.0.0.
375d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param address The source address
376d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param maskLength The number of bits to truncate the address to.
377d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
378d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static InetAddress
379d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chentruncate(InetAddress address, int maskLength)
380d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen{
381d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	int family = familyOf(address);
382d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	int maxMaskLength = addressLength(family) * 8;
383d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (maskLength < 0 || maskLength > maxMaskLength)
384d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		throw new IllegalArgumentException("invalid mask length");
385d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (maskLength == maxMaskLength)
386d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return address;
387d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	byte [] bytes = address.getAddress();
388d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	for (int i = maskLength / 8 + 1; i < bytes.length; i++)
389d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		bytes[i] = 0;
390d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	int maskBits = maskLength % 8;
391d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	int bitmask = 0;
392d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	for (int i = 0; i < maskBits; i++)
393d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		bitmask |= (1 << (7 - i));
394d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	bytes[maskLength / 8] &= bitmask;
395d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	try {
396d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return InetAddress.getByAddress(bytes);
397d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	} catch (UnknownHostException e) {
398d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		throw new IllegalArgumentException("invalid address");
399d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
400d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
401d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
402d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
403