linux/net/mac80211/debugfs_key.c
<<
>>
Prefs
   1/*
   2 * Copyright 2003-2005  Devicescape Software, Inc.
   3 * Copyright (c) 2006   Jiri Benc <jbenc@suse.cz>
   4 * Copyright 2007       Johannes Berg <johannes@sipsolutions.net>
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2 as
   8 * published by the Free Software Foundation.
   9 */
  10
  11#include <linux/kobject.h>
  12#include "ieee80211_i.h"
  13#include "ieee80211_key.h"
  14#include "debugfs.h"
  15#include "debugfs_key.h"
  16
  17#define KEY_READ(name, prop, buflen, format_string)                     \
  18static ssize_t key_##name##_read(struct file *file,                     \
  19                                 char __user *userbuf,                  \
  20                                 size_t count, loff_t *ppos)            \
  21{                                                                       \
  22        char buf[buflen];                                               \
  23        struct ieee80211_key *key = file->private_data;                 \
  24        int res = scnprintf(buf, buflen, format_string, key->prop);     \
  25        return simple_read_from_buffer(userbuf, count, ppos, buf, res); \
  26}
  27#define KEY_READ_D(name) KEY_READ(name, name, 20, "%d\n")
  28#define KEY_READ_X(name) KEY_READ(name, name, 20, "0x%x\n")
  29
  30#define KEY_OPS(name)                                                   \
  31static const struct file_operations key_ ##name## _ops = {              \
  32        .read = key_##name##_read,                                      \
  33        .open = mac80211_open_file_generic,                             \
  34}
  35
  36#define KEY_FILE(name, format)                                          \
  37                 KEY_READ_##format(name)                                \
  38                 KEY_OPS(name)
  39
  40#define KEY_CONF_READ(name, buflen, format_string)                      \
  41        KEY_READ(conf_##name, conf.name, buflen, format_string)
  42#define KEY_CONF_READ_D(name) KEY_CONF_READ(name, 20, "%d\n")
  43
  44#define KEY_CONF_OPS(name)                                              \
  45static const struct file_operations key_ ##name## _ops = {              \
  46        .read = key_conf_##name##_read,                                 \
  47        .open = mac80211_open_file_generic,                             \
  48}
  49
  50#define KEY_CONF_FILE(name, format)                                     \
  51                 KEY_CONF_READ_##format(name)                           \
  52                 KEY_CONF_OPS(name)
  53
  54KEY_CONF_FILE(keylen, D);
  55KEY_CONF_FILE(keyidx, D);
  56KEY_CONF_FILE(hw_key_idx, D);
  57KEY_FILE(flags, X);
  58KEY_FILE(tx_rx_count, D);
  59KEY_READ(ifindex, sdata->dev->ifindex, 20, "%d\n");
  60KEY_OPS(ifindex);
  61
  62static ssize_t key_algorithm_read(struct file *file,
  63                                  char __user *userbuf,
  64                                  size_t count, loff_t *ppos)
  65{
  66        char *alg;
  67        struct ieee80211_key *key = file->private_data;
  68
  69        switch (key->conf.alg) {
  70        case ALG_WEP:
  71                alg = "WEP\n";
  72                break;
  73        case ALG_TKIP:
  74                alg = "TKIP\n";
  75                break;
  76        case ALG_CCMP:
  77                alg = "CCMP\n";
  78                break;
  79        default:
  80                return 0;
  81        }
  82        return simple_read_from_buffer(userbuf, count, ppos, alg, strlen(alg));
  83}
  84KEY_OPS(algorithm);
  85
  86static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf,
  87                                size_t count, loff_t *ppos)
  88{
  89        const u8 *tpn;
  90        char buf[20];
  91        int len;
  92        struct ieee80211_key *key = file->private_data;
  93
  94        switch (key->conf.alg) {
  95        case ALG_WEP:
  96                len = scnprintf(buf, sizeof(buf), "\n");
  97                break;
  98        case ALG_TKIP:
  99                len = scnprintf(buf, sizeof(buf), "%08x %04x\n",
 100                                key->u.tkip.iv32,
 101                                key->u.tkip.iv16);
 102                break;
 103        case ALG_CCMP:
 104                tpn = key->u.ccmp.tx_pn;
 105                len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n",
 106                                tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], tpn[5]);
 107                break;
 108        default:
 109                return 0;
 110        }
 111        return simple_read_from_buffer(userbuf, count, ppos, buf, len);
 112}
 113KEY_OPS(tx_spec);
 114
 115static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf,
 116                                size_t count, loff_t *ppos)
 117{
 118        struct ieee80211_key *key = file->private_data;
 119        char buf[14*NUM_RX_DATA_QUEUES+1], *p = buf;
 120        int i, len;
 121        const u8 *rpn;
 122
 123        switch (key->conf.alg) {
 124        case ALG_WEP:
 125                len = scnprintf(buf, sizeof(buf), "\n");
 126                break;
 127        case ALG_TKIP:
 128                for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
 129                        p += scnprintf(p, sizeof(buf)+buf-p,
 130                                       "%08x %04x\n",
 131                                       key->u.tkip.iv32_rx[i],
 132                                       key->u.tkip.iv16_rx[i]);
 133                len = p - buf;
 134                break;
 135        case ALG_CCMP:
 136                for (i = 0; i < NUM_RX_DATA_QUEUES; i++) {
 137                        rpn = key->u.ccmp.rx_pn[i];
 138                        p += scnprintf(p, sizeof(buf)+buf-p,
 139                                       "%02x%02x%02x%02x%02x%02x\n",
 140                                       rpn[0], rpn[1], rpn[2],
 141                                       rpn[3], rpn[4], rpn[5]);
 142                }
 143                len = p - buf;
 144                break;
 145        default:
 146                return 0;
 147        }
 148        return simple_read_from_buffer(userbuf, count, ppos, buf, len);
 149}
 150KEY_OPS(rx_spec);
 151
 152static ssize_t key_replays_read(struct file *file, char __user *userbuf,
 153                                size_t count, loff_t *ppos)
 154{
 155        struct ieee80211_key *key = file->private_data;
 156        char buf[20];
 157        int len;
 158
 159        if (key->conf.alg != ALG_CCMP)
 160                return 0;
 161        len = scnprintf(buf, sizeof(buf), "%u\n", key->u.ccmp.replays);
 162        return simple_read_from_buffer(userbuf, count, ppos, buf, len);
 163}
 164KEY_OPS(replays);
 165
 166static ssize_t key_key_read(struct file *file, char __user *userbuf,
 167                            size_t count, loff_t *ppos)
 168{
 169        struct ieee80211_key *key = file->private_data;
 170        int i, res, bufsize = 2 * key->conf.keylen + 2;
 171        char *buf = kmalloc(bufsize, GFP_KERNEL);
 172        char *p = buf;
 173
 174        for (i = 0; i < key->conf.keylen; i++)
 175                p += scnprintf(p, bufsize + buf - p, "%02x", key->conf.key[i]);
 176        p += scnprintf(p, bufsize+buf-p, "\n");
 177        res = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
 178        kfree(buf);
 179        return res;
 180}
 181KEY_OPS(key);
 182
 183#define DEBUGFS_ADD(name) \
 184        key->debugfs.name = debugfs_create_file(#name, 0400,\
 185                                key->debugfs.dir, key, &key_##name##_ops);
 186
 187void ieee80211_debugfs_key_add(struct ieee80211_local *local,
 188                               struct ieee80211_key *key)
 189{
 190        static int keycount;
 191        char buf[20];
 192
 193        if (!local->debugfs.keys)
 194                return;
 195
 196        sprintf(buf, "%d", keycount);
 197        keycount++;
 198        key->debugfs.dir = debugfs_create_dir(buf,
 199                                        local->debugfs.keys);
 200
 201        if (!key->debugfs.dir)
 202                return;
 203
 204        DEBUGFS_ADD(keylen);
 205        DEBUGFS_ADD(flags);
 206        DEBUGFS_ADD(keyidx);
 207        DEBUGFS_ADD(hw_key_idx);
 208        DEBUGFS_ADD(tx_rx_count);
 209        DEBUGFS_ADD(algorithm);
 210        DEBUGFS_ADD(tx_spec);
 211        DEBUGFS_ADD(rx_spec);
 212        DEBUGFS_ADD(replays);
 213        DEBUGFS_ADD(key);
 214        DEBUGFS_ADD(ifindex);
 215};
 216
 217#define DEBUGFS_DEL(name) \
 218        debugfs_remove(key->debugfs.name); key->debugfs.name = NULL;
 219
 220void ieee80211_debugfs_key_remove(struct ieee80211_key *key)
 221{
 222        if (!key)
 223                return;
 224
 225        DEBUGFS_DEL(keylen);
 226        DEBUGFS_DEL(flags);
 227        DEBUGFS_DEL(keyidx);
 228        DEBUGFS_DEL(hw_key_idx);
 229        DEBUGFS_DEL(tx_rx_count);
 230        DEBUGFS_DEL(algorithm);
 231        DEBUGFS_DEL(tx_spec);
 232        DEBUGFS_DEL(rx_spec);
 233        DEBUGFS_DEL(replays);
 234        DEBUGFS_DEL(key);
 235        DEBUGFS_DEL(ifindex);
 236
 237        debugfs_remove(key->debugfs.stalink);
 238        key->debugfs.stalink = NULL;
 239        debugfs_remove(key->debugfs.dir);
 240        key->debugfs.dir = NULL;
 241}
 242void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata)
 243{
 244        char buf[50];
 245
 246        if (!sdata->debugfsdir)
 247                return;
 248
 249        sprintf(buf, "../keys/%d", sdata->default_key->conf.keyidx);
 250        sdata->debugfs.default_key =
 251                debugfs_create_symlink("default_key", sdata->debugfsdir, buf);
 252}
 253void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata)
 254{
 255        if (!sdata)
 256                return;
 257
 258        debugfs_remove(sdata->debugfs.default_key);
 259        sdata->debugfs.default_key = NULL;
 260}
 261void ieee80211_debugfs_key_sta_link(struct ieee80211_key *key,
 262                                    struct sta_info *sta)
 263{
 264        char buf[50];
 265        DECLARE_MAC_BUF(mac);
 266
 267        if (!key->debugfs.dir)
 268                return;
 269
 270        sprintf(buf, "../../stations/%s", print_mac(mac, sta->addr));
 271        key->debugfs.stalink =
 272                debugfs_create_symlink("station", key->debugfs.dir, buf);
 273}
 274
 275void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
 276                                   struct sta_info *sta)
 277{
 278        debugfs_remove(key->debugfs.stalink);
 279        key->debugfs.stalink = NULL;
 280}
 281