Default management interface (wmasterXap) confuses users. This patch removes it and gives userspace tools (such as hostapd or wpa_supplicant) possibility to switch it on/off as needed.
To do this, a new PRISM2_PARAM_MGMT_IF iwpriv ioctl is introduced. When set, it accepts one parameter: 1 for enabling the interface, 0 for disabling it. When read, it returns ifindex of the management interface or -ENOENT when the management interface is switched off. Signed-off-by: Jiri Benc <[EMAIL PROTECTED]> --- net/d80211/hostapd_ioctl.h | 1 net/d80211/ieee80211.c | 101 ++++++++++++++++++------------------------- net/d80211/ieee80211_i.h | 3 + net/d80211/ieee80211_iface.c | 66 ++++++++++++++++++++++++++-- net/d80211/ieee80211_ioctl.c | 16 ++++++ 5 files changed, 127 insertions(+), 60 deletions(-) --- dscape.orig/net/d80211/hostapd_ioctl.h +++ dscape/net/d80211/hostapd_ioctl.h @@ -91,6 +91,7 @@ enum { PRISM2_PARAM_KEY_MGMT = 1040, PRISM2_PARAM_RADAR_DETECT = 1043, PRISM2_PARAM_SPECTRUM_MGMT = 1044, + PRISM2_PARAM_MGMT_IF = 1045, /* NOTE: Please try to coordinate with other active development * branches before allocating new param numbers so that each new param * will be unique within all branches and the allocated number will not --- dscape.orig/net/d80211/ieee80211.c +++ dscape/net/d80211/ieee80211.c @@ -1954,8 +1954,6 @@ static inline int identical_mac_addr_all { return (type1 == IEEE80211_IF_TYPE_MNTR || type2 == IEEE80211_IF_TYPE_MNTR || - type1 == IEEE80211_IF_TYPE_MGMT || - type2 == IEEE80211_IF_TYPE_MGMT || (type1 == IEEE80211_IF_TYPE_AP && type2 == IEEE80211_IF_TYPE_WDS) || (type1 == IEEE80211_IF_TYPE_WDS && @@ -1990,6 +1988,20 @@ static int ieee80211_master_stop(struct return 0; } +static int ieee80211_mgmt_open(struct net_device *dev) +{ + struct ieee80211_local *local = dev->priv; + + if (!netif_running(local->mdev)) + return -EOPNOTSUPP; + return 0; +} + +static int ieee80211_mgmt_stop(struct net_device *dev) +{ + 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) @@ -2032,7 +2044,6 @@ static int ieee80211_open(struct net_dev struct net_device *ndev = nsdata->dev; if (ndev != dev && ndev != local->mdev && - ndev != local->apdev && netif_running(ndev) && memcmp(dev->dev_addr, ndev->dev_addr, ETH_ALEN) == 0 && !identical_mac_addr_allowed(sdata->type, nsdata->type)) { @@ -2075,8 +2086,11 @@ static int ieee80211_open(struct net_dev res = local->hw->open(sdata->master); if (res == 0) { res = dev_open(sdata->master); - if (res && local->hw->stop) - local->hw->stop(sdata->master); + if (res) { + if (local->hw->stop) + local->hw->stop(sdata->master); + } else if (local->apdev) + dev_open(local->apdev); } if (res) { if (local->hw->remove_interface) @@ -2119,6 +2133,8 @@ static int ieee80211_stop(struct net_dev if (local->open_count == 0) { ieee80211_stop_scan(sdata->master); dev_close(sdata->master); + if (local->apdev) + dev_close(local->apdev); if (local->hw->stop) local->hw->stop(sdata->master); } @@ -2367,6 +2383,10 @@ ieee80211_rx_mgmt(struct net_device *dev if (msg_type != ieee80211_msg_monitor) dev = local->apdev; + if (!dev) { + dev_kfree_skb(skb); + return; + } skb->dev = dev; sdata = IEEE80211_DEV_TO_SUB_IF(dev); @@ -3998,6 +4018,19 @@ void ieee80211_if_setup(struct net_devic dev->destructor = ieee80211_if_free; } +void ieee80211_if_mgmt_setup(struct net_device *dev) +{ + ether_setup(dev); + dev->hard_start_xmit = ieee80211_mgmt_start_xmit; + dev->change_mtu = ieee80211_change_mtu_apdev; + dev->get_stats = ieee80211_get_stats; + dev->open = ieee80211_mgmt_open; + dev->stop = ieee80211_mgmt_stop; + dev->type = ARPHRD_IEEE80211_PRISM; + dev->hard_header_parse = header_parse_80211; + dev->tx_queue_len = 0; + dev->destructor = ieee80211_if_free; +} static void ieee80211_precalc_rates(struct ieee80211_hw *hw) { @@ -4018,7 +4051,7 @@ static void ieee80211_precalc_rates(stru struct net_device *ieee80211_alloc_hw(size_t priv_data_len, void (*setup)(struct net_device *)) { - struct net_device *apdev, *mdev; + struct net_device *mdev; struct ieee80211_local *local; struct ieee80211_sub_if_data *sdata; int alloc_size; @@ -4038,17 +4071,11 @@ struct net_device *ieee80211_alloc_hw(si * 0b84 ***************** * * hw_priv * * 1664 ***************** - * * ap net_dev * - * 17c0 ***************** - * * sub_if * - * ***************** */ alloc_size = sizeof(struct net_device) + sizeof(struct ieee80211_sub_if_data) + 3 + sizeof(struct ieee80211_local) + 3 + priv_data_len + 3 + - sizeof(struct net_device) + 3 + - sizeof(struct ieee80211_sub_if_data) + 3 + 4096; mdev = (struct net_device *) kzalloc(alloc_size, GFP_KERNEL); if (mdev == NULL) @@ -4061,15 +4088,10 @@ struct net_device *ieee80211_alloc_hw(si local = mdev->priv; local->hw_priv = (void *) ((char *) local + ((sizeof(struct ieee80211_local) + 3) & ~3)); - apdev = (struct net_device *) - ((char *) local->hw_priv + ((priv_data_len + 3) & ~3)); ether_setup(mdev); memcpy(mdev->name, "wmaster%d", 10); - if (strlen(mdev->name) + 2 >= sizeof(mdev->name)) - goto fail; - local->dev_index = -1; local->mdev = mdev; local->rx_handlers = ieee80211_rx_handlers; @@ -4104,28 +4126,6 @@ struct net_device *ieee80211_alloc_hw(si ieee80211_if_init(mdev); - apdev = (struct net_device *) - ((char *) local->hw_priv + ((priv_data_len + 3) & ~3)); - local->apdev = apdev; - ether_setup(apdev); - apdev->priv = local; - apdev->hard_start_xmit = ieee80211_mgmt_start_xmit; - apdev->change_mtu = ieee80211_change_mtu_apdev; - apdev->get_stats = ieee80211_get_stats; - apdev->open = ieee80211_open; - apdev->stop = ieee80211_stop; - apdev->type = ARPHRD_IEEE80211_PRISM; - apdev->hard_header_parse = header_parse_80211; - apdev->tx_queue_len = 0; - sprintf(apdev->name, "%sap", mdev->name); - - sdata = IEEE80211_DEV_TO_SUB_IF(apdev); - sdata->type = IEEE80211_IF_TYPE_MGMT; - sdata->dev = apdev; - sdata->master = mdev; - sdata->local = local; - list_add_tail(&sdata->list, &local->sub_if_list); - mdev->hard_start_xmit = ieee80211_master_start_xmit; mdev->wireless_handlers = (struct iw_handler_def *) &ieee80211_iw_handler_def; @@ -4155,10 +4155,6 @@ struct net_device *ieee80211_alloc_hw(si setup(mdev); return mdev; - - fail: - ieee80211_free_hw(mdev); - return NULL; } @@ -4193,15 +4189,11 @@ int ieee80211_register_hw(struct net_dev sta_info_start(local); - result = register_netdev(local->apdev); - if (result < 0) - goto fail_1st_dev; - if (hw->fraglist) dev->features |= NETIF_F_FRAGLIST; result = register_netdev(dev); if (result < 0) - goto fail_2nd_dev; + goto fail_dev; if (rate_control_initialize(local) < 0) { printk(KERN_DEBUG "%s: Failed to initialize rate control " @@ -4226,9 +4218,7 @@ int ieee80211_register_hw(struct net_dev fail_rate: unregister_netdev(dev); -fail_2nd_dev: - unregister_netdev(local->apdev); -fail_1st_dev: +fail_dev: sta_info_stop(local); ieee80211_unregister_sysfs(local); fail_sysfs: @@ -4247,12 +4237,6 @@ int ieee80211_update_hw(struct net_devic if (hw->queues == 0) hw->queues = 1; - memcpy(local->apdev->dev_addr, dev->dev_addr, ETH_ALEN); - local->apdev->base_addr = dev->base_addr; - local->apdev->irq = dev->irq; - local->apdev->mem_start = dev->mem_start; - local->apdev->mem_end = dev->mem_end; - if (!hw->modes || !hw->modes->channels || !hw->modes->rates || !hw->modes->num_channels || !hw->modes->num_rates) return -1; @@ -4291,6 +4275,9 @@ void ieee80211_unregister_hw(struct net_ del_timer_sync(&local->scan_timer); ieee80211_rx_bss_list_deinit(dev); + if (local->apdev) + ieee80211_if_del(local->apdev); + list_for_each_safe(ptr, n, &local->sub_if_list) { struct ieee80211_sub_if_data *sdata = list_entry(ptr, struct ieee80211_sub_if_data, list); --- dscape.orig/net/d80211/ieee80211_i.h +++ dscape/net/d80211/ieee80211_i.h @@ -518,6 +518,7 @@ void ieee80211_prepare_rates(struct net_ void ieee80211_tx_set_iswep(struct ieee80211_txrx_data *tx); int ieee80211_if_update_wds(struct net_device *dev, u8 *remote_addr); void ieee80211_if_setup(struct net_device *dev); +void ieee80211_if_mgmt_setup(struct net_device *dev); /* ieee80211_ioctl.c */ int ieee80211_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); @@ -595,6 +596,8 @@ int ieee80211_if_remove(struct net_devic void ieee80211_if_free(struct net_device *dev); void ieee80211_if_flush(struct net_device *dev); void ieee80211_if_sdata_init(struct ieee80211_sub_if_data *sdata); +int ieee80211_if_add_mgmt(struct net_device *dev); +void ieee80211_if_del_mgmt(struct net_device *dev); /* ieee80211_sysfs.c */ int ieee80211_register_sysfs(struct ieee80211_local *local); --- dscape.orig/net/d80211/ieee80211_iface.c +++ dscape/net/d80211/ieee80211_iface.c @@ -93,6 +93,63 @@ fail: return ret; } +int ieee80211_if_add_mgmt(struct net_device *dev) +{ + struct net_device *ndev; + struct ieee80211_local *local = dev->priv; + struct ieee80211_sub_if_data *sdata, *nsdata; + int alloc_size, ret; + + sdata = IEEE80211_DEV_TO_SUB_IF(dev); + ASSERT_RTNL(); + alloc_size = sizeof(struct net_device) + 3 + + sizeof(struct ieee80211_sub_if_data) + 3; + + ndev = (struct net_device *) kzalloc(alloc_size, GFP_KERNEL); + if (ndev == NULL) + return -ENOMEM; + ret = dev_alloc_name(ndev, "wmgmt%d"); + if (ret) + goto fail; + + ndev->priv = local; + memcpy(ndev->dev_addr, dev->dev_addr, ETH_ALEN); + ndev->base_addr = dev->base_addr; + ndev->irq = dev->irq; + ndev->mem_start = dev->mem_start; + ndev->mem_end = dev->mem_end; + ieee80211_if_mgmt_setup(ndev); + + nsdata = IEEE80211_DEV_TO_SUB_IF(ndev); + nsdata->type = IEEE80211_IF_TYPE_MGMT; + nsdata->master = local->mdev; + nsdata->dev = ndev; + nsdata->local = local; + ieee80211_if_sdata_init(nsdata); + + ret = register_netdevice(ndev); + if (ret) + goto fail; + if (local->open_count > 0) + dev_open(ndev); + local->apdev = ndev; + return 0; +fail: + kfree(ndev); + return ret; +} + +void ieee80211_if_del_mgmt(struct net_device *dev) +{ + struct ieee80211_local *local = dev->priv; + struct net_device *apdev; + + ASSERT_RTNL(); + apdev = local->apdev; + local->apdev = NULL; + unregister_netdevice(apdev); +} + void ieee80211_if_set_type(struct net_device *dev, int type) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); @@ -110,6 +167,7 @@ void ieee80211_if_set_type(struct net_de sdata->u.ap.max_ratectrl_rateidx = -1; skb_queue_head_init(&sdata->u.ap.ps_bc_buf); sdata->bss = &sdata->u.ap; + sdata->type = IEEE80211_IF_TYPE_STA; break; case IEEE80211_IF_TYPE_STA: case IEEE80211_IF_TYPE_IBSS: { @@ -263,8 +321,7 @@ int ieee80211_if_remove(struct net_devic list_for_each_entry_safe(sdata, n, &local->sub_if_list, list) { if ((sdata->type == id || id == -1) && strcmp(name, sdata->dev->name) == 0 && - sdata->dev != local->mdev && - sdata->dev != local->apdev) { + sdata->dev != local->mdev) { __ieee80211_if_del(local, sdata); return 0; } @@ -298,6 +355,9 @@ void ieee80211_if_del(struct net_device struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); rtnl_lock(); - __ieee80211_if_del(local, sdata); + if (sdata->type == IEEE80211_IF_TYPE_MGMT) + ieee80211_if_del_mgmt(local->mdev); + else + __ieee80211_if_del(local, sdata); rtnl_unlock(); } --- dscape.orig/net/d80211/ieee80211_ioctl.c +++ dscape/net/d80211/ieee80211_ioctl.c @@ -2471,6 +2471,16 @@ static int ieee80211_ioctl_prism2_param( case PRISM2_PARAM_SPECTRUM_MGMT: local->conf.spect_mgmt = value; break; + case PRISM2_PARAM_MGMT_IF: + if (value == 1) { + if (local->apdev == NULL) + ret = ieee80211_if_add_mgmt(local->mdev); + } else if (value == 0) { + if (local->apdev) + ieee80211_if_del_mgmt(local->mdev); + } else + ret = -EINVAL; + break; default: ret = -EOPNOTSUPP; break; @@ -2653,6 +2663,12 @@ static int ieee80211_ioctl_get_prism2_pa else *param = !!sdata->u.sta.wmm_enabled; break; + case PRISM2_PARAM_MGMT_IF: + if (local->apdev) + *param = local->apdev->ifindex; + else + ret = -ENOENT; + break; default: ret = -EOPNOTSUPP; - 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