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