]> git.ipfire.org Git - people/ms/linux.git/blame - net/mac80211/iface.c
mac80211: make master netdev handling sane
[people/ms/linux.git] / net / mac80211 / iface.c
CommitLineData
f0706e82
JB
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"
e9f207f0 17#include "debugfs_netdev.h"
ee385855 18#include "mesh.h"
f0706e82
JB
19
20void ieee80211_if_sdata_init(struct ieee80211_sub_if_data *sdata)
21{
22 int i;
23
24 /* Default values for sub-interface parameters */
25 sdata->drop_unencrypted = 0;
f0706e82
JB
26 for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++)
27 skb_queue_head_init(&sdata->fragments[i].skb_list);
11a843b7
JB
28
29 INIT_LIST_HEAD(&sdata->key_list);
3e122be0
JB
30
31 sdata->force_unicast_rateidx = -1;
32 sdata->max_ratectrl_rateidx = -1;
f0706e82
JB
33}
34
35static void ieee80211_if_sdata_deinit(struct ieee80211_sub_if_data *sdata)
36{
37 int i;
38
988c0f72 39 for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++)
f0706e82 40 __skb_queue_purge(&sdata->fragments[i].skb_list);
f0706e82
JB
41}
42
43/* Must be called with rtnl lock held. */
3e122be0 44int ieee80211_if_add(struct ieee80211_local *local, const char *name,
ee385855
LCC
45 struct net_device **new_dev, int type,
46 struct vif_params *params)
f0706e82
JB
47{
48 struct net_device *ndev;
f0706e82
JB
49 struct ieee80211_sub_if_data *sdata = NULL;
50 int ret;
51
52 ASSERT_RTNL();
32bfd35d 53 ndev = alloc_netdev(sizeof(*sdata) + local->hw.vif_data_size,
f0706e82
JB
54 name, ieee80211_if_setup);
55 if (!ndev)
56 return -ENOMEM;
57
f3994ece
JB
58 ndev->needed_headroom = local->tx_headroom +
59 4*6 /* four MAC addresses */
60 + 2 + 2 + 2 + 2 /* ctl, dur, seq, qos */
61 + 6 /* mesh */
62 + 8 /* rfc1042/bridge tunnel */
63 - ETH_HLEN /* ethernet hard_header_len */
64 + IEEE80211_ENCRYPT_HEADROOM;
65 ndev->needed_tailroom = IEEE80211_ENCRYPT_TAILROOM;
66
f0706e82
JB
67 ret = dev_alloc_name(ndev, ndev->name);
68 if (ret < 0)
69 goto fail;
70
71 memcpy(ndev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN);
f0706e82
JB
72 SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy));
73
3e122be0
JB
74 /* don't use IEEE80211_DEV_TO_SUB_IF because it checks too much */
75 sdata = netdev_priv(ndev);
f0706e82
JB
76 ndev->ieee80211_ptr = &sdata->wdev;
77 sdata->wdev.wiphy = local->hw.wiphy;
51fb61e7 78 sdata->vif.type = IEEE80211_IF_TYPE_AP;
f0706e82
JB
79 sdata->dev = ndev;
80 sdata->local = local;
81 ieee80211_if_sdata_init(sdata);
82
83 ret = register_netdevice(ndev);
84 if (ret)
85 goto fail;
86
e9f207f0 87 ieee80211_debugfs_add_netdev(sdata);
f0706e82
JB
88 ieee80211_if_set_type(ndev, type);
89
902acc78
JB
90 if (ieee80211_vif_is_mesh(&sdata->vif) &&
91 params && params->mesh_id_len)
92 ieee80211_if_sta_set_mesh_id(&sdata->u.sta,
93 params->mesh_id_len,
94 params->mesh_id);
ee385855 95
79010420 96 /* we're under RTNL so all this is fine */
f0706e82 97 if (unlikely(local->reg_state == IEEE80211_DEV_UNREGISTERED)) {
f0706e82
JB
98 __ieee80211_if_del(local, sdata);
99 return -ENODEV;
100 }
79010420
JB
101 list_add_tail_rcu(&sdata->list, &local->interfaces);
102
f0706e82
JB
103 if (new_dev)
104 *new_dev = ndev;
f0706e82 105
f0706e82
JB
106 return 0;
107
108fail:
109 free_netdev(ndev);
110 return ret;
111}
112
f0706e82
JB
113void ieee80211_if_set_type(struct net_device *dev, int type)
114{
115 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
51fb61e7 116 int oldtype = sdata->vif.type;
f0706e82 117
5b2812e9
JB
118 /*
119 * Called even when register_netdevice fails, it would
120 * oops if assigned before initialising the rest.
121 */
122 dev->uninit = ieee80211_if_reinit;
123
124 /* most have no BSS pointer */
125 sdata->bss = NULL;
51fb61e7 126 sdata->vif.type = type;
5b2812e9 127
8318d78a
JB
128 sdata->basic_rates = 0;
129
f0706e82
JB
130 switch (type) {
131 case IEEE80211_IF_TYPE_WDS:
f0706e82 132 case IEEE80211_IF_TYPE_VLAN:
3e122be0 133 /* nothing special */
f0706e82
JB
134 break;
135 case IEEE80211_IF_TYPE_AP:
f0706e82 136 skb_queue_head_init(&sdata->u.ap.ps_bc_buf);
0ec3ca44 137 INIT_LIST_HEAD(&sdata->u.ap.vlans);
f0706e82 138 break;
ee385855 139 case IEEE80211_IF_TYPE_MESH_POINT:
f0706e82
JB
140 case IEEE80211_IF_TYPE_STA:
141 case IEEE80211_IF_TYPE_IBSS: {
f0706e82
JB
142 struct ieee80211_if_sta *ifsta;
143
144 ifsta = &sdata->u.sta;
145 INIT_WORK(&ifsta->work, ieee80211_sta_work);
146 setup_timer(&ifsta->timer, ieee80211_sta_timer,
147 (unsigned long) sdata);
148 skb_queue_head_init(&ifsta->skb_queue);
149
150 ifsta->capab = WLAN_CAPABILITY_ESS;
151 ifsta->auth_algs = IEEE80211_AUTH_ALG_OPEN |
152 IEEE80211_AUTH_ALG_SHARED_KEY;
d6f2da5b 153 ifsta->flags |= IEEE80211_STA_CREATE_IBSS |
d6f2da5b
JS
154 IEEE80211_STA_AUTO_BSSID_SEL |
155 IEEE80211_STA_AUTO_CHANNEL_SEL;
e2530083 156 if (ieee80211_num_regular_queues(&sdata->local->hw) >= 4)
3434fbd3 157 ifsta->flags |= IEEE80211_STA_WMM_ENABLED;
f0706e82 158
902acc78
JB
159 if (ieee80211_vif_is_mesh(&sdata->vif))
160 ieee80211_mesh_init_sdata(sdata);
f0706e82
JB
161 break;
162 }
163 case IEEE80211_IF_TYPE_MNTR:
164 dev->type = ARPHRD_IEEE80211_RADIOTAP;
40f7cac9 165 dev->hard_start_xmit = ieee80211_monitor_start_xmit;
8cc9a739
MW
166 sdata->u.mntr_flags = MONITOR_FLAG_CONTROL |
167 MONITOR_FLAG_OTHER_BSS;
f0706e82 168 break;
f4ea83dd
JB
169 case IEEE80211_IF_TYPE_INVALID:
170 BUG();
171 break;
f0706e82 172 }
e9f207f0 173 ieee80211_debugfs_change_if_type(sdata, oldtype);
f0706e82
JB
174}
175
176/* Must be called with rtnl lock held. */
177void ieee80211_if_reinit(struct net_device *dev)
178{
179 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
180 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
5b2812e9 181 struct sk_buff *skb;
44213b5e 182 int flushed;
f0706e82
JB
183
184 ASSERT_RTNL();
11a843b7
JB
185
186 ieee80211_free_keys(sdata);
187
f0706e82 188 ieee80211_if_sdata_deinit(sdata);
f0706e82 189
902acc78
JB
190 /* Need to handle mesh specially to allow eliding the function call */
191 if (ieee80211_vif_is_mesh(&sdata->vif))
192 mesh_rmc_free(dev);
193
51fb61e7 194 switch (sdata->vif.type) {
a2897552
JB
195 case IEEE80211_IF_TYPE_INVALID:
196 /* cannot happen */
197 WARN_ON(1);
198 break;
f0706e82 199 case IEEE80211_IF_TYPE_AP: {
e6a5ddf2 200 struct beacon_data *beacon;
f0706e82 201
e6a5ddf2
JB
202 beacon = sdata->u.ap.beacon;
203 rcu_assign_pointer(sdata->u.ap.beacon, NULL);
204 synchronize_rcu();
205 kfree(beacon);
f0706e82 206
5b2812e9
JB
207 while ((skb = skb_dequeue(&sdata->u.ap.ps_bc_buf))) {
208 local->total_ps_buffered--;
209 dev_kfree_skb(skb);
f0706e82
JB
210 }
211
212 break;
213 }
214 case IEEE80211_IF_TYPE_WDS:
3e122be0 215 case IEEE80211_IF_TYPE_VLAN:
44213b5e 216 /* nothing to do */
f0706e82 217 break;
6032f934 218 case IEEE80211_IF_TYPE_MESH_POINT:
f0706e82
JB
219 case IEEE80211_IF_TYPE_STA:
220 case IEEE80211_IF_TYPE_IBSS:
221 kfree(sdata->u.sta.extra_ie);
222 sdata->u.sta.extra_ie = NULL;
223 kfree(sdata->u.sta.assocreq_ies);
224 sdata->u.sta.assocreq_ies = NULL;
225 kfree(sdata->u.sta.assocresp_ies);
226 sdata->u.sta.assocresp_ies = NULL;
227 if (sdata->u.sta.probe_resp) {
228 dev_kfree_skb(sdata->u.sta.probe_resp);
229 sdata->u.sta.probe_resp = NULL;
230 }
231
232 break;
233 case IEEE80211_IF_TYPE_MNTR:
234 dev->type = ARPHRD_ETHER;
235 break;
236 }
237
44213b5e
JB
238 flushed = sta_info_flush(local, sdata);
239 WARN_ON(flushed);
f0706e82
JB
240
241 memset(&sdata->u, 0, sizeof(sdata->u));
242 ieee80211_if_sdata_init(sdata);
243}
244
245/* Must be called with rtnl lock held. */
246void __ieee80211_if_del(struct ieee80211_local *local,
247 struct ieee80211_sub_if_data *sdata)
248{
249 struct net_device *dev = sdata->dev;
250
e9f207f0 251 ieee80211_debugfs_remove_netdev(sdata);
f0706e82 252 unregister_netdevice(dev);
3e122be0
JB
253 /*
254 * The net_device will be freed by its destructor,
255 * i.e. ieee80211_if_free.
256 */
f0706e82
JB
257}
258
259/* Must be called with rtnl lock held. */
260int ieee80211_if_remove(struct net_device *dev, const char *name, int id)
261{
262 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
263 struct ieee80211_sub_if_data *sdata, *n;
264
265 ASSERT_RTNL();
266
79010420 267 list_for_each_entry_safe(sdata, n, &local->interfaces, list) {
51fb61e7 268 if ((sdata->vif.type == id || id == -1) &&
3e122be0 269 strcmp(name, sdata->dev->name) == 0) {
79010420
JB
270 list_del_rcu(&sdata->list);
271 synchronize_rcu();
f0706e82 272 __ieee80211_if_del(local, sdata);
f0706e82
JB
273 return 0;
274 }
275 }
f0706e82
JB
276 return -ENODEV;
277}
278
279void ieee80211_if_free(struct net_device *dev)
280{
f0706e82
JB
281 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
282
f0706e82
JB
283 ieee80211_if_sdata_deinit(sdata);
284 free_netdev(dev);
285}