aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rndis_wlan.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/rndis_wlan.c')
-rw-r--r--drivers/net/wireless/rndis_wlan.c216
1 files changed, 118 insertions, 98 deletions
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 52fc647e6cb6..c254fdf446fd 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -2,7 +2,7 @@
2 * Driver for RNDIS based wireless USB devices. 2 * Driver for RNDIS based wireless USB devices.
3 * 3 *
4 * Copyright (C) 2007 by Bjorge Dijkstra <bjd@jooz.net> 4 * Copyright (C) 2007 by Bjorge Dijkstra <bjd@jooz.net>
5 * Copyright (C) 2008 by Jussi Kivilinna <jussi.kivilinna@mbnet.fi> 5 * Copyright (C) 2008-2009 by Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by 8 * it under the terms of the GNU General Public License as published by
@@ -196,6 +196,18 @@ enum ndis_80211_priv_filter {
196 ndis_80211_priv_8021x_wep 196 ndis_80211_priv_8021x_wep
197}; 197};
198 198
199enum ndis_80211_addkey_bits {
200 ndis_80211_addkey_8021x_auth = cpu_to_le32(1 << 28),
201 ndis_80211_addkey_set_init_recv_seq = cpu_to_le32(1 << 29),
202 ndis_80211_addkey_pairwise_key = cpu_to_le32(1 << 30),
203 ndis_80211_addkey_transmit_key = cpu_to_le32(1 << 31),
204};
205
206enum ndis_80211_addwep_bits {
207 ndis_80211_addwep_perclient_key = cpu_to_le32(1 << 30),
208 ndis_80211_addwep_transmit_key = cpu_to_le32(1 << 31),
209};
210
199struct ndis_80211_ssid { 211struct ndis_80211_ssid {
200 __le32 length; 212 __le32 length;
201 u8 essid[NDIS_802_11_LENGTH_SSID]; 213 u8 essid[NDIS_802_11_LENGTH_SSID];
@@ -309,7 +321,6 @@ enum wpa_key_mgmt { KEY_MGMT_802_1X, KEY_MGMT_PSK, KEY_MGMT_NONE,
309#define CAP_MODE_80211B 2 321#define CAP_MODE_80211B 2
310#define CAP_MODE_80211G 4 322#define CAP_MODE_80211G 4
311#define CAP_MODE_MASK 7 323#define CAP_MODE_MASK 7
312#define CAP_SUPPORT_TXPOWER 8
313 324
314#define WORK_LINK_UP (1<<0) 325#define WORK_LINK_UP (1<<0)
315#define WORK_LINK_DOWN (1<<1) 326#define WORK_LINK_DOWN (1<<1)
@@ -394,6 +405,7 @@ struct rndis_wext_private {
394 int encr_tx_key_index; 405 int encr_tx_key_index;
395 char encr_keys[4][32]; 406 char encr_keys[4][32];
396 int encr_key_len[4]; 407 int encr_key_len[4];
408 char encr_key_wpa[4];
397 int wpa_version; 409 int wpa_version;
398 int wpa_keymgmt; 410 int wpa_keymgmt;
399 int wpa_authalg; 411 int wpa_authalg;
@@ -945,7 +957,7 @@ static int set_infra_mode(struct usbnet *usbdev, int mode)
945 if (priv->wpa_keymgmt == 0 || 957 if (priv->wpa_keymgmt == 0 ||
946 priv->wpa_keymgmt == IW_AUTH_KEY_MGMT_802_1X) { 958 priv->wpa_keymgmt == IW_AUTH_KEY_MGMT_802_1X) {
947 for (i = 0; i < 4; i++) { 959 for (i = 0; i < 4; i++) {
948 if (priv->encr_key_len[i] > 0) 960 if (priv->encr_key_len[i] > 0 && !priv->encr_key_wpa[i])
949 add_wep_key(usbdev, priv->encr_keys[i], 961 add_wep_key(usbdev, priv->encr_keys[i],
950 priv->encr_key_len[i], i); 962 priv->encr_key_len[i], i);
951 } 963 }
@@ -999,7 +1011,7 @@ static int add_wep_key(struct usbnet *usbdev, char *key, int key_len, int index)
999 memcpy(&ndis_key.material, key, key_len); 1011 memcpy(&ndis_key.material, key, key_len);
1000 1012
1001 if (index == priv->encr_tx_key_index) { 1013 if (index == priv->encr_tx_key_index) {
1002 ndis_key.index |= cpu_to_le32(1 << 31); 1014 ndis_key.index |= ndis_80211_addwep_transmit_key;
1003 ret = set_encr_mode(usbdev, IW_AUTH_CIPHER_WEP104, 1015 ret = set_encr_mode(usbdev, IW_AUTH_CIPHER_WEP104,
1004 IW_AUTH_CIPHER_NONE); 1016 IW_AUTH_CIPHER_NONE);
1005 if (ret) 1017 if (ret)
@@ -1016,12 +1028,81 @@ static int add_wep_key(struct usbnet *usbdev, char *key, int key_len, int index)
1016 } 1028 }
1017 1029
1018 priv->encr_key_len[index] = key_len; 1030 priv->encr_key_len[index] = key_len;
1031 priv->encr_key_wpa[index] = 0;
1019 memcpy(&priv->encr_keys[index], key, key_len); 1032 memcpy(&priv->encr_keys[index], key, key_len);
1020 1033
1021 return 0; 1034 return 0;
1022} 1035}
1023 1036
1024 1037
1038static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len,
1039 int index, const struct sockaddr *addr,
1040 const u8 *rx_seq, int alg, int flags)
1041{
1042 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
1043 struct ndis_80211_key ndis_key;
1044 int ret;
1045
1046 if (index < 0 || index >= 4)
1047 return -EINVAL;
1048 if (key_len > sizeof(ndis_key.material) || key_len < 0)
1049 return -EINVAL;
1050 if ((flags & ndis_80211_addkey_set_init_recv_seq) && !rx_seq)
1051 return -EINVAL;
1052 if ((flags & ndis_80211_addkey_pairwise_key) && !addr)
1053 return -EINVAL;
1054
1055 devdbg(usbdev, "add_wpa_key(%i): flags:%i%i%i", index,
1056 !!(flags & ndis_80211_addkey_transmit_key),
1057 !!(flags & ndis_80211_addkey_pairwise_key),
1058 !!(flags & ndis_80211_addkey_set_init_recv_seq));
1059
1060 memset(&ndis_key, 0, sizeof(ndis_key));
1061
1062 ndis_key.size = cpu_to_le32(sizeof(ndis_key) -
1063 sizeof(ndis_key.material) + key_len);
1064 ndis_key.length = cpu_to_le32(key_len);
1065 ndis_key.index = cpu_to_le32(index) | flags;
1066
1067 if (alg == IW_ENCODE_ALG_TKIP && key_len == 32) {
1068 /* wpa_supplicant gives us the Michael MIC RX/TX keys in
1069 * different order than NDIS spec, so swap the order here. */
1070 memcpy(ndis_key.material, key, 16);
1071 memcpy(ndis_key.material + 16, key + 24, 8);
1072 memcpy(ndis_key.material + 24, key + 16, 8);
1073 } else
1074 memcpy(ndis_key.material, key, key_len);
1075
1076 if (flags & ndis_80211_addkey_set_init_recv_seq)
1077 memcpy(ndis_key.rsc, rx_seq, 6);
1078
1079 if (flags & ndis_80211_addkey_pairwise_key) {
1080 /* pairwise key */
1081 memcpy(ndis_key.bssid, addr->sa_data, ETH_ALEN);
1082 } else {
1083 /* group key */
1084 if (priv->infra_mode == ndis_80211_infra_adhoc)
1085 memset(ndis_key.bssid, 0xff, ETH_ALEN);
1086 else
1087 get_bssid(usbdev, ndis_key.bssid);
1088 }
1089
1090 ret = rndis_set_oid(usbdev, OID_802_11_ADD_KEY, &ndis_key,
1091 le32_to_cpu(ndis_key.size));
1092 devdbg(usbdev, "add_wpa_key: OID_802_11_ADD_KEY -> %08X", ret);
1093 if (ret != 0)
1094 return ret;
1095
1096 priv->encr_key_len[index] = key_len;
1097 priv->encr_key_wpa[index] = 1;
1098
1099 if (flags & ndis_80211_addkey_transmit_key)
1100 priv->encr_tx_key_index = index;
1101
1102 return 0;
1103}
1104
1105
1025/* remove_key is for both wep and wpa */ 1106/* remove_key is for both wep and wpa */
1026static int remove_key(struct usbnet *usbdev, int index, u8 bssid[ETH_ALEN]) 1107static int remove_key(struct usbnet *usbdev, int index, u8 bssid[ETH_ALEN])
1027{ 1108{
@@ -1034,6 +1115,7 @@ static int remove_key(struct usbnet *usbdev, int index, u8 bssid[ETH_ALEN])
1034 return 0; 1115 return 0;
1035 1116
1036 priv->encr_key_len[index] = 0; 1117 priv->encr_key_len[index] = 0;
1118 priv->encr_key_wpa[index] = 0;
1037 memset(&priv->encr_keys[index], 0, sizeof(priv->encr_keys[index])); 1119 memset(&priv->encr_keys[index], 0, sizeof(priv->encr_keys[index]));
1038 1120
1039 if (priv->wpa_cipher_pair == IW_AUTH_CIPHER_TKIP || 1121 if (priv->wpa_cipher_pair == IW_AUTH_CIPHER_TKIP ||
@@ -1045,7 +1127,8 @@ static int remove_key(struct usbnet *usbdev, int index, u8 bssid[ETH_ALEN])
1045 if (bssid) { 1127 if (bssid) {
1046 /* pairwise key */ 1128 /* pairwise key */
1047 if (memcmp(bssid, ffff_bssid, ETH_ALEN) != 0) 1129 if (memcmp(bssid, ffff_bssid, ETH_ALEN) != 0)
1048 remove_key.index |= cpu_to_le32(1 << 30); 1130 remove_key.index |=
1131 ndis_80211_addkey_pairwise_key;
1049 memcpy(remove_key.bssid, bssid, 1132 memcpy(remove_key.bssid, bssid,
1050 sizeof(remove_key.bssid)); 1133 sizeof(remove_key.bssid));
1051 } else 1134 } else
@@ -1590,9 +1673,7 @@ static int rndis_iw_set_encode_ext(struct net_device *dev,
1590 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; 1673 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1591 struct usbnet *usbdev = netdev_priv(dev); 1674 struct usbnet *usbdev = netdev_priv(dev);
1592 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); 1675 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
1593 struct ndis_80211_key ndis_key; 1676 int keyidx, flags;
1594 int keyidx, ret;
1595 u8 *addr;
1596 1677
1597 keyidx = wrqu->encoding.flags & IW_ENCODE_INDEX; 1678 keyidx = wrqu->encoding.flags & IW_ENCODE_INDEX;
1598 1679
@@ -1615,58 +1696,16 @@ static int rndis_iw_set_encode_ext(struct net_device *dev,
1615 ext->alg == IW_ENCODE_ALG_NONE || ext->key_len == 0) 1696 ext->alg == IW_ENCODE_ALG_NONE || ext->key_len == 0)
1616 return remove_key(usbdev, keyidx, NULL); 1697 return remove_key(usbdev, keyidx, NULL);
1617 1698
1618 if (ext->key_len > sizeof(ndis_key.material)) 1699 flags = 0;
1619 return -1; 1700 if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
1620 1701 flags |= ndis_80211_addkey_set_init_recv_seq;
1621 memset(&ndis_key, 0, sizeof(ndis_key)); 1702 if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY))
1622 1703 flags |= ndis_80211_addkey_pairwise_key;
1623 ndis_key.size = cpu_to_le32(sizeof(ndis_key) -
1624 sizeof(ndis_key.material) + ext->key_len);
1625 ndis_key.length = cpu_to_le32(ext->key_len);
1626 ndis_key.index = cpu_to_le32(keyidx);
1627
1628 if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
1629 memcpy(ndis_key.rsc, ext->rx_seq, 6);
1630 ndis_key.index |= cpu_to_le32(1 << 29);
1631 }
1632
1633 addr = ext->addr.sa_data;
1634 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
1635 /* group key */
1636 if (priv->infra_mode == ndis_80211_infra_adhoc)
1637 memset(ndis_key.bssid, 0xff, ETH_ALEN);
1638 else
1639 get_bssid(usbdev, ndis_key.bssid);
1640 } else {
1641 /* pairwise key */
1642 ndis_key.index |= cpu_to_le32(1 << 30);
1643 memcpy(ndis_key.bssid, addr, ETH_ALEN);
1644 }
1645
1646 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
1647 ndis_key.index |= cpu_to_le32(1 << 31);
1648
1649 if (ext->alg == IW_ENCODE_ALG_TKIP && ext->key_len == 32) {
1650 /* wpa_supplicant gives us the Michael MIC RX/TX keys in
1651 * different order than NDIS spec, so swap the order here. */
1652 memcpy(ndis_key.material, ext->key, 16);
1653 memcpy(ndis_key.material + 16, ext->key + 24, 8);
1654 memcpy(ndis_key.material + 24, ext->key + 16, 8);
1655 } else
1656 memcpy(ndis_key.material, ext->key, ext->key_len);
1657
1658 ret = rndis_set_oid(usbdev, OID_802_11_ADD_KEY, &ndis_key,
1659 le32_to_cpu(ndis_key.size));
1660 devdbg(usbdev, "SIOCSIWENCODEEXT: OID_802_11_ADD_KEY -> %08X", ret);
1661 if (ret != 0)
1662 return ret;
1663
1664 priv->encr_key_len[keyidx] = ext->key_len;
1665 memcpy(&priv->encr_keys[keyidx], ndis_key.material, ext->key_len);
1666 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) 1704 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
1667 priv->encr_tx_key_index = keyidx; 1705 flags |= ndis_80211_addkey_transmit_key;
1668 1706
1669 return 0; 1707 return add_wpa_key(usbdev, ext->key, ext->key_len, keyidx, &ext->addr,
1708 ext->rx_seq, ext->alg, flags);
1670} 1709}
1671 1710
1672 1711
@@ -1849,18 +1888,10 @@ static int rndis_iw_get_txpower(struct net_device *dev,
1849 struct usbnet *usbdev = netdev_priv(dev); 1888 struct usbnet *usbdev = netdev_priv(dev);
1850 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); 1889 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
1851 __le32 tx_power; 1890 __le32 tx_power;
1852 int ret = 0, len;
1853 1891
1854 if (priv->radio_on) { 1892 if (priv->radio_on) {
1855 if (priv->caps & CAP_SUPPORT_TXPOWER) { 1893 /* fake since changing tx_power (by userlevel) not supported */
1856 len = sizeof(tx_power); 1894 tx_power = cpu_to_le32(get_bcm4320_power(priv));
1857 ret = rndis_query_oid(usbdev, OID_802_11_TX_POWER_LEVEL,
1858 &tx_power, &len);
1859 if (ret != 0)
1860 return ret;
1861 } else
1862 /* fake incase not supported */
1863 tx_power = cpu_to_le32(get_bcm4320_power(priv));
1864 1895
1865 wrqu->txpower.flags = IW_TXPOW_MWATT; 1896 wrqu->txpower.flags = IW_TXPOW_MWATT;
1866 wrqu->txpower.value = le32_to_cpu(tx_power); 1897 wrqu->txpower.value = le32_to_cpu(tx_power);
@@ -1873,7 +1904,7 @@ static int rndis_iw_get_txpower(struct net_device *dev,
1873 1904
1874 devdbg(usbdev, "SIOCGIWTXPOW: %d", wrqu->txpower.value); 1905 devdbg(usbdev, "SIOCGIWTXPOW: %d", wrqu->txpower.value);
1875 1906
1876 return ret; 1907 return 0;
1877} 1908}
1878 1909
1879 1910
@@ -1883,7 +1914,6 @@ static int rndis_iw_set_txpower(struct net_device *dev,
1883 struct usbnet *usbdev = netdev_priv(dev); 1914 struct usbnet *usbdev = netdev_priv(dev);
1884 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); 1915 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
1885 __le32 tx_power = 0; 1916 __le32 tx_power = 0;
1886 int ret = 0;
1887 1917
1888 if (!wrqu->txpower.disabled) { 1918 if (!wrqu->txpower.disabled) {
1889 if (wrqu->txpower.flags == IW_TXPOW_MWATT) 1919 if (wrqu->txpower.flags == IW_TXPOW_MWATT)
@@ -1906,22 +1936,10 @@ static int rndis_iw_set_txpower(struct net_device *dev,
1906 devdbg(usbdev, "SIOCSIWTXPOW: %d", le32_to_cpu(tx_power)); 1936 devdbg(usbdev, "SIOCSIWTXPOW: %d", le32_to_cpu(tx_power));
1907 1937
1908 if (le32_to_cpu(tx_power) != 0) { 1938 if (le32_to_cpu(tx_power) != 0) {
1909 if (priv->caps & CAP_SUPPORT_TXPOWER) { 1939 /* txpower unsupported, just turn radio on */
1910 /* turn radio on first */ 1940 if (!priv->radio_on)
1911 if (!priv->radio_on) 1941 return disassociate(usbdev, 1);
1912 disassociate(usbdev, 1); 1942 return 0; /* all ready on */
1913
1914 ret = rndis_set_oid(usbdev, OID_802_11_TX_POWER_LEVEL,
1915 &tx_power, sizeof(tx_power));
1916 if (ret != 0)
1917 ret = -EOPNOTSUPP;
1918 return ret;
1919 } else {
1920 /* txpower unsupported, just turn radio on */
1921 if (!priv->radio_on)
1922 return disassociate(usbdev, 1);
1923 return 0; /* all ready on */
1924 }
1925 } 1943 }
1926 1944
1927 /* tx_power == 0, turn off radio */ 1945 /* tx_power == 0, turn off radio */
@@ -2130,16 +2148,8 @@ static int rndis_wext_get_caps(struct usbnet *usbdev)
2130 __le32 items[8]; 2148 __le32 items[8];
2131 } networks_supported; 2149 } networks_supported;
2132 int len, retval, i, n; 2150 int len, retval, i, n;
2133 __le32 tx_power;
2134 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); 2151 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
2135 2152
2136 /* determine if supports setting txpower */
2137 len = sizeof(tx_power);
2138 retval = rndis_query_oid(usbdev, OID_802_11_TX_POWER_LEVEL, &tx_power,
2139 &len);
2140 if (retval == 0 && le32_to_cpu(tx_power) != 0xFF)
2141 priv->caps |= CAP_SUPPORT_TXPOWER;
2142
2143 /* determine supported modes */ 2153 /* determine supported modes */
2144 len = sizeof(networks_supported); 2154 len = sizeof(networks_supported);
2145 retval = rndis_query_oid(usbdev, OID_802_11_NETWORK_TYPES_SUPPORTED, 2155 retval = rndis_query_oid(usbdev, OID_802_11_NETWORK_TYPES_SUPPORTED,
@@ -2275,7 +2285,17 @@ end:
2275} 2285}
2276 2286
2277 2287
2278static int bcm4320_early_init(struct usbnet *usbdev) 2288static int bcm4320a_early_init(struct usbnet *usbdev)
2289{
2290 /* bcm4320a doesn't handle configuration parameters well. Try
2291 * set any and you get partially zeroed mac and broken device.
2292 */
2293
2294 return 0;
2295}
2296
2297
2298static int bcm4320b_early_init(struct usbnet *usbdev)
2279{ 2299{
2280 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); 2300 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
2281 char buf[8]; 2301 char buf[8];
@@ -2515,7 +2535,7 @@ static const struct driver_info bcm4320b_info = {
2515 .rx_fixup = rndis_rx_fixup, 2535 .rx_fixup = rndis_rx_fixup,
2516 .tx_fixup = rndis_tx_fixup, 2536 .tx_fixup = rndis_tx_fixup,
2517 .reset = rndis_wext_reset, 2537 .reset = rndis_wext_reset,
2518 .early_init = bcm4320_early_init, 2538 .early_init = bcm4320b_early_init,
2519 .link_change = rndis_wext_link_change, 2539 .link_change = rndis_wext_link_change,
2520}; 2540};
2521 2541
@@ -2528,7 +2548,7 @@ static const struct driver_info bcm4320a_info = {
2528 .rx_fixup = rndis_rx_fixup, 2548 .rx_fixup = rndis_rx_fixup,
2529 .tx_fixup = rndis_tx_fixup, 2549 .tx_fixup = rndis_tx_fixup,
2530 .reset = rndis_wext_reset, 2550 .reset = rndis_wext_reset,
2531 .early_init = bcm4320_early_init, 2551 .early_init = bcm4320a_early_init,
2532 .link_change = rndis_wext_link_change, 2552 .link_change = rndis_wext_link_change,
2533}; 2553};
2534 2554
@@ -2541,7 +2561,7 @@ static const struct driver_info rndis_wext_info = {
2541 .rx_fixup = rndis_rx_fixup, 2561 .rx_fixup = rndis_rx_fixup,
2542 .tx_fixup = rndis_tx_fixup, 2562 .tx_fixup = rndis_tx_fixup,
2543 .reset = rndis_wext_reset, 2563 .reset = rndis_wext_reset,
2544 .early_init = bcm4320_early_init, 2564 .early_init = bcm4320a_early_init,
2545 .link_change = rndis_wext_link_change, 2565 .link_change = rndis_wext_link_change,
2546}; 2566};
2547 2567