1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.wifi.util; 18 19 import static org.junit.Assert.assertArrayEquals; 20 import static org.junit.Assert.assertEquals; 21 import static org.junit.Assert.assertFalse; 22 import static org.junit.Assert.assertTrue; 23 24 import android.net.wifi.ScanResult.InformationElement; 25 import android.test.suitebuilder.annotation.SmallTest; 26 27 import com.android.server.wifi.hotspot2.NetworkDetail; 28 29 import org.junit.Test; 30 31 import java.io.ByteArrayOutputStream; 32 import java.io.IOException; 33 import java.util.Arrays; 34 import java.util.BitSet; 35 36 /** 37 * Unit tests for {@link com.android.server.wifi.util.InformationElementUtil}. 38 */ 39 @SmallTest 40 public class InformationElementUtilTest { 41 42 // SSID Information Element tags 43 private static final byte[] TEST_SSID_BYTES_TAG = new byte[] { (byte) 0x00, (byte) 0x0B }; 44 // SSID Information Element entry used for testing. 45 private static final byte[] TEST_SSID_BYTES = "GoogleGuest".getBytes(); 46 // Valid zero length tag. 47 private static final byte[] TEST_VALID_ZERO_LENGTH_TAG = 48 new byte[] { (byte) 0x0B, (byte) 0x00 }; 49 // BSS_LOAD Information Element entry used for testing. 50 private static final byte[] TEST_BSS_LOAD_BYTES_IE = 51 new byte[] { (byte) 0x0B, (byte) 0x01, (byte) 0x08 }; 52 53 /* 54 * Function to provide SSID Information Element (SSID = "GoogleGuest"). 55 * 56 * @return byte[] Byte array representing the test SSID 57 */ 58 private byte[] getTestSsidIEBytes() throws IOException { 59 return concatenateByteArrays(TEST_SSID_BYTES_TAG, TEST_SSID_BYTES); 60 } 61 62 /* 63 * Function used to set byte arrays used for testing. 64 * 65 * @param byteArrays variable number of byte arrays to concatenate 66 * @return byte[] Byte array resulting from concatenating the arrays passed to the function 67 */ 68 private static byte[] concatenateByteArrays(byte[]... byteArrays) throws IOException { 69 final ByteArrayOutputStream baos = new ByteArrayOutputStream(); 70 for (byte[] b : byteArrays) { 71 baos.write(b); 72 } 73 baos.flush(); 74 return baos.toByteArray(); 75 } 76 77 /** 78 * Test parseInformationElements with an empty byte array. 79 * Expect parseInformationElement to return an empty InformationElement array. 80 */ 81 @Test 82 public void parseInformationElements_withEmptyByteArray() { 83 byte[] emptyBytes = new byte[0]; 84 InformationElement[] results = 85 InformationElementUtil.parseInformationElements(emptyBytes); 86 assertEquals("parsed results should be empty", 0, results.length); 87 } 88 89 /** 90 * Test parseInformationElements called with a null parameter. 91 * Expect parseInfomrationElement to return an empty InformationElement array. 92 */ 93 @Test 94 public void parseInformationElements_withNullBytes() { 95 byte[] nullBytes = null; 96 InformationElement[] results = 97 InformationElementUtil.parseInformationElements(nullBytes); 98 assertEquals("parsed results should be empty", 0, results.length); 99 } 100 101 /* 102 * Test parseInformationElements with a single element represented in the byte array. 103 * Expect a single element to be returned in the InformationElements array. The 104 * length of this array should be 1 and the contents should be valid. 105 * 106 * @throws java.io.IOException 107 */ 108 @Test 109 public void parseInformationElements_withSingleElement() throws IOException { 110 byte[] ssidBytes = getTestSsidIEBytes(); 111 112 InformationElement[] results = 113 InformationElementUtil.parseInformationElements(ssidBytes); 114 assertEquals("Parsed results should have 1 IE", 1, results.length); 115 assertEquals("Parsed result should be a ssid", InformationElement.EID_SSID, results[0].id); 116 assertArrayEquals("parsed SSID does not match input", 117 TEST_SSID_BYTES, results[0].bytes); 118 } 119 120 /* 121 * Test parseInformationElement with extra padding in the data to parse. 122 * Expect the function to return the SSID information element. 123 * 124 * Note: Experience shows that APs often pad messages with 0x00. This happens to be the tag for 125 * EID_SSID. This test checks if padding will be properly discarded. 126 * 127 * @throws java.io.IOException 128 */ 129 @Test 130 public void parseInformationElements_withExtraPadding() throws IOException { 131 byte[] paddingBytes = new byte[10]; 132 Arrays.fill(paddingBytes, (byte) 0x00); 133 byte[] ssidBytesWithPadding = concatenateByteArrays(getTestSsidIEBytes(), paddingBytes); 134 135 InformationElement[] results = 136 InformationElementUtil.parseInformationElements(ssidBytesWithPadding); 137 assertEquals("Parsed results should have 1 IE", 1, results.length); 138 assertEquals("Parsed result should be a ssid", InformationElement.EID_SSID, results[0].id); 139 assertArrayEquals("parsed SSID does not match input", 140 TEST_SSID_BYTES, results[0].bytes); 141 } 142 143 /* 144 * Test parseInformationElement with two elements where the second element has an invalid 145 * length. 146 * Expect the function to return the first valid entry and skip the remaining information. 147 * 148 * Note: This test partially exposes issues with blindly parsing the data. A higher level 149 * function to validate the parsed data may be added. 150 * 151 * @throws java.io.IOException 152 * */ 153 @Test 154 public void parseInformationElements_secondElementInvalidLength() throws IOException { 155 byte[] invalidTag = new byte[] { (byte) 0x01, (byte) 0x08, (byte) 0x08 }; 156 byte[] twoTagsSecondInvalidBytes = concatenateByteArrays(getTestSsidIEBytes(), invalidTag); 157 158 InformationElement[] results = 159 InformationElementUtil.parseInformationElements(twoTagsSecondInvalidBytes); 160 assertEquals("Parsed results should have 1 IE", 1, results.length); 161 assertEquals("Parsed result should be a ssid.", InformationElement.EID_SSID, results[0].id); 162 assertArrayEquals("parsed SSID does not match input", 163 TEST_SSID_BYTES, results[0].bytes); 164 } 165 166 /* 167 * Test parseInformationElements with two valid Information Element entries. 168 * Expect the function to return an InformationElement array with two entries containing valid 169 * data. 170 * 171 * @throws java.io.IOException 172 */ 173 @Test 174 public void parseInformationElements_twoElements() throws IOException { 175 byte[] twoValidTagsBytes = 176 concatenateByteArrays(getTestSsidIEBytes(), TEST_BSS_LOAD_BYTES_IE); 177 178 InformationElement[] results = 179 InformationElementUtil.parseInformationElements(twoValidTagsBytes); 180 assertEquals("parsed results should have 2 elements", 2, results.length); 181 assertEquals("First parsed element should be a ssid", 182 InformationElement.EID_SSID, results[0].id); 183 assertArrayEquals("parsed SSID does not match input", 184 TEST_SSID_BYTES, results[0].bytes); 185 assertEquals("second element should be a BSS_LOAD tag", 186 InformationElement.EID_BSS_LOAD, results[1].id); 187 assertEquals("second element should have data of length 1", 1, results[1].bytes.length); 188 assertEquals("second element data was not parsed correctly.", 189 (byte) 0x08, results[1].bytes[0]); 190 } 191 192 /* 193 * Test parseInformationElements with two elements where the first information element has a 194 * length of zero. 195 * Expect the function to return an InformationElement array with two entries containing valid 196 * data. 197 * 198 * @throws java.io.IOException 199 */ 200 @Test 201 public void parseInformationElements_firstElementZeroLength() throws IOException { 202 byte[] zeroLengthTagWithSSIDBytes = 203 concatenateByteArrays(TEST_VALID_ZERO_LENGTH_TAG, getTestSsidIEBytes()); 204 205 InformationElement[] results = 206 InformationElementUtil.parseInformationElements(zeroLengthTagWithSSIDBytes); 207 assertEquals("Parsed results should have 2 elements.", 2, results.length); 208 assertEquals("First element tag should be EID_BSS_LOAD", 209 InformationElement.EID_BSS_LOAD, results[0].id); 210 assertEquals("First element should be length 0", 0, results[0].bytes.length); 211 212 assertEquals("Second element should be a ssid", InformationElement.EID_SSID, results[1].id); 213 assertArrayEquals("parsed SSID does not match input", 214 TEST_SSID_BYTES, results[1].bytes); 215 } 216 217 /* 218 * Test parseInformationElements with two elements where the first element has an invalid 219 * length. The invalid length in the first element causes us to miss the start of the second 220 * Infomation Element. This results in a single element in the returned array. 221 * Expect the function to return a single entry in an InformationElement array. This returned 222 * entry is not validated at this time and does not contain valid data (since the incorrect 223 * length was used). 224 * TODO: attempt to validate the data and recover as much as possible. When the follow-on CL 225 * is in development, this test will be updated to reflect the change. 226 * 227 * @throws java.io.IOException 228 */ 229 @Test 230 public void parseInformationElements_firstElementWrongLength() throws IOException { 231 byte[] invalidLengthTag = new byte[] {(byte) 0x0B, (byte) 0x01 }; 232 byte[] invalidLengthTagWithSSIDBytes = 233 concatenateByteArrays(invalidLengthTag, getTestSsidIEBytes()); 234 235 InformationElement[] results = 236 InformationElementUtil.parseInformationElements(invalidLengthTagWithSSIDBytes); 237 assertEquals("Parsed results should have 1 element", 1, results.length); 238 assertEquals("First result should be a EID_BSS_LOAD tag.", 239 InformationElement.EID_BSS_LOAD, results[0].id); 240 assertEquals("First result should have data of 1 byte", 1, results[0].bytes.length); 241 assertEquals("First result should have data set to 0x00", 242 invalidLengthTagWithSSIDBytes[2], results[0].bytes[0]); 243 } 244 245 /** 246 * Test Capabilities.generateCapabilitiesString() with a RSN IE. 247 * Expect the function to return a string with the proper security information. 248 */ 249 @Test 250 public void buildCapabilities_rsnElement() { 251 InformationElement ie = new InformationElement(); 252 ie.id = InformationElement.EID_RSN; 253 ie.bytes = new byte[] { (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x0F, 254 (byte) 0xAC, (byte) 0x02, (byte) 0x02, (byte) 0x00, 255 (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04, 256 (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x02, 257 (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x0F, 258 (byte) 0xAC, (byte) 0x02, (byte) 0x00, (byte) 0x00 }; 259 260 InformationElement[] ies = new InformationElement[] { ie }; 261 262 BitSet beaconCap = new BitSet(16); 263 beaconCap.set(4); 264 265 InformationElementUtil.Capabilities capabilities = 266 new InformationElementUtil.Capabilities(); 267 capabilities.from(ies, beaconCap); 268 String result = capabilities.generateCapabilitiesString(); 269 270 assertEquals("[WPA2-PSK-CCMP+TKIP]", result); 271 } 272 273 /** 274 * Test Capabilities.generateCapabilitiesString() with a RSN IE which is malformed. 275 * Expect the function to return a string with empty key management & pairswise cipher security 276 * information. 277 */ 278 @Test 279 public void buildCapabilities_malformedRsnElement() { 280 InformationElement ie = new InformationElement(); 281 ie.id = InformationElement.EID_RSN; 282 ie.bytes = new byte[] { (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x0F, 283 (byte) 0xAC, (byte) 0x02, (byte) 0x02, (byte) 0x00, 284 (byte) 0x00, (byte) 0x0F, (byte) 0xAC }; 285 286 InformationElement[] ies = new InformationElement[] { ie }; 287 288 BitSet beaconCap = new BitSet(16); 289 beaconCap.set(4); 290 291 InformationElementUtil.Capabilities capabilities = 292 new InformationElementUtil.Capabilities(); 293 capabilities.from(ies, beaconCap); 294 String result = capabilities.generateCapabilitiesString(); 295 296 assertEquals("[WPA2]", result); 297 } 298 299 /** 300 * Test Capabilities.generateCapabilitiesString() with a WPA type 1 IE. 301 * Expect the function to return a string with the proper security information. 302 */ 303 @Test 304 public void buildCapabilities_wpa1Element() { 305 InformationElement ie = new InformationElement(); 306 ie.id = InformationElement.EID_VSA; 307 ie.bytes = new byte[] { (byte) 0x00, (byte) 0x50, (byte) 0xF2, (byte) 0x01, 308 (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x50, 309 (byte) 0xF2, (byte) 0x02, (byte) 0x02, (byte) 0x00, 310 (byte) 0x00, (byte) 0x50, (byte) 0xF2, (byte) 0x04, 311 (byte) 0x00, (byte) 0x50, (byte) 0xF2, (byte) 0x02, 312 (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x50, 313 (byte) 0xF2, (byte) 0x02, (byte) 0x00, (byte) 0x00 }; 314 315 InformationElement[] ies = new InformationElement[] { ie }; 316 317 BitSet beaconCap = new BitSet(16); 318 beaconCap.set(4); 319 InformationElementUtil.Capabilities capabilities = 320 new InformationElementUtil.Capabilities(); 321 capabilities.from(ies, beaconCap); 322 String result = capabilities.generateCapabilitiesString(); 323 324 assertEquals("[WPA-PSK-CCMP+TKIP]", result); 325 } 326 327 /** 328 * Test Capabilities.generateCapabilitiesString() with a WPA type 1 IE which is malformed. 329 * Expect the function to return a string with empty key management & pairswise cipher security 330 * information. 331 */ 332 @Test 333 public void buildCapabilities_malformedWpa1Element() { 334 InformationElement ie = new InformationElement(); 335 ie.id = InformationElement.EID_VSA; 336 ie.bytes = new byte[] { (byte) 0x00, (byte) 0x50, (byte) 0xF2, (byte) 0x01, 337 (byte) 0x01, (byte) 0x00 }; 338 339 InformationElement[] ies = new InformationElement[] { ie }; 340 341 BitSet beaconCap = new BitSet(16); 342 beaconCap.set(4); 343 InformationElementUtil.Capabilities capabilities = 344 new InformationElementUtil.Capabilities(); 345 capabilities.from(ies, beaconCap); 346 String result = capabilities.generateCapabilitiesString(); 347 348 assertEquals("[WPA]", result); 349 } 350 351 /** 352 * Test Capabilities.generateCapabilitiesString() with both RSN and WPA1 IE. 353 * Expect the function to return a string with the proper security information. 354 */ 355 @Test 356 public void buildCapabilities_rsnAndWpaElement() { 357 InformationElement ieRsn = new InformationElement(); 358 ieRsn.id = InformationElement.EID_RSN; 359 ieRsn.bytes = new byte[] { (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x0F, 360 (byte) 0xAC, (byte) 0x02, (byte) 0x02, (byte) 0x00, 361 (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04, 362 (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x02, 363 (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x0F, 364 (byte) 0xAC, (byte) 0x02, (byte) 0x00, (byte) 0x00 }; 365 366 InformationElement ieWpa = new InformationElement(); 367 ieWpa.id = InformationElement.EID_VSA; 368 ieWpa.bytes = new byte[] { (byte) 0x00, (byte) 0x50, (byte) 0xF2, (byte) 0x01, 369 (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x50, 370 (byte) 0xF2, (byte) 0x02, (byte) 0x02, (byte) 0x00, 371 (byte) 0x00, (byte) 0x50, (byte) 0xF2, (byte) 0x04, 372 (byte) 0x00, (byte) 0x50, (byte) 0xF2, (byte) 0x02, 373 (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x50, 374 (byte) 0xF2, (byte) 0x02, (byte) 0x00, (byte) 0x00 }; 375 376 InformationElement[] ies = new InformationElement[] { ieWpa, ieRsn }; 377 378 BitSet beaconCap = new BitSet(16); 379 beaconCap.set(4); 380 381 InformationElementUtil.Capabilities capabilities = 382 new InformationElementUtil.Capabilities(); 383 capabilities.from(ies, beaconCap); 384 String result = capabilities.generateCapabilitiesString(); 385 386 assertEquals("[WPA-PSK-CCMP+TKIP][WPA2-PSK-CCMP+TKIP]", result); 387 } 388 389 /** 390 * Test Capabilities.generateCapabilitiesString() with both RSN and WPA1 IE which are malformed. 391 * Expect the function to return a string with empty key management & pairswise cipher security 392 * information. 393 */ 394 @Test 395 public void buildCapabilities_malformedRsnAndWpaElement() { 396 InformationElement ieRsn = new InformationElement(); 397 ieRsn.id = InformationElement.EID_RSN; 398 ieRsn.bytes = new byte[] { (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x0F, 399 (byte) 0xAC, (byte) 0x02, (byte) 0x02 }; 400 401 InformationElement ieWpa = new InformationElement(); 402 ieWpa.id = InformationElement.EID_VSA; 403 ieWpa.bytes = new byte[] { (byte) 0x00, (byte) 0x50, (byte) 0xF2, (byte) 0x01, 404 (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x50, 405 (byte) 0xF2, (byte) 0x02, (byte) 0x02, (byte) 0x00, 406 (byte) 0x00, (byte) 0x50 }; 407 408 InformationElement[] ies = new InformationElement[] { ieWpa, ieRsn }; 409 410 BitSet beaconCap = new BitSet(16); 411 beaconCap.set(4); 412 413 InformationElementUtil.Capabilities capabilities = 414 new InformationElementUtil.Capabilities(); 415 capabilities.from(ies, beaconCap); 416 String result = capabilities.generateCapabilitiesString(); 417 418 assertEquals("[WPA][WPA2]", result); 419 } 420 421 /** 422 * Test Capabilities.generateCapabilitiesString() with both WPS and WPA1 IE. 423 * Expect the function to return a string with the proper security information. 424 */ 425 @Test 426 public void buildCapabilities_wpaAndWpsElement() { 427 InformationElement ieWpa = new InformationElement(); 428 ieWpa.id = InformationElement.EID_VSA; 429 ieWpa.bytes = new byte[] { (byte) 0x00, (byte) 0x50, (byte) 0xF2, (byte) 0x01, 430 (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x50, 431 (byte) 0xF2, (byte) 0x02, (byte) 0x02, (byte) 0x00, 432 (byte) 0x00, (byte) 0x50, (byte) 0xF2, (byte) 0x04, 433 (byte) 0x00, (byte) 0x50, (byte) 0xF2, (byte) 0x02, 434 (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x50, 435 (byte) 0xF2, (byte) 0x02, (byte) 0x00, (byte) 0x00 }; 436 437 InformationElement ieWps = new InformationElement(); 438 ieWps.id = InformationElement.EID_VSA; 439 ieWps.bytes = new byte[] { (byte) 0x00, (byte) 0x50, (byte) 0xF2, (byte) 0x04 }; 440 441 InformationElement[] ies = new InformationElement[] { ieWpa, ieWps }; 442 443 BitSet beaconCap = new BitSet(16); 444 beaconCap.set(4); 445 446 447 InformationElementUtil.Capabilities capabilities = 448 new InformationElementUtil.Capabilities(); 449 capabilities.from(ies, beaconCap); 450 String result = capabilities.generateCapabilitiesString(); 451 452 assertEquals("[WPA-PSK-CCMP+TKIP][WPS]", result); 453 } 454 455 /** 456 * Test Capabilities.generateCapabilitiesString() with a vendor specific element which 457 * is not WPA type 1. Beacon Capability Information field has the Privacy 458 * bit set. 459 * 460 * Expect the function to return a string with the proper security information. 461 */ 462 @Test 463 public void buildCapabilities_nonRsnWpa1Element_privacySet() { 464 InformationElement ie = new InformationElement(); 465 ie.id = InformationElement.EID_VSA; 466 ie.bytes = new byte[] { (byte) 0x00, (byte) 0x04, (byte) 0x0E, (byte) 0x01, 467 (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x00, 468 (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 }; 469 470 InformationElement[] ies = new InformationElement[] { ie }; 471 472 BitSet beaconCap = new BitSet(16); 473 beaconCap.set(4); 474 475 InformationElementUtil.Capabilities capabilities = 476 new InformationElementUtil.Capabilities(); 477 capabilities.from(ies, beaconCap); 478 String result = capabilities.generateCapabilitiesString(); 479 480 481 assertEquals("[WEP]", result); 482 } 483 484 /** 485 * Test Capabilities.generateCapabilitiesString() with a vendor specific element which 486 * is not WPA type 1. Beacon Capability Information field doesn't have the 487 * Privacy bit set. 488 * 489 * Expect the function to return an empty string. 490 */ 491 @Test 492 public void buildCapabilities_nonRsnWpa1Element_privacyClear() { 493 InformationElement ie = new InformationElement(); 494 ie.id = InformationElement.EID_VSA; 495 ie.bytes = new byte[] { (byte) 0x00, (byte) 0x04, (byte) 0x0E, (byte) 0x01, 496 (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x00, 497 (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 }; 498 499 InformationElement[] ies = new InformationElement[] { ie }; 500 501 BitSet beaconCap = new BitSet(16); 502 beaconCap.clear(4); 503 504 InformationElementUtil.Capabilities capabilities = 505 new InformationElementUtil.Capabilities(); 506 capabilities.from(ies, beaconCap); 507 String result = capabilities.generateCapabilitiesString(); 508 509 510 assertEquals("", result); 511 } 512 513 /** 514 * Test Capabilities.generateCapabilitiesString() with a vendor specific element which 515 * is not WPA type 1. Beacon Capability Information field has the ESS bit set. 516 * 517 * Expect the function to return a string with [ESS] there. 518 */ 519 @Test 520 public void buildCapabilities_nonRsnWpa1Element_essSet() { 521 InformationElement ie = new InformationElement(); 522 ie.id = InformationElement.EID_VSA; 523 ie.bytes = new byte[] { (byte) 0x00, (byte) 0x04, (byte) 0x0E, (byte) 0x01, 524 (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x00, 525 (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 }; 526 527 InformationElement[] ies = new InformationElement[] { ie }; 528 529 BitSet beaconCap = new BitSet(16); 530 beaconCap.set(0); 531 532 InformationElementUtil.Capabilities capabilities = 533 new InformationElementUtil.Capabilities(); 534 capabilities.from(ies, beaconCap); 535 String result = capabilities.generateCapabilitiesString(); 536 537 538 assertEquals("[ESS]", result); 539 } 540 541 /** 542 * Test Capabilities.generateCapabilitiesString() with a vendor specific element which 543 * is not WPA type 1. Beacon Capability Information field doesn't have the 544 * ESS bit set. 545 * 546 * Expect the function to return an empty string. 547 */ 548 @Test 549 public void buildCapabilities_nonRsnWpa1Element_essClear() { 550 InformationElement ie = new InformationElement(); 551 ie.id = InformationElement.EID_VSA; 552 ie.bytes = new byte[] { (byte) 0x00, (byte) 0x04, (byte) 0x0E, (byte) 0x01, 553 (byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x00, 554 (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 }; 555 556 InformationElement[] ies = new InformationElement[] { ie }; 557 558 BitSet beaconCap = new BitSet(16); 559 beaconCap.clear(0); 560 561 InformationElementUtil.Capabilities capabilities = 562 new InformationElementUtil.Capabilities(); 563 capabilities.from(ies, beaconCap); 564 String result = capabilities.generateCapabilitiesString(); 565 566 567 assertEquals("", result); 568 } 569 570 /** 571 * Verify the expectations when building an ExtendedCapabilites IE from data with no bits set. 572 * Both ExtendedCapabilities#isStrictUtf8() and ExtendedCapabilites#is80211McRTTResponder() 573 * should return false. 574 */ 575 @Test 576 public void buildExtendedCapabilities_emptyBitSet() { 577 InformationElement ie = new InformationElement(); 578 ie.id = InformationElement.EID_EXTENDED_CAPS; 579 ie.bytes = new byte[8]; 580 581 InformationElementUtil.ExtendedCapabilities extendedCap = 582 new InformationElementUtil.ExtendedCapabilities(); 583 extendedCap.from(ie); 584 assertFalse(extendedCap.isStrictUtf8()); 585 assertFalse(extendedCap.is80211McRTTResponder()); 586 } 587 588 /** 589 * Verify the expectations when building an ExtendedCapabilites IE from data with UTF-8 SSID 590 * bit set (bit 48). ExtendedCapabilities#isStrictUtf8() should return true. 591 */ 592 @Test 593 public void buildExtendedCapabilites_strictUtf8() { 594 InformationElement ie = new InformationElement(); 595 ie.id = InformationElement.EID_EXTENDED_CAPS; 596 ie.bytes = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, 597 (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x00 }; 598 599 InformationElementUtil.ExtendedCapabilities extendedCap = 600 new InformationElementUtil.ExtendedCapabilities(); 601 extendedCap.from(ie); 602 assertTrue(extendedCap.isStrictUtf8()); 603 assertFalse(extendedCap.is80211McRTTResponder()); 604 } 605 606 /** 607 * Verify the expectations when building an ExtendedCapabilites IE from data with RTT Response 608 * Enable bit set (bit 70). ExtendedCapabilities#is80211McRTTResponder() should return true. 609 */ 610 @Test 611 public void buildExtendedCapabilites_80211McRTTResponder() { 612 InformationElement ie = new InformationElement(); 613 ie.id = InformationElement.EID_EXTENDED_CAPS; 614 ie.bytes = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, 615 (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, 616 (byte) 0x40 }; 617 618 InformationElementUtil.ExtendedCapabilities extendedCap = 619 new InformationElementUtil.ExtendedCapabilities(); 620 extendedCap.from(ie); 621 assertFalse(extendedCap.isStrictUtf8()); 622 assertTrue(extendedCap.is80211McRTTResponder()); 623 } 624 625 /** 626 * Test a that a correctly formed TIM Information Element is decoded into a valid TIM element, 627 * and the values are captured 628 */ 629 @Test 630 public void parseTrafficIndicationMapInformationElementValid() { 631 InformationElement ie = new InformationElement(); 632 ie.id = InformationElement.EID_TIM; 633 ie.bytes = new byte[] { (byte) 0x03, (byte) 0x05, (byte) 0x00, (byte) 0x00}; 634 InformationElementUtil.TrafficIndicationMap trafficIndicationMap = 635 new InformationElementUtil.TrafficIndicationMap(); 636 trafficIndicationMap.from(ie); 637 assertEquals(trafficIndicationMap.mLength, 4); 638 assertEquals(trafficIndicationMap.mDtimCount, 3); 639 assertEquals(trafficIndicationMap.mDtimPeriod, 5); 640 assertEquals(trafficIndicationMap.mBitmapControl, 0); 641 assertEquals(trafficIndicationMap.isValid(), true); 642 } 643 644 /** 645 * Test that a short invalid Information Element is marked as being an invalid TIM element when 646 * parsed as Traffic Indication Map. 647 */ 648 @Test 649 public void parseTrafficIndicationMapInformationElementInvalidTooShort() { 650 InformationElement ie = new InformationElement(); 651 ie.id = InformationElement.EID_TIM; 652 ie.bytes = new byte[] { (byte) 0x01, (byte) 0x07 }; 653 InformationElementUtil.TrafficIndicationMap trafficIndicationMap = 654 new InformationElementUtil.TrafficIndicationMap(); 655 trafficIndicationMap.from(ie); 656 assertEquals(trafficIndicationMap.isValid(), false); 657 } 658 659 /** 660 * Test that a too-large invalid Information Element is marked as an invalid TIM element when 661 * parsed as Traffic Indication Map. 662 */ 663 @Test 664 public void parseTrafficIndicationMapInformationElementInvalidTooLong() { 665 InformationElement ie = new InformationElement(); 666 ie.id = InformationElement.EID_TIM; 667 ie.bytes = new byte[255]; // bytes length of upto 254 is valid for TIM 668 Arrays.fill(ie.bytes, (byte) 7); 669 InformationElementUtil.TrafficIndicationMap trafficIndicationMap = 670 new InformationElementUtil.TrafficIndicationMap(); 671 trafficIndicationMap.from(ie); 672 assertEquals(trafficIndicationMap.isValid(), false); 673 } 674 675 /** 676 * Verify that the expected Roaming Consortium information element is parsed and retrieved 677 * from the list of IEs. 678 * 679 * @throws Exception 680 */ 681 @Test 682 public void getRoamingConsortiumIE() throws Exception { 683 InformationElement ie = new InformationElement(); 684 ie.id = InformationElement.EID_ROAMING_CONSORTIUM; 685 /** 686 * Roaming Consortium Format; 687 * | Number of OIs | OI#1 and OI#2 Lengths | OI #1 | OI #2 (optional) | OI #3 (optional) | 688 * 1 1 variable variable variable 689 */ 690 ie.bytes = new byte[] { (byte) 0x01 /* number of OIs */, (byte) 0x03 /* OI Length */, 691 (byte) 0x11, (byte) 0x22, (byte) 0x33}; 692 InformationElementUtil.RoamingConsortium roamingConsortium = 693 InformationElementUtil.getRoamingConsortiumIE(new InformationElement[] {ie}); 694 assertEquals(1, roamingConsortium.anqpOICount); 695 assertEquals(1, roamingConsortium.roamingConsortiums.length); 696 assertEquals(0x112233, roamingConsortium.roamingConsortiums[0]); 697 } 698 699 /** 700 * Verify that the expected Hotspot 2.0 Vendor Specific information element is parsed and 701 * retrieved from the list of IEs. 702 * 703 * @throws Exception 704 */ 705 @Test 706 public void getHS2VendorSpecificIE() throws Exception { 707 InformationElement ie = new InformationElement(); 708 ie.id = InformationElement.EID_VSA; 709 /** 710 * Vendor Specific OI Format: 711 * | OI | Type | Hotspot Configuration | PPS MO ID (optional) | ANQP Domain ID (optional) 712 * 3 1 1 2 2 713 * 714 * With OI=0x506F9A and Type=0x10 for Hotspot 2.0 715 * 716 * The Format of Hotspot Configuration: 717 * B0 B1 B2 B3 B4 B7 718 * | DGAF Disabled | PPS MO ID Flag | ANQP Domain ID Flag | reserved | Release Number | 719 */ 720 ie.bytes = new byte[] { (byte) 0x50, (byte) 0x6F, (byte) 0x9A, (byte) 0x10, 721 (byte) 0x14 /* Hotspot Configuration */, (byte) 0x11, (byte) 0x22}; 722 InformationElementUtil.Vsa vsa = 723 InformationElementUtil.getHS2VendorSpecificIE(new InformationElement[] {ie}); 724 assertEquals(NetworkDetail.HSRelease.R2, vsa.hsRelease); 725 assertEquals(0x2211, vsa.anqpDomainID); 726 } 727 728 /** 729 * Verify that the expected Interworking information element is parsed and retrieved from the 730 * list of IEs. 731 * 732 * @throws Exception 733 */ 734 @Test 735 public void getInterworkingElementIE() throws Exception { 736 InformationElement ie = new InformationElement(); 737 ie.id = InformationElement.EID_INTERWORKING; 738 /** 739 * Interworking Format: 740 * | Access Network Option | Venue Info (optional) | HESSID (optional) | 741 * 1 2 6 742 * 743 * Access Network Option Format: 744 * 745 * B0 B3 B4 B5 B6 B7 746 * | Access Network Type | Internet | ASRA | ESR | UESA | 747 */ 748 ie.bytes = new byte[] { (byte) 0x10, (byte) 0x11, (byte) 0x22, (byte) 0x33, (byte) 0x44, 749 (byte) 0x55, (byte) 0x66 }; 750 InformationElementUtil.Interworking interworking = 751 InformationElementUtil.getInterworkingIE(new InformationElement[] {ie}); 752 assertTrue(interworking.internet); 753 assertEquals(NetworkDetail.Ant.Private, interworking.ant); 754 assertEquals(0x112233445566L, interworking.hessid); 755 } 756 } 757