Commit 52933d81 authored by Holger Schurig's avatar Holger Schurig Committed by John W. Linville

libertas: implement SSID scanning for SIOCSIWSCAN

After my bit scan re-writing the SIOCSIWSCAN wext ioctl no longer supported
scanning for a specific SSID. However, wpa_supplicant is a possible user of
this ioctl, so here is code that add's this.

While passing, removed even more of the debugfs-based scanning. You can (and
should) the SIOCSIWSCAN to ask for scans, so there is no need for
proprietary interfaces for scanning. And, besides, the scan result couldn't
be used further, e.g. not for associating.
Signed-off-by: default avatarHolger Schurig <hs4233@mail.mn-solutions.de>
Acked-by: default avatarDan Williams <dcbw@redhat.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent d9357136
......@@ -38,7 +38,7 @@ static int assoc_helper_essid(struct lbs_private *priv,
escape_essid(assoc_req->ssid, assoc_req->ssid_len));
if (assoc_req->mode == IW_MODE_INFRA) {
lbs_send_specific_ssid_scan(priv, assoc_req->ssid,
assoc_req->ssid_len, 0);
assoc_req->ssid_len);
bss = lbs_find_ssid_in_list(priv, assoc_req->ssid,
assoc_req->ssid_len, NULL, IW_MODE_INFRA, channel);
......@@ -53,7 +53,7 @@ static int assoc_helper_essid(struct lbs_private *priv,
* scan data will cause us to join a non-existant adhoc network
*/
lbs_send_specific_ssid_scan(priv, assoc_req->ssid,
assoc_req->ssid_len, 1);
assoc_req->ssid_len);
/* Search for the requested SSID in the scan table */
bss = lbs_find_ssid_in_list(priv, assoc_req->ssid,
......
......@@ -164,173 +164,6 @@ static ssize_t lbs_sleepparams_read(struct file *file, char __user *userbuf,
return ret;
}
static ssize_t lbs_extscan(struct file *file, const char __user *userbuf,
size_t count, loff_t *ppos)
{
struct lbs_private *priv = file->private_data;
ssize_t res, buf_size;
union iwreq_data wrqu;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
buf_size = min(count, len - 1);
if (copy_from_user(buf, userbuf, buf_size)) {
res = -EFAULT;
goto out_unlock;
}
lbs_send_specific_ssid_scan(priv, buf, strlen(buf)-1, 0);
memset(&wrqu, 0, sizeof(union iwreq_data));
wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
out_unlock:
free_page(addr);
return count;
}
static void lbs_parse_bssid(char *buf, size_t count,
struct lbs_ioctl_user_scan_cfg *scan_cfg)
{
char *hold;
unsigned int mac[ETH_ALEN];
hold = strstr(buf, "bssid=");
if (!hold)
return;
hold += 6;
sscanf(hold, "%02x:%02x:%02x:%02x:%02x:%02x",
mac, mac+1, mac+2, mac+3, mac+4, mac+5);
memcpy(scan_cfg->bssid, mac, ETH_ALEN);
}
static void lbs_parse_ssid(char *buf, size_t count,
struct lbs_ioctl_user_scan_cfg *scan_cfg)
{
char *hold, *end;
ssize_t size;
hold = strstr(buf, "ssid=");
if (!hold)
return;
hold += 5;
end = strchr(hold, ' ');
if (!end)
end = buf + count - 1;
size = min((size_t)IW_ESSID_MAX_SIZE, (size_t) (end - hold));
strncpy(scan_cfg->ssid, hold, size);
return;
}
static int lbs_parse_clear(char *buf, size_t count, const char *tag)
{
char *hold;
int val;
hold = strstr(buf, tag);
if (!hold)
return 0;
hold += strlen(tag);
sscanf(hold, "%d", &val);
if (val != 0)
val = 1;
return val;
}
static int lbs_parse_dur(char *buf, size_t count,
struct lbs_ioctl_user_scan_cfg *scan_cfg)
{
char *hold;
int val;
hold = strstr(buf, "dur=");
if (!hold)
return 0;
hold += 4;
sscanf(hold, "%d", &val);
return val;
}
static void lbs_parse_type(char *buf, size_t count,
struct lbs_ioctl_user_scan_cfg *scan_cfg)
{
char *hold;
int val;
hold = strstr(buf, "type=");
if (!hold)
return;
hold += 5;
sscanf(hold, "%d", &val);
/* type=1,2 or 3 */
if (val < 1 || val > 3)
return;
scan_cfg->bsstype = val;
return;
}
static ssize_t lbs_setuserscan(struct file *file,
const char __user *userbuf,
size_t count, loff_t *ppos)
{
struct lbs_private *priv = file->private_data;
ssize_t res, buf_size;
struct lbs_ioctl_user_scan_cfg *scan_cfg;
union iwreq_data wrqu;
int dur;
char *buf = (char *)get_zeroed_page(GFP_KERNEL);
if (!buf)
return -ENOMEM;
buf_size = min(count, len - 1);
if (copy_from_user(buf, userbuf, buf_size)) {
res = -EFAULT;
goto out_buf;
}
scan_cfg = kzalloc(sizeof(struct lbs_ioctl_user_scan_cfg), GFP_KERNEL);
if (!scan_cfg) {
res = -ENOMEM;
goto out_buf;
}
res = count;
scan_cfg->bsstype = LBS_SCAN_BSS_TYPE_ANY;
dur = lbs_parse_dur(buf, count, scan_cfg);
lbs_parse_bssid(buf, count, scan_cfg);
scan_cfg->clear_bssid = lbs_parse_clear(buf, count, "clear_bssid=");
lbs_parse_ssid(buf, count, scan_cfg);
scan_cfg->clear_ssid = lbs_parse_clear(buf, count, "clear_ssid=");
lbs_parse_type(buf, count, scan_cfg);
lbs_scan_networks(priv, scan_cfg, 1);
wait_event_interruptible(priv->cmd_pending,
priv->surpriseremoved || !priv->scan_channel);
if (priv->surpriseremoved)
goto out_scan_cfg;
memset(&wrqu, 0x00, sizeof(union iwreq_data));
wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
out_scan_cfg:
kfree(scan_cfg);
out_buf:
free_page((unsigned long)buf);
return res;
}
/*
* When calling CMD_802_11_SUBSCRIBE_EVENT with CMD_ACT_GET, me might
* get a bunch of vendor-specific TLVs (a.k.a. IEs) back from the
......@@ -857,8 +690,6 @@ static struct lbs_debugfs_files debugfs_files[] = {
write_file_dummy), },
{ "sleepparams", 0644, FOPS(lbs_sleepparams_read,
lbs_sleepparams_write), },
{ "extscan", 0600, FOPS(NULL, lbs_extscan), },
{ "setuserscan", 0600, FOPS(NULL, lbs_setuserscan), },
};
static struct lbs_debugfs_files debugfs_events_files[] = {
......
......@@ -149,6 +149,8 @@ struct lbs_private {
struct work_struct sync_channel;
/* remember which channel was scanned last, != 0 if currently scanning */
int scan_channel;
u8 scan_ssid[IW_ESSID_MAX_SIZE + 1];
u8 scan_ssid_len;
/** Hardware access */
int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb);
......
This diff is collapsed.
......@@ -12,8 +12,6 @@
/**
* @brief Maximum number of channels that can be sent in a setuserscan ioctl
*
* @sa lbs_ioctl_user_scan_cfg
*/
#define LBS_IOCTL_USER_SCAN_CHAN_MAX 50
......@@ -26,60 +24,6 @@
//! Adhoc or Infrastructure BSS scan type in cmd_ds_802_11_scan, no filter
#define LBS_SCAN_BSS_TYPE_ANY 3
/**
* @brief IOCTL channel sub-structure sent in lbs_ioctl_user_scan_cfg
*
* Multiple instances of this structure are included in the IOCTL command
* to configure a instance of a scan on the specific channel.
*/
struct lbs_ioctl_user_scan_chan {
u8 channumber; //!< channel Number to scan
u8 radiotype; //!< Radio type: 'B/G' band = 0, 'A' band = 1
u8 scantype; //!< Scan type: Active = 0, Passive = 1
u16 scantime; //!< Scan duration in milliseconds; if 0 default used
};
/**
* @brief IOCTL input structure to configure an immediate scan cmd to firmware
*
* Used in the setuserscan (LBS_SET_USER_SCAN) private ioctl. Specifies
* a number of parameters to be used in general for the scan as well
* as a channel list (lbs_ioctl_user_scan_chan) for each scan period
* desired.
*
* @sa lbs_set_user_scan_ioctl
*/
struct lbs_ioctl_user_scan_cfg {
/**
* @brief BSS type to be sent in the firmware command
*
* Field can be used to restrict the types of networks returned in the
* scan. valid settings are:
*
* - LBS_SCAN_BSS_TYPE_BSS (infrastructure)
* - LBS_SCAN_BSS_TYPE_IBSS (adhoc)
* - LBS_SCAN_BSS_TYPE_ANY (unrestricted, adhoc and infrastructure)
*/
u8 bsstype;
/**
* @brief BSSID filter sent in the firmware command to limit the results
*/
u8 bssid[ETH_ALEN];
/* Clear existing scan results matching this BSSID */
u8 clear_bssid;
/**
* @brief SSID filter sent in the firmware command to limit the results
*/
char ssid[IW_ESSID_MAX_SIZE];
u8 ssid_len;
/* Clear existing scan results matching this SSID */
u8 clear_ssid;
};
/**
* @brief Structure used to store information for each beacon/probe response
*/
......@@ -136,21 +80,12 @@ int lbs_find_best_network_ssid(struct lbs_private *priv, u8 *out_ssid,
u8 *out_ssid_len, u8 preferred_mode, u8 *out_mode);
int lbs_send_specific_ssid_scan(struct lbs_private *priv, u8 *ssid,
u8 ssid_len, u8 clear_ssid);
int lbs_scan_networks(struct lbs_private *priv,
const struct lbs_ioctl_user_scan_cfg *puserscanin,
int full_scan);
struct ifreq;
u8 ssid_len);
struct iw_point;
struct iw_param;
struct iw_request_info;
int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
struct iw_point *dwrq, char *extra);
int lbs_set_scan(struct net_device *dev, struct iw_request_info *info,
struct iw_param *vwrq, char *extra);
union iwreq_data *wrqu, char *extra);
void lbs_scan_worker(struct work_struct *work);
......
......@@ -579,6 +579,9 @@ static int lbs_get_range(struct net_device *dev, struct iw_request_info *info,
range->num_bitrates);
range->num_frequency = 0;
range->scan_capa = IW_SCAN_CAPA_ESSID;
if (priv->enable11d &&
(priv->connect_status == LBS_CONNECTED ||
priv->mesh_connect_status == LBS_CONNECTED)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment