All new accounts created on Gitlab now require administrator approval. If you invite any collaborators, please let Flux staff know so they can approve the accounts.

Commit 70692ad2 authored by Jouni Malinen's avatar Jouni Malinen Committed by John W. Linville

nl80211: Optional IEs into scan request

This extends the NL80211_CMD_TRIGGER_SCAN command to allow applications
to specify a set of information element(s) to be added into Probe
Request frames with NL80211_ATTR_IE. This provides support for the
MLME-SCAN.request primitive parameter VendorSpecificInfo and can be
used, e.g., to implement WPS scanning.
Signed-off-by: default avatarJouni Malinen <jouni.malinen@atheros.com>
Acked-by: default avatarJohannes Berg <johannes@sipsolutions.net>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 83befbde
...@@ -525,6 +525,8 @@ struct cfg80211_ssid { ...@@ -525,6 +525,8 @@ struct cfg80211_ssid {
* @n_ssids: number of SSIDs * @n_ssids: number of SSIDs
* @channels: channels to scan on. * @channels: channels to scan on.
* @n_channels: number of channels for each band * @n_channels: number of channels for each band
* @ie: optional information element(s) to add into Probe Request or %NULL
* @ie_len: length of ie in octets
* @wiphy: the wiphy this was for * @wiphy: the wiphy this was for
* @ifidx: the interface index * @ifidx: the interface index
*/ */
...@@ -533,6 +535,8 @@ struct cfg80211_scan_request { ...@@ -533,6 +535,8 @@ struct cfg80211_scan_request {
int n_ssids; int n_ssids;
struct ieee80211_channel **channels; struct ieee80211_channel **channels;
u32 n_channels; u32 n_channels;
u8 *ie;
size_t ie_len;
/* internal */ /* internal */
struct wiphy *wiphy; struct wiphy *wiphy;
......
...@@ -1093,7 +1093,8 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, ...@@ -1093,7 +1093,8 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
u8 *extra, size_t extra_len, u8 *extra, size_t extra_len,
const u8 *bssid, int encrypt); const u8 *bssid, int encrypt);
void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
u8 *ssid, size_t ssid_len); u8 *ssid, size_t ssid_len,
u8 *ie, size_t ie_len);
void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata,
const size_t supp_rates_len, const size_t supp_rates_len,
......
...@@ -716,7 +716,7 @@ static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata) ...@@ -716,7 +716,7 @@ static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata)
* will not answer to direct packet in unassociated state. * will not answer to direct packet in unassociated state.
*/ */
ieee80211_send_probe_req(sdata, NULL, ieee80211_send_probe_req(sdata, NULL,
ifmgd->ssid, ifmgd->ssid_len); ifmgd->ssid, ifmgd->ssid_len, NULL, 0);
mod_timer(&ifmgd->timer, jiffies + IEEE80211_AUTH_TIMEOUT); mod_timer(&ifmgd->timer, jiffies + IEEE80211_AUTH_TIMEOUT);
} }
...@@ -946,7 +946,8 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata) ...@@ -946,7 +946,8 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata)
} else } else
ieee80211_send_probe_req(sdata, ifmgd->bssid, ieee80211_send_probe_req(sdata, ifmgd->bssid,
ifmgd->ssid, ifmgd->ssid,
ifmgd->ssid_len); ifmgd->ssid_len,
NULL, 0);
ifmgd->flags ^= IEEE80211_STA_PROBEREQ_POLL; ifmgd->flags ^= IEEE80211_STA_PROBEREQ_POLL;
} else { } else {
ifmgd->flags &= ~IEEE80211_STA_PROBEREQ_POLL; ifmgd->flags &= ~IEEE80211_STA_PROBEREQ_POLL;
...@@ -955,7 +956,8 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata) ...@@ -955,7 +956,8 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata)
ifmgd->last_probe = jiffies; ifmgd->last_probe = jiffies;
ieee80211_send_probe_req(sdata, ifmgd->bssid, ieee80211_send_probe_req(sdata, ifmgd->bssid,
ifmgd->ssid, ifmgd->ssid,
ifmgd->ssid_len); ifmgd->ssid_len,
NULL, 0);
} }
} }
} }
......
...@@ -338,7 +338,8 @@ void ieee80211_scan_work(struct work_struct *work) ...@@ -338,7 +338,8 @@ void ieee80211_scan_work(struct work_struct *work)
ieee80211_send_probe_req( ieee80211_send_probe_req(
sdata, NULL, sdata, NULL,
local->scan_req->ssids[i].ssid, local->scan_req->ssids[i].ssid,
local->scan_req->ssids[i].ssid_len); local->scan_req->ssids[i].ssid_len,
local->scan_req->ie, local->scan_req->ie_len);
next_delay = IEEE80211_CHANNEL_TIME; next_delay = IEEE80211_CHANNEL_TIME;
break; break;
} }
......
...@@ -884,7 +884,8 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, ...@@ -884,7 +884,8 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
} }
void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
u8 *ssid, size_t ssid_len) u8 *ssid, size_t ssid_len,
u8 *ie, size_t ie_len)
{ {
struct ieee80211_local *local = sdata->local; struct ieee80211_local *local = sdata->local;
struct ieee80211_supported_band *sband; struct ieee80211_supported_band *sband;
...@@ -903,7 +904,7 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, ...@@ -903,7 +904,7 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
} }
skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200 + skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200 +
extra_preq_ie_len); ie_len + extra_preq_ie_len);
if (!skb) { if (!skb) {
printk(KERN_DEBUG "%s: failed to allocate buffer for probe " printk(KERN_DEBUG "%s: failed to allocate buffer for probe "
"request\n", sdata->dev->name); "request\n", sdata->dev->name);
...@@ -950,6 +951,8 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, ...@@ -950,6 +951,8 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
*pos = rate->bitrate / 5; *pos = rate->bitrate / 5;
} }
if (ie)
memcpy(skb_put(skb, ie_len), ie, ie_len);
if (extra_preq_ie) if (extra_preq_ie)
memcpy(skb_put(skb, extra_preq_ie_len), extra_preq_ie, memcpy(skb_put(skb, extra_preq_ie_len), extra_preq_ie,
extra_preq_ie_len); extra_preq_ie_len);
......
...@@ -2286,6 +2286,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) ...@@ -2286,6 +2286,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
struct wiphy *wiphy; struct wiphy *wiphy;
int err, tmp, n_ssids = 0, n_channels = 0, i; int err, tmp, n_ssids = 0, n_channels = 0, i;
enum ieee80211_band band; enum ieee80211_band band;
size_t ie_len;
err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
if (err) if (err)
...@@ -2327,9 +2328,15 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) ...@@ -2327,9 +2328,15 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
goto out_unlock; goto out_unlock;
} }
if (info->attrs[NL80211_ATTR_IE])
ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
else
ie_len = 0;
request = kzalloc(sizeof(*request) request = kzalloc(sizeof(*request)
+ sizeof(*ssid) * n_ssids + sizeof(*ssid) * n_ssids
+ sizeof(channel) * n_channels, GFP_KERNEL); + sizeof(channel) * n_channels
+ ie_len, GFP_KERNEL);
if (!request) { if (!request) {
err = -ENOMEM; err = -ENOMEM;
goto out_unlock; goto out_unlock;
...@@ -2340,6 +2347,12 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) ...@@ -2340,6 +2347,12 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
if (n_ssids) if (n_ssids)
request->ssids = (void *)(request->channels + n_channels); request->ssids = (void *)(request->channels + n_channels);
request->n_ssids = n_ssids; request->n_ssids = n_ssids;
if (ie_len) {
if (request->ssids)
request->ie = (void *)(request->ssids + n_ssids);
else
request->ie = (void *)(request->channels + n_channels);
}
if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) { if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
/* user specified, bail out if channel not found */ /* user specified, bail out if channel not found */
...@@ -2380,6 +2393,12 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) ...@@ -2380,6 +2393,12 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
} }
} }
if (info->attrs[NL80211_ATTR_IE]) {
request->ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
memcpy(request->ie, nla_data(info->attrs[NL80211_ATTR_IE]),
request->ie_len);
}
request->ifidx = dev->ifindex; request->ifidx = dev->ifindex;
request->wiphy = &drv->wiphy; request->wiphy = &drv->wiphy;
......
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