First, I'm not on the list... cc-me if you've something to say ;) here it comes, en-wpa2.patch - adds lots of stuff for the current prism54 driver. (2.6.18-git) It fixes WPA2 support and add groupkey and replay counter through it. and yes, "wpa_supplicant -Dwext -c/etc/wpa_supplicant.conf -iethX" still works with the patch. (BTW, if someone is interested, I can make hostapd work with a PRISM GT too!) wext-patch - this patch just add two "#define" for SIOCSIWMLME ioctl. (It would be really nice to know why nobody came up with this idea before? Is there a really good reason?) Thx! _____________________________________________________________________ Der WEB.DE SmartSurfer hilft bis zu 70% Ihrer Onlinekosten zu sparen! http://smartsurfer.web.de/?mc=100071&distributionid=000000000066
diff -Nurp orig/isl_ioctl.c kernel/isl_ioctl.c --- orig/isl_ioctl.c 2006-09-28 21:13:25.000000000 +0200 +++ kernel/isl_ioctl.c 2006-10-01 17:11:13.000000000 +0200 @@ -35,10 +35,13 @@ #include <net/iw_handler.h> /* New driver API */ +#define WLAN_EID_GENERIC 0xdd +#define WLAN_EID_RSN 0x30 #define KEY_SIZE_WEP104 13 /* 104/128-bit WEP keys */ #define KEY_SIZE_WEP40 5 /* 40/64-bit WEP keys */ /* KEY_SIZE_TKIP should match isl_oid.h, struct obj_key.key[] size */ #define KEY_SIZE_TKIP 32 /* TKIP keys */ +static u8 wpa_oid[4] = { 0x00, 0x50, 0xf2, 1 }; static void prism54_wpa_bss_ie_add(islpci_private *priv, u8 *bssid, u8 *wpa_ie, size_t wpa_ie_len); @@ -436,11 +439,11 @@ prism54_get_range(struct net_device *nde /* Now the encoding capabilities */ range->num_encoding_sizes = 3; /* 64(40) bits WEP */ - range->encoding_size[0] = 5; + range->encoding_size[0] = KEY_SIZE_WEP40; /* 128(104) bits WEP */ - range->encoding_size[1] = 13; + range->encoding_size[1] = KEY_SIZE_WEP104; /* 256 bits for WPA-PSK */ - range->encoding_size[2] = 32; + range->encoding_size[2] = KEY_SIZE_TKIP; /* 4 keys are allowed */ range->max_encoding_tokens = 4; @@ -744,7 +747,7 @@ prism54_set_essid(struct net_device *nde if (dwrq->flags && dwrq->length) { if (dwrq->length > 32) return -E2BIG; - essid.length = dwrq->length; + essid.length = dwrq->length - 1; memcpy(essid.octets, extra, dwrq->length); } else essid.length = 0; @@ -876,15 +879,6 @@ prism54_set_rate(struct net_device *ndev data[1] = 0; } -/* - i = 0; - printk("prism54 rate: "); - while(data[i]) { - printk("%u ", data[i]); - i++; - } - printk("0\n"); -*/ profile = -1; ret = mgt_set_request(priv, DOT11_OID_PROFILES, 0, &profile); ret |= mgt_set_request(priv, DOT11_OID_EXTENDEDRATES, 0, data); @@ -1053,12 +1047,45 @@ prism54_get_retry(struct net_device *nde } static int +prism54_set_auth_alg(islpci_private *priv, u32 flag) +{ + int authen = DOT11_AUTH_OS, invoke = 0, exunencrypt = 0; + int ret; + + if (flag & IW_ENCODE_RESTRICTED) { + authen = DOT11_AUTH_SK; + invoke = 1; + exunencrypt = 1; + } + + if (flag & IW_ENCODE_OPEN) { + authen = DOT11_AUTH_OS; + invoke = 1; + if (priv->iw_mode == IW_MODE_MASTER) + exunencrypt = 1; // a special supplicants wants it this way! + else + exunencrypt = 0; + } + + ret = + mgt_set_request(priv, DOT11_OID_AUTHENABLE, + 0, &authen); + ret |= + mgt_set_request(priv, DOT11_OID_PRIVACYINVOKED, + 0, &invoke); + ret |= + mgt_set_request(priv, DOT11_OID_EXUNENCRYPTED, + 0,&exunencrypt); + + return ret; +} + +static int prism54_set_encode(struct net_device *ndev, struct iw_request_info *info, struct iw_point *dwrq, char *extra) { islpci_private *priv = netdev_priv(ndev); - int rvalue = 0, force = 0; - int authen = DOT11_AUTH_OS, invoke = 0, exunencrypt = 0; + int rvalue = 0, flags = dwrq->flags; union oid_res_t r; /* with the new API, it's impossible to get a NULL pointer. @@ -1092,7 +1119,7 @@ prism54_set_encode(struct net_device *nd key.length = KEY_SIZE_WEP40; } memset(key.key, 0, sizeof (key.key)); - memcpy(key.key, extra, dwrq->length); + memcpy(key.key, extra, key.length); if ((index < 0) || (index > 3)) /* no index provided use the current one */ @@ -1109,79 +1136,76 @@ prism54_set_encode(struct net_device *nd * This is also how "iwconfig ethX key on" works */ if ((index == current_index) && (key.length > 0)) - force = 1; + flags |= IW_ENCODE_RESTRICTED; } else { - int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; + int index = (flags & IW_ENCODE_INDEX) - 1; if ((index >= 0) && (index <= 3)) { /* we want to set the key index */ rvalue |= mgt_set_request(priv, DOT11_OID_DEFKEYID, 0, &index); } else { - if (!dwrq->flags & IW_ENCODE_MODE) { + if (!(flags & IW_ENCODE_MODE)) { /* we cannot do anything. Complain. */ return -EINVAL; } } } - /* now read the flags */ - if (dwrq->flags & IW_ENCODE_DISABLED) { - /* Encoding disabled, - * authen = DOT11_AUTH_OS; - * invoke = 0; - * exunencrypt = 0; */ - } - if (dwrq->flags & IW_ENCODE_OPEN) - /* Encode but accept non-encoded packets. No auth */ - invoke = 1; - if ((dwrq->flags & IW_ENCODE_RESTRICTED) || force) { - /* Refuse non-encoded packets. Auth */ - authen = DOT11_AUTH_BOTH; - invoke = 1; - exunencrypt = 1; - } /* do the change if requested */ - if ((dwrq->flags & IW_ENCODE_MODE) || force) { - rvalue |= - mgt_set_request(priv, DOT11_OID_AUTHENABLE, 0, &authen); - rvalue |= - mgt_set_request(priv, DOT11_OID_PRIVACYINVOKED, 0, &invoke); - rvalue |= - mgt_set_request(priv, DOT11_OID_EXUNENCRYPTED, 0, - &exunencrypt); - } + if (flags & IW_ENCODE_MODE) + rvalue = prism54_set_auth_alg(priv, flags); + return rvalue; } static int -prism54_get_encode(struct net_device *ndev, struct iw_request_info *info, - struct iw_point *dwrq, char *extra) +prism54_get_auth_algs(islpci_private *priv) { - islpci_private *priv = netdev_priv(ndev); - struct obj_key *key; - u32 devindex, index = (dwrq->flags & IW_ENCODE_INDEX) - 1; u32 authen = 0, invoke = 0, exunencrypt = 0; - int rvalue; union oid_res_t r; + int ret = 0; - /* first get the flags */ - rvalue = mgt_get_request(priv, DOT11_OID_AUTHENABLE, 0, NULL, &r); + ret = mgt_get_request(priv, DOT11_OID_AUTHENABLE, 0, NULL, &r); authen = r.u; - rvalue |= mgt_get_request(priv, DOT11_OID_PRIVACYINVOKED, 0, NULL, &r); + ret |= mgt_get_request(priv, DOT11_OID_PRIVACYINVOKED, 0, NULL, &r); invoke = r.u; - rvalue |= mgt_get_request(priv, DOT11_OID_EXUNENCRYPTED, 0, NULL, &r); + ret |= mgt_get_request(priv, DOT11_OID_EXUNENCRYPTED, 0, NULL, &r); exunencrypt = r.u; - if (invoke && (authen == DOT11_AUTH_BOTH) && exunencrypt) - dwrq->flags = IW_ENCODE_RESTRICTED; - else if ((authen == DOT11_AUTH_OS) && !exunencrypt) { + if (ret) + return ret; + + if (invoke && exunencrypt && + ((authen == DOT11_AUTH_SK) || (authen == DOT11_AUTH_BOTH))) + ret = IW_ENCODE_RESTRICTED; + else if ((authen == DOT11_AUTH_OS)) { if (invoke) - dwrq->flags = IW_ENCODE_OPEN; - else - dwrq->flags = IW_ENCODE_DISABLED; + ret = IW_ENCODE_OPEN; + else { + ret = IW_ENCODE_DISABLED; + } } else /* The card should not work in this state */ - dwrq->flags = 0; + ret = 0; + + return ret; +} + +static int +prism54_get_encode(struct net_device *ndev, struct iw_request_info *info, + struct iw_point *dwrq, char *extra) +{ + islpci_private *priv = netdev_priv(ndev); + struct obj_key *key; + u32 devindex, index = (dwrq->flags & IW_ENCODE_INDEX) - 1; + int rvalue; + union oid_res_t r; + + /* first get the flags */ + if ((rvalue = prism54_get_auth_algs(priv)) < 0) + return rvalue; + + dwrq->flags = rvalue; /* get the current device key index */ rvalue |= mgt_get_request(priv, DOT11_OID_DEFKEYID, 0, NULL, &r); @@ -1213,7 +1237,7 @@ prism54_get_txpower(struct net_device *n /* intersil firmware operates in 0.25 dBm (1/4 dBm) */ vwrq->value = (s32) r.u / 4; vwrq->fixed = 1; - /* radio is not turned of + /* radio is not turned off * btw: how is possible to turn off only the radio */ vwrq->disabled = 0; @@ -1247,14 +1271,14 @@ prism54_set_txpower(struct net_device *n } } -static int prism54_set_genie(struct net_device *ndev, - struct iw_request_info *info, - struct iw_point *data, char *extra) +static int +prism54_set_genie(struct net_device *ndev, struct iw_request_info *info, + struct iw_point *data, char *extra) { islpci_private *priv = netdev_priv(ndev); int alen, ret = 0; struct obj_attachment *attach; - + if (data->length > MAX_WPA_IE_LEN || (data->length && extra == NULL)) return -EINVAL; @@ -1267,28 +1291,25 @@ static int prism54_set_genie(struct net_ if (attach == NULL) return -ENOMEM; -#define WLAN_FC_TYPE_MGMT 0 -#define WLAN_FC_STYPE_ASSOC_REQ 0 -#define WLAN_FC_STYPE_REASSOC_REQ 2 - /* Note: endianness is covered by mgt_set_varlen */ - attach->type = (WLAN_FC_TYPE_MGMT << 2) | - (WLAN_FC_STYPE_ASSOC_REQ << 4); - attach->id = -1; - attach->size = priv->wpa_ie_len; - memcpy(attach->data, extra, priv->wpa_ie_len); - - ret = mgt_set_varlen(priv, DOT11_OID_ATTACHMENT, attach, - priv->wpa_ie_len); - if (ret == 0) { - attach->type = (WLAN_FC_TYPE_MGMT << 2) | - (WLAN_FC_STYPE_REASSOC_REQ << 4); - - ret = mgt_set_varlen(priv, DOT11_OID_ATTACHMENT, attach, - priv->wpa_ie_len); - if (ret == 0) - printk(KERN_DEBUG "%s: WPA IE Attachment was set\n", - ndev->name); + attach->id = -1; // global IE + attach->size = data->length; + memcpy(attach->data, extra, data->length); + + if (priv->iw_mode == IW_MODE_MASTER) { + attach->type = DOT11_PKT_BEACON; + ret = mgt_set_varlen(priv, DOT11_OID_ATTACHMENT, + attach, data->length); + attach->type = DOT11_PKT_PROBE_RESP; + ret |= mgt_set_varlen(priv, DOT11_OID_ATTACHMENT, + attach, data->length); + } + else { + attach->type = DOT11_PKT_ASSOC_REQ; + ret = mgt_set_varlen(priv, DOT11_OID_ATTACHMENT, attach, data->length); + attach->type = DOT11_PKT_REASSOC_REQ; + ret |= mgt_set_varlen(priv, DOT11_OID_ATTACHMENT, + attach, data->length); } kfree(attach); @@ -1296,9 +1317,9 @@ static int prism54_set_genie(struct net_ } -static int prism54_get_genie(struct net_device *ndev, - struct iw_request_info *info, - struct iw_point *data, char *extra) +static int +prism54_get_genie(struct net_device *ndev, struct iw_request_info *info, + struct iw_point *data, char *extra) { islpci_private *priv = netdev_priv(ndev); int len = priv->wpa_ie_len; @@ -1317,38 +1338,14 @@ static int prism54_get_genie(struct net_ return 0; } -static int prism54_set_auth(struct net_device *ndev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) +static int +prism54_set_auth(struct net_device *ndev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { islpci_private *priv = netdev_priv(ndev); struct iw_param *param = &wrqu->param; - u32 mlmelevel = 0, authen = 0, dot1x = 0; - u32 exunencrypt = 0, privinvoked = 0, wpa = 0; - u32 old_wpa; - int ret = 0; - union oid_res_t r; - - if (islpci_get_state(priv) < PRV_STATE_INIT) - return 0; - - /* first get the flags */ - down_write(&priv->mib_sem); - wpa = old_wpa = priv->wpa; - up_write(&priv->mib_sem); - ret = mgt_get_request(priv, DOT11_OID_AUTHENABLE, 0, NULL, &r); - authen = r.u; - ret = mgt_get_request(priv, DOT11_OID_PRIVACYINVOKED, 0, NULL, &r); - privinvoked = r.u; - ret = mgt_get_request(priv, DOT11_OID_EXUNENCRYPTED, 0, NULL, &r); - exunencrypt = r.u; - ret = mgt_get_request(priv, DOT11_OID_DOT1XENABLE, 0, NULL, &r); - dot1x = r.u; - ret = mgt_get_request(priv, DOT11_OID_MLMEAUTOLEVEL, 0, NULL, &r); - mlmelevel = r.u; - - if (ret < 0) - goto out; + u32 set = 0; + int rvalue = 0; switch (param->flags & IW_AUTH_INDEX) { case IW_AUTH_CIPHER_PAIRWISE: @@ -1356,103 +1353,69 @@ static int prism54_set_auth(struct net_d case IW_AUTH_KEY_MGMT: break; - case IW_AUTH_WPA_ENABLED: - /* Do the same thing as IW_AUTH_WPA_VERSION */ - if (param->value) { - wpa = 1; - privinvoked = 1; /* For privacy invoked */ - exunencrypt = 1; /* Filter out all unencrypted frames */ - dot1x = 0x01; /* To enable eap filter */ - mlmelevel = DOT11_MLME_EXTENDED; - authen = DOT11_AUTH_OS; /* Only WEP uses _SK and _BOTH */ - } else { - wpa = 0; - privinvoked = 0; - exunencrypt = 0; /* Do not filter un-encrypted data */ - dot1x = 0; - mlmelevel = DOT11_MLME_AUTO; - } - break; - case IW_AUTH_WPA_VERSION: - if (param->value & IW_AUTH_WPA_VERSION_DISABLED) { - wpa = 0; - privinvoked = 0; - exunencrypt = 0; /* Do not filter un-encrypted data */ - dot1x = 0; - mlmelevel = DOT11_MLME_AUTO; - } else { - if (param->value & IW_AUTH_WPA_VERSION_WPA) - wpa = 1; - else if (param->value & IW_AUTH_WPA_VERSION_WPA2) - wpa = 2; - privinvoked = 1; /* For privacy invoked */ - exunencrypt = 1; /* Filter out all unencrypted frames */ - dot1x = 0x01; /* To enable eap filter */ - mlmelevel = DOT11_MLME_EXTENDED; - authen = DOT11_AUTH_OS; /* Only WEP uses _SK and _BOTH */ - } + if (set & IW_AUTH_WPA_VERSION_WPA) + set = 1; + if (set & IW_AUTH_WPA_VERSION_WPA2) + set |= 2; + case IW_AUTH_WPA_ENABLED: + if (!set) + set = param->value ? 3 : 0; + rvalue = prism54_set_wpa(ndev, info, &set, extra); break; case IW_AUTH_RX_UNENCRYPTED_EAPOL: - dot1x = param->value ? 1 : 0; + set = param->value ? 1 : 0; + rvalue = mgt_set_request(priv, DOT11_OID_DOT1XENABLE, + 0, &set); break; case IW_AUTH_PRIVACY_INVOKED: - privinvoked = param->value ? 1 : 0; + set = param->value ? 1 : 0; + rvalue = mgt_set_request(priv, DOT11_OID_PRIVACYINVOKED, + 0, &set); + break; case IW_AUTH_DROP_UNENCRYPTED: - exunencrypt = param->value ? 1 : 0; + set = param->value ? 1 : 0; + rvalue = mgt_set_request(priv, DOT11_OID_EXUNENCRYPTED, + 0, &set); break; case IW_AUTH_80211_AUTH_ALG: - if (param->value & IW_AUTH_ALG_SHARED_KEY) { - /* Only WEP uses _SK and _BOTH */ - if (wpa > 0) { - ret = -EINVAL; - goto out; - } - authen = DOT11_AUTH_SK; - } else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) { - authen = DOT11_AUTH_OS; - } else { - ret = -EINVAL; - goto out; + switch (param->value) { + case IW_AUTH_ALG_OPEN_SYSTEM: + set = DOT11_AUTH_OS; + break; + case IW_AUTH_ALG_SHARED_KEY: + set = DOT11_AUTH_SK; + break; + default: + return -EINVAL; + break; } + rvalue = mgt_set_request(priv, DOT11_OID_AUTHENABLE, + 0, &set); break; default: - return -EOPNOTSUPP; + rvalue = -EOPNOTSUPP; + break; } - /* Set all the values */ - down_write(&priv->mib_sem); - priv->wpa = wpa; - up_write(&priv->mib_sem); - mgt_set_request(priv, DOT11_OID_AUTHENABLE, 0, &authen); - mgt_set_request(priv, DOT11_OID_PRIVACYINVOKED, 0, &privinvoked); - mgt_set_request(priv, DOT11_OID_EXUNENCRYPTED, 0, &exunencrypt); - mgt_set_request(priv, DOT11_OID_DOT1XENABLE, 0, &dot1x); - mgt_set_request(priv, DOT11_OID_MLMEAUTOLEVEL, 0, &mlmelevel); - -out: - return ret; + return rvalue; } -static int prism54_get_auth(struct net_device *ndev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) +static int +prism54_get_auth(struct net_device *ndev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) { islpci_private *priv = netdev_priv(ndev); struct iw_param *param = &wrqu->param; - u32 wpa = 0; - int ret = 0; union oid_res_t r; + u32 wpa = 0; + int rvalue = 0; - if (islpci_get_state(priv) < PRV_STATE_INIT) - return 0; - - /* first get the flags */ down_write(&priv->mib_sem); wpa = priv->wpa; up_write(&priv->mib_sem); @@ -1464,272 +1427,276 @@ static int prism54_get_auth(struct net_d /* * wpa_supplicant will control these internally */ - ret = -EOPNOTSUPP; - break; + rvalue = -EOPNOTSUPP; + break; case IW_AUTH_WPA_VERSION: - switch (wpa) { - case 1: - param->value = IW_AUTH_WPA_VERSION_WPA; - break; - case 2: - param->value = IW_AUTH_WPA_VERSION_WPA2; - break; - case 0: - default: + if (!wpa) param->value = IW_AUTH_WPA_VERSION_DISABLED; - break; - } + if (wpa & 1) + param->value = IW_AUTH_WPA_VERSION_WPA; + if (wpa & 2) + param->value |= IW_AUTH_WPA_VERSION_WPA2; + break; case IW_AUTH_DROP_UNENCRYPTED: - ret = mgt_get_request(priv, DOT11_OID_EXUNENCRYPTED, 0, NULL, &r); - if (ret >= 0) - param->value = r.u > 0 ? 1 : 0; + rvalue = mgt_get_request(priv, DOT11_OID_EXUNENCRYPTED, + 0, NULL, &r); + param->value = r.u; break; case IW_AUTH_80211_AUTH_ALG: - ret = mgt_get_request(priv, DOT11_OID_AUTHENABLE, 0, NULL, &r); - if (ret >= 0) { - switch (r.u) { - case DOT11_AUTH_OS: - param->value = IW_AUTH_ALG_OPEN_SYSTEM; - break; - case DOT11_AUTH_BOTH: - case DOT11_AUTH_SK: - param->value = IW_AUTH_ALG_SHARED_KEY; - case DOT11_AUTH_NONE: - default: - param->value = 0; - break; - } + rvalue = mgt_get_request(priv, DOT11_OID_AUTHENABLE, + 0, NULL, &r); + + switch (r.u) { + case DOT11_AUTH_OS: + param->value = IW_AUTH_ALG_OPEN_SYSTEM; + break; + case DOT11_AUTH_BOTH: + case DOT11_AUTH_SK: + param->value = IW_AUTH_ALG_SHARED_KEY; + break; + default: + param->value = 0; + rvalue = -EOPNOTSUPP; + break; } break; case IW_AUTH_WPA_ENABLED: - param->value = wpa > 0 ? 1 : 0; + param->value = wpa ? 0 : 1; break; case IW_AUTH_RX_UNENCRYPTED_EAPOL: - ret = mgt_get_request(priv, DOT11_OID_DOT1XENABLE, 0, NULL, &r); - if (ret >= 0) - param->value = r.u > 0 ? 1 : 0; + rvalue = mgt_get_request(priv, DOT11_OID_DOT1XENABLE, + 0, NULL, &r); + param->value = r.u; break; case IW_AUTH_PRIVACY_INVOKED: - ret = mgt_get_request(priv, DOT11_OID_PRIVACYINVOKED, 0, NULL, &r); - if (ret >= 0) - param->value = r.u > 0 ? 1 : 0; + rvalue = mgt_get_request(priv, DOT11_OID_PRIVACYINVOKED, + 0, NULL, &r); + param->value = r.u; break; default: return -EOPNOTSUPP; + break; } - return ret; + + return 0; } -static int prism54_set_encodeext(struct net_device *ndev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) +static int +prism54_set_encodeext(struct net_device *ndev, struct iw_request_info *info, + struct iw_point *dwrq, char *extra) { islpci_private *priv = netdev_priv(ndev); - struct iw_point *encoding = &wrqu->encoding; - struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; - int idx, alg = ext->alg, set_key = 1; + struct iw_encode_ext *enc = (struct iw_encode_ext *)extra; + struct obj_stakey* key; union oid_res_t r; - int authen = DOT11_AUTH_OS, invoke = 0, exunencrypt = 0; - int ret = 0; - - if (islpci_get_state(priv) < PRV_STATE_INIT) - return 0; - - /* Determine and validate the key index */ - idx = (encoding->flags & IW_ENCODE_INDEX) - 1; - if (idx) { - if (idx < 0 || idx > 3) - return -EINVAL; - } else { - ret = mgt_get_request(priv, DOT11_OID_DEFKEYID, 0, NULL, &r); - if (ret < 0) - goto out; - idx = r.u; - } + int index, key_type; + int ret = -EINVAL; - if (encoding->flags & IW_ENCODE_DISABLED) - alg = IW_ENCODE_ALG_NONE; + if (enc->key_len > (dwrq->length - sizeof(*enc))) { + return -EINVAL; + } - if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { - /* Only set transmit key index here, actual - * key is set below if needed. - */ - ret = mgt_set_request(priv, DOT11_OID_DEFKEYID, 0, &idx); - set_key = ext->key_len > 0 ? 1 : 0; - } + if (enc->addr.sa_family != ARPHRD_ETHER) { + return -EINVAL; + } - if (set_key) { - struct obj_key key = { DOT11_PRIV_WEP, 0, "" }; - switch (alg) { + switch (enc->alg) { case IW_ENCODE_ALG_NONE: + return 0; break; case IW_ENCODE_ALG_WEP: - if (ext->key_len > KEY_SIZE_WEP104) { - ret = -EINVAL; - goto out; - } - if (ext->key_len > KEY_SIZE_WEP40) - key.length = KEY_SIZE_WEP104; - else - key.length = KEY_SIZE_WEP40; + key_type = DOT11_PRIV_WEP; break; case IW_ENCODE_ALG_TKIP: - if (ext->key_len > KEY_SIZE_TKIP) { - ret = -EINVAL; - goto out; - } - key.type = DOT11_PRIV_TKIP; - key.length = KEY_SIZE_TKIP; + key_type = DOT11_PRIV_TKIP; + break; default: return -EINVAL; - } - - if (key.length) { - memset(key.key, 0, sizeof(key.key)); - memcpy(key.key, ext->key, ext->key_len); - ret = mgt_set_request(priv, DOT11_OID_DEFKEYX, idx, - &key); - if (ret < 0) - goto out; - } - } - - /* Read the flags */ - if (encoding->flags & IW_ENCODE_DISABLED) { - /* Encoding disabled, - * authen = DOT11_AUTH_OS; - * invoke = 0; - * exunencrypt = 0; */ - } - if (encoding->flags & IW_ENCODE_OPEN) { - /* Encode but accept non-encoded packets. No auth */ - invoke = 1; } - if (encoding->flags & IW_ENCODE_RESTRICTED) { - /* Refuse non-encoded packets. Auth */ - authen = DOT11_AUTH_BOTH; - invoke = 1; - exunencrypt = 1; + + index = dwrq->flags & IW_ENCODE_INDEX; + if ((index < 0) || (index > 3)) { + /* no index provided, so get the current one */ + ret = mgt_get_request(priv, DOT11_OID_DEFKEYID, 0, NULL, &r); + if (ret) + return ret; + index = r.u; } - /* do the change if requested */ - if (encoding->flags & IW_ENCODE_MODE) { - ret = mgt_set_request(priv, DOT11_OID_AUTHENABLE, 0, - &authen); - ret = mgt_set_request(priv, DOT11_OID_PRIVACYINVOKED, 0, - &invoke); - ret = mgt_set_request(priv, DOT11_OID_EXUNENCRYPTED, 0, - &exunencrypt); + key = kzalloc(sizeof(*key) + enc->key_len, GFP_KERNEL); + if (!key) + return -ENOMEM; + + + key->type = key_type; + key->length = enc->key_len; + key->keyid = index; + key->reserved = 0; + if ((!(enc->ext_flags & IW_ENCODE_EXT_GROUP_KEY)) || + memcmp(enc->addr.sa_data, "\xff\xff\xff\xff\xff\xff", ETH_ALEN)) + key->options = DOT11_STAKEY_OPTION_DEFAULTKEY; + memcpy(key->key, enc->key, key->length); + memcpy(key->address, enc->addr.sa_data, ETH_ALEN); + + ret = mgt_set_request(priv, DOT11_OID_STAKEY, 0, key); + kfree(key); + if (ret) + return ret; + + if (enc->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) { + struct obj_stasc *stasc; + stasc = kzalloc(sizeof(*stasc), GFP_KERNEL); + if (!stasc) + return -ENOMEM; + memcpy(stasc->address, enc->addr.sa_data, ETH_ALEN); + stasc->keyid = index; + stasc->tx_sc = 1; + memcpy(stasc->sc, enc->rx_seq, 6); + ret = mgt_set_request(priv, DOT11_OID_STASC, 0, stasc); + kfree(stasc); + if (ret) + return ret; } -out: + if (dwrq->flags & IW_ENCODE_MODE) + ret = prism54_set_auth_alg(priv, dwrq->flags); + return ret; } - -static int prism54_get_encodeext(struct net_device *ndev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) +static int +prism54_get_encodeext(struct net_device *ndev, + struct iw_request_info *info, struct iw_point *dwrq, char *extra) { islpci_private *priv = netdev_priv(ndev); - struct iw_point *encoding = &wrqu->encoding; - struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; - int idx, max_key_len; + struct iw_encode_ext *enc = (struct iw_encode_ext *)extra; + struct obj_stasc *stasc; union oid_res_t r; - int authen = DOT11_AUTH_OS, invoke = 0, exunencrypt = 0, wpa = 0; - int ret = 0; + int index; + int ret = -EINVAL; + int max_key_len; if (islpci_get_state(priv) < PRV_STATE_INIT) return 0; - /* first get the flags */ - ret = mgt_get_request(priv, DOT11_OID_AUTHENABLE, 0, NULL, &r); - authen = r.u; - ret = mgt_get_request(priv, DOT11_OID_PRIVACYINVOKED, 0, NULL, &r); - invoke = r.u; - ret = mgt_get_request(priv, DOT11_OID_EXUNENCRYPTED, 0, NULL, &r); - exunencrypt = r.u; - if (ret < 0) - goto out; + if (!capable(CAP_NET_ADMIN)) + return -EPERM; - max_key_len = encoding->length - sizeof(*ext); + max_key_len = dwrq->length - sizeof(*enc); if (max_key_len < 0) return -EINVAL; - idx = (encoding->flags & IW_ENCODE_INDEX) - 1; - if (idx) { - if (idx < 0 || idx > 3) - return -EINVAL; - } else { + index = (dwrq->flags & IW_ENCODE_INDEX) - 1; + if ((index < 0) || (index > 3)) { + /* no index provided, so get the current one */ ret = mgt_get_request(priv, DOT11_OID_DEFKEYID, 0, NULL, &r); - if (ret < 0) - goto out; - idx = r.u; - } - - encoding->flags = idx + 1; - memset(ext, 0, sizeof(*ext)); - - switch (authen) { - case DOT11_AUTH_BOTH: - case DOT11_AUTH_SK: - wrqu->encoding.flags |= IW_ENCODE_RESTRICTED; - case DOT11_AUTH_OS: - default: - wrqu->encoding.flags |= IW_ENCODE_OPEN; - break; + if (ret) + return ret; + index = r.u; } + memset(enc, 0, sizeof(*enc)); - down_write(&priv->mib_sem); - wpa = priv->wpa; - up_write(&priv->mib_sem); - - if (authen == DOT11_AUTH_OS && !exunencrypt && !invoke && !wpa) { - /* No encryption */ - ext->alg = IW_ENCODE_ALG_NONE; - ext->key_len = 0; - wrqu->encoding.flags |= IW_ENCODE_DISABLED; - } else { + if (enc->addr.sa_family != ARPHRD_ETHER) { + /* no specific key, just return the default stuff */ struct obj_key *key; - - ret = mgt_get_request(priv, DOT11_OID_DEFKEYX, idx, NULL, &r); - if (ret < 0) - goto out; + ret = mgt_get_request(priv, DOT11_OID_DEFKEYX, index, NULL, &r); key = r.ptr; - if (max_key_len < key->length) { - ret = -E2BIG; - goto out; + if (ret) { + kfree(key); + return ret; + } + + if (key->length > max_key_len) { + kfree(key); + return -E2BIG; } - memcpy(ext->key, key->key, key->length); - ext->key_len = key->length; - + + enc->key_len = key->length; switch (key->type) { - case DOT11_PRIV_TKIP: - ext->alg = IW_ENCODE_ALG_TKIP; + case DOT11_PRIV_WEP: + enc->alg = IW_ENCODE_ALG_WEP; break; + case DOT11_PRIV_TKIP: + enc->alg = IW_ENCODE_ALG_TKIP; + break; default: - case DOT11_PRIV_WEP: - ext->alg = IW_ENCODE_ALG_WEP; + kfree(key); + return -EINVAL; + break; + } + dwrq->flags |= IW_ENCODE_ENABLED; + memcpy(enc->key, key->key, enc->key_len); + dwrq->flags |= index +1; + + return ret; + } + else { + struct obj_stakey *key; + key = kzalloc(sizeof(*key), GFP_KERNEL); + if (!key) + return -ENOMEM; + + memcpy(key->address, enc->addr.sa_data, ETH_ALEN); + key->keyid = index; + ret = mgt_get_request(priv, DOT11_OID_STAKEY, 0, (void*)key, &r); + kfree(key); + key = (struct obj_stakey*)r.ptr; + if (ret) { + kfree(key); + return ret; + } + + if (key->length > max_key_len) { + kfree(key); + return -E2BIG; + } + + switch (key->type) { + case DOT11_PRIV_WEP: + enc->alg = IW_ENCODE_ALG_WEP; + break; + case DOT11_PRIV_TKIP: + enc->alg = IW_ENCODE_ALG_TKIP; + break; + default: + kfree(key); + return -EINVAL; break; } - wrqu->encoding.flags |= IW_ENCODE_ENABLED; + + enc->key_len = key->length; + dwrq->flags = index + 1; + memcpy(enc->key, key->key, key->length); + kfree(key); + + stasc = kzalloc(sizeof(*stasc), GFP_KERNEL); + if (!stasc) + return -ENOMEM; + + memcpy(stasc->address, enc->addr.sa_data, ETH_ALEN); + stasc->keyid = index; + stasc->tx_sc = 1; + ret = mgt_get_request(priv, DOT11_OID_STAKEY, 0, (void*)stasc, &r); + kfree(stasc); + + stasc = (struct obj_stasc*)r.ptr; + memcpy(enc->tx_seq, stasc->sc, 6); + kfree(stasc); + + enc->ext_flags |= IW_ENCODE_EXT_TX_SEQ_VALID; } -out: return ret; } - static int prism54_reset(struct net_device *ndev, struct iw_request_info *info, __u32 * uwrq, char *extra) @@ -2033,12 +2000,11 @@ format_event(islpci_private *priv, char { const u8 *a = mlme->address; int n = snprintf(dest, IW_CUSTOM_MAX, - "%s %s %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X %s (%2.2X)", + "%s %s %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X [%2.2x %2.2X %4.4X]", str, ((priv->iw_mode == IW_MODE_MASTER) ? "from" : "to"), a[0], a[1], a[2], a[3], a[4], a[5], - (error ? (mlme->code ? " : REJECTED " : " : ACCEPTED ") - : ""), mlme->code); + mlme->state, mlme->code, mlme->id); BUG_ON(n > IW_CUSTOM_MAX); *length = n; } @@ -2104,9 +2070,6 @@ struct ieee80211_beacon_phdr { u16 capab_info; } __attribute__ ((packed)); -#define WLAN_EID_GENERIC 0xdd -static u8 wpa_oid[4] = { 0x00, 0x50, 0xf2, 1 }; - #define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] #define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" @@ -2141,10 +2104,9 @@ prism54_wpa_bss_ie_add(islpci_private *p struct islpci_bss_wpa_ie, list); list_del(&bss->list); } else { - bss = kmalloc(sizeof (*bss), GFP_ATOMIC); + bss = kzalloc(sizeof (*bss), GFP_ATOMIC); if (bss != NULL) { priv->num_bss_wpa++; - memset(bss, 0, sizeof (*bss)); } } if (bss != NULL) { @@ -2236,8 +2198,14 @@ prism54_process_bss_data(islpci_private end = payload + len; while (pos < end) { if (pos + 2 + pos[1] > end) { - printk(KERN_DEBUG "Parsing Beacon/ProbeResp failed " - "for " MACSTR "\n", MAC2STR(addr)); + printk(KERN_DEBUG "Parsing %s failed " + "for " MACSTR "\n", (oid == DOT11_OID_BEACON ? "Beacon" : "ProbeResp"), MAC2STR(addr)); + return; + } + + /* Don't forget RSN/WPA2 ! */ + if (pos[0] == WLAN_EID_RSN && pos[1] > 4) { + prism54_wpa_bss_ie_add(priv, addr, pos, pos[1] + 2); return; } if (pos[0] == WLAN_EID_GENERIC && pos[1] >= 4 && @@ -2265,46 +2233,86 @@ handle_request(islpci_private *priv, str } static int +prism54_process_sta_trap(islpci_private *priv, enum oid_num_t oid, + struct obj_mlmeex* mlmeex) +{ + struct obj_mlme *mlme = (struct obj_mlme*)mlmeex; + int ret = 0; + + switch (oid) { + case DOT11_OID_DEAUTHENTICATEEX: + send_formatted_event(priv, "DeAuthenticate request", + mlme, 0); + break; + case DOT11_OID_AUTHENTICATEEX: + if (prism54_mac_accept(&priv->acl, mlmeex->address) && + (mlmeex->state == DOT11_STATE_AUTH)) { + + mlmeex->state = DOT11_STATE_ASSOCING; + mlmeex->code = 0; + mlmeex->size = 0; + ret = mgt_set_request(priv, DOT11_OID_ASSOCIATEEX, + 0, mlmeex); + if (ret) + return ret; + } + if (mlmeex->code != 0) + send_formatted_event(priv, "Authenticate request", mlme, 1); + break; + case DOT11_OID_DISASSOCIATEEX: + send_formatted_event(priv, "Disassociate request", mlme, 0); + break; + case DOT11_OID_ASSOCIATEEX: + if (mlmeex->code) + send_formatted_event(priv, "Associate request", mlme, 1); + break; + case DOT11_OID_REASSOCIATEEX: + if (mlmeex->code) + send_formatted_event(priv, "Reassociate request", + mlme, 1); + break; + default: + printk(KERN_INFO "%s: Unhandled OID %x, " + "please fill a bug-report!\n", priv->ndev->name, oid); + break; + } + return ret; +} + +static int prism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid, char *data) { struct obj_mlme *mlme = (struct obj_mlme *) data; struct obj_mlmeex *mlmeex = (struct obj_mlmeex *) data; - struct obj_mlmeex *confirm; - u8 wpa_ie[MAX_WPA_IE_LEN]; - int wpa_ie_len; - size_t len = 0; /* u16, better? */ - u8 *payload = NULL, *pos = NULL; - int ret; - - /* I think all trapable objects are listed here. - * Some oids have a EX version. The difference is that they are emitted - * in DOT11_MLME_EXTENDED mode (set with DOT11_OID_MLMEAUTOLEVEL) - * with more info. - * The few events already defined by the wireless tools are not really - * suited. We use the more flexible custom event facility. - */ - - if (oid >= DOT11_OID_BEACON) { - len = mlmeex->size; - payload = pos = mlmeex->data; - } + int ret = 0; + u8 *buf; /* I fear prism54_process_bss_data won't work with big endian data */ - if ((oid == DOT11_OID_BEACON) || (oid == DOT11_OID_PROBE)) - prism54_process_bss_data(priv, oid, mlmeex->address, - payload, len); mgt_le_to_cpu(isl_oid[oid].flags & OID_FLAG_TYPE, (void *) mlme); switch (oid) { + case DOT11_OID_BEACON: + case DOT11_OID_PROBE: + if (priv->iw_mode != IW_MODE_MASTER + && mlmeex->state != DOT11_STATE_AUTHING) + prism54_process_bss_data(priv, oid, mlmeex->address, + mlmeex->data, mlmeex->size); + break; case GEN_OID_LINKSTATE: link_changed(priv->ndev, (u32) *data); break; case DOT11_OID_MICFAILURE: - send_simple_event(priv, "Mic failure"); + buf = kmalloc(53, GFP_ATOMIC); // strlen + 1!); + snprintf(buf, 53, "MLME-MICHAELMICFAILURE.indication " + "addr=%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X", + mlmeex->address[0], mlmeex->address[1], mlmeex->address[2], + mlmeex->address[3], mlmeex->address[4], mlmeex->address[5]); + send_simple_event(priv, buf); + kfree(buf); break; case DOT11_OID_DEAUTHENTICATE: @@ -2330,163 +2338,12 @@ prism54_process_trap_helper(islpci_priva send_formatted_event(priv, "ReAssociate request", mlme, 1); break; - case DOT11_OID_BEACON: - send_formatted_event(priv, - "Received a beacon from an unkown AP", - mlme, 0); - break; - - case DOT11_OID_PROBE: - /* we received a probe from a client. */ - send_formatted_event(priv, "Received a probe from client", mlme, - 0); - break; - - /* Note : "mlme" is actually a "struct obj_mlmeex *" here, but this - * is backward compatible layout-wise with "struct obj_mlme". - */ - - case DOT11_OID_DEAUTHENTICATEEX: - send_formatted_event(priv, "DeAuthenticate request", mlme, 0); - break; - - case DOT11_OID_AUTHENTICATEEX: - handle_request(priv, mlme, oid); - send_formatted_event(priv, "Authenticate request (ex)", mlme, 1); - - if (priv->iw_mode != IW_MODE_MASTER - && mlmeex->state != DOT11_STATE_AUTHING) - break; - - confirm = kmalloc(sizeof(struct obj_mlmeex) + 6, GFP_ATOMIC); - - if (!confirm) - break; - - memcpy(&confirm->address, mlmeex->address, ETH_ALEN); - printk(KERN_DEBUG "Authenticate from: address:\t%02x:%02x:%02x:%02x:%02x:%02x\n", - mlmeex->address[0], - mlmeex->address[1], - mlmeex->address[2], - mlmeex->address[3], - mlmeex->address[4], - mlmeex->address[5] - ); - confirm->id = -1; /* or mlmeex->id ? */ - confirm->state = 0; /* not used */ - confirm->code = 0; - confirm->size = 6; - confirm->data[0] = 0x00; - confirm->data[1] = 0x00; - confirm->data[2] = 0x02; - confirm->data[3] = 0x00; - confirm->data[4] = 0x00; - confirm->data[5] = 0x00; - - ret = mgt_set_varlen(priv, DOT11_OID_ASSOCIATEEX, confirm, 6); - - kfree(confirm); - if (ret) - return ret; - break; - - case DOT11_OID_DISASSOCIATEEX: - send_formatted_event(priv, "Disassociate request (ex)", mlme, 0); - break; - - case DOT11_OID_ASSOCIATEEX: - handle_request(priv, mlme, oid); - send_formatted_event(priv, "Associate request (ex)", mlme, 1); - - if (priv->iw_mode != IW_MODE_MASTER - && mlmeex->state != DOT11_STATE_ASSOCING) - break; - - confirm = kmalloc(sizeof(struct obj_mlmeex), GFP_ATOMIC); - - if (!confirm) - break; - - memcpy(&confirm->address, mlmeex->address, ETH_ALEN); - - confirm->id = ((struct obj_mlmeex *)mlme)->id; - confirm->state = 0; /* not used */ - confirm->code = 0; - - wpa_ie_len = prism54_wpa_bss_ie_get(priv, mlmeex->address, wpa_ie); - - if (!wpa_ie_len) { - printk(KERN_DEBUG "No WPA IE found from " - "address:\t%02x:%02x:%02x:%02x:%02x:%02x\n", - mlmeex->address[0], - mlmeex->address[1], - mlmeex->address[2], - mlmeex->address[3], - mlmeex->address[4], - mlmeex->address[5] - ); - kfree(confirm); - break; - } - - confirm->size = wpa_ie_len; - memcpy(&confirm->data, wpa_ie, wpa_ie_len); - - mgt_set_varlen(priv, oid, confirm, wpa_ie_len); - - kfree(confirm); - - break; - - case DOT11_OID_REASSOCIATEEX: - handle_request(priv, mlme, oid); - send_formatted_event(priv, "Reassociate request (ex)", mlme, 1); - - if (priv->iw_mode != IW_MODE_MASTER - && mlmeex->state != DOT11_STATE_ASSOCING) - break; - - confirm = kmalloc(sizeof(struct obj_mlmeex), GFP_ATOMIC); - - if (!confirm) - break; - - memcpy(&confirm->address, mlmeex->address, ETH_ALEN); - - confirm->id = mlmeex->id; - confirm->state = 0; /* not used */ - confirm->code = 0; - - wpa_ie_len = prism54_wpa_bss_ie_get(priv, mlmeex->address, wpa_ie); - - if (!wpa_ie_len) { - printk(KERN_DEBUG "No WPA IE found from " - "address:\t%02x:%02x:%02x:%02x:%02x:%02x\n", - mlmeex->address[0], - mlmeex->address[1], - mlmeex->address[2], - mlmeex->address[3], - mlmeex->address[4], - mlmeex->address[5] - ); - kfree(confirm); - break; - } - - confirm->size = wpa_ie_len; - memcpy(&confirm->data, wpa_ie, wpa_ie_len); - - mgt_set_varlen(priv, oid, confirm, wpa_ie_len); - - kfree(confirm); - - break; - default: - return -EINVAL; + ret = prism54_process_sta_trap(priv, oid, mlmeex); + break; } - return 0; + return ret; } /* @@ -2522,368 +2379,33 @@ prism54_set_mac_address(struct net_devic return ret; } -/* Note: currently, use hostapd ioctl from the Host AP driver for WPA - * support. This is to be replaced with Linux wireless extensions once they - * get WPA support. */ - -/* Note II: please leave all this together as it will be easier to remove later, - * once wireless extensions add WPA support -mcgrof */ - -/* PRISM54_HOSTAPD ioctl() cmd: */ -enum { - PRISM2_SET_ENCRYPTION = 6, - PRISM2_HOSTAPD_SET_GENERIC_ELEMENT = 12, - PRISM2_HOSTAPD_MLME = 13, - PRISM2_HOSTAPD_SCAN_REQ = 14, -}; - -#define PRISM54_SET_WPA SIOCIWFIRSTPRIV+12 -#define PRISM54_HOSTAPD SIOCIWFIRSTPRIV+25 -#define PRISM54_DROP_UNENCRYPTED SIOCIWFIRSTPRIV+26 - -#define PRISM2_HOSTAPD_MAX_BUF_SIZE 1024 -#define PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN \ -((int) (&((struct prism2_hostapd_param *) 0)->u.generic_elem.data)) - -/* Maximum length for algorithm names (-1 for nul termination) - * used in ioctl() */ -#define HOSTAP_CRYPT_ALG_NAME_LEN 16 - -struct prism2_hostapd_param { - u32 cmd; - u8 sta_addr[ETH_ALEN]; - union { - struct { - u8 alg[HOSTAP_CRYPT_ALG_NAME_LEN]; - u32 flags; - u32 err; - u8 idx; - u8 seq[8]; /* sequence counter (set: RX, get: TX) */ - u16 key_len; - u8 key[0]; - } crypt; - struct { - u8 len; - u8 data[0]; - } generic_elem; - struct { -#define MLME_STA_DEAUTH 0 -#define MLME_STA_DISASSOC 1 - u16 cmd; - u16 reason_code; - } mlme; - struct { - u8 ssid_len; - u8 ssid[32]; - } scan_req; - } u; -}; - - -static int -prism2_ioctl_set_encryption(struct net_device *dev, - struct prism2_hostapd_param *param, - int param_len) -{ - islpci_private *priv = netdev_priv(dev); - int rvalue = 0, force = 0; - int authen = DOT11_AUTH_OS, invoke = 0, exunencrypt = 0; - union oid_res_t r; - - /* with the new API, it's impossible to get a NULL pointer. - * New version of iwconfig set the IW_ENCODE_NOKEY flag - * when no key is given, but older versions don't. */ - - if (param->u.crypt.key_len > 0) { - /* we have a key to set */ - int index = param->u.crypt.idx; - int current_index; - struct obj_key key = { DOT11_PRIV_TKIP, 0, "" }; - - /* get the current key index */ - rvalue = mgt_get_request(priv, DOT11_OID_DEFKEYID, 0, NULL, &r); - current_index = r.u; - /* Verify that the key is not marked as invalid */ - if (!(param->u.crypt.flags & IW_ENCODE_NOKEY)) { - key.length = param->u.crypt.key_len > sizeof (param->u.crypt.key) ? - sizeof (param->u.crypt.key) : param->u.crypt.key_len; - memcpy(key.key, param->u.crypt.key, key.length); - if (key.length == 32) - /* we want WPA-PSK */ - key.type = DOT11_PRIV_TKIP; - if ((index < 0) || (index > 3)) - /* no index provided use the current one */ - index = current_index; - - /* now send the key to the card */ - rvalue |= - mgt_set_request(priv, DOT11_OID_DEFKEYX, index, - &key); - } - /* - * If a valid key is set, encryption should be enabled - * (user may turn it off later). - * This is also how "iwconfig ethX key on" works - */ - if ((index == current_index) && (key.length > 0)) - force = 1; - } else { - int index = (param->u.crypt.flags & IW_ENCODE_INDEX) - 1; - if ((index >= 0) && (index <= 3)) { - /* we want to set the key index */ - rvalue |= - mgt_set_request(priv, DOT11_OID_DEFKEYID, 0, - &index); - } else { - if (!param->u.crypt.flags & IW_ENCODE_MODE) { - /* we cannot do anything. Complain. */ - return -EINVAL; - } - } - } - /* now read the flags */ - if (param->u.crypt.flags & IW_ENCODE_DISABLED) { - /* Encoding disabled, - * authen = DOT11_AUTH_OS; - * invoke = 0; - * exunencrypt = 0; */ - } - if (param->u.crypt.flags & IW_ENCODE_OPEN) - /* Encode but accept non-encoded packets. No auth */ - invoke = 1; - if ((param->u.crypt.flags & IW_ENCODE_RESTRICTED) || force) { - /* Refuse non-encoded packets. Auth */ - authen = DOT11_AUTH_BOTH; - invoke = 1; - exunencrypt = 1; - } - /* do the change if requested */ - if ((param->u.crypt.flags & IW_ENCODE_MODE) || force) { - rvalue |= - mgt_set_request(priv, DOT11_OID_AUTHENABLE, 0, &authen); - rvalue |= - mgt_set_request(priv, DOT11_OID_PRIVACYINVOKED, 0, &invoke); - rvalue |= - mgt_set_request(priv, DOT11_OID_EXUNENCRYPTED, 0, - &exunencrypt); - } - return rvalue; -} - -static int -prism2_ioctl_set_generic_element(struct net_device *ndev, - struct prism2_hostapd_param *param, - int param_len) -{ - islpci_private *priv = netdev_priv(ndev); - int max_len, len, alen, ret=0; - struct obj_attachment *attach; - - len = param->u.generic_elem.len; - max_len = param_len - PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN; - if (max_len < 0 || max_len < len) - return -EINVAL; - - alen = sizeof(*attach) + len; - attach = kmalloc(alen, GFP_KERNEL); - if (attach == NULL) - return -ENOMEM; - - memset(attach, 0, alen); -#define WLAN_FC_TYPE_MGMT 0 -#define WLAN_FC_STYPE_ASSOC_REQ 0 -#define WLAN_FC_STYPE_REASSOC_REQ 2 - - /* Note: endianness is covered by mgt_set_varlen */ - - attach->type = (WLAN_FC_TYPE_MGMT << 2) | - (WLAN_FC_STYPE_ASSOC_REQ << 4); - attach->id = -1; - attach->size = len; - memcpy(attach->data, param->u.generic_elem.data, len); - - ret = mgt_set_varlen(priv, DOT11_OID_ATTACHMENT, attach, len); - - if (ret == 0) { - attach->type = (WLAN_FC_TYPE_MGMT << 2) | - (WLAN_FC_STYPE_REASSOC_REQ << 4); - - ret = mgt_set_varlen(priv, DOT11_OID_ATTACHMENT, attach, len); - - if (ret == 0) - printk(KERN_DEBUG "%s: WPA IE Attachment was set\n", - ndev->name); - } - - kfree(attach); - return ret; - -} - -static int -prism2_ioctl_mlme(struct net_device *dev, struct prism2_hostapd_param *param) -{ - return -EOPNOTSUPP; -} - -static int -prism2_ioctl_scan_req(struct net_device *ndev, - struct prism2_hostapd_param *param) -{ - islpci_private *priv = netdev_priv(ndev); - int i, rvalue; - struct obj_bsslist *bsslist; - u32 noise = 0; - char *extra = ""; - char *current_ev = "foo"; - union oid_res_t r; - - if (islpci_get_state(priv) < PRV_STATE_INIT) { - /* device is not ready, fail gently */ - return 0; - } - - /* first get the noise value. We will use it to report the link quality */ - rvalue = mgt_get_request(priv, DOT11_OID_NOISEFLOOR, 0, NULL, &r); - noise = r.u; - - /* Ask the device for a list of known bss. We can report at most - * IW_MAX_AP=64 to the range struct. But the device won't repport anything - * if you change the value of IWMAX_BSS=24. - */ - rvalue |= mgt_get_request(priv, DOT11_OID_BSSLIST, 0, NULL, &r); - bsslist = r.ptr; - - /* ok now, scan the list and translate its info */ - for (i = 0; i < min(IW_MAX_AP, (int) bsslist->nr); i++) - current_ev = prism54_translate_bss(ndev, current_ev, - extra + IW_SCAN_MAX_DATA, - &(bsslist->bsslist[i]), - noise); - kfree(bsslist); - - return rvalue; -} - -static int -prism54_hostapd(struct net_device *ndev, struct iw_point *p) -{ - struct prism2_hostapd_param *param; - int ret = 0; - u32 uwrq; - - printk(KERN_DEBUG "prism54_hostapd - len=%d\n", p->length); - if (p->length < sizeof(struct prism2_hostapd_param) || - p->length > PRISM2_HOSTAPD_MAX_BUF_SIZE || !p->pointer) - return -EINVAL; - - param = (struct prism2_hostapd_param *) kmalloc(p->length, GFP_KERNEL); - if (param == NULL) - return -ENOMEM; - - if (copy_from_user(param, p->pointer, p->length)) { - kfree(param); - return -EFAULT; - } - - switch (param->cmd) { - case PRISM2_SET_ENCRYPTION: - printk(KERN_DEBUG "%s: Caught WPA supplicant set encryption request\n", - ndev->name); - ret = prism2_ioctl_set_encryption(ndev, param, p->length); - break; - case PRISM2_HOSTAPD_SET_GENERIC_ELEMENT: - printk(KERN_DEBUG "%s: Caught WPA supplicant set WPA IE request\n", - ndev->name); - ret = prism2_ioctl_set_generic_element(ndev, param, - p->length); - break; - case PRISM2_HOSTAPD_MLME: - printk(KERN_DEBUG "%s: Caught WPA supplicant MLME request\n", - ndev->name); - ret = prism2_ioctl_mlme(ndev, param); - break; - case PRISM2_HOSTAPD_SCAN_REQ: - printk(KERN_DEBUG "%s: Caught WPA supplicant scan request\n", - ndev->name); - ret = prism2_ioctl_scan_req(ndev, param); - break; - case PRISM54_SET_WPA: - printk(KERN_DEBUG "%s: Caught WPA supplicant wpa init request\n", - ndev->name); - uwrq = 1; - ret = prism54_set_wpa(ndev, NULL, &uwrq, NULL); - break; - case PRISM54_DROP_UNENCRYPTED: - printk(KERN_DEBUG "%s: Caught WPA drop unencrypted request\n", - ndev->name); -#if 0 - uwrq = 0x01; - mgt_set(priv, DOT11_OID_EXUNENCRYPTED, &uwrq); - down_write(&priv->mib_sem); - mgt_commit(priv); - up_write(&priv->mib_sem); -#endif - /* Not necessary, as set_wpa does it, should we just do it here though? */ - ret = 0; - break; - default: - printk(KERN_DEBUG "%s: Caught a WPA supplicant request that is not supported\n", - ndev->name); - ret = -EOPNOTSUPP; - break; - } - - if (ret == 0 && copy_to_user(p->pointer, param, p->length)) - ret = -EFAULT; - - kfree(param); - - return ret; -} - static int prism54_set_wpa(struct net_device *ndev, struct iw_request_info *info, __u32 * uwrq, char *extra) { islpci_private *priv = netdev_priv(ndev); - u32 mlme, authen, dot1x, filter, wep; + u32 mlme, dot1x; if (islpci_get_state(priv) < PRV_STATE_INIT) return 0; - wep = 1; /* For privacy invoked */ - filter = 1; /* Filter out all unencrypted frames */ - dot1x = 0x01; /* To enable eap filter */ - mlme = DOT11_MLME_EXTENDED; - authen = DOT11_AUTH_OS; /* Only WEP uses _SK and _BOTH */ + dot1x = 0; // disable global filtering + mlme = DOT11_MLME_AUTO; down_write(&priv->mib_sem); priv->wpa = *uwrq; - switch (priv->wpa) { - default: - case 0: /* Clears/disables WPA and friends */ - wep = 0; - filter = 0; /* Do not filter un-encrypted data */ - dot1x = 0; - mlme = DOT11_MLME_AUTO; - printk("%s: Disabling WPA\n", ndev->name); - break; - case 2: - case 1: /* WPA */ - printk("%s: Enabling WPA\n", ndev->name); - break; + if (priv->wpa) { + if (priv->iw_mode == IW_MODE_MASTER) + dot1x = 1; + mlme = DOT11_MLME_EXTENDED; } up_write(&priv->mib_sem); - mgt_set_request(priv, DOT11_OID_AUTHENABLE, 0, &authen); - mgt_set_request(priv, DOT11_OID_PRIVACYINVOKED, 0, &wep); - mgt_set_request(priv, DOT11_OID_EXUNENCRYPTED, 0, &filter); mgt_set_request(priv, DOT11_OID_DOT1XENABLE, 0, &dot1x); mgt_set_request(priv, DOT11_OID_MLMEAUTOLEVEL, 0, &mlme); - return 0; + return prism54_set_auth_alg(priv, IW_ENCODE_OPEN); } static int @@ -2891,7 +2413,9 @@ prism54_get_wpa(struct net_device *ndev, __u32 * uwrq, char *extra) { islpci_private *priv = netdev_priv(ndev); + down_write(&priv->mib_sem); *uwrq = priv->wpa; + up_write(&priv->mib_sem); return 0; } @@ -3026,6 +2550,56 @@ prism54_set_spy(struct net_device *ndev, return iw_handler_set_spy(ndev, info, uwrq, extra); } +static int +prism54_send_mlme(struct net_device *ndev, struct iw_request_info *info, + struct iw_mlme *dwrq, char *extra) +{ + islpci_private *priv = netdev_priv(ndev); + struct obj_mlmeex mlmeex; + struct obj_sta *sta; + union oid_res_t r; + int ret = 0; + + if (dwrq->addr.sa_family != ARPHRD_ETHER) + return -EINVAL; + + /* get sta-id */ + sta = (struct obj_sta*)kmalloc(sizeof(struct obj_sta), GFP_KERNEL); + if (!sta) + return -ENOMEM; + + memcpy(sta->address, dwrq->addr.sa_data, ETH_ALEN); + ret = mgt_get_request(priv, DOT11_OID_CLIENTFIND, 0, sta, &r); + kfree(sta); + + sta = r.ptr; + memcpy(mlmeex.address, dwrq->addr.sa_data, ETH_ALEN); + + if (sta->node >= 1) + mlmeex.id = sta->node; + else + mlmeex.id = -1; + + mlmeex.code = dwrq->reason_code; + mlmeex.size = 0; + + kfree(r.ptr); + switch (dwrq->cmd) { + case IW_MLME_DEAUTH: + mlmeex.state = DOT11_STATE_NONE; + return mgt_set_request(priv, DOT11_OID_DEAUTHENTICATE, + 0, &mlmeex); + break; + case IW_MLME_DISASSOC: + mlmeex.state = DOT11_STATE_NONE; + return mgt_set_request(priv, DOT11_OID_DISASSOCIATE, + 0, &mlmeex); + break; + } + + return -EOPNOTSUPP; +} + static const iw_handler prism54_handler[] = { (iw_handler) prism54_commit, /* SIOCSIWCOMMIT */ (iw_handler) prism54_get_name, /* SIOCGIWNAME */ @@ -3049,7 +2623,7 @@ static const iw_handler prism54_handler[ iw_handler_get_thrspy, /* SIOCGIWTHRSPY */ (iw_handler) prism54_set_wap, /* SIOCSIWAP */ (iw_handler) prism54_get_wap, /* SIOCGIWAP */ - (iw_handler) NULL, /* -- hole -- */ + (iw_handler) prism54_send_mlme, /* SIOCSIWMLME */ (iw_handler) NULL, /* SIOCGIWAPLIST depreciated */ (iw_handler) prism54_set_scan, /* SIOCSIWSCAN */ (iw_handler) prism54_get_scan, /* SIOCGIWSCAN */ @@ -3073,15 +2647,15 @@ static const iw_handler prism54_handler[ (iw_handler) prism54_get_encode, /* SIOCGIWENCODE */ (iw_handler) NULL, /* SIOCSIWPOWER */ (iw_handler) NULL, /* SIOCGIWPOWER */ - NULL, /* -- hole -- */ - NULL, /* -- hole -- */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* -- hole -- */ (iw_handler) prism54_set_genie, /* SIOCSIWGENIE */ (iw_handler) prism54_get_genie, /* SIOCGIWGENIE */ (iw_handler) prism54_set_auth, /* SIOCSIWAUTH */ (iw_handler) prism54_get_auth, /* SIOCGIWAUTH */ - (iw_handler) prism54_set_encodeext, /* SIOCSIWENCODEEXT */ - (iw_handler) prism54_get_encodeext, /* SIOCGIWENCODEEXT */ - NULL, /* SIOCSIWPMKSA */ + (iw_handler) prism54_set_encodeext, /* SIOCSIWENCODEEXT */ + (iw_handler) prism54_get_encodeext, /* SIOCGIWENCODEEXT */ + (iw_handler) NULL /* SIOCSIWPMKSA */ }; /* The low order bit identify a SET (0) or a GET (1) ioctl. */ @@ -3260,14 +2834,5 @@ const struct iw_handler_def prism54_hand int prism54_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) { - struct iwreq *wrq = (struct iwreq *) rq; - int ret = -1; - switch (cmd) { - case PRISM54_HOSTAPD: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - ret = prism54_hostapd(ndev, &wrq->u.data); - return ret; - } return -EOPNOTSUPP; } diff -Nurp orig/isl_ioctl.h kernel/isl_ioctl.h --- orig/isl_ioctl.h 2006-09-28 21:13:25.000000000 +0200 +++ kernel/isl_ioctl.h 2006-09-29 20:31:07.000000000 +0200 @@ -22,12 +22,14 @@ #ifndef _ISL_IOCTL_H #define _ISL_IOCTL_H +#include <net/iw_handler.h> /* New driver API */ #include "islpci_mgt.h" #include "islpci_dev.h" -#include <net/iw_handler.h> /* New driver API */ +#define SUPPORTED_WIRELESS_EXT 21 -#define SUPPORTED_WIRELESS_EXT 19 +#define PRISM54_SET_WPA SIOCIWFIRSTPRIV+12 +#define PRISM54_DROP_UNENCRYPTED SIOCIWFIRSTPRIV+26 void prism54_mib_init(islpci_private *); @@ -48,4 +50,5 @@ int prism54_ioctl(struct net_device *, s extern const struct iw_handler_def prism54_handler_def; + #endif /* _ISL_IOCTL_H */ diff -Nurp orig/isl_oid.h kernel/isl_oid.h --- orig/isl_oid.h 2006-09-20 05:42:06.000000000 +0200 +++ kernel/isl_oid.h 2006-09-29 20:26:45.000000000 +0200 @@ -4,6 +4,7 @@ * Copyright (C) 2003 Herbert Valerio Riedel <hvr@xxxxxxx> * Copyright (C) 2004 Luis R. Rodriguez <mcgrof@xxxxxxxxxxxxxxxxxx> * Copyright (C) 2004 Aurelien Alleaume <slts@xxxxxxx> + * Copyright (C) 2006 Christian Lamparter <chunkeey@xxxxxx> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,6 +29,8 @@ * with the device firmware */ +#define MAX_KEY_LEN 32 + struct obj_ssid { u8 length; char octets[33]; @@ -36,18 +39,28 @@ struct obj_ssid { struct obj_key { u8 type; /* dot11_priv_t */ u8 length; - char key[32]; + char key[MAX_KEY_LEN]; +} __attribute__ ((packed)); + +struct obj_stakey { + u8 address[ETH_ALEN]; + u8 keyid; + u8 reserved; + u16 options; // DOT11_STAKEY_OPTION_DEFAULTKEY + u8 type; /* dot11_priv_t */ + u8 length; + char key[MAX_KEY_LEN]; } __attribute__ ((packed)); struct obj_mlme { - u8 address[6]; + u8 address[ETH_ALEN]; u16 id; u16 state; u16 code; } __attribute__ ((packed)); struct obj_mlmeex { - u8 address[6]; + u8 address[ETH_ALEN]; u16 id; u16 state; u16 code; @@ -61,7 +74,7 @@ struct obj_buffer { } __attribute__ ((packed)); struct obj_bss { - u8 address[6]; + u8 address[ETH_ALEN]; int:16; /* padding */ char state; @@ -99,6 +112,25 @@ struct obj_attachment { char data[0]; } __attribute__((packed)); +struct obj_stasc { + char address[ETH_ALEN]; + char keyid; + char tx_sc; + char sc[6]; +} __attribute__ ((packed)); + +struct obj_sta { + u8 address[ETH_ALEN]; + int: 16; + u8 state; + u8 node; // STA AID + u16 age; + u8 reserved1; + u8 rssi; + u8 rate; + u8 reserved2; +} __attribute__ ((packed)); + /* * in case everything's ok, the inlined function below will be * optimized away by the compiler... @@ -114,6 +146,10 @@ __bug_on_wrong_struct_sizes(void) BUG_ON(sizeof (struct obj_bss) != 60); BUG_ON(sizeof (struct obj_bsslist) != 4); BUG_ON(sizeof (struct obj_frequencies) != 2); + BUG_ON(sizeof (struct obj_sta) != 16); + BUG_ON(sizeof (struct obj_stasc) != 14); + BUG_ON(sizeof (struct obj_stakey) != 44); + BUG_ON(sizeof (struct obj_attachment) != 6); } enum dot11_state_t { @@ -121,7 +157,7 @@ enum dot11_state_t { DOT11_STATE_AUTHING = 1, DOT11_STATE_AUTH = 2, DOT11_STATE_ASSOCING = 3, - + DOT11_STATE_REASSOC = 4, DOT11_STATE_ASSOC = 5, DOT11_STATE_IBSS = 6, DOT11_STATE_WDS = 7 @@ -310,6 +346,7 @@ enum oid_num_t { GEN_OID_MIBOP, GEN_OID_OPTIONS, GEN_OID_LEDCONFIG, + GEN_OID_COMMIT, /* 802.11 */ DOT11_OID_BSSTYPE, @@ -466,31 +503,32 @@ enum oid_num_t { OID_NUM_LAST }; -#define OID_FLAG_CACHED 0x80 -#define OID_FLAG_TYPE 0x7f - -#define OID_TYPE_U32 0x01 -#define OID_TYPE_SSID 0x02 -#define OID_TYPE_KEY 0x03 -#define OID_TYPE_BUFFER 0x04 -#define OID_TYPE_BSS 0x05 -#define OID_TYPE_BSSLIST 0x06 -#define OID_TYPE_FREQUENCIES 0x07 -#define OID_TYPE_MLME 0x08 -#define OID_TYPE_MLMEEX 0x09 -#define OID_TYPE_ADDR 0x0A -#define OID_TYPE_RAW 0x0B -#define OID_TYPE_ATTACH 0x0C +enum oid_types_t { + OID_TYPE_U32 = 0x01, + OID_TYPE_SSID = 0x02, + OID_TYPE_KEY = 0x03, + OID_TYPE_BUFFER = 0x04, + OID_TYPE_BSS = 0x05, + OID_TYPE_BSSLIST = 0x06, + OID_TYPE_FREQUENCIES = 0x07, + OID_TYPE_MLME = 0x08, + OID_TYPE_MLMEEX = 0x09, + OID_TYPE_ADDR = 0x0A, + OID_TYPE_RAW = 0x0B, + OID_TYPE_ATTACH = 0x0C, + OID_TYPE_STASC = 0x0D, + OID_TYPE_STAKEY = 0x0E, + OID_TYPE_STAINFO = 0x0F, -/* OID_TYPE_MLMEEX is special because of a variable size field when sending. - * Not yet implemented (not used in driver anyway). - */ + OID_FLAG_CACHED = 0x80, + OID_FLAG_TYPE = 0x7f +}; struct oid_t { enum oid_num_t oid; short range; /* to define a range of oid */ short size; /* max size of the associated data */ - char flags; + enum oid_types_t flags; }; union oid_res_t { @@ -503,5 +541,18 @@ union oid_res_t { #define IWMAX_FREQ 30 #define PRIV_STR_SIZE 1024 +enum dot11_pkt_t { + DOT11_PKT_ASSOC_REQ = 0x00, + DOT11_PKT_ASSOC_RESP = 0x10, + DOT11_PKT_REASSOC_REQ = 0x20, + DOT11_PKT_REASSOC_RESP = 0x30, + DOT11_PKT_PROBE_RESP = 0x50, + DOT11_PKT_BEACON = 0x80 +}; + +enum dot11_stakey_opt_t { + DOT11_STAKEY_OPTION_DEFAULTKEY = 0x0001 +}; + #endif /* !defined(_ISL_OID_H) */ /* EOF */ diff -Nurp orig/islpci_dev.c kernel/islpci_dev.c --- orig/islpci_dev.c 2006-09-28 21:13:25.000000000 +0200 +++ kernel/islpci_dev.c 2006-09-28 23:42:47.000000000 +0200 @@ -453,6 +453,7 @@ islpci_upload_fw(islpci_private *priv) printk(KERN_DEBUG "%s: uploading firmware...\n", priv->ndev->name); + request_module("firmware_class"); rc = isl_upload_firmware(priv); if (rc) { /* error uploading the firmware */ diff -Nurp orig/islpci_dev.h kernel/islpci_dev.h --- orig/islpci_dev.h 2006-09-28 21:13:25.000000000 +0200 +++ kernel/islpci_dev.h 2006-09-29 14:23:43.000000000 +0200 @@ -72,7 +72,6 @@ struct islpci_bss_wpa_ie { u8 bssid[ETH_ALEN]; u8 wpa_ie[MAX_WPA_IE_LEN]; size_t wpa_ie_len; - }; typedef struct { diff -Nurp orig/islpci_mgt.h kernel/islpci_mgt.h --- orig/islpci_mgt.h 2006-09-20 05:42:06.000000000 +0200 +++ kernel/islpci_mgt.h 2006-09-29 14:22:05.000000000 +0200 @@ -65,8 +65,8 @@ extern int pc_debug; #define CARD_DEFAULT_WEP 0 #define CARD_DEFAULT_FILTER 0 #define CARD_DEFAULT_WDS 0 -#define CARD_DEFAULT_AUTHEN DOT11_AUTH_OS -#define CARD_DEFAULT_DOT1X 0 +#define CARD_DEFAULT_AUTHEN DOT11_AUTH_OS +#define CARD_DEFAULT_DOT1X 0 #define CARD_DEFAULT_MLME_MODE DOT11_MLME_AUTO #define CARD_DEFAULT_CONFORMANCE OID_INL_CONFORMANCE_NONE #define CARD_DEFAULT_PROFILE DOT11_PROFILE_MIXED_G_WIFI diff -Nurp orig/oid_mgt.c kernel/oid_mgt.c --- orig/oid_mgt.c 2006-09-20 05:42:06.000000000 +0200 +++ kernel/oid_mgt.c 2006-09-29 20:27:45.000000000 +0200 @@ -59,7 +59,8 @@ struct oid_t isl_oid[] = { OID_UNKNOWN(GEN_OID_MIBOP, 0x00000003), OID_UNKNOWN(GEN_OID_OPTIONS, 0x00000004), OID_UNKNOWN(GEN_OID_LEDCONFIG, 0x00000005), - + OID_U32(GEN_OID_COMMIT, 0x0000000d), + /* 802.11 */ OID_U32_C(DOT11_OID_BSSTYPE, 0x10000000), OID_STRUCT_C(DOT11_OID_BSSID, 0x10000001, u8[6], OID_TYPE_RAW), @@ -85,9 +86,9 @@ struct oid_t isl_oid[] = { OID_U32_C(DOT11_OID_DEFKEYID, 0x12000003), [DOT11_OID_DEFKEYX] = {0x12000004, 3, sizeof (struct obj_key), OID_FLAG_CACHED | OID_TYPE_KEY}, /* DOT11_OID_DEFKEY1,...DOT11_OID_DEFKEY4 */ - OID_UNKNOWN(DOT11_OID_STAKEY, 0x12000008), + OID_STRUCT(DOT11_OID_STAKEY, 0x12000008, struct obj_stakey, OID_TYPE_STAKEY), OID_U32(DOT11_OID_REKEYTHRESHOLD, 0x12000009), - OID_UNKNOWN(DOT11_OID_STASC, 0x1200000a), + OID_STRUCT(DOT11_OID_STASC, 0x1200000a, struct obj_stasc, OID_TYPE_STASC), OID_U32(DOT11_OID_PRIVTXREJECTED, 0x1a000000), OID_U32(DOT11_OID_PRIVRXPLAIN, 0x1a000001), @@ -122,9 +123,9 @@ struct oid_t isl_oid[] = { OID_U32(DOT11_OID_BRIDGELOCAL, 0x15000000), OID_U32(DOT11_OID_CLIENTS, 0x15000001), OID_U32(DOT11_OID_CLIENTSASSOCIATED, 0x15000002), - [DOT11_OID_CLIENTX] = {0x15000003, 2006, 0, 0}, /* DOT11_OID_CLIENTX,...DOT11_OID_CLIENT2007 */ + [DOT11_OID_CLIENTX] = {0x15000003, 2006, sizeof(struct obj_sta), OID_TYPE_STAINFO}, /* DOT11_OID_CLIENTX,...DOT11_OID_CLIENT2007 */ - OID_STRUCT(DOT11_OID_CLIENTFIND, 0x150007DB, u8[6], OID_TYPE_ADDR), + OID_STRUCT(DOT11_OID_CLIENTFIND, 0x150007DB, struct obj_sta, OID_TYPE_STAINFO), OID_STRUCT(DOT11_OID_WDSLINKADD, 0x150007DC, u8[6], OID_TYPE_ADDR), OID_STRUCT(DOT11_OID_WDSLINKREMOVE, 0x150007DD, u8[6], OID_TYPE_ADDR), OID_STRUCT(DOT11_OID_EAPAUTHSTA, 0x150007DE, u8[6], OID_TYPE_ADDR), @@ -201,8 +202,7 @@ struct oid_t isl_oid[] = { OID_U32(DOT11_OID_STATIMEOUT, 0x19000000), OID_U32_C(DOT11_OID_MLMEAUTOLEVEL, 0x19000001), OID_U32(DOT11_OID_BSSTIMEOUT, 0x19000002), - [DOT11_OID_ATTACHMENT] = {0x19000003, 0, - sizeof(struct obj_attachment), OID_TYPE_ATTACH}, + OID_STRUCT_C(DOT11_OID_ATTACHMENT, 0x19000003, sizeof(struct obj_attachment), OID_TYPE_ATTACH), OID_STRUCT_C(DOT11_OID_PSMBUFFER, 0x19000004, struct obj_buffer, OID_TYPE_BUFFER), @@ -277,7 +277,7 @@ mgt_clean(islpci_private *priv) } void -mgt_le_to_cpu(int type, void *data) +mgt_le_to_cpu(enum oid_types_t type, void *data) { switch (type) { case OID_TYPE_U32: @@ -335,18 +335,30 @@ mgt_le_to_cpu(int type, void *data) attach->size = le16_to_cpu(attach->size); break; } + case OID_TYPE_STAKEY: { + struct obj_stakey *stakey = data; + stakey->options = le16_to_cpu(stakey->options); + break; + } + case OID_TYPE_STAINFO: { + struct obj_sta *sta = data; + sta->age = le16_to_cpu(sta->age); + break; + } case OID_TYPE_SSID: case OID_TYPE_KEY: case OID_TYPE_ADDR: case OID_TYPE_RAW: + case OID_TYPE_STASC: break; default: BUG(); + break; } } static void -mgt_cpu_to_le(int type, void *data) +mgt_cpu_to_le(enum oid_types_t type, void *data) { switch (type) { case OID_TYPE_U32: @@ -403,14 +415,26 @@ mgt_cpu_to_le(int type, void *data) attach->id = cpu_to_le16(attach->id); attach->size = cpu_to_le16(attach->size); break; - } + } + case OID_TYPE_STAKEY: { + struct obj_stakey *stakey = data; + stakey->options = cpu_to_le16(stakey->options); + break; + } + case OID_TYPE_STAINFO: { + struct obj_sta *sta = data; + sta->age = cpu_to_le16(sta->age); + break; + } case OID_TYPE_SSID: case OID_TYPE_KEY: case OID_TYPE_ADDR: case OID_TYPE_RAW: + case OID_TYPE_STASC: break; default: BUG(); + break; } } @@ -658,13 +682,16 @@ static enum oid_num_t commit_part1[] = { static enum oid_num_t commit_part2[] = { DOT11_OID_SSID, + /* unstable with WPA DOT11_OID_PSMBUFFER, + */ DOT11_OID_AUTHENABLE, DOT11_OID_PRIVACYINVOKED, DOT11_OID_EXUNENCRYPTED, DOT11_OID_DEFKEYX, /* MULTIPLE */ DOT11_OID_DEFKEYID, DOT11_OID_DOT1XENABLE, + DOT11_OID_ATTACHMENT, OID_INL_DOT11D_CONFORMANCE, /* Do not initialize this - fw < 1.0.4.3 rejects it OID_INL_OUTPUTPOWER, diff -Nurp orig/oid_mgt.h kernel/oid_mgt.h --- orig/oid_mgt.h 2006-09-20 05:42:06.000000000 +0200 +++ kernel/oid_mgt.h 2006-09-29 20:25:17.000000000 +0200 @@ -32,7 +32,7 @@ void mgt_clean(islpci_private *); extern const int frequency_list_a[]; int channel_of_freq(int); -void mgt_le_to_cpu(int, void *); +void mgt_le_to_cpu(enum oid_types_t, void *); int mgt_set_request(islpci_private *, enum oid_num_t, int, void *); int mgt_set_varlen(islpci_private *, enum oid_num_t, void *, int);
--- a/include/linux/wireless.h 2006-10-01 03:24:01.000000000 +0200 +++ b/include/linux/wireless.h 2006-10-01 03:24:38.000000000 +0200 @@ -546,6 +546,8 @@ /* MLME requests (SIOCSIWMLME / struct iw_mlme) */ #define IW_MLME_DEAUTH 0 #define IW_MLME_DISASSOC 1 +#define IW_MLME_AUTH 2 +#define IW_MLME_ASSOC 3 /* SIOCSIWAUTH/SIOCGIWAUTH struct iw_param flags */ #define IW_AUTH_INDEX 0x0FFF