#include <linux/etherdevice.h>
#include <linux/slab.h>
#include <net/lib80211.h>
#include <linux/if_arp.h>
#include "hostap_80211.h"
#include "hostap.h"
#include "hostap_ap.h"
/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
static unsigned char rfc1042_header[] =
{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
static unsigned char bridge_tunnel_header[] =
{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
/* No encapsulation header if EtherType < 0x600 (=length) */
void hostap_dump_rx_80211(const char *name, struct sk_buff *skb,
struct hostap_80211_rx_status *rx_stats)
{
struct ieee80211_hdr *hdr;
u16 fc;
hdr = (struct ieee80211_hdr *) skb->data;
printk(KERN_DEBUG "%s: RX signal=%d noise=%d rate=%d len=%d "
"jiffies=%ld\n",
name, rx_stats->signal, rx_stats->noise, rx_stats->rate,
skb->len, jiffies);
if (skb->len < 2)
return;
fc = le16_to_cpu(hdr->frame_control);
printk(KERN_DEBUG " FC=0x%04x (type=%d:%d)%s%s",
fc, (fc & IEEE80211_FCTL_FTYPE) >> 2,
(fc & IEEE80211_FCTL_STYPE) >> 4,
fc & IEEE80211_FCTL_TODS ? " [ToDS]" : "",
fc & IEEE80211_FCTL_FROMDS ? " [FromDS]" : "");
if (skb->len < IEEE80211_DATA_HDR3_LEN) {
printk("\n");
return;
}
printk(" dur=0x%04x seq=0x%04x\n", le16_to_cpu(hdr->duration_id),
le16_to_cpu(hdr->seq_ctrl));
printk(KERN_DEBUG " A1=%pM", hdr->addr1);
printk(" A2=%pM", hdr->addr2);
printk(" A3=%pM", hdr->addr3);
if (skb->len >= 30)
printk(" A4=%pM", hdr->addr4);
printk("\n");
}
/* Send RX frame to netif with 802.11 (and possible prism) header.
* Called from hardware or software IRQ context. */
int prism2_rx_80211(struct net_device *dev, struct sk_buff *skb,
struct hostap_80211_rx_status *rx_stats, int type)
{
struct hostap_interface *iface;
local_info_t *local;
int hdrlen, phdrlen, head_need, tail_need;
u16 fc;
int prism_header, ret;
struct ieee80211_hdr *fhdr;
iface = netdev_priv(dev);
local = iface->local;
if (dev->type == ARPHRD_IEEE80211_PRISM) {
if (local->monitor_type == PRISM2_MONITOR_PRISM) {
prism_header = 1;
phdrlen = sizeof(struct linux_wlan_ng_prism_hdr);
} else { /* local->monitor_type == PRISM2_MONITOR_CAPHDR */
prism_header = 2;
phdrlen = sizeof(struct linux_wlan_ng_cap_hdr);
}
} else if (dev->type == ARPHRD_IEEE80211_RADIOTAP) {
prism_header = 3;
phdrlen = sizeof(struct hostap_radiotap_rx);
} else {
prism_header = 0;
phdrlen = 0;
}
fhdr = (struct ieee80211_hdr *) skb->data;
fc = le16_to_cpu(fhdr->frame_control);
if (type == PRISM2_RX_MGMT && (fc & IEEE80211_FCTL_VERS))