LCOV - code coverage report
Current view: top level - net/wireless - wext-compat.c (source / functions) Hit Total Coverage
Test: Real Lines: 0 608 0.0 %
Date: 2020-10-17 15:46:43 Functions: 0 38 0.0 %
Legend: Neither, QEMU, Real, Both Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0
       2                 :            : /*
       3                 :            :  * cfg80211 - wext compat code
       4                 :            :  *
       5                 :            :  * This is temporary code until all wireless functionality is migrated
       6                 :            :  * into cfg80211, when that happens all the exports here go away and
       7                 :            :  * we directly assign the wireless handlers of wireless interfaces.
       8                 :            :  *
       9                 :            :  * Copyright 2008-2009  Johannes Berg <johannes@sipsolutions.net>
      10                 :            :  * Copyright (C) 2019 Intel Corporation
      11                 :            :  */
      12                 :            : 
      13                 :            : #include <linux/export.h>
      14                 :            : #include <linux/wireless.h>
      15                 :            : #include <linux/nl80211.h>
      16                 :            : #include <linux/if_arp.h>
      17                 :            : #include <linux/etherdevice.h>
      18                 :            : #include <linux/slab.h>
      19                 :            : #include <net/iw_handler.h>
      20                 :            : #include <net/cfg80211.h>
      21                 :            : #include <net/cfg80211-wext.h>
      22                 :            : #include "wext-compat.h"
      23                 :            : #include "core.h"
      24                 :            : #include "rdev-ops.h"
      25                 :            : 
      26                 :          0 : int cfg80211_wext_giwname(struct net_device *dev,
      27                 :            :                           struct iw_request_info *info,
      28                 :            :                           char *name, char *extra)
      29                 :            : {
      30                 :          0 :         strcpy(name, "IEEE 802.11");
      31                 :          0 :         return 0;
      32                 :            : }
      33                 :            : EXPORT_WEXT_HANDLER(cfg80211_wext_giwname);
      34                 :            : 
      35                 :          0 : int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info,
      36                 :            :                           u32 *mode, char *extra)
      37                 :            : {
      38                 :          0 :         struct wireless_dev *wdev = dev->ieee80211_ptr;
      39                 :            :         struct cfg80211_registered_device *rdev;
      40                 :            :         struct vif_params vifparams;
      41                 :            :         enum nl80211_iftype type;
      42                 :            : 
      43                 :          0 :         rdev = wiphy_to_rdev(wdev->wiphy);
      44                 :            : 
      45                 :          0 :         switch (*mode) {
      46                 :            :         case IW_MODE_INFRA:
      47                 :            :                 type = NL80211_IFTYPE_STATION;
      48                 :            :                 break;
      49                 :            :         case IW_MODE_ADHOC:
      50                 :            :                 type = NL80211_IFTYPE_ADHOC;
      51                 :          0 :                 break;
      52                 :            :         case IW_MODE_REPEAT:
      53                 :            :                 type = NL80211_IFTYPE_WDS;
      54                 :          0 :                 break;
      55                 :            :         case IW_MODE_MONITOR:
      56                 :            :                 type = NL80211_IFTYPE_MONITOR;
      57                 :          0 :                 break;
      58                 :            :         default:
      59                 :            :                 return -EINVAL;
      60                 :            :         }
      61                 :            : 
      62                 :          0 :         if (type == wdev->iftype)
      63                 :            :                 return 0;
      64                 :            : 
      65                 :          0 :         memset(&vifparams, 0, sizeof(vifparams));
      66                 :            : 
      67                 :          0 :         return cfg80211_change_iface(rdev, dev, type, &vifparams);
      68                 :            : }
      69                 :            : EXPORT_WEXT_HANDLER(cfg80211_wext_siwmode);
      70                 :            : 
      71                 :          0 : int cfg80211_wext_giwmode(struct net_device *dev, struct iw_request_info *info,
      72                 :            :                           u32 *mode, char *extra)
      73                 :            : {
      74                 :          0 :         struct wireless_dev *wdev = dev->ieee80211_ptr;
      75                 :            : 
      76                 :          0 :         if (!wdev)
      77                 :            :                 return -EOPNOTSUPP;
      78                 :            : 
      79                 :          0 :         switch (wdev->iftype) {
      80                 :            :         case NL80211_IFTYPE_AP:
      81                 :          0 :                 *mode = IW_MODE_MASTER;
      82                 :          0 :                 break;
      83                 :            :         case NL80211_IFTYPE_STATION:
      84                 :          0 :                 *mode = IW_MODE_INFRA;
      85                 :          0 :                 break;
      86                 :            :         case NL80211_IFTYPE_ADHOC:
      87                 :          0 :                 *mode = IW_MODE_ADHOC;
      88                 :          0 :                 break;
      89                 :            :         case NL80211_IFTYPE_MONITOR:
      90                 :          0 :                 *mode = IW_MODE_MONITOR;
      91                 :          0 :                 break;
      92                 :            :         case NL80211_IFTYPE_WDS:
      93                 :          0 :                 *mode = IW_MODE_REPEAT;
      94                 :          0 :                 break;
      95                 :            :         case NL80211_IFTYPE_AP_VLAN:
      96                 :          0 :                 *mode = IW_MODE_SECOND;         /* FIXME */
      97                 :          0 :                 break;
      98                 :            :         default:
      99                 :          0 :                 *mode = IW_MODE_AUTO;
     100                 :          0 :                 break;
     101                 :            :         }
     102                 :            :         return 0;
     103                 :            : }
     104                 :            : EXPORT_WEXT_HANDLER(cfg80211_wext_giwmode);
     105                 :            : 
     106                 :            : 
     107                 :          0 : int cfg80211_wext_giwrange(struct net_device *dev,
     108                 :            :                            struct iw_request_info *info,
     109                 :            :                            struct iw_point *data, char *extra)
     110                 :            : {
     111                 :          0 :         struct wireless_dev *wdev = dev->ieee80211_ptr;
     112                 :            :         struct iw_range *range = (struct iw_range *) extra;
     113                 :            :         enum nl80211_band band;
     114                 :            :         int i, c = 0;
     115                 :            : 
     116                 :          0 :         if (!wdev)
     117                 :            :                 return -EOPNOTSUPP;
     118                 :            : 
     119                 :          0 :         data->length = sizeof(struct iw_range);
     120                 :          0 :         memset(range, 0, sizeof(struct iw_range));
     121                 :            : 
     122                 :          0 :         range->we_version_compiled = WIRELESS_EXT;
     123                 :          0 :         range->we_version_source = 21;
     124                 :          0 :         range->retry_capa = IW_RETRY_LIMIT;
     125                 :          0 :         range->retry_flags = IW_RETRY_LIMIT;
     126                 :          0 :         range->min_retry = 0;
     127                 :          0 :         range->max_retry = 255;
     128                 :          0 :         range->min_rts = 0;
     129                 :          0 :         range->max_rts = 2347;
     130                 :          0 :         range->min_frag = 256;
     131                 :          0 :         range->max_frag = 2346;
     132                 :            : 
     133                 :          0 :         range->max_encoding_tokens = 4;
     134                 :            : 
     135                 :          0 :         range->max_qual.updated = IW_QUAL_NOISE_INVALID;
     136                 :            : 
     137                 :          0 :         switch (wdev->wiphy->signal_type) {
     138                 :            :         case CFG80211_SIGNAL_TYPE_NONE:
     139                 :            :                 break;
     140                 :            :         case CFG80211_SIGNAL_TYPE_MBM:
     141                 :          0 :                 range->max_qual.level = (u8)-110;
     142                 :          0 :                 range->max_qual.qual = 70;
     143                 :          0 :                 range->avg_qual.qual = 35;
     144                 :          0 :                 range->max_qual.updated |= IW_QUAL_DBM;
     145                 :          0 :                 range->max_qual.updated |= IW_QUAL_QUAL_UPDATED;
     146                 :          0 :                 range->max_qual.updated |= IW_QUAL_LEVEL_UPDATED;
     147                 :          0 :                 break;
     148                 :            :         case CFG80211_SIGNAL_TYPE_UNSPEC:
     149                 :          0 :                 range->max_qual.level = 100;
     150                 :          0 :                 range->max_qual.qual = 100;
     151                 :          0 :                 range->avg_qual.qual = 50;
     152                 :          0 :                 range->max_qual.updated |= IW_QUAL_QUAL_UPDATED;
     153                 :          0 :                 range->max_qual.updated |= IW_QUAL_LEVEL_UPDATED;
     154                 :          0 :                 break;
     155                 :            :         }
     156                 :            : 
     157                 :          0 :         range->avg_qual.level = range->max_qual.level / 2;
     158                 :          0 :         range->avg_qual.noise = range->max_qual.noise / 2;
     159                 :          0 :         range->avg_qual.updated = range->max_qual.updated;
     160                 :            : 
     161                 :          0 :         for (i = 0; i < wdev->wiphy->n_cipher_suites; i++) {
     162                 :          0 :                 switch (wdev->wiphy->cipher_suites[i]) {
     163                 :            :                 case WLAN_CIPHER_SUITE_TKIP:
     164                 :          0 :                         range->enc_capa |= (IW_ENC_CAPA_CIPHER_TKIP |
     165                 :            :                                             IW_ENC_CAPA_WPA);
     166                 :          0 :                         break;
     167                 :            : 
     168                 :            :                 case WLAN_CIPHER_SUITE_CCMP:
     169                 :          0 :                         range->enc_capa |= (IW_ENC_CAPA_CIPHER_CCMP |
     170                 :            :                                             IW_ENC_CAPA_WPA2);
     171                 :          0 :                         break;
     172                 :            : 
     173                 :            :                 case WLAN_CIPHER_SUITE_WEP40:
     174                 :          0 :                         range->encoding_size[range->num_encoding_sizes++] =
     175                 :            :                                 WLAN_KEY_LEN_WEP40;
     176                 :          0 :                         break;
     177                 :            : 
     178                 :            :                 case WLAN_CIPHER_SUITE_WEP104:
     179                 :          0 :                         range->encoding_size[range->num_encoding_sizes++] =
     180                 :            :                                 WLAN_KEY_LEN_WEP104;
     181                 :          0 :                         break;
     182                 :            :                 }
     183                 :            :         }
     184                 :            : 
     185                 :          0 :         for (band = 0; band < NUM_NL80211_BANDS; band ++) {
     186                 :            :                 struct ieee80211_supported_band *sband;
     187                 :            : 
     188                 :          0 :                 sband = wdev->wiphy->bands[band];
     189                 :            : 
     190                 :          0 :                 if (!sband)
     191                 :          0 :                         continue;
     192                 :            : 
     193                 :          0 :                 for (i = 0; i < sband->n_channels && c < IW_MAX_FREQUENCIES; i++) {
     194                 :          0 :                         struct ieee80211_channel *chan = &sband->channels[i];
     195                 :            : 
     196                 :          0 :                         if (!(chan->flags & IEEE80211_CHAN_DISABLED)) {
     197                 :          0 :                                 range->freq[c].i =
     198                 :          0 :                                         ieee80211_frequency_to_channel(
     199                 :          0 :                                                 chan->center_freq);
     200                 :          0 :                                 range->freq[c].m = chan->center_freq;
     201                 :          0 :                                 range->freq[c].e = 6;
     202                 :          0 :                                 c++;
     203                 :            :                         }
     204                 :            :                 }
     205                 :            :         }
     206                 :          0 :         range->num_channels = c;
     207                 :          0 :         range->num_frequency = c;
     208                 :            : 
     209                 :          0 :         IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
     210                 :          0 :         IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
     211                 :          0 :         IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
     212                 :            : 
     213                 :          0 :         if (wdev->wiphy->max_scan_ssids > 0)
     214                 :          0 :                 range->scan_capa |= IW_SCAN_CAPA_ESSID;
     215                 :            : 
     216                 :            :         return 0;
     217                 :            : }
     218                 :            : EXPORT_WEXT_HANDLER(cfg80211_wext_giwrange);
     219                 :            : 
     220                 :            : 
     221                 :            : /**
     222                 :            :  * cfg80211_wext_freq - get wext frequency for non-"auto"
     223                 :            :  * @dev: the net device
     224                 :            :  * @freq: the wext freq encoding
     225                 :            :  *
     226                 :            :  * Returns a frequency, or a negative error code, or 0 for auto.
     227                 :            :  */
     228                 :          0 : int cfg80211_wext_freq(struct iw_freq *freq)
     229                 :            : {
     230                 :            :         /*
     231                 :            :          * Parse frequency - return 0 for auto and
     232                 :            :          * -EINVAL for impossible things.
     233                 :            :          */
     234                 :          0 :         if (freq->e == 0) {
     235                 :            :                 enum nl80211_band band = NL80211_BAND_2GHZ;
     236                 :          0 :                 if (freq->m < 0)
     237                 :            :                         return 0;
     238                 :          0 :                 if (freq->m > 14)
     239                 :            :                         band = NL80211_BAND_5GHZ;
     240                 :          0 :                 return ieee80211_channel_to_frequency(freq->m, band);
     241                 :            :         } else {
     242                 :            :                 int i, div = 1000000;
     243                 :          0 :                 for (i = 0; i < freq->e; i++)
     244                 :          0 :                         div /= 10;
     245                 :          0 :                 if (div <= 0)
     246                 :            :                         return -EINVAL;
     247                 :          0 :                 return freq->m / div;
     248                 :            :         }
     249                 :            : }
     250                 :            : 
     251                 :          0 : int cfg80211_wext_siwrts(struct net_device *dev,
     252                 :            :                          struct iw_request_info *info,
     253                 :            :                          struct iw_param *rts, char *extra)
     254                 :            : {
     255                 :          0 :         struct wireless_dev *wdev = dev->ieee80211_ptr;
     256                 :          0 :         struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
     257                 :          0 :         u32 orts = wdev->wiphy->rts_threshold;
     258                 :            :         int err;
     259                 :            : 
     260                 :          0 :         if (rts->disabled || !rts->fixed)
     261                 :          0 :                 wdev->wiphy->rts_threshold = (u32) -1;
     262                 :          0 :         else if (rts->value < 0)
     263                 :            :                 return -EINVAL;
     264                 :            :         else
     265                 :          0 :                 wdev->wiphy->rts_threshold = rts->value;
     266                 :            : 
     267                 :          0 :         err = rdev_set_wiphy_params(rdev, WIPHY_PARAM_RTS_THRESHOLD);
     268                 :          0 :         if (err)
     269                 :          0 :                 wdev->wiphy->rts_threshold = orts;
     270                 :            : 
     271                 :          0 :         return err;
     272                 :            : }
     273                 :            : EXPORT_WEXT_HANDLER(cfg80211_wext_siwrts);
     274                 :            : 
     275                 :          0 : int cfg80211_wext_giwrts(struct net_device *dev,
     276                 :            :                          struct iw_request_info *info,
     277                 :            :                          struct iw_param *rts, char *extra)
     278                 :            : {
     279                 :          0 :         struct wireless_dev *wdev = dev->ieee80211_ptr;
     280                 :            : 
     281                 :          0 :         rts->value = wdev->wiphy->rts_threshold;
     282                 :          0 :         rts->disabled = rts->value == (u32) -1;
     283                 :          0 :         rts->fixed = 1;
     284                 :            : 
     285                 :          0 :         return 0;
     286                 :            : }
     287                 :            : EXPORT_WEXT_HANDLER(cfg80211_wext_giwrts);
     288                 :            : 
     289                 :          0 : int cfg80211_wext_siwfrag(struct net_device *dev,
     290                 :            :                           struct iw_request_info *info,
     291                 :            :                           struct iw_param *frag, char *extra)
     292                 :            : {
     293                 :          0 :         struct wireless_dev *wdev = dev->ieee80211_ptr;
     294                 :          0 :         struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
     295                 :          0 :         u32 ofrag = wdev->wiphy->frag_threshold;
     296                 :            :         int err;
     297                 :            : 
     298                 :          0 :         if (frag->disabled || !frag->fixed)
     299                 :          0 :                 wdev->wiphy->frag_threshold = (u32) -1;
     300                 :          0 :         else if (frag->value < 256)
     301                 :            :                 return -EINVAL;
     302                 :            :         else {
     303                 :            :                 /* Fragment length must be even, so strip LSB. */
     304                 :          0 :                 wdev->wiphy->frag_threshold = frag->value & ~0x1;
     305                 :            :         }
     306                 :            : 
     307                 :          0 :         err = rdev_set_wiphy_params(rdev, WIPHY_PARAM_FRAG_THRESHOLD);
     308                 :          0 :         if (err)
     309                 :          0 :                 wdev->wiphy->frag_threshold = ofrag;
     310                 :            : 
     311                 :          0 :         return err;
     312                 :            : }
     313                 :            : EXPORT_WEXT_HANDLER(cfg80211_wext_siwfrag);
     314                 :            : 
     315                 :          0 : int cfg80211_wext_giwfrag(struct net_device *dev,
     316                 :            :                           struct iw_request_info *info,
     317                 :            :                           struct iw_param *frag, char *extra)
     318                 :            : {
     319                 :          0 :         struct wireless_dev *wdev = dev->ieee80211_ptr;
     320                 :            : 
     321                 :          0 :         frag->value = wdev->wiphy->frag_threshold;
     322                 :          0 :         frag->disabled = frag->value == (u32) -1;
     323                 :          0 :         frag->fixed = 1;
     324                 :            : 
     325                 :          0 :         return 0;
     326                 :            : }
     327                 :            : EXPORT_WEXT_HANDLER(cfg80211_wext_giwfrag);
     328                 :            : 
     329                 :          0 : static int cfg80211_wext_siwretry(struct net_device *dev,
     330                 :            :                                   struct iw_request_info *info,
     331                 :            :                                   struct iw_param *retry, char *extra)
     332                 :            : {
     333                 :          0 :         struct wireless_dev *wdev = dev->ieee80211_ptr;
     334                 :          0 :         struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
     335                 :            :         u32 changed = 0;
     336                 :          0 :         u8 olong = wdev->wiphy->retry_long;
     337                 :          0 :         u8 oshort = wdev->wiphy->retry_short;
     338                 :            :         int err;
     339                 :            : 
     340                 :          0 :         if (retry->disabled || retry->value < 1 || retry->value > 255 ||
     341                 :          0 :             (retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT)
     342                 :            :                 return -EINVAL;
     343                 :            : 
     344                 :          0 :         if (retry->flags & IW_RETRY_LONG) {
     345                 :          0 :                 wdev->wiphy->retry_long = retry->value;
     346                 :            :                 changed |= WIPHY_PARAM_RETRY_LONG;
     347                 :          0 :         } else if (retry->flags & IW_RETRY_SHORT) {
     348                 :          0 :                 wdev->wiphy->retry_short = retry->value;
     349                 :            :                 changed |= WIPHY_PARAM_RETRY_SHORT;
     350                 :            :         } else {
     351                 :          0 :                 wdev->wiphy->retry_short = retry->value;
     352                 :          0 :                 wdev->wiphy->retry_long = retry->value;
     353                 :            :                 changed |= WIPHY_PARAM_RETRY_LONG;
     354                 :            :                 changed |= WIPHY_PARAM_RETRY_SHORT;
     355                 :            :         }
     356                 :            : 
     357                 :          0 :         err = rdev_set_wiphy_params(rdev, changed);
     358                 :          0 :         if (err) {
     359                 :          0 :                 wdev->wiphy->retry_short = oshort;
     360                 :          0 :                 wdev->wiphy->retry_long = olong;
     361                 :            :         }
     362                 :            : 
     363                 :          0 :         return err;
     364                 :            : }
     365                 :            : 
     366                 :          0 : int cfg80211_wext_giwretry(struct net_device *dev,
     367                 :            :                            struct iw_request_info *info,
     368                 :            :                            struct iw_param *retry, char *extra)
     369                 :            : {
     370                 :          0 :         struct wireless_dev *wdev = dev->ieee80211_ptr;
     371                 :            : 
     372                 :          0 :         retry->disabled = 0;
     373                 :            : 
     374                 :          0 :         if (retry->flags == 0 || (retry->flags & IW_RETRY_SHORT)) {
     375                 :            :                 /*
     376                 :            :                  * First return short value, iwconfig will ask long value
     377                 :            :                  * later if needed
     378                 :            :                  */
     379                 :          0 :                 retry->flags |= IW_RETRY_LIMIT | IW_RETRY_SHORT;
     380                 :          0 :                 retry->value = wdev->wiphy->retry_short;
     381                 :          0 :                 if (wdev->wiphy->retry_long == wdev->wiphy->retry_short)
     382                 :          0 :                         retry->flags |= IW_RETRY_LONG;
     383                 :            : 
     384                 :            :                 return 0;
     385                 :            :         }
     386                 :            : 
     387                 :          0 :         if (retry->flags & IW_RETRY_LONG) {
     388                 :          0 :                 retry->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
     389                 :          0 :                 retry->value = wdev->wiphy->retry_long;
     390                 :            :         }
     391                 :            : 
     392                 :            :         return 0;
     393                 :            : }
     394                 :            : EXPORT_WEXT_HANDLER(cfg80211_wext_giwretry);
     395                 :            : 
     396                 :          0 : static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
     397                 :            :                                      struct net_device *dev, bool pairwise,
     398                 :            :                                      const u8 *addr, bool remove, bool tx_key,
     399                 :            :                                      int idx, struct key_params *params)
     400                 :            : {
     401                 :          0 :         struct wireless_dev *wdev = dev->ieee80211_ptr;
     402                 :            :         int err, i;
     403                 :            :         bool rejoin = false;
     404                 :            : 
     405                 :          0 :         if (pairwise && !addr)
     406                 :            :                 return -EINVAL;
     407                 :            : 
     408                 :            :         /*
     409                 :            :          * In many cases we won't actually need this, but it's better
     410                 :            :          * to do it first in case the allocation fails. Don't use wext.
     411                 :            :          */
     412                 :          0 :         if (!wdev->wext.keys) {
     413                 :          0 :                 wdev->wext.keys = kzalloc(sizeof(*wdev->wext.keys),
     414                 :            :                                           GFP_KERNEL);
     415                 :          0 :                 if (!wdev->wext.keys)
     416                 :            :                         return -ENOMEM;
     417                 :          0 :                 for (i = 0; i < CFG80211_MAX_WEP_KEYS; i++)
     418                 :          0 :                         wdev->wext.keys->params[i].key =
     419                 :          0 :                                 wdev->wext.keys->data[i];
     420                 :            :         }
     421                 :            : 
     422                 :          0 :         if (wdev->iftype != NL80211_IFTYPE_ADHOC &&
     423                 :            :             wdev->iftype != NL80211_IFTYPE_STATION)
     424                 :            :                 return -EOPNOTSUPP;
     425                 :            : 
     426                 :          0 :         if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
     427                 :          0 :                 if (!wdev->current_bss)
     428                 :            :                         return -ENOLINK;
     429                 :            : 
     430                 :          0 :                 if (!rdev->ops->set_default_mgmt_key)
     431                 :            :                         return -EOPNOTSUPP;
     432                 :            : 
     433                 :          0 :                 if (idx < 4 || idx > 5)
     434                 :            :                         return -EINVAL;
     435                 :          0 :         } else if (idx < 0 || idx > 3)
     436                 :            :                 return -EINVAL;
     437                 :            : 
     438                 :          0 :         if (remove) {
     439                 :            :                 err = 0;
     440                 :          0 :                 if (wdev->current_bss) {
     441                 :            :                         /*
     442                 :            :                          * If removing the current TX key, we will need to
     443                 :            :                          * join a new IBSS without the privacy bit clear.
     444                 :            :                          */
     445                 :          0 :                         if (idx == wdev->wext.default_key &&
     446                 :            :                             wdev->iftype == NL80211_IFTYPE_ADHOC) {
     447                 :          0 :                                 __cfg80211_leave_ibss(rdev, wdev->netdev, true);
     448                 :            :                                 rejoin = true;
     449                 :            :                         }
     450                 :            : 
     451                 :          0 :                         if (!pairwise && addr &&
     452                 :          0 :                             !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
     453                 :            :                                 err = -ENOENT;
     454                 :            :                         else
     455                 :          0 :                                 err = rdev_del_key(rdev, dev, idx, pairwise,
     456                 :            :                                                    addr);
     457                 :            :                 }
     458                 :          0 :                 wdev->wext.connect.privacy = false;
     459                 :            :                 /*
     460                 :            :                  * Applications using wireless extensions expect to be
     461                 :            :                  * able to delete keys that don't exist, so allow that.
     462                 :            :                  */
     463                 :          0 :                 if (err == -ENOENT)
     464                 :            :                         err = 0;
     465                 :          0 :                 if (!err) {
     466                 :          0 :                         if (!addr && idx < 4) {
     467                 :          0 :                                 memset(wdev->wext.keys->data[idx], 0,
     468                 :            :                                        sizeof(wdev->wext.keys->data[idx]));
     469                 :          0 :                                 wdev->wext.keys->params[idx].key_len = 0;
     470                 :          0 :                                 wdev->wext.keys->params[idx].cipher = 0;
     471                 :            :                         }
     472                 :          0 :                         if (idx == wdev->wext.default_key)
     473                 :          0 :                                 wdev->wext.default_key = -1;
     474                 :          0 :                         else if (idx == wdev->wext.default_mgmt_key)
     475                 :          0 :                                 wdev->wext.default_mgmt_key = -1;
     476                 :            :                 }
     477                 :            : 
     478                 :          0 :                 if (!err && rejoin)
     479                 :          0 :                         err = cfg80211_ibss_wext_join(rdev, wdev);
     480                 :            : 
     481                 :          0 :                 return err;
     482                 :            :         }
     483                 :            : 
     484                 :          0 :         if (addr)
     485                 :            :                 tx_key = false;
     486                 :            : 
     487                 :          0 :         if (cfg80211_validate_key_settings(rdev, params, idx, pairwise, addr))
     488                 :            :                 return -EINVAL;
     489                 :            : 
     490                 :            :         err = 0;
     491                 :          0 :         if (wdev->current_bss)
     492                 :          0 :                 err = rdev_add_key(rdev, dev, idx, pairwise, addr, params);
     493                 :          0 :         else if (params->cipher != WLAN_CIPHER_SUITE_WEP40 &&
     494                 :            :                  params->cipher != WLAN_CIPHER_SUITE_WEP104)
     495                 :            :                 return -EINVAL;
     496                 :          0 :         if (err)
     497                 :            :                 return err;
     498                 :            : 
     499                 :            :         /*
     500                 :            :          * We only need to store WEP keys, since they're the only keys that
     501                 :            :          * can be be set before a connection is established and persist after
     502                 :            :          * disconnecting.
     503                 :            :          */
     504                 :          0 :         if (!addr && (params->cipher == WLAN_CIPHER_SUITE_WEP40 ||
     505                 :            :                       params->cipher == WLAN_CIPHER_SUITE_WEP104)) {
     506                 :          0 :                 wdev->wext.keys->params[idx] = *params;
     507                 :          0 :                 memcpy(wdev->wext.keys->data[idx],
     508                 :          0 :                         params->key, params->key_len);
     509                 :          0 :                 wdev->wext.keys->params[idx].key =
     510                 :          0 :                         wdev->wext.keys->data[idx];
     511                 :            :         }
     512                 :            : 
     513                 :          0 :         if ((params->cipher == WLAN_CIPHER_SUITE_WEP40 ||
     514                 :          0 :              params->cipher == WLAN_CIPHER_SUITE_WEP104) &&
     515                 :          0 :             (tx_key || (!addr && wdev->wext.default_key == -1))) {
     516                 :          0 :                 if (wdev->current_bss) {
     517                 :            :                         /*
     518                 :            :                          * If we are getting a new TX key from not having
     519                 :            :                          * had one before we need to join a new IBSS with
     520                 :            :                          * the privacy bit set.
     521                 :            :                          */
     522                 :          0 :                         if (wdev->iftype == NL80211_IFTYPE_ADHOC &&
     523                 :          0 :                             wdev->wext.default_key == -1) {
     524                 :          0 :                                 __cfg80211_leave_ibss(rdev, wdev->netdev, true);
     525                 :            :                                 rejoin = true;
     526                 :            :                         }
     527                 :          0 :                         err = rdev_set_default_key(rdev, dev, idx, true, true);
     528                 :            :                 }
     529                 :          0 :                 if (!err) {
     530                 :          0 :                         wdev->wext.default_key = idx;
     531                 :          0 :                         if (rejoin)
     532                 :          0 :                                 err = cfg80211_ibss_wext_join(rdev, wdev);
     533                 :            :                 }
     534                 :          0 :                 return err;
     535                 :            :         }
     536                 :            : 
     537                 :          0 :         if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC &&
     538                 :          0 :             (tx_key || (!addr && wdev->wext.default_mgmt_key == -1))) {
     539                 :          0 :                 if (wdev->current_bss)
     540                 :          0 :                         err = rdev_set_default_mgmt_key(rdev, dev, idx);
     541                 :          0 :                 if (!err)
     542                 :          0 :                         wdev->wext.default_mgmt_key = idx;
     543                 :          0 :                 return err;
     544                 :            :         }
     545                 :            : 
     546                 :            :         return 0;
     547                 :            : }
     548                 :            : 
     549                 :          0 : static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
     550                 :            :                                    struct net_device *dev, bool pairwise,
     551                 :            :                                    const u8 *addr, bool remove, bool tx_key,
     552                 :            :                                    int idx, struct key_params *params)
     553                 :            : {
     554                 :            :         int err;
     555                 :            : 
     556                 :          0 :         wdev_lock(dev->ieee80211_ptr);
     557                 :          0 :         err = __cfg80211_set_encryption(rdev, dev, pairwise, addr,
     558                 :            :                                         remove, tx_key, idx, params);
     559                 :          0 :         wdev_unlock(dev->ieee80211_ptr);
     560                 :            : 
     561                 :          0 :         return err;
     562                 :            : }
     563                 :            : 
     564                 :          0 : static int cfg80211_wext_siwencode(struct net_device *dev,
     565                 :            :                                    struct iw_request_info *info,
     566                 :            :                                    struct iw_point *erq, char *keybuf)
     567                 :            : {
     568                 :          0 :         struct wireless_dev *wdev = dev->ieee80211_ptr;
     569                 :          0 :         struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
     570                 :            :         int idx, err;
     571                 :            :         bool remove = false;
     572                 :            :         struct key_params params;
     573                 :            : 
     574                 :          0 :         if (wdev->iftype != NL80211_IFTYPE_STATION &&
     575                 :            :             wdev->iftype != NL80211_IFTYPE_ADHOC)
     576                 :            :                 return -EOPNOTSUPP;
     577                 :            : 
     578                 :            :         /* no use -- only MFP (set_default_mgmt_key) is optional */
     579                 :          0 :         if (!rdev->ops->del_key ||
     580                 :          0 :             !rdev->ops->add_key ||
     581                 :          0 :             !rdev->ops->set_default_key)
     582                 :            :                 return -EOPNOTSUPP;
     583                 :            : 
     584                 :          0 :         idx = erq->flags & IW_ENCODE_INDEX;
     585                 :          0 :         if (idx == 0) {
     586                 :          0 :                 idx = wdev->wext.default_key;
     587                 :          0 :                 if (idx < 0)
     588                 :            :                         idx = 0;
     589                 :          0 :         } else if (idx < 1 || idx > 4)
     590                 :            :                 return -EINVAL;
     591                 :            :         else
     592                 :          0 :                 idx--;
     593                 :            : 
     594                 :          0 :         if (erq->flags & IW_ENCODE_DISABLED)
     595                 :            :                 remove = true;
     596                 :          0 :         else if (erq->length == 0) {
     597                 :            :                 /* No key data - just set the default TX key index */
     598                 :            :                 err = 0;
     599                 :            :                 wdev_lock(wdev);
     600                 :          0 :                 if (wdev->current_bss)
     601                 :          0 :                         err = rdev_set_default_key(rdev, dev, idx, true,
     602                 :            :                                                    true);
     603                 :          0 :                 if (!err)
     604                 :          0 :                         wdev->wext.default_key = idx;
     605                 :            :                 wdev_unlock(wdev);
     606                 :          0 :                 return err;
     607                 :            :         }
     608                 :            : 
     609                 :          0 :         memset(&params, 0, sizeof(params));
     610                 :          0 :         params.key = keybuf;
     611                 :          0 :         params.key_len = erq->length;
     612                 :          0 :         if (erq->length == 5)
     613                 :          0 :                 params.cipher = WLAN_CIPHER_SUITE_WEP40;
     614                 :          0 :         else if (erq->length == 13)
     615                 :          0 :                 params.cipher = WLAN_CIPHER_SUITE_WEP104;
     616                 :          0 :         else if (!remove)
     617                 :            :                 return -EINVAL;
     618                 :            : 
     619                 :          0 :         return cfg80211_set_encryption(rdev, dev, false, NULL, remove,
     620                 :          0 :                                        wdev->wext.default_key == -1,
     621                 :            :                                        idx, &params);
     622                 :            : }
     623                 :            : 
     624                 :          0 : static int cfg80211_wext_siwencodeext(struct net_device *dev,
     625                 :            :                                       struct iw_request_info *info,
     626                 :            :                                       struct iw_point *erq, char *extra)
     627                 :            : {
     628                 :          0 :         struct wireless_dev *wdev = dev->ieee80211_ptr;
     629                 :          0 :         struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
     630                 :            :         struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
     631                 :            :         const u8 *addr;
     632                 :            :         int idx;
     633                 :            :         bool remove = false;
     634                 :            :         struct key_params params;
     635                 :            :         u32 cipher;
     636                 :            : 
     637                 :          0 :         if (wdev->iftype != NL80211_IFTYPE_STATION &&
     638                 :            :             wdev->iftype != NL80211_IFTYPE_ADHOC)
     639                 :            :                 return -EOPNOTSUPP;
     640                 :            : 
     641                 :            :         /* no use -- only MFP (set_default_mgmt_key) is optional */
     642                 :          0 :         if (!rdev->ops->del_key ||
     643                 :          0 :             !rdev->ops->add_key ||
     644                 :          0 :             !rdev->ops->set_default_key)
     645                 :            :                 return -EOPNOTSUPP;
     646                 :            : 
     647                 :          0 :         switch (ext->alg) {
     648                 :            :         case IW_ENCODE_ALG_NONE:
     649                 :            :                 remove = true;
     650                 :            :                 cipher = 0;
     651                 :            :                 break;
     652                 :            :         case IW_ENCODE_ALG_WEP:
     653                 :          0 :                 if (ext->key_len == 5)
     654                 :            :                         cipher = WLAN_CIPHER_SUITE_WEP40;
     655                 :          0 :                 else if (ext->key_len == 13)
     656                 :            :                         cipher = WLAN_CIPHER_SUITE_WEP104;
     657                 :            :                 else
     658                 :            :                         return -EINVAL;
     659                 :            :                 break;
     660                 :            :         case IW_ENCODE_ALG_TKIP:
     661                 :            :                 cipher = WLAN_CIPHER_SUITE_TKIP;
     662                 :          0 :                 break;
     663                 :            :         case IW_ENCODE_ALG_CCMP:
     664                 :            :                 cipher = WLAN_CIPHER_SUITE_CCMP;
     665                 :          0 :                 break;
     666                 :            :         case IW_ENCODE_ALG_AES_CMAC:
     667                 :            :                 cipher = WLAN_CIPHER_SUITE_AES_CMAC;
     668                 :          0 :                 break;
     669                 :            :         default:
     670                 :            :                 return -EOPNOTSUPP;
     671                 :            :         }
     672                 :            : 
     673                 :          0 :         if (erq->flags & IW_ENCODE_DISABLED)
     674                 :            :                 remove = true;
     675                 :            : 
     676                 :          0 :         idx = erq->flags & IW_ENCODE_INDEX;
     677                 :          0 :         if (cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
     678                 :          0 :                 if (idx < 4 || idx > 5) {
     679                 :          0 :                         idx = wdev->wext.default_mgmt_key;
     680                 :          0 :                         if (idx < 0)
     681                 :            :                                 return -EINVAL;
     682                 :            :                 } else
     683                 :          0 :                         idx--;
     684                 :            :         } else {
     685                 :          0 :                 if (idx < 1 || idx > 4) {
     686                 :          0 :                         idx = wdev->wext.default_key;
     687                 :          0 :                         if (idx < 0)
     688                 :            :                                 return -EINVAL;
     689                 :            :                 } else
     690                 :          0 :                         idx--;
     691                 :            :         }
     692                 :            : 
     693                 :          0 :         addr = ext->addr.sa_data;
     694                 :          0 :         if (is_broadcast_ether_addr(addr))
     695                 :            :                 addr = NULL;
     696                 :            : 
     697                 :          0 :         memset(&params, 0, sizeof(params));
     698                 :          0 :         params.key = ext->key;
     699                 :          0 :         params.key_len = ext->key_len;
     700                 :          0 :         params.cipher = cipher;
     701                 :            : 
     702                 :          0 :         if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
     703                 :          0 :                 params.seq = ext->rx_seq;
     704                 :          0 :                 params.seq_len = 6;
     705                 :            :         }
     706                 :            : 
     707                 :          0 :         return cfg80211_set_encryption(
     708                 :            :                         rdev, dev,
     709                 :          0 :                         !(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY),
     710                 :            :                         addr, remove,
     711                 :          0 :                         ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,
     712                 :            :                         idx, &params);
     713                 :            : }
     714                 :            : 
     715                 :          0 : static int cfg80211_wext_giwencode(struct net_device *dev,
     716                 :            :                                    struct iw_request_info *info,
     717                 :            :                                    struct iw_point *erq, char *keybuf)
     718                 :            : {
     719                 :          0 :         struct wireless_dev *wdev = dev->ieee80211_ptr;
     720                 :            :         int idx;
     721                 :            : 
     722                 :          0 :         if (wdev->iftype != NL80211_IFTYPE_STATION &&
     723                 :            :             wdev->iftype != NL80211_IFTYPE_ADHOC)
     724                 :            :                 return -EOPNOTSUPP;
     725                 :            : 
     726                 :          0 :         idx = erq->flags & IW_ENCODE_INDEX;
     727                 :          0 :         if (idx == 0) {
     728                 :          0 :                 idx = wdev->wext.default_key;
     729                 :          0 :                 if (idx < 0)
     730                 :            :                         idx = 0;
     731                 :          0 :         } else if (idx < 1 || idx > 4)
     732                 :            :                 return -EINVAL;
     733                 :            :         else
     734                 :          0 :                 idx--;
     735                 :            : 
     736                 :          0 :         erq->flags = idx + 1;
     737                 :            : 
     738                 :          0 :         if (!wdev->wext.keys || !wdev->wext.keys->params[idx].cipher) {
     739                 :          0 :                 erq->flags |= IW_ENCODE_DISABLED;
     740                 :          0 :                 erq->length = 0;
     741                 :          0 :                 return 0;
     742                 :            :         }
     743                 :            : 
     744                 :          0 :         erq->length = min_t(size_t, erq->length,
     745                 :            :                             wdev->wext.keys->params[idx].key_len);
     746                 :          0 :         memcpy(keybuf, wdev->wext.keys->params[idx].key, erq->length);
     747                 :            :         erq->flags |= IW_ENCODE_ENABLED;
     748                 :            : 
     749                 :          0 :         return 0;
     750                 :            : }
     751                 :            : 
     752                 :          0 : static int cfg80211_wext_siwfreq(struct net_device *dev,
     753                 :            :                                  struct iw_request_info *info,
     754                 :            :                                  struct iw_freq *wextfreq, char *extra)
     755                 :            : {
     756                 :          0 :         struct wireless_dev *wdev = dev->ieee80211_ptr;
     757                 :          0 :         struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
     758                 :          0 :         struct cfg80211_chan_def chandef = {
     759                 :            :                 .width = NL80211_CHAN_WIDTH_20_NOHT,
     760                 :            :         };
     761                 :            :         int freq;
     762                 :            : 
     763                 :          0 :         switch (wdev->iftype) {
     764                 :            :         case NL80211_IFTYPE_STATION:
     765                 :          0 :                 return cfg80211_mgd_wext_siwfreq(dev, info, wextfreq, extra);
     766                 :            :         case NL80211_IFTYPE_ADHOC:
     767                 :          0 :                 return cfg80211_ibss_wext_siwfreq(dev, info, wextfreq, extra);
     768                 :            :         case NL80211_IFTYPE_MONITOR:
     769                 :          0 :                 freq = cfg80211_wext_freq(wextfreq);
     770                 :          0 :                 if (freq < 0)
     771                 :            :                         return freq;
     772                 :          0 :                 if (freq == 0)
     773                 :            :                         return -EINVAL;
     774                 :          0 :                 chandef.center_freq1 = freq;
     775                 :          0 :                 chandef.chan = ieee80211_get_channel(&rdev->wiphy, freq);
     776                 :          0 :                 if (!chandef.chan)
     777                 :            :                         return -EINVAL;
     778                 :          0 :                 return cfg80211_set_monitor_channel(rdev, &chandef);
     779                 :            :         case NL80211_IFTYPE_MESH_POINT:
     780                 :          0 :                 freq = cfg80211_wext_freq(wextfreq);
     781                 :          0 :                 if (freq < 0)
     782                 :            :                         return freq;
     783                 :          0 :                 if (freq == 0)
     784                 :            :                         return -EINVAL;
     785                 :          0 :                 chandef.center_freq1 = freq;
     786                 :          0 :                 chandef.chan = ieee80211_get_channel(&rdev->wiphy, freq);
     787                 :          0 :                 if (!chandef.chan)
     788                 :            :                         return -EINVAL;
     789                 :          0 :                 return cfg80211_set_mesh_channel(rdev, wdev, &chandef);
     790                 :            :         default:
     791                 :            :                 return -EOPNOTSUPP;
     792                 :            :         }
     793                 :            : }
     794                 :            : 
     795                 :          0 : static int cfg80211_wext_giwfreq(struct net_device *dev,
     796                 :            :                                  struct iw_request_info *info,
     797                 :            :                                  struct iw_freq *freq, char *extra)
     798                 :            : {
     799                 :          0 :         struct wireless_dev *wdev = dev->ieee80211_ptr;
     800                 :          0 :         struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
     801                 :          0 :         struct cfg80211_chan_def chandef = {};
     802                 :            :         int ret;
     803                 :            : 
     804                 :          0 :         switch (wdev->iftype) {
     805                 :            :         case NL80211_IFTYPE_STATION:
     806                 :          0 :                 return cfg80211_mgd_wext_giwfreq(dev, info, freq, extra);
     807                 :            :         case NL80211_IFTYPE_ADHOC:
     808                 :          0 :                 return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra);
     809                 :            :         case NL80211_IFTYPE_MONITOR:
     810                 :          0 :                 if (!rdev->ops->get_channel)
     811                 :            :                         return -EINVAL;
     812                 :            : 
     813                 :          0 :                 ret = rdev_get_channel(rdev, wdev, &chandef);
     814                 :          0 :                 if (ret)
     815                 :            :                         return ret;
     816                 :          0 :                 freq->m = chandef.chan->center_freq;
     817                 :          0 :                 freq->e = 6;
     818                 :          0 :                 return 0;
     819                 :            :         default:
     820                 :            :                 return -EINVAL;
     821                 :            :         }
     822                 :            : }
     823                 :            : 
     824                 :          0 : static int cfg80211_wext_siwtxpower(struct net_device *dev,
     825                 :            :                                     struct iw_request_info *info,
     826                 :            :                                     union iwreq_data *data, char *extra)
     827                 :            : {
     828                 :          0 :         struct wireless_dev *wdev = dev->ieee80211_ptr;
     829                 :          0 :         struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
     830                 :            :         enum nl80211_tx_power_setting type;
     831                 :            :         int dbm = 0;
     832                 :            : 
     833                 :          0 :         if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
     834                 :            :                 return -EINVAL;
     835                 :          0 :         if (data->txpower.flags & IW_TXPOW_RANGE)
     836                 :            :                 return -EINVAL;
     837                 :            : 
     838                 :          0 :         if (!rdev->ops->set_tx_power)
     839                 :            :                 return -EOPNOTSUPP;
     840                 :            : 
     841                 :            :         /* only change when not disabling */
     842                 :          0 :         if (!data->txpower.disabled) {
     843                 :          0 :                 rfkill_set_sw_state(rdev->rfkill, false);
     844                 :            : 
     845                 :          0 :                 if (data->txpower.fixed) {
     846                 :            :                         /*
     847                 :            :                          * wext doesn't support negative values, see
     848                 :            :                          * below where it's for automatic
     849                 :            :                          */
     850                 :          0 :                         if (data->txpower.value < 0)
     851                 :            :                                 return -EINVAL;
     852                 :            :                         dbm = data->txpower.value;
     853                 :            :                         type = NL80211_TX_POWER_FIXED;
     854                 :            :                         /* TODO: do regulatory check! */
     855                 :            :                 } else {
     856                 :            :                         /*
     857                 :            :                          * Automatic power level setting, max being the value
     858                 :            :                          * passed in from userland.
     859                 :            :                          */
     860                 :          0 :                         if (data->txpower.value < 0) {
     861                 :            :                                 type = NL80211_TX_POWER_AUTOMATIC;
     862                 :            :                         } else {
     863                 :            :                                 dbm = data->txpower.value;
     864                 :            :                                 type = NL80211_TX_POWER_LIMITED;
     865                 :            :                         }
     866                 :            :                 }
     867                 :            :         } else {
     868                 :          0 :                 if (rfkill_set_sw_state(rdev->rfkill, true))
     869                 :          0 :                         schedule_work(&rdev->rfkill_block);
     870                 :            :                 return 0;
     871                 :            :         }
     872                 :            : 
     873                 :          0 :         return rdev_set_tx_power(rdev, wdev, type, DBM_TO_MBM(dbm));
     874                 :            : }
     875                 :            : 
     876                 :          0 : static int cfg80211_wext_giwtxpower(struct net_device *dev,
     877                 :            :                                     struct iw_request_info *info,
     878                 :            :                                     union iwreq_data *data, char *extra)
     879                 :            : {
     880                 :          0 :         struct wireless_dev *wdev = dev->ieee80211_ptr;
     881                 :          0 :         struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
     882                 :            :         int err, val;
     883                 :            : 
     884                 :          0 :         if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
     885                 :            :                 return -EINVAL;
     886                 :          0 :         if (data->txpower.flags & IW_TXPOW_RANGE)
     887                 :            :                 return -EINVAL;
     888                 :            : 
     889                 :          0 :         if (!rdev->ops->get_tx_power)
     890                 :            :                 return -EOPNOTSUPP;
     891                 :            : 
     892                 :          0 :         err = rdev_get_tx_power(rdev, wdev, &val);
     893                 :          0 :         if (err)
     894                 :            :                 return err;
     895                 :            : 
     896                 :            :         /* well... oh well */
     897                 :          0 :         data->txpower.fixed = 1;
     898                 :          0 :         data->txpower.disabled = rfkill_blocked(rdev->rfkill);
     899                 :          0 :         data->txpower.value = val;
     900                 :          0 :         data->txpower.flags = IW_TXPOW_DBM;
     901                 :            : 
     902                 :          0 :         return 0;
     903                 :            : }
     904                 :            : 
     905                 :          0 : static int cfg80211_set_auth_alg(struct wireless_dev *wdev,
     906                 :            :                                  s32 auth_alg)
     907                 :            : {
     908                 :            :         int nr_alg = 0;
     909                 :            : 
     910                 :          0 :         if (!auth_alg)
     911                 :            :                 return -EINVAL;
     912                 :            : 
     913                 :          0 :         if (auth_alg & ~(IW_AUTH_ALG_OPEN_SYSTEM |
     914                 :            :                          IW_AUTH_ALG_SHARED_KEY |
     915                 :            :                          IW_AUTH_ALG_LEAP))
     916                 :            :                 return -EINVAL;
     917                 :            : 
     918                 :          0 :         if (auth_alg & IW_AUTH_ALG_OPEN_SYSTEM) {
     919                 :            :                 nr_alg++;
     920                 :          0 :                 wdev->wext.connect.auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM;
     921                 :            :         }
     922                 :            : 
     923                 :          0 :         if (auth_alg & IW_AUTH_ALG_SHARED_KEY) {
     924                 :          0 :                 nr_alg++;
     925                 :          0 :                 wdev->wext.connect.auth_type = NL80211_AUTHTYPE_SHARED_KEY;
     926                 :            :         }
     927                 :            : 
     928                 :          0 :         if (auth_alg & IW_AUTH_ALG_LEAP) {
     929                 :          0 :                 nr_alg++;
     930                 :          0 :                 wdev->wext.connect.auth_type = NL80211_AUTHTYPE_NETWORK_EAP;
     931                 :            :         }
     932                 :            : 
     933                 :          0 :         if (nr_alg > 1)
     934                 :          0 :                 wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
     935                 :            : 
     936                 :            :         return 0;
     937                 :            : }
     938                 :            : 
     939                 :          0 : static int cfg80211_set_wpa_version(struct wireless_dev *wdev, u32 wpa_versions)
     940                 :            : {
     941                 :          0 :         if (wpa_versions & ~(IW_AUTH_WPA_VERSION_WPA |
     942                 :            :                              IW_AUTH_WPA_VERSION_WPA2|
     943                 :            :                              IW_AUTH_WPA_VERSION_DISABLED))
     944                 :            :                 return -EINVAL;
     945                 :            : 
     946                 :          0 :         if ((wpa_versions & IW_AUTH_WPA_VERSION_DISABLED) &&
     947                 :          0 :             (wpa_versions & (IW_AUTH_WPA_VERSION_WPA|
     948                 :            :                              IW_AUTH_WPA_VERSION_WPA2)))
     949                 :            :                 return -EINVAL;
     950                 :            : 
     951                 :          0 :         if (wpa_versions & IW_AUTH_WPA_VERSION_DISABLED)
     952                 :          0 :                 wdev->wext.connect.crypto.wpa_versions &=
     953                 :            :                         ~(NL80211_WPA_VERSION_1|NL80211_WPA_VERSION_2);
     954                 :            : 
     955                 :          0 :         if (wpa_versions & IW_AUTH_WPA_VERSION_WPA)
     956                 :          0 :                 wdev->wext.connect.crypto.wpa_versions |=
     957                 :            :                         NL80211_WPA_VERSION_1;
     958                 :            : 
     959                 :          0 :         if (wpa_versions & IW_AUTH_WPA_VERSION_WPA2)
     960                 :          0 :                 wdev->wext.connect.crypto.wpa_versions |=
     961                 :            :                         NL80211_WPA_VERSION_2;
     962                 :            : 
     963                 :            :         return 0;
     964                 :            : }
     965                 :            : 
     966                 :          0 : static int cfg80211_set_cipher_group(struct wireless_dev *wdev, u32 cipher)
     967                 :            : {
     968                 :          0 :         if (cipher & IW_AUTH_CIPHER_WEP40)
     969                 :          0 :                 wdev->wext.connect.crypto.cipher_group =
     970                 :            :                         WLAN_CIPHER_SUITE_WEP40;
     971                 :          0 :         else if (cipher & IW_AUTH_CIPHER_WEP104)
     972                 :          0 :                 wdev->wext.connect.crypto.cipher_group =
     973                 :            :                         WLAN_CIPHER_SUITE_WEP104;
     974                 :          0 :         else if (cipher & IW_AUTH_CIPHER_TKIP)
     975                 :          0 :                 wdev->wext.connect.crypto.cipher_group =
     976                 :            :                         WLAN_CIPHER_SUITE_TKIP;
     977                 :          0 :         else if (cipher & IW_AUTH_CIPHER_CCMP)
     978                 :          0 :                 wdev->wext.connect.crypto.cipher_group =
     979                 :            :                         WLAN_CIPHER_SUITE_CCMP;
     980                 :          0 :         else if (cipher & IW_AUTH_CIPHER_AES_CMAC)
     981                 :          0 :                 wdev->wext.connect.crypto.cipher_group =
     982                 :            :                         WLAN_CIPHER_SUITE_AES_CMAC;
     983                 :          0 :         else if (cipher & IW_AUTH_CIPHER_NONE)
     984                 :          0 :                 wdev->wext.connect.crypto.cipher_group = 0;
     985                 :            :         else
     986                 :            :                 return -EINVAL;
     987                 :            : 
     988                 :            :         return 0;
     989                 :            : }
     990                 :            : 
     991                 :          0 : static int cfg80211_set_cipher_pairwise(struct wireless_dev *wdev, u32 cipher)
     992                 :            : {
     993                 :            :         int nr_ciphers = 0;
     994                 :          0 :         u32 *ciphers_pairwise = wdev->wext.connect.crypto.ciphers_pairwise;
     995                 :            : 
     996                 :          0 :         if (cipher & IW_AUTH_CIPHER_WEP40) {
     997                 :          0 :                 ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_WEP40;
     998                 :            :                 nr_ciphers++;
     999                 :            :         }
    1000                 :            : 
    1001                 :          0 :         if (cipher & IW_AUTH_CIPHER_WEP104) {
    1002                 :          0 :                 ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_WEP104;
    1003                 :          0 :                 nr_ciphers++;
    1004                 :            :         }
    1005                 :            : 
    1006                 :          0 :         if (cipher & IW_AUTH_CIPHER_TKIP) {
    1007                 :          0 :                 ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_TKIP;
    1008                 :          0 :                 nr_ciphers++;
    1009                 :            :         }
    1010                 :            : 
    1011                 :          0 :         if (cipher & IW_AUTH_CIPHER_CCMP) {
    1012                 :          0 :                 ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_CCMP;
    1013                 :          0 :                 nr_ciphers++;
    1014                 :            :         }
    1015                 :            : 
    1016                 :          0 :         if (cipher & IW_AUTH_CIPHER_AES_CMAC) {
    1017                 :          0 :                 ciphers_pairwise[nr_ciphers] = WLAN_CIPHER_SUITE_AES_CMAC;
    1018                 :          0 :                 nr_ciphers++;
    1019                 :            :         }
    1020                 :            : 
    1021                 :            :         BUILD_BUG_ON(NL80211_MAX_NR_CIPHER_SUITES < 5);
    1022                 :            : 
    1023                 :          0 :         wdev->wext.connect.crypto.n_ciphers_pairwise = nr_ciphers;
    1024                 :            : 
    1025                 :          0 :         return 0;
    1026                 :            : }
    1027                 :            : 
    1028                 :            : 
    1029                 :            : static int cfg80211_set_key_mgt(struct wireless_dev *wdev, u32 key_mgt)
    1030                 :            : {
    1031                 :            :         int nr_akm_suites = 0;
    1032                 :            : 
    1033                 :          0 :         if (key_mgt & ~(IW_AUTH_KEY_MGMT_802_1X |
    1034                 :            :                         IW_AUTH_KEY_MGMT_PSK))
    1035                 :            :                 return -EINVAL;
    1036                 :            : 
    1037                 :          0 :         if (key_mgt & IW_AUTH_KEY_MGMT_802_1X) {
    1038                 :          0 :                 wdev->wext.connect.crypto.akm_suites[nr_akm_suites] =
    1039                 :            :                         WLAN_AKM_SUITE_8021X;
    1040                 :            :                 nr_akm_suites++;
    1041                 :            :         }
    1042                 :            : 
    1043                 :          0 :         if (key_mgt & IW_AUTH_KEY_MGMT_PSK) {
    1044                 :          0 :                 wdev->wext.connect.crypto.akm_suites[nr_akm_suites] =
    1045                 :            :                         WLAN_AKM_SUITE_PSK;
    1046                 :          0 :                 nr_akm_suites++;
    1047                 :            :         }
    1048                 :            : 
    1049                 :          0 :         wdev->wext.connect.crypto.n_akm_suites = nr_akm_suites;
    1050                 :            : 
    1051                 :            :         return 0;
    1052                 :            : }
    1053                 :            : 
    1054                 :          0 : static int cfg80211_wext_siwauth(struct net_device *dev,
    1055                 :            :                                  struct iw_request_info *info,
    1056                 :            :                                  struct iw_param *data, char *extra)
    1057                 :            : {
    1058                 :          0 :         struct wireless_dev *wdev = dev->ieee80211_ptr;
    1059                 :            : 
    1060                 :          0 :         if (wdev->iftype != NL80211_IFTYPE_STATION)
    1061                 :            :                 return -EOPNOTSUPP;
    1062                 :            : 
    1063                 :          0 :         switch (data->flags & IW_AUTH_INDEX) {
    1064                 :            :         case IW_AUTH_PRIVACY_INVOKED:
    1065                 :          0 :                 wdev->wext.connect.privacy = data->value;
    1066                 :          0 :                 return 0;
    1067                 :            :         case IW_AUTH_WPA_VERSION:
    1068                 :          0 :                 return cfg80211_set_wpa_version(wdev, data->value);
    1069                 :            :         case IW_AUTH_CIPHER_GROUP:
    1070                 :          0 :                 return cfg80211_set_cipher_group(wdev, data->value);
    1071                 :            :         case IW_AUTH_KEY_MGMT:
    1072                 :          0 :                 return cfg80211_set_key_mgt(wdev, data->value);
    1073                 :            :         case IW_AUTH_CIPHER_PAIRWISE:
    1074                 :          0 :                 return cfg80211_set_cipher_pairwise(wdev, data->value);
    1075                 :            :         case IW_AUTH_80211_AUTH_ALG:
    1076                 :          0 :                 return cfg80211_set_auth_alg(wdev, data->value);
    1077                 :            :         case IW_AUTH_WPA_ENABLED:
    1078                 :            :         case IW_AUTH_RX_UNENCRYPTED_EAPOL:
    1079                 :            :         case IW_AUTH_DROP_UNENCRYPTED:
    1080                 :            :         case IW_AUTH_MFP:
    1081                 :            :                 return 0;
    1082                 :            :         default:
    1083                 :          0 :                 return -EOPNOTSUPP;
    1084                 :            :         }
    1085                 :            : }
    1086                 :            : 
    1087                 :          0 : static int cfg80211_wext_giwauth(struct net_device *dev,
    1088                 :            :                                  struct iw_request_info *info,
    1089                 :            :                                  struct iw_param *data, char *extra)
    1090                 :            : {
    1091                 :            :         /* XXX: what do we need? */
    1092                 :            : 
    1093                 :          0 :         return -EOPNOTSUPP;
    1094                 :            : }
    1095                 :            : 
    1096                 :          0 : static int cfg80211_wext_siwpower(struct net_device *dev,
    1097                 :            :                                   struct iw_request_info *info,
    1098                 :            :                                   struct iw_param *wrq, char *extra)
    1099                 :            : {
    1100                 :          0 :         struct wireless_dev *wdev = dev->ieee80211_ptr;
    1101                 :          0 :         struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
    1102                 :            :         bool ps = wdev->ps;
    1103                 :          0 :         int timeout = wdev->ps_timeout;
    1104                 :            :         int err;
    1105                 :            : 
    1106                 :          0 :         if (wdev->iftype != NL80211_IFTYPE_STATION)
    1107                 :            :                 return -EINVAL;
    1108                 :            : 
    1109                 :          0 :         if (!rdev->ops->set_power_mgmt)
    1110                 :            :                 return -EOPNOTSUPP;
    1111                 :            : 
    1112                 :          0 :         if (wrq->disabled) {
    1113                 :            :                 ps = false;
    1114                 :            :         } else {
    1115                 :          0 :                 switch (wrq->flags & IW_POWER_MODE) {
    1116                 :            :                 case IW_POWER_ON:       /* If not specified */
    1117                 :            :                 case IW_POWER_MODE:     /* If set all mask */
    1118                 :            :                 case IW_POWER_ALL_R:    /* If explicitely state all */
    1119                 :            :                         ps = true;
    1120                 :            :                         break;
    1121                 :            :                 default:                /* Otherwise we ignore */
    1122                 :            :                         return -EINVAL;
    1123                 :            :                 }
    1124                 :            : 
    1125                 :          0 :                 if (wrq->flags & ~(IW_POWER_MODE | IW_POWER_TIMEOUT))
    1126                 :            :                         return -EINVAL;
    1127                 :            : 
    1128                 :          0 :                 if (wrq->flags & IW_POWER_TIMEOUT)
    1129                 :          0 :                         timeout = wrq->value / 1000;
    1130                 :            :         }
    1131                 :            : 
    1132                 :          0 :         err = rdev_set_power_mgmt(rdev, dev, ps, timeout);
    1133                 :          0 :         if (err)
    1134                 :            :                 return err;
    1135                 :            : 
    1136                 :          0 :         wdev->ps = ps;
    1137                 :          0 :         wdev->ps_timeout = timeout;
    1138                 :            : 
    1139                 :          0 :         return 0;
    1140                 :            : 
    1141                 :            : }
    1142                 :            : 
    1143                 :          0 : static int cfg80211_wext_giwpower(struct net_device *dev,
    1144                 :            :                                   struct iw_request_info *info,
    1145                 :            :                                   struct iw_param *wrq, char *extra)
    1146                 :            : {
    1147                 :          0 :         struct wireless_dev *wdev = dev->ieee80211_ptr;
    1148                 :            : 
    1149                 :          0 :         wrq->disabled = !wdev->ps;
    1150                 :            : 
    1151                 :          0 :         return 0;
    1152                 :            : }
    1153                 :            : 
    1154                 :          0 : static int cfg80211_wds_wext_siwap(struct net_device *dev,
    1155                 :            :                                    struct iw_request_info *info,
    1156                 :            :                                    struct sockaddr *addr, char *extra)
    1157                 :            : {
    1158                 :          0 :         struct wireless_dev *wdev = dev->ieee80211_ptr;
    1159                 :          0 :         struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
    1160                 :            :         int err;
    1161                 :            : 
    1162                 :          0 :         if (WARN_ON(wdev->iftype != NL80211_IFTYPE_WDS))
    1163                 :            :                 return -EINVAL;
    1164                 :            : 
    1165                 :          0 :         if (addr->sa_family != ARPHRD_ETHER)
    1166                 :            :                 return -EINVAL;
    1167                 :            : 
    1168                 :          0 :         if (netif_running(dev))
    1169                 :            :                 return -EBUSY;
    1170                 :            : 
    1171                 :          0 :         if (!rdev->ops->set_wds_peer)
    1172                 :            :                 return -EOPNOTSUPP;
    1173                 :            : 
    1174                 :          0 :         err = rdev_set_wds_peer(rdev, dev, (u8 *)&addr->sa_data);
    1175                 :          0 :         if (err)
    1176                 :            :                 return err;
    1177                 :            : 
    1178                 :          0 :         memcpy(&wdev->wext.bssid, (u8 *) &addr->sa_data, ETH_ALEN);
    1179                 :            : 
    1180                 :          0 :         return 0;
    1181                 :            : }
    1182                 :            : 
    1183                 :          0 : static int cfg80211_wds_wext_giwap(struct net_device *dev,
    1184                 :            :                                    struct iw_request_info *info,
    1185                 :            :                                    struct sockaddr *addr, char *extra)
    1186                 :            : {
    1187                 :          0 :         struct wireless_dev *wdev = dev->ieee80211_ptr;
    1188                 :            : 
    1189                 :          0 :         if (WARN_ON(wdev->iftype != NL80211_IFTYPE_WDS))
    1190                 :            :                 return -EINVAL;
    1191                 :            : 
    1192                 :          0 :         addr->sa_family = ARPHRD_ETHER;
    1193                 :          0 :         memcpy(&addr->sa_data, wdev->wext.bssid, ETH_ALEN);
    1194                 :            : 
    1195                 :          0 :         return 0;
    1196                 :            : }
    1197                 :            : 
    1198                 :          0 : static int cfg80211_wext_siwrate(struct net_device *dev,
    1199                 :            :                                  struct iw_request_info *info,
    1200                 :            :                                  struct iw_param *rate, char *extra)
    1201                 :            : {
    1202                 :          0 :         struct wireless_dev *wdev = dev->ieee80211_ptr;
    1203                 :          0 :         struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
    1204                 :            :         struct cfg80211_bitrate_mask mask;
    1205                 :            :         u32 fixed, maxrate;
    1206                 :            :         struct ieee80211_supported_band *sband;
    1207                 :            :         int band, ridx;
    1208                 :            :         bool match = false;
    1209                 :            : 
    1210                 :          0 :         if (!rdev->ops->set_bitrate_mask)
    1211                 :            :                 return -EOPNOTSUPP;
    1212                 :            : 
    1213                 :          0 :         memset(&mask, 0, sizeof(mask));
    1214                 :            :         fixed = 0;
    1215                 :            :         maxrate = (u32)-1;
    1216                 :            : 
    1217                 :          0 :         if (rate->value < 0) {
    1218                 :            :                 /* nothing */
    1219                 :          0 :         } else if (rate->fixed) {
    1220                 :          0 :                 fixed = rate->value / 100000;
    1221                 :            :         } else {
    1222                 :          0 :                 maxrate = rate->value / 100000;
    1223                 :            :         }
    1224                 :            : 
    1225                 :          0 :         for (band = 0; band < NUM_NL80211_BANDS; band++) {
    1226                 :          0 :                 sband = wdev->wiphy->bands[band];
    1227                 :          0 :                 if (sband == NULL)
    1228                 :          0 :                         continue;
    1229                 :          0 :                 for (ridx = 0; ridx < sband->n_bitrates; ridx++) {
    1230                 :          0 :                         struct ieee80211_rate *srate = &sband->bitrates[ridx];
    1231                 :          0 :                         if (fixed == srate->bitrate) {
    1232                 :          0 :                                 mask.control[band].legacy = 1 << ridx;
    1233                 :            :                                 match = true;
    1234                 :          0 :                                 break;
    1235                 :            :                         }
    1236                 :          0 :                         if (srate->bitrate <= maxrate) {
    1237                 :          0 :                                 mask.control[band].legacy |= 1 << ridx;
    1238                 :            :                                 match = true;
    1239                 :            :                         }
    1240                 :            :                 }
    1241                 :            :         }
    1242                 :            : 
    1243                 :          0 :         if (!match)
    1244                 :            :                 return -EINVAL;
    1245                 :            : 
    1246                 :          0 :         return rdev_set_bitrate_mask(rdev, dev, NULL, &mask);
    1247                 :            : }
    1248                 :            : 
    1249                 :          0 : static int cfg80211_wext_giwrate(struct net_device *dev,
    1250                 :            :                                  struct iw_request_info *info,
    1251                 :            :                                  struct iw_param *rate, char *extra)
    1252                 :            : {
    1253                 :          0 :         struct wireless_dev *wdev = dev->ieee80211_ptr;
    1254                 :          0 :         struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
    1255                 :          0 :         struct station_info sinfo = {};
    1256                 :            :         u8 addr[ETH_ALEN];
    1257                 :            :         int err;
    1258                 :            : 
    1259                 :          0 :         if (wdev->iftype != NL80211_IFTYPE_STATION)
    1260                 :            :                 return -EOPNOTSUPP;
    1261                 :            : 
    1262                 :          0 :         if (!rdev->ops->get_station)
    1263                 :            :                 return -EOPNOTSUPP;
    1264                 :            : 
    1265                 :            :         err = 0;
    1266                 :            :         wdev_lock(wdev);
    1267                 :          0 :         if (wdev->current_bss)
    1268                 :          0 :                 memcpy(addr, wdev->current_bss->pub.bssid, ETH_ALEN);
    1269                 :            :         else
    1270                 :            :                 err = -EOPNOTSUPP;
    1271                 :            :         wdev_unlock(wdev);
    1272                 :          0 :         if (err)
    1273                 :            :                 return err;
    1274                 :            : 
    1275                 :          0 :         err = rdev_get_station(rdev, dev, addr, &sinfo);
    1276                 :          0 :         if (err)
    1277                 :            :                 return err;
    1278                 :            : 
    1279                 :          0 :         if (!(sinfo.filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE))) {
    1280                 :            :                 err = -EOPNOTSUPP;
    1281                 :            :                 goto free;
    1282                 :            :         }
    1283                 :            : 
    1284                 :          0 :         rate->value = 100000 * cfg80211_calculate_bitrate(&sinfo.txrate);
    1285                 :            : 
    1286                 :            : free:
    1287                 :            :         cfg80211_sinfo_release_content(&sinfo);
    1288                 :          0 :         return err;
    1289                 :            : }
    1290                 :            : 
    1291                 :            : /* Get wireless statistics.  Called by /proc/net/wireless and by SIOCGIWSTATS */
    1292                 :          0 : static struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev)
    1293                 :            : {
    1294                 :          0 :         struct wireless_dev *wdev = dev->ieee80211_ptr;
    1295                 :          0 :         struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
    1296                 :            :         /* we are under RTNL - globally locked - so can use static structs */
    1297                 :            :         static struct iw_statistics wstats;
    1298                 :            :         static struct station_info sinfo = {};
    1299                 :            :         u8 bssid[ETH_ALEN];
    1300                 :            : 
    1301                 :          0 :         if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION)
    1302                 :            :                 return NULL;
    1303                 :            : 
    1304                 :          0 :         if (!rdev->ops->get_station)
    1305                 :            :                 return NULL;
    1306                 :            : 
    1307                 :            :         /* Grab BSSID of current BSS, if any */
    1308                 :            :         wdev_lock(wdev);
    1309                 :          0 :         if (!wdev->current_bss) {
    1310                 :            :                 wdev_unlock(wdev);
    1311                 :          0 :                 return NULL;
    1312                 :            :         }
    1313                 :          0 :         memcpy(bssid, wdev->current_bss->pub.bssid, ETH_ALEN);
    1314                 :            :         wdev_unlock(wdev);
    1315                 :            : 
    1316                 :          0 :         memset(&sinfo, 0, sizeof(sinfo));
    1317                 :            : 
    1318                 :          0 :         if (rdev_get_station(rdev, dev, bssid, &sinfo))
    1319                 :            :                 return NULL;
    1320                 :            : 
    1321                 :          0 :         memset(&wstats, 0, sizeof(wstats));
    1322                 :            : 
    1323                 :          0 :         switch (rdev->wiphy.signal_type) {
    1324                 :            :         case CFG80211_SIGNAL_TYPE_MBM:
    1325                 :          0 :                 if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_SIGNAL)) {
    1326                 :          0 :                         int sig = sinfo.signal;
    1327                 :          0 :                         wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED;
    1328                 :          0 :                         wstats.qual.updated |= IW_QUAL_QUAL_UPDATED;
    1329                 :          0 :                         wstats.qual.updated |= IW_QUAL_DBM;
    1330                 :          0 :                         wstats.qual.level = sig;
    1331                 :          0 :                         if (sig < -110)
    1332                 :            :                                 sig = -110;
    1333                 :          0 :                         else if (sig > -40)
    1334                 :            :                                 sig = -40;
    1335                 :          0 :                         wstats.qual.qual = sig + 110;
    1336                 :          0 :                         break;
    1337                 :            :                 }
    1338                 :            :                 /* fall through */
    1339                 :            :         case CFG80211_SIGNAL_TYPE_UNSPEC:
    1340                 :          0 :                 if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_SIGNAL)) {
    1341                 :          0 :                         wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED;
    1342                 :          0 :                         wstats.qual.updated |= IW_QUAL_QUAL_UPDATED;
    1343                 :          0 :                         wstats.qual.level = sinfo.signal;
    1344                 :          0 :                         wstats.qual.qual = sinfo.signal;
    1345                 :          0 :                         break;
    1346                 :            :                 }
    1347                 :            :                 /* fall through */
    1348                 :            :         default:
    1349                 :          0 :                 wstats.qual.updated |= IW_QUAL_LEVEL_INVALID;
    1350                 :          0 :                 wstats.qual.updated |= IW_QUAL_QUAL_INVALID;
    1351                 :            :         }
    1352                 :            : 
    1353                 :          0 :         wstats.qual.updated |= IW_QUAL_NOISE_INVALID;
    1354                 :          0 :         if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_RX_DROP_MISC))
    1355                 :          0 :                 wstats.discard.misc = sinfo.rx_dropped_misc;
    1356                 :          0 :         if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_TX_FAILED))
    1357                 :          0 :                 wstats.discard.retries = sinfo.tx_failed;
    1358                 :            : 
    1359                 :            :         cfg80211_sinfo_release_content(&sinfo);
    1360                 :            : 
    1361                 :          0 :         return &wstats;
    1362                 :            : }
    1363                 :            : 
    1364                 :          0 : static int cfg80211_wext_siwap(struct net_device *dev,
    1365                 :            :                                struct iw_request_info *info,
    1366                 :            :                                struct sockaddr *ap_addr, char *extra)
    1367                 :            : {
    1368                 :          0 :         struct wireless_dev *wdev = dev->ieee80211_ptr;
    1369                 :            : 
    1370                 :          0 :         switch (wdev->iftype) {
    1371                 :            :         case NL80211_IFTYPE_ADHOC:
    1372                 :          0 :                 return cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra);
    1373                 :            :         case NL80211_IFTYPE_STATION:
    1374                 :          0 :                 return cfg80211_mgd_wext_siwap(dev, info, ap_addr, extra);
    1375                 :            :         case NL80211_IFTYPE_WDS:
    1376                 :          0 :                 return cfg80211_wds_wext_siwap(dev, info, ap_addr, extra);
    1377                 :            :         default:
    1378                 :            :                 return -EOPNOTSUPP;
    1379                 :            :         }
    1380                 :            : }
    1381                 :            : 
    1382                 :          0 : static int cfg80211_wext_giwap(struct net_device *dev,
    1383                 :            :                                struct iw_request_info *info,
    1384                 :            :                                struct sockaddr *ap_addr, char *extra)
    1385                 :            : {
    1386                 :          0 :         struct wireless_dev *wdev = dev->ieee80211_ptr;
    1387                 :            : 
    1388                 :          0 :         switch (wdev->iftype) {
    1389                 :            :         case NL80211_IFTYPE_ADHOC:
    1390                 :          0 :                 return cfg80211_ibss_wext_giwap(dev, info, ap_addr, extra);
    1391                 :            :         case NL80211_IFTYPE_STATION:
    1392                 :          0 :                 return cfg80211_mgd_wext_giwap(dev, info, ap_addr, extra);
    1393                 :            :         case NL80211_IFTYPE_WDS:
    1394                 :          0 :                 return cfg80211_wds_wext_giwap(dev, info, ap_addr, extra);
    1395                 :            :         default:
    1396                 :            :                 return -EOPNOTSUPP;
    1397                 :            :         }
    1398                 :            : }
    1399                 :            : 
    1400                 :          0 : static int cfg80211_wext_siwessid(struct net_device *dev,
    1401                 :            :                                   struct iw_request_info *info,
    1402                 :            :                                   struct iw_point *data, char *ssid)
    1403                 :            : {
    1404                 :          0 :         struct wireless_dev *wdev = dev->ieee80211_ptr;
    1405                 :            : 
    1406                 :          0 :         switch (wdev->iftype) {
    1407                 :            :         case NL80211_IFTYPE_ADHOC:
    1408                 :          0 :                 return cfg80211_ibss_wext_siwessid(dev, info, data, ssid);
    1409                 :            :         case NL80211_IFTYPE_STATION:
    1410                 :          0 :                 return cfg80211_mgd_wext_siwessid(dev, info, data, ssid);
    1411                 :            :         default:
    1412                 :            :                 return -EOPNOTSUPP;
    1413                 :            :         }
    1414                 :            : }
    1415                 :            : 
    1416                 :          0 : static int cfg80211_wext_giwessid(struct net_device *dev,
    1417                 :            :                                   struct iw_request_info *info,
    1418                 :            :                                   struct iw_point *data, char *ssid)
    1419                 :            : {
    1420                 :          0 :         struct wireless_dev *wdev = dev->ieee80211_ptr;
    1421                 :            : 
    1422                 :          0 :         data->flags = 0;
    1423                 :          0 :         data->length = 0;
    1424                 :            : 
    1425                 :          0 :         switch (wdev->iftype) {
    1426                 :            :         case NL80211_IFTYPE_ADHOC:
    1427                 :          0 :                 return cfg80211_ibss_wext_giwessid(dev, info, data, ssid);
    1428                 :            :         case NL80211_IFTYPE_STATION:
    1429                 :          0 :                 return cfg80211_mgd_wext_giwessid(dev, info, data, ssid);
    1430                 :            :         default:
    1431                 :            :                 return -EOPNOTSUPP;
    1432                 :            :         }
    1433                 :            : }
    1434                 :            : 
    1435                 :          0 : static int cfg80211_wext_siwpmksa(struct net_device *dev,
    1436                 :            :                                   struct iw_request_info *info,
    1437                 :            :                                   struct iw_point *data, char *extra)
    1438                 :            : {
    1439                 :          0 :         struct wireless_dev *wdev = dev->ieee80211_ptr;
    1440                 :          0 :         struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
    1441                 :            :         struct cfg80211_pmksa cfg_pmksa;
    1442                 :            :         struct iw_pmksa *pmksa = (struct iw_pmksa *)extra;
    1443                 :            : 
    1444                 :          0 :         memset(&cfg_pmksa, 0, sizeof(struct cfg80211_pmksa));
    1445                 :            : 
    1446                 :          0 :         if (wdev->iftype != NL80211_IFTYPE_STATION)
    1447                 :            :                 return -EINVAL;
    1448                 :            : 
    1449                 :          0 :         cfg_pmksa.bssid = pmksa->bssid.sa_data;
    1450                 :          0 :         cfg_pmksa.pmkid = pmksa->pmkid;
    1451                 :            : 
    1452                 :          0 :         switch (pmksa->cmd) {
    1453                 :            :         case IW_PMKSA_ADD:
    1454                 :          0 :                 if (!rdev->ops->set_pmksa)
    1455                 :            :                         return -EOPNOTSUPP;
    1456                 :            : 
    1457                 :          0 :                 return rdev_set_pmksa(rdev, dev, &cfg_pmksa);
    1458                 :            : 
    1459                 :            :         case IW_PMKSA_REMOVE:
    1460                 :          0 :                 if (!rdev->ops->del_pmksa)
    1461                 :            :                         return -EOPNOTSUPP;
    1462                 :            : 
    1463                 :          0 :                 return rdev_del_pmksa(rdev, dev, &cfg_pmksa);
    1464                 :            : 
    1465                 :            :         case IW_PMKSA_FLUSH:
    1466                 :          0 :                 if (!rdev->ops->flush_pmksa)
    1467                 :            :                         return -EOPNOTSUPP;
    1468                 :            : 
    1469                 :          0 :                 return rdev_flush_pmksa(rdev, dev);
    1470                 :            : 
    1471                 :            :         default:
    1472                 :            :                 return -EOPNOTSUPP;
    1473                 :            :         }
    1474                 :            : }
    1475                 :            : 
    1476                 :            : static const iw_handler cfg80211_handlers[] = {
    1477                 :            :         [IW_IOCTL_IDX(SIOCGIWNAME)]     = (iw_handler) cfg80211_wext_giwname,
    1478                 :            :         [IW_IOCTL_IDX(SIOCSIWFREQ)]     = (iw_handler) cfg80211_wext_siwfreq,
    1479                 :            :         [IW_IOCTL_IDX(SIOCGIWFREQ)]     = (iw_handler) cfg80211_wext_giwfreq,
    1480                 :            :         [IW_IOCTL_IDX(SIOCSIWMODE)]     = (iw_handler) cfg80211_wext_siwmode,
    1481                 :            :         [IW_IOCTL_IDX(SIOCGIWMODE)]     = (iw_handler) cfg80211_wext_giwmode,
    1482                 :            :         [IW_IOCTL_IDX(SIOCGIWRANGE)]    = (iw_handler) cfg80211_wext_giwrange,
    1483                 :            :         [IW_IOCTL_IDX(SIOCSIWAP)]       = (iw_handler) cfg80211_wext_siwap,
    1484                 :            :         [IW_IOCTL_IDX(SIOCGIWAP)]       = (iw_handler) cfg80211_wext_giwap,
    1485                 :            :         [IW_IOCTL_IDX(SIOCSIWMLME)]     = (iw_handler) cfg80211_wext_siwmlme,
    1486                 :            :         [IW_IOCTL_IDX(SIOCSIWSCAN)]     = (iw_handler) cfg80211_wext_siwscan,
    1487                 :            :         [IW_IOCTL_IDX(SIOCGIWSCAN)]     = (iw_handler) cfg80211_wext_giwscan,
    1488                 :            :         [IW_IOCTL_IDX(SIOCSIWESSID)]    = (iw_handler) cfg80211_wext_siwessid,
    1489                 :            :         [IW_IOCTL_IDX(SIOCGIWESSID)]    = (iw_handler) cfg80211_wext_giwessid,
    1490                 :            :         [IW_IOCTL_IDX(SIOCSIWRATE)]     = (iw_handler) cfg80211_wext_siwrate,
    1491                 :            :         [IW_IOCTL_IDX(SIOCGIWRATE)]     = (iw_handler) cfg80211_wext_giwrate,
    1492                 :            :         [IW_IOCTL_IDX(SIOCSIWRTS)]      = (iw_handler) cfg80211_wext_siwrts,
    1493                 :            :         [IW_IOCTL_IDX(SIOCGIWRTS)]      = (iw_handler) cfg80211_wext_giwrts,
    1494                 :            :         [IW_IOCTL_IDX(SIOCSIWFRAG)]     = (iw_handler) cfg80211_wext_siwfrag,
    1495                 :            :         [IW_IOCTL_IDX(SIOCGIWFRAG)]     = (iw_handler) cfg80211_wext_giwfrag,
    1496                 :            :         [IW_IOCTL_IDX(SIOCSIWTXPOW)]    = (iw_handler) cfg80211_wext_siwtxpower,
    1497                 :            :         [IW_IOCTL_IDX(SIOCGIWTXPOW)]    = (iw_handler) cfg80211_wext_giwtxpower,
    1498                 :            :         [IW_IOCTL_IDX(SIOCSIWRETRY)]    = (iw_handler) cfg80211_wext_siwretry,
    1499                 :            :         [IW_IOCTL_IDX(SIOCGIWRETRY)]    = (iw_handler) cfg80211_wext_giwretry,
    1500                 :            :         [IW_IOCTL_IDX(SIOCSIWENCODE)]   = (iw_handler) cfg80211_wext_siwencode,
    1501                 :            :         [IW_IOCTL_IDX(SIOCGIWENCODE)]   = (iw_handler) cfg80211_wext_giwencode,
    1502                 :            :         [IW_IOCTL_IDX(SIOCSIWPOWER)]    = (iw_handler) cfg80211_wext_siwpower,
    1503                 :            :         [IW_IOCTL_IDX(SIOCGIWPOWER)]    = (iw_handler) cfg80211_wext_giwpower,
    1504                 :            :         [IW_IOCTL_IDX(SIOCSIWGENIE)]    = (iw_handler) cfg80211_wext_siwgenie,
    1505                 :            :         [IW_IOCTL_IDX(SIOCSIWAUTH)]     = (iw_handler) cfg80211_wext_siwauth,
    1506                 :            :         [IW_IOCTL_IDX(SIOCGIWAUTH)]     = (iw_handler) cfg80211_wext_giwauth,
    1507                 :            :         [IW_IOCTL_IDX(SIOCSIWENCODEEXT)]= (iw_handler) cfg80211_wext_siwencodeext,
    1508                 :            :         [IW_IOCTL_IDX(SIOCSIWPMKSA)]    = (iw_handler) cfg80211_wext_siwpmksa,
    1509                 :            : };
    1510                 :            : 
    1511                 :            : const struct iw_handler_def cfg80211_wext_handler = {
    1512                 :            :         .num_standard           = ARRAY_SIZE(cfg80211_handlers),
    1513                 :            :         .standard               = cfg80211_handlers,
    1514                 :            :         .get_wireless_stats = cfg80211_wireless_stats,
    1515                 :            : };
    

Generated by: LCOV version 1.14