blob: 6af795b3fe5b28417820aa4305374110a3583479 [file] [log] [blame]
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.net;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Range;
import com.android.net.module.util.InetAddressUtils;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.util.Objects;
/**
* DSCP policy to be set on the requesting NetworkAgent.
* @hide
*/
@SystemApi
public final class DscpPolicy implements Parcelable {
/**
* Indicates that the policy does not specify a protocol.
*/
public static final int PROTOCOL_ANY = -1;
/**
* Indicates that the policy does not specify a port.
*/
public static final int SOURCE_PORT_ANY = -1;
/** The unique policy ID. Each requesting network is responsible for maintaining policy IDs
* unique within that network. In the case where a policy with an existing ID is created, the
* new policy will update the existing policy with the same ID.
*/
private final int mPolicyId;
/** The QoS DSCP marking to be added to packets matching the policy. */
private final int mDscp;
/** The source IP address. */
private final @Nullable InetAddress mSrcAddr;
/** The destination IP address. */
private final @Nullable InetAddress mDstAddr;
/** The source port. */
private final int mSrcPort;
/** The IP protocol that the policy requires. */
private final int mProtocol;
/** Destination port range. Inclusive range. */
private final @Nullable Range<Integer> mDstPortRange;
/**
* Implement the Parcelable interface
*
* @hide
*/
public int describeContents() {
return 0;
}
/* package */ DscpPolicy(
int policyId,
int dscp,
@Nullable InetAddress srcAddr,
@Nullable InetAddress dstAddr,
int srcPort,
int protocol,
Range<Integer> dstPortRange) {
this.mPolicyId = policyId;
this.mDscp = dscp;
this.mSrcAddr = srcAddr;
this.mDstAddr = dstAddr;
this.mSrcPort = srcPort;
this.mProtocol = protocol;
this.mDstPortRange = dstPortRange;
if (mPolicyId < 1 || mPolicyId > 255) {
throw new IllegalArgumentException("Policy ID not in valid range: " + mPolicyId);
}
if (mDscp < 0 || mDscp > 63) {
throw new IllegalArgumentException("DSCP value not in valid range: " + mDscp);
}
// Since SOURCE_PORT_ANY is the default source port value need to allow it as well.
// TODO: Move the default value into this constructor or throw an error from the
// instead.
if (mSrcPort < -1 || mSrcPort > 65535) {
throw new IllegalArgumentException("Source port not in valid range: " + mSrcPort);
}
if (mDstPortRange != null
&& (dstPortRange.getLower() < 0 || mDstPortRange.getLower() > 65535)
&& (mDstPortRange.getUpper() < 0 || mDstPortRange.getUpper() > 65535)) {
throw new IllegalArgumentException("Destination port not in valid range");
}
if (mSrcAddr != null && mDstAddr != null && (mSrcAddr instanceof Inet6Address)
!= (mDstAddr instanceof Inet6Address)) {
throw new IllegalArgumentException("Source/destination address of different family");
}
}
/**
* The unique policy ID.
*
* Each requesting network is responsible for maintaining unique
* policy IDs. In the case where a policy with an existing ID is created, the new
* policy will update the existing policy with the same ID
*
* @return Policy ID set in Builder.
*/
public int getPolicyId() {
return mPolicyId;
}
/**
* The QoS DSCP marking to be added to packets matching the policy.
*
* @return DSCP value set in Builder.
*/
public int getDscpValue() {
return mDscp;
}
/**
* The source IP address.
*
* @return Source IP address set in Builder or {@code null} if none was set.
*/
public @Nullable InetAddress getSourceAddress() {
return mSrcAddr;
}
/**
* The destination IP address.
*
* @return Destination IP address set in Builder or {@code null} if none was set.
*/
public @Nullable InetAddress getDestinationAddress() {
return mDstAddr;
}
/**
* The source port.
*
* @return Source port set in Builder or {@link #SOURCE_PORT_ANY} if no port was set.
*/
public int getSourcePort() {
return mSrcPort;
}
/**
* The IP protocol that the policy requires.
*
* @return Protocol set in Builder or {@link #PROTOCOL_ANY} if no protocol was set.
* {@link #PROTOCOL_ANY} indicates that any protocol will be matched.
*/
public int getProtocol() {
return mProtocol;
}
/**
* Destination port range. Inclusive range.
*
* @return Range<Integer> set in Builder or {@code null} if none was set.
*/
public @Nullable Range<Integer> getDestinationPortRange() {
return mDstPortRange;
}
@Override
public String toString() {
return "DscpPolicy { "
+ "policyId = " + mPolicyId + ", "
+ "dscp = " + mDscp + ", "
+ "srcAddr = " + mSrcAddr + ", "
+ "dstAddr = " + mDstAddr + ", "
+ "srcPort = " + mSrcPort + ", "
+ "protocol = " + mProtocol + ", "
+ "dstPortRange = "
+ (mDstPortRange == null ? "none" : mDstPortRange.toString())
+ " }";
}
@Override
public boolean equals(@Nullable Object o) {
if (this == o) return true;
if (!(o instanceof DscpPolicy)) return false;
DscpPolicy that = (DscpPolicy) o;
return true
&& mPolicyId == that.mPolicyId
&& mDscp == that.mDscp
&& Objects.equals(mSrcAddr, that.mSrcAddr)
&& Objects.equals(mDstAddr, that.mDstAddr)
&& mSrcPort == that.mSrcPort
&& mProtocol == that.mProtocol
&& Objects.equals(mDstPortRange, that.mDstPortRange);
}
@Override
public int hashCode() {
return Objects.hash(mPolicyId, mDscp, mSrcAddr.hashCode(),
mDstAddr.hashCode(), mSrcPort, mProtocol, mDstPortRange.hashCode());
}
/** @hide */
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mPolicyId);
dest.writeInt(mDscp);
InetAddressUtils.parcelInetAddress(dest, mSrcAddr, flags);
InetAddressUtils.parcelInetAddress(dest, mDstAddr, flags);
dest.writeInt(mSrcPort);
dest.writeInt(mProtocol);
dest.writeBoolean(mDstPortRange != null ? true : false);
if (mDstPortRange != null) {
dest.writeInt(mDstPortRange.getLower());
dest.writeInt(mDstPortRange.getUpper());
}
}
/** @hide */
DscpPolicy(@NonNull Parcel in) {
this.mPolicyId = in.readInt();
this.mDscp = in.readInt();
this.mSrcAddr = InetAddressUtils.unparcelInetAddress(in);
this.mDstAddr = InetAddressUtils.unparcelInetAddress(in);
this.mSrcPort = in.readInt();
this.mProtocol = in.readInt();
if (in.readBoolean()) {
this.mDstPortRange = new Range<Integer>(in.readInt(), in.readInt());
} else {
this.mDstPortRange = null;
}
}
/** @hide */
public @SystemApi static final @NonNull Parcelable.Creator<DscpPolicy> CREATOR =
new Parcelable.Creator<DscpPolicy>() {
@Override
public DscpPolicy[] newArray(int size) {
return new DscpPolicy[size];
}
@Override
public DscpPolicy createFromParcel(@NonNull android.os.Parcel in) {
return new DscpPolicy(in);
}
};
/**
* A builder for {@link DscpPolicy}
*
*/
public static final class Builder {
private final int mPolicyId;
private final int mDscp;
private @Nullable InetAddress mSrcAddr;
private @Nullable InetAddress mDstAddr;
private int mSrcPort = SOURCE_PORT_ANY;
private int mProtocol = PROTOCOL_ANY;
private @Nullable Range<Integer> mDstPortRange;
private long mBuilderFieldsSet = 0L;
/**
* Creates a new Builder.
*
* @param policyId The unique policy ID. Each requesting network is responsible for
* maintaining unique policy IDs. In the case where a policy with an
* existing ID is created, the new policy will update the existing
* policy with the same ID
* @param dscpValue The DSCP value to set.
*/
public Builder(int policyId, int dscpValue) {
mPolicyId = policyId;
mDscp = dscpValue;
}
/**
* Specifies that this policy matches packets with the specified source IP address.
*/
public @NonNull Builder setSourceAddress(@NonNull InetAddress value) {
mSrcAddr = value;
return this;
}
/**
* Specifies that this policy matches packets with the specified destination IP address.
*/
public @NonNull Builder setDestinationAddress(@NonNull InetAddress value) {
mDstAddr = value;
return this;
}
/**
* Specifies that this policy matches packets with the specified source port.
*/
public @NonNull Builder setSourcePort(int value) {
mSrcPort = value;
return this;
}
/**
* Specifies that this policy matches packets with the specified protocol.
*/
public @NonNull Builder setProtocol(int value) {
mProtocol = value;
return this;
}
/**
* Specifies that this policy matches packets with the specified destination port range.
*/
public @NonNull Builder setDestinationPortRange(@NonNull Range<Integer> range) {
mDstPortRange = range;
return this;
}
/**
* Constructs a DscpPolicy with the specified parameters.
*/
public @NonNull DscpPolicy build() {
return new DscpPolicy(
mPolicyId,
mDscp,
mSrcAddr,
mDstAddr,
mSrcPort,
mProtocol,
mDstPortRange);
}
}
}