blob: 6af795b3fe5b28417820aa4305374110a3583479 [file] [log] [blame]
Tyler Wear72388212021-09-09 14:49:02 -07001/*
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
17package android.net;
18
Tyler Wear72388212021-09-09 14:49:02 -070019import android.annotation.NonNull;
20import android.annotation.Nullable;
21import android.annotation.SystemApi;
22import android.os.Parcel;
23import android.os.Parcelable;
24import android.util.Range;
25
26import com.android.net.module.util.InetAddressUtils;
27
Tyler Wear72388212021-09-09 14:49:02 -070028import java.net.Inet6Address;
29import java.net.InetAddress;
30import java.util.Objects;
31
32
33/**
34 * DSCP policy to be set on the requesting NetworkAgent.
35 * @hide
36 */
37@SystemApi
38public 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
Tyler Wear72388212021-09-09 14:49:02 -070049 /** 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 */
78 public int describeContents() {
79 return 0;
80 }
81
Tyler Wear72388212021-09-09 14:49:02 -070082 /* 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 */
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 */
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 */
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 */
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 */
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 */
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 */
185 public @Nullable Range<Integer> getDestinationPortRange() {
186 return mDstPortRange;
187 }
188
189 @Override
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
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
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
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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}