2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
20 import java.io.IOException;
21 import java.io.ObjectInputStream;
22 import java.io.ObjectOutputStream;
23 import java.io.ObjectStreamField;
24 import java.util.Enumeration;
27 * An IPv6 address. See {@link InetAddress}.
29 public final class Inet6Address extends InetAddress {
31 private static final long serialVersionUID = 6880410070516793377L;
33 private static final int AF_INET6 = 10;
35 static final InetAddress ANY = new Inet6Address(new byte[]
36 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 });
37 static final InetAddress LOOPBACK = new Inet6Address(new byte[]
38 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, "localhost");
44 boolean scope_ifname_set;
51 transient NetworkInterface scopedIf;
53 Inet6Address(byte[] address) {
59 Inet6Address(byte[] address, String name) {
67 * Constructs an {@code InetAddress} representing the {@code address} and
68 * {@code name} and {@code scope_id}.
71 * the network address.
73 * the name associated with the address.
75 * the scope id for link- or site-local addresses.
77 Inet6Address(byte[] address, String name, int scope_id) {
81 this.scope_id = scope_id;
88 * Constructs an IPv6 address according to the given {@code host}, {@code
89 * addr} and {@code scope_id}.
92 * the host name associated with the address.
94 * the network address.
96 * the scope id for link- or site-local addresses.
97 * @return the Inet6Address instance representing the IP address.
98 * @throws UnknownHostException
99 * if the address is null or has an invalid length.
101 public static Inet6Address getByAddress(String host, byte[] addr,
102 int scope_id) throws UnknownHostException {
103 if (addr == null || addr.length != 16) {
104 throw new UnknownHostException("Illegal IPv6 address");
109 return new Inet6Address(addr, host, scope_id);
113 * Gets an IPv6 address instance according to the given {@code host},
114 * {@code addr} and {@code nif}. {@code scope_id} is set according to the
115 * given {@code nif} and the {@code addr} type (for example site-local or
119 * the hostname associated with the address.
121 * the network address.
123 * the network interface that this address is associated with.
124 * @return the Inet6Address instance representing the IP address.
125 * @throws UnknownHostException
126 * if the address is {@code null} or has an invalid length or
127 * the interface doesn't have a numeric scope id for the given
130 public static Inet6Address getByAddress(String host, byte[] addr,
131 NetworkInterface nif) throws UnknownHostException {
133 Inet6Address address = Inet6Address.getByAddress(host, addr, 0);
135 // if nif is null, nothing needs to be set.
140 // find the first address which matches the type addr,
141 // then set the scope_id, ifname and scopedIf.
142 Enumeration<InetAddress> addressList = nif.getInetAddresses();
143 while (addressList.hasMoreElements()) {
144 InetAddress ia = addressList.nextElement();
145 if (ia.getAddress().length == 16) {
146 Inet6Address v6ia = (Inet6Address) ia;
147 boolean isSameType = v6ia.compareLocalType(address);
149 address.scope_id_set = true;
150 address.scope_id = v6ia.scope_id;
151 address.scope_ifname_set = true;
152 address.ifname = nif.getName();
153 address.scopedIf = nif;
158 // if no address matches the type of addr, throws an
159 // UnknownHostException.
160 if (!address.scope_id_set) {
161 throw new UnknownHostException("Scope id not found for the given address");
167 * Returns {@code true} if one of following cases applies:
170 * <li>both addresses are site local</li>
171 * <li>both addresses are link local</li>
172 * <li>{@code ia} is neither site local nor link local</li>
175 private boolean compareLocalType(Inet6Address ia) {
176 if (ia.isSiteLocalAddress() && isSiteLocalAddress()) {
179 if (ia.isLinkLocalAddress() && isLinkLocalAddress()) {
182 if (!ia.isSiteLocalAddress() && !ia.isLinkLocalAddress()) {
189 * Constructs an {@code InetAddress} representing the {@code address} and
193 * the network address.
195 * the scope id for link- or site-local addresses.
197 Inet6Address(byte[] address, int scope_id) {
199 this.scope_id = scope_id;
206 * Returns whether this address is an IP multicast address or not. Valid
207 * IPv6 multicast addresses are binary prefixed with 11111111 or FF (hex).
209 * @return {@code true} if this address is in the multicast group, {@code
213 public boolean isMulticastAddress() {
214 // Multicast addresses are prefixed with 11111111 (255)
215 return ipaddress[0] == -1;
219 * Returns whether this address is a unspecified wildcard address "::" or
222 * @return {@code true} if this instance represents a wildcard address,
223 * {@code false} otherwise.
226 public boolean isAnyLocalAddress() {
227 for (int i = 0; i < ipaddress.length; i++) {
228 if (ipaddress[i] != 0) {
236 * Returns whether this address is the loopback address or not. The only
237 * valid IPv6 loopback address is "::1".
239 * @return {@code true} if this instance represents the loopback address,
240 * {@code false} otherwise.
243 public boolean isLoopbackAddress() {
245 // The last word must be 1
246 if (ipaddress[15] != 1) {
250 // All other words must be 0
251 for (int i = 0; i < 15; i++) {
252 if (ipaddress[i] != 0) {
261 * Returns whether this address is a link-local address or not. A valid IPv6
262 * link-local address is prefixed with 1111111010.
264 * @return {@code true} if this instance represents a link-local address,
265 * {@code false} otherwise.
268 public boolean isLinkLocalAddress() {
270 // the first 10 bits need to be 1111111010 (1018)
271 return (ipaddress[0] == -2) && ((ipaddress[1] & 255) >>> 6) == 2;
275 * Returns whether this address is a site-local address or not. A valid IPv6
276 * site-local address is prefixed with 1111111011.
278 * @return {@code true} if this instance represents a site-local address,
279 * {@code false} otherwise.
282 public boolean isSiteLocalAddress() {
284 // the first 10 bits need to be 1111111011 (1019)
285 return (ipaddress[0] == -2) && ((ipaddress[1] & 255) >>> 6) == 3;
289 * Returns whether this address is a global multicast address or not. A
290 * valid IPv6 global multicast address is 11111111xxxx1110 or FF0E hex.
292 * @return {@code true} if this instance represents a global multicast
293 * address, {@code false} otherwise.
296 public boolean isMCGlobal() {
297 // the first byte should be 0xFF and the lower 4 bits
298 // of the second byte should be 0xE
299 return (ipaddress[0] == -1) && (ipaddress[1] & 15) == 14;
303 * Returns whether this address is a node-local multicast address or not. A
304 * valid IPv6 node-local multicast address is prefixed with
307 * @return {@code true} if this instance represents a node-local multicast
308 * address, {@code false} otherwise.
311 public boolean isMCNodeLocal() {
312 // the first byte should be 0xFF and the lower 4 bits
313 // of the second byte should be 0x1
314 return (ipaddress[0] == -1) && (ipaddress[1] & 15) == 1;
318 * Returns whether this address is a link-local multicast address or not. A
319 * valid IPv6 link-local multicast address is prefixed with
322 * @return {@code true} if this instance represents a link-local multicast
323 * address, {@code false} otherwise.
326 public boolean isMCLinkLocal() {
327 // the first byte should be 0xFF and the lower 4 bits
328 // of the second byte should be 0x2
329 return (ipaddress[0] == -1) && (ipaddress[1] & 15) == 2;
333 * Returns whether this address is a site-local multicast address or not. A
334 * valid IPv6 site-local multicast address is prefixed with
337 * @return {@code true} if this instance represents a site-local multicast
338 * address, {@code false} otherwise.
341 public boolean isMCSiteLocal() {
342 // the first byte should be 0xFF and the lower 4 bits
343 // of the second byte should be 0x5
344 return (ipaddress[0] == -1) && (ipaddress[1] & 15) == 5;
348 * Returns whether this address is a organization-local multicast address or
349 * not. A valid IPv6 org-local multicast address is prefixed with
352 * @return {@code true} if this instance represents a org-local multicast
353 * address, {@code false} otherwise.
356 public boolean isMCOrgLocal() {
357 // the first byte should be 0xFF and the lower 4 bits
358 // of the second byte should be 0x8
359 return (ipaddress[0] == -1) && (ipaddress[1] & 15) == 8;
362 // BEGIN android-removed
363 // public String getHostAddress() {
365 // END android-removed
368 * Gets the scope id as a number if this address is linked to an interface.
369 * Otherwise returns {@code 0}.
371 * @return the scope_id of this address or 0 when not linked with an
374 public int getScopeId() {
382 * Gets the network interface if this address is instanced with a scoped
383 * network interface. Otherwise returns {@code null}.
385 * @return the scoped network interface of this address.
387 public NetworkInterface getScopedInterface() {
388 if (scope_ifname_set) {
394 // BEGIN android-removed
395 // public int hashCode() {}
396 // END android-removed
398 // BEGIN android-removed
399 // public boolean equals(Object obj) {}
400 // END android-removed
403 * Returns whether this address is IPv4 compatible or not. An IPv4
404 * compatible address is prefixed with 96 bits of 0's. The last 32-bits are
405 * varied corresponding with the 32-bit IPv4 address space.
407 * @return {@code true} if this instance represents an IPv4 compatible
408 * address, {@code false} otherwise.
410 public boolean isIPv4CompatibleAddress() {
411 for (int i = 0; i < 12; i++) {
412 if (ipaddress[i] != 0) {
419 private static final ObjectStreamField[] serialPersistentFields = {
420 new ObjectStreamField("ipaddress", new byte[0].getClass()),
421 new ObjectStreamField("scope_id", Integer.TYPE),
422 new ObjectStreamField("scope_id_set", Boolean.TYPE),
423 new ObjectStreamField("scope_ifname_set", Boolean.TYPE),
424 new ObjectStreamField("ifname", String.class), };
426 private void writeObject(ObjectOutputStream stream) throws IOException {
427 ObjectOutputStream.PutField fields = stream.putFields();
428 if (ipaddress == null) {
429 fields.put("ipaddress", null);
431 fields.put("ipaddress", ipaddress);
434 fields.put("scope_id", scope_id);
435 fields.put("scope_id_set", scope_id_set);
436 fields.put("scope_ifname_set", scope_ifname_set);
437 fields.put("ifname", ifname);
438 stream.writeFields();
441 private void readObject(ObjectInputStream stream) throws IOException,
442 ClassNotFoundException {
443 ObjectInputStream.GetField fields = stream.readFields();
444 ipaddress = (byte[]) fields.get("ipaddress", null);
445 scope_id = fields.get("scope_id", 0);
446 scope_id_set = fields.get("scope_id_set", false);
447 ifname = (String) fields.get("ifname", null);
448 scope_ifname_set = fields.get("scope_ifname_set", false);
449 if (scope_ifname_set && null != ifname) {
450 scopedIf = NetworkInterface.getByName(ifname);
455 * Returns a string containing a concise, human-readable description of this
458 * @return the description, as host/address.
461 public String toString() {
462 if (ifname != null) {
463 return super.toString() + "%" + ifname;
466 return super.toString() + "%" + scope_id;
468 return super.toString();