diff options
Diffstat (limited to 'net/wireless')
-rw-r--r-- | net/wireless/nl80211.c | 34 | ||||
-rw-r--r-- | net/wireless/util.c | 5 |
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 | ||
971 | static 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 | |||
971 | static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) | 993 | static 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 | } |