blob: 923f162c92a6444d26a7ef1fd6a1ca68f0f4045c [file] [log] [blame]
Paul Jensen578a76e2016-01-14 14:54:39 -05001/*
2 * Copyright (C) 2016 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
Paul Jensenf21b4dc2016-03-18 12:22:09 -040017package android.net.apf;
Paul Jensen578a76e2016-01-14 14:54:39 -050018
Remi NGUYEN VAN811f6382019-01-20 12:08:21 +090019import static android.net.util.SocketUtils.makePacketSocketAddress;
Remi NGUYEN VANa5d31f52019-01-12 15:36:47 +090020import static android.system.OsConstants.AF_PACKET;
21import static android.system.OsConstants.ARPHRD_ETHER;
22import static android.system.OsConstants.ETH_P_ARP;
23import static android.system.OsConstants.ETH_P_IP;
24import static android.system.OsConstants.ETH_P_IPV6;
25import static android.system.OsConstants.IPPROTO_ICMPV6;
Aaron Huanga63c40e2019-01-15 16:53:51 +080026import static android.system.OsConstants.IPPROTO_TCP;
Remi NGUYEN VANa5d31f52019-01-12 15:36:47 +090027import static android.system.OsConstants.IPPROTO_UDP;
28import static android.system.OsConstants.SOCK_RAW;
29
Remi NGUYEN VAN3c600a12019-01-10 19:12:46 +090030import static com.android.server.util.NetworkStackConstants.ICMPV6_ECHO_REQUEST_TYPE;
31import static com.android.server.util.NetworkStackConstants.ICMPV6_NEIGHBOR_ADVERTISEMENT;
32import static com.android.server.util.NetworkStackConstants.ICMPV6_ROUTER_ADVERTISEMENT;
33import static com.android.server.util.NetworkStackConstants.ICMPV6_ROUTER_SOLICITATION;
Hugo Benichi495a17b2017-01-12 15:31:05 +090034
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +090035import android.annotation.Nullable;
Bernie Innocenti5be71dc2018-03-28 20:11:49 +090036import android.content.BroadcastReceiver;
37import android.content.Context;
38import android.content.Intent;
39import android.content.IntentFilter;
Hugo Benichi7d21eae2016-09-02 14:00:29 +090040import android.net.LinkAddress;
Paul Jensena8458c02016-03-25 11:25:57 -040041import android.net.LinkProperties;
junyulai352dc2f2019-01-08 20:04:33 +080042import android.net.TcpKeepalivePacketDataParcelable;
Paul Jensen578a76e2016-01-14 14:54:39 -050043import android.net.apf.ApfGenerator.IllegalInstructionException;
44import android.net.apf.ApfGenerator.Register;
Remi NGUYEN VAN3c600a12019-01-10 19:12:46 +090045import android.net.ip.IpClient.IpClientCallbacksWrapper;
Hugo Benichi4fc3ee52016-06-02 11:20:27 +090046import android.net.metrics.ApfProgramEvent;
Hugo Benichi647c86d2016-06-07 15:35:16 +090047import android.net.metrics.ApfStats;
Hugo Benichi4fc3ee52016-06-02 11:20:27 +090048import android.net.metrics.IpConnectivityLog;
Hugo Benichicfbf7412016-06-23 10:41:30 +090049import android.net.metrics.RaEvent;
Erik Kline8bd00d52017-12-08 17:47:50 +090050import android.net.util.InterfaceParams;
Remi NGUYEN VAN231b52b2019-01-29 15:38:52 +090051import android.net.util.NetworkStackUtils;
52import android.net.util.SocketUtils;
Bernie Innocenti5be71dc2018-03-28 20:11:49 +090053import android.os.PowerManager;
54import android.os.SystemClock;
Paul Jensen578a76e2016-01-14 14:54:39 -050055import android.system.ErrnoException;
56import android.system.Os;
Hugo Benichi4fc3ee52016-06-02 11:20:27 +090057import android.text.format.DateUtils;
Paul Jensen578a76e2016-01-14 14:54:39 -050058import android.util.Log;
59import android.util.Pair;
Aaron Huanga63c40e2019-01-15 16:53:51 +080060import android.util.SparseArray;
Remi NGUYEN VANa5d31f52019-01-12 15:36:47 +090061
Paul Jensendfd5a942016-03-17 13:22:29 -040062import com.android.internal.annotations.GuardedBy;
Paul Jensen9132f342016-04-13 15:00:26 -040063import com.android.internal.annotations.VisibleForTesting;
Paul Jensen578a76e2016-01-14 14:54:39 -050064import com.android.internal.util.HexDump;
Lorenzo Colitti5ff640d2016-03-03 17:53:46 +090065import com.android.internal.util.IndentingPrintWriter;
Remi NGUYEN VANa5d31f52019-01-12 15:36:47 +090066
Paul Jensen578a76e2016-01-14 14:54:39 -050067import java.io.FileDescriptor;
68import java.io.IOException;
Hugo Benichi7d21eae2016-09-02 14:00:29 +090069import java.net.Inet4Address;
Lorenzo Colitti5ff640d2016-03-03 17:53:46 +090070import java.net.Inet6Address;
71import java.net.InetAddress;
Remi NGUYEN VAN811f6382019-01-20 12:08:21 +090072import java.net.SocketAddress;
Paul Jensen578a76e2016-01-14 14:54:39 -050073import java.net.SocketException;
Lorenzo Colitti5ff640d2016-03-03 17:53:46 +090074import java.net.UnknownHostException;
Lorenzo Colitti5ff640d2016-03-03 17:53:46 +090075import java.nio.BufferUnderflowException;
Bernie Innocenti5be71dc2018-03-28 20:11:49 +090076import java.nio.ByteBuffer;
Paul Jensen578a76e2016-01-14 14:54:39 -050077import java.util.ArrayList;
78import java.util.Arrays;
Paul Jensen578a76e2016-01-14 14:54:39 -050079
80/**
81 * For networks that support packet filtering via APF programs, {@code ApfFilter}
82 * listens for IPv6 ICMPv6 router advertisements (RAs) and generates APF programs to
83 * filter out redundant duplicate ones.
84 *
Paul Jensendfd5a942016-03-17 13:22:29 -040085 * Threading model:
86 * A collection of RAs we've received is kept in mRas. Generating APF programs uses mRas to
87 * know what RAs to filter for, thus generating APF programs is dependent on mRas.
88 * mRas can be accessed by multiple threads:
89 * - ReceiveThread, which listens for RAs and adds them to mRas, and generates APF programs.
90 * - callers of:
91 * - setMulticastFilter(), which can cause an APF program to be generated.
92 * - dump(), which dumps mRas among other things.
93 * - shutdown(), which clears mRas.
94 * So access to mRas is synchronized.
95 *
Paul Jensen578a76e2016-01-14 14:54:39 -050096 * @hide
97 */
98public class ApfFilter {
Hugo Benichi647c86d2016-06-07 15:35:16 +090099
Hugo Benichi72166362017-10-13 16:32:20 +0900100 // Helper class for specifying functional filter parameters.
101 public static class ApfConfiguration {
102 public ApfCapabilities apfCapabilities;
103 public boolean multicastFilter;
104 public boolean ieee802_3Filter;
105 public int[] ethTypeBlackList;
106 }
107
Hugo Benichi647c86d2016-06-07 15:35:16 +0900108 // Enums describing the outcome of receiving an RA packet.
109 private static enum ProcessRaResult {
110 MATCH, // Received RA matched a known RA
111 DROPPED, // Received RA ignored due to MAX_RAS
112 PARSE_ERROR, // Received RA could not be parsed
113 ZERO_LIFETIME, // Received RA had 0 lifetime
114 UPDATE_NEW_RA, // APF program updated for new RA
115 UPDATE_EXPIRY // APF program updated for expiry
116 }
117
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +0900118 /**
119 * APF packet counters.
120 *
121 * Packet counters are 32bit big-endian values, and allocated near the end of the APF data
122 * buffer, using negative byte offsets, where -4 is equivalent to maximumApfProgramSize - 4,
123 * the last writable 32bit word.
124 */
125 @VisibleForTesting
Aaron Huang785e5f12018-10-31 15:57:48 +0800126 public static enum Counter {
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +0900127 RESERVED_OOB, // Points to offset 0 from the end of the buffer (out-of-bounds)
128 TOTAL_PACKETS,
129 PASSED_ARP,
130 PASSED_DHCP,
131 PASSED_IPV4,
132 PASSED_IPV6_NON_ICMP,
133 PASSED_IPV4_UNICAST,
134 PASSED_IPV6_ICMP,
135 PASSED_IPV6_UNICAST_NON_ICMP,
136 PASSED_ARP_NON_IPV4,
137 PASSED_ARP_UNKNOWN,
138 PASSED_ARP_UNICAST_REPLY,
139 PASSED_NON_IP_UNICAST,
140 DROPPED_ETH_BROADCAST,
141 DROPPED_RA,
142 DROPPED_GARP_REPLY,
143 DROPPED_ARP_OTHER_HOST,
144 DROPPED_IPV4_L2_BROADCAST,
145 DROPPED_IPV4_BROADCAST_ADDR,
146 DROPPED_IPV4_BROADCAST_NET,
147 DROPPED_IPV4_MULTICAST,
148 DROPPED_IPV6_ROUTER_SOLICITATION,
149 DROPPED_IPV6_MULTICAST_NA,
150 DROPPED_IPV6_MULTICAST,
151 DROPPED_IPV6_MULTICAST_PING,
152 DROPPED_IPV6_NON_ICMP_MULTICAST,
153 DROPPED_802_3_FRAME,
Aaron Huang04ed6a32018-11-15 20:30:46 +0800154 DROPPED_ETHERTYPE_BLACKLISTED,
Aaron Huanga63c40e2019-01-15 16:53:51 +0800155 DROPPED_ARP_REPLY_SPA_NO_HOST,
156 DROPPED_IPV4_KEEPALIVE_ACK,
157 DROPPED_IPV6_KEEPALIVE_ACK;
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +0900158
159 // Returns the negative byte offset from the end of the APF data segment for
160 // a given counter.
161 public int offset() {
162 return - this.ordinal() * 4; // Currently, all counters are 32bit long.
163 }
164
165 // Returns the total size of the data segment in bytes.
166 public static int totalSize() {
167 return (Counter.class.getEnumConstants().length - 1) * 4;
168 }
169 }
170
171 /**
172 * When APFv4 is supported, loads R1 with the offset of the specified counter.
173 */
Aaron Huang04ed6a32018-11-15 20:30:46 +0800174 private void maybeSetupCounter(ApfGenerator gen, Counter c) {
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +0900175 if (mApfCapabilities.hasDataAccess()) {
176 gen.addLoadImmediate(Register.R1, c.offset());
177 }
178 }
179
180 // When APFv4 is supported, these point to the trampolines generated by emitEpilogue().
181 // Otherwise, they're just aliases for PASS_LABEL and DROP_LABEL.
182 private final String mCountAndPassLabel;
183 private final String mCountAndDropLabel;
184
Paul Jensen578a76e2016-01-14 14:54:39 -0500185 // Thread to listen for RAs.
Paul Jensen9132f342016-04-13 15:00:26 -0400186 @VisibleForTesting
187 class ReceiveThread extends Thread {
Paul Jensen578a76e2016-01-14 14:54:39 -0500188 private final byte[] mPacket = new byte[1514];
189 private final FileDescriptor mSocket;
Hugo Benichi647c86d2016-06-07 15:35:16 +0900190 private final long mStart = SystemClock.elapsedRealtime();
Remi NGUYEN VAN7b84fb32019-01-19 21:13:24 +0900191
192 private int mReceivedRas = 0;
193 private int mMatchingRas = 0;
194 private int mDroppedRas = 0;
195 private int mParseErrors = 0;
196 private int mZeroLifetimeRas = 0;
197 private int mProgramUpdates = 0;
Hugo Benichi647c86d2016-06-07 15:35:16 +0900198
Hugo Benichi22d9b2d2017-02-22 13:02:27 +0900199 private volatile boolean mStopped;
Hugo Benichi647c86d2016-06-07 15:35:16 +0900200
Paul Jensen578a76e2016-01-14 14:54:39 -0500201 public ReceiveThread(FileDescriptor socket) {
202 mSocket = socket;
203 }
204
205 public void halt() {
206 mStopped = true;
Remi NGUYEN VAN231b52b2019-01-29 15:38:52 +0900207 // Interrupts the read() call the thread is blocked in.
208 NetworkStackUtils.closeSocketQuietly(mSocket);
Paul Jensen578a76e2016-01-14 14:54:39 -0500209 }
210
211 @Override
212 public void run() {
213 log("begin monitoring");
214 while (!mStopped) {
215 try {
216 int length = Os.read(mSocket, mPacket, 0, mPacket.length);
Hugo Benichi647c86d2016-06-07 15:35:16 +0900217 updateStats(processRa(mPacket, length));
Paul Jensen578a76e2016-01-14 14:54:39 -0500218 } catch (IOException|ErrnoException e) {
219 if (!mStopped) {
220 Log.e(TAG, "Read error", e);
221 }
222 }
223 }
Hugo Benichi647c86d2016-06-07 15:35:16 +0900224 logStats();
225 }
226
227 private void updateStats(ProcessRaResult result) {
Remi NGUYEN VAN7b84fb32019-01-19 21:13:24 +0900228 mReceivedRas++;
Hugo Benichi647c86d2016-06-07 15:35:16 +0900229 switch(result) {
230 case MATCH:
Remi NGUYEN VAN7b84fb32019-01-19 21:13:24 +0900231 mMatchingRas++;
Hugo Benichi647c86d2016-06-07 15:35:16 +0900232 return;
233 case DROPPED:
Remi NGUYEN VAN7b84fb32019-01-19 21:13:24 +0900234 mDroppedRas++;
Hugo Benichi647c86d2016-06-07 15:35:16 +0900235 return;
236 case PARSE_ERROR:
Remi NGUYEN VAN7b84fb32019-01-19 21:13:24 +0900237 mParseErrors++;
Hugo Benichi647c86d2016-06-07 15:35:16 +0900238 return;
239 case ZERO_LIFETIME:
Remi NGUYEN VAN7b84fb32019-01-19 21:13:24 +0900240 mZeroLifetimeRas++;
Hugo Benichi647c86d2016-06-07 15:35:16 +0900241 return;
242 case UPDATE_EXPIRY:
Remi NGUYEN VAN7b84fb32019-01-19 21:13:24 +0900243 mMatchingRas++;
244 mProgramUpdates++;
Hugo Benichi647c86d2016-06-07 15:35:16 +0900245 return;
246 case UPDATE_NEW_RA:
Remi NGUYEN VAN7b84fb32019-01-19 21:13:24 +0900247 mProgramUpdates++;
Hugo Benichi647c86d2016-06-07 15:35:16 +0900248 return;
249 }
250 }
251
252 private void logStats() {
Hugo Benichi22d9b2d2017-02-22 13:02:27 +0900253 final long nowMs = SystemClock.elapsedRealtime();
254 synchronized (this) {
Remi NGUYEN VAN7b84fb32019-01-19 21:13:24 +0900255 final ApfStats stats = new ApfStats.Builder()
256 .setReceivedRas(mReceivedRas)
257 .setMatchingRas(mMatchingRas)
258 .setDroppedRas(mDroppedRas)
259 .setParseErrors(mParseErrors)
260 .setZeroLifetimeRas(mZeroLifetimeRas)
261 .setProgramUpdates(mProgramUpdates)
262 .setDurationMs(nowMs - mStart)
263 .setMaxProgramSize(mApfCapabilities.maximumApfProgramSize)
264 .setProgramUpdatesAll(mNumProgramUpdates)
265 .setProgramUpdatesAllowingMulticast(mNumProgramUpdatesAllowingMulticast)
266 .build();
267 mMetricsLog.log(stats);
Hugo Benichi22d9b2d2017-02-22 13:02:27 +0900268 logApfProgramEventLocked(nowMs / DateUtils.SECOND_IN_MILLIS);
269 }
Paul Jensen578a76e2016-01-14 14:54:39 -0500270 }
271 }
272
273 private static final String TAG = "ApfFilter";
Lorenzo Colitti39c0d422016-03-23 00:23:29 +0900274 private static final boolean DBG = true;
Joe Onorato7a8797f2016-03-17 13:41:23 -0700275 private static final boolean VDBG = false;
Paul Jensen578a76e2016-01-14 14:54:39 -0500276
Paul Jensendfd5a942016-03-17 13:22:29 -0400277 private static final int ETH_HEADER_LEN = 14;
Paul Jensen91723d72016-04-14 14:51:02 -0400278 private static final int ETH_DEST_ADDR_OFFSET = 0;
Paul Jensendfd5a942016-03-17 13:22:29 -0400279 private static final int ETH_ETHERTYPE_OFFSET = 12;
Ahmed ElArabawy8537c582017-06-12 18:01:11 -0700280 private static final int ETH_TYPE_MIN = 0x0600;
Ahmed ElArabawyfd424162017-08-02 13:31:05 -0700281 private static final int ETH_TYPE_MAX = 0xFFFF;
Hugo Benichi961ca492016-09-02 11:04:34 +0900282 private static final byte[] ETH_BROADCAST_MAC_ADDRESS =
283 {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff };
Paul Jensendfd5a942016-03-17 13:22:29 -0400284 // TODO: Make these offsets relative to end of link-layer header; don't include ETH_HEADER_LEN.
285 private static final int IPV4_FRAGMENT_OFFSET_OFFSET = ETH_HEADER_LEN + 6;
286 // Endianness is not an issue for this constant because the APF interpreter always operates in
287 // network byte order.
288 private static final int IPV4_FRAGMENT_OFFSET_MASK = 0x1fff;
289 private static final int IPV4_PROTOCOL_OFFSET = ETH_HEADER_LEN + 9;
290 private static final int IPV4_DEST_ADDR_OFFSET = ETH_HEADER_LEN + 16;
Hugo Benichi38db9762016-07-12 15:08:50 +0900291 private static final int IPV4_ANY_HOST_ADDRESS = 0;
Hugo Benichi0dc1d312016-09-02 12:40:31 +0900292 private static final int IPV4_BROADCAST_ADDRESS = -1; // 255.255.255.255
Aaron Huanga63c40e2019-01-15 16:53:51 +0800293 private static final int IPV4_HEADER_LEN = 20; // Without options
Paul Jensendfd5a942016-03-17 13:22:29 -0400294
Joel Scherpelz967dec72017-05-24 15:08:39 +0900295 // Traffic class and Flow label are not byte aligned. Luckily we
296 // don't care about either value so we'll consider bytes 1-3 of the
297 // IPv6 header as don't care.
298 private static final int IPV6_FLOW_LABEL_OFFSET = ETH_HEADER_LEN + 1;
299 private static final int IPV6_FLOW_LABEL_LEN = 3;
Paul Jensendfd5a942016-03-17 13:22:29 -0400300 private static final int IPV6_NEXT_HEADER_OFFSET = ETH_HEADER_LEN + 6;
301 private static final int IPV6_SRC_ADDR_OFFSET = ETH_HEADER_LEN + 8;
302 private static final int IPV6_DEST_ADDR_OFFSET = ETH_HEADER_LEN + 24;
303 private static final int IPV6_HEADER_LEN = 40;
304 // The IPv6 all nodes address ff02::1
305 private static final byte[] IPV6_ALL_NODES_ADDRESS =
Hugo Benichi961ca492016-09-02 11:04:34 +0900306 { (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
Paul Jensendfd5a942016-03-17 13:22:29 -0400307
308 private static final int ICMP6_TYPE_OFFSET = ETH_HEADER_LEN + IPV6_HEADER_LEN;
Paul Jensendfd5a942016-03-17 13:22:29 -0400309
310 // NOTE: this must be added to the IPv4 header length in IPV4_HEADER_SIZE_MEMORY_SLOT
311 private static final int UDP_DESTINATION_PORT_OFFSET = ETH_HEADER_LEN + 2;
312 private static final int UDP_HEADER_LEN = 8;
313
Aaron Huanga63c40e2019-01-15 16:53:51 +0800314 private static final int TCP_HEADER_SIZE_OFFSET = 12;
315
Paul Jensendfd5a942016-03-17 13:22:29 -0400316 private static final int DHCP_CLIENT_PORT = 68;
317 // NOTE: this must be added to the IPv4 header length in IPV4_HEADER_SIZE_MEMORY_SLOT
318 private static final int DHCP_CLIENT_MAC_OFFSET = ETH_HEADER_LEN + UDP_HEADER_LEN + 28;
319
Hugo Benichi4fc3ee52016-06-02 11:20:27 +0900320 private static final int ARP_HEADER_OFFSET = ETH_HEADER_LEN;
Hugo Benichi961ca492016-09-02 11:04:34 +0900321 private static final byte[] ARP_IPV4_HEADER = {
Paul Jensena8458c02016-03-25 11:25:57 -0400322 0, 1, // Hardware type: Ethernet (1)
323 8, 0, // Protocol type: IP (0x0800)
324 6, // Hardware size: 6
325 4, // Protocol size: 4
Paul Jensena8458c02016-03-25 11:25:57 -0400326 };
Aaron Huang04ed6a32018-11-15 20:30:46 +0800327 private static final int ARP_OPCODE_OFFSET = ARP_HEADER_OFFSET + 6;
328 // Opcode: ARP request (0x0001), ARP reply (0x0002)
329 private static final short ARP_OPCODE_REQUEST = 1;
330 private static final short ARP_OPCODE_REPLY = 2;
331 private static final int ARP_SOURCE_IP_ADDRESS_OFFSET = ARP_HEADER_OFFSET + 14;
332 private static final int ARP_TARGET_IP_ADDRESS_OFFSET = ARP_HEADER_OFFSET + 24;
Hugo Benichi22d9b2d2017-02-22 13:02:27 +0900333 // Do not log ApfProgramEvents whose actual lifetimes was less than this.
334 private static final int APF_PROGRAM_EVENT_LIFETIME_THRESHOLD = 2;
Ahmed ElArabawyfd424162017-08-02 13:31:05 -0700335 // Limit on the Black List size to cap on program usage for this
336 // TODO: Select a proper max length
337 private static final int APF_MAX_ETH_TYPE_BLACK_LIST_LEN = 20;
Paul Jensena8458c02016-03-25 11:25:57 -0400338
Paul Jensenf21b4dc2016-03-18 12:22:09 -0400339 private final ApfCapabilities mApfCapabilities;
Remi NGUYEN VAN3c600a12019-01-10 19:12:46 +0900340 private final IpClientCallbacksWrapper mIpClientCallback;
Erik Kline8bd00d52017-12-08 17:47:50 +0900341 private final InterfaceParams mInterfaceParams;
Hugo Benichi6ccd51a2016-07-04 09:22:30 +0900342 private final IpConnectivityLog mMetricsLog;
Ahmed ElArabawy8537c582017-06-12 18:01:11 -0700343
Paul Jensen9132f342016-04-13 15:00:26 -0400344 @VisibleForTesting
345 byte[] mHardwareAddress;
346 @VisibleForTesting
347 ReceiveThread mReceiveThread;
Paul Jensendfd5a942016-03-17 13:22:29 -0400348 @GuardedBy("this")
Paul Jensen578a76e2016-01-14 14:54:39 -0500349 private long mUniqueCounter;
Paul Jensendfd5a942016-03-17 13:22:29 -0400350 @GuardedBy("this")
351 private boolean mMulticastFilter;
Bernie Innocenti5be71dc2018-03-28 20:11:49 +0900352 @GuardedBy("this")
353 private boolean mInDozeMode;
Ahmed ElArabawy8537c582017-06-12 18:01:11 -0700354 private final boolean mDrop802_3Frames;
Ahmed ElArabawyfd424162017-08-02 13:31:05 -0700355 private final int[] mEthTypeBlackList;
356
Bernie Innocenti5be71dc2018-03-28 20:11:49 +0900357 // Detects doze mode state transitions.
358 private final BroadcastReceiver mDeviceIdleReceiver = new BroadcastReceiver() {
359 @Override
360 public void onReceive(Context context, Intent intent) {
361 String action = intent.getAction();
362 if (action.equals(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED)) {
363 PowerManager powerManager =
364 (PowerManager) context.getSystemService(Context.POWER_SERVICE);
365 final boolean deviceIdle = powerManager.isDeviceIdleMode();
366 setDozeMode(deviceIdle);
367 }
368 }
369 };
370 private final Context mContext;
371
Paul Jensena8458c02016-03-25 11:25:57 -0400372 // Our IPv4 address, if we have just one, otherwise null.
373 @GuardedBy("this")
374 private byte[] mIPv4Address;
Hugo Benichi7d21eae2016-09-02 14:00:29 +0900375 // The subnet prefix length of our IPv4 network. Only valid if mIPv4Address is not null.
376 @GuardedBy("this")
377 private int mIPv4PrefixLength;
Paul Jensen578a76e2016-01-14 14:54:39 -0500378
Paul Jensen9132f342016-04-13 15:00:26 -0400379 @VisibleForTesting
Bernie Innocenti5be71dc2018-03-28 20:11:49 +0900380 ApfFilter(Context context, ApfConfiguration config, InterfaceParams ifParams,
Remi NGUYEN VAN3c600a12019-01-10 19:12:46 +0900381 IpClientCallbacksWrapper ipClientCallback, IpConnectivityLog log) {
Hugo Benichi72166362017-10-13 16:32:20 +0900382 mApfCapabilities = config.apfCapabilities;
Erik Kline1b293582017-10-11 19:43:10 +0900383 mIpClientCallback = ipClientCallback;
Erik Kline8bd00d52017-12-08 17:47:50 +0900384 mInterfaceParams = ifParams;
Hugo Benichi72166362017-10-13 16:32:20 +0900385 mMulticastFilter = config.multicastFilter;
386 mDrop802_3Frames = config.ieee802_3Filter;
Bernie Innocenti5be71dc2018-03-28 20:11:49 +0900387 mContext = context;
Ahmed ElArabawyfd424162017-08-02 13:31:05 -0700388
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +0900389 if (mApfCapabilities.hasDataAccess()) {
390 mCountAndPassLabel = "countAndPass";
391 mCountAndDropLabel = "countAndDrop";
392 } else {
393 // APFv4 unsupported: turn jumps to the counter trampolines to immediately PASS or DROP,
394 // preserving the original pre-APFv4 behavior.
395 mCountAndPassLabel = ApfGenerator.PASS_LABEL;
396 mCountAndDropLabel = ApfGenerator.DROP_LABEL;
397 }
398
Ahmed ElArabawyfd424162017-08-02 13:31:05 -0700399 // Now fill the black list from the passed array
Hugo Benichi72166362017-10-13 16:32:20 +0900400 mEthTypeBlackList = filterEthTypeBlackList(config.ethTypeBlackList);
Ahmed ElArabawyfd424162017-08-02 13:31:05 -0700401
Hugo Benichi6ccd51a2016-07-04 09:22:30 +0900402 mMetricsLog = log;
Paul Jensenf21b4dc2016-03-18 12:22:09 -0400403
Erik Kline1b293582017-10-11 19:43:10 +0900404 // TODO: ApfFilter should not generate programs until IpClient sends provisioning success.
Paul Jensen578a76e2016-01-14 14:54:39 -0500405 maybeStartFilter();
Bernie Innocenti5be71dc2018-03-28 20:11:49 +0900406
407 // Listen for doze-mode transition changes to enable/disable the IPv6 multicast filter.
408 mContext.registerReceiver(mDeviceIdleReceiver,
409 new IntentFilter(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED));
Paul Jensen578a76e2016-01-14 14:54:39 -0500410 }
411
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +0900412 public synchronized void setDataSnapshot(byte[] data) {
413 mDataSnapshot = data;
414 }
415
Paul Jensen578a76e2016-01-14 14:54:39 -0500416 private void log(String s) {
Erik Kline8bd00d52017-12-08 17:47:50 +0900417 Log.d(TAG, "(" + mInterfaceParams.name + "): " + s);
Paul Jensen578a76e2016-01-14 14:54:39 -0500418 }
419
Paul Jensendfd5a942016-03-17 13:22:29 -0400420 @GuardedBy("this")
421 private long getUniqueNumberLocked() {
Paul Jensen578a76e2016-01-14 14:54:39 -0500422 return mUniqueCounter++;
423 }
424
Ahmed ElArabawyfd424162017-08-02 13:31:05 -0700425 @GuardedBy("this")
426 private static int[] filterEthTypeBlackList(int[] ethTypeBlackList) {
427 ArrayList<Integer> bl = new ArrayList<Integer>();
428
429 for (int p : ethTypeBlackList) {
430 // Check if the protocol is a valid ether type
431 if ((p < ETH_TYPE_MIN) || (p > ETH_TYPE_MAX)) {
432 continue;
433 }
434
435 // Check if the protocol is not repeated in the passed array
436 if (bl.contains(p)) {
437 continue;
438 }
439
440 // Check if list reach its max size
441 if (bl.size() == APF_MAX_ETH_TYPE_BLACK_LIST_LEN) {
442 Log.w(TAG, "Passed EthType Black List size too large (" + bl.size() +
443 ") using top " + APF_MAX_ETH_TYPE_BLACK_LIST_LEN + " protocols");
444 break;
445 }
446
447 // Now add the protocol to the list
448 bl.add(p);
449 }
450
451 return bl.stream().mapToInt(Integer::intValue).toArray();
452 }
453
Paul Jensen578a76e2016-01-14 14:54:39 -0500454 /**
455 * Attempt to start listening for RAs and, if RAs are received, generating and installing
456 * filters to ignore useless RAs.
457 */
Paul Jensen9132f342016-04-13 15:00:26 -0400458 @VisibleForTesting
459 void maybeStartFilter() {
Paul Jensen578a76e2016-01-14 14:54:39 -0500460 FileDescriptor socket;
461 try {
Erik Kline8bd00d52017-12-08 17:47:50 +0900462 mHardwareAddress = mInterfaceParams.macAddr.toByteArray();
Paul Jensendfd5a942016-03-17 13:22:29 -0400463 synchronized(this) {
Bernie Innocenti8d65db32018-05-09 17:58:50 +0900464 // Clear the APF memory to reset all counters upon connecting to the first AP
465 // in an SSID. This is limited to APFv4 devices because this large write triggers
466 // a crash on some older devices (b/78905546).
467 if (mApfCapabilities.hasDataAccess()) {
468 byte[] zeroes = new byte[mApfCapabilities.maximumApfProgramSize];
469 mIpClientCallback.installPacketFilter(zeroes);
470 }
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +0900471
Paul Jensendfd5a942016-03-17 13:22:29 -0400472 // Install basic filters
473 installNewProgramLocked();
474 }
Paul Jensen578a76e2016-01-14 14:54:39 -0500475 socket = Os.socket(AF_PACKET, SOCK_RAW, ETH_P_IPV6);
Remi NGUYEN VAN811f6382019-01-20 12:08:21 +0900476 SocketAddress addr = makePacketSocketAddress(
Erik Kline8bd00d52017-12-08 17:47:50 +0900477 (short) ETH_P_IPV6, mInterfaceParams.index);
Remi NGUYEN VAN231b52b2019-01-29 15:38:52 +0900478 SocketUtils.bindSocket(socket, addr);
479 SocketUtils.attachRaFilter(socket, mApfCapabilities.apfPacketFormat);
Paul Jensen578a76e2016-01-14 14:54:39 -0500480 } catch(SocketException|ErrnoException e) {
Paul Jensendfd5a942016-03-17 13:22:29 -0400481 Log.e(TAG, "Error starting filter", e);
Paul Jensen578a76e2016-01-14 14:54:39 -0500482 return;
483 }
484 mReceiveThread = new ReceiveThread(socket);
485 mReceiveThread.start();
486 }
487
Hugo Benichidafc44e2016-10-17 14:21:33 +0900488 // Returns seconds since device boot.
Hugo Benichi4456f332016-12-19 14:50:52 +0900489 @VisibleForTesting
490 protected long currentTimeSeconds() {
Hugo Benichidafc44e2016-10-17 14:21:33 +0900491 return SystemClock.elapsedRealtime() / DateUtils.SECOND_IN_MILLIS;
Paul Jensen578a76e2016-01-14 14:54:39 -0500492 }
493
Hugo Benichi0668a612016-10-06 15:19:36 +0900494 public static class InvalidRaException extends Exception {
495 public InvalidRaException(String m) {
496 super(m);
497 }
498 }
499
Paul Jensen578a76e2016-01-14 14:54:39 -0500500 // A class to hold information about an RA.
Hugo Benichi0668a612016-10-06 15:19:36 +0900501 @VisibleForTesting
502 class Ra {
Paul Jensen578a76e2016-01-14 14:54:39 -0500503 // From RFC4861:
504 private static final int ICMP6_RA_HEADER_LEN = 16;
Lorenzo Colittie6dfc172016-03-03 17:53:33 +0900505 private static final int ICMP6_RA_CHECKSUM_OFFSET =
506 ETH_HEADER_LEN + IPV6_HEADER_LEN + 2;
507 private static final int ICMP6_RA_CHECKSUM_LEN = 2;
Paul Jensen578a76e2016-01-14 14:54:39 -0500508 private static final int ICMP6_RA_OPTION_OFFSET =
509 ETH_HEADER_LEN + IPV6_HEADER_LEN + ICMP6_RA_HEADER_LEN;
510 private static final int ICMP6_RA_ROUTER_LIFETIME_OFFSET =
511 ETH_HEADER_LEN + IPV6_HEADER_LEN + 6;
512 private static final int ICMP6_RA_ROUTER_LIFETIME_LEN = 2;
513 // Prefix information option.
514 private static final int ICMP6_PREFIX_OPTION_TYPE = 3;
515 private static final int ICMP6_PREFIX_OPTION_LEN = 32;
516 private static final int ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET = 4;
517 private static final int ICMP6_PREFIX_OPTION_VALID_LIFETIME_LEN = 4;
518 private static final int ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_OFFSET = 8;
519 private static final int ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_LEN = 4;
520
521 // From RFC6106: Recursive DNS Server option
522 private static final int ICMP6_RDNSS_OPTION_TYPE = 25;
523 // From RFC6106: DNS Search List option
524 private static final int ICMP6_DNSSL_OPTION_TYPE = 31;
525
526 // From RFC4191: Route Information option
527 private static final int ICMP6_ROUTE_INFO_OPTION_TYPE = 24;
528 // Above three options all have the same format:
529 private static final int ICMP6_4_BYTE_LIFETIME_OFFSET = 4;
530 private static final int ICMP6_4_BYTE_LIFETIME_LEN = 4;
531
Paul Jensen1c71cb32016-03-25 11:39:58 -0400532 // Note: mPacket's position() cannot be assumed to be reset.
Paul Jensen578a76e2016-01-14 14:54:39 -0500533 private final ByteBuffer mPacket;
534 // List of binary ranges that include the whole packet except the lifetimes.
535 // Pairs consist of offset and length.
536 private final ArrayList<Pair<Integer, Integer>> mNonLifetimes =
537 new ArrayList<Pair<Integer, Integer>>();
538 // Minimum lifetime in packet
539 long mMinLifetime;
540 // When the packet was last captured, in seconds since Unix Epoch
541 long mLastSeen;
542
Lorenzo Colitti5ff640d2016-03-03 17:53:46 +0900543 // For debugging only. Offsets into the packet where PIOs are.
Lorenzo Colitti059e2bb2016-04-08 20:51:39 +0900544 private final ArrayList<Integer> mPrefixOptionOffsets = new ArrayList<>();
545
546 // For debugging only. Offsets into the packet where RDNSS options are.
547 private final ArrayList<Integer> mRdnssOptionOffsets = new ArrayList<>();
548
Lorenzo Colitti5ff640d2016-03-03 17:53:46 +0900549 // For debugging only. How many times this RA was seen.
550 int seenCount = 0;
551
Lorenzo Colitti39c0d422016-03-23 00:23:29 +0900552 // For debugging only. Returns the hex representation of the last matching packet.
553 String getLastMatchingPacket() {
Lorenzo Colitti059e2bb2016-04-08 20:51:39 +0900554 return HexDump.toHexString(mPacket.array(), 0, mPacket.capacity(),
555 false /* lowercase */);
Lorenzo Colitti39c0d422016-03-23 00:23:29 +0900556 }
Lorenzo Colitti5ff640d2016-03-03 17:53:46 +0900557
Lorenzo Colitti059e2bb2016-04-08 20:51:39 +0900558 // For debugging only. Returns the string representation of the IPv6 address starting at
559 // position pos in the packet.
Lorenzo Colitti5ff640d2016-03-03 17:53:46 +0900560 private String IPv6AddresstoString(int pos) {
561 try {
562 byte[] array = mPacket.array();
563 // Can't just call copyOfRange() and see if it throws, because if it reads past the
564 // end it pads with zeros instead of throwing.
565 if (pos < 0 || pos + 16 > array.length || pos + 16 < pos) {
566 return "???";
567 }
568 byte[] addressBytes = Arrays.copyOfRange(array, pos, pos + 16);
569 InetAddress address = (Inet6Address) InetAddress.getByAddress(addressBytes);
570 return address.getHostAddress();
571 } catch (UnsupportedOperationException e) {
572 // array() failed. Cannot happen, mPacket is array-backed and read-write.
573 return "???";
Hugo Benichi0668a612016-10-06 15:19:36 +0900574 } catch (ClassCastException|UnknownHostException e) {
Lorenzo Colitti5ff640d2016-03-03 17:53:46 +0900575 // Cannot happen.
576 return "???";
577 }
578 }
579
580 // Can't be static because it's in a non-static inner class.
Hugo Benichicfbf7412016-06-23 10:41:30 +0900581 // TODO: Make this static once RA is its own class.
Lorenzo Colitti059e2bb2016-04-08 20:51:39 +0900582 private void prefixOptionToString(StringBuffer sb, int offset) {
583 String prefix = IPv6AddresstoString(offset + 16);
Hugo Benichi4104ff92016-10-13 09:26:01 +0900584 int length = getUint8(mPacket, offset + 2);
585 long valid = getUint32(mPacket, offset + 4);
586 long preferred = getUint32(mPacket, offset + 8);
Lorenzo Colitti059e2bb2016-04-08 20:51:39 +0900587 sb.append(String.format("%s/%d %ds/%ds ", prefix, length, valid, preferred));
588 }
589
590 private void rdnssOptionToString(StringBuffer sb, int offset) {
Hugo Benichi4104ff92016-10-13 09:26:01 +0900591 int optLen = getUint8(mPacket, offset + 1) * 8;
Lorenzo Colitti059e2bb2016-04-08 20:51:39 +0900592 if (optLen < 24) return; // Malformed or empty.
Hugo Benichi4104ff92016-10-13 09:26:01 +0900593 long lifetime = getUint32(mPacket, offset + 4);
Lorenzo Colitti059e2bb2016-04-08 20:51:39 +0900594 int numServers = (optLen - 8) / 16;
595 sb.append("DNS ").append(lifetime).append("s");
596 for (int server = 0; server < numServers; server++) {
597 sb.append(" ").append(IPv6AddresstoString(offset + 8 + 16 * server));
598 }
599 }
600
Lorenzo Colitti5ff640d2016-03-03 17:53:46 +0900601 public String toString() {
602 try {
603 StringBuffer sb = new StringBuffer();
Lorenzo Colitti059e2bb2016-04-08 20:51:39 +0900604 sb.append(String.format("RA %s -> %s %ds ",
Lorenzo Colitti5ff640d2016-03-03 17:53:46 +0900605 IPv6AddresstoString(IPV6_SRC_ADDR_OFFSET),
Paul Jensendfd5a942016-03-17 13:22:29 -0400606 IPv6AddresstoString(IPV6_DEST_ADDR_OFFSET),
Hugo Benichi4104ff92016-10-13 09:26:01 +0900607 getUint16(mPacket, ICMP6_RA_ROUTER_LIFETIME_OFFSET)));
Lorenzo Colitti5ff640d2016-03-03 17:53:46 +0900608 for (int i: mPrefixOptionOffsets) {
Lorenzo Colitti059e2bb2016-04-08 20:51:39 +0900609 prefixOptionToString(sb, i);
610 }
611 for (int i: mRdnssOptionOffsets) {
612 rdnssOptionToString(sb, i);
Lorenzo Colitti5ff640d2016-03-03 17:53:46 +0900613 }
614 return sb.toString();
Hugo Benichi0668a612016-10-06 15:19:36 +0900615 } catch (BufferUnderflowException|IndexOutOfBoundsException e) {
Lorenzo Colitti5ff640d2016-03-03 17:53:46 +0900616 return "<Malformed RA>";
617 }
618 }
619
Paul Jensen578a76e2016-01-14 14:54:39 -0500620 /**
621 * Add a binary range of the packet that does not include a lifetime to mNonLifetimes.
622 * Assumes mPacket.position() is as far as we've parsed the packet.
623 * @param lastNonLifetimeStart offset within packet of where the last binary range of
624 * data not including a lifetime.
625 * @param lifetimeOffset offset from mPacket.position() to the next lifetime data.
626 * @param lifetimeLength length of the next lifetime data.
627 * @return offset within packet of where the next binary range of data not including
Hugo Benichi6ccd51a2016-07-04 09:22:30 +0900628 * a lifetime. This can be passed into the next invocation of this function
Paul Jensen578a76e2016-01-14 14:54:39 -0500629 * via {@code lastNonLifetimeStart}.
630 */
631 private int addNonLifetime(int lastNonLifetimeStart, int lifetimeOffset,
632 int lifetimeLength) {
633 lifetimeOffset += mPacket.position();
634 mNonLifetimes.add(new Pair<Integer, Integer>(lastNonLifetimeStart,
635 lifetimeOffset - lastNonLifetimeStart));
636 return lifetimeOffset + lifetimeLength;
637 }
638
Hugo Benichicfbf7412016-06-23 10:41:30 +0900639 private int addNonLifetimeU32(int lastNonLifetimeStart) {
640 return addNonLifetime(lastNonLifetimeStart,
641 ICMP6_4_BYTE_LIFETIME_OFFSET, ICMP6_4_BYTE_LIFETIME_LEN);
642 }
643
Bernie Innocenti408dbda2018-03-22 23:07:47 +0900644 // Note that this parses RA and may throw InvalidRaException (from
Lorenzo Colitti8995d852016-06-23 15:24:46 +0900645 // Buffer.position(int) or due to an invalid-length option) or IndexOutOfBoundsException
646 // (from ByteBuffer.get(int) ) if parsing encounters something non-compliant with
647 // specifications.
Hugo Benichi0668a612016-10-06 15:19:36 +0900648 Ra(byte[] packet, int length) throws InvalidRaException {
649 if (length < ICMP6_RA_OPTION_OFFSET) {
650 throw new InvalidRaException("Not an ICMP6 router advertisement");
651 }
652
Hugo Benichi6ccd51a2016-07-04 09:22:30 +0900653 mPacket = ByteBuffer.wrap(Arrays.copyOf(packet, length));
Hugo Benichi4456f332016-12-19 14:50:52 +0900654 mLastSeen = currentTimeSeconds();
Paul Jensen4b545b02016-07-20 15:01:17 -0400655
656 // Sanity check packet in case a packet arrives before we attach RA filter
657 // to our packet socket. b/29586253
658 if (getUint16(mPacket, ETH_ETHERTYPE_OFFSET) != ETH_P_IPV6 ||
Hugo Benichi4104ff92016-10-13 09:26:01 +0900659 getUint8(mPacket, IPV6_NEXT_HEADER_OFFSET) != IPPROTO_ICMPV6 ||
Bernie Innocenti5be71dc2018-03-28 20:11:49 +0900660 getUint8(mPacket, ICMP6_TYPE_OFFSET) != ICMPV6_ROUTER_ADVERTISEMENT) {
Hugo Benichi0668a612016-10-06 15:19:36 +0900661 throw new InvalidRaException("Not an ICMP6 router advertisement");
Paul Jensen4b545b02016-07-20 15:01:17 -0400662 }
663
664
Hugo Benichi6ccd51a2016-07-04 09:22:30 +0900665 RaEvent.Builder builder = new RaEvent.Builder();
Paul Jensen578a76e2016-01-14 14:54:39 -0500666
Joel Scherpelz967dec72017-05-24 15:08:39 +0900667 // Ignore the flow label and low 4 bits of traffic class.
Lorenzo Colittie6dfc172016-03-03 17:53:33 +0900668 int lastNonLifetimeStart = addNonLifetime(0,
Joel Scherpelz967dec72017-05-24 15:08:39 +0900669 IPV6_FLOW_LABEL_OFFSET,
670 IPV6_FLOW_LABEL_LEN);
671
672 // Ignore the checksum.
673 lastNonLifetimeStart = addNonLifetime(lastNonLifetimeStart,
Lorenzo Colittie6dfc172016-03-03 17:53:33 +0900674 ICMP6_RA_CHECKSUM_OFFSET,
675 ICMP6_RA_CHECKSUM_LEN);
676
Paul Jensen578a76e2016-01-14 14:54:39 -0500677 // Parse router lifetime
Lorenzo Colittie6dfc172016-03-03 17:53:33 +0900678 lastNonLifetimeStart = addNonLifetime(lastNonLifetimeStart,
679 ICMP6_RA_ROUTER_LIFETIME_OFFSET,
Paul Jensen578a76e2016-01-14 14:54:39 -0500680 ICMP6_RA_ROUTER_LIFETIME_LEN);
Hugo Benichi6ccd51a2016-07-04 09:22:30 +0900681 builder.updateRouterLifetime(getUint16(mPacket, ICMP6_RA_ROUTER_LIFETIME_OFFSET));
Hugo Benichicfbf7412016-06-23 10:41:30 +0900682
Lorenzo Colitti059e2bb2016-04-08 20:51:39 +0900683 // Ensures that the RA is not truncated.
Paul Jensen578a76e2016-01-14 14:54:39 -0500684 mPacket.position(ICMP6_RA_OPTION_OFFSET);
685 while (mPacket.hasRemaining()) {
Hugo Benichicfbf7412016-06-23 10:41:30 +0900686 final int position = mPacket.position();
Hugo Benichi4104ff92016-10-13 09:26:01 +0900687 final int optionType = getUint8(mPacket, position);
688 final int optionLength = getUint8(mPacket, position + 1) * 8;
Hugo Benichi6ccd51a2016-07-04 09:22:30 +0900689 long lifetime;
Paul Jensen578a76e2016-01-14 14:54:39 -0500690 switch (optionType) {
691 case ICMP6_PREFIX_OPTION_TYPE:
692 // Parse valid lifetime
693 lastNonLifetimeStart = addNonLifetime(lastNonLifetimeStart,
694 ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET,
695 ICMP6_PREFIX_OPTION_VALID_LIFETIME_LEN);
Hugo Benichi6ccd51a2016-07-04 09:22:30 +0900696 lifetime = getUint32(mPacket,
697 position + ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET);
698 builder.updatePrefixValidLifetime(lifetime);
Paul Jensen578a76e2016-01-14 14:54:39 -0500699 // Parse preferred lifetime
700 lastNonLifetimeStart = addNonLifetime(lastNonLifetimeStart,
701 ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_OFFSET,
702 ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_LEN);
Hugo Benichi6ccd51a2016-07-04 09:22:30 +0900703 lifetime = getUint32(mPacket,
704 position + ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_OFFSET);
705 builder.updatePrefixPreferredLifetime(lifetime);
Hugo Benichicfbf7412016-06-23 10:41:30 +0900706 mPrefixOptionOffsets.add(position);
Paul Jensen578a76e2016-01-14 14:54:39 -0500707 break;
Hugo Benichicfbf7412016-06-23 10:41:30 +0900708 // These three options have the same lifetime offset and size, and
Hugo Benichi6ccd51a2016-07-04 09:22:30 +0900709 // are processed with the same specialized addNonLifetimeU32:
Paul Jensen578a76e2016-01-14 14:54:39 -0500710 case ICMP6_RDNSS_OPTION_TYPE:
Hugo Benichicfbf7412016-06-23 10:41:30 +0900711 mRdnssOptionOffsets.add(position);
712 lastNonLifetimeStart = addNonLifetimeU32(lastNonLifetimeStart);
Hugo Benichi6ccd51a2016-07-04 09:22:30 +0900713 lifetime = getUint32(mPacket, position + ICMP6_4_BYTE_LIFETIME_OFFSET);
714 builder.updateRdnssLifetime(lifetime);
Hugo Benichicfbf7412016-06-23 10:41:30 +0900715 break;
Lorenzo Colitti059e2bb2016-04-08 20:51:39 +0900716 case ICMP6_ROUTE_INFO_OPTION_TYPE:
Hugo Benichicfbf7412016-06-23 10:41:30 +0900717 lastNonLifetimeStart = addNonLifetimeU32(lastNonLifetimeStart);
Hugo Benichi6ccd51a2016-07-04 09:22:30 +0900718 lifetime = getUint32(mPacket, position + ICMP6_4_BYTE_LIFETIME_OFFSET);
719 builder.updateRouteInfoLifetime(lifetime);
Hugo Benichicfbf7412016-06-23 10:41:30 +0900720 break;
Paul Jensen578a76e2016-01-14 14:54:39 -0500721 case ICMP6_DNSSL_OPTION_TYPE:
Hugo Benichicfbf7412016-06-23 10:41:30 +0900722 lastNonLifetimeStart = addNonLifetimeU32(lastNonLifetimeStart);
Hugo Benichi6ccd51a2016-07-04 09:22:30 +0900723 lifetime = getUint32(mPacket, position + ICMP6_4_BYTE_LIFETIME_OFFSET);
724 builder.updateDnsslLifetime(lifetime);
Paul Jensen578a76e2016-01-14 14:54:39 -0500725 break;
726 default:
727 // RFC4861 section 4.2 dictates we ignore unknown options for fowards
728 // compatibility.
729 break;
730 }
Lorenzo Colitti8995d852016-06-23 15:24:46 +0900731 if (optionLength <= 0) {
Hugo Benichi0668a612016-10-06 15:19:36 +0900732 throw new InvalidRaException(String.format(
Lorenzo Colitti8995d852016-06-23 15:24:46 +0900733 "Invalid option length opt=%d len=%d", optionType, optionLength));
734 }
Hugo Benichicfbf7412016-06-23 10:41:30 +0900735 mPacket.position(position + optionLength);
Paul Jensen578a76e2016-01-14 14:54:39 -0500736 }
737 // Mark non-lifetime bytes since last lifetime.
738 addNonLifetime(lastNonLifetimeStart, 0, 0);
739 mMinLifetime = minLifetime(packet, length);
Hugo Benichi6ccd51a2016-07-04 09:22:30 +0900740 mMetricsLog.log(builder.build());
Paul Jensen578a76e2016-01-14 14:54:39 -0500741 }
742
743 // Ignoring lifetimes (which may change) does {@code packet} match this RA?
744 boolean matches(byte[] packet, int length) {
Paul Jensen1c71cb32016-03-25 11:39:58 -0400745 if (length != mPacket.capacity()) return false;
746 byte[] referencePacket = mPacket.array();
Paul Jensen578a76e2016-01-14 14:54:39 -0500747 for (Pair<Integer, Integer> nonLifetime : mNonLifetimes) {
Paul Jensen1c71cb32016-03-25 11:39:58 -0400748 for (int i = nonLifetime.first; i < (nonLifetime.first + nonLifetime.second); i++) {
749 if (packet[i] != referencePacket[i]) return false;
750 }
Paul Jensen578a76e2016-01-14 14:54:39 -0500751 }
752 return true;
753 }
754
755 // What is the minimum of all lifetimes within {@code packet} in seconds?
756 // Precondition: matches(packet, length) already returned true.
757 long minLifetime(byte[] packet, int length) {
758 long minLifetime = Long.MAX_VALUE;
759 // Wrap packet in ByteBuffer so we can read big-endian values easily
760 ByteBuffer byteBuffer = ByteBuffer.wrap(packet);
761 for (int i = 0; (i + 1) < mNonLifetimes.size(); i++) {
762 int offset = mNonLifetimes.get(i).first + mNonLifetimes.get(i).second;
Lorenzo Colittie6dfc172016-03-03 17:53:33 +0900763
Joel Scherpelz967dec72017-05-24 15:08:39 +0900764 // The flow label is in mNonLifetimes, but it's not a lifetime.
765 if (offset == IPV6_FLOW_LABEL_OFFSET) {
766 continue;
767 }
768
Lorenzo Colittie6dfc172016-03-03 17:53:33 +0900769 // The checksum is in mNonLifetimes, but it's not a lifetime.
770 if (offset == ICMP6_RA_CHECKSUM_OFFSET) {
Joel Scherpelz967dec72017-05-24 15:08:39 +0900771 continue;
Lorenzo Colittie6dfc172016-03-03 17:53:33 +0900772 }
773
Hugo Benichicfbf7412016-06-23 10:41:30 +0900774 final int lifetimeLength = mNonLifetimes.get(i+1).first - offset;
775 final long optionLifetime;
Paul Jensen578a76e2016-01-14 14:54:39 -0500776 switch (lifetimeLength) {
Hugo Benichicfbf7412016-06-23 10:41:30 +0900777 case 2:
Hugo Benichi4104ff92016-10-13 09:26:01 +0900778 optionLifetime = getUint16(byteBuffer, offset);
Hugo Benichicfbf7412016-06-23 10:41:30 +0900779 break;
780 case 4:
Hugo Benichi4104ff92016-10-13 09:26:01 +0900781 optionLifetime = getUint32(byteBuffer, offset);
Hugo Benichicfbf7412016-06-23 10:41:30 +0900782 break;
783 default:
784 throw new IllegalStateException("bogus lifetime size " + lifetimeLength);
Paul Jensen578a76e2016-01-14 14:54:39 -0500785 }
Hugo Benichicfbf7412016-06-23 10:41:30 +0900786 minLifetime = Math.min(minLifetime, optionLifetime);
Paul Jensen578a76e2016-01-14 14:54:39 -0500787 }
788 return minLifetime;
789 }
790
791 // How many seconds does this RA's have to live, taking into account the fact
792 // that we might have seen it a while ago.
793 long currentLifetime() {
Hugo Benichi4456f332016-12-19 14:50:52 +0900794 return mMinLifetime - (currentTimeSeconds() - mLastSeen);
Paul Jensen578a76e2016-01-14 14:54:39 -0500795 }
796
797 boolean isExpired() {
Paul Jensendfd5a942016-03-17 13:22:29 -0400798 // TODO: We may want to handle 0 lifetime RAs differently, if they are common. We'll
Aaron Huanga63c40e2019-01-15 16:53:51 +0800799 // have to calculate the filter lifetime specially as a fraction of 0 is still 0.
Paul Jensendfd5a942016-03-17 13:22:29 -0400800 return currentLifetime() <= 0;
Paul Jensen578a76e2016-01-14 14:54:39 -0500801 }
802
803 // Append a filter for this RA to {@code gen}. Jump to DROP_LABEL if it should be dropped.
804 // Jump to the next filter if packet doesn't match this RA.
Paul Jensendfd5a942016-03-17 13:22:29 -0400805 @GuardedBy("ApfFilter.this")
806 long generateFilterLocked(ApfGenerator gen) throws IllegalInstructionException {
807 String nextFilterLabel = "Ra" + getUniqueNumberLocked();
Paul Jensen578a76e2016-01-14 14:54:39 -0500808 // Skip if packet is not the right size
809 gen.addLoadFromMemory(Register.R0, gen.PACKET_SIZE_MEMORY_SLOT);
Paul Jensen1c71cb32016-03-25 11:39:58 -0400810 gen.addJumpIfR0NotEquals(mPacket.capacity(), nextFilterLabel);
Paul Jensen578a76e2016-01-14 14:54:39 -0500811 int filterLifetime = (int)(currentLifetime() / FRACTION_OF_LIFETIME_TO_FILTER);
812 // Skip filter if expired
813 gen.addLoadFromMemory(Register.R0, gen.FILTER_AGE_MEMORY_SLOT);
814 gen.addJumpIfR0GreaterThan(filterLifetime, nextFilterLabel);
815 for (int i = 0; i < mNonLifetimes.size(); i++) {
816 // Generate code to match the packet bytes
817 Pair<Integer, Integer> nonLifetime = mNonLifetimes.get(i);
Paul Jensen7c34b152016-03-22 14:23:46 -0400818 // Don't generate JNEBS instruction for 0 bytes as it always fails the
819 // ASSERT_FORWARD_IN_PROGRAM(pc + cmp_imm - 1) check where cmp_imm is
820 // the number of bytes to compare. nonLifetime is zero between the
821 // valid and preferred lifetimes in the prefix option.
822 if (nonLifetime.second != 0) {
823 gen.addLoadImmediate(Register.R0, nonLifetime.first);
824 gen.addJumpIfBytesNotEqual(Register.R0,
825 Arrays.copyOfRange(mPacket.array(), nonLifetime.first,
826 nonLifetime.first + nonLifetime.second),
827 nextFilterLabel);
828 }
Paul Jensen578a76e2016-01-14 14:54:39 -0500829 // Generate code to test the lifetimes haven't gone down too far
830 if ((i + 1) < mNonLifetimes.size()) {
831 Pair<Integer, Integer> nextNonLifetime = mNonLifetimes.get(i + 1);
832 int offset = nonLifetime.first + nonLifetime.second;
Joel Scherpelz967dec72017-05-24 15:08:39 +0900833
834 // Skip the Flow label.
835 if (offset == IPV6_FLOW_LABEL_OFFSET) {
836 continue;
837 }
Lorenzo Colittie6dfc172016-03-03 17:53:33 +0900838 // Skip the checksum.
839 if (offset == ICMP6_RA_CHECKSUM_OFFSET) {
840 continue;
841 }
Paul Jensen578a76e2016-01-14 14:54:39 -0500842 int length = nextNonLifetime.first - offset;
843 switch (length) {
844 case 4: gen.addLoad32(Register.R0, offset); break;
845 case 2: gen.addLoad16(Register.R0, offset); break;
846 default: throw new IllegalStateException("bogus lifetime size " + length);
847 }
848 gen.addJumpIfR0LessThan(filterLifetime, nextFilterLabel);
849 }
850 }
Aaron Huang04ed6a32018-11-15 20:30:46 +0800851 maybeSetupCounter(gen, Counter.DROPPED_RA);
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +0900852 gen.addJump(mCountAndDropLabel);
Paul Jensen578a76e2016-01-14 14:54:39 -0500853 gen.defineLabel(nextFilterLabel);
854 return filterLifetime;
855 }
856 }
857
Aaron Huanga63c40e2019-01-15 16:53:51 +0800858 // A class to hold keepalive ack information.
859 private abstract static class TcpKeepaliveAck {
860 // Note that the offset starts from IP header.
861 // These must be added ether header length when generating program.
862 static final int IP_HEADER_OFFSET = 0;
863
864 protected static class TcpKeepaliveAckData {
865 public final byte[] srcAddress;
866 public final int srcPort;
867 public final byte[] dstAddress;
868 public final int dstPort;
869 public final int seq;
870 public final int ack;
871 // Create the characteristics of the ack packet from the sent keepalive packet.
872 TcpKeepaliveAckData(final TcpKeepalivePacketDataParcelable sentKeepalivePacket) {
873 srcAddress = sentKeepalivePacket.dstAddress;
874 srcPort = sentKeepalivePacket.dstPort;
875 dstAddress = sentKeepalivePacket.srcAddress;
876 dstPort = sentKeepalivePacket.srcPort;
877 seq = sentKeepalivePacket.ack;
878 ack = sentKeepalivePacket.seq + 1;
879 }
880 }
881
882 protected final TcpKeepaliveAckData mPacket;
883 protected final byte[] mSrcDstAddr;
884
885 TcpKeepaliveAck(final TcpKeepaliveAckData packet, final byte[] srcDstAddr) {
886 mPacket = packet;
887 mSrcDstAddr = srcDstAddr;
888 }
889
890 static byte[] concatArrays(final byte[]... arr) {
891 int size = 0;
892 for (byte[] a : arr) {
893 size += a.length;
894 }
895 final byte[] result = new byte[size];
896 int offset = 0;
897 for (byte[] a : arr) {
898 System.arraycopy(a, 0, result, offset, a.length);
899 offset += a.length;
900 }
901 return result;
902 }
903
904 public String toString() {
905 return String.format("%s(%d) -> %s(%d), seq=%d, ack=%d",
906 mPacket.srcAddress,
907 mPacket.srcPort,
908 mPacket.dstAddress,
909 mPacket.dstPort,
910 mPacket.seq,
911 mPacket.ack);
912 }
913
914 // Append a filter for this keepalive ack to {@code gen}.
915 // Jump to drop if it matches the keepalive ack.
916 // Jump to the next filter if packet doesn't match the keepalive ack.
917 abstract void generateFilterLocked(ApfGenerator gen) throws IllegalInstructionException;
918 }
919
920 private class TcpKeepaliveAckV4 extends TcpKeepaliveAck {
921 private static final int IPV4_SRC_ADDR_OFFSET = IP_HEADER_OFFSET + 12;
922 private static final int IPV4_TCP_SRC_PORT_OFFSET = 0;
923 private static final int IPV4_TCP_DST_PORT_OFFSET = 2;
924 private static final int IPV4_TCP_SEQ_OFFSET = 4;
925 private static final int IPV4_TCP_ACK_OFFSET = 8;
926
927 TcpKeepaliveAckV4(final TcpKeepalivePacketDataParcelable sentKeepalivePacket) {
928 this(new TcpKeepaliveAckData(sentKeepalivePacket));
929 }
930 TcpKeepaliveAckV4(final TcpKeepaliveAckData packet) {
931 super(packet, concatArrays(packet.srcAddress, packet.dstAddress) /* srcDstAddr */);
932 }
933
934 @Override
935 void generateFilterLocked(ApfGenerator gen) throws IllegalInstructionException {
936 final String nextFilterLabel = "keepalive_ack" + getUniqueNumberLocked();
937 gen.addLoad8(Register.R0, IPV4_PROTOCOL_OFFSET);
938 gen.addJumpIfR0NotEquals(IPPROTO_TCP, nextFilterLabel);
939 gen.addLoadImmediate(Register.R0, ETH_HEADER_LEN + IPV4_SRC_ADDR_OFFSET);
940 gen.addJumpIfBytesNotEqual(Register.R0, mSrcDstAddr, nextFilterLabel);
941
942 // Pass the packet if it's not zero-sized :
943 // Load the IP header size into R1
944 gen.addLoadFromMemory(Register.R1, gen.IPV4_HEADER_SIZE_MEMORY_SLOT);
945 // Load the TCP header size into R0 (it's indexed by R1)
946 gen.addLoad8Indexed(Register.R0, ETH_HEADER_LEN + TCP_HEADER_SIZE_OFFSET);
947 // Size offset is in the top nibble, but it must be multiplied by 4, and the two
948 // top bits of the low nibble are guaranteed to be zeroes. Right-shift R0 by 2.
949 gen.addRightShift(2);
950 // R0 += R1 -> R0 contains TCP + IP headers lenght
951 gen.addAddR1();
952 // Add the Ethernet header length to R0.
953 gen.addLoadImmediate(Register.R1, ETH_HEADER_LEN);
954 gen.addAddR1();
955 // Compare total length of headers to the size of the packet.
956 gen.addLoadFromMemory(Register.R1, gen.PACKET_SIZE_MEMORY_SLOT);
957 gen.addNeg(Register.R0);
958 gen.addAddR1();
959 gen.addJumpIfR0NotEquals(0, nextFilterLabel);
960
961 // Add IPv4 header length
962 gen.addLoadFromMemory(Register.R1, gen.IPV4_HEADER_SIZE_MEMORY_SLOT);
963 gen.addLoad16Indexed(Register.R0, ETH_HEADER_LEN + IPV4_TCP_SRC_PORT_OFFSET);
964 gen.addJumpIfR0NotEquals(mPacket.srcPort, nextFilterLabel);
965 gen.addLoad16Indexed(Register.R0, ETH_HEADER_LEN + IPV4_TCP_DST_PORT_OFFSET);
966 gen.addJumpIfR0NotEquals(mPacket.dstPort, nextFilterLabel);
967 gen.addLoad32Indexed(Register.R0, ETH_HEADER_LEN + IPV4_TCP_SEQ_OFFSET);
968 gen.addJumpIfR0NotEquals(mPacket.seq, nextFilterLabel);
969 gen.addLoad32Indexed(Register.R0, ETH_HEADER_LEN + IPV4_TCP_ACK_OFFSET);
970 gen.addJumpIfR0NotEquals(mPacket.ack, nextFilterLabel);
971
972 maybeSetupCounter(gen, Counter.DROPPED_IPV4_KEEPALIVE_ACK);
973 gen.addJump(mCountAndDropLabel);
974 gen.defineLabel(nextFilterLabel);
975 }
976 }
977
978 private class TcpKeepaliveAckV6 extends TcpKeepaliveAck {
979 TcpKeepaliveAckV6(final TcpKeepalivePacketDataParcelable sentKeepalivePacket) {
980 this(new TcpKeepaliveAckData(sentKeepalivePacket));
981 }
982 TcpKeepaliveAckV6(final TcpKeepaliveAckData packet) {
983 super(packet, concatArrays(packet.srcAddress, packet.dstAddress) /* srcDstAddr */);
984 }
985
986 @Override
987 void generateFilterLocked(ApfGenerator gen) throws IllegalInstructionException {
988 throw new UnsupportedOperationException("IPv6 Keepalive is not supported yet");
989 }
990 }
991
Paul Jensen578a76e2016-01-14 14:54:39 -0500992 // Maximum number of RAs to filter for.
993 private static final int MAX_RAS = 10;
Paul Jensendfd5a942016-03-17 13:22:29 -0400994
995 @GuardedBy("this")
Aaron Huanga63c40e2019-01-15 16:53:51 +0800996 private ArrayList<Ra> mRas = new ArrayList<>();
997 @GuardedBy("this")
998 private SparseArray<TcpKeepaliveAck> mKeepaliveAcks = new SparseArray<>();
Paul Jensen578a76e2016-01-14 14:54:39 -0500999
1000 // There is always some marginal benefit to updating the installed APF program when an RA is
1001 // seen because we can extend the program's lifetime slightly, but there is some cost to
1002 // updating the program, so don't bother unless the program is going to expire soon. This
1003 // constant defines "soon" in seconds.
1004 private static final long MAX_PROGRAM_LIFETIME_WORTH_REFRESHING = 30;
1005 // We don't want to filter an RA for it's whole lifetime as it'll be expired by the time we ever
1006 // see a refresh. Using half the lifetime might be a good idea except for the fact that
1007 // packets may be dropped, so let's use 6.
1008 private static final int FRACTION_OF_LIFETIME_TO_FILTER = 6;
1009
1010 // When did we last install a filter program? In seconds since Unix Epoch.
Paul Jensendfd5a942016-03-17 13:22:29 -04001011 @GuardedBy("this")
Paul Jensen578a76e2016-01-14 14:54:39 -05001012 private long mLastTimeInstalledProgram;
1013 // How long should the last installed filter program live for? In seconds.
Paul Jensendfd5a942016-03-17 13:22:29 -04001014 @GuardedBy("this")
Paul Jensen578a76e2016-01-14 14:54:39 -05001015 private long mLastInstalledProgramMinLifetime;
Hugo Benichi22d9b2d2017-02-22 13:02:27 +09001016 @GuardedBy("this")
Remi NGUYEN VAN7b84fb32019-01-19 21:13:24 +09001017 private ApfProgramEvent.Builder mLastInstallEvent;
Paul Jensen578a76e2016-01-14 14:54:39 -05001018
Paul Jensendfd5a942016-03-17 13:22:29 -04001019 // For debugging only. The last program installed.
1020 @GuardedBy("this")
Lorenzo Colitti39c0d422016-03-23 00:23:29 +09001021 private byte[] mLastInstalledProgram;
Lorenzo Colitti5ff640d2016-03-03 17:53:46 +09001022
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +09001023 /**
1024 * For debugging only. Contains the latest APF buffer snapshot captured from the firmware.
1025 *
1026 * A typical size for this buffer is 4KB. It is present only if the WiFi HAL supports
1027 * IWifiStaIface#readApfPacketFilterData(), and the APF interpreter advertised support for
1028 * the opcodes to access the data buffer (LDDW and STDW).
1029 */
1030 @GuardedBy("this") @Nullable
1031 private byte[] mDataSnapshot;
1032
Hugo Benichi22d9b2d2017-02-22 13:02:27 +09001033 // How many times the program was updated since we started.
Lorenzo Colitti059e2bb2016-04-08 20:51:39 +09001034 @GuardedBy("this")
Hugo Benichi22d9b2d2017-02-22 13:02:27 +09001035 private int mNumProgramUpdates = 0;
1036 // How many times the program was updated since we started for allowing multicast traffic.
1037 @GuardedBy("this")
1038 private int mNumProgramUpdatesAllowingMulticast = 0;
Lorenzo Colitti059e2bb2016-04-08 20:51:39 +09001039
Paul Jensendfd5a942016-03-17 13:22:29 -04001040 /**
Paul Jensena8458c02016-03-25 11:25:57 -04001041 * Generate filter code to process ARP packets. Execution of this code ends in either the
1042 * DROP_LABEL or PASS_LABEL and does not fall off the end.
1043 * Preconditions:
1044 * - Packet being filtered is ARP
1045 */
1046 @GuardedBy("this")
1047 private void generateArpFilterLocked(ApfGenerator gen) throws IllegalInstructionException {
1048 // Here's a basic summary of what the ARP filter program does:
1049 //
Hugo Benichi38db9762016-07-12 15:08:50 +09001050 // if not ARP IPv4
1051 // pass
1052 // if not ARP IPv4 reply or request
1053 // pass
Aaron Huang04ed6a32018-11-15 20:30:46 +08001054 // if ARP reply source ip is 0.0.0.0
1055 // drop
Hugo Benichi38db9762016-07-12 15:08:50 +09001056 // if unicast ARP reply
1057 // pass
1058 // if interface has no IPv4 address
1059 // if target ip is 0.0.0.0
1060 // drop
1061 // else
1062 // if target ip is not the interface ip
1063 // drop
Paul Jensena8458c02016-03-25 11:25:57 -04001064 // pass
1065
Hugo Benichi38db9762016-07-12 15:08:50 +09001066 final String checkTargetIPv4 = "checkTargetIPv4";
1067
1068 // Pass if not ARP IPv4.
1069 gen.addLoadImmediate(Register.R0, ARP_HEADER_OFFSET);
Aaron Huang04ed6a32018-11-15 20:30:46 +08001070 maybeSetupCounter(gen, Counter.PASSED_ARP_NON_IPV4);
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +09001071 gen.addJumpIfBytesNotEqual(Register.R0, ARP_IPV4_HEADER, mCountAndPassLabel);
Hugo Benichi38db9762016-07-12 15:08:50 +09001072
1073 // Pass if unknown ARP opcode.
1074 gen.addLoad16(Register.R0, ARP_OPCODE_OFFSET);
1075 gen.addJumpIfR0Equals(ARP_OPCODE_REQUEST, checkTargetIPv4); // Skip to unicast check
Aaron Huang04ed6a32018-11-15 20:30:46 +08001076 maybeSetupCounter(gen, Counter.PASSED_ARP_UNKNOWN);
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +09001077 gen.addJumpIfR0NotEquals(ARP_OPCODE_REPLY, mCountAndPassLabel);
Hugo Benichi38db9762016-07-12 15:08:50 +09001078
Aaron Huang04ed6a32018-11-15 20:30:46 +08001079 // Drop if ARP reply source IP is 0.0.0.0
1080 gen.addLoad32(Register.R0, ARP_SOURCE_IP_ADDRESS_OFFSET);
1081 maybeSetupCounter(gen, Counter.DROPPED_ARP_REPLY_SPA_NO_HOST);
1082 gen.addJumpIfR0Equals(IPV4_ANY_HOST_ADDRESS, mCountAndDropLabel);
1083
Hugo Benichi38db9762016-07-12 15:08:50 +09001084 // Pass if unicast reply.
1085 gen.addLoadImmediate(Register.R0, ETH_DEST_ADDR_OFFSET);
Aaron Huang04ed6a32018-11-15 20:30:46 +08001086 maybeSetupCounter(gen, Counter.PASSED_ARP_UNICAST_REPLY);
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +09001087 gen.addJumpIfBytesNotEqual(Register.R0, ETH_BROADCAST_MAC_ADDRESS, mCountAndPassLabel);
Hugo Benichi38db9762016-07-12 15:08:50 +09001088
1089 // Either a unicast request, a unicast reply, or a broadcast reply.
1090 gen.defineLabel(checkTargetIPv4);
1091 if (mIPv4Address == null) {
1092 // When there is no IPv4 address, drop GARP replies (b/29404209).
1093 gen.addLoad32(Register.R0, ARP_TARGET_IP_ADDRESS_OFFSET);
Aaron Huang04ed6a32018-11-15 20:30:46 +08001094 maybeSetupCounter(gen, Counter.DROPPED_GARP_REPLY);
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +09001095 gen.addJumpIfR0Equals(IPV4_ANY_HOST_ADDRESS, mCountAndDropLabel);
Hugo Benichi38db9762016-07-12 15:08:50 +09001096 } else {
1097 // When there is an IPv4 address, drop unicast/broadcast requests
1098 // and broadcast replies with a different target IPv4 address.
Paul Jensendd7bee82016-05-06 10:27:56 -04001099 gen.addLoadImmediate(Register.R0, ARP_TARGET_IP_ADDRESS_OFFSET);
Aaron Huang04ed6a32018-11-15 20:30:46 +08001100 maybeSetupCounter(gen, Counter.DROPPED_ARP_OTHER_HOST);
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +09001101 gen.addJumpIfBytesNotEqual(Register.R0, mIPv4Address, mCountAndDropLabel);
Paul Jensendd7bee82016-05-06 10:27:56 -04001102 }
Paul Jensena8458c02016-03-25 11:25:57 -04001103
Aaron Huang04ed6a32018-11-15 20:30:46 +08001104 maybeSetupCounter(gen, Counter.PASSED_ARP);
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +09001105 gen.addJump(mCountAndPassLabel);
Paul Jensena8458c02016-03-25 11:25:57 -04001106 }
1107
1108 /**
Paul Jensendfd5a942016-03-17 13:22:29 -04001109 * Generate filter code to process IPv4 packets. Execution of this code ends in either the
1110 * DROP_LABEL or PASS_LABEL and does not fall off the end.
1111 * Preconditions:
1112 * - Packet being filtered is IPv4
Paul Jensendfd5a942016-03-17 13:22:29 -04001113 */
1114 @GuardedBy("this")
1115 private void generateIPv4FilterLocked(ApfGenerator gen) throws IllegalInstructionException {
1116 // Here's a basic summary of what the IPv4 filter program does:
1117 //
Paul Jensenf8a01e82016-05-26 09:16:11 -04001118 // if filtering multicast (i.e. multicast lock not held):
Hugo Benichi0dc1d312016-09-02 12:40:31 +09001119 // if it's DHCP destined to our MAC:
Paul Jensenf8a01e82016-05-26 09:16:11 -04001120 // pass
Hugo Benichi0dc1d312016-09-02 12:40:31 +09001121 // if it's L2 broadcast:
1122 // drop
1123 // if it's IPv4 multicast:
1124 // drop
1125 // if it's IPv4 broadcast:
Paul Jensenf8a01e82016-05-26 09:16:11 -04001126 // drop
Aaron Huanga63c40e2019-01-15 16:53:51 +08001127 // if keepalive ack
1128 // drop
Paul Jensendfd5a942016-03-17 13:22:29 -04001129 // pass
1130
1131 if (mMulticastFilter) {
Hugo Benichi0dc1d312016-09-02 12:40:31 +09001132 final String skipDhcpv4Filter = "skip_dhcp_v4_filter";
1133
1134 // Pass DHCP addressed to us.
1135 // Check it's UDP.
1136 gen.addLoad8(Register.R0, IPV4_PROTOCOL_OFFSET);
1137 gen.addJumpIfR0NotEquals(IPPROTO_UDP, skipDhcpv4Filter);
1138 // Check it's not a fragment. This matches the BPF filter installed by the DHCP client.
1139 gen.addLoad16(Register.R0, IPV4_FRAGMENT_OFFSET_OFFSET);
1140 gen.addJumpIfR0AnyBitsSet(IPV4_FRAGMENT_OFFSET_MASK, skipDhcpv4Filter);
1141 // Check it's addressed to DHCP client port.
1142 gen.addLoadFromMemory(Register.R1, gen.IPV4_HEADER_SIZE_MEMORY_SLOT);
1143 gen.addLoad16Indexed(Register.R0, UDP_DESTINATION_PORT_OFFSET);
1144 gen.addJumpIfR0NotEquals(DHCP_CLIENT_PORT, skipDhcpv4Filter);
1145 // Check it's DHCP to our MAC address.
1146 gen.addLoadImmediate(Register.R0, DHCP_CLIENT_MAC_OFFSET);
1147 // NOTE: Relies on R1 containing IPv4 header offset.
1148 gen.addAddR1();
1149 gen.addJumpIfBytesNotEqual(Register.R0, mHardwareAddress, skipDhcpv4Filter);
Aaron Huang04ed6a32018-11-15 20:30:46 +08001150 maybeSetupCounter(gen, Counter.PASSED_DHCP);
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +09001151 gen.addJump(mCountAndPassLabel);
Hugo Benichi0dc1d312016-09-02 12:40:31 +09001152
1153 // Drop all multicasts/broadcasts.
1154 gen.defineLabel(skipDhcpv4Filter);
1155
1156 // If IPv4 destination address is in multicast range, drop.
Paul Jensendfd5a942016-03-17 13:22:29 -04001157 gen.addLoad8(Register.R0, IPV4_DEST_ADDR_OFFSET);
1158 gen.addAnd(0xf0);
Aaron Huang04ed6a32018-11-15 20:30:46 +08001159 maybeSetupCounter(gen, Counter.DROPPED_IPV4_MULTICAST);
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +09001160 gen.addJumpIfR0Equals(0xe0, mCountAndDropLabel);
Paul Jensendfd5a942016-03-17 13:22:29 -04001161
Hugo Benichi0dc1d312016-09-02 12:40:31 +09001162 // If IPv4 broadcast packet, drop regardless of L2 (b/30231088).
Aaron Huang04ed6a32018-11-15 20:30:46 +08001163 maybeSetupCounter(gen, Counter.DROPPED_IPV4_BROADCAST_ADDR);
Hugo Benichi0dc1d312016-09-02 12:40:31 +09001164 gen.addLoad32(Register.R0, IPV4_DEST_ADDR_OFFSET);
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +09001165 gen.addJumpIfR0Equals(IPV4_BROADCAST_ADDRESS, mCountAndDropLabel);
Hugo Benichi7d21eae2016-09-02 14:00:29 +09001166 if (mIPv4Address != null && mIPv4PrefixLength < 31) {
Aaron Huang04ed6a32018-11-15 20:30:46 +08001167 maybeSetupCounter(gen, Counter.DROPPED_IPV4_BROADCAST_NET);
Hugo Benichi7d21eae2016-09-02 14:00:29 +09001168 int broadcastAddr = ipv4BroadcastAddress(mIPv4Address, mIPv4PrefixLength);
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +09001169 gen.addJumpIfR0Equals(broadcastAddr, mCountAndDropLabel);
Hugo Benichi7d21eae2016-09-02 14:00:29 +09001170 }
Hugo Benichi0dc1d312016-09-02 12:40:31 +09001171
Aaron Huanga63c40e2019-01-15 16:53:51 +08001172 // If any keepalive filters,
1173 generateKeepaliveFilter(gen);
1174
Hugo Benichi0dc1d312016-09-02 12:40:31 +09001175 // If L2 broadcast packet, drop.
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +09001176 // TODO: can we invert this condition to fall through to the common pass case below?
Aaron Huang04ed6a32018-11-15 20:30:46 +08001177 maybeSetupCounter(gen, Counter.PASSED_IPV4_UNICAST);
Paul Jensenf8a01e82016-05-26 09:16:11 -04001178 gen.addLoadImmediate(Register.R0, ETH_DEST_ADDR_OFFSET);
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +09001179 gen.addJumpIfBytesNotEqual(Register.R0, ETH_BROADCAST_MAC_ADDRESS, mCountAndPassLabel);
Aaron Huang04ed6a32018-11-15 20:30:46 +08001180 maybeSetupCounter(gen, Counter.DROPPED_IPV4_L2_BROADCAST);
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +09001181 gen.addJump(mCountAndDropLabel);
Aaron Huanga63c40e2019-01-15 16:53:51 +08001182 } else {
1183 generateKeepaliveFilter(gen);
Paul Jensenf8a01e82016-05-26 09:16:11 -04001184 }
Paul Jensendfd5a942016-03-17 13:22:29 -04001185
1186 // Otherwise, pass
Aaron Huang04ed6a32018-11-15 20:30:46 +08001187 maybeSetupCounter(gen, Counter.PASSED_IPV4);
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +09001188 gen.addJump(mCountAndPassLabel);
Paul Jensendfd5a942016-03-17 13:22:29 -04001189 }
1190
Aaron Huanga63c40e2019-01-15 16:53:51 +08001191 private void generateKeepaliveFilter(ApfGenerator gen) throws IllegalInstructionException {
1192 // Drop IPv4 Keepalive acks
1193 for (int i = 0; i < mKeepaliveAcks.size(); ++i) {
1194 final TcpKeepaliveAck ack = mKeepaliveAcks.valueAt(i);
1195 if (ack instanceof TcpKeepaliveAckV4) ack.generateFilterLocked(gen);
1196 }
1197 }
Paul Jensendfd5a942016-03-17 13:22:29 -04001198
1199 /**
1200 * Generate filter code to process IPv6 packets. Execution of this code ends in either the
1201 * DROP_LABEL or PASS_LABEL, or falls off the end for ICMPv6 packets.
1202 * Preconditions:
1203 * - Packet being filtered is IPv6
Paul Jensendfd5a942016-03-17 13:22:29 -04001204 */
1205 @GuardedBy("this")
1206 private void generateIPv6FilterLocked(ApfGenerator gen) throws IllegalInstructionException {
1207 // Here's a basic summary of what the IPv6 filter program does:
1208 //
Bernie Innocenti5be71dc2018-03-28 20:11:49 +09001209 // if we're dropping multicast
1210 // if it's not IPCMv6 or it's ICMPv6 but we're in doze mode:
1211 // if it's multicast:
1212 // drop
1213 // pass
Hugo Benichi02428982016-12-03 02:41:05 +09001214 // if it's ICMPv6 RS to any:
1215 // drop
Paul Jensendfd5a942016-03-17 13:22:29 -04001216 // if it's ICMPv6 NA to ff02::1:
1217 // drop
Aaron Huanga63c40e2019-01-15 16:53:51 +08001218 // if keepalive ack
1219 // drop
Paul Jensendfd5a942016-03-17 13:22:29 -04001220
Paul Jensendfd5a942016-03-17 13:22:29 -04001221 gen.addLoad8(Register.R0, IPV6_NEXT_HEADER_OFFSET);
Lorenzo Colitti11e13e22016-05-20 00:04:43 +09001222
1223 // Drop multicast if the multicast filter is enabled.
1224 if (mMulticastFilter) {
Bernie Innocenti5be71dc2018-03-28 20:11:49 +09001225 final String skipIPv6MulticastFilterLabel = "skipIPv6MulticastFilter";
1226 final String dropAllIPv6MulticastsLabel = "dropAllIPv6Multicast";
Lorenzo Colitti11e13e22016-05-20 00:04:43 +09001227
Bernie Innocenti5be71dc2018-03-28 20:11:49 +09001228 // While in doze mode, drop ICMPv6 multicast pings, let the others pass.
1229 // While awake, let all ICMPv6 multicasts through.
1230 if (mInDozeMode) {
1231 // Not ICMPv6? -> Proceed to multicast filtering
1232 gen.addJumpIfR0NotEquals(IPPROTO_ICMPV6, dropAllIPv6MulticastsLabel);
1233
1234 // ICMPv6 but not ECHO? -> Skip the multicast filter.
1235 // (ICMPv6 ECHO requests will go through the multicast filter below).
1236 gen.addLoad8(Register.R0, ICMP6_TYPE_OFFSET);
1237 gen.addJumpIfR0NotEquals(ICMPV6_ECHO_REQUEST_TYPE, skipIPv6MulticastFilterLabel);
1238 } else {
1239 gen.addJumpIfR0Equals(IPPROTO_ICMPV6, skipIPv6MulticastFilterLabel);
1240 }
1241
1242 // Drop all other packets sent to ff00::/8 (multicast prefix).
1243 gen.defineLabel(dropAllIPv6MulticastsLabel);
Aaron Huang04ed6a32018-11-15 20:30:46 +08001244 maybeSetupCounter(gen, Counter.DROPPED_IPV6_NON_ICMP_MULTICAST);
Lorenzo Colitti11e13e22016-05-20 00:04:43 +09001245 gen.addLoad8(Register.R0, IPV6_DEST_ADDR_OFFSET);
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +09001246 gen.addJumpIfR0Equals(0xff, mCountAndDropLabel);
Bernie Innocenti5be71dc2018-03-28 20:11:49 +09001247 // Not multicast. Pass.
Aaron Huang04ed6a32018-11-15 20:30:46 +08001248 maybeSetupCounter(gen, Counter.PASSED_IPV6_UNICAST_NON_ICMP);
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +09001249 gen.addJump(mCountAndPassLabel);
Bernie Innocenti5be71dc2018-03-28 20:11:49 +09001250 gen.defineLabel(skipIPv6MulticastFilterLabel);
Lorenzo Colitti11e13e22016-05-20 00:04:43 +09001251 } else {
1252 // If not ICMPv6, pass.
Aaron Huang04ed6a32018-11-15 20:30:46 +08001253 maybeSetupCounter(gen, Counter.PASSED_IPV6_NON_ICMP);
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +09001254 gen.addJumpIfR0NotEquals(IPPROTO_ICMPV6, mCountAndPassLabel);
Lorenzo Colitti11e13e22016-05-20 00:04:43 +09001255 }
1256
Bernie Innocenti5be71dc2018-03-28 20:11:49 +09001257 // If we got this far, the packet is ICMPv6. Drop some specific types.
1258
Paul Jensendfd5a942016-03-17 13:22:29 -04001259 // Add unsolicited multicast neighbor announcements filter
1260 String skipUnsolicitedMulticastNALabel = "skipUnsolicitedMulticastNA";
Paul Jensendfd5a942016-03-17 13:22:29 -04001261 gen.addLoad8(Register.R0, ICMP6_TYPE_OFFSET);
Hugo Benichi02428982016-12-03 02:41:05 +09001262 // Drop all router solicitations (b/32833400)
Aaron Huang04ed6a32018-11-15 20:30:46 +08001263 maybeSetupCounter(gen, Counter.DROPPED_IPV6_ROUTER_SOLICITATION);
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +09001264 gen.addJumpIfR0Equals(ICMPV6_ROUTER_SOLICITATION, mCountAndDropLabel);
Hugo Benichi02428982016-12-03 02:41:05 +09001265 // If not neighbor announcements, skip filter.
Bernie Innocenti5be71dc2018-03-28 20:11:49 +09001266 gen.addJumpIfR0NotEquals(ICMPV6_NEIGHBOR_ADVERTISEMENT, skipUnsolicitedMulticastNALabel);
Hugo Benichi02428982016-12-03 02:41:05 +09001267 // If to ff02::1, drop.
Paul Jensendfd5a942016-03-17 13:22:29 -04001268 // TODO: Drop only if they don't contain the address of on-link neighbours.
1269 gen.addLoadImmediate(Register.R0, IPV6_DEST_ADDR_OFFSET);
1270 gen.addJumpIfBytesNotEqual(Register.R0, IPV6_ALL_NODES_ADDRESS,
1271 skipUnsolicitedMulticastNALabel);
Aaron Huang04ed6a32018-11-15 20:30:46 +08001272 maybeSetupCounter(gen, Counter.DROPPED_IPV6_MULTICAST_NA);
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +09001273 gen.addJump(mCountAndDropLabel);
Paul Jensendfd5a942016-03-17 13:22:29 -04001274 gen.defineLabel(skipUnsolicitedMulticastNALabel);
Aaron Huanga63c40e2019-01-15 16:53:51 +08001275
1276 // Drop IPv6 Keepalive acks
1277 for (int i = 0; i < mKeepaliveAcks.size(); ++i) {
1278 final TcpKeepaliveAck ack = mKeepaliveAcks.valueAt(i);
1279 if (ack instanceof TcpKeepaliveAckV6) ack.generateFilterLocked(gen);
1280 }
Paul Jensendfd5a942016-03-17 13:22:29 -04001281 }
1282
1283 /**
1284 * Begin generating an APF program to:
1285 * <ul>
Ahmed ElArabawy8537c582017-06-12 18:01:11 -07001286 * <li>Drop/Pass 802.3 frames (based on policy)
Ahmed ElArabawyfd424162017-08-02 13:31:05 -07001287 * <li>Drop packets with EtherType within the Black List
Paul Jensena8458c02016-03-25 11:25:57 -04001288 * <li>Drop ARP requests not for us, if mIPv4Address is set,
Paul Jensendfd5a942016-03-17 13:22:29 -04001289 * <li>Drop IPv4 broadcast packets, except DHCP destined to our MAC,
1290 * <li>Drop IPv4 multicast packets, if mMulticastFilter,
1291 * <li>Pass all other IPv4 packets,
Paul Jensendd7bee82016-05-06 10:27:56 -04001292 * <li>Drop all broadcast non-IP non-ARP packets.
Paul Jensendfd5a942016-03-17 13:22:29 -04001293 * <li>Pass all non-ICMPv6 IPv6 packets,
1294 * <li>Pass all non-IPv4 and non-IPv6 packets,
1295 * <li>Drop IPv6 ICMPv6 NAs to ff02::1.
Hugo Benichi02428982016-12-03 02:41:05 +09001296 * <li>Drop IPv6 ICMPv6 RSs.
Paul Jensendfd5a942016-03-17 13:22:29 -04001297 * <li>Let execution continue off the end of the program for IPv6 ICMPv6 packets. This allows
1298 * insertion of RA filters here, or if there aren't any, just passes the packets.
1299 * </ul>
1300 */
1301 @GuardedBy("this")
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +09001302 private ApfGenerator emitPrologueLocked() throws IllegalInstructionException {
Bernie Innocenti408dbda2018-03-22 23:07:47 +09001303 // This is guaranteed to succeed because of the check in maybeCreate.
1304 ApfGenerator gen = new ApfGenerator(mApfCapabilities.apfVersionSupported);
Paul Jensendfd5a942016-03-17 13:22:29 -04001305
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +09001306 if (mApfCapabilities.hasDataAccess()) {
1307 // Increment TOTAL_PACKETS
Aaron Huang04ed6a32018-11-15 20:30:46 +08001308 maybeSetupCounter(gen, Counter.TOTAL_PACKETS);
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +09001309 gen.addLoadData(Register.R0, 0); // load counter
1310 gen.addAdd(1);
1311 gen.addStoreData(Register.R0, 0); // write-back counter
1312 }
1313
Paul Jensendfd5a942016-03-17 13:22:29 -04001314 // Here's a basic summary of what the initial program does:
1315 //
Ahmed ElArabawy8537c582017-06-12 18:01:11 -07001316 // if it's a 802.3 Frame (ethtype < 0x0600):
1317 // drop or pass based on configurations
Ahmed ElArabawyfd424162017-08-02 13:31:05 -07001318 // if it has a ether-type that belongs to the black list
1319 // drop
Paul Jensena8458c02016-03-25 11:25:57 -04001320 // if it's ARP:
Paul Jensendd7bee82016-05-06 10:27:56 -04001321 // insert ARP filter to drop or pass these appropriately
Paul Jensendfd5a942016-03-17 13:22:29 -04001322 // if it's IPv4:
1323 // insert IPv4 filter to drop or pass these appropriately
1324 // if it's not IPv6:
Paul Jensendd7bee82016-05-06 10:27:56 -04001325 // if it's broadcast:
1326 // drop
Paul Jensendfd5a942016-03-17 13:22:29 -04001327 // pass
1328 // insert IPv6 filter to drop, pass, or fall off the end for ICMPv6 packets
1329
Ahmed ElArabawy8537c582017-06-12 18:01:11 -07001330 gen.addLoad16(Register.R0, ETH_ETHERTYPE_OFFSET);
1331
1332 if (mDrop802_3Frames) {
1333 // drop 802.3 frames (ethtype < 0x0600)
Aaron Huang04ed6a32018-11-15 20:30:46 +08001334 maybeSetupCounter(gen, Counter.DROPPED_802_3_FRAME);
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +09001335 gen.addJumpIfR0LessThan(ETH_TYPE_MIN, mCountAndDropLabel);
Ahmed ElArabawy8537c582017-06-12 18:01:11 -07001336 }
1337
Ahmed ElArabawyfd424162017-08-02 13:31:05 -07001338 // Handle ether-type black list
Aaron Huang04ed6a32018-11-15 20:30:46 +08001339 maybeSetupCounter(gen, Counter.DROPPED_ETHERTYPE_BLACKLISTED);
Ahmed ElArabawyfd424162017-08-02 13:31:05 -07001340 for (int p : mEthTypeBlackList) {
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +09001341 gen.addJumpIfR0Equals(p, mCountAndDropLabel);
Ahmed ElArabawyfd424162017-08-02 13:31:05 -07001342 }
1343
Paul Jensendd7bee82016-05-06 10:27:56 -04001344 // Add ARP filters:
1345 String skipArpFiltersLabel = "skipArpFilters";
Paul Jensendd7bee82016-05-06 10:27:56 -04001346 gen.addJumpIfR0NotEquals(ETH_P_ARP, skipArpFiltersLabel);
1347 generateArpFilterLocked(gen);
1348 gen.defineLabel(skipArpFiltersLabel);
Paul Jensena8458c02016-03-25 11:25:57 -04001349
Paul Jensendfd5a942016-03-17 13:22:29 -04001350 // Add IPv4 filters:
1351 String skipIPv4FiltersLabel = "skipIPv4Filters";
Paul Jensena8458c02016-03-25 11:25:57 -04001352 // NOTE: Relies on R0 containing ethertype. This is safe because if we got here, we did not
1353 // execute the ARP filter, since that filter does not fall through, but either drops or
1354 // passes.
Paul Jensendfd5a942016-03-17 13:22:29 -04001355 gen.addJumpIfR0NotEquals(ETH_P_IP, skipIPv4FiltersLabel);
Paul Jensendfd5a942016-03-17 13:22:29 -04001356 generateIPv4FilterLocked(gen);
1357 gen.defineLabel(skipIPv4FiltersLabel);
1358
Paul Jensendd7bee82016-05-06 10:27:56 -04001359 // Check for IPv6:
Paul Jensendfd5a942016-03-17 13:22:29 -04001360 // NOTE: Relies on R0 containing ethertype. This is safe because if we got here, we did not
Paul Jensena8458c02016-03-25 11:25:57 -04001361 // execute the ARP or IPv4 filters, since those filters do not fall through, but either
1362 // drop or pass.
Paul Jensendd7bee82016-05-06 10:27:56 -04001363 String ipv6FilterLabel = "IPv6Filters";
1364 gen.addJumpIfR0Equals(ETH_P_IPV6, ipv6FilterLabel);
1365
1366 // Drop non-IP non-ARP broadcasts, pass the rest
1367 gen.addLoadImmediate(Register.R0, ETH_DEST_ADDR_OFFSET);
Aaron Huang04ed6a32018-11-15 20:30:46 +08001368 maybeSetupCounter(gen, Counter.PASSED_NON_IP_UNICAST);
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +09001369 gen.addJumpIfBytesNotEqual(Register.R0, ETH_BROADCAST_MAC_ADDRESS, mCountAndPassLabel);
Aaron Huang04ed6a32018-11-15 20:30:46 +08001370 maybeSetupCounter(gen, Counter.DROPPED_ETH_BROADCAST);
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +09001371 gen.addJump(mCountAndDropLabel);
Paul Jensendd7bee82016-05-06 10:27:56 -04001372
1373 // Add IPv6 filters:
1374 gen.defineLabel(ipv6FilterLabel);
Paul Jensendfd5a942016-03-17 13:22:29 -04001375 generateIPv6FilterLocked(gen);
1376 return gen;
1377 }
1378
Hugo Benichi4fc3ee52016-06-02 11:20:27 +09001379 /**
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +09001380 * Append packet counting epilogue to the APF program.
1381 *
1382 * Currently, the epilogue consists of two trampolines which count passed and dropped packets
1383 * before jumping to the actual PASS and DROP labels.
1384 */
1385 @GuardedBy("this")
1386 private void emitEpilogue(ApfGenerator gen) throws IllegalInstructionException {
1387 // If APFv4 is unsupported, no epilogue is necessary: if execution reached this far, it
1388 // will just fall-through to the PASS label.
1389 if (!mApfCapabilities.hasDataAccess()) return;
1390
1391 // Execution will reach the bottom of the program if none of the filters match,
1392 // which will pass the packet to the application processor.
Aaron Huang04ed6a32018-11-15 20:30:46 +08001393 maybeSetupCounter(gen, Counter.PASSED_IPV6_ICMP);
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +09001394
1395 // Append the count & pass trampoline, which increments the counter at the data address
1396 // pointed to by R1, then jumps to the pass label. This saves a few bytes over inserting
1397 // the entire sequence inline for every counter.
1398 gen.defineLabel(mCountAndPassLabel);
1399 gen.addLoadData(Register.R0, 0); // R0 = *(R1 + 0)
1400 gen.addAdd(1); // R0++
1401 gen.addStoreData(Register.R0, 0); // *(R1 + 0) = R0
1402 gen.addJump(gen.PASS_LABEL);
1403
1404 // Same as above for the count & drop trampoline.
1405 gen.defineLabel(mCountAndDropLabel);
1406 gen.addLoadData(Register.R0, 0); // R0 = *(R1 + 0)
1407 gen.addAdd(1); // R0++
1408 gen.addStoreData(Register.R0, 0); // *(R1 + 0) = R0
1409 gen.addJump(gen.DROP_LABEL);
1410 }
1411
1412 /**
Hugo Benichi4fc3ee52016-06-02 11:20:27 +09001413 * Generate and install a new filter program.
1414 */
Paul Jensendfd5a942016-03-17 13:22:29 -04001415 @GuardedBy("this")
Paul Jensen9132f342016-04-13 15:00:26 -04001416 @VisibleForTesting
1417 void installNewProgramLocked() {
Paul Jensendfd5a942016-03-17 13:22:29 -04001418 purgeExpiredRasLocked();
Hugo Benichi4fc3ee52016-06-02 11:20:27 +09001419 ArrayList<Ra> rasToFilter = new ArrayList<>();
Paul Jensen578a76e2016-01-14 14:54:39 -05001420 final byte[] program;
1421 long programMinLifetime = Long.MAX_VALUE;
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +09001422 long maximumApfProgramSize = mApfCapabilities.maximumApfProgramSize;
1423 if (mApfCapabilities.hasDataAccess()) {
1424 // Reserve space for the counters.
1425 maximumApfProgramSize -= Counter.totalSize();
1426 }
1427
Paul Jensen578a76e2016-01-14 14:54:39 -05001428 try {
Paul Jensen578a76e2016-01-14 14:54:39 -05001429 // Step 1: Determine how many RA filters we can fit in the program.
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +09001430 ApfGenerator gen = emitPrologueLocked();
1431
1432 // The epilogue normally goes after the RA filters, but add it early to include its
1433 // length when estimating the total.
1434 emitEpilogue(gen);
1435
1436 // Can't fit the program even without any RA filters?
1437 if (gen.programLengthOverEstimate() > maximumApfProgramSize) {
1438 Log.e(TAG, "Program exceeds maximum size " + maximumApfProgramSize);
1439 return;
1440 }
1441
Paul Jensen578a76e2016-01-14 14:54:39 -05001442 for (Ra ra : mRas) {
Paul Jensendfd5a942016-03-17 13:22:29 -04001443 ra.generateFilterLocked(gen);
1444 // Stop if we get too big.
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +09001445 if (gen.programLengthOverEstimate() > maximumApfProgramSize) break;
Paul Jensendfd5a942016-03-17 13:22:29 -04001446 rasToFilter.add(ra);
Paul Jensen578a76e2016-01-14 14:54:39 -05001447 }
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +09001448
Paul Jensendfd5a942016-03-17 13:22:29 -04001449 // Step 2: Actually generate the program
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +09001450 gen = emitPrologueLocked();
Paul Jensendfd5a942016-03-17 13:22:29 -04001451 for (Ra ra : rasToFilter) {
1452 programMinLifetime = Math.min(programMinLifetime, ra.generateFilterLocked(gen));
Paul Jensen578a76e2016-01-14 14:54:39 -05001453 }
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +09001454 emitEpilogue(gen);
Paul Jensen578a76e2016-01-14 14:54:39 -05001455 program = gen.generate();
Hugo Benichi0668a612016-10-06 15:19:36 +09001456 } catch (IllegalInstructionException|IllegalStateException e) {
1457 Log.e(TAG, "Failed to generate APF program.", e);
Paul Jensen578a76e2016-01-14 14:54:39 -05001458 return;
1459 }
Hugo Benichi22d9b2d2017-02-22 13:02:27 +09001460 final long now = currentTimeSeconds();
1461 mLastTimeInstalledProgram = now;
Paul Jensen578a76e2016-01-14 14:54:39 -05001462 mLastInstalledProgramMinLifetime = programMinLifetime;
Lorenzo Colitti39c0d422016-03-23 00:23:29 +09001463 mLastInstalledProgram = program;
Lorenzo Colitti059e2bb2016-04-08 20:51:39 +09001464 mNumProgramUpdates++;
1465
Lorenzo Colitti5ff640d2016-03-03 17:53:46 +09001466 if (VDBG) {
1467 hexDump("Installing filter: ", program, program.length);
Lorenzo Colitti5ff640d2016-03-03 17:53:46 +09001468 }
Erik Kline1b293582017-10-11 19:43:10 +09001469 mIpClientCallback.installPacketFilter(program);
Hugo Benichi22d9b2d2017-02-22 13:02:27 +09001470 logApfProgramEventLocked(now);
Remi NGUYEN VAN7b84fb32019-01-19 21:13:24 +09001471 mLastInstallEvent = new ApfProgramEvent.Builder()
1472 .setLifetime(programMinLifetime)
1473 .setFilteredRas(rasToFilter.size())
1474 .setCurrentRas(mRas.size())
1475 .setProgramLength(program.length)
1476 .setFlags(mIPv4Address != null, mMulticastFilter);
Hugo Benichi22d9b2d2017-02-22 13:02:27 +09001477 }
1478
Andreas Gampebbab23f2018-02-07 15:34:27 -08001479 @GuardedBy("this")
Hugo Benichi22d9b2d2017-02-22 13:02:27 +09001480 private void logApfProgramEventLocked(long now) {
1481 if (mLastInstallEvent == null) {
1482 return;
1483 }
Remi NGUYEN VAN7b84fb32019-01-19 21:13:24 +09001484 ApfProgramEvent.Builder ev = mLastInstallEvent;
Hugo Benichi22d9b2d2017-02-22 13:02:27 +09001485 mLastInstallEvent = null;
Remi NGUYEN VAN7b84fb32019-01-19 21:13:24 +09001486 final long actualLifetime = now - mLastTimeInstalledProgram;
1487 ev.setActualLifetime(actualLifetime);
1488 if (actualLifetime < APF_PROGRAM_EVENT_LIFETIME_THRESHOLD) {
Hugo Benichi22d9b2d2017-02-22 13:02:27 +09001489 return;
1490 }
Remi NGUYEN VAN7b84fb32019-01-19 21:13:24 +09001491 mMetricsLog.log(ev.build());
Paul Jensen578a76e2016-01-14 14:54:39 -05001492 }
1493
Hugo Benichi647c86d2016-06-07 15:35:16 +09001494 /**
1495 * Returns {@code true} if a new program should be installed because the current one dies soon.
1496 */
1497 private boolean shouldInstallnewProgram() {
Paul Jensen578a76e2016-01-14 14:54:39 -05001498 long expiry = mLastTimeInstalledProgram + mLastInstalledProgramMinLifetime;
Hugo Benichi4456f332016-12-19 14:50:52 +09001499 return expiry < currentTimeSeconds() + MAX_PROGRAM_LIFETIME_WORTH_REFRESHING;
Paul Jensen578a76e2016-01-14 14:54:39 -05001500 }
1501
1502 private void hexDump(String msg, byte[] packet, int length) {
Lorenzo Colitti39c0d422016-03-23 00:23:29 +09001503 log(msg + HexDump.toHexString(packet, 0, length, false /* lowercase */));
Paul Jensen578a76e2016-01-14 14:54:39 -05001504 }
1505
Paul Jensendfd5a942016-03-17 13:22:29 -04001506 @GuardedBy("this")
1507 private void purgeExpiredRasLocked() {
1508 for (int i = 0; i < mRas.size();) {
1509 if (mRas.get(i).isExpired()) {
1510 log("Expiring " + mRas.get(i));
1511 mRas.remove(i);
1512 } else {
1513 i++;
1514 }
1515 }
1516 }
1517
Hugo Benichi647c86d2016-06-07 15:35:16 +09001518 /**
1519 * Process an RA packet, updating the list of known RAs and installing a new APF program
1520 * if the current APF program should be updated.
1521 * @return a ProcessRaResult enum describing what action was performed.
1522 */
Hugo Benichi0668a612016-10-06 15:19:36 +09001523 @VisibleForTesting
1524 synchronized ProcessRaResult processRa(byte[] packet, int length) {
Lorenzo Colitti5ff640d2016-03-03 17:53:46 +09001525 if (VDBG) hexDump("Read packet = ", packet, length);
Paul Jensen578a76e2016-01-14 14:54:39 -05001526
1527 // Have we seen this RA before?
1528 for (int i = 0; i < mRas.size(); i++) {
1529 Ra ra = mRas.get(i);
1530 if (ra.matches(packet, length)) {
Lorenzo Colitti5ff640d2016-03-03 17:53:46 +09001531 if (VDBG) log("matched RA " + ra);
Paul Jensen578a76e2016-01-14 14:54:39 -05001532 // Update lifetimes.
Hugo Benichi4456f332016-12-19 14:50:52 +09001533 ra.mLastSeen = currentTimeSeconds();
Paul Jensen578a76e2016-01-14 14:54:39 -05001534 ra.mMinLifetime = ra.minLifetime(packet, length);
Lorenzo Colitti5ff640d2016-03-03 17:53:46 +09001535 ra.seenCount++;
Paul Jensen578a76e2016-01-14 14:54:39 -05001536
1537 // Keep mRas in LRU order so as to prioritize generating filters for recently seen
1538 // RAs. LRU prioritizes this because RA filters are generated in order from mRas
1539 // until the filter program exceeds the maximum filter program size allowed by the
1540 // chipset, so RAs appearing earlier in mRas are more likely to make it into the
1541 // filter program.
1542 // TODO: consider sorting the RAs in order of increasing expiry time as well.
1543 // Swap to front of array.
1544 mRas.add(0, mRas.remove(i));
1545
Hugo Benichi647c86d2016-06-07 15:35:16 +09001546 // If the current program doesn't expire for a while, don't update.
1547 if (shouldInstallnewProgram()) {
1548 installNewProgramLocked();
1549 return ProcessRaResult.UPDATE_EXPIRY;
1550 }
1551 return ProcessRaResult.MATCH;
Paul Jensen578a76e2016-01-14 14:54:39 -05001552 }
1553 }
Paul Jensendfd5a942016-03-17 13:22:29 -04001554 purgeExpiredRasLocked();
Paul Jensen578a76e2016-01-14 14:54:39 -05001555 // TODO: figure out how to proceed when we've received more then MAX_RAS RAs.
Hugo Benichi647c86d2016-06-07 15:35:16 +09001556 if (mRas.size() >= MAX_RAS) {
1557 return ProcessRaResult.DROPPED;
1558 }
Paul Jensendfd5a942016-03-17 13:22:29 -04001559 final Ra ra;
Paul Jensen578a76e2016-01-14 14:54:39 -05001560 try {
Paul Jensendfd5a942016-03-17 13:22:29 -04001561 ra = new Ra(packet, length);
Paul Jensen578a76e2016-01-14 14:54:39 -05001562 } catch (Exception e) {
Hugo Benichi0668a612016-10-06 15:19:36 +09001563 Log.e(TAG, "Error parsing RA", e);
Hugo Benichi647c86d2016-06-07 15:35:16 +09001564 return ProcessRaResult.PARSE_ERROR;
Paul Jensen578a76e2016-01-14 14:54:39 -05001565 }
Paul Jensendfd5a942016-03-17 13:22:29 -04001566 // Ignore 0 lifetime RAs.
Hugo Benichi647c86d2016-06-07 15:35:16 +09001567 if (ra.isExpired()) {
1568 return ProcessRaResult.ZERO_LIFETIME;
1569 }
Paul Jensendfd5a942016-03-17 13:22:29 -04001570 log("Adding " + ra);
1571 mRas.add(ra);
1572 installNewProgramLocked();
Hugo Benichi647c86d2016-06-07 15:35:16 +09001573 return ProcessRaResult.UPDATE_NEW_RA;
Paul Jensen578a76e2016-01-14 14:54:39 -05001574 }
1575
1576 /**
Paul Jensenf21b4dc2016-03-18 12:22:09 -04001577 * Create an {@link ApfFilter} if {@code apfCapabilities} indicates support for packet
Paul Jensen578a76e2016-01-14 14:54:39 -05001578 * filtering using APF programs.
1579 */
Bernie Innocenti5be71dc2018-03-28 20:11:49 +09001580 public static ApfFilter maybeCreate(Context context, ApfConfiguration config,
Remi NGUYEN VAN3c600a12019-01-10 19:12:46 +09001581 InterfaceParams ifParams, IpClientCallbacksWrapper ipClientCallback) {
Bernie Innocenti5be71dc2018-03-28 20:11:49 +09001582 if (context == null || config == null || ifParams == null) return null;
Hugo Benichi72166362017-10-13 16:32:20 +09001583 ApfCapabilities apfCapabilities = config.apfCapabilities;
Erik Kline8bd00d52017-12-08 17:47:50 +09001584 if (apfCapabilities == null) return null;
Paul Jensenf21b4dc2016-03-18 12:22:09 -04001585 if (apfCapabilities.apfVersionSupported == 0) return null;
1586 if (apfCapabilities.maximumApfProgramSize < 512) {
1587 Log.e(TAG, "Unacceptably small APF limit: " + apfCapabilities.maximumApfProgramSize);
1588 return null;
Paul Jensen578a76e2016-01-14 14:54:39 -05001589 }
1590 // For now only support generating programs for Ethernet frames. If this restriction is
1591 // lifted:
1592 // 1. the program generator will need its offsets adjusted.
1593 // 2. the packet filter attached to our packet socket will need its offset adjusted.
Paul Jensenf21b4dc2016-03-18 12:22:09 -04001594 if (apfCapabilities.apfPacketFormat != ARPHRD_ETHER) return null;
Bernie Innocenti408dbda2018-03-22 23:07:47 +09001595 if (!ApfGenerator.supportsVersion(apfCapabilities.apfVersionSupported)) {
Paul Jensenf21b4dc2016-03-18 12:22:09 -04001596 Log.e(TAG, "Unsupported APF version: " + apfCapabilities.apfVersionSupported);
1597 return null;
Paul Jensen578a76e2016-01-14 14:54:39 -05001598 }
Bernie Innocenti5be71dc2018-03-28 20:11:49 +09001599
1600 return new ApfFilter(context, config, ifParams, ipClientCallback, new IpConnectivityLog());
Paul Jensen578a76e2016-01-14 14:54:39 -05001601 }
1602
Paul Jensendfd5a942016-03-17 13:22:29 -04001603 public synchronized void shutdown() {
Paul Jensen578a76e2016-01-14 14:54:39 -05001604 if (mReceiveThread != null) {
Lorenzo Colitti5ff640d2016-03-03 17:53:46 +09001605 log("shutting down");
Paul Jensen578a76e2016-01-14 14:54:39 -05001606 mReceiveThread.halt(); // Also closes socket.
1607 mReceiveThread = null;
1608 }
Paul Jensendfd5a942016-03-17 13:22:29 -04001609 mRas.clear();
Bernie Innocenti5be71dc2018-03-28 20:11:49 +09001610 mContext.unregisterReceiver(mDeviceIdleReceiver);
Paul Jensen578a76e2016-01-14 14:54:39 -05001611 }
Lorenzo Colitti5ff640d2016-03-03 17:53:46 +09001612
Hugo Benichi22d9b2d2017-02-22 13:02:27 +09001613 public synchronized void setMulticastFilter(boolean isEnabled) {
Bernie Innocenti5be71dc2018-03-28 20:11:49 +09001614 if (mMulticastFilter == isEnabled) return;
Hugo Benichi22d9b2d2017-02-22 13:02:27 +09001615 mMulticastFilter = isEnabled;
1616 if (!isEnabled) {
1617 mNumProgramUpdatesAllowingMulticast++;
1618 }
1619 installNewProgramLocked();
Paul Jensendfd5a942016-03-17 13:22:29 -04001620 }
1621
Bernie Innocenti5be71dc2018-03-28 20:11:49 +09001622 @VisibleForTesting
1623 public synchronized void setDozeMode(boolean isEnabled) {
1624 if (mInDozeMode == isEnabled) return;
1625 mInDozeMode = isEnabled;
1626 installNewProgramLocked();
1627 }
1628
Hugo Benichi7d21eae2016-09-02 14:00:29 +09001629 /** Find the single IPv4 LinkAddress if there is one, otherwise return null. */
1630 private static LinkAddress findIPv4LinkAddress(LinkProperties lp) {
1631 LinkAddress ipv4Address = null;
1632 for (LinkAddress address : lp.getLinkAddresses()) {
1633 if (!(address.getAddress() instanceof Inet4Address)) {
1634 continue;
1635 }
1636 if (ipv4Address != null && !ipv4Address.isSameAddressAs(address)) {
1637 // More than one IPv4 address, abort.
1638 return null;
1639 }
1640 ipv4Address = address;
Paul Jensena8458c02016-03-25 11:25:57 -04001641 }
1642 return ipv4Address;
1643 }
1644
1645 public synchronized void setLinkProperties(LinkProperties lp) {
1646 // NOTE: Do not keep a copy of LinkProperties as it would further duplicate state.
Hugo Benichi7d21eae2016-09-02 14:00:29 +09001647 final LinkAddress ipv4Address = findIPv4LinkAddress(lp);
1648 final byte[] addr = (ipv4Address != null) ? ipv4Address.getAddress().getAddress() : null;
1649 final int prefix = (ipv4Address != null) ? ipv4Address.getPrefixLength() : 0;
1650 if ((prefix == mIPv4PrefixLength) && Arrays.equals(addr, mIPv4Address)) {
1651 return;
1652 }
1653 mIPv4Address = addr;
1654 mIPv4PrefixLength = prefix;
Paul Jensena8458c02016-03-25 11:25:57 -04001655 installNewProgramLocked();
1656 }
1657
junyulai352dc2f2019-01-08 20:04:33 +08001658 /**
Aaron Huanga63c40e2019-01-15 16:53:51 +08001659 * Add keepalive ack packet filter.
1660 * This will add a filter to drop acks to the keepalive packet passed as an argument.
junyulai352dc2f2019-01-08 20:04:33 +08001661 *
1662 * @param slot The index used to access the filter.
Aaron Huanga63c40e2019-01-15 16:53:51 +08001663 * @param sentKeepalivePacket The attributes of the sent keepalive packet.
junyulai352dc2f2019-01-08 20:04:33 +08001664 */
Aaron Huanga63c40e2019-01-15 16:53:51 +08001665 public synchronized void addKeepalivePacketFilter(final int slot,
1666 final TcpKeepalivePacketDataParcelable sentKeepalivePacket) {
1667 log("Adding keepalive ack(" + slot + ")");
1668 if (null != mKeepaliveAcks.get(slot)) {
1669 throw new IllegalArgumentException("Keepalive slot " + slot + " is occupied");
1670 }
1671 final int ipVersion = sentKeepalivePacket.srcAddress.length == 4 ? 4 : 6;
1672 mKeepaliveAcks.put(slot, (ipVersion == 4)
1673 ? new TcpKeepaliveAckV4(sentKeepalivePacket)
1674 : new TcpKeepaliveAckV6(sentKeepalivePacket));
1675 installNewProgramLocked();
junyulai352dc2f2019-01-08 20:04:33 +08001676 }
1677
1678 /**
1679 * Remove keepalive packet filter.
1680 *
1681 * @param slot The index used to access the filter.
1682 */
1683 public synchronized void removeKeepalivePacketFilter(int slot) {
Aaron Huanga63c40e2019-01-15 16:53:51 +08001684 mKeepaliveAcks.remove(slot);
1685 installNewProgramLocked();
junyulai352dc2f2019-01-08 20:04:33 +08001686 }
1687
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +09001688 static public long counterValue(byte[] data, Counter counter)
1689 throws ArrayIndexOutOfBoundsException {
1690 // Follow the same wrap-around addressing scheme of the interpreter.
1691 int offset = counter.offset();
1692 if (offset < 0) {
1693 offset = data.length + offset;
1694 }
1695
1696 // Decode 32bit big-endian integer into a long so we can count up beyond 2^31.
1697 long value = 0;
1698 for (int i = 0; i < 4; i++) {
1699 value = value << 8 | (data[offset] & 0xFF);
1700 offset++;
1701 }
1702 return value;
1703 }
1704
Paul Jensendfd5a942016-03-17 13:22:29 -04001705 public synchronized void dump(IndentingPrintWriter pw) {
Lorenzo Colitti059e2bb2016-04-08 20:51:39 +09001706 pw.println("Capabilities: " + mApfCapabilities);
Lorenzo Colitti5ff640d2016-03-03 17:53:46 +09001707 pw.println("Receive thread: " + (mReceiveThread != null ? "RUNNING" : "STOPPED"));
Lorenzo Colitti059e2bb2016-04-08 20:51:39 +09001708 pw.println("Multicast: " + (mMulticastFilter ? "DROP" : "ALLOW"));
Paul Jensena8458c02016-03-25 11:25:57 -04001709 try {
Lorenzo Colitti059e2bb2016-04-08 20:51:39 +09001710 pw.println("IPv4 address: " + InetAddress.getByAddress(mIPv4Address).getHostAddress());
Paul Jensena8458c02016-03-25 11:25:57 -04001711 } catch (UnknownHostException|NullPointerException e) {}
Lorenzo Colitti059e2bb2016-04-08 20:51:39 +09001712
Lorenzo Colitti5ff640d2016-03-03 17:53:46 +09001713 if (mLastTimeInstalledProgram == 0) {
1714 pw.println("No program installed.");
1715 return;
1716 }
Lorenzo Colitti059e2bb2016-04-08 20:51:39 +09001717 pw.println("Program updates: " + mNumProgramUpdates);
Lorenzo Colitti5ff640d2016-03-03 17:53:46 +09001718 pw.println(String.format(
Lorenzo Colitti059e2bb2016-04-08 20:51:39 +09001719 "Last program length %d, installed %ds ago, lifetime %ds",
Hugo Benichi4456f332016-12-19 14:50:52 +09001720 mLastInstalledProgram.length, currentTimeSeconds() - mLastTimeInstalledProgram,
Lorenzo Colitti5ff640d2016-03-03 17:53:46 +09001721 mLastInstalledProgramMinLifetime));
1722
1723 pw.println("RA filters:");
1724 pw.increaseIndent();
1725 for (Ra ra: mRas) {
1726 pw.println(ra);
1727 pw.increaseIndent();
1728 pw.println(String.format(
Hugo Benichi4456f332016-12-19 14:50:52 +09001729 "Seen: %d, last %ds ago", ra.seenCount, currentTimeSeconds() - ra.mLastSeen));
Lorenzo Colitti39c0d422016-03-23 00:23:29 +09001730 if (DBG) {
1731 pw.println("Last match:");
1732 pw.increaseIndent();
1733 pw.println(ra.getLastMatchingPacket());
1734 pw.decreaseIndent();
1735 }
Lorenzo Colitti5ff640d2016-03-03 17:53:46 +09001736 pw.decreaseIndent();
1737 }
Lorenzo Colitti059e2bb2016-04-08 20:51:39 +09001738 pw.decreaseIndent();
Lorenzo Colitti39c0d422016-03-23 00:23:29 +09001739
Aaron Huanga63c40e2019-01-15 16:53:51 +08001740 pw.println("Keepalive filter:");
1741 pw.increaseIndent();
1742 for (int i = 0; i < mKeepaliveAcks.size(); ++i) {
1743 final TcpKeepaliveAck keepaliveAck = mKeepaliveAcks.valueAt(i);
1744 pw.print("Slot ");
1745 pw.print(mKeepaliveAcks.keyAt(i));
1746 pw.print(" : ");
1747 pw.println(keepaliveAck);
1748 }
1749 pw.decreaseIndent();
1750
Lorenzo Colitti39c0d422016-03-23 00:23:29 +09001751 if (DBG) {
1752 pw.println("Last program:");
1753 pw.increaseIndent();
1754 pw.println(HexDump.toHexString(mLastInstalledProgram, false /* lowercase */));
1755 pw.decreaseIndent();
1756 }
Bernie Innocenti3cc40ea2018-04-24 01:25:42 +09001757
1758 pw.println("APF packet counters: ");
1759 pw.increaseIndent();
1760 if (!mApfCapabilities.hasDataAccess()) {
1761 pw.println("APF counters not supported");
1762 } else if (mDataSnapshot == null) {
1763 pw.println("No last snapshot.");
1764 } else {
1765 try {
1766 Counter[] counters = Counter.class.getEnumConstants();
1767 for (Counter c : Arrays.asList(counters).subList(1, counters.length)) {
1768 long value = counterValue(mDataSnapshot, c);
1769 // Only print non-zero counters
1770 if (value != 0) {
1771 pw.println(c.toString() + ": " + value);
1772 }
1773 }
1774 } catch (ArrayIndexOutOfBoundsException e) {
1775 pw.println("Uh-oh: " + e);
1776 }
1777 if (VDBG) {
1778 pw.println("Raw data dump: ");
1779 pw.println(HexDump.dumpHexString(mDataSnapshot));
1780 }
1781 }
1782 pw.decreaseIndent();
Lorenzo Colitti5ff640d2016-03-03 17:53:46 +09001783 }
Hugo Benichi7d21eae2016-09-02 14:00:29 +09001784
Hugo Benichi7d21eae2016-09-02 14:00:29 +09001785 // TODO: move to android.net.NetworkUtils
1786 @VisibleForTesting
1787 public static int ipv4BroadcastAddress(byte[] addrBytes, int prefixLength) {
Remi NGUYEN VAN3ba6c0d2019-01-20 13:48:19 +09001788 return bytesToBEInt(addrBytes) | (int) (Integer.toUnsignedLong(-1) >>> prefixLength);
1789 }
1790
1791 private static int uint8(byte b) {
1792 return b & 0xff;
1793 }
1794
1795 private static int getUint16(ByteBuffer buffer, int position) {
1796 return buffer.getShort(position) & 0xffff;
1797 }
1798
1799 private static long getUint32(ByteBuffer buffer, int position) {
1800 return Integer.toUnsignedLong(buffer.getInt(position));
1801 }
1802
1803 private static int getUint8(ByteBuffer buffer, int position) {
1804 return uint8(buffer.get(position));
1805 }
1806
1807 private static int bytesToBEInt(byte[] bytes) {
1808 return (uint8(bytes[0]) << 24)
1809 + (uint8(bytes[1]) << 16)
1810 + (uint8(bytes[2]) << 8)
1811 + (uint8(bytes[3]));
Hugo Benichi7d21eae2016-09-02 14:00:29 +09001812 }
Paul Jensen578a76e2016-01-14 14:54:39 -05001813}