wext.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. /*
  2. * Copyright 2002-2005, Instant802 Networks, Inc.
  3. * Copyright 2005-2006, Devicescape Software, Inc.
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. */
  9. #include <linux/module.h>
  10. #include <linux/init.h>
  11. #include <linux/netdevice.h>
  12. #include <linux/types.h>
  13. #include <linux/slab.h>
  14. #include <linux/skbuff.h>
  15. #include <linux/etherdevice.h>
  16. #include <linux/if_arp.h>
  17. #include <linux/wireless.h>
  18. #include <net/iw_handler.h>
  19. #include <asm/uaccess.h>
  20. #include <net/mac80211.h>
  21. #include "ieee80211_i.h"
  22. #include "led.h"
  23. #include "rate.h"
  24. #include "wpa.h"
  25. #include "aes_ccm.h"
  26. static int ieee80211_ioctl_siwfreq(struct net_device *dev,
  27. struct iw_request_info *info,
  28. struct iw_freq *freq, char *extra)
  29. {
  30. struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
  31. struct ieee80211_local *local = sdata->local;
  32. struct ieee80211_channel *chan;
  33. if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
  34. return cfg80211_ibss_wext_siwfreq(dev, info, freq, extra);
  35. else if (sdata->vif.type == NL80211_IFTYPE_STATION)
  36. return cfg80211_mgd_wext_siwfreq(dev, info, freq, extra);
  37. /* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */
  38. if (freq->e == 0) {
  39. if (freq->m < 0)
  40. return -EINVAL;
  41. else
  42. chan = ieee80211_get_channel(local->hw.wiphy,
  43. ieee80211_channel_to_frequency(freq->m));
  44. } else {
  45. int i, div = 1000000;
  46. for (i = 0; i < freq->e; i++)
  47. div /= 10;
  48. if (div <= 0)
  49. return -EINVAL;
  50. chan = ieee80211_get_channel(local->hw.wiphy, freq->m / div);
  51. }
  52. if (!chan)
  53. return -EINVAL;
  54. if (chan->flags & IEEE80211_CHAN_DISABLED)
  55. return -EINVAL;
  56. /*
  57. * no change except maybe auto -> fixed, ignore the HT
  58. * setting so you can fix a channel you're on already
  59. */
  60. if (local->oper_channel == chan)
  61. return 0;
  62. local->oper_channel = chan;
  63. local->oper_channel_type = NL80211_CHAN_NO_HT;
  64. ieee80211_hw_config(local, 0);
  65. return 0;
  66. }
  67. static int ieee80211_ioctl_giwfreq(struct net_device *dev,
  68. struct iw_request_info *info,
  69. struct iw_freq *freq, char *extra)
  70. {
  71. struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
  72. struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
  73. if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
  74. return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra);
  75. else if (sdata->vif.type == NL80211_IFTYPE_STATION)
  76. return cfg80211_mgd_wext_giwfreq(dev, info, freq, extra);
  77. freq->m = local->oper_channel->center_freq;
  78. freq->e = 6;
  79. return 0;
  80. }
  81. static int ieee80211_ioctl_siwessid(struct net_device *dev,
  82. struct iw_request_info *info,
  83. struct iw_point *data, char *ssid)
  84. {
  85. struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
  86. if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
  87. return cfg80211_ibss_wext_siwessid(dev, info, data, ssid);
  88. else if (sdata->vif.type == NL80211_IFTYPE_STATION)
  89. return cfg80211_mgd_wext_siwessid(dev, info, data, ssid);
  90. return -EOPNOTSUPP;
  91. }
  92. static int ieee80211_ioctl_giwessid(struct net_device *dev,
  93. struct iw_request_info *info,
  94. struct iw_point *data, char *ssid)
  95. {
  96. struct ieee80211_sub_if_data *sdata;
  97. sdata = IEEE80211_DEV_TO_SUB_IF(dev);
  98. if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
  99. return cfg80211_ibss_wext_giwessid(dev, info, data, ssid);
  100. else if (sdata->vif.type == NL80211_IFTYPE_STATION)
  101. return cfg80211_mgd_wext_giwessid(dev, info, data, ssid);
  102. return -EOPNOTSUPP;
  103. }
  104. static int ieee80211_ioctl_siwap(struct net_device *dev,
  105. struct iw_request_info *info,
  106. struct sockaddr *ap_addr, char *extra)
  107. {
  108. struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
  109. if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
  110. return cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra);
  111. if (sdata->vif.type == NL80211_IFTYPE_STATION)
  112. return cfg80211_mgd_wext_siwap(dev, info, ap_addr, extra);
  113. if (sdata->vif.type == NL80211_IFTYPE_WDS)
  114. return cfg80211_wds_wext_siwap(dev, info, ap_addr, extra);
  115. return -EOPNOTSUPP;
  116. }
  117. static int ieee80211_ioctl_giwap(struct net_device *dev,
  118. struct iw_request_info *info,
  119. struct sockaddr *ap_addr, char *extra)
  120. {
  121. struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
  122. if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
  123. return cfg80211_ibss_wext_giwap(dev, info, ap_addr, extra);
  124. if (sdata->vif.type == NL80211_IFTYPE_STATION)
  125. return cfg80211_mgd_wext_giwap(dev, info, ap_addr, extra);
  126. if (sdata->vif.type == NL80211_IFTYPE_WDS)
  127. return cfg80211_wds_wext_giwap(dev, info, ap_addr, extra);
  128. return -EOPNOTSUPP;
  129. }
  130. /* Structures to export the Wireless Handlers */
  131. static const iw_handler ieee80211_handler[] =
  132. {
  133. (iw_handler) NULL, /* SIOCSIWCOMMIT */
  134. (iw_handler) cfg80211_wext_giwname, /* SIOCGIWNAME */
  135. (iw_handler) NULL, /* SIOCSIWNWID */
  136. (iw_handler) NULL, /* SIOCGIWNWID */
  137. (iw_handler) ieee80211_ioctl_siwfreq, /* SIOCSIWFREQ */
  138. (iw_handler) ieee80211_ioctl_giwfreq, /* SIOCGIWFREQ */
  139. (iw_handler) cfg80211_wext_siwmode, /* SIOCSIWMODE */
  140. (iw_handler) cfg80211_wext_giwmode, /* SIOCGIWMODE */
  141. (iw_handler) NULL, /* SIOCSIWSENS */
  142. (iw_handler) NULL, /* SIOCGIWSENS */
  143. (iw_handler) NULL /* not used */, /* SIOCSIWRANGE */
  144. (iw_handler) cfg80211_wext_giwrange, /* SIOCGIWRANGE */
  145. (iw_handler) NULL /* not used */, /* SIOCSIWPRIV */
  146. (iw_handler) NULL /* kernel code */, /* SIOCGIWPRIV */
  147. (iw_handler) NULL /* not used */, /* SIOCSIWSTATS */
  148. (iw_handler) NULL /* kernel code */, /* SIOCGIWSTATS */
  149. (iw_handler) NULL, /* SIOCSIWSPY */
  150. (iw_handler) NULL, /* SIOCGIWSPY */
  151. (iw_handler) NULL, /* SIOCSIWTHRSPY */
  152. (iw_handler) NULL, /* SIOCGIWTHRSPY */
  153. (iw_handler) ieee80211_ioctl_siwap, /* SIOCSIWAP */
  154. (iw_handler) ieee80211_ioctl_giwap, /* SIOCGIWAP */
  155. (iw_handler) cfg80211_wext_siwmlme, /* SIOCSIWMLME */
  156. (iw_handler) NULL, /* SIOCGIWAPLIST */
  157. (iw_handler) cfg80211_wext_siwscan, /* SIOCSIWSCAN */
  158. (iw_handler) cfg80211_wext_giwscan, /* SIOCGIWSCAN */
  159. (iw_handler) ieee80211_ioctl_siwessid, /* SIOCSIWESSID */
  160. (iw_handler) ieee80211_ioctl_giwessid, /* SIOCGIWESSID */
  161. (iw_handler) NULL, /* SIOCSIWNICKN */
  162. (iw_handler) NULL, /* SIOCGIWNICKN */
  163. (iw_handler) NULL, /* -- hole -- */
  164. (iw_handler) NULL, /* -- hole -- */
  165. (iw_handler) cfg80211_wext_siwrate, /* SIOCSIWRATE */
  166. (iw_handler) cfg80211_wext_giwrate, /* SIOCGIWRATE */
  167. (iw_handler) cfg80211_wext_siwrts, /* SIOCSIWRTS */
  168. (iw_handler) cfg80211_wext_giwrts, /* SIOCGIWRTS */
  169. (iw_handler) cfg80211_wext_siwfrag, /* SIOCSIWFRAG */
  170. (iw_handler) cfg80211_wext_giwfrag, /* SIOCGIWFRAG */
  171. (iw_handler) cfg80211_wext_siwtxpower, /* SIOCSIWTXPOW */
  172. (iw_handler) cfg80211_wext_giwtxpower, /* SIOCGIWTXPOW */
  173. (iw_handler) cfg80211_wext_siwretry, /* SIOCSIWRETRY */
  174. (iw_handler) cfg80211_wext_giwretry, /* SIOCGIWRETRY */
  175. (iw_handler) cfg80211_wext_siwencode, /* SIOCSIWENCODE */
  176. (iw_handler) cfg80211_wext_giwencode, /* SIOCGIWENCODE */
  177. (iw_handler) cfg80211_wext_siwpower, /* SIOCSIWPOWER */
  178. (iw_handler) cfg80211_wext_giwpower, /* SIOCGIWPOWER */
  179. (iw_handler) NULL, /* -- hole -- */
  180. (iw_handler) NULL, /* -- hole -- */
  181. (iw_handler) cfg80211_wext_siwgenie, /* SIOCSIWGENIE */
  182. (iw_handler) NULL, /* SIOCGIWGENIE */
  183. (iw_handler) cfg80211_wext_siwauth, /* SIOCSIWAUTH */
  184. (iw_handler) cfg80211_wext_giwauth, /* SIOCGIWAUTH */
  185. (iw_handler) cfg80211_wext_siwencodeext, /* SIOCSIWENCODEEXT */
  186. (iw_handler) NULL, /* SIOCGIWENCODEEXT */
  187. (iw_handler) NULL, /* SIOCSIWPMKSA */
  188. (iw_handler) NULL, /* -- hole -- */
  189. };
  190. const struct iw_handler_def ieee80211_iw_handler_def =
  191. {
  192. .num_standard = ARRAY_SIZE(ieee80211_handler),
  193. .standard = (iw_handler *) ieee80211_handler,
  194. .get_wireless_stats = cfg80211_wireless_stats,
  195. };