Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * This file implement the Wireless Extensions proc API.
0003  *
0004  * Authors :    Jean Tourrilhes - HPL - <jt@hpl.hp.com>
0005  * Copyright (c) 1997-2007 Jean Tourrilhes, All Rights Reserved.
0006  *
0007  * (As all part of the Linux kernel, this file is GPL)
0008  */
0009 
0010 /*
0011  * The /proc/net/wireless file is a human readable user-space interface
0012  * exporting various wireless specific statistics from the wireless devices.
0013  * This is the most popular part of the Wireless Extensions ;-)
0014  *
0015  * This interface is a pure clone of /proc/net/dev (in net/core/dev.c).
0016  * The content of the file is basically the content of "struct iw_statistics".
0017  */
0018 
0019 #include <linux/module.h>
0020 #include <linux/proc_fs.h>
0021 #include <linux/seq_file.h>
0022 #include <linux/wireless.h>
0023 #include <linux/netdevice.h>
0024 #include <linux/rtnetlink.h>
0025 #include <net/iw_handler.h>
0026 #include <net/wext.h>
0027 
0028 
0029 static void wireless_seq_printf_stats(struct seq_file *seq,
0030                       struct net_device *dev)
0031 {
0032     /* Get stats from the driver */
0033     struct iw_statistics *stats = get_wireless_stats(dev);
0034     static struct iw_statistics nullstats = {};
0035 
0036     /* show device if it's wireless regardless of current stats */
0037     if (!stats) {
0038 #ifdef CONFIG_WIRELESS_EXT
0039         if (dev->wireless_handlers)
0040             stats = &nullstats;
0041 #endif
0042 #ifdef CONFIG_CFG80211
0043         if (dev->ieee80211_ptr)
0044             stats = &nullstats;
0045 #endif
0046     }
0047 
0048     if (stats) {
0049         seq_printf(seq, "%6s: %04x  %3d%c  %3d%c  %3d%c  %6d %6d %6d "
0050                 "%6d %6d   %6d\n",
0051                dev->name, stats->status, stats->qual.qual,
0052                stats->qual.updated & IW_QUAL_QUAL_UPDATED
0053                ? '.' : ' ',
0054                ((__s32) stats->qual.level) -
0055                ((stats->qual.updated & IW_QUAL_DBM) ? 0x100 : 0),
0056                stats->qual.updated & IW_QUAL_LEVEL_UPDATED
0057                ? '.' : ' ',
0058                ((__s32) stats->qual.noise) -
0059                ((stats->qual.updated & IW_QUAL_DBM) ? 0x100 : 0),
0060                stats->qual.updated & IW_QUAL_NOISE_UPDATED
0061                ? '.' : ' ',
0062                stats->discard.nwid, stats->discard.code,
0063                stats->discard.fragment, stats->discard.retries,
0064                stats->discard.misc, stats->miss.beacon);
0065 
0066         if (stats != &nullstats)
0067             stats->qual.updated &= ~IW_QUAL_ALL_UPDATED;
0068     }
0069 }
0070 
0071 /* ---------------------------------------------------------------- */
0072 /*
0073  * Print info for /proc/net/wireless (print all entries)
0074  */
0075 static int wireless_dev_seq_show(struct seq_file *seq, void *v)
0076 {
0077     might_sleep();
0078 
0079     if (v == SEQ_START_TOKEN)
0080         seq_printf(seq, "Inter-| sta-|   Quality        |   Discarded "
0081                 "packets               | Missed | WE\n"
0082                 " face | tus | link level noise |  nwid  "
0083                 "crypt   frag  retry   misc | beacon | %d\n",
0084                WIRELESS_EXT);
0085     else
0086         wireless_seq_printf_stats(seq, v);
0087     return 0;
0088 }
0089 
0090 static void *wireless_dev_seq_start(struct seq_file *seq, loff_t *pos)
0091 {
0092     struct net *net = seq_file_net(seq);
0093     loff_t off;
0094     struct net_device *dev;
0095 
0096     rtnl_lock();
0097     if (!*pos)
0098         return SEQ_START_TOKEN;
0099 
0100     off = 1;
0101     for_each_netdev(net, dev)
0102         if (off++ == *pos)
0103             return dev;
0104     return NULL;
0105 }
0106 
0107 static void *wireless_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
0108 {
0109     struct net *net = seq_file_net(seq);
0110 
0111     ++*pos;
0112 
0113     return v == SEQ_START_TOKEN ?
0114         first_net_device(net) : next_net_device(v);
0115 }
0116 
0117 static void wireless_dev_seq_stop(struct seq_file *seq, void *v)
0118 {
0119     rtnl_unlock();
0120 }
0121 
0122 static const struct seq_operations wireless_seq_ops = {
0123     .start = wireless_dev_seq_start,
0124     .next  = wireless_dev_seq_next,
0125     .stop  = wireless_dev_seq_stop,
0126     .show  = wireless_dev_seq_show,
0127 };
0128 
0129 int __net_init wext_proc_init(struct net *net)
0130 {
0131     /* Create /proc/net/wireless entry */
0132     if (!proc_create_net("wireless", 0444, net->proc_net,
0133             &wireless_seq_ops, sizeof(struct seq_net_private)))
0134         return -ENOMEM;
0135 
0136     return 0;
0137 }
0138 
0139 void __net_exit wext_proc_exit(struct net *net)
0140 {
0141     remove_proc_entry("wireless", net->proc_net);
0142 }