wifi.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822
  1. #include <linux/netlink.h>
  2. #include <linux/rtnetlink.h>
  3. #include <linux/nl80211.h>
  4. #include <ifaddrs.h>
  5. #include <net/if.h>
  6. #include <unistd.h>
  7. #include <sys/ioctl.h>
  8. #include <asm/types.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <errno.h>
  13. #include "common.h"
  14. #include "lock.h"
  15. #include "sys.h"
  16. #include "wifi.h"
  17. #include "paras.h"
  18. #include "cfg.h"
  19. #include <netlink/msg.h>
  20. #include <netlink/attr.h>
  21. #include <netlink/netlink.h>
  22. #include <netlink/cache.h>
  23. #include <netlink/genl/genl.h>
  24. #include <netlink/genl/ctrl.h>
  25. #include <netlink/route/link.h>
  26. #include <netlink/route/addr.h>
  27. #define ONCE_CNT 20
  28. #define WLAN_IFNAME "wlan0"
  29. #define AP_CONF "/etc/hostapd.conf"
  30. #define STA_CONF "/etc/wpa_supplicant.conf"
  31. #define AP_IP "192.168.2.132"
  32. enum {
  33. EVT_ERR=0,
  34. EVT_ACK,
  35. EVT_FIN,
  36. };
  37. typedef struct {
  38. int evt;
  39. ap_list_t list;
  40. }result_t;
  41. typedef struct {
  42. int ifindex;
  43. char *ifname;
  44. int nl_id; //nl80211_id
  45. struct nl_cb *cb;
  46. struct nl_msg *msg;
  47. struct nl_sock *sock;
  48. }nl_handle_t;
  49. typedef struct {
  50. int flag;
  51. }wifi_handle_t;
  52. static wifi_handle_t wfHandle={0};
  53. const char *auth_str[AUTH_MAX]={
  54. "NONE",
  55. "ERR",
  56. "PSK",
  57. "EAP",
  58. };
  59. const char *crypt_str[CRYPT_MAX]={
  60. "NONE",
  61. "ERR",
  62. "WEP",
  63. "WPA",
  64. "WPA2",
  65. };
  66. static void res_print(result_t *res)
  67. {
  68. int i;
  69. ap_info_t *info;
  70. if(res && res->list.cnt>0) {
  71. for(i=0; i<res->list.cnt; i++) {
  72. info = &res->list.info[i];
  73. printf("___[%d].ssid: %s\n", i, info->ssid);
  74. printf("___[%d].bssid: %s\n", i, info->bssid);
  75. printf("___[%d].freq: %dMHz\n", i, info->freq);
  76. printf("___[%d].auth: %s\n", i, auth_str[info->auth]);
  77. printf("___[%d].crypt: %s\n", i, crypt_str[info->crypt]);
  78. printf("\n");
  79. }
  80. }
  81. }
  82. static void res_free(result_t *res)
  83. {
  84. if(res) {
  85. if(res->list.info) {
  86. free(res->list.info);
  87. }
  88. }
  89. }
  90. static int udhcpc_start(int on)
  91. {
  92. int r;
  93. char tmp[200],path[100];
  94. sprintf(path, "/var/run/udhcpc_%s.pid", WLAN_IFNAME);
  95. if(on) {
  96. sprintf(tmp, "udhcpc -R -b -t 1 -A 1 -i %s -p %s", WLAN_IFNAME, path);
  97. }
  98. else {
  99. sprintf(tmp, "kill $(cat %s)", path);
  100. }
  101. r = system(tmp);
  102. return r;
  103. }
  104. static int sta_start(ap_info_t *info, int on)
  105. {
  106. int r,ipv,mask=24;
  107. char tmp[400],txt[200];
  108. //https://www.cnblogs.com/lidabo/p/5076560.html
  109. if(on) {
  110. snprintf(txt, sizeof(txt), "ctrl_interface=/var/run/wpa_supplicant\n"
  111. "network={\n"
  112. "ssid=\"%s\"\n"
  113. "psk=\"%s\"\n"
  114. "}\n", info->ssid, info->password);
  115. sprintf(tmp, "echo '%s' > %s", txt, STA_CONF);
  116. r = system(tmp);
  117. r = system("killall wpa_supplicant");
  118. sprintf(tmp, "wpa_supplicant -B -i %s -c %s", WLAN_IFNAME, STA_CONF);
  119. r = system(tmp);
  120. r = udhcpc_start(1);
  121. }
  122. else {
  123. r = system("wpa_cli disconnect");
  124. r = system("killall wpa_supplicant");
  125. r = udhcpc_start(0);
  126. }
  127. return r;
  128. }
  129. static int ap_start(ap_info_t *info, int on)
  130. {
  131. int r,ipv,mask=24;
  132. char tmp[100];
  133. //https://blog.csdn.net/qq_40311939/article/details/139552431
  134. r = system("killall hostapd udhcpd");
  135. if(on) {
  136. sprintf(tmp, "hostapd -B %s", AP_CONF);
  137. r = system(tmp);
  138. ipv = sys_get_ip_ver(info->ipaddr);
  139. if(ipv==IP_V6) {
  140. mask = 64;
  141. }
  142. sprintf(tmp, "ip addr add %s/%d dev %s", info->ipaddr, mask, WLAN_IFNAME);
  143. r = system(tmp);
  144. sprintf(tmp, "udhcpd -i %s -SC /etc/udhcpd.conf", WLAN_IFNAME);
  145. r = system(tmp);
  146. }
  147. return r;
  148. }
  149. static void priv_parse(uint8_t *ie, size_t ie_len, ap_info_t *info)
  150. {
  151. uint8_t *pos = ie;
  152. info->auth = AUTH_NONE;
  153. info->crypt = CRYPT_NONE;
  154. while (pos + 1 < ie + ie_len) {
  155. uint8_t id = pos[0];
  156. uint8_t len = pos[1];
  157. if (pos + 2 + len > ie + ie_len) {
  158. info->auth = AUTH_ERR;
  159. info->crypt = CRYPT_ERR;
  160. break; // ���� IE
  161. }
  162. // ���� RSN (WPA2) IE
  163. if (id == 48) { // RSN IE ID
  164. uint16_t auth = *((uint16_t *)(pos + 12)); // RSN ��֤�׼�ƫ��
  165. info->crypt = CRYPT_WPA2;
  166. switch (auth) {
  167. case 0x0001:
  168. info->auth = AUTH_PSK;
  169. break;
  170. case 0x0002:
  171. info->auth = AUTH_EAP;
  172. break;
  173. default:
  174. info->auth = AUTH_ERR;
  175. break;
  176. }
  177. break;
  178. }
  179. else if (id == 221 && len >= 4 && pos[2] == 0x00 && pos[3] == 0x50 && pos[4] == 0xF2 && pos[5] == 0x01) {
  180. uint16_t auth = *((uint16_t *)(pos + 12)); // WPA ��֤�׼�ƫ��
  181. info->crypt = CRYPT_WPA;
  182. switch (auth) {
  183. case 0x0001:
  184. info->auth = AUTH_PSK;
  185. break;
  186. case 0x0002:
  187. info->auth = AUTH_EAP;
  188. break;
  189. default:
  190. info->auth = AUTH_ERR;
  191. break;
  192. }
  193. break;
  194. }
  195. else if (id == 1 && len >= 4 && (pos[2] & 0x10)) { // Privacy bit in Capability Info
  196. printf("Encryption: WEP\n");
  197. info->crypt = CRYPT_WEP;
  198. break;
  199. }
  200. pos += 2 + len;
  201. }
  202. }
  203. struct trigger_results {
  204. int done;
  205. int aborted;
  206. };
  207. static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
  208. {
  209. // Callback for errors.
  210. printf("error_handler, %d\n", err->error);
  211. int *ret = arg;
  212. *ret = err->error;
  213. return NL_STOP;
  214. }
  215. static int finish_handler(struct nl_msg *msg, void *arg)
  216. {
  217. // Callback for NL_CB_FINISH.
  218. int *ret = arg;
  219. *ret = 0;
  220. return NL_SKIP;
  221. }
  222. static int ack_handler(struct nl_msg *msg, void *arg)
  223. {
  224. // Callback for NL_CB_ACK.
  225. int *ret = arg;
  226. *ret = 0;
  227. return NL_STOP;
  228. }
  229. static int no_seq_check(struct nl_msg *msg, void *arg)
  230. {
  231. // Callback for NL_CB_SEQ_CHECK.
  232. return NL_OK;
  233. }
  234. static int callback_stat(struct nl_msg *msg, void *arg)
  235. {
  236. struct nlattr *tb[NL80211_ATTR_MAX + 1];
  237. struct nlattr *bss[NL80211_BSS_MAX + 1];
  238. struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
  239. struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
  240. struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
  241. [NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 }, // 信号强度
  242. [NL80211_STA_INFO_CONNECTED_TIME] = { .type = NLA_U32 }, // 连接时间
  243. };
  244. ap_stat_t *stat=(ap_stat_t*)arg;
  245. nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL);
  246. if (!tb[NL80211_ATTR_STA_INFO]) {
  247. fprintf(stderr, "sta stats missing!\n");
  248. return NL_SKIP;
  249. }
  250. stat->link = 1;
  251. if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX, tb[NL80211_ATTR_STA_INFO], stats_policy)) {
  252. fprintf(stderr, "failed to parse nested attributes!\n");
  253. return NL_SKIP;
  254. }
  255. if (sinfo[NL80211_STA_INFO_SIGNAL]) {
  256. stat->signal = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
  257. }
  258. printf("___________________PPPPP_______________________link: %d, signal: %d\n", stat->link, stat->signal);
  259. return NL_SKIP;
  260. }
  261. static int callback_trigger(struct nl_msg *msg, void *arg)
  262. {
  263. // Called by the kernel when the scan is done or has been aborted.
  264. struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
  265. struct trigger_results *results = arg;
  266. //printf("Got something.\n");
  267. //printf("%d\n", arg);
  268. //nl_msg_dump(msg, stdout);
  269. if (gnlh->cmd == NL80211_CMD_SCAN_ABORTED) {
  270. printf("Got NL80211_CMD_SCAN_ABORTED.\n");
  271. results->done = 1;
  272. results->aborted = 1;
  273. } else if (gnlh->cmd == NL80211_CMD_NEW_SCAN_RESULTS) {
  274. printf("Got NL80211_CMD_NEW_SCAN_RESULTS.\n");
  275. results->done = 1;
  276. results->aborted = 0;
  277. } // else probably an uninteresting multicast message.
  278. return NL_SKIP;
  279. }
  280. static int callback_dump(struct nl_msg *msg, void *arg)
  281. {
  282. // Called by the kernel with a dump of the successful scan's data. Called for each SSID.
  283. struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
  284. struct nlattr *tb[NL80211_ATTR_MAX + 1];
  285. struct nlattr *bss[NL80211_BSS_MAX + 1];
  286. static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {
  287. [NL80211_BSS_TSF] = { .type = NLA_U64 },
  288. [NL80211_BSS_FREQUENCY] = { .type = NLA_U32 },
  289. [NL80211_BSS_BSSID] = { },
  290. [NL80211_BSS_BEACON_INTERVAL] = { .type = NLA_U16 },
  291. [NL80211_BSS_CAPABILITY] = { .type = NLA_U16 },
  292. [NL80211_BSS_INFORMATION_ELEMENTS] = { },
  293. [NL80211_BSS_SIGNAL_MBM] = { .type = NLA_U32 },
  294. [NL80211_BSS_SIGNAL_UNSPEC] = { .type = NLA_U8 },
  295. [NL80211_BSS_STATUS] = { .type = NLA_U32 },
  296. [NL80211_BSS_SEEN_MS_AGO] = { .type = NLA_U32 },
  297. [NL80211_BSS_BEACON_IES] = { },
  298. };
  299. result_t *res=(result_t*)arg;
  300. ap_info_t *info=&res->list.info[res->list.cnt];
  301. // Parse and error check.
  302. nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL);
  303. if (!tb[NL80211_ATTR_BSS]) {
  304. printf("bss info missing!\n");
  305. return NL_SKIP;
  306. }
  307. if (nla_parse_nested(bss, NL80211_BSS_MAX, tb[NL80211_ATTR_BSS], bss_policy)) {
  308. printf("failed to parse nested attributes!\n");
  309. return NL_SKIP;
  310. }
  311. if (bss[NL80211_BSS_BSSID]) {
  312. uint8_t *bssid = nla_data(bss[NL80211_BSS_BSSID]);
  313. sprintf(info->bssid, "%02x:%02x:%02x:%02x:%02x:%02x", bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);
  314. }
  315. if (bss[NL80211_BSS_FREQUENCY]) {
  316. uint32_t freq = nla_get_u32(bss[NL80211_BSS_FREQUENCY]);
  317. info->freq = freq;
  318. }
  319. if (bss[NL80211_BSS_INFORMATION_ELEMENTS]) {
  320. uint8_t *ies = nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
  321. int ies_len = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
  322. priv_parse(ies, nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]), info);
  323. // ���� SSID����ϢԪ�� ID Ϊ 0��
  324. int offset = 0;
  325. while (offset < ies_len) {
  326. uint8_t ie_id = ies[offset];
  327. uint8_t ie_len = ies[offset + 1];
  328. if (ie_id == 0 && ie_len > 0 && ie_len <= 32) { // SSID �� ID Ϊ 0
  329. memcpy(info->ssid, &ies[offset + 2], ie_len);
  330. info->ssid[ie_len] = 0;
  331. break;
  332. }
  333. offset += ie_len + 2;
  334. }
  335. }
  336. res->list.cnt++;
  337. if(res->list.cnt>=res->list.max) {
  338. int max = res->list.max+ONCE_CNT;
  339. res->list.info = (ap_info_t*)realloc(res->list.info, sizeof(ap_info_t)*max);
  340. if(res->list.info) {
  341. res->list.max = max;
  342. }
  343. else {
  344. fprintf(stderr, "res->info realloc failed\n");
  345. return NL_STOP;
  346. }
  347. }
  348. return NL_SKIP;
  349. }
  350. static int scan_trigger(nl_handle_t *h)
  351. {
  352. // Starts the scan and waits for it to finish. Does not return until the scan is done or has been aborted.
  353. struct trigger_results results = { .done = 0, .aborted = 0 };
  354. struct nl_msg *ssids_to_scan;
  355. int err,ret;
  356. int mcid = genl_ctrl_resolve_grp(h->sock, "nl80211", "scan");
  357. nl_socket_add_membership(h->sock, mcid); // Without this, callback_trigger() won't be called.
  358. // Allocate the messages and callback handler.
  359. ssids_to_scan = nlmsg_alloc();
  360. if (!ssids_to_scan) {
  361. printf("ERROR: Failed to allocate netlink message for ssids_to_scan.\n");
  362. return -ENOMEM;
  363. }
  364. // Setup the messages and callback handler.
  365. genlmsg_put(h->msg, 0, 0, h->nl_id, 0, 0, NL80211_CMD_TRIGGER_SCAN, 0); // Setup which command to run.
  366. nla_put_u32(h->msg, NL80211_ATTR_IFINDEX, h->ifindex); // Add message attribute, which interface to use.
  367. nla_put(ssids_to_scan, 1, 0, ""); // Scan all SSIDs.
  368. nla_put_nested(h->msg, NL80211_ATTR_SCAN_SSIDS, ssids_to_scan); // Add message attribute, which SSIDs to scan for.
  369. nlmsg_free(ssids_to_scan); // Copied to `msg` above, no longer need this.
  370. nl_cb_set(h->cb, NL_CB_VALID, NL_CB_CUSTOM, callback_trigger, &results); // Add the callback.
  371. nl_cb_err(h->cb, NL_CB_CUSTOM, error_handler, &err);
  372. nl_cb_set(h->cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err);
  373. nl_cb_set(h->cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);
  374. nl_cb_set(h->cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL); // No sequence checking for multicast messages.
  375. // Send NL80211_CMD_TRIGGER_SCAN to start the scan. The kernel may reply with NL80211_CMD_NEW_SCAN_RESULTS on
  376. // success or NL80211_CMD_SCAN_ABORTED if another scan was started by another process.
  377. err = 1;
  378. ret = nl_send_auto(h->sock, h->msg); // Send the message.
  379. printf("NL80211_CMD_TRIGGER_SCAN sent %d bytes to the kernel.\n", ret);
  380. printf("Waiting for scan to complete...\n");
  381. while (err > 0) ret = nl_recvmsgs(h->sock, h->cb); // First wait for ack_handler(). This helps with basic errors.
  382. if (err < 0) {
  383. printf("WARNING: err has a value of %d.\n", err);
  384. }
  385. if (ret < 0) {
  386. printf("ERROR: nl_recvmsgs() returned %d (%s).\n", ret, nl_geterror(-ret));
  387. return ret;
  388. }
  389. while (!results.done) nl_recvmsgs(h->sock, h->cb); // Now wait until the scan is done or aborted.
  390. if (results.aborted) {
  391. printf("ERROR: Kernel aborted scan.\n");
  392. return 1;
  393. }
  394. printf("Scan is done.\n");
  395. // Cleanup.
  396. nl_socket_drop_membership(h->sock, mcid); // No longer need this.
  397. return 0;
  398. }
  399. static int nl80211_init(nl_handle_t *h, int dbg)
  400. {
  401. h->ifname = WLAN_IFNAME;
  402. h->ifindex = if_nametoindex(h->ifname);
  403. if (!h->ifindex) {
  404. fprintf(stderr, "Failed to get interface index\n");
  405. return -1;
  406. }
  407. h->cb = nl_cb_alloc(dbg?NL_CB_DEBUG:NL_CB_DEFAULT);
  408. if (!h->cb) {
  409. fprintf(stderr, "Failed to allocate netlink callback.\n");
  410. goto fail;
  411. }
  412. h->msg = nlmsg_alloc();
  413. if (!h->msg) {
  414. fprintf(stderr, "Failed to allocate netlink message\n");
  415. goto fail;
  416. }
  417. h->sock = nl_socket_alloc();
  418. if (!h->sock) {
  419. fprintf(stderr, "Failed to allocate socket\n");
  420. goto fail;
  421. }
  422. nl_socket_set_buffer_size(h->sock, 8192, 8192);
  423. if (genl_connect(h->sock)) {
  424. fprintf(stderr, "Failed to connect to generic netlink.\n");
  425. goto fail;
  426. }
  427. h->nl_id = genl_ctrl_resolve(h->sock, "nl80211");
  428. return 0;
  429. fail:
  430. return -1;
  431. }
  432. static int nl80211_free(nl_handle_t *h)
  433. {
  434. if(h->cb) nl_cb_put(h->cb);
  435. if(h->msg) nlmsg_free(h->msg);
  436. if(h->sock) {
  437. nl_close(h->sock);
  438. nl_socket_free(h->sock);
  439. }
  440. return 0;
  441. }
  442. static int get_ipaddr(char *ifname, int family, char *ipaddr)
  443. {
  444. int r=-1;
  445. struct ifaddrs *ifap, *ifa;
  446. if (getifaddrs(&ifap) == -1) {
  447. printf("___getifaddrs() error\n");
  448. return -1;
  449. }
  450. for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
  451. if (ifa->ifa_addr != NULL && strcmp(ifa->ifa_name, ifname)==0 && ifa->ifa_addr->sa_family==family) {
  452. if(family==AF_INET) {
  453. struct sockaddr_in *sa,*msk;
  454. sa = (struct sockaddr_in *) ifa->ifa_addr;
  455. msk = (struct sockaddr_in *) ifa->ifa_netmask;
  456. char *p = (char*)inet_ntop(ifa->ifa_addr->sa_family, &sa->sin_addr, ipaddr, INET6_ADDRSTRLEN);
  457. if(p) r = 0;
  458. if(r==0) break;
  459. }
  460. else {
  461. struct sockaddr_in6 *sa,*msk;
  462. sa = (struct sockaddr_in6 *) ifa->ifa_addr;
  463. msk = (struct sockaddr_in6 *) ifa->ifa_netmask;
  464. char *p = (char*)inet_ntop(ifa->ifa_addr->sa_family, &sa->sin6_addr, ipaddr, INET6_ADDRSTRLEN);
  465. if(p) r = 0;
  466. if(r==0) break;
  467. }
  468. }
  469. }
  470. freeifaddrs(ifap);
  471. return r;
  472. }
  473. static int nl_get_ip(ap_stat_t *stat)
  474. {
  475. int r;
  476. stat->ipaddr[0] = 0;
  477. r = get_ipaddr(WLAN_IFNAME, AF_INET, stat->ipaddr);
  478. return r;
  479. }
  480. static int nl_get_signal(ap_stat_t *stat)
  481. {
  482. int r,err=1;
  483. nl_handle_t nl,*h;
  484. //https://github.com/Alamot/code-snippets/blob/master/nl80211_info/nl80211_info.c
  485. r = nl80211_init(&nl, 0);
  486. if(r) {
  487. return -1;
  488. }
  489. h = &nl;
  490. stat->link = stat->signal = 0;
  491. nl_cb_err(h->cb, NL_CB_CUSTOM, error_handler, &err);
  492. nl_cb_set(h->cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err);
  493. nl_cb_set(h->cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);
  494. r = nl_cb_set(h->cb, NL_CB_VALID, NL_CB_CUSTOM, callback_stat, stat);
  495. genlmsg_put(h->msg, NL_AUTO_PORT, NL_AUTO_SEQ, h->nl_id, 0, NLM_F_DUMP, NL80211_CMD_GET_STATION, 0); // Setup which command to run.
  496. nla_put_u32(h->msg, NL80211_ATTR_IFINDEX, h->ifindex); // Add message attribute, which interface to use.
  497. r = nl_send_auto(h->sock, h->msg);
  498. if(r<0) {
  499. nl80211_free(h);
  500. return -1;
  501. }
  502. r = 0;
  503. while(err>0) nl_recvmsgs(h->sock, h->cb);
  504. nl80211_free(h);
  505. return r;
  506. }
  507. static int nl_scan(result_t *res)
  508. {
  509. int r;
  510. nl_handle_t nl,*h;
  511. r = nl80211_init(&nl, 0);
  512. if(r) {
  513. return -1;
  514. }
  515. h = &nl;
  516. res->list.cnt = 0;
  517. res->list.max = 0;
  518. res->list.info = (ap_info_t*)malloc(sizeof(ap_info_t)*ONCE_CNT);
  519. if(!res->list.info) {
  520. nl80211_free(h);
  521. return -1;
  522. }
  523. res->list.max = ONCE_CNT;
  524. r = scan_trigger(h);
  525. if (r != 0) {
  526. printf("scan_trigger() failed with %d.\n", r);
  527. return -1;
  528. }
  529. genlmsg_put(h->msg, 0, 0, h->nl_id, 0, NLM_F_DUMP, NL80211_CMD_GET_SCAN, 0); // Setup which command to run.
  530. nla_put_u32(h->msg, NL80211_ATTR_IFINDEX, h->ifindex); // Add message attribute, which interface to use.
  531. nl_socket_modify_cb(h->sock, NL_CB_VALID, NL_CB_CUSTOM, callback_dump, res); // Add the callback.
  532. r = nl_send_auto(h->sock, h->msg);
  533. r = nl_recvmsgs_default(h->sock);
  534. if (r < 0) {
  535. printf("ERROR: nl_recvmsgs_default() returned %d (%s).\n", r, nl_geterror(-r));
  536. }
  537. nl80211_free(h);
  538. return r;
  539. }
  540. static int nl_conn(ap_info_t *info)
  541. {
  542. int err,r=0;
  543. nl_handle_t nl,*h;
  544. r = nl80211_init(&nl, 0);
  545. if(r) {
  546. return r;
  547. }
  548. h = &nl;
  549. genlmsg_put(h->msg, 0, 0, h->nl_id, 0, (NLM_F_REQUEST|NLM_F_ACK), NL80211_CMD_CONNECT, 0);
  550. nla_put_u32(h->msg, NL80211_ATTR_IFINDEX, h->ifindex);
  551. nla_put(h->msg, NL80211_ATTR_SSID, strlen(info->ssid), info->ssid);
  552. if (strlen(info->bssid)>0) {
  553. nla_put(h->msg, NL80211_ATTR_MAC, 6, info->bssid);
  554. }
  555. if (strlen(info->password)>0) {
  556. struct nlattr *sae_data = nla_nest_start(h->msg, NL80211_ATTR_AUTH_DATA);
  557. if (!sae_data) {
  558. fprintf(stderr, "Failed to nest auth data\n");
  559. r = -1;
  560. }
  561. nla_put(h->msg, NL80211_ATTR_AKM_SUITES, 2, "\x00\x0F"); // WPA2-PSK
  562. nla_put(h->msg, NL80211_ATTR_IE, strlen(info->password), info->password);
  563. nla_nest_end(h->msg, sae_data);
  564. }
  565. if (nl_send_auto_complete(h->sock, h->msg) < 0) {
  566. fprintf(stderr, "nl_send_auto_complete failed\n");
  567. r = -1;
  568. }
  569. if (r==0 && (err=nl_wait_for_ack(h->sock))<0) {
  570. fprintf(stderr, "Failed to receive ack: %s\n", nl_geterror(err));
  571. r = -1;
  572. }
  573. nl80211_free(h);
  574. return r;
  575. }
  576. static int nl_disconn(void)
  577. {
  578. int err,r;
  579. nl_handle_t nl,*h;
  580. r = nl80211_init(&nl, 0);
  581. if(r) {
  582. return r;
  583. }
  584. h = &nl;
  585. genlmsg_put(h->msg, 0, 0, h->nl_id, 0, 0, NL80211_CMD_DISCONNECT, 0);
  586. nla_put_u32(h->msg, NL80211_ATTR_IFINDEX, h->ifindex);
  587. // ������Ϣ
  588. if (nl_send_auto(h->sock, h->msg) < 0) {
  589. fprintf(stderr, "Failed to send disconnect request\n");
  590. r = -1;
  591. }
  592. // �ȴ���Ӧ
  593. if (r==0 && (err=nl_wait_for_ack(h->sock)) < 0) {
  594. fprintf(stderr, "Failed to receive ack: %s\n", nl_geterror(err));
  595. r = -1;
  596. }
  597. nl80211_free(h);
  598. return r;
  599. }
  600. static int nl_link(int on)
  601. {
  602. int r,fd;
  603. struct ifreq ifr;
  604. fd = socket(AF_INET, SOCK_DGRAM, 0);
  605. if (fd>=0) {
  606. strcpy(ifr.ifr_name, WLAN_IFNAME);
  607. r = ioctl(fd, SIOCGIFFLAGS, &ifr);
  608. if(r>=0) {
  609. if(on) {
  610. ifr.ifr_flags |= IFF_UP;
  611. }
  612. else {
  613. ifr.ifr_flags &= ~IFF_UP;
  614. }
  615. r = ioctl(fd, SIOCSIFFLAGS, &ifr);
  616. }
  617. close(fd);
  618. r = (r>=0)?0:-1;
  619. }
  620. return r;
  621. }
  622. ////////////////////////////////////////////////////////////////
  623. int wifi_init(void)
  624. {
  625. int r=-1;
  626. WIFIInfo_t *wm=&__globalDeviceManage._globalDevInfo.wifi;
  627. wifi_handle_t *h=&wfHandle;
  628. system("insmod /lib/modules/5.4.61/cfg80211.ko");
  629. system("insmod /lib/modules/5.4.61/lib80211.ko");
  630. r = wifi_set(wm);
  631. return r;
  632. }
  633. int wifi_scan(ap_list_t *list)
  634. {
  635. int r=-1;
  636. result_t res;
  637. wifi_handle_t *h=&wfHandle;
  638. r = nl_scan(&res);
  639. if(r==0) {
  640. if(list) {
  641. *list = res.list;
  642. }
  643. }
  644. return r;
  645. }
  646. int wifi_set(WIFIInfo_t *wm)
  647. {
  648. int r=-1;
  649. ap_info_t info;
  650. wifi_handle_t *h=&wfHandle;
  651. r = nl_link(wm->mode);
  652. if(wm->mode) {
  653. memset(&info, 0, sizeof(info));
  654. strcpy(info.ssid, wm->WIFI_name);
  655. strcpy(info.password, wm->WIFI_code);
  656. sta_start(&info, 0);
  657. r = sta_start(&info, 1);
  658. }
  659. else {
  660. sta_start(&info, 0);
  661. }
  662. return r;
  663. }
  664. int wifi_sta_info(ap_info_t *info)
  665. {
  666. int r=-1;
  667. wifi_handle_t *h=&wfHandle;
  668. return 0;
  669. }
  670. int wifi_sta_stat(ap_stat_t *stat)
  671. {
  672. int r=-1;
  673. wifi_handle_t *h=&wfHandle;
  674. if(!stat) {
  675. return -1;
  676. }
  677. nl_get_signal(stat);
  678. r = nl_get_ip(stat);
  679. if(r==0) {
  680. stat->link = 1; //不知道何原因导致获取信号强度的回调函数触发不了,暂时绕过
  681. }
  682. //printf("______ link: %d, signal: %d, ip: %s\n", stat->link, stat->signal, stat->ipaddr);
  683. return r;
  684. }
  685. int wifi_ap_info(ap_info_t *info)
  686. {
  687. int r=-1;
  688. wifi_handle_t *h=&wfHandle;
  689. return 0;
  690. }
  691. int wifi_list_free(ap_list_t *list)
  692. {
  693. if(!list || !list->info) {
  694. return -1;
  695. }
  696. free(list->info);
  697. list->cnt = 0;
  698. list->info = NULL;
  699. return 0;
  700. }