📄 driver_wext.c
字号:
const u8 *addr; if (len < sizeof(*cand)) return -1; cand = (const struct iw_pmkid_cand *) ev; addr = (const u8 *) cand->bssid.sa_data; wpa_printf(MSG_DEBUG, "PMKID candidate wireless event: " "flags=0x%x index=%d bssid=" MACSTR, cand->flags, cand->index, MAC2STR(addr)); os_memset(&data, 0, sizeof(data)); os_memcpy(data.pmkid_candidate.bssid, addr, ETH_ALEN); data.pmkid_candidate.index = cand->index; data.pmkid_candidate.preauth = cand->flags & IW_PMKID_CAND_PREAUTH; wpa_supplicant_event(drv->ctx, EVENT_PMKID_CANDIDATE, &data); return 0;}static int wpa_driver_wext_event_wireless_assocreqie( struct wpa_driver_wext_data *drv, const char *ev, int len){ if (len < 0) return -1; wpa_hexdump(MSG_DEBUG, "AssocReq IE wireless event", (const u8 *) ev, len); os_free(drv->assoc_req_ies); drv->assoc_req_ies = os_malloc(len); if (drv->assoc_req_ies == NULL) { drv->assoc_req_ies_len = 0; return -1; } os_memcpy(drv->assoc_req_ies, ev, len); drv->assoc_req_ies_len = len; return 0;}static int wpa_driver_wext_event_wireless_assocrespie( struct wpa_driver_wext_data *drv, const char *ev, int len){ if (len < 0) return -1; wpa_hexdump(MSG_DEBUG, "AssocResp IE wireless event", (const u8 *) ev, len); os_free(drv->assoc_resp_ies); drv->assoc_resp_ies = os_malloc(len); if (drv->assoc_resp_ies == NULL) { drv->assoc_resp_ies_len = 0; return -1; } os_memcpy(drv->assoc_resp_ies, ev, len); drv->assoc_resp_ies_len = len; return 0;}static void wpa_driver_wext_event_assoc_ies(struct wpa_driver_wext_data *drv){ union wpa_event_data data; if (drv->assoc_req_ies == NULL && drv->assoc_resp_ies == NULL) return; os_memset(&data, 0, sizeof(data)); if (drv->assoc_req_ies) { data.assoc_info.req_ies = drv->assoc_req_ies; drv->assoc_req_ies = NULL; data.assoc_info.req_ies_len = drv->assoc_req_ies_len; } if (drv->assoc_resp_ies) { data.assoc_info.resp_ies = drv->assoc_resp_ies; drv->assoc_resp_ies = NULL; data.assoc_info.resp_ies_len = drv->assoc_resp_ies_len; } wpa_supplicant_event(drv->ctx, EVENT_ASSOCINFO, &data); os_free(data.assoc_info.req_ies); os_free(data.assoc_info.resp_ies);}static void wpa_driver_wext_event_wireless(struct wpa_driver_wext_data *drv, void *ctx, char *data, int len){ struct iw_event iwe_buf, *iwe = &iwe_buf; char *pos, *end, *custom, *buf; pos = data; end = data + len; while (pos + IW_EV_LCP_LEN <= end) { /* Event data may be unaligned, so make a local, aligned copy * before processing. */ os_memcpy(&iwe_buf, pos, IW_EV_LCP_LEN); wpa_printf(MSG_DEBUG, "Wireless event: cmd=0x%x len=%d", iwe->cmd, iwe->len); if (iwe->len <= IW_EV_LCP_LEN) return; custom = pos + IW_EV_POINT_LEN; if (drv->we_version_compiled > 18 && (iwe->cmd == IWEVMICHAELMICFAILURE || iwe->cmd == IWEVCUSTOM || iwe->cmd == IWEVASSOCREQIE || iwe->cmd == IWEVASSOCRESPIE || iwe->cmd == IWEVPMKIDCAND)) { /* WE-19 removed the pointer from struct iw_point */ char *dpos = (char *) &iwe_buf.u.data.length; int dlen = dpos - (char *) &iwe_buf; os_memcpy(dpos, pos + IW_EV_LCP_LEN, sizeof(struct iw_event) - dlen); } else { os_memcpy(&iwe_buf, pos, sizeof(struct iw_event)); custom += IW_EV_POINT_OFF; } switch (iwe->cmd) { case SIOCGIWAP: wpa_printf(MSG_DEBUG, "Wireless event: new AP: " MACSTR, MAC2STR((u8 *) iwe->u.ap_addr.sa_data)); if (is_zero_ether_addr( (const u8 *) iwe->u.ap_addr.sa_data) || os_memcmp(iwe->u.ap_addr.sa_data, "\x44\x44\x44\x44\x44\x44", ETH_ALEN) == 0) { os_free(drv->assoc_req_ies); drv->assoc_req_ies = NULL; os_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( ctx, custom, iwe->u.data.length); break; case IWEVCUSTOM: if (custom + iwe->u.data.length > end) return; buf = os_malloc(iwe->u.data.length + 1); if (buf == NULL) return; os_memcpy(buf, custom, iwe->u.data.length); buf[iwe->u.data.length] = '\0'; wpa_driver_wext_event_wireless_custom(ctx, buf); os_free(buf); break; case SIOCGIWSCAN: drv->scan_complete_events = 1; 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, custom, iwe->u.data.length); break; case IWEVASSOCRESPIE: wpa_driver_wext_event_wireless_assocrespie( drv, custom, iwe->u.data.length); break; case IWEVPMKIDCAND: wpa_driver_wext_event_wireless_pmkidcand( drv, 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; os_memset(&event, 0, sizeof(event)); if (len > sizeof(event.interface_status.ifname)) len = sizeof(event.interface_status.ifname) - 1; os_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"); if (os_strcmp(drv->ifname, event.interface_status.ifname) == 0) { if (del) drv->if_removed = 1; else drv->if_removed = 0; } wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event);}static int wpa_driver_wext_own_ifname(struct wpa_driver_wext_data *drv, struct nlmsghdr *h){ struct ifinfomsg *ifi; int attrlen, nlmsg_len, rta_len; struct rtattr *attr; ifi = NLMSG_DATA(h); nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg)); attrlen = h->nlmsg_len - nlmsg_len; if (attrlen < 0) return 0; 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) { if (os_strcmp(((char *) attr) + rta_len, drv->ifname) == 0) return 1; else break; } attr = RTA_NEXT(attr, attrlen); } return 0;}static int wpa_driver_wext_own_ifindex(struct wpa_driver_wext_data *drv, int ifindex, struct nlmsghdr *h){ if (drv->ifindex == ifindex || drv->ifindex2 == ifindex) return 1; if (drv->if_removed && wpa_driver_wext_own_ifname(drv, h)) { drv->ifindex = if_nametoindex(drv->ifname); wpa_printf(MSG_DEBUG, "WEXT: Update ifindex for a removed " "interface"); wpa_driver_wext_finish_drv_init(drv); return 1; } return 0;}static void wpa_driver_wext_event_rtm_newlink(struct wpa_driver_wext_data *drv, void *ctx, struct nlmsghdr *h, size_t len){ struct ifinfomsg *ifi; int attrlen, nlmsg_len, rta_len; struct rtattr * attr; if (len < sizeof(*ifi)) return; ifi = NLMSG_DATA(h); if (!wpa_driver_wext_own_ifindex(drv, ifi->ifi_index, h)) { wpa_printf(MSG_DEBUG, "Ignore event for foreign ifindex %d", ifi->ifi_index); return; } wpa_printf(MSG_DEBUG, "RTM_NEWLINK: operstate=%d ifi_flags=0x%x " "(%s%s%s%s)", drv->operstate, ifi->ifi_flags, (ifi->ifi_flags & IFF_UP) ? "[UP]" : "", (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "", (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "", (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : ""); /* * Some drivers send the association event before the operup event--in * this case, lifting operstate in wpa_driver_wext_set_operstate() * fails. This will hit us when wpa_supplicant does not need to do * IEEE 802.1X authentication */ if (drv->operstate == 1 && (ifi->ifi_flags & (IFF_LOWER_UP | IFF_DORMANT)) == IFF_LOWER_UP && !(ifi->ifi_flags & IFF_RUNNING)) wpa_driver_wext_send_oper_ifla(drv, -1, IF_OPER_UP); 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, size_t 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; int max_events = 10;try_again: 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 >= (int) 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); } if (--max_events > 0) { /* * Try to receive all events in one eloop call in order to * limit race condition on cases where AssocInfo event, Assoc * event, and EAPOL frames are received more or less at the * same time. We want to process the event messages first * before starting EAPOL processing. */ goto try_again; }}static int wpa_driver_wext_get_ifflags_ifname(struct wpa_driver_wext_data *drv, const char *ifname, int *flags){ struct ifreq ifr; os_memset(&ifr, 0, sizeof(ifr)); os_strlcpy(ifr.ifr_name, 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_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){ return wpa_driver_wext_get_ifflags_ifname(drv, drv->ifname, flags);}static int wpa_driver_wext_set_ifflags_ifname(struct wpa_driver_wext_data *drv, const char *ifname, int flags){ struct ifreq ifr; os_memset(&ifr, 0, sizeof(ifr)); os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); ifr.ifr_flags = flags & 0xffff; if (ioctl(drv->ioctl_sock, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) { perror("SIOCSIFFLAGS"); return -1; } return 0;}#ifdef CONFIG_CLIENT_MLMEstatic int wpa_driver_prism2_param_set(struct wpa_driver_wext_data *drv, int param, int value){ struct iwreq iwr; int *i; os_memset(&iwr, 0, sizeof(iwr)); os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); i = (int *) iwr.u.name; *i++ = param; *i++ = value; return ioctl(drv->ioctl_sock, PRISM2_IOCTL_PRISM2_PARAM, &iwr);}static int wpa_driver_prism2_param_get(struct wpa_driver_wext_data *drv, int param){ struct iwreq iwr; int *i; os_memset(&iwr, 0, sizeof(iwr)); os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); i = (int *) iwr.u.name; *i = param; if (ioctl(drv->ioctl_sock, PRISM2_IOCTL_GET_PRISM2_PARAM, &iwr) < 0) { perror("ioctl[PRISM2_IOCTL_GET_PRISM2_PARAM]"); return -1; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -