aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2006-01-10 00:56:11 -0500
committerJeff Garzik <jgarzik@pobox.com>2006-01-12 16:34:24 -0500
commit9a6301c114aaab1df6de6fad9899bb89852a7592 (patch)
tree7889afd49f5d4a97434c4bac5995e1828192c96d
parentc213460fd4781c04832c81416532d64ae2bfa88b (diff)
[PATCH] wireless/atmel: add IWENCODEEXT, IWAUTH, and association event support
This patch allows the Atmel driver to work correctly with wpa_supplicant and other programs that require some conformance with WEXT-18. It should not affect current behavior of the driver. The patch does four things: 1) Implements SIOCSIWENCODEEXT, SIOCGIWENCODEEXT, SIOCSIWAUTH, and SIOCGIWAUTH calls for unencrypted and WEP operation 2) Accepts zero-filled addresses for SIOCSIWAP, which are legal and should turn off any previous forced WAP address 3) Sends association and de-association events to userspace at most of the appropriate times 4) Fixes erroneous order of CIPHER_SUITE_WEP_* arguments in one location which are actually unused anyway Signed-off-by: Dan Williams <dcbw@redhat.com> Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
-rw-r--r--drivers/net/wireless/atmel.c227
1 files changed, 223 insertions, 4 deletions
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
index e4729ddf29fd..f0ccfef66445 100644
--- a/drivers/net/wireless/atmel.c
+++ b/drivers/net/wireless/atmel.c
@@ -1407,6 +1407,17 @@ static int atmel_close(struct net_device *dev)
1407{ 1407{
1408 struct atmel_private *priv = netdev_priv(dev); 1408 struct atmel_private *priv = netdev_priv(dev);
1409 1409
1410 /* Send event to userspace that we are disassociating */
1411 if (priv->station_state == STATION_STATE_READY) {
1412 union iwreq_data wrqu;
1413
1414 wrqu.data.length = 0;
1415 wrqu.data.flags = 0;
1416 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
1417 memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
1418 wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
1419 }
1420
1410 atmel_enter_state(priv, STATION_STATE_DOWN); 1421 atmel_enter_state(priv, STATION_STATE_DOWN);
1411 1422
1412 if (priv->bus_type == BUS_TYPE_PCCARD) 1423 if (priv->bus_type == BUS_TYPE_PCCARD)
@@ -1780,10 +1791,10 @@ static int atmel_set_encode(struct net_device *dev,
1780 priv->wep_is_on = 1; 1791 priv->wep_is_on = 1;
1781 priv->exclude_unencrypted = 1; 1792 priv->exclude_unencrypted = 1;
1782 if (priv->wep_key_len[index] > 5) { 1793 if (priv->wep_key_len[index] > 5) {
1783 priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_64; 1794 priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_128;
1784 priv->encryption_level = 2; 1795 priv->encryption_level = 2;
1785 } else { 1796 } else {
1786 priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_128; 1797 priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_64;
1787 priv->encryption_level = 1; 1798 priv->encryption_level = 1;
1788 } 1799 }
1789 } 1800 }
@@ -1853,6 +1864,181 @@ static int atmel_get_encode(struct net_device *dev,
1853 return 0; 1864 return 0;
1854} 1865}
1855 1866
1867static int atmel_set_encodeext(struct net_device *dev,
1868 struct iw_request_info *info,
1869 union iwreq_data *wrqu,
1870 char *extra)
1871{
1872 struct atmel_private *priv = netdev_priv(dev);
1873 struct iw_point *encoding = &wrqu->encoding;
1874 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1875 int idx, key_len;
1876
1877 /* Determine and validate the key index */
1878 idx = encoding->flags & IW_ENCODE_INDEX;
1879 if (idx) {
1880 if (idx < 1 || idx > WEP_KEYS)
1881 return -EINVAL;
1882 idx--;
1883 } else
1884 idx = priv->default_key;
1885
1886 if ((encoding->flags & IW_ENCODE_DISABLED) ||
1887 ext->alg == IW_ENCODE_ALG_NONE) {
1888 priv->wep_is_on = 0;
1889 priv->encryption_level = 0;
1890 priv->pairwise_cipher_suite = CIPHER_SUITE_NONE;
1891 }
1892
1893 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
1894 priv->default_key = idx;
1895
1896 /* Set the requested key */
1897 switch (ext->alg) {
1898 case IW_ENCODE_ALG_NONE:
1899 break;
1900 case IW_ENCODE_ALG_WEP:
1901 if (ext->key_len > 5) {
1902 priv->wep_key_len[idx] = 13;
1903 priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_128;
1904 priv->encryption_level = 2;
1905 } else if (ext->key_len > 0) {
1906 priv->wep_key_len[idx] = 5;
1907 priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_64;
1908 priv->encryption_level = 1;
1909 } else {
1910 return -EINVAL;
1911 }
1912 priv->wep_is_on = 1;
1913 memset(priv->wep_keys[idx], 0, 13);
1914 key_len = min ((int)ext->key_len, priv->wep_key_len[idx]);
1915 memcpy(priv->wep_keys[idx], ext->key, key_len);
1916 break;
1917 default:
1918 return -EINVAL;
1919 }
1920
1921 return -EINPROGRESS;
1922}
1923
1924static int atmel_get_encodeext(struct net_device *dev,
1925 struct iw_request_info *info,
1926 union iwreq_data *wrqu,
1927 char *extra)
1928{
1929 struct atmel_private *priv = netdev_priv(dev);
1930 struct iw_point *encoding = &wrqu->encoding;
1931 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1932 int idx, max_key_len;
1933
1934 max_key_len = encoding->length - sizeof(*ext);
1935 if (max_key_len < 0)
1936 return -EINVAL;
1937
1938 idx = encoding->flags & IW_ENCODE_INDEX;
1939 if (idx) {
1940 if (idx < 1 || idx > WEP_KEYS)
1941 return -EINVAL;
1942 idx--;
1943 } else
1944 idx = priv->default_key;
1945
1946 encoding->flags = idx + 1;
1947 memset(ext, 0, sizeof(*ext));
1948
1949 if (!priv->wep_is_on) {
1950 ext->alg = IW_ENCODE_ALG_NONE;
1951 ext->key_len = 0;
1952 encoding->flags |= IW_ENCODE_DISABLED;
1953 } else {
1954 if (priv->encryption_level > 0)
1955 ext->alg = IW_ENCODE_ALG_WEP;
1956 else
1957 return -EINVAL;
1958
1959 ext->key_len = priv->wep_key_len[idx];
1960 memcpy(ext->key, priv->wep_keys[idx], ext->key_len);
1961 encoding->flags |= IW_ENCODE_ENABLED;
1962 }
1963
1964 return 0;
1965}
1966
1967static int atmel_set_auth(struct net_device *dev,
1968 struct iw_request_info *info,
1969 union iwreq_data *wrqu, char *extra)
1970{
1971 struct atmel_private *priv = netdev_priv(dev);
1972 struct iw_param *param = &wrqu->param;
1973
1974 switch (param->flags & IW_AUTH_INDEX) {
1975 case IW_AUTH_WPA_VERSION:
1976 case IW_AUTH_CIPHER_PAIRWISE:
1977 case IW_AUTH_CIPHER_GROUP:
1978 case IW_AUTH_KEY_MGMT:
1979 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1980 case IW_AUTH_PRIVACY_INVOKED:
1981 /*
1982 * atmel does not use these parameters
1983 */
1984 break;
1985
1986 case IW_AUTH_DROP_UNENCRYPTED:
1987 priv->exclude_unencrypted = param->value ? 1 : 0;
1988 break;
1989
1990 case IW_AUTH_80211_AUTH_ALG: {
1991 if (param->value & IW_AUTH_ALG_SHARED_KEY) {
1992 priv->exclude_unencrypted = 1;
1993 } else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) {
1994 priv->exclude_unencrypted = 0;
1995 } else
1996 return -EINVAL;
1997 break;
1998 }
1999
2000 case IW_AUTH_WPA_ENABLED:
2001 /* Silently accept disable of WPA */
2002 if (param->value > 0)
2003 return -EOPNOTSUPP;
2004 break;
2005
2006 default:
2007 return -EOPNOTSUPP;
2008 }
2009 return -EINPROGRESS;
2010}
2011
2012static int atmel_get_auth(struct net_device *dev,
2013 struct iw_request_info *info,
2014 union iwreq_data *wrqu, char *extra)
2015{
2016 struct atmel_private *priv = netdev_priv(dev);
2017 struct iw_param *param = &wrqu->param;
2018
2019 switch (param->flags & IW_AUTH_INDEX) {
2020 case IW_AUTH_DROP_UNENCRYPTED:
2021 param->value = priv->exclude_unencrypted;
2022 break;
2023
2024 case IW_AUTH_80211_AUTH_ALG:
2025 if (priv->exclude_unencrypted == 1)
2026 param->value = IW_AUTH_ALG_SHARED_KEY;
2027 else
2028 param->value = IW_AUTH_ALG_OPEN_SYSTEM;
2029 break;
2030
2031 case IW_AUTH_WPA_ENABLED:
2032 param->value = 0;
2033 break;
2034
2035 default:
2036 return -EOPNOTSUPP;
2037 }
2038 return 0;
2039}
2040
2041
1856static int atmel_get_name(struct net_device *dev, 2042static int atmel_get_name(struct net_device *dev,
1857 struct iw_request_info *info, 2043 struct iw_request_info *info,
1858 char *cwrq, 2044 char *cwrq,
@@ -2289,13 +2475,15 @@ static int atmel_set_wap(struct net_device *dev,
2289{ 2475{
2290 struct atmel_private *priv = netdev_priv(dev); 2476 struct atmel_private *priv = netdev_priv(dev);
2291 int i; 2477 int i;
2292 static const u8 bcast[] = { 255, 255, 255, 255, 255, 255 }; 2478 static const u8 any[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
2479 static const u8 off[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
2293 unsigned long flags; 2480 unsigned long flags;
2294 2481
2295 if (awrq->sa_family != ARPHRD_ETHER) 2482 if (awrq->sa_family != ARPHRD_ETHER)
2296 return -EINVAL; 2483 return -EINVAL;
2297 2484
2298 if (memcmp(bcast, awrq->sa_data, 6) == 0) { 2485 if (!memcmp(any, awrq->sa_data, 6) ||
2486 !memcmp(off, awrq->sa_data, 6)) {
2299 del_timer_sync(&priv->management_timer); 2487 del_timer_sync(&priv->management_timer);
2300 spin_lock_irqsave(&priv->irqlock, flags); 2488 spin_lock_irqsave(&priv->irqlock, flags);
2301 atmel_scan(priv, 1); 2489 atmel_scan(priv, 1);
@@ -2378,6 +2566,15 @@ static const iw_handler atmel_handler[] =
2378 (iw_handler) atmel_get_encode, /* SIOCGIWENCODE */ 2566 (iw_handler) atmel_get_encode, /* SIOCGIWENCODE */
2379 (iw_handler) atmel_set_power, /* SIOCSIWPOWER */ 2567 (iw_handler) atmel_set_power, /* SIOCSIWPOWER */
2380 (iw_handler) atmel_get_power, /* SIOCGIWPOWER */ 2568 (iw_handler) atmel_get_power, /* SIOCGIWPOWER */
2569 (iw_handler) NULL, /* -- hole -- */
2570 (iw_handler) NULL, /* -- hole -- */
2571 (iw_handler) NULL, /* SIOCSIWGENIE */
2572 (iw_handler) NULL, /* SIOCGIWGENIE */
2573 (iw_handler) atmel_set_auth, /* SIOCSIWAUTH */
2574 (iw_handler) atmel_get_auth, /* SIOCGIWAUTH */
2575 (iw_handler) atmel_set_encodeext, /* SIOCSIWENCODEEXT */
2576 (iw_handler) atmel_get_encodeext, /* SIOCGIWENCODEEXT */
2577 (iw_handler) NULL, /* SIOCSIWPMKSA */
2381}; 2578};
2382 2579
2383static const iw_handler atmel_private_handler[] = 2580static const iw_handler atmel_private_handler[] =
@@ -2924,6 +3121,8 @@ static void associate(struct atmel_private *priv, u16 frame_len, u16 subtype)
2924 u16 ass_id = le16_to_cpu(ass_resp->ass_id); 3121 u16 ass_id = le16_to_cpu(ass_resp->ass_id);
2925 u16 rates_len = ass_resp->length > 4 ? 4 : ass_resp->length; 3122 u16 rates_len = ass_resp->length > 4 ? 4 : ass_resp->length;
2926 3123
3124 union iwreq_data wrqu;
3125
2927 if (frame_len < 8 + rates_len) 3126 if (frame_len < 8 + rates_len)
2928 return; 3127 return;
2929 3128
@@ -2954,6 +3153,14 @@ static void associate(struct atmel_private *priv, u16 frame_len, u16 subtype)
2954 priv->station_is_associated = 1; 3153 priv->station_is_associated = 1;
2955 priv->station_was_associated = 1; 3154 priv->station_was_associated = 1;
2956 atmel_enter_state(priv, STATION_STATE_READY); 3155 atmel_enter_state(priv, STATION_STATE_READY);
3156
3157 /* Send association event to userspace */
3158 wrqu.data.length = 0;
3159 wrqu.data.flags = 0;
3160 memcpy(wrqu.ap_addr.sa_data, priv->CurrentBSSID, ETH_ALEN);
3161 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3162 wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
3163
2957 return; 3164 return;
2958 } 3165 }
2959 3166
@@ -3632,6 +3839,7 @@ static int reset_atmel_card(struct net_device *dev)
3632 3839
3633 struct atmel_private *priv = netdev_priv(dev); 3840 struct atmel_private *priv = netdev_priv(dev);
3634 u8 configuration; 3841 u8 configuration;
3842 int old_state = priv->station_state;
3635 3843
3636 /* data to add to the firmware names, in priority order 3844 /* data to add to the firmware names, in priority order
3637 this implemenents firmware versioning */ 3845 this implemenents firmware versioning */
@@ -3792,6 +4000,17 @@ static int reset_atmel_card(struct net_device *dev)
3792 else 4000 else
3793 build_wep_mib(priv); 4001 build_wep_mib(priv);
3794 4002
4003 if (old_state == STATION_STATE_READY)
4004 {
4005 union iwreq_data wrqu;
4006
4007 wrqu.data.length = 0;
4008 wrqu.data.flags = 0;
4009 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4010 memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
4011 wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
4012 }
4013
3795 return 1; 4014 return 1;
3796} 4015}
3797 4016