Added global monitor interface (hwsim#)
This new netdev is created by hwsim, not mac80211, and as such, it is available all the time (i.e., can be UP before starting mac80211 netdevs) and it will receive all frames regardless of the channel etc.
This commit is contained in:
parent
a837861751
commit
1f9afa67e3
1 changed files with 100 additions and 0 deletions
|
@ -15,6 +15,9 @@
|
|||
*/
|
||||
|
||||
#include <net/mac80211.h>
|
||||
#include <net/ieee80211_radiotap.h>
|
||||
#include <linux/if_arp.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
|
||||
MODULE_AUTHOR("Jouni Malinen");
|
||||
MODULE_DESCRIPTION("Software simulator of 802.11 radio(s) for mac80211");
|
||||
|
@ -29,6 +32,7 @@ static struct class *hwsim_class;
|
|||
|
||||
static struct ieee80211_hw **hwsim_radios;
|
||||
static int hwsim_radio_count;
|
||||
static struct net_device *hwsim_mon; /* global monitor netdev */
|
||||
|
||||
|
||||
static const struct ieee80211_channel hwsim_channels[] = {
|
||||
|
@ -79,6 +83,66 @@ struct mac80211_hwsim_data {
|
|||
};
|
||||
|
||||
|
||||
struct hwsim_radiotap_hdr {
|
||||
struct ieee80211_radiotap_header hdr;
|
||||
u8 rt_flags;
|
||||
u8 rt_rate;
|
||||
__le16 rt_channel;
|
||||
__le16 rt_chbitmask;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
static int hwsim_mon_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
/* TODO: allow packet injection */
|
||||
dev_kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void mac80211_hwsim_monitor_rx(struct mac80211_hwsim_data *data,
|
||||
struct sk_buff *tx_skb,
|
||||
struct ieee80211_tx_control *control)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct hwsim_radiotap_hdr *hdr;
|
||||
u16 flags;
|
||||
|
||||
if (!netif_running(hwsim_mon))
|
||||
return;
|
||||
|
||||
skb = skb_copy_expand(tx_skb, sizeof(*hdr), 0, GFP_ATOMIC);
|
||||
if (skb == NULL)
|
||||
return;
|
||||
|
||||
hdr = (struct hwsim_radiotap_hdr *) skb_push(skb, sizeof(*hdr));
|
||||
hdr->hdr.it_version = PKTHDR_RADIOTAP_VERSION;
|
||||
hdr->hdr.it_pad = 0;
|
||||
hdr->hdr.it_len = cpu_to_le16(sizeof(*hdr));
|
||||
hdr->hdr.it_present = __constant_cpu_to_le32(
|
||||
(1 << IEEE80211_RADIOTAP_FLAGS) |
|
||||
(1 << IEEE80211_RADIOTAP_RATE) |
|
||||
(1 << IEEE80211_RADIOTAP_CHANNEL));
|
||||
hdr->rt_flags = 0;
|
||||
hdr->rt_rate = control->tx_rate / 5;
|
||||
hdr->rt_channel = data->freq;
|
||||
flags = IEEE80211_CHAN_2GHZ;
|
||||
if (control->rate->flags & IEEE80211_RATE_OFDM)
|
||||
flags |= IEEE80211_CHAN_OFDM;
|
||||
if (control->rate->flags & IEEE80211_RATE_CCK)
|
||||
flags |= IEEE80211_CHAN_CCK;
|
||||
hdr->rt_chbitmask = cpu_to_le16(flags);
|
||||
|
||||
skb->dev = hwsim_mon;
|
||||
skb_set_mac_header(skb, 0);
|
||||
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
skb->pkt_type = PACKET_OTHERHOST;
|
||||
skb->protocol = __constant_htons(ETH_P_802_2);
|
||||
memset(skb->cb, 0, sizeof(skb->cb));
|
||||
netif_rx(skb);
|
||||
}
|
||||
|
||||
|
||||
static int mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
struct ieee80211_tx_control *control)
|
||||
{
|
||||
|
@ -87,6 +151,8 @@ static int mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
|
|||
struct ieee80211_rx_status rx_status;
|
||||
int i;
|
||||
|
||||
mac80211_hwsim_monitor_rx(data, skb, control);
|
||||
|
||||
if (!data->radio_enabled) {
|
||||
printk(KERN_DEBUG "%s: dropped TX frame since radio "
|
||||
"disabled\n", wiphy_name(hw->wiphy));
|
||||
|
@ -233,6 +299,18 @@ static struct device_driver mac80211_hwsim_driver = {
|
|||
};
|
||||
|
||||
|
||||
static void hwsim_mon_setup(struct net_device *dev)
|
||||
{
|
||||
dev->hard_start_xmit = hwsim_mon_xmit;
|
||||
dev->destructor = free_netdev;
|
||||
ether_setup(dev);
|
||||
dev->tx_queue_len = 0;
|
||||
dev->type = ARPHRD_IEEE80211_RADIOTAP;
|
||||
memset(dev->dev_addr, 0, ETH_ALEN);
|
||||
dev->dev_addr[0] = 0x12;
|
||||
}
|
||||
|
||||
|
||||
static int __init init_mac80211_hwsim(void)
|
||||
{
|
||||
int i, err = 0;
|
||||
|
@ -317,8 +395,29 @@ static int __init init_mac80211_hwsim(void)
|
|||
print_mac(mac, hw->wiphy->perm_addr));
|
||||
}
|
||||
|
||||
hwsim_mon = alloc_netdev(0, "hwsim%d", hwsim_mon_setup);
|
||||
if (hwsim_mon == NULL)
|
||||
goto failed;
|
||||
|
||||
rtnl_lock();
|
||||
|
||||
err = dev_alloc_name(hwsim_mon, hwsim_mon->name);
|
||||
if (err < 0) {
|
||||
goto failed_mon;
|
||||
}
|
||||
|
||||
err = register_netdevice(hwsim_mon);
|
||||
if (err < 0)
|
||||
goto failed_mon;
|
||||
|
||||
rtnl_unlock();
|
||||
|
||||
return 0;
|
||||
|
||||
failed_mon:
|
||||
rtnl_unlock();
|
||||
free_netdev(hwsim_mon);
|
||||
|
||||
failed:
|
||||
mac80211_hwsim_free();
|
||||
return err;
|
||||
|
@ -330,6 +429,7 @@ static void __exit exit_mac80211_hwsim(void)
|
|||
printk(KERN_DEBUG "mac80211_hwsim: unregister %d radios\n",
|
||||
hwsim_radio_count);
|
||||
|
||||
unregister_netdev(hwsim_mon);
|
||||
mac80211_hwsim_free();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue