1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/*
2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Licensed to the Apache Software Foundation (ASF) under one or more
3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  contributor license agreements.  See the NOTICE file distributed with
4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  this work for additional information regarding copyright ownership.
5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  The ASF licenses this file to You under the Apache License, Version 2.0
6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  (the "License"); you may not use this file except in compliance with
7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  the License.  You may obtain a copy of the License at
8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *     http://www.apache.org/licenses/LICENSE-2.0
10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Unless required by applicable law or agreed to in writing, software
12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  distributed under the License is distributed on an "AS IS" BASIS,
13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  See the License for the specific language governing permissions and
15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  limitations under the License.
16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage java.net;
19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.IOException;
21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.ObjectInputStream;
22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.ObjectOutputStream;
23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.ObjectStreamField;
24fbbae9740d65620b417b85576aa0d6c7daf4ba34Elliott Hughesimport java.util.Arrays;
25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Enumeration;
2632b0fa4d1a31ef07bc4297c615f0fe50e9aa7c21Elliott Hughesimport static libcore.io.OsConstants.*;
27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
294adff24306c86433ce4f771da8489a574e63318eElliott Hughes * An IPv6 address. See {@link InetAddress}.
30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic final class Inet6Address extends InetAddress {
32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final long serialVersionUID = 6880410070516793377L;
34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
354f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes    /**
364f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes     * @hide
374f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes     */
384f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes    public static final InetAddress ANY =
39fbbae9740d65620b417b85576aa0d6c7daf4ba34Elliott Hughes            new Inet6Address(new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, null, 0);
404f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes
414f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes    /**
424f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes     * @hide
434f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes     */
444f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes    public static final InetAddress LOOPBACK =
45fbbae9740d65620b417b85576aa0d6c7daf4ba34Elliott Hughes            new Inet6Address(new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
46fbbae9740d65620b417b85576aa0d6c7daf4ba34Elliott Hughes                    "localhost", 0);
47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
48f02f9397fd5984f476e056ddb8c04db9af9a15a0Elliott Hughes    private boolean scope_id_set;
49f02f9397fd5984f476e056ddb8c04db9af9a15a0Elliott Hughes    private int scope_id;
50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
51f02f9397fd5984f476e056ddb8c04db9af9a15a0Elliott Hughes    private boolean scope_ifname_set;
52f02f9397fd5984f476e056ddb8c04db9af9a15a0Elliott Hughes    private String ifname;
53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constructs an {@code InetAddress} representing the {@code address} and
56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code name} and {@code scope_id}.
57f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param address
59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the network address.
60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param name
61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the name associated with the address.
62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param scope_id
63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the scope id for link- or site-local addresses.
64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
654f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes    Inet6Address(byte[] ipaddress, String hostName, int scope_id) {
664f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes        super(AF_INET6, ipaddress, hostName);
67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.scope_id = scope_id;
68fbbae9740d65620b417b85576aa0d6c7daf4ba34Elliott Hughes        this.scope_id_set = (scope_id != 0);
69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constructs an IPv6 address according to the given {@code host}, {@code
73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * addr} and {@code scope_id}.
74f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param host
76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the host name associated with the address.
77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param addr
78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the network address.
79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param scope_id
80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the scope id for link- or site-local addresses.
81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the Inet6Address instance representing the IP address.
82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws UnknownHostException
83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the address is null or has an invalid length.
84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
85fbbae9740d65620b417b85576aa0d6c7daf4ba34Elliott Hughes    public static Inet6Address getByAddress(String host, byte[] addr, int scope_id)
86fbbae9740d65620b417b85576aa0d6c7daf4ba34Elliott Hughes            throws UnknownHostException {
87b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes        if (addr == null || addr.length != 16) {
88fbbae9740d65620b417b85576aa0d6c7daf4ba34Elliott Hughes            throw new UnknownHostException("Not an IPv6 address: " + Arrays.toString(addr));
89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (scope_id < 0) {
91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            scope_id = 0;
92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
93fbbae9740d65620b417b85576aa0d6c7daf4ba34Elliott Hughes        // TODO: should we clone 'addr'?
94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return new Inet6Address(addr, host, scope_id);
95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Gets an IPv6 address instance according to the given {@code host},
99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code addr} and {@code nif}. {@code scope_id} is set according to the
100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * given {@code nif} and the {@code addr} type (for example site-local or
101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * link-local).
102f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param host
104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the hostname associated with the address.
105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param addr
106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the network address.
107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param nif
108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the network interface that this address is associated with.
109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the Inet6Address instance representing the IP address.
110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws UnknownHostException
111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the address is {@code null} or has an invalid length or
112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             the interface doesn't have a numeric scope id for the given
113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             address type.
114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static Inet6Address getByAddress(String host, byte[] addr,
116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            NetworkInterface nif) throws UnknownHostException {
117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        Inet6Address address = Inet6Address.getByAddress(host, addr, 0);
119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // if nif is null, nothing needs to be set.
121b46dab348e2007bc08abaf7ecae34d89a2474e50Elliott Hughes        if (nif == null) {
122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return address;
123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // find the first address which matches the type addr,
126a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        // then set the scope_id and ifname.
127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        Enumeration<InetAddress> addressList = nif.getInetAddresses();
128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        while (addressList.hasMoreElements()) {
129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            InetAddress ia = addressList.nextElement();
130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (ia.getAddress().length == 16) {
131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                Inet6Address v6ia = (Inet6Address) ia;
132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                boolean isSameType = v6ia.compareLocalType(address);
133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (isSameType) {
134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    address.scope_id_set = true;
135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    address.scope_id = v6ia.scope_id;
136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    address.scope_ifname_set = true;
137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    address.ifname = nif.getName();
138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    break;
139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // if no address matches the type of addr, throws an
143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // UnknownHostException.
144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!address.scope_id_set) {
145fbbae9740d65620b417b85576aa0d6c7daf4ba34Elliott Hughes            throw new UnknownHostException("Scope id not found for address: " + Arrays.toString(addr));
146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return address;
148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns {@code true} if one of following cases applies:
152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <p>
153f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * <ol>
154f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *  <li>both addresses are site local</li>
155f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *  <li>both addresses are link local</li>
156f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *  <li>{@code ia} is neither site local nor link local</li>
157f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * </ol>
158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private boolean compareLocalType(Inet6Address ia) {
160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (ia.isSiteLocalAddress() && isSiteLocalAddress()) {
161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return true;
162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (ia.isLinkLocalAddress() && isLinkLocalAddress()) {
164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return true;
165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!ia.isSiteLocalAddress() && !ia.isLinkLocalAddress()) {
167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return true;
168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return false;
170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
172a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    @Override public boolean isAnyLocalAddress() {
173a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        return Arrays.equals(ipaddress, Inet6Address.ANY.ipaddress);
174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
177a7428d68453f6a74633221e8714f8d3d9597b2b4Elliott Hughes     * Returns whether this IPv6 address is an IPv4-compatible address or not.
178a7428d68453f6a74633221e8714f8d3d9597b2b4Elliott Hughes     * An IPv4-compatible address has the prefix {@code ::/96} and is a deprecated
179a7428d68453f6a74633221e8714f8d3d9597b2b4Elliott Hughes     * and no-longer used equivalent of the modern IPv4-mapped IPv6 addresses.
180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
181a7428d68453f6a74633221e8714f8d3d9597b2b4Elliott Hughes    public boolean isIPv4CompatibleAddress() {
182a7428d68453f6a74633221e8714f8d3d9597b2b4Elliott Hughes        for (int i = 0; i < 12; i++) {
183a7428d68453f6a74633221e8714f8d3d9597b2b4Elliott Hughes            if (ipaddress[i] != 0) {
184a7428d68453f6a74633221e8714f8d3d9597b2b4Elliott Hughes                return false;
185a7428d68453f6a74633221e8714f8d3d9597b2b4Elliott Hughes            }
186a7428d68453f6a74633221e8714f8d3d9597b2b4Elliott Hughes        }
187a7428d68453f6a74633221e8714f8d3d9597b2b4Elliott Hughes        return true;
188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
190a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    @Override public boolean isLinkLocalAddress() {
191a7428d68453f6a74633221e8714f8d3d9597b2b4Elliott Hughes        return ((ipaddress[0] & 0xff) == 0xfe) && ((ipaddress[1] & 0xc0) == 0x80); // fe80:/10
192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
194a7428d68453f6a74633221e8714f8d3d9597b2b4Elliott Hughes    @Override public boolean isLoopbackAddress() {
195a7428d68453f6a74633221e8714f8d3d9597b2b4Elliott Hughes        return Arrays.equals(ipaddress, Inet6Address.LOOPBACK.ipaddress);
196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
198a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    @Override public boolean isMCGlobal() {
199a7428d68453f6a74633221e8714f8d3d9597b2b4Elliott Hughes        return ((ipaddress[0] & 0xff) == 0xff) && ((ipaddress[1] & 0x0f) == 0x0e); // ffxe:/16
200a7428d68453f6a74633221e8714f8d3d9597b2b4Elliott Hughes    }
201a7428d68453f6a74633221e8714f8d3d9597b2b4Elliott Hughes
202a7428d68453f6a74633221e8714f8d3d9597b2b4Elliott Hughes    @Override public boolean isMCLinkLocal() {
203a7428d68453f6a74633221e8714f8d3d9597b2b4Elliott Hughes        return ((ipaddress[0] & 0xff) == 0xff) && ((ipaddress[1] & 0x0f) == 0x02); // ffx2:/16
204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
206a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    @Override public boolean isMCNodeLocal() {
207a7428d68453f6a74633221e8714f8d3d9597b2b4Elliott Hughes        return ((ipaddress[0] & 0xff) == 0xff) && ((ipaddress[1] & 0x0f) == 0x01); // ffx1:/16
208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
210a7428d68453f6a74633221e8714f8d3d9597b2b4Elliott Hughes    @Override public boolean isMCOrgLocal() {
211a7428d68453f6a74633221e8714f8d3d9597b2b4Elliott Hughes        return ((ipaddress[0] & 0xff) == 0xff) && ((ipaddress[1] & 0x0f) == 0x08); // ffx8:/16
212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
214a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    @Override public boolean isMCSiteLocal() {
215a7428d68453f6a74633221e8714f8d3d9597b2b4Elliott Hughes        return ((ipaddress[0] & 0xff) == 0xff) && ((ipaddress[1] & 0x0f) == 0x05); // ffx5:/16
216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
218a7428d68453f6a74633221e8714f8d3d9597b2b4Elliott Hughes    @Override public boolean isMulticastAddress() {
219a7428d68453f6a74633221e8714f8d3d9597b2b4Elliott Hughes        return ((ipaddress[0] & 0xff) == 0xff); // ff::/8
220a7428d68453f6a74633221e8714f8d3d9597b2b4Elliott Hughes    }
221a7428d68453f6a74633221e8714f8d3d9597b2b4Elliott Hughes
222a7428d68453f6a74633221e8714f8d3d9597b2b4Elliott Hughes    @Override public boolean isSiteLocalAddress() {
223a7428d68453f6a74633221e8714f8d3d9597b2b4Elliott Hughes        return ((ipaddress[0] & 0xff) == 0xfe) && ((ipaddress[1] & 0xc0) == 0xc0); // fec0:/10
224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
227a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes     * Returns the scope id if this address is scoped to an interface, 0 otherwise.
228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int getScopeId() {
230a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        return scope_id_set ? scope_id : 0;
231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
234a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes     * Returns the network interface if this address is instanced with a scoped
235a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes     * network interface, null otherwise.
236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public NetworkInterface getScopedInterface() {
238a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        try {
239f02f9397fd5984f476e056ddb8c04db9af9a15a0Elliott Hughes            return (scope_ifname_set && ifname != null) ? NetworkInterface.getByName(ifname) : null;
240a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        } catch (SocketException ex) {
241a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes            return null;
242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final ObjectStreamField[] serialPersistentFields = {
246e26ba79900d471d02d656f686926918ef7dc751fElliott Hughes        new ObjectStreamField("ipaddress", byte[].class),
247e26ba79900d471d02d656f686926918ef7dc751fElliott Hughes        new ObjectStreamField("scope_id", int.class),
248e26ba79900d471d02d656f686926918ef7dc751fElliott Hughes        new ObjectStreamField("scope_id_set", boolean.class),
249e26ba79900d471d02d656f686926918ef7dc751fElliott Hughes        new ObjectStreamField("scope_ifname_set", boolean.class),
25028eb98ecd43c27702e85b0561e040e2da10320a6Elliott Hughes        new ObjectStreamField("ifname", String.class),
25128eb98ecd43c27702e85b0561e040e2da10320a6Elliott Hughes    };
252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private void writeObject(ObjectOutputStream stream) throws IOException {
254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        ObjectOutputStream.PutField fields = stream.putFields();
255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (ipaddress == null) {
256f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            fields.put("ipaddress", null);
257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
258f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            fields.put("ipaddress", ipaddress);
259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
261f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        fields.put("scope_id", scope_id);
262f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        fields.put("scope_id_set", scope_id_set);
263f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        fields.put("scope_ifname_set", scope_ifname_set);
264f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        fields.put("ifname", ifname);
265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        stream.writeFields();
266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
268a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        ObjectInputStream.GetField fields = stream.readFields();
270f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        ipaddress = (byte[]) fields.get("ipaddress", null);
271f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        scope_id = fields.get("scope_id", 0);
272f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        scope_id_set = fields.get("scope_id_set", false);
273f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        ifname = (String) fields.get("ifname", null);
274f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        scope_ifname_set = fields.get("scope_ifname_set", false);
275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
277a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    @Override public String toString() {
278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (ifname != null) {
279f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            return super.toString() + "%" + ifname;
280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (scope_id != 0) {
282f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            return super.toString() + "%" + scope_id;
283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return super.toString();
285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
287