diff options
Diffstat (limited to 'drivers/staging/wlags49_h2/wl_wext.c')
-rw-r--r-- | drivers/staging/wlags49_h2/wl_wext.c | 1184 |
1 files changed, 524 insertions, 660 deletions
diff --git a/drivers/staging/wlags49_h2/wl_wext.c b/drivers/staging/wlags49_h2/wl_wext.c index 522a310..8ac5e10 100644 --- a/drivers/staging/wlags49_h2/wl_wext.c +++ b/drivers/staging/wlags49_h2/wl_wext.c @@ -75,20 +75,6 @@ #include <wl_wext.h> #include <wl_priv.h> - - -/* If WIRELESS_EXT is not defined (as a result of HAS_WIRELESS_EXTENSIONS - #including linux/wireless.h), then these functions do not need to be included - in the build. */ -#ifdef WIRELESS_EXT - -#define IWE_STREAM_ADD_EVENT(info, buf, end, iwe, len) \ - iwe_stream_add_event(info, buf, end, iwe, len) -#define IWE_STREAM_ADD_POINT(info, buf, end, iwe, msg) \ - iwe_stream_add_point(info, buf, end, iwe, msg) - - - /******************************************************************************* * global definitions ******************************************************************************/ @@ -97,7 +83,223 @@ extern dbg_info_t *DbgInfo; #endif // DBG +/* Set up the LTV to program the appropriate key */ +static int hermes_set_tkip_keys(ltv_t *ltv, u16 key_idx, u8 *addr, + int set_tx, u8 *seq, u8 *key, size_t key_len) +{ + int ret = -EINVAL; + int buf_idx = 0; + hcf_8 tsc[IW_ENCODE_SEQ_MAX_SIZE] = + { 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00 }; + + DBG_ENTER(DbgInfo); + + /* + * Check the key index here; if 0, load as Pairwise Key, otherwise, + * load as a group key. Note that for the Hermes, the RIDs for + * group/pairwise keys are different from each other and different + * than the default WEP keys as well. + */ + switch (key_idx) { + case 0: + ltv->len = 28; + ltv->typ = CFG_ADD_TKIP_MAPPED_KEY; + + /* Load the BSSID */ + memcpy(<v->u.u8[buf_idx], addr, ETH_ALEN); + buf_idx += ETH_ALEN; + + /* Load the TKIP key */ + memcpy(<v->u.u8[buf_idx], &key[0], 16); + buf_idx += 16; + + /* Load the TSC */ + memcpy(<v->u.u8[buf_idx], tsc, IW_ENCODE_SEQ_MAX_SIZE); + buf_idx += IW_ENCODE_SEQ_MAX_SIZE; + + /* Load the RSC */ + memcpy(<v->u.u8[buf_idx], seq, IW_ENCODE_SEQ_MAX_SIZE); + buf_idx += IW_ENCODE_SEQ_MAX_SIZE; + + /* Load the TxMIC key */ + memcpy(<v->u.u8[buf_idx], &key[16], 8); + buf_idx += 8; + + /* Load the RxMIC key */ + memcpy(<v->u.u8[buf_idx], &key[24], 8); + + ret = 0; + break; + case 1: + case 2: + case 3: + ltv->len = 26; + ltv->typ = CFG_ADD_TKIP_DEFAULT_KEY; + + /* Load the key Index */ + + /* If this is a Tx Key, set bit 8000 */ + if (set_tx) + key_idx |= 0x8000; + ltv->u.u16[buf_idx] = cpu_to_le16(key_idx); + buf_idx += 2; + + /* Load the RSC */ + memcpy(<v->u.u8[buf_idx], seq, IW_ENCODE_SEQ_MAX_SIZE); + buf_idx += IW_ENCODE_SEQ_MAX_SIZE; + + /* Load the TKIP, TxMIC, and RxMIC keys in one shot, because in + CFG_ADD_TKIP_DEFAULT_KEY they are back-to-back */ + memcpy(<v->u.u8[buf_idx], key, key_len); + buf_idx += key_len; + + /* Load the TSC */ + memcpy(<v->u.u8[buf_idx], tsc, IW_ENCODE_SEQ_MAX_SIZE); + + ret = 0; + break; + default: + break; + } + + DBG_LEAVE(DbgInfo); + return ret; +} + +/* Set up the LTV to clear the appropriate key */ +static int hermes_clear_tkip_keys(ltv_t *ltv, u16 key_idx, u8 *addr) +{ + int ret; + + switch (key_idx) { + case 0: + if (memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) != 0) { + ltv->len = 7; + ltv->typ = CFG_REMOVE_TKIP_MAPPED_KEY; + memcpy(<v->u.u8[0], addr, ETH_ALEN); + ret = 0; + } + break; + case 1: + case 2: + case 3: + /* Clear the Group TKIP keys by index */ + ltv->len = 2; + ltv->typ = CFG_REMOVE_TKIP_DEFAULT_KEY; + ltv->u.u16[0] = cpu_to_le16(key_idx); + + ret = 0; + break; + default: + break; + } + + return ret; +} + +/* Set the WEP keys in the wl_private structure */ +static int hermes_set_wep_keys(struct wl_private *lp, u16 key_idx, + u8 *key, size_t key_len, + bool enable, bool set_tx) +{ + hcf_8 encryption_state = lp->EnableEncryption; + int tk = lp->TransmitKeyID - 1; /* current key */ + int ret = 0; + + /* Is encryption supported? */ + if (!wl_has_wep(&(lp->hcfCtx))) { + DBG_WARNING(DbgInfo, "WEP not supported on this device\n"); + ret = -EOPNOTSUPP; + goto out; + } + DBG_NOTICE(DbgInfo, "pointer: %p, length: %d\n", + key, key_len); + + /* Check the size of the key */ + switch (key_len) { + case MIN_KEY_SIZE: + case MAX_KEY_SIZE: + + /* Check the index */ + if ((key_idx < 0) || (key_idx >= MAX_KEYS)) + key_idx = tk; + + /* Cleanup */ + memset(lp->DefaultKeys.key[key_idx].key, 0, MAX_KEY_SIZE); + + /* Copy the key in the driver */ + memcpy(lp->DefaultKeys.key[key_idx].key, key, key_len); + + /* Set the length */ + lp->DefaultKeys.key[key_idx].len = key_len; + + DBG_NOTICE(DbgInfo, "encoding.length: %d\n", key_len); + DBG_NOTICE(DbgInfo, "set key: %s(%d) [%d]\n", + lp->DefaultKeys.key[key_idx].key, + lp->DefaultKeys.key[key_idx].len, key_idx); + + /* Enable WEP (if possible) */ + if ((key_idx == tk) && (lp->DefaultKeys.key[tk].len > 0)) + lp->EnableEncryption = 1; + + break; + + case 0: + /* Do we want to just set the current transmit key? */ + if (set_tx && (key_idx >= 0) && (key_idx < MAX_KEYS)) { + DBG_NOTICE(DbgInfo, "index: %d; len: %d\n", key_idx, + lp->DefaultKeys.key[key_idx].len); + + if (lp->DefaultKeys.key[key_idx].len > 0) { + lp->TransmitKeyID = key_idx + 1; + lp->EnableEncryption = 1; + } else { + DBG_WARNING(DbgInfo, "Problem setting the current TxKey\n"); + ret = -EINVAL; + } + } + break; + + default: + DBG_WARNING(DbgInfo, "Invalid Key length\n"); + ret = -EINVAL; + goto out; + } + + /* Read the flags */ + if (enable) { + lp->EnableEncryption = 1; + lp->wext_enc = IW_ENCODE_ALG_WEP; + } else { + lp->EnableEncryption = 0; /* disable encryption */ + lp->wext_enc = IW_ENCODE_ALG_NONE; + } + + DBG_TRACE(DbgInfo, "encryption_state : %d\n", encryption_state); + DBG_TRACE(DbgInfo, "lp->EnableEncryption : %d\n", lp->EnableEncryption); + DBG_TRACE(DbgInfo, "erq->length : %d\n", key_len); + + /* Write the changes to the card */ + if (ret == 0) { + DBG_NOTICE(DbgInfo, "encrypt: %d, ID: %d\n", lp->EnableEncryption, + lp->TransmitKeyID); + + if (lp->EnableEncryption == encryption_state) { + if (key_len != 0) { + /* Dynamic WEP key update */ + wl_set_wep_keys(lp); + } + } else { + /* To switch encryption on/off, soft reset is + * required */ + wl_apply(lp); + } + } + +out: + return ret; +} /******************************************************************************* * wireless_commit() @@ -324,16 +526,8 @@ static int wireless_get_frequency(struct net_device *dev, struct iw_request_info if( ret == HCF_SUCCESS ) { hcf_16 channel = CNV_LITTLE_TO_INT( lp->ltvRecord.u.u16[0] ); -#ifdef USE_FREQUENCY - freq->m = wl_get_freq_from_chan( channel ) * 100000; freq->e = 1; -#else - - freq->m = channel; - freq->e = 0; - -#endif /* USE_FREQUENCY */ } wl_act_int_on( lp ); @@ -460,8 +654,6 @@ retry: /* Link quality */ -#ifdef USE_DBM - range->max_qual.qual = (u_char)HCF_MAX_COMM_QUALITY; /* If the value returned in /proc/net/wireless is greater than the maximum range, @@ -470,13 +662,6 @@ retry: range->max_qual.level = (u_char)( dbm( HCF_MIN_SIGNAL_LEVEL ) - 1 ); range->max_qual.noise = (u_char)( dbm( HCF_MIN_NOISE_LEVEL ) - 1 ); -#else - - range->max_qual.qual = 100; - range->max_qual.level = 100; - range->max_qual.noise = 100; - -#endif /* USE_DBM */ /* Set available rates */ @@ -508,8 +693,6 @@ retry: /* Encryption */ -#if WIRELESS_EXT > 8 - /* Holding the lock too long, make a gap to allow other processes */ wl_unlock(lp, &flags); wl_lock( lp, &flags ); @@ -526,26 +709,17 @@ retry: range->max_encoding_tokens = MAX_KEYS; } -#endif /* WIRELESS_EXT > 8 */ - /* Tx Power Info */ range->txpower_capa = IW_TXPOW_MWATT; range->num_txpower = 1; range->txpower[0] = RADIO_TX_POWER_MWATT; -#if WIRELESS_EXT > 10 - /* Wireless Extension Info */ range->we_version_compiled = WIRELESS_EXT; range->we_version_source = WIRELESS_SUPPORT; // Retry Limits and Lifetime - NOT SUPPORTED -#endif - - -#if WIRELESS_EXT > 11 - /* Holding the lock too long, make a gap to allow other processes */ wl_unlock(lp, &flags); wl_lock( lp, &flags ); @@ -555,18 +729,18 @@ retry: range->avg_qual = lp->wstats.qual; DBG_TRACE( DbgInfo, "wl_wireless_stats done\n" ); -#endif - /* Event capability (kernel + driver) */ - range->event_capa[0] = (IW_EVENT_CAPA_K_0 | - IW_EVENT_CAPA_MASK(SIOCGIWAP) | - IW_EVENT_CAPA_MASK(SIOCGIWSCAN)); - range->event_capa[1] = IW_EVENT_CAPA_K_1; - range->event_capa[4] = (IW_EVENT_CAPA_MASK(IWEVREGISTERED) | - IW_EVENT_CAPA_MASK(IWEVCUSTOM) | - IW_EVENT_CAPA_MASK(IWEVEXPIRED)); + IW_EVENT_CAPA_SET_KERNEL(range->event_capa); + IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP); + IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN); + IW_EVENT_CAPA_SET(range->event_capa, IWEVREGISTERED); + IW_EVENT_CAPA_SET(range->event_capa, IWEVEXPIRED); + IW_EVENT_CAPA_SET(range->event_capa, IWEVMICHAELMICFAILURE); + IW_EVENT_CAPA_SET(range->event_capa, IWEVASSOCREQIE); + IW_EVENT_CAPA_SET(range->event_capa, IWEVASSOCRESPIE); range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_CIPHER_TKIP; + range->scan_capa = IW_SCAN_CAPA_NONE; out_unlock: wl_act_int_on( lp ); @@ -1075,9 +1249,6 @@ static int wireless_get_essid(struct net_device *dev, struct iw_request_info *in /* Copy the information into the user buffer */ data->length = pName->length; - /* NOTE: Null terminating is necessary for proper display of the SSID in - the wireless tools */ - data->length = pName->length + 1; if( pName->length < HCF_MAX_NAME_LEN ) { pName->name[pName->length] = '\0'; } @@ -1087,7 +1258,6 @@ static int wireless_get_essid(struct net_device *dev, struct iw_request_info *in #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA //;?should we return an error status in AP mode -#ifdef RETURN_CURRENT_NETWORKNAME /* if desired is null ("any"), return current or "any" */ if( pName->name[0] == '\0' ) { @@ -1104,11 +1274,7 @@ static int wireless_get_essid(struct net_device *dev, struct iw_request_info *in pName->length = CNV_LITTLE_TO_INT( pName->length ); /* Copy the information into the user buffer */ - data->length = pName->length + 1; - if( pName->length < HCF_MAX_NAME_LEN ) { - pName->name[pName->length] = '\0'; - } - + data->length = pName->length; data->flags = 1; } else { ret = -EFAULT; @@ -1116,11 +1282,8 @@ static int wireless_get_essid(struct net_device *dev, struct iw_request_info *in } } -#endif // RETURN_CURRENT_NETWORKNAME #endif // HCF_STA - data->length--; - if (pName->length > IW_ESSID_MAX_SIZE) { ret = -EFAULT; goto out_unlock; @@ -1169,156 +1332,39 @@ static int wireless_set_encode(struct net_device *dev, struct iw_request_info *i { struct wl_private *lp = wl_priv(dev); unsigned long flags; - int ret = 0; - -#if 1 //;? #if WIRELESS_EXT > 8 - used unconditionally in the rest of the code... - hcf_8 encryption_state; -#endif // WIRELESS_EXT > 8 - /*------------------------------------------------------------------------*/ - + int key_idx = (erq->flags & IW_ENCODE_INDEX) - 1; + int ret = 0; + bool enable = true; - DBG_FUNC( "wireless_set_encode" ); - DBG_ENTER( DbgInfo ); + DBG_ENTER(DbgInfo); - if(lp->portState == WVLAN_PORT_STATE_DISABLED) { + if (lp->portState == WVLAN_PORT_STATE_DISABLED) { ret = -EBUSY; goto out; } - wl_lock( lp, &flags ); - - wl_act_int_off( lp ); - - /* Is encryption supported? */ - if( !wl_has_wep( &( lp->hcfCtx ))) { - DBG_WARNING( DbgInfo, "WEP not supported on this device\n" ); - ret = -EOPNOTSUPP; - goto out_unlock; - } - - DBG_NOTICE( DbgInfo, "pointer: %p, length: %d, flags: %#x\n", - keybuf, erq->length, - erq->flags); - - /* Save state of Encryption switch */ - encryption_state = lp->EnableEncryption; - - /* Basic checking: do we have a key to set? */ - if((erq->length) != 0) { - int index = ( erq->flags & IW_ENCODE_INDEX ) - 1; - int tk = lp->TransmitKeyID - 1; // current key - - - /* Check the size of the key */ - switch(erq->length) { - case 0: - break; - - case MIN_KEY_SIZE: - case MAX_KEY_SIZE: - - /* Check the index */ - if(( index < 0 ) || ( index >= MAX_KEYS )) { - index = tk; - } - - /* Cleanup */ - memset( lp->DefaultKeys.key[index].key, 0, MAX_KEY_SIZE ); - - /* Copy the key in the driver */ - memcpy( lp->DefaultKeys.key[index].key, keybuf, erq->length); - - /* Set the length */ - lp->DefaultKeys.key[index].len = erq->length; - - DBG_NOTICE( DbgInfo, "encoding.length: %d\n", erq->length ); - DBG_NOTICE( DbgInfo, "set key: %s(%d) [%d]\n", lp->DefaultKeys.key[index].key, - lp->DefaultKeys.key[index].len, index ); - - /* Enable WEP (if possible) */ - if(( index == tk ) && ( lp->DefaultKeys.key[tk].len > 0 )) { - lp->EnableEncryption = 1; - } - - break; - - default: - DBG_WARNING( DbgInfo, "Invalid Key length\n" ); - ret = -EINVAL; - goto out_unlock; - } - } else { - int index = ( erq->flags & IW_ENCODE_INDEX ) - 1; - - - /* Do we want to just set the current transmit key? */ - if(( index >= 0 ) && ( index < MAX_KEYS )) { - DBG_NOTICE( DbgInfo, "index: %d; len: %d\n", index, - lp->DefaultKeys.key[index].len ); - - if( lp->DefaultKeys.key[index].len > 0 ) { - lp->TransmitKeyID = index + 1; - lp->EnableEncryption = 1; - } else { - DBG_WARNING( DbgInfo, "Problem setting the current TxKey\n" ); - DBG_LEAVE( DbgInfo ); - ret = -EINVAL; - } - } - } - - /* Read the flags */ - if( erq->flags & IW_ENCODE_DISABLED ) { - lp->EnableEncryption = 0; // disable encryption - } else { - lp->EnableEncryption = 1; - } - - if( erq->flags & IW_ENCODE_RESTRICTED ) { - DBG_WARNING( DbgInfo, "IW_ENCODE_RESTRICTED invalid\n" ); - ret = -EINVAL; // Invalid - } + if (erq->flags & IW_ENCODE_DISABLED) + enable = false; - DBG_TRACE( DbgInfo, "encryption_state : %d\n", encryption_state ); - DBG_TRACE( DbgInfo, "lp->EnableEncryption : %d\n", lp->EnableEncryption ); - DBG_TRACE( DbgInfo, "erq->length : %d\n", - erq->length); - DBG_TRACE( DbgInfo, "erq->flags : 0x%x\n", - erq->flags); + wl_lock(lp, &flags); - /* Write the changes to the card */ - if( ret == 0 ) { - DBG_NOTICE( DbgInfo, "encrypt: %d, ID: %d\n", lp->EnableEncryption, - lp->TransmitKeyID ); + wl_act_int_off(lp); - if( lp->EnableEncryption == encryption_state ) { - if( erq->length != 0 ) { - /* Dynamic WEP key update */ - wl_set_wep_keys( lp ); - } - } else { - /* To switch encryption on/off, soft reset is required */ - wl_apply( lp ); - } - } + ret = hermes_set_wep_keys(lp, key_idx, keybuf, erq->length, + enable, true); /* Send an event that Encryption has been set */ - wl_wext_event_encode( dev ); - -out_unlock: + if (ret == 0) + wl_wext_event_encode(dev); - wl_act_int_on( lp ); + wl_act_int_on(lp); wl_unlock(lp, &flags); out: - DBG_LEAVE( DbgInfo ); + DBG_LEAVE(DbgInfo); return ret; -} // wireless_set_encode -/*============================================================================*/ - - - +} /******************************************************************************* * wireless_get_encode() @@ -2023,11 +2069,9 @@ static int wireless_set_rts_threshold (struct net_device *dev, struct iw_request goto out; } -#if WIRELESS_EXT > 8 if( rts->disabled ) { rthr = 2347; } -#endif /* WIRELESS_EXT > 8 */ if(( rthr < 256 ) || ( rthr > 2347 )) { ret = -EINVAL; @@ -2095,12 +2139,8 @@ static int wireless_get_rts_threshold (struct net_device *dev, struct iw_request rts->value = lp->RTSThreshold; -#if WIRELESS_EXT > 8 - rts->disabled = ( rts->value == 2347 ); -#endif /* WIRELESS_EXT > 8 */ - rts->fixed = 1; wl_act_int_on( lp ); @@ -2527,8 +2567,6 @@ out: -#if WIRELESS_EXT > 13 - /******************************************************************************* * wireless_set_scan() ******************************************************************************* @@ -2737,8 +2775,8 @@ static int wireless_get_scan(struct net_device *dev, struct iw_request_info *inf memcpy( iwe.u.ap_addr.sa_data, probe_resp->BSSID, ETH_ALEN); iwe.len = IW_EV_ADDR_LEN; - buf = IWE_STREAM_ADD_EVENT(info, buf, buf_end, &iwe, IW_EV_ADDR_LEN); - + buf = iwe_stream_add_event(info, buf, buf_end, + &iwe, IW_EV_ADDR_LEN); /* Use the mode to indicate if it's a station or AP */ /* Won't always be an AP if in IBSS mode */ @@ -2754,8 +2792,8 @@ static int wireless_get_scan(struct net_device *dev, struct iw_request_info *inf iwe.len = IW_EV_UINT_LEN; - buf = IWE_STREAM_ADD_EVENT(info, buf, buf_end, &iwe, IW_EV_UINT_LEN); - + buf = iwe_stream_add_event(info, buf, buf_end, + &iwe, IW_EV_UINT_LEN); /* Any quality information */ memset(&iwe, 0, sizeof(iwe)); @@ -2767,7 +2805,8 @@ static int wireless_get_scan(struct net_device *dev, struct iw_request_info *inf iwe.u.qual.updated = lp->probe_results.scan_complete | IW_QUAL_DBM; iwe.len = IW_EV_QUAL_LEN; - buf = IWE_STREAM_ADD_EVENT(info, buf, buf_end, &iwe, IW_EV_QUAL_LEN); + buf = iwe_stream_add_event(info, buf, buf_end, + &iwe, IW_EV_QUAL_LEN); /* ESSID information */ @@ -2778,7 +2817,8 @@ static int wireless_get_scan(struct net_device *dev, struct iw_request_info *inf iwe.u.data.length = probe_resp->rawData[1]; iwe.u.data.flags = 1; - buf = IWE_STREAM_ADD_POINT(info, buf, buf_end, &iwe, &probe_resp->rawData[2]); + buf = iwe_stream_add_point(info, buf, buf_end, + &iwe, &probe_resp->rawData[2]); } @@ -2796,7 +2836,7 @@ static int wireless_get_scan(struct net_device *dev, struct iw_request_info *inf iwe.u.data.flags |= IW_ENCODE_DISABLED; } - buf = IWE_STREAM_ADD_POINT(info, buf, buf_end, &iwe, NULL); + buf = iwe_stream_add_point(info, buf, buf_end, &iwe, NULL); /* Frequency Info */ @@ -2807,10 +2847,10 @@ static int wireless_get_scan(struct net_device *dev, struct iw_request_info *inf iwe.u.freq.m = wl_parse_ds_ie( probe_resp ); iwe.u.freq.e = 0; - buf = IWE_STREAM_ADD_EVENT(info, buf, buf_end, &iwe, IW_EV_FREQ_LEN); + buf = iwe_stream_add_event(info, buf, buf_end, + &iwe, IW_EV_FREQ_LEN); -#if WIRELESS_EXT > 14 /* Custom info (Beacon Interval) */ memset( &iwe, 0, sizeof( iwe )); memset( msg, 0, sizeof( msg )); @@ -2819,27 +2859,25 @@ static int wireless_get_scan(struct net_device *dev, struct iw_request_info *inf sprintf( msg, "beacon_interval=%d", probe_resp->beaconInterval ); iwe.u.data.length = strlen( msg ); - buf = IWE_STREAM_ADD_POINT(info, buf, buf_end, &iwe, msg); + buf = iwe_stream_add_point(info, buf, buf_end, &iwe, msg); - /* Custom info (WPA-IE) */ + /* WPA-IE */ wpa_ie = NULL; wpa_ie_len = 0; wpa_ie = wl_parse_wpa_ie( probe_resp, &wpa_ie_len ); if( wpa_ie != NULL ) { - memset( &iwe, 0, sizeof( iwe )); - memset( msg, 0, sizeof( msg )); + memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = IWEVCUSTOM; - sprintf( msg, "wpa_ie=%s", wl_print_wpa_ie( wpa_ie, wpa_ie_len )); - iwe.u.data.length = strlen( msg ); + iwe.cmd = IWEVGENIE; + iwe.u.data.length = wpa_ie_len; - buf = IWE_STREAM_ADD_POINT(info, buf, buf_end, &iwe, msg); + buf = iwe_stream_add_point(info, buf, buf_end, + &iwe, wpa_ie); } /* Add other custom info in formatted string format as needed... */ -#endif } data->length = buf - extra; @@ -2856,10 +2894,24 @@ out: } // wireless_get_scan /*============================================================================*/ -#endif // WIRELESS_EXT > 13 - - -#if WIRELESS_EXT > 17 +#if DBG +static const char * const auth_names[] = { + "IW_AUTH_WPA_VERSION", + "IW_AUTH_CIPHER_PAIRWISE", + "IW_AUTH_CIPHER_GROUP", + "IW_AUTH_KEY_MGMT", + "IW_AUTH_TKIP_COUNTERMEASURES", + "IW_AUTH_DROP_UNENCRYPTED", + "IW_AUTH_80211_AUTH_ALG", + "IW_AUTH_WPA_ENABLED", + "IW_AUTH_RX_UNENCRYPTED_EAPOL", + "IW_AUTH_ROAMING_CONTROL", + "IW_AUTH_PRIVACY_INVOKED", + "IW_AUTH_CIPHER_GROUP_MGMT", + "IW_AUTH_MFP", + "Unsupported" +}; +#endif static int wireless_set_auth(struct net_device *dev, struct iw_request_info *info, @@ -2867,14 +2919,15 @@ static int wireless_set_auth(struct net_device *dev, { struct wl_private *lp = wl_priv(dev); unsigned long flags; - int ret; - int iwa_idx = data->flags & IW_AUTH_INDEX; - int iwa_val = data->value; + ltv_t ltv; + int ret; + int iwa_idx = data->flags & IW_AUTH_INDEX; + int iwa_val = data->value; DBG_FUNC( "wireless_set_auth" ); DBG_ENTER( DbgInfo ); - if(lp->portState == WVLAN_PORT_STATE_DISABLED) { + if (lp->portState == WVLAN_PORT_STATE_DISABLED) { ret = -EBUSY; goto out; } @@ -2883,89 +2936,102 @@ static int wireless_set_auth(struct net_device *dev, wl_act_int_off( lp ); + if (iwa_idx > IW_AUTH_MFP) + iwa_idx = IW_AUTH_MFP + 1; + DBG_TRACE(DbgInfo, "%s\n", auth_names[iwa_idx]); switch (iwa_idx) { - case IW_AUTH_WPA_VERSION: - DBG_TRACE( DbgInfo, "IW_AUTH_WPA_VERSION\n"); - /* We do support WPA only; how should DISABLED be treated? */ - if (iwa_val == IW_AUTH_WPA_VERSION_WPA) - ret = 0; - else - ret = -EINVAL; - break; - - case IW_AUTH_WPA_ENABLED: - DBG_TRACE( DbgInfo, "IW_AUTH_WPA_ENABLED: val = %d\n", iwa_val); - if (iwa_val) - lp->EnableEncryption = 2; - else - lp->EnableEncryption = 0; + case IW_AUTH_WPA_VERSION: + /* We do support WPA */ + if ((iwa_val == IW_AUTH_WPA_VERSION_WPA) || + (iwa_val == IW_AUTH_WPA_VERSION_DISABLED)) ret = 0; - break; + else + ret = -EINVAL; + break; - case IW_AUTH_TKIP_COUNTERMEASURES: - DBG_TRACE( DbgInfo, "IW_AUTH_TKIP_COUNTERMEASURES\n"); - lp->driverEnable = !iwa_val; - if(lp->driverEnable) - hcf_cntl(&(lp->hcfCtx), HCF_CNTL_ENABLE | HCF_PORT_0); - else - hcf_cntl(&(lp->hcfCtx), HCF_CNTL_DISABLE | HCF_PORT_0); - ret = 0; - break; + case IW_AUTH_WPA_ENABLED: + DBG_TRACE(DbgInfo, "val = %d\n", iwa_val); + if (iwa_val) + lp->EnableEncryption = 2; + else + lp->EnableEncryption = 0; - case IW_AUTH_DROP_UNENCRYPTED: - DBG_TRACE( DbgInfo, "IW_AUTH_DROP_UNENCRYPTED\n"); - /* We do not actually do anything here, just to silence - * wpa_supplicant */ - ret = 0; - break; + /* Write straight to the card */ + ltv.len = 2; + ltv.typ = CFG_CNF_ENCRYPTION; + ltv.u.u16[0] = cpu_to_le16(lp->EnableEncryption); + ret = hcf_put_info(&lp->hcfCtx, (LTVP)<v); - case IW_AUTH_CIPHER_PAIRWISE: - DBG_TRACE( DbgInfo, "IW_AUTH_CIPHER_PAIRWISE\n"); - /* not implemented, return an error */ - ret = -EINVAL; - break; + break; - case IW_AUTH_CIPHER_GROUP: - DBG_TRACE( DbgInfo, "IW_AUTH_CIPHER_GROUP\n"); - /* not implemented, return an error */ - ret = -EINVAL; - break; + case IW_AUTH_TKIP_COUNTERMEASURES: - case IW_AUTH_KEY_MGMT: - DBG_TRACE( DbgInfo, "IW_AUTH_KEY_MGMT\n"); - /* not implemented, return an error */ - ret = -EINVAL; - break; + /* Immediately disable card */ + lp->driverEnable = !iwa_val; + if (lp->driverEnable) + hcf_cntl(&(lp->hcfCtx), HCF_CNTL_ENABLE | HCF_PORT_0); + else + hcf_cntl(&(lp->hcfCtx), HCF_CNTL_DISABLE | HCF_PORT_0); + ret = 0; + break; - case IW_AUTH_80211_AUTH_ALG: - DBG_TRACE( DbgInfo, "IW_AUTH_80211_AUTH_ALG\n"); - /* not implemented, return an error */ + case IW_AUTH_MFP: + /* Management Frame Protection not supported. + * Only fail if set to required. + */ + if (iwa_val == IW_AUTH_MFP_REQUIRED) ret = -EINVAL; - break; + else + ret = 0; + break; - case IW_AUTH_RX_UNENCRYPTED_EAPOL: - DBG_TRACE( DbgInfo, "IW_AUTH_RX_UNENCRYPTED_EAPOL\n"); - /* not implemented, return an error */ - ret = -EINVAL; - break; + case IW_AUTH_KEY_MGMT: - case IW_AUTH_ROAMING_CONTROL: - DBG_TRACE( DbgInfo, "IW_AUTH_ROAMING_CONTROL\n"); - /* not implemented, return an error */ - ret = -EINVAL; - break; + /* Record required management suite. + * Will take effect on next commit */ + if (iwa_val != 0) + lp->AuthKeyMgmtSuite = 4; + else + lp->AuthKeyMgmtSuite = 0; - case IW_AUTH_PRIVACY_INVOKED: - DBG_TRACE( DbgInfo, "IW_AUTH_PRIVACY_INVOKED\n"); - /* not implemented, return an error */ - ret = -EINVAL; - break; + ret = -EINPROGRESS; + break; - default: - DBG_TRACE( DbgInfo, "IW_AUTH_?? (%d) unknown\n", iwa_idx); - /* return an error */ + case IW_AUTH_80211_AUTH_ALG: + + /* Just record whether open or shared is required. + * Will take effect on next commit */ + ret = -EINPROGRESS; + + if (iwa_val & IW_AUTH_ALG_SHARED_KEY) + lp->authentication = 1; + else if (iwa_val & IW_AUTH_ALG_OPEN_SYSTEM) + lp->authentication = 0; + else ret = -EINVAL; - break; + break; + + case IW_AUTH_DROP_UNENCRYPTED: + /* Only needed for AP */ + lp->ExcludeUnencrypted = iwa_val; + ret = -EINPROGRESS; + break; + + case IW_AUTH_CIPHER_PAIRWISE: + case IW_AUTH_CIPHER_GROUP: + case IW_AUTH_RX_UNENCRYPTED_EAPOL: + case IW_AUTH_ROAMING_CONTROL: + case IW_AUTH_PRIVACY_INVOKED: + /* Not used. May need to do something with + * CIPHER_PAIRWISE and CIPHER_GROUP*/ + ret = -EINPROGRESS; + break; + + default: + DBG_TRACE(DbgInfo, "IW_AUTH_?? (%d) unknown\n", iwa_idx); + /* return an error */ + ret = -EOPNOTSUPP; + break; } wl_act_int_on( lp ); @@ -2979,290 +3045,176 @@ out: /*============================================================================*/ - -static int hermes_set_key(ltv_t *ltv, int alg, int key_idx, u8 *addr, - int set_tx, u8 *seq, u8 *key, size_t key_len) +static void flush_tx(struct wl_private *lp) { - int ret = -EINVAL; - // int count = 0; - int buf_idx = 0; - hcf_8 tsc[IW_ENCODE_SEQ_MAX_SIZE] = - { 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00 }; - - DBG_FUNC( "hermes_set_key" ); - DBG_ENTER( DbgInfo ); + ltv_t ltv; + int count; /* - * Check the key index here; if 0, load as Pairwise Key, otherwise, - * load as a group key. Note that for the Hermes, the RIDs for - * group/pariwise keys are different from each other and different - * than the default WEP keys as well. - */ - switch (alg) - { - case IW_ENCODE_ALG_TKIP: - DBG_TRACE( DbgInfo, "IW_ENCODE_ALG_TKIP: key(%d)\n", key_idx); -#if 0 - /* - * Make sure that there is no data queued up in the firmware - * before setting the TKIP keys. If this check is not - * performed, some data may be sent out with incorrect MIC - * and cause synchronizarion errors with the AP - */ - /* Check every 1ms for 100ms */ - for( count = 0; count < 100; count++ ) - { - usleep( 1000 ); + * Make sure that there is no data queued up in the firmware + * before setting the TKIP keys. If this check is not + * performed, some data may be sent out with incorrect MIC + * and cause synchronizarion errors with the AP + */ + /* Check every 1ms for 100ms */ + for (count = 0; count < 100; count++) { + udelay(1000); + + ltv.len = 2; + ltv.typ = 0xFD91; /* This RID not defined in HCF yet!!! */ + ltv.u.u16[0] = 0; + + hcf_get_info(&(lp->hcfCtx), (LTVP)<v); + + if (ltv.u.u16[0] == 0) + break; + } + + if (count >= 100) + DBG_TRACE(DbgInfo, "Timed out waiting for TxQ flush!\n"); - ltv.len = 2; - ltv.typ = 0xFD91; // This RID not defined in HCF yet!!! - ltv.u.u16[0] = 0; +} - wl_get_info( sock, <v, ifname ); +static int wireless_set_encodeext(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *erq, char *keybuf) +{ + struct wl_private *lp = wl_priv(dev); + unsigned long flags; + int ret; + int key_idx = (erq->flags & IW_ENCODE_INDEX) - 1; + ltv_t ltv; + struct iw_encode_ext *ext = (struct iw_encode_ext *)keybuf; + bool enable = true; + bool set_tx = false; - if( ltv.u.u16[0] == 0 ) - { - break; - } - } + DBG_ENTER(DbgInfo); - if( count == 100 ) - { - wpa_printf( MSG_DEBUG, "Timed out waiting for TxQ!" ); - } -#endif + if (lp->portState == WVLAN_PORT_STATE_DISABLED) { + ret = -EBUSY; + goto out; + } - switch (key_idx) { - case 0: - ltv->len = 28; - ltv->typ = CFG_ADD_TKIP_MAPPED_KEY; + if (erq->flags & IW_ENCODE_DISABLED) { + ext->alg = IW_ENCODE_ALG_NONE; + enable = false; + } - /* Load the BSSID */ - memcpy(<v->u.u8[buf_idx], addr, ETH_ALEN); - buf_idx += ETH_ALEN; + if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) + set_tx = true; - /* Load the TKIP key */ - memcpy(<v->u.u8[buf_idx], &key[0], 16); - buf_idx += 16; + wl_lock(lp, &flags); - /* Load the TSC */ - memcpy(<v->u.u8[buf_idx], tsc, IW_ENCODE_SEQ_MAX_SIZE); - buf_idx += IW_ENCODE_SEQ_MAX_SIZE; + wl_act_int_off(lp); - /* Load the RSC */ - memcpy(<v->u.u8[buf_idx], seq, IW_ENCODE_SEQ_MAX_SIZE); - buf_idx += IW_ENCODE_SEQ_MAX_SIZE; + memset(<v, 0, sizeof(ltv)); - /* Load the TxMIC key */ - memcpy(<v->u.u8[buf_idx], &key[16], 8); - buf_idx += 8; + switch (ext->alg) { + case IW_ENCODE_ALG_TKIP: + DBG_TRACE(DbgInfo, "IW_ENCODE_ALG_TKIP: key(%d)\n", key_idx); - /* Load the RxMIC key */ - memcpy(<v->u.u8[buf_idx], &key[24], 8); + if (sizeof(ext->rx_seq) != 8) { + DBG_TRACE(DbgInfo, "rx_seq size mismatch\n"); + DBG_LEAVE(DbgInfo); + ret = -EINVAL; + goto out_unlock; + } - ret = 0; - break; - case 1: - case 2: - case 3: - ltv->len = 26; - ltv->typ = CFG_ADD_TKIP_DEFAULT_KEY; + ret = hermes_set_tkip_keys(<v, key_idx, ext->addr.sa_data, + set_tx, + ext->rx_seq, ext->key, ext->key_len); - /* Load the key Index */ - ltv->u.u16[buf_idx] = key_idx; - /* If this is a Tx Key, set bit 8000 */ - if(set_tx) - ltv->u.u16[buf_idx] |= 0x8000; - buf_idx += 2; + if (ret != 0) { + DBG_TRACE(DbgInfo, "hermes_set_tkip_keys returned != 0, key not set\n"); + goto out_unlock; + } - /* Load the RSC */ - memcpy(<v->u.u8[buf_idx], seq, IW_ENCODE_SEQ_MAX_SIZE); - buf_idx += IW_ENCODE_SEQ_MAX_SIZE; + flush_tx(lp); - /* Load the TKIP, TxMIC, and RxMIC keys in one shot, because in - CFG_ADD_TKIP_DEFAULT_KEY they are back-to-back */ - memcpy(<v->u.u8[buf_idx], key, key_len); - buf_idx += key_len; + lp->wext_enc = IW_ENCODE_ALG_TKIP; - /* Load the TSC */ - memcpy(<v->u.u8[buf_idx], tsc, IW_ENCODE_SEQ_MAX_SIZE); + /* Write the key */ + ret = hcf_put_info(&(lp->hcfCtx), (LTVP)<v); + break; - ltv->u.u16[0] = CNV_INT_TO_LITTLE(ltv->u.u16[0]); + case IW_ENCODE_ALG_WEP: + DBG_TRACE(DbgInfo, "IW_ENCODE_ALG_WEP: key(%d)\n", key_idx); - ret = 0; - break; - default: - break; + if (erq->flags & IW_ENCODE_RESTRICTED) { + DBG_WARNING(DbgInfo, "IW_ENCODE_RESTRICTED invalid\n"); + ret = -EINVAL; + goto out_unlock; } - break; + ret = hermes_set_wep_keys(lp, key_idx, ext->key, ext->key_len, + enable, set_tx); - case IW_ENCODE_ALG_WEP: - DBG_TRACE( DbgInfo, "IW_ENCODE_ALG_WEP: key(%d)\n", key_idx); break; case IW_ENCODE_ALG_CCMP: - DBG_TRACE( DbgInfo, "IW_ENCODE_ALG_CCMP: key(%d)\n", key_idx); + DBG_TRACE(DbgInfo, "IW_ENCODE_ALG_CCMP: key(%d)\n", key_idx); + ret = -EOPNOTSUPP; break; case IW_ENCODE_ALG_NONE: - DBG_TRACE( DbgInfo, "IW_ENCODE_ALG_NONE: key(%d)\n", key_idx); - switch (key_idx) { - case 0: - if (memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) != 0) { - //if (addr != NULL) { - ltv->len = 7; - ltv->typ = CFG_REMOVE_TKIP_MAPPED_KEY; - memcpy(<v->u.u8[0], addr, ETH_ALEN); - ret = 0; - } - break; - case 1: - case 2: - case 3: - /* Clear the Group TKIP keys by index */ - ltv->len = 2; - ltv->typ = CFG_REMOVE_TKIP_DEFAULT_KEY; - ltv->u.u16[0] = key_idx; - + DBG_TRACE(DbgInfo, "IW_ENCODE_ALG_NONE: key(%d)\n", key_idx); + + if (lp->wext_enc == IW_ENCODE_ALG_TKIP) { + ret = hermes_clear_tkip_keys(<v, key_idx, + ext->addr.sa_data); + flush_tx(lp); + lp->wext_enc = IW_ENCODE_ALG_NONE; + ret = hcf_put_info(&(lp->hcfCtx), (LTVP)<v); + + } else if (lp->wext_enc == IW_ENCODE_ALG_WEP) { + ret = hermes_set_wep_keys(lp, key_idx, + ext->key, ext->key_len, + false, false); + } else { ret = 0; - break; - default: - break; } + break; + default: DBG_TRACE( DbgInfo, "IW_ENCODE_??: key(%d)\n", key_idx); + ret = -EOPNOTSUPP; break; } - DBG_LEAVE( DbgInfo ); - return ret; -} // hermes_set_key -/*============================================================================*/ - - - -static int wireless_set_encodeext (struct net_device *dev, - struct iw_request_info *info, - struct iw_point *erq, char *keybuf) -{ - struct wl_private *lp = wl_priv(dev); - unsigned long flags; - int ret; - int key_idx = (erq->flags&IW_ENCODE_INDEX) - 1; - ltv_t ltv; - struct iw_encode_ext *ext = (struct iw_encode_ext *)keybuf; - - DBG_FUNC( "wireless_set_encodeext" ); - DBG_ENTER( DbgInfo ); - - if(lp->portState == WVLAN_PORT_STATE_DISABLED) { - ret = -EBUSY; - goto out; - } - - if (sizeof(ext->rx_seq) != 8) { - DBG_TRACE(DbgInfo, "rz_seq size mismatch\n"); - DBG_LEAVE(DbgInfo); - return -EINVAL; - } - - /* Handle WEP keys via the old set encode procedure */ - if(ext->alg == IW_ENCODE_ALG_WEP) { - struct iw_point wep_erq; - char *wep_keybuf; - - /* Build request structure */ - wep_erq.flags = erq->flags; // take over flags with key index - wep_erq.length = ext->key_len; // take length from extended key info - wep_keybuf = ext->key; // pointer to the key text - - /* Call wireless_set_encode tot handle the WEP key */ - ret = wireless_set_encode(dev, info, &wep_erq, wep_keybuf); - goto out; - } - - /* Proceed for extended encode functions for WAP and NONE */ - wl_lock( lp, &flags ); - - wl_act_int_off( lp ); - - memset(<v, 0, sizeof(ltv)); - ret = hermes_set_key(<v, ext->alg, key_idx, ext->addr.sa_data, - ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY, - ext->rx_seq, ext->key, ext->key_len); - - if (ret != 0) { - DBG_TRACE( DbgInfo, "hermes_set_key returned != 0, key not set\n"); - goto out_unlock; - } - - /* Put the key in HCF */ - ret = hcf_put_info(&(lp->hcfCtx), (LTVP)<v); - out_unlock: - if(ret == HCF_SUCCESS) { - DBG_TRACE( DbgInfo, "Put key info succes\n"); - } else { - DBG_TRACE( DbgInfo, "Put key info failed, key not set\n"); - } - wl_act_int_on( lp ); + wl_act_int_on(lp); wl_unlock(lp, &flags); out: - DBG_LEAVE( DbgInfo ); + DBG_LEAVE(DbgInfo); return ret; -} // wireless_set_encodeext +} /*============================================================================*/ -static int wireless_get_genie(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *extra) +static int wireless_set_genie(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *extra) { - struct wl_private *lp = wl_priv(dev); - unsigned long flags; int ret = 0; - ltv_t ltv; - - DBG_FUNC( "wireless_get_genie" ); - DBG_ENTER( DbgInfo ); - - if(lp->portState == WVLAN_PORT_STATE_DISABLED) { - ret = -EBUSY; - goto out; - } - - wl_lock( lp, &flags ); - - wl_act_int_off( lp ); - - memset(<v, 0, sizeof(ltv)); - ltv.len = 2; - ltv.typ = CFG_SET_WPA_AUTH_KEY_MGMT_SUITE; - lp->AuthKeyMgmtSuite = ltv.u.u16[0] = 4; - ltv.u.u16[0] = CNV_INT_TO_LITTLE(ltv.u.u16[0]); - ret = hcf_put_info(&(lp->hcfCtx), (LTVP)<v); - - wl_act_int_on( lp ); + DBG_ENTER(DbgInfo); - wl_unlock(lp, &flags); + /* We can't write this to the card, but apparently this + * operation needs to succeed */ + ret = 0; -out: - DBG_LEAVE( DbgInfo ); + DBG_LEAVE(DbgInfo); return ret; } /*============================================================================*/ -#endif // WIRELESS_EXT > 17 - /******************************************************************************* * wl_wireless_stats() ******************************************************************************* @@ -3316,7 +3268,6 @@ struct iw_statistics * wl_wireless_stats( struct net_device *dev ) if( status == HCF_SUCCESS ) { pQual = (CFG_COMMS_QUALITY_STRCT *)&( lp->ltvRecord ); -#ifdef USE_DBM pStats->qual.qual = (u_char) CNV_LITTLE_TO_INT( pQual->coms_qual ); pStats->qual.level = (u_char) dbm( CNV_LITTLE_TO_INT( pQual->signal_lvl )); pStats->qual.noise = (u_char) dbm( CNV_LITTLE_TO_INT( pQual->noise_lvl )); @@ -3325,23 +3276,6 @@ struct iw_statistics * wl_wireless_stats( struct net_device *dev ) IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_UPDATED | IW_QUAL_DBM); -#else - pStats->qual.qual = percent( CNV_LITTLE_TO_INT( pQual->coms_qual ), - HCF_MIN_COMM_QUALITY, - HCF_MAX_COMM_QUALITY ); - - pStats->qual.level = percent( CNV_LITTLE_TO_INT( pQual->signal_lvl ), - HCF_MIN_SIGNAL_LEVEL, - HCF_MAX_SIGNAL_LEVEL ); - - pStats->qual.noise = percent( CNV_LITTLE_TO_INT( pQual->noise_lvl ), - HCF_MIN_NOISE_LEVEL, - HCF_MAX_NOISE_LEVEL ); - - pStats->qual.updated |= (IW_QUAL_QUAL_UPDATED | - IW_QUAL_LEVEL_UPDATED | - IW_QUAL_NOISE_UPDATED); -#endif /* USE_DBM */ } else { memset( &( pStats->qual ), 0, sizeof( pStats->qual )); } @@ -3512,7 +3446,6 @@ inline void wl_spy_gather( struct net_device *dev, u_char *mac ) ******************************************************************************/ void wl_wext_event_freq( struct net_device *dev ) { -#if WIRELESS_EXT > 13 union iwreq_data wrqu; struct wl_private *lp = wl_priv(dev); /*------------------------------------------------------------------------*/ @@ -3524,7 +3457,6 @@ void wl_wext_event_freq( struct net_device *dev ) wrqu.freq.e = 0; wireless_send_event( dev, SIOCSIWFREQ, &wrqu, NULL ); -#endif /* WIRELESS_EXT > 13 */ return; } // wl_wext_event_freq @@ -3554,7 +3486,6 @@ void wl_wext_event_freq( struct net_device *dev ) ******************************************************************************/ void wl_wext_event_mode( struct net_device *dev ) { -#if WIRELESS_EXT > 13 union iwreq_data wrqu; struct wl_private *lp = wl_priv(dev); /*------------------------------------------------------------------------*/ @@ -3569,7 +3500,6 @@ void wl_wext_event_mode( struct net_device *dev ) } wireless_send_event( dev, SIOCSIWMODE, &wrqu, NULL ); -#endif /* WIRELESS_EXT > 13 */ return; } // wl_wext_event_mode @@ -3599,7 +3529,6 @@ void wl_wext_event_mode( struct net_device *dev ) ******************************************************************************/ void wl_wext_event_essid( struct net_device *dev ) { -#if WIRELESS_EXT > 13 union iwreq_data wrqu; struct wl_private *lp = wl_priv(dev); /*------------------------------------------------------------------------*/ @@ -3616,7 +3545,6 @@ void wl_wext_event_essid( struct net_device *dev ) wrqu.essid.flags = 1; wireless_send_event( dev, SIOCSIWESSID, &wrqu, lp->NetworkName ); -#endif /* WIRELESS_EXT > 13 */ return; } // wl_wext_event_essid @@ -3646,7 +3574,6 @@ void wl_wext_event_essid( struct net_device *dev ) ******************************************************************************/ void wl_wext_event_encode( struct net_device *dev ) { -#if WIRELESS_EXT > 13 union iwreq_data wrqu; struct wl_private *lp = wl_priv(dev); int index = 0; @@ -3688,7 +3615,6 @@ void wl_wext_event_encode( struct net_device *dev ) wireless_send_event( dev, SIOCSIWENCODE, &wrqu, lp->DefaultKeys.key[index].key ); -#endif /* WIRELESS_EXT > 13 */ return; } // wl_wext_event_encode @@ -3718,7 +3644,6 @@ void wl_wext_event_encode( struct net_device *dev ) ******************************************************************************/ void wl_wext_event_ap( struct net_device *dev ) { -#if WIRELESS_EXT > 13 union iwreq_data wrqu; struct wl_private *lp = wl_priv(dev); int status; @@ -3747,8 +3672,6 @@ void wl_wext_event_ap( struct net_device *dev ) wireless_send_event( dev, SIOCGIWAP, &wrqu, NULL ); } -#endif /* WIRELESS_EXT > 13 */ - return; } // wl_wext_event_ap /*============================================================================*/ @@ -3776,7 +3699,6 @@ void wl_wext_event_ap( struct net_device *dev ) ******************************************************************************/ void wl_wext_event_scan_complete( struct net_device *dev ) { -#if WIRELESS_EXT > 13 union iwreq_data wrqu; /*------------------------------------------------------------------------*/ @@ -3785,7 +3707,6 @@ void wl_wext_event_scan_complete( struct net_device *dev ) wrqu.addr.sa_family = ARPHRD_ETHER; wireless_send_event( dev, SIOCGIWSCAN, &wrqu, NULL ); -#endif /* WIRELESS_EXT > 13 */ return; } // wl_wext_event_scan_complete @@ -3815,7 +3736,6 @@ void wl_wext_event_scan_complete( struct net_device *dev ) ******************************************************************************/ void wl_wext_event_new_sta( struct net_device *dev ) { -#if WIRELESS_EXT > 14 union iwreq_data wrqu; /*------------------------------------------------------------------------*/ @@ -3826,7 +3746,6 @@ void wl_wext_event_new_sta( struct net_device *dev ) memcpy( wrqu.addr.sa_data, dev->dev_addr, ETH_ALEN ); wrqu.addr.sa_family = ARPHRD_ETHER; wireless_send_event( dev, IWEVREGISTERED, &wrqu, NULL ); -#endif /* WIRELESS_EXT > 14 */ return; } // wl_wext_event_new_sta @@ -3856,7 +3775,6 @@ void wl_wext_event_new_sta( struct net_device *dev ) ******************************************************************************/ void wl_wext_event_expired_sta( struct net_device *dev ) { -#if WIRELESS_EXT > 14 union iwreq_data wrqu; /*------------------------------------------------------------------------*/ @@ -3866,7 +3784,6 @@ void wl_wext_event_expired_sta( struct net_device *dev ) memcpy( wrqu.addr.sa_data, dev->dev_addr, ETH_ALEN ); wrqu.addr.sa_family = ARPHRD_ETHER; wireless_send_event( dev, IWEVEXPIRED, &wrqu, NULL ); -#endif /* WIRELESS_EXT > 14 */ return; } // wl_wext_event_expired_sta @@ -3895,10 +3812,9 @@ void wl_wext_event_expired_sta( struct net_device *dev ) ******************************************************************************/ void wl_wext_event_mic_failed( struct net_device *dev ) { -#if WIRELESS_EXT > 14 - char msg[512]; union iwreq_data wrqu; struct wl_private *lp = wl_priv(dev); + struct iw_michaelmicfailure wxmic; int key_idx; char *addr1; char *addr2; @@ -3920,31 +3836,17 @@ void wl_wext_event_mic_failed( struct net_device *dev ) DBG_PRINT( "MIC FAIL - KEY USED : %d, STATUS : 0x%04x\n", key_idx, hdr->status ); - memset( &wrqu, 0, sizeof( wrqu )); - memset( msg, 0, sizeof( msg )); - - - /* Because MIC failures are not part of the Wireless Extensions yet, they - must be passed as a string using an IWEVCUSTOM event. In order for the - event to be effective, the string format must be known by both the - driver and the supplicant. The following is the string format used by the - hostap project's WPA supplicant, and will be used here until the Wireless - Extensions interface adds this support: + memset(&wrqu, 0, sizeof(wrqu)); + memset(&wxmic, 0, sizeof(wxmic)); - MLME-MICHAELMICFAILURE.indication(keyid=# broadcast/unicast addr=addr2) - */ + wxmic.flags = key_idx & IW_MICFAILURE_KEY_ID; + wxmic.flags |= (addr1[0] & 1) ? + IW_MICFAILURE_GROUP : IW_MICFAILURE_PAIRWISE; + wxmic.src_addr.sa_family = ARPHRD_ETHER; + memcpy(wxmic.src_addr.sa_data, addr2, ETH_ALEN); - /* NOTE: Format of MAC address (using colons to separate bytes) may cause - a problem in future versions of the supplicant, if they ever - actually parse these parameters */ -#if DBG - sprintf(msg, "MLME-MICHAELMICFAILURE.indication(keyid=%d %scast " - "addr=%pM)", key_idx, addr1[0] & 0x01 ? "broad" : "uni", - addr2); -#endif - wrqu.data.length = strlen( msg ); - wireless_send_event( dev, IWEVCUSTOM, &wrqu, msg ); -#endif /* WIRELESS_EXT > 14 */ + wrqu.data.length = sizeof(wxmic); + wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&wxmic); return; } // wl_wext_event_mic_failed @@ -3974,8 +3876,6 @@ void wl_wext_event_mic_failed( struct net_device *dev ) ******************************************************************************/ void wl_wext_event_assoc_ie( struct net_device *dev ) { -#if WIRELESS_EXT > 14 - char msg[512]; union iwreq_data wrqu; struct wl_private *lp = wl_priv(dev); int status; @@ -3986,7 +3886,6 @@ void wl_wext_event_assoc_ie( struct net_device *dev ) memset( &wrqu, 0, sizeof( wrqu )); - memset( msg, 0, sizeof( msg )); /* Retrieve the Association Request IE */ lp->ltvRecord.len = 45; @@ -3999,24 +3898,18 @@ void wl_wext_event_assoc_ie( struct net_device *dev ) memcpy( &data.rawData, &( lp->ltvRecord.u.u8[1] ), 88 ); wpa_ie = wl_parse_wpa_ie( &data, &length ); - /* Because this event (Association WPA-IE) is not part of the Wireless - Extensions yet, it must be passed as a string using an IWEVCUSTOM event. - In order for the event to be effective, the string format must be known - by both the driver and the supplicant. The following is the string format - used by the hostap project's WPA supplicant, and will be used here until - the Wireless Extensions interface adds this support: - - ASSOCINFO(ReqIEs=WPA-IE RespIEs=WPA-IE) - */ - if( length != 0 ) { - sprintf( msg, "ASSOCINFO(ReqIEs=%s)", wl_print_wpa_ie( wpa_ie, length )); - wrqu.data.length = strlen( msg ); - wireless_send_event( dev, IWEVCUSTOM, &wrqu, msg ); + wrqu.data.length = wpa_ie[1] + 2; + wireless_send_event(dev, IWEVASSOCREQIE, + &wrqu, wpa_ie); + + /* This bit is a hack. We send the respie + * event at the same time */ + wireless_send_event(dev, IWEVASSOCRESPIE, + &wrqu, wpa_ie); } } -#endif /* WIRELESS_EXT > 14 */ return; } // wl_wext_event_assoc_ie @@ -4025,66 +3918,39 @@ void wl_wext_event_assoc_ie( struct net_device *dev ) static const iw_handler wl_handler[] = { - (iw_handler) wireless_commit, /* SIOCSIWCOMMIT */ - (iw_handler) wireless_get_protocol, /* SIOCGIWNAME */ - (iw_handler) NULL, /* SIOCSIWNWID */ - (iw_handler) NULL, /* SIOCGIWNWID */ - (iw_handler) wireless_set_frequency, /* SIOCSIWFREQ */ - (iw_handler) wireless_get_frequency, /* SIOCGIWFREQ */ - (iw_handler) wireless_set_porttype, /* SIOCSIWMODE */ - (iw_handler) wireless_get_porttype, /* SIOCGIWMODE */ - (iw_handler) wireless_set_sensitivity, /* SIOCSIWSENS */ - (iw_handler) wireless_get_sensitivity, /* SIOCGIWSENS */ - (iw_handler) NULL , /* SIOCSIWRANGE */ - (iw_handler) wireless_get_range, /* SIOCGIWRANGE */ - (iw_handler) NULL , /* SIOCSIWPRIV */ - (iw_handler) NULL /* kernel code */, /* SIOCGIWPRIV */ - (iw_handler) NULL , /* SIOCSIWSTATS */ - (iw_handler) NULL /* kernel code */, /* SIOCGIWSTATS */ - iw_handler_set_spy, /* SIOCSIWSPY */ - iw_handler_get_spy, /* SIOCGIWSPY */ - NULL, /* SIOCSIWTHRSPY */ - NULL, /* SIOCGIWTHRSPY */ - (iw_handler) NULL, /* SIOCSIWAP */ + IW_HANDLER(SIOCSIWCOMMIT, (iw_handler) wireless_commit), + IW_HANDLER(SIOCGIWNAME, (iw_handler) wireless_get_protocol), + IW_HANDLER(SIOCSIWFREQ, (iw_handler) wireless_set_frequency), + IW_HANDLER(SIOCGIWFREQ, (iw_handler) wireless_get_frequency), + IW_HANDLER(SIOCSIWMODE, (iw_handler) wireless_set_porttype), + IW_HANDLER(SIOCGIWMODE, (iw_handler) wireless_get_porttype), + IW_HANDLER(SIOCSIWSENS, (iw_handler) wireless_set_sensitivity), + IW_HANDLER(SIOCGIWSENS, (iw_handler) wireless_get_sensitivity), + IW_HANDLER(SIOCGIWRANGE, (iw_handler) wireless_get_range), + IW_HANDLER(SIOCSIWSPY, iw_handler_set_spy), + IW_HANDLER(SIOCGIWSPY, iw_handler_get_spy), #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA - (iw_handler) wireless_get_bssid, /* SIOCGIWAP */ -#else - (iw_handler) NULL, /* SIOCGIWAP */ + IW_HANDLER(SIOCGIWAP, (iw_handler) wireless_get_bssid), #endif - (iw_handler) NULL, /* SIOCSIWMLME */ - (iw_handler) wireless_get_ap_list, /* SIOCGIWAPLIST */ - (iw_handler) wireless_set_scan, /* SIOCSIWSCAN */ - (iw_handler) wireless_get_scan, /* SIOCGIWSCAN */ - (iw_handler) wireless_set_essid, /* SIOCSIWESSID */ - (iw_handler) wireless_get_essid, /* SIOCGIWESSID */ - (iw_handler) wireless_set_nickname, /* SIOCSIWNICKN */ - (iw_handler) wireless_get_nickname, /* SIOCGIWNICKN */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) wireless_set_rate, /* SIOCSIWRATE */ - (iw_handler) wireless_get_rate, /* SIOCGIWRATE */ - (iw_handler) wireless_set_rts_threshold,/* SIOCSIWRTS */ - (iw_handler) wireless_get_rts_threshold,/* SIOCGIWRTS */ - (iw_handler) NULL, /* SIOCSIWFRAG */ - (iw_handler) NULL, /* SIOCGIWFRAG */ - (iw_handler) NULL, /* SIOCSIWTXPOW */ - (iw_handler) wireless_get_tx_power, /* SIOCGIWTXPOW */ - (iw_handler) NULL, /* SIOCSIWRETRY */ - (iw_handler) NULL, /* SIOCGIWRETRY */ - (iw_handler) wireless_set_encode, /* SIOCSIWENCODE */ - (iw_handler) wireless_get_encode, /* SIOCGIWENCODE */ - (iw_handler) wireless_set_power, /* SIOCSIWPOWER */ - (iw_handler) wireless_get_power, /* SIOCGIWPOWER */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) wireless_get_genie, /* SIOCSIWGENIE */ - (iw_handler) NULL, /* SIOCGIWGENIE */ - (iw_handler) wireless_set_auth, /* SIOCSIWAUTH */ - (iw_handler) NULL, /* SIOCGIWAUTH */ - (iw_handler) wireless_set_encodeext, /* SIOCSIWENCODEEXT */ - (iw_handler) NULL, /* SIOCGIWENCODEEXT */ - (iw_handler) NULL, /* SIOCSIWPMKSA */ - (iw_handler) NULL, /* -- hole -- */ + IW_HANDLER(SIOCGIWAPLIST, (iw_handler) wireless_get_ap_list), + IW_HANDLER(SIOCSIWSCAN, (iw_handler) wireless_set_scan), + IW_HANDLER(SIOCGIWSCAN, (iw_handler) wireless_get_scan), + IW_HANDLER(SIOCSIWESSID, (iw_handler) wireless_set_essid), + IW_HANDLER(SIOCGIWESSID, (iw_handler) wireless_get_essid), + IW_HANDLER(SIOCSIWNICKN, (iw_handler) wireless_set_nickname), + IW_HANDLER(SIOCGIWNICKN, (iw_handler) wireless_get_nickname), + IW_HANDLER(SIOCSIWRATE, (iw_handler) wireless_set_rate), + IW_HANDLER(SIOCGIWRATE, (iw_handler) wireless_get_rate), + IW_HANDLER(SIOCSIWRTS, (iw_handler) wireless_set_rts_threshold), + IW_HANDLER(SIOCGIWRTS, (iw_handler) wireless_get_rts_threshold), + IW_HANDLER(SIOCGIWTXPOW, (iw_handler) wireless_get_tx_power), + IW_HANDLER(SIOCSIWENCODE, (iw_handler) wireless_set_encode), + IW_HANDLER(SIOCGIWENCODE, (iw_handler) wireless_get_encode), + IW_HANDLER(SIOCSIWPOWER, (iw_handler) wireless_set_power), + IW_HANDLER(SIOCGIWPOWER, (iw_handler) wireless_get_power), + IW_HANDLER(SIOCSIWGENIE, (iw_handler) wireless_set_genie), + IW_HANDLER(SIOCSIWAUTH, (iw_handler) wireless_set_auth), + IW_HANDLER(SIOCSIWENCODEEXT, (iw_handler) wireless_set_encodeext), }; static const iw_handler wl_private_handler[] = @@ -4120,5 +3986,3 @@ const struct iw_handler_def wl_iw_handler_def = .standard = (iw_handler *) wl_handler, .get_wireless_stats = wl_get_wireless_stats, }; - -#endif // WIRELESS_EXT |