|
@@ -2175,426 +2175,6 @@ static int rndis_dump_station(struct wiphy *wiphy, struct net_device *dev,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * wireless extension handlers
|
|
|
- */
|
|
|
-
|
|
|
-#if 0
|
|
|
-/* Commented code out instead of removing to have more sane patch for review.
|
|
|
- * Will be removed later in the set.
|
|
|
- */
|
|
|
-static int rndis_iw_set_essid(struct net_device *dev,
|
|
|
- struct iw_request_info *info, union iwreq_data *wrqu, char *essid)
|
|
|
-{
|
|
|
- struct ndis_80211_ssid ssid;
|
|
|
- int length = wrqu->essid.length;
|
|
|
- struct usbnet *usbdev = netdev_priv(dev);
|
|
|
-
|
|
|
- devdbg(usbdev, "SIOCSIWESSID: [flags:%d,len:%d] '%.32s'",
|
|
|
- wrqu->essid.flags, wrqu->essid.length, essid);
|
|
|
-
|
|
|
- if (length > NDIS_802_11_LENGTH_SSID)
|
|
|
- length = NDIS_802_11_LENGTH_SSID;
|
|
|
-
|
|
|
- ssid.length = cpu_to_le32(length);
|
|
|
- if (length > 0)
|
|
|
- memcpy(ssid.essid, essid, length);
|
|
|
- else
|
|
|
- memset(ssid.essid, 0, NDIS_802_11_LENGTH_SSID);
|
|
|
-
|
|
|
- set_assoc_params(usbdev);
|
|
|
-
|
|
|
- if (!wrqu->essid.flags || length == 0)
|
|
|
- return disassociate(usbdev, 1);
|
|
|
- else {
|
|
|
- /* Pause and purge rx queue, so we don't pass packets before
|
|
|
- * 'media connect'-indication.
|
|
|
- */
|
|
|
- usbnet_pause_rx(usbdev);
|
|
|
- usbnet_purge_paused_rxq(usbdev);
|
|
|
-
|
|
|
- return set_essid(usbdev, &ssid);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-static int rndis_iw_get_essid(struct net_device *dev,
|
|
|
- struct iw_request_info *info, union iwreq_data *wrqu, char *essid)
|
|
|
-{
|
|
|
- struct ndis_80211_ssid ssid;
|
|
|
- struct usbnet *usbdev = netdev_priv(dev);
|
|
|
- int ret;
|
|
|
-
|
|
|
- ret = get_essid(usbdev, &ssid);
|
|
|
-
|
|
|
- if (ret == 0 && le32_to_cpu(ssid.length) > 0) {
|
|
|
- wrqu->essid.flags = 1;
|
|
|
- wrqu->essid.length = le32_to_cpu(ssid.length);
|
|
|
- memcpy(essid, ssid.essid, wrqu->essid.length);
|
|
|
- essid[wrqu->essid.length] = 0;
|
|
|
- } else {
|
|
|
- memset(essid, 0, sizeof(NDIS_802_11_LENGTH_SSID));
|
|
|
- wrqu->essid.flags = 0;
|
|
|
- wrqu->essid.length = 0;
|
|
|
- }
|
|
|
- devdbg(usbdev, "SIOCGIWESSID: %s", essid);
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-static int rndis_iw_get_bssid(struct net_device *dev,
|
|
|
- struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
|
|
|
-{
|
|
|
- struct usbnet *usbdev = netdev_priv(dev);
|
|
|
- unsigned char bssid[ETH_ALEN];
|
|
|
- int ret;
|
|
|
-
|
|
|
- ret = get_bssid(usbdev, bssid);
|
|
|
-
|
|
|
- if (ret == 0)
|
|
|
- devdbg(usbdev, "SIOCGIWAP: %pM", bssid);
|
|
|
- else
|
|
|
- devdbg(usbdev, "SIOCGIWAP: <not associated>");
|
|
|
-
|
|
|
- wrqu->ap_addr.sa_family = ARPHRD_ETHER;
|
|
|
- memcpy(wrqu->ap_addr.sa_data, bssid, ETH_ALEN);
|
|
|
-
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-static int rndis_iw_set_bssid(struct net_device *dev,
|
|
|
- struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
|
|
|
-{
|
|
|
- struct usbnet *usbdev = netdev_priv(dev);
|
|
|
- u8 *bssid = (u8 *)wrqu->ap_addr.sa_data;
|
|
|
- int ret;
|
|
|
-
|
|
|
- devdbg(usbdev, "SIOCSIWAP: %pM", bssid);
|
|
|
-
|
|
|
- ret = rndis_set_oid(usbdev, OID_802_11_BSSID, bssid, ETH_ALEN);
|
|
|
-
|
|
|
- /* user apps may set ap's mac address, which is not required;
|
|
|
- * they may fail to work if this function fails, so return
|
|
|
- * success */
|
|
|
- if (ret)
|
|
|
- devwarn(usbdev, "setting AP mac address failed (%08X)", ret);
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-static int rndis_iw_set_auth(struct net_device *dev,
|
|
|
- struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
|
|
|
-{
|
|
|
- struct iw_param *p = &wrqu->param;
|
|
|
- struct usbnet *usbdev = netdev_priv(dev);
|
|
|
- struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
|
|
- int ret = -ENOTSUPP;
|
|
|
-
|
|
|
- switch (p->flags & IW_AUTH_INDEX) {
|
|
|
- case IW_AUTH_WPA_VERSION:
|
|
|
- devdbg(usbdev, "SIOCSIWAUTH: WPA_VERSION, %08x", p->value);
|
|
|
- priv->wpa_version = p->value;
|
|
|
- ret = 0;
|
|
|
- break;
|
|
|
-
|
|
|
- case IW_AUTH_CIPHER_PAIRWISE:
|
|
|
- devdbg(usbdev, "SIOCSIWAUTH: CIPHER_PAIRWISE, %08x", p->value);
|
|
|
- priv->wpa_cipher_pair = p->value;
|
|
|
- ret = 0;
|
|
|
- break;
|
|
|
-
|
|
|
- case IW_AUTH_CIPHER_GROUP:
|
|
|
- devdbg(usbdev, "SIOCSIWAUTH: CIPHER_GROUP, %08x", p->value);
|
|
|
- priv->wpa_cipher_group = p->value;
|
|
|
- ret = 0;
|
|
|
- break;
|
|
|
-
|
|
|
- case IW_AUTH_KEY_MGMT:
|
|
|
- devdbg(usbdev, "SIOCSIWAUTH: KEY_MGMT, %08x", p->value);
|
|
|
- priv->wpa_keymgmt = p->value;
|
|
|
- ret = 0;
|
|
|
- break;
|
|
|
-
|
|
|
- case IW_AUTH_TKIP_COUNTERMEASURES:
|
|
|
- devdbg(usbdev, "SIOCSIWAUTH: TKIP_COUNTERMEASURES, %08x",
|
|
|
- p->value);
|
|
|
- ret = 0;
|
|
|
- break;
|
|
|
-
|
|
|
- case IW_AUTH_DROP_UNENCRYPTED:
|
|
|
- devdbg(usbdev, "SIOCSIWAUTH: DROP_UNENCRYPTED, %08x", p->value);
|
|
|
- ret = 0;
|
|
|
- break;
|
|
|
-
|
|
|
- case IW_AUTH_80211_AUTH_ALG:
|
|
|
- devdbg(usbdev, "SIOCSIWAUTH: 80211_AUTH_ALG, %08x", p->value);
|
|
|
- priv->wpa_authalg = p->value;
|
|
|
- ret = 0;
|
|
|
- break;
|
|
|
-
|
|
|
- case IW_AUTH_WPA_ENABLED:
|
|
|
- devdbg(usbdev, "SIOCSIWAUTH: WPA_ENABLED, %08x", p->value);
|
|
|
- if (wrqu->param.value)
|
|
|
- deauthenticate(usbdev);
|
|
|
- ret = 0;
|
|
|
- break;
|
|
|
-
|
|
|
- case IW_AUTH_RX_UNENCRYPTED_EAPOL:
|
|
|
- devdbg(usbdev, "SIOCSIWAUTH: RX_UNENCRYPTED_EAPOL, %08x",
|
|
|
- p->value);
|
|
|
- ret = 0;
|
|
|
- break;
|
|
|
-
|
|
|
- case IW_AUTH_ROAMING_CONTROL:
|
|
|
- devdbg(usbdev, "SIOCSIWAUTH: ROAMING_CONTROL, %08x", p->value);
|
|
|
- ret = 0;
|
|
|
- break;
|
|
|
-
|
|
|
- case IW_AUTH_PRIVACY_INVOKED:
|
|
|
- devdbg(usbdev, "SIOCSIWAUTH: invalid cmd %d",
|
|
|
- wrqu->param.flags & IW_AUTH_INDEX);
|
|
|
- return -EOPNOTSUPP;
|
|
|
-
|
|
|
- default:
|
|
|
- devdbg(usbdev, "SIOCSIWAUTH: UNKNOWN %08x, %08x",
|
|
|
- p->flags & IW_AUTH_INDEX, p->value);
|
|
|
- }
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-static int rndis_iw_get_auth(struct net_device *dev,
|
|
|
- struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
|
|
|
-{
|
|
|
- struct iw_param *p = &wrqu->param;
|
|
|
- struct usbnet *usbdev = netdev_priv(dev);
|
|
|
- struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
|
|
-
|
|
|
- switch (p->flags & IW_AUTH_INDEX) {
|
|
|
- case IW_AUTH_WPA_VERSION:
|
|
|
- p->value = priv->wpa_version;
|
|
|
- break;
|
|
|
- case IW_AUTH_CIPHER_PAIRWISE:
|
|
|
- p->value = priv->wpa_cipher_pair;
|
|
|
- break;
|
|
|
- case IW_AUTH_CIPHER_GROUP:
|
|
|
- p->value = priv->wpa_cipher_group;
|
|
|
- break;
|
|
|
- case IW_AUTH_KEY_MGMT:
|
|
|
- p->value = priv->wpa_keymgmt;
|
|
|
- break;
|
|
|
- case IW_AUTH_80211_AUTH_ALG:
|
|
|
- p->value = priv->wpa_authalg;
|
|
|
- break;
|
|
|
- default:
|
|
|
- devdbg(usbdev, "SIOCGIWAUTH: invalid cmd %d",
|
|
|
- wrqu->param.flags & IW_AUTH_INDEX);
|
|
|
- return -EOPNOTSUPP;
|
|
|
- }
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-static int rndis_iw_set_encode(struct net_device *dev,
|
|
|
- struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
|
|
|
-{
|
|
|
- struct usbnet *usbdev = netdev_priv(dev);
|
|
|
- struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
|
|
- struct rndis_wlan_encr_key key;
|
|
|
- int ret, index, key_len;
|
|
|
- u8 *keybuf;
|
|
|
-
|
|
|
- index = (wrqu->encoding.flags & IW_ENCODE_INDEX);
|
|
|
-
|
|
|
- /* iwconfig gives index as 1 - N */
|
|
|
- if (index > 0)
|
|
|
- index--;
|
|
|
- else
|
|
|
- index = priv->encr_tx_key_index;
|
|
|
-
|
|
|
- if (index < 0 || index >= 4) {
|
|
|
- devwarn(usbdev, "encryption index out of range (%u)", index);
|
|
|
- return -EINVAL;
|
|
|
- }
|
|
|
-
|
|
|
- /* remove key if disabled */
|
|
|
- if (wrqu->data.flags & IW_ENCODE_DISABLED) {
|
|
|
- if (remove_key(usbdev, index, NULL))
|
|
|
- return -EINVAL;
|
|
|
- else
|
|
|
- return 0;
|
|
|
- }
|
|
|
-
|
|
|
- /* global encryption state (for all keys) */
|
|
|
- if (wrqu->data.flags & IW_ENCODE_OPEN)
|
|
|
- ret = set_auth_mode(usbdev, 0, NL80211_AUTHTYPE_OPEN_SYSTEM,
|
|
|
- RNDIS_WLAN_KEY_MGMT_NONE);
|
|
|
- else /*if (wrqu->data.flags & IW_ENCODE_RESTRICTED)*/
|
|
|
- ret = set_auth_mode(usbdev, 0, NL80211_AUTHTYPE_SHARED_KEY,
|
|
|
- RNDIS_WLAN_KEY_MGMT_NONE);
|
|
|
- if (ret != 0)
|
|
|
- return ret;
|
|
|
-
|
|
|
- if (wrqu->data.length > 0) {
|
|
|
- key_len = wrqu->data.length;
|
|
|
- keybuf = extra;
|
|
|
- } else {
|
|
|
- /* must be set as tx key */
|
|
|
- if (priv->encr_keys[index].len == 0)
|
|
|
- return -EINVAL;
|
|
|
- key = priv->encr_keys[index];
|
|
|
- key_len = key.len;
|
|
|
- keybuf = key.material;
|
|
|
- priv->encr_tx_key_index = index;
|
|
|
- }
|
|
|
-
|
|
|
- if (add_wep_key(usbdev, keybuf, key_len, index) != 0)
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
- if (index == priv->encr_tx_key_index)
|
|
|
- /* ndis drivers want essid to be set after setting encr */
|
|
|
- set_essid(usbdev, &priv->essid);
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-static int rndis_iw_set_encode_ext(struct net_device *dev,
|
|
|
- struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
|
|
|
-{
|
|
|
- struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
|
|
|
- struct usbnet *usbdev = netdev_priv(dev);
|
|
|
- struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
|
|
- int keyidx, flags, cipher;
|
|
|
-
|
|
|
- keyidx = wrqu->encoding.flags & IW_ENCODE_INDEX;
|
|
|
-
|
|
|
- /* iwconfig gives index as 1 - N */
|
|
|
- if (keyidx)
|
|
|
- keyidx--;
|
|
|
- else
|
|
|
- keyidx = priv->encr_tx_key_index;
|
|
|
-
|
|
|
- if (keyidx < 0 || keyidx >= 4) {
|
|
|
- devwarn(usbdev, "encryption index out of range (%u)", keyidx);
|
|
|
- return -EINVAL;
|
|
|
- }
|
|
|
-
|
|
|
- if (ext->alg == IW_ENCODE_ALG_WEP) {
|
|
|
- if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
|
|
|
- priv->encr_tx_key_index = keyidx;
|
|
|
- return add_wep_key(usbdev, ext->key, ext->key_len, keyidx);
|
|
|
- }
|
|
|
-
|
|
|
- cipher = -1;
|
|
|
- if (ext->alg == IW_ENCODE_ALG_TKIP)
|
|
|
- cipher = WLAN_CIPHER_SUITE_TKIP;
|
|
|
- else if (ext->alg == IW_ENCODE_ALG_CCMP)
|
|
|
- cipher = WLAN_CIPHER_SUITE_CCMP;
|
|
|
-
|
|
|
- if ((wrqu->encoding.flags & IW_ENCODE_DISABLED) ||
|
|
|
- ext->alg == IW_ENCODE_ALG_NONE || ext->key_len == 0)
|
|
|
- return remove_key(usbdev, keyidx, NULL);
|
|
|
-
|
|
|
- if (cipher == -1)
|
|
|
- return -EOPNOTSUPP;
|
|
|
-
|
|
|
- flags = 0;
|
|
|
- if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
|
|
|
- flags |= NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ;
|
|
|
- if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY))
|
|
|
- flags |= NDIS_80211_ADDKEY_PAIRWISE_KEY;
|
|
|
- if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
|
|
|
- flags |= NDIS_80211_ADDKEY_TRANSMIT_KEY;
|
|
|
-
|
|
|
- return add_wpa_key(usbdev, ext->key, ext->key_len, keyidx,
|
|
|
- (u8 *)&ext->addr.sa_data, ext->rx_seq, cipher,
|
|
|
- flags);
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-static int rndis_iw_get_rate(struct net_device *dev,
|
|
|
- struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
|
|
|
-{
|
|
|
- struct usbnet *usbdev = netdev_priv(dev);
|
|
|
- __le32 tmp;
|
|
|
- int ret, len;
|
|
|
-
|
|
|
- len = sizeof(tmp);
|
|
|
- ret = rndis_query_oid(usbdev, OID_GEN_LINK_SPEED, &tmp, &len);
|
|
|
- if (ret == 0) {
|
|
|
- wrqu->bitrate.value = le32_to_cpu(tmp) * 100;
|
|
|
- wrqu->bitrate.disabled = 0;
|
|
|
- wrqu->bitrate.flags = 1;
|
|
|
- }
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-static struct iw_statistics *rndis_get_wireless_stats(struct net_device *dev)
|
|
|
-{
|
|
|
- struct usbnet *usbdev = netdev_priv(dev);
|
|
|
- struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
|
|
|
- unsigned long flags;
|
|
|
-
|
|
|
- spin_lock_irqsave(&priv->stats_lock, flags);
|
|
|
- memcpy(&priv->iwstats, &priv->privstats, sizeof(priv->iwstats));
|
|
|
- spin_unlock_irqrestore(&priv->stats_lock, flags);
|
|
|
-
|
|
|
- return &priv->iwstats;
|
|
|
-}
|
|
|
-#endif
|
|
|
-
|
|
|
-
|
|
|
-#define IW_IOCTL(x) [(x) - SIOCSIWCOMMIT]
|
|
|
-static const iw_handler rndis_iw_handler[] =
|
|
|
-{
|
|
|
- IW_IOCTL(SIOCGIWNAME) = (iw_handler) cfg80211_wext_giwname,
|
|
|
- IW_IOCTL(SIOCSIWFREQ) = (iw_handler) cfg80211_wext_siwfreq,
|
|
|
- IW_IOCTL(SIOCGIWFREQ) = (iw_handler) cfg80211_wext_giwfreq,
|
|
|
- IW_IOCTL(SIOCSIWMODE) = (iw_handler) cfg80211_wext_siwmode,
|
|
|
- IW_IOCTL(SIOCGIWMODE) = (iw_handler) cfg80211_wext_giwmode,
|
|
|
- IW_IOCTL(SIOCGIWRANGE) = (iw_handler) cfg80211_wext_giwrange,
|
|
|
- IW_IOCTL(SIOCSIWAP) = (iw_handler) cfg80211_wext_siwap,
|
|
|
- IW_IOCTL(SIOCGIWAP) = (iw_handler) cfg80211_wext_giwap,
|
|
|
- IW_IOCTL(SIOCSIWSCAN) = (iw_handler) cfg80211_wext_siwscan,
|
|
|
- IW_IOCTL(SIOCGIWSCAN) = (iw_handler) cfg80211_wext_giwscan,
|
|
|
- IW_IOCTL(SIOCSIWESSID) = (iw_handler) cfg80211_wext_siwessid,
|
|
|
- IW_IOCTL(SIOCGIWESSID) = (iw_handler) cfg80211_wext_giwessid,
|
|
|
- IW_IOCTL(SIOCGIWRATE) = (iw_handler) cfg80211_wext_giwrate,
|
|
|
- IW_IOCTL(SIOCSIWRTS) = (iw_handler) cfg80211_wext_siwrts,
|
|
|
- IW_IOCTL(SIOCGIWRTS) = (iw_handler) cfg80211_wext_giwrts,
|
|
|
- IW_IOCTL(SIOCSIWFRAG) = (iw_handler) cfg80211_wext_siwfrag,
|
|
|
- IW_IOCTL(SIOCGIWFRAG) = (iw_handler) cfg80211_wext_giwfrag,
|
|
|
- IW_IOCTL(SIOCSIWTXPOW) = (iw_handler) cfg80211_wext_siwtxpower,
|
|
|
- IW_IOCTL(SIOCGIWTXPOW) = (iw_handler) cfg80211_wext_giwtxpower,
|
|
|
- IW_IOCTL(SIOCSIWENCODE) = (iw_handler) cfg80211_wext_siwencode,
|
|
|
- IW_IOCTL(SIOCSIWENCODEEXT) = (iw_handler) cfg80211_wext_siwencodeext,
|
|
|
- IW_IOCTL(SIOCSIWAUTH) = (iw_handler) cfg80211_wext_siwauth,
|
|
|
- IW_IOCTL(SIOCGIWAUTH) = (iw_handler) cfg80211_wext_giwauth,
|
|
|
- IW_IOCTL(SIOCSIWGENIE) = (iw_handler) cfg80211_wext_siwgenie,
|
|
|
- IW_IOCTL(SIOCSIWMLME) = (iw_handler) cfg80211_wext_siwmlme,
|
|
|
-};
|
|
|
-
|
|
|
-static const iw_handler rndis_wlan_private_handler[] = {
|
|
|
-};
|
|
|
-
|
|
|
-static const struct iw_priv_args rndis_wlan_private_args[] = {
|
|
|
-};
|
|
|
-
|
|
|
-
|
|
|
-static const struct iw_handler_def rndis_iw_handlers = {
|
|
|
- .num_standard = ARRAY_SIZE(rndis_iw_handler),
|
|
|
- .num_private = ARRAY_SIZE(rndis_wlan_private_handler),
|
|
|
- .num_private_args = ARRAY_SIZE(rndis_wlan_private_args),
|
|
|
- .standard = (iw_handler *)rndis_iw_handler,
|
|
|
- .private = (iw_handler *)rndis_wlan_private_handler,
|
|
|
- .private_args = (struct iw_priv_args *)rndis_wlan_private_args,
|
|
|
- .get_wireless_stats = cfg80211_wireless_stats,
|
|
|
-};
|
|
|
-
|
|
|
|
|
|
static void rndis_wlan_do_link_up_work(struct usbnet *usbdev)
|
|
|
{
|
|
@@ -3166,7 +2746,6 @@ static int rndis_wlan_bind(struct usbnet *usbdev, struct usb_interface *intf)
|
|
|
* Otherwise we'll be in big trouble in rndis_wlan_early_init().
|
|
|
*/
|
|
|
usbdev->driver_priv = priv;
|
|
|
- usbdev->net->wireless_handlers = &rndis_iw_handlers;
|
|
|
priv->usbdev = usbdev;
|
|
|
|
|
|
mutex_init(&priv->command_lock);
|