2 * mac80211 configuration hooks for cfg80211
4 * Copyright 2006, 2007 Johannes Berg <johannes@sipsolutions.net>
6 * This file is GPLv2 as found in COPYING.
9 #include <linux/ieee80211.h>
10 #include <linux/nl80211.h>
11 #include <linux/rtnetlink.h>
12 #include <net/net_namespace.h>
13 #include <linux/rcupdate.h>
14 #include <net/cfg80211.h>
15 #include "ieee80211_i.h"
18 static enum ieee80211_if_types
19 nl80211_type_to_mac80211_type(enum nl80211_iftype type)
22 case NL80211_IFTYPE_UNSPECIFIED:
23 return IEEE80211_IF_TYPE_STA;
24 case NL80211_IFTYPE_ADHOC:
25 return IEEE80211_IF_TYPE_IBSS;
26 case NL80211_IFTYPE_STATION:
27 return IEEE80211_IF_TYPE_STA;
28 case NL80211_IFTYPE_MONITOR:
29 return IEEE80211_IF_TYPE_MNTR;
31 return IEEE80211_IF_TYPE_INVALID;
35 static int ieee80211_add_iface(struct wiphy *wiphy, char *name,
36 enum nl80211_iftype type)
38 struct ieee80211_local *local = wiphy_priv(wiphy);
39 enum ieee80211_if_types itype;
41 if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED))
44 itype = nl80211_type_to_mac80211_type(type);
45 if (itype == IEEE80211_IF_TYPE_INVALID)
48 return ieee80211_if_add(local->mdev, name, NULL, itype);
51 static int ieee80211_del_iface(struct wiphy *wiphy, int ifindex)
53 struct ieee80211_local *local = wiphy_priv(wiphy);
54 struct net_device *dev;
57 if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED))
60 /* we're under RTNL */
61 dev = __dev_get_by_index(&init_net, ifindex);
67 return ieee80211_if_remove(local->mdev, name, -1);
70 static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex,
71 enum nl80211_iftype type)
73 struct ieee80211_local *local = wiphy_priv(wiphy);
74 struct net_device *dev;
75 enum ieee80211_if_types itype;
76 struct ieee80211_sub_if_data *sdata;
78 if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED))
81 /* we're under RTNL */
82 dev = __dev_get_by_index(&init_net, ifindex);
86 if (netif_running(dev))
89 itype = nl80211_type_to_mac80211_type(type);
90 if (itype == IEEE80211_IF_TYPE_INVALID)
93 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
95 if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN)
98 ieee80211_if_reinit(dev);
99 ieee80211_if_set_type(dev, itype);
104 static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
105 u8 key_idx, u8 *mac_addr,
106 struct key_params *params)
108 struct ieee80211_sub_if_data *sdata;
109 struct sta_info *sta = NULL;
110 enum ieee80211_key_alg alg;
113 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
115 switch (params->cipher) {
116 case WLAN_CIPHER_SUITE_WEP40:
117 case WLAN_CIPHER_SUITE_WEP104:
120 case WLAN_CIPHER_SUITE_TKIP:
123 case WLAN_CIPHER_SUITE_CCMP:
131 sta = sta_info_get(sdata->local, mac_addr);
137 if (!ieee80211_key_alloc(sdata, sta, alg, key_idx,
138 params->key_len, params->key))
147 static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
148 u8 key_idx, u8 *mac_addr)
150 struct ieee80211_sub_if_data *sdata;
151 struct sta_info *sta;
154 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
157 sta = sta_info_get(sdata->local, mac_addr);
163 ieee80211_key_free(sta->key);
171 if (!sdata->keys[key_idx])
174 ieee80211_key_free(sdata->keys[key_idx]);
179 static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
180 u8 key_idx, u8 *mac_addr, void *cookie,
181 void (*callback)(void *cookie,
182 struct key_params *params))
184 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
185 struct sta_info *sta = NULL;
187 struct key_params params;
188 struct ieee80211_key *key;
194 sta = sta_info_get(sdata->local, mac_addr);
200 key = sdata->keys[key_idx];
205 memset(¶ms, 0, sizeof(params));
207 switch (key->conf.alg) {
209 params.cipher = WLAN_CIPHER_SUITE_TKIP;
211 iv32 = key->u.tkip.iv32;
212 iv16 = key->u.tkip.iv16;
214 if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE &&
215 sdata->local->ops->get_tkip_seq)
216 sdata->local->ops->get_tkip_seq(
217 local_to_hw(sdata->local),
218 key->conf.hw_key_idx,
221 seq[0] = iv16 & 0xff;
222 seq[1] = (iv16 >> 8) & 0xff;
223 seq[2] = iv32 & 0xff;
224 seq[3] = (iv32 >> 8) & 0xff;
225 seq[4] = (iv32 >> 16) & 0xff;
226 seq[5] = (iv32 >> 24) & 0xff;
231 params.cipher = WLAN_CIPHER_SUITE_CCMP;
232 seq[0] = key->u.ccmp.tx_pn[5];
233 seq[1] = key->u.ccmp.tx_pn[4];
234 seq[2] = key->u.ccmp.tx_pn[3];
235 seq[3] = key->u.ccmp.tx_pn[2];
236 seq[4] = key->u.ccmp.tx_pn[1];
237 seq[5] = key->u.ccmp.tx_pn[0];
242 if (key->conf.keylen == 5)
243 params.cipher = WLAN_CIPHER_SUITE_WEP40;
245 params.cipher = WLAN_CIPHER_SUITE_WEP104;
249 params.key = key->conf.key;
250 params.key_len = key->conf.keylen;
252 callback(cookie, ¶ms);
261 static int ieee80211_config_default_key(struct wiphy *wiphy,
262 struct net_device *dev,
265 struct ieee80211_sub_if_data *sdata;
267 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
268 ieee80211_set_default_key(sdata, key_idx);
273 static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev,
274 u8 *mac, struct station_stats *stats)
276 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
277 struct sta_info *sta;
279 sta = sta_info_get(local, mac);
283 /* XXX: verify sta->dev == dev */
285 stats->filled = STATION_STAT_INACTIVE_TIME |
286 STATION_STAT_RX_BYTES |
287 STATION_STAT_TX_BYTES;
289 stats->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
290 stats->rx_bytes = sta->rx_bytes;
291 stats->tx_bytes = sta->tx_bytes;
299 * This handles both adding a beacon and setting new beacon info
301 static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata,
302 struct beacon_parameters *params)
304 struct beacon_data *new, *old;
305 int new_head_len, new_tail_len;
309 old = sdata->u.ap.beacon;
311 /* head must not be zero-length */
312 if (params->head && !params->head_len)
316 * This is a kludge. beacon interval should really be part
317 * of the beacon information.
319 if (params->interval) {
320 sdata->local->hw.conf.beacon_int = params->interval;
321 if (ieee80211_hw_config(sdata->local))
324 * We updated some parameter so if below bails out
330 /* Need to have a beacon head if we don't have one yet */
331 if (!params->head && !old)
334 /* sorry, no way to start beaconing without dtim period */
335 if (!params->dtim_period && !old)
338 /* new or old head? */
340 new_head_len = params->head_len;
342 new_head_len = old->head_len;
344 /* new or old tail? */
345 if (params->tail || !old)
346 /* params->tail_len will be zero for !params->tail */
347 new_tail_len = params->tail_len;
349 new_tail_len = old->tail_len;
351 size = sizeof(*new) + new_head_len + new_tail_len;
353 new = kzalloc(size, GFP_KERNEL);
357 /* start filling the new info now */
359 /* new or old dtim period? */
360 if (params->dtim_period)
361 new->dtim_period = params->dtim_period;
363 new->dtim_period = old->dtim_period;
366 * pointers go into the block we allocated,
367 * memory is | beacon_data | head | tail |
369 new->head = ((u8 *) new) + sizeof(*new);
370 new->tail = new->head + new_head_len;
371 new->head_len = new_head_len;
372 new->tail_len = new_tail_len;
376 memcpy(new->head, params->head, new_head_len);
378 memcpy(new->head, old->head, new_head_len);
380 /* copy in optional tail */
382 memcpy(new->tail, params->tail, new_tail_len);
385 memcpy(new->tail, old->tail, new_tail_len);
387 rcu_assign_pointer(sdata->u.ap.beacon, new);
393 return ieee80211_if_config_beacon(sdata->dev);
396 static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev,
397 struct beacon_parameters *params)
399 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
400 struct beacon_data *old;
402 if (sdata->vif.type != IEEE80211_IF_TYPE_AP)
405 old = sdata->u.ap.beacon;
410 return ieee80211_config_beacon(sdata, params);
413 static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev,
414 struct beacon_parameters *params)
416 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
417 struct beacon_data *old;
419 if (sdata->vif.type != IEEE80211_IF_TYPE_AP)
422 old = sdata->u.ap.beacon;
427 return ieee80211_config_beacon(sdata, params);
430 static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev)
432 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
433 struct beacon_data *old;
435 if (sdata->vif.type != IEEE80211_IF_TYPE_AP)
438 old = sdata->u.ap.beacon;
443 rcu_assign_pointer(sdata->u.ap.beacon, NULL);
447 return ieee80211_if_config_beacon(dev);
450 struct cfg80211_ops mac80211_config_ops = {
451 .add_virtual_intf = ieee80211_add_iface,
452 .del_virtual_intf = ieee80211_del_iface,
453 .change_virtual_intf = ieee80211_change_iface,
454 .add_key = ieee80211_add_key,
455 .del_key = ieee80211_del_key,
456 .get_key = ieee80211_get_key,
457 .set_default_key = ieee80211_config_default_key,
458 .add_beacon = ieee80211_add_beacon,
459 .set_beacon = ieee80211_set_beacon,
460 .del_beacon = ieee80211_del_beacon,
461 .get_station = ieee80211_get_station,