[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>

authored by Dan Williams and committed by Jeff Garzik 9a6301c1 c213460f

+223 -4
+223 -4
drivers/net/wireless/atmel.c
··· 1407 1407 { 1408 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 1421 atmel_enter_state(priv, STATION_STATE_DOWN); 1411 1422 1412 1423 if (priv->bus_type == BUS_TYPE_PCCARD) ··· 1791 1780 priv->wep_is_on = 1; 1792 1781 priv->exclude_unencrypted = 1; 1793 1782 if (priv->wep_key_len[index] > 5) { 1794 - priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_64; 1783 + priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_128; 1795 1784 priv->encryption_level = 2; 1796 1785 } else { 1797 - priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_128; 1786 + priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_64; 1798 1787 priv->encryption_level = 1; 1799 1788 } 1800 1789 } ··· 1863 1852 1864 1853 return 0; 1865 1854 } 1855 + 1856 + static int atmel_set_encodeext(struct net_device *dev, 1857 + struct iw_request_info *info, 1858 + union iwreq_data *wrqu, 1859 + char *extra) 1860 + { 1861 + struct atmel_private *priv = netdev_priv(dev); 1862 + struct iw_point *encoding = &wrqu->encoding; 1863 + struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; 1864 + int idx, key_len; 1865 + 1866 + /* Determine and validate the key index */ 1867 + idx = encoding->flags & IW_ENCODE_INDEX; 1868 + if (idx) { 1869 + if (idx < 1 || idx > WEP_KEYS) 1870 + return -EINVAL; 1871 + idx--; 1872 + } else 1873 + idx = priv->default_key; 1874 + 1875 + if ((encoding->flags & IW_ENCODE_DISABLED) || 1876 + ext->alg == IW_ENCODE_ALG_NONE) { 1877 + priv->wep_is_on = 0; 1878 + priv->encryption_level = 0; 1879 + priv->pairwise_cipher_suite = CIPHER_SUITE_NONE; 1880 + } 1881 + 1882 + if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) 1883 + priv->default_key = idx; 1884 + 1885 + /* Set the requested key */ 1886 + switch (ext->alg) { 1887 + case IW_ENCODE_ALG_NONE: 1888 + break; 1889 + case IW_ENCODE_ALG_WEP: 1890 + if (ext->key_len > 5) { 1891 + priv->wep_key_len[idx] = 13; 1892 + priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_128; 1893 + priv->encryption_level = 2; 1894 + } else if (ext->key_len > 0) { 1895 + priv->wep_key_len[idx] = 5; 1896 + priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_64; 1897 + priv->encryption_level = 1; 1898 + } else { 1899 + return -EINVAL; 1900 + } 1901 + priv->wep_is_on = 1; 1902 + memset(priv->wep_keys[idx], 0, 13); 1903 + key_len = min ((int)ext->key_len, priv->wep_key_len[idx]); 1904 + memcpy(priv->wep_keys[idx], ext->key, key_len); 1905 + break; 1906 + default: 1907 + return -EINVAL; 1908 + } 1909 + 1910 + return -EINPROGRESS; 1911 + } 1912 + 1913 + static int atmel_get_encodeext(struct net_device *dev, 1914 + struct iw_request_info *info, 1915 + union iwreq_data *wrqu, 1916 + char *extra) 1917 + { 1918 + struct atmel_private *priv = netdev_priv(dev); 1919 + struct iw_point *encoding = &wrqu->encoding; 1920 + struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; 1921 + int idx, max_key_len; 1922 + 1923 + max_key_len = encoding->length - sizeof(*ext); 1924 + if (max_key_len < 0) 1925 + return -EINVAL; 1926 + 1927 + idx = encoding->flags & IW_ENCODE_INDEX; 1928 + if (idx) { 1929 + if (idx < 1 || idx > WEP_KEYS) 1930 + return -EINVAL; 1931 + idx--; 1932 + } else 1933 + idx = priv->default_key; 1934 + 1935 + encoding->flags = idx + 1; 1936 + memset(ext, 0, sizeof(*ext)); 1937 + 1938 + if (!priv->wep_is_on) { 1939 + ext->alg = IW_ENCODE_ALG_NONE; 1940 + ext->key_len = 0; 1941 + encoding->flags |= IW_ENCODE_DISABLED; 1942 + } else { 1943 + if (priv->encryption_level > 0) 1944 + ext->alg = IW_ENCODE_ALG_WEP; 1945 + else 1946 + return -EINVAL; 1947 + 1948 + ext->key_len = priv->wep_key_len[idx]; 1949 + memcpy(ext->key, priv->wep_keys[idx], ext->key_len); 1950 + encoding->flags |= IW_ENCODE_ENABLED; 1951 + } 1952 + 1953 + return 0; 1954 + } 1955 + 1956 + static int atmel_set_auth(struct net_device *dev, 1957 + struct iw_request_info *info, 1958 + union iwreq_data *wrqu, char *extra) 1959 + { 1960 + struct atmel_private *priv = netdev_priv(dev); 1961 + struct iw_param *param = &wrqu->param; 1962 + 1963 + switch (param->flags & IW_AUTH_INDEX) { 1964 + case IW_AUTH_WPA_VERSION: 1965 + case IW_AUTH_CIPHER_PAIRWISE: 1966 + case IW_AUTH_CIPHER_GROUP: 1967 + case IW_AUTH_KEY_MGMT: 1968 + case IW_AUTH_RX_UNENCRYPTED_EAPOL: 1969 + case IW_AUTH_PRIVACY_INVOKED: 1970 + /* 1971 + * atmel does not use these parameters 1972 + */ 1973 + break; 1974 + 1975 + case IW_AUTH_DROP_UNENCRYPTED: 1976 + priv->exclude_unencrypted = param->value ? 1 : 0; 1977 + break; 1978 + 1979 + case IW_AUTH_80211_AUTH_ALG: { 1980 + if (param->value & IW_AUTH_ALG_SHARED_KEY) { 1981 + priv->exclude_unencrypted = 1; 1982 + } else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) { 1983 + priv->exclude_unencrypted = 0; 1984 + } else 1985 + return -EINVAL; 1986 + break; 1987 + } 1988 + 1989 + case IW_AUTH_WPA_ENABLED: 1990 + /* Silently accept disable of WPA */ 1991 + if (param->value > 0) 1992 + return -EOPNOTSUPP; 1993 + break; 1994 + 1995 + default: 1996 + return -EOPNOTSUPP; 1997 + } 1998 + return -EINPROGRESS; 1999 + } 2000 + 2001 + static int atmel_get_auth(struct net_device *dev, 2002 + struct iw_request_info *info, 2003 + union iwreq_data *wrqu, char *extra) 2004 + { 2005 + struct atmel_private *priv = netdev_priv(dev); 2006 + struct iw_param *param = &wrqu->param; 2007 + 2008 + switch (param->flags & IW_AUTH_INDEX) { 2009 + case IW_AUTH_DROP_UNENCRYPTED: 2010 + param->value = priv->exclude_unencrypted; 2011 + break; 2012 + 2013 + case IW_AUTH_80211_AUTH_ALG: 2014 + if (priv->exclude_unencrypted == 1) 2015 + param->value = IW_AUTH_ALG_SHARED_KEY; 2016 + else 2017 + param->value = IW_AUTH_ALG_OPEN_SYSTEM; 2018 + break; 2019 + 2020 + case IW_AUTH_WPA_ENABLED: 2021 + param->value = 0; 2022 + break; 2023 + 2024 + default: 2025 + return -EOPNOTSUPP; 2026 + } 2027 + return 0; 2028 + } 2029 + 1866 2030 1867 2031 static int atmel_get_name(struct net_device *dev, 1868 2032 struct iw_request_info *info, ··· 2475 2289 { 2476 2290 struct atmel_private *priv = netdev_priv(dev); 2477 2291 int i; 2478 - static const u8 bcast[] = { 255, 255, 255, 255, 255, 255 }; 2292 + static const u8 any[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; 2293 + static const u8 off[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 2479 2294 unsigned long flags; 2480 2295 2481 2296 if (awrq->sa_family != ARPHRD_ETHER) 2482 2297 return -EINVAL; 2483 2298 2484 - if (memcmp(bcast, awrq->sa_data, 6) == 0) { 2299 + if (!memcmp(any, awrq->sa_data, 6) || 2300 + !memcmp(off, awrq->sa_data, 6)) { 2485 2301 del_timer_sync(&priv->management_timer); 2486 2302 spin_lock_irqsave(&priv->irqlock, flags); 2487 2303 atmel_scan(priv, 1); ··· 2566 2378 (iw_handler) atmel_get_encode, /* SIOCGIWENCODE */ 2567 2379 (iw_handler) atmel_set_power, /* SIOCSIWPOWER */ 2568 2380 (iw_handler) atmel_get_power, /* SIOCGIWPOWER */ 2381 + (iw_handler) NULL, /* -- hole -- */ 2382 + (iw_handler) NULL, /* -- hole -- */ 2383 + (iw_handler) NULL, /* SIOCSIWGENIE */ 2384 + (iw_handler) NULL, /* SIOCGIWGENIE */ 2385 + (iw_handler) atmel_set_auth, /* SIOCSIWAUTH */ 2386 + (iw_handler) atmel_get_auth, /* SIOCGIWAUTH */ 2387 + (iw_handler) atmel_set_encodeext, /* SIOCSIWENCODEEXT */ 2388 + (iw_handler) atmel_get_encodeext, /* SIOCGIWENCODEEXT */ 2389 + (iw_handler) NULL, /* SIOCSIWPMKSA */ 2569 2390 }; 2570 2391 2571 2392 static const iw_handler atmel_private_handler[] = ··· 3121 2924 u16 ass_id = le16_to_cpu(ass_resp->ass_id); 3122 2925 u16 rates_len = ass_resp->length > 4 ? 4 : ass_resp->length; 3123 2926 2927 + union iwreq_data wrqu; 2928 + 3124 2929 if (frame_len < 8 + rates_len) 3125 2930 return; 3126 2931 ··· 3153 2954 priv->station_is_associated = 1; 3154 2955 priv->station_was_associated = 1; 3155 2956 atmel_enter_state(priv, STATION_STATE_READY); 2957 + 2958 + /* Send association event to userspace */ 2959 + wrqu.data.length = 0; 2960 + wrqu.data.flags = 0; 2961 + memcpy(wrqu.ap_addr.sa_data, priv->CurrentBSSID, ETH_ALEN); 2962 + wrqu.ap_addr.sa_family = ARPHRD_ETHER; 2963 + wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); 2964 + 3156 2965 return; 3157 2966 } 3158 2967 ··· 3839 3632 3840 3633 struct atmel_private *priv = netdev_priv(dev); 3841 3634 u8 configuration; 3635 + int old_state = priv->station_state; 3842 3636 3843 3637 /* data to add to the firmware names, in priority order 3844 3638 this implemenents firmware versioning */ ··· 3999 3791 build_wpa_mib(priv); 4000 3792 else 4001 3793 build_wep_mib(priv); 3794 + 3795 + if (old_state == STATION_STATE_READY) 3796 + { 3797 + union iwreq_data wrqu; 3798 + 3799 + wrqu.data.length = 0; 3800 + wrqu.data.flags = 0; 3801 + wrqu.ap_addr.sa_family = ARPHRD_ETHER; 3802 + memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); 3803 + wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); 3804 + } 4002 3805 4003 3806 return 1; 4004 3807 }