1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.net; 18 19 import android.os.Parcel; 20 import android.os.Parcelable; 21 22 import java.net.InetAddress; 23 import java.net.UnknownHostException; 24 import java.util.Arrays; 25 26 /** 27 * This class represents an IP prefix, i.e., a contiguous block of IP addresses aligned on a 28 * power of two boundary (also known as an "IP subnet"). A prefix is specified by two pieces of 29 * information: 30 * 31 * <ul> 32 * <li>A starting IP address (IPv4 or IPv6). This is the first IP address of the prefix. 33 * <li>A prefix length. This specifies the length of the prefix by specifing the number of bits 34 * in the IP address, starting from the most significant bit in network byte order, that 35 * are constant for all addresses in the prefix. 36 * </ul> 37 * 38 * For example, the prefix <code>192.0.2.0/24</code> covers the 256 IPv4 addresses from 39 * <code>192.0.2.0</code> to <code>192.0.2.255</code>, inclusive, and the prefix 40 * <code>2001:db8:1:2</code> covers the 2^64 IPv6 addresses from <code>2001:db8:1:2::</code> to 41 * <code>2001:db8:1:2:ffff:ffff:ffff:ffff</code>, inclusive. 42 * 43 * Objects of this class are immutable. 44 */ 45 public class IpPrefix implements Parcelable { 46 private final byte[] address; // network byte order 47 private final int prefixLength; 48 49 /** 50 * Constructs a new {@code IpPrefix} from a byte array containing an IPv4 or IPv6 address in 51 * network byte order and a prefix length. 52 * 53 * @param address the IP address. Must be non-null and exactly 4 or 16 bytes long. 54 * @param prefixLength the prefix length. Must be >= 0 and <= (32 or 128) (IPv4 or IPv6). 55 * 56 * @hide 57 */ 58 public IpPrefix(byte[] address, int prefixLength) { 59 if (address.length != 4 && address.length != 16) { 60 throw new IllegalArgumentException( 61 "IpPrefix has " + address.length + " bytes which is neither 4 nor 16"); 62 } 63 if (prefixLength < 0 || prefixLength > (address.length * 8)) { 64 throw new IllegalArgumentException("IpPrefix with " + address.length + 65 " bytes has invalid prefix length " + prefixLength); 66 } 67 this.address = address.clone(); 68 this.prefixLength = prefixLength; 69 // TODO: Validate that the non-prefix bits are zero 70 } 71 72 /** 73 * @hide 74 */ 75 public IpPrefix(InetAddress address, int prefixLength) { 76 this(address.getAddress(), prefixLength); 77 } 78 79 /** 80 * Compares this {@code IpPrefix} object against the specified object in {@code obj}. Two 81 * objects are equal if they have the same startAddress and prefixLength. 82 * 83 * @param obj the object to be tested for equality. 84 * @return {@code true} if both objects are equal, {@code false} otherwise. 85 */ 86 @Override 87 public boolean equals(Object obj) { 88 if (!(obj instanceof IpPrefix)) { 89 return false; 90 } 91 IpPrefix that = (IpPrefix) obj; 92 return Arrays.equals(this.address, that.address) && this.prefixLength == that.prefixLength; 93 } 94 95 /** 96 * Gets the hashcode of the represented IP prefix. 97 * 98 * @return the appropriate hashcode value. 99 */ 100 @Override 101 public int hashCode() { 102 return Arrays.hashCode(address) + 11 * prefixLength; 103 } 104 105 /** 106 * Returns a copy of the first IP address in the prefix. Modifying the returned object does not 107 * change this object's contents. 108 * 109 * @return the address in the form of a byte array. 110 */ 111 public InetAddress getAddress() { 112 try { 113 return InetAddress.getByAddress(address); 114 } catch (UnknownHostException e) { 115 // Cannot happen. InetAddress.getByAddress can only throw an exception if the byte 116 // array is the wrong length, but we check that in the constructor. 117 return null; 118 } 119 } 120 121 /** 122 * Returns a copy of the IP address bytes in network order (the highest order byte is the zeroth 123 * element). Modifying the returned array does not change this object's contents. 124 * 125 * @return the address in the form of a byte array. 126 */ 127 public byte[] getRawAddress() { 128 return address.clone(); 129 } 130 131 /** 132 * Returns the prefix length of this {@code IpAddress}. 133 * 134 * @return the prefix length. 135 */ 136 public int getPrefixLength() { 137 return prefixLength; 138 } 139 140 /** 141 * Implement the Parcelable interface. 142 * @hide 143 */ 144 public int describeContents() { 145 return 0; 146 } 147 148 /** 149 * Implement the Parcelable interface. 150 * @hide 151 */ 152 public void writeToParcel(Parcel dest, int flags) { 153 dest.writeByteArray(address); 154 dest.writeInt(prefixLength); 155 } 156 157 /** 158 * Implement the Parcelable interface. 159 * @hide 160 */ 161 public static final Creator<IpPrefix> CREATOR = 162 new Creator<IpPrefix>() { 163 public IpPrefix createFromParcel(Parcel in) { 164 byte[] address = in.createByteArray(); 165 int prefixLength = in.readInt(); 166 return new IpPrefix(address, prefixLength); 167 } 168 169 public IpPrefix[] newArray(int size) { 170 return new IpPrefix[size]; 171 } 172 }; 173 } 174