1 /* 2 * Copyright (C) 2010 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 import android.util.Pair; 22 23 import java.net.Inet4Address; 24 import java.net.InetAddress; 25 import java.net.InterfaceAddress; 26 import java.net.UnknownHostException; 27 28 import static android.system.OsConstants.IFA_F_DADFAILED; 29 import static android.system.OsConstants.IFA_F_DEPRECATED; 30 import static android.system.OsConstants.IFA_F_TENTATIVE; 31 import static android.system.OsConstants.RT_SCOPE_HOST; 32 import static android.system.OsConstants.RT_SCOPE_LINK; 33 import static android.system.OsConstants.RT_SCOPE_SITE; 34 import static android.system.OsConstants.RT_SCOPE_UNIVERSE; 35 36 /** 37 * Identifies an IP address on a network link. 38 * 39 * A {@code LinkAddress} consists of: 40 * <ul> 41 * <li>An IP address and prefix length (e.g., {@code 2001:db8::1/64} or {@code 192.0.2.1/24}). 42 * The address must be unicast, as multicast addresses cannot be assigned to interfaces. 43 * <li>Address flags: A bitmask of {@code OsConstants.IFA_F_*} values representing properties 44 * of the address (e.g., {@code android.system.OsConstants.IFA_F_OPTIMISTIC}). 45 * <li>Address scope: One of the {@code OsConstants.IFA_F_*} values; defines the scope in which 46 * the address is unique (e.g., 47 * {@code android.system.OsConstants.RT_SCOPE_LINK} or 48 * {@code android.system.OsConstants.RT_SCOPE_UNIVERSE}). 49 * </ul> 50 */ 51 public class LinkAddress implements Parcelable { 52 /** 53 * IPv4 or IPv6 address. 54 */ 55 private InetAddress address; 56 57 /** 58 * Prefix length. 59 */ 60 private int prefixLength; 61 62 /** 63 * Address flags. A bitmask of IFA_F_* values. 64 */ 65 private int flags; 66 67 /** 68 * Address scope. One of the RT_SCOPE_* constants. 69 */ 70 private int scope; 71 72 /** 73 * Utility function to determines the scope of a unicast address. Per RFC 4291 section 2.5 and 74 * RFC 6724 section 3.2. 75 * @hide 76 */ 77 static int scopeForUnicastAddress(InetAddress addr) { 78 if (addr.isAnyLocalAddress()) { 79 return RT_SCOPE_HOST; 80 } 81 82 if (addr.isLoopbackAddress() || addr.isLinkLocalAddress()) { 83 return RT_SCOPE_LINK; 84 } 85 86 // isSiteLocalAddress() returns true for private IPv4 addresses, but RFC 6724 section 3.2 87 // says that they are assigned global scope. 88 if (!(addr instanceof Inet4Address) && addr.isSiteLocalAddress()) { 89 return RT_SCOPE_SITE; 90 } 91 92 return RT_SCOPE_UNIVERSE; 93 } 94 95 /** 96 * Utility function for the constructors. 97 */ 98 private void init(InetAddress address, int prefixLength, int flags, int scope) { 99 if (address == null || 100 address.isMulticastAddress() || 101 prefixLength < 0 || 102 ((address instanceof Inet4Address) && prefixLength > 32) || 103 (prefixLength > 128)) { 104 throw new IllegalArgumentException("Bad LinkAddress params " + address + 105 "/" + prefixLength); 106 } 107 this.address = address; 108 this.prefixLength = prefixLength; 109 this.flags = flags; 110 this.scope = scope; 111 } 112 113 /** 114 * Constructs a new {@code LinkAddress} from an {@code InetAddress} and prefix length, with 115 * the specified flags and scope. Flags and scope are not checked for validity. 116 * @param address The IP address. 117 * @param prefixLength The prefix length. 118 * @param flags A bitmask of {@code IFA_F_*} values representing properties of the address. 119 * @param scope An integer defining the scope in which the address is unique (e.g., 120 * {@link OsConstants#RT_SCOPE_LINK} or {@link OsConstants#RT_SCOPE_SITE}). 121 * @hide 122 */ 123 public LinkAddress(InetAddress address, int prefixLength, int flags, int scope) { 124 init(address, prefixLength, flags, scope); 125 } 126 127 /** 128 * Constructs a new {@code LinkAddress} from an {@code InetAddress} and a prefix length. 129 * The flags are set to zero and the scope is determined from the address. 130 * @param address The IP address. 131 * @param prefixLength The prefix length. 132 * @hide 133 */ 134 public LinkAddress(InetAddress address, int prefixLength) { 135 this(address, prefixLength, 0, 0); 136 this.scope = scopeForUnicastAddress(address); 137 } 138 139 /** 140 * Constructs a new {@code LinkAddress} from an {@code InterfaceAddress}. 141 * The flags are set to zero and the scope is determined from the address. 142 * @param interfaceAddress The interface address. 143 * @hide 144 */ 145 public LinkAddress(InterfaceAddress interfaceAddress) { 146 this(interfaceAddress.getAddress(), 147 interfaceAddress.getNetworkPrefixLength()); 148 } 149 150 /** 151 * Constructs a new {@code LinkAddress} from a string such as "192.0.2.5/24" or 152 * "2001:db8::1/64". The flags are set to zero and the scope is determined from the address. 153 * @param string The string to parse. 154 * @hide 155 */ 156 public LinkAddress(String address) { 157 this(address, 0, 0); 158 this.scope = scopeForUnicastAddress(this.address); 159 } 160 161 /** 162 * Constructs a new {@code LinkAddress} from a string such as "192.0.2.5/24" or 163 * "2001:db8::1/64", with the specified flags and scope. 164 * @param string The string to parse. 165 * @param flags The address flags. 166 * @param scope The address scope. 167 * @hide 168 */ 169 public LinkAddress(String address, int flags, int scope) { 170 // This may throw an IllegalArgumentException; catching it is the caller's responsibility. 171 Pair<InetAddress, Integer> ipAndMask = NetworkUtils.parseIpAndMask(address); 172 init(ipAndMask.first, ipAndMask.second, flags, scope); 173 } 174 175 /** 176 * Returns a string representation of this address, such as "192.0.2.1/24" or "2001:db8::1/64". 177 * The string representation does not contain the flags and scope, just the address and prefix 178 * length. 179 */ 180 @Override 181 public String toString() { 182 return address.getHostAddress() + "/" + prefixLength; 183 } 184 185 /** 186 * Compares this {@code LinkAddress} instance against {@code obj}. Two addresses are equal if 187 * their address, prefix length, flags and scope are equal. Thus, for example, two addresses 188 * that have the same address and prefix length are not equal if one of them is deprecated and 189 * the other is not. 190 * 191 * @param obj the object to be tested for equality. 192 * @return {@code true} if both objects are equal, {@code false} otherwise. 193 */ 194 @Override 195 public boolean equals(Object obj) { 196 if (!(obj instanceof LinkAddress)) { 197 return false; 198 } 199 LinkAddress linkAddress = (LinkAddress) obj; 200 return this.address.equals(linkAddress.address) && 201 this.prefixLength == linkAddress.prefixLength && 202 this.flags == linkAddress.flags && 203 this.scope == linkAddress.scope; 204 } 205 206 /** 207 * Returns a hashcode for this address. 208 */ 209 @Override 210 public int hashCode() { 211 return address.hashCode() + 11 * prefixLength + 19 * flags + 43 * scope; 212 } 213 214 /** 215 * Determines whether this {@code LinkAddress} and the provided {@code LinkAddress} 216 * represent the same address. Two {@code LinkAddresses} represent the same address 217 * if they have the same IP address and prefix length, even if their properties are 218 * different. 219 * 220 * @param other the {@code LinkAddress} to compare to. 221 * @return {@code true} if both objects have the same address and prefix length, {@code false} 222 * otherwise. 223 * @hide 224 */ 225 public boolean isSameAddressAs(LinkAddress other) { 226 return address.equals(other.address) && prefixLength == other.prefixLength; 227 } 228 229 /** 230 * Returns the {@link InetAddress} of this {@code LinkAddress}. 231 */ 232 public InetAddress getAddress() { 233 return address; 234 } 235 236 /** 237 * Returns the prefix length of this {@code LinkAddress}. 238 */ 239 public int getPrefixLength() { 240 return prefixLength; 241 } 242 243 /** 244 * Returns the prefix length of this {@code LinkAddress}. 245 * TODO: Delete all callers and remove in favour of getPrefixLength(). 246 * @hide 247 */ 248 public int getNetworkPrefixLength() { 249 return getPrefixLength(); 250 } 251 252 /** 253 * Returns the flags of this {@code LinkAddress}. 254 */ 255 public int getFlags() { 256 return flags; 257 } 258 259 /** 260 * Returns the scope of this {@code LinkAddress}. 261 */ 262 public int getScope() { 263 return scope; 264 } 265 266 /** 267 * Returns true if this {@code LinkAddress} is global scope and preferred. 268 * @hide 269 */ 270 public boolean isGlobalPreferred() { 271 return (scope == RT_SCOPE_UNIVERSE && 272 (flags & (IFA_F_DADFAILED | IFA_F_DEPRECATED | IFA_F_TENTATIVE)) == 0L); 273 } 274 275 /** 276 * Implement the Parcelable interface. 277 */ 278 public int describeContents() { 279 return 0; 280 } 281 282 /** 283 * Implement the Parcelable interface. 284 */ 285 public void writeToParcel(Parcel dest, int flags) { 286 dest.writeByteArray(address.getAddress()); 287 dest.writeInt(prefixLength); 288 dest.writeInt(this.flags); 289 dest.writeInt(scope); 290 } 291 292 /** 293 * Implement the Parcelable interface. 294 */ 295 public static final Creator<LinkAddress> CREATOR = 296 new Creator<LinkAddress>() { 297 public LinkAddress createFromParcel(Parcel in) { 298 InetAddress address = null; 299 try { 300 address = InetAddress.getByAddress(in.createByteArray()); 301 } catch (UnknownHostException e) { 302 // Nothing we can do here. When we call the constructor, we'll throw an 303 // IllegalArgumentException, because a LinkAddress can't have a null 304 // InetAddress. 305 } 306 int prefixLength = in.readInt(); 307 int flags = in.readInt(); 308 int scope = in.readInt(); 309 return new LinkAddress(address, prefixLength, flags, scope); 310 } 311 312 public LinkAddress[] newArray(int size) { 313 return new LinkAddress[size]; 314 } 315 }; 316 } 317