-#ifdef CONFIG_IPW2200_PROMISCUOUS
-#define ieee80211_is_probe_response(fc) \
- ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT && \
- (fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP )
-
-#define ieee80211_is_management(fc) \
- ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT)
-
-#define ieee80211_is_control(fc) \
- ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL)
-
-#define ieee80211_is_data(fc) \
- ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)
-
-#define ieee80211_is_assoc_request(fc) \
- ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_ASSOC_REQ)
-
-#define ieee80211_is_reassoc_request(fc) \
- ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_REASSOC_REQ)
-
-static void ipw_handle_promiscuous_rx(struct ipw_priv *priv,
- struct ipw_rx_mem_buffer *rxb,
- struct ieee80211_rx_stats *stats)
-{
- struct ipw_rx_packet *pkt = (struct ipw_rx_packet *)rxb->skb->data;
- struct ipw_rx_frame *frame = &pkt->u.frame;
- struct ipw_rt_hdr *ipw_rt;
-
- /* First cache any information we need before we overwrite
- * the information provided in the skb from the hardware */
- struct ieee80211_hdr *hdr;
- u16 channel = frame->received_channel;
- u8 phy_flags = frame->antennaAndPhy;
- s8 signal = frame->rssi_dbm - IPW_RSSI_TO_DBM;
- s8 noise = frame->noise;
- u8 rate = frame->rate;
- short len = le16_to_cpu(pkt->u.frame.length);
- u64 tsf = 0;
- struct sk_buff *skb;
- int hdr_only = 0;
- u16 filter = priv->prom_priv->filter;
-
- /* If the filter is set to not include Rx frames then return */
- if (filter & IPW_PROM_NO_RX)
- return;
-
- /* We received data from the HW, so stop the watchdog */
- priv->prom_net_dev->trans_start = jiffies;
-
- if (unlikely((len + IPW_RX_FRAME_SIZE) > skb_tailroom(rxb->skb))) {
- priv->prom_priv->ieee->stats.rx_errors++;
- IPW_DEBUG_DROP("Corruption detected! Oh no!\n");
- return;
- }
-
- /* We only process data packets if the interface is open */
- if (unlikely(!netif_running(priv->prom_net_dev))) {
- priv->prom_priv->ieee->stats.rx_dropped++;
- IPW_DEBUG_DROP("Dropping packet while interface is not up.\n");
- return;
- }
-
- /* Libpcap 0.9.3+ can handle variable length radiotap, so we'll use
- * that now */
- if (len > IPW_RX_BUF_SIZE - sizeof(struct ipw_rt_hdr)) {
- /* FIXME: Should alloc bigger skb instead */
- priv->prom_priv->ieee->stats.rx_dropped++;
- IPW_DEBUG_DROP("Dropping too large packet in monitor\n");
- return;
- }
-
- hdr = (void *)rxb->skb->data + IPW_RX_FRAME_SIZE;
- if (ieee80211_is_management(hdr->frame_ctl)) {
- if (filter & IPW_PROM_NO_MGMT)
- return;
- if (filter & IPW_PROM_MGMT_HEADER_ONLY)
- hdr_only = 1;
- } else if (ieee80211_is_control(hdr->frame_ctl)) {
- if (filter & IPW_PROM_NO_CTL)
- return;
- if (filter & IPW_PROM_CTL_HEADER_ONLY)
- hdr_only = 1;
- } else if (ieee80211_is_data(hdr->frame_ctl)) {
- if (filter & IPW_PROM_NO_DATA)
- return;
- if (filter & IPW_PROM_DATA_HEADER_ONLY)
- hdr_only = 1;
- }
-
- /* Copy the SKB since this is for the promiscuous side */
- skb = skb_copy(rxb->skb, GFP_ATOMIC);
- if (skb == NULL) {
- IPW_ERROR("skb_clone failed for promiscuous copy.\n");
- return;
- }
-
- /* copy the frame data to write after where the radiotap header goes */
- ipw_rt = (void *)skb->data;
-
- if (hdr_only)
- len = ieee80211_get_hdrlen(hdr->frame_ctl);
-
- memcpy(ipw_rt->payload, hdr, len);
-
- /* Zero the radiotap static buffer ... We only need to zero the bytes
- * NOT part of our real header, saves a little time.
- *
- * No longer necessary since we fill in all our data. Purge before
- * merging patch officially.
- * memset(rxb->skb->data + sizeof(struct ipw_rt_hdr), 0,
- * IEEE80211_RADIOTAP_HDRLEN - sizeof(struct ipw_rt_hdr));
- */
-
- ipw_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION;
- ipw_rt->rt_hdr.it_pad = 0; /* always good to zero */
- ipw_rt->rt_hdr.it_len = sizeof(*ipw_rt); /* total header+data */
-
- /* Set the size of the skb to the size of the frame */
- skb_put(skb, ipw_rt->rt_hdr.it_len + len);
-
- /* Big bitfield of all the fields we provide in radiotap */
- ipw_rt->rt_hdr.it_present =
- ((1 << IEEE80211_RADIOTAP_FLAGS) |
- (1 << IEEE80211_RADIOTAP_TSFT) |
- (1 << IEEE80211_RADIOTAP_RATE) |
- (1 << IEEE80211_RADIOTAP_CHANNEL) |
- (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |
- (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) |
- (1 << IEEE80211_RADIOTAP_ANTENNA));
-
- /* Zero the flags, we'll add to them as we go */
- ipw_rt->rt_flags = 0;
-
- ipw_rt->rt_tsf = tsf;
-
- /* Convert to DBM */
- ipw_rt->rt_dbmsignal = signal;
- ipw_rt->rt_dbmnoise = noise;
-
- /* Convert the channel data and set the flags */
- ipw_rt->rt_channel = cpu_to_le16(ieee80211chan2mhz(channel));
- if (channel > 14) { /* 802.11a */
- ipw_rt->rt_chbitmask =
- cpu_to_le16((IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ));
- } else if (phy_flags & (1 << 5)) { /* 802.11b */
- ipw_rt->rt_chbitmask =
- cpu_to_le16((IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ));
- } else { /* 802.11g */
- ipw_rt->rt_chbitmask =
- (IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ);
- }
-
- /* set the rate in multiples of 500k/s */
- switch (rate) {
- case IPW_TX_RATE_1MB:
- ipw_rt->rt_rate = 2;
- break;
- case IPW_TX_RATE_2MB:
- ipw_rt->rt_rate = 4;
- break;
- case IPW_TX_RATE_5MB:
- ipw_rt->rt_rate = 10;
- break;
- case IPW_TX_RATE_6MB:
- ipw_rt->rt_rate = 12;
- break;
- case IPW_TX_RATE_9MB:
- ipw_rt->rt_rate = 18;
- break;
- case IPW_TX_RATE_11MB:
- ipw_rt->rt_rate = 22;
- break;
- case IPW_TX_RATE_12MB:
- ipw_rt->rt_rate = 24;
- break;
- case IPW_TX_RATE_18MB:
- ipw_rt->rt_rate = 36;
- break;
- case IPW_TX_RATE_24MB:
- ipw_rt->rt_rate = 48;
- break;
- case IPW_TX_RATE_36MB:
- ipw_rt->rt_rate = 72;
- break;
- case IPW_TX_RATE_48MB:
- ipw_rt->rt_rate = 96;
- break;
- case IPW_TX_RATE_54MB:
- ipw_rt->rt_rate = 108;
- break;
- default:
- ipw_rt->rt_rate = 0;
- break;
- }
-
- /* antenna number */
- ipw_rt->rt_antenna = (phy_flags & 3);
-
- /* set the preamble flag if we have it */
- if (phy_flags & (1 << 6))
- ipw_rt->rt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
-
- IPW_DEBUG_RX("Rx packet of %d bytes.\n", skb->len);
-
- if (!ieee80211_rx(priv->prom_priv->ieee, skb, stats)) {
- priv->prom_priv->ieee->stats.rx_errors++;
- dev_kfree_skb_any(skb);
- }
-}
-#endif
-