X-Git-Url: http://vcs.maemo.org/git/?a=blobdiff_plain;f=src%2Fdrivers%2Fdriver_nl80211.c;h=62cf3f6e9e526042dc3ac3283496b0e1da9acb06;hb=7e76ee9c45bdac7dc253ae7305cffaa642aceabe;hp=9413575d13a00224d788041b5d24e37028be35ec;hpb=8a27af5c70387a2aef710204df219af662cb35e9;p=wpasupplicant diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 9413575..62cf3f6 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -40,10 +40,10 @@ #include "radiotap_iter.h" #include "../../hostapd/hostapd_defs.h" +#include "../../hostapd/sta_flags.h" #endif /* CONFIG_AP || HOSTAPD */ #ifdef HOSTAPD -#include "../../hostapd/sta_flags.h" #include "ieee802_11_common.h" #ifdef CONFIG_LIBNL20 @@ -130,6 +130,11 @@ static int wpa_driver_nl80211_set_mode(void *priv, int mode); static int wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv); +#if defined(CONFIG_AP) || defined(HOSTAPD) +static void nl80211_remove_monitor_interface( + struct wpa_driver_nl80211_data *drv); +#endif /* CONFIG_AP || HOSTAPD */ + #ifdef CONFIG_AP static void nl80211_remove_iface(struct wpa_driver_nl80211_data *drv, int ifidx); @@ -735,9 +740,40 @@ static void mlme_event_assoc(struct wpa_driver_nl80211_data *drv, } +static void mlme_timeout_event(struct wpa_driver_nl80211_data *drv, + enum nl80211_commands cmd, struct nlattr *addr) +{ + union wpa_event_data event; + enum wpa_event_type ev; + + if (nla_len(addr) != ETH_ALEN) + return; + + wpa_printf(MSG_DEBUG, "nl80211: MLME event %d; timeout with " MACSTR, + cmd, MAC2STR((u8 *) nla_data(addr))); + + if (cmd == NL80211_CMD_AUTHENTICATE) + ev = EVENT_AUTH_TIMED_OUT; + else if (cmd == NL80211_CMD_ASSOCIATE) + ev = EVENT_ASSOC_TIMED_OUT; + else + return; + + os_memset(&event, 0, sizeof(event)); + os_memcpy(event.timeout_event.addr, nla_data(addr), ETH_ALEN); + wpa_supplicant_event(drv->ctx, ev, &event); +} + + static void mlme_event(struct wpa_driver_nl80211_data *drv, - enum nl80211_commands cmd, struct nlattr *frame) + enum nl80211_commands cmd, struct nlattr *frame, + struct nlattr *addr, struct nlattr *timed_out) { + if (timed_out && addr) { + mlme_timeout_event(drv, cmd, addr); + return; + } + if (frame == NULL) { wpa_printf(MSG_DEBUG, "nl80211: MLME event %d without frame " "data", cmd); @@ -856,7 +892,8 @@ static int process_event(struct nl_msg *msg, void *arg) case NL80211_CMD_ASSOCIATE: case NL80211_CMD_DEAUTHENTICATE: case NL80211_CMD_DISASSOCIATE: - mlme_event(drv, gnlh->cmd, tb[NL80211_ATTR_FRAME]); + mlme_event(drv, gnlh->cmd, tb[NL80211_ATTR_FRAME], + tb[NL80211_ATTR_MAC], tb[NL80211_ATTR_TIMED_OUT]); break; #endif /* HOSTAPD */ case NL80211_CMD_MICHAEL_MIC_FAILURE: @@ -1294,8 +1331,7 @@ static void wpa_driver_nl80211_deinit(void *priv) struct wpa_driver_nl80211_data *drv = priv; #if defined(CONFIG_AP) || defined(HOSTAPD) - if (drv->monitor_ifidx >= 0) - nl80211_remove_iface(drv, drv->monitor_ifidx); + nl80211_remove_monitor_interface(drv); if (drv->monitor_sock >= 0) { eloop_unregister_read_sock(drv->monitor_sock); close(drv->monitor_sock); @@ -1749,6 +1785,7 @@ static int wpa_driver_nl80211_deauthenticate(void *priv, const u8 *addr, { struct wpa_driver_nl80211_data *drv = priv; wpa_printf(MSG_DEBUG, "%s", __func__); + drv->associated = 0; return wpa_driver_nl80211_mlme(drv, addr, NL80211_CMD_DEAUTHENTICATE, reason_code); } @@ -1759,6 +1796,7 @@ static int wpa_driver_nl80211_disassociate(void *priv, const u8 *addr, { struct wpa_driver_nl80211_data *drv = priv; wpa_printf(MSG_DEBUG, "%s", __func__); + drv->associated = 0; return wpa_driver_nl80211_mlme(drv, addr, NL80211_CMD_DISASSOCIATE, reason_code); } @@ -2316,6 +2354,73 @@ nla_put_failure: return -1; } + +static int wpa_driver_nl80211_sta_add(const char *ifname, void *priv, + struct hostapd_sta_add_params *params) +{ + struct wpa_driver_nl80211_data *drv = priv; + struct nl_msg *msg; + int ret = -ENOBUFS; + + msg = nlmsg_alloc(); + if (!msg) + return -ENOMEM; + + genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, + 0, NL80211_CMD_NEW_STATION, 0); + + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(ifname)); + NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->addr); + NLA_PUT_U16(msg, NL80211_ATTR_STA_AID, params->aid); + NLA_PUT(msg, NL80211_ATTR_STA_SUPPORTED_RATES, params->supp_rates_len, + params->supp_rates); + NLA_PUT_U16(msg, NL80211_ATTR_STA_LISTEN_INTERVAL, + params->listen_interval); + +#ifdef CONFIG_IEEE80211N + if (params->ht_capabilities) { + NLA_PUT(msg, NL80211_ATTR_HT_CAPABILITY, + params->ht_capabilities->length, + ¶ms->ht_capabilities->data); + } +#endif /* CONFIG_IEEE80211N */ + + ret = send_and_recv_msgs(drv, msg, NULL, NULL); + if (ret) + wpa_printf(MSG_DEBUG, "nl80211: NL80211_CMD_NEW_STATION " + "result: %d (%s)", ret, strerror(-ret)); + if (ret == -EEXIST) + ret = 0; + nla_put_failure: + return ret; +} + + +static int wpa_driver_nl80211_sta_remove(void *priv, const u8 *addr) +{ + struct wpa_driver_nl80211_data *drv = priv; + struct nl_msg *msg; + int ret; + + msg = nlmsg_alloc(); + if (!msg) + return -ENOMEM; + + genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, + 0, NL80211_CMD_DEL_STATION, 0); + + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, + if_nametoindex(drv->ifname)); + NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); + + ret = send_and_recv_msgs(drv, msg, NULL, NULL); + if (ret == -ENOENT) + return 0; + return ret; + nla_put_failure: + return -ENOBUFS; +} + #endif /* CONFIG_AP || HOSTAPD */ @@ -2742,6 +2847,16 @@ static int add_monitor_filter(int s) } +static void nl80211_remove_monitor_interface( + struct wpa_driver_nl80211_data *drv) +{ + if (drv->monitor_ifidx >= 0) { + nl80211_remove_iface(drv, drv->monitor_ifidx); + drv->monitor_ifidx = -1; + } +} + + static int nl80211_create_monitor_interface(struct wpa_driver_nl80211_data *drv) { @@ -2798,10 +2913,155 @@ nl80211_create_monitor_interface(struct wpa_driver_nl80211_data *drv) return 0; error: - nl80211_remove_iface(drv, drv->monitor_ifidx); + nl80211_remove_monitor_interface(drv); return -1; } + +static const u8 rfc1042_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; + +static int wpa_driver_nl80211_hapd_send_eapol( + void *priv, const u8 *addr, const u8 *data, + size_t data_len, int encrypt, const u8 *own_addr) +{ + struct wpa_driver_nl80211_data *drv = priv; + struct ieee80211_hdr *hdr; + size_t len; + u8 *pos; + int res; +#if 0 /* FIX */ + int qos = sta->flags & WLAN_STA_WME; +#else + int qos = 0; +#endif + + len = sizeof(*hdr) + (qos ? 2 : 0) + sizeof(rfc1042_header) + 2 + + data_len; + hdr = os_zalloc(len); + if (hdr == NULL) { + printf("malloc() failed for i802_send_data(len=%lu)\n", + (unsigned long) len); + return -1; + } + + hdr->frame_control = + IEEE80211_FC(WLAN_FC_TYPE_DATA, WLAN_FC_STYPE_DATA); + hdr->frame_control |= host_to_le16(WLAN_FC_FROMDS); + if (encrypt) + hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP); +#if 0 /* To be enabled if qos determination is added above */ + if (qos) { + hdr->frame_control |= + host_to_le16(WLAN_FC_STYPE_QOS_DATA << 4); + } +#endif + + memcpy(hdr->IEEE80211_DA_FROMDS, addr, ETH_ALEN); + memcpy(hdr->IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN); + memcpy(hdr->IEEE80211_SA_FROMDS, own_addr, ETH_ALEN); + pos = (u8 *) (hdr + 1); + +#if 0 /* To be enabled if qos determination is added above */ + if (qos) { + /* add an empty QoS header if needed */ + pos[0] = 0; + pos[1] = 0; + pos += 2; + } +#endif + + memcpy(pos, rfc1042_header, sizeof(rfc1042_header)); + pos += sizeof(rfc1042_header); + WPA_PUT_BE16(pos, ETH_P_PAE); + pos += 2; + memcpy(pos, data, data_len); + + res = wpa_driver_nl80211_send_frame(drv, (u8 *) hdr, len, encrypt); + if (res < 0) { + wpa_printf(MSG_ERROR, "i802_send_eapol - packet len: %lu - " + "failed: %d (%s)", + (unsigned long) len, errno, strerror(errno)); + } + free(hdr); + + return res; +} + + +static u32 sta_flags_nl80211(int flags) +{ + u32 f = 0; + + if (flags & WLAN_STA_AUTHORIZED) + f |= BIT(NL80211_STA_FLAG_AUTHORIZED); + if (flags & WLAN_STA_WMM) + f |= BIT(NL80211_STA_FLAG_WME); + if (flags & WLAN_STA_SHORT_PREAMBLE) + f |= BIT(NL80211_STA_FLAG_SHORT_PREAMBLE); + if (flags & WLAN_STA_MFP) + f |= BIT(NL80211_STA_FLAG_MFP); + + return f; +} + + +static int wpa_driver_nl80211_sta_set_flags(void *priv, const u8 *addr, + int total_flags, int flags_or, + int flags_and) +{ + struct wpa_driver_nl80211_data *drv = priv; + struct nl_msg *msg, *flags = NULL; + struct nl80211_sta_flag_update upd; + + msg = nlmsg_alloc(); + if (!msg) + return -ENOMEM; + + flags = nlmsg_alloc(); + if (!flags) { + nlmsg_free(msg); + return -ENOMEM; + } + + genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, + 0, NL80211_CMD_SET_STATION, 0); + + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, + if_nametoindex(drv->ifname)); + NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); + + /* + * Backwards compatibility version using NL80211_ATTR_STA_FLAGS. This + * can be removed eventually. + */ + if (total_flags & WLAN_STA_AUTHORIZED) + NLA_PUT_FLAG(flags, NL80211_STA_FLAG_AUTHORIZED); + + if (total_flags & WLAN_STA_WMM) + NLA_PUT_FLAG(flags, NL80211_STA_FLAG_WME); + + if (total_flags & WLAN_STA_SHORT_PREAMBLE) + NLA_PUT_FLAG(flags, NL80211_STA_FLAG_SHORT_PREAMBLE); + + if (total_flags & WLAN_STA_MFP) + NLA_PUT_FLAG(flags, NL80211_STA_FLAG_MFP); + + if (nla_put_nested(msg, NL80211_ATTR_STA_FLAGS, flags)) + goto nla_put_failure; + + os_memset(&upd, 0, sizeof(upd)); + upd.mask = sta_flags_nl80211(flags_or | ~flags_and); + upd.set = sta_flags_nl80211(flags_or); + NLA_PUT(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd); + + nlmsg_free(flags); + + return send_and_recv_msgs(drv, msg, NULL, NULL); + nla_put_failure: + nlmsg_free(flags); + return -ENOBUFS; +} + #endif /* CONFIG_AP || HOSTAPD */ #ifdef CONFIG_AP @@ -2809,14 +3069,9 @@ nl80211_create_monitor_interface(struct wpa_driver_nl80211_data *drv) static int wpa_driver_nl80211_ap(struct wpa_driver_nl80211_data *drv, struct wpa_driver_associate_params *params) { - if (drv->monitor_ifidx < 0 && - nl80211_create_monitor_interface(drv)) - return -1; - if (wpa_driver_nl80211_set_mode(drv, params->mode) || wpa_driver_nl80211_set_freq(drv, params->freq, 0, 0)) { - nl80211_remove_iface(drv, drv->monitor_ifidx); - drv->monitor_ifidx = -1; + nl80211_remove_monitor_interface(drv); return -1; } @@ -2882,6 +3137,11 @@ static int wpa_driver_nl80211_associate( NLA_PUT(msg, NL80211_ATTR_IE, params->wpa_ie_len, params->wpa_ie); +#ifdef CONFIG_IEEE80211W + if (params->mgmt_frame_protection == MGMT_FRAME_PROTECTION_REQUIRED) + NLA_PUT_U32(msg, NL80211_ATTR_USE_MFP, NL80211_MFP_REQUIRED); +#endif /* CONFIG_IEEE80211W */ + ret = send_and_recv_msgs(drv, msg, NULL, NULL); msg = NULL; if (ret) { @@ -2947,11 +3207,14 @@ static int wpa_driver_nl80211_set_mode(void *priv, int mode) if (nl80211_set_mode(drv, drv->ifindex, nlmode) == 0) { drv->nlmode = nlmode; - return 0; + ret = 0; + goto done; } - if (nlmode == drv->nlmode) - return 0; /* Already in the requested mode */ + if (nlmode == drv->nlmode) { + ret = 0; + goto done; /* Already in the requested mode */ + } /* mac80211 doesn't allow mode changes while the device is up, so * take the device down, try to set the mode again, and bring the @@ -2967,6 +3230,19 @@ static int wpa_driver_nl80211_set_mode(void *priv, int mode) if (!ret) drv->nlmode = nlmode; +done: +#if defined(CONFIG_AP) || defined(HOSTAPD) + if (!ret && nlmode == NL80211_IFTYPE_AP) { + /* Setup additional AP mode functionality if needed */ + if (drv->monitor_ifidx < 0 && + nl80211_create_monitor_interface(drv)) + return -1; + } else if (!ret && nlmode != NL80211_IFTYPE_AP) { + /* Remove additional AP mode functionality */ + nl80211_remove_monitor_interface(drv); + } +#endif /* CONFIG_AP || HOSTAPD */ + return ret; } @@ -3000,9 +3276,6 @@ static int wpa_driver_nl80211_set_operstate(void *priv, int state) #ifdef HOSTAPD -static const u8 rfc1042_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; - - static struct i802_bss * get_bss(struct wpa_driver_nl80211_data *drv, int ifindex) { @@ -3184,77 +3457,63 @@ static int i802_set_freq(void *priv, struct hostapd_freq_params *freq) static int i802_set_rts(void *priv, int rts) { -#ifdef NO_WEXT - return -1; -#else /* NO_WEXT */ struct wpa_driver_nl80211_data *drv = priv; - struct iwreq iwr; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.rts.value = rts; - iwr.u.rts.fixed = 1; - - if (ioctl(drv->ioctl_sock, SIOCSIWRTS, &iwr) < 0) { - perror("ioctl[SIOCSIWRTS]"); - return -1; - } - - return 0; -#endif /* NO_WEXT */ -} - + struct nl_msg *msg; + int ret = -ENOBUFS; + u32 val; -static int i802_set_frag(void *priv, int frag) -{ -#ifdef NO_WEXT - return -1; -#else /* NO_WEXT */ - struct wpa_driver_nl80211_data *drv = priv; - struct iwreq iwr; + msg = nlmsg_alloc(); + if (!msg) + return -ENOMEM; - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.frag.value = frag; - iwr.u.frag.fixed = 1; + if (rts >= 2347) + val = (u32) -1; + else + val = rts; - if (ioctl(drv->ioctl_sock, SIOCSIWFRAG, &iwr) < 0) { - perror("ioctl[SIOCSIWFRAG]"); - return -1; - } + genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, + 0, NL80211_CMD_SET_WIPHY, 0); + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); + NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD, val); - return 0; -#endif /* NO_WEXT */ + ret = send_and_recv_msgs(drv, msg, NULL, NULL); + if (!ret) + return 0; +nla_put_failure: + wpa_printf(MSG_DEBUG, "nl80211: Failed to set RTS threshold %d: " + "%d (%s)", rts, ret, strerror(-ret)); + return ret; } -static int i802_set_retry(void *priv, int short_retry, int long_retry) +static int i802_set_frag(void *priv, int frag) { -#ifdef NO_WEXT - return -1; -#else /* NO_WEXT */ struct wpa_driver_nl80211_data *drv = priv; - struct iwreq iwr; + struct nl_msg *msg; + int ret = -ENOBUFS; + u32 val; - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); + msg = nlmsg_alloc(); + if (!msg) + return -ENOMEM; - iwr.u.retry.value = short_retry; - iwr.u.retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN; - if (ioctl(drv->ioctl_sock, SIOCSIWRETRY, &iwr) < 0) { - perror("ioctl[SIOCSIWRETRY(short)]"); - return -1; - } + if (frag >= 2346) + val = (u32) -1; + else + val = frag; - iwr.u.retry.value = long_retry; - iwr.u.retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX; - if (ioctl(drv->ioctl_sock, SIOCSIWRETRY, &iwr) < 0) { - perror("ioctl[SIOCSIWRETRY(long)]"); - return -1; - } + genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, + 0, NL80211_CMD_SET_WIPHY, 0); + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); + NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD, val); - return 0; -#endif /* NO_WEXT */ + ret = send_and_recv_msgs(drv, msg, NULL, NULL); + if (!ret) + return 0; +nla_put_failure: + wpa_printf(MSG_DEBUG, "nl80211: Failed to set fragmentation threshold " + "%d: %d (%s)", frag, ret, strerror(-ret)); + return ret; } @@ -3356,188 +3615,6 @@ static int i802_read_sta_data(void *priv, struct hostap_sta_driver_data *data, } -static int i802_send_eapol(void *priv, const u8 *addr, const u8 *data, - size_t data_len, int encrypt, const u8 *own_addr) -{ - struct wpa_driver_nl80211_data *drv = priv; - struct ieee80211_hdr *hdr; - size_t len; - u8 *pos; - int res; -#if 0 /* FIX */ - int qos = sta->flags & WLAN_STA_WME; -#else - int qos = 0; -#endif - - len = sizeof(*hdr) + (qos ? 2 : 0) + sizeof(rfc1042_header) + 2 + - data_len; - hdr = os_zalloc(len); - if (hdr == NULL) { - printf("malloc() failed for i802_send_data(len=%lu)\n", - (unsigned long) len); - return -1; - } - - hdr->frame_control = - IEEE80211_FC(WLAN_FC_TYPE_DATA, WLAN_FC_STYPE_DATA); - hdr->frame_control |= host_to_le16(WLAN_FC_FROMDS); - if (encrypt) - hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP); -#if 0 /* To be enabled if qos determination is added above */ - if (qos) { - hdr->frame_control |= - host_to_le16(WLAN_FC_STYPE_QOS_DATA << 4); - } -#endif - - memcpy(hdr->IEEE80211_DA_FROMDS, addr, ETH_ALEN); - memcpy(hdr->IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN); - memcpy(hdr->IEEE80211_SA_FROMDS, own_addr, ETH_ALEN); - pos = (u8 *) (hdr + 1); - -#if 0 /* To be enabled if qos determination is added above */ - if (qos) { - /* add an empty QoS header if needed */ - pos[0] = 0; - pos[1] = 0; - pos += 2; - } -#endif - - memcpy(pos, rfc1042_header, sizeof(rfc1042_header)); - pos += sizeof(rfc1042_header); - WPA_PUT_BE16(pos, ETH_P_PAE); - pos += 2; - memcpy(pos, data, data_len); - - res = wpa_driver_nl80211_send_frame(drv, (u8 *) hdr, len, encrypt); - if (res < 0) { - wpa_printf(MSG_ERROR, "i802_send_eapol - packet len: %lu - " - "failed: %d (%s)", - (unsigned long) len, errno, strerror(errno)); - } - free(hdr); - - return res; -} - - -static int i802_sta_add(const char *ifname, void *priv, - struct hostapd_sta_add_params *params) -{ - struct wpa_driver_nl80211_data *drv = priv; - struct nl_msg *msg; - int ret = -ENOBUFS; - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_NEW_STATION, 0); - - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, - if_nametoindex(drv->ifname)); - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->addr); - NLA_PUT_U16(msg, NL80211_ATTR_STA_AID, params->aid); - NLA_PUT(msg, NL80211_ATTR_STA_SUPPORTED_RATES, params->supp_rates_len, - params->supp_rates); - NLA_PUT_U16(msg, NL80211_ATTR_STA_LISTEN_INTERVAL, - params->listen_interval); - -#ifdef CONFIG_IEEE80211N - if (params->ht_capabilities) { - NLA_PUT(msg, NL80211_ATTR_HT_CAPABILITY, - params->ht_capabilities->length, - ¶ms->ht_capabilities->data); - } -#endif /* CONFIG_IEEE80211N */ - - ret = send_and_recv_msgs(drv, msg, NULL, NULL); - if (ret) - wpa_printf(MSG_DEBUG, "nl80211: NL80211_CMD_NEW_STATION " - "result: %d (%s)", ret, strerror(-ret)); - if (ret == -EEXIST) - ret = 0; - nla_put_failure: - return ret; -} - - -static int i802_sta_remove(void *priv, const u8 *addr) -{ - struct wpa_driver_nl80211_data *drv = priv; - struct nl_msg *msg; - int ret; - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_DEL_STATION, 0); - - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, - if_nametoindex(drv->ifname)); - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); - - ret = send_and_recv_msgs(drv, msg, NULL, NULL); - if (ret == -ENOENT) - return 0; - return ret; - nla_put_failure: - return -ENOBUFS; -} - - -static int i802_sta_set_flags(void *priv, const u8 *addr, - int total_flags, int flags_or, int flags_and) -{ - struct wpa_driver_nl80211_data *drv = priv; - struct nl_msg *msg, *flags = NULL; - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - flags = nlmsg_alloc(); - if (!flags) { - nlmsg_free(msg); - return -ENOMEM; - } - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_SET_STATION, 0); - - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, - if_nametoindex(drv->ifname)); - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); - - if (total_flags & WLAN_STA_AUTHORIZED) - NLA_PUT_FLAG(flags, NL80211_STA_FLAG_AUTHORIZED); - - if (total_flags & WLAN_STA_WMM) - NLA_PUT_FLAG(flags, NL80211_STA_FLAG_WME); - - if (total_flags & WLAN_STA_SHORT_PREAMBLE) - NLA_PUT_FLAG(flags, NL80211_STA_FLAG_SHORT_PREAMBLE); - - if (total_flags & WLAN_STA_MFP) - NLA_PUT_FLAG(flags, NL80211_STA_FLAG_MFP); - - if (nla_put_nested(msg, NL80211_ATTR_STA_FLAGS, flags)) - goto nla_put_failure; - - nlmsg_free(flags); - - return send_and_recv_msgs(drv, msg, NULL, NULL); - nla_put_failure: - nlmsg_free(flags); - return -ENOBUFS; -} - - static int i802_set_tx_queue_params(void *priv, int queue, int aifs, int cw_min, int cw_max, int burst_time) { @@ -3855,15 +3932,13 @@ static void *i802_init(struct hostapd_data *hapd, /* start listening for EAPOL on the default AP interface */ add_ifidx(drv, drv->ifindex); - if (hostapd_set_iface_flags(drv, drv->ifname, 0)) - goto failed; - - if (params->bssid && set_ifhwaddr(drv, drv->ifname, params->bssid)) - goto failed; + if (params->bssid) { + if (hostapd_set_iface_flags(drv, drv->ifname, 0)) + goto failed; - /* Initialise a monitor interface */ - if (nl80211_create_monitor_interface(drv)) - goto failed; + if (set_ifhwaddr(drv, drv->ifname, params->bssid)) + goto failed; + } if (nl80211_set_mode(drv, drv->ifindex, NL80211_IFTYPE_AP)) { wpa_printf(MSG_ERROR, "nl80211: Failed to set interface %s " @@ -3892,8 +3967,7 @@ static void *i802_init(struct hostapd_data *hapd, return drv; failed: - if (drv->monitor_ifidx >= 0) - nl80211_remove_iface(drv, drv->monitor_ifidx); + nl80211_remove_monitor_interface(drv); if (drv->ioctl_sock >= 0) close(drv->ioctl_sock); @@ -3944,6 +4018,10 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = { .send_mlme = wpa_driver_nl80211_send_mlme, .set_beacon_int = wpa_driver_nl80211_set_beacon_int, .get_hw_feature_data = wpa_driver_nl80211_get_hw_feature_data, + .sta_add = wpa_driver_nl80211_sta_add, + .sta_remove = wpa_driver_nl80211_sta_remove, + .hapd_send_eapol = wpa_driver_nl80211_hapd_send_eapol, + .sta_set_flags = wpa_driver_nl80211_sta_set_flags, #endif /* CONFIG_AP || HOSTAPD */ #ifdef HOSTAPD .hapd_init = i802_init, @@ -3952,18 +4030,13 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = { .get_seqnum = i802_get_seqnum, .flush = i802_flush, .read_sta_data = i802_read_sta_data, - .hapd_send_eapol = i802_send_eapol, - .sta_set_flags = i802_sta_set_flags, .sta_deauth = i802_sta_deauth, .sta_disassoc = i802_sta_disassoc, - .sta_remove = i802_sta_remove, - .sta_add = i802_sta_add, .get_inact_sec = i802_get_inact_sec, .sta_clear_stats = i802_sta_clear_stats, .set_freq = i802_set_freq, .set_rts = i802_set_rts, .set_frag = i802_set_frag, - .set_retry = i802_set_retry, .set_rate_sets = i802_set_rate_sets, .hapd_set_beacon = i802_set_beacon, .set_cts_protect = i802_set_cts_protect,