📄 driver_nl80211.c
字号:
else if (!(flags & IFF_UP)) { if (wpa_driver_nl80211_set_ifflags(drv, flags | IFF_UP) != 0) { printf("Could not set interface '%s' UP\n", drv->ifname); } } /* * Make sure that the driver does not have any obsolete PMKID entries. */ wpa_driver_nl80211_flush_pmkid(drv); if (wpa_driver_nl80211_set_mode(drv, 0) < 0) { printf("Could not configure driver to use managed mode\n"); } wpa_driver_nl80211_get_range(drv); drv->ifindex = if_nametoindex(drv->ifname); wpa_driver_nl80211_send_oper_ifla(drv, 1, IF_OPER_DORMANT);}/** * wpa_driver_nl80211_deinit - Deinitialize nl80211 driver interface * @priv: Pointer to private nl80211 data from wpa_driver_nl80211_init() * * Shut down driver interface and processing of driver events. Free * private data buffer if one was allocated in wpa_driver_nl80211_init(). */static void wpa_driver_nl80211_deinit(void *priv){ struct wpa_driver_nl80211_data *drv = priv; int flags;#ifdef CONFIG_CLIENT_MLME if (drv->monitor_sock >= 0) { eloop_unregister_read_sock(drv->monitor_sock); close(drv->monitor_sock); } if (drv->monitor_ifidx > 0) nl80211_remove_iface(drv, drv->monitor_ifidx); if (drv->capa.flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME) wpa_driver_nl80211_set_userspace_mlme(drv, 0);#endif /* CONFIG_CLIENT_MLME */ eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx); /* * Clear possibly configured driver parameters in order to make it * easier to use the driver after wpa_supplicant has been terminated. */ (void) wpa_driver_nl80211_set_bssid(drv, (u8 *) "\x00\x00\x00\x00\x00\x00"); wpa_driver_nl80211_send_oper_ifla(priv, 0, IF_OPER_UP); eloop_unregister_read_sock(drv->wext_event_sock); if (wpa_driver_nl80211_get_ifflags(drv, &flags) == 0) (void) wpa_driver_nl80211_set_ifflags(drv, flags & ~IFF_UP); close(drv->wext_event_sock); close(drv->ioctl_sock); os_free(drv->assoc_req_ies); os_free(drv->assoc_resp_ies); eloop_unregister_read_sock(nl_socket_get_fd(drv->nl_handle)); genl_family_put(drv->nl80211); nl_cache_free(drv->nl_cache); nl_handle_destroy(drv->nl_handle); nl_cb_put(drv->nl_cb); os_free(drv);}/** * wpa_driver_nl80211_scan_timeout - Scan timeout to report scan completion * @eloop_ctx: Unused * @timeout_ctx: ctx argument given to wpa_driver_nl80211_init() * * This function can be used as registered timeout when starting a scan to * generate a scan completed event if the driver does not report this. */static void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx){ wpa_printf(MSG_DEBUG, "Scan timeout - try to get results"); wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);}/** * wpa_driver_nl80211_scan - Request the driver to initiate scan * @priv: Pointer to private wext data from wpa_driver_nl80211_init() * @ssid: Specific SSID to scan for (ProbeReq) or %NULL to scan for * all SSIDs (either active scan with broadcast SSID or passive * scan * @ssid_len: Length of the SSID * Returns: 0 on success, -1 on failure */static int wpa_driver_nl80211_scan(void *priv, const u8 *ssid, size_t ssid_len){ struct wpa_driver_nl80211_data *drv = priv; int ret = 0, timeout; struct nl_msg *msg, *ssids; msg = nlmsg_alloc(); ssids = nlmsg_alloc(); if (!msg || !ssids) { nlmsg_free(msg); nlmsg_free(ssids); return -1; } genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, NL80211_CMD_TRIGGER_SCAN, 0); NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); if (ssid && ssid_len) { /* Request an active scan for a specific SSID */ NLA_PUT(ssids, 1, ssid_len, ssid); } else { /* Request an active scan for wildcard SSID */ NLA_PUT(ssids, 1, 0, ""); } nla_put_nested(msg, NL80211_ATTR_SCAN_SSIDS, ssids); ret = send_and_recv_msgs(drv, msg, NULL, NULL); msg = NULL; if (ret) { wpa_printf(MSG_DEBUG, "nl80211: Scan trigger failed: ret=%d " "(%s)", ret, strerror(-ret)); goto nla_put_failure; } /* Not all drivers generate "scan completed" wireless event, so try to * read results after a timeout. */ timeout = 10; if (drv->scan_complete_events) { /* * The driver seems to deliver SIOCGIWSCAN events to notify * when scan is complete, so use longer timeout to avoid race * conditions with scanning and following association request. */ timeout = 30; } wpa_printf(MSG_DEBUG, "Scan requested (ret=%d) - scan timeout %d " "seconds", ret, timeout); eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx); eloop_register_timeout(timeout, 0, wpa_driver_nl80211_scan_timeout, drv, drv->ctx);nla_put_failure: nlmsg_free(ssids); nlmsg_free(msg); return ret;}static int bss_info_handler(struct nl_msg *msg, void *arg){ struct nlattr *tb[NL80211_ATTR_MAX + 1]; struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); struct nlattr *bss[NL80211_BSS_MAX + 1]; static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = { [NL80211_BSS_BSSID] = { .type = NLA_UNSPEC }, [NL80211_BSS_FREQUENCY] = { .type = NLA_U32 }, [NL80211_BSS_TSF] = { .type = NLA_U64 }, [NL80211_BSS_BEACON_INTERVAL] = { .type = NLA_U16 }, [NL80211_BSS_CAPABILITY] = { .type = NLA_U16 }, [NL80211_BSS_INFORMATION_ELEMENTS] = { .type = NLA_UNSPEC }, [NL80211_BSS_SIGNAL_MBM] = { .type = NLA_U32 }, [NL80211_BSS_SIGNAL_UNSPEC] = { .type = NLA_U8 }, }; struct wpa_scan_results *res = arg; struct wpa_scan_res **tmp; struct wpa_scan_res *r; const u8 *ie; size_t ie_len; nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL); if (!tb[NL80211_ATTR_BSS]) return NL_SKIP; if (nla_parse_nested(bss, NL80211_BSS_MAX, tb[NL80211_ATTR_BSS], bss_policy)) return NL_SKIP; if (bss[NL80211_BSS_INFORMATION_ELEMENTS]) { ie = nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]); ie_len = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]); } else { ie = NULL; ie_len = 0; } r = os_zalloc(sizeof(*r) + ie_len); if (r == NULL) return NL_SKIP; if (bss[NL80211_BSS_BSSID]) os_memcpy(r->bssid, nla_data(bss[NL80211_BSS_BSSID]), ETH_ALEN); if (bss[NL80211_BSS_FREQUENCY]) r->freq = nla_get_u32(bss[NL80211_BSS_FREQUENCY]); if (bss[NL80211_BSS_BEACON_INTERVAL]) r->beacon_int = nla_get_u16(bss[NL80211_BSS_BEACON_INTERVAL]); if (bss[NL80211_BSS_CAPABILITY]) r->caps = nla_get_u16(bss[NL80211_BSS_CAPABILITY]); if (bss[NL80211_BSS_SIGNAL_UNSPEC]) r->qual = nla_get_u8(bss[NL80211_BSS_SIGNAL_UNSPEC]); if (bss[NL80211_BSS_SIGNAL_MBM]) r->level = nla_get_u32(bss[NL80211_BSS_SIGNAL_MBM]); if (bss[NL80211_BSS_TSF]) r->tsf = nla_get_u64(bss[NL80211_BSS_TSF]); r->ie_len = ie_len; if (ie) os_memcpy(r + 1, ie, ie_len); tmp = os_realloc(res->res, (res->num + 1) * sizeof(struct wpa_scan_res *)); if (tmp == NULL) { os_free(r); return NL_SKIP; } tmp[res->num++] = r; res->res = tmp; return NL_SKIP;}/** * wpa_driver_nl80211_get_scan_results - Fetch the latest scan results * @priv: Pointer to private wext data from wpa_driver_nl80211_init() * Returns: Scan results on success, -1 on failure */static struct wpa_scan_results *wpa_driver_nl80211_get_scan_results(void *priv){ struct wpa_driver_nl80211_data *drv = priv; struct nl_msg *msg; struct wpa_scan_results *res; int ret; res = os_zalloc(sizeof(*res)); if (res == NULL) return 0; msg = nlmsg_alloc(); if (!msg) goto nla_put_failure; genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, NLM_F_DUMP, NL80211_CMD_GET_SCAN, 0); NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); ret = send_and_recv_msgs(drv, msg, bss_info_handler, res); msg = NULL; if (ret == 0) { wpa_printf(MSG_DEBUG, "Received scan results (%lu BSSes)", (unsigned long) res->num); return res; } wpa_printf(MSG_DEBUG, "nl80211: Scan result fetch failed: ret=%d " "(%s)", ret, strerror(-ret));nla_put_failure: nlmsg_free(msg); wpa_scan_results_free(res); return NULL;}static int wpa_driver_nl80211_get_range(void *priv){ struct wpa_driver_nl80211_data *drv = priv; struct iw_range *range; struct iwreq iwr; int minlen; size_t buflen; /* * Use larger buffer than struct iw_range in order to allow the * structure to grow in the future. */ buflen = sizeof(struct iw_range) + 500; range = os_zalloc(buflen); if (range == NULL) return -1; os_memset(&iwr, 0, sizeof(iwr)); os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); iwr.u.data.pointer = (caddr_t) range; iwr.u.data.length = buflen; minlen = ((char *) &range->enc_capa) - (char *) range + sizeof(range->enc_capa); if (ioctl(drv->ioctl_sock, SIOCGIWRANGE, &iwr) < 0) { perror("ioctl[SIOCGIWRANGE]"); os_free(range); return -1; } else if (iwr.u.data.length >= minlen && range->we_version_compiled >= 18) { wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: WE(compiled)=%d " "WE(source)=%d enc_capa=0x%x", range->we_version_compiled, range->we_version_source, range->enc_capa); drv->has_capability = 1; drv->we_version_compiled = range->we_version_compiled; if (range->enc_capa & IW_ENC_CAPA_WPA) { drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA | WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK; } if (range->enc_capa & IW_ENC_CAPA_WPA2) { drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK; } drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40 | WPA_DRIVER_CAPA_ENC_WEP104; if (range->enc_capa & IW_ENC_CAPA_CIPHER_TKIP) drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP; if (range->enc_capa & IW_ENC_CAPA_CIPHER_CCMP) drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP; wpa_printf(MSG_DEBUG, " capabilities: key_mgmt 0x%x enc 0x%x", drv->capa.key_mgmt, drv->capa.enc); } else { wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: too old (short) data - " "assuming WPA is not supported"); } os_free(range); return 0;}static int wpa_driver_nl80211_set_wpa(void *priv, int enabled){ struct wpa_driver_nl80211_data *drv = priv; wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); return wpa_driver_nl80211_set_auth_param(drv, IW_AUTH_WPA_ENABLED, enabled);}static int wpa_driver_nl80211_set_key(void *priv, wpa_alg alg, const u8 *addr, int key_idx, int set_tx, const u8 *seq, size_t seq_len, const u8 *key, size_t key_len){ struct wpa_driver_nl80211_data *drv = priv; int err; struct nl_msg *msg; wpa_printf(MSG_DEBUG, "%s: alg=%d addr=%p key_idx=%d set_tx=%d " "seq_len=%lu key_len=%lu", __func__, alg, addr, key_idx, set_tx, (unsigned long) seq_len, (unsigned long) key_len); msg = nlmsg_alloc(); if (msg == NULL) return -1; if (alg == WPA_ALG_NONE) { genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, NL80211_CMD_DEL_KEY, 0); } else { genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, NL80211_CMD_NEW_KEY, 0); NLA_PUT(msg, NL80211_ATTR_KEY_DATA, key_len, key); switch (alg) { case WPA_ALG_WEP: if (key_len == 5) NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER, 0x000FAC01); else NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER, 0x000FAC05); break; case WPA_ALG_TKIP: NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER, 0x000FAC02); break; case WPA_ALG_CCMP: NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER, 0x000FAC04); break; default: nlmsg_free(msg); return -1; } } if (addr && os_memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) != 0) { wpa_printf(MSG_DEBUG, " addr=" MACSTR, MAC2STR(addr)); NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); } NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx); NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); err = send_and_recv_msgs(drv, msg, NULL, NULL); if (err) { wpa_printf(MSG_DEBUG, "nl80211: set_key failed; err=%d", err); return -1; } if (set_tx && alg != WPA_ALG_NONE) { msg = nlmsg_alloc(); if (msg == NULL) return -1; genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, NL80211_CMD_SET_KEY, 0); NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx); NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); NLA_PUT_FLAG(msg, NL80211_ATTR_KEY_DEFAULT); err = send_and_recv_msgs(drv, msg, NULL, NULL); if (err) { wpa_printf(MSG_DEBUG, "nl80211: set default key " "failed; err=%d", err); return -1; } } return 0;nla_put_failure: return -ENOBUFS;}static int wpa_driver_nl80211_set_countermeasures(void *priv, int enabled){ struct wpa_driver_nl80211_data *drv = priv; wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); return wpa_driver_nl80211_set_auth_param(drv, IW_AUTH_TKIP_COUNTERMEASURES, enabled);}static int wpa_driver_nl80211_set_drop_unencrypted(void *priv, int enabled){ struct wpa_driver_nl80211_data *drv = priv; wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); drv->use_crypt = enabled; return wpa_driver_nl80211_set_auth_param(drv, IW_AUTH_DROP_UNENCRYPTED, enabled);}static int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv, const u8 *addr, int cmd, int reason_code){ struct iwreq iwr; struct iw_mlme mlme; int ret = 0; os_memset(&iwr, 0, sizeof(iwr)); os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); os_memset(&mlme, 0, sizeof(mlme)); mlme.cmd = cmd; mlme.reason_code = reason_code; mlme.addr.sa_family = ARPHRD_ETHER; os_memcpy(mlme.addr.sa_data, addr, ETH_ALEN); iwr.u.data.pointer = (caddr_t) &mlme; iwr.u.data.length = sizeof(mlme); if (ioctl(drv->ioctl_sock, SIOCSIWMLME, &iwr) < 0) { perror("ioctl[SIOCSIWMLME]"); ret = -1; } return ret;}static int wpa_driver_nl80211_deauthenticate(void *priv, const u8 *addr, int reason_code){ struct wpa_driver_nl80211_data *drv = priv; wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); return wpa_driver_nl80211_mlme(drv, addr, IW_MLME_DEAUTH, reason_code);}static int wpa_driver_nl80211_disassociate(void *priv, const u8 *addr, int reason_code){ struct wpa_driver_nl80211_data *drv = priv; wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); return wpa_driver_nl80211_mlme(drv, addr, IW_MLME_DISASSOC, reason_code);}static int wpa_driver_nl80211_set_gen_ie(void *priv, const u8 *ie, size_t ie_len){ struct wpa_driver_nl80211_data *drv = priv; struct iwreq iwr; int ret = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -