driver_bsd.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789
  1. /*
  2. * WPA Supplicant - driver interaction with BSD net80211 layer
  3. * Copyright (c) 2004, Sam Leffler <sam@errno.com>
  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 "includes.h"
  15. #include <sys/ioctl.h>
  16. #include "common.h"
  17. #include "driver.h"
  18. #include "eloop.h"
  19. #include "ieee802_11_defs.h"
  20. #include <net/if.h>
  21. #include <net/ethernet.h>
  22. #include <net80211/ieee80211.h>
  23. #include <net80211/ieee80211_crypto.h>
  24. #include <net80211/ieee80211_ioctl.h>
  25. struct wpa_driver_bsd_data {
  26. int sock; /* open socket for 802.11 ioctls */
  27. int route; /* routing socket for events */
  28. char ifname[IFNAMSIZ+1]; /* interface name */
  29. unsigned int ifindex; /* interface index */
  30. void *ctx;
  31. int prev_roaming; /* roaming state to restore on deinit */
  32. int prev_privacy; /* privacy state to restore on deinit */
  33. int prev_wpa; /* wpa state to restore on deinit */
  34. };
  35. static int
  36. set80211var(struct wpa_driver_bsd_data *drv, int op, const void *arg, int arg_len)
  37. {
  38. struct ieee80211req ireq;
  39. os_memset(&ireq, 0, sizeof(ireq));
  40. os_strlcpy(ireq.i_name, drv->ifname, IFNAMSIZ);
  41. ireq.i_type = op;
  42. ireq.i_len = arg_len;
  43. ireq.i_data = (void *) arg;
  44. if (ioctl(drv->sock, SIOCS80211, &ireq) < 0) {
  45. fprintf(stderr, "ioctl[SIOCS80211, op %u, len %u]: %s\n",
  46. op, arg_len, strerror(errno));
  47. return -1;
  48. }
  49. return 0;
  50. }
  51. static int
  52. get80211var(struct wpa_driver_bsd_data *drv, int op, void *arg, int arg_len)
  53. {
  54. struct ieee80211req ireq;
  55. os_memset(&ireq, 0, sizeof(ireq));
  56. os_strlcpy(ireq.i_name, drv->ifname, IFNAMSIZ);
  57. ireq.i_type = op;
  58. ireq.i_len = arg_len;
  59. ireq.i_data = arg;
  60. if (ioctl(drv->sock, SIOCG80211, &ireq) < 0) {
  61. fprintf(stderr, "ioctl[SIOCG80211, op %u, len %u]: %s\n",
  62. op, arg_len, strerror(errno));
  63. return -1;
  64. }
  65. return ireq.i_len;
  66. }
  67. static int
  68. set80211param(struct wpa_driver_bsd_data *drv, int op, int arg)
  69. {
  70. struct ieee80211req ireq;
  71. os_memset(&ireq, 0, sizeof(ireq));
  72. os_strlcpy(ireq.i_name, drv->ifname, IFNAMSIZ);
  73. ireq.i_type = op;
  74. ireq.i_val = arg;
  75. if (ioctl(drv->sock, SIOCS80211, &ireq) < 0) {
  76. fprintf(stderr, "ioctl[SIOCS80211, op %u, arg 0x%x]: %s\n",
  77. op, arg, strerror(errno));
  78. return -1;
  79. }
  80. return 0;
  81. }
  82. static int
  83. get80211param(struct wpa_driver_bsd_data *drv, int op)
  84. {
  85. struct ieee80211req ireq;
  86. os_memset(&ireq, 0, sizeof(ireq));
  87. os_strlcpy(ireq.i_name, drv->ifname, IFNAMSIZ);
  88. ireq.i_type = op;
  89. if (ioctl(drv->sock, SIOCG80211, &ireq) < 0) {
  90. fprintf(stderr, "ioctl[SIOCG80211, op %u]: %s\n",
  91. op, strerror(errno));
  92. return -1;
  93. }
  94. return ireq.i_val;
  95. }
  96. static int
  97. getifflags(struct wpa_driver_bsd_data *drv, int *flags)
  98. {
  99. struct ifreq ifr;
  100. os_memset(&ifr, 0, sizeof(ifr));
  101. os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name));
  102. if (ioctl(drv->sock, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
  103. perror("SIOCGIFFLAGS");
  104. return errno;
  105. }
  106. *flags = ifr.ifr_flags & 0xffff;
  107. return 0;
  108. }
  109. static int
  110. setifflags(struct wpa_driver_bsd_data *drv, int flags)
  111. {
  112. struct ifreq ifr;
  113. os_memset(&ifr, 0, sizeof(ifr));
  114. os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name));
  115. ifr.ifr_flags = flags & 0xffff;
  116. if (ioctl(drv->sock, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) {
  117. perror("SIOCSIFFLAGS");
  118. return errno;
  119. }
  120. return 0;
  121. }
  122. static int
  123. wpa_driver_bsd_get_bssid(void *priv, u8 *bssid)
  124. {
  125. struct wpa_driver_bsd_data *drv = priv;
  126. return get80211var(drv, IEEE80211_IOC_BSSID,
  127. bssid, IEEE80211_ADDR_LEN) < 0 ? -1 : 0;
  128. }
  129. #if 0
  130. static int
  131. wpa_driver_bsd_set_bssid(void *priv, const char *bssid)
  132. {
  133. struct wpa_driver_bsd_data *drv = priv;
  134. return set80211var(drv, IEEE80211_IOC_BSSID,
  135. bssid, IEEE80211_ADDR_LEN);
  136. }
  137. #endif
  138. static int
  139. wpa_driver_bsd_get_ssid(void *priv, u8 *ssid)
  140. {
  141. struct wpa_driver_bsd_data *drv = priv;
  142. return get80211var(drv, IEEE80211_IOC_SSID,
  143. ssid, IEEE80211_NWID_LEN);
  144. }
  145. static int
  146. wpa_driver_bsd_set_ssid(void *priv, const char *ssid,
  147. size_t ssid_len)
  148. {
  149. struct wpa_driver_bsd_data *drv = priv;
  150. return set80211var(drv, IEEE80211_IOC_SSID, ssid, ssid_len);
  151. }
  152. static int
  153. wpa_driver_bsd_set_wpa_ie(struct wpa_driver_bsd_data *drv,
  154. const char *wpa_ie, size_t wpa_ie_len)
  155. {
  156. return set80211var(drv, IEEE80211_IOC_OPTIE, wpa_ie, wpa_ie_len);
  157. }
  158. static int
  159. wpa_driver_bsd_set_wpa_internal(void *priv, int wpa, int privacy)
  160. {
  161. struct wpa_driver_bsd_data *drv = priv;
  162. int ret = 0;
  163. wpa_printf(MSG_DEBUG, "%s: wpa=%d privacy=%d",
  164. __FUNCTION__, wpa, privacy);
  165. if (!wpa && wpa_driver_bsd_set_wpa_ie(drv, NULL, 0) < 0)
  166. ret = -1;
  167. if (set80211param(drv, IEEE80211_IOC_PRIVACY, privacy) < 0)
  168. ret = -1;
  169. if (set80211param(drv, IEEE80211_IOC_WPA, wpa) < 0)
  170. ret = -1;
  171. return ret;
  172. }
  173. static int
  174. wpa_driver_bsd_set_wpa(void *priv, int enabled)
  175. {
  176. wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
  177. return wpa_driver_bsd_set_wpa_internal(priv, enabled ? 3 : 0, enabled);
  178. }
  179. static int
  180. wpa_driver_bsd_del_key(struct wpa_driver_bsd_data *drv, int key_idx,
  181. const unsigned char *addr)
  182. {
  183. struct ieee80211req_del_key wk;
  184. os_memset(&wk, 0, sizeof(wk));
  185. if (addr != NULL &&
  186. bcmp(addr, "\xff\xff\xff\xff\xff\xff", IEEE80211_ADDR_LEN) != 0) {
  187. struct ether_addr ea;
  188. os_memcpy(&ea, addr, IEEE80211_ADDR_LEN);
  189. wpa_printf(MSG_DEBUG, "%s: addr=%s keyidx=%d",
  190. __func__, ether_ntoa(&ea), key_idx);
  191. os_memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN);
  192. wk.idk_keyix = (uint8_t) IEEE80211_KEYIX_NONE;
  193. } else {
  194. wpa_printf(MSG_DEBUG, "%s: keyidx=%d", __func__, key_idx);
  195. wk.idk_keyix = key_idx;
  196. }
  197. return set80211var(drv, IEEE80211_IOC_DELKEY, &wk, sizeof(wk));
  198. }
  199. static int
  200. wpa_driver_bsd_set_key(void *priv, wpa_alg alg,
  201. const unsigned char *addr, int key_idx, int set_tx,
  202. const u8 *seq, size_t seq_len,
  203. const u8 *key, size_t key_len)
  204. {
  205. struct wpa_driver_bsd_data *drv = priv;
  206. struct ieee80211req_key wk;
  207. struct ether_addr ea;
  208. char *alg_name;
  209. u_int8_t cipher;
  210. if (alg == WPA_ALG_NONE)
  211. return wpa_driver_bsd_del_key(drv, key_idx, addr);
  212. switch (alg) {
  213. case WPA_ALG_WEP:
  214. alg_name = "WEP";
  215. cipher = IEEE80211_CIPHER_WEP;
  216. break;
  217. case WPA_ALG_TKIP:
  218. alg_name = "TKIP";
  219. cipher = IEEE80211_CIPHER_TKIP;
  220. break;
  221. case WPA_ALG_CCMP:
  222. alg_name = "CCMP";
  223. cipher = IEEE80211_CIPHER_AES_CCM;
  224. break;
  225. default:
  226. wpa_printf(MSG_DEBUG, "%s: unknown/unsupported algorithm %d",
  227. __func__, alg);
  228. return -1;
  229. }
  230. os_memcpy(&ea, addr, IEEE80211_ADDR_LEN);
  231. wpa_printf(MSG_DEBUG,
  232. "%s: alg=%s addr=%s key_idx=%d set_tx=%d seq_len=%zu key_len=%zu",
  233. __func__, alg_name, ether_ntoa(&ea), key_idx, set_tx,
  234. seq_len, key_len);
  235. if (seq_len > sizeof(u_int64_t)) {
  236. wpa_printf(MSG_DEBUG, "%s: seq_len %zu too big",
  237. __func__, seq_len);
  238. return -2;
  239. }
  240. if (key_len > sizeof(wk.ik_keydata)) {
  241. wpa_printf(MSG_DEBUG, "%s: key length %zu too big",
  242. __func__, key_len);
  243. return -3;
  244. }
  245. os_memset(&wk, 0, sizeof(wk));
  246. wk.ik_type = cipher;
  247. wk.ik_flags = IEEE80211_KEY_RECV;
  248. if (set_tx)
  249. wk.ik_flags |= IEEE80211_KEY_XMIT;
  250. os_memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
  251. /*
  252. * Deduce whether group/global or unicast key by checking
  253. * the address (yech). Note also that we can only mark global
  254. * keys default; doing this for a unicast key is an error.
  255. */
  256. if (bcmp(addr, "\xff\xff\xff\xff\xff\xff", IEEE80211_ADDR_LEN) == 0) {
  257. wk.ik_flags |= IEEE80211_KEY_GROUP;
  258. wk.ik_keyix = key_idx;
  259. } else {
  260. wk.ik_keyix = (key_idx == 0 ? IEEE80211_KEYIX_NONE : key_idx);
  261. }
  262. if (wk.ik_keyix != IEEE80211_KEYIX_NONE && set_tx)
  263. wk.ik_flags |= IEEE80211_KEY_DEFAULT;
  264. wk.ik_keylen = key_len;
  265. os_memcpy(&wk.ik_keyrsc, seq, seq_len);
  266. os_memcpy(wk.ik_keydata, key, key_len);
  267. return set80211var(drv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk));
  268. }
  269. static int
  270. wpa_driver_bsd_set_countermeasures(void *priv, int enabled)
  271. {
  272. struct wpa_driver_bsd_data *drv = priv;
  273. wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
  274. return set80211param(drv, IEEE80211_IOC_COUNTERMEASURES, enabled);
  275. }
  276. static int
  277. wpa_driver_bsd_set_drop_unencrypted(void *priv, int enabled)
  278. {
  279. struct wpa_driver_bsd_data *drv = priv;
  280. wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
  281. return set80211param(drv, IEEE80211_IOC_DROPUNENCRYPTED, enabled);
  282. }
  283. static int
  284. wpa_driver_bsd_deauthenticate(void *priv, const u8 *addr, int reason_code)
  285. {
  286. struct wpa_driver_bsd_data *drv = priv;
  287. struct ieee80211req_mlme mlme;
  288. wpa_printf(MSG_DEBUG, "%s", __func__);
  289. os_memset(&mlme, 0, sizeof(mlme));
  290. mlme.im_op = IEEE80211_MLME_DEAUTH;
  291. mlme.im_reason = reason_code;
  292. os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
  293. return set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme));
  294. }
  295. static int
  296. wpa_driver_bsd_disassociate(void *priv, const u8 *addr, int reason_code)
  297. {
  298. struct wpa_driver_bsd_data *drv = priv;
  299. struct ieee80211req_mlme mlme;
  300. wpa_printf(MSG_DEBUG, "%s", __func__);
  301. os_memset(&mlme, 0, sizeof(mlme));
  302. mlme.im_op = IEEE80211_MLME_DISASSOC;
  303. mlme.im_reason = reason_code;
  304. os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
  305. return set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme));
  306. }
  307. static int
  308. wpa_driver_bsd_associate(void *priv, struct wpa_driver_associate_params *params)
  309. {
  310. struct wpa_driver_bsd_data *drv = priv;
  311. struct ieee80211req_mlme mlme;
  312. int privacy;
  313. wpa_printf(MSG_DEBUG,
  314. "%s: ssid '%.*s' wpa ie len %u pairwise %u group %u key mgmt %u"
  315. , __func__
  316. , params->ssid_len, params->ssid
  317. , params->wpa_ie_len
  318. , params->pairwise_suite
  319. , params->group_suite
  320. , params->key_mgmt_suite
  321. );
  322. /* XXX error handling is wrong but unclear what to do... */
  323. if (wpa_driver_bsd_set_wpa_ie(drv, params->wpa_ie, params->wpa_ie_len) < 0)
  324. return -1;
  325. #ifndef NEW_FREEBSD_MLME_ASSOC
  326. if (wpa_driver_bsd_set_ssid(drv, params->ssid, params->ssid_len) < 0)
  327. return -1;
  328. #endif
  329. privacy = !(params->pairwise_suite == CIPHER_NONE &&
  330. params->group_suite == CIPHER_NONE &&
  331. params->key_mgmt_suite == KEY_MGMT_NONE &&
  332. params->wpa_ie_len == 0);
  333. wpa_printf(MSG_DEBUG, "%s: set PRIVACY %u", __func__, privacy);
  334. if (set80211param(drv, IEEE80211_IOC_PRIVACY, privacy) < 0)
  335. return -1;
  336. if (params->wpa_ie_len &&
  337. set80211param(drv, IEEE80211_IOC_WPA,
  338. params->wpa_ie[0] == WLAN_EID_RSN ? 2 : 1) < 0)
  339. return -1;
  340. os_memset(&mlme, 0, sizeof(mlme));
  341. mlme.im_op = IEEE80211_MLME_ASSOC;
  342. #ifdef NEW_FREEBSD_MLME_ASSOC
  343. if (params->ssid != NULL)
  344. os_memcpy(mlme.im_ssid, params->ssid, params->ssid_len);
  345. mlme.im_ssid_len = params->ssid_len;
  346. #endif
  347. if (params->bssid != NULL)
  348. os_memcpy(mlme.im_macaddr, params->bssid, IEEE80211_ADDR_LEN);
  349. if (set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme)) < 0)
  350. return -1;
  351. return 0;
  352. }
  353. static int
  354. wpa_driver_bsd_set_auth_alg(void *priv, int auth_alg)
  355. {
  356. struct wpa_driver_bsd_data *drv = priv;
  357. int authmode;
  358. if ((auth_alg & AUTH_ALG_OPEN_SYSTEM) &&
  359. (auth_alg & AUTH_ALG_SHARED_KEY))
  360. authmode = IEEE80211_AUTH_AUTO;
  361. else if (auth_alg & AUTH_ALG_SHARED_KEY)
  362. authmode = IEEE80211_AUTH_SHARED;
  363. else
  364. authmode = IEEE80211_AUTH_OPEN;
  365. return set80211param(drv, IEEE80211_IOC_AUTHMODE, authmode);
  366. }
  367. static int
  368. wpa_driver_bsd_scan(void *priv, const u8 *ssid, size_t ssid_len)
  369. {
  370. struct wpa_driver_bsd_data *drv = priv;
  371. int flags;
  372. /* NB: interface must be marked UP to do a scan */
  373. if (getifflags(drv, &flags) != 0 || setifflags(drv, flags | IFF_UP) != 0)
  374. return -1;
  375. /* set desired ssid before scan */
  376. if (wpa_driver_bsd_set_ssid(drv, ssid, ssid_len) < 0)
  377. return -1;
  378. /* NB: net80211 delivers a scan complete event so no need to poll */
  379. return set80211param(drv, IEEE80211_IOC_SCAN_REQ, 0);
  380. }
  381. #include <net/route.h>
  382. #include <net80211/ieee80211_freebsd.h>
  383. static void
  384. wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
  385. {
  386. struct wpa_driver_bsd_data *drv = sock_ctx;
  387. char buf[2048];
  388. struct if_announcemsghdr *ifan;
  389. struct if_msghdr *ifm;
  390. struct rt_msghdr *rtm;
  391. union wpa_event_data event;
  392. struct ieee80211_michael_event *mic;
  393. int n;
  394. n = read(sock, buf, sizeof(buf));
  395. if (n < 0) {
  396. if (errno != EINTR && errno != EAGAIN)
  397. perror("read(PF_ROUTE)");
  398. return;
  399. }
  400. rtm = (struct rt_msghdr *) buf;
  401. if (rtm->rtm_version != RTM_VERSION) {
  402. wpa_printf(MSG_DEBUG, "Routing message version %d not "
  403. "understood\n", rtm->rtm_version);
  404. return;
  405. }
  406. os_memset(&event, 0, sizeof(event));
  407. switch (rtm->rtm_type) {
  408. case RTM_IFANNOUNCE:
  409. ifan = (struct if_announcemsghdr *) rtm;
  410. if (ifan->ifan_index != drv->ifindex)
  411. break;
  412. strlcpy(event.interface_status.ifname, drv->ifname,
  413. sizeof(event.interface_status.ifname));
  414. switch (ifan->ifan_what) {
  415. case IFAN_DEPARTURE:
  416. event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
  417. default:
  418. return;
  419. }
  420. wpa_printf(MSG_DEBUG, "RTM_IFANNOUNCE: Interface '%s' %s",
  421. event.interface_status.ifname,
  422. ifan->ifan_what == IFAN_DEPARTURE ?
  423. "removed" : "added");
  424. wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event);
  425. break;
  426. case RTM_IEEE80211:
  427. ifan = (struct if_announcemsghdr *) rtm;
  428. if (ifan->ifan_index != drv->ifindex)
  429. break;
  430. switch (ifan->ifan_what) {
  431. case RTM_IEEE80211_ASSOC:
  432. case RTM_IEEE80211_REASSOC:
  433. wpa_supplicant_event(ctx, EVENT_ASSOC, NULL);
  434. break;
  435. case RTM_IEEE80211_DISASSOC:
  436. wpa_supplicant_event(ctx, EVENT_DISASSOC, NULL);
  437. break;
  438. case RTM_IEEE80211_SCAN:
  439. wpa_supplicant_event(ctx, EVENT_SCAN_RESULTS, NULL);
  440. break;
  441. case RTM_IEEE80211_REPLAY:
  442. /* ignore */
  443. break;
  444. case RTM_IEEE80211_MICHAEL:
  445. mic = (struct ieee80211_michael_event *) &ifan[1];
  446. wpa_printf(MSG_DEBUG,
  447. "Michael MIC failure wireless event: "
  448. "keyix=%u src_addr=" MACSTR, mic->iev_keyix,
  449. MAC2STR(mic->iev_src));
  450. os_memset(&event, 0, sizeof(event));
  451. event.michael_mic_failure.unicast =
  452. !IEEE80211_IS_MULTICAST(mic->iev_dst);
  453. wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE,
  454. &event);
  455. break;
  456. }
  457. break;
  458. case RTM_IFINFO:
  459. ifm = (struct if_msghdr *) rtm;
  460. if (ifm->ifm_index != drv->ifindex)
  461. break;
  462. if ((rtm->rtm_flags & RTF_UP) == 0) {
  463. strlcpy(event.interface_status.ifname, drv->ifname,
  464. sizeof(event.interface_status.ifname));
  465. event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
  466. wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' DOWN",
  467. event.interface_status.ifname);
  468. wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event);
  469. }
  470. break;
  471. }
  472. }
  473. /* Compare function for sorting scan results. Return >0 if @b is consider
  474. * better. */
  475. static int
  476. wpa_scan_result_compar(const void *a, const void *b)
  477. {
  478. const struct wpa_scan_result *wa = a;
  479. const struct wpa_scan_result *wb = b;
  480. /* WPA/WPA2 support preferred */
  481. if ((wb->wpa_ie_len || wb->rsn_ie_len) &&
  482. !(wa->wpa_ie_len || wa->rsn_ie_len))
  483. return 1;
  484. if (!(wb->wpa_ie_len || wb->rsn_ie_len) &&
  485. (wa->wpa_ie_len || wa->rsn_ie_len))
  486. return -1;
  487. /* privacy support preferred */
  488. if ((wa->caps & IEEE80211_CAPINFO_PRIVACY) &&
  489. (wb->caps & IEEE80211_CAPINFO_PRIVACY) == 0)
  490. return 1;
  491. if ((wa->caps & IEEE80211_CAPINFO_PRIVACY) == 0 &&
  492. (wb->caps & IEEE80211_CAPINFO_PRIVACY))
  493. return -1;
  494. /* best/max rate preferred if signal level close enough XXX */
  495. if (wa->maxrate != wb->maxrate && abs(wb->level - wa->level) < 5)
  496. return wb->maxrate - wa->maxrate;
  497. /* use freq for channel preference */
  498. /* all things being equal, use signal level */
  499. return wb->level - wa->level;
  500. }
  501. static int
  502. getmaxrate(uint8_t rates[15], uint8_t nrates)
  503. {
  504. int i, maxrate = -1;
  505. for (i = 0; i < nrates; i++) {
  506. int rate = rates[i] & IEEE80211_RATE_VAL;
  507. if (rate > maxrate)
  508. rate = maxrate;
  509. }
  510. return maxrate;
  511. }
  512. /* unalligned little endian access */
  513. #define LE_READ_4(p) \
  514. ((u_int32_t) \
  515. ((((const u_int8_t *)(p))[0] ) | \
  516. (((const u_int8_t *)(p))[1] << 8) | \
  517. (((const u_int8_t *)(p))[2] << 16) | \
  518. (((const u_int8_t *)(p))[3] << 24)))
  519. static int __inline
  520. iswpaoui(const u_int8_t *frm)
  521. {
  522. return frm[1] > 3 && LE_READ_4(frm+2) == ((WPA_OUI_TYPE<<24)|WPA_OUI);
  523. }
  524. static int
  525. wpa_driver_bsd_get_scan_results(void *priv,
  526. struct wpa_scan_result *results,
  527. size_t max_size)
  528. {
  529. #define min(a,b) ((a)>(b)?(b):(a))
  530. struct wpa_driver_bsd_data *drv = priv;
  531. uint8_t buf[24*1024];
  532. uint8_t *cp, *vp;
  533. struct ieee80211req_scan_result *sr;
  534. struct wpa_scan_result *wsr;
  535. int len, ielen;
  536. os_memset(results, 0, max_size * sizeof(struct wpa_scan_result));
  537. len = get80211var(drv, IEEE80211_IOC_SCAN_RESULTS, buf, sizeof(buf));
  538. if (len < 0)
  539. return -1;
  540. cp = buf;
  541. wsr = results;
  542. while (len >= sizeof(struct ieee80211req_scan_result)) {
  543. sr = (struct ieee80211req_scan_result *) cp;
  544. os_memcpy(wsr->bssid, sr->isr_bssid, IEEE80211_ADDR_LEN);
  545. wsr->ssid_len = sr->isr_ssid_len;
  546. wsr->freq = sr->isr_freq;
  547. wsr->noise = sr->isr_noise;
  548. wsr->qual = sr->isr_rssi;
  549. wsr->level = 0; /* XXX? */
  550. wsr->caps = sr->isr_capinfo;
  551. wsr->maxrate = getmaxrate(sr->isr_rates, sr->isr_nrates);
  552. vp = (u_int8_t *)(sr+1);
  553. os_memcpy(wsr->ssid, vp, sr->isr_ssid_len);
  554. if (sr->isr_ie_len > 0) {
  555. vp += sr->isr_ssid_len;
  556. ielen = sr->isr_ie_len;
  557. while (ielen > 0) {
  558. switch (vp[0]) {
  559. case IEEE80211_ELEMID_VENDOR:
  560. if (!iswpaoui(vp))
  561. break;
  562. wsr->wpa_ie_len =
  563. min(2+vp[1], SSID_MAX_WPA_IE_LEN);
  564. os_memcpy(wsr->wpa_ie, vp,
  565. wsr->wpa_ie_len);
  566. break;
  567. case IEEE80211_ELEMID_RSN:
  568. wsr->rsn_ie_len =
  569. min(2+vp[1], SSID_MAX_WPA_IE_LEN);
  570. os_memcpy(wsr->rsn_ie, vp,
  571. wsr->rsn_ie_len);
  572. break;
  573. }
  574. ielen -= 2+vp[1];
  575. vp += 2+vp[1];
  576. }
  577. }
  578. cp += sr->isr_len, len -= sr->isr_len;
  579. wsr++;
  580. }
  581. qsort(results, wsr - results, sizeof(struct wpa_scan_result),
  582. wpa_scan_result_compar);
  583. wpa_printf(MSG_DEBUG, "Received %d bytes of scan results (%d BSSes)",
  584. len, wsr - results);
  585. return wsr - results;
  586. #undef min
  587. }
  588. static void *
  589. wpa_driver_bsd_init(void *ctx, const char *ifname)
  590. {
  591. #define GETPARAM(drv, param, v) \
  592. (((v) = get80211param(drv, param)) != -1)
  593. struct wpa_driver_bsd_data *drv;
  594. drv = os_zalloc(sizeof(*drv));
  595. if (drv == NULL)
  596. return NULL;
  597. /*
  598. * NB: We require the interface name be mappable to an index.
  599. * This implies we do not support having wpa_supplicant
  600. * wait for an interface to appear. This seems ok; that
  601. * doesn't belong here; it's really the job of devd.
  602. */
  603. drv->ifindex = if_nametoindex(ifname);
  604. if (drv->ifindex == 0) {
  605. wpa_printf(MSG_DEBUG, "%s: interface %s does not exist",
  606. __func__, ifname);
  607. goto fail1;
  608. }
  609. drv->sock = socket(PF_INET, SOCK_DGRAM, 0);
  610. if (drv->sock < 0)
  611. goto fail1;
  612. drv->route = socket(PF_ROUTE, SOCK_RAW, 0);
  613. if (drv->route < 0)
  614. goto fail;
  615. eloop_register_read_sock(drv->route,
  616. wpa_driver_bsd_event_receive, ctx, drv);
  617. drv->ctx = ctx;
  618. os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
  619. if (!GETPARAM(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming)) {
  620. wpa_printf(MSG_DEBUG, "%s: failed to get roaming state: %s",
  621. __func__, strerror(errno));
  622. goto fail;
  623. }
  624. if (!GETPARAM(drv, IEEE80211_IOC_PRIVACY, drv->prev_privacy)) {
  625. wpa_printf(MSG_DEBUG, "%s: failed to get privacy state: %s",
  626. __func__, strerror(errno));
  627. goto fail;
  628. }
  629. if (!GETPARAM(drv, IEEE80211_IOC_WPA, drv->prev_wpa)) {
  630. wpa_printf(MSG_DEBUG, "%s: failed to get wpa state: %s",
  631. __func__, strerror(errno));
  632. goto fail;
  633. }
  634. if (set80211param(drv, IEEE80211_IOC_ROAMING, IEEE80211_ROAMING_MANUAL) < 0) {
  635. wpa_printf(MSG_DEBUG, "%s: failed to set wpa_supplicant-based "
  636. "roaming: %s", __func__, strerror(errno));
  637. goto fail;
  638. }
  639. if (set80211param(drv, IEEE80211_IOC_WPA, 1+2) < 0) {
  640. wpa_printf(MSG_DEBUG, "%s: failed to enable WPA support %s",
  641. __func__, strerror(errno));
  642. goto fail;
  643. }
  644. return drv;
  645. fail:
  646. close(drv->sock);
  647. fail1:
  648. os_free(drv);
  649. return NULL;
  650. #undef GETPARAM
  651. }
  652. static void
  653. wpa_driver_bsd_deinit(void *priv)
  654. {
  655. struct wpa_driver_bsd_data *drv = priv;
  656. int flags;
  657. eloop_unregister_read_sock(drv->route);
  658. /* NB: mark interface down */
  659. if (getifflags(drv, &flags) == 0)
  660. (void) setifflags(drv, flags &~ IFF_UP);
  661. wpa_driver_bsd_set_wpa_internal(drv, drv->prev_wpa, drv->prev_privacy);
  662. if (set80211param(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming) < 0)
  663. wpa_printf(MSG_DEBUG, "%s: failed to restore roaming state",
  664. __func__);
  665. (void) close(drv->route); /* ioctl socket */
  666. (void) close(drv->sock); /* event socket */
  667. os_free(drv);
  668. }
  669. const struct wpa_driver_ops wpa_driver_bsd_ops = {
  670. .name = "bsd",
  671. .desc = "BSD 802.11 support (Atheros, etc.)",
  672. .init = wpa_driver_bsd_init,
  673. .deinit = wpa_driver_bsd_deinit,
  674. .get_bssid = wpa_driver_bsd_get_bssid,
  675. .get_ssid = wpa_driver_bsd_get_ssid,
  676. .set_wpa = wpa_driver_bsd_set_wpa,
  677. .set_key = wpa_driver_bsd_set_key,
  678. .set_countermeasures = wpa_driver_bsd_set_countermeasures,
  679. .set_drop_unencrypted = wpa_driver_bsd_set_drop_unencrypted,
  680. .scan = wpa_driver_bsd_scan,
  681. .get_scan_results = wpa_driver_bsd_get_scan_results,
  682. .deauthenticate = wpa_driver_bsd_deauthenticate,
  683. .disassociate = wpa_driver_bsd_disassociate,
  684. .associate = wpa_driver_bsd_associate,
  685. .set_auth_alg = wpa_driver_bsd_set_auth_alg,
  686. };