• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 com.android.server.connectivity;
18 
19 import android.util.Log;
20 import android.util.Range;
21 
22 import com.android.net.module.util.Struct;
23 import com.android.net.module.util.Struct.Field;
24 import com.android.net.module.util.Struct.Type;
25 
26 import java.net.Inet4Address;
27 import java.net.InetAddress;
28 import java.net.UnknownHostException;
29 
30 /** Value type for DSCP setting and rewriting to DSCP policy BPF maps. */
31 public class DscpPolicyValue extends Struct {
32     private static final String TAG = DscpPolicyValue.class.getSimpleName();
33 
34     @Field(order = 0, type = Type.ByteArray, arraysize = 16)
35     public final byte[] src46;
36 
37     @Field(order = 1, type = Type.ByteArray, arraysize = 16)
38     public final byte[] dst46;
39 
40     @Field(order = 2, type = Type.S32)
41     public final int ifIndex;
42 
43     @Field(order = 3, type = Type.UBE16)
44     public final int srcPort;
45 
46     @Field(order = 4, type = Type.U16)
47     public final int dstPortStart;
48 
49     @Field(order = 5, type = Type.U16)
50     public final int dstPortEnd;
51 
52     @Field(order = 6, type = Type.U8)
53     public final short proto;
54 
55     @Field(order = 7, type = Type.S8)
56     public final byte dscp;
57 
58     @Field(order = 8, type = Type.Bool)
59     public final boolean match_src_ip;
60 
61     @Field(order = 9, type = Type.Bool)
62     public final boolean match_dst_ip;
63 
64     @Field(order = 10, type = Type.Bool)
65     public final boolean match_src_port;
66 
67     @Field(order = 11, type = Type.Bool)
68     public final boolean match_proto;
69 
ipEmpty(final byte[] ip)70     private boolean ipEmpty(final byte[] ip) {
71         for (int i = 0; i < ip.length; i++) {
72             if (ip[i] != 0) return false;
73         }
74         return true;
75     }
76 
77     // TODO:  move to frameworks/libs/net and have this and BpfCoordinator import it.
toIpv4MappedAddressBytes(InetAddress ia)78     private byte[] toIpv4MappedAddressBytes(InetAddress ia) {
79         final byte[] addr6 = new byte[16];
80         if (ia != null) {
81             final byte[] addr4 = ia.getAddress();
82             addr6[10] = (byte) 0xff;
83             addr6[11] = (byte) 0xff;
84             addr6[12] = addr4[0];
85             addr6[13] = addr4[1];
86             addr6[14] = addr4[2];
87             addr6[15] = addr4[3];
88         }
89         return addr6;
90     }
91 
toAddressField(InetAddress addr)92     private byte[] toAddressField(InetAddress addr) {
93         if (addr == null) {
94             return EMPTY_ADDRESS_FIELD;
95         } else if (addr instanceof Inet4Address) {
96             return toIpv4MappedAddressBytes(addr);
97         } else {
98             return addr.getAddress();
99         }
100     }
101 
102     private static final byte[] EMPTY_ADDRESS_FIELD =
103             InetAddress.parseNumericAddress("::").getAddress();
104 
DscpPolicyValue(final InetAddress src46, final InetAddress dst46, final int ifIndex, final int srcPort, final int dstPortStart, final int dstPortEnd, final short proto, final byte dscp)105     private DscpPolicyValue(final InetAddress src46, final InetAddress dst46, final int ifIndex,
106             final int srcPort, final int dstPortStart, final int dstPortEnd, final short proto,
107             final byte dscp) {
108         this.src46 = toAddressField(src46);
109         this.dst46 = toAddressField(dst46);
110         this.ifIndex = ifIndex;
111 
112         // These params need to be stored as 0 because uints are used in BpfMap.
113         // If they are -1 BpfMap write will throw errors.
114         this.srcPort = srcPort != -1 ? srcPort : 0;
115         this.dstPortStart = dstPortStart != -1 ? dstPortStart : 0;
116         this.dstPortEnd = dstPortEnd != -1 ? dstPortEnd : 65535;
117         this.proto = proto != -1 ? proto : 0;
118 
119         this.dscp = dscp;
120         this.match_src_ip = (src46 != null);
121         this.match_dst_ip = (dst46 != null);
122         this.match_src_port = (srcPort != -1);
123         this.match_proto = (proto != -1);
124     }
125 
DscpPolicyValue(final InetAddress src46, final InetAddress dst46, final int ifIndex, final int srcPort, final Range<Integer> dstPort, final short proto, final byte dscp)126     public DscpPolicyValue(final InetAddress src46, final InetAddress dst46, final int ifIndex,
127             final int srcPort, final Range<Integer> dstPort, final short proto,
128             final byte dscp) {
129         this(src46, dst46, ifIndex, srcPort, dstPort != null ? dstPort.getLower() : -1,
130                 dstPort != null ? dstPort.getUpper() : -1, proto, dscp);
131     }
132 
133     public static final DscpPolicyValue NONE = new DscpPolicyValue(
134             null /* src46 */, null /* dst46 */, 0 /* ifIndex */, -1 /* srcPort */,
135             -1 /* dstPortStart */, -1 /* dstPortEnd */, (short) -1 /* proto */,
136             (byte) -1 /* dscp */);
137 
138     @Override
toString()139     public String toString() {
140         String srcIpString = "empty";
141         String dstIpString = "empty";
142 
143         // Separate try/catch for IP's so it's easier to debug.
144         try {
145             srcIpString = InetAddress.getByAddress(src46).getHostAddress();
146         }  catch (UnknownHostException e) {
147             Log.e(TAG, "Invalid SRC IP address", e);
148         }
149 
150         try {
151             dstIpString = InetAddress.getByAddress(src46).getHostAddress();
152         }  catch (UnknownHostException e) {
153             Log.e(TAG, "Invalid DST IP address", e);
154         }
155 
156         try {
157             return String.format(
158                     "src46: %s, dst46: %s, ifIndex: %d, srcPort: %d, dstPortStart: %d,"
159                     + " dstPortEnd: %d, protocol: %d, dscp %s", srcIpString, dstIpString,
160                     ifIndex, srcPort, dstPortStart, dstPortEnd, proto, dscp);
161         } catch (IllegalArgumentException e) {
162             return String.format("String format error: " + e);
163         }
164     }
165 }
166