diff options
-rw-r--r-- | net/mac80211/cfg.c | 10 | ||||
-rw-r--r-- | net/mac80211/sta_info.h | 5 | ||||
-rw-r--r-- | net/mac80211/tx.c | 42 | ||||
-rw-r--r-- | net/wireless/util.c | 5 |
4 files changed, 55 insertions, 7 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 119a573af14b..bdf9852eec5b 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -2427,6 +2427,7 @@ fail: | |||
2427 | static int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, | 2427 | static int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, |
2428 | u8 *peer, enum nl80211_tdls_operation oper) | 2428 | u8 *peer, enum nl80211_tdls_operation oper) |
2429 | { | 2429 | { |
2430 | struct sta_info *sta; | ||
2430 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 2431 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
2431 | 2432 | ||
2432 | if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) | 2433 | if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) |
@@ -2441,6 +2442,15 @@ static int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, | |||
2441 | 2442 | ||
2442 | switch (oper) { | 2443 | switch (oper) { |
2443 | case NL80211_TDLS_ENABLE_LINK: | 2444 | case NL80211_TDLS_ENABLE_LINK: |
2445 | rcu_read_lock(); | ||
2446 | sta = sta_info_get(sdata, peer); | ||
2447 | if (!sta) { | ||
2448 | rcu_read_unlock(); | ||
2449 | return -ENOLINK; | ||
2450 | } | ||
2451 | |||
2452 | set_sta_flags(sta, WLAN_STA_TDLS_PEER_AUTH); | ||
2453 | rcu_read_unlock(); | ||
2444 | break; | 2454 | break; |
2445 | case NL80211_TDLS_DISABLE_LINK: | 2455 | case NL80211_TDLS_DISABLE_LINK: |
2446 | return sta_info_destroy_addr(sdata, peer); | 2456 | return sta_info_destroy_addr(sdata, peer); |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index b6bd4e9d8722..c10e2e8632b5 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -45,7 +45,9 @@ | |||
45 | * station in power-save mode, reply when the driver unblocks. | 45 | * station in power-save mode, reply when the driver unblocks. |
46 | * @WLAN_STA_PS_DRIVER_BUF: Station has frames pending in driver internal | 46 | * @WLAN_STA_PS_DRIVER_BUF: Station has frames pending in driver internal |
47 | * buffers. Automatically cleared on station wake-up. | 47 | * buffers. Automatically cleared on station wake-up. |
48 | * @WLAN_STA_TDLS_PEER: station is a TDLS peer. | 48 | * @WLAN_STA_TDLS_PEER: Station is a TDLS peer. |
49 | * @WLAN_STA_TDLS_PEER_AUTH: This TDLS peer is authorized to send direct | ||
50 | * packets. This means the link is enabled. | ||
49 | */ | 51 | */ |
50 | enum ieee80211_sta_info_flags { | 52 | enum ieee80211_sta_info_flags { |
51 | WLAN_STA_AUTH = 1<<0, | 53 | WLAN_STA_AUTH = 1<<0, |
@@ -63,6 +65,7 @@ enum ieee80211_sta_info_flags { | |||
63 | WLAN_STA_PSPOLL = 1<<13, | 65 | WLAN_STA_PSPOLL = 1<<13, |
64 | WLAN_STA_PS_DRIVER_BUF = 1<<14, | 66 | WLAN_STA_PS_DRIVER_BUF = 1<<14, |
65 | WLAN_STA_TDLS_PEER = 1<<15, | 67 | WLAN_STA_TDLS_PEER = 1<<15, |
68 | WLAN_STA_TDLS_PEER_AUTH = 1<<16, | ||
66 | }; | 69 | }; |
67 | 70 | ||
68 | #define STA_TID_NUM 16 | 71 | #define STA_TID_NUM 16 |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 542272acfc1a..0ca16880bbb4 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -1726,6 +1726,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1726 | struct sta_info *sta = NULL; | 1726 | struct sta_info *sta = NULL; |
1727 | u32 sta_flags = 0; | 1727 | u32 sta_flags = 0; |
1728 | struct sk_buff *tmp_skb; | 1728 | struct sk_buff *tmp_skb; |
1729 | bool tdls_direct = false; | ||
1729 | 1730 | ||
1730 | if (unlikely(skb->len < ETH_HLEN)) { | 1731 | if (unlikely(skb->len < ETH_HLEN)) { |
1731 | ret = NETDEV_TX_OK; | 1732 | ret = NETDEV_TX_OK; |
@@ -1837,11 +1838,43 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1837 | break; | 1838 | break; |
1838 | #endif | 1839 | #endif |
1839 | case NL80211_IFTYPE_STATION: | 1840 | case NL80211_IFTYPE_STATION: |
1840 | memcpy(hdr.addr1, sdata->u.mgd.bssid, ETH_ALEN); | 1841 | if (sdata->wdev.wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) { |
1841 | if (sdata->u.mgd.use_4addr && | 1842 | rcu_read_lock(); |
1842 | cpu_to_be16(ethertype) != sdata->control_port_protocol) { | 1843 | sta = sta_info_get(sdata, skb->data); |
1843 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); | 1844 | if (sta) |
1845 | sta_flags = get_sta_flags(sta); | ||
1846 | rcu_read_unlock(); | ||
1847 | |||
1848 | /* | ||
1849 | * If the TDLS link is enabled, send everything | ||
1850 | * directly. Otherwise, allow TDLS setup frames | ||
1851 | * to be transmitted indirectly. | ||
1852 | */ | ||
1853 | tdls_direct = | ||
1854 | (sta_flags & WLAN_STA_TDLS_PEER) && | ||
1855 | ((sta_flags & WLAN_STA_TDLS_PEER_AUTH) || | ||
1856 | !(ethertype == ETH_P_TDLS && skb->len > 14 && | ||
1857 | skb->data[14] == WLAN_TDLS_SNAP_RFTYPE)); | ||
1858 | } | ||
1859 | |||
1860 | if (tdls_direct) { | ||
1861 | /* link during setup - throw out frames to peer */ | ||
1862 | if (!(sta_flags & WLAN_STA_TDLS_PEER_AUTH)) { | ||
1863 | ret = NETDEV_TX_OK; | ||
1864 | goto fail; | ||
1865 | } | ||
1866 | |||
1867 | /* DA SA BSSID */ | ||
1868 | memcpy(hdr.addr1, skb->data, ETH_ALEN); | ||
1869 | memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN); | ||
1870 | memcpy(hdr.addr3, sdata->u.mgd.bssid, ETH_ALEN); | ||
1871 | hdrlen = 24; | ||
1872 | } else if (sdata->u.mgd.use_4addr && | ||
1873 | cpu_to_be16(ethertype) != sdata->control_port_protocol) { | ||
1874 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | | ||
1875 | IEEE80211_FCTL_TODS); | ||
1844 | /* RA TA DA SA */ | 1876 | /* RA TA DA SA */ |
1877 | memcpy(hdr.addr1, sdata->u.mgd.bssid, ETH_ALEN); | ||
1845 | memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN); | 1878 | memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN); |
1846 | memcpy(hdr.addr3, skb->data, ETH_ALEN); | 1879 | memcpy(hdr.addr3, skb->data, ETH_ALEN); |
1847 | memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); | 1880 | memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); |
@@ -1849,6 +1882,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1849 | } else { | 1882 | } else { |
1850 | fc |= cpu_to_le16(IEEE80211_FCTL_TODS); | 1883 | fc |= cpu_to_le16(IEEE80211_FCTL_TODS); |
1851 | /* BSSID SA DA */ | 1884 | /* BSSID SA DA */ |
1885 | memcpy(hdr.addr1, sdata->u.mgd.bssid, ETH_ALEN); | ||
1852 | memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN); | 1886 | memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN); |
1853 | memcpy(hdr.addr3, skb->data, ETH_ALEN); | 1887 | memcpy(hdr.addr3, skb->data, ETH_ALEN); |
1854 | hdrlen = 24; | 1888 | hdrlen = 24; |
diff --git a/net/wireless/util.c b/net/wireless/util.c index 6304ed63588a..2f178f73943f 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -396,8 +396,9 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, | |||
396 | } | 396 | } |
397 | break; | 397 | break; |
398 | case cpu_to_le16(0): | 398 | case cpu_to_le16(0): |
399 | if (iftype != NL80211_IFTYPE_ADHOC) | 399 | if (iftype != NL80211_IFTYPE_ADHOC && |
400 | return -1; | 400 | iftype != NL80211_IFTYPE_STATION) |
401 | return -1; | ||
401 | break; | 402 | break; |
402 | } | 403 | } |
403 | 404 | ||