cfg.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  1. /*
  2. * mac80211 configuration hooks for cfg80211
  3. *
  4. * Copyright 2006, 2007 Johannes Berg <johannes@sipsolutions.net>
  5. *
  6. * This file is GPLv2 as found in COPYING.
  7. */
  8. #include <linux/ieee80211.h>
  9. #include <linux/nl80211.h>
  10. #include <linux/rtnetlink.h>
  11. #include <net/net_namespace.h>
  12. #include <linux/rcupdate.h>
  13. #include <net/cfg80211.h>
  14. #include "ieee80211_i.h"
  15. #include "cfg.h"
  16. static enum ieee80211_if_types
  17. nl80211_type_to_mac80211_type(enum nl80211_iftype type)
  18. {
  19. switch (type) {
  20. case NL80211_IFTYPE_UNSPECIFIED:
  21. return IEEE80211_IF_TYPE_STA;
  22. case NL80211_IFTYPE_ADHOC:
  23. return IEEE80211_IF_TYPE_IBSS;
  24. case NL80211_IFTYPE_STATION:
  25. return IEEE80211_IF_TYPE_STA;
  26. case NL80211_IFTYPE_MONITOR:
  27. return IEEE80211_IF_TYPE_MNTR;
  28. default:
  29. return IEEE80211_IF_TYPE_INVALID;
  30. }
  31. }
  32. static int ieee80211_add_iface(struct wiphy *wiphy, char *name,
  33. enum nl80211_iftype type)
  34. {
  35. struct ieee80211_local *local = wiphy_priv(wiphy);
  36. enum ieee80211_if_types itype;
  37. if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED))
  38. return -ENODEV;
  39. itype = nl80211_type_to_mac80211_type(type);
  40. if (itype == IEEE80211_IF_TYPE_INVALID)
  41. return -EINVAL;
  42. return ieee80211_if_add(local->mdev, name, NULL, itype);
  43. }
  44. static int ieee80211_del_iface(struct wiphy *wiphy, int ifindex)
  45. {
  46. struct ieee80211_local *local = wiphy_priv(wiphy);
  47. struct net_device *dev;
  48. char *name;
  49. if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED))
  50. return -ENODEV;
  51. /* we're under RTNL */
  52. dev = __dev_get_by_index(&init_net, ifindex);
  53. if (!dev)
  54. return 0;
  55. name = dev->name;
  56. return ieee80211_if_remove(local->mdev, name, -1);
  57. }
  58. static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex,
  59. enum nl80211_iftype type)
  60. {
  61. struct ieee80211_local *local = wiphy_priv(wiphy);
  62. struct net_device *dev;
  63. enum ieee80211_if_types itype;
  64. struct ieee80211_sub_if_data *sdata;
  65. if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED))
  66. return -ENODEV;
  67. /* we're under RTNL */
  68. dev = __dev_get_by_index(&init_net, ifindex);
  69. if (!dev)
  70. return -ENODEV;
  71. if (netif_running(dev))
  72. return -EBUSY;
  73. itype = nl80211_type_to_mac80211_type(type);
  74. if (itype == IEEE80211_IF_TYPE_INVALID)
  75. return -EINVAL;
  76. sdata = IEEE80211_DEV_TO_SUB_IF(dev);
  77. if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN)
  78. return -EOPNOTSUPP;
  79. ieee80211_if_reinit(dev);
  80. ieee80211_if_set_type(dev, itype);
  81. return 0;
  82. }
  83. static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
  84. u8 key_idx, u8 *mac_addr,
  85. struct key_params *params)
  86. {
  87. struct ieee80211_sub_if_data *sdata;
  88. struct sta_info *sta = NULL;
  89. enum ieee80211_key_alg alg;
  90. int ret;
  91. sdata = IEEE80211_DEV_TO_SUB_IF(dev);
  92. switch (params->cipher) {
  93. case WLAN_CIPHER_SUITE_WEP40:
  94. case WLAN_CIPHER_SUITE_WEP104:
  95. alg = ALG_WEP;
  96. break;
  97. case WLAN_CIPHER_SUITE_TKIP:
  98. alg = ALG_TKIP;
  99. break;
  100. case WLAN_CIPHER_SUITE_CCMP:
  101. alg = ALG_CCMP;
  102. break;
  103. default:
  104. return -EINVAL;
  105. }
  106. if (mac_addr) {
  107. sta = sta_info_get(sdata->local, mac_addr);
  108. if (!sta)
  109. return -ENOENT;
  110. }
  111. ret = 0;
  112. if (!ieee80211_key_alloc(sdata, sta, alg, key_idx,
  113. params->key_len, params->key))
  114. ret = -ENOMEM;
  115. if (sta)
  116. sta_info_put(sta);
  117. return ret;
  118. }
  119. static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
  120. u8 key_idx, u8 *mac_addr)
  121. {
  122. struct ieee80211_sub_if_data *sdata;
  123. struct sta_info *sta;
  124. int ret;
  125. sdata = IEEE80211_DEV_TO_SUB_IF(dev);
  126. if (mac_addr) {
  127. sta = sta_info_get(sdata->local, mac_addr);
  128. if (!sta)
  129. return -ENOENT;
  130. ret = 0;
  131. if (sta->key)
  132. ieee80211_key_free(sta->key);
  133. else
  134. ret = -ENOENT;
  135. sta_info_put(sta);
  136. return ret;
  137. }
  138. if (!sdata->keys[key_idx])
  139. return -ENOENT;
  140. ieee80211_key_free(sdata->keys[key_idx]);
  141. return 0;
  142. }
  143. static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
  144. u8 key_idx, u8 *mac_addr, void *cookie,
  145. void (*callback)(void *cookie,
  146. struct key_params *params))
  147. {
  148. struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
  149. struct sta_info *sta = NULL;
  150. u8 seq[6] = {0};
  151. struct key_params params;
  152. struct ieee80211_key *key;
  153. u32 iv32;
  154. u16 iv16;
  155. int err = -ENOENT;
  156. if (mac_addr) {
  157. sta = sta_info_get(sdata->local, mac_addr);
  158. if (!sta)
  159. goto out;
  160. key = sta->key;
  161. } else
  162. key = sdata->keys[key_idx];
  163. if (!key)
  164. goto out;
  165. memset(&params, 0, sizeof(params));
  166. switch (key->conf.alg) {
  167. case ALG_TKIP:
  168. params.cipher = WLAN_CIPHER_SUITE_TKIP;
  169. iv32 = key->u.tkip.iv32;
  170. iv16 = key->u.tkip.iv16;
  171. if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE &&
  172. sdata->local->ops->get_tkip_seq)
  173. sdata->local->ops->get_tkip_seq(
  174. local_to_hw(sdata->local),
  175. key->conf.hw_key_idx,
  176. &iv32, &iv16);
  177. seq[0] = iv16 & 0xff;
  178. seq[1] = (iv16 >> 8) & 0xff;
  179. seq[2] = iv32 & 0xff;
  180. seq[3] = (iv32 >> 8) & 0xff;
  181. seq[4] = (iv32 >> 16) & 0xff;
  182. seq[5] = (iv32 >> 24) & 0xff;
  183. params.seq = seq;
  184. params.seq_len = 6;
  185. break;
  186. case ALG_CCMP:
  187. params.cipher = WLAN_CIPHER_SUITE_CCMP;
  188. seq[0] = key->u.ccmp.tx_pn[5];
  189. seq[1] = key->u.ccmp.tx_pn[4];
  190. seq[2] = key->u.ccmp.tx_pn[3];
  191. seq[3] = key->u.ccmp.tx_pn[2];
  192. seq[4] = key->u.ccmp.tx_pn[1];
  193. seq[5] = key->u.ccmp.tx_pn[0];
  194. params.seq = seq;
  195. params.seq_len = 6;
  196. break;
  197. case ALG_WEP:
  198. if (key->conf.keylen == 5)
  199. params.cipher = WLAN_CIPHER_SUITE_WEP40;
  200. else
  201. params.cipher = WLAN_CIPHER_SUITE_WEP104;
  202. break;
  203. }
  204. params.key = key->conf.key;
  205. params.key_len = key->conf.keylen;
  206. callback(cookie, &params);
  207. err = 0;
  208. out:
  209. if (sta)
  210. sta_info_put(sta);
  211. return err;
  212. }
  213. static int ieee80211_config_default_key(struct wiphy *wiphy,
  214. struct net_device *dev,
  215. u8 key_idx)
  216. {
  217. struct ieee80211_sub_if_data *sdata;
  218. sdata = IEEE80211_DEV_TO_SUB_IF(dev);
  219. ieee80211_set_default_key(sdata, key_idx);
  220. return 0;
  221. }
  222. static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev,
  223. u8 *mac, struct station_stats *stats)
  224. {
  225. struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
  226. struct sta_info *sta;
  227. sta = sta_info_get(local, mac);
  228. if (!sta)
  229. return -ENOENT;
  230. /* XXX: verify sta->dev == dev */
  231. stats->filled = STATION_STAT_INACTIVE_TIME |
  232. STATION_STAT_RX_BYTES |
  233. STATION_STAT_TX_BYTES;
  234. stats->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
  235. stats->rx_bytes = sta->rx_bytes;
  236. stats->tx_bytes = sta->tx_bytes;
  237. sta_info_put(sta);
  238. return 0;
  239. }
  240. /*
  241. * This handles both adding a beacon and setting new beacon info
  242. */
  243. static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata,
  244. struct beacon_parameters *params)
  245. {
  246. struct beacon_data *new, *old;
  247. int new_head_len, new_tail_len;
  248. int size;
  249. int err = -EINVAL;
  250. old = sdata->u.ap.beacon;
  251. /* head must not be zero-length */
  252. if (params->head && !params->head_len)
  253. return -EINVAL;
  254. /*
  255. * This is a kludge. beacon interval should really be part
  256. * of the beacon information.
  257. */
  258. if (params->interval) {
  259. sdata->local->hw.conf.beacon_int = params->interval;
  260. if (ieee80211_hw_config(sdata->local))
  261. return -EINVAL;
  262. /*
  263. * We updated some parameter so if below bails out
  264. * it's not an error.
  265. */
  266. err = 0;
  267. }
  268. /* Need to have a beacon head if we don't have one yet */
  269. if (!params->head && !old)
  270. return err;
  271. /* sorry, no way to start beaconing without dtim period */
  272. if (!params->dtim_period && !old)
  273. return err;
  274. /* new or old head? */
  275. if (params->head)
  276. new_head_len = params->head_len;
  277. else
  278. new_head_len = old->head_len;
  279. /* new or old tail? */
  280. if (params->tail || !old)
  281. /* params->tail_len will be zero for !params->tail */
  282. new_tail_len = params->tail_len;
  283. else
  284. new_tail_len = old->tail_len;
  285. size = sizeof(*new) + new_head_len + new_tail_len;
  286. new = kzalloc(size, GFP_KERNEL);
  287. if (!new)
  288. return -ENOMEM;
  289. /* start filling the new info now */
  290. /* new or old dtim period? */
  291. if (params->dtim_period)
  292. new->dtim_period = params->dtim_period;
  293. else
  294. new->dtim_period = old->dtim_period;
  295. /*
  296. * pointers go into the block we allocated,
  297. * memory is | beacon_data | head | tail |
  298. */
  299. new->head = ((u8 *) new) + sizeof(*new);
  300. new->tail = new->head + new_head_len;
  301. new->head_len = new_head_len;
  302. new->tail_len = new_tail_len;
  303. /* copy in head */
  304. if (params->head)
  305. memcpy(new->head, params->head, new_head_len);
  306. else
  307. memcpy(new->head, old->head, new_head_len);
  308. /* copy in optional tail */
  309. if (params->tail)
  310. memcpy(new->tail, params->tail, new_tail_len);
  311. else
  312. if (old)
  313. memcpy(new->tail, old->tail, new_tail_len);
  314. rcu_assign_pointer(sdata->u.ap.beacon, new);
  315. synchronize_rcu();
  316. kfree(old);
  317. return ieee80211_if_config_beacon(sdata->dev);
  318. }
  319. static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev,
  320. struct beacon_parameters *params)
  321. {
  322. struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
  323. struct beacon_data *old;
  324. if (sdata->vif.type != IEEE80211_IF_TYPE_AP)
  325. return -EINVAL;
  326. old = sdata->u.ap.beacon;
  327. if (old)
  328. return -EALREADY;
  329. return ieee80211_config_beacon(sdata, params);
  330. }
  331. static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev,
  332. struct beacon_parameters *params)
  333. {
  334. struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
  335. struct beacon_data *old;
  336. if (sdata->vif.type != IEEE80211_IF_TYPE_AP)
  337. return -EINVAL;
  338. old = sdata->u.ap.beacon;
  339. if (!old)
  340. return -ENOENT;
  341. return ieee80211_config_beacon(sdata, params);
  342. }
  343. static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev)
  344. {
  345. struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
  346. struct beacon_data *old;
  347. if (sdata->vif.type != IEEE80211_IF_TYPE_AP)
  348. return -EINVAL;
  349. old = sdata->u.ap.beacon;
  350. if (!old)
  351. return -ENOENT;
  352. rcu_assign_pointer(sdata->u.ap.beacon, NULL);
  353. synchronize_rcu();
  354. kfree(old);
  355. return ieee80211_if_config_beacon(dev);
  356. }
  357. struct cfg80211_ops mac80211_config_ops = {
  358. .add_virtual_intf = ieee80211_add_iface,
  359. .del_virtual_intf = ieee80211_del_iface,
  360. .change_virtual_intf = ieee80211_change_iface,
  361. .add_key = ieee80211_add_key,
  362. .del_key = ieee80211_del_key,
  363. .get_key = ieee80211_get_key,
  364. .set_default_key = ieee80211_config_default_key,
  365. .add_beacon = ieee80211_add_beacon,
  366. .set_beacon = ieee80211_set_beacon,
  367. .del_beacon = ieee80211_del_beacon,
  368. .get_station = ieee80211_get_station,
  369. };