blob: 88a05d506aa44866e788cdae5b5356f6b78bbbab [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;
Paul Jensen9132f342016-04-13 15:00:26 -040056import android.system.ErrnoException;
57import android.system.Os;
Hugo Benichi4456f332016-12-19 14:50:52 +090058import android.text.format.DateUtils;
Aaron Huang785e5f12018-10-31 15:57:48 +080059import android.util.Log;
Remi NGUYEN VANa5d31f52019-01-12 15:36:47 +090060
Brett Chabot84151d92019-02-27 15:37:59 -080061import androidx.test.InstrumentationRegistry;
62import androidx.test.filters.SmallTest;
63import androidx.test.runner.AndroidJUnit4;
64
Hugo Benichi0668a612016-10-06 15:19:36 +090065import com.android.internal.util.HexDump;
Remi NGUYEN VAN3c600a12019-01-10 19:12:46 +090066import com.android.server.networkstack.tests.R;
67import com.android.server.util.NetworkStackConstants;
Remi NGUYEN VANa5d31f52019-01-12 15:36:47 +090068
69import libcore.io.IoUtils;
70import libcore.io.Streams;
71
72import org.junit.Before;
73import org.junit.Test;
74import org.junit.runner.RunWith;
75import org.mockito.ArgumentCaptor;
76import org.mockito.Mock;
77import org.mockito.MockitoAnnotations;
78
Paul Jensen9132f342016-04-13 15:00:26 -040079import java.io.File;
80import java.io.FileDescriptor;
81import java.io.FileOutputStream;
82import java.io.IOException;
83import java.io.InputStream;
84import java.io.OutputStream;
85import java.net.InetAddress;
Paul Jensen9132f342016-04-13 15:00:26 -040086import java.nio.ByteBuffer;
Hugo Benichi6ccd51a2016-07-04 09:22:30 +090087import java.util.List;
Hugo Benichi0668a612016-10-06 15:19:36 +090088import java.util.Random;
Paul Jensen9132f342016-04-13 15:00:26 -040089
90/**
91 * Tests for APF program generator and interpreter.
92 *
93 * Build, install and run with:
Hugo Benichi495a17b2017-01-12 15:31:05 +090094 * runtest frameworks-net -c android.net.apf.ApfTest
Paul Jensen9132f342016-04-13 15:00:26 -040095 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090096@RunWith(AndroidJUnit4.class)
97@SmallTest
98public class ApfTest {
Paul Jensen9132f342016-04-13 15:00:26 -040099 private static final int TIMEOUT_MS = 500;
Bernie Innocenti3d479d92018-04-20 23:31:33 +0900100 private static final int MIN_APF_VERSION = 2;
Paul Jensen9132f342016-04-13 15:00:26 -0400101
Hugo Benichi6ccd51a2016-07-04 09:22:30 +0900102 @Mock IpConnectivityLog mLog;
Bernie Innocentie2c70f82018-03-28 20:11:49 +0900103 @Mock Context mContext;
Hugo Benichi6ccd51a2016-07-04 09:22:30 +0900104
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900105 @Before
Paul Jensen9132f342016-04-13 15:00:26 -0400106 public void setUp() throws Exception {
Hugo Benichi6ccd51a2016-07-04 09:22:30 +0900107 MockitoAnnotations.initMocks(this);
Paul Jensen9132f342016-04-13 15:00:26 -0400108 // Load up native shared library containing APF interpreter exposed via JNI.
Remi NGUYEN VAN3c600a12019-01-10 19:12:46 +0900109 System.loadLibrary("networkstacktestsjni");
Paul Jensen9132f342016-04-13 15:00:26 -0400110 }
111
Aaron Huang785e5f12018-10-31 15:57:48 +0800112 private static final String TAG = "ApfTest";
Paul Jensen9132f342016-04-13 15:00:26 -0400113 // Expected return codes from APF interpreter.
Bernie Innocenti3d479d92018-04-20 23:31:33 +0900114 private static final int PASS = 1;
115 private static final int DROP = 0;
Paul Jensen9132f342016-04-13 15:00:26 -0400116 // Interpreter will just accept packets without link layer headers, so pad fake packet to at
117 // least the minimum packet size.
Bernie Innocenti3d479d92018-04-20 23:31:33 +0900118 private static final int MIN_PKT_SIZE = 15;
Paul Jensen9132f342016-04-13 15:00:26 -0400119
Hugo Benichi72166362017-10-13 16:32:20 +0900120 private static final ApfCapabilities MOCK_APF_CAPABILITIES =
121 new ApfCapabilities(2, 1700, ARPHRD_ETHER);
122
Bernie Innocenti3d479d92018-04-20 23:31:33 +0900123 private static final boolean DROP_MULTICAST = true;
124 private static final boolean ALLOW_MULTICAST = false;
Hugo Benichi6ccd51a2016-07-04 09:22:30 +0900125
Bernie Innocenti3d479d92018-04-20 23:31:33 +0900126 private static final boolean DROP_802_3_FRAMES = true;
127 private static final boolean ALLOW_802_3_FRAMES = false;
128
129 // Constants for opcode encoding
130 private static final byte LI_OP = (byte)(13 << 3);
131 private static final byte LDDW_OP = (byte)(22 << 3);
132 private static final byte STDW_OP = (byte)(23 << 3);
133 private static final byte SIZE0 = (byte)(0 << 1);
134 private static final byte SIZE8 = (byte)(1 << 1);
135 private static final byte SIZE16 = (byte)(2 << 1);
136 private static final byte SIZE32 = (byte)(3 << 1);
137 private static final byte R1 = 1;
Ahmed ElArabawy8537c582017-06-12 18:01:11 -0700138
Hugo Benichi72166362017-10-13 16:32:20 +0900139 private static ApfConfiguration getDefaultConfig() {
140 ApfFilter.ApfConfiguration config = new ApfConfiguration();
141 config.apfCapabilities = MOCK_APF_CAPABILITIES;
142 config.multicastFilter = ALLOW_MULTICAST;
143 config.ieee802_3Filter = ALLOW_802_3_FRAMES;
144 config.ethTypeBlackList = new int[0];
145 return config;
146 }
147
Hugo Benichi961ca492016-09-02 11:04:34 +0900148 private static String label(int code) {
149 switch (code) {
150 case PASS: return "PASS";
151 case DROP: return "DROP";
152 default: return "UNKNOWN";
153 }
154 }
155
156 private static void assertReturnCodesEqual(int expected, int got) {
157 assertEquals(label(expected), label(got));
158 }
159
Paul Jensen9132f342016-04-13 15:00:26 -0400160 private void assertVerdict(int expected, byte[] program, byte[] packet, int filterAge) {
Bernie Innocentia9949e92018-03-22 23:07:47 +0900161 assertReturnCodesEqual(expected, apfSimulate(program, packet, null, filterAge));
Hugo Benichi961ca492016-09-02 11:04:34 +0900162 }
163
164 private void assertVerdict(int expected, byte[] program, byte[] packet) {
Bernie Innocentia9949e92018-03-22 23:07:47 +0900165 assertReturnCodesEqual(expected, apfSimulate(program, packet, null, 0));
Paul Jensen9132f342016-04-13 15:00:26 -0400166 }
167
168 private void assertPass(byte[] program, byte[] packet, int filterAge) {
169 assertVerdict(PASS, program, packet, filterAge);
170 }
171
Hugo Benichi961ca492016-09-02 11:04:34 +0900172 private void assertPass(byte[] program, byte[] packet) {
173 assertVerdict(PASS, program, packet);
174 }
175
Paul Jensen9132f342016-04-13 15:00:26 -0400176 private void assertDrop(byte[] program, byte[] packet, int filterAge) {
177 assertVerdict(DROP, program, packet, filterAge);
178 }
179
Hugo Benichi961ca492016-09-02 11:04:34 +0900180 private void assertDrop(byte[] program, byte[] packet) {
181 assertVerdict(DROP, program, packet);
182 }
183
Bernie Innocenti18050002018-04-19 20:53:00 +0900184 private void assertProgramEquals(byte[] expected, byte[] program) throws AssertionError {
185 // assertArrayEquals() would only print one byte, making debugging difficult.
186 if (!java.util.Arrays.equals(expected, program)) {
187 throw new AssertionError(
188 "\nexpected: " + HexDump.toHexString(expected) +
189 "\nactual: " + HexDump.toHexString(program));
190 }
191 }
192
193 private void assertDataMemoryContents(
194 int expected, byte[] program, byte[] packet, byte[] data, byte[] expected_data)
195 throws IllegalInstructionException, Exception {
Bernie Innocentia9949e92018-03-22 23:07:47 +0900196 assertReturnCodesEqual(expected, apfSimulate(program, packet, data, 0 /* filterAge */));
197
198 // assertArrayEquals() would only print one byte, making debugging difficult.
199 if (!java.util.Arrays.equals(expected_data, data)) {
200 throw new Exception(
Bernie Innocenti18050002018-04-19 20:53:00 +0900201 "\nprogram: " + HexDump.toHexString(program) +
Bernie Innocentia9949e92018-03-22 23:07:47 +0900202 "\ndata memory: " + HexDump.toHexString(data) +
Bernie Innocenti545d9362018-04-16 23:27:51 +0900203 "\nexpected: " + HexDump.toHexString(expected_data));
Bernie Innocentia9949e92018-03-22 23:07:47 +0900204 }
205 }
206
Paul Jensen9132f342016-04-13 15:00:26 -0400207 private void assertVerdict(int expected, ApfGenerator gen, byte[] packet, int filterAge)
208 throws IllegalInstructionException {
Bernie Innocentia9949e92018-03-22 23:07:47 +0900209 assertReturnCodesEqual(expected, apfSimulate(gen.generate(), packet, null,
210 filterAge));
Paul Jensen9132f342016-04-13 15:00:26 -0400211 }
212
213 private void assertPass(ApfGenerator gen, byte[] packet, int filterAge)
214 throws IllegalInstructionException {
215 assertVerdict(PASS, gen, packet, filterAge);
216 }
217
218 private void assertDrop(ApfGenerator gen, byte[] packet, int filterAge)
219 throws IllegalInstructionException {
220 assertVerdict(DROP, gen, packet, filterAge);
221 }
222
223 private void assertPass(ApfGenerator gen)
224 throws IllegalInstructionException {
225 assertVerdict(PASS, gen, new byte[MIN_PKT_SIZE], 0);
226 }
227
228 private void assertDrop(ApfGenerator gen)
229 throws IllegalInstructionException {
230 assertVerdict(DROP, gen, new byte[MIN_PKT_SIZE], 0);
231 }
232
233 /**
234 * Test each instruction by generating a program containing the instruction,
235 * generating bytecode for that program and running it through the
236 * interpreter to verify it functions correctly.
237 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900238 @Test
Paul Jensen9132f342016-04-13 15:00:26 -0400239 public void testApfInstructions() throws IllegalInstructionException {
240 // Empty program should pass because having the program counter reach the
241 // location immediately after the program indicates the packet should be
242 // passed to the AP.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900243 ApfGenerator gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400244 assertPass(gen);
245
246 // Test jumping to pass label.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900247 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400248 gen.addJump(gen.PASS_LABEL);
249 byte[] program = gen.generate();
250 assertEquals(1, program.length);
251 assertEquals((14 << 3) | (0 << 1) | 0, program[0]);
252 assertPass(program, new byte[MIN_PKT_SIZE], 0);
253
254 // Test jumping to drop label.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900255 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400256 gen.addJump(gen.DROP_LABEL);
257 program = gen.generate();
258 assertEquals(2, program.length);
259 assertEquals((14 << 3) | (1 << 1) | 0, program[0]);
260 assertEquals(1, program[1]);
261 assertDrop(program, new byte[15], 15);
262
263 // Test jumping if equal to 0.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900264 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400265 gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
266 assertDrop(gen);
267
268 // Test jumping if not equal to 0.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900269 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400270 gen.addJumpIfR0NotEquals(0, gen.DROP_LABEL);
271 assertPass(gen);
Bernie Innocentia9949e92018-03-22 23:07:47 +0900272 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400273 gen.addLoadImmediate(Register.R0, 1);
274 gen.addJumpIfR0NotEquals(0, gen.DROP_LABEL);
275 assertDrop(gen);
276
277 // Test jumping if registers equal.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900278 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400279 gen.addJumpIfR0EqualsR1(gen.DROP_LABEL);
280 assertDrop(gen);
281
282 // Test jumping if registers not equal.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900283 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400284 gen.addJumpIfR0NotEqualsR1(gen.DROP_LABEL);
285 assertPass(gen);
Bernie Innocentia9949e92018-03-22 23:07:47 +0900286 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400287 gen.addLoadImmediate(Register.R0, 1);
288 gen.addJumpIfR0NotEqualsR1(gen.DROP_LABEL);
289 assertDrop(gen);
290
291 // Test load immediate.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900292 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400293 gen.addLoadImmediate(Register.R0, 1234567890);
294 gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
295 assertDrop(gen);
296
297 // Test add.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900298 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400299 gen.addAdd(1234567890);
300 gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
301 assertDrop(gen);
302
303 // Test subtract.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900304 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400305 gen.addAdd(-1234567890);
306 gen.addJumpIfR0Equals(-1234567890, gen.DROP_LABEL);
307 assertDrop(gen);
308
309 // Test or.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900310 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400311 gen.addOr(1234567890);
312 gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
313 assertDrop(gen);
314
315 // Test and.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900316 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400317 gen.addLoadImmediate(Register.R0, 1234567890);
318 gen.addAnd(123456789);
319 gen.addJumpIfR0Equals(1234567890 & 123456789, gen.DROP_LABEL);
320 assertDrop(gen);
321
322 // Test left shift.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900323 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400324 gen.addLoadImmediate(Register.R0, 1234567890);
325 gen.addLeftShift(1);
326 gen.addJumpIfR0Equals(1234567890 << 1, gen.DROP_LABEL);
327 assertDrop(gen);
328
329 // Test right shift.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900330 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400331 gen.addLoadImmediate(Register.R0, 1234567890);
332 gen.addRightShift(1);
333 gen.addJumpIfR0Equals(1234567890 >> 1, gen.DROP_LABEL);
334 assertDrop(gen);
335
336 // Test multiply.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900337 gen = new ApfGenerator(MIN_APF_VERSION);
Andreas Gampe5b003112018-06-13 11:35:16 -0700338 gen.addLoadImmediate(Register.R0, 123456789);
Paul Jensen9132f342016-04-13 15:00:26 -0400339 gen.addMul(2);
Andreas Gampe5b003112018-06-13 11:35:16 -0700340 gen.addJumpIfR0Equals(123456789 * 2, gen.DROP_LABEL);
Paul Jensen9132f342016-04-13 15:00:26 -0400341 assertDrop(gen);
342
343 // Test divide.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900344 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400345 gen.addLoadImmediate(Register.R0, 1234567890);
346 gen.addDiv(2);
347 gen.addJumpIfR0Equals(1234567890 / 2, gen.DROP_LABEL);
348 assertDrop(gen);
349
350 // Test divide by zero.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900351 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400352 gen.addDiv(0);
353 gen.addJump(gen.DROP_LABEL);
354 assertPass(gen);
355
356 // Test add.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900357 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400358 gen.addLoadImmediate(Register.R1, 1234567890);
359 gen.addAddR1();
360 gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
361 assertDrop(gen);
362
363 // Test subtract.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900364 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400365 gen.addLoadImmediate(Register.R1, -1234567890);
366 gen.addAddR1();
367 gen.addJumpIfR0Equals(-1234567890, gen.DROP_LABEL);
368 assertDrop(gen);
369
370 // Test or.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900371 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400372 gen.addLoadImmediate(Register.R1, 1234567890);
373 gen.addOrR1();
374 gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
375 assertDrop(gen);
376
377 // Test and.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900378 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400379 gen.addLoadImmediate(Register.R0, 1234567890);
380 gen.addLoadImmediate(Register.R1, 123456789);
381 gen.addAndR1();
382 gen.addJumpIfR0Equals(1234567890 & 123456789, gen.DROP_LABEL);
383 assertDrop(gen);
384
385 // Test left shift.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900386 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400387 gen.addLoadImmediate(Register.R0, 1234567890);
388 gen.addLoadImmediate(Register.R1, 1);
389 gen.addLeftShiftR1();
390 gen.addJumpIfR0Equals(1234567890 << 1, gen.DROP_LABEL);
391 assertDrop(gen);
392
393 // Test right shift.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900394 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400395 gen.addLoadImmediate(Register.R0, 1234567890);
396 gen.addLoadImmediate(Register.R1, -1);
397 gen.addLeftShiftR1();
398 gen.addJumpIfR0Equals(1234567890 >> 1, gen.DROP_LABEL);
399 assertDrop(gen);
400
401 // Test multiply.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900402 gen = new ApfGenerator(MIN_APF_VERSION);
Andreas Gampe5b003112018-06-13 11:35:16 -0700403 gen.addLoadImmediate(Register.R0, 123456789);
Paul Jensen9132f342016-04-13 15:00:26 -0400404 gen.addLoadImmediate(Register.R1, 2);
405 gen.addMulR1();
Andreas Gampe5b003112018-06-13 11:35:16 -0700406 gen.addJumpIfR0Equals(123456789 * 2, gen.DROP_LABEL);
Paul Jensen9132f342016-04-13 15:00:26 -0400407 assertDrop(gen);
408
409 // Test divide.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900410 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400411 gen.addLoadImmediate(Register.R0, 1234567890);
412 gen.addLoadImmediate(Register.R1, 2);
413 gen.addDivR1();
414 gen.addJumpIfR0Equals(1234567890 / 2, gen.DROP_LABEL);
415 assertDrop(gen);
416
417 // Test divide by zero.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900418 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400419 gen.addDivR1();
420 gen.addJump(gen.DROP_LABEL);
421 assertPass(gen);
422
423 // Test byte load.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900424 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400425 gen.addLoad8(Register.R0, 1);
426 gen.addJumpIfR0Equals(45, gen.DROP_LABEL);
427 assertDrop(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
428
429 // Test out of bounds load.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900430 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400431 gen.addLoad8(Register.R0, 16);
432 gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
433 assertPass(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
434
435 // Test half-word load.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900436 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400437 gen.addLoad16(Register.R0, 1);
438 gen.addJumpIfR0Equals((45 << 8) | 67, gen.DROP_LABEL);
439 assertDrop(gen, new byte[]{123,45,67,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
440
441 // Test word load.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900442 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400443 gen.addLoad32(Register.R0, 1);
444 gen.addJumpIfR0Equals((45 << 24) | (67 << 16) | (89 << 8) | 12, gen.DROP_LABEL);
445 assertDrop(gen, new byte[]{123,45,67,89,12,0,0,0,0,0,0,0,0,0,0}, 0);
446
447 // Test byte indexed load.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900448 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400449 gen.addLoadImmediate(Register.R1, 1);
450 gen.addLoad8Indexed(Register.R0, 0);
451 gen.addJumpIfR0Equals(45, gen.DROP_LABEL);
452 assertDrop(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
453
454 // Test out of bounds indexed load.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900455 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400456 gen.addLoadImmediate(Register.R1, 8);
457 gen.addLoad8Indexed(Register.R0, 8);
458 gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
459 assertPass(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
460
461 // Test half-word indexed load.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900462 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400463 gen.addLoadImmediate(Register.R1, 1);
464 gen.addLoad16Indexed(Register.R0, 0);
465 gen.addJumpIfR0Equals((45 << 8) | 67, gen.DROP_LABEL);
466 assertDrop(gen, new byte[]{123,45,67,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
467
468 // Test word indexed load.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900469 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400470 gen.addLoadImmediate(Register.R1, 1);
471 gen.addLoad32Indexed(Register.R0, 0);
472 gen.addJumpIfR0Equals((45 << 24) | (67 << 16) | (89 << 8) | 12, gen.DROP_LABEL);
473 assertDrop(gen, new byte[]{123,45,67,89,12,0,0,0,0,0,0,0,0,0,0}, 0);
474
475 // Test jumping if greater than.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900476 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400477 gen.addJumpIfR0GreaterThan(0, gen.DROP_LABEL);
478 assertPass(gen);
Bernie Innocentia9949e92018-03-22 23:07:47 +0900479 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400480 gen.addLoadImmediate(Register.R0, 1);
481 gen.addJumpIfR0GreaterThan(0, gen.DROP_LABEL);
482 assertDrop(gen);
483
484 // Test jumping if less than.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900485 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400486 gen.addJumpIfR0LessThan(0, gen.DROP_LABEL);
487 assertPass(gen);
Bernie Innocentia9949e92018-03-22 23:07:47 +0900488 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400489 gen.addJumpIfR0LessThan(1, gen.DROP_LABEL);
490 assertDrop(gen);
491
492 // Test jumping if any bits set.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900493 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400494 gen.addJumpIfR0AnyBitsSet(3, gen.DROP_LABEL);
495 assertPass(gen);
Bernie Innocentia9949e92018-03-22 23:07:47 +0900496 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400497 gen.addLoadImmediate(Register.R0, 1);
498 gen.addJumpIfR0AnyBitsSet(3, gen.DROP_LABEL);
499 assertDrop(gen);
Bernie Innocentia9949e92018-03-22 23:07:47 +0900500 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400501 gen.addLoadImmediate(Register.R0, 3);
502 gen.addJumpIfR0AnyBitsSet(3, gen.DROP_LABEL);
503 assertDrop(gen);
504
505 // Test jumping if register greater than.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900506 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400507 gen.addJumpIfR0GreaterThanR1(gen.DROP_LABEL);
508 assertPass(gen);
Bernie Innocentia9949e92018-03-22 23:07:47 +0900509 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400510 gen.addLoadImmediate(Register.R0, 2);
511 gen.addLoadImmediate(Register.R1, 1);
512 gen.addJumpIfR0GreaterThanR1(gen.DROP_LABEL);
513 assertDrop(gen);
514
515 // Test jumping if register less than.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900516 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400517 gen.addJumpIfR0LessThanR1(gen.DROP_LABEL);
518 assertPass(gen);
Bernie Innocentia9949e92018-03-22 23:07:47 +0900519 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400520 gen.addLoadImmediate(Register.R1, 1);
521 gen.addJumpIfR0LessThanR1(gen.DROP_LABEL);
522 assertDrop(gen);
523
524 // Test jumping if any bits set in register.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900525 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400526 gen.addLoadImmediate(Register.R1, 3);
527 gen.addJumpIfR0AnyBitsSetR1(gen.DROP_LABEL);
528 assertPass(gen);
Bernie Innocentia9949e92018-03-22 23:07:47 +0900529 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400530 gen.addLoadImmediate(Register.R1, 3);
531 gen.addLoadImmediate(Register.R0, 1);
532 gen.addJumpIfR0AnyBitsSetR1(gen.DROP_LABEL);
533 assertDrop(gen);
Bernie Innocentia9949e92018-03-22 23:07:47 +0900534 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400535 gen.addLoadImmediate(Register.R1, 3);
536 gen.addLoadImmediate(Register.R0, 3);
537 gen.addJumpIfR0AnyBitsSetR1(gen.DROP_LABEL);
538 assertDrop(gen);
539
540 // Test load from memory.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900541 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400542 gen.addLoadFromMemory(Register.R0, 0);
543 gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
544 assertDrop(gen);
545
546 // Test store to memory.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900547 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400548 gen.addLoadImmediate(Register.R1, 1234567890);
549 gen.addStoreToMemory(Register.R1, 12);
550 gen.addLoadFromMemory(Register.R0, 12);
551 gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
552 assertDrop(gen);
553
554 // Test filter age pre-filled memory.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900555 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400556 gen.addLoadFromMemory(Register.R0, gen.FILTER_AGE_MEMORY_SLOT);
557 gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
558 assertDrop(gen, new byte[MIN_PKT_SIZE], 1234567890);
559
560 // Test packet size pre-filled memory.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900561 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400562 gen.addLoadFromMemory(Register.R0, gen.PACKET_SIZE_MEMORY_SLOT);
563 gen.addJumpIfR0Equals(MIN_PKT_SIZE, gen.DROP_LABEL);
564 assertDrop(gen);
565
566 // Test IPv4 header size pre-filled memory.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900567 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400568 gen.addLoadFromMemory(Register.R0, gen.IPV4_HEADER_SIZE_MEMORY_SLOT);
569 gen.addJumpIfR0Equals(20, gen.DROP_LABEL);
570 assertDrop(gen, new byte[]{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x45}, 0);
571
572 // Test not.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900573 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400574 gen.addLoadImmediate(Register.R0, 1234567890);
575 gen.addNot(Register.R0);
576 gen.addJumpIfR0Equals(~1234567890, gen.DROP_LABEL);
577 assertDrop(gen);
578
579 // Test negate.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900580 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400581 gen.addLoadImmediate(Register.R0, 1234567890);
582 gen.addNeg(Register.R0);
583 gen.addJumpIfR0Equals(-1234567890, gen.DROP_LABEL);
584 assertDrop(gen);
585
586 // Test move.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900587 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400588 gen.addLoadImmediate(Register.R1, 1234567890);
589 gen.addMove(Register.R0);
590 gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
591 assertDrop(gen);
Bernie Innocentia9949e92018-03-22 23:07:47 +0900592 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400593 gen.addLoadImmediate(Register.R0, 1234567890);
594 gen.addMove(Register.R1);
595 gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
596 assertDrop(gen);
597
598 // Test swap.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900599 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400600 gen.addLoadImmediate(Register.R1, 1234567890);
601 gen.addSwap();
602 gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
603 assertDrop(gen);
Bernie Innocentia9949e92018-03-22 23:07:47 +0900604 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400605 gen.addLoadImmediate(Register.R0, 1234567890);
606 gen.addSwap();
607 gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
608 assertDrop(gen);
609
610 // Test jump if bytes not equal.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900611 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400612 gen.addLoadImmediate(Register.R0, 1);
613 gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{123}, gen.DROP_LABEL);
614 program = gen.generate();
615 assertEquals(6, program.length);
616 assertEquals((13 << 3) | (1 << 1) | 0, program[0]);
617 assertEquals(1, program[1]);
618 assertEquals(((20 << 3) | (1 << 1) | 0) - 256, program[2]);
619 assertEquals(1, program[3]);
620 assertEquals(1, program[4]);
621 assertEquals(123, program[5]);
622 assertDrop(program, new byte[MIN_PKT_SIZE], 0);
Bernie Innocentia9949e92018-03-22 23:07:47 +0900623 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400624 gen.addLoadImmediate(Register.R0, 1);
625 gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{123}, gen.DROP_LABEL);
Hugo Benichi961ca492016-09-02 11:04:34 +0900626 byte[] packet123 = {0,123,0,0,0,0,0,0,0,0,0,0,0,0,0};
Paul Jensen9132f342016-04-13 15:00:26 -0400627 assertPass(gen, packet123, 0);
Bernie Innocentia9949e92018-03-22 23:07:47 +0900628 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400629 gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{123}, gen.DROP_LABEL);
630 assertDrop(gen, packet123, 0);
Bernie Innocentia9949e92018-03-22 23:07:47 +0900631 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400632 gen.addLoadImmediate(Register.R0, 1);
633 gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{1,2,30,4,5}, gen.DROP_LABEL);
Hugo Benichi961ca492016-09-02 11:04:34 +0900634 byte[] packet12345 = {0,1,2,3,4,5,0,0,0,0,0,0,0,0,0};
Paul Jensen9132f342016-04-13 15:00:26 -0400635 assertDrop(gen, packet12345, 0);
Bernie Innocentia9949e92018-03-22 23:07:47 +0900636 gen = new ApfGenerator(MIN_APF_VERSION);
Paul Jensen9132f342016-04-13 15:00:26 -0400637 gen.addLoadImmediate(Register.R0, 1);
638 gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{1,2,3,4,5}, gen.DROP_LABEL);
639 assertPass(gen, packet12345, 0);
640 }
641
Bernie Innocentia9949e92018-03-22 23:07:47 +0900642 @Test(expected = ApfGenerator.IllegalInstructionException.class)
643 public void testApfGeneratorWantsV2OrGreater() throws Exception {
644 // The minimum supported APF version is 2.
645 new ApfGenerator(1);
646 }
647
648 @Test
649 public void testApfDataOpcodesWantApfV3() throws IllegalInstructionException, Exception {
650 ApfGenerator gen = new ApfGenerator(MIN_APF_VERSION);
651 try {
652 gen.addStoreData(Register.R0, 0);
653 fail();
654 } catch (IllegalInstructionException expected) {
655 /* pass */
656 }
657 try {
658 gen.addLoadData(Register.R0, 0);
659 fail();
660 } catch (IllegalInstructionException expected) {
661 /* pass */
662 }
663 }
664
Bernie Innocenti18050002018-04-19 20:53:00 +0900665 /**
666 * Test that the generator emits immediates using the shortest possible encoding.
667 */
668 @Test
669 public void testImmediateEncoding() throws IllegalInstructionException {
Bernie Innocenti18050002018-04-19 20:53:00 +0900670 ApfGenerator gen;
671
672 // 0-byte immediate: li R0, 0
Bernie Innocenti3d479d92018-04-20 23:31:33 +0900673 gen = new ApfGenerator(4);
Bernie Innocenti18050002018-04-19 20:53:00 +0900674 gen.addLoadImmediate(Register.R0, 0);
Bernie Innocenti3d479d92018-04-20 23:31:33 +0900675 assertProgramEquals(new byte[]{LI_OP | SIZE0}, gen.generate());
Bernie Innocenti18050002018-04-19 20:53:00 +0900676
677 // 1-byte immediate: li R0, 42
Bernie Innocenti3d479d92018-04-20 23:31:33 +0900678 gen = new ApfGenerator(4);
Bernie Innocenti18050002018-04-19 20:53:00 +0900679 gen.addLoadImmediate(Register.R0, 42);
Bernie Innocenti3d479d92018-04-20 23:31:33 +0900680 assertProgramEquals(new byte[]{LI_OP | SIZE8, 42}, gen.generate());
Bernie Innocenti18050002018-04-19 20:53:00 +0900681
682 // 2-byte immediate: li R1, 0x1234
Bernie Innocenti3d479d92018-04-20 23:31:33 +0900683 gen = new ApfGenerator(4);
Bernie Innocenti18050002018-04-19 20:53:00 +0900684 gen.addLoadImmediate(Register.R1, 0x1234);
Bernie Innocenti3d479d92018-04-20 23:31:33 +0900685 assertProgramEquals(new byte[]{LI_OP | SIZE16 | R1, 0x12, 0x34}, gen.generate());
Bernie Innocenti18050002018-04-19 20:53:00 +0900686
687 // 4-byte immediate: li R0, 0x12345678
688 gen = new ApfGenerator(3);
689 gen.addLoadImmediate(Register.R0, 0x12345678);
690 assertProgramEquals(
Bernie Innocenti3d479d92018-04-20 23:31:33 +0900691 new byte[]{LI_OP | SIZE32, 0x12, 0x34, 0x56, 0x78},
Bernie Innocenti18050002018-04-19 20:53:00 +0900692 gen.generate());
693 }
694
695 /**
696 * Test that the generator emits negative immediates using the shortest possible encoding.
697 */
698 @Test
699 public void testNegativeImmediateEncoding() throws IllegalInstructionException {
Bernie Innocenti18050002018-04-19 20:53:00 +0900700 ApfGenerator gen;
701
702 // 1-byte negative immediate: li R0, -42
703 gen = new ApfGenerator(3);
704 gen.addLoadImmediate(Register.R0, -42);
Bernie Innocenti3d479d92018-04-20 23:31:33 +0900705 assertProgramEquals(new byte[]{LI_OP | SIZE8, -42}, gen.generate());
Bernie Innocenti18050002018-04-19 20:53:00 +0900706
Bernie Innocenti3d479d92018-04-20 23:31:33 +0900707 // 2-byte negative immediate: li R1, -0x1122
Bernie Innocenti18050002018-04-19 20:53:00 +0900708 gen = new ApfGenerator(3);
709 gen.addLoadImmediate(Register.R1, -0x1122);
Bernie Innocenti3d479d92018-04-20 23:31:33 +0900710 assertProgramEquals(new byte[]{LI_OP | SIZE16 | R1, (byte)0xEE, (byte)0xDE},
Bernie Innocenti18050002018-04-19 20:53:00 +0900711 gen.generate());
712
713 // 4-byte negative immediate: li R0, -0x11223344
714 gen = new ApfGenerator(3);
715 gen.addLoadImmediate(Register.R0, -0x11223344);
716 assertProgramEquals(
Bernie Innocenti3d479d92018-04-20 23:31:33 +0900717 new byte[]{LI_OP | SIZE32, (byte)0xEE, (byte)0xDD, (byte)0xCC, (byte)0xBC},
Bernie Innocenti18050002018-04-19 20:53:00 +0900718 gen.generate());
719 }
720
Bernie Innocenti3d479d92018-04-20 23:31:33 +0900721 /**
722 * Test that the generator correctly emits positive and negative immediates for LDDW/STDW.
723 */
724 @Test
725 public void testLoadStoreDataEncoding() throws IllegalInstructionException {
726 ApfGenerator gen;
727
728 // Load data with no offset: lddw R0, [0 + r1]
729 gen = new ApfGenerator(3);
730 gen.addLoadData(Register.R0, 0);
731 assertProgramEquals(new byte[]{LDDW_OP | SIZE0}, gen.generate());
732
733 // Store data with 8bit negative offset: lddw r0, [-42 + r1]
734 gen = new ApfGenerator(3);
735 gen.addStoreData(Register.R0, -42);
736 assertProgramEquals(new byte[]{STDW_OP | SIZE8, -42}, gen.generate());
737
738 // Store data to R1 with 16bit negative offset: stdw r1, [-0x1122 + r0]
739 gen = new ApfGenerator(3);
740 gen.addStoreData(Register.R1, -0x1122);
741 assertProgramEquals(new byte[]{STDW_OP | SIZE16 | R1, (byte)0xEE, (byte)0xDE},
742 gen.generate());
743
744 // Load data to R1 with 32bit negative offset: lddw r1, [0xDEADBEEF + r0]
745 gen = new ApfGenerator(3);
746 gen.addLoadData(Register.R1, 0xDEADBEEF);
747 assertProgramEquals(
748 new byte[]{LDDW_OP | SIZE32 | R1, (byte)0xDE, (byte)0xAD, (byte)0xBE, (byte)0xEF},
749 gen.generate());
750 }
751
752 /**
753 * Test that the interpreter correctly executes STDW with a negative 8bit offset
754 */
Bernie Innocentia9949e92018-03-22 23:07:47 +0900755 @Test
756 public void testApfDataWrite() throws IllegalInstructionException, Exception {
757 byte[] packet = new byte[MIN_PKT_SIZE];
Bernie Innocenti545d9362018-04-16 23:27:51 +0900758 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 +0900759 byte[] expected_data = data.clone();
760
761 // No memory access instructions: should leave the data segment untouched.
762 ApfGenerator gen = new ApfGenerator(3);
763 assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data);
764
Bernie Innocenti545d9362018-04-16 23:27:51 +0900765 // Expect value 0x87654321 to be stored starting from address -11 from the end of the
766 // data buffer, in big-endian order.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900767 gen = new ApfGenerator(3);
768 gen.addLoadImmediate(Register.R0, 0x87654321);
Bernie Innocenti545d9362018-04-16 23:27:51 +0900769 gen.addLoadImmediate(Register.R1, -5);
770 gen.addStoreData(Register.R0, -6); // -5 + -6 = -11 (offset +5 with data_len=16)
Bernie Innocentia9949e92018-03-22 23:07:47 +0900771 expected_data[5] = (byte)0x87;
772 expected_data[6] = (byte)0x65;
773 expected_data[7] = (byte)0x43;
774 expected_data[8] = (byte)0x21;
775 assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data);
776 }
777
Bernie Innocenti3d479d92018-04-20 23:31:33 +0900778 /**
779 * Test that the interpreter correctly executes LDDW with a negative 16bit offset
780 */
Bernie Innocentia9949e92018-03-22 23:07:47 +0900781 @Test
782 public void testApfDataRead() throws IllegalInstructionException, Exception {
Bernie Innocenti545d9362018-04-16 23:27:51 +0900783 // Program that DROPs if address 10 (-6) contains 0x87654321.
Bernie Innocentia9949e92018-03-22 23:07:47 +0900784 ApfGenerator gen = new ApfGenerator(3);
Bernie Innocenti3d479d92018-04-20 23:31:33 +0900785 gen.addLoadImmediate(Register.R1, 1000);
786 gen.addLoadData(Register.R0, -1006); // 1000 + -1006 = -6 (offset +10 with data_len=16)
Bernie Innocentia9949e92018-03-22 23:07:47 +0900787 gen.addJumpIfR0Equals(0x87654321, gen.DROP_LABEL);
788 byte[] program = gen.generate();
789 byte[] packet = new byte[MIN_PKT_SIZE];
790
791 // Content is incorrect (last byte does not match) -> PASS
Bernie Innocenti545d9362018-04-16 23:27:51 +0900792 byte[] data = new byte[16];
Bernie Innocentia9949e92018-03-22 23:07:47 +0900793 data[10] = (byte)0x87;
794 data[11] = (byte)0x65;
795 data[12] = (byte)0x43;
796 data[13] = (byte)0x00; // != 0x21
797 byte[] expected_data = data.clone();
798 assertDataMemoryContents(PASS, program, packet, data, expected_data);
799
800 // Fix the last byte -> conditional jump taken -> DROP
801 data[13] = (byte)0x21;
802 expected_data = data;
803 assertDataMemoryContents(DROP, program, packet, data, expected_data);
804 }
805
Bernie Innocenti3d479d92018-04-20 23:31:33 +0900806 /**
807 * Test that the interpreter correctly executes LDDW followed by a STDW.
808 * To cover a few more edge cases, LDDW has a 0bit offset, while STDW has a positive 8bit
809 * offset.
810 */
Bernie Innocentia9949e92018-03-22 23:07:47 +0900811 @Test
812 public void testApfDataReadModifyWrite() throws IllegalInstructionException, Exception {
813 ApfGenerator gen = new ApfGenerator(3);
Bernie Innocenti545d9362018-04-16 23:27:51 +0900814 gen.addLoadImmediate(Register.R1, -22);
815 gen.addLoadData(Register.R0, 0); // Load from address 32 -22 + 0 = 10
Bernie Innocentia9949e92018-03-22 23:07:47 +0900816 gen.addAdd(0x78453412); // 87654321 + 78453412 = FFAA7733
Bernie Innocenti545d9362018-04-16 23:27:51 +0900817 gen.addStoreData(Register.R0, 4); // Write back to address 32 -22 + 4 = 14
Bernie Innocentia9949e92018-03-22 23:07:47 +0900818
819 byte[] packet = new byte[MIN_PKT_SIZE];
820 byte[] data = new byte[32];
821 data[10] = (byte)0x87;
822 data[11] = (byte)0x65;
823 data[12] = (byte)0x43;
824 data[13] = (byte)0x21;
825 byte[] expected_data = data.clone();
826 expected_data[14] = (byte)0xFF;
827 expected_data[15] = (byte)0xAA;
828 expected_data[16] = (byte)0x77;
829 expected_data[17] = (byte)0x33;
830 assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data);
831 }
832
833 @Test
834 public void testApfDataBoundChecking() throws IllegalInstructionException, Exception {
835 byte[] packet = new byte[MIN_PKT_SIZE];
836 byte[] data = new byte[32];
837 byte[] expected_data = data;
838
839 // Program that DROPs unconditionally. This is our the baseline.
840 ApfGenerator gen = new ApfGenerator(3);
841 gen.addLoadImmediate(Register.R0, 3);
842 gen.addLoadData(Register.R1, 7);
843 gen.addJump(gen.DROP_LABEL);
844 assertDataMemoryContents(DROP, gen.generate(), packet, data, expected_data);
845
846 // Same program as before, but this time we're trying to load past the end of the data.
847 gen = new ApfGenerator(3);
848 gen.addLoadImmediate(Register.R0, 20);
849 gen.addLoadData(Register.R1, 15); // 20 + 15 > 32
850 gen.addJump(gen.DROP_LABEL); // Not reached.
851 assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data);
852
853 // Subtracting an immediate should work...
854 gen = new ApfGenerator(3);
855 gen.addLoadImmediate(Register.R0, 20);
856 gen.addLoadData(Register.R1, -4);
857 gen.addJump(gen.DROP_LABEL);
858 assertDataMemoryContents(DROP, gen.generate(), packet, data, expected_data);
859
Bernie Innocenti545d9362018-04-16 23:27:51 +0900860 // ...and underflowing simply wraps around to the end of the buffer...
Bernie Innocentia9949e92018-03-22 23:07:47 +0900861 gen = new ApfGenerator(3);
862 gen.addLoadImmediate(Register.R0, 20);
863 gen.addLoadData(Register.R1, -30);
Bernie Innocenti545d9362018-04-16 23:27:51 +0900864 gen.addJump(gen.DROP_LABEL);
865 assertDataMemoryContents(DROP, gen.generate(), packet, data, expected_data);
866
867 // ...but doesn't allow accesses before the start of the buffer
868 gen = new ApfGenerator(3);
869 gen.addLoadImmediate(Register.R0, 20);
870 gen.addLoadData(Register.R1, -1000);
Bernie Innocentia9949e92018-03-22 23:07:47 +0900871 gen.addJump(gen.DROP_LABEL); // Not reached.
872 assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data);
873 }
874
Paul Jensen9132f342016-04-13 15:00:26 -0400875 /**
876 * Generate some BPF programs, translate them to APF, then run APF and BPF programs
877 * over packet traces and verify both programs filter out the same packets.
878 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900879 @Test
Paul Jensen9132f342016-04-13 15:00:26 -0400880 public void testApfAgainstBpf() throws Exception {
881 String[] tcpdump_filters = new String[]{ "udp", "tcp", "icmp", "icmp6", "udp port 53",
882 "arp", "dst 239.255.255.250", "arp or tcp or udp port 53", "net 192.168.1.0/24",
883 "arp or icmp6 or portrange 53-54", "portrange 53-54 or portrange 100-50000",
884 "tcp[tcpflags] & (tcp-ack|tcp-fin) != 0 and (ip[2:2] > 57 or icmp)" };
885 String pcap_filename = stageFile(R.raw.apf);
886 for (String tcpdump_filter : tcpdump_filters) {
887 byte[] apf_program = Bpf2Apf.convert(compileToBpf(tcpdump_filter));
888 assertTrue("Failed to match for filter: " + tcpdump_filter,
889 compareBpfApf(tcpdump_filter, pcap_filename, apf_program));
890 }
891 }
892
Aaron Huang785e5f12018-10-31 15:57:48 +0800893 /**
894 * Generate APF program, run pcap file though APF filter, then check all the packets in the file
895 * should be dropped.
896 */
897 @Test
898 public void testApfFilterPcapFile() throws Exception {
899 final byte[] MOCK_PCAP_IPV4_ADDR = {(byte) 172, 16, 7, (byte) 151};
900 String pcapFilename = stageFile(R.raw.apfPcap);
901 MockIpClientCallback ipClientCallback = new MockIpClientCallback();
902 LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_PCAP_IPV4_ADDR), 16);
903 LinkProperties lp = new LinkProperties();
904 lp.addLinkAddress(link);
905
906 ApfConfiguration config = getDefaultConfig();
907 ApfCapabilities MOCK_APF_PCAP_CAPABILITIES = new ApfCapabilities(4, 1700, ARPHRD_ETHER);
908 config.apfCapabilities = MOCK_APF_PCAP_CAPABILITIES;
909 config.multicastFilter = DROP_MULTICAST;
910 config.ieee802_3Filter = DROP_802_3_FRAMES;
911 TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
912 apfFilter.setLinkProperties(lp);
913 byte[] program = ipClientCallback.getApfProgram();
914 byte[] data = new byte[ApfFilter.Counter.totalSize()];
915 final boolean result;
916
917 result = dropsAllPackets(program, data, pcapFilename);
918 Log.i(TAG, "testApfFilterPcapFile(): Data counters: " + HexDump.toHexString(data, false));
919
920 assertTrue("Failed to drop all packets by filter. \nAPF counters:" +
921 HexDump.toHexString(data, false), result);
922 }
923
Remi NGUYEN VAN3c600a12019-01-10 19:12:46 +0900924 private class MockIpClientCallback extends IpClientCallbacksWrapper {
Paul Jensen9132f342016-04-13 15:00:26 -0400925 private final ConditionVariable mGotApfProgram = new ConditionVariable();
926 private byte[] mLastApfProgram;
927
Remi NGUYEN VAN3c600a12019-01-10 19:12:46 +0900928 MockIpClientCallback() {
929 super(mock(IIpClientCallbacks.class), mock(SharedLog.class));
930 }
931
Paul Jensen9132f342016-04-13 15:00:26 -0400932 @Override
933 public void installPacketFilter(byte[] filter) {
934 mLastApfProgram = filter;
935 mGotApfProgram.open();
936 }
937
938 public void resetApfProgramWait() {
939 mGotApfProgram.close();
940 }
941
942 public byte[] getApfProgram() {
943 assertTrue(mGotApfProgram.block(TIMEOUT_MS));
944 return mLastApfProgram;
945 }
Lorenzo Colitti8995d852016-06-23 15:24:46 +0900946
947 public void assertNoProgramUpdate() {
948 assertFalse(mGotApfProgram.block(TIMEOUT_MS));
949 }
Paul Jensen9132f342016-04-13 15:00:26 -0400950 }
951
952 private static class TestApfFilter extends ApfFilter {
Bernie Innocenti3d479d92018-04-20 23:31:33 +0900953 public static final byte[] MOCK_MAC_ADDR = {1,2,3,4,5,6};
Paul Jensen9132f342016-04-13 15:00:26 -0400954
Hugo Benichi72166362017-10-13 16:32:20 +0900955 private FileDescriptor mWriteSocket;
Hugo Benichi4456f332016-12-19 14:50:52 +0900956 private final long mFixedTimeMs = SystemClock.elapsedRealtime();
957
Bernie Innocentie2c70f82018-03-28 20:11:49 +0900958 public TestApfFilter(Context context, ApfConfiguration config,
Remi NGUYEN VAN3c600a12019-01-10 19:12:46 +0900959 IpClientCallbacksWrapper ipClientCallback, IpConnectivityLog log) throws Exception {
Erik Kline8d1fe542018-03-12 23:18:58 +0900960 super(context, config, InterfaceParams.getByName("lo"), ipClientCallback, log);
Paul Jensen9132f342016-04-13 15:00:26 -0400961 }
962
963 // Pretend an RA packet has been received and show it to ApfFilter.
964 public void pretendPacketReceived(byte[] packet) throws IOException, ErrnoException {
965 // ApfFilter's ReceiveThread will be waiting to read this.
966 Os.write(mWriteSocket, packet, 0, packet.length);
967 }
968
969 @Override
Hugo Benichi4456f332016-12-19 14:50:52 +0900970 protected long currentTimeSeconds() {
971 return mFixedTimeMs / DateUtils.SECOND_IN_MILLIS;
972 }
973
974 @Override
Paul Jensen9132f342016-04-13 15:00:26 -0400975 void maybeStartFilter() {
976 mHardwareAddress = MOCK_MAC_ADDR;
977 installNewProgramLocked();
978
979 // Create two sockets, "readSocket" and "mWriteSocket" and connect them together.
980 FileDescriptor readSocket = new FileDescriptor();
981 mWriteSocket = new FileDescriptor();
982 try {
983 Os.socketpair(AF_UNIX, SOCK_STREAM, 0, mWriteSocket, readSocket);
984 } catch (ErrnoException e) {
985 fail();
986 return;
987 }
988 // Now pass readSocket to ReceiveThread as if it was setup to read raw RAs.
989 // This allows us to pretend RA packets have been recieved via pretendPacketReceived().
990 mReceiveThread = new ReceiveThread(readSocket);
991 mReceiveThread.start();
992 }
993
994 @Override
995 public void shutdown() {
996 super.shutdown();
997 IoUtils.closeQuietly(mWriteSocket);
998 }
999 }
1000
1001 private static final int ETH_HEADER_LEN = 14;
Hugo Benichi38db9762016-07-12 15:08:50 +09001002 private static final int ETH_DEST_ADDR_OFFSET = 0;
Paul Jensen9132f342016-04-13 15:00:26 -04001003 private static final int ETH_ETHERTYPE_OFFSET = 12;
Hugo Benichi961ca492016-09-02 11:04:34 +09001004 private static final byte[] ETH_BROADCAST_MAC_ADDRESS =
1005 {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff };
Paul Jensen9132f342016-04-13 15:00:26 -04001006
Aaron Huanga63c40e2019-01-15 16:53:51 +08001007 private static final int IPV4_HEADER_LEN = 20;
Paul Jensen9132f342016-04-13 15:00:26 -04001008 private static final int IPV4_VERSION_IHL_OFFSET = ETH_HEADER_LEN + 0;
Aaron Huanga63c40e2019-01-15 16:53:51 +08001009 private static final int IPV4_TOTAL_LENGTH_OFFSET = ETH_HEADER_LEN + 2;
Paul Jensen9132f342016-04-13 15:00:26 -04001010 private static final int IPV4_PROTOCOL_OFFSET = ETH_HEADER_LEN + 9;
Aaron Huanga63c40e2019-01-15 16:53:51 +08001011 private static final int IPV4_SRC_ADDR_OFFSET = ETH_HEADER_LEN + 12;
Paul Jensen9132f342016-04-13 15:00:26 -04001012 private static final int IPV4_DEST_ADDR_OFFSET = ETH_HEADER_LEN + 16;
Aaron Huanga63c40e2019-01-15 16:53:51 +08001013 private static final int IPV4_TCP_HEADER_LEN = 20;
1014 private static final int IPV4_TCP_HEADER_OFFSET = ETH_HEADER_LEN + IPV4_HEADER_LEN;
1015 private static final int IPV4_TCP_SRC_PORT_OFFSET = IPV4_TCP_HEADER_OFFSET + 0;
1016 private static final int IPV4_TCP_DEST_PORT_OFFSET = IPV4_TCP_HEADER_OFFSET + 2;
1017 private static final int IPV4_TCP_SEQ_NUM_OFFSET = IPV4_TCP_HEADER_OFFSET + 4;
1018 private static final int IPV4_TCP_ACK_NUM_OFFSET = IPV4_TCP_HEADER_OFFSET + 8;
1019 private static final int IPV4_TCP_HEADER_LENGTH_OFFSET = IPV4_TCP_HEADER_OFFSET + 12;
Xiao Mad36a89c2019-02-10 14:52:37 +09001020 private static final int IPV4_TCP_HEADER_FLAG_OFFSET = IPV4_TCP_HEADER_OFFSET + 13;
Hugo Benichi961ca492016-09-02 11:04:34 +09001021 private static final byte[] IPV4_BROADCAST_ADDRESS =
1022 {(byte) 255, (byte) 255, (byte) 255, (byte) 255};
Paul Jensen9132f342016-04-13 15:00:26 -04001023
1024 private static final int IPV6_NEXT_HEADER_OFFSET = ETH_HEADER_LEN + 6;
1025 private static final int IPV6_HEADER_LEN = 40;
Aaron Huanga63c40e2019-01-15 16:53:51 +08001026 private static final int IPV6_SRC_ADDR_OFFSET = ETH_HEADER_LEN + 8;
Paul Jensen9132f342016-04-13 15:00:26 -04001027 private static final int IPV6_DEST_ADDR_OFFSET = ETH_HEADER_LEN + 24;
Aaron Huanga63c40e2019-01-15 16:53:51 +08001028 private static final int IPV6_TCP_HEADER_OFFSET = ETH_HEADER_LEN + IPV6_HEADER_LEN;
1029 private static final int IPV6_TCP_SRC_PORT_OFFSET = IPV6_TCP_HEADER_OFFSET + 0;
1030 private static final int IPV6_TCP_DEST_PORT_OFFSET = IPV6_TCP_HEADER_OFFSET + 2;
1031 private static final int IPV6_TCP_SEQ_NUM_OFFSET = IPV6_TCP_HEADER_OFFSET + 4;
1032 private static final int IPV6_TCP_ACK_NUM_OFFSET = IPV6_TCP_HEADER_OFFSET + 8;
Paul Jensen9132f342016-04-13 15:00:26 -04001033 // The IPv6 all nodes address ff02::1
1034 private static final byte[] IPV6_ALL_NODES_ADDRESS =
Hugo Benichi961ca492016-09-02 11:04:34 +09001035 { (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
Hugo Benichi02428982016-12-03 02:41:05 +09001036 private static final byte[] IPV6_ALL_ROUTERS_ADDRESS =
1037 { (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 };
Paul Jensen9132f342016-04-13 15:00:26 -04001038
1039 private static final int ICMP6_TYPE_OFFSET = ETH_HEADER_LEN + IPV6_HEADER_LEN;
Hugo Benichi02428982016-12-03 02:41:05 +09001040 private static final int ICMP6_ROUTER_SOLICITATION = 133;
Paul Jensen9132f342016-04-13 15:00:26 -04001041 private static final int ICMP6_ROUTER_ADVERTISEMENT = 134;
Hugo Benichi02428982016-12-03 02:41:05 +09001042 private static final int ICMP6_NEIGHBOR_SOLICITATION = 135;
Paul Jensen9132f342016-04-13 15:00:26 -04001043 private static final int ICMP6_NEIGHBOR_ANNOUNCEMENT = 136;
1044
1045 private static final int ICMP6_RA_HEADER_LEN = 16;
1046 private static final int ICMP6_RA_ROUTER_LIFETIME_OFFSET =
1047 ETH_HEADER_LEN + IPV6_HEADER_LEN + 6;
1048 private static final int ICMP6_RA_CHECKSUM_OFFSET =
1049 ETH_HEADER_LEN + IPV6_HEADER_LEN + 2;
1050 private static final int ICMP6_RA_OPTION_OFFSET =
1051 ETH_HEADER_LEN + IPV6_HEADER_LEN + ICMP6_RA_HEADER_LEN;
1052
1053 private static final int ICMP6_PREFIX_OPTION_TYPE = 3;
1054 private static final int ICMP6_PREFIX_OPTION_LEN = 32;
1055 private static final int ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET = 4;
1056 private static final int ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_OFFSET = 8;
1057
1058 // From RFC6106: Recursive DNS Server option
1059 private static final int ICMP6_RDNSS_OPTION_TYPE = 25;
1060 // From RFC6106: DNS Search List option
1061 private static final int ICMP6_DNSSL_OPTION_TYPE = 31;
1062
1063 // From RFC4191: Route Information option
1064 private static final int ICMP6_ROUTE_INFO_OPTION_TYPE = 24;
1065 // Above three options all have the same format:
1066 private static final int ICMP6_4_BYTE_OPTION_LEN = 8;
1067 private static final int ICMP6_4_BYTE_LIFETIME_OFFSET = 4;
1068 private static final int ICMP6_4_BYTE_LIFETIME_LEN = 4;
1069
1070 private static final int UDP_HEADER_LEN = 8;
1071 private static final int UDP_DESTINATION_PORT_OFFSET = ETH_HEADER_LEN + 22;
1072
1073 private static final int DHCP_CLIENT_PORT = 68;
1074 private static final int DHCP_CLIENT_MAC_OFFSET = ETH_HEADER_LEN + UDP_HEADER_LEN + 48;
1075
Hugo Benichi4fc3ee52016-06-02 11:20:27 +09001076 private static final int ARP_HEADER_OFFSET = ETH_HEADER_LEN;
Hugo Benichi961ca492016-09-02 11:04:34 +09001077 private static final byte[] ARP_IPV4_REQUEST_HEADER = {
Paul Jensen9132f342016-04-13 15:00:26 -04001078 0, 1, // Hardware type: Ethernet (1)
1079 8, 0, // Protocol type: IP (0x0800)
1080 6, // Hardware size: 6
1081 4, // Protocol size: 4
1082 0, 1 // Opcode: request (1)
1083 };
Hugo Benichi961ca492016-09-02 11:04:34 +09001084 private static final byte[] ARP_IPV4_REPLY_HEADER = {
Hugo Benichi38db9762016-07-12 15:08:50 +09001085 0, 1, // Hardware type: Ethernet (1)
1086 8, 0, // Protocol type: IP (0x0800)
1087 6, // Hardware size: 6
1088 4, // Protocol size: 4
1089 0, 2 // Opcode: reply (2)
1090 };
Aaron Huang04ed6a32018-11-15 20:30:46 +08001091 private static final int ARP_SOURCE_IP_ADDRESS_OFFSET = ARP_HEADER_OFFSET + 14;
1092 private static final int ARP_TARGET_IP_ADDRESS_OFFSET = ARP_HEADER_OFFSET + 24;
Paul Jensen9132f342016-04-13 15:00:26 -04001093
Hugo Benichi961ca492016-09-02 11:04:34 +09001094 private static final byte[] MOCK_IPV4_ADDR = {10, 0, 0, 1};
Hugo Benichi7d21eae2016-09-02 14:00:29 +09001095 private static final byte[] MOCK_BROADCAST_IPV4_ADDR = {10, 0, 31, (byte) 255}; // prefix = 19
Hugo Benichi961ca492016-09-02 11:04:34 +09001096 private static final byte[] MOCK_MULTICAST_IPV4_ADDR = {(byte) 224, 0, 0, 1};
1097 private static final byte[] ANOTHER_IPV4_ADDR = {10, 0, 0, 2};
Aaron Huang04ed6a32018-11-15 20:30:46 +08001098 private static final byte[] IPV4_SOURCE_ADDR = {10, 0, 0, 3};
1099 private static final byte[] ANOTHER_IPV4_SOURCE_ADDR = {(byte) 192, 0, 2, 1};
1100 private static final byte[] BUG_PROBE_SOURCE_ADDR1 = {0, 0, 1, 2};
1101 private static final byte[] BUG_PROBE_SOURCE_ADDR2 = {3, 4, 0, 0};
Hugo Benichi961ca492016-09-02 11:04:34 +09001102 private static final byte[] IPV4_ANY_HOST_ADDR = {0, 0, 0, 0};
Paul Jensen9132f342016-04-13 15:00:26 -04001103
Bernie Innocentie2c70f82018-03-28 20:11:49 +09001104 // Helper to initialize a default apfFilter.
Remi NGUYEN VAN3c600a12019-01-10 19:12:46 +09001105 private ApfFilter setupApfFilter(
1106 IpClientCallbacksWrapper ipClientCallback, ApfConfiguration config) throws Exception {
Bernie Innocentie2c70f82018-03-28 20:11:49 +09001107 LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19);
1108 LinkProperties lp = new LinkProperties();
1109 lp.addLinkAddress(link);
Erik Kline8d1fe542018-03-12 23:18:58 +09001110 TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
Bernie Innocentie2c70f82018-03-28 20:11:49 +09001111 apfFilter.setLinkProperties(lp);
1112 return apfFilter;
1113 }
1114
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001115 @Test
Paul Jensen9132f342016-04-13 15:00:26 -04001116 public void testApfFilterIPv4() throws Exception {
Erik Kline8d1fe542018-03-12 23:18:58 +09001117 MockIpClientCallback ipClientCallback = new MockIpClientCallback();
Hugo Benichi7d21eae2016-09-02 14:00:29 +09001118 LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19);
1119 LinkProperties lp = new LinkProperties();
1120 lp.addLinkAddress(link);
Hugo Benichi0dc1d312016-09-02 12:40:31 +09001121
Hugo Benichi72166362017-10-13 16:32:20 +09001122 ApfConfiguration config = getDefaultConfig();
1123 config.multicastFilter = DROP_MULTICAST;
Erik Kline8d1fe542018-03-12 23:18:58 +09001124 TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
Hugo Benichi7d21eae2016-09-02 14:00:29 +09001125 apfFilter.setLinkProperties(lp);
Hugo Benichi0dc1d312016-09-02 12:40:31 +09001126
Erik Kline8d1fe542018-03-12 23:18:58 +09001127 byte[] program = ipClientCallback.getApfProgram();
Paul Jensen9132f342016-04-13 15:00:26 -04001128
1129 // Verify empty packet of 100 zero bytes is passed
1130 ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
Hugo Benichi961ca492016-09-02 11:04:34 +09001131 assertPass(program, packet.array());
Paul Jensen9132f342016-04-13 15:00:26 -04001132
1133 // Verify unicast IPv4 packet is passed
Hugo Benichi961ca492016-09-02 11:04:34 +09001134 put(packet, ETH_DEST_ADDR_OFFSET, TestApfFilter.MOCK_MAC_ADDR);
Paul Jensen9132f342016-04-13 15:00:26 -04001135 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
Hugo Benichi961ca492016-09-02 11:04:34 +09001136 put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_IPV4_ADDR);
1137 assertPass(program, packet.array());
Paul Jensen9132f342016-04-13 15:00:26 -04001138
Hugo Benichi0dc1d312016-09-02 12:40:31 +09001139 // Verify L2 unicast to IPv4 broadcast addresses is dropped (b/30231088)
Hugo Benichi961ca492016-09-02 11:04:34 +09001140 put(packet, IPV4_DEST_ADDR_OFFSET, IPV4_BROADCAST_ADDRESS);
Hugo Benichi0dc1d312016-09-02 12:40:31 +09001141 assertDrop(program, packet.array());
Hugo Benichi961ca492016-09-02 11:04:34 +09001142 put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_BROADCAST_IPV4_ADDR);
Hugo Benichi7d21eae2016-09-02 14:00:29 +09001143 assertDrop(program, packet.array());
Hugo Benichi961ca492016-09-02 11:04:34 +09001144
1145 // Verify multicast/broadcast IPv4, not DHCP to us, is dropped
1146 put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS);
1147 assertDrop(program, packet.array());
Paul Jensen9132f342016-04-13 15:00:26 -04001148 packet.put(IPV4_VERSION_IHL_OFFSET, (byte)0x45);
Hugo Benichi961ca492016-09-02 11:04:34 +09001149 assertDrop(program, packet.array());
Paul Jensen9132f342016-04-13 15:00:26 -04001150 packet.put(IPV4_PROTOCOL_OFFSET, (byte)IPPROTO_UDP);
Hugo Benichi961ca492016-09-02 11:04:34 +09001151 assertDrop(program, packet.array());
Paul Jensen9132f342016-04-13 15:00:26 -04001152 packet.putShort(UDP_DESTINATION_PORT_OFFSET, (short)DHCP_CLIENT_PORT);
Hugo Benichi961ca492016-09-02 11:04:34 +09001153 assertDrop(program, packet.array());
1154 put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_MULTICAST_IPV4_ADDR);
1155 assertDrop(program, packet.array());
1156 put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_BROADCAST_IPV4_ADDR);
1157 assertDrop(program, packet.array());
1158 put(packet, IPV4_DEST_ADDR_OFFSET, IPV4_BROADCAST_ADDRESS);
1159 assertDrop(program, packet.array());
Paul Jensen9132f342016-04-13 15:00:26 -04001160
1161 // Verify broadcast IPv4 DHCP to us is passed
Hugo Benichi961ca492016-09-02 11:04:34 +09001162 put(packet, DHCP_CLIENT_MAC_OFFSET, TestApfFilter.MOCK_MAC_ADDR);
1163 assertPass(program, packet.array());
1164
1165 // Verify unicast IPv4 DHCP to us is passed
1166 put(packet, ETH_DEST_ADDR_OFFSET, TestApfFilter.MOCK_MAC_ADDR);
1167 assertPass(program, packet.array());
Paul Jensen9132f342016-04-13 15:00:26 -04001168
1169 apfFilter.shutdown();
1170 }
1171
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001172 @Test
Paul Jensen9132f342016-04-13 15:00:26 -04001173 public void testApfFilterIPv6() throws Exception {
Erik Kline8d1fe542018-03-12 23:18:58 +09001174 MockIpClientCallback ipClientCallback = new MockIpClientCallback();
Hugo Benichi72166362017-10-13 16:32:20 +09001175 ApfConfiguration config = getDefaultConfig();
Erik Kline8d1fe542018-03-12 23:18:58 +09001176 TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
1177 byte[] program = ipClientCallback.getApfProgram();
Paul Jensen9132f342016-04-13 15:00:26 -04001178
1179 // Verify empty IPv6 packet is passed
1180 ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
1181 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
Hugo Benichi961ca492016-09-02 11:04:34 +09001182 assertPass(program, packet.array());
Paul Jensen9132f342016-04-13 15:00:26 -04001183
1184 // Verify empty ICMPv6 packet is passed
1185 packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6);
Hugo Benichi961ca492016-09-02 11:04:34 +09001186 assertPass(program, packet.array());
Paul Jensen9132f342016-04-13 15:00:26 -04001187
1188 // Verify empty ICMPv6 NA packet is passed
1189 packet.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_NEIGHBOR_ANNOUNCEMENT);
Hugo Benichi961ca492016-09-02 11:04:34 +09001190 assertPass(program, packet.array());
Paul Jensen9132f342016-04-13 15:00:26 -04001191
1192 // Verify ICMPv6 NA to ff02::1 is dropped
Hugo Benichi961ca492016-09-02 11:04:34 +09001193 put(packet, IPV6_DEST_ADDR_OFFSET, IPV6_ALL_NODES_ADDRESS);
1194 assertDrop(program, packet.array());
Paul Jensen9132f342016-04-13 15:00:26 -04001195
Hugo Benichi02428982016-12-03 02:41:05 +09001196 // Verify ICMPv6 RS to any is dropped
1197 packet.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_ROUTER_SOLICITATION);
1198 assertDrop(program, packet.array());
1199 put(packet, IPV6_DEST_ADDR_OFFSET, IPV6_ALL_ROUTERS_ADDRESS);
1200 assertDrop(program, packet.array());
1201
Paul Jensen9132f342016-04-13 15:00:26 -04001202 apfFilter.shutdown();
1203 }
1204
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001205 @Test
Lorenzo Colitti11e13e22016-05-20 00:04:43 +09001206 public void testApfFilterMulticast() throws Exception {
Hugo Benichi961ca492016-09-02 11:04:34 +09001207 final byte[] unicastIpv4Addr = {(byte)192,0,2,63};
Hugo Benichi7d21eae2016-09-02 14:00:29 +09001208 final byte[] broadcastIpv4Addr = {(byte)192,0,2,(byte)255};
Hugo Benichi961ca492016-09-02 11:04:34 +09001209 final byte[] multicastIpv4Addr = {(byte)224,0,0,1};
1210 final byte[] multicastIpv6Addr = {(byte)0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,(byte)0xfb};
1211
Erik Kline8d1fe542018-03-12 23:18:58 +09001212 MockIpClientCallback ipClientCallback = new MockIpClientCallback();
Hugo Benichi7d21eae2016-09-02 14:00:29 +09001213 LinkAddress link = new LinkAddress(InetAddress.getByAddress(unicastIpv4Addr), 24);
1214 LinkProperties lp = new LinkProperties();
1215 lp.addLinkAddress(link);
1216
Hugo Benichi72166362017-10-13 16:32:20 +09001217 ApfConfiguration config = getDefaultConfig();
1218 config.ieee802_3Filter = DROP_802_3_FRAMES;
Erik Kline8d1fe542018-03-12 23:18:58 +09001219 TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
Hugo Benichi7d21eae2016-09-02 14:00:29 +09001220 apfFilter.setLinkProperties(lp);
1221
Erik Kline8d1fe542018-03-12 23:18:58 +09001222 byte[] program = ipClientCallback.getApfProgram();
Hugo Benichi7d21eae2016-09-02 14:00:29 +09001223
Lorenzo Colitti11e13e22016-05-20 00:04:43 +09001224 // Construct IPv4 and IPv6 multicast packets.
Paul Jensenf8a01e82016-05-26 09:16:11 -04001225 ByteBuffer mcastv4packet = ByteBuffer.wrap(new byte[100]);
1226 mcastv4packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
Hugo Benichi961ca492016-09-02 11:04:34 +09001227 put(mcastv4packet, IPV4_DEST_ADDR_OFFSET, multicastIpv4Addr);
Lorenzo Colitti11e13e22016-05-20 00:04:43 +09001228
Paul Jensenf8a01e82016-05-26 09:16:11 -04001229 ByteBuffer mcastv6packet = ByteBuffer.wrap(new byte[100]);
1230 mcastv6packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
1231 mcastv6packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_UDP);
Hugo Benichi961ca492016-09-02 11:04:34 +09001232 put(mcastv6packet, IPV6_DEST_ADDR_OFFSET, multicastIpv6Addr);
Paul Jensenf8a01e82016-05-26 09:16:11 -04001233
1234 // Construct IPv4 broadcast packet.
Hugo Benichi961ca492016-09-02 11:04:34 +09001235 ByteBuffer bcastv4packet1 = ByteBuffer.wrap(new byte[100]);
1236 bcastv4packet1.put(ETH_BROADCAST_MAC_ADDRESS);
1237 bcastv4packet1.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
1238 put(bcastv4packet1, IPV4_DEST_ADDR_OFFSET, multicastIpv4Addr);
1239
1240 ByteBuffer bcastv4packet2 = ByteBuffer.wrap(new byte[100]);
1241 bcastv4packet2.put(ETH_BROADCAST_MAC_ADDRESS);
1242 bcastv4packet2.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
1243 put(bcastv4packet2, IPV4_DEST_ADDR_OFFSET, IPV4_BROADCAST_ADDRESS);
1244
1245 // Construct IPv4 broadcast with L2 unicast address packet (b/30231088).
1246 ByteBuffer bcastv4unicastl2packet = ByteBuffer.wrap(new byte[100]);
1247 bcastv4unicastl2packet.put(TestApfFilter.MOCK_MAC_ADDR);
1248 bcastv4unicastl2packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
1249 put(bcastv4unicastl2packet, IPV4_DEST_ADDR_OFFSET, broadcastIpv4Addr);
Lorenzo Colitti11e13e22016-05-20 00:04:43 +09001250
Paul Jensen9132f342016-04-13 15:00:26 -04001251 // Verify initially disabled multicast filter is off
Hugo Benichi961ca492016-09-02 11:04:34 +09001252 assertPass(program, mcastv4packet.array());
1253 assertPass(program, mcastv6packet.array());
1254 assertPass(program, bcastv4packet1.array());
1255 assertPass(program, bcastv4packet2.array());
1256 assertPass(program, bcastv4unicastl2packet.array());
Paul Jensen9132f342016-04-13 15:00:26 -04001257
1258 // Turn on multicast filter and verify it works
Erik Kline8d1fe542018-03-12 23:18:58 +09001259 ipClientCallback.resetApfProgramWait();
Paul Jensen9132f342016-04-13 15:00:26 -04001260 apfFilter.setMulticastFilter(true);
Erik Kline8d1fe542018-03-12 23:18:58 +09001261 program = ipClientCallback.getApfProgram();
Hugo Benichi961ca492016-09-02 11:04:34 +09001262 assertDrop(program, mcastv4packet.array());
1263 assertDrop(program, mcastv6packet.array());
1264 assertDrop(program, bcastv4packet1.array());
1265 assertDrop(program, bcastv4packet2.array());
Hugo Benichi7d21eae2016-09-02 14:00:29 +09001266 assertDrop(program, bcastv4unicastl2packet.array());
Paul Jensen9132f342016-04-13 15:00:26 -04001267
1268 // Turn off multicast filter and verify it's off
Erik Kline8d1fe542018-03-12 23:18:58 +09001269 ipClientCallback.resetApfProgramWait();
Paul Jensen9132f342016-04-13 15:00:26 -04001270 apfFilter.setMulticastFilter(false);
Erik Kline8d1fe542018-03-12 23:18:58 +09001271 program = ipClientCallback.getApfProgram();
Hugo Benichi961ca492016-09-02 11:04:34 +09001272 assertPass(program, mcastv4packet.array());
1273 assertPass(program, mcastv6packet.array());
1274 assertPass(program, bcastv4packet1.array());
1275 assertPass(program, bcastv4packet2.array());
1276 assertPass(program, bcastv4unicastl2packet.array());
Paul Jensen9132f342016-04-13 15:00:26 -04001277
1278 // Verify it can be initialized to on
Erik Kline8d1fe542018-03-12 23:18:58 +09001279 ipClientCallback.resetApfProgramWait();
Paul Jensen9132f342016-04-13 15:00:26 -04001280 apfFilter.shutdown();
Hugo Benichi72166362017-10-13 16:32:20 +09001281 config.multicastFilter = DROP_MULTICAST;
1282 config.ieee802_3Filter = DROP_802_3_FRAMES;
Erik Kline8d1fe542018-03-12 23:18:58 +09001283 apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
Hugo Benichi7d21eae2016-09-02 14:00:29 +09001284 apfFilter.setLinkProperties(lp);
Erik Kline8d1fe542018-03-12 23:18:58 +09001285 program = ipClientCallback.getApfProgram();
Hugo Benichi961ca492016-09-02 11:04:34 +09001286 assertDrop(program, mcastv4packet.array());
1287 assertDrop(program, mcastv6packet.array());
1288 assertDrop(program, bcastv4packet1.array());
Hugo Benichi7d21eae2016-09-02 14:00:29 +09001289 assertDrop(program, bcastv4unicastl2packet.array());
Lorenzo Colitti11e13e22016-05-20 00:04:43 +09001290
1291 // Verify that ICMPv6 multicast is not dropped.
Paul Jensenf8a01e82016-05-26 09:16:11 -04001292 mcastv6packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6);
Hugo Benichi961ca492016-09-02 11:04:34 +09001293 assertPass(program, mcastv6packet.array());
Paul Jensen9132f342016-04-13 15:00:26 -04001294
1295 apfFilter.shutdown();
1296 }
1297
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001298 @Test
Bernie Innocentie2c70f82018-03-28 20:11:49 +09001299 public void testApfFilterMulticastPingWhileDozing() throws Exception {
Erik Kline8d1fe542018-03-12 23:18:58 +09001300 MockIpClientCallback ipClientCallback = new MockIpClientCallback();
1301 ApfFilter apfFilter = setupApfFilter(ipClientCallback, getDefaultConfig());
Bernie Innocentie2c70f82018-03-28 20:11:49 +09001302
1303 // Construct a multicast ICMPv6 ECHO request.
1304 final byte[] multicastIpv6Addr = {(byte)0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,(byte)0xfb};
1305 ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
1306 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
1307 packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6);
1308 packet.put(ICMP6_TYPE_OFFSET, (byte)ICMPV6_ECHO_REQUEST_TYPE);
1309 put(packet, IPV6_DEST_ADDR_OFFSET, multicastIpv6Addr);
1310
1311 // Normally, we let multicast pings alone...
Erik Kline8d1fe542018-03-12 23:18:58 +09001312 assertPass(ipClientCallback.getApfProgram(), packet.array());
Bernie Innocentie2c70f82018-03-28 20:11:49 +09001313
1314 // ...and even while dozing...
1315 apfFilter.setDozeMode(true);
Erik Kline8d1fe542018-03-12 23:18:58 +09001316 assertPass(ipClientCallback.getApfProgram(), packet.array());
Bernie Innocentie2c70f82018-03-28 20:11:49 +09001317
1318 // ...but when the multicast filter is also enabled, drop the multicast pings to save power.
1319 apfFilter.setMulticastFilter(true);
Erik Kline8d1fe542018-03-12 23:18:58 +09001320 assertDrop(ipClientCallback.getApfProgram(), packet.array());
Bernie Innocentie2c70f82018-03-28 20:11:49 +09001321
1322 // However, we should still let through all other ICMPv6 types.
1323 ByteBuffer raPacket = ByteBuffer.wrap(packet.array().clone());
Remi NGUYEN VAN3c600a12019-01-10 19:12:46 +09001324 raPacket.put(ICMP6_TYPE_OFFSET, (byte) NetworkStackConstants.ICMPV6_ROUTER_ADVERTISEMENT);
Erik Kline8d1fe542018-03-12 23:18:58 +09001325 assertPass(ipClientCallback.getApfProgram(), raPacket.array());
Bernie Innocentie2c70f82018-03-28 20:11:49 +09001326
1327 // Now wake up from doze mode to ensure that we no longer drop the packets.
1328 // (The multicast filter is still enabled at this point).
1329 apfFilter.setDozeMode(false);
Erik Kline8d1fe542018-03-12 23:18:58 +09001330 assertPass(ipClientCallback.getApfProgram(), packet.array());
Bernie Innocentie2c70f82018-03-28 20:11:49 +09001331
1332 apfFilter.shutdown();
1333 }
1334
1335 @Test
Ahmed ElArabawy8537c582017-06-12 18:01:11 -07001336 public void testApfFilter802_3() throws Exception {
Erik Kline8d1fe542018-03-12 23:18:58 +09001337 MockIpClientCallback ipClientCallback = new MockIpClientCallback();
Hugo Benichi72166362017-10-13 16:32:20 +09001338 ApfConfiguration config = getDefaultConfig();
Erik Kline8d1fe542018-03-12 23:18:58 +09001339 ApfFilter apfFilter = setupApfFilter(ipClientCallback, config);
1340 byte[] program = ipClientCallback.getApfProgram();
Ahmed ElArabawy8537c582017-06-12 18:01:11 -07001341
1342 // Verify empty packet of 100 zero bytes is passed
1343 // Note that eth-type = 0 makes it an IEEE802.3 frame
1344 ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
1345 assertPass(program, packet.array());
1346
1347 // Verify empty packet with IPv4 is passed
1348 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
1349 assertPass(program, packet.array());
1350
1351 // Verify empty IPv6 packet is passed
1352 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
1353 assertPass(program, packet.array());
1354
1355 // Now turn on the filter
Erik Kline8d1fe542018-03-12 23:18:58 +09001356 ipClientCallback.resetApfProgramWait();
Ahmed ElArabawy8537c582017-06-12 18:01:11 -07001357 apfFilter.shutdown();
Hugo Benichi72166362017-10-13 16:32:20 +09001358 config.ieee802_3Filter = DROP_802_3_FRAMES;
Erik Kline8d1fe542018-03-12 23:18:58 +09001359 apfFilter = setupApfFilter(ipClientCallback, config);
1360 program = ipClientCallback.getApfProgram();
Ahmed ElArabawy8537c582017-06-12 18:01:11 -07001361
1362 // Verify that IEEE802.3 frame is dropped
1363 // In this case ethtype is used for payload length
1364 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)(100 - 14));
1365 assertDrop(program, packet.array());
1366
1367 // Verify that IPv4 (as example of Ethernet II) frame will pass
1368 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
1369 assertPass(program, packet.array());
1370
1371 // Verify that IPv6 (as example of Ethernet II) frame will pass
1372 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
1373 assertPass(program, packet.array());
1374
1375 apfFilter.shutdown();
1376 }
1377
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001378 @Test
Ahmed ElArabawyfd424162017-08-02 13:31:05 -07001379 public void testApfFilterEthTypeBL() throws Exception {
Ahmed ElArabawyfd424162017-08-02 13:31:05 -07001380 final int[] emptyBlackList = {};
1381 final int[] ipv4BlackList = {ETH_P_IP};
1382 final int[] ipv4Ipv6BlackList = {ETH_P_IP, ETH_P_IPV6};
1383
Erik Kline8d1fe542018-03-12 23:18:58 +09001384 MockIpClientCallback ipClientCallback = new MockIpClientCallback();
Hugo Benichi72166362017-10-13 16:32:20 +09001385 ApfConfiguration config = getDefaultConfig();
Erik Kline8d1fe542018-03-12 23:18:58 +09001386 ApfFilter apfFilter = setupApfFilter(ipClientCallback, config);
1387 byte[] program = ipClientCallback.getApfProgram();
Ahmed ElArabawyfd424162017-08-02 13:31:05 -07001388
1389 // Verify empty packet of 100 zero bytes is passed
1390 // Note that eth-type = 0 makes it an IEEE802.3 frame
1391 ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
1392 assertPass(program, packet.array());
1393
1394 // Verify empty packet with IPv4 is passed
1395 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
1396 assertPass(program, packet.array());
1397
1398 // Verify empty IPv6 packet is passed
1399 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
1400 assertPass(program, packet.array());
1401
1402 // Now add IPv4 to the black list
Erik Kline8d1fe542018-03-12 23:18:58 +09001403 ipClientCallback.resetApfProgramWait();
Ahmed ElArabawyfd424162017-08-02 13:31:05 -07001404 apfFilter.shutdown();
Hugo Benichi72166362017-10-13 16:32:20 +09001405 config.ethTypeBlackList = ipv4BlackList;
Erik Kline8d1fe542018-03-12 23:18:58 +09001406 apfFilter = setupApfFilter(ipClientCallback, config);
1407 program = ipClientCallback.getApfProgram();
Ahmed ElArabawyfd424162017-08-02 13:31:05 -07001408
1409 // Verify that IPv4 frame will be dropped
1410 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
1411 assertDrop(program, packet.array());
1412
1413 // Verify that IPv6 frame will pass
1414 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
1415 assertPass(program, packet.array());
1416
1417 // Now let us have both IPv4 and IPv6 in the black list
Erik Kline8d1fe542018-03-12 23:18:58 +09001418 ipClientCallback.resetApfProgramWait();
Ahmed ElArabawyfd424162017-08-02 13:31:05 -07001419 apfFilter.shutdown();
Hugo Benichi72166362017-10-13 16:32:20 +09001420 config.ethTypeBlackList = ipv4Ipv6BlackList;
Erik Kline8d1fe542018-03-12 23:18:58 +09001421 apfFilter = setupApfFilter(ipClientCallback, config);
1422 program = ipClientCallback.getApfProgram();
Ahmed ElArabawyfd424162017-08-02 13:31:05 -07001423
1424 // Verify that IPv4 frame will be dropped
1425 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
1426 assertDrop(program, packet.array());
1427
1428 // Verify that IPv6 frame will be dropped
1429 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
1430 assertDrop(program, packet.array());
1431
1432 apfFilter.shutdown();
1433 }
1434
Erik Kline8d1fe542018-03-12 23:18:58 +09001435 private byte[] getProgram(MockIpClientCallback cb, ApfFilter filter, LinkProperties lp) {
Hugo Benichi38db9762016-07-12 15:08:50 +09001436 cb.resetApfProgramWait();
1437 filter.setLinkProperties(lp);
1438 return cb.getApfProgram();
1439 }
1440
1441 private void verifyArpFilter(byte[] program, int filterResult) {
1442 // Verify ARP request packet
Hugo Benichi961ca492016-09-02 11:04:34 +09001443 assertPass(program, arpRequestBroadcast(MOCK_IPV4_ADDR));
1444 assertVerdict(filterResult, program, arpRequestBroadcast(ANOTHER_IPV4_ADDR));
1445 assertDrop(program, arpRequestBroadcast(IPV4_ANY_HOST_ADDR));
Hugo Benichi38db9762016-07-12 15:08:50 +09001446
Aaron Huang04ed6a32018-11-15 20:30:46 +08001447 // Verify ARP reply packets from different source ip
1448 assertDrop(program, arpReply(IPV4_ANY_HOST_ADDR, IPV4_ANY_HOST_ADDR));
1449 assertPass(program, arpReply(ANOTHER_IPV4_SOURCE_ADDR, IPV4_ANY_HOST_ADDR));
1450 assertPass(program, arpReply(BUG_PROBE_SOURCE_ADDR1, IPV4_ANY_HOST_ADDR));
1451 assertPass(program, arpReply(BUG_PROBE_SOURCE_ADDR2, IPV4_ANY_HOST_ADDR));
1452
Hugo Benichi38db9762016-07-12 15:08:50 +09001453 // Verify unicast ARP reply packet is always accepted.
Aaron Huang04ed6a32018-11-15 20:30:46 +08001454 assertPass(program, arpReply(IPV4_SOURCE_ADDR, MOCK_IPV4_ADDR));
1455 assertPass(program, arpReply(IPV4_SOURCE_ADDR, ANOTHER_IPV4_ADDR));
1456 assertPass(program, arpReply(IPV4_SOURCE_ADDR, IPV4_ANY_HOST_ADDR));
Hugo Benichi38db9762016-07-12 15:08:50 +09001457
1458 // Verify GARP reply packets are always filtered
Hugo Benichi961ca492016-09-02 11:04:34 +09001459 assertDrop(program, garpReply());
Paul Jensen9132f342016-04-13 15:00:26 -04001460 }
1461
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001462 @Test
Paul Jensen9132f342016-04-13 15:00:26 -04001463 public void testApfFilterArp() throws Exception {
Erik Kline8d1fe542018-03-12 23:18:58 +09001464 MockIpClientCallback ipClientCallback = new MockIpClientCallback();
Hugo Benichi72166362017-10-13 16:32:20 +09001465 ApfConfiguration config = getDefaultConfig();
1466 config.multicastFilter = DROP_MULTICAST;
1467 config.ieee802_3Filter = DROP_802_3_FRAMES;
Erik Kline8d1fe542018-03-12 23:18:58 +09001468 TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
Paul Jensen9132f342016-04-13 15:00:26 -04001469
Hugo Benichi38db9762016-07-12 15:08:50 +09001470 // Verify initially ARP request filter is off, and GARP filter is on.
Erik Kline8d1fe542018-03-12 23:18:58 +09001471 verifyArpFilter(ipClientCallback.getApfProgram(), PASS);
Paul Jensen9132f342016-04-13 15:00:26 -04001472
1473 // Inform ApfFilter of our address and verify ARP filtering is on
Hugo Benichi38db9762016-07-12 15:08:50 +09001474 LinkAddress linkAddress = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 24);
Paul Jensen9132f342016-04-13 15:00:26 -04001475 LinkProperties lp = new LinkProperties();
Hugo Benichi38db9762016-07-12 15:08:50 +09001476 assertTrue(lp.addLinkAddress(linkAddress));
Erik Kline8d1fe542018-03-12 23:18:58 +09001477 verifyArpFilter(getProgram(ipClientCallback, apfFilter, lp), DROP);
Paul Jensen9132f342016-04-13 15:00:26 -04001478
1479 // Inform ApfFilter of loss of IP and verify ARP filtering is off
Erik Kline8d1fe542018-03-12 23:18:58 +09001480 verifyArpFilter(getProgram(ipClientCallback, apfFilter, new LinkProperties()), PASS);
Paul Jensen9132f342016-04-13 15:00:26 -04001481
1482 apfFilter.shutdown();
1483 }
1484
Aaron Huang04ed6a32018-11-15 20:30:46 +08001485 private static byte[] arpReply(byte[] sip, byte[] tip) {
Hugo Benichi38db9762016-07-12 15:08:50 +09001486 ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
1487 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP);
Hugo Benichi961ca492016-09-02 11:04:34 +09001488 put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REPLY_HEADER);
Aaron Huang04ed6a32018-11-15 20:30:46 +08001489 put(packet, ARP_SOURCE_IP_ADDRESS_OFFSET, sip);
Hugo Benichi961ca492016-09-02 11:04:34 +09001490 put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, tip);
Hugo Benichi38db9762016-07-12 15:08:50 +09001491 return packet.array();
1492 }
1493
Aaron Huang04ed6a32018-11-15 20:30:46 +08001494 private static byte[] arpRequestBroadcast(byte[] tip) {
Hugo Benichi38db9762016-07-12 15:08:50 +09001495 ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
1496 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP);
Aaron Huang04ed6a32018-11-15 20:30:46 +08001497 put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS);
1498 put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REQUEST_HEADER);
Hugo Benichi961ca492016-09-02 11:04:34 +09001499 put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, tip);
Hugo Benichi38db9762016-07-12 15:08:50 +09001500 return packet.array();
1501 }
1502
1503 private static byte[] garpReply() {
1504 ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
1505 packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP);
Hugo Benichi961ca492016-09-02 11:04:34 +09001506 put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS);
1507 put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REPLY_HEADER);
1508 put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, IPV4_ANY_HOST_ADDR);
Hugo Benichi38db9762016-07-12 15:08:50 +09001509 return packet.array();
1510 }
1511
Aaron Huanga63c40e2019-01-15 16:53:51 +08001512 private static final byte[] IPV4_KEEPALIVE_SRC_ADDR = {10, 0, 0, 5};
1513 private static final byte[] IPV4_KEEPALIVE_DST_ADDR = {10, 0, 0, 6};
1514 private static final byte[] IPV4_ANOTHER_ADDR = {10, 0 , 0, 7};
1515 private static final byte[] IPV6_KEEPALIVE_SRC_ADDR =
1516 {(byte) 0x24, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (byte) 0xfa, (byte) 0xf1};
1517 private static final byte[] IPV6_KEEPALIVE_DST_ADDR =
1518 {(byte) 0x24, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (byte) 0xfa, (byte) 0xf2};
1519 private static final byte[] IPV6_ANOTHER_ADDR =
1520 {(byte) 0x24, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (byte) 0xfa, (byte) 0xf5};
1521
1522 @Test
1523 public void testApfFilterKeepaliveAck() throws Exception {
1524 final MockIpClientCallback cb = new MockIpClientCallback();
1525 final ApfConfiguration config = getDefaultConfig();
1526 config.multicastFilter = DROP_MULTICAST;
1527 config.ieee802_3Filter = DROP_802_3_FRAMES;
1528 final TestApfFilter apfFilter = new TestApfFilter(mContext, config, cb, mLog);
1529 byte[] program;
1530 final int srcPort = 12345;
1531 final int dstPort = 54321;
1532 final int seqNum = 2123456789;
1533 final int ackNum = 1234567890;
1534 final int anotherSrcPort = 23456;
1535 final int anotherDstPort = 65432;
1536 final int anotherSeqNum = 2123456780;
1537 final int anotherAckNum = 1123456789;
1538 final int slot1 = 1;
1539 final int slot2 = 2;
1540 final int window = 14480;
1541 final int windowScale = 4;
1542
1543 // src: 10.0.0.5, port: 12345
1544 // dst: 10.0.0.6, port: 54321
1545 InetAddress srcAddr = InetAddress.getByAddress(IPV4_KEEPALIVE_SRC_ADDR);
1546 InetAddress dstAddr = InetAddress.getByAddress(IPV4_KEEPALIVE_DST_ADDR);
1547
Xiao Ma6b4de8f2019-02-15 19:18:21 +09001548 final TcpKeepalivePacketDataParcelable parcel = new TcpKeepalivePacketDataParcelable();
1549 parcel.srcAddress = srcAddr.getAddress();
1550 parcel.srcPort = srcPort;
1551 parcel.dstAddress = dstAddr.getAddress();
1552 parcel.dstPort = dstPort;
1553 parcel.seq = seqNum;
1554 parcel.ack = ackNum;
Aaron Huanga63c40e2019-01-15 16:53:51 +08001555
Xiao Ma6b4de8f2019-02-15 19:18:21 +09001556 apfFilter.addKeepalivePacketFilter(slot1, parcel);
Aaron Huanga63c40e2019-01-15 16:53:51 +08001557 program = cb.getApfProgram();
1558
1559 // Verify IPv4 keepalive ack packet is dropped
1560 // src: 10.0.0.6, port: 54321
1561 // dst: 10.0.0.5, port: 12345
1562 assertDrop(program,
1563 ipv4Packet(IPV4_KEEPALIVE_DST_ADDR, IPV4_KEEPALIVE_SRC_ADDR,
1564 dstPort, srcPort, ackNum, seqNum + 1, 0 /* dataLength */));
1565 // Verify IPv4 non-keepalive ack packet from the same source address is passed
1566 assertPass(program,
1567 ipv4Packet(IPV4_KEEPALIVE_DST_ADDR, IPV4_KEEPALIVE_SRC_ADDR,
1568 dstPort, srcPort, ackNum + 100, seqNum, 0 /* dataLength */));
1569 assertPass(program,
1570 ipv4Packet(IPV4_KEEPALIVE_DST_ADDR, IPV4_KEEPALIVE_SRC_ADDR,
1571 dstPort, srcPort, ackNum, seqNum + 1, 10 /* dataLength */));
1572 // Verify IPv4 packet from another address is passed
1573 assertPass(program,
1574 ipv4Packet(IPV4_ANOTHER_ADDR, IPV4_KEEPALIVE_SRC_ADDR, anotherSrcPort,
Xiao Mad36a89c2019-02-10 14:52:37 +09001575 anotherDstPort, anotherSeqNum, anotherAckNum, 0 /* dataLength */));
Aaron Huanga63c40e2019-01-15 16:53:51 +08001576
1577 // Remove IPv4 keepalive filter
1578 apfFilter.removeKeepalivePacketFilter(slot1);
1579
1580 try {
1581 // src: 2404:0:0:0:0:0:faf1, port: 12345
1582 // dst: 2404:0:0:0:0:0:faf2, port: 54321
1583 srcAddr = InetAddress.getByAddress(IPV6_KEEPALIVE_SRC_ADDR);
1584 dstAddr = InetAddress.getByAddress(IPV6_KEEPALIVE_DST_ADDR);
Xiao Ma6b4de8f2019-02-15 19:18:21 +09001585
1586 final TcpKeepalivePacketDataParcelable ipv6Parcel =
1587 new TcpKeepalivePacketDataParcelable();
1588 ipv6Parcel.srcAddress = srcAddr.getAddress();
1589 ipv6Parcel.srcPort = srcPort;
1590 ipv6Parcel.dstAddress = dstAddr.getAddress();
1591 ipv6Parcel.dstPort = dstPort;
1592 ipv6Parcel.seq = seqNum;
1593 ipv6Parcel.ack = ackNum;
1594
1595 apfFilter.addKeepalivePacketFilter(slot1, ipv6Parcel);
Aaron Huanga63c40e2019-01-15 16:53:51 +08001596 program = cb.getApfProgram();
1597
1598 // Verify IPv6 keepalive ack packet is dropped
1599 // src: 2404:0:0:0:0:0:faf2, port: 54321
1600 // dst: 2404:0:0:0:0:0:faf1, port: 12345
1601 assertDrop(program,
1602 ipv6Packet(IPV6_KEEPALIVE_DST_ADDR, IPV6_KEEPALIVE_SRC_ADDR,
1603 dstPort, srcPort, ackNum, seqNum + 1));
1604 // Verify IPv6 non-keepalive ack packet from the same source address is passed
1605 assertPass(program,
1606 ipv6Packet(IPV6_KEEPALIVE_DST_ADDR, IPV6_KEEPALIVE_SRC_ADDR,
1607 dstPort, srcPort, ackNum + 100, seqNum));
1608 // Verify IPv6 packet from another address is passed
1609 assertPass(program,
1610 ipv6Packet(IPV6_ANOTHER_ADDR, IPV6_KEEPALIVE_SRC_ADDR, anotherSrcPort,
1611 anotherDstPort, anotherSeqNum, anotherAckNum));
1612
1613 // Remove IPv6 keepalive filter
1614 apfFilter.removeKeepalivePacketFilter(slot1);
1615
1616 // Verify multiple filters
Xiao Ma6b4de8f2019-02-15 19:18:21 +09001617 apfFilter.addKeepalivePacketFilter(slot1, parcel);
1618 apfFilter.addKeepalivePacketFilter(slot2, ipv6Parcel);
Aaron Huanga63c40e2019-01-15 16:53:51 +08001619 program = cb.getApfProgram();
1620
1621 // Verify IPv4 keepalive ack packet is dropped
1622 // src: 10.0.0.6, port: 54321
1623 // dst: 10.0.0.5, port: 12345
1624 assertDrop(program,
1625 ipv4Packet(IPV4_KEEPALIVE_DST_ADDR, IPV4_KEEPALIVE_SRC_ADDR,
Xiao Mad36a89c2019-02-10 14:52:37 +09001626 dstPort, srcPort, ackNum, seqNum + 1, 0 /* dataLength */));
Aaron Huanga63c40e2019-01-15 16:53:51 +08001627 // Verify IPv4 non-keepalive ack packet from the same source address is passed
1628 assertPass(program,
1629 ipv4Packet(IPV4_KEEPALIVE_DST_ADDR, IPV4_KEEPALIVE_SRC_ADDR,
Xiao Mad36a89c2019-02-10 14:52:37 +09001630 dstPort, srcPort, ackNum + 100, seqNum, 0 /* dataLength */));
Aaron Huanga63c40e2019-01-15 16:53:51 +08001631 // Verify IPv4 packet from another address is passed
1632 assertPass(program,
1633 ipv4Packet(IPV4_ANOTHER_ADDR, IPV4_KEEPALIVE_SRC_ADDR, anotherSrcPort,
Xiao Mad36a89c2019-02-10 14:52:37 +09001634 anotherDstPort, anotherSeqNum, anotherAckNum, 0 /* dataLength */));
Aaron Huanga63c40e2019-01-15 16:53:51 +08001635
1636 // Verify IPv6 keepalive ack packet is dropped
1637 // src: 2404:0:0:0:0:0:faf2, port: 54321
1638 // dst: 2404:0:0:0:0:0:faf1, port: 12345
1639 assertDrop(program,
1640 ipv6Packet(IPV6_KEEPALIVE_DST_ADDR, IPV6_KEEPALIVE_SRC_ADDR,
1641 dstPort, srcPort, ackNum, seqNum + 1));
1642 // Verify IPv6 non-keepalive ack packet from the same source address is passed
1643 assertPass(program,
1644 ipv6Packet(IPV6_KEEPALIVE_DST_ADDR, IPV6_KEEPALIVE_SRC_ADDR,
1645 dstPort, srcPort, ackNum + 100, seqNum));
1646 // Verify IPv6 packet from another address is passed
1647 assertPass(program,
1648 ipv6Packet(IPV6_ANOTHER_ADDR, IPV6_KEEPALIVE_SRC_ADDR, anotherSrcPort,
1649 anotherDstPort, anotherSeqNum, anotherAckNum));
1650
1651 // Remove keepalive filters
1652 apfFilter.removeKeepalivePacketFilter(slot1);
1653 apfFilter.removeKeepalivePacketFilter(slot2);
Xiao Ma6b4de8f2019-02-15 19:18:21 +09001654 } catch (UnsupportedOperationException e) {
Aaron Huanga63c40e2019-01-15 16:53:51 +08001655 // TODO: support V6 packets
1656 }
1657
1658 program = cb.getApfProgram();
1659
1660 // Verify IPv4, IPv6 packets are passed
1661 assertPass(program,
1662 ipv4Packet(IPV4_KEEPALIVE_DST_ADDR, IPV4_KEEPALIVE_SRC_ADDR,
Xiao Mad36a89c2019-02-10 14:52:37 +09001663 dstPort, srcPort, ackNum, seqNum + 1, 0 /* dataLength */));
Aaron Huanga63c40e2019-01-15 16:53:51 +08001664 assertPass(program,
1665 ipv6Packet(IPV6_KEEPALIVE_DST_ADDR, IPV6_KEEPALIVE_SRC_ADDR,
1666 dstPort, srcPort, ackNum, seqNum + 1));
1667 assertPass(program,
1668 ipv4Packet(IPV4_ANOTHER_ADDR, IPV4_KEEPALIVE_SRC_ADDR, srcPort,
Xiao Mad36a89c2019-02-10 14:52:37 +09001669 dstPort, anotherSeqNum, anotherAckNum, 0 /* dataLength */));
Aaron Huanga63c40e2019-01-15 16:53:51 +08001670 assertPass(program,
1671 ipv6Packet(IPV6_ANOTHER_ADDR, IPV6_KEEPALIVE_SRC_ADDR, srcPort,
1672 dstPort, anotherSeqNum, anotherAckNum));
1673
1674 apfFilter.shutdown();
1675 }
1676
Xiao Mad36a89c2019-02-10 14:52:37 +09001677 private static byte[] ipv4Packet(byte[] sip, byte[] dip, int sport,
1678 int dport, int seq, int ack, int dataLength) {
1679 final int totalLength = dataLength + IPV4_HEADER_LEN + IPV4_TCP_HEADER_LEN;
1680
1681 ByteBuffer packet = ByteBuffer.wrap(new byte[totalLength + ETH_HEADER_LEN]);
1682
1683 // ether type
Aaron Huanga63c40e2019-01-15 16:53:51 +08001684 packet.putShort(ETH_ETHERTYPE_OFFSET, (short) ETH_P_IP);
Xiao Mad36a89c2019-02-10 14:52:37 +09001685
1686 // IPv4 header
Aaron Huanga63c40e2019-01-15 16:53:51 +08001687 packet.put(IPV4_VERSION_IHL_OFFSET, (byte) 0x45);
Xiao Mad36a89c2019-02-10 14:52:37 +09001688 packet.putShort(IPV4_TOTAL_LENGTH_OFFSET, (short) totalLength);
1689 packet.put(IPV4_PROTOCOL_OFFSET, (byte) IPPROTO_TCP);
Aaron Huanga63c40e2019-01-15 16:53:51 +08001690 put(packet, IPV4_SRC_ADDR_OFFSET, sip);
Xiao Mad36a89c2019-02-10 14:52:37 +09001691 put(packet, IPV4_DEST_ADDR_OFFSET, dip);
Aaron Huanga63c40e2019-01-15 16:53:51 +08001692 packet.putShort(IPV4_TCP_SRC_PORT_OFFSET, (short) sport);
1693 packet.putShort(IPV4_TCP_DEST_PORT_OFFSET, (short) dport);
1694 packet.putInt(IPV4_TCP_SEQ_NUM_OFFSET, seq);
1695 packet.putInt(IPV4_TCP_ACK_NUM_OFFSET, ack);
Aaron Huanga63c40e2019-01-15 16:53:51 +08001696
Xiao Mad36a89c2019-02-10 14:52:37 +09001697 // TCP header length 5(20 bytes), reserved 3 bits, NS=0
Aaron Huanga63c40e2019-01-15 16:53:51 +08001698 packet.put(IPV4_TCP_HEADER_LENGTH_OFFSET, (byte) 0x50);
Xiao Mad36a89c2019-02-10 14:52:37 +09001699 // TCP flags: ACK set
1700 packet.put(IPV4_TCP_HEADER_FLAG_OFFSET, (byte) 0x10);
Aaron Huanga63c40e2019-01-15 16:53:51 +08001701 return packet.array();
1702 }
1703
1704 private static byte[] ipv6Packet(byte[] sip, byte[] tip, int sport,
1705 int dport, int seq, int ack) {
1706 ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
1707 packet.putShort(ETH_ETHERTYPE_OFFSET, (short) ETH_P_IPV6);
1708 put(packet, IPV6_SRC_ADDR_OFFSET, sip);
1709 put(packet, IPV6_DEST_ADDR_OFFSET, tip);
1710 packet.putShort(IPV6_TCP_SRC_PORT_OFFSET, (short) sport);
1711 packet.putShort(IPV6_TCP_DEST_PORT_OFFSET, (short) dport);
1712 packet.putInt(IPV6_TCP_SEQ_NUM_OFFSET, seq);
1713 packet.putInt(IPV6_TCP_ACK_NUM_OFFSET, ack);
1714 return packet.array();
1715 }
1716
Erik Kline8d1fe542018-03-12 23:18:58 +09001717 // Verify that the last program pushed to the IpClient.Callback properly filters the
Paul Jensen9132f342016-04-13 15:00:26 -04001718 // given packet for the given lifetime.
Hugo Benichi4456f332016-12-19 14:50:52 +09001719 private void verifyRaLifetime(byte[] program, ByteBuffer packet, int lifetime) {
1720 final int FRACTION_OF_LIFETIME = 6;
1721 final int ageLimit = lifetime / FRACTION_OF_LIFETIME;
Paul Jensen9132f342016-04-13 15:00:26 -04001722
Hugo Benichi4456f332016-12-19 14:50:52 +09001723 // Verify new program should drop RA for 1/6th its lifetime and pass afterwards.
Hugo Benichi961ca492016-09-02 11:04:34 +09001724 assertDrop(program, packet.array());
Hugo Benichi4456f332016-12-19 14:50:52 +09001725 assertDrop(program, packet.array(), ageLimit);
1726 assertPass(program, packet.array(), ageLimit + 1);
Paul Jensen9132f342016-04-13 15:00:26 -04001727 assertPass(program, packet.array(), lifetime);
Paul Jensen9132f342016-04-13 15:00:26 -04001728 // Verify RA checksum is ignored
Hugo Benichi4456f332016-12-19 14:50:52 +09001729 final short originalChecksum = packet.getShort(ICMP6_RA_CHECKSUM_OFFSET);
Paul Jensen9132f342016-04-13 15:00:26 -04001730 packet.putShort(ICMP6_RA_CHECKSUM_OFFSET, (short)12345);
Hugo Benichi961ca492016-09-02 11:04:34 +09001731 assertDrop(program, packet.array());
Paul Jensen9132f342016-04-13 15:00:26 -04001732 packet.putShort(ICMP6_RA_CHECKSUM_OFFSET, (short)-12345);
Hugo Benichi961ca492016-09-02 11:04:34 +09001733 assertDrop(program, packet.array());
Hugo Benichi4456f332016-12-19 14:50:52 +09001734 packet.putShort(ICMP6_RA_CHECKSUM_OFFSET, originalChecksum);
Paul Jensen9132f342016-04-13 15:00:26 -04001735
1736 // Verify other changes to RA make it not match filter
Hugo Benichi4456f332016-12-19 14:50:52 +09001737 final byte originalFirstByte = packet.get(0);
Paul Jensen9132f342016-04-13 15:00:26 -04001738 packet.put(0, (byte)-1);
Hugo Benichi961ca492016-09-02 11:04:34 +09001739 assertPass(program, packet.array());
Paul Jensen9132f342016-04-13 15:00:26 -04001740 packet.put(0, (byte)0);
Hugo Benichi961ca492016-09-02 11:04:34 +09001741 assertDrop(program, packet.array());
Hugo Benichi4456f332016-12-19 14:50:52 +09001742 packet.put(0, originalFirstByte);
Paul Jensen9132f342016-04-13 15:00:26 -04001743 }
1744
1745 // Test that when ApfFilter is shown the given packet, it generates a program to filter it
1746 // for the given lifetime.
Erik Kline8d1fe542018-03-12 23:18:58 +09001747 private void verifyRaLifetime(TestApfFilter apfFilter, MockIpClientCallback ipClientCallback,
Paul Jensen9132f342016-04-13 15:00:26 -04001748 ByteBuffer packet, int lifetime) throws IOException, ErrnoException {
1749 // Verify new program generated if ApfFilter witnesses RA
Erik Kline8d1fe542018-03-12 23:18:58 +09001750 ipClientCallback.resetApfProgramWait();
Paul Jensen9132f342016-04-13 15:00:26 -04001751 apfFilter.pretendPacketReceived(packet.array());
Erik Kline8d1fe542018-03-12 23:18:58 +09001752 byte[] program = ipClientCallback.getApfProgram();
Hugo Benichi4456f332016-12-19 14:50:52 +09001753 verifyRaLifetime(program, packet, lifetime);
Paul Jensen9132f342016-04-13 15:00:26 -04001754 }
1755
Hugo Benichi6ccd51a2016-07-04 09:22:30 +09001756 private void verifyRaEvent(RaEvent expected) {
Remi NGUYEN VAN7b84fb32019-01-19 21:13:24 +09001757 ArgumentCaptor<IpConnectivityLog.Event> captor =
1758 ArgumentCaptor.forClass(IpConnectivityLog.Event.class);
Hugo Benichi6ccd51a2016-07-04 09:22:30 +09001759 verify(mLog, atLeastOnce()).log(captor.capture());
1760 RaEvent got = lastRaEvent(captor.getAllValues());
1761 if (!raEventEquals(expected, got)) {
1762 assertEquals(expected, got); // fail for printing an assertion error message.
1763 }
1764 }
1765
Remi NGUYEN VAN7b84fb32019-01-19 21:13:24 +09001766 private RaEvent lastRaEvent(List<IpConnectivityLog.Event> events) {
Hugo Benichi6ccd51a2016-07-04 09:22:30 +09001767 RaEvent got = null;
1768 for (Parcelable ev : events) {
1769 if (ev instanceof RaEvent) {
1770 got = (RaEvent) ev;
1771 }
1772 }
1773 return got;
1774 }
1775
1776 private boolean raEventEquals(RaEvent ev1, RaEvent ev2) {
1777 return (ev1 != null) && (ev2 != null)
1778 && (ev1.routerLifetime == ev2.routerLifetime)
1779 && (ev1.prefixValidLifetime == ev2.prefixValidLifetime)
1780 && (ev1.prefixPreferredLifetime == ev2.prefixPreferredLifetime)
1781 && (ev1.routeInfoLifetime == ev2.routeInfoLifetime)
1782 && (ev1.rdnssLifetime == ev2.rdnssLifetime)
1783 && (ev1.dnsslLifetime == ev2.dnsslLifetime);
1784 }
1785
Erik Kline8d1fe542018-03-12 23:18:58 +09001786 private void assertInvalidRa(TestApfFilter apfFilter, MockIpClientCallback ipClientCallback,
Lorenzo Colitti8995d852016-06-23 15:24:46 +09001787 ByteBuffer packet) throws IOException, ErrnoException {
Erik Kline8d1fe542018-03-12 23:18:58 +09001788 ipClientCallback.resetApfProgramWait();
Lorenzo Colitti8995d852016-06-23 15:24:46 +09001789 apfFilter.pretendPacketReceived(packet.array());
Erik Kline8d1fe542018-03-12 23:18:58 +09001790 ipClientCallback.assertNoProgramUpdate();
Lorenzo Colitti8995d852016-06-23 15:24:46 +09001791 }
1792
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001793 @Test
Paul Jensen9132f342016-04-13 15:00:26 -04001794 public void testApfFilterRa() throws Exception {
Erik Kline8d1fe542018-03-12 23:18:58 +09001795 MockIpClientCallback ipClientCallback = new MockIpClientCallback();
Hugo Benichi72166362017-10-13 16:32:20 +09001796 ApfConfiguration config = getDefaultConfig();
1797 config.multicastFilter = DROP_MULTICAST;
1798 config.ieee802_3Filter = DROP_802_3_FRAMES;
Erik Kline8d1fe542018-03-12 23:18:58 +09001799 TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog);
1800 byte[] program = ipClientCallback.getApfProgram();
Paul Jensen9132f342016-04-13 15:00:26 -04001801
Hugo Benichi4456f332016-12-19 14:50:52 +09001802 final int ROUTER_LIFETIME = 1000;
1803 final int PREFIX_VALID_LIFETIME = 200;
1804 final int PREFIX_PREFERRED_LIFETIME = 100;
1805 final int RDNSS_LIFETIME = 300;
1806 final int ROUTE_LIFETIME = 400;
1807 // Note that lifetime of 2000 will be ignored in favor of shorter route lifetime of 1000.
1808 final int DNSSL_LIFETIME = 2000;
Joel Scherpelz967dec72017-05-24 15:08:39 +09001809 final int VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET = ETH_HEADER_LEN;
1810 // IPv6, traffic class = 0, flow label = 0x12345
1811 final int VERSION_TRAFFIC_CLASS_FLOW_LABEL = 0x60012345;
Hugo Benichi4456f332016-12-19 14:50:52 +09001812
Paul Jensen9132f342016-04-13 15:00:26 -04001813 // Verify RA is passed the first time
1814 ByteBuffer basePacket = ByteBuffer.wrap(new byte[ICMP6_RA_OPTION_OFFSET]);
1815 basePacket.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
Joel Scherpelz967dec72017-05-24 15:08:39 +09001816 basePacket.putInt(VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET,
1817 VERSION_TRAFFIC_CLASS_FLOW_LABEL);
Paul Jensen9132f342016-04-13 15:00:26 -04001818 basePacket.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6);
1819 basePacket.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_ROUTER_ADVERTISEMENT);
Hugo Benichi4456f332016-12-19 14:50:52 +09001820 basePacket.putShort(ICMP6_RA_ROUTER_LIFETIME_OFFSET, (short)ROUTER_LIFETIME);
Lorenzo Colitti11e13e22016-05-20 00:04:43 +09001821 basePacket.position(IPV6_DEST_ADDR_OFFSET);
1822 basePacket.put(IPV6_ALL_NODES_ADDRESS);
Hugo Benichi961ca492016-09-02 11:04:34 +09001823 assertPass(program, basePacket.array());
Paul Jensen9132f342016-04-13 15:00:26 -04001824
Erik Kline8d1fe542018-03-12 23:18:58 +09001825 verifyRaLifetime(apfFilter, ipClientCallback, basePacket, ROUTER_LIFETIME);
Hugo Benichi4456f332016-12-19 14:50:52 +09001826 verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, -1, -1));
Paul Jensen9132f342016-04-13 15:00:26 -04001827
Joel Scherpelz967dec72017-05-24 15:08:39 +09001828 ByteBuffer newFlowLabelPacket = ByteBuffer.wrap(new byte[ICMP6_RA_OPTION_OFFSET]);
1829 basePacket.clear();
1830 newFlowLabelPacket.put(basePacket);
1831 // Check that changes are ignored in every byte of the flow label.
1832 newFlowLabelPacket.putInt(VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET,
1833 VERSION_TRAFFIC_CLASS_FLOW_LABEL + 0x11111);
1834
Lorenzo Colitti8995d852016-06-23 15:24:46 +09001835 // Ensure zero-length options cause the packet to be silently skipped.
1836 // Do this before we test other packets. http://b/29586253
1837 ByteBuffer zeroLengthOptionPacket = ByteBuffer.wrap(
1838 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]);
1839 basePacket.clear();
1840 zeroLengthOptionPacket.put(basePacket);
1841 zeroLengthOptionPacket.put((byte)ICMP6_PREFIX_OPTION_TYPE);
1842 zeroLengthOptionPacket.put((byte)0);
Erik Kline8d1fe542018-03-12 23:18:58 +09001843 assertInvalidRa(apfFilter, ipClientCallback, zeroLengthOptionPacket);
Lorenzo Colitti8995d852016-06-23 15:24:46 +09001844
Paul Jensen9132f342016-04-13 15:00:26 -04001845 // Generate several RAs with different options and lifetimes, and verify when
1846 // ApfFilter is shown these packets, it generates programs to filter them for the
1847 // appropriate lifetime.
1848 ByteBuffer prefixOptionPacket = ByteBuffer.wrap(
1849 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_PREFIX_OPTION_LEN]);
1850 basePacket.clear();
1851 prefixOptionPacket.put(basePacket);
1852 prefixOptionPacket.put((byte)ICMP6_PREFIX_OPTION_TYPE);
1853 prefixOptionPacket.put((byte)(ICMP6_PREFIX_OPTION_LEN / 8));
1854 prefixOptionPacket.putInt(
Hugo Benichi4456f332016-12-19 14:50:52 +09001855 ICMP6_RA_OPTION_OFFSET + ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_OFFSET,
1856 PREFIX_PREFERRED_LIFETIME);
Paul Jensen9132f342016-04-13 15:00:26 -04001857 prefixOptionPacket.putInt(
Hugo Benichi4456f332016-12-19 14:50:52 +09001858 ICMP6_RA_OPTION_OFFSET + ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET,
1859 PREFIX_VALID_LIFETIME);
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001860 verifyRaLifetime(
Erik Kline8d1fe542018-03-12 23:18:58 +09001861 apfFilter, ipClientCallback, prefixOptionPacket, PREFIX_PREFERRED_LIFETIME);
Hugo Benichi4456f332016-12-19 14:50:52 +09001862 verifyRaEvent(new RaEvent(
1863 ROUTER_LIFETIME, PREFIX_VALID_LIFETIME, PREFIX_PREFERRED_LIFETIME, -1, -1, -1));
Paul Jensen9132f342016-04-13 15:00:26 -04001864
1865 ByteBuffer rdnssOptionPacket = ByteBuffer.wrap(
1866 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]);
1867 basePacket.clear();
1868 rdnssOptionPacket.put(basePacket);
1869 rdnssOptionPacket.put((byte)ICMP6_RDNSS_OPTION_TYPE);
1870 rdnssOptionPacket.put((byte)(ICMP6_4_BYTE_OPTION_LEN / 8));
1871 rdnssOptionPacket.putInt(
Hugo Benichi4456f332016-12-19 14:50:52 +09001872 ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, RDNSS_LIFETIME);
Erik Kline8d1fe542018-03-12 23:18:58 +09001873 verifyRaLifetime(apfFilter, ipClientCallback, rdnssOptionPacket, RDNSS_LIFETIME);
Hugo Benichi4456f332016-12-19 14:50:52 +09001874 verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, RDNSS_LIFETIME, -1));
Paul Jensen9132f342016-04-13 15:00:26 -04001875
1876 ByteBuffer routeInfoOptionPacket = ByteBuffer.wrap(
1877 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]);
1878 basePacket.clear();
1879 routeInfoOptionPacket.put(basePacket);
1880 routeInfoOptionPacket.put((byte)ICMP6_ROUTE_INFO_OPTION_TYPE);
1881 routeInfoOptionPacket.put((byte)(ICMP6_4_BYTE_OPTION_LEN / 8));
1882 routeInfoOptionPacket.putInt(
Hugo Benichi4456f332016-12-19 14:50:52 +09001883 ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, ROUTE_LIFETIME);
Erik Kline8d1fe542018-03-12 23:18:58 +09001884 verifyRaLifetime(apfFilter, ipClientCallback, routeInfoOptionPacket, ROUTE_LIFETIME);
Hugo Benichi4456f332016-12-19 14:50:52 +09001885 verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, ROUTE_LIFETIME, -1, -1));
Paul Jensen9132f342016-04-13 15:00:26 -04001886
1887 ByteBuffer dnsslOptionPacket = ByteBuffer.wrap(
1888 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]);
1889 basePacket.clear();
1890 dnsslOptionPacket.put(basePacket);
1891 dnsslOptionPacket.put((byte)ICMP6_DNSSL_OPTION_TYPE);
1892 dnsslOptionPacket.put((byte)(ICMP6_4_BYTE_OPTION_LEN / 8));
1893 dnsslOptionPacket.putInt(
Hugo Benichi4456f332016-12-19 14:50:52 +09001894 ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, DNSSL_LIFETIME);
Erik Kline8d1fe542018-03-12 23:18:58 +09001895 verifyRaLifetime(apfFilter, ipClientCallback, dnsslOptionPacket, ROUTER_LIFETIME);
Hugo Benichi4456f332016-12-19 14:50:52 +09001896 verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, -1, DNSSL_LIFETIME));
Paul Jensen9132f342016-04-13 15:00:26 -04001897
1898 // Verify that current program filters all five RAs:
Erik Kline8d1fe542018-03-12 23:18:58 +09001899 program = ipClientCallback.getApfProgram();
Hugo Benichi4456f332016-12-19 14:50:52 +09001900 verifyRaLifetime(program, basePacket, ROUTER_LIFETIME);
Joel Scherpelz967dec72017-05-24 15:08:39 +09001901 verifyRaLifetime(program, newFlowLabelPacket, ROUTER_LIFETIME);
Hugo Benichi4456f332016-12-19 14:50:52 +09001902 verifyRaLifetime(program, prefixOptionPacket, PREFIX_PREFERRED_LIFETIME);
1903 verifyRaLifetime(program, rdnssOptionPacket, RDNSS_LIFETIME);
1904 verifyRaLifetime(program, routeInfoOptionPacket, ROUTE_LIFETIME);
1905 verifyRaLifetime(program, dnsslOptionPacket, ROUTER_LIFETIME);
Paul Jensen9132f342016-04-13 15:00:26 -04001906
1907 apfFilter.shutdown();
1908 }
1909
1910 /**
1911 * Stage a file for testing, i.e. make it native accessible. Given a resource ID,
1912 * copy that resource into the app's data directory and return the path to it.
1913 */
1914 private String stageFile(int rawId) throws Exception {
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001915 File file = new File(InstrumentationRegistry.getContext().getFilesDir(), "staged_file");
Paul Jensen9132f342016-04-13 15:00:26 -04001916 new File(file.getParent()).mkdirs();
1917 InputStream in = null;
1918 OutputStream out = null;
1919 try {
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001920 in = InstrumentationRegistry.getContext().getResources().openRawResource(rawId);
Paul Jensen9132f342016-04-13 15:00:26 -04001921 out = new FileOutputStream(file);
1922 Streams.copy(in, out);
1923 } finally {
1924 if (in != null) in.close();
1925 if (out != null) out.close();
1926 }
1927 return file.getAbsolutePath();
1928 }
1929
Hugo Benichi961ca492016-09-02 11:04:34 +09001930 private static void put(ByteBuffer buffer, int position, byte[] bytes) {
1931 final int original = buffer.position();
1932 buffer.position(position);
1933 buffer.put(bytes);
1934 buffer.position(original);
1935 }
1936
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001937 @Test
Hugo Benichi0668a612016-10-06 15:19:36 +09001938 public void testRaParsing() throws Exception {
1939 final int maxRandomPacketSize = 512;
1940 final Random r = new Random();
Erik Kline8d1fe542018-03-12 23:18:58 +09001941 MockIpClientCallback cb = new MockIpClientCallback();
Hugo Benichi72166362017-10-13 16:32:20 +09001942 ApfConfiguration config = getDefaultConfig();
1943 config.multicastFilter = DROP_MULTICAST;
1944 config.ieee802_3Filter = DROP_802_3_FRAMES;
Bernie Innocentie2c70f82018-03-28 20:11:49 +09001945 TestApfFilter apfFilter = new TestApfFilter(mContext, config, cb, mLog);
Hugo Benichi0668a612016-10-06 15:19:36 +09001946 for (int i = 0; i < 1000; i++) {
1947 byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)];
1948 r.nextBytes(packet);
1949 try {
1950 apfFilter.new Ra(packet, packet.length);
1951 } catch (ApfFilter.InvalidRaException e) {
1952 } catch (Exception e) {
1953 throw new Exception("bad packet: " + HexDump.toHexString(packet), e);
1954 }
1955 }
1956 }
1957
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09001958 @Test
Hugo Benichi0668a612016-10-06 15:19:36 +09001959 public void testRaProcessing() throws Exception {
1960 final int maxRandomPacketSize = 512;
1961 final Random r = new Random();
Erik Kline8d1fe542018-03-12 23:18:58 +09001962 MockIpClientCallback cb = new MockIpClientCallback();
Hugo Benichi72166362017-10-13 16:32:20 +09001963 ApfConfiguration config = getDefaultConfig();
1964 config.multicastFilter = DROP_MULTICAST;
1965 config.ieee802_3Filter = DROP_802_3_FRAMES;
Bernie Innocentie2c70f82018-03-28 20:11:49 +09001966 TestApfFilter apfFilter = new TestApfFilter(mContext, config, cb, mLog);
Hugo Benichi0668a612016-10-06 15:19:36 +09001967 for (int i = 0; i < 1000; i++) {
1968 byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)];
1969 r.nextBytes(packet);
1970 try {
1971 apfFilter.processRa(packet, packet.length);
1972 } catch (Exception e) {
1973 throw new Exception("bad packet: " + HexDump.toHexString(packet), e);
1974 }
1975 }
1976 }
1977
Paul Jensen9132f342016-04-13 15:00:26 -04001978 /**
Bernie Innocentia9949e92018-03-22 23:07:47 +09001979 * Call the APF interpreter to run {@code program} on {@code packet} with persistent memory
1980 * segment {@data} pretending the filter was installed {@code filter_age} seconds ago.
Paul Jensen9132f342016-04-13 15:00:26 -04001981 */
Bernie Innocentia9949e92018-03-22 23:07:47 +09001982 private native static int apfSimulate(byte[] program, byte[] packet, byte[] data,
1983 int filter_age);
Paul Jensen9132f342016-04-13 15:00:26 -04001984
1985 /**
1986 * Compile a tcpdump human-readable filter (e.g. "icmp" or "tcp port 54") into a BPF
1987 * prorgam and return a human-readable dump of the BPF program identical to "tcpdump -d".
1988 */
1989 private native static String compileToBpf(String filter);
1990
1991 /**
1992 * Open packet capture file {@code pcap_filename} and filter the packets using tcpdump
1993 * human-readable filter (e.g. "icmp" or "tcp port 54") compiled to a BPF program and
1994 * at the same time using APF program {@code apf_program}. Return {@code true} if
1995 * both APF and BPF programs filter out exactly the same packets.
1996 */
1997 private native static boolean compareBpfApf(String filter, String pcap_filename,
1998 byte[] apf_program);
Hugo Benichi7d21eae2016-09-02 14:00:29 +09001999
Aaron Huang785e5f12018-10-31 15:57:48 +08002000
2001 /**
2002 * Open packet capture file {@code pcapFilename} and run it through APF filter. Then
2003 * checks whether all the packets are dropped and populates data[] {@code data} with
2004 * the APF counters.
2005 */
2006 private native static boolean dropsAllPackets(byte[] program, byte[] data, String pcapFilename);
2007
Hugo Benichi4a0c5d72017-10-11 11:26:25 +09002008 @Test
Hugo Benichi7d21eae2016-09-02 14:00:29 +09002009 public void testBroadcastAddress() throws Exception {
2010 assertEqualsIp("255.255.255.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 0));
2011 assertEqualsIp("0.0.0.0", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 32));
2012 assertEqualsIp("0.0.3.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 22));
2013 assertEqualsIp("0.255.255.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 8));
2014
2015 assertEqualsIp("255.255.255.255", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 0));
2016 assertEqualsIp("10.0.0.1", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 32));
2017 assertEqualsIp("10.0.0.255", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 24));
2018 assertEqualsIp("10.0.255.255", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 16));
2019 }
2020
2021 public void assertEqualsIp(String expected, int got) throws Exception {
Hugo Benichi495a17b2017-01-12 15:31:05 +09002022 int want = bytesToBEInt(InetAddress.getByName(expected).getAddress());
Hugo Benichi7d21eae2016-09-02 14:00:29 +09002023 assertEquals(want, got);
2024 }
Paul Jensen9132f342016-04-13 15:00:26 -04002025}