170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan/* 270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan * Copyright (C) 2016 The Android Open Source Project 370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan * 470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan * Licensed under the Apache License, Version 2.0 (the "License"); 570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan * you may not use this file except in compliance with the License. 670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan * You may obtain a copy of the License at 770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan * 870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan * http://www.apache.org/licenses/LICENSE-2.0 970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan * 1070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan * Unless required by applicable law or agreed to in writing, software 1170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan * distributed under the License is distributed on an "AS IS" BASIS, 1270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan * See the License for the specific language governing permissions and 1470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan * limitations under the License. 1570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan */ 1670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tanpackage com.android.server.wifi.util; 1770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 1870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tanimport android.util.Log; 1970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 2070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tanimport com.android.server.wifi.WifiLoggerHal; 2170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 2270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tanimport java.nio.BufferUnderflowException; 2370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tanimport java.nio.ByteBuffer; 2470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tanimport java.nio.ByteOrder; 2570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tanimport java.util.HashSet; 2670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tanimport java.util.Set; 2770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 2870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan/** 2970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan * This class parses the raw bytes of a network frame, and stores the parsed information in its 3070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan * public fields. 3170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan */ 3270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tanpublic class FrameParser { 3370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan /** 3470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan * Note: When adding constants derived from network protocol specifications, please encode 3570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan * these constants the same way as the relevant specification, for ease of comparison. 3670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan */ 3770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 3870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final String TAG = "FrameParser"; 3970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 4070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan /* These fields hold the information parsed from this frame. */ 4170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan public String mMostSpecificProtocolString = "N/A"; 4270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan public String mTypeString = "N/A"; 435e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal public String mResultString = "N/A"; 4470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 4570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan /** 4670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan * Parses the contents of a given network frame. 4770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan * 4870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan * @param frameType The type of the frame, as defined in 4970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan * {@link com.android.server.wifi.WifiLoggerHal}. 5070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan * @param frameBytes The raw bytes of the frame to be parsed. 5170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan */ 5270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan public FrameParser(byte frameType, byte[] frameBytes) { 5370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan try { 5470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan ByteBuffer frameBuffer = ByteBuffer.wrap(frameBytes); 5570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan frameBuffer.order(ByteOrder.BIG_ENDIAN); 5670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan if (frameType == WifiLoggerHal.FRAME_TYPE_ETHERNET_II) { 5770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan parseEthernetFrame(frameBuffer); 5870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } else if (frameType == WifiLoggerHal.FRAME_TYPE_80211_MGMT) { 5970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan parseManagementFrame(frameBuffer); 6070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 6170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } catch (BufferUnderflowException | IllegalArgumentException e) { 6270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan Log.e(TAG, "Dissection aborted mid-frame: " + e); 6370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 6470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 6570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 6670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan /** 6770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan * Read one byte into a form that can easily be compared against, or output as, an integer 6870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan * in the range (0, 255). 6970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan */ 7070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static short getUnsignedByte(ByteBuffer data) { 7170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return (short) (data.get() & 0x00ff); 7270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 7370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan /** 7470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan * Read two bytes into a form that can easily be compared against, or output as, an integer 7570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan * in the range (0, 65535). 7670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan */ 7770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static int getUnsignedShort(ByteBuffer data) { 7870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return (data.getShort() & 0xffff); 7970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 8070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 8170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final int ETHERNET_SRC_MAC_ADDR_LEN = 6; 8270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final int ETHERNET_DST_MAC_ADDR_LEN = 6; 8370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final short ETHERTYPE_IP_V4 = (short) 0x0800; 8470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final short ETHERTYPE_ARP = (short) 0x0806; 8570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final short ETHERTYPE_IP_V6 = (short) 0x86dd; 8670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final short ETHERTYPE_EAPOL = (short) 0x888e; 8770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 8870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private void parseEthernetFrame(ByteBuffer data) { 8970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan mMostSpecificProtocolString = "Ethernet"; 9070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan data.position(data.position() + ETHERNET_SRC_MAC_ADDR_LEN + ETHERNET_DST_MAC_ADDR_LEN); 9170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan short etherType = data.getShort(); 9270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan switch (etherType) { 9370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan case ETHERTYPE_IP_V4: 9470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan parseIpv4Packet(data); 9570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return; 9670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan case ETHERTYPE_ARP: 9770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan parseArpPacket(data); 9870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return; 9970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan case ETHERTYPE_IP_V6: 10070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan parseIpv6Packet(data); 10170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return; 10270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan case ETHERTYPE_EAPOL: 10370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan parseEapolPacket(data); 10470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return; 10570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan default: 10670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return; 10770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 10870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 10970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 11070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte IP_V4_VERSION_BYTE_MASK = (byte) 0b11110000; 11170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte IP_V4_IHL_BYTE_MASK = (byte) 0b00001111; 11270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte IP_V4_ADDR_LEN = 4; 11370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte IP_V4_DSCP_AND_ECN_LEN = 1; 11470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte IP_V4_TOTAL_LEN_LEN = 2; 11570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte IP_V4_ID_LEN = 2; 11670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte IP_V4_FLAGS_AND_FRAG_OFFSET_LEN = 2; 11770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte IP_V4_TTL_LEN = 1; 11870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte IP_V4_HEADER_CHECKSUM_LEN = 2; 11970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte IP_V4_SRC_ADDR_LEN = 4; 12070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte IP_V4_DST_ADDR_LEN = 4; 12170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte IP_PROTO_ICMP = 1; 12270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte IP_PROTO_TCP = 6; 12370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte IP_PROTO_UDP = 17; 12470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte BYTES_PER_QUAD = 4; 12570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 12670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private void parseIpv4Packet(ByteBuffer data) { 12770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan mMostSpecificProtocolString = "IPv4"; 12870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan data.mark(); 12970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan byte versionAndHeaderLen = data.get(); 13070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan int version = (versionAndHeaderLen & IP_V4_VERSION_BYTE_MASK) >> 4; 13170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan if (version != 4) { 13270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan Log.e(TAG, "IPv4 header: Unrecognized protocol version " + version); 13370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return; 13470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 13570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 13670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan data.position(data.position() + IP_V4_DSCP_AND_ECN_LEN + IP_V4_TOTAL_LEN_LEN 13770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan + IP_V4_ID_LEN + IP_V4_FLAGS_AND_FRAG_OFFSET_LEN + IP_V4_TTL_LEN); 13870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan short protocolNumber = getUnsignedByte(data); 13970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan data.position(data.position() + IP_V4_HEADER_CHECKSUM_LEN + IP_V4_SRC_ADDR_LEN 14070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan + IP_V4_DST_ADDR_LEN); 14170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 14270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan int headerLen = (versionAndHeaderLen & IP_V4_IHL_BYTE_MASK) * BYTES_PER_QUAD; 14370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan data.reset(); // back to start of IPv4 header 14470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan data.position(data.position() + headerLen); 14570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 14670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan switch (protocolNumber) { 14770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan case IP_PROTO_ICMP: 14870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan parseIcmpPacket(data); 14970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan break; 15070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan case IP_PROTO_TCP: 15170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan parseTcpPacket(data); 15270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan break; 15370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan case IP_PROTO_UDP: 15470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan parseUdpPacket(data); 15570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan break; 15670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan default: 15770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan break; 15870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 15970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 16070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 16170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte TCP_SRC_PORT_LEN = 2; 16270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final int HTTPS_PORT = 443; 16370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final Set<Integer> HTTP_PORTS = new HashSet<>(); 16470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan static { 16570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan HTTP_PORTS.add(80); 16670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan HTTP_PORTS.add(3128); 16770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan HTTP_PORTS.add(3132); 16870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan HTTP_PORTS.add(5985); 16970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan HTTP_PORTS.add(8080); 17070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan HTTP_PORTS.add(8088); 17170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan HTTP_PORTS.add(11371); 17270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan HTTP_PORTS.add(1900); 17370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan HTTP_PORTS.add(2869); 17470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan HTTP_PORTS.add(2710); 17570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 17670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 17770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private void parseTcpPacket(ByteBuffer data) { 17870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan mMostSpecificProtocolString = "TCP"; 17970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan data.position(data.position() + TCP_SRC_PORT_LEN); 18070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan int dstPort = getUnsignedShort(data); 18170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 18270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan if (dstPort == HTTPS_PORT) { 18370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan mTypeString = "HTTPS"; 18470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } else if (HTTP_PORTS.contains(dstPort)) { 18570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan mTypeString = "HTTP"; 18670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 18770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 18870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 18970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte UDP_PORT_BOOTPS = 67; 19070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte UDP_PORT_BOOTPC = 68; 19170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte UDP_PORT_NTP = 123; 19270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte UDP_CHECKSUM_LEN = 2; 19370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 19470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private void parseUdpPacket(ByteBuffer data) { 19570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan mMostSpecificProtocolString = "UDP"; 19670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan int srcPort = getUnsignedShort(data); 19770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan int dstPort = getUnsignedShort(data); 19870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan int length = getUnsignedShort(data); 19970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 20070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan data.position(data.position() + UDP_CHECKSUM_LEN); 20170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan if ((srcPort == UDP_PORT_BOOTPC && dstPort == UDP_PORT_BOOTPS) 20270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan || (srcPort == UDP_PORT_BOOTPS && dstPort == UDP_PORT_BOOTPC)) { 20370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan parseDhcpPacket(data); 20470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return; 20570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 20670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan if (srcPort == UDP_PORT_NTP || dstPort == UDP_PORT_NTP) { 20770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan mMostSpecificProtocolString = "NTP"; 20870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return; 20970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 21070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 21170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 21270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte BOOTP_OPCODE_LEN = 1; 21370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte BOOTP_HWTYPE_LEN = 1; 21470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte BOOTP_HWADDR_LEN_LEN = 1; 21570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte BOOTP_HOPCOUNT_LEN = 1; 21670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte BOOTP_TRANSACTION_ID_LEN = 4; 21770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte BOOTP_ELAPSED_SECONDS_LEN = 2; 21870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte BOOTP_FLAGS_LEN = 2; 21970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte BOOTP_CLIENT_HWADDR_LEN = 16; 22070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte BOOTP_SERVER_HOSTNAME_LEN = 64; 22170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final short BOOTP_BOOT_FILENAME_LEN = 128; 22270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte BOOTP_MAGIC_COOKIE_LEN = 4; 22370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final short DHCP_OPTION_TAG_PAD = 0; 22470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final short DHCP_OPTION_TAG_MESSAGE_TYPE = 53; 22570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final short DHCP_OPTION_TAG_END = 255; 22670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 22770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private void parseDhcpPacket(ByteBuffer data) { 22870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan mMostSpecificProtocolString = "DHCP"; 22970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan data.position(data.position() + BOOTP_OPCODE_LEN + BOOTP_HWTYPE_LEN + BOOTP_HWADDR_LEN_LEN 23070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan + BOOTP_HOPCOUNT_LEN + BOOTP_TRANSACTION_ID_LEN + BOOTP_ELAPSED_SECONDS_LEN 23170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan + BOOTP_FLAGS_LEN + IP_V4_ADDR_LEN * 4 + BOOTP_CLIENT_HWADDR_LEN 23270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan + BOOTP_SERVER_HOSTNAME_LEN + BOOTP_BOOT_FILENAME_LEN + BOOTP_MAGIC_COOKIE_LEN); 23370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan while (data.remaining() > 0) { 23470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan short dhcpOptionTag = getUnsignedByte(data); 23570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan if (dhcpOptionTag == DHCP_OPTION_TAG_PAD) { 23670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan continue; 23770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 23870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan if (dhcpOptionTag == DHCP_OPTION_TAG_END) { 23970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan break; 24070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 24170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan short dhcpOptionLen = getUnsignedByte(data); 24270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan switch (dhcpOptionTag) { 24370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan case DHCP_OPTION_TAG_MESSAGE_TYPE: 24470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan if (dhcpOptionLen != 1) { 24570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan Log.e(TAG, "DHCP option len: " + dhcpOptionLen + " (expected |1|)"); 24670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return; 24770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 24870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan mTypeString = decodeDhcpMessageType(getUnsignedByte(data)); 24970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return; 25070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan default: 25170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan data.position(data.position() + dhcpOptionLen); 25270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 25370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 25470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 25570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 25670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte DHCP_MESSAGE_TYPE_DISCOVER = 1; 25770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte DHCP_MESSAGE_TYPE_OFFER = 2; 25870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte DHCP_MESSAGE_TYPE_REQUEST = 3; 25970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte DHCP_MESSAGE_TYPE_DECLINE = 4; 26070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte DHCP_MESSAGE_TYPE_ACK = 5; 26170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte DHCP_MESSAGE_TYPE_NAK = 6; 26270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte DHCP_MESSAGE_TYPE_RELEASE = 7; 26370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte DHCP_MESSAGE_TYPE_INFORM = 8; 26470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 26570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static String decodeDhcpMessageType(short messageType) { 26670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan switch (messageType) { 26770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan case DHCP_MESSAGE_TYPE_DISCOVER: 26870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return "Discover"; 26970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan case DHCP_MESSAGE_TYPE_OFFER: 27070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return "Offer"; 27170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan case DHCP_MESSAGE_TYPE_REQUEST: 27270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return "Request"; 27370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan case DHCP_MESSAGE_TYPE_DECLINE: 27470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return "Decline"; 27570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan case DHCP_MESSAGE_TYPE_ACK: 27670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return "Ack"; 27770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan case DHCP_MESSAGE_TYPE_NAK: 27870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return "Nak"; 27970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan case DHCP_MESSAGE_TYPE_RELEASE: 28070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return "Release"; 28170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan case DHCP_MESSAGE_TYPE_INFORM: 28270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return "Inform"; 28370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan default: 28470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return "Unknown type " + messageType; 28570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 28670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 28770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 28870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte ICMP_TYPE_ECHO_REPLY = 0; 28970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte ICMP_TYPE_DEST_UNREACHABLE = 3; 29070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte ICMP_TYPE_REDIRECT = 5; 29170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte ICMP_TYPE_ECHO_REQUEST = 8; 29270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 29370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private void parseIcmpPacket(ByteBuffer data) { 29470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan mMostSpecificProtocolString = "ICMP"; 29570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan short messageType = getUnsignedByte(data); 29670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan switch (messageType) { 29770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan case ICMP_TYPE_ECHO_REPLY: 29870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan mTypeString = "Echo Reply"; 29970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return; 30070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan case ICMP_TYPE_DEST_UNREACHABLE: 30170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan mTypeString = "Destination Unreachable"; 30270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return; 30370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan case ICMP_TYPE_REDIRECT: 30470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan mTypeString = "Redirect"; 30570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return; 30670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan case ICMP_TYPE_ECHO_REQUEST: 30770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan mTypeString = "Echo Request"; 30870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return; 30970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan default: 31070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan mTypeString = "Type " + messageType; 31170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return; 31270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 31370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 31470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 31570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte ARP_HWTYPE_LEN = 2; 31670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte ARP_PROTOTYPE_LEN = 2; 31770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte ARP_HWADDR_LEN_LEN = 1; 31870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte ARP_PROTOADDR_LEN_LEN = 1; 31970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte ARP_OPCODE_REQUEST = 1; 32070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte ARP_OPCODE_REPLY = 2; 32170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 32270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private void parseArpPacket(ByteBuffer data) { 32370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan mMostSpecificProtocolString = "ARP"; 32470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan data.position(data.position() + ARP_HWTYPE_LEN + ARP_PROTOTYPE_LEN + ARP_HWADDR_LEN_LEN 32570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan + ARP_PROTOADDR_LEN_LEN); 32670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan int opCode = getUnsignedShort(data); 32770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan switch (opCode) { 32870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan case ARP_OPCODE_REQUEST: 32970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan mTypeString = "Request"; 33070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan break; 33170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan case ARP_OPCODE_REPLY: 33270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan mTypeString = "Reply"; 33370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan break; 33470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan default: 33570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan mTypeString = "Operation " + opCode; 33670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 33770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 33870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 33970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte IP_V6_PAYLOAD_LENGTH_LEN = 2; 34070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte IP_V6_HOP_LIMIT_LEN = 1; 34170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte IP_V6_ADDR_LEN = 16; 34270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte IP_V6_HEADER_TYPE_HOP_BY_HOP_OPTION = 0; 34370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte IP_V6_HEADER_TYPE_ICMP_V6 = 58; 34470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte BYTES_PER_OCT = 8; 34570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 34670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private void parseIpv6Packet(ByteBuffer data) { 34770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan mMostSpecificProtocolString = "IPv6"; 34870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan int versionClassAndLabel = data.getInt(); 34970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan int version = (versionClassAndLabel & 0xf0000000) >> 28; 35070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan if (version != 6) { 35170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan Log.e(TAG, "IPv6 header: invalid IP version " + version); 35270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return; 35370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 35470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan data.position(data.position() + IP_V6_PAYLOAD_LENGTH_LEN); 35570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 35670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan short nextHeaderType = getUnsignedByte(data); 35770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan data.position(data.position() + IP_V6_HOP_LIMIT_LEN + IP_V6_ADDR_LEN * 2); 35870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan while (nextHeaderType == IP_V6_HEADER_TYPE_HOP_BY_HOP_OPTION) { 35970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan int thisHeaderLen; 36070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan data.mark(); 36170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan nextHeaderType = getUnsignedByte(data); 36270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan thisHeaderLen = (getUnsignedByte(data) + 1) * BYTES_PER_OCT; 36370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan data.reset(); // back to start of this header 36470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan data.position(data.position() + thisHeaderLen); 36570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 36670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan switch (nextHeaderType) { 36770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan case IP_V6_HEADER_TYPE_ICMP_V6: 36870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan parseIcmpV6Packet(data); 36970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return; 37070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan default: 37170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan mTypeString = "Option/Protocol " + nextHeaderType; 37270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return; 37370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 37470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 37570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 37670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final short ICMP_V6_TYPE_ECHO_REQUEST = 128; 37770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final short ICMP_V6_TYPE_ECHO_REPLY = 129; 37870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final short ICMP_V6_TYPE_ROUTER_SOLICITATION = 133; 37970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final short ICMP_V6_TYPE_ROUTER_ADVERTISEMENT = 134; 38070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final short ICMP_V6_TYPE_NEIGHBOR_SOLICITATION = 135; 38170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final short ICMP_V6_TYPE_NEIGHBOR_ADVERTISEMENT = 136; 38270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final short ICMP_V6_TYPE_MULTICAST_LISTENER_DISCOVERY = 143; 38370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 38470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private void parseIcmpV6Packet(ByteBuffer data) { 38570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan mMostSpecificProtocolString = "ICMPv6"; 38670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan short icmpV6Type = getUnsignedByte(data); 38770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan switch (icmpV6Type) { 38870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan case ICMP_V6_TYPE_ECHO_REQUEST: 38970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan mTypeString = "Echo Request"; 39070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return; 39170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan case ICMP_V6_TYPE_ECHO_REPLY: 39270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan mTypeString = "Echo Reply"; 39370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return; 39470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan case ICMP_V6_TYPE_ROUTER_SOLICITATION: 39570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan mTypeString = "Router Solicitation"; 39670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return; 39770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan case ICMP_V6_TYPE_ROUTER_ADVERTISEMENT: 39870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan mTypeString = "Router Advertisement"; 39970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return; 40070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan case ICMP_V6_TYPE_NEIGHBOR_SOLICITATION: 40170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan mTypeString = "Neighbor Solicitation"; 40270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return; 40370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan case ICMP_V6_TYPE_NEIGHBOR_ADVERTISEMENT: 40470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan mTypeString = "Neighbor Advertisement"; 40570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return; 40670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan case ICMP_V6_TYPE_MULTICAST_LISTENER_DISCOVERY: 40770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan mTypeString = "MLDv2 report"; 40870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return; 40970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan default: 41070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan mTypeString = "Type " + icmpV6Type; 41170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return; 41270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 41370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 41470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 41570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte EAPOL_TYPE_KEY = 3; 41670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte EAPOL_KEY_DESCRIPTOR_RSN_KEY = 2; 41770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte EAPOL_LENGTH_LEN = 2; 41870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final short WPA_KEY_INFO_FLAG_PAIRWISE = (short) 1 << 3; // bit 4 41970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final short WPA_KEY_INFO_FLAG_INSTALL = (short) 1 << 6; // bit 7 42070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final short WPA_KEY_INFO_FLAG_MIC = (short) 1 << 8; // bit 9 42170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte WPA_KEYLEN_LEN = 2; 42270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte WPA_REPLAY_COUNTER_LEN = 8; 42370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte WPA_KEY_NONCE_LEN = 32; 42470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte WPA_KEY_IV_LEN = 16; 42570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte WPA_KEY_RECEIVE_SEQUENCE_COUNTER_LEN = 8; 42670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte WPA_KEY_IDENTIFIER_LEN = 8; 42770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte WPA_KEY_MIC_LEN = 16; 42870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 42970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private void parseEapolPacket(ByteBuffer data) { 43070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan mMostSpecificProtocolString = "EAPOL"; 43170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan short eapolVersion = getUnsignedByte(data); 43270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan if (eapolVersion < 1 || eapolVersion > 2) { 43370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan Log.e(TAG, "Unrecognized EAPOL version " + eapolVersion); 43470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return; 43570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 43670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 43770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan short eapolType = getUnsignedByte(data); 43870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan if (eapolType != EAPOL_TYPE_KEY) { 43970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan Log.e(TAG, "Unrecognized EAPOL type " + eapolType); 44070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return; 44170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 44270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 44370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan data.position(data.position() + EAPOL_LENGTH_LEN); 44470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan short eapolKeyDescriptorType = getUnsignedByte(data); 44570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan if (eapolKeyDescriptorType != EAPOL_KEY_DESCRIPTOR_RSN_KEY) { 44670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan Log.e(TAG, "Unrecognized key descriptor " + eapolKeyDescriptorType); 44770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return; 44870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 44970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 45070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan short wpaKeyInfo = data.getShort(); 45170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan if ((wpaKeyInfo & WPA_KEY_INFO_FLAG_PAIRWISE) == 0) { 45270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan mTypeString = "Group Key"; 45370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } else { 45470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan mTypeString = "Pairwise Key"; 45570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 45670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 45770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan // See goo.gl/tu8AQC for details. 45870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan if ((wpaKeyInfo & WPA_KEY_INFO_FLAG_MIC) == 0) { 45970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan mTypeString += " message 1/4"; 46070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return; 46170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 46270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 46370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan if ((wpaKeyInfo & WPA_KEY_INFO_FLAG_INSTALL) != 0) { 46470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan mTypeString += " message 3/4"; 46570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return; 46670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 46770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 46870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan data.position(data.position() + WPA_KEYLEN_LEN + WPA_REPLAY_COUNTER_LEN 46970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan + WPA_KEY_NONCE_LEN + WPA_KEY_IV_LEN + WPA_KEY_RECEIVE_SEQUENCE_COUNTER_LEN 47070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan + WPA_KEY_IDENTIFIER_LEN + WPA_KEY_MIC_LEN); 47170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan int wpaKeyDataLen = getUnsignedShort(data); 47270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan if (wpaKeyDataLen > 0) { 47370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan mTypeString += " message 2/4"; 47470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } else { 47570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan mTypeString += " message 4/4"; 47670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 47770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 47870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 47970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte IEEE_80211_FRAME_CTRL_TYPE_MGMT = 0x00; 48070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte IEEE_80211_FRAME_CTRL_SUBTYPE_ASSOC_REQ = 0x00; 48170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte IEEE_80211_FRAME_CTRL_SUBTYPE_ASSOC_RESP = 0x01; 48270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte IEEE_80211_FRAME_CTRL_SUBTYPE_PROBE_REQ = 0x04; 48370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte IEEE_80211_FRAME_CTRL_SUBTYPE_PROBE_RESP = 0x05; 48470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static final byte IEEE_80211_FRAME_CTRL_SUBTYPE_AUTH = 0x0b; 4855e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal private static final byte IEEE_80211_FRAME_CTRL_FLAG_ORDER = (byte) (1 << 7); // bit 8 4865e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal private static final byte IEEE_80211_DURATION_LEN = 2; 4875e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal private static final byte IEEE_80211_ADDR1_LEN = 6; 4885e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal private static final byte IEEE_80211_ADDR2_LEN = 6; 4895e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal private static final byte IEEE_80211_ADDR3_LEN = 6; 4905e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal private static final byte IEEE_80211_SEQUENCE_CONTROL_LEN = 2; 4915e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal private static final byte IEEE_80211_HT_CONTROL_LEN = 4; 49270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 49370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static byte parseIeee80211FrameCtrlVersion(byte b) { 49470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return (byte) (b & 0b00000011); 49570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 4965e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal private static byte parseIeee80211FrameCtrlType(byte b) { 49770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return (byte) ((b & 0b00001100) >> 2); 49870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 49970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan private static byte parseIeee80211FrameCtrlSubtype(byte b) { 50070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return (byte) ((b & 0b11110000) >> 4); 50170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 5025e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal private void parseManagementFrame(ByteBuffer data) { // 802.11-2012 Sec 8.3.3.1 5035e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal data.order(ByteOrder.LITTLE_ENDIAN); 5045e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal 50570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan mMostSpecificProtocolString = "802.11 Mgmt"; 5065e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal byte frameControlVersionTypeSubtype = data.get(); 5075e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal byte ieee80211Version = parseIeee80211FrameCtrlVersion(frameControlVersionTypeSubtype); 50870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan if (ieee80211Version != 0) { 50970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan Log.e(TAG, "Unrecognized 802.11 version " + ieee80211Version); 51070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return; 51170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 51270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 5135e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal byte ieee80211FrameType = parseIeee80211FrameCtrlType(frameControlVersionTypeSubtype); 51470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan if (ieee80211FrameType != IEEE_80211_FRAME_CTRL_TYPE_MGMT) { 51570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan Log.e(TAG, "Unexpected frame type " + ieee80211FrameType); 51670b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return; 51770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 51870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan 5195e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal byte frameControlFlags = data.get(); 5205e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal 5215e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal data.position(data.position() + IEEE_80211_DURATION_LEN + IEEE_80211_ADDR1_LEN 5225e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal + IEEE_80211_ADDR2_LEN + IEEE_80211_ADDR3_LEN + IEEE_80211_SEQUENCE_CONTROL_LEN); 5235e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal 5245e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal if ((frameControlFlags & IEEE_80211_FRAME_CTRL_FLAG_ORDER) != 0) { 5255e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal // Per 802.11-2012 Sec 8.2.4.1.10. 5265e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal data.position(data.position() + IEEE_80211_HT_CONTROL_LEN); 5275e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal } 5285e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal 5295e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal byte ieee80211FrameSubtype = parseIeee80211FrameCtrlSubtype(frameControlVersionTypeSubtype); 53070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan switch (ieee80211FrameSubtype) { 53170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan case IEEE_80211_FRAME_CTRL_SUBTYPE_ASSOC_REQ: 53270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan mTypeString = "Association Request"; 53370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return; 53470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan case IEEE_80211_FRAME_CTRL_SUBTYPE_ASSOC_RESP: 53570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan mTypeString = "Association Response"; 5365e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal parseAssociationResponse(data); 53770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return; 53870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan case IEEE_80211_FRAME_CTRL_SUBTYPE_PROBE_REQ: 53970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan mTypeString = "Probe Request"; 54070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return; 54170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan case IEEE_80211_FRAME_CTRL_SUBTYPE_PROBE_RESP: 54270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan mTypeString = "Probe Response"; 54370b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return; 54470b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan case IEEE_80211_FRAME_CTRL_SUBTYPE_AUTH: 54570b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan mTypeString = "Authentication"; 5465e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal parseAuthenticationFrame(data); 54770b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return; 54870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan default: 54970b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan mTypeString = "Unexpected subtype " + ieee80211FrameSubtype; 55070b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan return; 55170b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 55270b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan } 5535e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal 5545e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal // Per 802.11-2012 Secs 8.3.3.6 and 8.4.1. 5555e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal private static final byte IEEE_80211_CAPABILITY_INFO_LEN = 2; 5565e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal private void parseAssociationResponse(ByteBuffer data) { 5575e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal data.position(data.position() + IEEE_80211_CAPABILITY_INFO_LEN); 5585e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal short resultCode = data.getShort(); 5595e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal mResultString = String.format( 5605e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal "%d: %s", resultCode, decodeIeee80211StatusCode(resultCode)); 5615e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal } 5625e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal 5635e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal // Per 802.11-2012 Secs 8.3.3.11 and 8.4.1. 5645e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal private static final short IEEE_80211_AUTH_ALG_OPEN = 0; 5655e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal private static final short IEEE_80211_AUTH_ALG_SHARED_KEY = 1; 5665e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal private static final short IEEE_80211_AUTH_ALG_FAST_BSS_TRANSITION = 2; 5675e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal private static final short IEEE_80211_AUTH_ALG_SIMUL_AUTH_OF_EQUALS = 3; 5685e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal private void parseAuthenticationFrame(ByteBuffer data) { 5695e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal short algorithm = data.getShort(); 5705e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal short sequenceNum = data.getShort(); 5715e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal boolean hasResultCode = false; 5725e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal switch (algorithm) { 5735e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case IEEE_80211_AUTH_ALG_OPEN: 5745e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case IEEE_80211_AUTH_ALG_SHARED_KEY: 5755e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal if (sequenceNum == 2) { 5765e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal hasResultCode = true; 5775e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal } 5785e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal break; 5795e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case IEEE_80211_AUTH_ALG_FAST_BSS_TRANSITION: 5805e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal if (sequenceNum == 2 || sequenceNum == 4) { 5815e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal hasResultCode = true; 5825e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal } 5835e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal break; 5845e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case IEEE_80211_AUTH_ALG_SIMUL_AUTH_OF_EQUALS: 5855e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal hasResultCode = true; 5865e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal break; 5875e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal default: 5885e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal // Ignore unknown algorithm -- don't know which frames would have result codes. 5895e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal } 5905e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal 5915e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal if (hasResultCode) { 5925e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal short resultCode = data.getShort(); 5935e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal mResultString = String.format( 5945e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal "%d: %s", resultCode, decodeIeee80211StatusCode(resultCode)); 5955e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal } 5965e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal } 5975e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal 5985e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal // Per 802.11-2012 Table 8-37. 5995e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal private String decodeIeee80211StatusCode(short statusCode) { 6005e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal switch (statusCode) { 6015e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 0: 6025e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Success"; 6035e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 1: 6045e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Unspecified failure"; 6055e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 2: 6065e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "TDLS wakeup schedule rejected; alternative provided"; 6075e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 3: 6085e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "TDLS wakeup schedule rejected"; 6095e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 4: 6105e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Reserved"; 6115e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 5: 6125e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Security disabled"; 6135e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 6: 6145e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Unacceptable lifetime"; 6155e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 7: 6165e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Not in same BSS"; 6175e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 8: 6185e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 9: 6195e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Reserved"; 6205e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 10: 6215e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Capabilities mismatch"; 6225e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 11: 6235e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Reassociation denied; could not confirm association exists"; 6245e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 12: 6255e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Association denied for reasons outside standard"; 6265e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 13: 6275e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Unsupported authentication algorithm"; 6285e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 14: 6295e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Authentication sequence number of of sequence"; 6305e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 15: 6315e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Authentication challenge failure"; 6325e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 16: 6335e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Authentication timeout"; 6345e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 17: 6355e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Association denied; too many STAs"; 6365e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 18: 6375e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Association denied; must support BSSBasicRateSet"; 6385e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 19: 6395e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Association denied; must support short preamble"; 6405e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 20: 6415e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Association denied; must support PBCC"; 6425e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 21: 6435e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Association denied; must support channel agility"; 6445e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 22: 6455e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Association rejected; must support spectrum management"; 6465e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 23: 6475e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Association rejected; unacceptable power capability"; 6485e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 24: 6495e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Association rejected; unacceptable supported channels"; 6505e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 25: 6515e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Association denied; must support short slot time"; 6525e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 26: 6535e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Association denied; must support DSSS-OFDM"; 6545e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 27: 6555e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Association denied; must support HT"; 6565e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 28: 6575e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "R0 keyholder unreachable (802.11r)"; 6585e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 29: 6595e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Association denied; must support PCO transition time"; 6605e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 30: 6615e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Refused temporarily"; 6625e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 31: 6635e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Robust management frame policy violation"; 6645e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 32: 6655e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Unspecified QoS failure"; 6665e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 33: 6675e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Association denied; insufficient bandwidth for QoS"; 6685e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 34: 6695e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Association denied; poor channel"; 6705e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 35: 6715e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Association denied; must support QoS"; 6725e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 36: 6735e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Reserved"; 6745e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 37: 6755e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Declined"; 6765e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 38: 6775e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Invalid parameters"; 6785e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 39: 6795e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "TS cannot be honored; changes suggested"; 6805e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 40: 6815e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Invalid element"; 6825e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 41: 6835e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Invalid group cipher"; 6845e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 42: 6855e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Invalid pairwise cipher"; 6865e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 43: 6875e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Invalid auth/key mgmt proto (AKMP)"; 6885e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 44: 6895e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Unsupported RSNE version"; 6905e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 45: 6915e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Invalid RSNE capabilities"; 6925e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 46: 6935e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Cipher suite rejected by policy"; 6945e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 47: 6955e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "TS cannot be honored now; try again later"; 6965e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 48: 6975e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Direct link rejected by policy"; 6985e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 49: 6995e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Destination STA not in BSS"; 7005e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 50: 7015e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Destination STA not configured for QoS"; 7025e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 51: 7035e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Association denied; listen interval too large"; 7045e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 52: 7055e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Invalid fast transition action frame count"; 7065e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 53: 7075e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Invalid PMKID"; 7085e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 54: 7095e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Invalid MDE"; 7105e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 55: 7115e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Invalid FTE"; 7125e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 56: 7135e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Unsupported TCLAS"; 7145e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 57: 7155e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Requested TCLAS exceeds resources"; 7165e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 58: 7175e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "TS cannot be honored; try another BSS"; 7185e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 59: 7195e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "GAS Advertisement not supported"; 7205e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 60: 7215e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "No outstanding GAS request"; 7225e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 61: 7235e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "No query response from GAS server"; 7245e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 62: 7255e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "GAS query timeout"; 7265e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 63: 7275e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "GAS response too large"; 7285e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 64: 7295e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Home network does not support request"; 7305e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 65: 7315e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Advertisement server unreachable"; 7325e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 66: 7335e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Reserved"; 7345e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 67: 7355e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Rejected for SSP permissions"; 7365e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 68: 7375e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Authentication required"; 7385e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 69: 7395e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 70: 7405e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 71: 7415e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Reserved"; 7425e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 72: 7435e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Invalid RSNE contents"; 7445e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 73: 7455e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "U-APSD coexistence unsupported"; 7465e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 74: 7475e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Requested U-APSD coex mode unsupported"; 7485e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 75: 7495e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Requested parameter unsupported with U-APSD coex"; 7505e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 76: 7515e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Auth rejected; anti-clogging token required"; 7525e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 77: 7535e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Auth rejected; offered group is not supported"; 7545e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 78: 7555e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Cannot find alternative TBTT"; 7565e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 79: 7575e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Transmission failure"; 7585e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 80: 7595e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Requested TCLAS not supported"; 7605e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 81: 7615e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "TCLAS resources exhausted"; 7625e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 82: 7635e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Rejected with suggested BSS transition"; 7645e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 83: 7655e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Reserved"; 7665e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 84: 7675e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 85: 7685e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 86: 7695e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 87: 7705e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 88: 7715e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 89: 7725e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 90: 7735e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 91: 7745e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "<unspecified>"; 7755e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 92: 7765e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Refused due to external reason"; 7775e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 93: 7785e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Refused; AP out of memory"; 7795e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 94: 7805e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Refused; emergency services not supported"; 7815e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 95: 7825e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "GAS query response outstanding"; 7835e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 96: 7845e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 97: 7855e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 98: 7865e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 99: 7875e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Reserved"; 7885e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 100: 7895e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Failed; reservation conflict"; 7905e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 101: 7915e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Failed; exceeded MAF limit"; 7925e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal case 102: 7935e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Failed; exceeded MCCA track limit"; 7945e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal default: 7955e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal return "Reserved"; 7965e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal } 7975e550bdccf8aaace892366fbbaf90bd0a7c456afmukesh agrawal } 79870b4f7f1b8f57c5ae449dedb48edc0d07b6b5c41Samuel Tan} 799