aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/nl80211.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r--net/wireless/nl80211.c40
1 files changed, 38 insertions, 2 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 37264d56bace..149539ade15e 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -561,7 +561,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
561 CMD(deauth, DEAUTHENTICATE); 561 CMD(deauth, DEAUTHENTICATE);
562 CMD(disassoc, DISASSOCIATE); 562 CMD(disassoc, DISASSOCIATE);
563 CMD(join_ibss, JOIN_IBSS); 563 CMD(join_ibss, JOIN_IBSS);
564 if (dev->wiphy.netnsok) { 564 if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) {
565 i++; 565 i++;
566 NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS); 566 NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS);
567 } 567 }
@@ -968,6 +968,32 @@ 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 struct net_device *netdev, u8 use_4addr,
973 enum nl80211_iftype iftype)
974{
975 if (!use_4addr) {
976 if (netdev && netdev->br_port)
977 return -EBUSY;
978 return 0;
979 }
980
981 switch (iftype) {
982 case NL80211_IFTYPE_AP_VLAN:
983 if (rdev->wiphy.flags & WIPHY_FLAG_4ADDR_AP)
984 return 0;
985 break;
986 case NL80211_IFTYPE_STATION:
987 if (rdev->wiphy.flags & WIPHY_FLAG_4ADDR_STATION)
988 return 0;
989 break;
990 default:
991 break;
992 }
993
994 return -EOPNOTSUPP;
995}
996
971static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) 997static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
972{ 998{
973 struct cfg80211_registered_device *rdev; 999 struct cfg80211_registered_device *rdev;
@@ -1011,6 +1037,9 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
1011 if (info->attrs[NL80211_ATTR_4ADDR]) { 1037 if (info->attrs[NL80211_ATTR_4ADDR]) {
1012 params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]); 1038 params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
1013 change = true; 1039 change = true;
1040 err = nl80211_valid_4addr(rdev, dev, params.use_4addr, ntype);
1041 if (err)
1042 goto unlock;
1014 } else { 1043 } else {
1015 params.use_4addr = -1; 1044 params.use_4addr = -1;
1016 } 1045 }
@@ -1034,6 +1063,9 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
1034 else 1063 else
1035 err = 0; 1064 err = 0;
1036 1065
1066 if (!err && params.use_4addr != -1)
1067 dev->ieee80211_ptr->use_4addr = params.use_4addr;
1068
1037 unlock: 1069 unlock:
1038 dev_put(dev); 1070 dev_put(dev);
1039 cfg80211_unlock_rdev(rdev); 1071 cfg80211_unlock_rdev(rdev);
@@ -1081,8 +1113,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]); 1113 params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
1082 } 1114 }
1083 1115
1084 if (info->attrs[NL80211_ATTR_4ADDR]) 1116 if (info->attrs[NL80211_ATTR_4ADDR]) {
1085 params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]); 1117 params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
1118 err = nl80211_valid_4addr(rdev, NULL, params.use_4addr, type);
1119 if (err)
1120 goto unlock;
1121 }
1086 1122
1087 err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ? 1123 err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ?
1088 info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL, 1124 info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL,