3 @@ -1526,6 +1526,8 @@ struct hostapd_config * hostapd_config_r
7 + } else if (os_strcmp(buf, "wds_sta") == 0) {
8 + bss->wds_sta = atoi(pos);
9 } else if (os_strcmp(buf, "ap_max_inactivity") == 0) {
10 bss->ap_max_inactivity = atoi(pos);
11 } else if (os_strcmp(buf, "country_code") == 0) {
12 --- a/hostapd/config.h
13 +++ b/hostapd/config.h
14 @@ -195,6 +195,7 @@ struct hostapd_bss_config {
16 struct mac_acl_entry *deny_mac;
20 int auth_algs; /* bitfield of allowed IEEE 802.11 authentication
21 * algorithms, WPA_AUTH_ALG_{OPEN,SHARED,LEAP} */
22 --- a/src/drivers/driver.h
23 +++ b/src/drivers/driver.h
24 @@ -1127,6 +1127,7 @@ struct wpa_driver_ops {
25 const char *ifname, const u8 *addr);
26 int (*set_sta_vlan)(void *priv, const u8 *addr, const char *ifname,
28 + int (*set_wds_sta)(void *priv, const u8 *addr, int aid, int val);
30 * commit - Optional commit changes handler
31 * @priv: driver private data
32 --- a/src/drivers/driver_nl80211.c
33 +++ b/src/drivers/driver_nl80211.c
34 @@ -2675,7 +2675,7 @@ static void nl80211_remove_iface(struct
35 static int nl80211_create_iface_once(struct wpa_driver_nl80211_data *drv,
37 enum nl80211_iftype iftype,
39 + const u8 *addr, int wds)
41 struct nl_msg *msg, *flags = NULL;
43 @@ -2706,6 +2706,8 @@ static int nl80211_create_iface_once(str
48 + NLA_PUT_U8(msg, NL80211_ATTR_4ADDR, wds);
51 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
52 @@ -2736,11 +2738,11 @@ static int nl80211_create_iface_once(str
54 static int nl80211_create_iface(struct wpa_driver_nl80211_data *drv,
55 const char *ifname, enum nl80211_iftype iftype,
57 + const u8 *addr, int wds)
61 - ret = nl80211_create_iface_once(drv, ifname, iftype, addr);
62 + ret = nl80211_create_iface_once(drv, ifname, iftype, addr, wds);
64 /* if error occured and interface exists already */
65 if (ret == -ENFILE && if_nametoindex(ifname)) {
66 @@ -2750,7 +2752,7 @@ static int nl80211_create_iface(struct w
67 nl80211_remove_iface(drv, if_nametoindex(ifname));
69 /* Try to create the interface again */
70 - ret = nl80211_create_iface_once(drv, ifname, iftype, addr);
71 + ret = nl80211_create_iface_once(drv, ifname, iftype, addr, wds);
75 @@ -2975,7 +2977,7 @@ static struct sock_filter msock_filter_i
79 - * drop non-data frames, WDS frames
80 + * drop non-data frames
82 /* load the lower byte of the frame control field */
83 BPF_STMT(BPF_LD | BPF_B | BPF_IND, 0),
84 @@ -2983,13 +2985,13 @@ static struct sock_filter msock_filter_i
85 BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x0c),
86 /* drop non-data frames */
87 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 8, 0, FAIL),
89 /* load the upper byte of the frame control field */
90 - BPF_STMT(BPF_LD | BPF_B | BPF_IND, 0),
91 + BPF_STMT(BPF_LD | BPF_B | BPF_IND, 1),
92 /* mask off toDS/fromDS */
93 BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x03),
94 - /* drop WDS frames */
95 - BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 3, FAIL, 0),
97 + /* accept WDS frames */
98 + BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 3, PASS, 0),
101 * add header length to index
102 @@ -3095,7 +3097,7 @@ nl80211_create_monitor_interface(struct
103 buf[IFNAMSIZ - 1] = '\0';
106 - nl80211_create_iface(drv, buf, NL80211_IFTYPE_MONITOR, NULL);
107 + nl80211_create_iface(drv, buf, NL80211_IFTYPE_MONITOR, NULL, 0);
109 if (drv->monitor_ifidx < 0)
111 @@ -4064,7 +4066,7 @@ static int i802_bss_add(void *priv, cons
115 - ifidx = nl80211_create_iface(priv, ifname, NL80211_IFTYPE_AP, bssid);
116 + ifidx = nl80211_create_iface(priv, ifname, NL80211_IFTYPE_AP, bssid, 0);
120 @@ -4162,7 +4164,7 @@ static int i802_if_add(const char *iface
121 enum hostapd_driver_if_type type, char *ifname,
124 - if (nl80211_create_iface(priv, ifname, i802_if_type(type), addr) < 0)
125 + if (nl80211_create_iface(priv, ifname, i802_if_type(type), addr, 0) < 0)
129 @@ -4208,6 +4210,22 @@ static int i802_set_sta_vlan(void *priv,
133 +static int i802_set_wds_sta(void *priv, const u8 *addr, int aid, int val)
135 + struct wpa_driver_nl80211_data *drv = priv;
138 + sprintf(name, "%s.sta%d", drv->ifname, aid);
140 + if (nl80211_create_iface(priv, name, NL80211_IFTYPE_AP_VLAN, NULL, 1) < 0)
142 + hostapd_set_iface_flags(drv, name, 1);
143 + return i802_set_sta_vlan(priv, addr, name, 0);
145 + i802_set_sta_vlan(priv, addr, drv->ifname, 0);
146 + return i802_if_remove(priv, HOSTAPD_IF_VLAN, name, NULL);
150 static void handle_eapol(int sock, void *eloop_ctx, void *sock_ctx)
152 @@ -4424,5 +4442,6 @@ const struct wpa_driver_ops wpa_driver_n
153 .if_update = i802_if_update,
154 .if_remove = i802_if_remove,
155 .set_sta_vlan = i802_set_sta_vlan,
156 + .set_wds_sta = i802_set_wds_sta,
159 --- a/hostapd/driver_i.h
160 +++ b/hostapd/driver_i.h
161 @@ -446,6 +446,14 @@ hostapd_set_sta_vlan(const char *ifname,
165 +hostapd_set_wds_sta(struct hostapd_data *hapd, const u8 *addr, int aid, int val)
167 + if (hapd->driver == NULL || hapd->driver->set_wds_sta == NULL)
169 + return hapd->driver->set_wds_sta(hapd->drv_priv, addr, aid, val);
173 hostapd_driver_commit(struct hostapd_data *hapd)
175 if (hapd->driver == NULL || hapd->driver->commit == NULL)
176 --- a/hostapd/drv_callbacks.c
177 +++ b/hostapd/drv_callbacks.c
178 @@ -167,6 +167,7 @@ static const u8 * get_hdr_bssid(const st
181 switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) {
182 + case WLAN_FC_FROMDS|WLAN_FC_TODS:
186 @@ -213,6 +214,7 @@ void hostapd_rx_from_unknown_sta(struct
188 struct sta_info *sta;
190 + u16 fc = le_to_host16(hdr->frame_control);
192 hapd = get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len));
193 if (hapd == NULL || hapd == HAPD_BROADCAST)
194 @@ -231,6 +233,14 @@ void hostapd_rx_from_unknown_sta(struct
197 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
199 + if (!sta->wds_sta) {
200 + if ((fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) ==
201 + (WLAN_FC_TODS | WLAN_FC_FROMDS)) {
203 + hostapd_set_wds_sta(hapd, addr, sta->aid, 1);
209 --- a/hostapd/sta_info.c
210 +++ b/hostapd/sta_info.c
211 @@ -120,6 +120,7 @@ void ap_free_sta(struct hostapd_data *ha
213 accounting_sta_stop(hapd, sta);
215 + hostapd_set_wds_sta(hapd, sta->addr, sta->aid, 0);
216 if (!ap_sta_in_other_bss(hapd, sta, WLAN_STA_ASSOC) &&
217 !(sta->flags & WLAN_STA_PREAUTH))
218 hostapd_sta_remove(hapd, sta->addr);
219 --- a/hostapd/sta_info.h
220 +++ b/hostapd/sta_info.h
221 @@ -78,6 +78,7 @@ struct sta_info {
222 struct hostapd_ssid *ssid_probe; /* SSID selection based on ProbeReq */
227 #ifdef CONFIG_IEEE80211N
228 struct ht_cap_ie ht_capabilities; /* IEEE 802.11n capabilities */
229 --- a/src/common/nl80211_copy.h
230 +++ b/src/common/nl80211_copy.h
231 @@ -584,6 +584,8 @@ enum nl80211_commands {
232 * changed then the list changed and the dump should be repeated
233 * completely from scratch.
235 + * @NL80211_ATTR_4ADDR: Use 4-address frames on a virtual interface
237 * @NL80211_ATTR_MAX: highest attribute number currently defined
238 * @__NL80211_ATTR_AFTER_LAST: internal use
240 @@ -714,6 +716,8 @@ enum nl80211_attrs {
244 + NL80211_ATTR_4ADDR,
246 /* add attributes here, update the policy in nl80211.c */
248 __NL80211_ATTR_AFTER_LAST,