aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mlme.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r--net/mac80211/mlme.c254
1 files changed, 146 insertions, 108 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 332397415890..fbb766afe599 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -808,9 +808,6 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
808 bss_info_changed |= BSS_CHANGED_ASSOC; 808 bss_info_changed |= BSS_CHANGED_ASSOC;
809 ifsta->flags |= IEEE80211_STA_ASSOCIATED; 809 ifsta->flags |= IEEE80211_STA_ASSOCIATED;
810 810
811 if (sdata->vif.type != NL80211_IFTYPE_STATION)
812 return;
813
814 bss = ieee80211_rx_bss_get(local, ifsta->bssid, 811 bss = ieee80211_rx_bss_get(local, ifsta->bssid,
815 conf->channel->center_freq, 812 conf->channel->center_freq,
816 ifsta->ssid, ifsta->ssid_len); 813 ifsta->ssid, ifsta->ssid_len);
@@ -1169,6 +1166,30 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata,
1169 elems.challenge_len + 2, 1); 1166 elems.challenge_len + 2, 1);
1170} 1167}
1171 1168
1169static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata,
1170 struct ieee80211_if_sta *ifsta,
1171 struct ieee80211_mgmt *mgmt,
1172 size_t len)
1173{
1174 u16 auth_alg, auth_transaction, status_code;
1175
1176 if (len < 24 + 6)
1177 return;
1178
1179 auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg);
1180 auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction);
1181 status_code = le16_to_cpu(mgmt->u.auth.status_code);
1182
1183 /*
1184 * IEEE 802.11 standard does not require authentication in IBSS
1185 * networks and most implementations do not seem to use it.
1186 * However, try to reply to authentication attempts if someone
1187 * has actually implemented this.
1188 */
1189 if (auth_alg == WLAN_AUTH_OPEN && auth_transaction == 1)
1190 ieee80211_send_auth(sdata, ifsta, 2, NULL, 0, 0);
1191}
1192
1172static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, 1193static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
1173 struct ieee80211_if_sta *ifsta, 1194 struct ieee80211_if_sta *ifsta,
1174 struct ieee80211_mgmt *mgmt, 1195 struct ieee80211_mgmt *mgmt,
@@ -1176,38 +1197,22 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
1176{ 1197{
1177 u16 auth_alg, auth_transaction, status_code; 1198 u16 auth_alg, auth_transaction, status_code;
1178 1199
1179 if (ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE && 1200 if (ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE)
1180 sdata->vif.type != NL80211_IFTYPE_ADHOC)
1181 return; 1201 return;
1182 1202
1183 if (len < 24 + 6) 1203 if (len < 24 + 6)
1184 return; 1204 return;
1185 1205
1186 if (sdata->vif.type != NL80211_IFTYPE_ADHOC && 1206 if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0)
1187 memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0)
1188 return; 1207 return;
1189 1208
1190 if (sdata->vif.type != NL80211_IFTYPE_ADHOC && 1209 if (memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0)
1191 memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0)
1192 return; 1210 return;
1193 1211
1194 auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg); 1212 auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg);
1195 auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction); 1213 auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction);
1196 status_code = le16_to_cpu(mgmt->u.auth.status_code); 1214 status_code = le16_to_cpu(mgmt->u.auth.status_code);
1197 1215
1198 if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
1199 /*
1200 * IEEE 802.11 standard does not require authentication in IBSS
1201 * networks and most implementations do not seem to use it.
1202 * However, try to reply to authentication attempts if someone
1203 * has actually implemented this.
1204 */
1205 if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1)
1206 return;
1207 ieee80211_send_auth(sdata, ifsta, 2, NULL, 0, 0);
1208 return;
1209 }
1210
1211 if (auth_alg != ifsta->auth_alg || 1216 if (auth_alg != ifsta->auth_alg ||
1212 auth_transaction != ifsta->auth_transaction) 1217 auth_transaction != ifsta->auth_transaction)
1213 return; 1218 return;
@@ -1762,74 +1767,85 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
1762 /* was just updated in ieee80211_bss_info_update */ 1767 /* was just updated in ieee80211_bss_info_update */
1763 beacon_timestamp = bss->cbss.tsf; 1768 beacon_timestamp = bss->cbss.tsf;
1764 1769
1765 /* 1770 if (sdata->vif.type != NL80211_IFTYPE_ADHOC)
1766 * In STA mode, the remaining parameters should not be overridden 1771 goto put_bss;
1767 * by beacons because they're not necessarily accurate there.
1768 */
1769 if (sdata->vif.type != NL80211_IFTYPE_ADHOC &&
1770 bss->last_probe_resp && beacon) {
1771 ieee80211_rx_bss_put(local, bss);
1772 return;
1773 }
1774 1772
1775 /* check if we need to merge IBSS */ 1773 /* check if we need to merge IBSS */
1776 if (sdata->vif.type == NL80211_IFTYPE_ADHOC && beacon && 1774
1777 (!(sdata->u.sta.flags & IEEE80211_STA_BSSID_SET)) && 1775 /* merge only on beacons (???) */
1778 bss->cbss.capability & WLAN_CAPABILITY_IBSS && 1776 if (!beacon)
1779 bss->cbss.channel == local->oper_channel && 1777 goto put_bss;
1780 elems->ssid_len == sdata->u.sta.ssid_len && 1778
1779 /* we use a fixed BSSID */
1780 if (sdata->u.sta.flags & IEEE80211_STA_BSSID_SET)
1781 goto put_bss;
1782
1783 /* not an IBSS */
1784 if (!(bss->cbss.capability & WLAN_CAPABILITY_IBSS))
1785 goto put_bss;
1786
1787 /* different channel */
1788 if (bss->cbss.channel != local->oper_channel)
1789 goto put_bss;
1790
1791 /* different SSID */
1792 if (elems->ssid_len != sdata->u.sta.ssid_len ||
1781 memcmp(elems->ssid, sdata->u.sta.ssid, 1793 memcmp(elems->ssid, sdata->u.sta.ssid,
1782 sdata->u.sta.ssid_len) == 0) { 1794 sdata->u.sta.ssid_len))
1783 if (rx_status->flag & RX_FLAG_TSFT) { 1795 goto put_bss;
1784 /* in order for correct IBSS merging we need mactime 1796
1785 * 1797 if (rx_status->flag & RX_FLAG_TSFT) {
1786 * since mactime is defined as the time the first data 1798 /*
1787 * symbol of the frame hits the PHY, and the timestamp 1799 * For correct IBSS merging we need mactime; since mactime is
1788 * of the beacon is defined as "the time that the data 1800 * defined as the time the first data symbol of the frame hits
1789 * symbol containing the first bit of the timestamp is 1801 * the PHY, and the timestamp of the beacon is defined as "the
1790 * transmitted to the PHY plus the transmitting STA’s 1802 * time that the data symbol containing the first bit of the
1791 * delays through its local PHY from the MAC-PHY 1803 * timestamp is transmitted to the PHY plus the transmitting
1792 * interface to its interface with the WM" 1804 * STA's delays through its local PHY from the MAC-PHY
1793 * (802.11 11.1.2) - equals the time this bit arrives at 1805 * interface to its interface with the WM" (802.11 11.1.2)
1794 * the receiver - we have to take into account the 1806 * - equals the time this bit arrives at the receiver - we have
1795 * offset between the two. 1807 * to take into account the offset between the two.
1796 * e.g: at 1 MBit that means mactime is 192 usec earlier 1808 *
1797 * (=24 bytes * 8 usecs/byte) than the beacon timestamp. 1809 * E.g. at 1 MBit that means mactime is 192 usec earlier
1798 */ 1810 * (=24 bytes * 8 usecs/byte) than the beacon timestamp.
1799 int rate; 1811 */
1800 if (rx_status->flag & RX_FLAG_HT) { 1812 int rate;
1801 rate = 65; /* TODO: HT rates */ 1813
1802 } else { 1814 if (rx_status->flag & RX_FLAG_HT)
1803 rate = local->hw.wiphy->bands[band]-> 1815 rate = 65; /* TODO: HT rates */
1804 bitrates[rx_status->rate_idx].bitrate;
1805 }
1806 rx_timestamp = rx_status->mactime + (24 * 8 * 10 / rate);
1807 } else if (local && local->ops && local->ops->get_tsf)
1808 /* second best option: get current TSF */
1809 rx_timestamp = local->ops->get_tsf(local_to_hw(local));
1810 else 1816 else
1811 /* can't merge without knowing the TSF */ 1817 rate = local->hw.wiphy->bands[band]->
1812 rx_timestamp = -1LLU; 1818 bitrates[rx_status->rate_idx].bitrate;
1819
1820 rx_timestamp = rx_status->mactime + (24 * 8 * 10 / rate);
1821 } else if (local && local->ops && local->ops->get_tsf)
1822 /* second best option: get current TSF */
1823 rx_timestamp = local->ops->get_tsf(local_to_hw(local));
1824 else
1825 /* can't merge without knowing the TSF */
1826 rx_timestamp = -1LLU;
1827
1813#ifdef CONFIG_MAC80211_IBSS_DEBUG 1828#ifdef CONFIG_MAC80211_IBSS_DEBUG
1814 printk(KERN_DEBUG "RX beacon SA=%pM BSSID=" 1829 printk(KERN_DEBUG "RX beacon SA=%pM BSSID="
1815 "%pM TSF=0x%llx BCN=0x%llx diff=%lld @%lu\n", 1830 "%pM TSF=0x%llx BCN=0x%llx diff=%lld @%lu\n",
1816 mgmt->sa, mgmt->bssid, 1831 mgmt->sa, mgmt->bssid,
1817 (unsigned long long)rx_timestamp, 1832 (unsigned long long)rx_timestamp,
1818 (unsigned long long)beacon_timestamp, 1833 (unsigned long long)beacon_timestamp,
1819 (unsigned long long)(rx_timestamp - beacon_timestamp), 1834 (unsigned long long)(rx_timestamp - beacon_timestamp),
1820 jiffies); 1835 jiffies);
1821#endif /* CONFIG_MAC80211_IBSS_DEBUG */ 1836#endif
1822 if (beacon_timestamp > rx_timestamp) { 1837
1838 if (beacon_timestamp > rx_timestamp) {
1823#ifdef CONFIG_MAC80211_IBSS_DEBUG 1839#ifdef CONFIG_MAC80211_IBSS_DEBUG
1824 printk(KERN_DEBUG "%s: beacon TSF higher than " 1840 printk(KERN_DEBUG "%s: beacon TSF higher than "
1825 "local TSF - IBSS merge with BSSID %pM\n", 1841 "local TSF - IBSS merge with BSSID %pM\n",
1826 sdata->dev->name, mgmt->bssid); 1842 sdata->dev->name, mgmt->bssid);
1827#endif 1843#endif
1828 ieee80211_sta_join_ibss(sdata, &sdata->u.sta, bss); 1844 ieee80211_sta_join_ibss(sdata, &sdata->u.sta, bss);
1829 ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, supp_rates); 1845 ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, supp_rates);
1830 }
1831 } 1846 }
1832 1847
1848 put_bss:
1833 ieee80211_rx_bss_put(local, bss); 1849 ieee80211_rx_bss_put(local, bss);
1834} 1850}
1835 1851
@@ -1993,8 +2009,7 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata,
1993 struct ieee80211_mgmt *resp; 2009 struct ieee80211_mgmt *resp;
1994 u8 *pos, *end; 2010 u8 *pos, *end;
1995 2011
1996 if (sdata->vif.type != NL80211_IFTYPE_ADHOC || 2012 if (ifsta->state != IEEE80211_STA_MLME_IBSS_JOINED ||
1997 ifsta->state != IEEE80211_STA_MLME_IBSS_JOINED ||
1998 len < 24 + 2 || !ifsta->probe_resp) 2013 len < 24 + 2 || !ifsta->probe_resp)
1999 return; 2014 return;
2000 2015
@@ -2098,31 +2113,54 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
2098 mgmt = (struct ieee80211_mgmt *) skb->data; 2113 mgmt = (struct ieee80211_mgmt *) skb->data;
2099 fc = le16_to_cpu(mgmt->frame_control); 2114 fc = le16_to_cpu(mgmt->frame_control);
2100 2115
2101 switch (fc & IEEE80211_FCTL_STYPE) { 2116 if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
2102 case IEEE80211_STYPE_PROBE_REQ: 2117 switch (fc & IEEE80211_FCTL_STYPE) {
2103 ieee80211_rx_mgmt_probe_req(sdata, ifsta, mgmt, skb->len); 2118 case IEEE80211_STYPE_PROBE_REQ:
2104 break; 2119 ieee80211_rx_mgmt_probe_req(sdata, ifsta, mgmt,
2105 case IEEE80211_STYPE_PROBE_RESP: 2120 skb->len);
2106 ieee80211_rx_mgmt_probe_resp(sdata, mgmt, skb->len, rx_status); 2121 break;
2107 break; 2122 case IEEE80211_STYPE_PROBE_RESP:
2108 case IEEE80211_STYPE_BEACON: 2123 ieee80211_rx_mgmt_probe_resp(sdata, mgmt, skb->len,
2109 ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len, rx_status); 2124 rx_status);
2110 break; 2125 break;
2111 case IEEE80211_STYPE_AUTH: 2126 case IEEE80211_STYPE_BEACON:
2112 ieee80211_rx_mgmt_auth(sdata, ifsta, mgmt, skb->len); 2127 ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len,
2113 break; 2128 rx_status);
2114 case IEEE80211_STYPE_ASSOC_RESP: 2129 break;
2115 ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt, skb->len, 0); 2130 case IEEE80211_STYPE_AUTH:
2116 break; 2131 ieee80211_rx_mgmt_auth_ibss(sdata, ifsta, mgmt,
2117 case IEEE80211_STYPE_REASSOC_RESP: 2132 skb->len);
2118 ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt, skb->len, 1); 2133 break;
2119 break; 2134 }
2120 case IEEE80211_STYPE_DEAUTH: 2135 } else { /* NL80211_IFTYPE_STATION */
2121 ieee80211_rx_mgmt_deauth(sdata, ifsta, mgmt, skb->len); 2136 switch (fc & IEEE80211_FCTL_STYPE) {
2122 break; 2137 case IEEE80211_STYPE_PROBE_RESP:
2123 case IEEE80211_STYPE_DISASSOC: 2138 ieee80211_rx_mgmt_probe_resp(sdata, mgmt, skb->len,
2124 ieee80211_rx_mgmt_disassoc(sdata, ifsta, mgmt, skb->len); 2139 rx_status);
2125 break; 2140 break;
2141 case IEEE80211_STYPE_BEACON:
2142 ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len,
2143 rx_status);
2144 break;
2145 case IEEE80211_STYPE_AUTH:
2146 ieee80211_rx_mgmt_auth(sdata, ifsta, mgmt, skb->len);
2147 break;
2148 case IEEE80211_STYPE_ASSOC_RESP:
2149 ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt,
2150 skb->len, 0);
2151 break;
2152 case IEEE80211_STYPE_REASSOC_RESP:
2153 ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt,
2154 skb->len, 1);
2155 break;
2156 case IEEE80211_STYPE_DEAUTH:
2157 ieee80211_rx_mgmt_deauth(sdata, ifsta, mgmt, skb->len);
2158 break;
2159 case IEEE80211_STYPE_DISASSOC:
2160 ieee80211_rx_mgmt_disassoc(sdata, ifsta, mgmt,
2161 skb->len);
2162 break;
2163 }
2126 } 2164 }
2127 2165
2128 kfree_skb(skb); 2166 kfree_skb(skb);