PageRenderTime 53ms CodeModel.GetById 11ms RepoModel.GetById 1ms app.codeStats 0ms

/external/bsd/wpa/dist/wpa_supplicant/ctrl_iface.c

https://github.com/rumpkernel/netbsd-userspace-src
C | 5545 lines | 5168 code | 340 blank | 37 comment | 599 complexity | c7e7c27cfa7ce7c8990a2ac8021d9fcc MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * WPA Supplicant / Control interface (shared code for all backends)
  3. * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
  4. *
  5. * This software may be distributed under the terms of the BSD license.
  6. * See README for more details.
  7. */
  8. #include "utils/includes.h"
  9. #include "utils/common.h"
  10. #include "utils/eloop.h"
  11. #include "common/version.h"
  12. #include "common/ieee802_11_defs.h"
  13. #include "common/ieee802_11_common.h"
  14. #include "common/wpa_ctrl.h"
  15. #include "eap_peer/eap.h"
  16. #include "eapol_supp/eapol_supp_sm.h"
  17. #include "rsn_supp/wpa.h"
  18. #include "rsn_supp/preauth.h"
  19. #include "rsn_supp/pmksa_cache.h"
  20. #include "l2_packet/l2_packet.h"
  21. #include "wps/wps.h"
  22. #include "config.h"
  23. #include "wpa_supplicant_i.h"
  24. #include "driver_i.h"
  25. #include "wps_supplicant.h"
  26. #include "ibss_rsn.h"
  27. #include "ap.h"
  28. #include "p2p_supplicant.h"
  29. #include "p2p/p2p.h"
  30. #include "hs20_supplicant.h"
  31. #include "wifi_display.h"
  32. #include "notify.h"
  33. #include "bss.h"
  34. #include "scan.h"
  35. #include "ctrl_iface.h"
  36. #include "interworking.h"
  37. #include "blacklist.h"
  38. #include "autoscan.h"
  39. #include "wnm_sta.h"
  40. extern struct wpa_driver_ops *wpa_drivers[];
  41. static int wpa_supplicant_global_iface_list(struct wpa_global *global,
  42. char *buf, int len);
  43. static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
  44. char *buf, int len);
  45. static int pno_start(struct wpa_supplicant *wpa_s)
  46. {
  47. int ret;
  48. size_t i, num_ssid;
  49. struct wpa_ssid *ssid;
  50. struct wpa_driver_scan_params params;
  51. if (wpa_s->pno)
  52. return 0;
  53. if (wpa_s->wpa_state == WPA_SCANNING) {
  54. wpa_supplicant_cancel_sched_scan(wpa_s);
  55. wpa_supplicant_cancel_scan(wpa_s);
  56. }
  57. os_memset(&params, 0, sizeof(params));
  58. num_ssid = 0;
  59. ssid = wpa_s->conf->ssid;
  60. while (ssid) {
  61. if (!wpas_network_disabled(wpa_s, ssid))
  62. num_ssid++;
  63. ssid = ssid->next;
  64. }
  65. if (num_ssid > WPAS_MAX_SCAN_SSIDS) {
  66. wpa_printf(MSG_DEBUG, "PNO: Use only the first %u SSIDs from "
  67. "%u", WPAS_MAX_SCAN_SSIDS, (unsigned int) num_ssid);
  68. num_ssid = WPAS_MAX_SCAN_SSIDS;
  69. }
  70. if (num_ssid == 0) {
  71. wpa_printf(MSG_DEBUG, "PNO: No configured SSIDs");
  72. return -1;
  73. }
  74. params.filter_ssids = os_malloc(sizeof(struct wpa_driver_scan_filter) *
  75. num_ssid);
  76. if (params.filter_ssids == NULL)
  77. return -1;
  78. i = 0;
  79. ssid = wpa_s->conf->ssid;
  80. while (ssid) {
  81. if (!wpas_network_disabled(wpa_s, ssid)) {
  82. params.ssids[i].ssid = ssid->ssid;
  83. params.ssids[i].ssid_len = ssid->ssid_len;
  84. params.num_ssids++;
  85. os_memcpy(params.filter_ssids[i].ssid, ssid->ssid,
  86. ssid->ssid_len);
  87. params.filter_ssids[i].ssid_len = ssid->ssid_len;
  88. params.num_filter_ssids++;
  89. i++;
  90. if (i == num_ssid)
  91. break;
  92. }
  93. ssid = ssid->next;
  94. }
  95. if (wpa_s->conf->filter_rssi)
  96. params.filter_rssi = wpa_s->conf->filter_rssi;
  97. ret = wpa_drv_sched_scan(wpa_s, &params, 10 * 1000);
  98. os_free(params.filter_ssids);
  99. if (ret == 0)
  100. wpa_s->pno = 1;
  101. return ret;
  102. }
  103. static int pno_stop(struct wpa_supplicant *wpa_s)
  104. {
  105. int ret = 0;
  106. if (wpa_s->pno) {
  107. wpa_s->pno = 0;
  108. ret = wpa_drv_stop_sched_scan(wpa_s);
  109. }
  110. if (wpa_s->wpa_state == WPA_SCANNING)
  111. wpa_supplicant_req_scan(wpa_s, 0, 0);
  112. return ret;
  113. }
  114. static int set_bssid_filter(struct wpa_supplicant *wpa_s, char *val)
  115. {
  116. char *pos;
  117. u8 addr[ETH_ALEN], *filter = NULL, *n;
  118. size_t count = 0;
  119. pos = val;
  120. while (pos) {
  121. if (*pos == '\0')
  122. break;
  123. if (hwaddr_aton(pos, addr)) {
  124. os_free(filter);
  125. return -1;
  126. }
  127. n = os_realloc_array(filter, count + 1, ETH_ALEN);
  128. if (n == NULL) {
  129. os_free(filter);
  130. return -1;
  131. }
  132. filter = n;
  133. os_memcpy(filter + count * ETH_ALEN, addr, ETH_ALEN);
  134. count++;
  135. pos = os_strchr(pos, ' ');
  136. if (pos)
  137. pos++;
  138. }
  139. wpa_hexdump(MSG_DEBUG, "bssid_filter", filter, count * ETH_ALEN);
  140. os_free(wpa_s->bssid_filter);
  141. wpa_s->bssid_filter = filter;
  142. wpa_s->bssid_filter_count = count;
  143. return 0;
  144. }
  145. static int set_disallow_aps(struct wpa_supplicant *wpa_s, char *val)
  146. {
  147. char *pos;
  148. u8 addr[ETH_ALEN], *bssid = NULL, *n;
  149. struct wpa_ssid_value *ssid = NULL, *ns;
  150. size_t count = 0, ssid_count = 0;
  151. struct wpa_ssid *c;
  152. /*
  153. * disallow_list ::= <ssid_spec> | <bssid_spec> | <disallow_list> | “”
  154. * SSID_SPEC ::= ssid <SSID_HEX>
  155. * BSSID_SPEC ::= bssid <BSSID_HEX>
  156. */
  157. pos = val;
  158. while (pos) {
  159. if (*pos == '\0')
  160. break;
  161. if (os_strncmp(pos, "bssid ", 6) == 0) {
  162. int res;
  163. pos += 6;
  164. res = hwaddr_aton2(pos, addr);
  165. if (res < 0) {
  166. os_free(ssid);
  167. os_free(bssid);
  168. wpa_printf(MSG_DEBUG, "Invalid disallow_aps "
  169. "BSSID value '%s'", pos);
  170. return -1;
  171. }
  172. pos += res;
  173. n = os_realloc_array(bssid, count + 1, ETH_ALEN);
  174. if (n == NULL) {
  175. os_free(ssid);
  176. os_free(bssid);
  177. return -1;
  178. }
  179. bssid = n;
  180. os_memcpy(bssid + count * ETH_ALEN, addr, ETH_ALEN);
  181. count++;
  182. } else if (os_strncmp(pos, "ssid ", 5) == 0) {
  183. char *end;
  184. pos += 5;
  185. end = pos;
  186. while (*end) {
  187. if (*end == '\0' || *end == ' ')
  188. break;
  189. end++;
  190. }
  191. ns = os_realloc_array(ssid, ssid_count + 1,
  192. sizeof(struct wpa_ssid_value));
  193. if (ns == NULL) {
  194. os_free(ssid);
  195. os_free(bssid);
  196. return -1;
  197. }
  198. ssid = ns;
  199. if ((end - pos) & 0x01 || end - pos > 2 * 32 ||
  200. hexstr2bin(pos, ssid[ssid_count].ssid,
  201. (end - pos) / 2) < 0) {
  202. os_free(ssid);
  203. os_free(bssid);
  204. wpa_printf(MSG_DEBUG, "Invalid disallow_aps "
  205. "SSID value '%s'", pos);
  206. return -1;
  207. }
  208. ssid[ssid_count].ssid_len = (end - pos) / 2;
  209. wpa_hexdump_ascii(MSG_DEBUG, "disallow_aps SSID",
  210. ssid[ssid_count].ssid,
  211. ssid[ssid_count].ssid_len);
  212. ssid_count++;
  213. pos = end;
  214. } else {
  215. wpa_printf(MSG_DEBUG, "Unexpected disallow_aps value "
  216. "'%s'", pos);
  217. os_free(ssid);
  218. os_free(bssid);
  219. return -1;
  220. }
  221. pos = os_strchr(pos, ' ');
  222. if (pos)
  223. pos++;
  224. }
  225. wpa_hexdump(MSG_DEBUG, "disallow_aps_bssid", bssid, count * ETH_ALEN);
  226. os_free(wpa_s->disallow_aps_bssid);
  227. wpa_s->disallow_aps_bssid = bssid;
  228. wpa_s->disallow_aps_bssid_count = count;
  229. wpa_printf(MSG_DEBUG, "disallow_aps_ssid_count %d", (int) ssid_count);
  230. os_free(wpa_s->disallow_aps_ssid);
  231. wpa_s->disallow_aps_ssid = ssid;
  232. wpa_s->disallow_aps_ssid_count = ssid_count;
  233. if (!wpa_s->current_ssid || wpa_s->wpa_state < WPA_AUTHENTICATING)
  234. return 0;
  235. c = wpa_s->current_ssid;
  236. if (c->mode != WPAS_MODE_INFRA && c->mode != WPAS_MODE_IBSS)
  237. return 0;
  238. if (!disallowed_bssid(wpa_s, wpa_s->bssid) &&
  239. !disallowed_ssid(wpa_s, c->ssid, c->ssid_len))
  240. return 0;
  241. wpa_printf(MSG_DEBUG, "Disconnect and try to find another network "
  242. "because current AP was marked disallowed");
  243. #ifdef CONFIG_SME
  244. wpa_s->sme.prev_bssid_set = 0;
  245. #endif /* CONFIG_SME */
  246. wpa_s->reassociate = 1;
  247. wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
  248. wpa_supplicant_req_scan(wpa_s, 0, 0);
  249. return 0;
  250. }
  251. static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
  252. char *cmd)
  253. {
  254. char *value;
  255. int ret = 0;
  256. value = os_strchr(cmd, ' ');
  257. if (value == NULL)
  258. return -1;
  259. *value++ = '\0';
  260. wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
  261. if (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) {
  262. eapol_sm_configure(wpa_s->eapol,
  263. atoi(value), -1, -1, -1);
  264. } else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) {
  265. eapol_sm_configure(wpa_s->eapol,
  266. -1, atoi(value), -1, -1);
  267. } else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) {
  268. eapol_sm_configure(wpa_s->eapol,
  269. -1, -1, atoi(value), -1);
  270. } else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) {
  271. eapol_sm_configure(wpa_s->eapol,
  272. -1, -1, -1, atoi(value));
  273. } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) {
  274. if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
  275. atoi(value)))
  276. ret = -1;
  277. } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") ==
  278. 0) {
  279. if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
  280. atoi(value)))
  281. ret = -1;
  282. } else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) {
  283. if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, atoi(value)))
  284. ret = -1;
  285. } else if (os_strcasecmp(cmd, "wps_fragment_size") == 0) {
  286. wpa_s->wps_fragment_size = atoi(value);
  287. #ifdef CONFIG_WPS_TESTING
  288. } else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
  289. long int val;
  290. val = strtol(value, NULL, 0);
  291. if (val < 0 || val > 0xff) {
  292. ret = -1;
  293. wpa_printf(MSG_DEBUG, "WPS: Invalid "
  294. "wps_version_number %ld", val);
  295. } else {
  296. wps_version_number = val;
  297. wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
  298. "version %u.%u",
  299. (wps_version_number & 0xf0) >> 4,
  300. wps_version_number & 0x0f);
  301. }
  302. } else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) {
  303. wps_testing_dummy_cred = atoi(value);
  304. wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d",
  305. wps_testing_dummy_cred);
  306. #endif /* CONFIG_WPS_TESTING */
  307. } else if (os_strcasecmp(cmd, "ampdu") == 0) {
  308. if (wpa_drv_ampdu(wpa_s, atoi(value)) < 0)
  309. ret = -1;
  310. #ifdef CONFIG_TDLS_TESTING
  311. } else if (os_strcasecmp(cmd, "tdls_testing") == 0) {
  312. extern unsigned int tdls_testing;
  313. tdls_testing = strtol(value, NULL, 0);
  314. wpa_printf(MSG_DEBUG, "TDLS: tdls_testing=0x%x", tdls_testing);
  315. #endif /* CONFIG_TDLS_TESTING */
  316. #ifdef CONFIG_TDLS
  317. } else if (os_strcasecmp(cmd, "tdls_disabled") == 0) {
  318. int disabled = atoi(value);
  319. wpa_printf(MSG_DEBUG, "TDLS: tdls_disabled=%d", disabled);
  320. if (disabled) {
  321. if (wpa_drv_tdls_oper(wpa_s, TDLS_DISABLE, NULL) < 0)
  322. ret = -1;
  323. } else if (wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL) < 0)
  324. ret = -1;
  325. wpa_tdls_enable(wpa_s->wpa, !disabled);
  326. #endif /* CONFIG_TDLS */
  327. } else if (os_strcasecmp(cmd, "pno") == 0) {
  328. if (atoi(value))
  329. ret = pno_start(wpa_s);
  330. else
  331. ret = pno_stop(wpa_s);
  332. } else if (os_strcasecmp(cmd, "radio_disabled") == 0) {
  333. int disabled = atoi(value);
  334. if (wpa_drv_radio_disable(wpa_s, disabled) < 0)
  335. ret = -1;
  336. else if (disabled)
  337. wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
  338. } else if (os_strcasecmp(cmd, "uapsd") == 0) {
  339. if (os_strcmp(value, "disable") == 0)
  340. wpa_s->set_sta_uapsd = 0;
  341. else {
  342. int be, bk, vi, vo;
  343. char *pos;
  344. /* format: BE,BK,VI,VO;max SP Length */
  345. be = atoi(value);
  346. pos = os_strchr(value, ',');
  347. if (pos == NULL)
  348. return -1;
  349. pos++;
  350. bk = atoi(pos);
  351. pos = os_strchr(pos, ',');
  352. if (pos == NULL)
  353. return -1;
  354. pos++;
  355. vi = atoi(pos);
  356. pos = os_strchr(pos, ',');
  357. if (pos == NULL)
  358. return -1;
  359. pos++;
  360. vo = atoi(pos);
  361. /* ignore max SP Length for now */
  362. wpa_s->set_sta_uapsd = 1;
  363. wpa_s->sta_uapsd = 0;
  364. if (be)
  365. wpa_s->sta_uapsd |= BIT(0);
  366. if (bk)
  367. wpa_s->sta_uapsd |= BIT(1);
  368. if (vi)
  369. wpa_s->sta_uapsd |= BIT(2);
  370. if (vo)
  371. wpa_s->sta_uapsd |= BIT(3);
  372. }
  373. } else if (os_strcasecmp(cmd, "ps") == 0) {
  374. ret = wpa_drv_set_p2p_powersave(wpa_s, atoi(value), -1, -1);
  375. #ifdef CONFIG_WIFI_DISPLAY
  376. } else if (os_strcasecmp(cmd, "wifi_display") == 0) {
  377. wifi_display_enable(wpa_s->global, !!atoi(value));
  378. #endif /* CONFIG_WIFI_DISPLAY */
  379. } else if (os_strcasecmp(cmd, "bssid_filter") == 0) {
  380. ret = set_bssid_filter(wpa_s, value);
  381. } else if (os_strcasecmp(cmd, "disallow_aps") == 0) {
  382. ret = set_disallow_aps(wpa_s, value);
  383. } else if (os_strcasecmp(cmd, "no_keep_alive") == 0) {
  384. wpa_s->no_keep_alive = !!atoi(value);
  385. } else {
  386. value[-1] = '=';
  387. ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
  388. if (ret == 0)
  389. wpa_supplicant_update_config(wpa_s);
  390. }
  391. return ret;
  392. }
  393. static int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s,
  394. char *cmd, char *buf, size_t buflen)
  395. {
  396. int res = -1;
  397. wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
  398. if (os_strcmp(cmd, "version") == 0) {
  399. res = os_snprintf(buf, buflen, "%s", VERSION_STR);
  400. } else if (os_strcasecmp(cmd, "country") == 0) {
  401. if (wpa_s->conf->country[0] && wpa_s->conf->country[1])
  402. res = os_snprintf(buf, buflen, "%c%c",
  403. wpa_s->conf->country[0],
  404. wpa_s->conf->country[1]);
  405. #ifdef CONFIG_WIFI_DISPLAY
  406. } else if (os_strcasecmp(cmd, "wifi_display") == 0) {
  407. res = os_snprintf(buf, buflen, "%d",
  408. wpa_s->global->wifi_display);
  409. if (res < 0 || (unsigned int) res >= buflen)
  410. return -1;
  411. return res;
  412. #endif /* CONFIG_WIFI_DISPLAY */
  413. }
  414. if (res < 0 || (unsigned int) res >= buflen)
  415. return -1;
  416. return res;
  417. }
  418. #ifdef IEEE8021X_EAPOL
  419. static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s,
  420. char *addr)
  421. {
  422. u8 bssid[ETH_ALEN];
  423. struct wpa_ssid *ssid = wpa_s->current_ssid;
  424. if (hwaddr_aton(addr, bssid)) {
  425. wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address "
  426. "'%s'", addr);
  427. return -1;
  428. }
  429. wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid));
  430. rsn_preauth_deinit(wpa_s->wpa);
  431. if (rsn_preauth_init(wpa_s->wpa, bssid, ssid ? &ssid->eap : NULL))
  432. return -1;
  433. return 0;
  434. }
  435. #endif /* IEEE8021X_EAPOL */
  436. #ifdef CONFIG_PEERKEY
  437. /* MLME-STKSTART.request(peer) */
  438. static int wpa_supplicant_ctrl_iface_stkstart(
  439. struct wpa_supplicant *wpa_s, char *addr)
  440. {
  441. u8 peer[ETH_ALEN];
  442. if (hwaddr_aton(addr, peer)) {
  443. wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART: invalid "
  444. "address '%s'", addr);
  445. return -1;
  446. }
  447. wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART " MACSTR,
  448. MAC2STR(peer));
  449. return wpa_sm_stkstart(wpa_s->wpa, peer);
  450. }
  451. #endif /* CONFIG_PEERKEY */
  452. #ifdef CONFIG_TDLS
  453. static int wpa_supplicant_ctrl_iface_tdls_discover(
  454. struct wpa_supplicant *wpa_s, char *addr)
  455. {
  456. u8 peer[ETH_ALEN];
  457. int ret;
  458. if (hwaddr_aton(addr, peer)) {
  459. wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER: invalid "
  460. "address '%s'", addr);
  461. return -1;
  462. }
  463. wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER " MACSTR,
  464. MAC2STR(peer));
  465. if (wpa_tdls_is_external_setup(wpa_s->wpa))
  466. ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer);
  467. else
  468. ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
  469. return ret;
  470. }
  471. static int wpa_supplicant_ctrl_iface_tdls_setup(
  472. struct wpa_supplicant *wpa_s, char *addr)
  473. {
  474. u8 peer[ETH_ALEN];
  475. int ret;
  476. if (hwaddr_aton(addr, peer)) {
  477. wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP: invalid "
  478. "address '%s'", addr);
  479. return -1;
  480. }
  481. wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP " MACSTR,
  482. MAC2STR(peer));
  483. ret = wpa_tdls_reneg(wpa_s->wpa, peer);
  484. if (ret) {
  485. if (wpa_tdls_is_external_setup(wpa_s->wpa))
  486. ret = wpa_tdls_start(wpa_s->wpa, peer);
  487. else
  488. ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
  489. }
  490. return ret;
  491. }
  492. static int wpa_supplicant_ctrl_iface_tdls_teardown(
  493. struct wpa_supplicant *wpa_s, char *addr)
  494. {
  495. u8 peer[ETH_ALEN];
  496. if (hwaddr_aton(addr, peer)) {
  497. wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN: invalid "
  498. "address '%s'", addr);
  499. return -1;
  500. }
  501. wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN " MACSTR,
  502. MAC2STR(peer));
  503. return wpa_tdls_teardown_link(wpa_s->wpa, peer,
  504. WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
  505. }
  506. #endif /* CONFIG_TDLS */
  507. #ifdef CONFIG_IEEE80211R
  508. static int wpa_supplicant_ctrl_iface_ft_ds(
  509. struct wpa_supplicant *wpa_s, char *addr)
  510. {
  511. u8 target_ap[ETH_ALEN];
  512. struct wpa_bss *bss;
  513. const u8 *mdie;
  514. if (hwaddr_aton(addr, target_ap)) {
  515. wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS: invalid "
  516. "address '%s'", addr);
  517. return -1;
  518. }
  519. wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS " MACSTR, MAC2STR(target_ap));
  520. bss = wpa_bss_get_bssid(wpa_s, target_ap);
  521. if (bss)
  522. mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
  523. else
  524. mdie = NULL;
  525. return wpa_ft_start_over_ds(wpa_s->wpa, target_ap, mdie);
  526. }
  527. #endif /* CONFIG_IEEE80211R */
  528. #ifdef CONFIG_WPS
  529. static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s,
  530. char *cmd)
  531. {
  532. u8 bssid[ETH_ALEN], *_bssid = bssid;
  533. #ifdef CONFIG_P2P
  534. u8 p2p_dev_addr[ETH_ALEN];
  535. #endif /* CONFIG_P2P */
  536. #ifdef CONFIG_AP
  537. u8 *_p2p_dev_addr = NULL;
  538. #endif /* CONFIG_AP */
  539. if (cmd == NULL || os_strcmp(cmd, "any") == 0) {
  540. _bssid = NULL;
  541. #ifdef CONFIG_P2P
  542. } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) {
  543. if (hwaddr_aton(cmd + 13, p2p_dev_addr)) {
  544. wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid "
  545. "P2P Device Address '%s'",
  546. cmd + 13);
  547. return -1;
  548. }
  549. _p2p_dev_addr = p2p_dev_addr;
  550. #endif /* CONFIG_P2P */
  551. } else if (hwaddr_aton(cmd, bssid)) {
  552. wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'",
  553. cmd);
  554. return -1;
  555. }
  556. #ifdef CONFIG_AP
  557. if (wpa_s->ap_iface)
  558. return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid, _p2p_dev_addr);
  559. #endif /* CONFIG_AP */
  560. return wpas_wps_start_pbc(wpa_s, _bssid, 0);
  561. }
  562. static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s,
  563. char *cmd, char *buf,
  564. size_t buflen)
  565. {
  566. u8 bssid[ETH_ALEN], *_bssid = bssid;
  567. char *pin;
  568. int ret;
  569. pin = os_strchr(cmd, ' ');
  570. if (pin)
  571. *pin++ = '\0';
  572. if (os_strcmp(cmd, "any") == 0)
  573. _bssid = NULL;
  574. else if (os_strcmp(cmd, "get") == 0) {
  575. ret = wps_generate_pin();
  576. goto done;
  577. } else if (hwaddr_aton(cmd, bssid)) {
  578. wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'",
  579. cmd);
  580. return -1;
  581. }
  582. #ifdef CONFIG_AP
  583. if (wpa_s->ap_iface) {
  584. int timeout = 0;
  585. char *pos;
  586. if (pin) {
  587. pos = os_strchr(pin, ' ');
  588. if (pos) {
  589. *pos++ = '\0';
  590. timeout = atoi(pos);
  591. }
  592. }
  593. return wpa_supplicant_ap_wps_pin(wpa_s, _bssid, pin,
  594. buf, buflen, timeout);
  595. }
  596. #endif /* CONFIG_AP */
  597. if (pin) {
  598. ret = wpas_wps_start_pin(wpa_s, _bssid, pin, 0,
  599. DEV_PW_DEFAULT);
  600. if (ret < 0)
  601. return -1;
  602. ret = os_snprintf(buf, buflen, "%s", pin);
  603. if (ret < 0 || (size_t) ret >= buflen)
  604. return -1;
  605. return ret;
  606. }
  607. ret = wpas_wps_start_pin(wpa_s, _bssid, NULL, 0, DEV_PW_DEFAULT);
  608. if (ret < 0)
  609. return -1;
  610. done:
  611. /* Return the generated PIN */
  612. ret = os_snprintf(buf, buflen, "%08d", ret);
  613. if (ret < 0 || (size_t) ret >= buflen)
  614. return -1;
  615. return ret;
  616. }
  617. static int wpa_supplicant_ctrl_iface_wps_check_pin(
  618. struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
  619. {
  620. char pin[9];
  621. size_t len;
  622. char *pos;
  623. int ret;
  624. wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN",
  625. (u8 *) cmd, os_strlen(cmd));
  626. for (pos = cmd, len = 0; *pos != '\0'; pos++) {
  627. if (*pos < '0' || *pos > '9')
  628. continue;
  629. pin[len++] = *pos;
  630. if (len == 9) {
  631. wpa_printf(MSG_DEBUG, "WPS: Too long PIN");
  632. return -1;
  633. }
  634. }
  635. if (len != 4 && len != 8) {
  636. wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len);
  637. return -1;
  638. }
  639. pin[len] = '\0';
  640. if (len == 8) {
  641. unsigned int pin_val;
  642. pin_val = atoi(pin);
  643. if (!wps_pin_valid(pin_val)) {
  644. wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit");
  645. ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n");
  646. if (ret < 0 || (size_t) ret >= buflen)
  647. return -1;
  648. return ret;
  649. }
  650. }
  651. ret = os_snprintf(buf, buflen, "%s", pin);
  652. if (ret < 0 || (size_t) ret >= buflen)
  653. return -1;
  654. return ret;
  655. }
  656. #ifdef CONFIG_WPS_NFC
  657. static int wpa_supplicant_ctrl_iface_wps_nfc(struct wpa_supplicant *wpa_s,
  658. char *cmd)
  659. {
  660. u8 bssid[ETH_ALEN], *_bssid = bssid;
  661. if (cmd == NULL || cmd[0] == '\0')
  662. _bssid = NULL;
  663. else if (hwaddr_aton(cmd, bssid))
  664. return -1;
  665. return wpas_wps_start_nfc(wpa_s, _bssid);
  666. }
  667. static int wpa_supplicant_ctrl_iface_wps_nfc_token(
  668. struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
  669. {
  670. int ndef;
  671. struct wpabuf *buf;
  672. int res;
  673. if (os_strcmp(cmd, "WPS") == 0)
  674. ndef = 0;
  675. else if (os_strcmp(cmd, "NDEF") == 0)
  676. ndef = 1;
  677. else
  678. return -1;
  679. buf = wpas_wps_nfc_token(wpa_s, ndef);
  680. if (buf == NULL)
  681. return -1;
  682. res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
  683. wpabuf_len(buf));
  684. reply[res++] = '\n';
  685. reply[res] = '\0';
  686. wpabuf_free(buf);
  687. return res;
  688. }
  689. static int wpa_supplicant_ctrl_iface_wps_nfc_tag_read(
  690. struct wpa_supplicant *wpa_s, char *pos)
  691. {
  692. size_t len;
  693. struct wpabuf *buf;
  694. int ret;
  695. len = os_strlen(pos);
  696. if (len & 0x01)
  697. return -1;
  698. len /= 2;
  699. buf = wpabuf_alloc(len);
  700. if (buf == NULL)
  701. return -1;
  702. if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
  703. wpabuf_free(buf);
  704. return -1;
  705. }
  706. ret = wpas_wps_nfc_tag_read(wpa_s, buf);
  707. wpabuf_free(buf);
  708. return ret;
  709. }
  710. static int wpas_ctrl_nfc_get_handover_req_wps(struct wpa_supplicant *wpa_s,
  711. char *reply, size_t max_len)
  712. {
  713. struct wpabuf *buf;
  714. int res;
  715. buf = wpas_wps_nfc_handover_req(wpa_s);
  716. if (buf == NULL)
  717. return -1;
  718. res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
  719. wpabuf_len(buf));
  720. reply[res++] = '\n';
  721. reply[res] = '\0';
  722. wpabuf_free(buf);
  723. return res;
  724. }
  725. static int wpas_ctrl_nfc_get_handover_req(struct wpa_supplicant *wpa_s,
  726. char *cmd, char *reply,
  727. size_t max_len)
  728. {
  729. char *pos;
  730. pos = os_strchr(cmd, ' ');
  731. if (pos == NULL)
  732. return -1;
  733. *pos++ = '\0';
  734. if (os_strcmp(cmd, "NDEF") != 0)
  735. return -1;
  736. if (os_strcmp(pos, "WPS") == 0) {
  737. return wpas_ctrl_nfc_get_handover_req_wps(wpa_s, reply,
  738. max_len);
  739. }
  740. return -1;
  741. }
  742. static int wpas_ctrl_nfc_get_handover_sel_wps(struct wpa_supplicant *wpa_s,
  743. char *reply, size_t max_len)
  744. {
  745. struct wpabuf *buf;
  746. int res;
  747. buf = wpas_wps_nfc_handover_sel(wpa_s);
  748. if (buf == NULL)
  749. return -1;
  750. res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
  751. wpabuf_len(buf));
  752. reply[res++] = '\n';
  753. reply[res] = '\0';
  754. wpabuf_free(buf);
  755. return res;
  756. }
  757. static int wpas_ctrl_nfc_get_handover_sel(struct wpa_supplicant *wpa_s,
  758. char *cmd, char *reply,
  759. size_t max_len)
  760. {
  761. char *pos;
  762. pos = os_strchr(cmd, ' ');
  763. if (pos == NULL)
  764. return -1;
  765. *pos++ = '\0';
  766. if (os_strcmp(cmd, "NDEF") != 0)
  767. return -1;
  768. if (os_strcmp(pos, "WPS") == 0) {
  769. return wpas_ctrl_nfc_get_handover_sel_wps(wpa_s, reply,
  770. max_len);
  771. }
  772. return -1;
  773. }
  774. static int wpas_ctrl_nfc_rx_handover_req(struct wpa_supplicant *wpa_s,
  775. char *cmd, char *reply,
  776. size_t max_len)
  777. {
  778. size_t len;
  779. struct wpabuf *buf;
  780. int ret;
  781. len = os_strlen(cmd);
  782. if (len & 0x01)
  783. return -1;
  784. len /= 2;
  785. buf = wpabuf_alloc(len);
  786. if (buf == NULL)
  787. return -1;
  788. if (hexstr2bin(cmd, wpabuf_put(buf, len), len) < 0) {
  789. wpabuf_free(buf);
  790. return -1;
  791. }
  792. ret = wpas_wps_nfc_rx_handover_req(wpa_s, buf);
  793. wpabuf_free(buf);
  794. return ret;
  795. }
  796. static int wpas_ctrl_nfc_rx_handover_sel(struct wpa_supplicant *wpa_s,
  797. char *cmd)
  798. {
  799. size_t len;
  800. struct wpabuf *buf;
  801. int ret;
  802. len = os_strlen(cmd);
  803. if (len & 0x01)
  804. return -1;
  805. len /= 2;
  806. buf = wpabuf_alloc(len);
  807. if (buf == NULL)
  808. return -1;
  809. if (hexstr2bin(cmd, wpabuf_put(buf, len), len) < 0) {
  810. wpabuf_free(buf);
  811. return -1;
  812. }
  813. ret = wpas_wps_nfc_rx_handover_sel(wpa_s, buf);
  814. wpabuf_free(buf);
  815. return ret;
  816. }
  817. #endif /* CONFIG_WPS_NFC */
  818. static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s,
  819. char *cmd)
  820. {
  821. u8 bssid[ETH_ALEN];
  822. char *pin;
  823. char *new_ssid;
  824. char *new_auth;
  825. char *new_encr;
  826. char *new_key;
  827. struct wps_new_ap_settings ap;
  828. pin = os_strchr(cmd, ' ');
  829. if (pin == NULL)
  830. return -1;
  831. *pin++ = '\0';
  832. if (hwaddr_aton(cmd, bssid)) {
  833. wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_REG: invalid BSSID '%s'",
  834. cmd);
  835. return -1;
  836. }
  837. new_ssid = os_strchr(pin, ' ');
  838. if (new_ssid == NULL)
  839. return wpas_wps_start_reg(wpa_s, bssid, pin, NULL);
  840. *new_ssid++ = '\0';
  841. new_auth = os_strchr(new_ssid, ' ');
  842. if (new_auth == NULL)
  843. return -1;
  844. *new_auth++ = '\0';
  845. new_encr = os_strchr(new_auth, ' ');
  846. if (new_encr == NULL)
  847. return -1;
  848. *new_encr++ = '\0';
  849. new_key = os_strchr(new_encr, ' ');
  850. if (new_key == NULL)
  851. return -1;
  852. *new_key++ = '\0';
  853. os_memset(&ap, 0, sizeof(ap));
  854. ap.ssid_hex = new_ssid;
  855. ap.auth = new_auth;
  856. ap.encr = new_encr;
  857. ap.key_hex = new_key;
  858. return wpas_wps_start_reg(wpa_s, bssid, pin, &ap);
  859. }
  860. #ifdef CONFIG_AP
  861. static int wpa_supplicant_ctrl_iface_wps_ap_pin(struct wpa_supplicant *wpa_s,
  862. char *cmd, char *buf,
  863. size_t buflen)
  864. {
  865. int timeout = 300;
  866. char *pos;
  867. const char *pin_txt;
  868. if (!wpa_s->ap_iface)
  869. return -1;
  870. pos = os_strchr(cmd, ' ');
  871. if (pos)
  872. *pos++ = '\0';
  873. if (os_strcmp(cmd, "disable") == 0) {
  874. wpas_wps_ap_pin_disable(wpa_s);
  875. return os_snprintf(buf, buflen, "OK\n");
  876. }
  877. if (os_strcmp(cmd, "random") == 0) {
  878. if (pos)
  879. timeout = atoi(pos);
  880. pin_txt = wpas_wps_ap_pin_random(wpa_s, timeout);
  881. if (pin_txt == NULL)
  882. return -1;
  883. return os_snprintf(buf, buflen, "%s", pin_txt);
  884. }
  885. if (os_strcmp(cmd, "get") == 0) {
  886. pin_txt = wpas_wps_ap_pin_get(wpa_s);
  887. if (pin_txt == NULL)
  888. return -1;
  889. return os_snprintf(buf, buflen, "%s", pin_txt);
  890. }
  891. if (os_strcmp(cmd, "set") == 0) {
  892. char *pin;
  893. if (pos == NULL)
  894. return -1;
  895. pin = pos;
  896. pos = os_strchr(pos, ' ');
  897. if (pos) {
  898. *pos++ = '\0';
  899. timeout = atoi(pos);
  900. }
  901. if (os_strlen(pin) > buflen)
  902. return -1;
  903. if (wpas_wps_ap_pin_set(wpa_s, pin, timeout) < 0)
  904. return -1;
  905. return os_snprintf(buf, buflen, "%s", pin);
  906. }
  907. return -1;
  908. }
  909. #endif /* CONFIG_AP */
  910. #ifdef CONFIG_WPS_ER
  911. static int wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant *wpa_s,
  912. char *cmd)
  913. {
  914. char *uuid = cmd, *pin, *pos;
  915. u8 addr_buf[ETH_ALEN], *addr = NULL;
  916. pin = os_strchr(uuid, ' ');
  917. if (pin == NULL)
  918. return -1;
  919. *pin++ = '\0';
  920. pos = os_strchr(pin, ' ');
  921. if (pos) {
  922. *pos++ = '\0';
  923. if (hwaddr_aton(pos, addr_buf) == 0)
  924. addr = addr_buf;
  925. }
  926. return wpas_wps_er_add_pin(wpa_s, addr, uuid, pin);
  927. }
  928. static int wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant *wpa_s,
  929. char *cmd)
  930. {
  931. char *uuid = cmd, *pin;
  932. pin = os_strchr(uuid, ' ');
  933. if (pin == NULL)
  934. return -1;
  935. *pin++ = '\0';
  936. return wpas_wps_er_learn(wpa_s, uuid, pin);
  937. }
  938. static int wpa_supplicant_ctrl_iface_wps_er_set_config(
  939. struct wpa_supplicant *wpa_s, char *cmd)
  940. {
  941. char *uuid = cmd, *id;
  942. id = os_strchr(uuid, ' ');
  943. if (id == NULL)
  944. return -1;
  945. *id++ = '\0';
  946. return wpas_wps_er_set_config(wpa_s, uuid, atoi(id));
  947. }
  948. static int wpa_supplicant_ctrl_iface_wps_er_config(
  949. struct wpa_supplicant *wpa_s, char *cmd)
  950. {
  951. char *pin;
  952. char *new_ssid;
  953. char *new_auth;
  954. char *new_encr;
  955. char *new_key;
  956. struct wps_new_ap_settings ap;
  957. pin = os_strchr(cmd, ' ');
  958. if (pin == NULL)
  959. return -1;
  960. *pin++ = '\0';
  961. new_ssid = os_strchr(pin, ' ');
  962. if (new_ssid == NULL)
  963. return -1;
  964. *new_ssid++ = '\0';
  965. new_auth = os_strchr(new_ssid, ' ');
  966. if (new_auth == NULL)
  967. return -1;
  968. *new_auth++ = '\0';
  969. new_encr = os_strchr(new_auth, ' ');
  970. if (new_encr == NULL)
  971. return -1;
  972. *new_encr++ = '\0';
  973. new_key = os_strchr(new_encr, ' ');
  974. if (new_key == NULL)
  975. return -1;
  976. *new_key++ = '\0';
  977. os_memset(&ap, 0, sizeof(ap));
  978. ap.ssid_hex = new_ssid;
  979. ap.auth = new_auth;
  980. ap.encr = new_encr;
  981. ap.key_hex = new_key;
  982. return wpas_wps_er_config(wpa_s, cmd, pin, &ap);
  983. }
  984. #ifdef CONFIG_WPS_NFC
  985. static int wpa_supplicant_ctrl_iface_wps_er_nfc_config_token(
  986. struct wpa_supplicant *wpa_s, char *cmd, char *reply, size_t max_len)
  987. {
  988. int ndef;
  989. struct wpabuf *buf;
  990. int res;
  991. char *uuid;
  992. uuid = os_strchr(cmd, ' ');
  993. if (uuid == NULL)
  994. return -1;
  995. *uuid++ = '\0';
  996. if (os_strcmp(cmd, "WPS") == 0)
  997. ndef = 0;
  998. else if (os_strcmp(cmd, "NDEF") == 0)
  999. ndef = 1;
  1000. else
  1001. return -1;
  1002. buf = wpas_wps_er_nfc_config_token(wpa_s, ndef, uuid);
  1003. if (buf == NULL)
  1004. return -1;
  1005. res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
  1006. wpabuf_len(buf));
  1007. reply[res++] = '\n';
  1008. reply[res] = '\0';
  1009. wpabuf_free(buf);
  1010. return res;
  1011. }
  1012. #endif /* CONFIG_WPS_NFC */
  1013. #endif /* CONFIG_WPS_ER */
  1014. #endif /* CONFIG_WPS */
  1015. #ifdef CONFIG_IBSS_RSN
  1016. static int wpa_supplicant_ctrl_iface_ibss_rsn(
  1017. struct wpa_supplicant *wpa_s, char *addr)
  1018. {
  1019. u8 peer[ETH_ALEN];
  1020. if (hwaddr_aton(addr, peer)) {
  1021. wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN: invalid "
  1022. "address '%s'", addr);
  1023. return -1;
  1024. }
  1025. wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN " MACSTR,
  1026. MAC2STR(peer));
  1027. return ibss_rsn_start(wpa_s->ibss_rsn, peer);
  1028. }
  1029. #endif /* CONFIG_IBSS_RSN */
  1030. static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
  1031. char *rsp)
  1032. {
  1033. #ifdef IEEE8021X_EAPOL
  1034. char *pos, *id_pos;
  1035. int id;
  1036. struct wpa_ssid *ssid;
  1037. pos = os_strchr(rsp, '-');
  1038. if (pos == NULL)
  1039. return -1;
  1040. *pos++ = '\0';
  1041. id_pos = pos;
  1042. pos = os_strchr(pos, ':');
  1043. if (pos == NULL)
  1044. return -1;
  1045. *pos++ = '\0';
  1046. id = atoi(id_pos);
  1047. wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id);
  1048. wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
  1049. (u8 *) pos, os_strlen(pos));
  1050. ssid = wpa_config_get_network(wpa_s->conf, id);
  1051. if (ssid == NULL) {
  1052. wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
  1053. "to update", id);
  1054. return -1;
  1055. }
  1056. return wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid, rsp,
  1057. pos);
  1058. #else /* IEEE8021X_EAPOL */
  1059. wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
  1060. return -1;
  1061. #endif /* IEEE8021X_EAPOL */
  1062. }
  1063. static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
  1064. const char *params,
  1065. char *buf, size_t buflen)
  1066. {
  1067. char *pos, *end, tmp[30];
  1068. int res, verbose, wps, ret;
  1069. verbose = os_strcmp(params, "-VERBOSE") == 0;
  1070. wps = os_strcmp(params, "-WPS") == 0;
  1071. pos = buf;
  1072. end = buf + buflen;
  1073. if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
  1074. struct wpa_ssid *ssid = wpa_s->current_ssid;
  1075. ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
  1076. MAC2STR(wpa_s->bssid));
  1077. if (ret < 0 || ret >= end - pos)
  1078. return pos - buf;
  1079. pos += ret;
  1080. if (ssid) {
  1081. u8 *_ssid = ssid->ssid;
  1082. size_t ssid_len = ssid->ssid_len;
  1083. u8 ssid_buf[MAX_SSID_LEN];
  1084. if (ssid_len == 0) {
  1085. int _res = wpa_drv_get_ssid(wpa_s, ssid_buf);
  1086. if (_res < 0)
  1087. ssid_len = 0;
  1088. else
  1089. ssid_len = _res;
  1090. _ssid = ssid_buf;
  1091. }
  1092. ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n",
  1093. wpa_ssid_txt(_ssid, ssid_len),
  1094. ssid->id);
  1095. if (ret < 0 || ret >= end - pos)
  1096. return pos - buf;
  1097. pos += ret;
  1098. if (wps && ssid->passphrase &&
  1099. wpa_key_mgmt_wpa_psk(ssid->key_mgmt) &&
  1100. (ssid->mode == WPAS_MODE_AP ||
  1101. ssid->mode == WPAS_MODE_P2P_GO)) {
  1102. ret = os_snprintf(pos, end - pos,
  1103. "passphrase=%s\n",
  1104. ssid->passphrase);
  1105. if (ret < 0 || ret >= end - pos)
  1106. return pos - buf;
  1107. pos += ret;
  1108. }
  1109. if (ssid->id_str) {
  1110. ret = os_snprintf(pos, end - pos,
  1111. "id_str=%s\n",
  1112. ssid->id_str);
  1113. if (ret < 0 || ret >= end - pos)
  1114. return pos - buf;
  1115. pos += ret;
  1116. }
  1117. switch (ssid->mode) {
  1118. case WPAS_MODE_INFRA:
  1119. ret = os_snprintf(pos, end - pos,
  1120. "mode=station\n");
  1121. break;
  1122. case WPAS_MODE_IBSS:
  1123. ret = os_snprintf(pos, end - pos,
  1124. "mode=IBSS\n");
  1125. break;
  1126. case WPAS_MODE_AP:
  1127. ret = os_snprintf(pos, end - pos,
  1128. "mode=AP\n");
  1129. break;
  1130. case WPAS_MODE_P2P_GO:
  1131. ret = os_snprintf(pos, end - pos,
  1132. "mode=P2P GO\n");
  1133. break;
  1134. case WPAS_MODE_P2P_GROUP_FORMATION:
  1135. ret = os_snprintf(pos, end - pos,
  1136. "mode=P2P GO - group "
  1137. "formation\n");
  1138. break;
  1139. default:
  1140. ret = 0;
  1141. break;
  1142. }
  1143. if (ret < 0 || ret >= end - pos)
  1144. return pos - buf;
  1145. pos += ret;
  1146. }
  1147. #ifdef CONFIG_AP
  1148. if (wpa_s->ap_iface) {
  1149. pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos,
  1150. end - pos,
  1151. verbose);
  1152. } else
  1153. #endif /* CONFIG_AP */
  1154. pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose);
  1155. }
  1156. ret = os_snprintf(pos, end - pos, "wpa_state=%s\n",
  1157. wpa_supplicant_state_txt(wpa_s->wpa_state));
  1158. if (ret < 0 || ret >= end - pos)
  1159. return pos - buf;
  1160. pos += ret;
  1161. if (wpa_s->l2 &&
  1162. l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) {
  1163. ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp);
  1164. if (ret < 0 || ret >= end - pos)
  1165. return pos - buf;
  1166. pos += ret;
  1167. }
  1168. #ifdef CONFIG_P2P
  1169. if (wpa_s->global->p2p) {
  1170. ret = os_snprintf(pos, end - pos, "p2p_device_address=" MACSTR
  1171. "\n", MAC2STR(wpa_s->global->p2p_dev_addr));
  1172. if (ret < 0 || ret >= end - pos)
  1173. return pos - buf;
  1174. pos += ret;
  1175. }
  1176. #endif /* CONFIG_P2P */
  1177. ret = os_snprintf(pos, end - pos, "address=" MACSTR "\n",
  1178. MAC2STR(wpa_s->own_addr));
  1179. if (ret < 0 || ret >= end - pos)
  1180. return pos - buf;
  1181. pos += ret;
  1182. #ifdef CONFIG_HS20
  1183. if (wpa_s->current_bss &&
  1184. wpa_bss_get_vendor_ie(wpa_s->current_bss, HS20_IE_VENDOR_TYPE) &&
  1185. wpa_s->wpa_proto == WPA_PROTO_RSN &&
  1186. wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
  1187. ret = os_snprintf(pos, end - pos, "hs20=1\n");
  1188. if (ret < 0 || ret >= end - pos)
  1189. return pos - buf;
  1190. pos += ret;
  1191. }
  1192. if (wpa_s->current_ssid) {
  1193. struct wpa_cred *cred;
  1194. char *type;
  1195. for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
  1196. if (wpa_s->current_ssid->parent_cred != cred)
  1197. continue;
  1198. if (!cred->domain)
  1199. continue;
  1200. ret = os_snprintf(pos, end - pos, "home_sp=%s\n",
  1201. cred->domain);
  1202. if (ret < 0 || ret >= end - pos)
  1203. return pos - buf;
  1204. pos += ret;
  1205. if (wpa_s->current_bss == NULL ||
  1206. wpa_s->current_bss->anqp == NULL)
  1207. res = -1;
  1208. else
  1209. res = interworking_home_sp_cred(
  1210. wpa_s, cred,
  1211. wpa_s->current_bss->anqp->domain_name);
  1212. if (res > 0)
  1213. type = "home";
  1214. else if (res == 0)
  1215. type = "roaming";
  1216. else
  1217. type = "unknown";
  1218. ret = os_snprintf(pos, end - pos, "sp_type=%s\n", type);
  1219. if (ret < 0 || ret >= end - pos)
  1220. return pos - buf;
  1221. pos += ret;
  1222. break;
  1223. }
  1224. }
  1225. #endif /* CONFIG_HS20 */
  1226. if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
  1227. wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
  1228. res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos,
  1229. verbose);
  1230. if (res >= 0)
  1231. pos += res;
  1232. }
  1233. res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose);
  1234. if (res >= 0)
  1235. pos += res;
  1236. return pos - buf;
  1237. }
  1238. static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s,
  1239. char *cmd)
  1240. {
  1241. char *pos;
  1242. int id;
  1243. struct wpa_ssid *ssid;
  1244. u8 bssid[ETH_ALEN];
  1245. /* cmd: "<network id> <BSSID>" */
  1246. pos = os_strchr(cmd, ' ');
  1247. if (pos == NULL)
  1248. return -1;
  1249. *pos++ = '\0';
  1250. id = atoi(cmd);
  1251. wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos);
  1252. if (hwaddr_aton(pos, bssid)) {
  1253. wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos);
  1254. return -1;
  1255. }
  1256. ssid = wpa_config_get_network(wpa_s->conf, id);
  1257. if (ssid == NULL) {
  1258. wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
  1259. "to update", id);
  1260. return -1;
  1261. }
  1262. os_memcpy(ssid->bssid, bssid, ETH_ALEN);
  1263. ssid->bssid_set = !is_zero_ether_addr(bssid);
  1264. return 0;
  1265. }
  1266. static int wpa_supplicant_ctrl_iface_blacklist(struct wpa_supplicant *wpa_s,
  1267. char *cmd, char *buf,
  1268. size_t buflen)
  1269. {
  1270. u8 bssid[ETH_ALEN];
  1271. struct wpa_blacklist *e;
  1272. char *pos, *end;
  1273. int ret;
  1274. /* cmd: "BLACKLIST [<BSSID>]" */
  1275. if (*cmd == '\0') {
  1276. pos = buf;
  1277. end = buf + buflen;
  1278. e = wpa_s->blacklist;
  1279. while (e) {
  1280. ret = os_snprintf(pos, end - pos, MACSTR "\n",
  1281. MAC2STR(e->bssid));
  1282. if (ret < 0 || ret >= end - pos)
  1283. return pos - buf;
  1284. pos += ret;
  1285. e = e->next;
  1286. }
  1287. return pos - buf;
  1288. }
  1289. cmd++;
  1290. if (os_strncmp(cmd, "clear", 5) == 0) {
  1291. wpa_blacklist_clear(wpa_s);
  1292. os_memcpy(buf, "OK\n", 3);
  1293. return 3;
  1294. }
  1295. wpa_printf(MSG_DEBUG, "CTRL_IFACE: BLACKLIST bssid='%s'", cmd);
  1296. if (hwaddr_aton(cmd, bssid)) {
  1297. wpa_printf(MSG_DEBUG, "CTRL_IFACE: invalid BSSID '%s'", cmd);
  1298. return -1;
  1299. }
  1300. /*
  1301. * Add the BSSID twice, so its count will be 2, causing it to be
  1302. * skipped when processing scan results.
  1303. */
  1304. ret = wpa_blacklist_add(wpa_s, bssid);
  1305. if (ret != 0)
  1306. return -1;
  1307. ret = wpa_blacklist_add(wpa_s, bssid);
  1308. if (ret != 0)
  1309. return -1;
  1310. os_memcpy(buf, "OK\n", 3);
  1311. return 3;
  1312. }
  1313. extern int wpa_debug_level;
  1314. extern int wpa_debug_timestamp;
  1315. static const char * debug_level_str(int level)
  1316. {
  1317. switch (level) {
  1318. case MSG_EXCESSIVE:
  1319. return "EXCESSIVE";
  1320. case MSG_MSGDUMP:
  1321. return "MSGDUMP";
  1322. case MSG_DEBUG:
  1323. return "DEBUG";
  1324. case MSG_INFO:
  1325. return "INFO";
  1326. case MSG_WARNING:
  1327. return "WARNING";
  1328. case MSG_ERROR:
  1329. return "ERROR";
  1330. default:
  1331. return "?";
  1332. }
  1333. }
  1334. static int str_to_debug_level(const char *s)
  1335. {
  1336. if (os_strcasecmp(s, "EXCESSIVE") == 0)
  1337. return MSG_EXCESSIVE;
  1338. if (os_strcasecmp(s, "MSGDUMP") == 0)
  1339. return MSG_MSGDUMP;
  1340. if (os_strcasecmp(s, "DEBUG") == 0)
  1341. return MSG_DEBUG;
  1342. if (os_strcasecmp(s, "INFO") == 0)
  1343. return MSG_INFO;
  1344. if (os_strcasecmp(s, "WARNING") == 0)
  1345. return MSG_WARNING;
  1346. if (os_strcasecmp(s, "ERROR") == 0)
  1347. return MSG_ERROR;
  1348. return -1;
  1349. }
  1350. static int wpa_supplicant_ctrl_iface_log_level(struct wpa_supplicant *wpa_s,
  1351. char *cmd, char *buf,
  1352. size_t buflen)
  1353. {
  1354. char *pos, *end, *stamp;
  1355. int ret;
  1356. if (cmd == NULL) {
  1357. return -1;
  1358. }
  1359. /* cmd: "LOG_LEVEL [<level>]" */
  1360. if (*cmd == '\0') {
  1361. pos = buf;
  1362. end = buf + buflen;
  1363. ret = os_snprintf(pos, end - pos, "Current level: %s\n"
  1364. "Timestamp: %d\n",
  1365. debug_level_str(wpa_debug_level),
  1366. wpa_debug_timestamp);
  1367. if (ret < 0 || ret >= end - pos)
  1368. ret = 0;
  1369. return ret;
  1370. }
  1371. while (*cmd == ' ')
  1372. cmd++;
  1373. stamp = os_strchr(cmd, ' ');
  1374. if (stamp) {
  1375. *stamp++ = '\0';
  1376. while (*stamp == ' ') {
  1377. stamp++;
  1378. }
  1379. }
  1380. if (cmd && os_strlen(cmd)) {
  1381. int level = str_to_debug_level(cmd);
  1382. if (level < 0)
  1383. return -1;
  1384. wpa_debug_level = level;
  1385. }
  1386. if (stamp && os_strlen(stamp))
  1387. wpa_debug_timestamp = atoi(stamp);
  1388. os_memcpy(buf, "OK\n", 3);
  1389. return 3;
  1390. }
  1391. static int wpa_supplicant_ctrl_iface_list_networks(
  1392. struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
  1393. {
  1394. char *pos, *end;
  1395. struct wpa_ssid *ssid;
  1396. int ret;
  1397. pos = buf;
  1398. end = buf + buflen;
  1399. ret = os_snprintf(pos, end - pos,
  1400. "network id / ssid / bssid / flags\n");
  1401. if (ret < 0 || ret >= end - pos)
  1402. return pos - buf;
  1403. pos += ret;
  1404. ssid = wpa_s->conf->ssid;
  1405. while (ssid) {
  1406. ret = os_snprintf(pos, end - pos, "%d\t%s",
  1407. ssid->id,
  1408. wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
  1409. if (ret < 0 || ret >= end - pos)
  1410. return pos - buf;
  1411. pos += ret;
  1412. if (ssid->bssid_set) {
  1413. ret = os_snprintf(pos, end - pos, "\t" MACSTR,
  1414. MAC2STR(ssid->bssid));
  1415. } else {
  1416. ret = os_snprintf(pos, end - pos, "\tany");
  1417. }
  1418. if (ret < 0 || ret >= end - pos)
  1419. return pos - buf;
  1420. pos += ret;
  1421. ret = os_snprintf(pos, end - pos, "\t%s%s%s%s",
  1422. ssid == wpa_s->current_ssid ?
  1423. "[CURRENT]" : "",
  1424. ssid->disabled ? "[DISABLED]" : "",
  1425. ssid->disabled_until.sec ?
  1426. "[TEMP-DISABLED]" : "",
  1427. ssid->disabled == 2 ? "[P2P-PERSISTENT]" :
  1428. "");
  1429. if (ret < 0 || ret >= end - pos)
  1430. return pos - buf;
  1431. pos += ret;
  1432. ret = os_snprintf(pos, end - pos, "\n");
  1433. if (ret < 0 || ret >= end - pos)
  1434. return pos - buf;
  1435. pos += ret;
  1436. ssid = ssid->next;
  1437. }
  1438. return pos - buf;
  1439. }
  1440. static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher)
  1441. {
  1442. int first = 1, ret;
  1443. ret = os_snprintf(pos, end - pos, "-");
  1444. if (ret < 0 || ret >= end - pos)
  1445. return pos;
  1446. pos += ret;
  1447. if (cipher & WPA_CIPHER_NONE) {
  1448. ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : "+");
  1449. if (ret < 0 || ret >= end - pos)
  1450. return pos;
  1451. pos += ret;
  1452. first = 0;
  1453. }
  1454. if (cipher & WPA_CIPHER_WEP40) {
  1455. ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : "+");
  1456. if (ret < 0 || ret >= end - pos)
  1457. return pos;
  1458. pos += ret;
  1459. first = 0;
  1460. }
  1461. if (cipher & WPA_CIPHER_WEP104) {
  1462. ret = os_snprintf(pos, end - pos, "%sWEP104",
  1463. first ? "" : "+");
  1464. if (ret < 0 || ret >= end - pos)
  1465. return pos;
  1466. pos += ret;
  1467. first = 0;
  1468. }
  1469. if (cipher & WPA_CIPHER_TKIP) {
  1470. ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : "+");
  1471. if (ret < 0 || ret >= end - pos)
  1472. return pos;
  1473. pos += ret;
  1474. first = 0;
  1475. }
  1476. if (cipher & WPA_CIPHER_CCMP) {
  1477. ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : "+");
  1478. if (ret < 0 || ret >= end - pos)
  1479. return pos;
  1480. pos += ret;
  1481. first = 0;
  1482. }
  1483. if (cipher & WPA_CIPHER_GCMP) {
  1484. ret = os_snprintf(pos, end - pos, "%sGCMP", first ? "" : "+");
  1485. if (ret < 0 || ret >= end - pos)
  1486. return pos;
  1487. pos += ret;
  1488. first = 0;
  1489. }
  1490. return pos;
  1491. }
  1492. static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto,
  1493. const u8 *ie, size_t ie_len)
  1494. {
  1495. struct wpa_ie_data data;
  1496. int first, ret;
  1497. ret = os_snprintf(pos, end - pos, "[%s-", proto);
  1498. if (ret < 0 || ret >= end - pos)
  1499. return pos;
  1500. pos += ret;
  1501. if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) {
  1502. ret = os_snprintf(pos, end - pos, "?]");
  1503. if (ret < 0 || ret >= end - pos)
  1504. return pos;
  1505. pos += ret;
  1506. return pos;
  1507. }
  1508. first = 1;
  1509. if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
  1510. ret = os_snprintf(pos, end - pos, "%sEAP", first ? "" : "+");
  1511. if (ret < 0 || ret >= end - pos)
  1512. return pos;
  1513. pos += ret;
  1514. first = 0;
  1515. }
  1516. if (data.key_mgmt & WPA_KEY_MGMT_PSK) {
  1517. ret = os_snprintf(pos, end - pos, "%sPSK", first ? "" : "+");
  1518. if (ret < 0 || ret >= end - pos)
  1519. return pos;
  1520. pos += ret;
  1521. first = 0;
  1522. }
  1523. if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
  1524. ret = os_snprintf(pos, end - pos, "%sNone", first ? "" : "+");
  1525. if (ret < 0 || ret >= end - pos)
  1526. return pos;
  1527. pos += ret;
  1528. first = 0;
  1529. }
  1530. #ifdef CONFIG_IEEE80211R
  1531. if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
  1532. ret = os_snprintf(pos, end - pos, "%sFT/EAP",
  1533. first ? "" : "+");
  1534. if (ret < 0 || ret >= end - pos)
  1535. return pos;
  1536. pos += ret;
  1537. first = 0;
  1538. }
  1539. if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) {
  1540. ret = os_snprintf(pos, end - pos, "%sFT/PSK",
  1541. first ? "" : "+");
  1542. if (ret < 0 || ret >= end - pos)
  1543. return pos;
  1544. pos += ret;
  1545. first = 0;
  1546. }
  1547. #endif /* CONFIG_IEEE80211R */
  1548. #ifdef CONFIG_IEEE80211W
  1549. if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
  1550. ret = os_snprintf(pos, end - pos, "%sEAP-SHA256",
  1551. first ? "" : "+");
  1552. if (ret < 0 || ret >= end - pos)
  1553. return pos;
  1554. pos += ret;
  1555. first = 0;
  1556. }
  1557. if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
  1558. ret = os_snprintf(pos, end - pos, "%sPSK-SHA256",
  1559. first ? "" : "+");
  1560. if (ret < 0 || ret >= end - pos)
  1561. return pos;
  1562. pos += ret;
  1563. first = 0;
  1564. }
  1565. #endif /* CONFIG_IEEE80211W */
  1566. pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher);
  1567. if (data.capabilities & WPA_CAPABILITY_PREAUTH) {
  1568. ret = os_snprintf(pos, end - pos, "-preauth");
  1569. if (ret < 0 || ret >= end - pos)
  1570. return pos;
  1571. pos += ret;
  1572. }
  1573. ret = os_snprintf(pos, end - pos, "]");
  1574. if (ret < 0 || ret >= end - pos)
  1575. return pos;
  1576. pos += ret;
  1577. return pos;
  1578. }
  1579. #ifdef CONFIG_WPS
  1580. static char * wpa_supplicant_wps_ie_txt_buf(struct wpa_supplicant *wpa_s,
  1581. char *pos, char *end,
  1582. struct wpabuf *wps_ie)
  1583. {
  1584. int ret;
  1585. const char *txt;
  1586. if (wps_ie == NULL)
  1587. return pos;
  1588. if (wps_is_selected_pbc_registrar(wps_ie))
  1589. txt = "[WPS-PBC]";
  1590. #ifdef CONFIG_WPS2
  1591. else if (wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 0))
  1592. txt = "[WPS-AUTH]";
  1593. #endif /* CONFIG_WPS2 */
  1594. else if (wps_is_selected_pin_registrar(wps_ie))
  1595. txt = "[WPS-PIN]";
  1596. else
  1597. txt = "[WPS]";
  1598. ret = os_snprintf(pos, end - pos, "%s", txt);
  1599. if (ret >= 0 && ret < end - pos)
  1600. pos += ret;
  1601. wpabuf_free(wps_ie);
  1602. return pos;
  1603. }
  1604. #endif /* CONFIG_WPS */
  1605. static char * wpa_supplicant_wps_ie_txt(struct wpa_supplicant *wpa_s,
  1606. char *pos, char *end,
  1607. const struct wpa_bss *bss)
  1608. {
  1609. #ifdef CONFIG_WPS
  1610. struct wpabuf *wps_ie;
  1611. wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
  1612. return wpa_supplicant_wps_ie_txt_buf(wpa_s, pos, end, wps_ie);
  1613. #else /* CONFIG_WPS */
  1614. return pos;
  1615. #endif /* CONFIG_WPS */
  1616. }
  1617. /* Format one result on one text line into a buffer. */
  1618. static int wpa_supplicant_ctrl_iface_scan_result(
  1619. struct wpa_supplicant *wpa_s,
  1620. const struct wpa_bss *bss, char *buf, size_t buflen)
  1621. {
  1622. char *pos, *end;
  1623. int ret;
  1624. const u8 *ie, *ie2, *p2p;
  1625. p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE);
  1626. if (p2p && bss->ssid_len == P2P_WILDCARD_SSID_LEN &&
  1627. os_memcmp(bss->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) ==
  1628. 0)
  1629. return 0; /* Do not show P2P listen discovery results here */
  1630. pos = buf;
  1631. end = buf + buflen;
  1632. ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t",
  1633. MAC2STR(bss->bssid), bss->freq, bss->level);
  1634. if (ret < 0 || ret >= end - pos)
  1635. return -1;
  1636. pos += ret;
  1637. ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
  1638. if (ie)
  1639. pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
  1640. ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
  1641. if (ie2)
  1642. pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]);
  1643. pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
  1644. if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
  1645. ret = os_snprintf(pos, end - pos, "[WEP]");
  1646. if (ret < 0 || ret >= end - pos)
  1647. return -1;
  1648. pos += ret;
  1649. }
  1650. if (bss->caps & IEEE80211_CAP_IBSS) {
  1651. ret = os_snprintf(pos, end - pos, "[IBSS]");
  1652. if (ret < 0 || ret >= end - pos)
  1653. return -1;
  1654. pos += ret;
  1655. }
  1656. if (bss->caps & IEEE80211_CAP_ESS) {
  1657. ret = os_snprintf(pos, end - pos, "[ESS]");
  1658. if (ret < 0 || ret >= end - pos)
  1659. return -1;
  1660. pos += ret;
  1661. }
  1662. if (p2p) {
  1663. ret = os_snprintf(pos, end - pos, "[P2P]");
  1664. if (ret < 0 || ret >= end - pos)
  1665. return -1;
  1666. pos += ret;
  1667. }
  1668. #ifdef CONFIG_HS20
  1669. if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE) && ie2) {
  1670. ret = os_snprintf(pos, end - pos, "[HS20]");
  1671. if (ret < 0 || ret >= end - pos)
  1672. return -1;
  1673. pos += ret;
  1674. }
  1675. #endif /* CONFIG_HS20 */
  1676. ret = os_snprintf(pos, end - pos, "\t%s",
  1677. wpa_ssid_txt(bss->ssid, bss->ssid_len));
  1678. if (ret < 0 || ret >= end - pos)
  1679. return -1;
  1680. pos += ret;
  1681. ret = os_snprintf(pos, end - pos, "\n");
  1682. if (ret < 0 || ret >= end - pos)
  1683. return -1;
  1684. pos += ret;
  1685. return pos - buf;
  1686. }
  1687. static int wpa_supplicant_ctrl_iface_scan_results(
  1688. struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
  1689. {
  1690. char *pos, *end;
  1691. struct wpa_bss *bss;
  1692. int ret;
  1693. pos = buf;
  1694. end = buf + buflen;
  1695. ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / "
  1696. "flags / ssid\n");
  1697. if (ret < 0 || ret >= end - pos)
  1698. return pos - buf;
  1699. pos += ret;
  1700. dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
  1701. ret = wpa_supplicant_ctrl_iface_scan_result(wpa_s, bss, pos,
  1702. end - pos);
  1703. if (ret < 0 || ret >= end - pos)
  1704. return pos - buf;
  1705. pos += ret;
  1706. }
  1707. return pos - buf;
  1708. }
  1709. static int wpa_supplicant_ctrl_iface_select_network(
  1710. struct wpa_supplicant *wpa_s, char *cmd)
  1711. {
  1712. int id;
  1713. struct wpa_ssid *ssid;
  1714. /* cmd: "<network id>" or "any" */
  1715. if (os_strcmp(cmd, "any") == 0) {
  1716. wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any");
  1717. ssid = NULL;
  1718. } else {
  1719. id = atoi(cmd);
  1720. wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id);
  1721. ssid = wpa_config_get_network(wpa_s->conf, id);
  1722. if (ssid == NULL) {
  1723. wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
  1724. "network id=%d", id);
  1725. return -1;
  1726. }
  1727. if (ssid->disabled == 2) {
  1728. wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
  1729. "SELECT_NETWORK with persistent P2P group");
  1730. return -1;
  1731. }
  1732. }
  1733. wpa_supplicant_select_network(wpa_s, ssid);
  1734. return 0;
  1735. }
  1736. static int wpa_supplicant_ctrl_iface_enable_network(
  1737. struct wpa_supplicant *wpa_s, char *cmd)
  1738. {
  1739. int id;
  1740. struct wpa_ssid *ssid;
  1741. /* cmd: "<network id>" or "all" */
  1742. if (os_strcmp(cmd, "all") == 0) {
  1743. wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all");
  1744. ssid = NULL;
  1745. } else {
  1746. id = atoi(cmd);
  1747. wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id);
  1748. ssid = wpa_config_get_network(wpa_s->conf, id);
  1749. if (ssid == NULL) {
  1750. wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
  1751. "network id=%d", id);
  1752. return -1;
  1753. }
  1754. if (ssid->disabled == 2) {
  1755. wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
  1756. "ENABLE_NETWORK with persistent P2P group");
  1757. return -1;
  1758. }
  1759. if (os_strstr(cmd, " no-connect")) {
  1760. ssid->disabled = 0;
  1761. return 0;
  1762. }
  1763. }
  1764. wpa_supplicant_enable_network(wpa_s, ssid);
  1765. return 0;
  1766. }
  1767. static int wpa_supplicant_ctrl_iface_disable_network(
  1768. struct wpa_supplicant *wpa_s, char *cmd)
  1769. {
  1770. int id;
  1771. struct wpa_ssid *ssid;
  1772. /* cmd: "<network id>" or "all" */
  1773. if (os_strcmp(cmd, "all") == 0) {
  1774. wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all");
  1775. ssid = NULL;
  1776. } else {
  1777. id = atoi(cmd);
  1778. wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id);
  1779. ssid = wpa_config_get_network(wpa_s->conf, id);
  1780. if (ssid == NULL) {
  1781. wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
  1782. "network id=%d", id);
  1783. return -1;
  1784. }
  1785. if (ssid->disabled == 2) {
  1786. wpa_printf(MSG_DEBUG, "CTRL_IFACE: Cannot use "
  1787. "DISABLE_NETWORK with persistent P2P "
  1788. "group");
  1789. return -1;
  1790. }
  1791. }
  1792. wpa_supplicant_disable_network(wpa_s, ssid);
  1793. return 0;
  1794. }
  1795. static int wpa_supplicant_ctrl_iface_add_network(
  1796. struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
  1797. {
  1798. struct wpa_ssid *ssid;
  1799. int ret;
  1800. wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
  1801. ssid = wpa_config_add_network(wpa_s->conf);
  1802. if (ssid == NULL)
  1803. return -1;
  1804. wpas_notify_network_added(wpa_s, ssid);
  1805. ssid->disabled = 1;
  1806. wpa_config_set_network_defaults(ssid);
  1807. ret = os_snprintf(buf, buflen, "%d\n", ssid->id);
  1808. if (ret < 0 || (size_t) ret >= buflen)
  1809. return -1;
  1810. return ret;
  1811. }
  1812. static int wpa_supplicant_ctrl_iface_remove_network(
  1813. struct wpa_supplicant *wpa_s, char *cmd)
  1814. {
  1815. int id;
  1816. struct wpa_ssid *ssid;
  1817. /* cmd: "<network id>" or "all" */
  1818. if (os_strcmp(cmd, "all") == 0) {
  1819. wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all");
  1820. ssid = wpa_s->conf->ssid;
  1821. while (ssid) {
  1822. struct wpa_ssid *remove_ssid = ssid;
  1823. id = ssid->id;
  1824. ssid = ssid->next;
  1825. wpas_notify_network_removed(wpa_s, remove_ssid);
  1826. wpa_config_remove_network(wpa_s->conf, id);
  1827. }
  1828. eapol_sm_invalidate_cached_session(wpa_s->eapol);
  1829. if (wpa_s->current_ssid) {
  1830. #ifdef CONFIG_SME
  1831. wpa_s->sme.prev_bssid_set = 0;
  1832. #endif /* CONFIG_SME */
  1833. wpa_sm_set_config(wpa_s->wpa, NULL);
  1834. eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
  1835. wpa_supplicant_deauthenticate(
  1836. wpa_s, WLAN_REASON_DEAUTH_LEAVING);
  1837. }
  1838. return 0;
  1839. }
  1840. id = atoi(cmd);
  1841. wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id);
  1842. ssid = wpa_config_get_network(wpa_s->conf, id);
  1843. if (ssid)
  1844. wpas_notify_network_removed(wpa_s, ssid);
  1845. if (ssid == NULL) {
  1846. wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
  1847. "id=%d", id);
  1848. return -1;
  1849. }
  1850. if (ssid == wpa_s->current_ssid || wpa_s->current_ssid == NULL) {
  1851. #ifdef CONFIG_SME
  1852. wpa_s->sme.prev_bssid_set = 0;
  1853. #endif /* CONFIG_SME */
  1854. /*
  1855. * Invalidate the EAP session cache if the current or
  1856. * previously used network is removed.
  1857. */
  1858. eapol_sm_invalidate_cached_session(wpa_s->eapol);
  1859. }
  1860. if (ssid == wpa_s

Large files files are truncated, but you can click here to view the full file