The patch titled airo: wpa support has been removed from the -mm tree. Its filename was airo-wpa-support.patch This patch was dropped because it was nacked ------------------------------------------------------ Subject: airo: wpa support From: matthieu castet <castet.matthieu@xxxxxxx> Add wpa support for airo driver. In then end of 2005 I manage to make work wpa but the code was really ugly. I manage to find some time to clean it. To support wpa, a new interface of the firmware should be used. This interface is incompatible with the old interface and using both interface at the same time make the firmware hang. Porting OPEN and WEP mode to new interface need some driver rewrite, and the old interface should be keep for the older cards (or the cards that doesn't have newer firmware). That's why I didn't do it, and I added a module parameter for choosing between the old driver behavior (with no wpa support) or the driver with wpa only support. The wireless extension handlers are a bit ugly, I will be very happy, if somebody could help me to clean them. Cc: Jean Tourrilhes <jt@xxxxxxxxxx> Cc: Herbert Xu <herbert@xxxxxxxxxxxxxxxxxxx> Cc: Dan Williams <dcbw@xxxxxxxxxx> Cc: "John W. Linville" <linville@xxxxxxxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> --- drivers/net/wireless/airo.c | 403 +++++++++++++++++++++++++++++++--- 1 file changed, 379 insertions(+), 24 deletions(-) diff -puN drivers/net/wireless/airo.c~airo-wpa-support drivers/net/wireless/airo.c --- a/drivers/net/wireless/airo.c~airo-wpa-support +++ a/drivers/net/wireless/airo.c @@ -16,6 +16,7 @@ Code was also integrated from the Cisco Aironet driver for Linux. Support for MPI350 cards was added by Fabrice Bellet <fabrice@xxxxxxxxxxx>. + (C) 2005-2007 Matthieu CASTET <castet.matthieu@xxxxxxx> for WPA support ======================================================================*/ @@ -90,6 +91,12 @@ static struct pci_driver airo_driver = { #include <linux/delay.h> #endif +/* enable rx mic checking + *disable because it takes some time in ISR + * XXX crypto doesn't work anymore in ISR on 2.6.21 + */ +//#define WPA_CHECK_RX_MIC + /* Hack to do some power saving */ #define POWER_ON_DOWN @@ -222,6 +229,7 @@ static int maxencrypt /* = 0 */; /* The highest rate that the card can encrypt at. 0 means no limit. For old cards this was 4 */ +static int wpa_enabled; /* If set the card is in WPA mode. This is incompatible with WEP or open mode */ static int auto_wep /* = 0 */; /* If set, it tries to figure out the wep mode */ static int aux_bap /* = 0 */; /* Checks to see if the aux ports are needed to read the bap, needed on some older cards and buses. */ @@ -249,6 +257,9 @@ module_param(basic_rate, int, 0); module_param_array(rates, int, NULL, 0); module_param_array(ssids, charp, NULL, 0); module_param(auto_wep, int, 0); +module_param(wpa_enabled, int, 0); +MODULE_PARM_DESC(wpa_enabled, "If non-zero, the driver can use WPA \ +but Open and WEP mode won't be possible"); MODULE_PARM_DESC(auto_wep, "If non-zero, the driver will keep looping through \ the authentication options until an association is made. The value of \ auto_wep is number of the wep keys to check. A value of 2 will try using \ @@ -451,6 +462,7 @@ static int do8bitIO = 0; #define RID_UNKNOWN22 0xFF22 #define RID_LEAPUSERNAME 0xFF23 #define RID_LEAPPASSWORD 0xFF24 +#define RID_WPA 0xFF25 #define RID_STATUS 0xFF50 #define RID_BEACON_HST 0xFF51 #define RID_BUSY_HST 0xFF52 @@ -505,6 +517,14 @@ typedef struct { u8 key[16]; } WepKeyRid; +typedef struct { + u16 len; + u16 kindex; + u8 mac[ETH_ALEN]; + u16 klen; + u8 key[48]; +} WpaKeyRid; + /* These structures are from the Aironet's PC4500 Developers Manual */ typedef struct { u16 len; @@ -524,6 +544,19 @@ typedef struct { #define MOD_MOK 2 } ModulationRid; +/* Only present on firmware >= 5.30.17 */ +typedef struct { + u16 _reserved5[4]; + u16 auth_cipher; +#define AUTH_CIPHER_NONE 1 +#define AUTH_CIPHER_WEP 0xc +#define AUTH_CIPHER_TKIP 0x210 + u16 auth_key; +#define AUTH_KEY_MGMT_NONE 1 +#define AUTH_KEY_MGMT_802_1X 4 +#define AUTH_KEY_MGMT_PSK 8 +} ConfigRidExtra; + typedef struct { u16 len; /* sizeof(ConfigRid) */ u16 opmode; /* operating mode */ @@ -579,6 +612,7 @@ typedef struct { #define AUTH_ENCRYPT 0x101 #define AUTH_SHAREDKEY 0x102 #define AUTH_ALLOW_UNENCRYPTED 0x200 +#define AUTH_ENCRYPT_WPA 0xc101 u16 associationTimeout; u16 specifiedApTimeout; u16 offlineScanInterval; @@ -642,6 +676,8 @@ typedef struct { #define MAGIC_STAY_IN_CAM (1<<10) u8 magicControl; u16 autoWake; + /* Only present on firmware >= 5.30.17 */ + ConfigRidExtra extra; } ConfigRid; typedef struct { @@ -1227,6 +1263,15 @@ struct airo_info { unsigned int bssListFirst; unsigned int bssListNext; unsigned int bssListRidLen; + unsigned int ConfigRidLen; + unsigned char wpa_tx_key [8]; + unsigned char wpa_rx_key [8]; + unsigned char wpa_rx_key_m [8]; + unsigned char wpa_rx_key_m_old [8]; + u8 LLC [10]; + struct crypto_hash *tfm_michael; + int wpa_enabled; + int wpa_key_enabled; struct list_head network_list; struct list_head network_free_list; @@ -1723,6 +1768,55 @@ static void emmh32_final(emmh32_context digest[3] = val & 0xFF; } +static void wpa_compute_mic(struct airo_info *ai ,char *pPacket, u8 *mic, int len, char *key) +{ + struct scatterlist sg[3]; + struct hash_desc desc; + + sg[0].page = virt_to_page(pPacket); + sg[0].offset = offset_in_page(pPacket); + sg[0].length = sizeof(etherHead); + + + sg[1].page = virt_to_page(ai->LLC); + sg[1].offset = offset_in_page(ai->LLC); + sg[1].length = sizeof(ai->LLC); + + sg[2].page = virt_to_page(pPacket + sizeof(etherHead)); + sg[2].offset = offset_in_page(pPacket + sizeof(etherHead)); + sg[2].length = len - sizeof(etherHead); + + crypto_hash_setkey(ai->tfm_michael, key, 8); + + desc.tfm = ai->tfm_michael; + desc.flags = 0; + + crypto_hash_digest(&desc, sg, len + sizeof(ai->LLC), + mic); +} + +#ifdef WPA_CHECK_RX_MIC +static int wpa_check_rx_mic(struct airo_info *ai ,char *buffer, int len) +{ + u8 mic[8]; + /* multicast */ + if (buffer[0] & 1) { + wpa_compute_mic(ai, buffer, mic, len, ai->wpa_rx_key_m); + if (memcmp(mic, buffer + len, 8)) { + /* we don't know the current index, try the old one */ + wpa_compute_mic(ai, buffer, mic, len, ai->wpa_rx_key_m_old); + return memcmp(mic, buffer + len, 8); + } + } + else { + wpa_compute_mic(ai, buffer, mic, len, ai->wpa_rx_key); + return memcmp(mic, buffer + len, 8); + } + return 0; +} +#endif + + static int readBSSListRid(struct airo_info *ai, int first, BSSListRid *list) { int rc; @@ -1786,6 +1880,18 @@ static int writeWepKeyRid(struct airo_in return rc; } +static int writeWpaKeyRid(struct airo_info*ai, WpaKeyRid *pwkr, int lock) { + int rc; + WpaKeyRid wkr = *pwkr; + + wkr.len = cpu_to_le16(wkr.len); + wkr.kindex = cpu_to_le16(wkr.kindex); + wkr.klen = cpu_to_le16(wkr.klen); + rc = PC4500_writerid(ai, RID_WPA, &wkr, sizeof(wkr), lock); + if (rc!=SUCCESS) airo_print_err(ai->dev->name, "WPA set %x", rc); + return rc; +} + static int readSsidRid(struct airo_info*ai, SsidRid *ssidr) { int i; int rc = PC4500_readrid(ai, RID_SSID, ssidr, sizeof(*ssidr), 1); @@ -1816,7 +1922,7 @@ static int readConfigRid(struct airo_inf if (ai->config.len) return SUCCESS; - rc = PC4500_readrid(ai, RID_ACTUALCONFIG, &cfg, sizeof(cfg), lock); + rc = PC4500_readrid(ai, RID_ACTUALCONFIG, &cfg, ai->ConfigRidLen, lock); if (rc != SUCCESS) return rc; @@ -1879,7 +1985,7 @@ static int writeConfigRid(struct airo_in for(s = &cfgr.autoWake; s <= &cfgr.autoWake; s++) *s = cpu_to_le16(*s); - return PC4500_writerid( ai, RID_CONFIG, &cfgr, sizeof(cfgr), lock); + return PC4500_writerid( ai, RID_CONFIG, &cfgr, ai->ConfigRidLen, lock); } static int readStatusRid(struct airo_info*ai, StatusRid *statr, int lock) { int rc = PC4500_readrid(ai, RID_STATUS, statr, sizeof(*statr), lock); @@ -2040,7 +2146,20 @@ static int mpi_send_packet (struct net_d * Firmware automaticly puts 802 header on so * we don't need to account for it in the length */ - if (test_bit(FLAG_MIC_CAPABLE, &ai->flags) && ai->micstats.enabled && + if (ai->wpa_key_enabled) { + u8 mic [8]; + + *payloadLen = cpu_to_le16(len-sizeof(etherHead)+8); + ai->txfids[0].tx_desc.len += 8; + + wpa_compute_mic(ai, buffer, mic, len, ai->wpa_tx_key); + + dev->trans_start = jiffies; + /* copy data into airo dma buffer */ + memcpy(sendbuf, buffer, len); + memcpy(sendbuf + len, mic, 8); + } + else if (test_bit(FLAG_MIC_CAPABLE, &ai->flags) && ai->micstats.enabled && (ntohs(((u16 *)buffer)[6]) != 0x888E)) { MICBuffer pMic; @@ -2446,6 +2565,8 @@ void stop_airo_card( struct net_device * ai->shared, ai->shared_dma); } } + if (ai->tfm_michael) + crypto_free_hash(ai->tfm_michael); crypto_free_cipher(ai->tfm); del_airo_dev(ai); free_netdev( dev ); @@ -2779,6 +2900,7 @@ static int airo_test_wpa_capable(struct if ((cap_rid.softVer > 0x530) || ((cap_rid.softVer == 0x530) && (cap_rid.softSubVer >= 17))) { airo_print_info(name, "WPA is supported."); + airo_print_info(name, "Version 5.41 is recomended"); return 1; } @@ -2808,6 +2930,11 @@ static struct net_device *_init_airo_car } ai = dev->priv; + /* this is needed for initialisation, the firware check will be done + * latter. The windows driver, do it a different way : it reads + * ConfigRid.len . + */ + ai->ConfigRidLen = sizeof(ConfigRid) - sizeof(ConfigRidExtra); ai->wifidev = NULL; ai->flags = 0; ai->jobs = 0; @@ -2888,15 +3015,29 @@ static struct net_device *_init_airo_car } /* Test for WPA support */ - if (airo_test_wpa_capable(ai)) { + if (airo_test_wpa_capable(ai) && wpa_enabled) { + char LLC1 [] = {0, 0, 0, 0, 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; set_bit(FLAG_WPA_CAPABLE, &ai->flags); ai->bssListFirst = RID_WPA_BSSLISTFIRST; ai->bssListNext = RID_WPA_BSSLISTNEXT; ai->bssListRidLen = sizeof(BSSListRid); + ai->ConfigRidLen = sizeof(ConfigRid); + memcpy(ai->LLC, LLC1, sizeof(ai->LLC)); + ai->tfm_michael = crypto_alloc_hash("michael_mic", 0, CRYPTO_ALG_ASYNC); + if (ai->tfm_michael == NULL) { + printk(KERN_DEBUG "crypto API michael_mic failed. Removing WPA\n"); + } + else { + ai->wpa_enabled = 1; + /* we don't want to enable wep mode : it will make the firmware + * hanging */ + auto_wep = 0; + } } else { ai->bssListFirst = RID_BSSLISTFIRST; ai->bssListNext = RID_BSSLISTNEXT; ai->bssListRidLen = sizeof(BSSListRid) - sizeof(BSSListRidExtra); + ai->ConfigRidLen = sizeof(ConfigRid) - sizeof(ConfigRidExtra); } rc = register_netdev(dev); @@ -3199,7 +3340,9 @@ static irqreturn_t airo_interrupt ( int if ( status & EV_MIC ) { OUT4500( apriv, EVACK, EV_MIC ); - if (test_bit(FLAG_MIC_CAPABLE, &apriv->flags)) { + if (apriv->wpa_enabled) { + } + else if (test_bit(FLAG_MIC_CAPABLE, &apriv->flags)) { set_bit(JOB_MIC, &apriv->jobs); wake_up_interruptible(&apriv->thr_wait); } @@ -3243,6 +3386,8 @@ static irqreturn_t airo_interrupt ( int leaving BSS */ #define RC_NOAUTH 9 /* Station requesting (Re)Association is not Authenticated with the responding station */ + printk("status : %x\n", newStatus); + if (newStatus == FORCELOSS && apriv->scan_timeout > 0) scan_forceloss = 1; if(newStatus == ASSOCIATED || newStatus == REASSOCIATED) { @@ -3369,7 +3514,9 @@ static irqreturn_t airo_interrupt ( int } else { MICBuffer micbuf; bap_read (apriv, buffer, ETH_ALEN*2, BAP0); - if (apriv->micstats.enabled) { + if (apriv->wpa_key_enabled) { + } + else if (apriv->micstats.enabled) { bap_read (apriv,(u16*)&micbuf,sizeof(micbuf),BAP0); if (ntohs(micbuf.typelen) > 0x05DC) bap_setup (apriv, fid, 0x44, BAP0); @@ -3382,7 +3529,18 @@ static irqreturn_t airo_interrupt ( int } } bap_read(apriv,buffer+ETH_ALEN,len,BAP0); - if (decapsulate(apriv,&micbuf,(etherHead*)buffer,len)) { + if (apriv->wpa_key_enabled) { + len -= 8; + + //this is easy to do, but take some time in ISR +#ifdef WPA_CHECK_RX_MIC + if (wpa_check_rx_mic(apriv, skb->data, len + hdrlen)) + goto badmic; + +#endif + skb_trim (skb, len + hdrlen); + } + else if (decapsulate(apriv,&micbuf,(etherHead*)buffer,len)) { badmic: dev_kfree_skb_irq (skb); badrx: @@ -3611,7 +3769,9 @@ static void mpi_receive_802_3(struct air } buffer = skb_put(skb,len); memcpy(buffer, ai->rxfids[0].virtual_host_addr, ETH_ALEN * 2); - if (ai->micstats.enabled) { + if (ai->wpa_key_enabled) { + } + else if (ai->micstats.enabled) { memcpy(&micbuf, ai->rxfids[0].virtual_host_addr + ETH_ALEN * 2, sizeof(micbuf)); @@ -3626,7 +3786,17 @@ static void mpi_receive_802_3(struct air memcpy(buffer + ETH_ALEN * 2, ai->rxfids[0].virtual_host_addr + ETH_ALEN * 2 + off, len - ETH_ALEN * 2 - off); - if (decapsulate (ai, &micbuf, (etherHead*)buffer, len - off - ETH_ALEN * 2)) { + if (ai->wpa_key_enabled) { + len -= 8; + +#ifdef WPA_CHECK_RX_MIC + if (wpa_check_rx_mic(ai, buffer, len)) + goto badmic; +#endif + + skb_trim (skb, len); + } + else if (decapsulate (ai, &micbuf, (etherHead*)buffer, len - off - ETH_ALEN * 2)) { badmic: dev_kfree_skb_irq (skb); goto badrx; @@ -4325,7 +4495,10 @@ static int transmit_802_3_packet(struct } len -= ETH_ALEN * 2; - if (test_bit(FLAG_MIC_CAPABLE, &ai->flags) && ai->micstats.enabled && + if (ai->wpa_key_enabled) { + miclen = 8; + } + else if (test_bit(FLAG_MIC_CAPABLE, &ai->flags) && ai->micstats.enabled && (ntohs(((u16 *)pPacket)[6]) != 0x888E)) { if (encapsulate(ai,(etherHead *)pPacket,&pMic,len) != SUCCESS) return ERROR; @@ -4339,9 +4512,27 @@ static int transmit_802_3_packet(struct payloadLen = cpu_to_le16(len + miclen); bap_write(ai, &payloadLen, sizeof(payloadLen),BAP1); bap_write(ai, (const u16*)pPacket, sizeof(etherHead), BAP1); - if (miclen) - bap_write(ai, (const u16*)&pMic, miclen, BAP1); - bap_write(ai, (const u16*)(pPacket + sizeof(etherHead)), len, BAP1); + if (ai->wpa_key_enabled) { + u8 mic[8]; + + wpa_compute_mic(ai, pPacket, mic, len + sizeof(etherHead), ai->wpa_tx_key); + //XXX ugly hack because we write per 16 bits packet + bap_write(ai, (const u16*)(pPacket + sizeof(etherHead)), len - (len&1), BAP1); + if (len&1) { + u8 tmp [2]; + tmp [0] = pPacket [sizeof(etherHead) + len-1]; + tmp [1] = mic[0]; + bap_write(ai, (const u16*)tmp, 2, BAP1); + bap_write(ai, (const u16*)(mic+1), sizeof(mic)-1, BAP1); + } + else + bap_write(ai, (const u16*)mic, sizeof(mic), BAP1); + } + else { + if (miclen) + bap_write(ai, (const u16*)&pMic, miclen, BAP1); + bap_write(ai, (const u16*)(pPacket + sizeof(etherHead)), len, BAP1); + } // issue the transmit command memset( &cmd, 0, sizeof( cmd ) ); cmd.cmd = CMD_TRANSMIT; @@ -6354,6 +6545,10 @@ static int airo_set_encode(struct net_de int perm = ( dwrq->flags & IW_ENCODE_TEMP ? 0 : 1 ); u16 currentAuthType = local->config.authType; + /* In wpa mode, only wpa is allowed */ + if (local->wpa_enabled) + return -EINVAL; + /* Is WEP supported ? */ readCapabilityRid(local, &cap_rid, 1); /* Older firmware doesn't support this... @@ -6449,6 +6644,7 @@ static int airo_get_encode(struct net_de readConfigRid(local, 1); /* Check encryption mode */ switch(local->config.authType) { + case AUTH_ENCRYPT_WPA: case AUTH_ENCRYPT: dwrq->flags = IW_ENCODE_OPEN; break; @@ -6480,6 +6676,85 @@ static int airo_get_encode(struct net_de /* * Wireless Handler : set extended Encryption parameters */ +static int airo_set_encodeext_wpa(struct airo_info *local, + struct iw_encode_ext *ext, + struct iw_point *encoding) +{ + static const unsigned char macaddr[ETH_ALEN] = { 0x01, 0, 0, 0, 0, 0 }; + WpaKeyRid wkr; + int index = (encoding->flags & IW_ENCODE_INDEX) - 1; + + printk("set wpa : %d %d %d %x\n", ext->alg, ext->key_len, index, ext->ext_flags); + + memset(&wkr, 0, sizeof(wkr)); + wkr.len = sizeof(wkr); + + if ((encoding->flags & IW_ENCODE_DISABLED) || + ext->alg == IW_ENCODE_ALG_NONE || ext->key_len == 0) { + wkr.kindex = index; + memcpy( wkr.mac, macaddr, ETH_ALEN ); + printk(KERN_INFO "Wpa Removing key %d\n", index); + memset(local->wpa_tx_key, 0, 8); + memset(local->wpa_rx_key, 0, 8); + memset(local->wpa_rx_key_m, 0, 8); + memset(local->wpa_rx_key_m_old, 0, 8); + local->wpa_key_enabled = 0; + } + else if (ext->alg == IW_ENCODE_ALG_WEP) + return -EOPNOTSUPP; + else if (ext->alg == IW_ENCODE_ALG_TKIP && ext->key_len == 32) { + // we cannot set a WPA key in a non-WPA mode + if (local->config.authType != AUTH_ENCRYPT_WPA) + return -EINVAL; + wkr.kindex = index; + memcpy( wkr.mac, macaddr, ETH_ALEN ); + wkr.klen = 0x30; + + /* firmware use ndis order + a hole at 16-21 */ + memcpy(wkr.key, ext->key, 16); /* temporal key */ + memcpy(wkr.key + 40, ext->key + 16, 8); /*TX*/ + memcpy(wkr.key + 32, ext->key + 24, 8); /*RX*/ + + if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) { + memcpy(wkr.key + 22, ext->rx_seq, 6); + } + + if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { + memcpy(local->wpa_rx_key_m_old, local->wpa_rx_key_m, 8); + memcpy(local->wpa_rx_key_m, ext->key+16, 8); + } + else { + memcpy(local->wpa_tx_key, ext->key+16, 8); + memcpy(local->wpa_rx_key, ext->key+24, 8); + } + } + else + return -EINVAL; + + + + if (down_interruptible(&local->sem)) + return ERROR; + + writeWpaKeyRid(local, &wkr, 0); + + if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { + memset(&wkr, 0, sizeof(wkr)); + wkr.len = sizeof(wkr); + wkr.kindex = 0xffff; + wkr.mac[0] = (char)index; + wkr.klen = 0x30; + + printk(KERN_INFO "Setting default tx key to %d\n", index); + writeWpaKeyRid(local, &wkr, 0); + + local->wpa_key_enabled = 1; + } + + up(&local->sem); + return 0; +} + static int airo_set_encodeext(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, @@ -6502,6 +6777,8 @@ static int airo_set_encodeext(struct net } */ readConfigRid(local, 1); + if (local->wpa_enabled) + return airo_set_encodeext_wpa(local, ext, encoding); /* Determine and validate the key index */ idx = encoding->flags & IW_ENCODE_INDEX; if (idx) { @@ -6576,6 +6853,7 @@ static int airo_get_encodeext(struct net struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; CapabilityRid cap_rid; /* Card capability info */ int idx, max_key_len; + printk("get_encode\n"); /* Is it supported ? */ readCapabilityRid(local, &cap_rid, 1); @@ -6601,6 +6879,7 @@ static int airo_get_encodeext(struct net /* Check encryption mode */ switch(local->config.authType) { + case AUTH_ENCRYPT_WPA: case AUTH_ENCRYPT: encoding->flags = IW_ENCODE_ALG_WEP | IW_ENCODE_ENABLED; break; @@ -6626,6 +6905,20 @@ static int airo_get_encodeext(struct net } +static void wpa_off(struct airo_info *local) +{ + printk(KERN_INFO"WPA dis\n"); + local->config.authType=AUTH_OPEN; + local->config.extra.auth_key=AUTH_KEY_MGMT_NONE; +} + +static void wpa_on(struct airo_info *local) +{ + printk(KERN_INFO"WPA enable\n"); + local->config.authType=AUTH_ENCRYPT_WPA; + local->config.extra.auth_cipher=AUTH_CIPHER_TKIP; + //local->config.extra._reserved5[0]=0x40; +} /*------------------------------------------------------------------*/ /* * Wireless Handler : set extended authentication parameters @@ -6640,17 +6933,55 @@ static int airo_set_auth(struct net_devi switch (param->flags & IW_AUTH_INDEX) { case IW_AUTH_WPA_VERSION: + if (param->value == IW_AUTH_WPA_VERSION_WPA) + wpa_on(local); + else if (param->value == IW_AUTH_WPA_VERSION_DISABLED) + wpa_off(local); + else + return -EINVAL; + break; case IW_AUTH_CIPHER_PAIRWISE: case IW_AUTH_CIPHER_GROUP: + if ((param->value == IW_AUTH_CIPHER_TKIP) && (local->config.authType == AUTH_ENCRYPT_WPA)) + return 0; + else if (((param->value == IW_AUTH_CIPHER_WEP40) ||(param->value == IW_AUTH_CIPHER_WEP104)) + && (local->config.authType != AUTH_ENCRYPT_WPA)) + return 0; + else if ((param->value == IW_AUTH_CIPHER_NONE) && (local->config.authType != AUTH_ENCRYPT_WPA)) + local->config.authType = AUTH_OPEN; + else + return -EINVAL; + break; case IW_AUTH_KEY_MGMT: - case IW_AUTH_RX_UNENCRYPTED_EAPOL: + if (local->config.authType != AUTH_ENCRYPT_WPA) + return -EINVAL; + if (param->value == IW_AUTH_KEY_MGMT_802_1X) + local->config.extra.auth_key=AUTH_KEY_MGMT_802_1X; + else if (param->value == IW_AUTH_KEY_MGMT_PSK) + local->config.extra.auth_key=AUTH_KEY_MGMT_PSK; + else + return -EINVAL; + break; case IW_AUTH_PRIVACY_INVOKED: + if (!param->value) { + if (local->config.authType == AUTH_ENCRYPT_WPA) + wpa_off(local); + else + wpa_on(local); + } + else + return 0; + break; + case IW_AUTH_RX_UNENCRYPTED_EAPOL: + case IW_AUTH_TKIP_COUNTERMEASURES: /* * airo does not use these parameters */ break; case IW_AUTH_DROP_UNENCRYPTED: + if (local->wpa_enabled) + break; if (param->value) { /* Only change auth type if unencrypted */ if (currentAuthType == AUTH_OPEN) @@ -6659,15 +6990,16 @@ static int airo_set_auth(struct net_devi local->config.authType = AUTH_OPEN; } - /* Commit the changes to flags if needed */ - if (local->config.authType != currentAuthType) - set_bit (FLAG_COMMIT, &local->flags); break; case IW_AUTH_80211_AUTH_ALG: { /* FIXME: What about AUTH_OPEN? This API seems to * disallow setting our auth to AUTH_OPEN. */ + /* does not make sense with WPA */ + if (local->config.authType == AUTH_ENCRYPT_WPA) + return 0; + if (param->value & IW_AUTH_ALG_SHARED_KEY) { local->config.authType = AUTH_SHAREDKEY; } else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) { @@ -6675,21 +7007,20 @@ static int airo_set_auth(struct net_devi } else return -EINVAL; break; - - /* Commit the changes to flags if needed */ - if (local->config.authType != currentAuthType) - set_bit (FLAG_COMMIT, &local->flags); } case IW_AUTH_WPA_ENABLED: - /* Silently accept disable of WPA */ - if (param->value > 0) - return -EOPNOTSUPP; + if (param->value == 0) + wpa_off(local); + else + wpa_on(local); break; default: return -EOPNOTSUPP; } + + set_bit (FLAG_COMMIT, &local->flags); return -EINPROGRESS; } @@ -6741,6 +7072,29 @@ static int airo_get_auth(struct net_devi return 0; } +static int airo_disasociate(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *extra) +{ + struct airo_info *local = dev->priv; + Resp rsp; + SsidRid SSID_rid; /* SSIDs */ + + /* reset the list */ + memset(&SSID_rid, 0, sizeof(SSID_rid)); + + /* Set the SSID */ + strcpy(SSID_rid.ssids[0].ssid, "tsunami"); + SSID_rid.ssids[0].len = 7; + SSID_rid.len = sizeof(SSID_rid); + /* Write it to the card */ + disable_MAC(local, 1); + writeSsidRid(local, &SSID_rid, 1); + enable_MAC(local, &rsp, 1); + + return 0; +} + /*------------------------------------------------------------------*/ /* @@ -7558,6 +7912,7 @@ static const iw_handler airo_handler[] (iw_handler) airo_set_encodeext, /* SIOCSIWENCODEEXT */ (iw_handler) airo_get_encodeext, /* SIOCGIWENCODEEXT */ (iw_handler) NULL, /* SIOCSIWPMKSA */ + [SIOCSIWMLME-SIOCSIWCOMMIT] = (iw_handler) airo_disasociate, }; /* Note : don't describe AIROIDIFC and AIROOLDIDIFC in here. _ Patches currently in -mm which might be from castet.matthieu@xxxxxxx are origin.patch tuner-simplec-add-suport-for-secam-bg-with-fi1216mf.patch airo-wpa-support.patch - To unsubscribe from this list: send the line "unsubscribe mm-commits" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html