📄 driver_wext.c
字号:
} switch (iwe->cmd) { case SIOCGIWAP: wpa_printf(MSG_DEBUG, "Wireless event: new AP: " MACSTR, MAC2STR((u8 *) iwe->u.ap_addr.sa_data)); if (memcmp(iwe->u.ap_addr.sa_data, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0 || memcmp(iwe->u.ap_addr.sa_data, "\x44\x44\x44\x44\x44\x44", ETH_ALEN) == 0) { free(drv->assoc_req_ies); drv->assoc_req_ies = NULL; free(drv->assoc_resp_ies); drv->assoc_resp_ies = NULL; wpa_supplicant_event(ctx, EVENT_DISASSOC, NULL); } else { wpa_driver_wext_event_assoc_ies(drv); wpa_supplicant_event(ctx, EVENT_ASSOC, NULL); } break; case IWEVMICHAELMICFAILURE: wpa_driver_wext_event_wireless_michaelmicfailure( drv, ctx, custom, iwe->u.data.length); break; case IWEVCUSTOM: if (custom + iwe->u.data.length > end) return; buf = malloc(iwe->u.data.length + 1); if (buf == NULL) return; memcpy(buf, custom, iwe->u.data.length); buf[iwe->u.data.length] = '\0'; wpa_driver_wext_event_wireless_custom(drv, ctx, buf); free(buf); break; case SIOCGIWSCAN: eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv, ctx); wpa_supplicant_event(ctx, EVENT_SCAN_RESULTS, NULL); break; case IWEVASSOCREQIE: wpa_driver_wext_event_wireless_assocreqie( drv, ctx, custom, iwe->u.data.length); break; case IWEVASSOCRESPIE: wpa_driver_wext_event_wireless_assocrespie( drv, ctx, custom, iwe->u.data.length); break; case IWEVPMKIDCAND: wpa_driver_wext_event_wireless_pmkidcand( drv, ctx, custom, iwe->u.data.length); break; } pos += iwe->len; }}static void wpa_driver_wext_event_link(struct wpa_driver_wext_data *drv, void *ctx, char *buf, size_t len, int del){ union wpa_event_data event; memset(&event, 0, sizeof(event)); if (len > sizeof(event.interface_status.ifname)) len = sizeof(event.interface_status.ifname) - 1; memcpy(event.interface_status.ifname, buf, len); event.interface_status.ievent = del ? EVENT_INTERFACE_REMOVED : EVENT_INTERFACE_ADDED; wpa_printf(MSG_DEBUG, "RTM_%sLINK, IFLA_IFNAME: Interface '%s' %s", del ? "DEL" : "NEW", event.interface_status.ifname, del ? "removed" : "added"); wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event);}static void wpa_driver_wext_event_rtm_newlink(struct wpa_driver_wext_data *drv, void *ctx, struct nlmsghdr *h, int len){ struct ifinfomsg *ifi; int attrlen, nlmsg_len, rta_len; struct rtattr * attr; if (len < sizeof(*ifi)) return; ifi = NLMSG_DATA(h); if (drv->ifindex != ifi->ifi_index && drv->ifindex2 != ifi->ifi_index) { wpa_printf(MSG_DEBUG, "Ignore event for foreign ifindex %d", ifi->ifi_index); return; } nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg)); attrlen = h->nlmsg_len - nlmsg_len; if (attrlen < 0) return; attr = (struct rtattr *) (((char *) ifi) + nlmsg_len); rta_len = RTA_ALIGN(sizeof(struct rtattr)); while (RTA_OK(attr, attrlen)) { if (attr->rta_type == IFLA_WIRELESS) { wpa_driver_wext_event_wireless( drv, ctx, ((char *) attr) + rta_len, attr->rta_len - rta_len); } else if (attr->rta_type == IFLA_IFNAME) { wpa_driver_wext_event_link(drv, ctx, ((char *) attr) + rta_len, attr->rta_len - rta_len, 0); } attr = RTA_NEXT(attr, attrlen); }}static void wpa_driver_wext_event_rtm_dellink(struct wpa_driver_wext_data *drv, void *ctx, struct nlmsghdr *h, int len){ struct ifinfomsg *ifi; int attrlen, nlmsg_len, rta_len; struct rtattr * attr; if (len < sizeof(*ifi)) return; ifi = NLMSG_DATA(h); nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg)); attrlen = h->nlmsg_len - nlmsg_len; if (attrlen < 0) return; attr = (struct rtattr *) (((char *) ifi) + nlmsg_len); rta_len = RTA_ALIGN(sizeof(struct rtattr)); while (RTA_OK(attr, attrlen)) { if (attr->rta_type == IFLA_IFNAME) { wpa_driver_wext_event_link(drv, ctx, ((char *) attr) + rta_len, attr->rta_len - rta_len, 1); } attr = RTA_NEXT(attr, attrlen); }}static void wpa_driver_wext_event_receive(int sock, void *eloop_ctx, void *sock_ctx){ char buf[8192]; int left; struct sockaddr_nl from; socklen_t fromlen; struct nlmsghdr *h; fromlen = sizeof(from); left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT, (struct sockaddr *) &from, &fromlen); if (left < 0) { if (errno != EINTR && errno != EAGAIN) perror("recvfrom(netlink)"); return; } h = (struct nlmsghdr *) buf; while (left >= sizeof(*h)) { int len, plen; len = h->nlmsg_len; plen = len - sizeof(*h); if (len > left || plen < 0) { wpa_printf(MSG_DEBUG, "Malformed netlink message: " "len=%d left=%d plen=%d", len, left, plen); break; } switch (h->nlmsg_type) { case RTM_NEWLINK: wpa_driver_wext_event_rtm_newlink(eloop_ctx, sock_ctx, h, plen); break; case RTM_DELLINK: wpa_driver_wext_event_rtm_dellink(eloop_ctx, sock_ctx, h, plen); break; } len = NLMSG_ALIGN(len); left -= len; h = (struct nlmsghdr *) ((char *) h + len); } if (left > 0) { wpa_printf(MSG_DEBUG, "%d extra bytes in the end of netlink " "message", left); }}/** * wpa_driver_wext_get_ifflags - Get interface flags (SIOCGIFFLAGS) * @drv: driver_wext private data * @flags: Pointer to returned flags value * Returns: 0 on success, -1 on failure */int wpa_driver_wext_get_ifflags(struct wpa_driver_wext_data *drv, int *flags){ struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, drv->ifname, IFNAMSIZ); if (ioctl(drv->ioctl_sock, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) { perror("ioctl[SIOCGIFFLAGS]"); return -1; } *flags = ifr.ifr_flags & 0xffff; return 0;}/** * 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){ struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, drv->ifname, IFNAMSIZ); ifr.ifr_flags = flags & 0xffff; if (ioctl(drv->ioctl_sock, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) { perror("SIOCSIFFLAGS"); return -1; } return 0;}/** * 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, flags; struct sockaddr_nl local; struct wpa_driver_wext_data *drv; drv = malloc(sizeof(*drv)); if (drv == NULL) return NULL; memset(drv, 0, sizeof(*drv)); drv->ctx = ctx; strncpy(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)"); 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); free(drv); return NULL; } 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); free(drv); return NULL; } eloop_register_read_sock(s, wpa_driver_wext_event_receive, drv, ctx); drv->event_sock = s; /* * 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"); } if (wpa_driver_wext_get_ifflags(drv, &flags) != 0 || wpa_driver_wext_set_ifflags(drv, flags | IFF_UP) != 0) { printf("Could not set interface '%s' UP\n", drv->ifname); } wpa_driver_wext_get_range(drv); drv->ifindex = if_nametoindex(drv->ifname); if (strncmp(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]; strncpy(ifname2, ifname, sizeof(ifname2)); memcpy(ifname2, "wifi", 4); wpa_driver_wext_alternative_ifindex(drv, ifname2); } return drv;}/** * 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; /* * Clear possibly configured driver parameters in order to make it * easier to use the driver after wpa_supplicant has been terminated. */ wpa_driver_wext_set_bssid(drv, (u8 *) "\x00\x00\x00\x00\x00\x00"); eloop_unregister_read_sock(drv->event_sock); if (wpa_driver_wext_get_ifflags(drv, &flags) == 0) (void) wpa_driver_wext_set_ifflags(drv, flags & ~IFF_UP); close(drv->event_sock); close(drv->ioctl_sock); free(drv->assoc_req_ies); free(drv->assoc_resp_ies); 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; 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; } memset(&iwr, 0, sizeof(iwr)); strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); if (ssid && ssid_len) { memset(&req, 0, sizeof(req)); req.essid_len = ssid_len; req.bssid.sa_family = ARPHRD_ETHER; memset(req.bssid.sa_data, 0xff, ETH_ALEN); 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. */ eloop_register_timeout(3, 0, wpa_driver_wext_scan_timeout, drv, drv->ctx); return ret;}/* Compare function for sorting scan results. Return >0 if @b is considered * better. */static int wpa_scan_result_compar(const void *a, const void *b){ const struct wpa_scan_result *wa = a; const struct wpa_scan_result *wb = b; /* WPA/WPA2 support preferred */ if ((wb->wpa_ie_len || wb->rsn_ie_len) && !(wa->wpa_ie_len || wa->rsn_ie_len)) return 1; if (!(wb->wpa_ie_len || wb->rsn_ie_len) && (wa->wpa_ie_len || wa->rsn_ie_len)) return -1; /* privacy support preferred */ if ((wa->caps & IEEE80211_CAP_PRIVACY) == 0 && (wb->caps & IEEE80211_CAP_PRIVACY)) return 1; if ((wa->caps & IEEE80211_CAP_PRIVACY) && (wb->caps & IEEE80211_CAP_PRIVACY) == 0) return -1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -