mac80211: create Probe Request template
Kalle Valo [Tue, 5 Jan 2010 18:16:38 +0000 (20:16 +0200)]
Certain type of hardware, for example wl1251 and wl1271, need a template
for the Probe Request. Create a function ieee80211_probereq_get() which
creates the template and drivers send it to hardware.

Signed-off-by: Kalle Valo <kalle.valo@nokia.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>

include/net/mac80211.h
net/mac80211/tx.c

index 75f46e2..e1e73c6 100644 (file)
@@ -1905,6 +1905,23 @@ struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw,
                                       struct ieee80211_vif *vif);
 
 /**
+ * ieee80211_probereq_get - retrieve a Probe Request template
+ * @hw: pointer obtained from ieee80211_alloc_hw().
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ * @ssid: SSID buffer
+ * @ssid_len: length of SSID
+ * @ie: buffer containing all IEs except SSID for the template
+ * @ie_len: length of the IE buffer
+ *
+ * Creates a Probe Request template which can, for example, be uploaded to
+ * hardware.
+ */
+struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw,
+                                      struct ieee80211_vif *vif,
+                                      const u8 *ssid, size_t ssid_len,
+                                      const u8 *ie, size_t ie_len);
+
+/**
  * ieee80211_rts_get - RTS frame generation function
  * @hw: pointer obtained from ieee80211_alloc_hw().
  * @vif: &struct ieee80211_vif pointer from the add_interface callback.
index 055b45b..0661e69 100644 (file)
@@ -2278,6 +2278,56 @@ struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw,
 }
 EXPORT_SYMBOL(ieee80211_nullfunc_get);
 
+struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw,
+                                      struct ieee80211_vif *vif,
+                                      const u8 *ssid, size_t ssid_len,
+                                      const u8 *ie, size_t ie_len)
+{
+       struct ieee80211_sub_if_data *sdata;
+       struct ieee80211_local *local;
+       struct ieee80211_hdr_3addr *hdr;
+       struct sk_buff *skb;
+       size_t ie_ssid_len;
+       u8 *pos;
+
+       sdata = vif_to_sdata(vif);
+       local = sdata->local;
+       ie_ssid_len = 2 + ssid_len;
+
+       skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*hdr) +
+                           ie_ssid_len + ie_len);
+       if (!skb) {
+               printk(KERN_DEBUG "%s: failed to allocate buffer for probe "
+                      "request template\n", sdata->name);
+               return NULL;
+       }
+
+       skb_reserve(skb, local->hw.extra_tx_headroom);
+
+       hdr = (struct ieee80211_hdr_3addr *) skb_put(skb, sizeof(*hdr));
+       memset(hdr, 0, sizeof(*hdr));
+       hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+                                        IEEE80211_STYPE_PROBE_REQ);
+       memset(hdr->addr1, 0xff, ETH_ALEN);
+       memcpy(hdr->addr2, vif->addr, ETH_ALEN);
+       memset(hdr->addr3, 0xff, ETH_ALEN);
+
+       pos = skb_put(skb, ie_ssid_len);
+       *pos++ = WLAN_EID_SSID;
+       *pos++ = ssid_len;
+       if (ssid)
+               memcpy(pos, ssid, ssid_len);
+       pos += ssid_len;
+
+       if (ie) {
+               pos = skb_put(skb, ie_len);
+               memcpy(pos, ie, ie_len);
+       }
+
+       return skb;
+}
+EXPORT_SYMBOL(ieee80211_probereq_get);
+
 void ieee80211_rts_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
                       const void *frame, size_t frame_len,
                       const struct ieee80211_tx_info *frame_txctl,