1f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle/*
2f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * Copyright (C) 2008 The Android Open Source Project
3f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle *
4f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * Licensed under the Apache License, Version 2.0 (the "License");
5f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * you may not use this file except in compliance with the License.
6f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * You may obtain a copy of the License at
7f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle *
8f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle *      http://www.apache.org/licenses/LICENSE-2.0
9f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle *
10f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * Unless required by applicable law or agreed to in writing, software
11f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * distributed under the License is distributed on an "AS IS" BASIS,
12f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * See the License for the specific language governing permissions and
14f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * limitations under the License.
15f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle */
16f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
17647207cce53bad5ef911e16278d5a2c910cdab92Jeff Davidsonpackage com.android.server.wifi;
18f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
19f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalleimport android.os.Parcelable;
20f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalleimport android.os.Parcel;
21f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
22f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalleimport java.util.BitSet;
23f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
24f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalleimport java.nio.ByteBuffer;
25f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
26f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalleimport java.util.Date;
27f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
28f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle/**
29f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * Describes information about a detected access point. In addition
30f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * to the attributes described here, the supplicant keeps track of
31f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * {@code quality}, {@code noise}, and {@code maxbitrate} attributes,
32f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle * but does not currently report them to external clients.
33f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle */
34f22d23092ab37286a5ef9d257d5bb32c421d2669vandwallepublic class WifiParser {
35f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
36f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    public WifiParser() {}
37f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
38f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
39f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    /*
40f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle     * {@hide}
41f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle     */
42f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    class IE {
43f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        int id;
44f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        byte data[];
45f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    }
46f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
47f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    private static final int VENDOR_SPECIFIC_IE = 221;
48f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    private static final int IEEE_RSN_IE = 48; //IEEE 2012 8.4.2.27
49f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
50f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
51f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    private static final int WPA_IE_VENDOR_TYPE = 0x0050f201; //WFA WPA vendor IE OUI/type
52f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
53f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    /*
54f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle     * parse beacon or probe response frame and build the capabilities
55f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle     * {@hide}
56f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle     *
57f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle     * This function is called so as to build the capabilities string of the scan result, hence it is called
58f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle     * by AutoJoin controller when handling scan results that are coming from WifiScanner.
59f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle     *
60f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle     * It parses the ieee beacon's capability field, WPA and RSNE IE as per spec, but build the
61f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle     * ScanResult.capabilities String in a way that mirror the values returned by wpa_supplicant.
62f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle     *
63f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle     * Once the capabilities string is build, the ScanResult can be used be the system as if it was coming from supplicant.
64f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle     */
65f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle     /* @hide
66f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle     * */
67f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    static public String parse_akm(IE full_IE[], BitSet ieee_cap) {
68f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        boolean privacy = false;
69f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        boolean error = false;
70f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        if (ieee_cap == null)
71f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            return null;
72f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
73f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        if (full_IE == null)
74f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            return null;
75f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
76f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        privacy = ieee_cap.get(4);
77f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
78f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        String capabilities = "";
79f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        boolean rsne_found = false;
80f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        boolean wpa_found = false;
81f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
82f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        for (IE ie : full_IE) {
83f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            String security = "";
84f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            if (ie.id == IEEE_RSN_IE) {
85f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                rsne_found = true;
86f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                //parsing WPA2 capabilities
87f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
88f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                ByteBuffer buf = ByteBuffer.wrap(ie.data);
89f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
90f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                int total_len = ie.data.length;
91f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                int offset = 2;
92f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
93f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                //version
94f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                if ((total_len - offset) < 2) {
95f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    //not enough space for version field
96f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    security = "";
97f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    error = true;
98f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    break;
99f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                }
100f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                int val = 0;
101f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                if (0x0100 != buf.getShort(offset)) {
102f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    //incorrect version
103f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    security = "";
104f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    error = true;
105f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    break;
106f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                }
107f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                offset += 2;
108f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
109f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
110f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                //group cipher
111f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                if ((total_len - offset) < 4) {
112f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    security = ""; //parse error on group cipher suite
113f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    error = true;
114f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    break;
115f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                }
116f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                offset += 4; //skip the group cipher
117f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
118f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                security = "[WPA2"; //found the RSNE IE, hence start building the capability string
119f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
120f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                //pairwise cipher
121f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                if ((total_len - offset) < 2) {
122f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    security = ""; //parse error no pairwise cipher
123f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    error = true;
124f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    break;
125f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                }
126f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                val = buf.getShort(offset);
127f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                if ((total_len - offset) < (2 + val * 4)) {
128f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    security = ""; //parse error no pairwise cipher
129f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    error = true;
130f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    break;
131f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                }
132f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                offset += 2 + val * 4; //skip the pairwise ciphers
133f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
134f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                //AKM
135f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                if ((total_len - offset) < 2) {
136f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    security = ""; //parse error no AKM
137f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    error = true;
138f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    break;
139f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                }
140f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                val = buf.getShort(offset);
141f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                if ((total_len - offset) < (2 + val * 4)) {
142f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    security = ""; //parse error no pairwise cipher
143f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    error = true;
144f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    break;
145f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                }
146f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                offset += 2;
147f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                if (val == 0) {
148f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    security += "-EAP"; //default AKM
149f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                }
150f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                for (int i = 0; i < val; i++) {
151f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    int akm = buf.getInt(offset);
152f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    boolean found = false;
153f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    switch (akm) {
154f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                        case 0x01ac0f00:
155f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                            security += found ? "+" : "-" + "EAP";
156f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                            found = true;
157f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                            break;
158f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                        case 0x02ac0f00:
159f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                            security += found ? "+" : "-" + "PSK"; //PSK as 802.11-2012 11.6.1.2
160f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                            found = true;
161f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                            break;
162f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                        case 0x03ac0f00:
163f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                            security += found ? "+" : "-" + "FT/EAP";
164f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                            found = true;
165f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                            break;
166f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                        case 0x04ac0f00:
167f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                            security += found ? "+" : "-" + "FT/PSK";
168f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                            found = true;
169f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                            break;
170f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                        case 0x06ac0f00:
171f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                            security += found ? "+" : "-" + "PSK-SHA256";
172f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                            found = true;
173f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                            break;
174f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                        case 0x05ac0f00:
175f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                            security += found ? "+" : "-" + "EAP-SHA256";
176f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                            found = true;
177f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                            break;
178f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    }
179f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    offset += 4;
180f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                }
181f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                //we parsed what we want at this point
182f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                security += "]";
183f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                capabilities += security;
184f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
185f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            }
186f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
187f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            if (ie.id == VENDOR_SPECIFIC_IE) {
188f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                int total_len = ie.data.length;
189f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                int offset = 2;
190f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
191f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                //version
192f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                if ((total_len - offset) < 4) {
193f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    //not enough space for OUI and type field
194f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    security = "";
195f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    error = true;
196f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    break;
197f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                }
198f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
199f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                ByteBuffer buf = ByteBuffer.wrap(ie.data);
200f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
201f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                if (buf.getInt(offset) != 0x01F25000) {
202f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    //look for HS2.0 and WPA IE
203f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    security = "";
204f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    continue;
205f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                }
206f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
207f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                security = "[WPA"; //prep the string for WPA
208f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
209f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                //version
210f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                if ((total_len - offset) < 2) {
211f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    //not enough space for version field
212f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    security = "";
213f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    error = true;
214f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    break;
215f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                }
216f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                int val = 0;
217f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                if (0x0100 != buf.getShort(offset)) {
218f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    //incorrect version
219f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    security = "";
220f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    error = true;
221f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    break;
222f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                }
223f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                offset += 2;
224f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
225f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
226f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                //group cipher
227f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                if ((total_len - offset) < 4) {
228f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    security = ""; //parse error on group cipher suite
229f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    error = true;
230f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    break;
231f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                }
232f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                offset += 4; //skip the group cipher
233f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
234f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
235f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                //pairwise cipher
236f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                if ((total_len - offset) < 2) {
237f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    security = ""; //parse error no pairwise cipher
238f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    error = true;
239f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    break;
240f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                }
241f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                val = buf.getShort(offset);
242f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                if ((total_len - offset) < (2 + val * 4)) {
243f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    security = ""; //parse error no pairwise cipher
244f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    error = true;
245f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    break;
246f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                }
247f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                offset += 2 + val * 4; //skip the pairwise ciphers
248f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
249f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                //AKM
250f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                if ((total_len - offset) < 2) {
251f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    security = ""; //parse error no AKM
252f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    error = true;
253f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    break;
254f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                }
255f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                val = buf.getShort(offset);
256f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                if ((total_len - offset) < (2 + val * 4)) {
257f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    security = ""; //parse error no pairwise cipher
258f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    error = true;
259f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    break;
260f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                }
261f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                offset += 2;
262f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                if (val == 0) {
263f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    security += "-EAP"; //default AKM
264f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                }
265f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                for (int i = 0; i < val; i++) {
266f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    int akm = buf.getInt(offset);
267f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    boolean found = false;
268f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    switch (akm) {
269f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                        case 0x01f25000:
270f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                            security += found ? "+" : "-" + "EAP";
271f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                            found = true;
272f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                            break;
273f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                        case 0x02f25000:
274f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                            security += found ? "+" : "-" + "PSK"; //PSK as 802.11-2012 11.6.1.2
275f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                            found = true;
276f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                            break;
277f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
278f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    }
279f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    offset += 4;
280f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                }
281f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                //we parsed what we want at this point
282f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                security += "]";
283f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            }
284f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        }
285f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
286f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        if (rsne_found == false && wpa_found == false && privacy) {
287f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            //private Beacon without an RSNE or WPA IE, hence WEP0
288f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            capabilities += "[WEP]";
289f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        }
290f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
291f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        if (error)
292f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            return null;
293f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        else
294f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            return capabilities;
295f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    }
296f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
297f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
298f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle}
299