mirror of
git://projects.qi-hardware.com/openwrt-xburst.git
synced 2024-11-19 05:51:32 +02:00
mac80211: implement wds sta support (wds ap support work in progress, needs hostapd changes)
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@18356 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
parent
a4df146bd6
commit
3b3a36db38
155
package/iw/patches/000-upstream.patch
Normal file
155
package/iw/patches/000-upstream.patch
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
--- a/Makefile
|
||||||
|
+++ b/Makefile
|
||||||
|
@@ -3,7 +3,7 @@
|
||||||
|
MAKEFLAGS += --no-print-directory
|
||||||
|
|
||||||
|
PREFIX ?= /usr
|
||||||
|
-BINDIR ?= $(PREFIX)/bin
|
||||||
|
+SBINDIR ?= $(PREFIX)/sbin
|
||||||
|
MANDIR ?= $(PREFIX)/share/man
|
||||||
|
PKG_CONFIG ?= pkg-config
|
||||||
|
|
||||||
|
@@ -85,8 +85,8 @@ check:
|
||||||
|
|
||||||
|
install: iw iw.8.gz
|
||||||
|
@$(NQ) ' INST iw'
|
||||||
|
- $(Q)$(MKDIR) $(DESTDIR)$(BINDIR)
|
||||||
|
- $(Q)$(INSTALL) -m 755 -t $(DESTDIR)$(BINDIR) iw
|
||||||
|
+ $(Q)$(MKDIR) $(DESTDIR)$(SBINDIR)
|
||||||
|
+ $(Q)$(INSTALL) -m 755 -t $(DESTDIR)$(SBINDIR) iw
|
||||||
|
@$(NQ) ' INST iw.8'
|
||||||
|
$(Q)$(MKDIR) $(DESTDIR)$(MANDIR)/man8/
|
||||||
|
$(Q)$(INSTALL) -m 644 -t $(DESTDIR)$(MANDIR)/man8/ iw.8.gz
|
||||||
|
--- a/iw.c
|
||||||
|
+++ b/iw.c
|
||||||
|
@@ -223,9 +223,12 @@ static int phy_lookup(char *name)
|
||||||
|
if (fd < 0)
|
||||||
|
return -1;
|
||||||
|
pos = read(fd, buf, sizeof(buf) - 1);
|
||||||
|
- if (pos < 0)
|
||||||
|
+ if (pos < 0) {
|
||||||
|
+ close(fd);
|
||||||
|
return -1;
|
||||||
|
+ }
|
||||||
|
buf[pos] = '\0';
|
||||||
|
+ close(fd);
|
||||||
|
return atoi(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
--- a/nl80211.h
|
||||||
|
+++ b/nl80211.h
|
||||||
|
@@ -262,6 +262,9 @@
|
||||||
|
* reasons, for this the %NL80211_ATTR_DISCONNECTED_BY_AP and
|
||||||
|
* %NL80211_ATTR_REASON_CODE attributes are used.
|
||||||
|
*
|
||||||
|
+ * @NL80211_CMD_SET_WIPHY_NETNS: Set a wiphy's netns. Note that all devices
|
||||||
|
+ * associated with this wiphy must be down and will follow.
|
||||||
|
+ *
|
||||||
|
* @NL80211_CMD_MAX: highest used command number
|
||||||
|
* @__NL80211_CMD_AFTER_LAST: internal use
|
||||||
|
*/
|
||||||
|
@@ -336,6 +339,8 @@ enum nl80211_commands {
|
||||||
|
NL80211_CMD_ROAM,
|
||||||
|
NL80211_CMD_DISCONNECT,
|
||||||
|
|
||||||
|
+ NL80211_CMD_SET_WIPHY_NETNS,
|
||||||
|
+
|
||||||
|
/* add new commands above here */
|
||||||
|
|
||||||
|
/* used to define NL80211_CMD_MAX below */
|
||||||
|
@@ -475,10 +480,6 @@ enum nl80211_commands {
|
||||||
|
* @NL80211_ATTR_SCAN_FREQUENCIES: nested attribute with frequencies (in MHz)
|
||||||
|
* @NL80211_ATTR_SCAN_SSIDS: nested attribute with SSIDs, leave out for passive
|
||||||
|
* scanning and include a zero-length SSID (wildcard) for wildcard scan
|
||||||
|
- * @NL80211_ATTR_SCAN_GENERATION: the scan generation increases whenever the
|
||||||
|
- * scan result list changes (BSS expired or added) so that applications
|
||||||
|
- * can verify that they got a single, consistent snapshot (when all dump
|
||||||
|
- * messages carried the same generation number)
|
||||||
|
* @NL80211_ATTR_BSS: scan result BSS
|
||||||
|
*
|
||||||
|
* @NL80211_ATTR_REG_INITIATOR: indicates who requested the regulatory domain
|
||||||
|
@@ -573,6 +574,16 @@ enum nl80211_commands {
|
||||||
|
* and join_ibss(), key information is in a nested attribute each
|
||||||
|
* with %NL80211_KEY_* sub-attributes
|
||||||
|
*
|
||||||
|
+ * @NL80211_ATTR_PID: Process ID of a network namespace.
|
||||||
|
+ *
|
||||||
|
+ * @NL80211_ATTR_GENERATION: Used to indicate consistent snapshots for
|
||||||
|
+ * dumps. This number increases whenever the object list being
|
||||||
|
+ * dumped changes, and as such userspace can verify that it has
|
||||||
|
+ * obtained a complete and consistent snapshot by verifying that
|
||||||
|
+ * all dump messages contain the same generation number. If it
|
||||||
|
+ * changed then the list changed and the dump should be repeated
|
||||||
|
+ * completely from scratch.
|
||||||
|
+ *
|
||||||
|
* @NL80211_ATTR_MAX: highest attribute number currently defined
|
||||||
|
* @__NL80211_ATTR_AFTER_LAST: internal use
|
||||||
|
*/
|
||||||
|
@@ -644,7 +655,7 @@ enum nl80211_attrs {
|
||||||
|
|
||||||
|
NL80211_ATTR_SCAN_FREQUENCIES,
|
||||||
|
NL80211_ATTR_SCAN_SSIDS,
|
||||||
|
- NL80211_ATTR_SCAN_GENERATION,
|
||||||
|
+ NL80211_ATTR_GENERATION, /* replaces old SCAN_GENERATION */
|
||||||
|
NL80211_ATTR_BSS,
|
||||||
|
|
||||||
|
NL80211_ATTR_REG_INITIATOR,
|
||||||
|
@@ -701,12 +712,17 @@ enum nl80211_attrs {
|
||||||
|
NL80211_ATTR_KEY,
|
||||||
|
NL80211_ATTR_KEYS,
|
||||||
|
|
||||||
|
+ NL80211_ATTR_PID,
|
||||||
|
+
|
||||||
|
/* add attributes here, update the policy in nl80211.c */
|
||||||
|
|
||||||
|
__NL80211_ATTR_AFTER_LAST,
|
||||||
|
NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1
|
||||||
|
};
|
||||||
|
|
||||||
|
+/* source-level API compatibility */
|
||||||
|
+#define NL80211_ATTR_SCAN_GENERATION NL80211_ATTR_GENERATION
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* Allow user space programs to use #ifdef on new attributes by defining them
|
||||||
|
* here
|
||||||
|
--- a/phy.c
|
||||||
|
+++ b/phy.c
|
||||||
|
@@ -140,3 +140,27 @@ static int handle_rts(struct nl80211_sta
|
||||||
|
COMMAND(set, rts, "<rts threshold|off>",
|
||||||
|
NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_rts,
|
||||||
|
"Set rts threshold.");
|
||||||
|
+
|
||||||
|
+static int handle_netns(struct nl80211_state *state,
|
||||||
|
+ struct nl_cb *cb,
|
||||||
|
+ struct nl_msg *msg,
|
||||||
|
+ int argc, char **argv)
|
||||||
|
+{
|
||||||
|
+ char *end;
|
||||||
|
+
|
||||||
|
+ if (argc != 1)
|
||||||
|
+ return 1;
|
||||||
|
+
|
||||||
|
+ NLA_PUT_U32(msg, NL80211_ATTR_PID,
|
||||||
|
+ strtoul(argv[0], &end, 10));
|
||||||
|
+
|
||||||
|
+ if (*end != '\0')
|
||||||
|
+ return 1;
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+ nla_put_failure:
|
||||||
|
+ return -ENOBUFS;
|
||||||
|
+}
|
||||||
|
+COMMAND(set, netns, "<pid>",
|
||||||
|
+ NL80211_CMD_SET_WIPHY_NETNS, 0, CIB_PHY, handle_netns,
|
||||||
|
+ "Put this wireless device into a different network namespace");
|
||||||
|
--- a/station.c
|
||||||
|
+++ b/station.c
|
||||||
|
@@ -127,7 +127,7 @@ static int print_sta_handler(struct nl_m
|
||||||
|
printf("\n\tmesh plid:\t%d",
|
||||||
|
nla_get_u16(sinfo[NL80211_STA_INFO_PLID]));
|
||||||
|
if (sinfo[NL80211_STA_INFO_PLINK_STATE]) {
|
||||||
|
- switch (nla_get_u16(sinfo[NL80211_STA_INFO_PLINK_STATE])) {
|
||||||
|
+ switch (nla_get_u8(sinfo[NL80211_STA_INFO_PLINK_STATE])) {
|
||||||
|
case LISTEN:
|
||||||
|
strcpy(state_name, "LISTEN");
|
||||||
|
break;
|
76
package/iw/patches/100-4addr.patch
Normal file
76
package/iw/patches/100-4addr.patch
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
--- a/interface.c
|
||||||
|
+++ b/interface.c
|
||||||
|
@@ -137,6 +137,20 @@ static int get_if_type(int *argc, char *
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int parse_wds_flag(const char *value, struct nl_msg *msg)
|
||||||
|
+{
|
||||||
|
+ if (strcmp(value, "on") == 0)
|
||||||
|
+ NLA_PUT_U8(msg, NL80211_ATTR_4ADDR, 1);
|
||||||
|
+ else if (strcmp(value, "off") == 0)
|
||||||
|
+ NLA_PUT_U8(msg, NL80211_ATTR_4ADDR, 0);
|
||||||
|
+ else
|
||||||
|
+ return 1;
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+nla_put_failure:
|
||||||
|
+ return 1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int handle_interface_add(struct nl80211_state *state,
|
||||||
|
struct nl_cb *cb,
|
||||||
|
struct nl_msg *msg,
|
||||||
|
@@ -168,6 +182,15 @@ static int handle_interface_add(struct n
|
||||||
|
mesh_id = argv[0];
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
+ } else if (strcmp(argv[0], "wds") == 0) {
|
||||||
|
+ argc--;
|
||||||
|
+ argv++;
|
||||||
|
+ if (parse_wds_flag(argv[0], msg)) {
|
||||||
|
+ fprintf(stderr, "wds error\n");
|
||||||
|
+ return 2;
|
||||||
|
+ }
|
||||||
|
+ argc--;
|
||||||
|
+ argv++;
|
||||||
|
} else if (strcmp(argv[0], "flags") == 0) {
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
@@ -192,14 +215,14 @@ static int handle_interface_add(struct n
|
||||||
|
nla_put_failure:
|
||||||
|
return -ENOBUFS;
|
||||||
|
}
|
||||||
|
-COMMAND(interface, add, "<name> type <type> [mesh_id <meshid>] [flags <flag>*]",
|
||||||
|
+COMMAND(interface, add, "<name> type <type> [mesh_id <meshid>] [wds on|off] [flags <flag>*]",
|
||||||
|
NL80211_CMD_NEW_INTERFACE, 0, CIB_PHY, handle_interface_add,
|
||||||
|
"Add a new virtual interface with the given configuration.\n"
|
||||||
|
IFACE_TYPES "\n\n"
|
||||||
|
"The flags are only used for monitor interfaces, valid flags are:\n"
|
||||||
|
VALID_FLAGS "\n\n"
|
||||||
|
"The mesh_id is used only for mesh mode.");
|
||||||
|
-COMMAND(interface, add, "<name> type <type> [mesh_id <meshid>] [flags <flag>*]",
|
||||||
|
+COMMAND(interface, add, "<name> type <type> [mesh_id <meshid>] [wds on|off] [flags <flag>*]",
|
||||||
|
NL80211_CMD_NEW_INTERFACE, 0, CIB_NETDEV, handle_interface_add, NULL);
|
||||||
|
|
||||||
|
static int handle_interface_del(struct nl80211_state *state,
|
||||||
|
--- a/nl80211.h
|
||||||
|
+++ b/nl80211.h
|
||||||
|
@@ -584,6 +584,8 @@ enum nl80211_commands {
|
||||||
|
* changed then the list changed and the dump should be repeated
|
||||||
|
* completely from scratch.
|
||||||
|
*
|
||||||
|
+ * @NL80211_ATTR_4ADDR: Use 4-address frames on a virtual interface
|
||||||
|
+ *
|
||||||
|
* @NL80211_ATTR_MAX: highest attribute number currently defined
|
||||||
|
* @__NL80211_ATTR_AFTER_LAST: internal use
|
||||||
|
*/
|
||||||
|
@@ -714,6 +716,8 @@ enum nl80211_attrs {
|
||||||
|
|
||||||
|
NL80211_ATTR_PID,
|
||||||
|
|
||||||
|
+ NL80211_ATTR_4ADDR,
|
||||||
|
+
|
||||||
|
/* add attributes here, update the policy in nl80211.c */
|
||||||
|
|
||||||
|
__NL80211_ATTR_AFTER_LAST,
|
69
package/iw/patches/110-sta_vlan.patch
Normal file
69
package/iw/patches/110-sta_vlan.patch
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
--- a/station.c
|
||||||
|
+++ b/station.c
|
||||||
|
@@ -196,7 +196,7 @@ COMMAND(station, del, "<MAC address>",
|
||||||
|
NL80211_CMD_DEL_STATION, 0, CIB_NETDEV, handle_station_get,
|
||||||
|
"Remove the given station entry (use with caution!)");
|
||||||
|
|
||||||
|
-static int handle_station_set(struct nl80211_state *state,
|
||||||
|
+static int handle_station_set_plink(struct nl80211_state *state,
|
||||||
|
struct nl_cb *cb,
|
||||||
|
struct nl_msg *msg,
|
||||||
|
int argc, char **argv)
|
||||||
|
@@ -241,9 +241,56 @@ static int handle_station_set(struct nl8
|
||||||
|
return -ENOBUFS;
|
||||||
|
}
|
||||||
|
COMMAND(station, set, "<MAC address> plink_action <open|block>",
|
||||||
|
- NL80211_CMD_SET_STATION, 0, CIB_NETDEV, handle_station_set,
|
||||||
|
+ NL80211_CMD_SET_STATION, 0, CIB_NETDEV, handle_station_set_plink,
|
||||||
|
"Set mesh peer link action for this station (peer).");
|
||||||
|
|
||||||
|
+static int handle_station_set_vlan(struct nl80211_state *state,
|
||||||
|
+ struct nl_cb *cb,
|
||||||
|
+ struct nl_msg *msg,
|
||||||
|
+ int argc, char **argv)
|
||||||
|
+{
|
||||||
|
+ unsigned char mac_addr[ETH_ALEN];
|
||||||
|
+ unsigned long sta_vlan = 0;
|
||||||
|
+ char *err = NULL;
|
||||||
|
+
|
||||||
|
+ if (argc < 3)
|
||||||
|
+ return 1;
|
||||||
|
+
|
||||||
|
+ if (mac_addr_a2n(mac_addr, argv[0])) {
|
||||||
|
+ fprintf(stderr, "invalid mac address\n");
|
||||||
|
+ return 2;
|
||||||
|
+ }
|
||||||
|
+ argc--;
|
||||||
|
+ argv++;
|
||||||
|
+
|
||||||
|
+ if (strcmp("vlan", argv[0]) != 0)
|
||||||
|
+ return 1;
|
||||||
|
+ argc--;
|
||||||
|
+ argv++;
|
||||||
|
+
|
||||||
|
+ sta_vlan = strtoul(argv[0], &err, 0);
|
||||||
|
+ if (err && *err) {
|
||||||
|
+ fprintf(stderr, "invalid vlan id\n");
|
||||||
|
+ return 2;
|
||||||
|
+ }
|
||||||
|
+ argc--;
|
||||||
|
+ argv++;
|
||||||
|
+
|
||||||
|
+ if (argc)
|
||||||
|
+ return 1;
|
||||||
|
+
|
||||||
|
+ NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
|
||||||
|
+ NLA_PUT_U32(msg, NL80211_ATTR_STA_VLAN, sta_vlan);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+ nla_put_failure:
|
||||||
|
+ return -ENOBUFS;
|
||||||
|
+}
|
||||||
|
+COMMAND(station, set, "<MAC address> vlan <ifindex>",
|
||||||
|
+ NL80211_CMD_SET_STATION, 0, CIB_NETDEV, handle_station_set_vlan,
|
||||||
|
+ "Set an AP VLAN for this station.");
|
||||||
|
+
|
||||||
|
+
|
||||||
|
static int handle_station_dump(struct nl80211_state *state,
|
||||||
|
struct nl_cb *cb,
|
||||||
|
struct nl_msg *msg,
|
@ -104,6 +104,7 @@ enable_mac80211() {
|
|||||||
config_get enc "$vif" encryption
|
config_get enc "$vif" encryption
|
||||||
config_get mode "$vif" mode
|
config_get mode "$vif" mode
|
||||||
config_get ssid "$vif" ssid
|
config_get ssid "$vif" ssid
|
||||||
|
config_get_bool wds "$vif" wds 0
|
||||||
|
|
||||||
# It is far easier to delete and create the desired interface
|
# It is far easier to delete and create the desired interface
|
||||||
case "$mode" in
|
case "$mode" in
|
||||||
@ -123,7 +124,9 @@ enable_mac80211() {
|
|||||||
iw phy "$phy" interface add "$ifname" type monitor
|
iw phy "$phy" interface add "$ifname" type monitor
|
||||||
;;
|
;;
|
||||||
sta)
|
sta)
|
||||||
iw phy "$phy" interface add "$ifname" type managed
|
local wdsflag
|
||||||
|
[ "$wds" -gt 0 ] && wdsflag="wds on"
|
||||||
|
iw phy "$phy" interface add "$ifname" type managed $wdsflag
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
69
package/mac80211/patches/500-nl80211_4addr.patch
Normal file
69
package/mac80211/patches/500-nl80211_4addr.patch
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
--- a/include/linux/nl80211.h
|
||||||
|
+++ b/include/linux/nl80211.h
|
||||||
|
@@ -584,6 +584,8 @@ enum nl80211_commands {
|
||||||
|
* changed then the list changed and the dump should be repeated
|
||||||
|
* completely from scratch.
|
||||||
|
*
|
||||||
|
+ * @NL80211_ATTR_4ADDR: Use 4-address frames on a virtual interface
|
||||||
|
+ *
|
||||||
|
* @NL80211_ATTR_MAX: highest attribute number currently defined
|
||||||
|
* @__NL80211_ATTR_AFTER_LAST: internal use
|
||||||
|
*/
|
||||||
|
@@ -714,6 +716,8 @@ enum nl80211_attrs {
|
||||||
|
|
||||||
|
NL80211_ATTR_PID,
|
||||||
|
|
||||||
|
+ NL80211_ATTR_4ADDR,
|
||||||
|
+
|
||||||
|
/* add attributes here, update the policy in nl80211.c */
|
||||||
|
|
||||||
|
__NL80211_ATTR_AFTER_LAST,
|
||||||
|
--- a/include/net/cfg80211.h
|
||||||
|
+++ b/include/net/cfg80211.h
|
||||||
|
@@ -207,10 +207,12 @@ struct ieee80211_supported_band {
|
||||||
|
* struct vif_params - describes virtual interface parameters
|
||||||
|
* @mesh_id: mesh ID to use
|
||||||
|
* @mesh_id_len: length of the mesh ID
|
||||||
|
+ * @use_4addr: use 4-address frames
|
||||||
|
*/
|
||||||
|
struct vif_params {
|
||||||
|
u8 *mesh_id;
|
||||||
|
int mesh_id_len;
|
||||||
|
+ int use_4addr;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
--- a/net/wireless/nl80211.c
|
||||||
|
+++ b/net/wireless/nl80211.c
|
||||||
|
@@ -140,6 +140,7 @@ static struct nla_policy nl80211_policy[
|
||||||
|
[NL80211_ATTR_CIPHER_SUITE_GROUP] = { .type = NLA_U32 },
|
||||||
|
[NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 },
|
||||||
|
[NL80211_ATTR_PID] = { .type = NLA_U32 },
|
||||||
|
+ [NL80211_ATTR_4ADDR] = { .type = NLA_U8 },
|
||||||
|
};
|
||||||
|
|
||||||
|
/* policy for the attributes */
|
||||||
|
@@ -989,6 +990,13 @@ static int nl80211_set_interface(struct
|
||||||
|
change = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (info->attrs[NL80211_ATTR_4ADDR]) {
|
||||||
|
+ params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
|
||||||
|
+ change = true;
|
||||||
|
+ } else {
|
||||||
|
+ params.use_4addr = -1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) {
|
||||||
|
if (ntype != NL80211_IFTYPE_MONITOR) {
|
||||||
|
err = -EINVAL;
|
||||||
|
@@ -1055,6 +1063,9 @@ static int nl80211_new_interface(struct
|
||||||
|
params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (info->attrs[NL80211_ATTR_4ADDR])
|
||||||
|
+ params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
|
||||||
|
+
|
||||||
|
err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ?
|
||||||
|
info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL,
|
||||||
|
&flags);
|
260
package/mac80211/patches/510-mac80211_4addr_vlan.patch
Normal file
260
package/mac80211/patches/510-mac80211_4addr_vlan.patch
Normal file
@ -0,0 +1,260 @@
|
|||||||
|
--- a/net/mac80211/ieee80211_i.h
|
||||||
|
+++ b/net/mac80211/ieee80211_i.h
|
||||||
|
@@ -208,6 +208,9 @@ struct ieee80211_if_wds {
|
||||||
|
|
||||||
|
struct ieee80211_if_vlan {
|
||||||
|
struct list_head list;
|
||||||
|
+
|
||||||
|
+ /* used for all tx if the VLAN is configured to 4-addr mode */
|
||||||
|
+ struct sta_info *sta;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mesh_stats {
|
||||||
|
@@ -457,6 +460,8 @@ struct ieee80211_sub_if_data {
|
||||||
|
int force_unicast_rateidx; /* forced TX rateidx for unicast frames */
|
||||||
|
int max_ratectrl_rateidx; /* max TX rateidx for rate control */
|
||||||
|
|
||||||
|
+ bool use_4addr; /* use 4-address frames */
|
||||||
|
+
|
||||||
|
union {
|
||||||
|
struct ieee80211_if_ap ap;
|
||||||
|
struct ieee80211_if_wds wds;
|
||||||
|
--- a/net/mac80211/cfg.c
|
||||||
|
+++ b/net/mac80211/cfg.c
|
||||||
|
@@ -36,6 +36,24 @@ static bool nl80211_type_check(enum nl80
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+static bool nl80211_params_check(enum nl80211_iftype type,
|
||||||
|
+ struct vif_params *params)
|
||||||
|
+{
|
||||||
|
+ if (!nl80211_type_check(type))
|
||||||
|
+ return false;
|
||||||
|
+
|
||||||
|
+ if (params->use_4addr > 0) {
|
||||||
|
+ switch(type) {
|
||||||
|
+ case NL80211_IFTYPE_AP_VLAN:
|
||||||
|
+ case NL80211_IFTYPE_STATION:
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ return true;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int ieee80211_add_iface(struct wiphy *wiphy, char *name,
|
||||||
|
enum nl80211_iftype type, u32 *flags,
|
||||||
|
struct vif_params *params)
|
||||||
|
@@ -45,7 +63,7 @@ static int ieee80211_add_iface(struct wi
|
||||||
|
struct ieee80211_sub_if_data *sdata;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
- if (!nl80211_type_check(type))
|
||||||
|
+ if (!nl80211_params_check(type, params))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
err = ieee80211_if_add(local, name, &dev, type, params);
|
||||||
|
@@ -75,7 +93,7 @@ static int ieee80211_change_iface(struct
|
||||||
|
if (netif_running(dev))
|
||||||
|
return -EBUSY;
|
||||||
|
|
||||||
|
- if (!nl80211_type_check(type))
|
||||||
|
+ if (!nl80211_params_check(type, params))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||||
|
@@ -89,6 +107,9 @@ static int ieee80211_change_iface(struct
|
||||||
|
params->mesh_id_len,
|
||||||
|
params->mesh_id);
|
||||||
|
|
||||||
|
+ if (params->use_4addr >= 0)
|
||||||
|
+ sdata->use_4addr = !!params->use_4addr;
|
||||||
|
+
|
||||||
|
if (sdata->vif.type != NL80211_IFTYPE_MONITOR || !flags)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
@@ -806,6 +827,13 @@ static int ieee80211_change_station(stru
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (vlansdata->use_4addr) {
|
||||||
|
+ if (vlansdata->u.vlan.sta)
|
||||||
|
+ return -EBUSY;
|
||||||
|
+
|
||||||
|
+ rcu_assign_pointer(vlansdata->u.vlan.sta, sta);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
sta->sdata = vlansdata;
|
||||||
|
ieee80211_send_layer2_update(sta);
|
||||||
|
}
|
||||||
|
--- a/net/mac80211/sta_info.c
|
||||||
|
+++ b/net/mac80211/sta_info.c
|
||||||
|
@@ -489,6 +489,9 @@ static void __sta_info_unlink(struct sta
|
||||||
|
local->num_sta--;
|
||||||
|
local->sta_generation++;
|
||||||
|
|
||||||
|
+ if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
|
||||||
|
+ rcu_assign_pointer(sdata->u.vlan.sta, NULL);
|
||||||
|
+
|
||||||
|
if (local->ops->sta_notify) {
|
||||||
|
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
|
||||||
|
sdata = container_of(sdata->bss,
|
||||||
|
--- a/net/mac80211/tx.c
|
||||||
|
+++ b/net/mac80211/tx.c
|
||||||
|
@@ -1046,7 +1046,10 @@ ieee80211_tx_prepare(struct ieee80211_su
|
||||||
|
|
||||||
|
hdr = (struct ieee80211_hdr *) skb->data;
|
||||||
|
|
||||||
|
- tx->sta = sta_info_get(local, hdr->addr1);
|
||||||
|
+ if ((sdata->vif.type == NL80211_IFTYPE_AP_VLAN) && sdata->use_4addr)
|
||||||
|
+ tx->sta = rcu_dereference(sdata->u.vlan.sta);
|
||||||
|
+ if (!tx->sta)
|
||||||
|
+ tx->sta = sta_info_get(local, hdr->addr1);
|
||||||
|
|
||||||
|
if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) &&
|
||||||
|
(local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION)) {
|
||||||
|
@@ -1608,7 +1611,7 @@ netdev_tx_t ieee80211_subif_start_xmit(s
|
||||||
|
const u8 *encaps_data;
|
||||||
|
int encaps_len, skip_header_bytes;
|
||||||
|
int nh_pos, h_pos;
|
||||||
|
- struct sta_info *sta;
|
||||||
|
+ struct sta_info *sta = NULL;
|
||||||
|
u32 sta_flags = 0;
|
||||||
|
|
||||||
|
if (unlikely(skb->len < ETH_HLEN)) {
|
||||||
|
@@ -1625,8 +1628,25 @@ netdev_tx_t ieee80211_subif_start_xmit(s
|
||||||
|
fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA);
|
||||||
|
|
||||||
|
switch (sdata->vif.type) {
|
||||||
|
- case NL80211_IFTYPE_AP:
|
||||||
|
case NL80211_IFTYPE_AP_VLAN:
|
||||||
|
+ rcu_read_lock();
|
||||||
|
+ if (sdata->use_4addr)
|
||||||
|
+ sta = rcu_dereference(sdata->u.vlan.sta);
|
||||||
|
+ if (sta) {
|
||||||
|
+ fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
|
||||||
|
+ /* RA TA DA SA */
|
||||||
|
+ memcpy(hdr.addr1, sta->sta.addr, ETH_ALEN);
|
||||||
|
+ memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
|
||||||
|
+ memcpy(hdr.addr3, skb->data, ETH_ALEN);
|
||||||
|
+ memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
|
||||||
|
+ hdrlen = 30;
|
||||||
|
+ sta_flags = get_sta_flags(sta);
|
||||||
|
+ }
|
||||||
|
+ rcu_read_unlock();
|
||||||
|
+ if (sta)
|
||||||
|
+ break;
|
||||||
|
+ /* fall through */
|
||||||
|
+ case NL80211_IFTYPE_AP:
|
||||||
|
fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
|
||||||
|
/* DA BSSID SA */
|
||||||
|
memcpy(hdr.addr1, skb->data, ETH_ALEN);
|
||||||
|
@@ -1700,12 +1720,21 @@ netdev_tx_t ieee80211_subif_start_xmit(s
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
case NL80211_IFTYPE_STATION:
|
||||||
|
- fc |= cpu_to_le16(IEEE80211_FCTL_TODS);
|
||||||
|
- /* BSSID SA DA */
|
||||||
|
memcpy(hdr.addr1, sdata->u.mgd.bssid, ETH_ALEN);
|
||||||
|
- memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
|
||||||
|
- memcpy(hdr.addr3, skb->data, ETH_ALEN);
|
||||||
|
- hdrlen = 24;
|
||||||
|
+ if (sdata->use_4addr && ethertype != ETH_P_PAE) {
|
||||||
|
+ fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
|
||||||
|
+ /* RA TA DA SA */
|
||||||
|
+ memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
|
||||||
|
+ memcpy(hdr.addr3, skb->data, ETH_ALEN);
|
||||||
|
+ memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
|
||||||
|
+ hdrlen = 30;
|
||||||
|
+ } else {
|
||||||
|
+ fc |= cpu_to_le16(IEEE80211_FCTL_TODS);
|
||||||
|
+ /* BSSID SA DA */
|
||||||
|
+ memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
|
||||||
|
+ memcpy(hdr.addr3, skb->data, ETH_ALEN);
|
||||||
|
+ hdrlen = 24;
|
||||||
|
+ }
|
||||||
|
break;
|
||||||
|
case NL80211_IFTYPE_ADHOC:
|
||||||
|
/* DA SA BSSID */
|
||||||
|
--- a/net/mac80211/iface.c
|
||||||
|
+++ b/net/mac80211/iface.c
|
||||||
|
@@ -772,6 +772,7 @@ int ieee80211_if_change_type(struct ieee
|
||||||
|
ieee80211_mandatory_rates(sdata->local,
|
||||||
|
sdata->local->hw.conf.channel->band);
|
||||||
|
sdata->drop_unencrypted = 0;
|
||||||
|
+ sdata->use_4addr = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@@ -853,6 +854,9 @@ int ieee80211_if_add(struct ieee80211_lo
|
||||||
|
params->mesh_id_len,
|
||||||
|
params->mesh_id);
|
||||||
|
|
||||||
|
+ if (params && params->use_4addr >= 0)
|
||||||
|
+ sdata->use_4addr = !!params->use_4addr;
|
||||||
|
+
|
||||||
|
mutex_lock(&local->iflist_mtx);
|
||||||
|
list_add_tail_rcu(&sdata->list, &local->interfaces);
|
||||||
|
mutex_unlock(&local->iflist_mtx);
|
||||||
|
--- a/net/mac80211/rx.c
|
||||||
|
+++ b/net/mac80211/rx.c
|
||||||
|
@@ -1237,6 +1237,13 @@ __ieee80211_data_to_8023(struct ieee8021
|
||||||
|
{
|
||||||
|
struct net_device *dev = rx->dev;
|
||||||
|
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||||
|
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
|
||||||
|
+
|
||||||
|
+ if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN && !sdata->use_4addr &&
|
||||||
|
+ ieee80211_has_a4(hdr->frame_control))
|
||||||
|
+ return -1;
|
||||||
|
+ if (sdata->use_4addr && is_multicast_ether_addr(hdr->addr1))
|
||||||
|
+ return -1;
|
||||||
|
|
||||||
|
return ieee80211_data_to_8023(rx->skb, dev->dev_addr, sdata->vif.type);
|
||||||
|
}
|
||||||
|
@@ -1590,6 +1597,7 @@ ieee80211_rx_h_data(struct ieee80211_rx_
|
||||||
|
{
|
||||||
|
struct net_device *dev = rx->dev;
|
||||||
|
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
|
||||||
|
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||||
|
__le16 fc = hdr->frame_control;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
@@ -1599,6 +1607,14 @@ ieee80211_rx_h_data(struct ieee80211_rx_
|
||||||
|
if (unlikely(!ieee80211_is_data_present(hdr->frame_control)))
|
||||||
|
return RX_DROP_MONITOR;
|
||||||
|
|
||||||
|
+ /*
|
||||||
|
+ * Allow the cooked monitor interface of an AP to see 4-addr frames so
|
||||||
|
+ * that a 4-addr station can be detected and moved into a separate VLAN
|
||||||
|
+ */
|
||||||
|
+ if (ieee80211_has_a4(hdr->frame_control) &&
|
||||||
|
+ sdata->vif.type == NL80211_IFTYPE_AP)
|
||||||
|
+ return RX_DROP_MONITOR;
|
||||||
|
+
|
||||||
|
err = __ieee80211_data_to_8023(rx);
|
||||||
|
if (unlikely(err))
|
||||||
|
return RX_DROP_UNUSABLE;
|
||||||
|
@@ -2039,7 +2055,7 @@ static int prepare_for_handlers(struct i
|
||||||
|
|
||||||
|
switch (sdata->vif.type) {
|
||||||
|
case NL80211_IFTYPE_STATION:
|
||||||
|
- if (!bssid)
|
||||||
|
+ if (!bssid && !sdata->use_4addr)
|
||||||
|
return 0;
|
||||||
|
if (!multicast &&
|
||||||
|
compare_ether_addr(sdata->dev->dev_addr, hdr->addr1) != 0) {
|
||||||
|
--- a/net/wireless/util.c
|
||||||
|
+++ b/net/wireless/util.c
|
||||||
|
@@ -320,7 +320,9 @@ int ieee80211_data_to_8023(struct sk_buf
|
||||||
|
break;
|
||||||
|
case cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS):
|
||||||
|
if (unlikely(iftype != NL80211_IFTYPE_WDS &&
|
||||||
|
- iftype != NL80211_IFTYPE_MESH_POINT))
|
||||||
|
+ iftype != NL80211_IFTYPE_MESH_POINT &&
|
||||||
|
+ iftype != NL80211_IFTYPE_AP_VLAN &&
|
||||||
|
+ iftype != NL80211_IFTYPE_STATION))
|
||||||
|
return -1;
|
||||||
|
if (iftype == NL80211_IFTYPE_MESH_POINT) {
|
||||||
|
struct ieee80211s_hdr *meshdr =
|
Loading…
Reference in New Issue
Block a user