diff options
Diffstat (limited to 'net/wireless/util.c')
-rw-r--r-- | net/wireless/util.c | 40 |
1 files changed, 39 insertions, 1 deletions
diff --git a/net/wireless/util.c b/net/wireless/util.c index 3fc2df86278f..59361fdcb5d0 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -320,7 +320,9 @@ int ieee80211_data_to_8023(struct sk_buff *skb, u8 *addr, | |||
320 | break; | 320 | break; |
321 | case cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS): | 321 | case cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS): |
322 | if (unlikely(iftype != NL80211_IFTYPE_WDS && | 322 | if (unlikely(iftype != NL80211_IFTYPE_WDS && |
323 | iftype != NL80211_IFTYPE_MESH_POINT)) | 323 | iftype != NL80211_IFTYPE_MESH_POINT && |
324 | iftype != NL80211_IFTYPE_AP_VLAN && | ||
325 | iftype != NL80211_IFTYPE_STATION)) | ||
324 | return -1; | 326 | return -1; |
325 | if (iftype == NL80211_IFTYPE_MESH_POINT) { | 327 | if (iftype == NL80211_IFTYPE_MESH_POINT) { |
326 | struct ieee80211s_hdr *meshdr = | 328 | struct ieee80211s_hdr *meshdr = |
@@ -656,7 +658,14 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, | |||
656 | !(rdev->wiphy.interface_modes & (1 << ntype))) | 658 | !(rdev->wiphy.interface_modes & (1 << ntype))) |
657 | return -EOPNOTSUPP; | 659 | return -EOPNOTSUPP; |
658 | 660 | ||
661 | /* if it's part of a bridge, reject changing type to station/ibss */ | ||
662 | if (dev->br_port && (ntype == NL80211_IFTYPE_ADHOC || | ||
663 | ntype == NL80211_IFTYPE_STATION)) | ||
664 | return -EBUSY; | ||
665 | |||
659 | if (ntype != otype) { | 666 | if (ntype != otype) { |
667 | dev->ieee80211_ptr->use_4addr = false; | ||
668 | |||
660 | switch (otype) { | 669 | switch (otype) { |
661 | case NL80211_IFTYPE_ADHOC: | 670 | case NL80211_IFTYPE_ADHOC: |
662 | cfg80211_leave_ibss(rdev, dev, false); | 671 | cfg80211_leave_ibss(rdev, dev, false); |
@@ -680,5 +689,34 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, | |||
680 | 689 | ||
681 | WARN_ON(!err && dev->ieee80211_ptr->iftype != ntype); | 690 | WARN_ON(!err && dev->ieee80211_ptr->iftype != ntype); |
682 | 691 | ||
692 | if (!err && params && params->use_4addr != -1) | ||
693 | dev->ieee80211_ptr->use_4addr = params->use_4addr; | ||
694 | |||
695 | if (!err) { | ||
696 | dev->priv_flags &= ~IFF_DONT_BRIDGE; | ||
697 | switch (ntype) { | ||
698 | case NL80211_IFTYPE_STATION: | ||
699 | if (dev->ieee80211_ptr->use_4addr) | ||
700 | break; | ||
701 | /* fall through */ | ||
702 | case NL80211_IFTYPE_ADHOC: | ||
703 | dev->priv_flags |= IFF_DONT_BRIDGE; | ||
704 | break; | ||
705 | case NL80211_IFTYPE_AP: | ||
706 | case NL80211_IFTYPE_AP_VLAN: | ||
707 | case NL80211_IFTYPE_WDS: | ||
708 | case NL80211_IFTYPE_MESH_POINT: | ||
709 | /* bridging OK */ | ||
710 | break; | ||
711 | case NL80211_IFTYPE_MONITOR: | ||
712 | /* monitor can't bridge anyway */ | ||
713 | break; | ||
714 | case NL80211_IFTYPE_UNSPECIFIED: | ||
715 | case __NL80211_IFTYPE_AFTER_LAST: | ||
716 | /* not happening */ | ||
717 | break; | ||
718 | } | ||
719 | } | ||
720 | |||
683 | return err; | 721 | return err; |
684 | } | 722 | } |