hostapd: Add WDS (4-address frame) mode with per-station interfaces
This mode allows associated stations to use 4-address frames to allow layer 2 bridging to be used. At least for the time being, this is only supported with driver=nl80211.
This commit is contained in:
parent
09eac1ac56
commit
fbbfcbac29
14 changed files with 96 additions and 18 deletions
|
@ -1534,6 +1534,8 @@ struct hostapd_config * hostapd_config_read(const char *fname)
|
||||||
line, pos);
|
line, pos);
|
||||||
errors++;
|
errors++;
|
||||||
}
|
}
|
||||||
|
} else if (os_strcmp(buf, "wds_sta") == 0) {
|
||||||
|
bss->wds_sta = atoi(pos);
|
||||||
} else if (os_strcmp(buf, "ap_max_inactivity") == 0) {
|
} else if (os_strcmp(buf, "ap_max_inactivity") == 0) {
|
||||||
bss->ap_max_inactivity = atoi(pos);
|
bss->ap_max_inactivity = atoi(pos);
|
||||||
} else if (os_strcmp(buf, "country_code") == 0) {
|
} else if (os_strcmp(buf, "country_code") == 0) {
|
||||||
|
|
|
@ -194,6 +194,7 @@ struct hostapd_bss_config {
|
||||||
int num_accept_mac;
|
int num_accept_mac;
|
||||||
struct mac_acl_entry *deny_mac;
|
struct mac_acl_entry *deny_mac;
|
||||||
int num_deny_mac;
|
int num_deny_mac;
|
||||||
|
int wds_sta;
|
||||||
|
|
||||||
int auth_algs; /* bitfield of allowed IEEE 802.11 authentication
|
int auth_algs; /* bitfield of allowed IEEE 802.11 authentication
|
||||||
* algorithms, WPA_AUTH_ALG_{OPEN,SHARED,LEAP} */
|
* algorithms, WPA_AUTH_ALG_{OPEN,SHARED,LEAP} */
|
||||||
|
|
|
@ -399,6 +399,15 @@ hostapd_set_sta_vlan(const char *ifname, struct hostapd_data *hapd,
|
||||||
return hapd->driver->set_sta_vlan(hapd->drv_priv, addr, ifname, vlan_id);
|
return hapd->driver->set_sta_vlan(hapd->drv_priv, addr, ifname, vlan_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
hostapd_set_wds_sta(struct hostapd_data *hapd, const u8 *addr, int aid,
|
||||||
|
int val)
|
||||||
|
{
|
||||||
|
if (hapd->driver == NULL || hapd->driver->set_wds_sta == NULL)
|
||||||
|
return 0;
|
||||||
|
return hapd->driver->set_wds_sta(hapd->drv_priv, addr, aid, val);
|
||||||
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
hostapd_driver_commit(struct hostapd_data *hapd)
|
hostapd_driver_commit(struct hostapd_data *hapd)
|
||||||
{
|
{
|
||||||
|
|
|
@ -299,6 +299,7 @@ static const u8 * get_hdr_bssid(const struct ieee80211_hdr *hdr, size_t len)
|
||||||
if (len < 24)
|
if (len < 24)
|
||||||
return NULL;
|
return NULL;
|
||||||
switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) {
|
switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) {
|
||||||
|
case WLAN_FC_FROMDS | WLAN_FC_TODS:
|
||||||
case WLAN_FC_TODS:
|
case WLAN_FC_TODS:
|
||||||
return hdr->addr1;
|
return hdr->addr1;
|
||||||
case WLAN_FC_FROMDS:
|
case WLAN_FC_FROMDS:
|
||||||
|
@ -344,11 +345,14 @@ static void hostapd_rx_from_unknown_sta(struct hostapd_data *hapd,
|
||||||
const struct ieee80211_hdr *hdr,
|
const struct ieee80211_hdr *hdr,
|
||||||
size_t len)
|
size_t len)
|
||||||
{
|
{
|
||||||
|
u16 fc = le_to_host16(hdr->frame_control);
|
||||||
hapd = get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len));
|
hapd = get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len));
|
||||||
if (hapd == NULL || hapd == HAPD_BROADCAST)
|
if (hapd == NULL || hapd == HAPD_BROADCAST)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ieee802_11_rx_from_unknown(hapd, hdr->addr2);
|
ieee802_11_rx_from_unknown(hapd, hdr->addr2,
|
||||||
|
(fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) ==
|
||||||
|
(WLAN_FC_TODS | WLAN_FC_FROMDS));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -106,7 +106,7 @@ static void hostapd_dump_state(struct hostapd_data *hapd)
|
||||||
fprintf(f, "\nSTA=" MACSTR "\n", MAC2STR(sta->addr));
|
fprintf(f, "\nSTA=" MACSTR "\n", MAC2STR(sta->addr));
|
||||||
|
|
||||||
fprintf(f,
|
fprintf(f,
|
||||||
" AID=%d flags=0x%x %s%s%s%s%s%s%s%s%s%s%s%s%s%s\n"
|
" AID=%d flags=0x%x %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n"
|
||||||
" capability=0x%x listen_interval=%d\n",
|
" capability=0x%x listen_interval=%d\n",
|
||||||
sta->aid,
|
sta->aid,
|
||||||
sta->flags,
|
sta->flags,
|
||||||
|
@ -126,6 +126,7 @@ static void hostapd_dump_state(struct hostapd_data *hapd)
|
||||||
(sta->flags & WLAN_STA_MFP ? "[MFP]" : ""),
|
(sta->flags & WLAN_STA_MFP ? "[MFP]" : ""),
|
||||||
(sta->flags & WLAN_STA_WPS ? "[WPS]" : ""),
|
(sta->flags & WLAN_STA_WPS ? "[WPS]" : ""),
|
||||||
(sta->flags & WLAN_STA_MAYBE_WPS ? "[MAYBE_WPS]" : ""),
|
(sta->flags & WLAN_STA_MAYBE_WPS ? "[MAYBE_WPS]" : ""),
|
||||||
|
(sta->flags & WLAN_STA_WDS ? "[WDS]" : ""),
|
||||||
(sta->flags & WLAN_STA_NONERP ? "[NonERP]" : ""),
|
(sta->flags & WLAN_STA_NONERP ? "[NonERP]" : ""),
|
||||||
sta->capability,
|
sta->capability,
|
||||||
sta->listen_interval);
|
sta->listen_interval);
|
||||||
|
|
|
@ -346,6 +346,12 @@ wmm_ac_vo_acm=0
|
||||||
# remain asleep). Default: 65535 (no limit apart from field size)
|
# remain asleep). Default: 65535 (no limit apart from field size)
|
||||||
#max_listen_interval=100
|
#max_listen_interval=100
|
||||||
|
|
||||||
|
# WDS (4-address frame) mode with per-station virtual interfaces
|
||||||
|
# (only supported with driver=nl80211)
|
||||||
|
# This mode allows associated stations to use 4-address frames to allow layer 2
|
||||||
|
# bridging to be used.
|
||||||
|
#wds_sta=1
|
||||||
|
|
||||||
##### IEEE 802.11n related configuration ######################################
|
##### IEEE 802.11n related configuration ######################################
|
||||||
|
|
||||||
# ieee80211n: Whether IEEE 802.11n (HT) is enabled
|
# ieee80211n: Whether IEEE 802.11n (HT) is enabled
|
||||||
|
|
|
@ -1689,13 +1689,22 @@ void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src)
|
void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src,
|
||||||
|
int wds)
|
||||||
{
|
{
|
||||||
struct sta_info *sta;
|
struct sta_info *sta;
|
||||||
|
|
||||||
sta = ap_get_sta(hapd, src);
|
sta = ap_get_sta(hapd, src);
|
||||||
if (sta && (sta->flags & WLAN_STA_ASSOC))
|
if (sta && (sta->flags & WLAN_STA_ASSOC)) {
|
||||||
|
if (wds && !(sta->flags & WLAN_STA_WDS)) {
|
||||||
|
wpa_printf(MSG_DEBUG, "Enable 4-address WDS mode for "
|
||||||
|
"STA " MACSTR " (aid %u)",
|
||||||
|
MAC2STR(sta->addr), sta->aid);
|
||||||
|
sta->flags |= WLAN_STA_WDS;
|
||||||
|
hostapd_set_wds_sta(hapd, sta->addr, sta->aid, 1);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "Data/PS-poll frame from not associated STA "
|
wpa_printf(MSG_DEBUG, "Data/PS-poll frame from not associated STA "
|
||||||
MACSTR, MAC2STR(src));
|
MACSTR, MAC2STR(src));
|
||||||
|
|
|
@ -65,6 +65,7 @@ u16 copy_sta_ht_capab(struct sta_info *sta, const u8 *ht_capab,
|
||||||
void update_ht_state(struct hostapd_data *hapd, struct sta_info *sta);
|
void update_ht_state(struct hostapd_data *hapd, struct sta_info *sta);
|
||||||
void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,
|
void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,
|
||||||
const u8 *buf, size_t len, int ack);
|
const u8 *buf, size_t len, int ack);
|
||||||
void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src);
|
void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src,
|
||||||
|
int wds);
|
||||||
|
|
||||||
#endif /* IEEE802_11_H */
|
#endif /* IEEE802_11_H */
|
||||||
|
|
|
@ -120,6 +120,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
|
||||||
|
|
||||||
accounting_sta_stop(hapd, sta);
|
accounting_sta_stop(hapd, sta);
|
||||||
|
|
||||||
|
hostapd_set_wds_sta(hapd, sta->addr, sta->aid, 0);
|
||||||
if (!ap_sta_in_other_bss(hapd, sta, WLAN_STA_ASSOC) &&
|
if (!ap_sta_in_other_bss(hapd, sta, WLAN_STA_ASSOC) &&
|
||||||
!(sta->flags & WLAN_STA_PREAUTH))
|
!(sta->flags & WLAN_STA_PREAUTH))
|
||||||
hostapd_sta_remove(hapd, sta->addr);
|
hostapd_sta_remove(hapd, sta->addr);
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#define WLAN_STA_HT BIT(11)
|
#define WLAN_STA_HT BIT(11)
|
||||||
#define WLAN_STA_WPS BIT(12)
|
#define WLAN_STA_WPS BIT(12)
|
||||||
#define WLAN_STA_MAYBE_WPS BIT(13)
|
#define WLAN_STA_MAYBE_WPS BIT(13)
|
||||||
|
#define WLAN_STA_WDS BIT(14)
|
||||||
#define WLAN_STA_NONERP BIT(31)
|
#define WLAN_STA_NONERP BIT(31)
|
||||||
|
|
||||||
/* Maximum number of supported rates (from both Supported Rates and Extended
|
/* Maximum number of supported rates (from both Supported Rates and Extended
|
||||||
|
|
|
@ -1527,6 +1527,16 @@ struct wpa_driver_ops {
|
||||||
* Returns: 0 on success, -1 on failure
|
* Returns: 0 on success, -1 on failure
|
||||||
*/
|
*/
|
||||||
int (*set_supp_port)(void *priv, int authorized);
|
int (*set_supp_port)(void *priv, int authorized);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set_wds_sta - Bind a station into a 4-address WDS (AP only)
|
||||||
|
* @priv: Private driver interface data
|
||||||
|
* @addr: MAC address of the associated station
|
||||||
|
* @aid: Association ID
|
||||||
|
* @val: 1 = bind to 4-address WDS; 0 = unbind
|
||||||
|
* Returns: 0 on success, -1 on failure
|
||||||
|
*/
|
||||||
|
int (*set_wds_sta)(void *priv, const u8 *addr, int aid, int val);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -3244,5 +3244,6 @@ const struct wpa_driver_ops wpa_driver_ndis_ops = {
|
||||||
NULL /* set_ht_params */,
|
NULL /* set_ht_params */,
|
||||||
NULL /* set_wps_beacon_ie */,
|
NULL /* set_wps_beacon_ie */,
|
||||||
NULL /* set_wps_probe_resp_ie */,
|
NULL /* set_wps_probe_resp_ie */,
|
||||||
NULL /* set_supp_port */
|
NULL /* set_supp_port */,
|
||||||
|
NULL /* set_wds_sta */
|
||||||
};
|
};
|
||||||
|
|
|
@ -128,6 +128,9 @@ static void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx);
|
||||||
static struct i802_bss * get_bss(struct wpa_driver_nl80211_data *drv,
|
static struct i802_bss * get_bss(struct wpa_driver_nl80211_data *drv,
|
||||||
int ifindex);
|
int ifindex);
|
||||||
static int i802_set_freq(void *priv, struct hostapd_freq_params *freq);
|
static int i802_set_freq(void *priv, struct hostapd_freq_params *freq);
|
||||||
|
static int wpa_driver_nl80211_if_remove(void *priv,
|
||||||
|
enum wpa_driver_if_type type,
|
||||||
|
const char *ifname);
|
||||||
#endif /* HOSTAPD */
|
#endif /* HOSTAPD */
|
||||||
|
|
||||||
|
|
||||||
|
@ -2553,7 +2556,7 @@ static void nl80211_remove_iface(struct wpa_driver_nl80211_data *drv,
|
||||||
static int nl80211_create_iface_once(struct wpa_driver_nl80211_data *drv,
|
static int nl80211_create_iface_once(struct wpa_driver_nl80211_data *drv,
|
||||||
const char *ifname,
|
const char *ifname,
|
||||||
enum nl80211_iftype iftype,
|
enum nl80211_iftype iftype,
|
||||||
const u8 *addr)
|
const u8 *addr, int wds)
|
||||||
{
|
{
|
||||||
struct nl_msg *msg, *flags = NULL;
|
struct nl_msg *msg, *flags = NULL;
|
||||||
int ifidx;
|
int ifidx;
|
||||||
|
@ -2584,6 +2587,8 @@ static int nl80211_create_iface_once(struct wpa_driver_nl80211_data *drv,
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
|
} else if (wds) {
|
||||||
|
NLA_PUT_U8(msg, NL80211_ATTR_4ADDR, wds);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
|
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
|
||||||
|
@ -2616,11 +2621,11 @@ static int nl80211_create_iface_once(struct wpa_driver_nl80211_data *drv,
|
||||||
|
|
||||||
static int nl80211_create_iface(struct wpa_driver_nl80211_data *drv,
|
static int nl80211_create_iface(struct wpa_driver_nl80211_data *drv,
|
||||||
const char *ifname, enum nl80211_iftype iftype,
|
const char *ifname, enum nl80211_iftype iftype,
|
||||||
const u8 *addr)
|
const u8 *addr, int wds)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = nl80211_create_iface_once(drv, ifname, iftype, addr);
|
ret = nl80211_create_iface_once(drv, ifname, iftype, addr, wds);
|
||||||
|
|
||||||
/* if error occured and interface exists already */
|
/* if error occured and interface exists already */
|
||||||
if (ret == -ENFILE && if_nametoindex(ifname)) {
|
if (ret == -ENFILE && if_nametoindex(ifname)) {
|
||||||
|
@ -2630,7 +2635,8 @@ static int nl80211_create_iface(struct wpa_driver_nl80211_data *drv,
|
||||||
nl80211_remove_iface(drv, if_nametoindex(ifname));
|
nl80211_remove_iface(drv, if_nametoindex(ifname));
|
||||||
|
|
||||||
/* Try to create the interface again */
|
/* Try to create the interface again */
|
||||||
ret = nl80211_create_iface_once(drv, ifname, iftype, addr);
|
ret = nl80211_create_iface_once(drv, ifname, iftype, addr,
|
||||||
|
wds);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -2817,7 +2823,7 @@ static struct sock_filter msock_filter_insns[] = {
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/*
|
/*
|
||||||
* drop non-data frames, WDS frames
|
* drop non-data frames
|
||||||
*/
|
*/
|
||||||
/* load the lower byte of the frame control field */
|
/* load the lower byte of the frame control field */
|
||||||
BPF_STMT(BPF_LD | BPF_B | BPF_IND, 0),
|
BPF_STMT(BPF_LD | BPF_B | BPF_IND, 0),
|
||||||
|
@ -2825,13 +2831,13 @@ static struct sock_filter msock_filter_insns[] = {
|
||||||
BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x0c),
|
BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x0c),
|
||||||
/* drop non-data frames */
|
/* drop non-data frames */
|
||||||
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 8, 0, FAIL),
|
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 8, 0, FAIL),
|
||||||
|
#endif
|
||||||
/* load the upper byte of the frame control field */
|
/* load the upper byte of the frame control field */
|
||||||
BPF_STMT(BPF_LD | BPF_B | BPF_IND, 0),
|
BPF_STMT(BPF_LD | BPF_B | BPF_IND, 1),
|
||||||
/* mask off toDS/fromDS */
|
/* mask off toDS/fromDS */
|
||||||
BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x03),
|
BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x03),
|
||||||
/* drop WDS frames */
|
/* accept WDS frames */
|
||||||
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 3, FAIL, 0),
|
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 3, PASS, 0),
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* add header length to index
|
* add header length to index
|
||||||
|
@ -2937,7 +2943,8 @@ nl80211_create_monitor_interface(struct wpa_driver_nl80211_data *drv)
|
||||||
buf[IFNAMSIZ - 1] = '\0';
|
buf[IFNAMSIZ - 1] = '\0';
|
||||||
|
|
||||||
drv->monitor_ifidx =
|
drv->monitor_ifidx =
|
||||||
nl80211_create_iface(drv, buf, NL80211_IFTYPE_MONITOR, NULL);
|
nl80211_create_iface(drv, buf, NL80211_IFTYPE_MONITOR, NULL,
|
||||||
|
0);
|
||||||
|
|
||||||
if (drv->monitor_ifidx < 0)
|
if (drv->monitor_ifidx < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -4065,6 +4072,26 @@ static int i802_set_sta_vlan(void *priv, const u8 *addr,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int i802_set_wds_sta(void *priv, const u8 *addr, int aid, int val)
|
||||||
|
{
|
||||||
|
struct wpa_driver_nl80211_data *drv = priv;
|
||||||
|
char name[16];
|
||||||
|
|
||||||
|
os_snprintf(name, sizeof(name), "%s.sta%d", drv->ifname, aid);
|
||||||
|
if (val) {
|
||||||
|
if (nl80211_create_iface(priv, name, NL80211_IFTYPE_AP_VLAN,
|
||||||
|
NULL, 1) < 0)
|
||||||
|
return -1;
|
||||||
|
hostapd_set_iface_flags(drv, name, 1);
|
||||||
|
return i802_set_sta_vlan(priv, addr, name, 0);
|
||||||
|
} else {
|
||||||
|
i802_set_sta_vlan(priv, addr, drv->ifname, 0);
|
||||||
|
return wpa_driver_nl80211_if_remove(priv, WPA_IF_AP_VLAN,
|
||||||
|
name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void handle_eapol(int sock, void *eloop_ctx, void *sock_ctx)
|
static void handle_eapol(int sock, void *eloop_ctx, void *sock_ctx)
|
||||||
{
|
{
|
||||||
struct wpa_driver_nl80211_data *drv = eloop_ctx;
|
struct wpa_driver_nl80211_data *drv = eloop_ctx;
|
||||||
|
@ -4262,7 +4289,8 @@ static int wpa_driver_nl80211_if_add(const char *iface, void *priv,
|
||||||
#endif /* HOSTAPD */
|
#endif /* HOSTAPD */
|
||||||
|
|
||||||
ifidx = nl80211_create_iface(drv, ifname,
|
ifidx = nl80211_create_iface(drv, ifname,
|
||||||
wpa_driver_nl80211_if_type(type), addr);
|
wpa_driver_nl80211_if_type(type), addr,
|
||||||
|
0);
|
||||||
if (ifidx < 0) {
|
if (ifidx < 0) {
|
||||||
#ifdef HOSTAPD
|
#ifdef HOSTAPD
|
||||||
os_free(bss);
|
os_free(bss);
|
||||||
|
@ -4363,5 +4391,6 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
|
||||||
.set_short_slot_time = i802_set_short_slot_time,
|
.set_short_slot_time = i802_set_short_slot_time,
|
||||||
.set_tx_queue_params = i802_set_tx_queue_params,
|
.set_tx_queue_params = i802_set_tx_queue_params,
|
||||||
.set_sta_vlan = i802_set_sta_vlan,
|
.set_sta_vlan = i802_set_sta_vlan,
|
||||||
|
.set_wds_sta = i802_set_wds_sta,
|
||||||
#endif /* HOSTAPD */
|
#endif /* HOSTAPD */
|
||||||
};
|
};
|
||||||
|
|
|
@ -507,7 +507,10 @@ void ap_rx_from_unknown_sta(void *ctx, const struct ieee80211_hdr *hdr,
|
||||||
{
|
{
|
||||||
#ifdef NEED_AP_MLME
|
#ifdef NEED_AP_MLME
|
||||||
struct wpa_supplicant *wpa_s = ctx;
|
struct wpa_supplicant *wpa_s = ctx;
|
||||||
ieee802_11_rx_from_unknown(wpa_s->ap_iface->bss[0], hdr->addr2);
|
u16 fc = le_to_host16(hdr->frame_control);
|
||||||
|
ieee802_11_rx_from_unknown(wpa_s->ap_iface->bss[0], hdr->addr2,
|
||||||
|
(fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) ==
|
||||||
|
(WLAN_FC_TODS | WLAN_FC_FROMDS));
|
||||||
#endif /* NEED_AP_MLME */
|
#endif /* NEED_AP_MLME */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue