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