• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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