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