wext-proc.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. /*
  2. * This file implement the Wireless Extensions proc API.
  3. *
  4. * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
  5. * Copyright (c) 1997-2007 Jean Tourrilhes, All Rights Reserved.
  6. *
  7. * (As all part of the Linux kernel, this file is GPL)
  8. */
  9. /*
  10. * The /proc/net/wireless file is a human readable user-space interface
  11. * exporting various wireless specific statistics from the wireless devices.
  12. * This is the most popular part of the Wireless Extensions ;-)
  13. *
  14. * This interface is a pure clone of /proc/net/dev (in net/core/dev.c).
  15. * The content of the file is basically the content of "struct iw_statistics".
  16. */
  17. #include <linux/module.h>
  18. #include <linux/proc_fs.h>
  19. #include <linux/seq_file.h>
  20. #include <linux/wireless.h>
  21. #include <linux/netdevice.h>
  22. #include <linux/rtnetlink.h>
  23. #include <net/iw_handler.h>
  24. #include <net/wext.h>
  25. static void wireless_seq_printf_stats(struct seq_file *seq,
  26. struct net_device *dev)
  27. {
  28. /* Get stats from the driver */
  29. struct iw_statistics *stats = get_wireless_stats(dev);
  30. static struct iw_statistics nullstats = {};
  31. /* show device if it's wireless regardless of current stats */
  32. if (!stats) {
  33. #ifdef CONFIG_WIRELESS_EXT
  34. if (dev->wireless_handlers)
  35. stats = &nullstats;
  36. #endif
  37. #ifdef CONFIG_CFG80211
  38. if (dev->ieee80211_ptr)
  39. stats = &nullstats;
  40. #endif
  41. }
  42. if (stats) {
  43. seq_printf(seq, "%6s: %04x %3d%c %3d%c %3d%c %6d %6d %6d "
  44. "%6d %6d %6d\n",
  45. dev->name, stats->status, stats->qual.qual,
  46. stats->qual.updated & IW_QUAL_QUAL_UPDATED
  47. ? '.' : ' ',
  48. ((__s32) stats->qual.level) -
  49. ((stats->qual.updated & IW_QUAL_DBM) ? 0x100 : 0),
  50. stats->qual.updated & IW_QUAL_LEVEL_UPDATED
  51. ? '.' : ' ',
  52. ((__s32) stats->qual.noise) -
  53. ((stats->qual.updated & IW_QUAL_DBM) ? 0x100 : 0),
  54. stats->qual.updated & IW_QUAL_NOISE_UPDATED
  55. ? '.' : ' ',
  56. stats->discard.nwid, stats->discard.code,
  57. stats->discard.fragment, stats->discard.retries,
  58. stats->discard.misc, stats->miss.beacon);
  59. if (stats != &nullstats)
  60. stats->qual.updated &= ~IW_QUAL_ALL_UPDATED;
  61. }
  62. }
  63. /* ---------------------------------------------------------------- */
  64. /*
  65. * Print info for /proc/net/wireless (print all entries)
  66. */
  67. static int wireless_dev_seq_show(struct seq_file *seq, void *v)
  68. {
  69. might_sleep();
  70. if (v == SEQ_START_TOKEN)
  71. seq_printf(seq, "Inter-| sta-| Quality | Discarded "
  72. "packets | Missed | WE\n"
  73. " face | tus | link level noise | nwid "
  74. "crypt frag retry misc | beacon | %d\n",
  75. WIRELESS_EXT);
  76. else
  77. wireless_seq_printf_stats(seq, v);
  78. return 0;
  79. }
  80. static void *wireless_dev_seq_start(struct seq_file *seq, loff_t *pos)
  81. {
  82. struct net *net = seq_file_net(seq);
  83. loff_t off;
  84. struct net_device *dev;
  85. rtnl_lock();
  86. if (!*pos)
  87. return SEQ_START_TOKEN;
  88. off = 1;
  89. for_each_netdev(net, dev)
  90. if (off++ == *pos)
  91. return dev;
  92. return NULL;
  93. }
  94. static void *wireless_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
  95. {
  96. struct net *net = seq_file_net(seq);
  97. ++*pos;
  98. return v == SEQ_START_TOKEN ?
  99. first_net_device(net) : next_net_device(v);
  100. }
  101. static void wireless_dev_seq_stop(struct seq_file *seq, void *v)
  102. {
  103. rtnl_unlock();
  104. }
  105. static const struct seq_operations wireless_seq_ops = {
  106. .start = wireless_dev_seq_start,
  107. .next = wireless_dev_seq_next,
  108. .stop = wireless_dev_seq_stop,
  109. .show = wireless_dev_seq_show,
  110. };
  111. static int seq_open_wireless(struct inode *inode, struct file *file)
  112. {
  113. return seq_open_net(inode, file, &wireless_seq_ops,
  114. sizeof(struct seq_net_private));
  115. }
  116. static const struct file_operations wireless_seq_fops = {
  117. .owner = THIS_MODULE,
  118. .open = seq_open_wireless,
  119. .read = seq_read,
  120. .llseek = seq_lseek,
  121. .release = seq_release_net,
  122. };
  123. int __net_init wext_proc_init(struct net *net)
  124. {
  125. /* Create /proc/net/wireless entry */
  126. if (!proc_create("wireless", S_IRUGO, net->proc_net,
  127. &wireless_seq_fops))
  128. return -ENOMEM;
  129. return 0;
  130. }
  131. void __net_exit wext_proc_exit(struct net *net)
  132. {
  133. remove_proc_entry("wireless", net->proc_net);
  134. }