1ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff/*
2ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff * Copyright (C) 2010 The Android Open Source Project
3ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff *
4ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff * Licensed under the Apache License, Version 2.0 (the "License");
5ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff * you may not use this file except in compliance with the License.
6ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff * You may obtain a copy of the License at
7ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff *
8ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff *      http://www.apache.org/licenses/LICENSE-2.0
9ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff *
10ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff * Unless required by applicable law or agreed to in writing, software
11ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff * distributed under the License is distributed on an "AS IS" BASIS,
12ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff * See the License for the specific language governing permissions and
14ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff * limitations under the License.
15ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff */
16ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff
17ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriffpackage android.net;
18ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff
19ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriffimport android.os.Parcel;
20ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriffimport android.os.Parcelable;
21ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff
22b979f79158f9c470fa09ff3b96d72db274262201Robert Greenwaltimport java.net.Inet4Address;
23ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriffimport java.net.InetAddress;
24ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriffimport java.net.InterfaceAddress;
25ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriffimport java.net.UnknownHostException;
26ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff
27ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff/**
28ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff * Identifies an address of a network link
29ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff * @hide
30ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff */
31ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriffpublic class LinkAddress implements Parcelable {
32ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff    /**
33ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff     * IPv4 or IPv6 address.
34ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff     */
356eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti    private InetAddress address;
36ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff
37ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff    /**
3896ca91761e6857c1ca2e4fafe5b35e4b5fefe5a1Irfan Sheriff     * Network prefix length
39ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff     */
406eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti    private int prefixLength;
41ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff
426eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti    private void init(InetAddress address, int prefixLength) {
43b979f79158f9c470fa09ff3b96d72db274262201Robert Greenwalt        if (address == null || prefixLength < 0 ||
44b979f79158f9c470fa09ff3b96d72db274262201Robert Greenwalt                ((address instanceof Inet4Address) && prefixLength > 32) ||
45b979f79158f9c470fa09ff3b96d72db274262201Robert Greenwalt                (prefixLength > 128)) {
46b979f79158f9c470fa09ff3b96d72db274262201Robert Greenwalt            throw new IllegalArgumentException("Bad LinkAddress params " + address +
476eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti                    "/" + prefixLength);
48b979f79158f9c470fa09ff3b96d72db274262201Robert Greenwalt        }
49ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        this.address = address;
5096ca91761e6857c1ca2e4fafe5b35e4b5fefe5a1Irfan Sheriff        this.prefixLength = prefixLength;
51ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff    }
52ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff
536eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti    public LinkAddress(InetAddress address, int prefixLength) {
546eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti        init(address, prefixLength);
556eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti    }
566eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti
57ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff    public LinkAddress(InterfaceAddress interfaceAddress) {
586eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti        init(interfaceAddress.getAddress(),
596eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti             interfaceAddress.getNetworkPrefixLength());
606eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti    }
616eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti
626eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti    /**
636eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti     * Constructs a new {@code LinkAddress} from a string such as "192.0.2.5/24" or
646eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti     * "2001:db8::1/64".
656eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti     * @param string The string to parse.
666eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti     */
676eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti    public LinkAddress(String address) {
686eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti        InetAddress inetAddress = null;
696eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti        int prefixLength = -1;
706eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti        try {
716eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti            String [] pieces = address.split("/", 2);
726eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti            prefixLength = Integer.parseInt(pieces[1]);
736eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti            inetAddress = InetAddress.parseNumericAddress(pieces[0]);
746eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti        } catch (NullPointerException e) {            // Null string.
756eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti        } catch (ArrayIndexOutOfBoundsException e) {  // No prefix length.
766eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti        } catch (NumberFormatException e) {           // Non-numeric prefix.
776eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti        } catch (IllegalArgumentException e) {        // Invalid IP address.
786eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti        }
796eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti
806eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti        if (inetAddress == null || prefixLength == -1) {
816eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti            throw new IllegalArgumentException("Bad LinkAddress params " + address);
826eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti        }
836eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti
846eb8a62a26f35ed1c2938945bb86a65f486a8052Lorenzo Colitti        init(inetAddress, prefixLength);
85ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff    }
86ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff
87ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff    @Override
88ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff    public String toString() {
8996ca91761e6857c1ca2e4fafe5b35e4b5fefe5a1Irfan Sheriff        return (address == null ? "" : (address.getHostAddress() + "/" + prefixLength));
90ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff    }
91ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff
92ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff    /**
93ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff     * Compares this {@code LinkAddress} instance against the specified address
9496ca91761e6857c1ca2e4fafe5b35e4b5fefe5a1Irfan Sheriff     * in {@code obj}. Two addresses are equal if their InetAddress and prefixLength
95ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff     * are equal
96ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff     *
97ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff     * @param obj the object to be tested for equality.
98ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff     * @return {@code true} if both objects are equal, {@code false} otherwise.
99ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff     */
100ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff    @Override
101ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff    public boolean equals(Object obj) {
102ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        if (!(obj instanceof LinkAddress)) {
103ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff            return false;
104ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        }
105ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        LinkAddress linkAddress = (LinkAddress) obj;
106ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        return this.address.equals(linkAddress.address) &&
10796ca91761e6857c1ca2e4fafe5b35e4b5fefe5a1Irfan Sheriff            this.prefixLength == linkAddress.prefixLength;
108ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff    }
109ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff
1104e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang    @Override
1114e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang    /*
1124e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     * generate hashcode based on significant fields
1134e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     */
1144e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang    public int hashCode() {
1154e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang        return ((null == address) ? 0 : address.hashCode()) + prefixLength;
1164e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang    }
1174e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang
118ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff    /**
119ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff     * Returns the InetAddress for this address.
120ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff     */
121ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff    public InetAddress getAddress() {
122ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        return address;
123ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff    }
124ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff
125ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff    /**
126ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff     * Get network prefix length
127ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff     */
12896ca91761e6857c1ca2e4fafe5b35e4b5fefe5a1Irfan Sheriff    public int getNetworkPrefixLength() {
12996ca91761e6857c1ca2e4fafe5b35e4b5fefe5a1Irfan Sheriff        return prefixLength;
130ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff    }
131ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff
132ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff    /**
133ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff     * Implement the Parcelable interface
134ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff     * @hide
135ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff     */
136ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff    public int describeContents() {
137ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        return 0;
138ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff    }
139ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff
140ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff    /**
141ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff     * Implement the Parcelable interface.
142ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff     * @hide
143ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff     */
144ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff    public void writeToParcel(Parcel dest, int flags) {
145ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        if (address != null) {
146ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff            dest.writeByte((byte)1);
147ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff            dest.writeByteArray(address.getAddress());
14896ca91761e6857c1ca2e4fafe5b35e4b5fefe5a1Irfan Sheriff            dest.writeInt(prefixLength);
149ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        } else {
150ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff            dest.writeByte((byte)0);
151ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        }
152ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff    }
153ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff
154ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff    /**
155ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff     * Implement the Parcelable interface.
156ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff     * @hide
157ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff     */
158ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff    public static final Creator<LinkAddress> CREATOR =
159ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        new Creator<LinkAddress>() {
160ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff            public LinkAddress createFromParcel(Parcel in) {
161ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff                InetAddress address = null;
16296ca91761e6857c1ca2e4fafe5b35e4b5fefe5a1Irfan Sheriff                int prefixLength = 0;
163ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff                if (in.readByte() == 1) {
164ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff                    try {
165ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff                        address = InetAddress.getByAddress(in.createByteArray());
16696ca91761e6857c1ca2e4fafe5b35e4b5fefe5a1Irfan Sheriff                        prefixLength = in.readInt();
167ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff                    } catch (UnknownHostException e) { }
168ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff                }
16996ca91761e6857c1ca2e4fafe5b35e4b5fefe5a1Irfan Sheriff                return new LinkAddress(address, prefixLength);
170ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff            }
171ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff
172ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff            public LinkAddress[] newArray(int size) {
173ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff                return new LinkAddress[size];
174ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff            }
175ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        };
176ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff}
177