linux/net/mac80211/debugfs_netdev.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2006   Jiri Benc <jbenc@suse.cz>
   3 * Copyright 2007       Johannes Berg <johannes@sipsolutions.net>
   4 *
   5 * This program is free software; you can redistribute it and/or modify
   6 * it under the terms of the GNU General Public License version 2 as
   7 * published by the Free Software Foundation.
   8 */
   9
  10#include <linux/kernel.h>
  11#include <linux/device.h>
  12#include <linux/if.h>
  13#include <linux/interrupt.h>
  14#include <linux/netdevice.h>
  15#include <linux/rtnetlink.h>
  16#include <linux/notifier.h>
  17#include <net/mac80211.h>
  18#include <net/cfg80211.h>
  19#include "ieee80211_i.h"
  20#include "ieee80211_rate.h"
  21#include "debugfs.h"
  22#include "debugfs_netdev.h"
  23
  24static ssize_t ieee80211_if_read(
  25        struct ieee80211_sub_if_data *sdata,
  26        char __user *userbuf,
  27        size_t count, loff_t *ppos,
  28        ssize_t (*format)(const struct ieee80211_sub_if_data *, char *, int))
  29{
  30        char buf[70];
  31        ssize_t ret = -EINVAL;
  32
  33        read_lock(&dev_base_lock);
  34        if (sdata->dev->reg_state == NETREG_REGISTERED) {
  35                ret = (*format)(sdata, buf, sizeof(buf));
  36                ret = simple_read_from_buffer(userbuf, count, ppos, buf, ret);
  37        }
  38        read_unlock(&dev_base_lock);
  39        return ret;
  40}
  41
  42#define IEEE80211_IF_FMT(name, field, format_string)                    \
  43static ssize_t ieee80211_if_fmt_##name(                                 \
  44        const struct ieee80211_sub_if_data *sdata, char *buf,           \
  45        int buflen)                                                     \
  46{                                                                       \
  47        return scnprintf(buf, buflen, format_string, sdata->field);     \
  48}
  49#define IEEE80211_IF_FMT_DEC(name, field)                               \
  50                IEEE80211_IF_FMT(name, field, "%d\n")
  51#define IEEE80211_IF_FMT_HEX(name, field)                               \
  52                IEEE80211_IF_FMT(name, field, "%#x\n")
  53#define IEEE80211_IF_FMT_SIZE(name, field)                              \
  54                IEEE80211_IF_FMT(name, field, "%zd\n")
  55
  56#define IEEE80211_IF_FMT_ATOMIC(name, field)                            \
  57static ssize_t ieee80211_if_fmt_##name(                                 \
  58        const struct ieee80211_sub_if_data *sdata,                      \
  59        char *buf, int buflen)                                          \
  60{                                                                       \
  61        return scnprintf(buf, buflen, "%d\n", atomic_read(&sdata->field));\
  62}
  63
  64#define IEEE80211_IF_FMT_MAC(name, field)                               \
  65static ssize_t ieee80211_if_fmt_##name(                                 \
  66        const struct ieee80211_sub_if_data *sdata, char *buf,           \
  67        int buflen)                                                     \
  68{                                                                       \
  69        return scnprintf(buf, buflen, MAC_FMT "\n", MAC_ARG(sdata->field));\
  70}
  71
  72#define __IEEE80211_IF_FILE(name)                                       \
  73static ssize_t ieee80211_if_read_##name(struct file *file,              \
  74                                        char __user *userbuf,           \
  75                                        size_t count, loff_t *ppos)     \
  76{                                                                       \
  77        return ieee80211_if_read(file->private_data,                    \
  78                                 userbuf, count, ppos,                  \
  79                                 ieee80211_if_fmt_##name);              \
  80}                                                                       \
  81static const struct file_operations name##_ops = {                      \
  82        .read = ieee80211_if_read_##name,                               \
  83        .open = mac80211_open_file_generic,                             \
  84}
  85
  86#define IEEE80211_IF_FILE(name, field, format)                          \
  87                IEEE80211_IF_FMT_##format(name, field)                  \
  88                __IEEE80211_IF_FILE(name)
  89
  90/* common attributes */
  91IEEE80211_IF_FILE(channel_use, channel_use, DEC);
  92IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC);
  93IEEE80211_IF_FILE(eapol, eapol, DEC);
  94IEEE80211_IF_FILE(ieee8021_x, ieee802_1x, DEC);
  95
  96/* STA/IBSS attributes */
  97IEEE80211_IF_FILE(state, u.sta.state, DEC);
  98IEEE80211_IF_FILE(bssid, u.sta.bssid, MAC);
  99IEEE80211_IF_FILE(prev_bssid, u.sta.prev_bssid, MAC);
 100IEEE80211_IF_FILE(ssid_len, u.sta.ssid_len, SIZE);
 101IEEE80211_IF_FILE(aid, u.sta.aid, DEC);
 102IEEE80211_IF_FILE(ap_capab, u.sta.ap_capab, HEX);
 103IEEE80211_IF_FILE(capab, u.sta.capab, HEX);
 104IEEE80211_IF_FILE(extra_ie_len, u.sta.extra_ie_len, SIZE);
 105IEEE80211_IF_FILE(auth_tries, u.sta.auth_tries, DEC);
 106IEEE80211_IF_FILE(assoc_tries, u.sta.assoc_tries, DEC);
 107IEEE80211_IF_FILE(auth_algs, u.sta.auth_algs, HEX);
 108IEEE80211_IF_FILE(auth_alg, u.sta.auth_alg, DEC);
 109IEEE80211_IF_FILE(auth_transaction, u.sta.auth_transaction, DEC);
 110
 111static ssize_t ieee80211_if_fmt_flags(
 112        const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
 113{
 114        return scnprintf(buf, buflen, "%s%s%s%s%s%s%s\n",
 115                         sdata->u.sta.ssid_set ? "SSID\n" : "",
 116                         sdata->u.sta.bssid_set ? "BSSID\n" : "",
 117                         sdata->u.sta.prev_bssid_set ? "prev BSSID\n" : "",
 118                         sdata->u.sta.authenticated ? "AUTH\n" : "",
 119                         sdata->u.sta.associated ? "ASSOC\n" : "",
 120                         sdata->u.sta.probereq_poll ? "PROBEREQ POLL\n" : "",
 121                         sdata->u.sta.use_protection ? "CTS prot\n" : "");
 122}
 123__IEEE80211_IF_FILE(flags);
 124
 125/* AP attributes */
 126IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC);
 127IEEE80211_IF_FILE(dtim_period, u.ap.dtim_period, DEC);
 128IEEE80211_IF_FILE(dtim_count, u.ap.dtim_count, DEC);
 129IEEE80211_IF_FILE(num_beacons, u.ap.num_beacons, DEC);
 130IEEE80211_IF_FILE(force_unicast_rateidx, u.ap.force_unicast_rateidx, DEC);
 131IEEE80211_IF_FILE(max_ratectrl_rateidx, u.ap.max_ratectrl_rateidx, DEC);
 132
 133static ssize_t ieee80211_if_fmt_num_buffered_multicast(
 134        const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
 135{
 136        return scnprintf(buf, buflen, "%u\n",
 137                         skb_queue_len(&sdata->u.ap.ps_bc_buf));
 138}
 139__IEEE80211_IF_FILE(num_buffered_multicast);
 140
 141static ssize_t ieee80211_if_fmt_beacon_head_len(
 142        const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
 143{
 144        if (sdata->u.ap.beacon_head)
 145                return scnprintf(buf, buflen, "%d\n",
 146                                 sdata->u.ap.beacon_head_len);
 147        return scnprintf(buf, buflen, "\n");
 148}
 149__IEEE80211_IF_FILE(beacon_head_len);
 150
 151static ssize_t ieee80211_if_fmt_beacon_tail_len(
 152        const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
 153{
 154        if (sdata->u.ap.beacon_tail)
 155                return scnprintf(buf, buflen, "%d\n",
 156                                 sdata->u.ap.beacon_tail_len);
 157        return scnprintf(buf, buflen, "\n");
 158}
 159__IEEE80211_IF_FILE(beacon_tail_len);
 160
 161/* WDS attributes */
 162IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC);
 163
 164/* VLAN attributes */
 165IEEE80211_IF_FILE(vlan_id, u.vlan.id, DEC);
 166
 167/* MONITOR attributes */
 168static ssize_t ieee80211_if_fmt_mode(
 169        const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
 170{
 171        struct ieee80211_local *local = sdata->local;
 172
 173        return scnprintf(buf, buflen, "%s\n",
 174                         ((local->hw.flags & IEEE80211_HW_MONITOR_DURING_OPER) ||
 175                          local->open_count == local->monitors) ?
 176                         "hard" : "soft");
 177}
 178__IEEE80211_IF_FILE(mode);
 179
 180
 181#define DEBUGFS_ADD(name, type)\
 182        sdata->debugfs.type.name = debugfs_create_file(#name, 0444,\
 183                sdata->debugfsdir, sdata, &name##_ops);
 184
 185static void add_sta_files(struct ieee80211_sub_if_data *sdata)
 186{
 187        DEBUGFS_ADD(channel_use, sta);
 188        DEBUGFS_ADD(drop_unencrypted, sta);
 189        DEBUGFS_ADD(eapol, sta);
 190        DEBUGFS_ADD(ieee8021_x, sta);
 191        DEBUGFS_ADD(state, sta);
 192        DEBUGFS_ADD(bssid, sta);
 193        DEBUGFS_ADD(prev_bssid, sta);
 194        DEBUGFS_ADD(ssid_len, sta);
 195        DEBUGFS_ADD(aid, sta);
 196        DEBUGFS_ADD(ap_capab, sta);
 197        DEBUGFS_ADD(capab, sta);
 198        DEBUGFS_ADD(extra_ie_len, sta);
 199        DEBUGFS_ADD(auth_tries, sta);
 200        DEBUGFS_ADD(assoc_tries, sta);
 201        DEBUGFS_ADD(auth_algs, sta);
 202        DEBUGFS_ADD(auth_alg, sta);
 203        DEBUGFS_ADD(auth_transaction, sta);
 204        DEBUGFS_ADD(flags, sta);
 205}
 206
 207static void add_ap_files(struct ieee80211_sub_if_data *sdata)
 208{
 209        DEBUGFS_ADD(channel_use, ap);
 210        DEBUGFS_ADD(drop_unencrypted, ap);
 211        DEBUGFS_ADD(eapol, ap);
 212        DEBUGFS_ADD(ieee8021_x, ap);
 213        DEBUGFS_ADD(num_sta_ps, ap);
 214        DEBUGFS_ADD(dtim_period, ap);
 215        DEBUGFS_ADD(dtim_count, ap);
 216        DEBUGFS_ADD(num_beacons, ap);
 217        DEBUGFS_ADD(force_unicast_rateidx, ap);
 218        DEBUGFS_ADD(max_ratectrl_rateidx, ap);
 219        DEBUGFS_ADD(num_buffered_multicast, ap);
 220        DEBUGFS_ADD(beacon_head_len, ap);
 221        DEBUGFS_ADD(beacon_tail_len, ap);
 222}
 223
 224static void add_wds_files(struct ieee80211_sub_if_data *sdata)
 225{
 226        DEBUGFS_ADD(channel_use, wds);
 227        DEBUGFS_ADD(drop_unencrypted, wds);
 228        DEBUGFS_ADD(eapol, wds);
 229        DEBUGFS_ADD(ieee8021_x, wds);
 230        DEBUGFS_ADD(peer, wds);
 231}
 232
 233static void add_vlan_files(struct ieee80211_sub_if_data *sdata)
 234{
 235        DEBUGFS_ADD(channel_use, vlan);
 236        DEBUGFS_ADD(drop_unencrypted, vlan);
 237        DEBUGFS_ADD(eapol, vlan);
 238        DEBUGFS_ADD(ieee8021_x, vlan);
 239        DEBUGFS_ADD(vlan_id, vlan);
 240}
 241
 242static void add_monitor_files(struct ieee80211_sub_if_data *sdata)
 243{
 244        DEBUGFS_ADD(mode, monitor);
 245}
 246
 247static void add_files(struct ieee80211_sub_if_data *sdata)
 248{
 249        if (!sdata->debugfsdir)
 250                return;
 251
 252        switch (sdata->type) {
 253        case IEEE80211_IF_TYPE_STA:
 254        case IEEE80211_IF_TYPE_IBSS:
 255                add_sta_files(sdata);
 256                break;
 257        case IEEE80211_IF_TYPE_AP:
 258                add_ap_files(sdata);
 259                break;
 260        case IEEE80211_IF_TYPE_WDS:
 261                add_wds_files(sdata);
 262                break;
 263        case IEEE80211_IF_TYPE_MNTR:
 264                add_monitor_files(sdata);
 265                break;
 266        case IEEE80211_IF_TYPE_VLAN:
 267                add_vlan_files(sdata);
 268                break;
 269        default:
 270                break;
 271        }
 272}
 273
 274#define DEBUGFS_DEL(name, type)\
 275        debugfs_remove(sdata->debugfs.type.name);\
 276        sdata->debugfs.type.name = NULL;
 277
 278static void del_sta_files(struct ieee80211_sub_if_data *sdata)
 279{
 280        DEBUGFS_DEL(channel_use, sta);
 281        DEBUGFS_DEL(drop_unencrypted, sta);
 282        DEBUGFS_DEL(eapol, sta);
 283        DEBUGFS_DEL(ieee8021_x, sta);
 284        DEBUGFS_DEL(state, sta);
 285        DEBUGFS_DEL(bssid, sta);
 286        DEBUGFS_DEL(prev_bssid, sta);
 287        DEBUGFS_DEL(ssid_len, sta);
 288        DEBUGFS_DEL(aid, sta);
 289        DEBUGFS_DEL(ap_capab, sta);
 290        DEBUGFS_DEL(capab, sta);
 291        DEBUGFS_DEL(extra_ie_len, sta);
 292        DEBUGFS_DEL(auth_tries, sta);
 293        DEBUGFS_DEL(assoc_tries, sta);
 294        DEBUGFS_DEL(auth_algs, sta);
 295        DEBUGFS_DEL(auth_alg, sta);
 296        DEBUGFS_DEL(auth_transaction, sta);
 297        DEBUGFS_DEL(flags, sta);
 298}
 299
 300static void del_ap_files(struct ieee80211_sub_if_data *sdata)
 301{
 302        DEBUGFS_DEL(channel_use, ap);
 303        DEBUGFS_DEL(drop_unencrypted, ap);
 304        DEBUGFS_DEL(eapol, ap);
 305        DEBUGFS_DEL(ieee8021_x, ap);
 306        DEBUGFS_DEL(num_sta_ps, ap);
 307        DEBUGFS_DEL(dtim_period, ap);
 308        DEBUGFS_DEL(dtim_count, ap);
 309        DEBUGFS_DEL(num_beacons, ap);
 310        DEBUGFS_DEL(force_unicast_rateidx, ap);
 311        DEBUGFS_DEL(max_ratectrl_rateidx, ap);
 312        DEBUGFS_DEL(num_buffered_multicast, ap);
 313        DEBUGFS_DEL(beacon_head_len, ap);
 314        DEBUGFS_DEL(beacon_tail_len, ap);
 315}
 316
 317static void del_wds_files(struct ieee80211_sub_if_data *sdata)
 318{
 319        DEBUGFS_DEL(channel_use, wds);
 320        DEBUGFS_DEL(drop_unencrypted, wds);
 321        DEBUGFS_DEL(eapol, wds);
 322        DEBUGFS_DEL(ieee8021_x, wds);
 323        DEBUGFS_DEL(peer, wds);
 324}
 325
 326static void del_vlan_files(struct ieee80211_sub_if_data *sdata)
 327{
 328        DEBUGFS_DEL(channel_use, vlan);
 329        DEBUGFS_DEL(drop_unencrypted, vlan);
 330        DEBUGFS_DEL(eapol, vlan);
 331        DEBUGFS_DEL(ieee8021_x, vlan);
 332        DEBUGFS_DEL(vlan_id, vlan);
 333}
 334
 335static void del_monitor_files(struct ieee80211_sub_if_data *sdata)
 336{
 337        DEBUGFS_DEL(mode, monitor);
 338}
 339
 340static void del_files(struct ieee80211_sub_if_data *sdata, int type)
 341{
 342        if (!sdata->debugfsdir)
 343                return;
 344
 345        switch (type) {
 346        case IEEE80211_IF_TYPE_STA:
 347        case IEEE80211_IF_TYPE_IBSS:
 348                del_sta_files(sdata);
 349                break;
 350        case IEEE80211_IF_TYPE_AP:
 351                del_ap_files(sdata);
 352                break;
 353        case IEEE80211_IF_TYPE_WDS:
 354                del_wds_files(sdata);
 355                break;
 356        case IEEE80211_IF_TYPE_MNTR:
 357                del_monitor_files(sdata);
 358                break;
 359        case IEEE80211_IF_TYPE_VLAN:
 360                del_vlan_files(sdata);
 361                break;
 362        default:
 363                break;
 364        }
 365}
 366
 367static int notif_registered;
 368
 369void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata)
 370{
 371        char buf[10+IFNAMSIZ];
 372
 373        if (!notif_registered)
 374                return;
 375
 376        sprintf(buf, "netdev:%s", sdata->dev->name);
 377        sdata->debugfsdir = debugfs_create_dir(buf,
 378                sdata->local->hw.wiphy->debugfsdir);
 379}
 380
 381void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata)
 382{
 383        del_files(sdata, sdata->type);
 384        debugfs_remove(sdata->debugfsdir);
 385        sdata->debugfsdir = NULL;
 386}
 387
 388void ieee80211_debugfs_change_if_type(struct ieee80211_sub_if_data *sdata,
 389                                      int oldtype)
 390{
 391        del_files(sdata, oldtype);
 392        add_files(sdata);
 393}
 394
 395static int netdev_notify(struct notifier_block * nb,
 396                         unsigned long state,
 397                         void *ndev)
 398{
 399        struct net_device *dev = ndev;
 400        char buf[10+IFNAMSIZ];
 401
 402        if (state != NETDEV_CHANGENAME)
 403                return 0;
 404
 405        if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy)
 406                return 0;
 407
 408        if (dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid)
 409                return 0;
 410
 411        /* TODO
 412        sprintf(buf, "netdev:%s", dev->name);
 413        debugfs_rename(IEEE80211_DEV_TO_SUB_IF(dev)->debugfsdir, buf);
 414        */
 415
 416        return 0;
 417}
 418
 419static struct notifier_block mac80211_debugfs_netdev_notifier = {
 420        .notifier_call = netdev_notify,
 421};
 422
 423void ieee80211_debugfs_netdev_init(void)
 424{
 425        int err;
 426
 427        err = register_netdevice_notifier(&mac80211_debugfs_netdev_notifier);
 428        if (err) {
 429                printk(KERN_ERR
 430                       "mac80211: failed to install netdev notifier,"
 431                       " disabling per-netdev debugfs!\n");
 432        } else
 433                notif_registered = 1;
 434}
 435
 436void ieee80211_debugfs_netdev_exit(void)
 437{
 438        unregister_netdevice_notifier(&mac80211_debugfs_netdev_notifier);
 439        notif_registered = 0;
 440}
 441
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.