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