diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index c0d1f5b708c5836d3fcf0cc9ededd748bc9a6657..33f43b0d08fb1bbc1b8a59a822388837f1ef8181 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -525,6 +525,8 @@ struct cfg80211_ssid { * @n_ssids: number of SSIDs * @channels: channels to scan on. * @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 * @ifidx: the interface index */ @@ -533,6 +535,8 @@ struct cfg80211_scan_request { int n_ssids; struct ieee80211_channel **channels; u32 n_channels; + u8 *ie; + size_t ie_len; /* internal */ struct wiphy *wiphy; diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 27d56414019d5dfd453fba049b6700009f5734dc..d06c75720ced9be7a11ce8698b8e47f3be3bf09d 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1093,7 +1093,8 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, u8 *extra, size_t extra_len, const u8 *bssid, int encrypt); 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, const size_t supp_rates_len, diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index ec5a0900cba01c3cdaf5ff8c60151fd9078572be..5a4977936f6fcdfa024248cf78e8b337a78306d1 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -716,7 +716,7 @@ static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata) * will not answer to direct packet in unassociated state. */ 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); } @@ -946,7 +946,8 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata) } else ieee80211_send_probe_req(sdata, ifmgd->bssid, ifmgd->ssid, - ifmgd->ssid_len); + ifmgd->ssid_len, + NULL, 0); ifmgd->flags ^= IEEE80211_STA_PROBEREQ_POLL; } else { ifmgd->flags &= ~IEEE80211_STA_PROBEREQ_POLL; @@ -955,7 +956,8 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata) ifmgd->last_probe = jiffies; ieee80211_send_probe_req(sdata, ifmgd->bssid, ifmgd->ssid, - ifmgd->ssid_len); + ifmgd->ssid_len, + NULL, 0); } } } diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 08a1fc27ca100570e08d42aed5b07c942c6e417e..c063f8204263d1883151aa5723308ce6ebf2fbde 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -338,7 +338,8 @@ void ieee80211_scan_work(struct work_struct *work) ieee80211_send_probe_req( sdata, NULL, 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; break; } diff --git a/net/mac80211/util.c b/net/mac80211/util.c index dee17e5cbb898b8f4da487130992421e4209a3af..e0431a1d218b1a299c092560c6d07b4f6c181780 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -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, - 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_supported_band *sband; @@ -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 + - extra_preq_ie_len); + ie_len + extra_preq_ie_len); if (!skb) { printk(KERN_DEBUG "%s: failed to allocate buffer for probe " "request\n", sdata->dev->name); @@ -950,6 +951,8 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, *pos = rate->bitrate / 5; } + if (ie) + memcpy(skb_put(skb, ie_len), ie, ie_len); if (extra_preq_ie) memcpy(skb_put(skb, extra_preq_ie_len), extra_preq_ie, extra_preq_ie_len); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 298a4de5994833b39380d7936e75dbf66e98a85b..67b18b3a93a03f8407d7971ef92d8a0db97b0c22 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -2286,6 +2286,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) struct wiphy *wiphy; int err, tmp, n_ssids = 0, n_channels = 0, i; enum ieee80211_band band; + size_t ie_len; err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); if (err) @@ -2327,9 +2328,15 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) 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) + sizeof(*ssid) * n_ssids - + sizeof(channel) * n_channels, GFP_KERNEL); + + sizeof(channel) * n_channels + + ie_len, GFP_KERNEL); if (!request) { err = -ENOMEM; goto out_unlock; @@ -2340,6 +2347,12 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) if (n_ssids) request->ssids = (void *)(request->channels + n_channels); 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]) { /* 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) } } + 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->wiphy = &drv->wiphy;