📄 driver_wext.c
字号:
return *i;}#endif /* CONFIG_CLIENT_MLME *//** * wpa_driver_wext_set_ifflags - Set interface flags (SIOCSIFFLAGS) * @drv: driver_wext private data * @flags: New value for flags * Returns: 0 on success, -1 on failure */int wpa_driver_wext_set_ifflags(struct wpa_driver_wext_data *drv, int flags){ return wpa_driver_wext_set_ifflags_ifname(drv, drv->ifname, flags);}/** * wpa_driver_wext_init - Initialize WE driver interface * @ctx: context to be used when calling wpa_supplicant functions, * e.g., wpa_supplicant_event() * @ifname: interface name, e.g., wlan0 * Returns: Pointer to private data, %NULL on failure */void * wpa_driver_wext_init(void *ctx, const char *ifname){ int s; struct sockaddr_nl local; struct wpa_driver_wext_data *drv; drv = os_zalloc(sizeof(*drv)); if (drv == NULL) return NULL; drv->ctx = ctx; os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0); if (drv->ioctl_sock < 0) { perror("socket(PF_INET,SOCK_DGRAM)"); os_free(drv); return NULL; } s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); if (s < 0) { perror("socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE)"); close(drv->ioctl_sock); os_free(drv); return NULL; } os_memset(&local, 0, sizeof(local)); local.nl_family = AF_NETLINK; local.nl_groups = RTMGRP_LINK; if (bind(s, (struct sockaddr *) &local, sizeof(local)) < 0) { perror("bind(netlink)"); close(s); close(drv->ioctl_sock); os_free(drv); return NULL; } eloop_register_read_sock(s, wpa_driver_wext_event_receive, drv, ctx); drv->event_sock = s; drv->mlme_sock = -1; wpa_driver_wext_finish_drv_init(drv); return drv;}static void wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv){ int flags; if (wpa_driver_wext_get_ifflags(drv, &flags) != 0) printf("Could not get interface '%s' flags\n", drv->ifname); else if (!(flags & IFF_UP)) { if (wpa_driver_wext_set_ifflags(drv, flags | IFF_UP) != 0) { printf("Could not set interface '%s' UP\n", drv->ifname); } else { /* * Wait some time to allow driver to initialize before * starting configuring the driver. This seems to be * needed at least some drivers that load firmware etc. * when the interface is set up. */ wpa_printf(MSG_DEBUG, "Interface %s set UP - waiting " "a second for the driver to complete " "initialization", drv->ifname); sleep(1); } } /* * Make sure that the driver does not have any obsolete PMKID entries. */ wpa_driver_wext_flush_pmkid(drv); if (wpa_driver_wext_set_mode(drv, 0) < 0) { printf("Could not configure driver to use managed mode\n"); } wpa_driver_wext_get_range(drv); drv->ifindex = if_nametoindex(drv->ifname); if (os_strncmp(drv->ifname, "wlan", 4) == 0) { /* * Host AP driver may use both wlan# and wifi# interface in * wireless events. Since some of the versions included WE-18 * support, let's add the alternative ifindex also from * driver_wext.c for the time being. This may be removed at * some point once it is believed that old versions of the * driver are not in use anymore. */ char ifname2[IFNAMSIZ + 1]; os_strlcpy(ifname2, drv->ifname, sizeof(ifname2)); os_memcpy(ifname2, "wifi", 4); wpa_driver_wext_alternative_ifindex(drv, ifname2); } wpa_driver_wext_send_oper_ifla(drv, 1, IF_OPER_DORMANT);}/** * wpa_driver_wext_deinit - Deinitialize WE driver interface * @priv: Pointer to private wext data from wpa_driver_wext_init() * * Shut down driver interface and processing of driver events. Free * private data buffer if one was allocated in wpa_driver_wext_init(). */void wpa_driver_wext_deinit(void *priv){ struct wpa_driver_wext_data *drv = priv; int flags; eloop_cancel_timeout(wpa_driver_wext_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_wext_set_bssid(drv, (u8 *) "\x00\x00\x00\x00\x00\x00"); wpa_driver_wext_send_oper_ifla(priv, 0, IF_OPER_UP); eloop_unregister_read_sock(drv->event_sock); if (drv->mlme_sock >= 0) eloop_unregister_read_sock(drv->mlme_sock); if (wpa_driver_wext_get_ifflags(drv, &flags) == 0) (void) wpa_driver_wext_set_ifflags(drv, flags & ~IFF_UP);#ifdef CONFIG_CLIENT_MLME if (drv->mlmedev[0]) { if (wpa_driver_wext_get_ifflags_ifname(drv, drv->mlmedev, &flags) == 0) (void) wpa_driver_wext_set_ifflags_ifname( drv, drv->mlmedev, flags & ~IFF_UP); wpa_driver_prism2_param_set(drv, PRISM2_PARAM_MGMT_IF, 0); wpa_driver_prism2_param_set(drv, PRISM2_PARAM_USER_SPACE_MLME, 0); }#endif /* CONFIG_CLIENT_MLME */ close(drv->event_sock); close(drv->ioctl_sock); if (drv->mlme_sock >= 0) close(drv->mlme_sock); os_free(drv->assoc_req_ies); os_free(drv->assoc_resp_ies); os_free(drv);}/** * wpa_driver_wext_scan_timeout - Scan timeout to report scan completion * @eloop_ctx: Unused * @timeout_ctx: ctx argument given to wpa_driver_wext_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. */void wpa_driver_wext_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_wext_scan - Request the driver to initiate scan * @priv: Pointer to private wext data from wpa_driver_wext_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 */int wpa_driver_wext_scan(void *priv, const u8 *ssid, size_t ssid_len){ struct wpa_driver_wext_data *drv = priv; struct iwreq iwr; int ret = 0, timeout; struct iw_scan_req req; if (ssid_len > IW_ESSID_MAX_SIZE) { wpa_printf(MSG_DEBUG, "%s: too long SSID (%lu)", __FUNCTION__, (unsigned long) ssid_len); return -1; } os_memset(&iwr, 0, sizeof(iwr)); os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); if (ssid && ssid_len) { os_memset(&req, 0, sizeof(req)); req.essid_len = ssid_len; req.bssid.sa_family = ARPHRD_ETHER; os_memset(req.bssid.sa_data, 0xff, ETH_ALEN); os_memcpy(req.essid, ssid, ssid_len); iwr.u.data.pointer = (caddr_t) &req; iwr.u.data.length = sizeof(req); iwr.u.data.flags = IW_SCAN_THIS_ESSID; } if (ioctl(drv->ioctl_sock, SIOCSIWSCAN, &iwr) < 0) { perror("ioctl[SIOCSIWSCAN]"); ret = -1; } /* Not all drivers generate "scan completed" wireless event, so try to * read results after a timeout. */ timeout = 5; 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_wext_scan_timeout, drv, drv->ctx); eloop_register_timeout(timeout, 0, wpa_driver_wext_scan_timeout, drv, drv->ctx); return ret;}static u8 * wpa_driver_wext_giwscan(struct wpa_driver_wext_data *drv, size_t *len){ struct iwreq iwr; u8 *res_buf; size_t res_buf_len; res_buf_len = IW_SCAN_MAX_DATA; for (;;) { res_buf = os_malloc(res_buf_len); if (res_buf == NULL) return NULL; os_memset(&iwr, 0, sizeof(iwr)); os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); iwr.u.data.pointer = res_buf; iwr.u.data.length = res_buf_len; if (ioctl(drv->ioctl_sock, SIOCGIWSCAN, &iwr) == 0) break; if (errno == E2BIG && res_buf_len < 100000) { os_free(res_buf); res_buf = NULL; res_buf_len *= 2; wpa_printf(MSG_DEBUG, "Scan results did not fit - " "trying larger buffer (%lu bytes)", (unsigned long) res_buf_len); } else { perror("ioctl[SIOCGIWSCAN]"); os_free(res_buf); return NULL; } } if (iwr.u.data.length > res_buf_len) { os_free(res_buf); return NULL; } *len = iwr.u.data.length; return res_buf;}/* * Data structure for collecting WEXT scan results. This is needed to allow * the various methods of reporting IEs to be combined into a single IE buffer. */struct wext_scan_data { struct wpa_scan_res res; u8 *ie; size_t ie_len; u8 ssid[32]; size_t ssid_len; int maxrate;};static void wext_get_scan_mode(struct iw_event *iwe, struct wext_scan_data *res){ if (iwe->u.mode == IW_MODE_ADHOC) res->res.caps |= IEEE80211_CAP_IBSS; else if (iwe->u.mode == IW_MODE_MASTER || iwe->u.mode == IW_MODE_INFRA) res->res.caps |= IEEE80211_CAP_ESS;}static void wext_get_scan_ssid(struct iw_event *iwe, struct wext_scan_data *res, char *custom, char *end){ int ssid_len = iwe->u.essid.length; if (custom + ssid_len > end) return; if (iwe->u.essid.flags && ssid_len > 0 && ssid_len <= IW_ESSID_MAX_SIZE) { os_memcpy(res->ssid, custom, ssid_len); res->ssid_len = ssid_len; }}static void wext_get_scan_freq(struct iw_event *iwe, struct wext_scan_data *res){ int divi = 1000000, i; if (iwe->u.freq.e == 0) { /* * Some drivers do not report frequency, but a channel. * Try to map this to frequency by assuming they are using * IEEE 802.11b/g. But don't overwrite a previously parsed * frequency if the driver sends both frequency and channel, * since the driver may be sending an A-band channel that we * don't handle here. */ if (res->res.freq) return; if (iwe->u.freq.m >= 1 && iwe->u.freq.m <= 13) { res->res.freq = 2407 + 5 * iwe->u.freq.m; return; } else if (iwe->u.freq.m == 14) { res->res.freq = 2484; return; } } if (iwe->u.freq.e > 6) { wpa_printf(MSG_DEBUG, "Invalid freq in scan results (BSSID=" MACSTR " m=%d e=%d)", MAC2STR(res->res.bssid), iwe->u.freq.m, iwe->u.freq.e); return; } for (i = 0; i < iwe->u.freq.e; i++) divi /= 10; res->res.freq = iwe->u.freq.m / divi;}static void wext_get_scan_qual(struct iw_event *iwe, struct wext_scan_data *res){ res->res.qual = iwe->u.qual.qual; res->res.noise = iwe->u.qual.noise; res->res.level = iwe->u.qual.level;}static void wext_get_scan_encode(struct iw_event *iwe, struct wext_scan_data *res){ if (!(iwe->u.data.flags & IW_ENCODE_DISABLED)) res->res.caps |= IEEE80211_CAP_PRIVACY;}static void wext_get_scan_rate(struct iw_event *iwe, struct wext_scan_data *res, char *pos, char *end){ int maxrate; char *custom = pos + IW_EV_LCP_LEN; struct iw_param p; size_t clen; clen = iwe->len; if (custom + clen > end) return; maxrate = 0; while (((ssize_t) clen) >= (ssize_t) sizeof(struct iw_param)) { /* Note: may be misaligned, make a local, aligned copy */ os_memcpy(&p, custom, sizeof(struct iw_param)); if (p.value > maxrate) maxrate = p.value; clen -= sizeof(struct iw_param); custom += sizeof(struct iw_param); } /* Convert the maxrate from WE-style (b/s units) to * 802.11 rates (500000 b/s units). */ res->maxrate = maxrate / 500000;}static void wext_get_scan_iwevgenie(struct iw_event *iwe, struct wext_scan_data *res, char *custom, char *end){ char *genie, *gpos, *gend; u8 *tmp; gpos = genie = custom; gend = genie + iwe->u.data.length; if (gend > end) { wpa_printf(MSG_INFO, "IWEVGENIE overflow"); return; } tmp = os_realloc(res->ie, res->ie_len + gend - gpos); if (tmp == NULL) return; os_memcpy(tmp + res->ie_len, gpos, gend - gpos); res->ie = tmp; res->ie_len += gend - gpos;}static void wext_get_scan_custom(struct iw_event *iwe, struct wext_scan_data *res, char *custom, char *end){ size_t clen; u8 *tmp; clen = iwe->u.data.length; if (custom + clen > end) return; if (clen > 7 && os_strncmp(custom, "wpa_ie=", 7) == 0) { char *spos; int bytes; spos = custom + 7; bytes = custom + clen - spos; if (bytes & 1) return; bytes /= 2; tmp = os_realloc(res->ie, res->ie_len + bytes); if (tmp == NULL) return; hexstr2bin(spos, tmp + res->ie_len, bytes); res->ie = tmp; res->ie_len += bytes; } else if (clen > 7 && os_strncmp(custom, "rsn_ie=", 7) == 0) { char *spos; int bytes; spos = custom + 7; bytes = custom + clen - spos; if (bytes & 1) return; bytes /= 2; tmp = os_realloc(res->ie, res->ie_len + bytes); if (tmp == NULL) return; hexstr2bin(spos, tmp + res->ie_len, bytes); res->ie = tmp; res->ie_len += bytes; } else if (clen > 4 && os_strncmp(custom, "tsf=", 4) == 0) { char *spos; int bytes; u8 bin[8]; spos = custom + 4; bytes = custom + clen - spos; if (bytes != 16) { wpa_printf(MSG_INFO, "Invalid TSF length (%d)", bytes); return; } bytes /= 2; hexstr2bin(spos, bin, bytes); res->res.tsf += WPA_GET_BE64(bin); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -