blob: 3414397d73c31e42b7787687791f78763208ab29 [file] [log] [blame]
Paul Jensen9132f342016-04-13 15:00:26 -04001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.net.apf;
18
Remi NGUYEN VANa5d31f52019-01-12 15:36:47 +090019import static android.system.OsConstants.AF_UNIX;
20import static android.system.OsConstants.ARPHRD_ETHER;
21import static android.system.OsConstants.ETH_P_ARP;
22import static android.system.OsConstants.ETH_P_IP;
23import static android.system.OsConstants.ETH_P_IPV6;
24import static android.system.OsConstants.IPPROTO_ICMPV6;
Xiao Mad36a89c2019-02-10 14:52:37 +090025import static android.system.OsConstants.IPPROTO_TCP;
Remi NGUYEN VANa5d31f52019-01-12 15:36:47 +090026import static android.system.OsConstants.IPPROTO_UDP;
27import static android.system.OsConstants.SOCK_STREAM;
28
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090029import static com.android.internal.util.BitUtils.bytesToBEInt;
Remi NGUYEN VAN3c600a12019-01-10 19:12:46 +090030import static com.android.server.util.NetworkStackConstants.ICMPV6_ECHO_REQUEST_TYPE;
Remi NGUYEN VANa5d31f52019-01-12 15:36:47 +090031
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090032import static org.junit.Assert.assertEquals;
33import static org.junit.Assert.assertFalse;
34import static org.junit.Assert.assertTrue;
35import static org.junit.Assert.fail;
36import static org.mockito.Mockito.atLeastOnce;
Remi NGUYEN VAN3c600a12019-01-10 19:12:46 +090037import static org.mockito.Mockito.mock;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090038import static org.mockito.Mockito.verify;
39
Bernie Innocentie2c70f82018-03-28 20:11:49 +090040import android.content.Context;
Hugo Benichi7d21eae2016-09-02 14:00:29 +090041import android.net.LinkAddress;
42import android.net.LinkProperties;
Xiao Ma6b4de8f2019-02-15 19:18:21 +090043import android.net.TcpKeepalivePacketDataParcelable;
Hugo Benichi72166362017-10-13 16:32:20 +090044import android.net.apf.ApfFilter.ApfConfiguration;
Paul Jensen9132f342016-04-13 15:00:26 -040045import android.net.apf.ApfGenerator.IllegalInstructionException;
46import android.net.apf.ApfGenerator.Register;
Remi NGUYEN VAN3c600a12019-01-10 19:12:46 +090047import android.net.ip.IIpClientCallbacks;
Remi NGUYEN VAN3c600a12019-01-10 19:12:46 +090048import android.net.ip.IpClient.IpClientCallbacksWrapper;
Hugo Benichi6ccd51a2016-07-04 09:22:30 +090049import android.net.metrics.IpConnectivityLog;
50import android.net.metrics.RaEvent;
Erik Kline8bd00d52017-12-08 17:47:50 +090051import android.net.util.InterfaceParams;
Remi NGUYEN VAN3c600a12019-01-10 19:12:46 +090052import android.net.util.SharedLog;
Paul Jensen9132f342016-04-13 15:00:26 -040053import android.os.ConditionVariable;
Hugo Benichi6ccd51a2016-07-04 09:22:30 +090054import android.os.Parcelable;
Hugo Benichi4456f332016-12-19 14:50:52 +090055import android.os.SystemClock;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090056import android.support.test.InstrumentationRegistry;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090057import android.support.test.filters.SmallTest;
Bernie Innocentia9949e92018-03-22 23:07:47 +090058import android.support.test.runner.AndroidJUnit4;
Paul Jensen9132f342016-04-13 15:00:26 -040059import android.system.ErrnoException;
60import android.system.Os;
Hugo Benichi4456f332016-12-19 14:50:52 +090061import android.text.format.DateUtils;
Aaron Huang785e5f12018-10-31 15:57:48 +080062import android.util.Log;
Remi NGUYEN VANa5d31f52019-01-12 15:36:47 +090063
Hugo Benichi0668a612016-10-06 15:19:36 +090064import com.android.internal.util.HexDump;
Remi NGUYEN VAN3c600a12019-01-10 19:12:46 +090065import com.android.server.networkstack.tests.R;
66import com.android.server.util.NetworkStackConstants;
Remi NGUYEN VANa5d31f52019-01-12 15:36:47 +090067
68import libcore.io.IoUtils;
69import libcore.io.Streams;
70
71import org.junit.Before;
72import org.junit.Test;
73import org.junit.runner.RunWith;
74import org.mockito.ArgumentCaptor;
75import org.mockito.Mock;
76import org.mockito.MockitoAnnotations;
77
Paul Jensen9132f342016-04-13 15:00:26 -040078import java.io.File;
79import java.io.FileDescriptor;
80import java.io.FileOutputStream;
81import java.io.IOException;
82import java.io.InputStream;
83import java.io.OutputStream;
84import java.net.InetAddress;
Paul Jensen9132f342016-04-13 15:00:26 -040085import java.nio.ByteBuffer;
Hugo Benichi6ccd51a2016-07-04 09:22:30 +090086import java.util.List;
Hugo Benichi0668a612016-10-06 15:19:36 +090087import java.util.Random;
Paul Jensen9132f342016-04-13 15:00:26 -040088
89/**
90 * Tests for APF program generator and interpreter.
91 *
92 * Build, install and run with:
Hugo Benichi495a17b2017-01-12 15:31:05 +090093 * runtest frameworks-net -c android.net.apf.ApfTest
Paul Jensen9132f342016-04-13 15:00:26 -040094 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090095@RunWith(AndroidJUnit4.class)
96@SmallTest
97public class ApfTest {
Paul Jensen9132f342016-04-13 15:00:26 -040098 private static final int TIMEOUT_MS = 500;
Bernie Innocenti3d479d92018-04-20 23:31:33 +090099 private static final int MIN_APF_VERSION = 2;
Paul Jensen9132f342016-04-13 15:00:26 -0400100
Hugo Benichi6ccd51a2016-07-04 09:22:30 +0900101 @Mock IpConnectivityLog mLog;
Bernie Innocentie2c70f82018-03-28 20:11:49 +0900102 @Mock Context mContext;
Hugo Benichi6ccd51a2016-07-04 09:22:30 +0900103
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900104 @Before
Paul Jensen9132f342016-04-13 15:00:26 -0400105 public void setUp() throws Exception {
Hugo Benichi6ccd51a2016-07-04 09:22:30 +0900106 MockitoAnnotations.initMocks(this);
Paul Jensen9132f342016-04-13 15:00:26 -0400107 // Load up native shared library containing APF interpreter exposed via JNI.
Remi NGUYEN VAN3c600a12019-01-10 19:12:46 +0900108 System.loadLibrary("networkstacktestsjni");
Paul Jensen9132f342016-04-13 15:00:26 -0400109 }
110
Aaron Huang785e5f12018-10-31 15:57:48 +0800111 private static final String TAG = "ApfTest";
Paul Jensen9132f342016-04-13 15:00:26 -0400112 // Expected return codes from APF interpreter.
Bernie Innocenti3d479d92018-04-20 23:31:33 +0900113 private static final int PASS = 1;
114 private static final int DROP = 0;
Paul Jensen9132f342016-04-13 15:00:26 -0400115 // Interpreter will just accept packets without link layer headers, so pad fake packet to at
116 // least the minimum packet size.
Bernie Innocenti3d479d92018-04-20 23:31:33 +0900117 private static final int MIN_PKT_SIZE = 15;
Paul Jensen9132f342016-04-13 15:00:26 -0400118
Hugo Benichi72166362017-10-13 16:32:20 +0900119 private static final ApfCapabilities MOCK_APF_CAPABILITIES =
120 new ApfCapabilities(2, 1700, ARPHRD_ETHER);
121
Bernie Innocenti3d479d92018-04-20 23:31:33 +0900122 private static final boolean DROP_MULTICAST = true;
123 private static final boolean ALLOW_MULTICAST = false;
Hugo Benichi6ccd51a2016-07-04 09:22:30 +0900124
Bernie Innocenti3d479d92018-04-20 23:31:33 +0900125 private static final boolean DROP_802_3_FRAMES = true;
126 private static final boolean ALLOW_802_3_FRAMES = false;
127
128 // Constants for opcode encoding
129 private static final byte LI_OP = (byte)(13 << 3);
130 private static final byte LDDW_OP = (byte)(22 << 3);
131 private static final byte STDW_OP = (byte)(23 << 3);
132 private static final byte SIZE0 = (byte)(0 << 1);
133 private static final byte SIZE8 = (byte)(1 << 1);
134 private static final byte SIZE16 = (byte)(2 << 1);
135 private static final byte SIZE32 = (byte)(3 << 1);
136 private static final byte R1 = 1;
Ahmed ElArabawy8537c582017-06-12 18:01:11 -0700137
Hugo Benichi72166362017-10-13 16:32:20 +0900138 private static ApfConfiguration getDefaultConfig() {
139 ApfFilter.ApfConfiguration config = new ApfConfiguration();
140 config.apfCapabilities = MOCK_APF_CAPABILITIES;
141 config.multicastFilter = ALLOW_MULTICAST;
142 config.ieee802_3Filter = ALLOW_802_3_FRAMES;
143 config.ethTypeBlackList = new int[0];
144 return config;
145 }
146
Hugo Benichi961ca492016-09-02 11:04:34 +0900147 private static String label(int code) {
148 switch (code) {
149 case PASS: return "PASS";
150 case DROP: return "DROP";
151 default: return "UNKNOWN";
152 }
153 }
154
155 private static void assertReturnCodesEqual(int expected, int got) {
156 assertEquals(label(expected), label(got));
157 }
158
Paul Jensen9132f342016-04-13 15:00:26 -0400159 private void assertVerdict(int expected, byte[] program, byte[] packet, int filterAge) {
Bernie Innocentia9949e92018-03-22 23:07:47 +0900160 assertReturnCodesEqual(expected, apfSimulate(program, packet, null, filterAge));
Hugo Benichi961ca492016-09-02 11:04:34 +0900161 }
162
163 private void assertVerdict(int expected, byte[] program, byte[] packet) {
Bernie Innocentia9949e92018-03-22 23:07:47 +0900164 assertReturnCodesEqual(expected, apfSimulate(program, packet, null, 0));
Paul Jensen9132f342016-04-13 15:00:26 -0400165 }
166
167 private void assertPass(byte[] program, byte[] packet, int filterAge) {
168 assertVerdict(PASS, program, packet, filterAge);
169 }
170
Hugo Benichi961ca492016-09-02 11:04:34 +0900171 private void assertPass(byte[] program, byte[] packet) {
172 assertVerdict(PASS, program, packet);
173 }
174
Paul Jensen9132f342016-04-13 15:00:26 -0400175 private void assertDrop(byte[] program, byte[] packet, int filterAge) {
176 assertVerdict(DROP, program, packet, filterAge);
177 }
178
Hugo Benichi961ca492016-09-02 11:04:34 +0900179 private void assertDrop(byte[] program, byte[] packet) {
180 assertVerdict(DROP, program, packet);
181 }
182
Bernie Innocenti18050002018-04-19 20:53:00 +0900183 private void assertProgramEquals(byte[] expected, byte[] program) throws AssertionError {
184 // assertArrayEquals() would only print one byte, making debugging difficult.
185 if (!java.util.Arrays.equals(expected, program)) {
186 throw new AssertionError(
187 "\nexpected: " + HexDump.toHexString(expected) +
188 "\nactual: " + HexDump.toHexString(program));
189 }
190 }
191
192 private void assertDataMemoryContents(
193 int expected, byte[] program, byte[] packet, byte[] data, byte[] expected_data)
194 throws IllegalInstructionException, Exception {
Bernie Innocentia9949e92018-03-22 23:07:47 +0900195 assertReturnCodesEqual(expected, apfSimulate(program, packet, data, 0 /* filterAge */));
196
197 // assertArrayEquals() would only print one byte, making debugging difficult.
198 if (!java.util.Arrays.equals(expected_data, data)) {
199 throw new Exception(
Bernie Innocenti18050002018-04-19 20:53:00 +0900200 "\nprogram: " + HexDump.toHexString(program) +
Bernie Innocentia9949e92018-03-22 23:07:47 +0900201 "\ndata memory: " + HexDump.toHexString(data) +
Bernie Innocenti545d9362018-04-16 23:27:51 +0900202 "\nexpected: " + HexDump.toHexString(expected_data));
Bernie Innocentia9949e92018-03-22 23:07:47 +0900203 }
204 }
205
Paul Jensen9132f342016-04-13 15:00:26 -0400206 private void assertVerdict(int expected, ApfGenerator gen, byte[] packet, int filterAge)
207 throws IllegalInstructionException {
Bernie Innocentia9949e92018-03-22 23:07:47 +0900208 assertReturnCodesEqual(expected, apfSimulate(gen.generate(), packet, null,
209 filterAge));
Paul Jensen9132f342016-04-13 15:00:26 -0400210 }
211
212 private void assertPass(ApfGenerator gen, byte[] packet, int filterAge)
213 throws IllegalInstructionException {
214 assertVerdict(PASS, gen, packet, filterAge);
215 }
216
217 private void assertDrop(ApfGenerator gen, byte[] packet, int filterAge)
218 throws IllegalInstructionException {
219 assertVerdict(DROP, gen, packet, filterAge);
220 }
221
222 private void assertPass(ApfGenerator gen)
223 throws IllegalInstructionException {
224 assertVerdict(PASS, gen, new byte[MIN_PKT_SIZE], 0);
225 }
226
227 private void assertDrop(ApfGenerator gen)
228 throws IllegalInstructionException {
229 assertVerdict(DROP, gen, new byte[MIN_PKT_SIZE], 0);
230 }
231
232 /**
233 * Test each instruction by generating a program containing the instruction,
234 * generating bytecode for that program and running it through the
235 * interpreter to verify it functions correctly.
236 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900237 @Test
Paul Jensen9132f342016-04-13 15:00:26 -0400238 public void testApfInstructions() throws IllegalInstructionException {
239 // Empty program should pass because having the program counter reach the
240 // location immediately after the program indicates the packet should be
241 // passed to the AP.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900242 ApfGenerator gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400243 assertPass(gen);
244
245 // Test jumping to pass label.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900246 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400247 gen.addJump(gen.PASS_LABEL);
248 byte[] program = gen.generate();
249 assertEquals(1, program.length);
250 assertEquals((14 << 3) | (0 << 1) | 0, program[0]);
251 assertPass(program, new byte[MIN_PKT_SIZE], 0);
252
253 // Test jumping to drop label.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900254 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400255 gen.addJump(gen.DROP_LABEL);
256 program = gen.generate();
257 assertEquals(2, program.length);
258 assertEquals((14 << 3) | (1 << 1) | 0, program[0]);
259 assertEquals(1, program[1]);
260 assertDrop(program, new byte[15], 15);
261
262 // Test jumping if equal to 0.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900263 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400264 gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
265 assertDrop(gen);
266
267 // Test jumping if not equal to 0.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900268 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400269 gen.addJumpIfR0NotEquals(0, gen.DROP_LABEL);
270 assertPass(gen);
Bernie Innocentia9949e92018-03-22 23:07:47 +0900271 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400272 gen.addLoadImmediate(Register.R0, 1);
273 gen.addJumpIfR0NotEquals(0, gen.DROP_LABEL);
274 assertDrop(gen);
275
276 // Test jumping if registers equal.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900277 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400278 gen.addJumpIfR0EqualsR1(gen.DROP_LABEL);
279 assertDrop(gen);
280
281 // Test jumping if registers not equal.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900282 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400283 gen.addJumpIfR0NotEqualsR1(gen.DROP_LABEL);
284 assertPass(gen);
Bernie Innocentia9949e92018-03-22 23:07:47 +0900285 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400286 gen.addLoadImmediate(Register.R0, 1);
287 gen.addJumpIfR0NotEqualsR1(gen.DROP_LABEL);
288 assertDrop(gen);
289
290 // Test load immediate.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900291 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400292 gen.addLoadImmediate(Register.R0, 1234567890);
293 gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
294 assertDrop(gen);
295
296 // Test add.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900297 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400298 gen.addAdd(1234567890);
299 gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
300 assertDrop(gen);
301
302 // Test subtract.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900303 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400304 gen.addAdd(-1234567890);
305 gen.addJumpIfR0Equals(-1234567890, gen.DROP_LABEL);
306 assertDrop(gen);
307
308 // Test or.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900309 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400310 gen.addOr(1234567890);
311 gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
312 assertDrop(gen);
313
314 // Test and.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900315 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400316 gen.addLoadImmediate(Register.R0, 1234567890);
317 gen.addAnd(123456789);
318 gen.addJumpIfR0Equals(1234567890 & 123456789, gen.DROP_LABEL);
319 assertDrop(gen);
320
321 // Test left shift.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900322 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400323 gen.addLoadImmediate(Register.R0, 1234567890);
324 gen.addLeftShift(1);
325 gen.addJumpIfR0Equals(1234567890 << 1, gen.DROP_LABEL);
326 assertDrop(gen);
327
328 // Test right shift.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900329 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400330 gen.addLoadImmediate(Register.R0, 1234567890);
331 gen.addRightShift(1);
332 gen.addJumpIfR0Equals(1234567890 >> 1, gen.DROP_LABEL);
333 assertDrop(gen);
334
335 // Test multiply.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900336 gen = new ApfGenerator(MIN_APF_VERSION);
Andreas Gampe5b003112018-06-13 11:35:16 -0700337 gen.addLoadImmediate(Register.R0, 123456789);
Paul Jensen9132f342016-04-13 15:00:26 -0400338 gen.addMul(2);
Andreas Gampe5b003112018-06-13 11:35:16 -0700339 gen.addJumpIfR0Equals(123456789 * 2, gen.DROP_LABEL);
Paul Jensen9132f342016-04-13 15:00:26 -0400340 assertDrop(gen);
341
342 // Test divide.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900343 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400344 gen.addLoadImmediate(Register.R0, 1234567890);
345 gen.addDiv(2);
346 gen.addJumpIfR0Equals(1234567890 / 2, gen.DROP_LABEL);
347 assertDrop(gen);
348
349 // Test divide by zero.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900350 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400351 gen.addDiv(0);
352 gen.addJump(gen.DROP_LABEL);
353 assertPass(gen);
354
355 // Test add.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900356 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400357 gen.addLoadImmediate(Register.R1, 1234567890);
358 gen.addAddR1();
359 gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
360 assertDrop(gen);
361
362 // Test subtract.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900363 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400364 gen.addLoadImmediate(Register.R1, -1234567890);
365 gen.addAddR1();
366 gen.addJumpIfR0Equals(-1234567890, gen.DROP_LABEL);
367 assertDrop(gen);
368
369 // Test or.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900370 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400371 gen.addLoadImmediate(Register.R1, 1234567890);
372 gen.addOrR1();
373 gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
374 assertDrop(gen);
375
376 // Test and.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900377 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400378 gen.addLoadImmediate(Register.R0, 1234567890);
379 gen.addLoadImmediate(Register.R1, 123456789);
380 gen.addAndR1();
381 gen.addJumpIfR0Equals(1234567890 & 123456789, gen.DROP_LABEL);
382 assertDrop(gen);
383
384 // Test left shift.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900385 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400386 gen.addLoadImmediate(Register.R0, 1234567890);
387 gen.addLoadImmediate(Register.R1, 1);
388 gen.addLeftShiftR1();
389 gen.addJumpIfR0Equals(1234567890 << 1, gen.DROP_LABEL);
390 assertDrop(gen);
391
392 // Test right shift.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900393 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400394 gen.addLoadImmediate(Register.R0, 1234567890);
395 gen.addLoadImmediate(Register.R1, -1);
396 gen.addLeftShiftR1();
397 gen.addJumpIfR0Equals(1234567890 >> 1, gen.DROP_LABEL);
398 assertDrop(gen);
399
400 // Test multiply.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900401 gen = new ApfGenerator(MIN_APF_VERSION);
Andreas Gampe5b003112018-06-13 11:35:16 -0700402 gen.addLoadImmediate(Register.R0, 123456789);
Paul Jensen9132f342016-04-13 15:00:26 -0400403 gen.addLoadImmediate(Register.R1, 2);
404 gen.addMulR1();
Andreas Gampe5b003112018-06-13 11:35:16 -0700405 gen.addJumpIfR0Equals(123456789 * 2, gen.DROP_LABEL);
Paul Jensen9132f342016-04-13 15:00:26 -0400406 assertDrop(gen);
407
408 // Test divide.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900409 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400410 gen.addLoadImmediate(Register.R0, 1234567890);
411 gen.addLoadImmediate(Register.R1, 2);
412 gen.addDivR1();
413 gen.addJumpIfR0Equals(1234567890 / 2, gen.DROP_LABEL);
414 assertDrop(gen);
415
416 // Test divide by zero.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900417 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400418 gen.addDivR1();
419 gen.addJump(gen.DROP_LABEL);
420 assertPass(gen);
421
422 // Test byte load.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900423 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400424 gen.addLoad8(Register.R0, 1);
425 gen.addJumpIfR0Equals(45, gen.DROP_LABEL);
426 assertDrop(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
427
428 // Test out of bounds load.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900429 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400430 gen.addLoad8(Register.R0, 16);
431 gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
432 assertPass(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
433
434 // Test half-word load.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900435 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400436 gen.addLoad16(Register.R0, 1);
437 gen.addJumpIfR0Equals((45 << 8) | 67, gen.DROP_LABEL);
438 assertDrop(gen, new byte[]{123,45,67,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
439
440 // Test word load.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900441 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400442 gen.addLoad32(Register.R0, 1);
443 gen.addJumpIfR0Equals((45 << 24) | (67 << 16) | (89 << 8) | 12, gen.DROP_LABEL);
444 assertDrop(gen, new byte[]{123,45,67,89,12,0,0,0,0,0,0,0,0,0,0}, 0);
445
446 // Test byte indexed load.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900447 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400448 gen.addLoadImmediate(Register.R1, 1);
449 gen.addLoad8Indexed(Register.R0, 0);
450 gen.addJumpIfR0Equals(45, gen.DROP_LABEL);
451 assertDrop(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
452
453 // Test out of bounds indexed load.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900454 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400455 gen.addLoadImmediate(Register.R1, 8);
456 gen.addLoad8Indexed(Register.R0, 8);
457 gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
458 assertPass(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
459
460 // Test half-word indexed load.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900461 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400462 gen.addLoadImmediate(Register.R1, 1);
463 gen.addLoad16Indexed(Register.R0, 0);
464 gen.addJumpIfR0Equals((45 << 8) | 67, gen.DROP_LABEL);
465 assertDrop(gen, new byte[]{123,45,67,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
466
467 // Test word indexed load.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900468 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400469 gen.addLoadImmediate(Register.R1, 1);
470 gen.addLoad32Indexed(Register.R0, 0);
471 gen.addJumpIfR0Equals((45 << 24) | (67 << 16) | (89 << 8) | 12, gen.DROP_LABEL);
472 assertDrop(gen, new byte[]{123,45,67,89,12,0,0,0,0,0,0,0,0,0,0}, 0);
473
474 // Test jumping if greater than.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900475 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400476 gen.addJumpIfR0GreaterThan(0, gen.DROP_LABEL);
477 assertPass(gen);
Bernie Innocentia9949e92018-03-22 23:07:47 +0900478 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400479 gen.addLoadImmediate(Register.R0, 1);
480 gen.addJumpIfR0GreaterThan(0, gen.DROP_LABEL);
481 assertDrop(gen);
482
483 // Test jumping if less than.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900484 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400485 gen.addJumpIfR0LessThan(0, gen.DROP_LABEL);
486 assertPass(gen);
Bernie Innocentia9949e92018-03-22 23:07:47 +0900487 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400488 gen.addJumpIfR0LessThan(1, gen.DROP_LABEL);
489 assertDrop(gen);
490
491 // Test jumping if any bits set.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900492 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400493 gen.addJumpIfR0AnyBitsSet(3, gen.DROP_LABEL);
494 assertPass(gen);
Bernie Innocentia9949e92018-03-22 23:07:47 +0900495 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400496 gen.addLoadImmediate(Register.R0, 1);
497 gen.addJumpIfR0AnyBitsSet(3, gen.DROP_LABEL);
498 assertDrop(gen);
Bernie Innocentia9949e92018-03-22 23:07:47 +0900499 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400500 gen.addLoadImmediate(Register.R0, 3);
501 gen.addJumpIfR0AnyBitsSet(3, gen.DROP_LABEL);
502 assertDrop(gen);
503
504 // Test jumping if register greater than.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900505 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400506 gen.addJumpIfR0GreaterThanR1(gen.DROP_LABEL);
507 assertPass(gen);
Bernie Innocentia9949e92018-03-22 23:07:47 +0900508 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400509 gen.addLoadImmediate(Register.R0, 2);
510 gen.addLoadImmediate(Register.R1, 1);
511 gen.addJumpIfR0GreaterThanR1(gen.DROP_LABEL);
512 assertDrop(gen);
513
514 // Test jumping if register less than.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900515 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400516 gen.addJumpIfR0LessThanR1(gen.DROP_LABEL);
517 assertPass(gen);
Bernie Innocentia9949e92018-03-22 23:07:47 +0900518 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400519 gen.addLoadImmediate(Register.R1, 1);
520 gen.addJumpIfR0LessThanR1(gen.DROP_LABEL);
521 assertDrop(gen);
522
523 // Test jumping if any bits set in register.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900524 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400525 gen.addLoadImmediate(Register.R1, 3);
526 gen.addJumpIfR0AnyBitsSetR1(gen.DROP_LABEL);
527 assertPass(gen);
Bernie Innocentia9949e92018-03-22 23:07:47 +0900528 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400529 gen.addLoadImmediate(Register.R1, 3);
530 gen.addLoadImmediate(Register.R0, 1);
531 gen.addJumpIfR0AnyBitsSetR1(gen.DROP_LABEL);
532 assertDrop(gen);
Bernie Innocentia9949e92018-03-22 23:07:47 +0900533 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400534 gen.addLoadImmediate(Register.R1, 3);
535 gen.addLoadImmediate(Register.R0, 3);
536 gen.addJumpIfR0AnyBitsSetR1(gen.DROP_LABEL);
537 assertDrop(gen);
538
539 // Test load from memory.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900540 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400541 gen.addLoadFromMemory(Register.R0, 0);
542 gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
543 assertDrop(gen);
544
545 // Test store to memory.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900546 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400547 gen.addLoadImmediate(Register.R1, 1234567890);
548 gen.addStoreToMemory(Register.R1, 12);
549 gen.addLoadFromMemory(Register.R0, 12);
550 gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
551 assertDrop(gen);
552
553 // Test filter age pre-filled memory.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900554 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400555 gen.addLoadFromMemory(Register.R0, gen.FILTER_AGE_MEMORY_SLOT);
556 gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
557 assertDrop(gen, new byte[MIN_PKT_SIZE], 1234567890);
558
559 // Test packet size pre-filled memory.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900560 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400561 gen.addLoadFromMemory(Register.R0, gen.PACKET_SIZE_MEMORY_SLOT);
562 gen.addJumpIfR0Equals(MIN_PKT_SIZE, gen.DROP_LABEL);
563 assertDrop(gen);
564
565 // Test IPv4 header size pre-filled memory.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900566 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400567 gen.addLoadFromMemory(Register.R0, gen.IPV4_HEADER_SIZE_MEMORY_SLOT);
568 gen.addJumpIfR0Equals(20, gen.DROP_LABEL);
569 assertDrop(gen, new byte[]{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x45}, 0);
570
571 // Test not.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900572 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400573 gen.addLoadImmediate(Register.R0, 1234567890);
574 gen.addNot(Register.R0);
575 gen.addJumpIfR0Equals(~1234567890, gen.DROP_LABEL);
576 assertDrop(gen);
577
578 // Test negate.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900579 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400580 gen.addLoadImmediate(Register.R0, 1234567890);
581 gen.addNeg(Register.R0);
582 gen.addJumpIfR0Equals(-1234567890, gen.DROP_LABEL);
583 assertDrop(gen);
584
585 // Test move.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900586 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400587 gen.addLoadImmediate(Register.R1, 1234567890);
588 gen.addMove(Register.R0);
589 gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
590 assertDrop(gen);
Bernie Innocentia9949e92018-03-22 23:07:47 +0900591 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400592 gen.addLoadImmediate(Register.R0, 1234567890);
593 gen.addMove(Register.R1);
594 gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
595 assertDrop(gen);
596
597 // Test swap.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900598 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400599 gen.addLoadImmediate(Register.R1, 1234567890);
600 gen.addSwap();
601 gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
602 assertDrop(gen);
Bernie Innocentia9949e92018-03-22 23:07:47 +0900603 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400604 gen.addLoadImmediate(Register.R0, 1234567890);
605 gen.addSwap();
606 gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
607 assertDrop(gen);
608
609 // Test jump if bytes not equal.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900610 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400611 gen.addLoadImmediate(Register.R0, 1);
612 gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{123}, gen.DROP_LABEL);
613 program = gen.generate();
614 assertEquals(6, program.length);
615 assertEquals((13 << 3) | (1 << 1) | 0, program[0]);
616 assertEquals(1, program[1]);
617 assertEquals(((20 << 3) | (1 << 1) | 0) - 256, program[2]);
618 assertEquals(1, program[3]);
619 assertEquals(1, program[4]);
620 assertEquals(123, program[5]);
621 assertDrop(program, new byte[MIN_PKT_SIZE], 0);
Bernie Innocentia9949e92018-03-22 23:07:47 +0900622 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400623 gen.addLoadImmediate(Register.R0, 1);
624 gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{123}, gen.DROP_LABEL);
Hugo Benichi961ca492016-09-02 11:04:34 +0900625 byte[] packet123 = {0,123,0,0,0,0,0,0,0,0,0,0,0,0,0};
Paul Jensen9132f342016-04-13 15:00:26 -0400626 assertPass(gen, packet123, 0);
Bernie Innocentia9949e92018-03-22 23:07:47 +0900627 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400628 gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{123}, gen.DROP_LABEL);
629 assertDrop(gen, packet123, 0);
Bernie Innocentia9949e92018-03-22 23:07:47 +0900630 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400631 gen.addLoadImmediate(Register.R0, 1);
632 gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{1,2,30,4,5}, gen.DROP_LABEL);
Hugo Benichi961ca492016-09-02 11:04:34 +0900633 byte[] packet12345 = {0,1,2,3,4,5,0,0,0,0,0,0,0,0,0};
Paul Jensen9132f342016-04-13 15:00:26 -0400634 assertDrop(gen, packet12345, 0);
Bernie Innocentia9949e92018-03-22 23:07:47 +0900635 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400636 gen.addLoadImmediate(Register.R0, 1);
637 gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{1,2,3,4,5}, gen.DROP_LABEL);
638 assertPass(gen, packet12345, 0);
639 }
640
Bernie Innocentia9949e92018-03-22 23:07:47 +0900641 @Test(expected = ApfGenerator.IllegalInstructionException.class)
642 public void testApfGeneratorWantsV2OrGreater() throws Exception {
643 // The minimum supported APF version is 2.
644 new ApfGenerator(1);
645 }
646
647 @Test
648 public void testApfDataOpcodesWantApfV3() throws IllegalInstructionException, Exception {
649 ApfGenerator gen = new ApfGenerator(MIN_APF_VERSION);
650 try {
651 gen.addStoreData(Register.R0, 0);
652 fail();
653 } catch (IllegalInstructionException expected) {
654 /* pass */
655 }
656 try {
657 gen.addLoadData(Register.R0, 0);
658 fail();
659 } catch (IllegalInstructionException expected) {
660 /* pass */
661 }
662 }
663
Bernie Innocenti18050002018-04-19 20:53:00 +0900664 /**
665 * Test that the generator emits immediates using the shortest possible encoding.
666 */
667 @Test
668 public void testImmediateEncoding() throws IllegalInstructionException {
Bernie Innocenti18050002018-04-19 20:53:00 +0900669 ApfGenerator gen;
670
671 // 0-byte immediate: li R0, 0
Bernie Innocenti3d479d92018-04-20 23:31:33 +0900672 gen = new ApfGenerator(4);
Bernie Innocenti18050002018-04-19 20:53:00 +0900673 gen.addLoadImmediate(Register.R0, 0);
Bernie Innocenti3d479d92018-04-20 23:31:33 +0900674 assertProgramEquals(new byte[]{LI_OP | SIZE0}, gen.generate());
Bernie Innocenti18050002018-04-19 20:53:00 +0900675
676 // 1-byte immediate: li R0, 42
Bernie Innocenti3d479d92018-04-20 23:31:33 +0900677 gen = new ApfGenerator(4);
Bernie Innocenti18050002018-04-19 20:53:00 +0900678 gen.addLoadImmediate(Register.R0, 42);
Bernie Innocenti3d479d92018-04-20 23:31:33 +0900679 assertProgramEquals(new byte[]{LI_OP | SIZE8, 42}, gen.generate());
Bernie Innocenti18050002018-04-19 20:53:00 +0900680
681 // 2-byte immediate: li R1, 0x1234
Bernie Innocenti3d479d92018-04-20 23:31:33 +0900682 gen = new ApfGenerator(4);
Bernie Innocenti18050002018-04-19 20:53:00 +0900683 gen.addLoadImmediate(Register.R1, 0x1234);
Bernie Innocenti3d479d92018-04-20 23:31:33 +0900684 assertProgramEquals(new byte[]{LI_OP | SIZE16 | R1, 0x12, 0x34}, gen.generate());
Bernie Innocenti18050002018-04-19 20:53:00 +0900685
686 // 4-byte immediate: li R0, 0x12345678
687 gen = new ApfGenerator(3);
688 gen.addLoadImmediate(Register.R0, 0x12345678);
689 assertProgramEquals(
Bernie Innocenti3d479d92018-04-20 23:31:33 +0900690 new byte[]{LI_OP | SIZE32, 0x12, 0x34, 0x56, 0x78},
Bernie Innocenti18050002018-04-19 20:53:00 +0900691 gen.generate());
692 }
693
694 /**
695 * Test that the generator emits negative immediates using the shortest possible encoding.
696 */
697 @Test
698 public void testNegativeImmediateEncoding() throws IllegalInstructionException {
Bernie Innocenti18050002018-04-19 20:53:00 +0900699 ApfGenerator gen;
700
701 // 1-byte negative immediate: li R0, -42
702 gen = new ApfGenerator(3);
703 gen.addLoadImmediate(Register.R0, -42);
Bernie Innocenti3d479d92018-04-20 23:31:33 +0900704 assertProgramEquals(new byte[]{LI_OP | SIZE8, -42}, gen.generate());
Bernie Innocenti18050002018-04-19 20:53:00 +0900705
Bernie Innocenti3d479d92018-04-20 23:31:33 +0900706 // 2-byte negative immediate: li R1, -0x1122
Bernie Innocenti18050002018-04-19 20:53:00 +0900707 gen = new ApfGenerator(3);
708 gen.addLoadImmediate(Register.R1, -0x1122);
Bernie Innocenti3d479d92018-04-20 23:31:33 +0900709 assertProgramEquals(new byte[]{LI_OP | SIZE16 | R1, (byte)0xEE, (byte)0xDE},
Bernie Innocenti18050002018-04-19 20:53:00 +0900710 gen.generate());
711
712 // 4-byte negative immediate: li R0, -0x11223344
713 gen = new ApfGenerator(3);
714 gen.addLoadImmediate(Register.R0, -0x11223344);
715 assertProgramEquals(
Bernie Innocenti3d479d92018-04-20 23:31:33 +0900716 new byte[]{LI_OP | SIZE32, (byte)0xEE, (byte)0xDD, (byte)0xCC, (byte)0xBC},
Bernie Innocenti18050002018-04-19 20:53:00 +0900717 gen.generate());
718 }
719
Bernie Innocenti3d479d92018-04-20 23:31:33 +0900720 /**
721 * Test that the generator correctly emits positive and negative immediates for LDDW/STDW.
722 */
723 @Test
724 public void testLoadStoreDataEncoding() throws IllegalInstructionException {
725 ApfGenerator gen;
726
727 // Load data with no offset: lddw R0, [0 + r1]
728 gen = new ApfGenerator(3);
729 gen.addLoadData(Register.R0, 0);
730 assertProgramEquals(new byte[]{LDDW_OP | SIZE0}, gen.generate());
731
732 // Store data with 8bit negative offset: lddw r0, [-42 + r1]
733 gen = new ApfGenerator(3);
734 gen.addStoreData(Register.R0, -42);
735 assertProgramEquals(new byte[]{STDW_OP | SIZE8, -42}, gen.generate());
736
737 // Store data to R1 with 16bit negative offset: stdw r1, [-0x1122 + r0]
738 gen = new ApfGenerator(3);
739 gen.addStoreData(Register.R1, -0x1122);
740 assertProgramEquals(new byte[]{STDW_OP | SIZE16 | R1, (byte)0xEE, (byte)0xDE},
741 gen.generate());
742
743 // Load data to R1 with 32bit negative offset: lddw r1, [0xDEADBEEF + r0]
744 gen = new ApfGenerator(3);
745 gen.addLoadData(Register.R1, 0xDEADBEEF);
746 assertProgramEquals(
747 new byte[]{LDDW_OP | SIZE32 | R1, (byte)0xDE, (byte)0xAD, (byte)0xBE, (byte)0xEF},
748 gen.generate());
749 }
750
751 /**
752 * Test that the interpreter correctly executes STDW with a negative 8bit offset
753 */
Bernie Innocentia9949e92018-03-22 23:07:47 +0900754 @Test
755 public void testApfDataWrite() throws IllegalInstructionException, Exception {
756 byte[] packet = new byte[MIN_PKT_SIZE];
Bernie Innocenti545d9362018-04-16 23:27:51 +0900757 byte[] data = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
Bernie Innocentia9949e92018-03-22 23:07:47 +0900758 byte[] expected_data = data.clone();
759
760 // No memory access instructions: should leave the data segment untouched.
761 ApfGenerator gen = new ApfGenerator(3);
762 assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data);
763
Bernie Innocenti545d9362018-04-16 23:27:51 +0900764 // Expect value 0x87654321 to be stored starting from address -11 from the end of the
765 // data buffer, in big-endian order.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900766 gen = new ApfGenerator(3);
767 gen.addLoadImmediate(Register.R0, 0x87654321);
Bernie Innocenti545d9362018-04-16 23:27:51 +0900768 gen.addLoadImmediate(Register.R1, -5);
769 gen.addStoreData(Register.R0, -6); // -5 + -6 = -11 (offset +5 with data_len=16)
Bernie Innocentia9949e92018-03-22 23:07:47 +0900770 expected_data[5] = (byte)0x87;
771 expected_data[6] = (byte)0x65;
772 expected_data[7] = (byte)0x43;
773 expected_data[8] = (byte)0x21;
774 assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data);
775 }
776
Bernie Innocenti3d479d92018-04-20 23:31:33 +0900777 /**
778 * Test that the interpreter correctly executes LDDW with a negative 16bit offset
779 */
Bernie Innocentia9949e92018-03-22 23:07:47 +0900780 @Test
781 public void testApfDataRead() throws IllegalInstructionException, Exception {
Bernie Innocenti545d9362018-04-16 23:27:51 +0900782 // Program that DROPs if address 10 (-6) contains 0x87654321.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900783 ApfGenerator gen = new ApfGenerator(3);
Bernie Innocenti3d479d92018-04-20 23:31:33 +0900784 gen.addLoadImmediate(Register.R1, 1000);
785 gen.addLoadData(Register.R0, -1006); // 1000 + -1006 = -6 (offset +10 with data_len=16)
Bernie Innocentia9949e92018-03-22 23:07:47 +0900786 gen.addJumpIfR0Equals(0x87654321, gen.DROP_LABEL);
787 byte[] program = gen.generate();
788 byte[] packet = new byte[MIN_PKT_SIZE];
789
790 // Content is incorrect (last byte does not match) -> PASS
Bernie Innocenti545d9362018-04-16 23:27:51 +0900791 byte[] data = new byte[16];
Bernie Innocentia9949e92018-03-22 23:07:47 +0900792 data[10] = (byte)0x87;
793 data[11] = (byte)0x65;
794 data[12] = (byte)0x43;
795 data[13] = (byte)0x00; // != 0x21
796 byte[] expected_data = data.clone();
797 assertDataMemoryContents(PASS, program, packet, data, expected_data);
798
799 // Fix the last byte -> conditional jump taken -> DROP
800 data[13] = (byte)0x21;
801 expected_data = data;
802 assertDataMemoryContents(DROP, program, packet, data, expected_data);
803 }
804
Bernie Innocenti3d479d92018-04-20 23:31:33 +0900805 /**
806 * Test that the interpreter correctly executes LDDW followed by a STDW.
807 * To cover a few more edge cases, LDDW has a 0bit offset, while STDW has a positive 8bit
808 * offset.
809 */
Bernie Innocentia9949e92018-03-22 23:07:47 +0900810 @Test
811 public void testApfDataReadModifyWrite() throws IllegalInstructionException, Exception {
812 ApfGenerator gen = new ApfGenerator(3);
Bernie Innocenti545d9362018-04-16 23:27:51 +0900813 gen.addLoadImmediate(Register.R1, -22);
814 gen.addLoadData(Register.R0, 0); // Load from address 32 -22 + 0 = 10
Bernie Innocentia9949e92018-03-22 23:07:47 +0900815 gen.addAdd(0x78453412); // 87654321 + 78453412 = FFAA7733
Bernie Innocenti545d9362018-04-16 23:27:51 +0900816 gen.addStoreData(Register.R0, 4); // Write back to address 32 -22 + 4 = 14
Bernie Innocentia9949e92018-03-22 23:07:47 +0900817
818 byte[] packet = new byte[MIN_PKT_SIZE];
819 byte[] data = new byte[32];
820 data[10] = (byte)0x87;
821 data[11] = (byte)0x65;
822 data[12] = (byte)0x43;
823 data[13] = (byte)0x21;
824 byte[] expected_data = data.clone();
825 expected_data[14] = (byte)0xFF;
826 expected_data[15] = (byte)0xAA;
827 expected_data[16] = (byte)0x77;
828 expected_data[17] = (byte)0x33;
829 assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data);
830 }
831
832 @Test
833 public void testApfDataBoundChecking() throws IllegalInstructionException, Exception {
834 byte[] packet = new byte[MIN_PKT_SIZE];
835 byte[] data = new byte[32];
836 byte[] expected_data = data;
837
838 // Program that DROPs unconditionally. This is our the baseline.
839 ApfGenerator gen = new ApfGenerator(3);
840 gen.addLoadImmediate(Register.R0, 3);
841 gen.addLoadData(Register.R1, 7);
842 gen.addJump(gen.DROP_LABEL);
843 assertDataMemoryContents(DROP, gen.generate(), packet, data, expected_data);
844
845 // Same program as before, but this time we're trying to load past the end of the data.
846 gen = new ApfGenerator(3);
847 gen.addLoadImmediate(Register.R0, 20);
848 gen.addLoadData(Register.R1, 15); // 20 + 15 > 32
849 gen.addJump(gen.DROP_LABEL); // Not reached.
850 assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data);
851
852 // Subtracting an immediate should work...
853 gen = new ApfGenerator(3);
854 gen.addLoadImmediate(Register.R0, 20);
855 gen.addLoadData(Register.R1, -4);
856 gen.addJump(gen.DROP_LABEL);
857 assertDataMemoryContents(DROP, gen.generate(), packet, data, expected_data);
858
Bernie Innocenti545d9362018-04-16 23:27:51 +0900859 // ...and underflowing simply wraps around to the end of the buffer...
Bernie Innocentia9949e92018-03-22 23:07:47 +0900860 gen = new ApfGenerator(3);
861 gen.addLoadImmediate(Register.R0, 20);
862 gen.addLoadData(Register.R1, -30);
Bernie Innocenti545d9362018-04-16 23:27:51 +0900863 gen.addJump(gen.DROP_LABEL);
864 assertDataMemoryContents(DROP, gen.generate(), packet, data, expected_data);
865
866 // ...but doesn't allow accesses before the start of the buffer
867 gen = new ApfGenerator(3);
868 gen.addLoadImmediate(Register.R0, 20);
869 gen.addLoadData(Register.R1, -1000);
Bernie Innocentia9949e92018-03-22 23:07:47 +0900870 gen.addJump(gen.DROP_LABEL); // Not reached.
871 assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data);
872 }
873
Paul Jensen9132f342016-04-13 15:00:26 -0400874 /**
875 * Generate some BPF programs, translate them to APF, then run APF and BPF programs
876 * over packet traces and verify both programs filter out the same packets.
877 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900878 @Test
Paul Jensen9132f342016-04-13 15:00:26 -0400879 public void testApfAgainstBpf() throws Exception {
880 String[] tcpdump_filters = new String[]{ "udp", "tcp", "icmp", "icmp6", "udp port 53",
881 "arp", "dst 239.255.255.250", "arp or tcp or udp port 53", "net 192.168.1.0/24",
882 "arp or icmp6 or portrange 53-54", "portrange 53-54 or portrange 100-50000",
883 "tcp[tcpflags] & (tcp-ack|tcp-fin) != 0 and (ip[2:2] > 57 or icmp)" };
884 String pcap_filename = stageFile(R.raw.apf);
885 for (String tcpdump_filter : tcpdump_filters) {
886 byte[] apf_program = Bpf2Apf.convert(compileToBpf(tcpdump_filter));
887 assertTrue("Failed to match for filter: " + tcpdump_filter,
888 compareBpfApf(tcpdump_filter, pcap_filename, apf_program));
889 }
890 }
891
Aaron Huang785e5f12018-10-31 15:57:48 +0800892 /**
893 * Generate APF program, run pcap file though APF filter, then check all the packets in the file
894 * should be dropped.
895 */
896 @Test
897 public void testApfFilterPcapFile() throws Exception {
898 final byte[] MOCK_PCAP_IPV4_ADDR = {(byte) 172, 16, 7, (byte) 151};
899 String pcapFilename = stageFile(R.raw.apfPcap);
900 MockIpClientCallback ipClientCallback = new MockIpClientCallback();
901 LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_PCAP_IPV4_ADDR), 16);
902 LinkProperties lp = new LinkProperties();
903 lp.addLinkAddress(link);
904
905 ApfConfiguration config = getDefaultConfig();
906 ApfCapabilities MOCK_APF_PCAP_CAPABILITIES = new ApfCapabilities(4, 1700, ARPHRD_ETHER);
907 config.apfCapabilities = MOCK_APF_PCAP_CAPABILITIES;
908 config.multicastFilter = DROP_MULTICAST;
909 config.ieee802_3Filter = DROP_802_3_FRAMES;
910 TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
911 apfFilter.setLinkProperties(lp);
912 byte[] program = ipClientCallback.getApfProgram();
913 byte[] data = new byte[ApfFilter.Counter.totalSize()];
914 final boolean result;
915
916 result = dropsAllPackets(program, data, pcapFilename);
917 Log.i(TAG, "testApfFilterPcapFile(): Data counters: " + HexDump.toHexString(data, false));
918
919 assertTrue("Failed to drop all packets by filter. \nAPF counters:" +
920 HexDump.toHexString(data, false), result);
921 }
922
Remi NGUYEN VAN3c600a12019-01-10 19:12:46 +0900923 private class MockIpClientCallback extends IpClientCallbacksWrapper {
Paul Jensen9132f342016-04-13 15:00:26 -0400924 private final ConditionVariable mGotApfProgram = new ConditionVariable();
925 private byte[] mLastApfProgram;
926
Remi NGUYEN VAN3c600a12019-01-10 19:12:46 +0900927 MockIpClientCallback() {
928 super(mock(IIpClientCallbacks.class), mock(SharedLog.class));
929 }
930
Paul Jensen9132f342016-04-13 15:00:26 -0400931 @Override
932 public void installPacketFilter(byte[] filter) {
933 mLastApfProgram = filter;
934 mGotApfProgram.open();
935 }
936
937 public void resetApfProgramWait() {
938 mGotApfProgram.close();
939 }
940
941 public byte[] getApfProgram() {
942 assertTrue(mGotApfProgram.block(TIMEOUT_MS));
943 return mLastApfProgram;
944 }
Lorenzo Colitti8995d852016-06-23 15:24:46 +0900945
946 public void assertNoProgramUpdate() {
947 assertFalse(mGotApfProgram.block(TIMEOUT_MS));
948 }
Paul Jensen9132f342016-04-13 15:00:26 -0400949 }
950
951 private static class TestApfFilter extends ApfFilter {
Bernie Innocenti3d479d92018-04-20 23:31:33 +0900952 public static final byte[] MOCK_MAC_ADDR = {1,2,3,4,5,6};
Paul Jensen9132f342016-04-13 15:00:26 -0400953
Hugo Benichi72166362017-10-13 16:32:20 +0900954 private FileDescriptor mWriteSocket;
Hugo Benichi4456f332016-12-19 14:50:52 +0900955 private final long mFixedTimeMs = SystemClock.elapsedRealtime();
956
Bernie Innocentie2c70f82018-03-28 20:11:49 +0900957 public TestApfFilter(Context context, ApfConfiguration config,
Remi NGUYEN VAN3c600a12019-01-10 19:12:46 +0900958 IpClientCallbacksWrapper ipClientCallback, IpConnectivityLog log) throws Exception {
Erik Kline8d1fe542018-03-12 23:18:58 +0900959 super(context, config, InterfaceParams.getByName("lo"), ipClientCallback, log);
Paul Jensen9132f342016-04-13 15:00:26 -0400960 }
961
962 // Pretend an RA packet has been received and show it to ApfFilter.
963 public void pretendPacketReceived(byte[] packet) throws IOException, ErrnoException {
964 // ApfFilter's ReceiveThread will be waiting to read this.
965 Os.write(mWriteSocket, packet, 0, packet.length);
966 }
967
968 @Override
Hugo Benichi4456f332016-12-19 14:50:52 +0900969 protected long currentTimeSeconds() {
970 return mFixedTimeMs / DateUtils.SECOND_IN_MILLIS;
971 }
972
973 @Override
Paul Jensen9132f342016-04-13 15:00:26 -0400974 void maybeStartFilter() {
975 mHardwareAddress = MOCK_MAC_ADDR;
976 installNewProgramLocked();
977
978 // Create two sockets, "readSocket" and "mWriteSocket" and connect them together.
979 FileDescriptor readSocket = new FileDescriptor();
980 mWriteSocket = new FileDescriptor();
981 try {
982 Os.socketpair(AF_UNIX, SOCK_STREAM, 0, mWriteSocket, readSocket);
983 } catch (ErrnoException e) {
984 fail();
985 return;
986 }
987 // Now pass readSocket to ReceiveThread as if it was setup to read raw RAs.
988 // This allows us to pretend RA packets have been recieved via pretendPacketReceived().
989 mReceiveThread = new ReceiveThread(readSocket);
990 mReceiveThread.start();
991 }
992
993 @Override
994 public void shutdown() {
995 super.shutdown();
996 IoUtils.closeQuietly(mWriteSocket);
997 }
998 }
999
1000 private static final int ETH_HEADER_LEN = 14;
Hugo Benichi38db9762016-07-12 15:08:50 +09001001 private static final int ETH_DEST_ADDR_OFFSET = 0;
Paul Jensen9132f342016-04-13 15:00:26 -04001002 private static final int ETH_ETHERTYPE_OFFSET = 12;
Hugo Benichi961ca492016-09-02 11:04:34 +09001003 private static final byte[] ETH_BROADCAST_MAC_ADDRESS =
1004 {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff };
Paul Jensen9132f342016-04-13 15:00:26 -04001005
Aaron Huanga63c40e2019-01-15 16:53:51 +08001006 private static final int IPV4_HEADER_LEN = 20;
Paul Jensen9132f342016-04-13 15:00:26 -04001007 private static final int IPV4_VERSION_IHL_OFFSET = ETH_HEADER_LEN + 0;
Aaron Huanga63c40e2019-01-15 16:53:51 +08001008 private static final int IPV4_TOTAL_LENGTH_OFFSET = ETH_HEADER_LEN + 2;
Paul Jensen9132f342016-04-13 15:00:26 -04001009 private static final int IPV4_PROTOCOL_OFFSET = ETH_HEADER_LEN + 9;
Aaron Huanga63c40e2019-01-15 16:53:51 +08001010 private static final int IPV4_SRC_ADDR_OFFSET = ETH_HEADER_LEN + 12;
Paul Jensen9132f342016-04-13 15:00:26 -04001011 private static final int IPV4_DEST_ADDR_OFFSET = ETH_HEADER_LEN + 16;
Aaron Huanga63c40e2019-01-15 16:53:51 +08001012 private static final int IPV4_TCP_HEADER_LEN = 20;
1013 private static final int IPV4_TCP_HEADER_OFFSET = ETH_HEADER_LEN + IPV4_HEADER_LEN;
1014 private static final int IPV4_TCP_SRC_PORT_OFFSET = IPV4_TCP_HEADER_OFFSET + 0;
1015 private static final int IPV4_TCP_DEST_PORT_OFFSET = IPV4_TCP_HEADER_OFFSET + 2;
1016 private static final int IPV4_TCP_SEQ_NUM_OFFSET = IPV4_TCP_HEADER_OFFSET + 4;
1017 private static final int IPV4_TCP_ACK_NUM_OFFSET = IPV4_TCP_HEADER_OFFSET + 8;
1018 private static final int IPV4_TCP_HEADER_LENGTH_OFFSET = IPV4_TCP_HEADER_OFFSET + 12;
Xiao Mad36a89c2019-02-10 14:52:37 +09001019 private static final int IPV4_TCP_HEADER_FLAG_OFFSET = IPV4_TCP_HEADER_OFFSET + 13;
Hugo Benichi961ca492016-09-02 11:04:34 +09001020 private static final byte[] IPV4_BROADCAST_ADDRESS =
1021 {(byte) 255, (byte) 255, (byte) 255, (byte) 255};
Paul Jensen9132f342016-04-13 15:00:26 -04001022
1023 private static final int IPV6_NEXT_HEADER_OFFSET = ETH_HEADER_LEN + 6;
1024 private static final int IPV6_HEADER_LEN = 40;
Aaron Huanga63c40e2019-01-15 16:53:51 +08001025 private static final int IPV6_SRC_ADDR_OFFSET = ETH_HEADER_LEN + 8;
Paul Jensen9132f342016-04-13 15:00:26 -04001026 private static final int IPV6_DEST_ADDR_OFFSET = ETH_HEADER_LEN + 24;
Aaron Huanga63c40e2019-01-15 16:53:51 +08001027 private static final int IPV6_TCP_HEADER_OFFSET = ETH_HEADER_LEN + IPV6_HEADER_LEN;
1028 private static final int IPV6_TCP_SRC_PORT_OFFSET = IPV6_TCP_HEADER_OFFSET + 0;
1029 private static final int IPV6_TCP_DEST_PORT_OFFSET = IPV6_TCP_HEADER_OFFSET + 2;
1030 private static final int IPV6_TCP_SEQ_NUM_OFFSET = IPV6_TCP_HEADER_OFFSET + 4;
1031 private static final int IPV6_TCP_ACK_NUM_OFFSET = IPV6_TCP_HEADER_OFFSET + 8;
Paul Jensen9132f342016-04-13 15:00:26 -04001032 // The IPv6 all nodes address ff02::1
1033 private static final byte[] IPV6_ALL_NODES_ADDRESS =
Hugo Benichi961ca492016-09-02 11:04:34 +09001034 { (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
Hugo Benichi02428982016-12-03 02:41:05 +09001035 private static final byte[] IPV6_ALL_ROUTERS_ADDRESS =
1036 { (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 };
Paul Jensen9132f342016-04-13 15:00:26 -04001037
1038 private static final int ICMP6_TYPE_OFFSET = ETH_HEADER_LEN + IPV6_HEADER_LEN;
Hugo Benichi02428982016-12-03 02:41:05 +09001039 private static final int ICMP6_ROUTER_SOLICITATION = 133;
Paul Jensen9132f342016-04-13 15:00:26 -04001040 private static final int ICMP6_ROUTER_ADVERTISEMENT = 134;
Hugo Benichi02428982016-12-03 02:41:05 +09001041 private static final int ICMP6_NEIGHBOR_SOLICITATION = 135;
Paul Jensen9132f342016-04-13 15:00:26 -04001042 private static final int ICMP6_NEIGHBOR_ANNOUNCEMENT = 136;
1043
1044 private static final int ICMP6_RA_HEADER_LEN = 16;
1045 private static final int ICMP6_RA_ROUTER_LIFETIME_OFFSET =
1046 ETH_HEADER_LEN + IPV6_HEADER_LEN + 6;
1047 private static final int ICMP6_RA_CHECKSUM_OFFSET =
1048 ETH_HEADER_LEN + IPV6_HEADER_LEN + 2;
1049 private static final int ICMP6_RA_OPTION_OFFSET =
1050 ETH_HEADER_LEN + IPV6_HEADER_LEN + ICMP6_RA_HEADER_LEN;
1051
1052 private static final int ICMP6_PREFIX_OPTION_TYPE = 3;
1053 private static final int ICMP6_PREFIX_OPTION_LEN = 32;
1054 private static final int ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET = 4;
1055 private static final int ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_OFFSET = 8;
1056
1057 // From RFC6106: Recursive DNS Server option
1058 private static final int ICMP6_RDNSS_OPTION_TYPE = 25;
1059 // From RFC6106: DNS Search List option
1060 private static final int ICMP6_DNSSL_OPTION_TYPE = 31;
1061
1062 // From RFC4191: Route Information option
1063 private static final int ICMP6_ROUTE_INFO_OPTION_TYPE = 24;
1064 // Above three options all have the same format:
1065 private static final int ICMP6_4_BYTE_OPTION_LEN = 8;
1066 private static final int ICMP6_4_BYTE_LIFETIME_OFFSET = 4;
1067 private static final int ICMP6_4_BYTE_LIFETIME_LEN = 4;
1068
1069 private static final int UDP_HEADER_LEN = 8;
1070 private static final int UDP_DESTINATION_PORT_OFFSET = ETH_HEADER_LEN + 22;
1071
1072 private static final int DHCP_CLIENT_PORT = 68;
1073 private static final int DHCP_CLIENT_MAC_OFFSET = ETH_HEADER_LEN + UDP_HEADER_LEN + 48;
1074
Hugo Benichi4fc3ee52016-06-02 11:20:27 +09001075 private static final int ARP_HEADER_OFFSET = ETH_HEADER_LEN;
Hugo Benichi961ca492016-09-02 11:04:34 +09001076 private static final byte[] ARP_IPV4_REQUEST_HEADER = {
Paul Jensen9132f342016-04-13 15:00:26 -04001077 0, 1, // Hardware type: Ethernet (1)
1078 8, 0, // Protocol type: IP (0x0800)
1079 6, // Hardware size: 6
1080 4, // Protocol size: 4
1081 0, 1 // Opcode: request (1)
1082 };
Hugo Benichi961ca492016-09-02 11:04:34 +09001083 private static final byte[] ARP_IPV4_REPLY_HEADER = {
Hugo Benichi38db9762016-07-12 15:08:50 +09001084 0, 1, // Hardware type: Ethernet (1)
1085 8, 0, // Protocol type: IP (0x0800)
1086 6, // Hardware size: 6
1087 4, // Protocol size: 4
1088 0, 2 // Opcode: reply (2)
1089 };
Aaron Huang04ed6a32018-11-15 20:30:46 +08001090 private static final int ARP_SOURCE_IP_ADDRESS_OFFSET = ARP_HEADER_OFFSET + 14;
1091 private static final int ARP_TARGET_IP_ADDRESS_OFFSET = ARP_HEADER_OFFSET + 24;
Paul Jensen9132f342016-04-13 15:00:26 -04001092
Hugo Benichi961ca492016-09-02 11:04:34 +09001093 private static final byte[] MOCK_IPV4_ADDR = {10, 0, 0, 1};
Hugo Benichi7d21eae2016-09-02 14:00:29 +09001094 private static final byte[] MOCK_BROADCAST_IPV4_ADDR = {10, 0, 31, (byte) 255}; // prefix = 19
Hugo Benichi961ca492016-09-02 11:04:34 +09001095 private static final byte[] MOCK_MULTICAST_IPV4_ADDR = {(byte) 224, 0, 0, 1};
1096 private static final byte[] ANOTHER_IPV4_ADDR = {10, 0, 0, 2};
Aaron Huang04ed6a32018-11-15 20:30:46 +08001097 private static final byte[] IPV4_SOURCE_ADDR = {10, 0, 0, 3};
1098 private static final byte[] ANOTHER_IPV4_SOURCE_ADDR = {(byte) 192, 0, 2, 1};
1099 private static final byte[] BUG_PROBE_SOURCE_ADDR1 = {0, 0, 1, 2};
1100 private static final byte[] BUG_PROBE_SOURCE_ADDR2 = {3, 4, 0, 0};
Hugo Benichi961ca492016-09-02 11:04:34 +09001101 private static final byte[] IPV4_ANY_HOST_ADDR = {0, 0, 0, 0};
Paul Jensen9132f342016-04-13 15:00:26 -04001102
Bernie Innocentie2c70f82018-03-28 20:11:49 +09001103 // Helper to initialize a default apfFilter.
Remi NGUYEN VAN3c600a12019-01-10 19:12:46 +09001104 private ApfFilter setupApfFilter(
1105 IpClientCallbacksWrapper ipClientCallback, ApfConfiguration config) throws Exception {
Bernie Innocentie2c70f82018-03-28 20:11:49 +09001106 LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19);
1107 LinkProperties lp = new LinkProperties();
1108 lp.addLinkAddress(link);
Erik Kline8d1fe542018-03-12 23:18:58 +09001109 TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
Bernie Innocentie2c70f82018-03-28 20:11:49 +09001110 apfFilter.setLinkProperties(lp);
1111 return apfFilter;
1112 }
1113
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001114 @Test
Paul Jensen9132f342016-04-13 15:00:26 -04001115 public void testApfFilterIPv4() throws Exception {
Erik Kline8d1fe542018-03-12 23:18:58 +09001116 MockIpClientCallback ipClientCallback = new MockIpClientCallback();
Hugo Benichi7d21eae2016-09-02 14:00:29 +09001117 LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19);
1118 LinkProperties lp = new LinkProperties();
1119 lp.addLinkAddress(link);
Hugo Benichi0dc1d312016-09-02 12:40:31 +09001120
Hugo Benichi72166362017-10-13 16:32:20 +09001121 ApfConfiguration config = getDefaultConfig();
1122 config.multicastFilter = DROP_MULTICAST;
Erik Kline8d1fe542018-03-12 23:18:58 +09001123 TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
Hugo Benichi7d21eae2016-09-02 14:00:29 +09001124 apfFilter.setLinkProperties(lp);
Hugo Benichi0dc1d312016-09-02 12:40:31 +09001125
Erik Kline8d1fe542018-03-12 23:18:58 +09001126 byte[] program = ipClientCallback.getApfProgram();
Paul Jensen9132f342016-04-13 15:00:26 -04001127
1128 // Verify empty packet of 100 zero bytes is passed
1129 ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
Hugo Benichi961ca492016-09-02 11:04:34 +09001130 assertPass(program, packet.array());
Paul Jensen9132f342016-04-13 15:00:26 -04001131
1132 // Verify unicast IPv4 packet is passed
Hugo Benichi961ca492016-09-02 11:04:34 +09001133 put(packet, ETH_DEST_ADDR_OFFSET, TestApfFilter.MOCK_MAC_ADDR);
Paul Jensen9132f342016-04-13 15:00:26 -04001134 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
Hugo Benichi961ca492016-09-02 11:04:34 +09001135 put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_IPV4_ADDR);
1136 assertPass(program, packet.array());
Paul Jensen9132f342016-04-13 15:00:26 -04001137
Hugo Benichi0dc1d312016-09-02 12:40:31 +09001138 // Verify L2 unicast to IPv4 broadcast addresses is dropped (b/30231088)
Hugo Benichi961ca492016-09-02 11:04:34 +09001139 put(packet, IPV4_DEST_ADDR_OFFSET, IPV4_BROADCAST_ADDRESS);
Hugo Benichi0dc1d312016-09-02 12:40:31 +09001140 assertDrop(program, packet.array());
Hugo Benichi961ca492016-09-02 11:04:34 +09001141 put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_BROADCAST_IPV4_ADDR);
Hugo Benichi7d21eae2016-09-02 14:00:29 +09001142 assertDrop(program, packet.array());
Hugo Benichi961ca492016-09-02 11:04:34 +09001143
1144 // Verify multicast/broadcast IPv4, not DHCP to us, is dropped
1145 put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS);
1146 assertDrop(program, packet.array());
Paul Jensen9132f342016-04-13 15:00:26 -04001147 packet.put(IPV4_VERSION_IHL_OFFSET, (byte)0x45);
Hugo Benichi961ca492016-09-02 11:04:34 +09001148 assertDrop(program, packet.array());
Paul Jensen9132f342016-04-13 15:00:26 -04001149 packet.put(IPV4_PROTOCOL_OFFSET, (byte)IPPROTO_UDP);
Hugo Benichi961ca492016-09-02 11:04:34 +09001150 assertDrop(program, packet.array());
Paul Jensen9132f342016-04-13 15:00:26 -04001151 packet.putShort(UDP_DESTINATION_PORT_OFFSET, (short)DHCP_CLIENT_PORT);
Hugo Benichi961ca492016-09-02 11:04:34 +09001152 assertDrop(program, packet.array());
1153 put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_MULTICAST_IPV4_ADDR);
1154 assertDrop(program, packet.array());
1155 put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_BROADCAST_IPV4_ADDR);
1156 assertDrop(program, packet.array());
1157 put(packet, IPV4_DEST_ADDR_OFFSET, IPV4_BROADCAST_ADDRESS);
1158 assertDrop(program, packet.array());
Paul Jensen9132f342016-04-13 15:00:26 -04001159
1160 // Verify broadcast IPv4 DHCP to us is passed
Hugo Benichi961ca492016-09-02 11:04:34 +09001161 put(packet, DHCP_CLIENT_MAC_OFFSET, TestApfFilter.MOCK_MAC_ADDR);
1162 assertPass(program, packet.array());
1163
1164 // Verify unicast IPv4 DHCP to us is passed
1165 put(packet, ETH_DEST_ADDR_OFFSET, TestApfFilter.MOCK_MAC_ADDR);
1166 assertPass(program, packet.array());
Paul Jensen9132f342016-04-13 15:00:26 -04001167
1168 apfFilter.shutdown();
1169 }
1170
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001171 @Test
Paul Jensen9132f342016-04-13 15:00:26 -04001172 public void testApfFilterIPv6() throws Exception {
Erik Kline8d1fe542018-03-12 23:18:58 +09001173 MockIpClientCallback ipClientCallback = new MockIpClientCallback();
Hugo Benichi72166362017-10-13 16:32:20 +09001174 ApfConfiguration config = getDefaultConfig();
Erik Kline8d1fe542018-03-12 23:18:58 +09001175 TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
1176 byte[] program = ipClientCallback.getApfProgram();
Paul Jensen9132f342016-04-13 15:00:26 -04001177
1178 // Verify empty IPv6 packet is passed
1179 ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
1180 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
Hugo Benichi961ca492016-09-02 11:04:34 +09001181 assertPass(program, packet.array());
Paul Jensen9132f342016-04-13 15:00:26 -04001182
1183 // Verify empty ICMPv6 packet is passed
1184 packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6);
Hugo Benichi961ca492016-09-02 11:04:34 +09001185 assertPass(program, packet.array());
Paul Jensen9132f342016-04-13 15:00:26 -04001186
1187 // Verify empty ICMPv6 NA packet is passed
1188 packet.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_NEIGHBOR_ANNOUNCEMENT);
Hugo Benichi961ca492016-09-02 11:04:34 +09001189 assertPass(program, packet.array());
Paul Jensen9132f342016-04-13 15:00:26 -04001190
1191 // Verify ICMPv6 NA to ff02::1 is dropped
Hugo Benichi961ca492016-09-02 11:04:34 +09001192 put(packet, IPV6_DEST_ADDR_OFFSET, IPV6_ALL_NODES_ADDRESS);
1193 assertDrop(program, packet.array());
Paul Jensen9132f342016-04-13 15:00:26 -04001194
Hugo Benichi02428982016-12-03 02:41:05 +09001195 // Verify ICMPv6 RS to any is dropped
1196 packet.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_ROUTER_SOLICITATION);
1197 assertDrop(program, packet.array());
1198 put(packet, IPV6_DEST_ADDR_OFFSET, IPV6_ALL_ROUTERS_ADDRESS);
1199 assertDrop(program, packet.array());
1200
Paul Jensen9132f342016-04-13 15:00:26 -04001201 apfFilter.shutdown();
1202 }
1203
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001204 @Test
Lorenzo Colitti11e13e22016-05-20 00:04:43 +09001205 public void testApfFilterMulticast() throws Exception {
Hugo Benichi961ca492016-09-02 11:04:34 +09001206 final byte[] unicastIpv4Addr = {(byte)192,0,2,63};
Hugo Benichi7d21eae2016-09-02 14:00:29 +09001207 final byte[] broadcastIpv4Addr = {(byte)192,0,2,(byte)255};
Hugo Benichi961ca492016-09-02 11:04:34 +09001208 final byte[] multicastIpv4Addr = {(byte)224,0,0,1};
1209 final byte[] multicastIpv6Addr = {(byte)0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,(byte)0xfb};
1210
Erik Kline8d1fe542018-03-12 23:18:58 +09001211 MockIpClientCallback ipClientCallback = new MockIpClientCallback();
Hugo Benichi7d21eae2016-09-02 14:00:29 +09001212 LinkAddress link = new LinkAddress(InetAddress.getByAddress(unicastIpv4Addr), 24);
1213 LinkProperties lp = new LinkProperties();
1214 lp.addLinkAddress(link);
1215
Hugo Benichi72166362017-10-13 16:32:20 +09001216 ApfConfiguration config = getDefaultConfig();
1217 config.ieee802_3Filter = DROP_802_3_FRAMES;
Erik Kline8d1fe542018-03-12 23:18:58 +09001218 TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
Hugo Benichi7d21eae2016-09-02 14:00:29 +09001219 apfFilter.setLinkProperties(lp);
1220
Erik Kline8d1fe542018-03-12 23:18:58 +09001221 byte[] program = ipClientCallback.getApfProgram();
Hugo Benichi7d21eae2016-09-02 14:00:29 +09001222
Lorenzo Colitti11e13e22016-05-20 00:04:43 +09001223 // Construct IPv4 and IPv6 multicast packets.
Paul Jensenf8a01e82016-05-26 09:16:11 -04001224 ByteBuffer mcastv4packet = ByteBuffer.wrap(new byte[100]);
1225 mcastv4packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
Hugo Benichi961ca492016-09-02 11:04:34 +09001226 put(mcastv4packet, IPV4_DEST_ADDR_OFFSET, multicastIpv4Addr);
Lorenzo Colitti11e13e22016-05-20 00:04:43 +09001227
Paul Jensenf8a01e82016-05-26 09:16:11 -04001228 ByteBuffer mcastv6packet = ByteBuffer.wrap(new byte[100]);
1229 mcastv6packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
1230 mcastv6packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_UDP);
Hugo Benichi961ca492016-09-02 11:04:34 +09001231 put(mcastv6packet, IPV6_DEST_ADDR_OFFSET, multicastIpv6Addr);
Paul Jensenf8a01e82016-05-26 09:16:11 -04001232
1233 // Construct IPv4 broadcast packet.
Hugo Benichi961ca492016-09-02 11:04:34 +09001234 ByteBuffer bcastv4packet1 = ByteBuffer.wrap(new byte[100]);
1235 bcastv4packet1.put(ETH_BROADCAST_MAC_ADDRESS);
1236 bcastv4packet1.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
1237 put(bcastv4packet1, IPV4_DEST_ADDR_OFFSET, multicastIpv4Addr);
1238
1239 ByteBuffer bcastv4packet2 = ByteBuffer.wrap(new byte[100]);
1240 bcastv4packet2.put(ETH_BROADCAST_MAC_ADDRESS);
1241 bcastv4packet2.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
1242 put(bcastv4packet2, IPV4_DEST_ADDR_OFFSET, IPV4_BROADCAST_ADDRESS);
1243
1244 // Construct IPv4 broadcast with L2 unicast address packet (b/30231088).
1245 ByteBuffer bcastv4unicastl2packet = ByteBuffer.wrap(new byte[100]);
1246 bcastv4unicastl2packet.put(TestApfFilter.MOCK_MAC_ADDR);
1247 bcastv4unicastl2packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
1248 put(bcastv4unicastl2packet, IPV4_DEST_ADDR_OFFSET, broadcastIpv4Addr);
Lorenzo Colitti11e13e22016-05-20 00:04:43 +09001249
Paul Jensen9132f342016-04-13 15:00:26 -04001250 // Verify initially disabled multicast filter is off
Hugo Benichi961ca492016-09-02 11:04:34 +09001251 assertPass(program, mcastv4packet.array());
1252 assertPass(program, mcastv6packet.array());
1253 assertPass(program, bcastv4packet1.array());
1254 assertPass(program, bcastv4packet2.array());
1255 assertPass(program, bcastv4unicastl2packet.array());
Paul Jensen9132f342016-04-13 15:00:26 -04001256
1257 // Turn on multicast filter and verify it works
Erik Kline8d1fe542018-03-12 23:18:58 +09001258 ipClientCallback.resetApfProgramWait();
Paul Jensen9132f342016-04-13 15:00:26 -04001259 apfFilter.setMulticastFilter(true);
Erik Kline8d1fe542018-03-12 23:18:58 +09001260 program = ipClientCallback.getApfProgram();
Hugo Benichi961ca492016-09-02 11:04:34 +09001261 assertDrop(program, mcastv4packet.array());
1262 assertDrop(program, mcastv6packet.array());
1263 assertDrop(program, bcastv4packet1.array());
1264 assertDrop(program, bcastv4packet2.array());
Hugo Benichi7d21eae2016-09-02 14:00:29 +09001265 assertDrop(program, bcastv4unicastl2packet.array());
Paul Jensen9132f342016-04-13 15:00:26 -04001266
1267 // Turn off multicast filter and verify it's off
Erik Kline8d1fe542018-03-12 23:18:58 +09001268 ipClientCallback.resetApfProgramWait();
Paul Jensen9132f342016-04-13 15:00:26 -04001269 apfFilter.setMulticastFilter(false);
Erik Kline8d1fe542018-03-12 23:18:58 +09001270 program = ipClientCallback.getApfProgram();
Hugo Benichi961ca492016-09-02 11:04:34 +09001271 assertPass(program, mcastv4packet.array());
1272 assertPass(program, mcastv6packet.array());
1273 assertPass(program, bcastv4packet1.array());
1274 assertPass(program, bcastv4packet2.array());
1275 assertPass(program, bcastv4unicastl2packet.array());
Paul Jensen9132f342016-04-13 15:00:26 -04001276
1277 // Verify it can be initialized to on
Erik Kline8d1fe542018-03-12 23:18:58 +09001278 ipClientCallback.resetApfProgramWait();
Paul Jensen9132f342016-04-13 15:00:26 -04001279 apfFilter.shutdown();
Hugo Benichi72166362017-10-13 16:32:20 +09001280 config.multicastFilter = DROP_MULTICAST;
1281 config.ieee802_3Filter = DROP_802_3_FRAMES;
Erik Kline8d1fe542018-03-12 23:18:58 +09001282 apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
Hugo Benichi7d21eae2016-09-02 14:00:29 +09001283 apfFilter.setLinkProperties(lp);
Erik Kline8d1fe542018-03-12 23:18:58 +09001284 program = ipClientCallback.getApfProgram();
Hugo Benichi961ca492016-09-02 11:04:34 +09001285 assertDrop(program, mcastv4packet.array());
1286 assertDrop(program, mcastv6packet.array());
1287 assertDrop(program, bcastv4packet1.array());
Hugo Benichi7d21eae2016-09-02 14:00:29 +09001288 assertDrop(program, bcastv4unicastl2packet.array());
Lorenzo Colitti11e13e22016-05-20 00:04:43 +09001289
1290 // Verify that ICMPv6 multicast is not dropped.
Paul Jensenf8a01e82016-05-26 09:16:11 -04001291 mcastv6packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6);
Hugo Benichi961ca492016-09-02 11:04:34 +09001292 assertPass(program, mcastv6packet.array());
Paul Jensen9132f342016-04-13 15:00:26 -04001293
1294 apfFilter.shutdown();
1295 }
1296
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001297 @Test
Bernie Innocentie2c70f82018-03-28 20:11:49 +09001298 public void testApfFilterMulticastPingWhileDozing() throws Exception {
Erik Kline8d1fe542018-03-12 23:18:58 +09001299 MockIpClientCallback ipClientCallback = new MockIpClientCallback();
1300 ApfFilter apfFilter = setupApfFilter(ipClientCallback, getDefaultConfig());
Bernie Innocentie2c70f82018-03-28 20:11:49 +09001301
1302 // Construct a multicast ICMPv6 ECHO request.
1303 final byte[] multicastIpv6Addr = {(byte)0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,(byte)0xfb};
1304 ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
1305 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
1306 packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6);
1307 packet.put(ICMP6_TYPE_OFFSET, (byte)ICMPV6_ECHO_REQUEST_TYPE);
1308 put(packet, IPV6_DEST_ADDR_OFFSET, multicastIpv6Addr);
1309
1310 // Normally, we let multicast pings alone...
Erik Kline8d1fe542018-03-12 23:18:58 +09001311 assertPass(ipClientCallback.getApfProgram(), packet.array());
Bernie Innocentie2c70f82018-03-28 20:11:49 +09001312
1313 // ...and even while dozing...
1314 apfFilter.setDozeMode(true);
Erik Kline8d1fe542018-03-12 23:18:58 +09001315 assertPass(ipClientCallback.getApfProgram(), packet.array());
Bernie Innocentie2c70f82018-03-28 20:11:49 +09001316
1317 // ...but when the multicast filter is also enabled, drop the multicast pings to save power.
1318 apfFilter.setMulticastFilter(true);
Erik Kline8d1fe542018-03-12 23:18:58 +09001319 assertDrop(ipClientCallback.getApfProgram(), packet.array());
Bernie Innocentie2c70f82018-03-28 20:11:49 +09001320
1321 // However, we should still let through all other ICMPv6 types.
1322 ByteBuffer raPacket = ByteBuffer.wrap(packet.array().clone());
Remi NGUYEN VAN3c600a12019-01-10 19:12:46 +09001323 raPacket.put(ICMP6_TYPE_OFFSET, (byte) NetworkStackConstants.ICMPV6_ROUTER_ADVERTISEMENT);
Erik Kline8d1fe542018-03-12 23:18:58 +09001324 assertPass(ipClientCallback.getApfProgram(), raPacket.array());
Bernie Innocentie2c70f82018-03-28 20:11:49 +09001325
1326 // Now wake up from doze mode to ensure that we no longer drop the packets.
1327 // (The multicast filter is still enabled at this point).
1328 apfFilter.setDozeMode(false);
Erik Kline8d1fe542018-03-12 23:18:58 +09001329 assertPass(ipClientCallback.getApfProgram(), packet.array());
Bernie Innocentie2c70f82018-03-28 20:11:49 +09001330
1331 apfFilter.shutdown();
1332 }
1333
1334 @Test
Ahmed ElArabawy8537c582017-06-12 18:01:11 -07001335 public void testApfFilter802_3() throws Exception {
Erik Kline8d1fe542018-03-12 23:18:58 +09001336 MockIpClientCallback ipClientCallback = new MockIpClientCallback();
Hugo Benichi72166362017-10-13 16:32:20 +09001337 ApfConfiguration config = getDefaultConfig();
Erik Kline8d1fe542018-03-12 23:18:58 +09001338 ApfFilter apfFilter = setupApfFilter(ipClientCallback, config);
1339 byte[] program = ipClientCallback.getApfProgram();
Ahmed ElArabawy8537c582017-06-12 18:01:11 -07001340
1341 // Verify empty packet of 100 zero bytes is passed
1342 // Note that eth-type = 0 makes it an IEEE802.3 frame
1343 ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
1344 assertPass(program, packet.array());
1345
1346 // Verify empty packet with IPv4 is passed
1347 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
1348 assertPass(program, packet.array());
1349
1350 // Verify empty IPv6 packet is passed
1351 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
1352 assertPass(program, packet.array());
1353
1354 // Now turn on the filter
Erik Kline8d1fe542018-03-12 23:18:58 +09001355 ipClientCallback.resetApfProgramWait();
Ahmed ElArabawy8537c582017-06-12 18:01:11 -07001356 apfFilter.shutdown();
Hugo Benichi72166362017-10-13 16:32:20 +09001357 config.ieee802_3Filter = DROP_802_3_FRAMES;
Erik Kline8d1fe542018-03-12 23:18:58 +09001358 apfFilter = setupApfFilter(ipClientCallback, config);
1359 program = ipClientCallback.getApfProgram();
Ahmed ElArabawy8537c582017-06-12 18:01:11 -07001360
1361 // Verify that IEEE802.3 frame is dropped
1362 // In this case ethtype is used for payload length
1363 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)(100 - 14));
1364 assertDrop(program, packet.array());
1365
1366 // Verify that IPv4 (as example of Ethernet II) frame will pass
1367 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
1368 assertPass(program, packet.array());
1369
1370 // Verify that IPv6 (as example of Ethernet II) frame will pass
1371 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
1372 assertPass(program, packet.array());
1373
1374 apfFilter.shutdown();
1375 }
1376
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001377 @Test
Ahmed ElArabawyfd424162017-08-02 13:31:05 -07001378 public void testApfFilterEthTypeBL() throws Exception {
Ahmed ElArabawyfd424162017-08-02 13:31:05 -07001379 final int[] emptyBlackList = {};
1380 final int[] ipv4BlackList = {ETH_P_IP};
1381 final int[] ipv4Ipv6BlackList = {ETH_P_IP, ETH_P_IPV6};
1382
Erik Kline8d1fe542018-03-12 23:18:58 +09001383 MockIpClientCallback ipClientCallback = new MockIpClientCallback();
Hugo Benichi72166362017-10-13 16:32:20 +09001384 ApfConfiguration config = getDefaultConfig();
Erik Kline8d1fe542018-03-12 23:18:58 +09001385 ApfFilter apfFilter = setupApfFilter(ipClientCallback, config);
1386 byte[] program = ipClientCallback.getApfProgram();
Ahmed ElArabawyfd424162017-08-02 13:31:05 -07001387
1388 // Verify empty packet of 100 zero bytes is passed
1389 // Note that eth-type = 0 makes it an IEEE802.3 frame
1390 ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
1391 assertPass(program, packet.array());
1392
1393 // Verify empty packet with IPv4 is passed
1394 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
1395 assertPass(program, packet.array());
1396
1397 // Verify empty IPv6 packet is passed
1398 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
1399 assertPass(program, packet.array());
1400
1401 // Now add IPv4 to the black list
Erik Kline8d1fe542018-03-12 23:18:58 +09001402 ipClientCallback.resetApfProgramWait();
Ahmed ElArabawyfd424162017-08-02 13:31:05 -07001403 apfFilter.shutdown();
Hugo Benichi72166362017-10-13 16:32:20 +09001404 config.ethTypeBlackList = ipv4BlackList;
Erik Kline8d1fe542018-03-12 23:18:58 +09001405 apfFilter = setupApfFilter(ipClientCallback, config);
1406 program = ipClientCallback.getApfProgram();
Ahmed ElArabawyfd424162017-08-02 13:31:05 -07001407
1408 // Verify that IPv4 frame will be dropped
1409 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
1410 assertDrop(program, packet.array());
1411
1412 // Verify that IPv6 frame will pass
1413 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
1414 assertPass(program, packet.array());
1415
1416 // Now let us have both IPv4 and IPv6 in the black list
Erik Kline8d1fe542018-03-12 23:18:58 +09001417 ipClientCallback.resetApfProgramWait();
Ahmed ElArabawyfd424162017-08-02 13:31:05 -07001418 apfFilter.shutdown();
Hugo Benichi72166362017-10-13 16:32:20 +09001419 config.ethTypeBlackList = ipv4Ipv6BlackList;
Erik Kline8d1fe542018-03-12 23:18:58 +09001420 apfFilter = setupApfFilter(ipClientCallback, config);
1421 program = ipClientCallback.getApfProgram();
Ahmed ElArabawyfd424162017-08-02 13:31:05 -07001422
1423 // Verify that IPv4 frame will be dropped
1424 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
1425 assertDrop(program, packet.array());
1426
1427 // Verify that IPv6 frame will be dropped
1428 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
1429 assertDrop(program, packet.array());
1430
1431 apfFilter.shutdown();
1432 }
1433
Erik Kline8d1fe542018-03-12 23:18:58 +09001434 private byte[] getProgram(MockIpClientCallback cb, ApfFilter filter, LinkProperties lp) {
Hugo Benichi38db9762016-07-12 15:08:50 +09001435 cb.resetApfProgramWait();
1436 filter.setLinkProperties(lp);
1437 return cb.getApfProgram();
1438 }
1439
1440 private void verifyArpFilter(byte[] program, int filterResult) {
1441 // Verify ARP request packet
Hugo Benichi961ca492016-09-02 11:04:34 +09001442 assertPass(program, arpRequestBroadcast(MOCK_IPV4_ADDR));
1443 assertVerdict(filterResult, program, arpRequestBroadcast(ANOTHER_IPV4_ADDR));
1444 assertDrop(program, arpRequestBroadcast(IPV4_ANY_HOST_ADDR));
Hugo Benichi38db9762016-07-12 15:08:50 +09001445
Aaron Huang04ed6a32018-11-15 20:30:46 +08001446 // Verify ARP reply packets from different source ip
1447 assertDrop(program, arpReply(IPV4_ANY_HOST_ADDR, IPV4_ANY_HOST_ADDR));
1448 assertPass(program, arpReply(ANOTHER_IPV4_SOURCE_ADDR, IPV4_ANY_HOST_ADDR));
1449 assertPass(program, arpReply(BUG_PROBE_SOURCE_ADDR1, IPV4_ANY_HOST_ADDR));
1450 assertPass(program, arpReply(BUG_PROBE_SOURCE_ADDR2, IPV4_ANY_HOST_ADDR));
1451
Hugo Benichi38db9762016-07-12 15:08:50 +09001452 // Verify unicast ARP reply packet is always accepted.
Aaron Huang04ed6a32018-11-15 20:30:46 +08001453 assertPass(program, arpReply(IPV4_SOURCE_ADDR, MOCK_IPV4_ADDR));
1454 assertPass(program, arpReply(IPV4_SOURCE_ADDR, ANOTHER_IPV4_ADDR));
1455 assertPass(program, arpReply(IPV4_SOURCE_ADDR, IPV4_ANY_HOST_ADDR));
Hugo Benichi38db9762016-07-12 15:08:50 +09001456
1457 // Verify GARP reply packets are always filtered
Hugo Benichi961ca492016-09-02 11:04:34 +09001458 assertDrop(program, garpReply());
Paul Jensen9132f342016-04-13 15:00:26 -04001459 }
1460
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001461 @Test
Paul Jensen9132f342016-04-13 15:00:26 -04001462 public void testApfFilterArp() throws Exception {
Erik Kline8d1fe542018-03-12 23:18:58 +09001463 MockIpClientCallback ipClientCallback = new MockIpClientCallback();
Hugo Benichi72166362017-10-13 16:32:20 +09001464 ApfConfiguration config = getDefaultConfig();
1465 config.multicastFilter = DROP_MULTICAST;
1466 config.ieee802_3Filter = DROP_802_3_FRAMES;
Erik Kline8d1fe542018-03-12 23:18:58 +09001467 TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
Paul Jensen9132f342016-04-13 15:00:26 -04001468
Hugo Benichi38db9762016-07-12 15:08:50 +09001469 // Verify initially ARP request filter is off, and GARP filter is on.
Erik Kline8d1fe542018-03-12 23:18:58 +09001470 verifyArpFilter(ipClientCallback.getApfProgram(), PASS);
Paul Jensen9132f342016-04-13 15:00:26 -04001471
1472 // Inform ApfFilter of our address and verify ARP filtering is on
Hugo Benichi38db9762016-07-12 15:08:50 +09001473 LinkAddress linkAddress = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 24);
Paul Jensen9132f342016-04-13 15:00:26 -04001474 LinkProperties lp = new LinkProperties();
Hugo Benichi38db9762016-07-12 15:08:50 +09001475 assertTrue(lp.addLinkAddress(linkAddress));
Erik Kline8d1fe542018-03-12 23:18:58 +09001476 verifyArpFilter(getProgram(ipClientCallback, apfFilter, lp), DROP);
Paul Jensen9132f342016-04-13 15:00:26 -04001477
1478 // Inform ApfFilter of loss of IP and verify ARP filtering is off
Erik Kline8d1fe542018-03-12 23:18:58 +09001479 verifyArpFilter(getProgram(ipClientCallback, apfFilter, new LinkProperties()), PASS);
Paul Jensen9132f342016-04-13 15:00:26 -04001480
1481 apfFilter.shutdown();
1482 }
1483
Aaron Huang04ed6a32018-11-15 20:30:46 +08001484 private static byte[] arpReply(byte[] sip, byte[] tip) {
Hugo Benichi38db9762016-07-12 15:08:50 +09001485 ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
1486 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP);
Hugo Benichi961ca492016-09-02 11:04:34 +09001487 put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REPLY_HEADER);
Aaron Huang04ed6a32018-11-15 20:30:46 +08001488 put(packet, ARP_SOURCE_IP_ADDRESS_OFFSET, sip);
Hugo Benichi961ca492016-09-02 11:04:34 +09001489 put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, tip);
Hugo Benichi38db9762016-07-12 15:08:50 +09001490 return packet.array();
1491 }
1492
Aaron Huang04ed6a32018-11-15 20:30:46 +08001493 private static byte[] arpRequestBroadcast(byte[] tip) {
Hugo Benichi38db9762016-07-12 15:08:50 +09001494 ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
1495 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP);
Aaron Huang04ed6a32018-11-15 20:30:46 +08001496 put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS);
1497 put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REQUEST_HEADER);
Hugo Benichi961ca492016-09-02 11:04:34 +09001498 put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, tip);
Hugo Benichi38db9762016-07-12 15:08:50 +09001499 return packet.array();
1500 }
1501
1502 private static byte[] garpReply() {
1503 ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
1504 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP);
Hugo Benichi961ca492016-09-02 11:04:34 +09001505 put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS);
1506 put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REPLY_HEADER);
1507 put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, IPV4_ANY_HOST_ADDR);
Hugo Benichi38db9762016-07-12 15:08:50 +09001508 return packet.array();
1509 }
1510
Aaron Huanga63c40e2019-01-15 16:53:51 +08001511 private static final byte[] IPV4_KEEPALIVE_SRC_ADDR = {10, 0, 0, 5};
1512 private static final byte[] IPV4_KEEPALIVE_DST_ADDR = {10, 0, 0, 6};
1513 private static final byte[] IPV4_ANOTHER_ADDR = {10, 0 , 0, 7};
1514 private static final byte[] IPV6_KEEPALIVE_SRC_ADDR =
1515 {(byte) 0x24, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (byte) 0xfa, (byte) 0xf1};
1516 private static final byte[] IPV6_KEEPALIVE_DST_ADDR =
1517 {(byte) 0x24, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (byte) 0xfa, (byte) 0xf2};
1518 private static final byte[] IPV6_ANOTHER_ADDR =
1519 {(byte) 0x24, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (byte) 0xfa, (byte) 0xf5};
1520
1521 @Test
1522 public void testApfFilterKeepaliveAck() throws Exception {
1523 final MockIpClientCallback cb = new MockIpClientCallback();
1524 final ApfConfiguration config = getDefaultConfig();
1525 config.multicastFilter = DROP_MULTICAST;
1526 config.ieee802_3Filter = DROP_802_3_FRAMES;
1527 final TestApfFilter apfFilter = new TestApfFilter(mContext, config, cb, mLog);
1528 byte[] program;
1529 final int srcPort = 12345;
1530 final int dstPort = 54321;
1531 final int seqNum = 2123456789;
1532 final int ackNum = 1234567890;
1533 final int anotherSrcPort = 23456;
1534 final int anotherDstPort = 65432;
1535 final int anotherSeqNum = 2123456780;
1536 final int anotherAckNum = 1123456789;
1537 final int slot1 = 1;
1538 final int slot2 = 2;
1539 final int window = 14480;
1540 final int windowScale = 4;
1541
1542 // src: 10.0.0.5, port: 12345
1543 // dst: 10.0.0.6, port: 54321
1544 InetAddress srcAddr = InetAddress.getByAddress(IPV4_KEEPALIVE_SRC_ADDR);
1545 InetAddress dstAddr = InetAddress.getByAddress(IPV4_KEEPALIVE_DST_ADDR);
1546
Xiao Ma6b4de8f2019-02-15 19:18:21 +09001547 final TcpKeepalivePacketDataParcelable parcel = new TcpKeepalivePacketDataParcelable();
1548 parcel.srcAddress = srcAddr.getAddress();
1549 parcel.srcPort = srcPort;
1550 parcel.dstAddress = dstAddr.getAddress();
1551 parcel.dstPort = dstPort;
1552 parcel.seq = seqNum;
1553 parcel.ack = ackNum;
Aaron Huanga63c40e2019-01-15 16:53:51 +08001554
Xiao Ma6b4de8f2019-02-15 19:18:21 +09001555 apfFilter.addKeepalivePacketFilter(slot1, parcel);
Aaron Huanga63c40e2019-01-15 16:53:51 +08001556 program = cb.getApfProgram();
1557
1558 // Verify IPv4 keepalive ack packet is dropped
1559 // src: 10.0.0.6, port: 54321
1560 // dst: 10.0.0.5, port: 12345
1561 assertDrop(program,
1562 ipv4Packet(IPV4_KEEPALIVE_DST_ADDR, IPV4_KEEPALIVE_SRC_ADDR,
1563 dstPort, srcPort, ackNum, seqNum + 1, 0 /* dataLength */));
1564 // Verify IPv4 non-keepalive ack packet from the same source address is passed
1565 assertPass(program,
1566 ipv4Packet(IPV4_KEEPALIVE_DST_ADDR, IPV4_KEEPALIVE_SRC_ADDR,
1567 dstPort, srcPort, ackNum + 100, seqNum, 0 /* dataLength */));
1568 assertPass(program,
1569 ipv4Packet(IPV4_KEEPALIVE_DST_ADDR, IPV4_KEEPALIVE_SRC_ADDR,
1570 dstPort, srcPort, ackNum, seqNum + 1, 10 /* dataLength */));
1571 // Verify IPv4 packet from another address is passed
1572 assertPass(program,
1573 ipv4Packet(IPV4_ANOTHER_ADDR, IPV4_KEEPALIVE_SRC_ADDR, anotherSrcPort,
Xiao Mad36a89c2019-02-10 14:52:37 +09001574 anotherDstPort, anotherSeqNum, anotherAckNum, 0 /* dataLength */));
Aaron Huanga63c40e2019-01-15 16:53:51 +08001575
1576 // Remove IPv4 keepalive filter
1577 apfFilter.removeKeepalivePacketFilter(slot1);
1578
1579 try {
1580 // src: 2404:0:0:0:0:0:faf1, port: 12345
1581 // dst: 2404:0:0:0:0:0:faf2, port: 54321
1582 srcAddr = InetAddress.getByAddress(IPV6_KEEPALIVE_SRC_ADDR);
1583 dstAddr = InetAddress.getByAddress(IPV6_KEEPALIVE_DST_ADDR);
Xiao Ma6b4de8f2019-02-15 19:18:21 +09001584
1585 final TcpKeepalivePacketDataParcelable ipv6Parcel =
1586 new TcpKeepalivePacketDataParcelable();
1587 ipv6Parcel.srcAddress = srcAddr.getAddress();
1588 ipv6Parcel.srcPort = srcPort;
1589 ipv6Parcel.dstAddress = dstAddr.getAddress();
1590 ipv6Parcel.dstPort = dstPort;
1591 ipv6Parcel.seq = seqNum;
1592 ipv6Parcel.ack = ackNum;
1593
1594 apfFilter.addKeepalivePacketFilter(slot1, ipv6Parcel);
Aaron Huanga63c40e2019-01-15 16:53:51 +08001595 program = cb.getApfProgram();
1596
1597 // Verify IPv6 keepalive ack packet is dropped
1598 // src: 2404:0:0:0:0:0:faf2, port: 54321
1599 // dst: 2404:0:0:0:0:0:faf1, port: 12345
1600 assertDrop(program,
1601 ipv6Packet(IPV6_KEEPALIVE_DST_ADDR, IPV6_KEEPALIVE_SRC_ADDR,
1602 dstPort, srcPort, ackNum, seqNum + 1));
1603 // Verify IPv6 non-keepalive ack packet from the same source address is passed
1604 assertPass(program,
1605 ipv6Packet(IPV6_KEEPALIVE_DST_ADDR, IPV6_KEEPALIVE_SRC_ADDR,
1606 dstPort, srcPort, ackNum + 100, seqNum));
1607 // Verify IPv6 packet from another address is passed
1608 assertPass(program,
1609 ipv6Packet(IPV6_ANOTHER_ADDR, IPV6_KEEPALIVE_SRC_ADDR, anotherSrcPort,
1610 anotherDstPort, anotherSeqNum, anotherAckNum));
1611
1612 // Remove IPv6 keepalive filter
1613 apfFilter.removeKeepalivePacketFilter(slot1);
1614
1615 // Verify multiple filters
Xiao Ma6b4de8f2019-02-15 19:18:21 +09001616 apfFilter.addKeepalivePacketFilter(slot1, parcel);
1617 apfFilter.addKeepalivePacketFilter(slot2, ipv6Parcel);
Aaron Huanga63c40e2019-01-15 16:53:51 +08001618 program = cb.getApfProgram();
1619
1620 // Verify IPv4 keepalive ack packet is dropped
1621 // src: 10.0.0.6, port: 54321
1622 // dst: 10.0.0.5, port: 12345
1623 assertDrop(program,
1624 ipv4Packet(IPV4_KEEPALIVE_DST_ADDR, IPV4_KEEPALIVE_SRC_ADDR,
Xiao Mad36a89c2019-02-10 14:52:37 +09001625 dstPort, srcPort, ackNum, seqNum + 1, 0 /* dataLength */));
Aaron Huanga63c40e2019-01-15 16:53:51 +08001626 // Verify IPv4 non-keepalive ack packet from the same source address is passed
1627 assertPass(program,
1628 ipv4Packet(IPV4_KEEPALIVE_DST_ADDR, IPV4_KEEPALIVE_SRC_ADDR,
Xiao Mad36a89c2019-02-10 14:52:37 +09001629 dstPort, srcPort, ackNum + 100, seqNum, 0 /* dataLength */));
Aaron Huanga63c40e2019-01-15 16:53:51 +08001630 // Verify IPv4 packet from another address is passed
1631 assertPass(program,
1632 ipv4Packet(IPV4_ANOTHER_ADDR, IPV4_KEEPALIVE_SRC_ADDR, anotherSrcPort,
Xiao Mad36a89c2019-02-10 14:52:37 +09001633 anotherDstPort, anotherSeqNum, anotherAckNum, 0 /* dataLength */));
Aaron Huanga63c40e2019-01-15 16:53:51 +08001634
1635 // Verify IPv6 keepalive ack packet is dropped
1636 // src: 2404:0:0:0:0:0:faf2, port: 54321
1637 // dst: 2404:0:0:0:0:0:faf1, port: 12345
1638 assertDrop(program,
1639 ipv6Packet(IPV6_KEEPALIVE_DST_ADDR, IPV6_KEEPALIVE_SRC_ADDR,
1640 dstPort, srcPort, ackNum, seqNum + 1));
1641 // Verify IPv6 non-keepalive ack packet from the same source address is passed
1642 assertPass(program,
1643 ipv6Packet(IPV6_KEEPALIVE_DST_ADDR, IPV6_KEEPALIVE_SRC_ADDR,
1644 dstPort, srcPort, ackNum + 100, seqNum));
1645 // Verify IPv6 packet from another address is passed
1646 assertPass(program,
1647 ipv6Packet(IPV6_ANOTHER_ADDR, IPV6_KEEPALIVE_SRC_ADDR, anotherSrcPort,
1648 anotherDstPort, anotherSeqNum, anotherAckNum));
1649
1650 // Remove keepalive filters
1651 apfFilter.removeKeepalivePacketFilter(slot1);
1652 apfFilter.removeKeepalivePacketFilter(slot2);
Xiao Ma6b4de8f2019-02-15 19:18:21 +09001653 } catch (UnsupportedOperationException e) {
Aaron Huanga63c40e2019-01-15 16:53:51 +08001654 // TODO: support V6 packets
1655 }
1656
1657 program = cb.getApfProgram();
1658
1659 // Verify IPv4, IPv6 packets are passed
1660 assertPass(program,
1661 ipv4Packet(IPV4_KEEPALIVE_DST_ADDR, IPV4_KEEPALIVE_SRC_ADDR,
Xiao Mad36a89c2019-02-10 14:52:37 +09001662 dstPort, srcPort, ackNum, seqNum + 1, 0 /* dataLength */));
Aaron Huanga63c40e2019-01-15 16:53:51 +08001663 assertPass(program,
1664 ipv6Packet(IPV6_KEEPALIVE_DST_ADDR, IPV6_KEEPALIVE_SRC_ADDR,
1665 dstPort, srcPort, ackNum, seqNum + 1));
1666 assertPass(program,
1667 ipv4Packet(IPV4_ANOTHER_ADDR, IPV4_KEEPALIVE_SRC_ADDR, srcPort,
Xiao Mad36a89c2019-02-10 14:52:37 +09001668 dstPort, anotherSeqNum, anotherAckNum, 0 /* dataLength */));
Aaron Huanga63c40e2019-01-15 16:53:51 +08001669 assertPass(program,
1670 ipv6Packet(IPV6_ANOTHER_ADDR, IPV6_KEEPALIVE_SRC_ADDR, srcPort,
1671 dstPort, anotherSeqNum, anotherAckNum));
1672
1673 apfFilter.shutdown();
1674 }
1675
Xiao Mad36a89c2019-02-10 14:52:37 +09001676 private static byte[] ipv4Packet(byte[] sip, byte[] dip, int sport,
1677 int dport, int seq, int ack, int dataLength) {
1678 final int totalLength = dataLength + IPV4_HEADER_LEN + IPV4_TCP_HEADER_LEN;
1679
1680 ByteBuffer packet = ByteBuffer.wrap(new byte[totalLength + ETH_HEADER_LEN]);
1681
1682 // ether type
Aaron Huanga63c40e2019-01-15 16:53:51 +08001683 packet.putShort(ETH_ETHERTYPE_OFFSET, (short) ETH_P_IP);
Xiao Mad36a89c2019-02-10 14:52:37 +09001684
1685 // IPv4 header
Aaron Huanga63c40e2019-01-15 16:53:51 +08001686 packet.put(IPV4_VERSION_IHL_OFFSET, (byte) 0x45);
Xiao Mad36a89c2019-02-10 14:52:37 +09001687 packet.putShort(IPV4_TOTAL_LENGTH_OFFSET, (short) totalLength);
1688 packet.put(IPV4_PROTOCOL_OFFSET, (byte) IPPROTO_TCP);
Aaron Huanga63c40e2019-01-15 16:53:51 +08001689 put(packet, IPV4_SRC_ADDR_OFFSET, sip);
Xiao Mad36a89c2019-02-10 14:52:37 +09001690 put(packet, IPV4_DEST_ADDR_OFFSET, dip);
Aaron Huanga63c40e2019-01-15 16:53:51 +08001691 packet.putShort(IPV4_TCP_SRC_PORT_OFFSET, (short) sport);
1692 packet.putShort(IPV4_TCP_DEST_PORT_OFFSET, (short) dport);
1693 packet.putInt(IPV4_TCP_SEQ_NUM_OFFSET, seq);
1694 packet.putInt(IPV4_TCP_ACK_NUM_OFFSET, ack);
Aaron Huanga63c40e2019-01-15 16:53:51 +08001695
Xiao Mad36a89c2019-02-10 14:52:37 +09001696 // TCP header length 5(20 bytes), reserved 3 bits, NS=0
Aaron Huanga63c40e2019-01-15 16:53:51 +08001697 packet.put(IPV4_TCP_HEADER_LENGTH_OFFSET, (byte) 0x50);
Xiao Mad36a89c2019-02-10 14:52:37 +09001698 // TCP flags: ACK set
1699 packet.put(IPV4_TCP_HEADER_FLAG_OFFSET, (byte) 0x10);
Aaron Huanga63c40e2019-01-15 16:53:51 +08001700 return packet.array();
1701 }
1702
1703 private static byte[] ipv6Packet(byte[] sip, byte[] tip, int sport,
1704 int dport, int seq, int ack) {
1705 ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
1706 packet.putShort(ETH_ETHERTYPE_OFFSET, (short) ETH_P_IPV6);
1707 put(packet, IPV6_SRC_ADDR_OFFSET, sip);
1708 put(packet, IPV6_DEST_ADDR_OFFSET, tip);
1709 packet.putShort(IPV6_TCP_SRC_PORT_OFFSET, (short) sport);
1710 packet.putShort(IPV6_TCP_DEST_PORT_OFFSET, (short) dport);
1711 packet.putInt(IPV6_TCP_SEQ_NUM_OFFSET, seq);
1712 packet.putInt(IPV6_TCP_ACK_NUM_OFFSET, ack);
1713 return packet.array();
1714 }
1715
Erik Kline8d1fe542018-03-12 23:18:58 +09001716 // Verify that the last program pushed to the IpClient.Callback properly filters the
Paul Jensen9132f342016-04-13 15:00:26 -04001717 // given packet for the given lifetime.
Hugo Benichi4456f332016-12-19 14:50:52 +09001718 private void verifyRaLifetime(byte[] program, ByteBuffer packet, int lifetime) {
1719 final int FRACTION_OF_LIFETIME = 6;
1720 final int ageLimit = lifetime / FRACTION_OF_LIFETIME;
Paul Jensen9132f342016-04-13 15:00:26 -04001721
Hugo Benichi4456f332016-12-19 14:50:52 +09001722 // Verify new program should drop RA for 1/6th its lifetime and pass afterwards.
Hugo Benichi961ca492016-09-02 11:04:34 +09001723 assertDrop(program, packet.array());
Hugo Benichi4456f332016-12-19 14:50:52 +09001724 assertDrop(program, packet.array(), ageLimit);
1725 assertPass(program, packet.array(), ageLimit + 1);
Paul Jensen9132f342016-04-13 15:00:26 -04001726 assertPass(program, packet.array(), lifetime);
Paul Jensen9132f342016-04-13 15:00:26 -04001727 // Verify RA checksum is ignored
Hugo Benichi4456f332016-12-19 14:50:52 +09001728 final short originalChecksum = packet.getShort(ICMP6_RA_CHECKSUM_OFFSET);
Paul Jensen9132f342016-04-13 15:00:26 -04001729 packet.putShort(ICMP6_RA_CHECKSUM_OFFSET, (short)12345);
Hugo Benichi961ca492016-09-02 11:04:34 +09001730 assertDrop(program, packet.array());
Paul Jensen9132f342016-04-13 15:00:26 -04001731 packet.putShort(ICMP6_RA_CHECKSUM_OFFSET, (short)-12345);
Hugo Benichi961ca492016-09-02 11:04:34 +09001732 assertDrop(program, packet.array());
Hugo Benichi4456f332016-12-19 14:50:52 +09001733 packet.putShort(ICMP6_RA_CHECKSUM_OFFSET, originalChecksum);
Paul Jensen9132f342016-04-13 15:00:26 -04001734
1735 // Verify other changes to RA make it not match filter
Hugo Benichi4456f332016-12-19 14:50:52 +09001736 final byte originalFirstByte = packet.get(0);
Paul Jensen9132f342016-04-13 15:00:26 -04001737 packet.put(0, (byte)-1);
Hugo Benichi961ca492016-09-02 11:04:34 +09001738 assertPass(program, packet.array());
Paul Jensen9132f342016-04-13 15:00:26 -04001739 packet.put(0, (byte)0);
Hugo Benichi961ca492016-09-02 11:04:34 +09001740 assertDrop(program, packet.array());
Hugo Benichi4456f332016-12-19 14:50:52 +09001741 packet.put(0, originalFirstByte);
Paul Jensen9132f342016-04-13 15:00:26 -04001742 }
1743
1744 // Test that when ApfFilter is shown the given packet, it generates a program to filter it
1745 // for the given lifetime.
Erik Kline8d1fe542018-03-12 23:18:58 +09001746 private void verifyRaLifetime(TestApfFilter apfFilter, MockIpClientCallback ipClientCallback,
Paul Jensen9132f342016-04-13 15:00:26 -04001747 ByteBuffer packet, int lifetime) throws IOException, ErrnoException {
1748 // Verify new program generated if ApfFilter witnesses RA
Erik Kline8d1fe542018-03-12 23:18:58 +09001749 ipClientCallback.resetApfProgramWait();
Paul Jensen9132f342016-04-13 15:00:26 -04001750 apfFilter.pretendPacketReceived(packet.array());
Erik Kline8d1fe542018-03-12 23:18:58 +09001751 byte[] program = ipClientCallback.getApfProgram();
Hugo Benichi4456f332016-12-19 14:50:52 +09001752 verifyRaLifetime(program, packet, lifetime);
Paul Jensen9132f342016-04-13 15:00:26 -04001753 }
1754
Hugo Benichi6ccd51a2016-07-04 09:22:30 +09001755 private void verifyRaEvent(RaEvent expected) {
Remi NGUYEN VAN7b84fb32019-01-19 21:13:24 +09001756 ArgumentCaptor<IpConnectivityLog.Event> captor =
1757 ArgumentCaptor.forClass(IpConnectivityLog.Event.class);
Hugo Benichi6ccd51a2016-07-04 09:22:30 +09001758 verify(mLog, atLeastOnce()).log(captor.capture());
1759 RaEvent got = lastRaEvent(captor.getAllValues());
1760 if (!raEventEquals(expected, got)) {
1761 assertEquals(expected, got); // fail for printing an assertion error message.
1762 }
1763 }
1764
Remi NGUYEN VAN7b84fb32019-01-19 21:13:24 +09001765 private RaEvent lastRaEvent(List<IpConnectivityLog.Event> events) {
Hugo Benichi6ccd51a2016-07-04 09:22:30 +09001766 RaEvent got = null;
1767 for (Parcelable ev : events) {
1768 if (ev instanceof RaEvent) {
1769 got = (RaEvent) ev;
1770 }
1771 }
1772 return got;
1773 }
1774
1775 private boolean raEventEquals(RaEvent ev1, RaEvent ev2) {
1776 return (ev1 != null) && (ev2 != null)
1777 && (ev1.routerLifetime == ev2.routerLifetime)
1778 && (ev1.prefixValidLifetime == ev2.prefixValidLifetime)
1779 && (ev1.prefixPreferredLifetime == ev2.prefixPreferredLifetime)
1780 && (ev1.routeInfoLifetime == ev2.routeInfoLifetime)
1781 && (ev1.rdnssLifetime == ev2.rdnssLifetime)
1782 && (ev1.dnsslLifetime == ev2.dnsslLifetime);
1783 }
1784
Erik Kline8d1fe542018-03-12 23:18:58 +09001785 private void assertInvalidRa(TestApfFilter apfFilter, MockIpClientCallback ipClientCallback,
Lorenzo Colitti8995d852016-06-23 15:24:46 +09001786 ByteBuffer packet) throws IOException, ErrnoException {
Erik Kline8d1fe542018-03-12 23:18:58 +09001787 ipClientCallback.resetApfProgramWait();
Lorenzo Colitti8995d852016-06-23 15:24:46 +09001788 apfFilter.pretendPacketReceived(packet.array());
Erik Kline8d1fe542018-03-12 23:18:58 +09001789 ipClientCallback.assertNoProgramUpdate();
Lorenzo Colitti8995d852016-06-23 15:24:46 +09001790 }
1791
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001792 @Test
Paul Jensen9132f342016-04-13 15:00:26 -04001793 public void testApfFilterRa() throws Exception {
Erik Kline8d1fe542018-03-12 23:18:58 +09001794 MockIpClientCallback ipClientCallback = new MockIpClientCallback();
Hugo Benichi72166362017-10-13 16:32:20 +09001795 ApfConfiguration config = getDefaultConfig();
1796 config.multicastFilter = DROP_MULTICAST;
1797 config.ieee802_3Filter = DROP_802_3_FRAMES;
Erik Kline8d1fe542018-03-12 23:18:58 +09001798 TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
1799 byte[] program = ipClientCallback.getApfProgram();
Paul Jensen9132f342016-04-13 15:00:26 -04001800
Hugo Benichi4456f332016-12-19 14:50:52 +09001801 final int ROUTER_LIFETIME = 1000;
1802 final int PREFIX_VALID_LIFETIME = 200;
1803 final int PREFIX_PREFERRED_LIFETIME = 100;
1804 final int RDNSS_LIFETIME = 300;
1805 final int ROUTE_LIFETIME = 400;
1806 // Note that lifetime of 2000 will be ignored in favor of shorter route lifetime of 1000.
1807 final int DNSSL_LIFETIME = 2000;
Joel Scherpelz967dec72017-05-24 15:08:39 +09001808 final int VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET = ETH_HEADER_LEN;
1809 // IPv6, traffic class = 0, flow label = 0x12345
1810 final int VERSION_TRAFFIC_CLASS_FLOW_LABEL = 0x60012345;
Hugo Benichi4456f332016-12-19 14:50:52 +09001811
Paul Jensen9132f342016-04-13 15:00:26 -04001812 // Verify RA is passed the first time
1813 ByteBuffer basePacket = ByteBuffer.wrap(new byte[ICMP6_RA_OPTION_OFFSET]);
1814 basePacket.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
Joel Scherpelz967dec72017-05-24 15:08:39 +09001815 basePacket.putInt(VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET,
1816 VERSION_TRAFFIC_CLASS_FLOW_LABEL);
Paul Jensen9132f342016-04-13 15:00:26 -04001817 basePacket.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6);
1818 basePacket.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_ROUTER_ADVERTISEMENT);
Hugo Benichi4456f332016-12-19 14:50:52 +09001819 basePacket.putShort(ICMP6_RA_ROUTER_LIFETIME_OFFSET, (short)ROUTER_LIFETIME);
Lorenzo Colitti11e13e22016-05-20 00:04:43 +09001820 basePacket.position(IPV6_DEST_ADDR_OFFSET);
1821 basePacket.put(IPV6_ALL_NODES_ADDRESS);
Hugo Benichi961ca492016-09-02 11:04:34 +09001822 assertPass(program, basePacket.array());
Paul Jensen9132f342016-04-13 15:00:26 -04001823
Erik Kline8d1fe542018-03-12 23:18:58 +09001824 verifyRaLifetime(apfFilter, ipClientCallback, basePacket, ROUTER_LIFETIME);
Hugo Benichi4456f332016-12-19 14:50:52 +09001825 verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, -1, -1));
Paul Jensen9132f342016-04-13 15:00:26 -04001826
Joel Scherpelz967dec72017-05-24 15:08:39 +09001827 ByteBuffer newFlowLabelPacket = ByteBuffer.wrap(new byte[ICMP6_RA_OPTION_OFFSET]);
1828 basePacket.clear();
1829 newFlowLabelPacket.put(basePacket);
1830 // Check that changes are ignored in every byte of the flow label.
1831 newFlowLabelPacket.putInt(VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET,
1832 VERSION_TRAFFIC_CLASS_FLOW_LABEL + 0x11111);
1833
Lorenzo Colitti8995d852016-06-23 15:24:46 +09001834 // Ensure zero-length options cause the packet to be silently skipped.
1835 // Do this before we test other packets. http://b/29586253
1836 ByteBuffer zeroLengthOptionPacket = ByteBuffer.wrap(
1837 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]);
1838 basePacket.clear();
1839 zeroLengthOptionPacket.put(basePacket);
1840 zeroLengthOptionPacket.put((byte)ICMP6_PREFIX_OPTION_TYPE);
1841 zeroLengthOptionPacket.put((byte)0);
Erik Kline8d1fe542018-03-12 23:18:58 +09001842 assertInvalidRa(apfFilter, ipClientCallback, zeroLengthOptionPacket);
Lorenzo Colitti8995d852016-06-23 15:24:46 +09001843
Paul Jensen9132f342016-04-13 15:00:26 -04001844 // Generate several RAs with different options and lifetimes, and verify when
1845 // ApfFilter is shown these packets, it generates programs to filter them for the
1846 // appropriate lifetime.
1847 ByteBuffer prefixOptionPacket = ByteBuffer.wrap(
1848 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_PREFIX_OPTION_LEN]);
1849 basePacket.clear();
1850 prefixOptionPacket.put(basePacket);
1851 prefixOptionPacket.put((byte)ICMP6_PREFIX_OPTION_TYPE);
1852 prefixOptionPacket.put((byte)(ICMP6_PREFIX_OPTION_LEN / 8));
1853 prefixOptionPacket.putInt(
Hugo Benichi4456f332016-12-19 14:50:52 +09001854 ICMP6_RA_OPTION_OFFSET + ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_OFFSET,
1855 PREFIX_PREFERRED_LIFETIME);
Paul Jensen9132f342016-04-13 15:00:26 -04001856 prefixOptionPacket.putInt(
Hugo Benichi4456f332016-12-19 14:50:52 +09001857 ICMP6_RA_OPTION_OFFSET + ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET,
1858 PREFIX_VALID_LIFETIME);
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001859 verifyRaLifetime(
Erik Kline8d1fe542018-03-12 23:18:58 +09001860 apfFilter, ipClientCallback, prefixOptionPacket, PREFIX_PREFERRED_LIFETIME);
Hugo Benichi4456f332016-12-19 14:50:52 +09001861 verifyRaEvent(new RaEvent(
1862 ROUTER_LIFETIME, PREFIX_VALID_LIFETIME, PREFIX_PREFERRED_LIFETIME, -1, -1, -1));
Paul Jensen9132f342016-04-13 15:00:26 -04001863
1864 ByteBuffer rdnssOptionPacket = ByteBuffer.wrap(
1865 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]);
1866 basePacket.clear();
1867 rdnssOptionPacket.put(basePacket);
1868 rdnssOptionPacket.put((byte)ICMP6_RDNSS_OPTION_TYPE);
1869 rdnssOptionPacket.put((byte)(ICMP6_4_BYTE_OPTION_LEN / 8));
1870 rdnssOptionPacket.putInt(
Hugo Benichi4456f332016-12-19 14:50:52 +09001871 ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, RDNSS_LIFETIME);
Erik Kline8d1fe542018-03-12 23:18:58 +09001872 verifyRaLifetime(apfFilter, ipClientCallback, rdnssOptionPacket, RDNSS_LIFETIME);
Hugo Benichi4456f332016-12-19 14:50:52 +09001873 verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, RDNSS_LIFETIME, -1));
Paul Jensen9132f342016-04-13 15:00:26 -04001874
1875 ByteBuffer routeInfoOptionPacket = ByteBuffer.wrap(
1876 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]);
1877 basePacket.clear();
1878 routeInfoOptionPacket.put(basePacket);
1879 routeInfoOptionPacket.put((byte)ICMP6_ROUTE_INFO_OPTION_TYPE);
1880 routeInfoOptionPacket.put((byte)(ICMP6_4_BYTE_OPTION_LEN / 8));
1881 routeInfoOptionPacket.putInt(
Hugo Benichi4456f332016-12-19 14:50:52 +09001882 ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, ROUTE_LIFETIME);
Erik Kline8d1fe542018-03-12 23:18:58 +09001883 verifyRaLifetime(apfFilter, ipClientCallback, routeInfoOptionPacket, ROUTE_LIFETIME);
Hugo Benichi4456f332016-12-19 14:50:52 +09001884 verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, ROUTE_LIFETIME, -1, -1));
Paul Jensen9132f342016-04-13 15:00:26 -04001885
1886 ByteBuffer dnsslOptionPacket = ByteBuffer.wrap(
1887 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]);
1888 basePacket.clear();
1889 dnsslOptionPacket.put(basePacket);
1890 dnsslOptionPacket.put((byte)ICMP6_DNSSL_OPTION_TYPE);
1891 dnsslOptionPacket.put((byte)(ICMP6_4_BYTE_OPTION_LEN / 8));
1892 dnsslOptionPacket.putInt(
Hugo Benichi4456f332016-12-19 14:50:52 +09001893 ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, DNSSL_LIFETIME);
Erik Kline8d1fe542018-03-12 23:18:58 +09001894 verifyRaLifetime(apfFilter, ipClientCallback, dnsslOptionPacket, ROUTER_LIFETIME);
Hugo Benichi4456f332016-12-19 14:50:52 +09001895 verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, -1, DNSSL_LIFETIME));
Paul Jensen9132f342016-04-13 15:00:26 -04001896
1897 // Verify that current program filters all five RAs:
Erik Kline8d1fe542018-03-12 23:18:58 +09001898 program = ipClientCallback.getApfProgram();
Hugo Benichi4456f332016-12-19 14:50:52 +09001899 verifyRaLifetime(program, basePacket, ROUTER_LIFETIME);
Joel Scherpelz967dec72017-05-24 15:08:39 +09001900 verifyRaLifetime(program, newFlowLabelPacket, ROUTER_LIFETIME);
Hugo Benichi4456f332016-12-19 14:50:52 +09001901 verifyRaLifetime(program, prefixOptionPacket, PREFIX_PREFERRED_LIFETIME);
1902 verifyRaLifetime(program, rdnssOptionPacket, RDNSS_LIFETIME);
1903 verifyRaLifetime(program, routeInfoOptionPacket, ROUTE_LIFETIME);
1904 verifyRaLifetime(program, dnsslOptionPacket, ROUTER_LIFETIME);
Paul Jensen9132f342016-04-13 15:00:26 -04001905
1906 apfFilter.shutdown();
1907 }
1908
1909 /**
1910 * Stage a file for testing, i.e. make it native accessible. Given a resource ID,
1911 * copy that resource into the app's data directory and return the path to it.
1912 */
1913 private String stageFile(int rawId) throws Exception {
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001914 File file = new File(InstrumentationRegistry.getContext().getFilesDir(), "staged_file");
Paul Jensen9132f342016-04-13 15:00:26 -04001915 new File(file.getParent()).mkdirs();
1916 InputStream in = null;
1917 OutputStream out = null;
1918 try {
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001919 in = InstrumentationRegistry.getContext().getResources().openRawResource(rawId);
Paul Jensen9132f342016-04-13 15:00:26 -04001920 out = new FileOutputStream(file);
1921 Streams.copy(in, out);
1922 } finally {
1923 if (in != null) in.close();
1924 if (out != null) out.close();
1925 }
1926 return file.getAbsolutePath();
1927 }
1928
Hugo Benichi961ca492016-09-02 11:04:34 +09001929 private static void put(ByteBuffer buffer, int position, byte[] bytes) {
1930 final int original = buffer.position();
1931 buffer.position(position);
1932 buffer.put(bytes);
1933 buffer.position(original);
1934 }
1935
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001936 @Test
Hugo Benichi0668a612016-10-06 15:19:36 +09001937 public void testRaParsing() throws Exception {
1938 final int maxRandomPacketSize = 512;
1939 final Random r = new Random();
Erik Kline8d1fe542018-03-12 23:18:58 +09001940 MockIpClientCallback cb = new MockIpClientCallback();
Hugo Benichi72166362017-10-13 16:32:20 +09001941 ApfConfiguration config = getDefaultConfig();
1942 config.multicastFilter = DROP_MULTICAST;
1943 config.ieee802_3Filter = DROP_802_3_FRAMES;
Bernie Innocentie2c70f82018-03-28 20:11:49 +09001944 TestApfFilter apfFilter = new TestApfFilter(mContext, config, cb, mLog);
Hugo Benichi0668a612016-10-06 15:19:36 +09001945 for (int i = 0; i < 1000; i++) {
1946 byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)];
1947 r.nextBytes(packet);
1948 try {
1949 apfFilter.new Ra(packet, packet.length);
1950 } catch (ApfFilter.InvalidRaException e) {
1951 } catch (Exception e) {
1952 throw new Exception("bad packet: " + HexDump.toHexString(packet), e);
1953 }
1954 }
1955 }
1956
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001957 @Test
Hugo Benichi0668a612016-10-06 15:19:36 +09001958 public void testRaProcessing() throws Exception {
1959 final int maxRandomPacketSize = 512;
1960 final Random r = new Random();
Erik Kline8d1fe542018-03-12 23:18:58 +09001961 MockIpClientCallback cb = new MockIpClientCallback();
Hugo Benichi72166362017-10-13 16:32:20 +09001962 ApfConfiguration config = getDefaultConfig();
1963 config.multicastFilter = DROP_MULTICAST;
1964 config.ieee802_3Filter = DROP_802_3_FRAMES;
Bernie Innocentie2c70f82018-03-28 20:11:49 +09001965 TestApfFilter apfFilter = new TestApfFilter(mContext, config, cb, mLog);
Hugo Benichi0668a612016-10-06 15:19:36 +09001966 for (int i = 0; i < 1000; i++) {
1967 byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)];
1968 r.nextBytes(packet);
1969 try {
1970 apfFilter.processRa(packet, packet.length);
1971 } catch (Exception e) {
1972 throw new Exception("bad packet: " + HexDump.toHexString(packet), e);
1973 }
1974 }
1975 }
1976
Paul Jensen9132f342016-04-13 15:00:26 -04001977 /**
Bernie Innocentia9949e92018-03-22 23:07:47 +09001978 * Call the APF interpreter to run {@code program} on {@code packet} with persistent memory
1979 * segment {@data} pretending the filter was installed {@code filter_age} seconds ago.
Paul Jensen9132f342016-04-13 15:00:26 -04001980 */
Bernie Innocentia9949e92018-03-22 23:07:47 +09001981 private native static int apfSimulate(byte[] program, byte[] packet, byte[] data,
1982 int filter_age);
Paul Jensen9132f342016-04-13 15:00:26 -04001983
1984 /**
1985 * Compile a tcpdump human-readable filter (e.g. "icmp" or "tcp port 54") into a BPF
1986 * prorgam and return a human-readable dump of the BPF program identical to "tcpdump -d".
1987 */
1988 private native static String compileToBpf(String filter);
1989
1990 /**
1991 * Open packet capture file {@code pcap_filename} and filter the packets using tcpdump
1992 * human-readable filter (e.g. "icmp" or "tcp port 54") compiled to a BPF program and
1993 * at the same time using APF program {@code apf_program}. Return {@code true} if
1994 * both APF and BPF programs filter out exactly the same packets.
1995 */
1996 private native static boolean compareBpfApf(String filter, String pcap_filename,
1997 byte[] apf_program);
Hugo Benichi7d21eae2016-09-02 14:00:29 +09001998
Aaron Huang785e5f12018-10-31 15:57:48 +08001999
2000 /**
2001 * Open packet capture file {@code pcapFilename} and run it through APF filter. Then
2002 * checks whether all the packets are dropped and populates data[] {@code data} with
2003 * the APF counters.
2004 */
2005 private native static boolean dropsAllPackets(byte[] program, byte[] data, String pcapFilename);
2006
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002007 @Test
Hugo Benichi7d21eae2016-09-02 14:00:29 +09002008 public void testBroadcastAddress() throws Exception {
2009 assertEqualsIp("255.255.255.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 0));
2010 assertEqualsIp("0.0.0.0", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 32));
2011 assertEqualsIp("0.0.3.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 22));
2012 assertEqualsIp("0.255.255.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 8));
2013
2014 assertEqualsIp("255.255.255.255", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 0));
2015 assertEqualsIp("10.0.0.1", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 32));
2016 assertEqualsIp("10.0.0.255", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 24));
2017 assertEqualsIp("10.0.255.255", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 16));
2018 }
2019
2020 public void assertEqualsIp(String expected, int got) throws Exception {
Hugo Benichi495a17b2017-01-12 15:31:05 +09002021 int want = bytesToBEInt(InetAddress.getByName(expected).getAddress());
Hugo Benichi7d21eae2016-09-02 14:00:29 +09002022 assertEquals(want, got);
2023 }
Paul Jensen9132f342016-04-13 15:00:26 -04002024}