|
@@ -0,0 +1,579 @@
|
|
|
|
|
+#include <linux/netlink.h>
|
|
|
|
|
+#include <linux/rtnetlink.h>
|
|
|
|
|
+#include <netlink/netlink.h>
|
|
|
|
|
+#include <netlink/genl/genl.h>
|
|
|
|
|
+#include <netlink/genl/ctrl.h>
|
|
|
|
|
+#include <netlink/msg.h>
|
|
|
|
|
+#include <netlink/attr.h>
|
|
|
|
|
+#include <linux/nl80211.h>
|
|
|
|
|
+#include <net/if.h>
|
|
|
|
|
+#include <asm/types.h>
|
|
|
|
|
+#include <stdio.h>
|
|
|
|
|
+#include <stdlib.h>
|
|
|
|
|
+#include <string.h>
|
|
|
|
|
+#include <errno.h>
|
|
|
|
|
+#include "lock.h"
|
|
|
|
|
+#include "wifi.h"
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+#define ONCE_CNT 20
|
|
|
|
|
+#define WLAN_IFNAME "wlan0"
|
|
|
|
|
+
|
|
|
|
|
+typedef struct {
|
|
|
|
|
+ char *ssid;
|
|
|
|
|
+ ap_list_t list;
|
|
|
|
|
+}ap_res_t;
|
|
|
|
|
+typedef struct {
|
|
|
|
|
+ int ifindex;
|
|
|
|
|
+ char *ifname;
|
|
|
|
|
+ int nl_id; //nl80211_id
|
|
|
|
|
+ struct nl_cb *cb;
|
|
|
|
|
+ struct nl_msg *msg;
|
|
|
|
|
+ struct nl_sock *sock;
|
|
|
|
|
+}nl_handle_t;
|
|
|
|
|
+typedef struct {
|
|
|
|
|
+ int flag;
|
|
|
|
|
+}wifi_handle_t;
|
|
|
|
|
+static wifi_handle_t wfHandle={0};
|
|
|
|
|
+
|
|
|
|
|
+#ifdef USE_WIFI
|
|
|
|
|
+static void priv_parse(uint8_t *ie, size_t ie_len, ap_info_t *info)
|
|
|
|
|
+{
|
|
|
|
|
+ uint8_t *pos = ie;
|
|
|
|
|
+
|
|
|
|
|
+ info->auth = AUTH_NONE;
|
|
|
|
|
+ info->crypt = CRYPT_NONE;
|
|
|
|
|
+ while (pos + 1 < ie + ie_len) {
|
|
|
|
|
+ uint8_t id = pos[0];
|
|
|
|
|
+ uint8_t len = pos[1];
|
|
|
|
|
+
|
|
|
|
|
+ if (pos + 2 + len > ie + ie_len) {
|
|
|
|
|
+ info->auth = AUTH_WRONG;
|
|
|
|
|
+ info->crypt = CRYPT_WRONG;
|
|
|
|
|
+ break; // ���� IE
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ���� RSN (WPA2) IE
|
|
|
|
|
+ if (id == 48) { // RSN IE ID
|
|
|
|
|
+ uint16_t *auth_suites = (uint16_t *)(pos + 12); // RSN ��֤��ƫ��
|
|
|
|
|
+
|
|
|
|
|
+ printf("Encryption: WPA2\n");
|
|
|
|
|
+ info->crypt = CRYPT_WPA2;
|
|
|
|
|
+ switch (*auth_suites) {
|
|
|
|
|
+ case 0x0001:
|
|
|
|
|
+ info->auth = AUTH_PSK;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case 0x0002:
|
|
|
|
|
+ info->auth = AUTH_EAP;
|
|
|
|
|
+ break;
|
|
|
|
|
+ default:
|
|
|
|
|
+ info->auth = AUTH_WRONG;
|
|
|
|
|
+ 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 ��֤��ƫ��
|
|
|
|
|
+
|
|
|
|
|
+ printf("Encryption: WPA\n");
|
|
|
|
|
+ info->crypt = CRYPT_WPA;
|
|
|
|
|
+ switch (*auth_suites) {
|
|
|
|
|
+ case 0x0001:
|
|
|
|
|
+ info->auth = AUTH_PSK;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case 0x0002:
|
|
|
|
|
+ info->auth = AUTH_EAP;
|
|
|
|
|
+ break;
|
|
|
|
|
+ default:
|
|
|
|
|
+ info->auth = AUTH_WRONG;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ else if (id == 1 && len >= 4 && (pos[2] & 0x10)) { // Privacy bit in Capability Info
|
|
|
|
|
+ printf("Encryption: WEP\n");
|
|
|
|
|
+ info->crypt = CRYPT_WEP;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ pos += 2 + len;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+static int nl_callback(struct nl_msg *msg, void *arg)
|
|
|
|
|
+{
|
|
|
|
|
+ int flag=0;
|
|
|
|
|
+ struct nlattr *tb[NL80211_ATTR_MAX + 1];
|
|
|
|
|
+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
|
|
|
|
|
+ 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 },
|
|
|
|
|
+ [NL80211_BSS_FREQUENCY] = { .type = NLA_U32 },
|
|
|
|
|
+ [NL80211_BSS_SIGNAL_MBM] = { .type = NLA_U32 },
|
|
|
|
|
+ };
|
|
|
|
|
+ ap_res_t *res=(ap_res_t*)arg;
|
|
|
|
|
+ ap_info_t *info=&res->list.info[res->list.cnt];
|
|
|
|
|
+
|
|
|
|
|
+ if(res->ssid) {
|
|
|
|
|
+ info = &res->list.info[0];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ������Ϣ����
|
|
|
|
|
+ nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL);
|
|
|
|
|
+
|
|
|
|
|
+ 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_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; // �ƶ�����һ����ϢԪ��
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ 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;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if(flag) {
|
|
|
|
|
+ return NL_STOP;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return NL_SKIP;
|
|
|
|
|
+}
|
|
|
|
|
+static int nl_init(nl_handle_t *h)
|
|
|
|
|
+{
|
|
|
|
|
+ h->ifname = WLAN_IFNAME;
|
|
|
|
|
+ h->ifindex = if_nametoindex(h->ifname);
|
|
|
|
|
+ if (!h->ifindex) {
|
|
|
|
|
+ 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) {
|
|
|
|
|
+ fprintf(stderr, "Failed to allocate netlink callback.\n");
|
|
|
|
|
+ goto fail;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ h->sock = nl_socket_alloc();
|
|
|
|
|
+ if (!h->sock) {
|
|
|
|
|
+ fprintf(stderr, "Failed to allocate socket\n");
|
|
|
|
|
+ goto fail;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (genl_connect(h->sock)) {
|
|
|
|
|
+ fprintf(stderr, "Failed to connect to generic netlink.\n");
|
|
|
|
|
+ goto fail;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ h->msg = nlmsg_alloc();
|
|
|
|
|
+ if (!h->msg) {
|
|
|
|
|
+ fprintf(stderr, "Failed to allocate netlink message\n");
|
|
|
|
|
+ goto fail;
|
|
|
|
|
+ }
|
|
|
|
|
+ return 0;
|
|
|
|
|
+
|
|
|
|
|
+fail:
|
|
|
|
|
+ return -1;
|
|
|
|
|
+}
|
|
|
|
|
+static int nl_free(nl_handle_t *h)
|
|
|
|
|
+{
|
|
|
|
|
+ if(h->cb) nl_cb_put(h->cb);
|
|
|
|
|
+ if(h->msg) nlmsg_free(h->msg);
|
|
|
|
|
+ if(h->sock) nl_socket_free(h->sock);
|
|
|
|
|
+
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+static int nl_scan(ap_res_t *res)
|
|
|
|
|
+{
|
|
|
|
|
+ int r;
|
|
|
|
|
+ nl_handle_t nl,*h;
|
|
|
|
|
+
|
|
|
|
|
+ r = nl_init(&nl);
|
|
|
|
|
+ if(r) {
|
|
|
|
|
+ return -1;
|
|
|
|
|
+ }
|
|
|
|
|
+ h = &nl;
|
|
|
|
|
+
|
|
|
|
|
+ res->list.cnt = 0;
|
|
|
|
|
+ res->list.max = 0;
|
|
|
|
|
+ res->list.info = (ap_info_t*)malloc(sizeof(ap_info_t)*ONCE_CNT);
|
|
|
|
|
+ if(!res->list.info) {
|
|
|
|
|
+ nl_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);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ nl_free(h);
|
|
|
|
|
+
|
|
|
|
|
+ return r;
|
|
|
|
|
+}
|
|
|
|
|
+static int nl_conn(ap_info_t *info, char *password)
|
|
|
|
|
+{
|
|
|
|
|
+ int err,r=0;
|
|
|
|
|
+ nl_handle_t nl,*h;
|
|
|
|
|
+
|
|
|
|
|
+ r = nl_init(&nl);
|
|
|
|
|
+ if(r) {
|
|
|
|
|
+ return r;
|
|
|
|
|
+ }
|
|
|
|
|
+ h = &nl;
|
|
|
|
|
+
|
|
|
|
|
+ genlmsg_put(h->msg, 0, 0, h->nl_id, 0, 0, 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) {
|
|
|
|
|
+ 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_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");
|
|
|
|
|
+ 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_disconn(void)
|
|
|
|
|
+{
|
|
|
|
|
+ int err,r;
|
|
|
|
|
+ nl_handle_t nl,*h;
|
|
|
|
|
+
|
|
|
|
|
+ r = nl_init(&nl);
|
|
|
|
|
+ if(r) {
|
|
|
|
|
+ return r;
|
|
|
|
|
+ }
|
|
|
|
|
+ h = &nl;
|
|
|
|
|
+
|
|
|
|
|
+ genlmsg_put(h->msg, 0, 0, h->nl_id, 0, 0, NL80211_CMD_DISCONNECT, 0);
|
|
|
|
|
+ nla_put_u32(h->msg, NL80211_ATTR_IFINDEX, h->ifindex);
|
|
|
|
|
+
|
|
|
|
|
+ // ������Ϣ
|
|
|
|
|
+ if (nl_send_auto(h->sock, h->msg) < 0) {
|
|
|
|
|
+ fprintf(stderr, "Failed to send disconnect 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_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;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+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;
|
|
|
|
|
+ wifi_handle_t *h=&wfHandle;
|
|
|
|
|
+
|
|
|
|
|
+#ifdef USE_WIFI
|
|
|
|
|
+ r = nl_set_link(1);
|
|
|
|
|
+ nl_set_mode(MODE_STA);
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+ return r;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+int wifi_sta_scan(ap_list_t *list)
|
|
|
|
|
+{
|
|
|
|
|
+ int r=-1;
|
|
|
|
|
+ ap_res_t res;
|
|
|
|
|
+ wifi_handle_t *h=&wfHandle;
|
|
|
|
|
+
|
|
|
|
|
+#ifdef USE_WIFI
|
|
|
|
|
+ res.ssid = NULL;
|
|
|
|
|
+ r = nl_scan(&res);
|
|
|
|
|
+ if(r==0) {
|
|
|
|
|
+ if(list) {
|
|
|
|
|
+ *list = res.list;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+ return r;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+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 r;
|
|
|
|
|
+ wifi_handle_t *h=&wfHandle;
|
|
|
|
|
+
|
|
|
|
|
+#ifdef USE_WIFI
|
|
|
|
|
+ r = nl_conn(info, password);
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+ return r;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+int wifi_sta_disconn(void)
|
|
|
|
|
+{
|
|
|
|
|
+ int r=-1;
|
|
|
|
|
+ wifi_handle_t *h=&wfHandle;
|
|
|
|
|
+
|
|
|
|
|
+#ifdef USE_WIFI
|
|
|
|
|
+ r = nl_disconn();
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+ return r;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+int wifi_ap_set(char *ssid, char *password)
|
|
|
|
|
+{
|
|
|
|
|
+ int r=-1;
|
|
|
|
|
+ wifi_handle_t *h=&wfHandle;
|
|
|
|
|
+
|
|
|
|
|
+#ifdef USE_WIFI
|
|
|
|
|
+
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|