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 <net/ieee80211_crypt.h>
   6
   7#include "hostap_wlan.h"
   8#include "hostap.h"
   9
  10#define PROC_LIMIT (PAGE_SIZE - 80)
  11
  12
  13#ifndef PRISM2_NO_PROCFS_DEBUG
  14static int prism2_debug_proc_read(char *page, char **start, off_t off,
  15                                  int count, int *eof, void *data)
  16{
  17        char *p = page;
  18        local_info_t *local = (local_info_t *) data;
  19        int i;
  20
  21        if (off != 0) {
  22                *eof = 1;
  23                return 0;
  24        }
  25
  26        p += sprintf(p, "next_txfid=%d next_alloc=%d\n",
  27                     local->next_txfid, local->next_alloc);
  28        for (i = 0; i < PRISM2_TXFID_COUNT; i++)
  29                p += sprintf(p, "FID: tx=%04X intransmit=%04X\n",
  30                             local->txfid[i], local->intransmitfid[i]);
  31        p += sprintf(p, "FW TX rate control: %d\n", local->fw_tx_rate_control);
  32        p += sprintf(p, "beacon_int=%d\n", local->beacon_int);
  33        p += sprintf(p, "dtim_period=%d\n", local->dtim_period);
  34        p += sprintf(p, "wds_max_connections=%d\n",
  35                     local->wds_max_connections);
  36        p += sprintf(p, "dev_enabled=%d\n", local->dev_enabled);
  37        p += sprintf(p, "sw_tick_stuck=%d\n", local->sw_tick_stuck);
  38        for (i = 0; i < WEP_KEYS; i++) {
  39                if (local->crypt[i] && local->crypt[i]->ops) {
  40                        p += sprintf(p, "crypt[%d]=%s\n",
  41                                     i, local->crypt[i]->ops->name);
  42                }
  43        }
  44        p += sprintf(p, "pri_only=%d\n", local->pri_only);
  45        p += sprintf(p, "pci=%d\n", local->func->hw_type == HOSTAP_HW_PCI);
  46        p += sprintf(p, "sram_type=%d\n", local->sram_type);
  47        p += sprintf(p, "no_pri=%d\n", local->no_pri);
  48
  49        return (p - page);
  50}
  51#endif /* PRISM2_NO_PROCFS_DEBUG */
  52
  53
  54static int prism2_stats_proc_read(char *page, char **start, off_t off,
  55                                  int count, int *eof, void *data)
  56{
  57        char *p = page;
  58        local_info_t *local = (local_info_t *) data;
  59        struct comm_tallies_sums *sums = (struct comm_tallies_sums *)
  60                &local->comm_tallies;
  61
  62        if (off != 0) {
  63                *eof = 1;
  64                return 0;
  65        }
  66
  67        p += sprintf(p, "TxUnicastFrames=%u\n", sums->tx_unicast_frames);
  68        p += sprintf(p, "TxMulticastframes=%u\n", sums->tx_multicast_frames);
  69        p += sprintf(p, "TxFragments=%u\n", sums->tx_fragments);
  70        p += sprintf(p, "TxUnicastOctets=%u\n", sums->tx_unicast_octets);
  71        p += sprintf(p, "TxMulticastOctets=%u\n", sums->tx_multicast_octets);
  72        p += sprintf(p, "TxDeferredTransmissions=%u\n",
  73                     sums->tx_deferred_transmissions);
  74        p += sprintf(p, "TxSingleRetryFrames=%u\n",
  75                     sums->tx_single_retry_frames);
  76        p += sprintf(p, "TxMultipleRetryFrames=%u\n",
  77                     sums->tx_multiple_retry_frames);
  78        p += sprintf(p, "TxRetryLimitExceeded=%u\n",
  79                     sums->tx_retry_limit_exceeded);
  80        p += sprintf(p, "TxDiscards=%u\n", sums->tx_discards);
  81        p += sprintf(p, "RxUnicastFrames=%u\n", sums->rx_unicast_frames);
  82        p += sprintf(p, "RxMulticastFrames=%u\n", sums->rx_multicast_frames);
  83        p += sprintf(p, "RxFragments=%u\n", sums->rx_fragments);
  84        p += sprintf(p, "RxUnicastOctets=%u\n", sums->rx_unicast_octets);
  85        p += sprintf(p, "RxMulticastOctets=%u\n", sums->rx_multicast_octets);
  86        p += sprintf(p, "RxFCSErrors=%u\n", sums->rx_fcs_errors);
  87        p += sprintf(p, "RxDiscardsNoBuffer=%u\n",
  88                     sums->rx_discards_no_buffer);
  89        p += sprintf(p, "TxDiscardsWrongSA=%u\n", sums->tx_discards_wrong_sa);
  90        p += sprintf(p, "RxDiscardsWEPUndecryptable=%u\n",
  91                     sums->rx_discards_wep_undecryptable);
  92        p += sprintf(p, "RxMessageInMsgFragments=%u\n",
  93                     sums->rx_message_in_msg_fragments);
  94        p += sprintf(p, "RxMessageInBadMsgFragments=%u\n",
  95                     sums->rx_message_in_bad_msg_fragments);
  96        /* FIX: this may grow too long for one page(?) */
  97
  98        return (p - page);
  99}
 100
 101
 102static int prism2_wds_proc_read(char *page, char **start, off_t off,
 103                                int count, int *eof, void *data)
 104{
 105        char *p = page;
 106        local_info_t *local = (local_info_t *) data;
 107        struct list_head *ptr;
 108        struct hostap_interface *iface;
 109        DECLARE_MAC_BUF(mac);
 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%s\n",
 122                             iface->dev->name,
 123                             print_mac(mac, 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        DECLARE_MAC_BUF(mac);
 152
 153        if (off > PROC_LIMIT) {
 154                *eof = 1;
 155                return 0;
 156        }
 157
 158        p += sprintf(p, "#BSSID\tlast_update\tcount\tcapab_info\tSSID(txt)\t"
 159                     "SSID(hex)\tWPA IE\n");
 160        spin_lock_bh(&local->lock);
 161        list_for_each(ptr, &local->bss_list) {
 162                bss = list_entry(ptr, struct hostap_bss_info, list);
 163                p += sprintf(p, "%s\t%lu\t%u\t0x%x\t",
 164                             print_mac(mac, bss->bssid), bss->last_update,
 165                             bss->count, bss->capab_info);
 166                for (i = 0; i < bss->ssid_len; i++) {
 167                        p += sprintf(p, "%c",
 168                                     bss->ssid[i] >= 32 && bss->ssid[i] < 127 ?
 169                                     bss->ssid[i] : '_');
 170                }
 171                p += sprintf(p, "\t");
 172                for (i = 0; i < bss->ssid_len; i++) {
 173                        p += sprintf(p, "%02x", bss->ssid[i]);
 174                }
 175                p += sprintf(p, "\t");
 176                for (i = 0; i < bss->wpa_ie_len; i++) {
 177                        p += sprintf(p, "%02x", bss->wpa_ie[i]);
 178                }
 179                p += sprintf(p, "\n");
 180                if ((p - page) > PROC_LIMIT) {
 181                        printk(KERN_DEBUG "%s: BSS proc did not fit\n",
 182                               local->dev->name);
 183                        break;
 184                }
 185        }
 186        spin_unlock_bh(&local->lock);
 187
 188        if ((p - page) <= off) {
 189                *eof = 1;
 190                return 0;
 191        }
 192
 193        *start = page + off;
 194
 195        return (p - page - off);
 196}
 197
 198
 199static int prism2_crypt_proc_read(char *page, char **start, off_t off,
 200                                  int count, int *eof, void *data)
 201{
 202        char *p = page;
 203        local_info_t *local = (local_info_t *) data;
 204        int i;
 205
 206        if (off > PROC_LIMIT) {
 207                *eof = 1;
 208                return 0;
 209        }
 210
 211        p += sprintf(p, "tx_keyidx=%d\n", local->tx_keyidx);
 212        for (i = 0; i < WEP_KEYS; i++) {
 213                if (local->crypt[i] && local->crypt[i]->ops &&
 214                    local->crypt[i]->ops->print_stats) {
 215                        p = local->crypt[i]->ops->print_stats(
 216                                p, local->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        DECLARE_MAC_BUF(mac);
 318
 319        p += sprintf(p, "CHID ANL SL BcnInt Capab Rate BSSID ATIM SupRates "
 320                     "SSID\n");
 321
 322        spin_lock_bh(&local->lock);
 323        for (entry = 0; entry < local->last_scan_results_count; entry++) {
 324                scanres = &local->last_scan_results[entry];
 325
 326                if (total + (p - page) <= off) {
 327                        total += p - page;
 328                        p = page;
 329                }
 330                if (total + (p - page) > off + count)
 331                        break;
 332                if ((p - page) > (PAGE_SIZE - 200))
 333                        break;
 334
 335                p += sprintf(p, "%d %d %d %d 0x%02x %d %s %d ",
 336                             le16_to_cpu(scanres->chid),
 337                             (s16) le16_to_cpu(scanres->anl),
 338                             (s16) le16_to_cpu(scanres->sl),
 339                             le16_to_cpu(scanres->beacon_interval),
 340                             le16_to_cpu(scanres->capability),
 341                             le16_to_cpu(scanres->rate),
 342                             print_mac(mac, scanres->bssid),
 343                             le16_to_cpu(scanres->atim));
 344
 345                pos = scanres->sup_rates;
 346                for (i = 0; i < sizeof(scanres->sup_rates); i++) {
 347                        if (pos[i] == 0)
 348                                break;
 349                        p += sprintf(p, "<%02x>", pos[i]);
 350                }
 351                p += sprintf(p, " ");
 352
 353                pos = scanres->ssid;
 354                len = le16_to_cpu(scanres->ssid_len);
 355                if (len > 32)
 356                        len = 32;
 357                for (i = 0; i < len; i++) {
 358                        unsigned char c = pos[i];
 359                        if (c >= 32 && c < 127)
 360                                p += sprintf(p, "%c", c);
 361                        else
 362                                p += sprintf(p, "<%02x>", c);
 363                }
 364                p += sprintf(p, "\n");
 365        }
 366        spin_unlock_bh(&local->lock);
 367
 368        total += (p - page);
 369        if (total >= off + count)
 370                *eof = 1;
 371
 372        if (total < off) {
 373                *eof = 1;
 374                return 0;
 375        }
 376
 377        len = total - off;
 378        if (len > (p - page))
 379                len = p - page;
 380        *start = p - len;
 381        if (len > count)
 382                len = count;
 383
 384        return len;
 385}
 386#endif /* PRISM2_NO_STATION_MODES */
 387
 388
 389void hostap_init_proc(local_info_t *local)
 390{
 391        local->proc = NULL;
 392
 393        if (hostap_proc == NULL) {
 394                printk(KERN_WARNING "%s: hostap proc directory not created\n",
 395                       local->dev->name);
 396                return;
 397        }
 398
 399        local->proc = proc_mkdir(local->ddev->name, hostap_proc);
 400        if (local->proc == NULL) {
 401                printk(KERN_INFO "/proc/net/hostap/%s creation failed\n",
 402                       local->ddev->name);
 403                return;
 404        }
 405
 406#ifndef PRISM2_NO_PROCFS_DEBUG
 407        create_proc_read_entry("debug", 0, local->proc,
 408                               prism2_debug_proc_read, local);
 409#endif /* PRISM2_NO_PROCFS_DEBUG */
 410        create_proc_read_entry("stats", 0, local->proc,
 411                               prism2_stats_proc_read, local);
 412        create_proc_read_entry("wds", 0, local->proc,
 413                               prism2_wds_proc_read, local);
 414        create_proc_read_entry("pda", 0, local->proc,
 415                               prism2_pda_proc_read, local);
 416        create_proc_read_entry("aux_dump", 0, local->proc,
 417                               prism2_aux_dump_proc_read, local);
 418        create_proc_read_entry("bss_list", 0, local->proc,
 419                               prism2_bss_list_proc_read, local);
 420        create_proc_read_entry("crypt", 0, local->proc,
 421                               prism2_crypt_proc_read, local);
 422#ifdef PRISM2_IO_DEBUG
 423        create_proc_read_entry("io_debug", 0, local->proc,
 424                               prism2_io_debug_proc_read, local);
 425#endif /* PRISM2_IO_DEBUG */
 426#ifndef PRISM2_NO_STATION_MODES
 427        create_proc_read_entry("scan_results", 0, local->proc,
 428                               prism2_scan_results_proc_read, local);
 429#endif /* PRISM2_NO_STATION_MODES */
 430}
 431
 432
 433void hostap_remove_proc(local_info_t *local)
 434{
 435        if (local->proc != NULL) {
 436#ifndef PRISM2_NO_STATION_MODES
 437                remove_proc_entry("scan_results", local->proc);
 438#endif /* PRISM2_NO_STATION_MODES */
 439#ifdef PRISM2_IO_DEBUG
 440                remove_proc_entry("io_debug", local->proc);
 441#endif /* PRISM2_IO_DEBUG */
 442                remove_proc_entry("pda", local->proc);
 443                remove_proc_entry("aux_dump", local->proc);
 444                remove_proc_entry("wds", local->proc);
 445                remove_proc_entry("stats", local->proc);
 446                remove_proc_entry("bss_list", local->proc);
 447                remove_proc_entry("crypt", local->proc);
 448#ifndef PRISM2_NO_PROCFS_DEBUG
 449                remove_proc_entry("debug", local->proc);
 450#endif /* PRISM2_NO_PROCFS_DEBUG */
 451                if (hostap_proc != NULL)
 452                        remove_proc_entry(local->proc->name, hostap_proc);
 453        }
 454}
 455
 456
 457EXPORT_SYMBOL(hostap_init_proc);
 458EXPORT_SYMBOL(hostap_remove_proc);
 459
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.