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 <net/cfg80211.h>
14 #include "ieee80211_i.h"
17 static enum ieee80211_if_types
18 nl80211_type_to_mac80211_type(enum nl80211_iftype type
)
21 case NL80211_IFTYPE_UNSPECIFIED
:
22 return IEEE80211_IF_TYPE_STA
;
23 case NL80211_IFTYPE_ADHOC
:
24 return IEEE80211_IF_TYPE_IBSS
;
25 case NL80211_IFTYPE_STATION
:
26 return IEEE80211_IF_TYPE_STA
;
27 case NL80211_IFTYPE_MONITOR
:
28 return IEEE80211_IF_TYPE_MNTR
;
30 return IEEE80211_IF_TYPE_INVALID
;
34 static int ieee80211_add_iface(struct wiphy
*wiphy
, char *name
,
35 enum nl80211_iftype type
)
37 struct ieee80211_local
*local
= wiphy_priv(wiphy
);
38 enum ieee80211_if_types itype
;
40 if (unlikely(local
->reg_state
!= IEEE80211_DEV_REGISTERED
))
43 itype
= nl80211_type_to_mac80211_type(type
);
44 if (itype
== IEEE80211_IF_TYPE_INVALID
)
47 return ieee80211_if_add(local
->mdev
, name
, NULL
, itype
);
50 static int ieee80211_del_iface(struct wiphy
*wiphy
, int ifindex
)
52 struct ieee80211_local
*local
= wiphy_priv(wiphy
);
53 struct net_device
*dev
;
56 if (unlikely(local
->reg_state
!= IEEE80211_DEV_REGISTERED
))
59 /* we're under RTNL */
60 dev
= __dev_get_by_index(&init_net
, ifindex
);
66 return ieee80211_if_remove(local
->mdev
, name
, -1);
69 static int ieee80211_change_iface(struct wiphy
*wiphy
, int ifindex
,
70 enum nl80211_iftype type
)
72 struct ieee80211_local
*local
= wiphy_priv(wiphy
);
73 struct net_device
*dev
;
74 enum ieee80211_if_types itype
;
75 struct ieee80211_sub_if_data
*sdata
;
77 if (unlikely(local
->reg_state
!= IEEE80211_DEV_REGISTERED
))
80 /* we're under RTNL */
81 dev
= __dev_get_by_index(&init_net
, ifindex
);
85 if (netif_running(dev
))
88 itype
= nl80211_type_to_mac80211_type(type
);
89 if (itype
== IEEE80211_IF_TYPE_INVALID
)
92 sdata
= IEEE80211_DEV_TO_SUB_IF(dev
);
94 if (sdata
->type
== IEEE80211_IF_TYPE_VLAN
)
97 ieee80211_if_reinit(dev
);
98 ieee80211_if_set_type(dev
, itype
);
103 static int ieee80211_add_key(struct wiphy
*wiphy
, struct net_device
*dev
,
104 u8 key_idx
, u8
*mac_addr
,
105 struct key_params
*params
)
107 struct ieee80211_sub_if_data
*sdata
;
108 struct sta_info
*sta
= NULL
;
109 enum ieee80211_key_alg alg
;
112 sdata
= IEEE80211_DEV_TO_SUB_IF(dev
);
114 switch (params
->cipher
) {
115 case WLAN_CIPHER_SUITE_WEP40
:
116 case WLAN_CIPHER_SUITE_WEP104
:
119 case WLAN_CIPHER_SUITE_TKIP
:
122 case WLAN_CIPHER_SUITE_CCMP
:
130 sta
= sta_info_get(sdata
->local
, mac_addr
);
136 if (!ieee80211_key_alloc(sdata
, sta
, alg
, key_idx
,
137 params
->key_len
, params
->key
))
146 static int ieee80211_del_key(struct wiphy
*wiphy
, struct net_device
*dev
,
147 u8 key_idx
, u8
*mac_addr
)
149 struct ieee80211_sub_if_data
*sdata
;
150 struct sta_info
*sta
;
153 sdata
= IEEE80211_DEV_TO_SUB_IF(dev
);
156 sta
= sta_info_get(sdata
->local
, mac_addr
);
162 ieee80211_key_free(sta
->key
);
170 if (!sdata
->keys
[key_idx
])
173 ieee80211_key_free(sdata
->keys
[key_idx
]);
178 static int ieee80211_get_key(struct wiphy
*wiphy
, struct net_device
*dev
,
179 u8 key_idx
, u8
*mac_addr
, void *cookie
,
180 void (*callback
)(void *cookie
,
181 struct key_params
*params
))
183 struct ieee80211_sub_if_data
*sdata
= IEEE80211_DEV_TO_SUB_IF(dev
);
184 struct sta_info
*sta
= NULL
;
186 struct key_params params
;
187 struct ieee80211_key
*key
;
193 sta
= sta_info_get(sdata
->local
, mac_addr
);
199 key
= sdata
->keys
[key_idx
];
204 memset(¶ms
, 0, sizeof(params
));
206 switch (key
->conf
.alg
) {
208 params
.cipher
= WLAN_CIPHER_SUITE_TKIP
;
210 iv32
= key
->u
.tkip
.iv32
;
211 iv16
= key
->u
.tkip
.iv16
;
213 if (key
->flags
& KEY_FLAG_UPLOADED_TO_HARDWARE
&&
214 sdata
->local
->ops
->get_tkip_seq
)
215 sdata
->local
->ops
->get_tkip_seq(
216 local_to_hw(sdata
->local
),
217 key
->conf
.hw_key_idx
,
220 seq
[0] = iv16
& 0xff;
221 seq
[1] = (iv16
>> 8) & 0xff;
222 seq
[2] = iv32
& 0xff;
223 seq
[3] = (iv32
>> 8) & 0xff;
224 seq
[4] = (iv32
>> 16) & 0xff;
225 seq
[5] = (iv32
>> 24) & 0xff;
230 params
.cipher
= WLAN_CIPHER_SUITE_CCMP
;
231 seq
[0] = key
->u
.ccmp
.tx_pn
[5];
232 seq
[1] = key
->u
.ccmp
.tx_pn
[4];
233 seq
[2] = key
->u
.ccmp
.tx_pn
[3];
234 seq
[3] = key
->u
.ccmp
.tx_pn
[2];
235 seq
[4] = key
->u
.ccmp
.tx_pn
[1];
236 seq
[5] = key
->u
.ccmp
.tx_pn
[0];
241 if (key
->conf
.keylen
== 5)
242 params
.cipher
= WLAN_CIPHER_SUITE_WEP40
;
244 params
.cipher
= WLAN_CIPHER_SUITE_WEP104
;
248 params
.key
= key
->conf
.key
;
249 params
.key_len
= key
->conf
.keylen
;
251 callback(cookie
, ¶ms
);
260 static int ieee80211_config_default_key(struct wiphy
*wiphy
,
261 struct net_device
*dev
,
264 struct ieee80211_sub_if_data
*sdata
;
266 sdata
= IEEE80211_DEV_TO_SUB_IF(dev
);
267 ieee80211_set_default_key(sdata
, key_idx
);
272 static int ieee80211_get_station(struct wiphy
*wiphy
, struct net_device
*dev
,
273 u8
*mac
, struct station_stats
*stats
)
275 struct ieee80211_local
*local
= wdev_priv(dev
->ieee80211_ptr
);
276 struct sta_info
*sta
;
278 sta
= sta_info_get(local
, mac
);
282 /* XXX: verify sta->dev == dev */
284 stats
->filled
= STATION_STAT_INACTIVE_TIME
|
285 STATION_STAT_RX_BYTES
|
286 STATION_STAT_TX_BYTES
;
288 stats
->inactive_time
= jiffies_to_msecs(jiffies
- sta
->last_rx
);
289 stats
->rx_bytes
= sta
->rx_bytes
;
290 stats
->tx_bytes
= sta
->tx_bytes
;
297 struct cfg80211_ops mac80211_config_ops
= {
298 .add_virtual_intf
= ieee80211_add_iface
,
299 .del_virtual_intf
= ieee80211_del_iface
,
300 .change_virtual_intf
= ieee80211_change_iface
,
301 .add_key
= ieee80211_add_key
,
302 .del_key
= ieee80211_del_key
,
303 .get_key
= ieee80211_get_key
,
304 .set_default_key
= ieee80211_config_default_key
,
305 .get_station
= ieee80211_get_station
,