diff options
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r-- | net/wireless/nl80211.c | 34 |
1 files changed, 33 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, |