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 package com.android.server.wifi.util; 17 18 import android.util.Log; 19 20 import com.android.server.wifi.WifiLoggerHal; 21 22 import java.nio.BufferUnderflowException; 23 import java.nio.ByteBuffer; 24 import java.nio.ByteOrder; 25 import java.util.HashSet; 26 import java.util.Set; 27 28 /** 29 * This class parses the raw bytes of a network frame, and stores the parsed information in its 30 * public fields. 31 */ 32 public class FrameParser { 33 /** 34 * Note: When adding constants derived from network protocol specifications, please encode 35 * these constants the same way as the relevant specification, for ease of comparison. 36 */ 37 38 private static final String TAG = "FrameParser"; 39 40 /* These fields hold the information parsed from this frame. */ 41 public String mMostSpecificProtocolString = "N/A"; 42 public String mTypeString = "N/A"; 43 public String mResultString = "N/A"; 44 45 /** 46 * Parses the contents of a given network frame. 47 * 48 * @param frameType The type of the frame, as defined in 49 * {@link com.android.server.wifi.WifiLoggerHal}. 50 * @param frameBytes The raw bytes of the frame to be parsed. 51 */ FrameParser(byte frameType, byte[] frameBytes)52 public FrameParser(byte frameType, byte[] frameBytes) { 53 try { 54 ByteBuffer frameBuffer = ByteBuffer.wrap(frameBytes); 55 frameBuffer.order(ByteOrder.BIG_ENDIAN); 56 if (frameType == WifiLoggerHal.FRAME_TYPE_ETHERNET_II) { 57 parseEthernetFrame(frameBuffer); 58 } else if (frameType == WifiLoggerHal.FRAME_TYPE_80211_MGMT) { 59 parseManagementFrame(frameBuffer); 60 } 61 } catch (BufferUnderflowException | IllegalArgumentException e) { 62 Log.e(TAG, "Dissection aborted mid-frame: " + e); 63 } 64 } 65 66 /** 67 * Read one byte into a form that can easily be compared against, or output as, an integer 68 * in the range (0, 255). 69 */ getUnsignedByte(ByteBuffer data)70 private static short getUnsignedByte(ByteBuffer data) { 71 return (short) (data.get() & 0x00ff); 72 } 73 /** 74 * Read two bytes into a form that can easily be compared against, or output as, an integer 75 * in the range (0, 65535). 76 */ getUnsignedShort(ByteBuffer data)77 private static int getUnsignedShort(ByteBuffer data) { 78 return (data.getShort() & 0xffff); 79 } 80 81 private static final int ETHERNET_SRC_MAC_ADDR_LEN = 6; 82 private static final int ETHERNET_DST_MAC_ADDR_LEN = 6; 83 private static final short ETHERTYPE_IP_V4 = (short) 0x0800; 84 private static final short ETHERTYPE_ARP = (short) 0x0806; 85 private static final short ETHERTYPE_IP_V6 = (short) 0x86dd; 86 private static final short ETHERTYPE_EAPOL = (short) 0x888e; 87 parseEthernetFrame(ByteBuffer data)88 private void parseEthernetFrame(ByteBuffer data) { 89 mMostSpecificProtocolString = "Ethernet"; 90 data.position(data.position() + ETHERNET_SRC_MAC_ADDR_LEN + ETHERNET_DST_MAC_ADDR_LEN); 91 short etherType = data.getShort(); 92 switch (etherType) { 93 case ETHERTYPE_IP_V4: 94 parseIpv4Packet(data); 95 return; 96 case ETHERTYPE_ARP: 97 parseArpPacket(data); 98 return; 99 case ETHERTYPE_IP_V6: 100 parseIpv6Packet(data); 101 return; 102 case ETHERTYPE_EAPOL: 103 parseEapolPacket(data); 104 return; 105 default: 106 return; 107 } 108 } 109 110 private static final byte IP_V4_VERSION_BYTE_MASK = (byte) 0b11110000; 111 private static final byte IP_V4_IHL_BYTE_MASK = (byte) 0b00001111; 112 private static final byte IP_V4_ADDR_LEN = 4; 113 private static final byte IP_V4_DSCP_AND_ECN_LEN = 1; 114 private static final byte IP_V4_TOTAL_LEN_LEN = 2; 115 private static final byte IP_V4_ID_LEN = 2; 116 private static final byte IP_V4_FLAGS_AND_FRAG_OFFSET_LEN = 2; 117 private static final byte IP_V4_TTL_LEN = 1; 118 private static final byte IP_V4_HEADER_CHECKSUM_LEN = 2; 119 private static final byte IP_V4_SRC_ADDR_LEN = 4; 120 private static final byte IP_V4_DST_ADDR_LEN = 4; 121 private static final byte IP_PROTO_ICMP = 1; 122 private static final byte IP_PROTO_TCP = 6; 123 private static final byte IP_PROTO_UDP = 17; 124 private static final byte BYTES_PER_QUAD = 4; 125 parseIpv4Packet(ByteBuffer data)126 private void parseIpv4Packet(ByteBuffer data) { 127 mMostSpecificProtocolString = "IPv4"; 128 data.mark(); 129 byte versionAndHeaderLen = data.get(); 130 int version = (versionAndHeaderLen & IP_V4_VERSION_BYTE_MASK) >> 4; 131 if (version != 4) { 132 Log.e(TAG, "IPv4 header: Unrecognized protocol version " + version); 133 return; 134 } 135 136 data.position(data.position() + IP_V4_DSCP_AND_ECN_LEN + IP_V4_TOTAL_LEN_LEN 137 + IP_V4_ID_LEN + IP_V4_FLAGS_AND_FRAG_OFFSET_LEN + IP_V4_TTL_LEN); 138 short protocolNumber = getUnsignedByte(data); 139 data.position(data.position() + IP_V4_HEADER_CHECKSUM_LEN + IP_V4_SRC_ADDR_LEN 140 + IP_V4_DST_ADDR_LEN); 141 142 int headerLen = (versionAndHeaderLen & IP_V4_IHL_BYTE_MASK) * BYTES_PER_QUAD; 143 data.reset(); // back to start of IPv4 header 144 data.position(data.position() + headerLen); 145 146 switch (protocolNumber) { 147 case IP_PROTO_ICMP: 148 parseIcmpPacket(data); 149 break; 150 case IP_PROTO_TCP: 151 parseTcpPacket(data); 152 break; 153 case IP_PROTO_UDP: 154 parseUdpPacket(data); 155 break; 156 default: 157 break; 158 } 159 } 160 161 private static final byte TCP_SRC_PORT_LEN = 2; 162 private static final int HTTPS_PORT = 443; 163 private static final Set<Integer> HTTP_PORTS = new HashSet<>(); 164 static { 165 HTTP_PORTS.add(80); 166 HTTP_PORTS.add(3128); 167 HTTP_PORTS.add(3132); 168 HTTP_PORTS.add(5985); 169 HTTP_PORTS.add(8080); 170 HTTP_PORTS.add(8088); 171 HTTP_PORTS.add(11371); 172 HTTP_PORTS.add(1900); 173 HTTP_PORTS.add(2869); 174 HTTP_PORTS.add(2710); 175 } 176 parseTcpPacket(ByteBuffer data)177 private void parseTcpPacket(ByteBuffer data) { 178 mMostSpecificProtocolString = "TCP"; 179 data.position(data.position() + TCP_SRC_PORT_LEN); 180 int dstPort = getUnsignedShort(data); 181 182 if (dstPort == HTTPS_PORT) { 183 mTypeString = "HTTPS"; 184 } else if (HTTP_PORTS.contains(dstPort)) { 185 mTypeString = "HTTP"; 186 } 187 } 188 189 private static final byte UDP_PORT_BOOTPS = 67; 190 private static final byte UDP_PORT_BOOTPC = 68; 191 private static final byte UDP_PORT_NTP = 123; 192 private static final byte UDP_CHECKSUM_LEN = 2; 193 parseUdpPacket(ByteBuffer data)194 private void parseUdpPacket(ByteBuffer data) { 195 mMostSpecificProtocolString = "UDP"; 196 int srcPort = getUnsignedShort(data); 197 int dstPort = getUnsignedShort(data); 198 int length = getUnsignedShort(data); 199 200 data.position(data.position() + UDP_CHECKSUM_LEN); 201 if ((srcPort == UDP_PORT_BOOTPC && dstPort == UDP_PORT_BOOTPS) 202 || (srcPort == UDP_PORT_BOOTPS && dstPort == UDP_PORT_BOOTPC)) { 203 parseDhcpPacket(data); 204 return; 205 } 206 if (srcPort == UDP_PORT_NTP || dstPort == UDP_PORT_NTP) { 207 mMostSpecificProtocolString = "NTP"; 208 return; 209 } 210 } 211 212 private static final byte BOOTP_OPCODE_LEN = 1; 213 private static final byte BOOTP_HWTYPE_LEN = 1; 214 private static final byte BOOTP_HWADDR_LEN_LEN = 1; 215 private static final byte BOOTP_HOPCOUNT_LEN = 1; 216 private static final byte BOOTP_TRANSACTION_ID_LEN = 4; 217 private static final byte BOOTP_ELAPSED_SECONDS_LEN = 2; 218 private static final byte BOOTP_FLAGS_LEN = 2; 219 private static final byte BOOTP_CLIENT_HWADDR_LEN = 16; 220 private static final byte BOOTP_SERVER_HOSTNAME_LEN = 64; 221 private static final short BOOTP_BOOT_FILENAME_LEN = 128; 222 private static final byte BOOTP_MAGIC_COOKIE_LEN = 4; 223 private static final short DHCP_OPTION_TAG_PAD = 0; 224 private static final short DHCP_OPTION_TAG_MESSAGE_TYPE = 53; 225 private static final short DHCP_OPTION_TAG_END = 255; 226 parseDhcpPacket(ByteBuffer data)227 private void parseDhcpPacket(ByteBuffer data) { 228 mMostSpecificProtocolString = "DHCP"; 229 data.position(data.position() + BOOTP_OPCODE_LEN + BOOTP_HWTYPE_LEN + BOOTP_HWADDR_LEN_LEN 230 + BOOTP_HOPCOUNT_LEN + BOOTP_TRANSACTION_ID_LEN + BOOTP_ELAPSED_SECONDS_LEN 231 + BOOTP_FLAGS_LEN + IP_V4_ADDR_LEN * 4 + BOOTP_CLIENT_HWADDR_LEN 232 + BOOTP_SERVER_HOSTNAME_LEN + BOOTP_BOOT_FILENAME_LEN + BOOTP_MAGIC_COOKIE_LEN); 233 while (data.remaining() > 0) { 234 short dhcpOptionTag = getUnsignedByte(data); 235 if (dhcpOptionTag == DHCP_OPTION_TAG_PAD) { 236 continue; 237 } 238 if (dhcpOptionTag == DHCP_OPTION_TAG_END) { 239 break; 240 } 241 short dhcpOptionLen = getUnsignedByte(data); 242 switch (dhcpOptionTag) { 243 case DHCP_OPTION_TAG_MESSAGE_TYPE: 244 if (dhcpOptionLen != 1) { 245 Log.e(TAG, "DHCP option len: " + dhcpOptionLen + " (expected |1|)"); 246 return; 247 } 248 mTypeString = decodeDhcpMessageType(getUnsignedByte(data)); 249 return; 250 default: 251 data.position(data.position() + dhcpOptionLen); 252 } 253 } 254 } 255 256 private static final byte DHCP_MESSAGE_TYPE_DISCOVER = 1; 257 private static final byte DHCP_MESSAGE_TYPE_OFFER = 2; 258 private static final byte DHCP_MESSAGE_TYPE_REQUEST = 3; 259 private static final byte DHCP_MESSAGE_TYPE_DECLINE = 4; 260 private static final byte DHCP_MESSAGE_TYPE_ACK = 5; 261 private static final byte DHCP_MESSAGE_TYPE_NAK = 6; 262 private static final byte DHCP_MESSAGE_TYPE_RELEASE = 7; 263 private static final byte DHCP_MESSAGE_TYPE_INFORM = 8; 264 decodeDhcpMessageType(short messageType)265 private static String decodeDhcpMessageType(short messageType) { 266 switch (messageType) { 267 case DHCP_MESSAGE_TYPE_DISCOVER: 268 return "Discover"; 269 case DHCP_MESSAGE_TYPE_OFFER: 270 return "Offer"; 271 case DHCP_MESSAGE_TYPE_REQUEST: 272 return "Request"; 273 case DHCP_MESSAGE_TYPE_DECLINE: 274 return "Decline"; 275 case DHCP_MESSAGE_TYPE_ACK: 276 return "Ack"; 277 case DHCP_MESSAGE_TYPE_NAK: 278 return "Nak"; 279 case DHCP_MESSAGE_TYPE_RELEASE: 280 return "Release"; 281 case DHCP_MESSAGE_TYPE_INFORM: 282 return "Inform"; 283 default: 284 return "Unknown type " + messageType; 285 } 286 } 287 288 private static final byte ICMP_TYPE_ECHO_REPLY = 0; 289 private static final byte ICMP_TYPE_DEST_UNREACHABLE = 3; 290 private static final byte ICMP_TYPE_REDIRECT = 5; 291 private static final byte ICMP_TYPE_ECHO_REQUEST = 8; 292 parseIcmpPacket(ByteBuffer data)293 private void parseIcmpPacket(ByteBuffer data) { 294 mMostSpecificProtocolString = "ICMP"; 295 short messageType = getUnsignedByte(data); 296 switch (messageType) { 297 case ICMP_TYPE_ECHO_REPLY: 298 mTypeString = "Echo Reply"; 299 return; 300 case ICMP_TYPE_DEST_UNREACHABLE: 301 mTypeString = "Destination Unreachable"; 302 return; 303 case ICMP_TYPE_REDIRECT: 304 mTypeString = "Redirect"; 305 return; 306 case ICMP_TYPE_ECHO_REQUEST: 307 mTypeString = "Echo Request"; 308 return; 309 default: 310 mTypeString = "Type " + messageType; 311 return; 312 } 313 } 314 315 private static final byte ARP_HWTYPE_LEN = 2; 316 private static final byte ARP_PROTOTYPE_LEN = 2; 317 private static final byte ARP_HWADDR_LEN_LEN = 1; 318 private static final byte ARP_PROTOADDR_LEN_LEN = 1; 319 private static final byte ARP_OPCODE_REQUEST = 1; 320 private static final byte ARP_OPCODE_REPLY = 2; 321 parseArpPacket(ByteBuffer data)322 private void parseArpPacket(ByteBuffer data) { 323 mMostSpecificProtocolString = "ARP"; 324 data.position(data.position() + ARP_HWTYPE_LEN + ARP_PROTOTYPE_LEN + ARP_HWADDR_LEN_LEN 325 + ARP_PROTOADDR_LEN_LEN); 326 int opCode = getUnsignedShort(data); 327 switch (opCode) { 328 case ARP_OPCODE_REQUEST: 329 mTypeString = "Request"; 330 break; 331 case ARP_OPCODE_REPLY: 332 mTypeString = "Reply"; 333 break; 334 default: 335 mTypeString = "Operation " + opCode; 336 } 337 } 338 339 private static final byte IP_V6_PAYLOAD_LENGTH_LEN = 2; 340 private static final byte IP_V6_HOP_LIMIT_LEN = 1; 341 private static final byte IP_V6_ADDR_LEN = 16; 342 private static final byte IP_V6_HEADER_TYPE_HOP_BY_HOP_OPTION = 0; 343 private static final byte IP_V6_HEADER_TYPE_ICMP_V6 = 58; 344 private static final byte BYTES_PER_OCT = 8; 345 parseIpv6Packet(ByteBuffer data)346 private void parseIpv6Packet(ByteBuffer data) { 347 mMostSpecificProtocolString = "IPv6"; 348 int versionClassAndLabel = data.getInt(); 349 int version = (versionClassAndLabel & 0xf0000000) >> 28; 350 if (version != 6) { 351 Log.e(TAG, "IPv6 header: invalid IP version " + version); 352 return; 353 } 354 data.position(data.position() + IP_V6_PAYLOAD_LENGTH_LEN); 355 356 short nextHeaderType = getUnsignedByte(data); 357 data.position(data.position() + IP_V6_HOP_LIMIT_LEN + IP_V6_ADDR_LEN * 2); 358 while (nextHeaderType == IP_V6_HEADER_TYPE_HOP_BY_HOP_OPTION) { 359 int thisHeaderLen; 360 data.mark(); 361 nextHeaderType = getUnsignedByte(data); 362 thisHeaderLen = (getUnsignedByte(data) + 1) * BYTES_PER_OCT; 363 data.reset(); // back to start of this header 364 data.position(data.position() + thisHeaderLen); 365 } 366 switch (nextHeaderType) { 367 case IP_V6_HEADER_TYPE_ICMP_V6: 368 parseIcmpV6Packet(data); 369 return; 370 default: 371 mTypeString = "Option/Protocol " + nextHeaderType; 372 return; 373 } 374 } 375 376 private static final short ICMP_V6_TYPE_ECHO_REQUEST = 128; 377 private static final short ICMP_V6_TYPE_ECHO_REPLY = 129; 378 private static final short ICMP_V6_TYPE_ROUTER_SOLICITATION = 133; 379 private static final short ICMP_V6_TYPE_ROUTER_ADVERTISEMENT = 134; 380 private static final short ICMP_V6_TYPE_NEIGHBOR_SOLICITATION = 135; 381 private static final short ICMP_V6_TYPE_NEIGHBOR_ADVERTISEMENT = 136; 382 private static final short ICMP_V6_TYPE_MULTICAST_LISTENER_DISCOVERY = 143; 383 parseIcmpV6Packet(ByteBuffer data)384 private void parseIcmpV6Packet(ByteBuffer data) { 385 mMostSpecificProtocolString = "ICMPv6"; 386 short icmpV6Type = getUnsignedByte(data); 387 switch (icmpV6Type) { 388 case ICMP_V6_TYPE_ECHO_REQUEST: 389 mTypeString = "Echo Request"; 390 return; 391 case ICMP_V6_TYPE_ECHO_REPLY: 392 mTypeString = "Echo Reply"; 393 return; 394 case ICMP_V6_TYPE_ROUTER_SOLICITATION: 395 mTypeString = "Router Solicitation"; 396 return; 397 case ICMP_V6_TYPE_ROUTER_ADVERTISEMENT: 398 mTypeString = "Router Advertisement"; 399 return; 400 case ICMP_V6_TYPE_NEIGHBOR_SOLICITATION: 401 mTypeString = "Neighbor Solicitation"; 402 return; 403 case ICMP_V6_TYPE_NEIGHBOR_ADVERTISEMENT: 404 mTypeString = "Neighbor Advertisement"; 405 return; 406 case ICMP_V6_TYPE_MULTICAST_LISTENER_DISCOVERY: 407 mTypeString = "MLDv2 report"; 408 return; 409 default: 410 mTypeString = "Type " + icmpV6Type; 411 return; 412 } 413 } 414 415 private static final byte EAPOL_TYPE_KEY = 3; 416 private static final byte EAPOL_KEY_DESCRIPTOR_RSN_KEY = 2; 417 private static final byte EAPOL_LENGTH_LEN = 2; 418 private static final short WPA_KEY_INFO_FLAG_PAIRWISE = (short) 1 << 3; // bit 4 419 private static final short WPA_KEY_INFO_FLAG_INSTALL = (short) 1 << 6; // bit 7 420 private static final short WPA_KEY_INFO_FLAG_MIC = (short) 1 << 8; // bit 9 421 private static final byte WPA_KEYLEN_LEN = 2; 422 private static final byte WPA_REPLAY_COUNTER_LEN = 8; 423 private static final byte WPA_KEY_NONCE_LEN = 32; 424 private static final byte WPA_KEY_IV_LEN = 16; 425 private static final byte WPA_KEY_RECEIVE_SEQUENCE_COUNTER_LEN = 8; 426 private static final byte WPA_KEY_IDENTIFIER_LEN = 8; 427 private static final byte WPA_KEY_MIC_LEN = 16; 428 parseEapolPacket(ByteBuffer data)429 private void parseEapolPacket(ByteBuffer data) { 430 mMostSpecificProtocolString = "EAPOL"; 431 short eapolVersion = getUnsignedByte(data); 432 if (eapolVersion < 1 || eapolVersion > 2) { 433 Log.e(TAG, "Unrecognized EAPOL version " + eapolVersion); 434 return; 435 } 436 437 short eapolType = getUnsignedByte(data); 438 if (eapolType != EAPOL_TYPE_KEY) { 439 Log.e(TAG, "Unrecognized EAPOL type " + eapolType); 440 return; 441 } 442 443 data.position(data.position() + EAPOL_LENGTH_LEN); 444 short eapolKeyDescriptorType = getUnsignedByte(data); 445 if (eapolKeyDescriptorType != EAPOL_KEY_DESCRIPTOR_RSN_KEY) { 446 Log.e(TAG, "Unrecognized key descriptor " + eapolKeyDescriptorType); 447 return; 448 } 449 450 short wpaKeyInfo = data.getShort(); 451 if ((wpaKeyInfo & WPA_KEY_INFO_FLAG_PAIRWISE) == 0) { 452 mTypeString = "Group Key"; 453 } else { 454 mTypeString = "Pairwise Key"; 455 } 456 457 // See goo.gl/tu8AQC for details. 458 if ((wpaKeyInfo & WPA_KEY_INFO_FLAG_MIC) == 0) { 459 mTypeString += " message 1/4"; 460 return; 461 } 462 463 if ((wpaKeyInfo & WPA_KEY_INFO_FLAG_INSTALL) != 0) { 464 mTypeString += " message 3/4"; 465 return; 466 } 467 468 data.position(data.position() + WPA_KEYLEN_LEN + WPA_REPLAY_COUNTER_LEN 469 + WPA_KEY_NONCE_LEN + WPA_KEY_IV_LEN + WPA_KEY_RECEIVE_SEQUENCE_COUNTER_LEN 470 + WPA_KEY_IDENTIFIER_LEN + WPA_KEY_MIC_LEN); 471 int wpaKeyDataLen = getUnsignedShort(data); 472 if (wpaKeyDataLen > 0) { 473 mTypeString += " message 2/4"; 474 } else { 475 mTypeString += " message 4/4"; 476 } 477 } 478 479 private static final byte IEEE_80211_FRAME_CTRL_TYPE_MGMT = 0x00; 480 private static final byte IEEE_80211_FRAME_CTRL_SUBTYPE_ASSOC_REQ = 0x00; 481 private static final byte IEEE_80211_FRAME_CTRL_SUBTYPE_ASSOC_RESP = 0x01; 482 private static final byte IEEE_80211_FRAME_CTRL_SUBTYPE_PROBE_REQ = 0x04; 483 private static final byte IEEE_80211_FRAME_CTRL_SUBTYPE_PROBE_RESP = 0x05; 484 private static final byte IEEE_80211_FRAME_CTRL_SUBTYPE_AUTH = 0x0b; 485 private static final byte IEEE_80211_FRAME_CTRL_FLAG_ORDER = (byte) (1 << 7); // bit 8 486 private static final byte IEEE_80211_DURATION_LEN = 2; 487 private static final byte IEEE_80211_ADDR1_LEN = 6; 488 private static final byte IEEE_80211_ADDR2_LEN = 6; 489 private static final byte IEEE_80211_ADDR3_LEN = 6; 490 private static final byte IEEE_80211_SEQUENCE_CONTROL_LEN = 2; 491 private static final byte IEEE_80211_HT_CONTROL_LEN = 4; 492 parseIeee80211FrameCtrlVersion(byte b)493 private static byte parseIeee80211FrameCtrlVersion(byte b) { 494 return (byte) (b & 0b00000011); 495 } parseIeee80211FrameCtrlType(byte b)496 private static byte parseIeee80211FrameCtrlType(byte b) { 497 return (byte) ((b & 0b00001100) >> 2); 498 } parseIeee80211FrameCtrlSubtype(byte b)499 private static byte parseIeee80211FrameCtrlSubtype(byte b) { 500 return (byte) ((b & 0b11110000) >> 4); 501 } parseManagementFrame(ByteBuffer data)502 private void parseManagementFrame(ByteBuffer data) { // 802.11-2012 Sec 8.3.3.1 503 data.order(ByteOrder.LITTLE_ENDIAN); 504 505 mMostSpecificProtocolString = "802.11 Mgmt"; 506 byte frameControlVersionTypeSubtype = data.get(); 507 byte ieee80211Version = parseIeee80211FrameCtrlVersion(frameControlVersionTypeSubtype); 508 if (ieee80211Version != 0) { 509 Log.e(TAG, "Unrecognized 802.11 version " + ieee80211Version); 510 return; 511 } 512 513 byte ieee80211FrameType = parseIeee80211FrameCtrlType(frameControlVersionTypeSubtype); 514 if (ieee80211FrameType != IEEE_80211_FRAME_CTRL_TYPE_MGMT) { 515 Log.e(TAG, "Unexpected frame type " + ieee80211FrameType); 516 return; 517 } 518 519 byte frameControlFlags = data.get(); 520 521 data.position(data.position() + IEEE_80211_DURATION_LEN + IEEE_80211_ADDR1_LEN 522 + IEEE_80211_ADDR2_LEN + IEEE_80211_ADDR3_LEN + IEEE_80211_SEQUENCE_CONTROL_LEN); 523 524 if ((frameControlFlags & IEEE_80211_FRAME_CTRL_FLAG_ORDER) != 0) { 525 // Per 802.11-2012 Sec 8.2.4.1.10. 526 data.position(data.position() + IEEE_80211_HT_CONTROL_LEN); 527 } 528 529 byte ieee80211FrameSubtype = parseIeee80211FrameCtrlSubtype(frameControlVersionTypeSubtype); 530 switch (ieee80211FrameSubtype) { 531 case IEEE_80211_FRAME_CTRL_SUBTYPE_ASSOC_REQ: 532 mTypeString = "Association Request"; 533 return; 534 case IEEE_80211_FRAME_CTRL_SUBTYPE_ASSOC_RESP: 535 mTypeString = "Association Response"; 536 parseAssociationResponse(data); 537 return; 538 case IEEE_80211_FRAME_CTRL_SUBTYPE_PROBE_REQ: 539 mTypeString = "Probe Request"; 540 return; 541 case IEEE_80211_FRAME_CTRL_SUBTYPE_PROBE_RESP: 542 mTypeString = "Probe Response"; 543 return; 544 case IEEE_80211_FRAME_CTRL_SUBTYPE_AUTH: 545 mTypeString = "Authentication"; 546 parseAuthenticationFrame(data); 547 return; 548 default: 549 mTypeString = "Unexpected subtype " + ieee80211FrameSubtype; 550 return; 551 } 552 } 553 554 // Per 802.11-2012 Secs 8.3.3.6 and 8.4.1. 555 private static final byte IEEE_80211_CAPABILITY_INFO_LEN = 2; parseAssociationResponse(ByteBuffer data)556 private void parseAssociationResponse(ByteBuffer data) { 557 data.position(data.position() + IEEE_80211_CAPABILITY_INFO_LEN); 558 short resultCode = data.getShort(); 559 mResultString = String.format( 560 "%d: %s", resultCode, decodeIeee80211StatusCode(resultCode)); 561 } 562 563 // Per 802.11-2012 Secs 8.3.3.11 and 8.4.1. 564 private static final short IEEE_80211_AUTH_ALG_OPEN = 0; 565 private static final short IEEE_80211_AUTH_ALG_SHARED_KEY = 1; 566 private static final short IEEE_80211_AUTH_ALG_FAST_BSS_TRANSITION = 2; 567 private static final short IEEE_80211_AUTH_ALG_SIMUL_AUTH_OF_EQUALS = 3; parseAuthenticationFrame(ByteBuffer data)568 private void parseAuthenticationFrame(ByteBuffer data) { 569 short algorithm = data.getShort(); 570 short sequenceNum = data.getShort(); 571 boolean hasResultCode = false; 572 switch (algorithm) { 573 case IEEE_80211_AUTH_ALG_OPEN: 574 case IEEE_80211_AUTH_ALG_SHARED_KEY: 575 if (sequenceNum == 2) { 576 hasResultCode = true; 577 } 578 break; 579 case IEEE_80211_AUTH_ALG_FAST_BSS_TRANSITION: 580 if (sequenceNum == 2 || sequenceNum == 4) { 581 hasResultCode = true; 582 } 583 break; 584 case IEEE_80211_AUTH_ALG_SIMUL_AUTH_OF_EQUALS: 585 hasResultCode = true; 586 break; 587 default: 588 // Ignore unknown algorithm -- don't know which frames would have result codes. 589 } 590 591 if (hasResultCode) { 592 short resultCode = data.getShort(); 593 mResultString = String.format( 594 "%d: %s", resultCode, decodeIeee80211StatusCode(resultCode)); 595 } 596 } 597 598 // Per 802.11-2012 Table 8-37. decodeIeee80211StatusCode(short statusCode)599 private String decodeIeee80211StatusCode(short statusCode) { 600 switch (statusCode) { 601 case 0: 602 return "Success"; 603 case 1: 604 return "Unspecified failure"; 605 case 2: 606 return "TDLS wakeup schedule rejected; alternative provided"; 607 case 3: 608 return "TDLS wakeup schedule rejected"; 609 case 4: 610 return "Reserved"; 611 case 5: 612 return "Security disabled"; 613 case 6: 614 return "Unacceptable lifetime"; 615 case 7: 616 return "Not in same BSS"; 617 case 8: 618 case 9: 619 return "Reserved"; 620 case 10: 621 return "Capabilities mismatch"; 622 case 11: 623 return "Reassociation denied; could not confirm association exists"; 624 case 12: 625 return "Association denied for reasons outside standard"; 626 case 13: 627 return "Unsupported authentication algorithm"; 628 case 14: 629 return "Authentication sequence number of of sequence"; 630 case 15: 631 return "Authentication challenge failure"; 632 case 16: 633 return "Authentication timeout"; 634 case 17: 635 return "Association denied; too many STAs"; 636 case 18: 637 return "Association denied; must support BSSBasicRateSet"; 638 case 19: 639 return "Association denied; must support short preamble"; 640 case 20: 641 return "Association denied; must support PBCC"; 642 case 21: 643 return "Association denied; must support channel agility"; 644 case 22: 645 return "Association rejected; must support spectrum management"; 646 case 23: 647 return "Association rejected; unacceptable power capability"; 648 case 24: 649 return "Association rejected; unacceptable supported channels"; 650 case 25: 651 return "Association denied; must support short slot time"; 652 case 26: 653 return "Association denied; must support DSSS-OFDM"; 654 case 27: 655 return "Association denied; must support HT"; 656 case 28: 657 return "R0 keyholder unreachable (802.11r)"; 658 case 29: 659 return "Association denied; must support PCO transition time"; 660 case 30: 661 return "Refused temporarily"; 662 case 31: 663 return "Robust management frame policy violation"; 664 case 32: 665 return "Unspecified QoS failure"; 666 case 33: 667 return "Association denied; insufficient bandwidth for QoS"; 668 case 34: 669 return "Association denied; poor channel"; 670 case 35: 671 return "Association denied; must support QoS"; 672 case 36: 673 return "Reserved"; 674 case 37: 675 return "Declined"; 676 case 38: 677 return "Invalid parameters"; 678 case 39: 679 return "TS cannot be honored; changes suggested"; 680 case 40: 681 return "Invalid element"; 682 case 41: 683 return "Invalid group cipher"; 684 case 42: 685 return "Invalid pairwise cipher"; 686 case 43: 687 return "Invalid auth/key mgmt proto (AKMP)"; 688 case 44: 689 return "Unsupported RSNE version"; 690 case 45: 691 return "Invalid RSNE capabilities"; 692 case 46: 693 return "Cipher suite rejected by policy"; 694 case 47: 695 return "TS cannot be honored now; try again later"; 696 case 48: 697 return "Direct link rejected by policy"; 698 case 49: 699 return "Destination STA not in BSS"; 700 case 50: 701 return "Destination STA not configured for QoS"; 702 case 51: 703 return "Association denied; listen interval too large"; 704 case 52: 705 return "Invalid fast transition action frame count"; 706 case 53: 707 return "Invalid PMKID"; 708 case 54: 709 return "Invalid MDE"; 710 case 55: 711 return "Invalid FTE"; 712 case 56: 713 return "Unsupported TCLAS"; 714 case 57: 715 return "Requested TCLAS exceeds resources"; 716 case 58: 717 return "TS cannot be honored; try another BSS"; 718 case 59: 719 return "GAS Advertisement not supported"; 720 case 60: 721 return "No outstanding GAS request"; 722 case 61: 723 return "No query response from GAS server"; 724 case 62: 725 return "GAS query timeout"; 726 case 63: 727 return "GAS response too large"; 728 case 64: 729 return "Home network does not support request"; 730 case 65: 731 return "Advertisement server unreachable"; 732 case 66: 733 return "Reserved"; 734 case 67: 735 return "Rejected for SSP permissions"; 736 case 68: 737 return "Authentication required"; 738 case 69: 739 case 70: 740 case 71: 741 return "Reserved"; 742 case 72: 743 return "Invalid RSNE contents"; 744 case 73: 745 return "U-APSD coexistence unsupported"; 746 case 74: 747 return "Requested U-APSD coex mode unsupported"; 748 case 75: 749 return "Requested parameter unsupported with U-APSD coex"; 750 case 76: 751 return "Auth rejected; anti-clogging token required"; 752 case 77: 753 return "Auth rejected; offered group is not supported"; 754 case 78: 755 return "Cannot find alternative TBTT"; 756 case 79: 757 return "Transmission failure"; 758 case 80: 759 return "Requested TCLAS not supported"; 760 case 81: 761 return "TCLAS resources exhausted"; 762 case 82: 763 return "Rejected with suggested BSS transition"; 764 case 83: 765 return "Reserved"; 766 case 84: 767 case 85: 768 case 86: 769 case 87: 770 case 88: 771 case 89: 772 case 90: 773 case 91: 774 return "<unspecified>"; 775 case 92: 776 return "Refused due to external reason"; 777 case 93: 778 return "Refused; AP out of memory"; 779 case 94: 780 return "Refused; emergency services not supported"; 781 case 95: 782 return "GAS query response outstanding"; 783 case 96: 784 case 97: 785 case 98: 786 case 99: 787 return "Reserved"; 788 case 100: 789 return "Failed; reservation conflict"; 790 case 101: 791 return "Failed; exceeded MAF limit"; 792 case 102: 793 return "Failed; exceeded MCCA track limit"; 794 default: 795 return "Reserved"; 796 } 797 } 798 } 799