|
|
@@ -7,22 +7,39 @@
|
|
|
#include <netlink/attr.h>
|
|
|
#include <linux/nl80211.h>
|
|
|
#include <net/if.h>
|
|
|
+#include <unistd.h>
|
|
|
+#include <sys/ioctl.h>
|
|
|
#include <asm/types.h>
|
|
|
#include <stdio.h>
|
|
|
#include <stdlib.h>
|
|
|
#include <string.h>
|
|
|
#include <errno.h>
|
|
|
+#include "common.h"
|
|
|
#include "lock.h"
|
|
|
+#include "sys.h"
|
|
|
#include "wifi.h"
|
|
|
+#include "paras.h"
|
|
|
+#include "common.h"
|
|
|
|
|
|
+#define USE_WIFI
|
|
|
+#define USE_LIBNL
|
|
|
|
|
|
#define ONCE_CNT 20
|
|
|
#define WLAN_IFNAME "wlan0"
|
|
|
+#define AP_CONF "/etc/hostapd.conf"
|
|
|
+#define STA_CONF "/etc/wpa_supplicant.conf"
|
|
|
+#define AP_IP "192.168.2.132"
|
|
|
+
|
|
|
+enum {
|
|
|
+ EVT_ERR=0,
|
|
|
+ EVT_ACK,
|
|
|
+ EVT_FIN,
|
|
|
+};
|
|
|
|
|
|
typedef struct {
|
|
|
- char *ssid;
|
|
|
+ int evt;
|
|
|
ap_list_t list;
|
|
|
-}ap_res_t;
|
|
|
+}result_t;
|
|
|
typedef struct {
|
|
|
int ifindex;
|
|
|
char *ifname;
|
|
|
@@ -32,9 +49,105 @@ typedef struct {
|
|
|
struct nl_sock *sock;
|
|
|
}nl_handle_t;
|
|
|
typedef struct {
|
|
|
- int flag;
|
|
|
+ int flag;
|
|
|
}wifi_handle_t;
|
|
|
static wifi_handle_t wfHandle={0};
|
|
|
+const char *auth_str[AUTH_MAX]={
|
|
|
+ "NONE",
|
|
|
+ "ERR",
|
|
|
+ "PSK",
|
|
|
+ "EAP",
|
|
|
+};
|
|
|
+const char *crypt_str[CRYPT_MAX]={
|
|
|
+ "NONE",
|
|
|
+ "ERR",
|
|
|
+ "WEP",
|
|
|
+ "WPA",
|
|
|
+ "WPA2",
|
|
|
+};
|
|
|
+
|
|
|
+static void res_print(result_t *res)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ ap_info_t *info;
|
|
|
+ if(res && res->list.cnt>0) {
|
|
|
+ for(i=0; i<res->list.cnt; i++) {
|
|
|
+ info = &res->list.info[i];
|
|
|
+ printf("___[%d].ssid: %s\n", i, info->ssid);
|
|
|
+ printf("___[%d].bssid: %s\n", i, info->bssid);
|
|
|
+ printf("___[%d].freq: %dMHz\n", i, info->freq);
|
|
|
+ printf("___[%d].intensity: %d\n", i, info->intensity);
|
|
|
+ printf("___[%d].auth: %s\n", i, auth_str[info->auth]);
|
|
|
+ printf("___[%d].crypt: %s\n", i, crypt_str[info->crypt]);
|
|
|
+ printf("\n");
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+static void res_free(result_t *res)
|
|
|
+{
|
|
|
+ if(res) {
|
|
|
+ if(res->list.info) {
|
|
|
+ free(res->list.info);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+static int sta_start(ap_info_t *info, int on)
|
|
|
+{
|
|
|
+ int r,ipv,mask=24;
|
|
|
+ char tmp[400],txt[200];
|
|
|
+
|
|
|
+ //https://www.cnblogs.com/lidabo/p/5076560.html
|
|
|
+ r = system("killall wpa_supplicant");
|
|
|
+ if(on) {
|
|
|
+ snprintf(txt, sizeof(txt), "ctrl_interface=/var/run/wpa_supplicant\n"
|
|
|
+ "network={\n"
|
|
|
+ "ssid=\"%s\"\n"
|
|
|
+ "psk=\"%s\"\n"
|
|
|
+ "}\n", info->ssid, info->password);
|
|
|
+
|
|
|
+ sprintf(tmp, "echo '%s' > %s", txt, STA_CONF);
|
|
|
+ r = system(tmp);
|
|
|
+
|
|
|
+ sprintf(tmp, "wpa_supplicant -B -i %s -c %s", WLAN_IFNAME, STA_CONF);
|
|
|
+ r = system(tmp);
|
|
|
+
|
|
|
+ ipv = sys_get_ip_ver(info->ipaddr);
|
|
|
+ if(ipv==IP_V6) {
|
|
|
+ mask = 64;
|
|
|
+ }
|
|
|
+ sprintf(tmp, "ip addr add %s/%d dev %s", info->ipaddr, mask, WLAN_IFNAME);
|
|
|
+ r = system(tmp);
|
|
|
+
|
|
|
+ sprintf(tmp, "udhcpc -b -i %s", WLAN_IFNAME);
|
|
|
+ r = system(tmp);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ r = system("wpa_cli disconnect");
|
|
|
+ r = system("killall wpa_supplicant udhcpc");
|
|
|
+ }
|
|
|
+
|
|
|
+ return r;
|
|
|
+}
|
|
|
+static int ap_start(ap_info_t *info, int on)
|
|
|
+{
|
|
|
+ int r;
|
|
|
+ char tmp[100];
|
|
|
+
|
|
|
+ //https://blog.csdn.net/qq_40311939/article/details/139552431
|
|
|
+ r = system("killall hostapd udhcpd");
|
|
|
+ if(on) {
|
|
|
+ sprintf(tmp, "hostapd -B %s", AP_CONF);
|
|
|
+ r = system(tmp);
|
|
|
+
|
|
|
+ //ipv = sys_get_ip_ver(info->ipaddr);
|
|
|
+ sprintf(tmp, "ip addr add %s/24 dev %s", info->ipaddr, WLAN_IFNAME);
|
|
|
+ r = system(tmp);
|
|
|
+
|
|
|
+ sprintf(tmp, "udhcpd -i %s -SC /etc/udhcpd.conf", WLAN_IFNAME);
|
|
|
+ r = system(tmp);
|
|
|
+ }
|
|
|
+ return r;
|
|
|
+}
|
|
|
|
|
|
#ifdef USE_WIFI
|
|
|
static void priv_parse(uint8_t *ie, size_t ie_len, ap_info_t *info)
|
|
|
@@ -48,18 +161,17 @@ static void priv_parse(uint8_t *ie, size_t ie_len, ap_info_t *info)
|
|
|
uint8_t len = pos[1];
|
|
|
|
|
|
if (pos + 2 + len > ie + ie_len) {
|
|
|
- info->auth = AUTH_WRONG;
|
|
|
- info->crypt = CRYPT_WRONG;
|
|
|
+ info->auth = AUTH_ERR;
|
|
|
+ info->crypt = CRYPT_ERR;
|
|
|
break; // ���� IE
|
|
|
}
|
|
|
|
|
|
// ���� RSN (WPA2) IE
|
|
|
if (id == 48) { // RSN IE ID
|
|
|
- uint16_t *auth_suites = (uint16_t *)(pos + 12); // RSN ��֤��ƫ��
|
|
|
+ uint16_t auth = *((uint16_t *)(pos + 12)); // RSN ��֤��ƫ��
|
|
|
|
|
|
- printf("Encryption: WPA2\n");
|
|
|
info->crypt = CRYPT_WPA2;
|
|
|
- switch (*auth_suites) {
|
|
|
+ switch (auth) {
|
|
|
case 0x0001:
|
|
|
info->auth = AUTH_PSK;
|
|
|
break;
|
|
|
@@ -67,17 +179,16 @@ static void priv_parse(uint8_t *ie, size_t ie_len, ap_info_t *info)
|
|
|
info->auth = AUTH_EAP;
|
|
|
break;
|
|
|
default:
|
|
|
- info->auth = AUTH_WRONG;
|
|
|
+ info->auth = AUTH_ERR;
|
|
|
break;
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
else if (id == 221 && len >= 4 && pos[2] == 0x00 && pos[3] == 0x50 && pos[4] == 0xF2 && pos[5] == 0x01) {
|
|
|
- uint16_t *auth_suites = (uint16_t *)(pos + 12); // WPA ��֤��ƫ��
|
|
|
+ uint16_t auth = *((uint16_t *)(pos + 12)); // WPA ��֤��ƫ��
|
|
|
|
|
|
- printf("Encryption: WPA\n");
|
|
|
info->crypt = CRYPT_WPA;
|
|
|
- switch (*auth_suites) {
|
|
|
+ switch (auth) {
|
|
|
case 0x0001:
|
|
|
info->auth = AUTH_PSK;
|
|
|
break;
|
|
|
@@ -85,7 +196,7 @@ static void priv_parse(uint8_t *ie, size_t ie_len, ap_info_t *info)
|
|
|
info->auth = AUTH_EAP;
|
|
|
break;
|
|
|
default:
|
|
|
- info->auth = AUTH_WRONG;
|
|
|
+ info->auth = AUTH_ERR;
|
|
|
break;
|
|
|
}
|
|
|
break;
|
|
|
@@ -99,97 +210,200 @@ static void priv_parse(uint8_t *ie, size_t ie_len, ap_info_t *info)
|
|
|
pos += 2 + len;
|
|
|
}
|
|
|
}
|
|
|
-static int nl_callback(struct nl_msg *msg, void *arg)
|
|
|
+
|
|
|
+
|
|
|
+struct trigger_results {
|
|
|
+ int done;
|
|
|
+ int aborted;
|
|
|
+};
|
|
|
+static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
|
|
|
{
|
|
|
- int flag=0;
|
|
|
- struct nlattr *tb[NL80211_ATTR_MAX + 1];
|
|
|
+ // Callback for errors.
|
|
|
+ printf("error_handler() called.\n");
|
|
|
+ int *ret = arg;
|
|
|
+ *ret = err->error;
|
|
|
+ return NL_STOP;
|
|
|
+}
|
|
|
+static int finish_handler(struct nl_msg *msg, void *arg)
|
|
|
+{
|
|
|
+ // Callback for NL_CB_FINISH.
|
|
|
+ int *ret = arg;
|
|
|
+ *ret = 0;
|
|
|
+ return NL_SKIP;
|
|
|
+}
|
|
|
+static int ack_handler(struct nl_msg *msg, void *arg)
|
|
|
+{
|
|
|
+ // Callback for NL_CB_ACK.
|
|
|
+ int *ret = arg;
|
|
|
+ *ret = 0;
|
|
|
+ return NL_STOP;
|
|
|
+}
|
|
|
+static int no_seq_check(struct nl_msg *msg, void *arg)
|
|
|
+{
|
|
|
+ // Callback for NL_CB_SEQ_CHECK.
|
|
|
+ return NL_OK;
|
|
|
+}
|
|
|
+static int callback_trigger(struct nl_msg *msg, void *arg)
|
|
|
+{
|
|
|
+ // Called by the kernel when the scan is done or has been aborted.
|
|
|
+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
|
|
|
+ struct trigger_results *results = arg;
|
|
|
+
|
|
|
+ //printf("Got something.\n");
|
|
|
+ //printf("%d\n", arg);
|
|
|
+ //nl_msg_dump(msg, stdout);
|
|
|
+
|
|
|
+ if (gnlh->cmd == NL80211_CMD_SCAN_ABORTED) {
|
|
|
+ printf("Got NL80211_CMD_SCAN_ABORTED.\n");
|
|
|
+ results->done = 1;
|
|
|
+ results->aborted = 1;
|
|
|
+ } else if (gnlh->cmd == NL80211_CMD_NEW_SCAN_RESULTS) {
|
|
|
+ printf("Got NL80211_CMD_NEW_SCAN_RESULTS.\n");
|
|
|
+ results->done = 1;
|
|
|
+ results->aborted = 0;
|
|
|
+ } // else probably an uninteresting multicast message.
|
|
|
+
|
|
|
+ return NL_SKIP;
|
|
|
+}
|
|
|
+static int callback_dump(struct nl_msg *msg, void *arg)
|
|
|
+{
|
|
|
+ // Called by the kernel with a dump of the successful scan's data. Called for each SSID.
|
|
|
struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
|
|
|
+ char mac_addr[20];
|
|
|
+ struct nlattr *tb[NL80211_ATTR_MAX + 1];
|
|
|
struct nlattr *bss[NL80211_BSS_MAX + 1];
|
|
|
- struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {
|
|
|
- [NL80211_BSS_BSSID] = { .type = NLA_UNSPEC },
|
|
|
- [NL80211_BSS_INFORMATION_ELEMENTS] = { .type = NLA_UNSPEC },
|
|
|
+ static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {
|
|
|
+ [NL80211_BSS_TSF] = { .type = NLA_U64 },
|
|
|
[NL80211_BSS_FREQUENCY] = { .type = NLA_U32 },
|
|
|
+ [NL80211_BSS_BSSID] = { },
|
|
|
+ [NL80211_BSS_BEACON_INTERVAL] = { .type = NLA_U16 },
|
|
|
+ [NL80211_BSS_CAPABILITY] = { .type = NLA_U16 },
|
|
|
+ [NL80211_BSS_INFORMATION_ELEMENTS] = { },
|
|
|
[NL80211_BSS_SIGNAL_MBM] = { .type = NLA_U32 },
|
|
|
+ [NL80211_BSS_SIGNAL_UNSPEC] = { .type = NLA_U8 },
|
|
|
+ [NL80211_BSS_STATUS] = { .type = NLA_U32 },
|
|
|
+ [NL80211_BSS_SEEN_MS_AGO] = { .type = NLA_U32 },
|
|
|
+ [NL80211_BSS_BEACON_IES] = { },
|
|
|
};
|
|
|
- ap_res_t *res=(ap_res_t*)arg;
|
|
|
+ result_t *res=(result_t*)arg;
|
|
|
ap_info_t *info=&res->list.info[res->list.cnt];
|
|
|
-
|
|
|
- if(res->ssid) {
|
|
|
- info = &res->list.info[0];
|
|
|
- }
|
|
|
|
|
|
- // ������Ϣ����
|
|
|
+ // Parse and error check.
|
|
|
nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL);
|
|
|
+ if (!tb[NL80211_ATTR_BSS]) {
|
|
|
+ printf("bss info missing!\n");
|
|
|
+ return NL_SKIP;
|
|
|
+ }
|
|
|
+ if (nla_parse_nested(bss, NL80211_BSS_MAX, tb[NL80211_ATTR_BSS], bss_policy)) {
|
|
|
+ printf("failed to parse nested attributes!\n");
|
|
|
+ return NL_SKIP;
|
|
|
+ }
|
|
|
|
|
|
- if (tb[NL80211_ATTR_BSS]) {
|
|
|
- // ����Ƕ�� BSS ����
|
|
|
- nla_parse_nested(bss, NL80211_BSS_MAX, tb[NL80211_ATTR_BSS], bss_policy);
|
|
|
-
|
|
|
- // ��ӡ BSSID
|
|
|
- if (bss[NL80211_BSS_BSSID]) {
|
|
|
- uint8_t *bssid = nla_data(bss[NL80211_BSS_BSSID]);
|
|
|
- sprintf(info->bssid, "%02x:%02x:%02x:%02x:%02x:%02x", bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);
|
|
|
- }
|
|
|
+ if (bss[NL80211_BSS_BSSID]) {
|
|
|
+ uint8_t *bssid = nla_data(bss[NL80211_BSS_BSSID]);
|
|
|
+ sprintf(info->bssid, "%02x:%02x:%02x:%02x:%02x:%02x", bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);
|
|
|
+ }
|
|
|
|
|
|
- // ��ӡ�ź�ǿ��
|
|
|
- if (bss[NL80211_BSS_SIGNAL_MBM]) {
|
|
|
- int32_t signal = nla_get_u32(bss[NL80211_BSS_SIGNAL_MBM]);
|
|
|
- info->intensity = (signal/100);
|
|
|
- }
|
|
|
+ if (bss[NL80211_BSS_SIGNAL_MBM]) {
|
|
|
+ int32_t signal = nla_get_u32(bss[NL80211_BSS_SIGNAL_MBM]);
|
|
|
+ info->intensity = (signal/100);
|
|
|
+ }
|
|
|
|
|
|
- // ��ӡƵ��
|
|
|
- if (bss[NL80211_BSS_FREQUENCY]) {
|
|
|
- uint32_t freq = nla_get_u32(bss[NL80211_BSS_FREQUENCY]);
|
|
|
- info->freq = freq;
|
|
|
- }
|
|
|
-
|
|
|
- // ������ϢԪ�أ�IEs���Ի�ȡ SSID
|
|
|
- if (bss[NL80211_BSS_INFORMATION_ELEMENTS]) {
|
|
|
- uint8_t *ies = nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
|
|
|
- int ies_len = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
|
|
|
-
|
|
|
- priv_parse(ies, nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]), info);
|
|
|
-
|
|
|
- // ���� SSID����ϢԪ�� ID Ϊ 0��
|
|
|
- int offset = 0;
|
|
|
- while (offset < ies_len) {
|
|
|
- uint8_t ie_id = ies[offset];
|
|
|
- uint8_t ie_len = ies[offset + 1];
|
|
|
-
|
|
|
- if (ie_id == 0 && ie_len > 0 && ie_len <= 32) { // SSID �� ID Ϊ 0
|
|
|
- memcpy(info->ssid, &ies[offset + 2], ie_len);
|
|
|
- info->ssid[ie_len] = 0;
|
|
|
- if(res->ssid && strcmp(res->ssid, info->ssid)==0) {
|
|
|
- flag = 1;
|
|
|
- fprintf(stderr, "%s find\n", res->ssid);
|
|
|
- }
|
|
|
- break;
|
|
|
- }
|
|
|
- offset += ie_len + 2; // �ƶ�����һ����ϢԪ��
|
|
|
+ if (bss[NL80211_BSS_FREQUENCY]) {
|
|
|
+ uint32_t freq = nla_get_u32(bss[NL80211_BSS_FREQUENCY]);
|
|
|
+ info->freq = freq;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (bss[NL80211_BSS_INFORMATION_ELEMENTS]) {
|
|
|
+ uint8_t *ies = nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
|
|
|
+ int ies_len = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
|
|
|
+
|
|
|
+ priv_parse(ies, nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]), info);
|
|
|
+
|
|
|
+ // ���� SSID����ϢԪ�� ID Ϊ 0��
|
|
|
+ int offset = 0;
|
|
|
+ while (offset < ies_len) {
|
|
|
+ uint8_t ie_id = ies[offset];
|
|
|
+ uint8_t ie_len = ies[offset + 1];
|
|
|
+
|
|
|
+ if (ie_id == 0 && ie_len > 0 && ie_len <= 32) { // SSID �� ID Ϊ 0
|
|
|
+ memcpy(info->ssid, &ies[offset + 2], ie_len);
|
|
|
+ info->ssid[ie_len] = 0;
|
|
|
+ break;
|
|
|
}
|
|
|
+ offset += ie_len + 2;
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- res->list.cnt++;
|
|
|
- if(res->list.cnt>=res->list.max) {
|
|
|
- int max = res->list.max+ONCE_CNT;
|
|
|
- res->list.info = (ap_info_t*)realloc(res->list.info, sizeof(ap_info_t)*max);
|
|
|
- if(res->list.info) {
|
|
|
- res->list.max = max;
|
|
|
- }
|
|
|
- else {
|
|
|
- fprintf(stderr, "res->info realloc failed\n");
|
|
|
- return NL_STOP;
|
|
|
- }
|
|
|
+ res->list.cnt++;
|
|
|
+ if(res->list.cnt>=res->list.max) {
|
|
|
+ int max = res->list.max+ONCE_CNT;
|
|
|
+ res->list.info = (ap_info_t*)realloc(res->list.info, sizeof(ap_info_t)*max);
|
|
|
+ if(res->list.info) {
|
|
|
+ res->list.max = max;
|
|
|
}
|
|
|
-
|
|
|
- if(flag) {
|
|
|
+ else {
|
|
|
+ fprintf(stderr, "res->info realloc failed\n");
|
|
|
return NL_STOP;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return NL_SKIP;
|
|
|
}
|
|
|
-static int nl_init(nl_handle_t *h)
|
|
|
+static int scan_trigger(nl_handle_t *h)
|
|
|
+{
|
|
|
+ // Starts the scan and waits for it to finish. Does not return until the scan is done or has been aborted.
|
|
|
+ struct trigger_results results = { .done = 0, .aborted = 0 };
|
|
|
+ struct nl_msg *ssids_to_scan;
|
|
|
+ int err,ret;
|
|
|
+ int mcid = genl_ctrl_resolve_grp(h->sock, "nl80211", "scan");
|
|
|
+ nl_socket_add_membership(h->sock, mcid); // Without this, callback_trigger() won't be called.
|
|
|
+
|
|
|
+ // Allocate the messages and callback handler.
|
|
|
+ ssids_to_scan = nlmsg_alloc();
|
|
|
+ if (!ssids_to_scan) {
|
|
|
+ printf("ERROR: Failed to allocate netlink message for ssids_to_scan.\n");
|
|
|
+ return -ENOMEM;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Setup the messages and callback handler.
|
|
|
+ genlmsg_put(h->msg, 0, 0, h->nl_id, 0, 0, NL80211_CMD_TRIGGER_SCAN, 0); // Setup which command to run.
|
|
|
+ nla_put_u32(h->msg, NL80211_ATTR_IFINDEX, h->ifindex); // Add message attribute, which interface to use.
|
|
|
+ nla_put(ssids_to_scan, 1, 0, ""); // Scan all SSIDs.
|
|
|
+ nla_put_nested(h->msg, NL80211_ATTR_SCAN_SSIDS, ssids_to_scan); // Add message attribute, which SSIDs to scan for.
|
|
|
+ nlmsg_free(ssids_to_scan); // Copied to `msg` above, no longer need this.
|
|
|
+ nl_cb_set(h->cb, NL_CB_VALID, NL_CB_CUSTOM, callback_trigger, &results); // Add the callback.
|
|
|
+ nl_cb_err(h->cb, NL_CB_CUSTOM, error_handler, &err);
|
|
|
+ nl_cb_set(h->cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err);
|
|
|
+ nl_cb_set(h->cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);
|
|
|
+ nl_cb_set(h->cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL); // No sequence checking for multicast messages.
|
|
|
+
|
|
|
+ // Send NL80211_CMD_TRIGGER_SCAN to start the scan. The kernel may reply with NL80211_CMD_NEW_SCAN_RESULTS on
|
|
|
+ // success or NL80211_CMD_SCAN_ABORTED if another scan was started by another process.
|
|
|
+ err = 1;
|
|
|
+ ret = nl_send_auto(h->sock, h->msg); // Send the message.
|
|
|
+ printf("NL80211_CMD_TRIGGER_SCAN sent %d bytes to the kernel.\n", ret);
|
|
|
+ printf("Waiting for scan to complete...\n");
|
|
|
+ while (err > 0) ret = nl_recvmsgs(h->sock, h->cb); // First wait for ack_handler(). This helps with basic errors.
|
|
|
+ if (err < 0) {
|
|
|
+ printf("WARNING: err has a value of %d.\n", err);
|
|
|
+ }
|
|
|
+ if (ret < 0) {
|
|
|
+ printf("ERROR: nl_recvmsgs() returned %d (%s).\n", ret, nl_geterror(-ret));
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+ while (!results.done) nl_recvmsgs(h->sock, h->cb); // Now wait until the scan is done or aborted.
|
|
|
+ if (results.aborted) {
|
|
|
+ printf("ERROR: Kernel aborted scan.\n");
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ printf("Scan is done.\n");
|
|
|
+
|
|
|
+ // Cleanup.
|
|
|
+ nl_socket_drop_membership(h->sock, mcid); // No longer need this.
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+static int nl80211_init(nl_handle_t *h)
|
|
|
{
|
|
|
h->ifname = WLAN_IFNAME;
|
|
|
h->ifindex = if_nametoindex(h->ifname);
|
|
|
@@ -197,7 +411,6 @@ static int nl_init(nl_handle_t *h)
|
|
|
fprintf(stderr, "Failed to get interface index\n");
|
|
|
return -1;
|
|
|
}
|
|
|
- h->nl_id = genl_ctrl_resolve(h->sock, "nl80211");
|
|
|
|
|
|
h->cb = nl_cb_alloc(NL_CB_DEFAULT);
|
|
|
if (!h->cb) {
|
|
|
@@ -221,12 +434,14 @@ static int nl_init(nl_handle_t *h)
|
|
|
fprintf(stderr, "Failed to allocate netlink message\n");
|
|
|
goto fail;
|
|
|
}
|
|
|
+ h->nl_id = genl_ctrl_resolve(h->sock, "nl80211");
|
|
|
+
|
|
|
return 0;
|
|
|
|
|
|
fail:
|
|
|
return -1;
|
|
|
}
|
|
|
-static int nl_free(nl_handle_t *h)
|
|
|
+static int nl80211_free(nl_handle_t *h)
|
|
|
{
|
|
|
if(h->cb) nl_cb_put(h->cb);
|
|
|
if(h->msg) nlmsg_free(h->msg);
|
|
|
@@ -234,12 +449,13 @@ static int nl_free(nl_handle_t *h)
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
-static int nl_scan(ap_res_t *res)
|
|
|
+
|
|
|
+static int nl_scan(result_t *res)
|
|
|
{
|
|
|
int r;
|
|
|
nl_handle_t nl,*h;
|
|
|
|
|
|
- r = nl_init(&nl);
|
|
|
+ r = nl80211_init(&nl);
|
|
|
if(r) {
|
|
|
return -1;
|
|
|
}
|
|
|
@@ -249,63 +465,61 @@ static int nl_scan(ap_res_t *res)
|
|
|
res->list.max = 0;
|
|
|
res->list.info = (ap_info_t*)malloc(sizeof(ap_info_t)*ONCE_CNT);
|
|
|
if(!res->list.info) {
|
|
|
- nl_free(h);
|
|
|
+ nl80211_free(h);
|
|
|
return -1;
|
|
|
}
|
|
|
res->list.max = ONCE_CNT;
|
|
|
-
|
|
|
- nl_cb_set(h->cb, NL_CB_VALID, NL_CB_CUSTOM, nl_callback, NULL);
|
|
|
- genlmsg_put(h->msg, 0, 0, h->nl_id, 0, NLM_F_DUMP, NL80211_CMD_GET_SCAN, 0);
|
|
|
- nla_put_u32(h->msg, NL80211_ATTR_IFINDEX, if_nametoindex(WLAN_IFNAME)); // �滻Ϊ������߽ӿ�����
|
|
|
-
|
|
|
- // ������Ϣ
|
|
|
- if (nl_send_auto(h->sock, h->msg) < 0) {
|
|
|
- fprintf(stderr, "Failed to send message.\n");
|
|
|
- r = -1;
|
|
|
- }
|
|
|
- else {
|
|
|
- nl_recvmsgs(h->sock, h->cb);
|
|
|
+
|
|
|
+ r = scan_trigger(h);
|
|
|
+ if (r != 0) {
|
|
|
+ printf("scan_trigger() failed with %d.\n", r);
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
- nl_free(h);
|
|
|
+ genlmsg_put(h->msg, 0, 0, h->nl_id, 0, NLM_F_DUMP, NL80211_CMD_GET_SCAN, 0); // Setup which command to run.
|
|
|
+ nla_put_u32(h->msg, NL80211_ATTR_IFINDEX, h->ifindex); // Add message attribute, which interface to use.
|
|
|
+ nl_socket_modify_cb(h->sock, NL_CB_VALID, NL_CB_CUSTOM, callback_dump, res); // Add the callback.
|
|
|
+ r = nl_send_auto(h->sock, h->msg);
|
|
|
+ r = nl_recvmsgs_default(h->sock);
|
|
|
+ if (r < 0) {
|
|
|
+ printf("ERROR: nl_recvmsgs_default() returned %d (%s).\n", r, nl_geterror(-r));
|
|
|
+ }
|
|
|
+ nl80211_free(h);
|
|
|
|
|
|
return r;
|
|
|
}
|
|
|
-static int nl_conn(ap_info_t *info, char *password)
|
|
|
+static int nl_conn(ap_info_t *info)
|
|
|
{
|
|
|
int err,r=0;
|
|
|
nl_handle_t nl,*h;
|
|
|
|
|
|
- r = nl_init(&nl);
|
|
|
+ r = nl80211_init(&nl);
|
|
|
if(r) {
|
|
|
return r;
|
|
|
}
|
|
|
h = &nl;
|
|
|
|
|
|
- genlmsg_put(h->msg, 0, 0, h->nl_id, 0, 0, NL80211_CMD_CONNECT, 0);
|
|
|
+ genlmsg_put(h->msg, 0, 0, h->nl_id, 0, (NLM_F_REQUEST|NLM_F_ACK), NL80211_CMD_CONNECT, 0);
|
|
|
nla_put_u32(h->msg, NL80211_ATTR_IFINDEX, h->ifindex);
|
|
|
nla_put(h->msg, NL80211_ATTR_SSID, strlen(info->ssid), info->ssid);
|
|
|
|
|
|
- // ����ṩ�� BSSID��������
|
|
|
if (strlen(info->bssid)>0) {
|
|
|
nla_put(h->msg, NL80211_ATTR_MAC, 6, info->bssid);
|
|
|
}
|
|
|
|
|
|
- // ����ṩ�� PSK�����룩��������
|
|
|
- if (password) {
|
|
|
+ if (strlen(info->password)>0) {
|
|
|
struct nlattr *sae_data = nla_nest_start(h->msg, NL80211_ATTR_AUTH_DATA);
|
|
|
if (!sae_data) {
|
|
|
fprintf(stderr, "Failed to nest auth data\n");
|
|
|
r = -1;
|
|
|
}
|
|
|
nla_put(h->msg, NL80211_ATTR_AKM_SUITES, 2, "\x00\x0F"); // WPA2-PSK
|
|
|
- nla_put(h->msg, NL80211_ATTR_IE, strlen(password), password);
|
|
|
+ nla_put(h->msg, NL80211_ATTR_IE, strlen(info->password), info->password);
|
|
|
nla_nest_end(h->msg, sae_data);
|
|
|
}
|
|
|
|
|
|
- // ������Ϣ
|
|
|
- if (r==0 && nl_send_auto(h->sock, h->msg) < 0) {
|
|
|
- fprintf(stderr, "Failed to send connect request\n");
|
|
|
+ if (nl_send_auto_complete(h->sock, h->msg) < 0) {
|
|
|
+ fprintf(stderr, "nl_send_auto_complete failed\n");
|
|
|
r = -1;
|
|
|
}
|
|
|
|
|
|
@@ -313,7 +527,7 @@ static int nl_conn(ap_info_t *info, char *password)
|
|
|
fprintf(stderr, "Failed to receive ack: %s\n", nl_geterror(err));
|
|
|
r = -1;
|
|
|
}
|
|
|
- nl_free(h);
|
|
|
+ nl80211_free(h);
|
|
|
|
|
|
return r;
|
|
|
}
|
|
|
@@ -322,7 +536,7 @@ static int nl_disconn(void)
|
|
|
int err,r;
|
|
|
nl_handle_t nl,*h;
|
|
|
|
|
|
- r = nl_init(&nl);
|
|
|
+ r = nl80211_init(&nl);
|
|
|
if(r) {
|
|
|
return r;
|
|
|
}
|
|
|
@@ -342,167 +556,61 @@ static int nl_disconn(void)
|
|
|
fprintf(stderr, "Failed to receive ack: %s\n", nl_geterror(err));
|
|
|
r = -1;
|
|
|
}
|
|
|
- nl_free(h);
|
|
|
+ nl80211_free(h);
|
|
|
|
|
|
return r;
|
|
|
}
|
|
|
static int nl_set_link(int on)
|
|
|
{
|
|
|
- struct rtnl_link *link;
|
|
|
- struct nl_cache *cache;
|
|
|
- struct nl_sock *sock;
|
|
|
- int err,r=0;
|
|
|
-
|
|
|
-#if 0
|
|
|
- sock = nl_socket_alloc();
|
|
|
- if(!sock) {
|
|
|
- fprintf(stderr, "Failed to alloc sock.\n");
|
|
|
- r = -1;
|
|
|
- }
|
|
|
-
|
|
|
- // ���ӵ� netlink
|
|
|
- if ((err = nl_connect(sock, NETLINK_ROUTE)) < 0) {
|
|
|
- fprintf(stderr, "Failed to connect to netlink: %s\n", nl_geterror(err));
|
|
|
- r = -1;
|
|
|
- goto fail;
|
|
|
- }
|
|
|
-
|
|
|
- // ��ȡ��·����
|
|
|
- if ((err = rtnl_link_alloc_cache(sock, AF_UNSPEC, &cache)) < 0) {
|
|
|
- fprintf(stderr, "Failed to allocate link cache: %s\n", nl_geterror(err));
|
|
|
- r = -1;
|
|
|
- goto fail;
|
|
|
- }
|
|
|
-
|
|
|
- link = rtnl_link_get_by_name(cache, WLAN_IFNAME);
|
|
|
- if (!link) {
|
|
|
- fprintf(stderr, "Failed to find link: %s\n", WLAN_IFNAME);
|
|
|
- r = -1;
|
|
|
- goto fail;
|
|
|
- }
|
|
|
-
|
|
|
- if(r==0) {
|
|
|
- rtnl_link_set_flags(link, on ? IFF_UP : 0, IFF_UP);
|
|
|
- if ((err=rtnl_link_change(sock, link, link, 0)) < 0) {
|
|
|
- fprintf(stderr, "Failed to change link state: %s\n", nl_geterror(err));
|
|
|
- r = -1;
|
|
|
+ int r,fd;
|
|
|
+ struct ifreq ifr;
|
|
|
+
|
|
|
+ fd = socket(AF_INET, SOCK_DGRAM, 0);
|
|
|
+ if (fd>=0) {
|
|
|
+ strcpy(ifr.ifr_name, WLAN_IFNAME);
|
|
|
+ r = ioctl(fd, SIOCGIFFLAGS, &ifr);
|
|
|
+ if(r>=0) {
|
|
|
+ if(on) {
|
|
|
+ ifr.ifr_flags |= IFF_UP;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ ifr.ifr_flags &= ~IFF_UP;
|
|
|
+ }
|
|
|
+ r = ioctl(fd, SIOCSIFFLAGS, &ifr);
|
|
|
}
|
|
|
+ close(fd);
|
|
|
+ r = (r>=0)?0:-1;
|
|
|
}
|
|
|
|
|
|
-fail:
|
|
|
- // �ͷ���Դ
|
|
|
- if(link) {
|
|
|
- rtnl_link_put(link);
|
|
|
- nl_close(sock);
|
|
|
- }
|
|
|
- if(cache) nl_cache_free(cache);
|
|
|
- if(sock) nl_socket_free(sock);
|
|
|
-#endif
|
|
|
-
|
|
|
- return r;
|
|
|
-}
|
|
|
-static int nl_set_mode(int mode)
|
|
|
-{
|
|
|
- int nl_mode=(mode==MODE_AP)?NL80211_IFTYPE_AP:NL80211_IFTYPE_STATION;
|
|
|
- nl_handle_t nl,*h;
|
|
|
- int err,r=0;
|
|
|
-
|
|
|
- r = nl_init(&nl);
|
|
|
- if(r) {
|
|
|
- return -1;
|
|
|
- }
|
|
|
- h = &nl;
|
|
|
-
|
|
|
- // ��������ģʽ����
|
|
|
- genlmsg_put(h->msg, 0, 0, h->nl_id, 0, 0, NL80211_CMD_SET_INTERFACE, 0);
|
|
|
- nla_put_u32(h->msg, NL80211_ATTR_IFINDEX, h->ifindex);
|
|
|
- nla_put_u32(h->msg, NL80211_ATTR_IFTYPE, nl_mode);
|
|
|
-
|
|
|
- // ������Ϣ
|
|
|
- if (nl_send_auto(h->sock, h->msg) < 0) {
|
|
|
- fprintf(stderr, "Failed to send set mode request\n");
|
|
|
- r = -1;
|
|
|
- }
|
|
|
-
|
|
|
- if (r==0 && (err=nl_wait_for_ack(h->sock)) < 0) {
|
|
|
- fprintf(stderr, "Failed to receive ack: %s\n", nl_geterror(err));
|
|
|
- r = -1;
|
|
|
- }
|
|
|
- nl_free(h);
|
|
|
-
|
|
|
return r;
|
|
|
}
|
|
|
-static int nl_set_ap(const char *ssid, const char *password)
|
|
|
-{
|
|
|
- nl_handle_t nl,*h;
|
|
|
- int err,r;
|
|
|
-
|
|
|
- r = nl_init(&nl);
|
|
|
- if(r) {
|
|
|
- return -1;
|
|
|
- }
|
|
|
- h = &nl;
|
|
|
-
|
|
|
- // ������Ϣ
|
|
|
- genlmsg_put(h->msg, 0, 0, genl_ctrl_resolve(h->sock, "nl80211"), 0, 0, NL80211_CMD_NEW_INTERFACE, 0);
|
|
|
-
|
|
|
- // ���ýӿ�����
|
|
|
- nla_put_u32(h->msg, NL80211_ATTR_IFINDEX, h->ifindex);
|
|
|
-
|
|
|
- // ���� SSID
|
|
|
- nla_put(h->msg, NL80211_ATTR_SSID, strlen(ssid), ssid);
|
|
|
-
|
|
|
- // �������루WPA2-PSK��
|
|
|
- if (password) {
|
|
|
- nla_put_u32(h->msg, NL80211_ATTR_KEY_TYPE, NL80211_KEYTYPE_PAIRWISE);
|
|
|
- nla_put(h->msg, NL80211_ATTR_KEY_DATA, strlen(password), password);
|
|
|
- nla_put_u8(h->msg, NL80211_ATTR_KEY_IDX, 0);
|
|
|
- nla_put_u32(h->msg, NL80211_ATTR_KEY_CIPHER, 0x000FAC04); // WPA2 cipher suite
|
|
|
- }
|
|
|
-
|
|
|
- if ((err=nl_send_auto(h->sock, h->msg)) < 0) {
|
|
|
- fprintf(stderr, "Failed to send netlink message: %s\n", nl_geterror(err));
|
|
|
- r = -1;
|
|
|
- }
|
|
|
- nl_free(h);
|
|
|
-
|
|
|
- return r;
|
|
|
-}
|
|
|
-static void res_free(ap_res_t *res)
|
|
|
-{
|
|
|
- if(res) {
|
|
|
- if(res->list.info) {
|
|
|
- free(res->list.info);
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
#endif
|
|
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
-
|
|
|
int wifi_init(void)
|
|
|
{
|
|
|
- int r;
|
|
|
+ int r=-1;
|
|
|
+ WIFIManager *wm=&_globalWIFIManager;
|
|
|
wifi_handle_t *h=&wfHandle;
|
|
|
-
|
|
|
+
|
|
|
+ *wm = __globalDeviceManage._globalDevInfo.wifi;
|
|
|
#ifdef USE_WIFI
|
|
|
- r = nl_set_link(1);
|
|
|
- nl_set_mode(MODE_STA);
|
|
|
+ {
|
|
|
+ r = wifi_set(wm);
|
|
|
+ }
|
|
|
#endif
|
|
|
|
|
|
return r;
|
|
|
}
|
|
|
|
|
|
|
|
|
-
|
|
|
-int wifi_sta_scan(ap_list_t *list)
|
|
|
+int wifi_scan(ap_list_t *list)
|
|
|
{
|
|
|
int r=-1;
|
|
|
- ap_res_t res;
|
|
|
+ result_t res;
|
|
|
wifi_handle_t *h=&wfHandle;
|
|
|
|
|
|
#ifdef USE_WIFI
|
|
|
- res.ssid = NULL;
|
|
|
r = nl_scan(&res);
|
|
|
if(r==0) {
|
|
|
if(list) {
|
|
|
@@ -515,55 +623,52 @@ int wifi_sta_scan(ap_list_t *list)
|
|
|
}
|
|
|
|
|
|
|
|
|
-int wifi_sta_scan_ssid(char *ssid, ap_info_t *info)
|
|
|
-{
|
|
|
- int r=-1;
|
|
|
- ap_res_t res;
|
|
|
- wifi_handle_t *h=&wfHandle;
|
|
|
-
|
|
|
-#ifdef USE_WIFI
|
|
|
- res.ssid = ssid;
|
|
|
- r = nl_scan(&res);
|
|
|
- if(r==0) {
|
|
|
- if(info && res.list.cnt==1) {
|
|
|
- *info = res.list.info[0];
|
|
|
- }
|
|
|
- res_free(&res);
|
|
|
- }
|
|
|
-#endif
|
|
|
-
|
|
|
- return r;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-int wifi_sta_conn(ap_info_t *info, char *password)
|
|
|
+int wifi_set(WIFIManager *wm)
|
|
|
{
|
|
|
int r;
|
|
|
+ ap_info_t info;
|
|
|
wifi_handle_t *h=&wfHandle;
|
|
|
|
|
|
#ifdef USE_WIFI
|
|
|
- r = nl_conn(info, password);
|
|
|
+ r = nl_set_link(wm->mode);
|
|
|
+ if(wm->mode) {
|
|
|
+ memset(&info, 0, sizeof(info));
|
|
|
+
|
|
|
+ #if 0
|
|
|
+ strcpy(info.ssid, wm->WIFI_name);
|
|
|
+ strcpy(info.password, wm->WIFI_code);
|
|
|
+ //strcpy(info.ipaddr, wm->WIFI_ip);
|
|
|
+ #else
|
|
|
+ strcpy(info.ssid, "ChinaNet-Gowone");
|
|
|
+ strcpy(info.password, "gowone520");
|
|
|
+ //strcpy(info.ipaddr, "");
|
|
|
+ #endif
|
|
|
+ r = sta_start(&info, 1);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ sta_start(&info, 0);
|
|
|
+ }
|
|
|
#endif
|
|
|
|
|
|
return r;
|
|
|
}
|
|
|
|
|
|
|
|
|
-int wifi_sta_disconn(void)
|
|
|
+
|
|
|
+int wifi_sta_info(ap_info_t *info)
|
|
|
{
|
|
|
int r=-1;
|
|
|
wifi_handle_t *h=&wfHandle;
|
|
|
-
|
|
|
+
|
|
|
#ifdef USE_WIFI
|
|
|
- r = nl_disconn();
|
|
|
-#endif
|
|
|
|
|
|
- return r;
|
|
|
+#endif
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
|
|
|
-
|
|
|
-int wifi_ap_set(char *ssid, char *password)
|
|
|
+int wifi_ap_info(ap_info_t *info)
|
|
|
{
|
|
|
int r=-1;
|
|
|
wifi_handle_t *h=&wfHandle;
|
|
|
@@ -576,4 +681,13 @@ int wifi_ap_set(char *ssid, char *password)
|
|
|
}
|
|
|
|
|
|
|
|
|
-
|
|
|
+int wifi_list_free(ap_list_t *list)
|
|
|
+{
|
|
|
+ if(!list || !list->info) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ free(list->info);
|
|
|
+ list->cnt = 0;
|
|
|
+ list->info = NULL;
|
|
|
+ return 0;
|
|
|
+}
|