hostap_proc.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  1. /* /proc routines for Host AP driver */
  2. #define PROC_LIMIT (PAGE_SIZE - 80)
  3. #ifndef PRISM2_NO_PROCFS_DEBUG
  4. static int prism2_debug_proc_read(char *page, char **start, off_t off,
  5. int count, int *eof, void *data)
  6. {
  7. char *p = page;
  8. local_info_t *local = (local_info_t *) data;
  9. int i;
  10. if (off != 0) {
  11. *eof = 1;
  12. return 0;
  13. }
  14. p += sprintf(p, "next_txfid=%d next_alloc=%d\n",
  15. local->next_txfid, local->next_alloc);
  16. for (i = 0; i < PRISM2_TXFID_COUNT; i++)
  17. p += sprintf(p, "FID: tx=%04X intransmit=%04X\n",
  18. local->txfid[i], local->intransmitfid[i]);
  19. p += sprintf(p, "FW TX rate control: %d\n", local->fw_tx_rate_control);
  20. p += sprintf(p, "beacon_int=%d\n", local->beacon_int);
  21. p += sprintf(p, "dtim_period=%d\n", local->dtim_period);
  22. p += sprintf(p, "wds_max_connections=%d\n",
  23. local->wds_max_connections);
  24. p += sprintf(p, "dev_enabled=%d\n", local->dev_enabled);
  25. p += sprintf(p, "sw_tick_stuck=%d\n", local->sw_tick_stuck);
  26. for (i = 0; i < WEP_KEYS; i++) {
  27. if (local->crypt[i] && local->crypt[i]->ops) {
  28. p += sprintf(p, "crypt[%d]=%s\n",
  29. i, local->crypt[i]->ops->name);
  30. }
  31. }
  32. p += sprintf(p, "pri_only=%d\n", local->pri_only);
  33. p += sprintf(p, "pci=%d\n", local->func->hw_type == HOSTAP_HW_PCI);
  34. p += sprintf(p, "sram_type=%d\n", local->sram_type);
  35. p += sprintf(p, "no_pri=%d\n", local->no_pri);
  36. return (p - page);
  37. }
  38. #endif /* PRISM2_NO_PROCFS_DEBUG */
  39. static int prism2_stats_proc_read(char *page, char **start, off_t off,
  40. int count, int *eof, void *data)
  41. {
  42. char *p = page;
  43. local_info_t *local = (local_info_t *) data;
  44. struct comm_tallies_sums *sums = (struct comm_tallies_sums *)
  45. &local->comm_tallies;
  46. if (off != 0) {
  47. *eof = 1;
  48. return 0;
  49. }
  50. p += sprintf(p, "TxUnicastFrames=%u\n", sums->tx_unicast_frames);
  51. p += sprintf(p, "TxMulticastframes=%u\n", sums->tx_multicast_frames);
  52. p += sprintf(p, "TxFragments=%u\n", sums->tx_fragments);
  53. p += sprintf(p, "TxUnicastOctets=%u\n", sums->tx_unicast_octets);
  54. p += sprintf(p, "TxMulticastOctets=%u\n", sums->tx_multicast_octets);
  55. p += sprintf(p, "TxDeferredTransmissions=%u\n",
  56. sums->tx_deferred_transmissions);
  57. p += sprintf(p, "TxSingleRetryFrames=%u\n",
  58. sums->tx_single_retry_frames);
  59. p += sprintf(p, "TxMultipleRetryFrames=%u\n",
  60. sums->tx_multiple_retry_frames);
  61. p += sprintf(p, "TxRetryLimitExceeded=%u\n",
  62. sums->tx_retry_limit_exceeded);
  63. p += sprintf(p, "TxDiscards=%u\n", sums->tx_discards);
  64. p += sprintf(p, "RxUnicastFrames=%u\n", sums->rx_unicast_frames);
  65. p += sprintf(p, "RxMulticastFrames=%u\n", sums->rx_multicast_frames);
  66. p += sprintf(p, "RxFragments=%u\n", sums->rx_fragments);
  67. p += sprintf(p, "RxUnicastOctets=%u\n", sums->rx_unicast_octets);
  68. p += sprintf(p, "RxMulticastOctets=%u\n", sums->rx_multicast_octets);
  69. p += sprintf(p, "RxFCSErrors=%u\n", sums->rx_fcs_errors);
  70. p += sprintf(p, "RxDiscardsNoBuffer=%u\n",
  71. sums->rx_discards_no_buffer);
  72. p += sprintf(p, "TxDiscardsWrongSA=%u\n", sums->tx_discards_wrong_sa);
  73. p += sprintf(p, "RxDiscardsWEPUndecryptable=%u\n",
  74. sums->rx_discards_wep_undecryptable);
  75. p += sprintf(p, "RxMessageInMsgFragments=%u\n",
  76. sums->rx_message_in_msg_fragments);
  77. p += sprintf(p, "RxMessageInBadMsgFragments=%u\n",
  78. sums->rx_message_in_bad_msg_fragments);
  79. /* FIX: this may grow too long for one page(?) */
  80. return (p - page);
  81. }
  82. static int prism2_wds_proc_read(char *page, char **start, off_t off,
  83. int count, int *eof, void *data)
  84. {
  85. char *p = page;
  86. local_info_t *local = (local_info_t *) data;
  87. struct list_head *ptr;
  88. struct hostap_interface *iface;
  89. if (off > PROC_LIMIT) {
  90. *eof = 1;
  91. return 0;
  92. }
  93. read_lock_bh(&local->iface_lock);
  94. list_for_each(ptr, &local->hostap_interfaces) {
  95. iface = list_entry(ptr, struct hostap_interface, list);
  96. if (iface->type != HOSTAP_INTERFACE_WDS)
  97. continue;
  98. p += sprintf(p, "%s\t" MACSTR "\n",
  99. iface->dev->name,
  100. MAC2STR(iface->u.wds.remote_addr));
  101. if ((p - page) > PROC_LIMIT) {
  102. printk(KERN_DEBUG "%s: wds proc did not fit\n",
  103. local->dev->name);
  104. break;
  105. }
  106. }
  107. read_unlock_bh(&local->iface_lock);
  108. if ((p - page) <= off) {
  109. *eof = 1;
  110. return 0;
  111. }
  112. *start = page + off;
  113. return (p - page - off);
  114. }
  115. static int prism2_bss_list_proc_read(char *page, char **start, off_t off,
  116. int count, int *eof, void *data)
  117. {
  118. char *p = page;
  119. local_info_t *local = (local_info_t *) data;
  120. struct list_head *ptr;
  121. struct hostap_bss_info *bss;
  122. int i;
  123. if (off > PROC_LIMIT) {
  124. *eof = 1;
  125. return 0;
  126. }
  127. p += sprintf(p, "#BSSID\tlast_update\tcount\tcapab_info\tSSID(txt)\t"
  128. "SSID(hex)\tWPA IE\n");
  129. spin_lock_bh(&local->lock);
  130. list_for_each(ptr, &local->bss_list) {
  131. bss = list_entry(ptr, struct hostap_bss_info, list);
  132. p += sprintf(p, MACSTR "\t%lu\t%u\t0x%x\t",
  133. MAC2STR(bss->bssid), bss->last_update,
  134. bss->count, bss->capab_info);
  135. for (i = 0; i < bss->ssid_len; i++) {
  136. p += sprintf(p, "%c",
  137. bss->ssid[i] >= 32 && bss->ssid[i] < 127 ?
  138. bss->ssid[i] : '_');
  139. }
  140. p += sprintf(p, "\t");
  141. for (i = 0; i < bss->ssid_len; i++) {
  142. p += sprintf(p, "%02x", bss->ssid[i]);
  143. }
  144. p += sprintf(p, "\t");
  145. for (i = 0; i < bss->wpa_ie_len; i++) {
  146. p += sprintf(p, "%02x", bss->wpa_ie[i]);
  147. }
  148. p += sprintf(p, "\n");
  149. if ((p - page) > PROC_LIMIT) {
  150. printk(KERN_DEBUG "%s: BSS proc did not fit\n",
  151. local->dev->name);
  152. break;
  153. }
  154. }
  155. spin_unlock_bh(&local->lock);
  156. if ((p - page) <= off) {
  157. *eof = 1;
  158. return 0;
  159. }
  160. *start = page + off;
  161. return (p - page - off);
  162. }
  163. static int prism2_crypt_proc_read(char *page, char **start, off_t off,
  164. int count, int *eof, void *data)
  165. {
  166. char *p = page;
  167. local_info_t *local = (local_info_t *) data;
  168. int i;
  169. if (off > PROC_LIMIT) {
  170. *eof = 1;
  171. return 0;
  172. }
  173. p += sprintf(p, "tx_keyidx=%d\n", local->tx_keyidx);
  174. for (i = 0; i < WEP_KEYS; i++) {
  175. if (local->crypt[i] && local->crypt[i]->ops &&
  176. local->crypt[i]->ops->print_stats) {
  177. p = local->crypt[i]->ops->print_stats(
  178. p, local->crypt[i]->priv);
  179. }
  180. }
  181. if ((p - page) <= off) {
  182. *eof = 1;
  183. return 0;
  184. }
  185. *start = page + off;
  186. return (p - page - off);
  187. }
  188. static int prism2_pda_proc_read(char *page, char **start, off_t off,
  189. int count, int *eof, void *data)
  190. {
  191. local_info_t *local = (local_info_t *) data;
  192. if (local->pda == NULL || off >= PRISM2_PDA_SIZE) {
  193. *eof = 1;
  194. return 0;
  195. }
  196. if (off + count > PRISM2_PDA_SIZE)
  197. count = PRISM2_PDA_SIZE - off;
  198. memcpy(page, local->pda + off, count);
  199. return count;
  200. }
  201. static int prism2_aux_dump_proc_read(char *page, char **start, off_t off,
  202. int count, int *eof, void *data)
  203. {
  204. local_info_t *local = (local_info_t *) data;
  205. if (local->func->read_aux == NULL) {
  206. *eof = 1;
  207. return 0;
  208. }
  209. if (local->func->read_aux(local->dev, off, count, page)) {
  210. *eof = 1;
  211. return 0;
  212. }
  213. *start = page;
  214. return count;
  215. }
  216. #ifdef PRISM2_IO_DEBUG
  217. static int prism2_io_debug_proc_read(char *page, char **start, off_t off,
  218. int count, int *eof, void *data)
  219. {
  220. local_info_t *local = (local_info_t *) data;
  221. int head = local->io_debug_head;
  222. int start_bytes, left, copy, copied;
  223. if (off + count > PRISM2_IO_DEBUG_SIZE * 4) {
  224. *eof = 1;
  225. if (off >= PRISM2_IO_DEBUG_SIZE * 4)
  226. return 0;
  227. count = PRISM2_IO_DEBUG_SIZE * 4 - off;
  228. }
  229. copied = 0;
  230. start_bytes = (PRISM2_IO_DEBUG_SIZE - head) * 4;
  231. left = count;
  232. if (off < start_bytes) {
  233. copy = start_bytes - off;
  234. if (copy > count)
  235. copy = count;
  236. memcpy(page, ((u8 *) &local->io_debug[head]) + off, copy);
  237. left -= copy;
  238. if (left > 0)
  239. memcpy(&page[copy], local->io_debug, left);
  240. } else {
  241. memcpy(page, ((u8 *) local->io_debug) + (off - start_bytes),
  242. left);
  243. }
  244. *start = page;
  245. return count;
  246. }
  247. #endif /* PRISM2_IO_DEBUG */
  248. #ifndef PRISM2_NO_STATION_MODES
  249. static int prism2_scan_results_proc_read(char *page, char **start, off_t off,
  250. int count, int *eof, void *data)
  251. {
  252. char *p = page;
  253. local_info_t *local = (local_info_t *) data;
  254. int entries, entry, i, len, total = 0, hostscan;
  255. struct hfa384x_scan_result *scanres;
  256. struct hfa384x_hostscan_result *hscanres;
  257. u8 *pos;
  258. p += sprintf(p, "CHID ANL SL BcnInt Capab Rate BSSID ATIM SupRates "
  259. "SSID\n");
  260. spin_lock_bh(&local->lock);
  261. hostscan = local->last_scan_type == PRISM2_HOSTSCAN;
  262. entries = hostscan ? local->last_hostscan_results_count :
  263. local->last_scan_results_count;
  264. for (entry = 0; entry < entries; entry++) {
  265. hscanres = &local->last_hostscan_results[entry];
  266. scanres = &local->last_scan_results[entry];
  267. if (total + (p - page) <= off) {
  268. total += p - page;
  269. p = page;
  270. }
  271. if (total + (p - page) > off + count)
  272. break;
  273. if ((p - page) > (PAGE_SIZE - 200))
  274. break;
  275. if (hostscan) {
  276. p += sprintf(p, "%d %d %d %d 0x%02x %d " MACSTR " %d ",
  277. le16_to_cpu(hscanres->chid),
  278. (s16) le16_to_cpu(hscanres->anl),
  279. (s16) le16_to_cpu(hscanres->sl),
  280. le16_to_cpu(hscanres->beacon_interval),
  281. le16_to_cpu(hscanres->capability),
  282. le16_to_cpu(hscanres->rate),
  283. MAC2STR(hscanres->bssid),
  284. le16_to_cpu(hscanres->atim));
  285. } else {
  286. p += sprintf(p, "%d %d %d %d 0x%02x %d " MACSTR
  287. " N/A ",
  288. le16_to_cpu(scanres->chid),
  289. (s16) le16_to_cpu(scanres->anl),
  290. (s16) le16_to_cpu(scanres->sl),
  291. le16_to_cpu(scanres->beacon_interval),
  292. le16_to_cpu(scanres->capability),
  293. le16_to_cpu(scanres->rate),
  294. MAC2STR(scanres->bssid));
  295. }
  296. pos = hostscan ? hscanres->sup_rates : scanres->sup_rates;
  297. for (i = 0; i < sizeof(hscanres->sup_rates); i++) {
  298. if (pos[i] == 0)
  299. break;
  300. p += sprintf(p, "<%02x>", pos[i]);
  301. }
  302. p += sprintf(p, " ");
  303. pos = hostscan ? hscanres->ssid : scanres->ssid;
  304. len = le16_to_cpu(hostscan ? hscanres->ssid_len :
  305. scanres->ssid_len);
  306. if (len > 32)
  307. len = 32;
  308. for (i = 0; i < len; i++) {
  309. unsigned char c = pos[i];
  310. if (c >= 32 && c < 127)
  311. p += sprintf(p, "%c", c);
  312. else
  313. p += sprintf(p, "<%02x>", c);
  314. }
  315. p += sprintf(p, "\n");
  316. }
  317. spin_unlock_bh(&local->lock);
  318. total += (p - page);
  319. if (total >= off + count)
  320. *eof = 1;
  321. if (total < off) {
  322. *eof = 1;
  323. return 0;
  324. }
  325. len = total - off;
  326. if (len > (p - page))
  327. len = p - page;
  328. *start = p - len;
  329. if (len > count)
  330. len = count;
  331. return len;
  332. }
  333. #endif /* PRISM2_NO_STATION_MODES */
  334. void hostap_init_proc(local_info_t *local)
  335. {
  336. local->proc = NULL;
  337. if (hostap_proc == NULL) {
  338. printk(KERN_WARNING "%s: hostap proc directory not created\n",
  339. local->dev->name);
  340. return;
  341. }
  342. local->proc = proc_mkdir(local->ddev->name, hostap_proc);
  343. if (local->proc == NULL) {
  344. printk(KERN_INFO "/proc/net/hostap/%s creation failed\n",
  345. local->ddev->name);
  346. return;
  347. }
  348. #ifndef PRISM2_NO_PROCFS_DEBUG
  349. create_proc_read_entry("debug", 0, local->proc,
  350. prism2_debug_proc_read, local);
  351. #endif /* PRISM2_NO_PROCFS_DEBUG */
  352. create_proc_read_entry("stats", 0, local->proc,
  353. prism2_stats_proc_read, local);
  354. create_proc_read_entry("wds", 0, local->proc,
  355. prism2_wds_proc_read, local);
  356. create_proc_read_entry("pda", 0, local->proc,
  357. prism2_pda_proc_read, local);
  358. create_proc_read_entry("aux_dump", 0, local->proc,
  359. prism2_aux_dump_proc_read, local);
  360. create_proc_read_entry("bss_list", 0, local->proc,
  361. prism2_bss_list_proc_read, local);
  362. create_proc_read_entry("crypt", 0, local->proc,
  363. prism2_crypt_proc_read, local);
  364. #ifdef PRISM2_IO_DEBUG
  365. create_proc_read_entry("io_debug", 0, local->proc,
  366. prism2_io_debug_proc_read, local);
  367. #endif /* PRISM2_IO_DEBUG */
  368. #ifndef PRISM2_NO_STATION_MODES
  369. create_proc_read_entry("scan_results", 0, local->proc,
  370. prism2_scan_results_proc_read, local);
  371. #endif /* PRISM2_NO_STATION_MODES */
  372. }
  373. void hostap_remove_proc(local_info_t *local)
  374. {
  375. if (local->proc != NULL) {
  376. #ifndef PRISM2_NO_STATION_MODES
  377. remove_proc_entry("scan_results", local->proc);
  378. #endif /* PRISM2_NO_STATION_MODES */
  379. #ifdef PRISM2_IO_DEBUG
  380. remove_proc_entry("io_debug", local->proc);
  381. #endif /* PRISM2_IO_DEBUG */
  382. remove_proc_entry("pda", local->proc);
  383. remove_proc_entry("aux_dump", local->proc);
  384. remove_proc_entry("wds", local->proc);
  385. remove_proc_entry("stats", local->proc);
  386. remove_proc_entry("bss_list", local->proc);
  387. remove_proc_entry("crypt", local->proc);
  388. #ifndef PRISM2_NO_PROCFS_DEBUG
  389. remove_proc_entry("debug", local->proc);
  390. #endif /* PRISM2_NO_PROCFS_DEBUG */
  391. if (hostap_proc != NULL)
  392. remove_proc_entry(local->proc->name, hostap_proc);
  393. }
  394. }
  395. EXPORT_SYMBOL(hostap_init_proc);
  396. EXPORT_SYMBOL(hostap_remove_proc);