1/* 2 * Copyright 2002-2005, Instant802 Networks, Inc. 3 * Copyright 2005-2006, Devicescape Software, Inc. 4 * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 */ 10#include <linux/kernel.h> 11#include <linux/if_arp.h> 12#include <linux/netdevice.h> 13#include <linux/rtnetlink.h> 14#include <net/mac80211.h> 15#include "ieee80211_i.h" 16#include "sta_info.h" 17#include "debugfs_netdev.h" 18 19void ieee80211_if_sdata_init(struct ieee80211_sub_if_data *sdata) 20{ 21 int i; 22 23 /* Default values for sub-interface parameters */ 24 sdata->drop_unencrypted = 0; 25 sdata->eapol = 1; 26 for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) 27 skb_queue_head_init(&sdata->fragments[i].skb_list); 28} 29 30static void ieee80211_if_sdata_deinit(struct ieee80211_sub_if_data *sdata) 31{ 32 int i; 33 34 for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) { 35 __skb_queue_purge(&sdata->fragments[i].skb_list); 36 } 37} 38 39/* Must be called with rtnl lock held. */ 40int ieee80211_if_add(struct net_device *dev, const char *name, 41 struct net_device **new_dev, int type) 42{ 43 struct net_device *ndev; 44 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 45 struct ieee80211_sub_if_data *sdata = NULL; 46 int ret; 47 48 ASSERT_RTNL(); 49 ndev = alloc_netdev(sizeof(struct ieee80211_sub_if_data), 50 name, ieee80211_if_setup); 51 if (!ndev) 52 return -ENOMEM; 53 54 ret = dev_alloc_name(ndev, ndev->name); 55 if (ret < 0) 56 goto fail; 57 58 memcpy(ndev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN); 59 ndev->base_addr = dev->base_addr; 60 ndev->irq = dev->irq; 61 ndev->mem_start = dev->mem_start; 62 ndev->mem_end = dev->mem_end; 63 SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy)); 64 65 sdata = IEEE80211_DEV_TO_SUB_IF(ndev); 66 ndev->ieee80211_ptr = &sdata->wdev; 67 sdata->wdev.wiphy = local->hw.wiphy; 68 sdata->type = IEEE80211_IF_TYPE_AP; 69 sdata->dev = ndev; 70 sdata->local = local; 71 ieee80211_if_sdata_init(sdata); 72 73 ret = register_netdevice(ndev); 74 if (ret) 75 goto fail; 76 77 ieee80211_debugfs_add_netdev(sdata); 78 ieee80211_if_set_type(ndev, type); 79 80 write_lock_bh(&local->sub_if_lock); 81 if (unlikely(local->reg_state == IEEE80211_DEV_UNREGISTERED)) { 82 write_unlock_bh(&local->sub_if_lock); 83 __ieee80211_if_del(local, sdata); 84 return -ENODEV; 85 } 86 list_add(&sdata->list, &local->sub_if_list); 87 if (new_dev) 88 *new_dev = ndev; 89 write_unlock_bh(&local->sub_if_lock); 90 91 ieee80211_update_default_wep_only(local); 92 93 return 0; 94 95fail: 96 free_netdev(ndev); 97 return ret; 98} 99 100int ieee80211_if_add_mgmt(struct ieee80211_local *local) 101{ 102 struct net_device *ndev; 103 struct ieee80211_sub_if_data *nsdata; 104 int ret; 105 106 ASSERT_RTNL(); 107 108 ndev = alloc_netdev(sizeof(struct ieee80211_sub_if_data), "wmgmt%d", 109 ieee80211_if_mgmt_setup); 110 if (!ndev) 111 return -ENOMEM; 112 ret = dev_alloc_name(ndev, ndev->name); 113 if (ret < 0) 114 goto fail; 115 116 memcpy(ndev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN); 117 SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy)); 118 119 nsdata = IEEE80211_DEV_TO_SUB_IF(ndev); 120 ndev->ieee80211_ptr = &nsdata->wdev; 121 nsdata->wdev.wiphy = local->hw.wiphy; 122 nsdata->type = IEEE80211_IF_TYPE_MGMT; 123 nsdata->dev = ndev; 124 nsdata->local = local; 125 ieee80211_if_sdata_init(nsdata); 126 127 ret = register_netdevice(ndev); 128 if (ret) 129 goto fail; 130 131 ieee80211_debugfs_add_netdev(nsdata); 132 133 if (local->open_count > 0) 134 dev_open(ndev); 135 local->apdev = ndev; 136 return 0; 137 138fail: 139 free_netdev(ndev); 140 return ret; 141} 142 143void ieee80211_if_del_mgmt(struct ieee80211_local *local) 144{ 145 struct net_device *apdev; 146 147 ASSERT_RTNL(); 148 apdev = local->apdev; 149 ieee80211_debugfs_remove_netdev(IEEE80211_DEV_TO_SUB_IF(apdev)); 150 local->apdev = NULL; 151 unregister_netdevice(apdev); 152} 153 154void ieee80211_if_set_type(struct net_device *dev, int type) 155{ 156 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 157 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 158 int oldtype = sdata->type; 159 160 sdata->type = type; 161 switch (type) { 162 case IEEE80211_IF_TYPE_WDS: 163 sdata->bss = NULL; 164 break; 165 case IEEE80211_IF_TYPE_VLAN: 166 break; 167 case IEEE80211_IF_TYPE_AP: 168 sdata->u.ap.dtim_period = 2; 169 sdata->u.ap.force_unicast_rateidx = -1; 170 sdata->u.ap.max_ratectrl_rateidx = -1; 171 skb_queue_head_init(&sdata->u.ap.ps_bc_buf); 172 sdata->bss = &sdata->u.ap; 173 break; 174 case IEEE80211_IF_TYPE_STA: 175 case IEEE80211_IF_TYPE_IBSS: { 176 struct ieee80211_sub_if_data *msdata; 177 struct ieee80211_if_sta *ifsta; 178 179 ifsta = &sdata->u.sta; 180 INIT_WORK(&ifsta->work, ieee80211_sta_work); 181 setup_timer(&ifsta->timer, ieee80211_sta_timer, 182 (unsigned long) sdata); 183 skb_queue_head_init(&ifsta->skb_queue); 184 185 ifsta->capab = WLAN_CAPABILITY_ESS; 186 ifsta->auth_algs = IEEE80211_AUTH_ALG_OPEN | 187 IEEE80211_AUTH_ALG_SHARED_KEY; 188 ifsta->create_ibss = 1; 189 ifsta->wmm_enabled = 1; 190 ifsta->auto_channel_sel = 1; 191 ifsta->auto_bssid_sel = 1; 192 193 msdata = IEEE80211_DEV_TO_SUB_IF(sdata->local->mdev); 194 sdata->bss = &msdata->u.ap; 195 break; 196 } 197 case IEEE80211_IF_TYPE_MNTR: 198 dev->type = ARPHRD_IEEE80211_RADIOTAP; 199 break; 200 default: 201 printk(KERN_WARNING "%s: %s: Unknown interface type 0x%x", 202 dev->name, __FUNCTION__, type); 203 } 204 ieee80211_debugfs_change_if_type(sdata, oldtype); 205 ieee80211_update_default_wep_only(local); 206} 207 208/* Must be called with rtnl lock held. */ 209void ieee80211_if_reinit(struct net_device *dev) 210{ 211 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 212 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 213 struct sta_info *sta; 214 int i; 215 216 ASSERT_RTNL(); 217 ieee80211_if_sdata_deinit(sdata); 218 for (i = 0; i < NUM_DEFAULT_KEYS; i++) { 219 if (!sdata->keys[i]) 220 continue; 221 ieee80211_key_free(sdata->keys[i]); 222 sdata->keys[i] = NULL; 223 } 224 225 switch (sdata->type) { 226 case IEEE80211_IF_TYPE_AP: { 227 /* Remove all virtual interfaces that use this BSS 228 * as their sdata->bss */ 229 struct ieee80211_sub_if_data *tsdata, *n; 230 LIST_HEAD(tmp_list); 231 232 write_lock_bh(&local->sub_if_lock); 233 list_for_each_entry_safe(tsdata, n, &local->sub_if_list, list) { 234 if (tsdata != sdata && tsdata->bss == &sdata->u.ap) { 235 printk(KERN_DEBUG "%s: removing virtual " 236 "interface %s because its BSS interface" 237 " is being removed\n", 238 sdata->dev->name, tsdata->dev->name); 239 list_move_tail(&tsdata->list, &tmp_list); 240 } 241 } 242 write_unlock_bh(&local->sub_if_lock); 243 244 list_for_each_entry_safe(tsdata, n, &tmp_list, list) 245 __ieee80211_if_del(local, tsdata); 246 247 kfree(sdata->u.ap.beacon_head); 248 kfree(sdata->u.ap.beacon_tail); 249 kfree(sdata->u.ap.generic_elem); 250 251 if (dev != local->mdev) { 252 struct sk_buff *skb; 253 while ((skb = skb_dequeue(&sdata->u.ap.ps_bc_buf))) { 254 local->total_ps_buffered--; 255 dev_kfree_skb(skb); 256 } 257 } 258 259 break; 260 } 261 case IEEE80211_IF_TYPE_WDS: 262 sta = sta_info_get(local, sdata->u.wds.remote_addr); 263 if (sta) { 264 sta_info_put(sta); 265 sta_info_free(sta, 0); 266 } else { 267#ifdef CONFIG_MAC80211_VERBOSE_DEBUG 268 printk(KERN_DEBUG "%s: Someone had deleted my STA " 269 "entry for the WDS link\n", dev->name); 270#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ 271 } 272 break; 273 case IEEE80211_IF_TYPE_STA: 274 case IEEE80211_IF_TYPE_IBSS: 275 kfree(sdata->u.sta.extra_ie); 276 sdata->u.sta.extra_ie = NULL; 277 kfree(sdata->u.sta.assocreq_ies); 278 sdata->u.sta.assocreq_ies = NULL; 279 kfree(sdata->u.sta.assocresp_ies); 280 sdata->u.sta.assocresp_ies = NULL; 281 if (sdata->u.sta.probe_resp) { 282 dev_kfree_skb(sdata->u.sta.probe_resp); 283 sdata->u.sta.probe_resp = NULL; 284 } 285 286 break; 287 case IEEE80211_IF_TYPE_MNTR: 288 dev->type = ARPHRD_ETHER; 289 break; 290 } 291 292 /* remove all STAs that are bound to this virtual interface */ 293 sta_info_flush(local, dev); 294 295 memset(&sdata->u, 0, sizeof(sdata->u)); 296 ieee80211_if_sdata_init(sdata); 297} 298 299/* Must be called with rtnl lock held. */ 300void __ieee80211_if_del(struct ieee80211_local *local, 301 struct ieee80211_sub_if_data *sdata) 302{ 303 struct net_device *dev = sdata->dev; 304 305 ieee80211_debugfs_remove_netdev(sdata); 306 unregister_netdevice(dev); 307 /* Except master interface, the net_device will be freed by 308 * net_device->destructor (i. e. ieee80211_if_free). */ 309} 310 311/* Must be called with rtnl lock held. */ 312int ieee80211_if_remove(struct net_device *dev, const char *name, int id) 313{ 314 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 315 struct ieee80211_sub_if_data *sdata, *n; 316 317 ASSERT_RTNL(); 318 319 write_lock_bh(&local->sub_if_lock); 320 list_for_each_entry_safe(sdata, n, &local->sub_if_list, list) { 321 if ((sdata->type == id || id == -1) && 322 strcmp(name, sdata->dev->name) == 0 && 323 sdata->dev != local->mdev) { 324 list_del(&sdata->list); 325 write_unlock_bh(&local->sub_if_lock); 326 __ieee80211_if_del(local, sdata); 327 ieee80211_update_default_wep_only(local); 328 return 0; 329 } 330 } 331 write_unlock_bh(&local->sub_if_lock); 332 return -ENODEV; 333} 334 335void ieee80211_if_free(struct net_device *dev) 336{ 337 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 338 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 339 340 /* local->apdev must be NULL when freeing management interface */ 341 BUG_ON(dev == local->apdev); 342 ieee80211_if_sdata_deinit(sdata); 343 free_netdev(dev); 344} 345