aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-11-19 05:55:19 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-11-19 11:08:53 -0500
commit9bc383de37090ba7ca3ff32a12c9d809dc5867f0 (patch)
tree2b502b918f585427b45357e5a9a781ea9f06c263 /net/wireless
parent5be83de54c16944dea9c16c6a5a53c1fa75ed304 (diff)
cfg80211: introduce capability for 4addr mode
It's very likely that not many devices will support four-address mode in station or AP mode so introduce capability bits for both modes, set them in mac80211 and check them when userspace tries to use the mode. Also, keep track of 4addr in cfg80211 (wireless_dev) and not in mac80211 any more. mac80211 can also be improved for the VLAN case by not looking at the 4addr flag but maintaining the station pointer for it correctly. However, keep track of use_4addr for station mode in mac80211 to avoid all the derefs. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/nl80211.c34
-rw-r--r--net/wireless/util.c5
2 files changed, 38 insertions, 1 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 6634188f9453..b7b0f67b0c61 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -968,6 +968,28 @@ static int parse_monitor_flags(struct nlattr *nla, u32 *mntrflags)
968 return 0; 968 return 0;
969} 969}
970 970
971static int nl80211_valid_4addr(struct cfg80211_registered_device *rdev,
972 u8 use_4addr, enum nl80211_iftype iftype)
973{
974 if (!use_4addr)
975 return 0;
976
977 switch (iftype) {
978 case NL80211_IFTYPE_AP_VLAN:
979 if (rdev->wiphy.flags & WIPHY_FLAG_4ADDR_AP)
980 return 0;
981 break;
982 case NL80211_IFTYPE_STATION:
983 if (rdev->wiphy.flags & WIPHY_FLAG_4ADDR_STATION)
984 return 0;
985 break;
986 default:
987 break;
988 }
989
990 return -EOPNOTSUPP;
991}
992
971static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) 993static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
972{ 994{
973 struct cfg80211_registered_device *rdev; 995 struct cfg80211_registered_device *rdev;
@@ -1011,6 +1033,9 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
1011 if (info->attrs[NL80211_ATTR_4ADDR]) { 1033 if (info->attrs[NL80211_ATTR_4ADDR]) {
1012 params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]); 1034 params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
1013 change = true; 1035 change = true;
1036 err = nl80211_valid_4addr(rdev, params.use_4addr, ntype);
1037 if (err)
1038 goto unlock;
1014 } else { 1039 } else {
1015 params.use_4addr = -1; 1040 params.use_4addr = -1;
1016 } 1041 }
@@ -1034,6 +1059,9 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
1034 else 1059 else
1035 err = 0; 1060 err = 0;
1036 1061
1062 if (!err && params.use_4addr != -1)
1063 dev->ieee80211_ptr->use_4addr = params.use_4addr;
1064
1037 unlock: 1065 unlock:
1038 dev_put(dev); 1066 dev_put(dev);
1039 cfg80211_unlock_rdev(rdev); 1067 cfg80211_unlock_rdev(rdev);
@@ -1081,8 +1109,12 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
1081 params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]); 1109 params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
1082 } 1110 }
1083 1111
1084 if (info->attrs[NL80211_ATTR_4ADDR]) 1112 if (info->attrs[NL80211_ATTR_4ADDR]) {
1085 params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]); 1113 params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
1114 err = nl80211_valid_4addr(rdev, params.use_4addr, type);
1115 if (err)
1116 goto unlock;
1117 }
1086 1118
1087 err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ? 1119 err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ?
1088 info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL, 1120 info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL,
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 5aa39f7cf9b9..17a7a4cfc617 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -659,6 +659,8 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
659 return -EOPNOTSUPP; 659 return -EOPNOTSUPP;
660 660
661 if (ntype != otype) { 661 if (ntype != otype) {
662 dev->ieee80211_ptr->use_4addr = false;
663
662 switch (otype) { 664 switch (otype) {
663 case NL80211_IFTYPE_ADHOC: 665 case NL80211_IFTYPE_ADHOC:
664 cfg80211_leave_ibss(rdev, dev, false); 666 cfg80211_leave_ibss(rdev, dev, false);
@@ -682,5 +684,8 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
682 684
683 WARN_ON(!err && dev->ieee80211_ptr->iftype != ntype); 685 WARN_ON(!err && dev->ieee80211_ptr->iftype != ntype);
684 686
687 if (!err && params && params->use_4addr != -1)
688 dev->ieee80211_ptr->use_4addr = params->use_4addr;
689
685 return err; 690 return err;
686} 691}