X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=src%2Fdrivers%2Fdriver_nl80211.c;h=8d43c6926e5919c1d7c051b3a4afc72cd6b0f715;hb=052b8d38c5799fb0c0983d6cf96d5d60754b46ae;hp=e7a818aec3421385b1e84ae9d46022e17ac513f9;hpb=7a69fad7aded13fff654282134e9d98de7dafdfd;p=mech_eap.git diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index e7a818a..8d43c69 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -200,6 +200,10 @@ static int nl80211_leave_ibss(struct wpa_driver_nl80211_data *drv, static int i802_set_iface_flags(struct i802_bss *bss, int up); static int nl80211_set_param(void *priv, const char *param); +#ifdef CONFIG_MESH +static int nl80211_put_mesh_config(struct nl_msg *msg, + struct wpa_driver_mesh_bss_params *params); +#endif /* CONFIG_MESH */ /* Converts nl80211_chan_width to a common format */ @@ -2332,7 +2336,8 @@ wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv, if (drv->hostapd || bss->static_ap) nlmode = NL80211_IFTYPE_AP; - else if (bss->if_dynamic) + else if (bss->if_dynamic || + nl80211_get_ifmode(bss) == NL80211_IFTYPE_MESH_POINT) nlmode = nl80211_get_ifmode(bss); else nlmode = NL80211_IFTYPE_STATION; @@ -3468,6 +3473,48 @@ static int nl80211_put_beacon_int(struct nl_msg *msg, int beacon_int) } +static int nl80211_put_dtim_period(struct nl_msg *msg, int dtim_period) +{ + if (dtim_period > 0) { + wpa_printf(MSG_DEBUG, " * dtim_period=%d", dtim_period); + return nla_put_u32(msg, NL80211_ATTR_DTIM_PERIOD, dtim_period); + } + + return 0; +} + + +#ifdef CONFIG_MESH +static int nl80211_set_mesh_config(void *priv, + struct wpa_driver_mesh_bss_params *params) +{ + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; + struct nl_msg *msg; + int ret; + + msg = nl80211_drv_msg(drv, 0, NL80211_CMD_SET_MESH_CONFIG); + if (!msg) + return -1; + + ret = nl80211_put_mesh_config(msg, params); + if (ret < 0) { + nlmsg_free(msg); + return ret; + } + + ret = send_and_recv_msgs(drv, msg, NULL, NULL); + if (ret) { + wpa_printf(MSG_ERROR, + "nl80211: Mesh config set failed: %d (%s)", + ret, strerror(-ret)); + return ret; + } + return 0; +} +#endif /* CONFIG_MESH */ + + static int wpa_driver_nl80211_set_ap(void *priv, struct wpa_driver_ap_params *params) { @@ -3481,6 +3528,9 @@ static int wpa_driver_nl80211_set_ap(void *priv, int smps_mode; u32 suites[10], suite; u32 ver; +#ifdef CONFIG_MESH + struct wpa_driver_mesh_bss_params mesh_params; +#endif /* CONFIG_MESH */ beacon_set = params->reenable ? 0 : bss->beacon_set; @@ -3504,7 +3554,7 @@ static int wpa_driver_nl80211_set_ap(void *priv, nla_put(msg, NL80211_ATTR_BEACON_TAIL, params->tail_len, params->tail) || nl80211_put_beacon_int(msg, params->beacon_int) || - nla_put_u32(msg, NL80211_ATTR_DTIM_PERIOD, params->dtim_period) || + nl80211_put_dtim_period(msg, params->dtim_period) || nla_put(msg, NL80211_ATTR_SSID, params->ssid_len, params->ssid)) goto fail; if (params->proberesp && params->proberesp_len) { @@ -3575,8 +3625,10 @@ static int wpa_driver_nl80211_set_ap(void *priv, goto fail; if (params->key_mgmt_suites & WPA_KEY_MGMT_IEEE8021X_NO_WPA && - params->pairwise_ciphers & (WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40) && - nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT)) + (!params->pairwise_ciphers || + params->pairwise_ciphers & (WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40)) && + (nla_put_u16(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE, ETH_P_PAE) || + nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT))) goto fail; wpa_printf(MSG_DEBUG, "nl80211: pairwise_ciphers=0x%x", @@ -3695,7 +3747,7 @@ static int wpa_driver_nl80211_set_ap(void *priv, "nl80211: Frequency set succeeded for ht2040 coex"); bss->bandwidth = params->freq->bandwidth; } - } else if (!beacon_set) { + } else if (!beacon_set && params->freq) { /* * cfg80211 updates the driver on frequence change in AP * mode only at the point when beaconing is started, so @@ -3704,6 +3756,18 @@ static int wpa_driver_nl80211_set_ap(void *priv, bss->bandwidth = params->freq->bandwidth; } } + +#ifdef CONFIG_MESH + if (is_mesh_interface(drv->nlmode) && params->ht_opmode != -1) { + os_memset(&mesh_params, 0, sizeof(mesh_params)); + mesh_params.flags |= WPA_DRIVER_MESH_CONF_FLAG_HT_OP_MODE; + mesh_params.ht_opmode = params->ht_opmode; + ret = nl80211_set_mesh_config(priv, &mesh_params); + if (ret < 0) + return ret; + } +#endif /* CONFIG_MESH */ + return ret; fail: nlmsg_free(msg); @@ -3777,6 +3841,12 @@ static int nl80211_put_freq_params(struct nl_msg *msg, wpa_printf(MSG_DEBUG, " * channel_type=%d", ct); if (nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, ct)) return -ENOBUFS; + } else { + wpa_printf(MSG_DEBUG, " * channel_type=%d", + NL80211_CHAN_NO_HT); + if (nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, + NL80211_CHAN_NO_HT)) + return -ENOBUFS; } return 0; } @@ -3839,11 +3909,11 @@ static u32 sta_flags_nl80211(int flags) static u32 sta_plink_state_nl80211(enum mesh_plink_state state) { switch (state) { - case PLINK_LISTEN: + case PLINK_IDLE: return NL80211_PLINK_LISTEN; - case PLINK_OPEN_SENT: + case PLINK_OPN_SNT: return NL80211_PLINK_OPN_SNT; - case PLINK_OPEN_RCVD: + case PLINK_OPN_RCVD: return NL80211_PLINK_OPN_RCVD; case PLINK_CNF_RCVD: return NL80211_PLINK_CNF_RCVD; @@ -4032,6 +4102,15 @@ static int wpa_driver_nl80211_sta_add(void *priv, if (!(params->flags & WPA_STA_ASSOCIATED)) upd.mask |= BIT(NL80211_STA_FLAG_ASSOCIATED); } +#ifdef CONFIG_MESH + } else { + if (params->plink_state == PLINK_ESTAB && params->peer_aid) { + ret = nla_put_u16(msg, NL80211_ATTR_MESH_PEER_AID, + params->peer_aid); + if (ret) + goto fail; + } +#endif /* CONFIG_MESH */ } wpa_printf(MSG_DEBUG, " * flags set=0x%x mask=0x%x", @@ -4355,8 +4434,7 @@ static int nl80211_setup_ap(struct i802_bss *bss) "nl80211: Failed to subscribe for mgmt frames from SME driver - trying to run without it"); if (!drv->device_ap_sme && drv->use_monitor && - nl80211_create_monitor_interface(drv) && - !drv->device_ap_sme) + nl80211_create_monitor_interface(drv)) return -1; if (drv->device_ap_sme && @@ -4877,6 +4955,14 @@ static int nl80211_connect_common(struct wpa_driver_nl80211_data *drv, if (nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT)) return -1; + if (params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_NO_WPA && + (params->pairwise_suite == WPA_CIPHER_NONE || + params->pairwise_suite == WPA_CIPHER_WEP104 || + params->pairwise_suite == WPA_CIPHER_WEP40) && + (nla_put_u16(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE, ETH_P_PAE) || + nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT))) + return -1; + if (params->mgmt_frame_protection == MGMT_FRAME_PROTECTION_REQUIRED && nla_put_u32(msg, NL80211_ATTR_USE_MFP, NL80211_MFP_REQUIRED)) return -1; @@ -7706,7 +7792,7 @@ static int wpa_driver_nl80211_update_ft_ies(void *priv, const u8 *md, } -const u8 * wpa_driver_nl80211_get_macaddr(void *priv) +static const u8 * wpa_driver_nl80211_get_macaddr(void *priv) { struct i802_bss *bss = priv; struct wpa_driver_nl80211_data *drv = bss->drv; @@ -8377,6 +8463,46 @@ static int nl80211_put_mesh_id(struct nl_msg *msg, const u8 *mesh_id, } +static int nl80211_put_mesh_config(struct nl_msg *msg, + struct wpa_driver_mesh_bss_params *params) +{ + struct nlattr *container; + + container = nla_nest_start(msg, NL80211_ATTR_MESH_CONFIG); + if (!container) + return -1; + + if (((params->flags & WPA_DRIVER_MESH_CONF_FLAG_AUTO_PLINKS) && + nla_put_u32(msg, NL80211_MESHCONF_AUTO_OPEN_PLINKS, + params->auto_plinks)) || + ((params->flags & WPA_DRIVER_MESH_CONF_FLAG_MAX_PEER_LINKS) && + nla_put_u16(msg, NL80211_MESHCONF_MAX_PEER_LINKS, + params->max_peer_links))) + return -1; + + /* + * Set NL80211_MESHCONF_PLINK_TIMEOUT even if user mpm is used because + * the timer could disconnect stations even in that case. + */ + if ((params->flags & WPA_DRIVER_MESH_CONF_FLAG_PEER_LINK_TIMEOUT) && + nla_put_u32(msg, NL80211_MESHCONF_PLINK_TIMEOUT, + params->peer_link_timeout)) { + wpa_printf(MSG_ERROR, "nl80211: Failed to set PLINK_TIMEOUT"); + return -1; + } + + if ((params->flags & WPA_DRIVER_MESH_CONF_FLAG_HT_OP_MODE) && + nla_put_u16(msg, NL80211_MESHCONF_HT_OPMODE, params->ht_opmode)) { + wpa_printf(MSG_ERROR, "nl80211: Failed to set HT_OP_MODE"); + return -1; + } + + nla_nest_end(msg, container); + + return 0; +} + + static int nl80211_join_mesh(struct i802_bss *bss, struct wpa_driver_mesh_join_params *params) { @@ -8391,7 +8517,8 @@ static int nl80211_join_mesh(struct i802_bss *bss, nl80211_put_freq_params(msg, ¶ms->freq) || nl80211_put_basic_rates(msg, params->basic_rates) || nl80211_put_mesh_id(msg, params->meshid, params->meshid_len) || - nl80211_put_beacon_int(msg, params->beacon_int)) + nl80211_put_beacon_int(msg, params->beacon_int) || + nl80211_put_dtim_period(msg, params->dtim_period)) goto fail; wpa_printf(MSG_DEBUG, " * flags=%08X", params->flags); @@ -8420,28 +8547,11 @@ static int nl80211_join_mesh(struct i802_bss *bss, goto fail; nla_nest_end(msg, container); - container = nla_nest_start(msg, NL80211_ATTR_MESH_CONFIG); - if (!container) - goto fail; - - if (!(params->conf.flags & WPA_DRIVER_MESH_CONF_FLAG_AUTO_PLINKS) && - nla_put_u32(msg, NL80211_MESHCONF_AUTO_OPEN_PLINKS, 0)) - goto fail; - if (nla_put_u16(msg, NL80211_MESHCONF_MAX_PEER_LINKS, - params->max_peer_links)) - goto fail; - - /* - * Set NL80211_MESHCONF_PLINK_TIMEOUT even if user mpm is used because - * the timer could disconnect stations even in that case. - */ - if (nla_put_u32(msg, NL80211_MESHCONF_PLINK_TIMEOUT, - params->conf.peer_link_timeout)) { - wpa_printf(MSG_ERROR, "nl80211: Failed to set PLINK_TIMEOUT"); + params->conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_AUTO_PLINKS; + params->conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_PEER_LINK_TIMEOUT; + params->conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_MAX_PEER_LINKS; + if (nl80211_put_mesh_config(msg, ¶ms->conf) < 0) goto fail; - } - - nla_nest_end(msg, container); ret = send_and_recv_msgs(drv, msg, NULL, NULL); msg = NULL; @@ -9117,6 +9227,89 @@ static int nl80211_set_prob_oper_freq(void *priv, unsigned int freq) return 0; } + +static int nl80211_p2p_lo_start(void *priv, unsigned int freq, + unsigned int period, unsigned int interval, + unsigned int count, const u8 *device_types, + size_t dev_types_len, + const u8 *ies, size_t ies_len) +{ + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; + struct nl_msg *msg; + struct nlattr *container; + int ret; + + wpa_printf(MSG_DEBUG, + "nl80211: Start P2P Listen offload: freq=%u, period=%u, interval=%u, count=%u", + freq, period, interval, count); + + if (!(drv->capa.flags & WPA_DRIVER_FLAGS_P2P_LISTEN_OFFLOAD)) + return -1; + + if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) || + nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) || + nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, + QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START)) + goto fail; + + container = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA); + if (!container) + goto fail; + + if (nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL, + freq) || + nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD, + period) || + nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL, + interval) || + nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT, + count) || + nla_put(msg, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES, + dev_types_len, device_types) || + nla_put(msg, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE, + ies_len, ies)) + goto fail; + + nla_nest_end(msg, container); + ret = send_and_recv_msgs(drv, msg, NULL, NULL); + msg = NULL; + if (ret) { + wpa_printf(MSG_DEBUG, + "nl80211: Failed to send P2P Listen offload vendor command"); + goto fail; + } + + return 0; + +fail: + nlmsg_free(msg); + return -1; +} + + +static int nl80211_p2p_lo_stop(void *priv) +{ + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; + struct nl_msg *msg; + + wpa_printf(MSG_DEBUG, "nl80211: Stop P2P Listen offload"); + + if (!(drv->capa.flags & WPA_DRIVER_FLAGS_P2P_LISTEN_OFFLOAD)) + return -1; + + if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) || + nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) || + nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, + QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP)) { + nlmsg_free(msg); + return -1; + } + + return send_and_recv_msgs(drv, msg, NULL, NULL); +} + #endif /* CONFIG_DRIVER_NL80211_QCA */ @@ -9338,9 +9531,6 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = { .vendor_cmd = nl80211_vendor_cmd, .set_qos_map = nl80211_set_qos_map, .set_wowlan = nl80211_set_wowlan, -#ifdef CONFIG_DRIVER_NL80211_QCA - .roaming = nl80211_roaming, -#endif /* CONFIG_DRIVER_NL80211_QCA */ .set_mac_addr = nl80211_set_mac_addr, #ifdef CONFIG_MESH .init_mesh = wpa_driver_nl80211_init_mesh, @@ -9355,10 +9545,14 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = { .del_tx_ts = nl80211_del_ts, .get_ifindex = nl80211_get_ifindex, #ifdef CONFIG_DRIVER_NL80211_QCA + .roaming = nl80211_roaming, .do_acs = wpa_driver_do_acs, .set_band = nl80211_set_band, .get_pref_freq_list = nl80211_get_pref_freq_list, .set_prob_oper_freq = nl80211_set_prob_oper_freq, + .p2p_lo_start = nl80211_p2p_lo_start, + .p2p_lo_stop = nl80211_p2p_lo_stop, + .set_default_scan_ies = nl80211_set_default_scan_ies, #endif /* CONFIG_DRIVER_NL80211_QCA */ .configure_data_frame_filters = nl80211_configure_data_frame_filters, .get_ext_capab = nl80211_get_ext_capab,