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_TYPE_MGMT = 0b00; 480 // Per 802.11-2016 Table 9-1 481 private static final byte IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_ASSOC_REQ = 0b0000; 482 private static final byte IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_ASSOC_RESP = 0b0001; 483 private static final byte IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_REASSOC_REQ = 0b0010; 484 private static final byte IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_REASSOC_RESP = 0b0011; 485 private static final byte IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_PROBE_REQ = 0b0100; 486 private static final byte IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_PROBE_RESP = 0b0101; 487 private static final byte IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_TIMING_AD = 0b0110; 488 // 0b0111 reserved 489 private static final byte IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_BEACON = 0b1000; 490 private static final byte IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_ATIM = 0b1001; 491 private static final byte IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_DISASSOC = 0b1010; 492 private static final byte IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_AUTH = 0b1011; 493 private static final byte IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_DEAUTH = 0b1100; 494 private static final byte IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_ACTION = 0b1101; 495 private static final byte IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_ACTION_NO_ACK = 0b1110; 496 // 0b1111 reserved 497 498 private static final byte IEEE_80211_FRAME_FLAG_ORDER = (byte) (1 << 7); // bit 8 499 private static final byte IEEE_80211_DURATION_LEN = 2; 500 private static final byte IEEE_80211_ADDR1_LEN = 6; 501 private static final byte IEEE_80211_ADDR2_LEN = 6; 502 private static final byte IEEE_80211_ADDR3_LEN = 6; 503 private static final byte IEEE_80211_SEQUENCE_CONTROL_LEN = 2; 504 private static final byte IEEE_80211_HT_CONTROL_LEN = 4; 505 parseIeee80211FrameCtrlVersion(byte b)506 private static byte parseIeee80211FrameCtrlVersion(byte b) { 507 return (byte) (b & 0b00000011); 508 } parseIeee80211FrameCtrlType(byte b)509 private static byte parseIeee80211FrameCtrlType(byte b) { 510 return (byte) ((b & 0b00001100) >> 2); 511 } parseIeee80211FrameCtrlSubtype(byte b)512 private static byte parseIeee80211FrameCtrlSubtype(byte b) { 513 return (byte) ((b & 0b11110000) >> 4); 514 } parseManagementFrame(ByteBuffer data)515 private void parseManagementFrame(ByteBuffer data) { // 802.11-2012 Sec 8.3.3.1 516 data.order(ByteOrder.LITTLE_ENDIAN); 517 518 mMostSpecificProtocolString = "802.11 Mgmt"; 519 byte frameControlVersionTypeSubtype = data.get(); 520 byte ieee80211Version = parseIeee80211FrameCtrlVersion(frameControlVersionTypeSubtype); 521 if (ieee80211Version != 0) { 522 Log.e(TAG, "Unrecognized 802.11 version " + ieee80211Version); 523 return; 524 } 525 526 byte ieee80211FrameType = parseIeee80211FrameCtrlType(frameControlVersionTypeSubtype); 527 if (ieee80211FrameType != IEEE_80211_FRAME_TYPE_MGMT) { 528 Log.e(TAG, "Unexpected frame type " + ieee80211FrameType); 529 return; 530 } 531 532 byte frameControlFlags = data.get(); 533 534 data.position(data.position() + IEEE_80211_DURATION_LEN + IEEE_80211_ADDR1_LEN 535 + IEEE_80211_ADDR2_LEN + IEEE_80211_ADDR3_LEN + IEEE_80211_SEQUENCE_CONTROL_LEN); 536 537 if ((frameControlFlags & IEEE_80211_FRAME_FLAG_ORDER) != 0) { 538 // Per 802.11-2012 Sec 8.2.4.1.10. 539 data.position(data.position() + IEEE_80211_HT_CONTROL_LEN); 540 } 541 542 byte ieee80211FrameSubtype = parseIeee80211FrameCtrlSubtype(frameControlVersionTypeSubtype); 543 switch (ieee80211FrameSubtype) { 544 case IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_ASSOC_REQ: 545 mTypeString = "Association Request"; 546 return; 547 case IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_ASSOC_RESP: 548 mTypeString = "Association Response"; 549 parseAssociationResponse(data); 550 return; 551 case IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_REASSOC_REQ: 552 mTypeString = "Reassociation Request"; 553 return; 554 case IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_REASSOC_RESP: 555 mTypeString = "Reassociation Response"; 556 return; 557 case IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_PROBE_REQ: 558 mTypeString = "Probe Request"; 559 return; 560 case IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_PROBE_RESP: 561 mTypeString = "Probe Response"; 562 return; 563 case IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_TIMING_AD: 564 mTypeString = "Timing Advertisement"; 565 return; 566 case IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_BEACON: 567 mTypeString = "Beacon"; 568 return; 569 case IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_ATIM: 570 mTypeString = "ATIM"; 571 return; 572 case IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_DISASSOC: 573 mTypeString = "Disassociation"; 574 parseDisassociationFrame(data); 575 return; 576 case IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_AUTH: 577 mTypeString = "Authentication"; 578 parseAuthenticationFrame(data); 579 return; 580 case IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_DEAUTH: 581 mTypeString = "Deauthentication"; 582 parseDeauthenticationFrame(data); 583 return; 584 case IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_ACTION: 585 mTypeString = "Action"; 586 return; 587 case IEEE_80211_FRAME_TYPE_MGMT_SUBTYPE_ACTION_NO_ACK: 588 mTypeString = "Action No Ack"; 589 return; 590 case 0b0111: 591 case 0b1111: 592 mTypeString = "Reserved"; 593 return; 594 default: 595 mTypeString = "Unexpected subtype " + ieee80211FrameSubtype; 596 return; 597 } 598 } 599 600 // Per 802.11-2012 Secs 8.3.3.6 and 8.4.1. 601 private static final byte IEEE_80211_CAPABILITY_INFO_LEN = 2; parseAssociationResponse(ByteBuffer data)602 private void parseAssociationResponse(ByteBuffer data) { 603 data.position(data.position() + IEEE_80211_CAPABILITY_INFO_LEN); 604 short resultCode = data.getShort(); 605 mResultString = String.format( 606 "%d: %s", resultCode, decodeIeee80211StatusCode(resultCode)); 607 } 608 609 // Per 802.11-2016 Sec 9.3.3.5 parseDisassociationFrame(ByteBuffer data)610 private void parseDisassociationFrame(ByteBuffer data) { 611 short reasonCode = data.getShort(); 612 mResultString = String.format("%d: %s", reasonCode, decodeIeee80211ReasonCode(reasonCode)); 613 } 614 615 // Per 802.11-2012 Secs 8.3.3.11 and 8.4.1. 616 private static final short IEEE_80211_AUTH_ALG_OPEN = 0; 617 private static final short IEEE_80211_AUTH_ALG_SHARED_KEY = 1; 618 private static final short IEEE_80211_AUTH_ALG_FAST_BSS_TRANSITION = 2; 619 private static final short IEEE_80211_AUTH_ALG_SIMUL_AUTH_OF_EQUALS = 3; parseAuthenticationFrame(ByteBuffer data)620 private void parseAuthenticationFrame(ByteBuffer data) { 621 short algorithm = data.getShort(); 622 short sequenceNum = data.getShort(); 623 boolean hasResultCode = false; 624 switch (algorithm) { 625 case IEEE_80211_AUTH_ALG_OPEN: 626 case IEEE_80211_AUTH_ALG_SHARED_KEY: 627 if (sequenceNum == 2) { 628 hasResultCode = true; 629 } 630 break; 631 case IEEE_80211_AUTH_ALG_FAST_BSS_TRANSITION: 632 if (sequenceNum == 2 || sequenceNum == 4) { 633 hasResultCode = true; 634 } 635 break; 636 case IEEE_80211_AUTH_ALG_SIMUL_AUTH_OF_EQUALS: 637 hasResultCode = true; 638 break; 639 default: 640 // Ignore unknown algorithm -- don't know which frames would have result codes. 641 } 642 643 if (hasResultCode) { 644 short resultCode = data.getShort(); 645 mResultString = String.format( 646 "%d: %s", resultCode, decodeIeee80211StatusCode(resultCode)); 647 } 648 } 649 650 // Per 802.11-2016 Sec 9.3.3.13 parseDeauthenticationFrame(ByteBuffer data)651 private void parseDeauthenticationFrame(ByteBuffer data) { 652 short reasonCode = data.getShort(); 653 mResultString = String.format("%d: %s", reasonCode, decodeIeee80211ReasonCode(reasonCode)); 654 } 655 656 // Per 802.11-2016 Table 9-45 decodeIeee80211ReasonCode(short reasonCode)657 private String decodeIeee80211ReasonCode(short reasonCode) { 658 switch (reasonCode) { 659 case 0: 660 return "Reserved"; 661 case 1: 662 return "Unspecified reason"; 663 case 2: 664 return "Previous authentication no longer valid"; 665 case 3: 666 return "Deauthenticated because sending STA is leaving (or has left) IBSS or ESS"; 667 case 4: 668 return "Disassociated due to inactivity"; 669 case 5: 670 return "Disassociated because AP is unable to handle all currently associated STAs"; 671 case 6: 672 return "Class 2 frame received from nonauthenticated STA"; 673 case 7: 674 return "Class 3 frame received from nonassociated STA"; 675 case 8: 676 return "Disassociated because sending STA is leaving (or has left) BSS"; 677 case 9: 678 return "STA requesting (re)association is not authenticated with responding STA"; 679 case 10: 680 return "Disassociated because the information in the Power Capability element is " 681 + "unacceptable"; 682 case 11: 683 return "Disassociated because the information in the Supported Channels element " 684 + "is unacceptable"; 685 case 12: 686 return "Disassociated due to BSS transition management"; 687 case 13: 688 return "Invalid element, i.e., an element defined in this standard for which the " 689 + "content does not meet the specifications in Clause 9"; 690 case 14: 691 return "Message integrity code (MIC) failure"; 692 case 15: 693 return "4-way handshake timeout"; 694 case 16: 695 return "Group key handshake timeout"; 696 case 17: 697 return "Element in 4-way handshake different from (Re)Association Request/Probe " 698 + "Response/Beacon frame"; 699 case 18: 700 return "Invalid group cipher"; 701 case 19: 702 return "Invalid pairwise cipher"; 703 case 20: 704 return "Invalid AKMP"; 705 case 21: 706 return "Unsupported RSNE version"; 707 case 22: 708 return "Invalid RSNE capabilities"; 709 case 23: 710 return "IEEE 802.1X authentication failed"; 711 case 24: 712 return "Cipher suite rejected because of the security policy"; 713 case 25: 714 return "TDLS direct-link teardown due to TDLS peer STA unreachable via the TDLS " 715 + "direct link"; 716 case 26: 717 return "TDLS direct-link teardown for unspecified reason"; 718 case 27: 719 return "Disassociated because session terminated by SSP request"; 720 case 28: 721 return "Disassociated because of lack of SSP roaming agreement"; 722 case 29: 723 return "Requested service rejected because of SSP cipher suite or AKM requirement"; 724 case 30: 725 return "Requested service not authorized in this location"; 726 case 31: 727 return "TS deleted because QoS AP lacks sufficient bandwidth for this QoS STA due" 728 + " to a change in BSS service characteristics or operational mode (e.g.," 729 + " an HT BSS change from 40 MHz channel to 20 MHz channel)"; 730 case 32: 731 return "Disassociated for unspecified, QoS-related reason"; 732 case 33: 733 return "Disassociated because QoS AP lacks sufficient bandwidth for this QoS STA"; 734 case 34: 735 return "Disassociated because excessive number of frames need to be acknowledged," 736 + " but are not acknowledged due to AP transmissions and/or poor channel " 737 + "conditions"; 738 case 35: 739 return "Disassociated because STA is transmitting outside the limits of its TXOPs"; 740 case 36: 741 return "Requesting STA is leaving the BSS (or resetting)"; 742 case 37: 743 return "Requesting STA is no longer using the stream or session"; 744 case 38: 745 return "Requesting STA received frames using a mechanism for which a setup has " 746 + "not been completed"; 747 case 39: 748 return "Requested from peer STA due to timeout"; 749 case 40: 750 case 41: 751 case 42: 752 case 43: 753 case 44: 754 return "<unspecified>"; 755 case 45: 756 return "Peer STA does not support the requested cipher suite"; 757 case 46: 758 return "In a DLS Teardown frame: The teardown was initiated by the DLS peer. In a" 759 + " Disassociation frame: Disassociated because authorized access limit " 760 + "reached"; 761 case 47: 762 return "In a DLS Teardown frame: The teardown was initiated by the AP. In a " 763 + "Disassociation frame: Disassociated due to external service " 764 + "requirements"; 765 case 48: 766 return "Invalid FT Action frame count"; 767 case 49: 768 return "Invalid pairwise master key identifier (PMKID)"; 769 case 50: 770 return "Invalid MDE"; 771 case 51: 772 return "Invalid FTE"; 773 case 52: 774 return "Mesh peering canceled for unknown reasons"; 775 case 53: 776 return "The mesh STA has reached the supported maximum number of peer mesh STAs"; 777 case 54: 778 return "The received information violates the Mesh Configuration policy " 779 + "configured in the mesh STA profile"; 780 case 55: 781 return "The mesh STA has received a Mesh Peering Close frame requesting to close " 782 + "the mesh peering."; 783 case 56: 784 return "The mesh STA has resent dot11MeshMaxRetries Mesh Peering Open frames, " 785 + "without receiving a Mesh Peering Confirm frame."; 786 case 57: 787 return "The confirmTimer for the mesh peering instance times out."; 788 case 58: 789 return "The mesh STA fails to unwrap the GTK or the values in the wrapped " 790 + "contents do not match"; 791 case 59: 792 return "The mesh STA receives inconsistent information about the mesh parameters " 793 + "between mesh peering Management frames"; 794 case 60: 795 return "The mesh STA fails the authenticated mesh peering exchange because due to" 796 + " failure in selecting either the pairwise ciphersuite or group " 797 + "ciphersuite"; 798 case 61: 799 return "The mesh STA does not have proxy information for this external " 800 + "destination."; 801 case 62: 802 return "The mesh STA does not have forwarding information for this destination."; 803 case 63: 804 return "The mesh STA determines that the link to the next hop of an active path " 805 + "in its forwarding information is no longer usable."; 806 case 64: 807 return "The Deauthentication frame was sent because the MAC address of the STA " 808 + "already exists in the mesh BSS. See 11.3.6."; 809 case 65: 810 return "The mesh STA performs channel switch to meet regulatory requirements."; 811 case 66: 812 return "The mesh STA performs channel switching with unspecified reason."; 813 default: 814 return "Reserved"; 815 } 816 } 817 818 // Per 802.11-2012 Table 8-37. decodeIeee80211StatusCode(short statusCode)819 private String decodeIeee80211StatusCode(short statusCode) { 820 switch (statusCode) { 821 case 0: 822 return "Success"; 823 case 1: 824 return "Unspecified failure"; 825 case 2: 826 return "TDLS wakeup schedule rejected; alternative provided"; 827 case 3: 828 return "TDLS wakeup schedule rejected"; 829 case 4: 830 return "Reserved"; 831 case 5: 832 return "Security disabled"; 833 case 6: 834 return "Unacceptable lifetime"; 835 case 7: 836 return "Not in same BSS"; 837 case 8: 838 case 9: 839 return "Reserved"; 840 case 10: 841 return "Capabilities mismatch"; 842 case 11: 843 return "Reassociation denied; could not confirm association exists"; 844 case 12: 845 return "Association denied for reasons outside standard"; 846 case 13: 847 return "Unsupported authentication algorithm"; 848 case 14: 849 return "Authentication sequence number of of sequence"; 850 case 15: 851 return "Authentication challenge failure"; 852 case 16: 853 return "Authentication timeout"; 854 case 17: 855 return "Association denied; too many STAs"; 856 case 18: 857 return "Association denied; must support BSSBasicRateSet"; 858 case 19: 859 return "Association denied; must support short preamble"; 860 case 20: 861 return "Association denied; must support PBCC"; 862 case 21: 863 return "Association denied; must support channel agility"; 864 case 22: 865 return "Association rejected; must support spectrum management"; 866 case 23: 867 return "Association rejected; unacceptable power capability"; 868 case 24: 869 return "Association rejected; unacceptable supported channels"; 870 case 25: 871 return "Association denied; must support short slot time"; 872 case 26: 873 return "Association denied; must support DSSS-OFDM"; 874 case 27: 875 return "Association denied; must support HT"; 876 case 28: 877 return "R0 keyholder unreachable (802.11r)"; 878 case 29: 879 return "Association denied; must support PCO transition time"; 880 case 30: 881 return "Refused temporarily"; 882 case 31: 883 return "Robust management frame policy violation"; 884 case 32: 885 return "Unspecified QoS failure"; 886 case 33: 887 return "Association denied; insufficient bandwidth for QoS"; 888 case 34: 889 return "Association denied; poor channel"; 890 case 35: 891 return "Association denied; must support QoS"; 892 case 36: 893 return "Reserved"; 894 case 37: 895 return "Declined"; 896 case 38: 897 return "Invalid parameters"; 898 case 39: 899 return "TS cannot be honored; changes suggested"; 900 case 40: 901 return "Invalid element"; 902 case 41: 903 return "Invalid group cipher"; 904 case 42: 905 return "Invalid pairwise cipher"; 906 case 43: 907 return "Invalid auth/key mgmt proto (AKMP)"; 908 case 44: 909 return "Unsupported RSNE version"; 910 case 45: 911 return "Invalid RSNE capabilities"; 912 case 46: 913 return "Cipher suite rejected by policy"; 914 case 47: 915 return "TS cannot be honored now; try again later"; 916 case 48: 917 return "Direct link rejected by policy"; 918 case 49: 919 return "Destination STA not in BSS"; 920 case 50: 921 return "Destination STA not configured for QoS"; 922 case 51: 923 return "Association denied; listen interval too large"; 924 case 52: 925 return "Invalid fast transition action frame count"; 926 case 53: 927 return "Invalid PMKID"; 928 case 54: 929 return "Invalid MDE"; 930 case 55: 931 return "Invalid FTE"; 932 case 56: 933 return "Unsupported TCLAS"; 934 case 57: 935 return "Requested TCLAS exceeds resources"; 936 case 58: 937 return "TS cannot be honored; try another BSS"; 938 case 59: 939 return "GAS Advertisement not supported"; 940 case 60: 941 return "No outstanding GAS request"; 942 case 61: 943 return "No query response from GAS server"; 944 case 62: 945 return "GAS query timeout"; 946 case 63: 947 return "GAS response too large"; 948 case 64: 949 return "Home network does not support request"; 950 case 65: 951 return "Advertisement server unreachable"; 952 case 66: 953 return "Reserved"; 954 case 67: 955 return "Rejected for SSP permissions"; 956 case 68: 957 return "Authentication required"; 958 case 69: 959 case 70: 960 case 71: 961 return "Reserved"; 962 case 72: 963 return "Invalid RSNE contents"; 964 case 73: 965 return "U-APSD coexistence unsupported"; 966 case 74: 967 return "Requested U-APSD coex mode unsupported"; 968 case 75: 969 return "Requested parameter unsupported with U-APSD coex"; 970 case 76: 971 return "Auth rejected; anti-clogging token required"; 972 case 77: 973 return "Auth rejected; offered group is not supported"; 974 case 78: 975 return "Cannot find alternative TBTT"; 976 case 79: 977 return "Transmission failure"; 978 case 80: 979 return "Requested TCLAS not supported"; 980 case 81: 981 return "TCLAS resources exhausted"; 982 case 82: 983 return "Rejected with suggested BSS transition"; 984 case 83: 985 return "Reserved"; 986 case 84: 987 case 85: 988 case 86: 989 case 87: 990 case 88: 991 case 89: 992 case 90: 993 case 91: 994 return "<unspecified>"; 995 case 92: 996 return "Refused due to external reason"; 997 case 93: 998 return "Refused; AP out of memory"; 999 case 94: 1000 return "Refused; emergency services not supported"; 1001 case 95: 1002 return "GAS query response outstanding"; 1003 case 96: 1004 case 97: 1005 case 98: 1006 case 99: 1007 return "Reserved"; 1008 case 100: 1009 return "Failed; reservation conflict"; 1010 case 101: 1011 return "Failed; exceeded MAF limit"; 1012 case 102: 1013 return "Failed; exceeded MCCA track limit"; 1014 default: 1015 return "Reserved"; 1016 } 1017 } 1018 } 1019