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