1 /* 2 * Copyright (C) 2021 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.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.annotation.SystemApi; 22 import android.os.Parcel; 23 import android.os.Parcelable; 24 import android.util.Range; 25 26 import com.android.net.module.util.InetAddressUtils; 27 28 import java.net.Inet6Address; 29 import java.net.InetAddress; 30 import java.util.Objects; 31 32 33 /** 34 * DSCP policy to be set on the requesting NetworkAgent. 35 * @hide 36 */ 37 @SystemApi 38 public final class DscpPolicy implements Parcelable { 39 /** 40 * Indicates that the policy does not specify a protocol. 41 */ 42 public static final int PROTOCOL_ANY = -1; 43 44 /** 45 * Indicates that the policy does not specify a port. 46 */ 47 public static final int SOURCE_PORT_ANY = -1; 48 49 /** The unique policy ID. Each requesting network is responsible for maintaining policy IDs 50 * unique within that network. In the case where a policy with an existing ID is created, the 51 * new policy will update the existing policy with the same ID. 52 */ 53 private final int mPolicyId; 54 55 /** The QoS DSCP marking to be added to packets matching the policy. */ 56 private final int mDscp; 57 58 /** The source IP address. */ 59 private final @Nullable InetAddress mSrcAddr; 60 61 /** The destination IP address. */ 62 private final @Nullable InetAddress mDstAddr; 63 64 /** The source port. */ 65 private final int mSrcPort; 66 67 /** The IP protocol that the policy requires. */ 68 private final int mProtocol; 69 70 /** Destination port range. Inclusive range. */ 71 private final @Nullable Range<Integer> mDstPortRange; 72 73 /** 74 * Implement the Parcelable interface 75 * 76 * @hide 77 */ describeContents()78 public int describeContents() { 79 return 0; 80 } 81 DscpPolicy( int policyId, int dscp, @Nullable InetAddress srcAddr, @Nullable InetAddress dstAddr, int srcPort, int protocol, Range<Integer> dstPortRange)82 /* package */ DscpPolicy( 83 int policyId, 84 int dscp, 85 @Nullable InetAddress srcAddr, 86 @Nullable InetAddress dstAddr, 87 int srcPort, 88 int protocol, 89 Range<Integer> dstPortRange) { 90 this.mPolicyId = policyId; 91 this.mDscp = dscp; 92 this.mSrcAddr = srcAddr; 93 this.mDstAddr = dstAddr; 94 this.mSrcPort = srcPort; 95 this.mProtocol = protocol; 96 this.mDstPortRange = dstPortRange; 97 98 if (mPolicyId < 1 || mPolicyId > 255) { 99 throw new IllegalArgumentException("Policy ID not in valid range: " + mPolicyId); 100 } 101 if (mDscp < 0 || mDscp > 63) { 102 throw new IllegalArgumentException("DSCP value not in valid range: " + mDscp); 103 } 104 // Since SOURCE_PORT_ANY is the default source port value need to allow it as well. 105 // TODO: Move the default value into this constructor or throw an error from the 106 // instead. 107 if (mSrcPort < -1 || mSrcPort > 65535) { 108 throw new IllegalArgumentException("Source port not in valid range: " + mSrcPort); 109 } 110 if (mDstPortRange != null 111 && (dstPortRange.getLower() < 0 || mDstPortRange.getLower() > 65535) 112 && (mDstPortRange.getUpper() < 0 || mDstPortRange.getUpper() > 65535)) { 113 throw new IllegalArgumentException("Destination port not in valid range"); 114 } 115 if (mSrcAddr != null && mDstAddr != null && (mSrcAddr instanceof Inet6Address) 116 != (mDstAddr instanceof Inet6Address)) { 117 throw new IllegalArgumentException("Source/destination address of different family"); 118 } 119 } 120 121 /** 122 * The unique policy ID. 123 * 124 * Each requesting network is responsible for maintaining unique 125 * policy IDs. In the case where a policy with an existing ID is created, the new 126 * policy will update the existing policy with the same ID 127 * 128 * @return Policy ID set in Builder. 129 */ getPolicyId()130 public int getPolicyId() { 131 return mPolicyId; 132 } 133 134 /** 135 * The QoS DSCP marking to be added to packets matching the policy. 136 * 137 * @return DSCP value set in Builder. 138 */ getDscpValue()139 public int getDscpValue() { 140 return mDscp; 141 } 142 143 /** 144 * The source IP address. 145 * 146 * @return Source IP address set in Builder or {@code null} if none was set. 147 */ getSourceAddress()148 public @Nullable InetAddress getSourceAddress() { 149 return mSrcAddr; 150 } 151 152 /** 153 * The destination IP address. 154 * 155 * @return Destination IP address set in Builder or {@code null} if none was set. 156 */ getDestinationAddress()157 public @Nullable InetAddress getDestinationAddress() { 158 return mDstAddr; 159 } 160 161 /** 162 * The source port. 163 * 164 * @return Source port set in Builder or {@link #SOURCE_PORT_ANY} if no port was set. 165 */ getSourcePort()166 public int getSourcePort() { 167 return mSrcPort; 168 } 169 170 /** 171 * The IP protocol that the policy requires. 172 * 173 * @return Protocol set in Builder or {@link #PROTOCOL_ANY} if no protocol was set. 174 * {@link #PROTOCOL_ANY} indicates that any protocol will be matched. 175 */ getProtocol()176 public int getProtocol() { 177 return mProtocol; 178 } 179 180 /** 181 * Destination port range. Inclusive range. 182 * 183 * @return Range<Integer> set in Builder or {@code null} if none was set. 184 */ getDestinationPortRange()185 public @Nullable Range<Integer> getDestinationPortRange() { 186 return mDstPortRange; 187 } 188 189 @Override toString()190 public String toString() { 191 return "DscpPolicy { " 192 + "policyId = " + mPolicyId + ", " 193 + "dscp = " + mDscp + ", " 194 + "srcAddr = " + mSrcAddr + ", " 195 + "dstAddr = " + mDstAddr + ", " 196 + "srcPort = " + mSrcPort + ", " 197 + "protocol = " + mProtocol + ", " 198 + "dstPortRange = " 199 + (mDstPortRange == null ? "none" : mDstPortRange.toString()) 200 + " }"; 201 } 202 203 @Override equals(@ullable Object o)204 public boolean equals(@Nullable Object o) { 205 if (this == o) return true; 206 if (!(o instanceof DscpPolicy)) return false; 207 DscpPolicy that = (DscpPolicy) o; 208 return true 209 && mPolicyId == that.mPolicyId 210 && mDscp == that.mDscp 211 && Objects.equals(mSrcAddr, that.mSrcAddr) 212 && Objects.equals(mDstAddr, that.mDstAddr) 213 && mSrcPort == that.mSrcPort 214 && mProtocol == that.mProtocol 215 && Objects.equals(mDstPortRange, that.mDstPortRange); 216 } 217 218 @Override hashCode()219 public int hashCode() { 220 return Objects.hash(mPolicyId, mDscp, mSrcAddr.hashCode(), 221 mDstAddr.hashCode(), mSrcPort, mProtocol, mDstPortRange.hashCode()); 222 } 223 224 /** @hide */ 225 @Override writeToParcel(@onNull Parcel dest, int flags)226 public void writeToParcel(@NonNull Parcel dest, int flags) { 227 dest.writeInt(mPolicyId); 228 dest.writeInt(mDscp); 229 InetAddressUtils.parcelInetAddress(dest, mSrcAddr, flags); 230 InetAddressUtils.parcelInetAddress(dest, mDstAddr, flags); 231 dest.writeInt(mSrcPort); 232 dest.writeInt(mProtocol); 233 dest.writeBoolean(mDstPortRange != null ? true : false); 234 if (mDstPortRange != null) { 235 dest.writeInt(mDstPortRange.getLower()); 236 dest.writeInt(mDstPortRange.getUpper()); 237 } 238 } 239 240 /** @hide */ DscpPolicy(@onNull Parcel in)241 DscpPolicy(@NonNull Parcel in) { 242 this.mPolicyId = in.readInt(); 243 this.mDscp = in.readInt(); 244 this.mSrcAddr = InetAddressUtils.unparcelInetAddress(in); 245 this.mDstAddr = InetAddressUtils.unparcelInetAddress(in); 246 this.mSrcPort = in.readInt(); 247 this.mProtocol = in.readInt(); 248 if (in.readBoolean()) { 249 this.mDstPortRange = new Range<Integer>(in.readInt(), in.readInt()); 250 } else { 251 this.mDstPortRange = null; 252 } 253 } 254 255 /** @hide */ 256 public @SystemApi static final @NonNull Parcelable.Creator<DscpPolicy> CREATOR = 257 new Parcelable.Creator<DscpPolicy>() { 258 @Override 259 public DscpPolicy[] newArray(int size) { 260 return new DscpPolicy[size]; 261 } 262 263 @Override 264 public DscpPolicy createFromParcel(@NonNull android.os.Parcel in) { 265 return new DscpPolicy(in); 266 } 267 }; 268 269 /** 270 * A builder for {@link DscpPolicy} 271 * 272 */ 273 public static final class Builder { 274 275 private final int mPolicyId; 276 private final int mDscp; 277 private @Nullable InetAddress mSrcAddr; 278 private @Nullable InetAddress mDstAddr; 279 private int mSrcPort = SOURCE_PORT_ANY; 280 private int mProtocol = PROTOCOL_ANY; 281 private @Nullable Range<Integer> mDstPortRange; 282 283 private long mBuilderFieldsSet = 0L; 284 285 /** 286 * Creates a new Builder. 287 * 288 * @param policyId The unique policy ID. Each requesting network is responsible for 289 * maintaining unique policy IDs. In the case where a policy with an 290 * existing ID is created, the new policy will update the existing 291 * policy with the same ID 292 * @param dscpValue The DSCP value to set. 293 */ Builder(int policyId, int dscpValue)294 public Builder(int policyId, int dscpValue) { 295 mPolicyId = policyId; 296 mDscp = dscpValue; 297 } 298 299 /** 300 * Specifies that this policy matches packets with the specified source IP address. 301 */ setSourceAddress(@onNull InetAddress value)302 public @NonNull Builder setSourceAddress(@NonNull InetAddress value) { 303 mSrcAddr = value; 304 return this; 305 } 306 307 /** 308 * Specifies that this policy matches packets with the specified destination IP address. 309 */ setDestinationAddress(@onNull InetAddress value)310 public @NonNull Builder setDestinationAddress(@NonNull InetAddress value) { 311 mDstAddr = value; 312 return this; 313 } 314 315 /** 316 * Specifies that this policy matches packets with the specified source port. 317 */ setSourcePort(int value)318 public @NonNull Builder setSourcePort(int value) { 319 mSrcPort = value; 320 return this; 321 } 322 323 /** 324 * Specifies that this policy matches packets with the specified protocol. 325 */ setProtocol(int value)326 public @NonNull Builder setProtocol(int value) { 327 mProtocol = value; 328 return this; 329 } 330 331 /** 332 * Specifies that this policy matches packets with the specified destination port range. 333 */ setDestinationPortRange(@onNull Range<Integer> range)334 public @NonNull Builder setDestinationPortRange(@NonNull Range<Integer> range) { 335 mDstPortRange = range; 336 return this; 337 } 338 339 /** 340 * Constructs a DscpPolicy with the specified parameters. 341 */ build()342 public @NonNull DscpPolicy build() { 343 return new DscpPolicy( 344 mPolicyId, 345 mDscp, 346 mSrcAddr, 347 mDstAddr, 348 mSrcPort, 349 mProtocol, 350 mDstPortRange); 351 } 352 } 353 } 354