cfg.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  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 <net/cfg80211.h>
  13. #include "ieee80211_i.h"
  14. #include "cfg.h"
  15. static enum ieee80211_if_types
  16. nl80211_type_to_mac80211_type(enum nl80211_iftype type)
  17. {
  18. switch (type) {
  19. case NL80211_IFTYPE_UNSPECIFIED:
  20. return IEEE80211_IF_TYPE_STA;
  21. case NL80211_IFTYPE_ADHOC:
  22. return IEEE80211_IF_TYPE_IBSS;
  23. case NL80211_IFTYPE_STATION:
  24. return IEEE80211_IF_TYPE_STA;
  25. case NL80211_IFTYPE_MONITOR:
  26. return IEEE80211_IF_TYPE_MNTR;
  27. default:
  28. return IEEE80211_IF_TYPE_INVALID;
  29. }
  30. }
  31. static int ieee80211_add_iface(struct wiphy *wiphy, char *name,
  32. enum nl80211_iftype type)
  33. {
  34. struct ieee80211_local *local = wiphy_priv(wiphy);
  35. enum ieee80211_if_types itype;
  36. if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED))
  37. return -ENODEV;
  38. itype = nl80211_type_to_mac80211_type(type);
  39. if (itype == IEEE80211_IF_TYPE_INVALID)
  40. return -EINVAL;
  41. return ieee80211_if_add(local->mdev, name, NULL, itype);
  42. }
  43. static int ieee80211_del_iface(struct wiphy *wiphy, int ifindex)
  44. {
  45. struct ieee80211_local *local = wiphy_priv(wiphy);
  46. struct net_device *dev;
  47. char *name;
  48. if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED))
  49. return -ENODEV;
  50. /* we're under RTNL */
  51. dev = __dev_get_by_index(&init_net, ifindex);
  52. if (!dev)
  53. return 0;
  54. name = dev->name;
  55. return ieee80211_if_remove(local->mdev, name, -1);
  56. }
  57. static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex,
  58. enum nl80211_iftype type)
  59. {
  60. struct ieee80211_local *local = wiphy_priv(wiphy);
  61. struct net_device *dev;
  62. enum ieee80211_if_types itype;
  63. struct ieee80211_sub_if_data *sdata;
  64. if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED))
  65. return -ENODEV;
  66. /* we're under RTNL */
  67. dev = __dev_get_by_index(&init_net, ifindex);
  68. if (!dev)
  69. return -ENODEV;
  70. if (netif_running(dev))
  71. return -EBUSY;
  72. itype = nl80211_type_to_mac80211_type(type);
  73. if (itype == IEEE80211_IF_TYPE_INVALID)
  74. return -EINVAL;
  75. sdata = IEEE80211_DEV_TO_SUB_IF(dev);
  76. if (sdata->type == IEEE80211_IF_TYPE_VLAN)
  77. return -EOPNOTSUPP;
  78. ieee80211_if_reinit(dev);
  79. ieee80211_if_set_type(dev, itype);
  80. return 0;
  81. }
  82. static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
  83. u8 key_idx, u8 *mac_addr,
  84. struct key_params *params)
  85. {
  86. struct ieee80211_sub_if_data *sdata;
  87. struct sta_info *sta = NULL;
  88. enum ieee80211_key_alg alg;
  89. int ret;
  90. sdata = IEEE80211_DEV_TO_SUB_IF(dev);
  91. switch (params->cipher) {
  92. case WLAN_CIPHER_SUITE_WEP40:
  93. case WLAN_CIPHER_SUITE_WEP104:
  94. alg = ALG_WEP;
  95. break;
  96. case WLAN_CIPHER_SUITE_TKIP:
  97. alg = ALG_TKIP;
  98. break;
  99. case WLAN_CIPHER_SUITE_CCMP:
  100. alg = ALG_CCMP;
  101. break;
  102. default:
  103. return -EINVAL;
  104. }
  105. if (mac_addr) {
  106. sta = sta_info_get(sdata->local, mac_addr);
  107. if (!sta)
  108. return -ENOENT;
  109. }
  110. ret = 0;
  111. if (!ieee80211_key_alloc(sdata, sta, alg, key_idx,
  112. params->key_len, params->key))
  113. ret = -ENOMEM;
  114. if (sta)
  115. sta_info_put(sta);
  116. return ret;
  117. }
  118. static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
  119. u8 key_idx, u8 *mac_addr)
  120. {
  121. struct ieee80211_sub_if_data *sdata;
  122. struct sta_info *sta;
  123. int ret;
  124. sdata = IEEE80211_DEV_TO_SUB_IF(dev);
  125. if (mac_addr) {
  126. sta = sta_info_get(sdata->local, mac_addr);
  127. if (!sta)
  128. return -ENOENT;
  129. ret = 0;
  130. if (sta->key)
  131. ieee80211_key_free(sta->key);
  132. else
  133. ret = -ENOENT;
  134. sta_info_put(sta);
  135. return ret;
  136. }
  137. if (!sdata->keys[key_idx])
  138. return -ENOENT;
  139. ieee80211_key_free(sdata->keys[key_idx]);
  140. return 0;
  141. }
  142. static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
  143. u8 key_idx, u8 *mac_addr, void *cookie,
  144. void (*callback)(void *cookie,
  145. struct key_params *params))
  146. {
  147. struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
  148. struct sta_info *sta = NULL;
  149. u8 seq[6] = {0};
  150. struct key_params params;
  151. struct ieee80211_key *key;
  152. u32 iv32;
  153. u16 iv16;
  154. int err = -ENOENT;
  155. if (mac_addr) {
  156. sta = sta_info_get(sdata->local, mac_addr);
  157. if (!sta)
  158. goto out;
  159. key = sta->key;
  160. } else
  161. key = sdata->keys[key_idx];
  162. if (!key)
  163. goto out;
  164. memset(&params, 0, sizeof(params));
  165. switch (key->conf.alg) {
  166. case ALG_TKIP:
  167. params.cipher = WLAN_CIPHER_SUITE_TKIP;
  168. iv32 = key->u.tkip.iv32;
  169. iv16 = key->u.tkip.iv16;
  170. if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE &&
  171. sdata->local->ops->get_tkip_seq)
  172. sdata->local->ops->get_tkip_seq(
  173. local_to_hw(sdata->local),
  174. key->conf.hw_key_idx,
  175. &iv32, &iv16);
  176. seq[0] = iv16 & 0xff;
  177. seq[1] = (iv16 >> 8) & 0xff;
  178. seq[2] = iv32 & 0xff;
  179. seq[3] = (iv32 >> 8) & 0xff;
  180. seq[4] = (iv32 >> 16) & 0xff;
  181. seq[5] = (iv32 >> 24) & 0xff;
  182. params.seq = seq;
  183. params.seq_len = 6;
  184. break;
  185. case ALG_CCMP:
  186. params.cipher = WLAN_CIPHER_SUITE_CCMP;
  187. seq[0] = key->u.ccmp.tx_pn[5];
  188. seq[1] = key->u.ccmp.tx_pn[4];
  189. seq[2] = key->u.ccmp.tx_pn[3];
  190. seq[3] = key->u.ccmp.tx_pn[2];
  191. seq[4] = key->u.ccmp.tx_pn[1];
  192. seq[5] = key->u.ccmp.tx_pn[0];
  193. params.seq = seq;
  194. params.seq_len = 6;
  195. break;
  196. case ALG_WEP:
  197. if (key->conf.keylen == 5)
  198. params.cipher = WLAN_CIPHER_SUITE_WEP40;
  199. else
  200. params.cipher = WLAN_CIPHER_SUITE_WEP104;
  201. break;
  202. }
  203. params.key = key->conf.key;
  204. params.key_len = key->conf.keylen;
  205. callback(cookie, &params);
  206. err = 0;
  207. out:
  208. if (sta)
  209. sta_info_put(sta);
  210. return err;
  211. }
  212. static int ieee80211_config_default_key(struct wiphy *wiphy,
  213. struct net_device *dev,
  214. u8 key_idx)
  215. {
  216. struct ieee80211_sub_if_data *sdata;
  217. sdata = IEEE80211_DEV_TO_SUB_IF(dev);
  218. ieee80211_set_default_key(sdata, key_idx);
  219. return 0;
  220. }
  221. static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev,
  222. u8 *mac, struct station_stats *stats)
  223. {
  224. struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
  225. struct sta_info *sta;
  226. sta = sta_info_get(local, mac);
  227. if (!sta)
  228. return -ENOENT;
  229. /* XXX: verify sta->dev == dev */
  230. stats->filled = STATION_STAT_INACTIVE_TIME |
  231. STATION_STAT_RX_BYTES |
  232. STATION_STAT_TX_BYTES;
  233. stats->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
  234. stats->rx_bytes = sta->rx_bytes;
  235. stats->tx_bytes = sta->tx_bytes;
  236. sta_info_put(sta);
  237. return 0;
  238. }
  239. struct cfg80211_ops mac80211_config_ops = {
  240. .add_virtual_intf = ieee80211_add_iface,
  241. .del_virtual_intf = ieee80211_del_iface,
  242. .change_virtual_intf = ieee80211_change_iface,
  243. .add_key = ieee80211_add_key,
  244. .del_key = ieee80211_del_key,
  245. .get_key = ieee80211_get_key,
  246. .set_default_key = ieee80211_config_default_key,
  247. .get_station = ieee80211_get_station,
  248. };