blob: 6de31f6b4be12b391000576359364f25b68551da [file] [log] [blame]
Hugo Benichi88ad29b2017-10-12 21:33:40 +09001/*
2 * Copyright 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.net;
18
Etan Cohen42ab31a2018-11-02 15:07:20 -070019import static org.junit.Assert.assertArrayEquals;
Hugo Benichi88ad29b2017-10-12 21:33:40 +090020import static org.junit.Assert.assertEquals;
Hugo Benichi88ad29b2017-10-12 21:33:40 +090021import static org.junit.Assert.assertFalse;
Roshan Piuse26dae32018-10-05 09:42:19 -070022import static org.junit.Assert.assertTrue;
Hugo Benichid380d142017-11-09 00:22:25 +090023import static org.junit.Assert.fail;
Hugo Benichi88ad29b2017-10-12 21:33:40 +090024
Brett Chabot147f6cf2019-03-04 14:14:56 -080025import androidx.test.filters.SmallTest;
26import androidx.test.runner.AndroidJUnit4;
Hugo Benichi88ad29b2017-10-12 21:33:40 +090027
Chalard Jean79162542020-08-19 16:07:22 +090028import com.android.net.module.util.MacAddressUtils;
29
Hugo Benichi88ad29b2017-10-12 21:33:40 +090030import org.junit.Test;
31import org.junit.runner.RunWith;
32
Etan Cohen42ab31a2018-11-02 15:07:20 -070033import java.net.Inet6Address;
34import java.util.Arrays;
35import java.util.Random;
36
Hugo Benichi88ad29b2017-10-12 21:33:40 +090037@SmallTest
38@RunWith(AndroidJUnit4.class)
39public class MacAddressTest {
40
41 static class AddrTypeTestCase {
42 byte[] addr;
Hugo Benichi5bc35462017-11-16 14:40:16 +090043 int expectedType;
Hugo Benichi88ad29b2017-10-12 21:33:40 +090044
Hugo Benichi5bc35462017-11-16 14:40:16 +090045 static AddrTypeTestCase of(int expectedType, int... addr) {
Hugo Benichi88ad29b2017-10-12 21:33:40 +090046 AddrTypeTestCase t = new AddrTypeTestCase();
Hugo Benichi5bc35462017-11-16 14:40:16 +090047 t.expectedType = expectedType;
Hugo Benichi88ad29b2017-10-12 21:33:40 +090048 t.addr = toByteArray(addr);
49 return t;
50 }
51 }
52
53 @Test
54 public void testMacAddrTypes() {
55 AddrTypeTestCase[] testcases = {
Hugo Benichi5bc35462017-11-16 14:40:16 +090056 AddrTypeTestCase.of(MacAddress.TYPE_UNKNOWN),
57 AddrTypeTestCase.of(MacAddress.TYPE_UNKNOWN, 0),
58 AddrTypeTestCase.of(MacAddress.TYPE_UNKNOWN, 1, 2, 3, 4, 5),
59 AddrTypeTestCase.of(MacAddress.TYPE_UNKNOWN, 1, 2, 3, 4, 5, 6, 7),
60 AddrTypeTestCase.of(MacAddress.TYPE_UNICAST, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0),
61 AddrTypeTestCase.of(MacAddress.TYPE_BROADCAST, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff),
62 AddrTypeTestCase.of(MacAddress.TYPE_MULTICAST, 1, 2, 3, 4, 5, 6),
63 AddrTypeTestCase.of(MacAddress.TYPE_MULTICAST, 11, 22, 33, 44, 55, 66),
64 AddrTypeTestCase.of(MacAddress.TYPE_MULTICAST, 33, 33, 0xaa, 0xbb, 0xcc, 0xdd)
Hugo Benichi88ad29b2017-10-12 21:33:40 +090065 };
66
67 for (AddrTypeTestCase t : testcases) {
Hugo Benichi5bc35462017-11-16 14:40:16 +090068 int got = MacAddress.macAddressType(t.addr);
Hugo Benichi88ad29b2017-10-12 21:33:40 +090069 String msg = String.format("expected type of %s to be %s, but got %s",
Hugo Benichi5bc35462017-11-16 14:40:16 +090070 Arrays.toString(t.addr), t.expectedType, got);
71 assertEquals(msg, t.expectedType, got);
Hugo Benichid380d142017-11-09 00:22:25 +090072
Hugo Benichi5bc35462017-11-16 14:40:16 +090073 if (got != MacAddress.TYPE_UNKNOWN) {
Hugo Benichi8f217582018-01-12 09:46:29 +090074 assertEquals(got, MacAddress.fromBytes(t.addr).getAddressType());
Hugo Benichid380d142017-11-09 00:22:25 +090075 }
Hugo Benichi88ad29b2017-10-12 21:33:40 +090076 }
77 }
78
Hugo Benichid380d142017-11-09 00:22:25 +090079 @Test
Hugo Benichi3f83b8a2017-12-15 10:07:35 +090080 public void testToOuiString() {
Hugo Benichi5bc35462017-11-16 14:40:16 +090081 String[][] macs = {
Hugo Benichi3f83b8a2017-12-15 10:07:35 +090082 {"07:00:d3:56:8a:c4", "07:00:d3"},
83 {"33:33:aa:bb:cc:dd", "33:33:aa"},
84 {"06:00:00:00:00:00", "06:00:00"},
85 {"07:00:d3:56:8a:c4", "07:00:d3"}
Hugo Benichi5bc35462017-11-16 14:40:16 +090086 };
87
88 for (String[] pair : macs) {
89 String mac = pair[0];
90 String expected = pair[1];
Hugo Benichi3f83b8a2017-12-15 10:07:35 +090091 assertEquals(expected, MacAddress.fromString(mac).toOuiString());
Hugo Benichi5bc35462017-11-16 14:40:16 +090092 }
93 }
94
95 @Test
96 public void testHexPaddingWhenPrinting() {
97 String[] macs = {
98 "07:00:d3:56:8a:c4",
99 "33:33:aa:bb:cc:dd",
100 "06:00:00:00:00:00",
101 "07:00:d3:56:8a:c4"
102 };
103
104 for (String mac : macs) {
105 assertEquals(mac, MacAddress.fromString(mac).toString());
106 assertEquals(mac,
107 MacAddress.stringAddrFromByteAddr(MacAddress.byteAddrFromStringAddr(mac)));
108 }
109 }
110
111 @Test
Hugo Benichid380d142017-11-09 00:22:25 +0900112 public void testIsMulticastAddress() {
113 MacAddress[] multicastAddresses = {
114 MacAddress.BROADCAST_ADDRESS,
Hugo Benichi5bc35462017-11-16 14:40:16 +0900115 MacAddress.fromString("07:00:d3:56:8a:c4"),
116 MacAddress.fromString("33:33:aa:bb:cc:dd"),
Hugo Benichid380d142017-11-09 00:22:25 +0900117 };
118 MacAddress[] unicastAddresses = {
119 MacAddress.ALL_ZEROS_ADDRESS,
Hugo Benichi5bc35462017-11-16 14:40:16 +0900120 MacAddress.fromString("00:01:44:55:66:77"),
121 MacAddress.fromString("08:00:22:33:44:55"),
122 MacAddress.fromString("06:00:00:00:00:00"),
Hugo Benichid380d142017-11-09 00:22:25 +0900123 };
124
125 for (MacAddress mac : multicastAddresses) {
126 String msg = mac.toString() + " expected to be a multicast address";
Aaron Huangadfebb82019-12-17 00:33:18 +0800127 assertTrue(msg, MacAddressUtils.isMulticastAddress(mac));
Hugo Benichid380d142017-11-09 00:22:25 +0900128 }
129 for (MacAddress mac : unicastAddresses) {
130 String msg = mac.toString() + " expected not to be a multicast address";
Aaron Huangadfebb82019-12-17 00:33:18 +0800131 assertFalse(msg, MacAddressUtils.isMulticastAddress(mac));
Hugo Benichid380d142017-11-09 00:22:25 +0900132 }
133 }
134
135 @Test
136 public void testIsLocallyAssignedAddress() {
137 MacAddress[] localAddresses = {
Hugo Benichi5bc35462017-11-16 14:40:16 +0900138 MacAddress.fromString("06:00:00:00:00:00"),
139 MacAddress.fromString("07:00:d3:56:8a:c4"),
140 MacAddress.fromString("33:33:aa:bb:cc:dd"),
Hugo Benichid380d142017-11-09 00:22:25 +0900141 };
142 MacAddress[] universalAddresses = {
Hugo Benichi5bc35462017-11-16 14:40:16 +0900143 MacAddress.fromString("00:01:44:55:66:77"),
144 MacAddress.fromString("08:00:22:33:44:55"),
Hugo Benichid380d142017-11-09 00:22:25 +0900145 };
146
147 for (MacAddress mac : localAddresses) {
148 String msg = mac.toString() + " expected to be a locally assigned address";
149 assertTrue(msg, mac.isLocallyAssigned());
150 }
151 for (MacAddress mac : universalAddresses) {
152 String msg = mac.toString() + " expected not to be globally unique address";
153 assertFalse(msg, mac.isLocallyAssigned());
154 }
155 }
156
157 @Test
158 public void testMacAddressConversions() {
159 final int iterations = 10000;
160 for (int i = 0; i < iterations; i++) {
Aaron Huangadfebb82019-12-17 00:33:18 +0800161 MacAddress mac = MacAddressUtils.createRandomUnicastAddress();
Hugo Benichid380d142017-11-09 00:22:25 +0900162
163 String stringRepr = mac.toString();
164 byte[] bytesRepr = mac.toByteArray();
165
Hugo Benichi5bc35462017-11-16 14:40:16 +0900166 assertEquals(mac, MacAddress.fromString(stringRepr));
167 assertEquals(mac, MacAddress.fromBytes(bytesRepr));
Hugo Benichi21c7a522017-12-05 13:14:08 +0900168
169 assertEquals(mac, MacAddress.fromString(MacAddress.stringAddrFromByteAddr(bytesRepr)));
170 assertEquals(mac, MacAddress.fromBytes(MacAddress.byteAddrFromStringAddr(stringRepr)));
Hugo Benichid380d142017-11-09 00:22:25 +0900171 }
172 }
173
174 @Test
175 public void testMacAddressRandomGeneration() {
176 final int iterations = 1000;
177 final String expectedAndroidOui = "da:a1:19";
178 for (int i = 0; i < iterations; i++) {
Jong Wook Kim93dd5e62018-01-31 19:03:19 -0800179 MacAddress mac = MacAddress.createRandomUnicastAddressWithGoogleBase();
Hugo Benichid380d142017-11-09 00:22:25 +0900180 String stringRepr = mac.toString();
181
182 assertTrue(stringRepr + " expected to be a locally assigned address",
183 mac.isLocallyAssigned());
184 assertTrue(stringRepr + " expected to begin with " + expectedAndroidOui,
185 stringRepr.startsWith(expectedAndroidOui));
186 }
187
188 final Random r = new Random();
189 final String anotherOui = "24:5f:78";
190 final String expectedLocalOui = "26:5f:78";
Hugo Benichi5bc35462017-11-16 14:40:16 +0900191 final MacAddress base = MacAddress.fromString(anotherOui + ":0:0:0");
Hugo Benichid380d142017-11-09 00:22:25 +0900192 for (int i = 0; i < iterations; i++) {
Aaron Huangadfebb82019-12-17 00:33:18 +0800193 MacAddress mac = MacAddressUtils.createRandomUnicastAddress(base, r);
Hugo Benichid380d142017-11-09 00:22:25 +0900194 String stringRepr = mac.toString();
195
196 assertTrue(stringRepr + " expected to be a locally assigned address",
197 mac.isLocallyAssigned());
Hugo Benichi8f217582018-01-12 09:46:29 +0900198 assertEquals(MacAddress.TYPE_UNICAST, mac.getAddressType());
Hugo Benichid380d142017-11-09 00:22:25 +0900199 assertTrue(stringRepr + " expected to begin with " + expectedLocalOui,
200 stringRepr.startsWith(expectedLocalOui));
201 }
Jong Wook Kim93dd5e62018-01-31 19:03:19 -0800202
203 for (int i = 0; i < iterations; i++) {
Aaron Huangadfebb82019-12-17 00:33:18 +0800204 MacAddress mac = MacAddressUtils.createRandomUnicastAddress();
Jong Wook Kim93dd5e62018-01-31 19:03:19 -0800205 String stringRepr = mac.toString();
206
207 assertTrue(stringRepr + " expected to be a locally assigned address",
208 mac.isLocallyAssigned());
209 assertEquals(MacAddress.TYPE_UNICAST, mac.getAddressType());
210 }
Hugo Benichid380d142017-11-09 00:22:25 +0900211 }
212
213 @Test
214 public void testConstructorInputValidation() {
215 String[] invalidStringAddresses = {
Hugo Benichid380d142017-11-09 00:22:25 +0900216 "",
217 "abcd",
218 "1:2:3:4:5",
219 "1:2:3:4:5:6:7",
220 "10000:2:3:4:5:6",
221 };
222
223 for (String s : invalidStringAddresses) {
224 try {
Hugo Benichi5bc35462017-11-16 14:40:16 +0900225 MacAddress mac = MacAddress.fromString(s);
226 fail("MacAddress.fromString(" + s + ") should have failed, but returned " + mac);
Hugo Benichid380d142017-11-09 00:22:25 +0900227 } catch (IllegalArgumentException excepted) {
228 }
229 }
230
Hugo Benichi5bc35462017-11-16 14:40:16 +0900231 try {
232 MacAddress mac = MacAddress.fromString(null);
233 fail("MacAddress.fromString(null) should have failed, but returned " + mac);
234 } catch (NullPointerException excepted) {
235 }
236
Hugo Benichid380d142017-11-09 00:22:25 +0900237 byte[][] invalidBytesAddresses = {
Hugo Benichid380d142017-11-09 00:22:25 +0900238 {},
239 {1,2,3,4,5},
240 {1,2,3,4,5,6,7},
241 };
242
243 for (byte[] b : invalidBytesAddresses) {
244 try {
Hugo Benichi5bc35462017-11-16 14:40:16 +0900245 MacAddress mac = MacAddress.fromBytes(b);
246 fail("MacAddress.fromBytes(" + Arrays.toString(b)
Hugo Benichid380d142017-11-09 00:22:25 +0900247 + ") should have failed, but returned " + mac);
248 } catch (IllegalArgumentException excepted) {
249 }
250 }
Hugo Benichi5bc35462017-11-16 14:40:16 +0900251
252 try {
253 MacAddress mac = MacAddress.fromBytes(null);
254 fail("MacAddress.fromBytes(null) should have failed, but returned " + mac);
255 } catch (NullPointerException excepted) {
256 }
Hugo Benichid380d142017-11-09 00:22:25 +0900257 }
258
Roshan Piuse26dae32018-10-05 09:42:19 -0700259 @Test
260 public void testMatches() {
261 // match 4 bytes prefix
262 assertTrue(MacAddress.fromString("aa:bb:cc:dd:ee:11").matches(
263 MacAddress.fromString("aa:bb:cc:dd:00:00"),
264 MacAddress.fromString("ff:ff:ff:ff:00:00")));
265
266 // match bytes 0,1,2 and 5
267 assertTrue(MacAddress.fromString("aa:bb:cc:dd:ee:11").matches(
268 MacAddress.fromString("aa:bb:cc:00:00:11"),
269 MacAddress.fromString("ff:ff:ff:00:00:ff")));
270
271 // match 34 bit prefix
272 assertTrue(MacAddress.fromString("aa:bb:cc:dd:ee:11").matches(
273 MacAddress.fromString("aa:bb:cc:dd:c0:00"),
274 MacAddress.fromString("ff:ff:ff:ff:c0:00")));
275
276 // fail to match 36 bit prefix
277 assertFalse(MacAddress.fromString("aa:bb:cc:dd:ee:11").matches(
278 MacAddress.fromString("aa:bb:cc:dd:40:00"),
279 MacAddress.fromString("ff:ff:ff:ff:f0:00")));
280
281 // match all 6 bytes
282 assertTrue(MacAddress.fromString("aa:bb:cc:dd:ee:11").matches(
283 MacAddress.fromString("aa:bb:cc:dd:ee:11"),
284 MacAddress.fromString("ff:ff:ff:ff:ff:ff")));
285
286 // match none of 6 bytes
287 assertTrue(MacAddress.fromString("aa:bb:cc:dd:ee:11").matches(
288 MacAddress.fromString("00:00:00:00:00:00"),
289 MacAddress.fromString("00:00:00:00:00:00")));
290 }
291
Etan Cohen42ab31a2018-11-02 15:07:20 -0700292 /**
293 * Tests that link-local address generation from MAC is valid.
294 */
295 @Test
296 public void testLinkLocalFromMacGeneration() {
297 MacAddress mac = MacAddress.fromString("52:74:f2:b1:a8:7f");
298 byte[] inet6ll = {(byte) 0xfe, (byte) 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x74,
299 (byte) 0xf2, (byte) 0xff, (byte) 0xfe, (byte) 0xb1, (byte) 0xa8, 0x7f};
300 Inet6Address llv6 = mac.getLinkLocalIpv6FromEui48Mac();
301 assertTrue(llv6.isLinkLocalAddress());
302 assertArrayEquals(inet6ll, llv6.getAddress());
303 }
304
Hugo Benichid380d142017-11-09 00:22:25 +0900305 static byte[] toByteArray(int... in) {
Hugo Benichi88ad29b2017-10-12 21:33:40 +0900306 byte[] out = new byte[in.length];
307 for (int i = 0; i < in.length; i++) {
308 out[i] = (byte) in[i];
309 }
310 return out;
311 }
312}