aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/cfg80211.h11
-rw-r--r--net/mac80211/cfg.c21
-rw-r--r--net/mac80211/ieee80211_i.h4
-rw-r--r--net/mac80211/iface.c12
-rw-r--r--net/mac80211/main.c4
-rw-r--r--net/mac80211/rx.c14
-rw-r--r--net/mac80211/tx.c7
-rw-r--r--net/wireless/nl80211.c34
-rw-r--r--net/wireless/util.c5
9 files changed, 82 insertions, 30 deletions
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index eca36abca8f5..d1e05aeb0c09 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1134,6 +1134,9 @@ struct cfg80211_ops {
1134 * by default -- this flag will be set depending on the kernel's default 1134 * by default -- this flag will be set depending on the kernel's default
1135 * on wiphy_new(), but can be changed by the driver if it has a good 1135 * on wiphy_new(), but can be changed by the driver if it has a good
1136 * reason to override the default 1136 * reason to override the default
1137 * @WIPHY_FLAG_4ADDR_AP: supports 4addr mode even on AP (with a single station
1138 * on a VLAN interface)
1139 * @WIPHY_FLAG_4ADDR_STATION: supports 4addr mode even as a station
1137 */ 1140 */
1138enum wiphy_flags { 1141enum wiphy_flags {
1139 WIPHY_FLAG_CUSTOM_REGULATORY = BIT(0), 1142 WIPHY_FLAG_CUSTOM_REGULATORY = BIT(0),
@@ -1141,6 +1144,8 @@ enum wiphy_flags {
1141 WIPHY_FLAG_DISABLE_BEACON_HINTS = BIT(2), 1144 WIPHY_FLAG_DISABLE_BEACON_HINTS = BIT(2),
1142 WIPHY_FLAG_NETNS_OK = BIT(3), 1145 WIPHY_FLAG_NETNS_OK = BIT(3),
1143 WIPHY_FLAG_PS_ON_BY_DEFAULT = BIT(4), 1146 WIPHY_FLAG_PS_ON_BY_DEFAULT = BIT(4),
1147 WIPHY_FLAG_4ADDR_AP = BIT(5),
1148 WIPHY_FLAG_4ADDR_STATION = BIT(6),
1144}; 1149};
1145 1150
1146/** 1151/**
@@ -1366,6 +1371,10 @@ struct cfg80211_cached_keys;
1366 * @ssid_len: (private) Used by the internal configuration code 1371 * @ssid_len: (private) Used by the internal configuration code
1367 * @wext: (private) Used by the internal wireless extensions compat code 1372 * @wext: (private) Used by the internal wireless extensions compat code
1368 * @wext_bssid: (private) Used by the internal wireless extensions compat code 1373 * @wext_bssid: (private) Used by the internal wireless extensions compat code
1374 * @use_4addr: indicates 4addr mode is used on this interface, must be
1375 * set by driver (if supported) on add_interface BEFORE registering the
1376 * netdev and may otherwise be used by driver read-only, will be update
1377 * by cfg80211 on change_interface
1369 */ 1378 */
1370struct wireless_dev { 1379struct wireless_dev {
1371 struct wiphy *wiphy; 1380 struct wiphy *wiphy;
@@ -1379,6 +1388,8 @@ struct wireless_dev {
1379 1388
1380 struct work_struct cleanup_work; 1389 struct work_struct cleanup_work;
1381 1390
1391 bool use_4addr;
1392
1382 /* currently used for IBSS and SME - might be rearranged later */ 1393 /* currently used for IBSS and SME - might be rearranged later */
1383 u8 ssid[IEEE80211_MAX_SSID_LEN]; 1394 u8 ssid[IEEE80211_MAX_SSID_LEN];
1384 u8 ssid_len; 1395 u8 ssid_len;
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 7d591816ed10..c484a882140e 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -42,15 +42,6 @@ static bool nl80211_params_check(enum nl80211_iftype type,
42 if (!nl80211_type_check(type)) 42 if (!nl80211_type_check(type))
43 return false; 43 return false;
44 44
45 if (params->use_4addr > 0) {
46 switch(type) {
47 case NL80211_IFTYPE_AP_VLAN:
48 case NL80211_IFTYPE_STATION:
49 break;
50 default:
51 return false;
52 }
53 }
54 return true; 45 return true;
55} 46}
56 47
@@ -107,12 +98,16 @@ static int ieee80211_change_iface(struct wiphy *wiphy,
107 params->mesh_id_len, 98 params->mesh_id_len,
108 params->mesh_id); 99 params->mesh_id);
109 100
110 if (params->use_4addr >= 0)
111 sdata->use_4addr = !!params->use_4addr;
112
113 if (sdata->vif.type != NL80211_IFTYPE_MONITOR || !flags) 101 if (sdata->vif.type != NL80211_IFTYPE_MONITOR || !flags)
114 return 0; 102 return 0;
115 103
104 if (type == NL80211_IFTYPE_AP_VLAN &&
105 params && params->use_4addr == 0)
106 rcu_assign_pointer(sdata->u.vlan.sta, NULL);
107 else if (type == NL80211_IFTYPE_STATION &&
108 params && params->use_4addr >= 0)
109 sdata->u.mgd.use_4addr = params->use_4addr;
110
116 sdata->u.mntr_flags = *flags; 111 sdata->u.mntr_flags = *flags;
117 return 0; 112 return 0;
118} 113}
@@ -827,7 +822,7 @@ static int ieee80211_change_station(struct wiphy *wiphy,
827 return -EINVAL; 822 return -EINVAL;
828 } 823 }
829 824
830 if (vlansdata->use_4addr) { 825 if (params->vlan->ieee80211_ptr->use_4addr) {
831 if (vlansdata->u.vlan.sta) 826 if (vlansdata->u.vlan.sta)
832 return -EBUSY; 827 return -EBUSY;
833 828
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 87d27f450a05..f13d76c9b575 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -312,6 +312,8 @@ struct ieee80211_if_managed {
312 } mfp; /* management frame protection */ 312 } mfp; /* management frame protection */
313 313
314 int wmm_last_param_set; 314 int wmm_last_param_set;
315
316 u8 use_4addr;
315}; 317};
316 318
317enum ieee80211_ibss_request { 319enum ieee80211_ibss_request {
@@ -459,8 +461,6 @@ struct ieee80211_sub_if_data {
459 int force_unicast_rateidx; /* forced TX rateidx for unicast frames */ 461 int force_unicast_rateidx; /* forced TX rateidx for unicast frames */
460 int max_ratectrl_rateidx; /* max TX rateidx for rate control */ 462 int max_ratectrl_rateidx; /* max TX rateidx for rate control */
461 463
462 bool use_4addr; /* use 4-address frames */
463
464 union { 464 union {
465 struct ieee80211_if_ap ap; 465 struct ieee80211_if_ap ap;
466 struct ieee80211_if_wds wds; 466 struct ieee80211_if_wds wds;
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 1f02b0610e82..1bf12a26b45e 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -752,7 +752,8 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata,
752 ieee80211_mandatory_rates(sdata->local, 752 ieee80211_mandatory_rates(sdata->local,
753 sdata->local->hw.conf.channel->band); 753 sdata->local->hw.conf.channel->band);
754 sdata->drop_unencrypted = 0; 754 sdata->drop_unencrypted = 0;
755 sdata->use_4addr = 0; 755 if (type == NL80211_IFTYPE_STATION)
756 sdata->u.mgd.use_4addr = false;
756 757
757 return 0; 758 return 0;
758} 759}
@@ -810,6 +811,12 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
810 /* setup type-dependent data */ 811 /* setup type-dependent data */
811 ieee80211_setup_sdata(sdata, type); 812 ieee80211_setup_sdata(sdata, type);
812 813
814 if (params) {
815 ndev->ieee80211_ptr->use_4addr = params->use_4addr;
816 if (type == NL80211_IFTYPE_STATION)
817 sdata->u.mgd.use_4addr = params->use_4addr;
818 }
819
813 ret = register_netdevice(ndev); 820 ret = register_netdevice(ndev);
814 if (ret) 821 if (ret)
815 goto fail; 822 goto fail;
@@ -820,9 +827,6 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
820 params->mesh_id_len, 827 params->mesh_id_len,
821 params->mesh_id); 828 params->mesh_id);
822 829
823 if (params && params->use_4addr >= 0)
824 sdata->use_4addr = !!params->use_4addr;
825
826 mutex_lock(&local->iflist_mtx); 830 mutex_lock(&local->iflist_mtx);
827 list_add_tail_rcu(&sdata->list, &local->interfaces); 831 list_add_tail_rcu(&sdata->list, &local->interfaces);
828 mutex_unlock(&local->iflist_mtx); 832 mutex_unlock(&local->iflist_mtx);
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 8084b622e97e..dd8ec8d5e8b2 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -328,7 +328,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
328 if (!wiphy) 328 if (!wiphy)
329 return NULL; 329 return NULL;
330 330
331 wiphy->flags |= WIPHY_FLAG_NETNS_OK; 331 wiphy->flags |= WIPHY_FLAG_NETNS_OK |
332 WIPHY_FLAG_4ADDR_AP |
333 WIPHY_FLAG_4ADDR_STATION;
332 wiphy->privid = mac80211_wiphy_privid; 334 wiphy->privid = mac80211_wiphy_privid;
333 335
334 /* Yes, putting cfg80211_bss into ieee80211_bss is a hack */ 336 /* Yes, putting cfg80211_bss into ieee80211_bss is a hack */
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 775365f856c9..96f13ad05d3c 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1192,10 +1192,13 @@ __ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
1192 struct net_device *dev = sdata->dev; 1192 struct net_device *dev = sdata->dev;
1193 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; 1193 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
1194 1194
1195 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN && !sdata->use_4addr && 1195 if (ieee80211_has_a4(hdr->frame_control) &&
1196 ieee80211_has_a4(hdr->frame_control)) 1196 sdata->vif.type == NL80211_IFTYPE_AP_VLAN && !sdata->u.vlan.sta)
1197 return -1; 1197 return -1;
1198 if (sdata->use_4addr && is_multicast_ether_addr(hdr->addr1)) 1198
1199 if (is_multicast_ether_addr(hdr->addr1) &&
1200 ((sdata->vif.type == NL80211_IFTYPE_AP_VLAN && sdata->u.vlan.sta) ||
1201 (sdata->vif.type == NL80211_IFTYPE_STATION && sdata->u.mgd.use_4addr)))
1199 return -1; 1202 return -1;
1200 1203
1201 return ieee80211_data_to_8023(rx->skb, dev->dev_addr, sdata->vif.type); 1204 return ieee80211_data_to_8023(rx->skb, dev->dev_addr, sdata->vif.type);
@@ -1245,7 +1248,8 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
1245 if ((sdata->vif.type == NL80211_IFTYPE_AP || 1248 if ((sdata->vif.type == NL80211_IFTYPE_AP ||
1246 sdata->vif.type == NL80211_IFTYPE_AP_VLAN) && 1249 sdata->vif.type == NL80211_IFTYPE_AP_VLAN) &&
1247 !(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) && 1250 !(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) &&
1248 (rx->flags & IEEE80211_RX_RA_MATCH) && !rx->sdata->use_4addr) { 1251 (rx->flags & IEEE80211_RX_RA_MATCH) &&
1252 (sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->u.vlan.sta)) {
1249 if (is_multicast_ether_addr(ehdr->h_dest)) { 1253 if (is_multicast_ether_addr(ehdr->h_dest)) {
1250 /* 1254 /*
1251 * send multicast frames both to higher layers in 1255 * send multicast frames both to higher layers in
@@ -2007,7 +2011,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
2007 2011
2008 switch (sdata->vif.type) { 2012 switch (sdata->vif.type) {
2009 case NL80211_IFTYPE_STATION: 2013 case NL80211_IFTYPE_STATION:
2010 if (!bssid && !sdata->use_4addr) 2014 if (!bssid && !sdata->u.mgd.use_4addr)
2011 return 0; 2015 return 0;
2012 if (!multicast && 2016 if (!multicast &&
2013 compare_ether_addr(sdata->dev->dev_addr, hdr->addr1) != 0) { 2017 compare_ether_addr(sdata->dev->dev_addr, hdr->addr1) != 0) {
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index b3c1faeb5927..5af2f40ea4db 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1051,7 +1051,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
1051 1051
1052 hdr = (struct ieee80211_hdr *) skb->data; 1052 hdr = (struct ieee80211_hdr *) skb->data;
1053 1053
1054 if ((sdata->vif.type == NL80211_IFTYPE_AP_VLAN) && sdata->use_4addr) 1054 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
1055 tx->sta = rcu_dereference(sdata->u.vlan.sta); 1055 tx->sta = rcu_dereference(sdata->u.vlan.sta);
1056 if (!tx->sta) 1056 if (!tx->sta)
1057 tx->sta = sta_info_get(local, hdr->addr1); 1057 tx->sta = sta_info_get(local, hdr->addr1);
@@ -1632,8 +1632,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
1632 switch (sdata->vif.type) { 1632 switch (sdata->vif.type) {
1633 case NL80211_IFTYPE_AP_VLAN: 1633 case NL80211_IFTYPE_AP_VLAN:
1634 rcu_read_lock(); 1634 rcu_read_lock();
1635 if (sdata->use_4addr) 1635 sta = rcu_dereference(sdata->u.vlan.sta);
1636 sta = rcu_dereference(sdata->u.vlan.sta);
1637 if (sta) { 1636 if (sta) {
1638 fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); 1637 fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
1639 /* RA TA DA SA */ 1638 /* RA TA DA SA */
@@ -1727,7 +1726,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
1727#endif 1726#endif
1728 case NL80211_IFTYPE_STATION: 1727 case NL80211_IFTYPE_STATION:
1729 memcpy(hdr.addr1, sdata->u.mgd.bssid, ETH_ALEN); 1728 memcpy(hdr.addr1, sdata->u.mgd.bssid, ETH_ALEN);
1730 if (sdata->use_4addr && ethertype != ETH_P_PAE) { 1729 if (sdata->u.mgd.use_4addr && ethertype != ETH_P_PAE) {
1731 fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); 1730 fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
1732 /* RA TA DA SA */ 1731 /* RA TA DA SA */
1733 memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); 1732 memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
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}