From mboxrd@z Thu Jan 1 00:00:00 1970 From: chunkeey@web.de Subject: Re: [PATCH wireless-2.6-git] prism54: WPA/RSN support for fullmac cards Date: Fri, 3 Nov 2006 19:12:35 +0100 Message-ID: <200611031912.35525.chunkeey@web.de> References: <200610031457.33215.chunkeey@web.de> <1162565362.2863.1.camel@localhost.localdomain> <43e72e890611030806x14745b17q4916b785a7fb5f8e@mail.gmail.com> Mime-Version: 1.0 Content-Type: Multipart/Mixed; boundary="Boundary-00=_Ta4SF92vWCJTswQ" Cc: netdev@vger.kernel.org, Dan Williams Return-path: Received: from fmmailgate02.web.de ([217.72.192.227]:17585 "EHLO fmmailgate02.web.de") by vger.kernel.org with ESMTP id S1753334AbWKCSMk (ORCPT ); Fri, 3 Nov 2006 13:12:40 -0500 To: "Luis R. Rodriguez" In-Reply-To: <43e72e890611030806x14745b17q4916b785a7fb5f8e@mail.gmail.com> Sender: netdev-owner@vger.kernel.org List-Id: netdev.vger.kernel.org --Boundary-00=_Ta4SF92vWCJTswQ Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Content-Disposition: inline Am Freitag, 3. November 2006 17:06 schrieben Sie: > On 11/3/06, Dan Williams wrote: > > On Tue, 2006-10-31 at 11:05 -0500, Dan Williams wrote: > > > On Mon, 2006-10-30 at 15:17 -0500, Luis R. Rodriguez wrote: > > > > On 10/29/06, chunkeey@web.de wrote: > > > > > This patch completes WPA/RSN with TKIP support for all fullmac > > > > > prism54 cards. I removed all parts which are not relevant for > > > > > wpa_supplicant (managed mode). > > > > > > > > This is great effort and thanks for it! My only concern with the > > > > patch is breaking compatiblity with 2.4 but then again I'm tired of > > > > having to keep this compat work up too and soon, after d80211 full > > > > force push it may not be possible. So I ACK it. > > > > > > I'd like to test it a bit first with my fullmac card before it gets > > > committed/added... But it's great to get some movement on this > > > card/driver! > > > > So my prism54 fullmac card appears to be broken, since it refuses to > > associate with anything at all, even unencrypted access points. It > > doesn't throw any errors at all, and it appears to be operating > > correctly other than not associating. > > chunkeey, I figured your patch was well tested as you had it sitting > there for a while I gotta find a fullmac working card (most of them > broke while debugging) to debug. > well, it was already tested by: Maxi, Dan S., Gabriel, C and "me". "The best configuration is: WPA2 with TKIP!" > > Is there any way to get more information out of the firmware about what > > it's doing? > > The driver supports prism54_get_oid and prism54_set_u32. The list of > OIDs available are on isl_oid.h on oid_num_t enum. Just an FYI you if > you need to access the *EX OIDs you just need to be in extended mode. > Also for WPA you need to be in extended mode. To say the least last > the driver was pretty unstable in extended mode last I used worked on > it. Dan do you get any funky mgt timeouts on your ring buffer? > Anything useful there? > > Luis yes, especially mgt_commit_list caused alot headaches, until I removed DOT11_OID_PSM from the cache list. Now, I can "hammer" it with ping -f for hours. OT: I don't know if my last mail made it to the mailing-list. I haven't seen it on the inet archieves, so here's a "resend". Christian --Boundary-00=_Ta4SF92vWCJTswQ Content-Type: text/x-diff; charset="utf-8"; name="prism-wpa-wl26git4.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="prism-wpa-wl26git4.patch" diff --git a/drivers/net/wireless/prism54/isl_38xx.c b/drivers/net/wireless/prism54/isl_38xx.c index 02fc67b..044a23f 100644 --- a/drivers/net/wireless/prism54/isl_38xx.c +++ b/drivers/net/wireless/prism54/isl_38xx.c @@ -24,7 +24,6 @@ #include #include #include -#include "prismcompat.h" #include "isl_38xx.h" #include "islpci_dev.h" #include "islpci_mgt.h" diff --git a/drivers/net/wireless/prism54/isl_38xx.h b/drivers/net/wireless/prism54/isl_38xx.h diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c index 4a20e45..126a85e 100644 --- a/drivers/net/wireless/prism54/isl_ioctl.c +++ b/drivers/net/wireless/prism54/isl_ioctl.c @@ -3,6 +3,7 @@ * (C) 2003,2004 Aurelien Alleaume * (C) 2003 Herbert Valerio Riedel * (C) 2003 Luis R. Rodriguez + * (C) 2006 Christian Lamparter * * 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 @@ -26,18 +27,13 @@ #include #include -#include "prismcompat.h" #include "isl_ioctl.h" #include "islpci_mgt.h" #include "isl_oid.h" /* additional types and defs for isl38xx fw */ #include "oid_mgt.h" #include /* New driver API */ - -#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 */ +#include static void prism54_wpa_bss_ie_add(islpci_private *priv, u8 *bssid, u8 *wpa_ie, size_t wpa_ie_len); @@ -45,11 +41,6 @@ static size_t prism54_wpa_bss_ie_get(isl static int prism54_set_wpa(struct net_device *, struct iw_request_info *, __u32 *, char *); -/* In 500 kbps */ -static const unsigned char scan_rate_list[] = { 2, 4, 11, 22, - 12, 18, 24, 36, - 48, 72, 96, 108 }; - /** * prism54_mib_mode_helper - MIB change mode helper function * @mib: the &struct islpci_mib object to modify @@ -167,14 +158,16 @@ prism54_update_stats(islpci_private *pri if (down_interruptible(&priv->stats_sem)) return; -/* Noise floor. - * I'm not sure if the unit is dBm. - * Note : If we are not connected, this value seems to be irrelevant. */ + /* Noise floor. + * I'm not sure if the unit is dBm. + + * Note : + * If we are not connected, this value seems to be irrelevant. */ mgt_get_request(priv, DOT11_OID_NOISEFLOOR, 0, NULL, &r); priv->local_iwstatistics.qual.noise = r.u; -/* Get the rssi of the link. To do this we need to retrieve a bss. */ + /* Get the rssi of the link. To do this we need to retrieve a bss. */ /* First get the MAC address of the AP we are associated with. */ mgt_get_request(priv, DOT11_OID_BSSID, 0, NULL, &r); @@ -199,11 +192,11 @@ prism54_update_stats(islpci_private *pri /* report that the stats are new */ priv->local_iwstatistics.qual.updated = 0x7; -/* Rx : unable to decrypt the MPDU */ + /* Rx : unable to decrypt the MPDU */ mgt_get_request(priv, DOT11_OID_PRIVRXFAILED, 0, NULL, &r); priv->local_iwstatistics.discard.code = r.u; -/* Tx : Max MAC retries num reached */ + /* Tx : Max MAC retries num reached */ mgt_get_request(priv, DOT11_OID_MPDUTXFAILED, 0, NULL, &r); priv->local_iwstatistics.discard.retries = r.u; @@ -227,7 +220,7 @@ prism54_get_wireless_stats(struct net_de } else priv->iwstatistics.qual.updated = 0; - /* Update our wireless stats, but do not schedule to often + /* Update our wireless stats, but do not schedule too often * (max 1 HZ) */ if ((priv->stats_timestamp == 0) || time_after(jiffies, priv->stats_timestamp + 1 * HZ)) { @@ -414,6 +407,8 @@ prism54_get_sens(struct net_device *ndev return rvalue; } +#define WEP40_KEY_LEN 5 /* 40/64-bit WEP keys */ + static int prism54_get_range(struct net_device *ndev, struct iw_request_info *info, struct iw_point *dwrq, char *extra) @@ -435,11 +430,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] = WEP40_KEY_LEN; /* 128(104) bits WEP */ - range->encoding_size[1] = 13; + range->encoding_size[1] = WEP_KEY_LEN; /* 256 bits for WPA-PSK */ - range->encoding_size[2] = 32; + range->encoding_size[2] = SCM_KEY_LEN; /* 4 keys are allowed */ range->max_encoding_tokens = 4; @@ -565,6 +560,11 @@ prism54_set_scan(struct net_device *dev, return 0; } +/* In 500 kbps */ +static const unsigned char scan_rate_list[] = { 2, 4, 11, 22, + 12, 18, 24, 36, + 48, 72, 96, 108 }; + /* a little helper that will translate our data into a card independent * format that the Wireless Tools will understand. This was inspired by * the "Aironet driver for 4500 and 4800 series cards" (GPL) @@ -596,17 +596,12 @@ prism54_translate_bss(struct net_device current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, bss->ssid.octets); - /* Capabilities */ -#define CAP_ESS 0x01 -#define CAP_IBSS 0x02 -#define CAP_CRYPT 0x10 - /* Mode */ cap = bss->capinfo; iwe.u.mode = 0; - if (cap & CAP_ESS) + if (cap & WLAN_CAPABILITY_ESS) iwe.u.mode = IW_MODE_MASTER; - else if (cap & CAP_IBSS) + else if (cap & WLAN_CAPABILITY_IBSS) iwe.u.mode = IW_MODE_ADHOC; iwe.cmd = SIOCGIWMODE; if (iwe.u.mode) @@ -615,7 +610,7 @@ #define CAP_CRYPT 0x10 IW_EV_UINT_LEN); /* Encryption capability */ - if (cap & CAP_CRYPT) + if (cap & WLAN_CAPABILITY_PRIVACY) iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; else iwe.u.data.flags = IW_ENCODE_DISABLED; @@ -875,15 +870,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); @@ -1052,18 +1038,58 @@ prism54_get_retry(struct net_device *nde } static int +prism54_set_auth_alg(islpci_private *priv, u32 flag) +{ + int authen = DOT11_AUTH_NONE, 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; + /* + This is very wrong here, but we've to ensure bug-to-bug compatibility. + + If we set exunencrypt, the Firmware adds the "Privacy" flag to the + Capability Information, which is misreaded by many STA/AP as + "the device supports WEP, WPA and WPA2" + */ + exunencrypt = 1; + } + + 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. * New version of iwconfig set the IW_ENCODE_NOKEY flag * when no key is given, but older versions don't. */ + if (islpci_get_state(priv) < PRV_STATE_INIT) + return -EINVAL; + if (dwrq->length > 0) { /* we have a key to set */ int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; @@ -1071,27 +1097,27 @@ prism54_set_encode(struct net_device *nd struct obj_key key = { DOT11_PRIV_WEP, 0, "" }; /* get the current key index */ - rvalue = mgt_get_request(priv, DOT11_OID_DEFKEYID, 0, NULL, &r); + 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 (!(dwrq->flags & IW_ENCODE_NOKEY)) { - if (dwrq->length > KEY_SIZE_TKIP) { + if (dwrq->length > MAX_KEY_LEN) { /* User-provided key data too big */ return -EINVAL; } - if (dwrq->length > KEY_SIZE_WEP104) { + if (dwrq->length > WEP_KEY_LEN) { /* WPA-PSK TKIP */ key.type = DOT11_PRIV_TKIP; - key.length = KEY_SIZE_TKIP; - } else if (dwrq->length > KEY_SIZE_WEP40) { + key.length = MAX_KEY_LEN; + } else if (dwrq->length > WEP40_KEY_LEN) { /* WEP 104/128 */ - key.length = KEY_SIZE_WEP104; + key.length = WEP_KEY_LEN; } else { /* WEP 40/64 */ - key.length = KEY_SIZE_WEP40; + key.length = WEP40_KEY_LEN; } 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 */ @@ -1108,95 +1134,111 @@ 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_auth_algs(islpci_private *priv) +{ + u32 authen = 0, invoke = 0, exunencrypt = 0; + union oid_res_t r; + int ret = 0; + + 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) + return ret; + + if (invoke && exunencrypt && + ((authen == DOT11_AUTH_SK) || (authen == DOT11_AUTH_BOTH))) + ret = IW_ENCODE_RESTRICTED | IW_ENCODE_ENABLED; + else if ((authen == DOT11_AUTH_OS)) { + if (invoke) + ret = IW_ENCODE_OPEN | IW_ENCODE_ENABLED; + else { + ret = IW_ENCODE_DISABLED; + } + } + else { + ret = IW_ENCODE_DISABLED; + } + + 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; - u32 authen = 0, invoke = 0, exunencrypt = 0; - int rvalue; + int rvalue = 0, flags; union oid_res_t r; + if (islpci_get_state(priv) < PRV_STATE_INIT) { + dwrq->flags = IW_ENCODE_DISABLED; + dwrq->length = 0; + return 0; + } + /* first get the flags */ - rvalue = mgt_get_request(priv, DOT11_OID_AUTHENABLE, 0, NULL, &r); - authen = r.u; - rvalue |= mgt_get_request(priv, DOT11_OID_PRIVACYINVOKED, 0, NULL, &r); - invoke = r.u; - rvalue |= mgt_get_request(priv, DOT11_OID_EXUNENCRYPTED, 0, NULL, &r); - exunencrypt = r.u; + if ((flags = prism54_get_auth_algs(priv)) < 0) + return rvalue; - if (invoke && (authen == DOT11_AUTH_BOTH) && exunencrypt) - dwrq->flags = IW_ENCODE_RESTRICTED; - else if ((authen == DOT11_AUTH_OS) && !exunencrypt) { - if (invoke) - dwrq->flags = IW_ENCODE_OPEN; - else - dwrq->flags = IW_ENCODE_DISABLED; - } else - /* The card should not work in this state */ - dwrq->flags = 0; + memset(extra, 0x0, dwrq->length); + dwrq->flags = flags; - /* get the current device key index */ - rvalue |= mgt_get_request(priv, DOT11_OID_DEFKEYID, 0, NULL, &r); - devindex = r.u; - /* Now get the key, return it */ - if ((index < 0) || (index > 3)) - /* no index provided, use the current one */ - index = devindex; - rvalue |= mgt_get_request(priv, DOT11_OID_DEFKEYX, index, NULL, &r); - key = r.ptr; - dwrq->length = key->length; - memcpy(extra, key->key, dwrq->length); - kfree(key); - /* return the used key index */ - dwrq->flags |= devindex + 1; + if (flags != IW_ENCODE_DISABLED) { + /* get the current device key index */ + rvalue = mgt_get_request(priv, DOT11_OID_DEFKEYID, 0, NULL, &r); + devindex = r.u; + /* Now get the key, return it */ + if ((index < 0) || (index > 3)) + /* no index provided, use the current one */ + index = devindex; + + rvalue |= mgt_get_request(priv, DOT11_OID_DEFKEYX, index, NULL, &r); + key = r.ptr; + + if (dwrq->length < key->length) { + kfree(key); + return -EINVAL; + } + + dwrq->length = key->length; + memcpy(extra, key->key, dwrq->length); + kfree(key); + /* return the used key index */ + dwrq->flags |= devindex + 1; + } else + rvalue = 0; + return rvalue; } @@ -1212,7 +1254,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; @@ -1246,9 +1288,9 @@ 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; @@ -1258,6 +1300,9 @@ static int prism54_set_genie(struct net_ (data->length && extra == NULL)) return -EINVAL; + if (islpci_get_state(priv) < PRV_STATE_INIT) + return -EINVAL; + memcpy(priv->wpa_ie, extra, data->length); priv->wpa_ie_len = data->length; @@ -1266,28 +1311,26 @@ 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 = IEEE80211_STYPE_BEACON; + ret = mgt_set_varlen(priv, DOT11_OID_ATTACHMENT, + attach, data->length); + attach->type = IEEE80211_STYPE_PROBE_RESP; + ret |= mgt_set_varlen(priv, DOT11_OID_ATTACHMENT, + attach, data->length); + } + else { + attach->type = IEEE80211_STYPE_ASSOC_REQ; + ret = mgt_set_varlen(priv, DOT11_OID_ATTACHMENT, + attach, data->length); + attach->type = IEEE80211_STYPE_REASSOC_REQ; + ret |= mgt_set_varlen(priv, DOT11_OID_ATTACHMENT, + attach, data->length); } kfree(attach); @@ -1295,9 +1338,9 @@ #define WLAN_FC_STYPE_REASSOC_REQ 2 } -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; @@ -1316,38 +1359,17 @@ 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; + u32 set = 0; + int rvalue = 0; 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; + return -EINVAL; switch (param->flags & IW_AUTH_INDEX) { case IW_AUTH_CIPHER_PAIRWISE: @@ -1355,103 +1377,72 @@ 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); @@ -1463,272 +1454,292 @@ static int prism54_get_auth(struct net_d /* * wpa_supplicant will control these internally */ - ret = -EOPNOTSUPP; - break; + param->value = 0; + return -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, keyop = DOT11_KEYOP_SET_KEY; + int ret = -EINVAL; - if (encoding->flags & IW_ENCODE_DISABLED) - alg = IW_ENCODE_ALG_NONE; - - 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 ((islpci_get_state(priv) < PRV_STATE_INIT) || + (enc->key_len > (dwrq->length - sizeof(*enc))) || + (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: +#if 0 + key_type = DOT11_PRIV_WEP; + keyop = DOT11_KEYOP_REMOVE_KEY; +#else + return 0; +#endif 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; - } + return -EOPNOTSUPP; } - /* 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 = keyop; + if (!(enc->ext_flags & IW_ENCODE_EXT_GROUP_KEY)) + key->options = DOT11_STAKEY_OPTION_DEFAULTKEY; + else + key->options = DOT11_STAKEY_OPTION_GROUPKEY; + + 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 { + memset(enc, 0, sizeof(*enc)); + + if (islpci_get_state(priv) < PRV_STATE_INIT) { + dwrq->flags = IW_ENCODE_DISABLED; + return 0; + } + + 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; + if (ret) + return ret; + index = r.u; } - encoding->flags = idx + 1; - memset(ext, 0, sizeof(*ext)); + if (enc->addr.sa_family != ARPHRD_ETHER) { + /* no "per-station key" */ + struct obj_key *key; + ret = mgt_get_request(priv, DOT11_OID_DEFKEYX, index, NULL, &r); + key = r.ptr; + if (ret) { + kfree(key); + return ret; + } - 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; + if (key->length > max_key_len) { + kfree(key); + return -E2BIG; + } + + enc->key_len = key->length; + 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 -EIO; + break; + } - down_write(&priv->mib_sem); - wpa = priv->wpa; - up_write(&priv->mib_sem); + dwrq->flags |= IW_ENCODE_ENABLED; + memcpy(enc->key, key->key, enc->key_len); + dwrq->flags |= index +1; + return ret; - 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 { - struct obj_key *key; + } + else { + /* no "per-station key" */ + 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; + } - ret = mgt_get_request(priv, DOT11_OID_DEFKEYX, idx, NULL, &r); - if (ret < 0) - goto out; - key = r.ptr; - if (max_key_len < key->length) { - ret = -E2BIG; - goto out; + if (key->length > max_key_len) { + kfree(key); + return -EINVAL; } - memcpy(ext->key, key->key, key->length); - ext->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; - default: - case DOT11_PRIV_WEP: - ext->alg = IW_ENCODE_ALG_WEP; + case DOT11_PRIV_TKIP: + enc->alg = IW_ENCODE_ALG_TKIP; + break; + default: + kfree(key); + return -EIO; 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); + + /* add replay counter */ + 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_STASC, 0, (void*)stasc, &r); + kfree(stasc); + stasc = (struct obj_stasc*)r.ptr; + if (ret) { + kfree(stasc); + return ret; + } + + memset(enc->tx_seq, 0, IW_ENCODE_SEQ_MAX_SIZE); + // prism's FW has only a 6 byte wide RSC! + memcpy(enc->tx_seq, stasc->sc, IW_ENCODE_SEQ_MAX_SIZE - 2); + enc->ext_flags |= IW_ENCODE_EXT_TX_SEQ_VALID; + kfree(stasc); + } -out: return ret; } - static int prism54_reset(struct net_device *ndev, struct iw_request_info *info, __u32 * uwrq, char *extra) @@ -2030,14 +2041,12 @@ static void format_event(islpci_private *priv, char *dest, const char *str, const struct obj_mlme *mlme, u16 *length, int error) { - 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 " MAC_FMT " [%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); + MAC_ARG(mlme->address), + mlme->state, mlme->code, mlme->id); BUG_ON(n > IW_CUSTOM_MAX); *length = n; } @@ -2103,12 +2112,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" - static void prism54_wpa_bss_ie_add(islpci_private *priv, u8 *bssid, u8 *wpa_ie, size_t wpa_ie_len) @@ -2140,10 +2143,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) { @@ -2157,8 +2159,8 @@ prism54_wpa_bss_ie_add(islpci_private *p bss->wpa_ie_len = wpa_ie_len; bss->last_update = jiffies; } else { - printk(KERN_DEBUG "Failed to add BSS WPA entry for " MACSTR - "\n", MAC2STR(bssid)); + printk(KERN_DEBUG "Failed to add BSS WPA entry for " MAC_FMT + "\n", MAC_ARG(bssid)); } /* expire old entries from WPA list */ @@ -2220,6 +2222,8 @@ prism54_wpa_bss_ie_clean(islpci_private } } +static u8 wpa_oid[4] = { 0x00, 0x50, 0xf2, 1 }; + static void prism54_process_bss_data(islpci_private *priv, u32 oid, u8 *addr, u8 *payload, size_t len) @@ -2235,11 +2239,16 @@ 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 " MAC_FMT "\n", (oid == DOT11_OID_BEACON ? "Beacon" : "ProbeResp"), MAC_ARG(addr)); return; } - if (pos[0] == WLAN_EID_GENERIC && pos[1] >= 4 && + /* Don't forget RSN/WPA2 ! */ + if (pos[0] == MFIE_TYPE_RSN && pos[1] > 4) { + prism54_wpa_bss_ie_add(priv, addr, pos, pos[1] + 2); + return; + } + if (pos[0] == MFIE_TYPE_GENERIC && pos[1] >= 4 && memcmp(pos + 2, wpa_oid, 4) == 0) { prism54_wpa_bss_ie_add(priv, addr, pos, pos[1] + 2); return; @@ -2264,39 +2273,81 @@ 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; /* 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); @@ -2329,163 +2380,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; } /* @@ -2521,368 +2421,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 @@ -2890,7 +2455,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; } @@ -3025,6 +2592,80 @@ 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_point *dwrq, char *extra) +{ + islpci_private *priv = netdev_priv(ndev); + struct iw_mlme *iwmlme; + struct obj_mlme mlme; + struct obj_sta *sta; + union oid_res_t r; + int ret = 0; + + if (dwrq->length != sizeof(*iwmlme)) + return -EINVAL; + + iwmlme = (struct iw_mlme*)extra; + + if (iwmlme->addr.sa_family != ARPHRD_ETHER) + return -EINVAL; + + /* get STA/AP Id. + or the card will BROADCAST the packet! */ + + sta = (struct obj_sta*)kzalloc(sizeof(*sta), GFP_KERNEL); + if (!sta) + return -ENOMEM; + + memcpy(sta->address, iwmlme->addr.sa_data, ETH_ALEN); + ret = mgt_get_request(priv, DOT11_OID_CLIENTFIND, 0, sta, &r); + kfree(sta); + + if (ret) { + sta = r.ptr; + memcpy(mlme.address, iwmlme->addr.sa_data, ETH_ALEN); + + if (sta->node >= 1) + mlme.id = sta->node; + else + mlme.id = -1; + } else + /* use broadcast id */ + mlme.id = -1; + + mlme.code = iwmlme->reason_code; + + kfree(r.ptr); + switch (iwmlme->cmd) { + case IW_MLME_DEAUTH: + mlme.state = DOT11_STATE_NONE; + return mgt_set_request(priv, DOT11_OID_DEAUTHENTICATE, + 0, &mlme); + break; + case IW_MLME_DISASSOC: + mlme.state = DOT11_STATE_NONE; + return mgt_set_request(priv, DOT11_OID_DISASSOCIATE, + 0, &mlme); + break; +#if 0 + /* not in WEXT yet */ + case IW_MLME_AUTH: + mlme.state = DOT11_STATE_AUTH; + return mgt_set_request(priv, DOT11_OID_AUTHENTICATE, + 0, &mlme); + break; + case IW_MLME_ASSOC: + mlme.state = DOT11_STATE_ASSOC; + return mgt_set_request(priv, DOT11_OID_ASSOCIATE, + 0, &mlme); + break; +#endif + } + + return -EOPNOTSUPP; +} + static const iw_handler prism54_handler[] = { (iw_handler) prism54_commit, /* SIOCSIWCOMMIT */ (iw_handler) prism54_get_name, /* SIOCGIWNAME */ @@ -3042,13 +2683,13 @@ static const iw_handler prism54_handler[ (iw_handler) NULL, /* SIOCGIWPRIV */ (iw_handler) NULL, /* SIOCSIWSTATS */ (iw_handler) NULL, /* SIOCGIWSTATS */ - prism54_set_spy, /* SIOCSIWSPY */ + (iw_handler) prism54_set_spy, /* SIOCSIWSPY */ iw_handler_get_spy, /* SIOCGIWSPY */ iw_handler_set_thrspy, /* SIOCSIWTHRSPY */ 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 */ @@ -3072,15 +2713,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. */ @@ -3259,14 +2900,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 --git a/drivers/net/wireless/prism54/isl_ioctl.h b/drivers/net/wireless/prism54/isl_ioctl.h index e8183d3..8322133 100644 --- a/drivers/net/wireless/prism54/isl_ioctl.h +++ b/drivers/net/wireless/prism54/isl_ioctl.h @@ -1,4 +1,5 @@ /* + * * Copyright (C) 2002 Intersil Americas Inc. * (C) 2003 Aurelien Alleaume * (C) 2003 Luis R. Rodriguez @@ -21,12 +22,11 @@ #ifndef _ISL_IOCTL_H #define _ISL_IOCTL_H +#include /* New driver API */ #include "islpci_mgt.h" #include "islpci_dev.h" -#include /* New driver API */ - -#define SUPPORTED_WIRELESS_EXT 19 +#define SUPPORTED_WIRELESS_EXT 21 void prism54_mib_init(islpci_private *); diff --git a/drivers/net/wireless/prism54/isl_oid.h b/drivers/net/wireless/prism54/isl_oid.h index b7534c2..88b24d6 100644 --- a/drivers/net/wireless/prism54/isl_oid.h +++ b/drivers/net/wireless/prism54/isl_oid.h @@ -2,6 +2,7 @@ * Copyright (C) 2003 Herbert Valerio Riedel * Copyright (C) 2004 Luis R. Rodriguez * Copyright (C) 2004 Aurelien Alleaume + * Copyright (C) 2006 Christian Lamparter * * 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 @@ -26,29 +27,67 @@ #define _ISL_OID_H * with the device firmware */ +#define MAX_KEY_LEN 32 + struct obj_ssid { u8 length; - char octets[33]; + u8 octets[IW_ESSID_MAX_SIZE + 1]; } __attribute__ ((packed)); +enum dot11_priv_t { + DOT11_PRIV_WEP = 0, + DOT11_PRIV_TKIP = 1 +}; + struct obj_key { u8 type; /* dot11_priv_t */ u8 length; - char key[32]; + u8 key[MAX_KEY_LEN]; } __attribute__ ((packed)); +enum dot11_stakey_opt_t { + DOT11_STAKEY_OPTION_GROUPKEY = 0x0000, + DOT11_STAKEY_OPTION_DEFAULTKEY = 0x0001 +}; + +enum dot11_keyop_t { + DOT11_KEYOP_SET_KEY = 0x0000, + DOT11_KEYOP_REMOVE_KEY = 0x0001 +}; + +struct obj_stakey { + u8 address[ETH_ALEN]; + u8 keyid; + u8 reserved; /* dot11_keyop_t */ + u16 options; /* dot11_stakey_opt_t */ + u8 type; /* dot11_priv_t */ + u8 length; + u8 key[MAX_KEY_LEN]; +} __attribute__ ((packed)); + +enum dot11_state_t { + DOT11_STATE_NONE = 0, + 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 +}; + struct obj_mlme { - u8 address[6]; + u8 address[ETH_ALEN]; u16 id; - u16 state; - u16 code; + u16 state; /* dot11_state_t */ + u16 code; /* WLAN_STATUS_ / WLAN_REASON_ */ } __attribute__ ((packed)); struct obj_mlmeex { - u8 address[6]; + u8 address[ETH_ALEN]; u16 id; - u16 state; - u16 code; + u16 state; /* dot11_state_t */ + u16 code; /* WLAN_STATUS_ / WLAN_REASON_ */ u16 size; u8 data[0]; } __attribute__ ((packed)); @@ -59,23 +98,23 @@ struct obj_buffer { } __attribute__ ((packed)); struct obj_bss { - u8 address[6]; + u8 address[ETH_ALEN]; int:16; /* padding */ - char state; - char reserved; - short age; + u8 state; /* dot11_state_t */ + u8 reserved; + u16 age; - char quality; - char rssi; + u8 quality; + u8 rssi; struct obj_ssid ssid; - short channel; - char beacon_period; - char dtim_period; - short capinfo; - short rates; - short basic_rates; + u16 channel; + u8 beacon_period; + u8 dtim_period; + u16 capinfo; /* WLAN_CAPABILITY_ */ + u16 rates; + u16 basic_rates; int:16; /* padding */ } __attribute__ ((packed)); @@ -90,14 +129,33 @@ struct obj_frequencies { } __attribute__ ((packed)); struct obj_attachment { - char type; - char reserved; - short id; - short size; - char data[0]; + u8 type; /* IEEE80211_STYPE_ */ + u8 reserved; + u16 id; + u16 size; + u8 data[0]; } __attribute__((packed)); -/* +struct obj_stasc { + u8 address[ETH_ALEN]; + u8 keyid; + u8 tx_sc; + u8 sc[6]; +} __attribute__ ((packed)); + +struct obj_sta { + u8 address[ETH_ALEN]; + int:16; + u8 state; /* dot11_state_t */ + u8 node; /* Station ID */ + 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... */ @@ -112,19 +170,12 @@ __bug_on_wrong_struct_sizes(void) BUILD_BUG_ON(sizeof (struct obj_bss) != 60); BUILD_BUG_ON(sizeof (struct obj_bsslist) != 4); BUILD_BUG_ON(sizeof (struct obj_frequencies) != 2); + BUILD_BUG_ON(sizeof (struct obj_sta) != 16); + BUILD_BUG_ON(sizeof (struct obj_stasc) != 14); + BUILD_BUG_ON(sizeof (struct obj_stakey) != 44); + BUILD_BUG_ON(sizeof (struct obj_attachment) != 6); } -enum dot11_state_t { - DOT11_STATE_NONE = 0, - DOT11_STATE_AUTHING = 1, - DOT11_STATE_AUTH = 2, - DOT11_STATE_ASSOCING = 3, - - DOT11_STATE_ASSOC = 5, - DOT11_STATE_IBSS = 6, - DOT11_STATE_WDS = 7 -}; - enum dot11_bsstype_t { DOT11_BSSTYPE_NONE = 0, DOT11_BSSTYPE_INFRA = 1, @@ -145,11 +196,6 @@ enum dot11_mlme_t { DOT11_MLME_EXTENDED = 2 }; -enum dot11_priv_t { - DOT11_PRIV_WEP = 0, - DOT11_PRIV_TKIP = 1 -}; - /* Prism "Nitro" / Frameburst / "Packet Frame Grouping" * Value is in microseconds. Represents the # microseconds * the firmware will take to group frames before sending out then out @@ -464,31 +510,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 - -/* OID_TYPE_MLMEEX is special because of a variable size field when sending. - * Not yet implemented (not used in driver anyway). - */ +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_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; + u16 range; /* to define a range of oid */ + u16 size; /* max size of the associated data */ + enum oid_types_t flags; }; union oid_res_t { @@ -496,8 +543,8 @@ union oid_res_t { u32 u; }; -#define IWMAX_BITRATES 20 -#define IWMAX_BSS 24 +#define IWMAX_BITRATES 20 +#define IWMAX_BSS 24 #define IWMAX_FREQ 30 #define PRIV_STR_SIZE 1024 diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c index 1e0603c..e6d9b26 100644 --- a/drivers/net/wireless/prism54/islpci_dev.c +++ b/drivers/net/wireless/prism54/islpci_dev.c @@ -25,10 +25,10 @@ #include #include #include #include +#include #include -#include "prismcompat.h" #include "isl_38xx.h" #include "isl_ioctl.h" #include "islpci_dev.h" @@ -86,7 +86,7 @@ isl_upload_firmware(islpci_private *priv long fw_len; const u32 *fw_ptr; - rc = request_firmware(&fw_entry, priv->firmware, PRISM_FW_PDEV); + rc = request_firmware(&fw_entry, priv->firmware, &priv->pdev->dev); if (rc) { printk(KERN_ERR "%s: request_firmware() failed for '%s'\n", diff --git a/drivers/net/wireless/prism54/islpci_dev.h b/drivers/net/wireless/prism54/islpci_dev.h index a9aa166..3d0bb8f 100644 --- a/drivers/net/wireless/prism54/islpci_dev.h +++ b/drivers/net/wireless/prism54/islpci_dev.h @@ -71,7 +71,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 --git a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wireless/prism54/islpci_eth.c index 676d838..6da1f86 100644 --- a/drivers/net/wireless/prism54/islpci_eth.c +++ b/drivers/net/wireless/prism54/islpci_eth.c @@ -24,7 +24,6 @@ #include #include #include -#include "prismcompat.h" #include "isl_38xx.h" #include "islpci_eth.h" #include "islpci_mgt.h" @@ -482,8 +481,7 @@ #endif void islpci_do_reset_and_wake(void *data) { - islpci_private *priv = data; - + islpci_private *priv = (islpci_private *) data; islpci_reset(priv, 1); priv->reset_task_pending = 0; smp_wmb(); @@ -500,13 +498,12 @@ islpci_eth_tx_timeout(struct net_device statistics->tx_errors++; if (!priv->reset_task_pending) { - printk(KERN_WARNING - "%s: tx_timeout, scheduling reset", ndev->name); + printk(KERN_WARNING "%s: tx_timeout\n", ndev->name); netif_stop_queue(ndev); priv->reset_task_pending = 1; schedule_work(&priv->reset_task); } else { printk(KERN_WARNING - "%s: tx_timeout, waiting for reset", ndev->name); + "%s: tx_timeout, waiting for reset\n", ndev->name); } } diff --git a/drivers/net/wireless/prism54/islpci_eth.h b/drivers/net/wireless/prism54/islpci_eth.h diff --git a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c index f6354b1..0e07c2b 100644 --- a/drivers/net/wireless/prism54/islpci_hotplug.c +++ b/drivers/net/wireless/prism54/islpci_hotplug.c @@ -23,7 +23,6 @@ #include #include /* For __init, __exit */ #include -#include "prismcompat.h" #include "islpci_dev.h" #include "islpci_mgt.h" /* for pc_debug */ #include "isl_oid.h" @@ -170,7 +169,8 @@ #endif pci_set_master(pdev); /* enable MWI */ - pci_set_mwi(pdev); + if (pci_set_mwi(pdev)) + printk(KERN_ERR "%s: pci_set_mwi failed\n", DRV_NAME); /* setup the network device interface and its structure */ if (!(ndev = islpci_setup(pdev))) { @@ -289,7 +289,10 @@ prism54_resume(struct pci_dev *pdev) islpci_private *priv = ndev ? netdev_priv(ndev) : NULL; BUG_ON(!priv); - pci_enable_device(pdev); + if (pci_enable_device(pdev)) { + printk(KERN_ERR "%s: pci_enable_device() failed.\n", DRV_NAME); + return -ENODEV; + } printk(KERN_NOTICE "%s: got resume request\n", ndev->name); diff --git a/drivers/net/wireless/prism54/islpci_mgt.c b/drivers/net/wireless/prism54/islpci_mgt.c index 036a875..8fd781d 100644 --- a/drivers/net/wireless/prism54/islpci_mgt.c +++ b/drivers/net/wireless/prism54/islpci_mgt.c @@ -25,7 +25,6 @@ #include #include #include -#include "prismcompat.h" #include "isl_38xx.h" #include "islpci_mgt.h" #include "isl_oid.h" /* additional types and defs for isl38xx fw */ diff --git a/drivers/net/wireless/prism54/islpci_mgt.h b/drivers/net/wireless/prism54/islpci_mgt.h diff --git a/drivers/net/wireless/prism54/oid_mgt.c b/drivers/net/wireless/prism54/oid_mgt.c index fbc52b6..24b5a49 100644 --- a/drivers/net/wireless/prism54/oid_mgt.c +++ b/drivers/net/wireless/prism54/oid_mgt.c @@ -16,7 +16,6 @@ * */ -#include "prismcompat.h" #include "islpci_dev.h" #include "islpci_mgt.h" #include "isl_oid.h" @@ -85,9 +84,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 +121,10 @@ 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 +201,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 +276,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: @@ -334,19 +333,31 @@ mgt_le_to_cpu(int type, void *data) attach->id = le16_to_cpu(attach->id); 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 +414,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 +681,16 @@ static enum oid_num_t commit_part1[] = { static enum oid_num_t commit_part2[] = { DOT11_OID_SSID, + /* problematic 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 --git a/drivers/net/wireless/prism54/oid_mgt.h b/drivers/net/wireless/prism54/oid_mgt.h index 92c8a2d..10a5cc3 100644 --- a/drivers/net/wireless/prism54/oid_mgt.h +++ b/drivers/net/wireless/prism54/oid_mgt.h @@ -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); diff --git a/drivers/net/wireless/prism54/prismcompat.h b/drivers/net/wireless/prism54/prismcompat.h deleted file mode 100644 index aa1d174..0000000 --- a/drivers/net/wireless/prism54/prismcompat.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * (C) 2004 Margit Schubert-While - * - * 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 - * the Free Software Foundation; either version 2 of the License - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/* - * Compatibility header file to aid support of different kernel versions - */ - -#ifdef PRISM54_COMPAT24 -#include "prismcompat24.h" -#else /* PRISM54_COMPAT24 */ - -#ifndef _PRISM_COMPAT_H -#define _PRISM_COMPAT_H - -#include -#include -#include -#include -#include - -#ifndef __iomem -#define __iomem -#endif - -#define PRISM_FW_PDEV &priv->pdev->dev - -#endif /* _PRISM_COMPAT_H */ -#endif /* PRISM54_COMPAT24 */ diff --git a/scripts/package/Makefile b/scripts/package/Makefile diff --git a/scripts/package/builddeb b/scripts/package/builddeb diff --git a/scripts/package/buildtar b/scripts/package/buildtar diff --git a/scripts/package/mkspec b/scripts/package/mkspec --Boundary-00=_Ta4SF92vWCJTswQ--