This patch allows monitor interfaces to be set by SIOCSIWMODE and to receive
frames.
Also, "soft" and "hard" monitor modes are introduced.
Signed-off-by: Jiri Benc <[EMAIL PROTECTED]>
Index: dscape/include/net/d80211.h
===================================================================
--- dscape.orig/include/net/d80211.h 2006-03-06 14:18:01.000000000 +0100
+++ dscape/include/net/d80211.h 2006-03-06 14:18:10.000000000 +0100
@@ -430,6 +430,10 @@ struct ieee80211_hw {
*/
unsigned int device_strips_mic:1;
+ /* Device is capable of performing full monitor mode even during
+ * normal operation. */
+ unsigned int monitor_during_oper:1;
+
/* 1 = low-level driver supports skb fraglist (NETIF_F_FRAGLIST), i.e.,
* more than one skb per frame */
unsigned int fraglist;
@@ -465,7 +469,9 @@ struct ieee80211_hw {
* more exactly, set UP). If the handler returns zero, the interface
* is added. Driver should perform any initialization it needs prior
* to returning zero. By returning non-zero, adding of the interface
- * is not permitted. The open() handler is called after
+ * is not permitted. Unless monitor_during_oper is set, it is
+ * guaranteed that monitor interfaces and normal interfaces are
+ * mutually exclusive. The open() handler is called after
* add_interface() if this is the first device added. At least one
* of open() and add_interface() handler has to be non-NULL. If
* add_interface() is NULL, one STA interface is permitted only. */
Index: dscape/net/d80211/ieee80211.c
===================================================================
--- dscape.orig/net/d80211/ieee80211.c 2006-03-06 14:18:06.000000000 +0100
+++ dscape/net/d80211/ieee80211.c 2006-03-06 14:18:10.000000000 +0100
@@ -1872,7 +1872,9 @@ static struct net_device_stats *ieee8021
static inline int identical_mac_addr_allowed(int type1, int type2)
{
- return ((type1 == IEEE80211_SUB_IF_TYPE_AP &&
+ return (type1 == IEEE80211_SUB_IF_TYPE_MNTR ||
+ type2 == IEEE80211_SUB_IF_TYPE_MNTR ||
+ (type1 == IEEE80211_SUB_IF_TYPE_AP &&
type2 == IEEE80211_SUB_IF_TYPE_WDS) ||
(type1 == IEEE80211_SUB_IF_TYPE_WDS &&
(type2 == IEEE80211_SUB_IF_TYPE_WDS ||
@@ -1906,6 +1908,34 @@ static int ieee80211_master_stop(struct
return 0;
}
+/* Check if running monitor interfaces should go to a "soft monitor" mode
+ * and switch them if necessary. */
+static inline void ieee80211_start_soft_monitor(struct ieee80211_local *local)
+{
+ struct ieee80211_if_conf conf;
+
+ if (local->open_count && local->open_count == local->monitors &&
+ !local->hw->monitor_during_oper && local->hw->remove_interface) {
+ conf.type = IEEE80211_SUB_IF_TYPE_MNTR;
+ conf.mac_addr = NULL;
+ local->hw->remove_interface(local->mdev, &conf);
+ }
+}
+
+/* Check if running monitor interfaces should go to a "hard monitor" mode
+ * and switch them if necessary. */
+static void ieee80211_start_hard_monitor(struct ieee80211_local *local)
+{
+ struct ieee80211_if_conf conf;
+
+ if (local->open_count && local->open_count == local->monitors &&
+ !local->hw->monitor_during_oper && local->hw->add_interface) {
+ conf.type = IEEE80211_SUB_IF_TYPE_MNTR;
+ conf.mac_addr = NULL;
+ local->hw->add_interface(local->mdev, &conf);
+ }
+}
+
static int ieee80211_open(struct net_device *dev)
{
struct ieee80211_sub_if_data *sdata, *nsdata;
@@ -1929,12 +1959,24 @@ static int ieee80211_open(struct net_dev
memcmp(sdata->u.wds.remote_addr, "\0\0\0\0\0\0", ETH_ALEN) == 0)
return -ENOLINK;
+ if (sdata->type == IEEE80211_SUB_IF_TYPE_MNTR && local->open_count &&
+ !local->hw->monitor_during_oper) {
+ /* run the interface in a "soft monitor" mode */
+ local->monitors++;
+ local->open_count++;
+ return 0;
+ }
+ ieee80211_start_soft_monitor(local);
+
if (local->hw->add_interface) {
conf.type = sdata->type;
conf.mac_addr = dev->dev_addr;
res = local->hw->add_interface(sdata->master, &conf);
- if (res)
+ if (res) {
+ if (sdata->type == IEEE80211_SUB_IF_TYPE_MNTR)
+ ieee80211_start_hard_monitor(local);
return res;
+ }
} else {
if (sdata->type != IEEE80211_SUB_IF_TYPE_STA)
return -EOPNOTSUPP;
@@ -1972,6 +2014,14 @@ static int ieee80211_stop(struct net_dev
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ if (sdata->type == IEEE80211_SUB_IF_TYPE_MNTR &&
+ local->open_count > 1 && !local->hw->monitor_during_oper) {
+ /* remove "soft monitor" interface */
+ local->open_count--;
+ local->monitors--;
+ return 0;
+ }
+
netif_stop_queue(dev);
local->open_count--;
@@ -1989,6 +2039,8 @@ static int ieee80211_stop(struct net_dev
local->hw->remove_interface(sdata->master, &conf);
}
+ ieee80211_start_hard_monitor(local);
+
return 0;
}
@@ -2221,7 +2273,8 @@ ieee80211_rx_mgmt(struct net_device *dev
size_t hlen;
struct ieee80211_sub_if_data *sdata;
- dev = local->apdev;
+ if (msg_type != ieee80211_msg_monitor)
+ dev = local->apdev;
skb->dev = dev;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
Index: dscape/net/d80211/ieee80211_i.h
===================================================================
--- dscape.orig/net/d80211/ieee80211_i.h 2006-03-06 14:18:01.000000000
+0100
+++ dscape/net/d80211/ieee80211_i.h 2006-03-06 14:18:10.000000000 +0100
@@ -305,6 +305,7 @@ struct ieee80211_local {
struct net_device *wdev; /* wlan# - default Ethernet (data) devide */
struct net_device *apdev; /* wlan#ap - management frames (hostapd) */
int open_count;
+ int monitors;
struct ieee80211_conf conf;
int dev_index;
Index: dscape/net/d80211/ieee80211_iface.c
===================================================================
--- dscape.orig/net/d80211/ieee80211_iface.c 2006-03-06 14:18:01.000000000
+0100
+++ dscape/net/d80211/ieee80211_iface.c 2006-03-06 14:18:10.000000000 +0100
@@ -8,6 +8,7 @@
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
+#include <linux/if_arp.h>
#include <linux/netdevice.h>
#include <linux/rtnetlink.h>
#include <net/d80211.h>
@@ -125,6 +126,9 @@ void ieee80211_if_set_type(struct net_de
ifsta->wmm_enabled = 1;
break;
}
+ case IEEE80211_SUB_IF_TYPE_MNTR:
+ dev->type = ARPHRD_IEEE80211_PRISM;
+ break;
default:
printk(KERN_WARNING "%s: %s: Unknown interface type 0x%x",
dev->name, __FUNCTION__, type);
@@ -212,6 +216,9 @@ void ieee80211_if_reinit(struct net_devi
}
break;
+ case IEEE80211_SUB_IF_TYPE_MNTR:
+ dev->type = ARPHRD_ETHER;
+ break;
}
/* remove all STAs that are bound to this virtual interface */
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html