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