ctrl_iface.c 53 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218
  1. /*
  2. * WPA Supplicant / Control interface (shared code for all backends)
  3. * Copyright (c) 2004-2010, Jouni Malinen <j@w1.fi>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. *
  9. * Alternatively, this software may be distributed under the terms of BSD
  10. * license.
  11. *
  12. * See README and COPYING for more details.
  13. */
  14. #include "utils/includes.h"
  15. #include "utils/common.h"
  16. #include "utils/eloop.h"
  17. #include "common/ieee802_11_defs.h"
  18. #include "common/wpa_ctrl.h"
  19. #include "eap_peer/eap.h"
  20. #include "eapol_supp/eapol_supp_sm.h"
  21. #include "rsn_supp/wpa.h"
  22. #include "rsn_supp/preauth.h"
  23. #include "rsn_supp/pmksa_cache.h"
  24. #include "l2_packet/l2_packet.h"
  25. #include "wps/wps.h"
  26. #include "config.h"
  27. #include "wpa_supplicant_i.h"
  28. #include "driver_i.h"
  29. #include "wps_supplicant.h"
  30. #include "ibss_rsn.h"
  31. #include "ap.h"
  32. #include "notify.h"
  33. #include "bss.h"
  34. #include "scan.h"
  35. #include "ctrl_iface.h"
  36. extern struct wpa_driver_ops *wpa_drivers[];
  37. static int wpa_supplicant_global_iface_list(struct wpa_global *global,
  38. char *buf, int len);
  39. static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
  40. char *buf, int len);
  41. static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
  42. char *cmd)
  43. {
  44. char *value;
  45. int ret = 0;
  46. value = os_strchr(cmd, ' ');
  47. if (value == NULL)
  48. return -1;
  49. *value++ = '\0';
  50. wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
  51. if (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) {
  52. eapol_sm_configure(wpa_s->eapol,
  53. atoi(value), -1, -1, -1);
  54. } else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) {
  55. eapol_sm_configure(wpa_s->eapol,
  56. -1, atoi(value), -1, -1);
  57. } else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) {
  58. eapol_sm_configure(wpa_s->eapol,
  59. -1, -1, atoi(value), -1);
  60. } else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) {
  61. eapol_sm_configure(wpa_s->eapol,
  62. -1, -1, -1, atoi(value));
  63. } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) {
  64. if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
  65. atoi(value)))
  66. ret = -1;
  67. } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") ==
  68. 0) {
  69. if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
  70. atoi(value)))
  71. ret = -1;
  72. } else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) {
  73. if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, atoi(value)))
  74. ret = -1;
  75. } else
  76. ret = -1;
  77. return ret;
  78. }
  79. #ifdef IEEE8021X_EAPOL
  80. static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s,
  81. char *addr)
  82. {
  83. u8 bssid[ETH_ALEN];
  84. struct wpa_ssid *ssid = wpa_s->current_ssid;
  85. if (hwaddr_aton(addr, bssid)) {
  86. wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address "
  87. "'%s'", addr);
  88. return -1;
  89. }
  90. wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid));
  91. rsn_preauth_deinit(wpa_s->wpa);
  92. if (rsn_preauth_init(wpa_s->wpa, bssid, ssid ? &ssid->eap : NULL))
  93. return -1;
  94. return 0;
  95. }
  96. #endif /* IEEE8021X_EAPOL */
  97. #ifdef CONFIG_PEERKEY
  98. /* MLME-STKSTART.request(peer) */
  99. static int wpa_supplicant_ctrl_iface_stkstart(
  100. struct wpa_supplicant *wpa_s, char *addr)
  101. {
  102. u8 peer[ETH_ALEN];
  103. if (hwaddr_aton(addr, peer)) {
  104. wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART: invalid "
  105. "address '%s'", addr);
  106. return -1;
  107. }
  108. wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART " MACSTR,
  109. MAC2STR(peer));
  110. return wpa_sm_stkstart(wpa_s->wpa, peer);
  111. }
  112. #endif /* CONFIG_PEERKEY */
  113. #ifdef CONFIG_IEEE80211R
  114. static int wpa_supplicant_ctrl_iface_ft_ds(
  115. struct wpa_supplicant *wpa_s, char *addr)
  116. {
  117. u8 target_ap[ETH_ALEN];
  118. struct wpa_bss *bss;
  119. const u8 *mdie;
  120. if (hwaddr_aton(addr, target_ap)) {
  121. wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS: invalid "
  122. "address '%s'", addr);
  123. return -1;
  124. }
  125. wpa_printf(MSG_DEBUG, "CTRL_IFACE FT_DS " MACSTR, MAC2STR(target_ap));
  126. bss = wpa_bss_get_bssid(wpa_s, target_ap);
  127. if (bss)
  128. mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
  129. else
  130. mdie = NULL;
  131. return wpa_ft_start_over_ds(wpa_s->wpa, target_ap, mdie);
  132. }
  133. #endif /* CONFIG_IEEE80211R */
  134. #ifdef CONFIG_WPS
  135. static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s,
  136. char *cmd)
  137. {
  138. u8 bssid[ETH_ALEN], *_bssid = bssid;
  139. if (cmd == NULL || os_strcmp(cmd, "any") == 0)
  140. _bssid = NULL;
  141. else if (hwaddr_aton(cmd, bssid)) {
  142. wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'",
  143. cmd);
  144. return -1;
  145. }
  146. #ifdef CONFIG_AP
  147. if (wpa_s->ap_iface)
  148. return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid);
  149. #endif /* CONFIG_AP */
  150. return wpas_wps_start_pbc(wpa_s, _bssid);
  151. }
  152. static int wpa_supplicant_ctrl_iface_wps_pin(struct wpa_supplicant *wpa_s,
  153. char *cmd, char *buf,
  154. size_t buflen)
  155. {
  156. u8 bssid[ETH_ALEN], *_bssid = bssid;
  157. char *pin;
  158. int ret;
  159. pin = os_strchr(cmd, ' ');
  160. if (pin)
  161. *pin++ = '\0';
  162. if (os_strcmp(cmd, "any") == 0)
  163. _bssid = NULL;
  164. else if (hwaddr_aton(cmd, bssid)) {
  165. wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'",
  166. cmd);
  167. return -1;
  168. }
  169. #ifdef CONFIG_AP
  170. if (wpa_s->ap_iface)
  171. return wpa_supplicant_ap_wps_pin(wpa_s, _bssid, pin,
  172. buf, buflen);
  173. #endif /* CONFIG_AP */
  174. if (pin) {
  175. ret = wpas_wps_start_pin(wpa_s, _bssid, pin);
  176. if (ret < 0)
  177. return -1;
  178. ret = os_snprintf(buf, buflen, "%s", pin);
  179. if (ret < 0 || (size_t) ret >= buflen)
  180. return -1;
  181. return ret;
  182. }
  183. ret = wpas_wps_start_pin(wpa_s, _bssid, NULL);
  184. if (ret < 0)
  185. return -1;
  186. /* Return the generated PIN */
  187. ret = os_snprintf(buf, buflen, "%08d", ret);
  188. if (ret < 0 || (size_t) ret >= buflen)
  189. return -1;
  190. return ret;
  191. }
  192. #ifdef CONFIG_WPS_OOB
  193. static int wpa_supplicant_ctrl_iface_wps_oob(struct wpa_supplicant *wpa_s,
  194. char *cmd)
  195. {
  196. char *path, *method, *name;
  197. path = os_strchr(cmd, ' ');
  198. if (path == NULL)
  199. return -1;
  200. *path++ = '\0';
  201. method = os_strchr(path, ' ');
  202. if (method == NULL)
  203. return -1;
  204. *method++ = '\0';
  205. name = os_strchr(method, ' ');
  206. if (name != NULL)
  207. *name++ = '\0';
  208. return wpas_wps_start_oob(wpa_s, cmd, path, method, name);
  209. }
  210. #endif /* CONFIG_WPS_OOB */
  211. static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s,
  212. char *cmd)
  213. {
  214. u8 bssid[ETH_ALEN], *_bssid = bssid;
  215. char *pin;
  216. char *new_ssid;
  217. char *new_auth;
  218. char *new_encr;
  219. char *new_key;
  220. struct wps_new_ap_settings ap;
  221. pin = os_strchr(cmd, ' ');
  222. if (pin == NULL)
  223. return -1;
  224. *pin++ = '\0';
  225. if (os_strcmp(cmd, "any") == 0)
  226. _bssid = NULL;
  227. else if (hwaddr_aton(cmd, bssid)) {
  228. wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_REG: invalid BSSID '%s'",
  229. cmd);
  230. return -1;
  231. }
  232. new_ssid = os_strchr(pin, ' ');
  233. if (new_ssid == NULL)
  234. return wpas_wps_start_reg(wpa_s, _bssid, pin, NULL);
  235. *new_ssid++ = '\0';
  236. new_auth = os_strchr(new_ssid, ' ');
  237. if (new_auth == NULL)
  238. return -1;
  239. *new_auth++ = '\0';
  240. new_encr = os_strchr(new_auth, ' ');
  241. if (new_encr == NULL)
  242. return -1;
  243. *new_encr++ = '\0';
  244. new_key = os_strchr(new_encr, ' ');
  245. if (new_key == NULL)
  246. return -1;
  247. *new_key++ = '\0';
  248. os_memset(&ap, 0, sizeof(ap));
  249. ap.ssid_hex = new_ssid;
  250. ap.auth = new_auth;
  251. ap.encr = new_encr;
  252. ap.key_hex = new_key;
  253. return wpas_wps_start_reg(wpa_s, _bssid, pin, &ap);
  254. }
  255. #ifdef CONFIG_WPS_ER
  256. static int wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant *wpa_s,
  257. char *cmd)
  258. {
  259. char *uuid = cmd, *pin, *pos;
  260. u8 addr_buf[ETH_ALEN], *addr = NULL;
  261. pin = os_strchr(uuid, ' ');
  262. if (pin == NULL)
  263. return -1;
  264. *pin++ = '\0';
  265. pos = os_strchr(pin, ' ');
  266. if (pos) {
  267. *pos++ = '\0';
  268. if (hwaddr_aton(pos, addr_buf) == 0)
  269. addr = addr_buf;
  270. }
  271. return wpas_wps_er_add_pin(wpa_s, addr, uuid, pin);
  272. }
  273. static int wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant *wpa_s,
  274. char *cmd)
  275. {
  276. char *uuid = cmd, *pin;
  277. pin = os_strchr(uuid, ' ');
  278. if (pin == NULL)
  279. return -1;
  280. *pin++ = '\0';
  281. return wpas_wps_er_learn(wpa_s, uuid, pin);
  282. }
  283. static int wpa_supplicant_ctrl_iface_wps_er_config(
  284. struct wpa_supplicant *wpa_s, char *cmd)
  285. {
  286. char *pin;
  287. char *new_ssid;
  288. char *new_auth;
  289. char *new_encr;
  290. char *new_key;
  291. struct wps_new_ap_settings ap;
  292. pin = os_strchr(cmd, ' ');
  293. if (pin == NULL)
  294. return -1;
  295. *pin++ = '\0';
  296. new_ssid = os_strchr(pin, ' ');
  297. if (new_ssid == NULL)
  298. return -1;
  299. *new_ssid++ = '\0';
  300. new_auth = os_strchr(new_ssid, ' ');
  301. if (new_auth == NULL)
  302. return -1;
  303. *new_auth++ = '\0';
  304. new_encr = os_strchr(new_auth, ' ');
  305. if (new_encr == NULL)
  306. return -1;
  307. *new_encr++ = '\0';
  308. new_key = os_strchr(new_encr, ' ');
  309. if (new_key == NULL)
  310. return -1;
  311. *new_key++ = '\0';
  312. os_memset(&ap, 0, sizeof(ap));
  313. ap.ssid_hex = new_ssid;
  314. ap.auth = new_auth;
  315. ap.encr = new_encr;
  316. ap.key_hex = new_key;
  317. return wpas_wps_er_config(wpa_s, cmd, pin, &ap);
  318. }
  319. #endif /* CONFIG_WPS_ER */
  320. #endif /* CONFIG_WPS */
  321. #ifdef CONFIG_IBSS_RSN
  322. static int wpa_supplicant_ctrl_iface_ibss_rsn(
  323. struct wpa_supplicant *wpa_s, char *addr)
  324. {
  325. u8 peer[ETH_ALEN];
  326. if (hwaddr_aton(addr, peer)) {
  327. wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN: invalid "
  328. "address '%s'", addr);
  329. return -1;
  330. }
  331. wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN " MACSTR,
  332. MAC2STR(peer));
  333. return ibss_rsn_start(wpa_s->ibss_rsn, peer);
  334. }
  335. #endif /* CONFIG_IBSS_RSN */
  336. static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
  337. char *rsp)
  338. {
  339. #ifdef IEEE8021X_EAPOL
  340. char *pos, *id_pos;
  341. int id;
  342. struct wpa_ssid *ssid;
  343. struct eap_peer_config *eap;
  344. pos = os_strchr(rsp, '-');
  345. if (pos == NULL)
  346. return -1;
  347. *pos++ = '\0';
  348. id_pos = pos;
  349. pos = os_strchr(pos, ':');
  350. if (pos == NULL)
  351. return -1;
  352. *pos++ = '\0';
  353. id = atoi(id_pos);
  354. wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id);
  355. wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
  356. (u8 *) pos, os_strlen(pos));
  357. ssid = wpa_config_get_network(wpa_s->conf, id);
  358. if (ssid == NULL) {
  359. wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
  360. "to update", id);
  361. return -1;
  362. }
  363. eap = &ssid->eap;
  364. if (os_strcmp(rsp, "IDENTITY") == 0) {
  365. os_free(eap->identity);
  366. eap->identity = (u8 *) os_strdup(pos);
  367. eap->identity_len = os_strlen(pos);
  368. eap->pending_req_identity = 0;
  369. if (ssid == wpa_s->current_ssid)
  370. wpa_s->reassociate = 1;
  371. } else if (os_strcmp(rsp, "PASSWORD") == 0) {
  372. os_free(eap->password);
  373. eap->password = (u8 *) os_strdup(pos);
  374. eap->password_len = os_strlen(pos);
  375. eap->pending_req_password = 0;
  376. if (ssid == wpa_s->current_ssid)
  377. wpa_s->reassociate = 1;
  378. } else if (os_strcmp(rsp, "NEW_PASSWORD") == 0) {
  379. os_free(eap->new_password);
  380. eap->new_password = (u8 *) os_strdup(pos);
  381. eap->new_password_len = os_strlen(pos);
  382. eap->pending_req_new_password = 0;
  383. if (ssid == wpa_s->current_ssid)
  384. wpa_s->reassociate = 1;
  385. } else if (os_strcmp(rsp, "PIN") == 0) {
  386. os_free(eap->pin);
  387. eap->pin = os_strdup(pos);
  388. eap->pending_req_pin = 0;
  389. if (ssid == wpa_s->current_ssid)
  390. wpa_s->reassociate = 1;
  391. } else if (os_strcmp(rsp, "OTP") == 0) {
  392. os_free(eap->otp);
  393. eap->otp = (u8 *) os_strdup(pos);
  394. eap->otp_len = os_strlen(pos);
  395. os_free(eap->pending_req_otp);
  396. eap->pending_req_otp = NULL;
  397. eap->pending_req_otp_len = 0;
  398. } else if (os_strcmp(rsp, "PASSPHRASE") == 0) {
  399. os_free(eap->private_key_passwd);
  400. eap->private_key_passwd = (u8 *) os_strdup(pos);
  401. eap->pending_req_passphrase = 0;
  402. if (ssid == wpa_s->current_ssid)
  403. wpa_s->reassociate = 1;
  404. } else {
  405. wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", rsp);
  406. return -1;
  407. }
  408. return 0;
  409. #else /* IEEE8021X_EAPOL */
  410. wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
  411. return -1;
  412. #endif /* IEEE8021X_EAPOL */
  413. }
  414. static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
  415. const char *params,
  416. char *buf, size_t buflen)
  417. {
  418. char *pos, *end, tmp[30];
  419. int res, verbose, ret;
  420. verbose = os_strcmp(params, "-VERBOSE") == 0;
  421. pos = buf;
  422. end = buf + buflen;
  423. if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
  424. struct wpa_ssid *ssid = wpa_s->current_ssid;
  425. ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n",
  426. MAC2STR(wpa_s->bssid));
  427. if (ret < 0 || ret >= end - pos)
  428. return pos - buf;
  429. pos += ret;
  430. if (ssid) {
  431. u8 *_ssid = ssid->ssid;
  432. size_t ssid_len = ssid->ssid_len;
  433. u8 ssid_buf[MAX_SSID_LEN];
  434. if (ssid_len == 0) {
  435. int _res = wpa_drv_get_ssid(wpa_s, ssid_buf);
  436. if (_res < 0)
  437. ssid_len = 0;
  438. else
  439. ssid_len = _res;
  440. _ssid = ssid_buf;
  441. }
  442. ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n",
  443. wpa_ssid_txt(_ssid, ssid_len),
  444. ssid->id);
  445. if (ret < 0 || ret >= end - pos)
  446. return pos - buf;
  447. pos += ret;
  448. if (ssid->id_str) {
  449. ret = os_snprintf(pos, end - pos,
  450. "id_str=%s\n",
  451. ssid->id_str);
  452. if (ret < 0 || ret >= end - pos)
  453. return pos - buf;
  454. pos += ret;
  455. }
  456. switch (ssid->mode) {
  457. case WPAS_MODE_INFRA:
  458. ret = os_snprintf(pos, end - pos,
  459. "mode=station\n");
  460. break;
  461. case WPAS_MODE_IBSS:
  462. ret = os_snprintf(pos, end - pos,
  463. "mode=IBSS\n");
  464. break;
  465. case WPAS_MODE_AP:
  466. ret = os_snprintf(pos, end - pos,
  467. "mode=AP\n");
  468. break;
  469. default:
  470. ret = 0;
  471. break;
  472. }
  473. if (ret < 0 || ret >= end - pos)
  474. return pos - buf;
  475. pos += ret;
  476. }
  477. #ifdef CONFIG_AP
  478. if (wpa_s->ap_iface) {
  479. pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos,
  480. end - pos,
  481. verbose);
  482. } else
  483. #endif /* CONFIG_AP */
  484. pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose);
  485. }
  486. ret = os_snprintf(pos, end - pos, "wpa_state=%s\n",
  487. wpa_supplicant_state_txt(wpa_s->wpa_state));
  488. if (ret < 0 || ret >= end - pos)
  489. return pos - buf;
  490. pos += ret;
  491. if (wpa_s->l2 &&
  492. l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) {
  493. ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp);
  494. if (ret < 0 || ret >= end - pos)
  495. return pos - buf;
  496. pos += ret;
  497. }
  498. if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
  499. wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
  500. res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos,
  501. verbose);
  502. if (res >= 0)
  503. pos += res;
  504. }
  505. res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose);
  506. if (res >= 0)
  507. pos += res;
  508. return pos - buf;
  509. }
  510. static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s,
  511. char *cmd)
  512. {
  513. char *pos;
  514. int id;
  515. struct wpa_ssid *ssid;
  516. u8 bssid[ETH_ALEN];
  517. /* cmd: "<network id> <BSSID>" */
  518. pos = os_strchr(cmd, ' ');
  519. if (pos == NULL)
  520. return -1;
  521. *pos++ = '\0';
  522. id = atoi(cmd);
  523. wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos);
  524. if (hwaddr_aton(pos, bssid)) {
  525. wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos);
  526. return -1;
  527. }
  528. ssid = wpa_config_get_network(wpa_s->conf, id);
  529. if (ssid == NULL) {
  530. wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
  531. "to update", id);
  532. return -1;
  533. }
  534. os_memcpy(ssid->bssid, bssid, ETH_ALEN);
  535. ssid->bssid_set = !is_zero_ether_addr(bssid);
  536. return 0;
  537. }
  538. static int wpa_supplicant_ctrl_iface_list_networks(
  539. struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
  540. {
  541. char *pos, *end;
  542. struct wpa_ssid *ssid;
  543. int ret;
  544. pos = buf;
  545. end = buf + buflen;
  546. ret = os_snprintf(pos, end - pos,
  547. "network id / ssid / bssid / flags\n");
  548. if (ret < 0 || ret >= end - pos)
  549. return pos - buf;
  550. pos += ret;
  551. ssid = wpa_s->conf->ssid;
  552. while (ssid) {
  553. ret = os_snprintf(pos, end - pos, "%d\t%s",
  554. ssid->id,
  555. wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
  556. if (ret < 0 || ret >= end - pos)
  557. return pos - buf;
  558. pos += ret;
  559. if (ssid->bssid_set) {
  560. ret = os_snprintf(pos, end - pos, "\t" MACSTR,
  561. MAC2STR(ssid->bssid));
  562. } else {
  563. ret = os_snprintf(pos, end - pos, "\tany");
  564. }
  565. if (ret < 0 || ret >= end - pos)
  566. return pos - buf;
  567. pos += ret;
  568. ret = os_snprintf(pos, end - pos, "\t%s%s",
  569. ssid == wpa_s->current_ssid ?
  570. "[CURRENT]" : "",
  571. ssid->disabled ? "[DISABLED]" : "");
  572. if (ret < 0 || ret >= end - pos)
  573. return pos - buf;
  574. pos += ret;
  575. ret = os_snprintf(pos, end - pos, "\n");
  576. if (ret < 0 || ret >= end - pos)
  577. return pos - buf;
  578. pos += ret;
  579. ssid = ssid->next;
  580. }
  581. return pos - buf;
  582. }
  583. static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher)
  584. {
  585. int first = 1, ret;
  586. ret = os_snprintf(pos, end - pos, "-");
  587. if (ret < 0 || ret >= end - pos)
  588. return pos;
  589. pos += ret;
  590. if (cipher & WPA_CIPHER_NONE) {
  591. ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : "+");
  592. if (ret < 0 || ret >= end - pos)
  593. return pos;
  594. pos += ret;
  595. first = 0;
  596. }
  597. if (cipher & WPA_CIPHER_WEP40) {
  598. ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : "+");
  599. if (ret < 0 || ret >= end - pos)
  600. return pos;
  601. pos += ret;
  602. first = 0;
  603. }
  604. if (cipher & WPA_CIPHER_WEP104) {
  605. ret = os_snprintf(pos, end - pos, "%sWEP104",
  606. first ? "" : "+");
  607. if (ret < 0 || ret >= end - pos)
  608. return pos;
  609. pos += ret;
  610. first = 0;
  611. }
  612. if (cipher & WPA_CIPHER_TKIP) {
  613. ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : "+");
  614. if (ret < 0 || ret >= end - pos)
  615. return pos;
  616. pos += ret;
  617. first = 0;
  618. }
  619. if (cipher & WPA_CIPHER_CCMP) {
  620. ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : "+");
  621. if (ret < 0 || ret >= end - pos)
  622. return pos;
  623. pos += ret;
  624. first = 0;
  625. }
  626. return pos;
  627. }
  628. static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto,
  629. const u8 *ie, size_t ie_len)
  630. {
  631. struct wpa_ie_data data;
  632. int first, ret;
  633. ret = os_snprintf(pos, end - pos, "[%s-", proto);
  634. if (ret < 0 || ret >= end - pos)
  635. return pos;
  636. pos += ret;
  637. if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) {
  638. ret = os_snprintf(pos, end - pos, "?]");
  639. if (ret < 0 || ret >= end - pos)
  640. return pos;
  641. pos += ret;
  642. return pos;
  643. }
  644. first = 1;
  645. if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
  646. ret = os_snprintf(pos, end - pos, "%sEAP", first ? "" : "+");
  647. if (ret < 0 || ret >= end - pos)
  648. return pos;
  649. pos += ret;
  650. first = 0;
  651. }
  652. if (data.key_mgmt & WPA_KEY_MGMT_PSK) {
  653. ret = os_snprintf(pos, end - pos, "%sPSK", first ? "" : "+");
  654. if (ret < 0 || ret >= end - pos)
  655. return pos;
  656. pos += ret;
  657. first = 0;
  658. }
  659. if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
  660. ret = os_snprintf(pos, end - pos, "%sNone", first ? "" : "+");
  661. if (ret < 0 || ret >= end - pos)
  662. return pos;
  663. pos += ret;
  664. first = 0;
  665. }
  666. #ifdef CONFIG_IEEE80211R
  667. if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
  668. ret = os_snprintf(pos, end - pos, "%sFT/EAP",
  669. first ? "" : "+");
  670. if (ret < 0 || ret >= end - pos)
  671. return pos;
  672. pos += ret;
  673. first = 0;
  674. }
  675. if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) {
  676. ret = os_snprintf(pos, end - pos, "%sFT/PSK",
  677. first ? "" : "+");
  678. if (ret < 0 || ret >= end - pos)
  679. return pos;
  680. pos += ret;
  681. first = 0;
  682. }
  683. #endif /* CONFIG_IEEE80211R */
  684. #ifdef CONFIG_IEEE80211W
  685. if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
  686. ret = os_snprintf(pos, end - pos, "%sEAP-SHA256",
  687. first ? "" : "+");
  688. if (ret < 0 || ret >= end - pos)
  689. return pos;
  690. pos += ret;
  691. first = 0;
  692. }
  693. if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
  694. ret = os_snprintf(pos, end - pos, "%sPSK-SHA256",
  695. first ? "" : "+");
  696. if (ret < 0 || ret >= end - pos)
  697. return pos;
  698. pos += ret;
  699. first = 0;
  700. }
  701. #endif /* CONFIG_IEEE80211W */
  702. pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher);
  703. if (data.capabilities & WPA_CAPABILITY_PREAUTH) {
  704. ret = os_snprintf(pos, end - pos, "-preauth");
  705. if (ret < 0 || ret >= end - pos)
  706. return pos;
  707. pos += ret;
  708. }
  709. ret = os_snprintf(pos, end - pos, "]");
  710. if (ret < 0 || ret >= end - pos)
  711. return pos;
  712. pos += ret;
  713. return pos;
  714. }
  715. #ifdef CONFIG_WPS
  716. static char * wpa_supplicant_wps_ie_txt_buf(struct wpa_supplicant *wpa_s,
  717. char *pos, char *end,
  718. struct wpabuf *wps_ie)
  719. {
  720. int ret;
  721. const char *txt;
  722. if (wps_ie == NULL)
  723. return pos;
  724. if (wps_is_selected_pbc_registrar(wps_ie))
  725. txt = "[WPS-PBC]";
  726. #ifdef CONFIG_WPS2
  727. else if (wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 0))
  728. txt = "[WPS-AUTH]";
  729. #endif /* CONFIG_WPS2 */
  730. else if (wps_is_selected_pin_registrar(wps_ie))
  731. txt = "[WPS-PIN]";
  732. else
  733. txt = "[WPS]";
  734. ret = os_snprintf(pos, end - pos, "%s", txt);
  735. if (ret >= 0 && ret < end - pos)
  736. pos += ret;
  737. wpabuf_free(wps_ie);
  738. return pos;
  739. }
  740. #endif /* CONFIG_WPS */
  741. static char * wpa_supplicant_wps_ie_txt(struct wpa_supplicant *wpa_s,
  742. char *pos, char *end,
  743. const struct wpa_bss *bss)
  744. {
  745. #ifdef CONFIG_WPS
  746. struct wpabuf *wps_ie;
  747. wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
  748. return wpa_supplicant_wps_ie_txt_buf(wpa_s, pos, end, wps_ie);
  749. #else /* CONFIG_WPS */
  750. return pos;
  751. #endif /* CONFIG_WPS */
  752. }
  753. /* Format one result on one text line into a buffer. */
  754. static int wpa_supplicant_ctrl_iface_scan_result(
  755. struct wpa_supplicant *wpa_s,
  756. const struct wpa_bss *bss, char *buf, size_t buflen)
  757. {
  758. char *pos, *end;
  759. int ret;
  760. const u8 *ie, *ie2;
  761. pos = buf;
  762. end = buf + buflen;
  763. ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t",
  764. MAC2STR(bss->bssid), bss->freq, bss->level);
  765. if (ret < 0 || ret >= end - pos)
  766. return pos - buf;
  767. pos += ret;
  768. ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
  769. if (ie)
  770. pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
  771. ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
  772. if (ie2)
  773. pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]);
  774. pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
  775. if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
  776. ret = os_snprintf(pos, end - pos, "[WEP]");
  777. if (ret < 0 || ret >= end - pos)
  778. return pos - buf;
  779. pos += ret;
  780. }
  781. if (bss->caps & IEEE80211_CAP_IBSS) {
  782. ret = os_snprintf(pos, end - pos, "[IBSS]");
  783. if (ret < 0 || ret >= end - pos)
  784. return pos - buf;
  785. pos += ret;
  786. }
  787. if (bss->caps & IEEE80211_CAP_ESS) {
  788. ret = os_snprintf(pos, end - pos, "[ESS]");
  789. if (ret < 0 || ret >= end - pos)
  790. return pos - buf;
  791. pos += ret;
  792. }
  793. ret = os_snprintf(pos, end - pos, "\t%s",
  794. wpa_ssid_txt(bss->ssid, bss->ssid_len));
  795. if (ret < 0 || ret >= end - pos)
  796. return pos - buf;
  797. pos += ret;
  798. ret = os_snprintf(pos, end - pos, "\n");
  799. if (ret < 0 || ret >= end - pos)
  800. return pos - buf;
  801. pos += ret;
  802. return pos - buf;
  803. }
  804. static int wpa_supplicant_ctrl_iface_scan_results(
  805. struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
  806. {
  807. char *pos, *end;
  808. struct wpa_bss *bss;
  809. int ret;
  810. pos = buf;
  811. end = buf + buflen;
  812. ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / "
  813. "flags / ssid\n");
  814. if (ret < 0 || ret >= end - pos)
  815. return pos - buf;
  816. pos += ret;
  817. dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
  818. ret = wpa_supplicant_ctrl_iface_scan_result(wpa_s, bss, pos,
  819. end - pos);
  820. if (ret < 0 || ret >= end - pos)
  821. return pos - buf;
  822. pos += ret;
  823. }
  824. return pos - buf;
  825. }
  826. static int wpa_supplicant_ctrl_iface_select_network(
  827. struct wpa_supplicant *wpa_s, char *cmd)
  828. {
  829. int id;
  830. struct wpa_ssid *ssid;
  831. /* cmd: "<network id>" or "any" */
  832. if (os_strcmp(cmd, "any") == 0) {
  833. wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any");
  834. ssid = NULL;
  835. } else {
  836. id = atoi(cmd);
  837. wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id);
  838. ssid = wpa_config_get_network(wpa_s->conf, id);
  839. if (ssid == NULL) {
  840. wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
  841. "network id=%d", id);
  842. return -1;
  843. }
  844. }
  845. wpa_supplicant_select_network(wpa_s, ssid);
  846. return 0;
  847. }
  848. static int wpa_supplicant_ctrl_iface_enable_network(
  849. struct wpa_supplicant *wpa_s, char *cmd)
  850. {
  851. int id;
  852. struct wpa_ssid *ssid;
  853. /* cmd: "<network id>" or "all" */
  854. if (os_strcmp(cmd, "all") == 0) {
  855. wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all");
  856. ssid = NULL;
  857. } else {
  858. id = atoi(cmd);
  859. wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id);
  860. ssid = wpa_config_get_network(wpa_s->conf, id);
  861. if (ssid == NULL) {
  862. wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
  863. "network id=%d", id);
  864. return -1;
  865. }
  866. }
  867. wpa_supplicant_enable_network(wpa_s, ssid);
  868. return 0;
  869. }
  870. static int wpa_supplicant_ctrl_iface_disable_network(
  871. struct wpa_supplicant *wpa_s, char *cmd)
  872. {
  873. int id;
  874. struct wpa_ssid *ssid;
  875. /* cmd: "<network id>" or "all" */
  876. if (os_strcmp(cmd, "all") == 0) {
  877. wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all");
  878. ssid = NULL;
  879. } else {
  880. id = atoi(cmd);
  881. wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id);
  882. ssid = wpa_config_get_network(wpa_s->conf, id);
  883. if (ssid == NULL) {
  884. wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
  885. "network id=%d", id);
  886. return -1;
  887. }
  888. }
  889. wpa_supplicant_disable_network(wpa_s, ssid);
  890. return 0;
  891. }
  892. static int wpa_supplicant_ctrl_iface_add_network(
  893. struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
  894. {
  895. struct wpa_ssid *ssid;
  896. int ret;
  897. wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
  898. ssid = wpa_config_add_network(wpa_s->conf);
  899. if (ssid == NULL)
  900. return -1;
  901. wpas_notify_network_added(wpa_s, ssid);
  902. ssid->disabled = 1;
  903. wpa_config_set_network_defaults(ssid);
  904. ret = os_snprintf(buf, buflen, "%d\n", ssid->id);
  905. if (ret < 0 || (size_t) ret >= buflen)
  906. return -1;
  907. return ret;
  908. }
  909. static int wpa_supplicant_ctrl_iface_remove_network(
  910. struct wpa_supplicant *wpa_s, char *cmd)
  911. {
  912. int id;
  913. struct wpa_ssid *ssid;
  914. /* cmd: "<network id>" or "all" */
  915. if (os_strcmp(cmd, "all") == 0) {
  916. wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all");
  917. ssid = wpa_s->conf->ssid;
  918. while (ssid) {
  919. struct wpa_ssid *remove_ssid = ssid;
  920. id = ssid->id;
  921. ssid = ssid->next;
  922. wpas_notify_network_removed(wpa_s, remove_ssid);
  923. wpa_config_remove_network(wpa_s->conf, id);
  924. }
  925. if (wpa_s->current_ssid) {
  926. eapol_sm_invalidate_cached_session(wpa_s->eapol);
  927. wpa_supplicant_disassociate(wpa_s,
  928. WLAN_REASON_DEAUTH_LEAVING);
  929. }
  930. return 0;
  931. }
  932. id = atoi(cmd);
  933. wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id);
  934. ssid = wpa_config_get_network(wpa_s->conf, id);
  935. if (ssid == NULL ||
  936. wpa_config_remove_network(wpa_s->conf, id) < 0) {
  937. wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
  938. "id=%d", id);
  939. return -1;
  940. }
  941. if (ssid == wpa_s->current_ssid) {
  942. /*
  943. * Invalidate the EAP session cache if the current network is
  944. * removed.
  945. */
  946. eapol_sm_invalidate_cached_session(wpa_s->eapol);
  947. wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
  948. }
  949. return 0;
  950. }
  951. static int wpa_supplicant_ctrl_iface_set_network(
  952. struct wpa_supplicant *wpa_s, char *cmd)
  953. {
  954. int id;
  955. struct wpa_ssid *ssid;
  956. char *name, *value;
  957. /* cmd: "<network id> <variable name> <value>" */
  958. name = os_strchr(cmd, ' ');
  959. if (name == NULL)
  960. return -1;
  961. *name++ = '\0';
  962. value = os_strchr(name, ' ');
  963. if (value == NULL)
  964. return -1;
  965. *value++ = '\0';
  966. id = atoi(cmd);
  967. wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'",
  968. id, name);
  969. wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
  970. (u8 *) value, os_strlen(value));
  971. ssid = wpa_config_get_network(wpa_s->conf, id);
  972. if (ssid == NULL) {
  973. wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
  974. "id=%d", id);
  975. return -1;
  976. }
  977. if (wpa_config_set(ssid, name, value, 0) < 0) {
  978. wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
  979. "variable '%s'", name);
  980. return -1;
  981. }
  982. if (wpa_s->current_ssid == ssid) {
  983. /*
  984. * Invalidate the EAP session cache if anything in the current
  985. * configuration changes.
  986. */
  987. eapol_sm_invalidate_cached_session(wpa_s->eapol);
  988. }
  989. if ((os_strcmp(name, "psk") == 0 &&
  990. value[0] == '"' && ssid->ssid_len) ||
  991. (os_strcmp(name, "ssid") == 0 && ssid->passphrase))
  992. wpa_config_update_psk(ssid);
  993. else if (os_strcmp(name, "priority") == 0)
  994. wpa_config_update_prio_list(wpa_s->conf);
  995. return 0;
  996. }
  997. static int wpa_supplicant_ctrl_iface_get_network(
  998. struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
  999. {
  1000. int id;
  1001. size_t res;
  1002. struct wpa_ssid *ssid;
  1003. char *name, *value;
  1004. /* cmd: "<network id> <variable name>" */
  1005. name = os_strchr(cmd, ' ');
  1006. if (name == NULL || buflen == 0)
  1007. return -1;
  1008. *name++ = '\0';
  1009. id = atoi(cmd);
  1010. wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_NETWORK id=%d name='%s'",
  1011. id, name);
  1012. ssid = wpa_config_get_network(wpa_s->conf, id);
  1013. if (ssid == NULL) {
  1014. wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
  1015. "id=%d", id);
  1016. return -1;
  1017. }
  1018. value = wpa_config_get_no_key(ssid, name);
  1019. if (value == NULL) {
  1020. wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
  1021. "variable '%s'", name);
  1022. return -1;
  1023. }
  1024. res = os_strlcpy(buf, value, buflen);
  1025. if (res >= buflen) {
  1026. os_free(value);
  1027. return -1;
  1028. }
  1029. os_free(value);
  1030. return res;
  1031. }
  1032. #ifndef CONFIG_NO_CONFIG_WRITE
  1033. static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s)
  1034. {
  1035. int ret;
  1036. if (!wpa_s->conf->update_config) {
  1037. wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed "
  1038. "to update configuration (update_config=0)");
  1039. return -1;
  1040. }
  1041. ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
  1042. if (ret) {
  1043. wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to "
  1044. "update configuration");
  1045. } else {
  1046. wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration"
  1047. " updated");
  1048. }
  1049. return ret;
  1050. }
  1051. #endif /* CONFIG_NO_CONFIG_WRITE */
  1052. static int ctrl_iface_get_capability_pairwise(int res, char *strict,
  1053. struct wpa_driver_capa *capa,
  1054. char *buf, size_t buflen)
  1055. {
  1056. int ret, first = 1;
  1057. char *pos, *end;
  1058. size_t len;
  1059. pos = buf;
  1060. end = pos + buflen;
  1061. if (res < 0) {
  1062. if (strict)
  1063. return 0;
  1064. len = os_strlcpy(buf, "CCMP TKIP NONE", buflen);
  1065. if (len >= buflen)
  1066. return -1;
  1067. return len;
  1068. }
  1069. if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) {
  1070. ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " ");
  1071. if (ret < 0 || ret >= end - pos)
  1072. return pos - buf;
  1073. pos += ret;
  1074. first = 0;
  1075. }
  1076. if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) {
  1077. ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " ");
  1078. if (ret < 0 || ret >= end - pos)
  1079. return pos - buf;
  1080. pos += ret;
  1081. first = 0;
  1082. }
  1083. if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
  1084. ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : " ");
  1085. if (ret < 0 || ret >= end - pos)
  1086. return pos - buf;
  1087. pos += ret;
  1088. first = 0;
  1089. }
  1090. return pos - buf;
  1091. }
  1092. static int ctrl_iface_get_capability_group(int res, char *strict,
  1093. struct wpa_driver_capa *capa,
  1094. char *buf, size_t buflen)
  1095. {
  1096. int ret, first = 1;
  1097. char *pos, *end;
  1098. size_t len;
  1099. pos = buf;
  1100. end = pos + buflen;
  1101. if (res < 0) {
  1102. if (strict)
  1103. return 0;
  1104. len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen);
  1105. if (len >= buflen)
  1106. return -1;
  1107. return len;
  1108. }
  1109. if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) {
  1110. ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " ");
  1111. if (ret < 0 || ret >= end - pos)
  1112. return pos - buf;
  1113. pos += ret;
  1114. first = 0;
  1115. }
  1116. if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) {
  1117. ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " ");
  1118. if (ret < 0 || ret >= end - pos)
  1119. return pos - buf;
  1120. pos += ret;
  1121. first = 0;
  1122. }
  1123. if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP104) {
  1124. ret = os_snprintf(pos, end - pos, "%sWEP104",
  1125. first ? "" : " ");
  1126. if (ret < 0 || ret >= end - pos)
  1127. return pos - buf;
  1128. pos += ret;
  1129. first = 0;
  1130. }
  1131. if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP40) {
  1132. ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : " ");
  1133. if (ret < 0 || ret >= end - pos)
  1134. return pos - buf;
  1135. pos += ret;
  1136. first = 0;
  1137. }
  1138. return pos - buf;
  1139. }
  1140. static int ctrl_iface_get_capability_key_mgmt(int res, char *strict,
  1141. struct wpa_driver_capa *capa,
  1142. char *buf, size_t buflen)
  1143. {
  1144. int ret;
  1145. char *pos, *end;
  1146. size_t len;
  1147. pos = buf;
  1148. end = pos + buflen;
  1149. if (res < 0) {
  1150. if (strict)
  1151. return 0;
  1152. len = os_strlcpy(buf, "WPA-PSK WPA-EAP IEEE8021X WPA-NONE "
  1153. "NONE", buflen);
  1154. if (len >= buflen)
  1155. return -1;
  1156. return len;
  1157. }
  1158. ret = os_snprintf(pos, end - pos, "NONE IEEE8021X");
  1159. if (ret < 0 || ret >= end - pos)
  1160. return pos - buf;
  1161. pos += ret;
  1162. if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
  1163. WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
  1164. ret = os_snprintf(pos, end - pos, " WPA-EAP");
  1165. if (ret < 0 || ret >= end - pos)
  1166. return pos - buf;
  1167. pos += ret;
  1168. }
  1169. if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
  1170. WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
  1171. ret = os_snprintf(pos, end - pos, " WPA-PSK");
  1172. if (ret < 0 || ret >= end - pos)
  1173. return pos - buf;
  1174. pos += ret;
  1175. }
  1176. if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
  1177. ret = os_snprintf(pos, end - pos, " WPA-NONE");
  1178. if (ret < 0 || ret >= end - pos)
  1179. return pos - buf;
  1180. pos += ret;
  1181. }
  1182. return pos - buf;
  1183. }
  1184. static int ctrl_iface_get_capability_proto(int res, char *strict,
  1185. struct wpa_driver_capa *capa,
  1186. char *buf, size_t buflen)
  1187. {
  1188. int ret, first = 1;
  1189. char *pos, *end;
  1190. size_t len;
  1191. pos = buf;
  1192. end = pos + buflen;
  1193. if (res < 0) {
  1194. if (strict)
  1195. return 0;
  1196. len = os_strlcpy(buf, "RSN WPA", buflen);
  1197. if (len >= buflen)
  1198. return -1;
  1199. return len;
  1200. }
  1201. if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
  1202. WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
  1203. ret = os_snprintf(pos, end - pos, "%sRSN", first ? "" : " ");
  1204. if (ret < 0 || ret >= end - pos)
  1205. return pos - buf;
  1206. pos += ret;
  1207. first = 0;
  1208. }
  1209. if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
  1210. WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
  1211. ret = os_snprintf(pos, end - pos, "%sWPA", first ? "" : " ");
  1212. if (ret < 0 || ret >= end - pos)
  1213. return pos - buf;
  1214. pos += ret;
  1215. first = 0;
  1216. }
  1217. return pos - buf;
  1218. }
  1219. static int ctrl_iface_get_capability_auth_alg(int res, char *strict,
  1220. struct wpa_driver_capa *capa,
  1221. char *buf, size_t buflen)
  1222. {
  1223. int ret, first = 1;
  1224. char *pos, *end;
  1225. size_t len;
  1226. pos = buf;
  1227. end = pos + buflen;
  1228. if (res < 0) {
  1229. if (strict)
  1230. return 0;
  1231. len = os_strlcpy(buf, "OPEN SHARED LEAP", buflen);
  1232. if (len >= buflen)
  1233. return -1;
  1234. return len;
  1235. }
  1236. if (capa->auth & (WPA_DRIVER_AUTH_OPEN)) {
  1237. ret = os_snprintf(pos, end - pos, "%sOPEN", first ? "" : " ");
  1238. if (ret < 0 || ret >= end - pos)
  1239. return pos - buf;
  1240. pos += ret;
  1241. first = 0;
  1242. }
  1243. if (capa->auth & (WPA_DRIVER_AUTH_SHARED)) {
  1244. ret = os_snprintf(pos, end - pos, "%sSHARED",
  1245. first ? "" : " ");
  1246. if (ret < 0 || ret >= end - pos)
  1247. return pos - buf;
  1248. pos += ret;
  1249. first = 0;
  1250. }
  1251. if (capa->auth & (WPA_DRIVER_AUTH_LEAP)) {
  1252. ret = os_snprintf(pos, end - pos, "%sLEAP", first ? "" : " ");
  1253. if (ret < 0 || ret >= end - pos)
  1254. return pos - buf;
  1255. pos += ret;
  1256. first = 0;
  1257. }
  1258. return pos - buf;
  1259. }
  1260. static int wpa_supplicant_ctrl_iface_get_capability(
  1261. struct wpa_supplicant *wpa_s, const char *_field, char *buf,
  1262. size_t buflen)
  1263. {
  1264. struct wpa_driver_capa capa;
  1265. int res;
  1266. char *strict;
  1267. char field[30];
  1268. size_t len;
  1269. /* Determine whether or not strict checking was requested */
  1270. len = os_strlcpy(field, _field, sizeof(field));
  1271. if (len >= sizeof(field))
  1272. return -1;
  1273. strict = os_strchr(field, ' ');
  1274. if (strict != NULL) {
  1275. *strict++ = '\0';
  1276. if (os_strcmp(strict, "strict") != 0)
  1277. return -1;
  1278. }
  1279. wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s",
  1280. field, strict ? strict : "");
  1281. if (os_strcmp(field, "eap") == 0) {
  1282. return eap_get_names(buf, buflen);
  1283. }
  1284. res = wpa_drv_get_capa(wpa_s, &capa);
  1285. if (os_strcmp(field, "pairwise") == 0)
  1286. return ctrl_iface_get_capability_pairwise(res, strict, &capa,
  1287. buf, buflen);
  1288. if (os_strcmp(field, "group") == 0)
  1289. return ctrl_iface_get_capability_group(res, strict, &capa,
  1290. buf, buflen);
  1291. if (os_strcmp(field, "key_mgmt") == 0)
  1292. return ctrl_iface_get_capability_key_mgmt(res, strict, &capa,
  1293. buf, buflen);
  1294. if (os_strcmp(field, "proto") == 0)
  1295. return ctrl_iface_get_capability_proto(res, strict, &capa,
  1296. buf, buflen);
  1297. if (os_strcmp(field, "auth_alg") == 0)
  1298. return ctrl_iface_get_capability_auth_alg(res, strict, &capa,
  1299. buf, buflen);
  1300. wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
  1301. field);
  1302. return -1;
  1303. }
  1304. static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s,
  1305. const char *cmd, char *buf,
  1306. size_t buflen)
  1307. {
  1308. u8 bssid[ETH_ALEN];
  1309. size_t i;
  1310. struct wpa_bss *bss;
  1311. int ret;
  1312. char *pos, *end;
  1313. const u8 *ie, *ie2;
  1314. if (os_strcmp(cmd, "FIRST") == 0)
  1315. bss = dl_list_first(&wpa_s->bss, struct wpa_bss, list);
  1316. else if (os_strncmp(cmd, "ID-", 3) == 0) {
  1317. i = atoi(cmd + 3);
  1318. bss = wpa_bss_get_id(wpa_s, i);
  1319. } else if (os_strncmp(cmd, "NEXT-", 5) == 0) {
  1320. i = atoi(cmd + 5);
  1321. bss = wpa_bss_get_id(wpa_s, i);
  1322. if (bss) {
  1323. struct dl_list *next = bss->list_id.next;
  1324. if (next == &wpa_s->bss_id)
  1325. bss = NULL;
  1326. else
  1327. bss = dl_list_entry(next, struct wpa_bss,
  1328. list_id);
  1329. }
  1330. } else if (hwaddr_aton(cmd, bssid) == 0)
  1331. bss = wpa_bss_get_bssid(wpa_s, bssid);
  1332. else {
  1333. struct wpa_bss *tmp;
  1334. i = atoi(cmd);
  1335. bss = NULL;
  1336. dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id)
  1337. {
  1338. if (i-- == 0) {
  1339. bss = tmp;
  1340. break;
  1341. }
  1342. }
  1343. }
  1344. if (bss == NULL)
  1345. return 0;
  1346. pos = buf;
  1347. end = buf + buflen;
  1348. ret = os_snprintf(pos, end - pos,
  1349. "id=%u\n"
  1350. "bssid=" MACSTR "\n"
  1351. "freq=%d\n"
  1352. "beacon_int=%d\n"
  1353. "capabilities=0x%04x\n"
  1354. "qual=%d\n"
  1355. "noise=%d\n"
  1356. "level=%d\n"
  1357. "tsf=%016llu\n"
  1358. "ie=",
  1359. bss->id,
  1360. MAC2STR(bss->bssid), bss->freq, bss->beacon_int,
  1361. bss->caps, bss->qual, bss->noise, bss->level,
  1362. (unsigned long long) bss->tsf);
  1363. if (ret < 0 || ret >= end - pos)
  1364. return pos - buf;
  1365. pos += ret;
  1366. ie = (const u8 *) (bss + 1);
  1367. for (i = 0; i < bss->ie_len; i++) {
  1368. ret = os_snprintf(pos, end - pos, "%02x", *ie++);
  1369. if (ret < 0 || ret >= end - pos)
  1370. return pos - buf;
  1371. pos += ret;
  1372. }
  1373. ret = os_snprintf(pos, end - pos, "\n");
  1374. if (ret < 0 || ret >= end - pos)
  1375. return pos - buf;
  1376. pos += ret;
  1377. ret = os_snprintf(pos, end - pos, "flags=");
  1378. if (ret < 0 || ret >= end - pos)
  1379. return pos - buf;
  1380. pos += ret;
  1381. ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
  1382. if (ie)
  1383. pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]);
  1384. ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN);
  1385. if (ie2)
  1386. pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, 2 + ie2[1]);
  1387. pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
  1388. if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
  1389. ret = os_snprintf(pos, end - pos, "[WEP]");
  1390. if (ret < 0 || ret >= end - pos)
  1391. return pos - buf;
  1392. pos += ret;
  1393. }
  1394. if (bss->caps & IEEE80211_CAP_IBSS) {
  1395. ret = os_snprintf(pos, end - pos, "[IBSS]");
  1396. if (ret < 0 || ret >= end - pos)
  1397. return pos - buf;
  1398. pos += ret;
  1399. }
  1400. if (bss->caps & IEEE80211_CAP_ESS) {
  1401. ret = os_snprintf(pos, end - pos, "[ESS]");
  1402. if (ret < 0 || ret >= end - pos)
  1403. return pos - buf;
  1404. pos += ret;
  1405. }
  1406. ret = os_snprintf(pos, end - pos, "\n");
  1407. if (ret < 0 || ret >= end - pos)
  1408. return pos - buf;
  1409. pos += ret;
  1410. ret = os_snprintf(pos, end - pos, "ssid=%s\n",
  1411. wpa_ssid_txt(bss->ssid, bss->ssid_len));
  1412. if (ret < 0 || ret >= end - pos)
  1413. return pos - buf;
  1414. pos += ret;
  1415. #ifdef CONFIG_WPS
  1416. ie = (const u8 *) (bss + 1);
  1417. ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end);
  1418. if (ret < 0 || ret >= end - pos)
  1419. return pos - buf;
  1420. pos += ret;
  1421. #endif /* CONFIG_WPS */
  1422. return pos - buf;
  1423. }
  1424. static int wpa_supplicant_ctrl_iface_ap_scan(
  1425. struct wpa_supplicant *wpa_s, char *cmd)
  1426. {
  1427. int ap_scan = atoi(cmd);
  1428. return wpa_supplicant_set_ap_scan(wpa_s, ap_scan);
  1429. }
  1430. static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s)
  1431. {
  1432. u8 *bcast = (u8 *) "\xff\xff\xff\xff\xff\xff";
  1433. wpa_printf(MSG_DEBUG, "Dropping SA without deauthentication");
  1434. /* MLME-DELETEKEYS.request */
  1435. wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 0, 0, NULL, 0, NULL, 0);
  1436. wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 1, 0, NULL, 0, NULL, 0);
  1437. wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 2, 0, NULL, 0, NULL, 0);
  1438. wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 3, 0, NULL, 0, NULL, 0);
  1439. #ifdef CONFIG_IEEE80211W
  1440. wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 4, 0, NULL, 0, NULL, 0);
  1441. wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 5, 0, NULL, 0, NULL, 0);
  1442. #endif /* CONFIG_IEEE80211W */
  1443. wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0, NULL,
  1444. 0);
  1445. /* MLME-SETPROTECTION.request(None) */
  1446. wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid,
  1447. MLME_SETPROTECTION_PROTECT_TYPE_NONE,
  1448. MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
  1449. wpa_sm_drop_sa(wpa_s->wpa);
  1450. }
  1451. static int wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant *wpa_s,
  1452. char *addr)
  1453. {
  1454. u8 bssid[ETH_ALEN];
  1455. struct wpa_bss *bss;
  1456. struct wpa_ssid *ssid = wpa_s->current_ssid;
  1457. if (hwaddr_aton(addr, bssid)) {
  1458. wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: invalid "
  1459. "address '%s'", addr);
  1460. return -1;
  1461. }
  1462. wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM " MACSTR, MAC2STR(bssid));
  1463. bss = wpa_bss_get_bssid(wpa_s, bssid);
  1464. if (!bss) {
  1465. wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: Target AP not found "
  1466. "from BSS table");
  1467. return -1;
  1468. }
  1469. /*
  1470. * TODO: Find best network configuration block from configuration to
  1471. * allow roaming to other networks
  1472. */
  1473. if (!ssid) {
  1474. wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: No network "
  1475. "configuration known for the target AP");
  1476. return -1;
  1477. }
  1478. wpa_s->reassociate = 1;
  1479. wpa_supplicant_connect(wpa_s, bss, ssid);
  1480. return 0;
  1481. }
  1482. char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
  1483. char *buf, size_t *resp_len)
  1484. {
  1485. char *reply;
  1486. const int reply_size = 2048;
  1487. int ctrl_rsp = 0;
  1488. int reply_len;
  1489. if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 ||
  1490. os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
  1491. wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
  1492. (const u8 *) buf, os_strlen(buf));
  1493. } else {
  1494. wpa_hexdump_ascii(MSG_DEBUG, "RX ctrl_iface",
  1495. (const u8 *) buf, os_strlen(buf));
  1496. }
  1497. reply = os_malloc(reply_size);
  1498. if (reply == NULL) {
  1499. *resp_len = 1;
  1500. return NULL;
  1501. }
  1502. os_memcpy(reply, "OK\n", 3);
  1503. reply_len = 3;
  1504. if (os_strcmp(buf, "PING") == 0) {
  1505. os_memcpy(reply, "PONG\n", 5);
  1506. reply_len = 5;
  1507. } else if (os_strncmp(buf, "NOTE ", 5) == 0) {
  1508. wpa_printf(MSG_INFO, "NOTE: %s", buf + 5);
  1509. } else if (os_strcmp(buf, "MIB") == 0) {
  1510. reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
  1511. if (reply_len >= 0) {
  1512. int res;
  1513. res = eapol_sm_get_mib(wpa_s->eapol, reply + reply_len,
  1514. reply_size - reply_len);
  1515. if (res < 0)
  1516. reply_len = -1;
  1517. else
  1518. reply_len += res;
  1519. }
  1520. } else if (os_strncmp(buf, "STATUS", 6) == 0) {
  1521. reply_len = wpa_supplicant_ctrl_iface_status(
  1522. wpa_s, buf + 6, reply, reply_size);
  1523. } else if (os_strcmp(buf, "PMKSA") == 0) {
  1524. reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, reply,
  1525. reply_size);
  1526. } else if (os_strncmp(buf, "SET ", 4) == 0) {
  1527. if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
  1528. reply_len = -1;
  1529. } else if (os_strcmp(buf, "LOGON") == 0) {
  1530. eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
  1531. } else if (os_strcmp(buf, "LOGOFF") == 0) {
  1532. eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
  1533. } else if (os_strcmp(buf, "REASSOCIATE") == 0) {
  1534. if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
  1535. reply_len = -1;
  1536. else {
  1537. wpa_s->disconnected = 0;
  1538. wpa_s->reassociate = 1;
  1539. wpa_supplicant_req_scan(wpa_s, 0, 0);
  1540. }
  1541. } else if (os_strcmp(buf, "RECONNECT") == 0) {
  1542. if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
  1543. reply_len = -1;
  1544. else if (wpa_s->disconnected) {
  1545. wpa_s->disconnected = 0;
  1546. wpa_s->reassociate = 1;
  1547. wpa_supplicant_req_scan(wpa_s, 0, 0);
  1548. }
  1549. #ifdef IEEE8021X_EAPOL
  1550. } else if (os_strncmp(buf, "PREAUTH ", 8) == 0) {
  1551. if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
  1552. reply_len = -1;
  1553. #endif /* IEEE8021X_EAPOL */
  1554. #ifdef CONFIG_PEERKEY
  1555. } else if (os_strncmp(buf, "STKSTART ", 9) == 0) {
  1556. if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9))
  1557. reply_len = -1;
  1558. #endif /* CONFIG_PEERKEY */
  1559. #ifdef CONFIG_IEEE80211R
  1560. } else if (os_strncmp(buf, "FT_DS ", 6) == 0) {
  1561. if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6))
  1562. reply_len = -1;
  1563. #endif /* CONFIG_IEEE80211R */
  1564. #ifdef CONFIG_WPS
  1565. } else if (os_strcmp(buf, "WPS_PBC") == 0) {
  1566. if (wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, NULL))
  1567. reply_len = -1;
  1568. } else if (os_strncmp(buf, "WPS_PBC ", 8) == 0) {
  1569. if (wpa_supplicant_ctrl_iface_wps_pbc(wpa_s, buf + 8))
  1570. reply_len = -1;
  1571. } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
  1572. reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8,
  1573. reply,
  1574. reply_size);
  1575. #ifdef CONFIG_WPS_OOB
  1576. } else if (os_strncmp(buf, "WPS_OOB ", 8) == 0) {
  1577. if (wpa_supplicant_ctrl_iface_wps_oob(wpa_s, buf + 8))
  1578. reply_len = -1;
  1579. #endif /* CONFIG_WPS_OOB */
  1580. } else if (os_strncmp(buf, "WPS_REG ", 8) == 0) {
  1581. if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8))
  1582. reply_len = -1;
  1583. #ifdef CONFIG_WPS_ER
  1584. } else if (os_strcmp(buf, "WPS_ER_START") == 0) {
  1585. if (wpas_wps_er_start(wpa_s, NULL))
  1586. reply_len = -1;
  1587. } else if (os_strncmp(buf, "WPS_ER_START ", 13) == 0) {
  1588. if (wpas_wps_er_start(wpa_s, buf + 13))
  1589. reply_len = -1;
  1590. } else if (os_strcmp(buf, "WPS_ER_STOP") == 0) {
  1591. if (wpas_wps_er_stop(wpa_s))
  1592. reply_len = -1;
  1593. } else if (os_strncmp(buf, "WPS_ER_PIN ", 11) == 0) {
  1594. if (wpa_supplicant_ctrl_iface_wps_er_pin(wpa_s, buf + 11))
  1595. reply_len = -1;
  1596. } else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) {
  1597. if (wpas_wps_er_pbc(wpa_s, buf + 11))
  1598. reply_len = -1;
  1599. } else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) {
  1600. if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13))
  1601. reply_len = -1;
  1602. } else if (os_strncmp(buf, "WPS_ER_CONFIG ", 14) == 0) {
  1603. if (wpa_supplicant_ctrl_iface_wps_er_config(wpa_s, buf + 14))
  1604. reply_len = -1;
  1605. #endif /* CONFIG_WPS_ER */
  1606. #endif /* CONFIG_WPS */
  1607. #ifdef CONFIG_IBSS_RSN
  1608. } else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) {
  1609. if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9))
  1610. reply_len = -1;
  1611. #endif /* CONFIG_IBSS_RSN */
  1612. } else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0)
  1613. {
  1614. if (wpa_supplicant_ctrl_iface_ctrl_rsp(
  1615. wpa_s, buf + os_strlen(WPA_CTRL_RSP)))
  1616. reply_len = -1;
  1617. else
  1618. ctrl_rsp = 1;
  1619. } else if (os_strcmp(buf, "RECONFIGURE") == 0) {
  1620. if (wpa_supplicant_reload_configuration(wpa_s))
  1621. reply_len = -1;
  1622. } else if (os_strcmp(buf, "TERMINATE") == 0) {
  1623. wpa_supplicant_terminate_proc(wpa_s->global);
  1624. } else if (os_strncmp(buf, "BSSID ", 6) == 0) {
  1625. if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
  1626. reply_len = -1;
  1627. } else if (os_strcmp(buf, "LIST_NETWORKS") == 0) {
  1628. reply_len = wpa_supplicant_ctrl_iface_list_networks(
  1629. wpa_s, reply, reply_size);
  1630. } else if (os_strcmp(buf, "DISCONNECT") == 0) {
  1631. wpa_s->reassociate = 0;
  1632. wpa_s->disconnected = 1;
  1633. wpa_supplicant_deauthenticate(wpa_s,
  1634. WLAN_REASON_DEAUTH_LEAVING);
  1635. } else if (os_strcmp(buf, "SCAN") == 0) {
  1636. if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
  1637. reply_len = -1;
  1638. else {
  1639. wpa_s->scan_req = 2;
  1640. wpa_supplicant_req_scan(wpa_s, 0, 0);
  1641. }
  1642. } else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
  1643. reply_len = wpa_supplicant_ctrl_iface_scan_results(
  1644. wpa_s, reply, reply_size);
  1645. } else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
  1646. if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
  1647. reply_len = -1;
  1648. } else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) {
  1649. if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15))
  1650. reply_len = -1;
  1651. } else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) {
  1652. if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16))
  1653. reply_len = -1;
  1654. } else if (os_strcmp(buf, "ADD_NETWORK") == 0) {
  1655. reply_len = wpa_supplicant_ctrl_iface_add_network(
  1656. wpa_s, reply, reply_size);
  1657. } else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) {
  1658. if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15))
  1659. reply_len = -1;
  1660. } else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
  1661. if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12))
  1662. reply_len = -1;
  1663. } else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) {
  1664. reply_len = wpa_supplicant_ctrl_iface_get_network(
  1665. wpa_s, buf + 12, reply, reply_size);
  1666. #ifndef CONFIG_NO_CONFIG_WRITE
  1667. } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
  1668. if (wpa_supplicant_ctrl_iface_save_config(wpa_s))
  1669. reply_len = -1;
  1670. #endif /* CONFIG_NO_CONFIG_WRITE */
  1671. } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
  1672. reply_len = wpa_supplicant_ctrl_iface_get_capability(
  1673. wpa_s, buf + 15, reply, reply_size);
  1674. } else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) {
  1675. if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8))
  1676. reply_len = -1;
  1677. } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
  1678. reply_len = wpa_supplicant_global_iface_list(
  1679. wpa_s->global, reply, reply_size);
  1680. } else if (os_strcmp(buf, "INTERFACES") == 0) {
  1681. reply_len = wpa_supplicant_global_iface_interfaces(
  1682. wpa_s->global, reply, reply_size);
  1683. } else if (os_strncmp(buf, "BSS ", 4) == 0) {
  1684. reply_len = wpa_supplicant_ctrl_iface_bss(
  1685. wpa_s, buf + 4, reply, reply_size);
  1686. #ifdef CONFIG_AP
  1687. } else if (os_strcmp(buf, "STA-FIRST") == 0) {
  1688. reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size);
  1689. } else if (os_strncmp(buf, "STA ", 4) == 0) {
  1690. reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply,
  1691. reply_size);
  1692. } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
  1693. reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
  1694. reply_size);
  1695. #endif /* CONFIG_AP */
  1696. } else if (os_strcmp(buf, "SUSPEND") == 0) {
  1697. wpas_notify_suspend(wpa_s->global);
  1698. } else if (os_strcmp(buf, "RESUME") == 0) {
  1699. wpas_notify_resume(wpa_s->global);
  1700. } else if (os_strcmp(buf, "DROP_SA") == 0) {
  1701. wpa_supplicant_ctrl_iface_drop_sa(wpa_s);
  1702. } else if (os_strncmp(buf, "ROAM ", 5) == 0) {
  1703. if (wpa_supplicant_ctrl_iface_roam(wpa_s, buf + 5))
  1704. reply_len = -1;
  1705. } else {
  1706. os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
  1707. reply_len = 16;
  1708. }
  1709. if (reply_len < 0) {
  1710. os_memcpy(reply, "FAIL\n", 5);
  1711. reply_len = 5;
  1712. }
  1713. if (ctrl_rsp)
  1714. eapol_sm_notify_ctrl_response(wpa_s->eapol);
  1715. *resp_len = reply_len;
  1716. return reply;
  1717. }
  1718. static int wpa_supplicant_global_iface_add(struct wpa_global *global,
  1719. char *cmd)
  1720. {
  1721. struct wpa_interface iface;
  1722. char *pos;
  1723. /*
  1724. * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
  1725. * TAB<bridge_ifname>
  1726. */
  1727. wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
  1728. os_memset(&iface, 0, sizeof(iface));
  1729. do {
  1730. iface.ifname = pos = cmd;
  1731. pos = os_strchr(pos, '\t');
  1732. if (pos)
  1733. *pos++ = '\0';
  1734. if (iface.ifname[0] == '\0')
  1735. return -1;
  1736. if (pos == NULL)
  1737. break;
  1738. iface.confname = pos;
  1739. pos = os_strchr(pos, '\t');
  1740. if (pos)
  1741. *pos++ = '\0';
  1742. if (iface.confname[0] == '\0')
  1743. iface.confname = NULL;
  1744. if (pos == NULL)
  1745. break;
  1746. iface.driver = pos;
  1747. pos = os_strchr(pos, '\t');
  1748. if (pos)
  1749. *pos++ = '\0';
  1750. if (iface.driver[0] == '\0')
  1751. iface.driver = NULL;
  1752. if (pos == NULL)
  1753. break;
  1754. iface.ctrl_interface = pos;
  1755. pos = os_strchr(pos, '\t');
  1756. if (pos)
  1757. *pos++ = '\0';
  1758. if (iface.ctrl_interface[0] == '\0')
  1759. iface.ctrl_interface = NULL;
  1760. if (pos == NULL)
  1761. break;
  1762. iface.driver_param = pos;
  1763. pos = os_strchr(pos, '\t');
  1764. if (pos)
  1765. *pos++ = '\0';
  1766. if (iface.driver_param[0] == '\0')
  1767. iface.driver_param = NULL;
  1768. if (pos == NULL)
  1769. break;
  1770. iface.bridge_ifname = pos;
  1771. pos = os_strchr(pos, '\t');
  1772. if (pos)
  1773. *pos++ = '\0';
  1774. if (iface.bridge_ifname[0] == '\0')
  1775. iface.bridge_ifname = NULL;
  1776. if (pos == NULL)
  1777. break;
  1778. } while (0);
  1779. if (wpa_supplicant_get_iface(global, iface.ifname))
  1780. return -1;
  1781. return wpa_supplicant_add_iface(global, &iface) ? 0 : -1;
  1782. }
  1783. static int wpa_supplicant_global_iface_remove(struct wpa_global *global,
  1784. char *cmd)
  1785. {
  1786. struct wpa_supplicant *wpa_s;
  1787. wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);
  1788. wpa_s = wpa_supplicant_get_iface(global, cmd);
  1789. if (wpa_s == NULL)
  1790. return -1;
  1791. return wpa_supplicant_remove_iface(global, wpa_s);
  1792. }
  1793. static void wpa_free_iface_info(struct wpa_interface_info *iface)
  1794. {
  1795. struct wpa_interface_info *prev;
  1796. while (iface) {
  1797. prev = iface;
  1798. iface = iface->next;
  1799. os_free(prev->ifname);
  1800. os_free(prev->desc);
  1801. os_free(prev);
  1802. }
  1803. }
  1804. static int wpa_supplicant_global_iface_list(struct wpa_global *global,
  1805. char *buf, int len)
  1806. {
  1807. int i, res;
  1808. struct wpa_interface_info *iface = NULL, *last = NULL, *tmp;
  1809. char *pos, *end;
  1810. for (i = 0; wpa_drivers[i]; i++) {
  1811. struct wpa_driver_ops *drv = wpa_drivers[i];
  1812. if (drv->get_interfaces == NULL)
  1813. continue;
  1814. tmp = drv->get_interfaces(global->drv_priv[i]);
  1815. if (tmp == NULL)
  1816. continue;
  1817. if (last == NULL)
  1818. iface = last = tmp;
  1819. else
  1820. last->next = tmp;
  1821. while (last->next)
  1822. last = last->next;
  1823. }
  1824. pos = buf;
  1825. end = buf + len;
  1826. for (tmp = iface; tmp; tmp = tmp->next) {
  1827. res = os_snprintf(pos, end - pos, "%s\t%s\t%s\n",
  1828. tmp->drv_name, tmp->ifname,
  1829. tmp->desc ? tmp->desc : "");
  1830. if (res < 0 || res >= end - pos) {
  1831. *pos = '\0';
  1832. break;
  1833. }
  1834. pos += res;
  1835. }
  1836. wpa_free_iface_info(iface);
  1837. return pos - buf;
  1838. }
  1839. static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
  1840. char *buf, int len)
  1841. {
  1842. int res;
  1843. char *pos, *end;
  1844. struct wpa_supplicant *wpa_s;
  1845. wpa_s = global->ifaces;
  1846. pos = buf;
  1847. end = buf + len;
  1848. while (wpa_s) {
  1849. res = os_snprintf(pos, end - pos, "%s\n", wpa_s->ifname);
  1850. if (res < 0 || res >= end - pos) {
  1851. *pos = '\0';
  1852. break;
  1853. }
  1854. pos += res;
  1855. wpa_s = wpa_s->next;
  1856. }
  1857. return pos - buf;
  1858. }
  1859. char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
  1860. char *buf, size_t *resp_len)
  1861. {
  1862. char *reply;
  1863. const int reply_size = 2048;
  1864. int reply_len;
  1865. wpa_hexdump_ascii(MSG_DEBUG, "RX global ctrl_iface",
  1866. (const u8 *) buf, os_strlen(buf));
  1867. reply = os_malloc(reply_size);
  1868. if (reply == NULL) {
  1869. *resp_len = 1;
  1870. return NULL;
  1871. }
  1872. os_memcpy(reply, "OK\n", 3);
  1873. reply_len = 3;
  1874. if (os_strcmp(buf, "PING") == 0) {
  1875. os_memcpy(reply, "PONG\n", 5);
  1876. reply_len = 5;
  1877. } else if (os_strncmp(buf, "INTERFACE_ADD ", 14) == 0) {
  1878. if (wpa_supplicant_global_iface_add(global, buf + 14))
  1879. reply_len = -1;
  1880. } else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) {
  1881. if (wpa_supplicant_global_iface_remove(global, buf + 17))
  1882. reply_len = -1;
  1883. } else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
  1884. reply_len = wpa_supplicant_global_iface_list(
  1885. global, reply, reply_size);
  1886. } else if (os_strcmp(buf, "INTERFACES") == 0) {
  1887. reply_len = wpa_supplicant_global_iface_interfaces(
  1888. global, reply, reply_size);
  1889. } else if (os_strcmp(buf, "TERMINATE") == 0) {
  1890. wpa_supplicant_terminate_proc(global);
  1891. } else if (os_strcmp(buf, "SUSPEND") == 0) {
  1892. wpas_notify_suspend(global);
  1893. } else if (os_strcmp(buf, "RESUME") == 0) {
  1894. wpas_notify_resume(global);
  1895. } else {
  1896. os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
  1897. reply_len = 16;
  1898. }
  1899. if (reply_len < 0) {
  1900. os_memcpy(reply, "FAIL\n", 5);
  1901. reply_len = 5;
  1902. }
  1903. *resp_len = reply_len;
  1904. return reply;
  1905. }