00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <linux/kobject.h>
00012 #include <linux/slab.h>
00013 #include "ieee80211_i.h"
00014 #include "key.h"
00015 #include "debugfs.h"
00016 #include "debugfs_key.h"
00017
00018 #define KEY_READ(name, prop, format_string) \
00019 static ssize_t key_##name##_read(struct file *file, \
00020 char __user *userbuf, \
00021 size_t count, loff_t *ppos) \
00022 { \
00023 struct ieee80211_key *key = file->private_data; \
00024 return mac80211_format_buffer(userbuf, count, ppos, \
00025 format_string, key->prop); \
00026 }
00027 #define KEY_READ_D(name) KEY_READ(name, name, "%d\n")
00028 #define KEY_READ_X(name) KEY_READ(name, name, "0x%x\n")
00029
00030 #define KEY_OPS(name) \
00031 static const struct file_operations key_ ##name## _ops = { \
00032 .read = key_##name##_read, \
00033 .open = mac80211_open_file_generic, \
00034 .llseek = generic_file_llseek, \
00035 }
00036
00037 #define KEY_FILE(name, format) \
00038 KEY_READ_##format(name) \
00039 KEY_OPS(name)
00040
00041 #define KEY_CONF_READ(name, format_string) \
00042 KEY_READ(conf_##name, conf.name, format_string)
00043 #define KEY_CONF_READ_D(name) KEY_CONF_READ(name, "%d\n")
00044
00045 #define KEY_CONF_OPS(name) \
00046 static const struct file_operations key_ ##name## _ops = { \
00047 .read = key_conf_##name##_read, \
00048 .open = mac80211_open_file_generic, \
00049 .llseek = generic_file_llseek, \
00050 }
00051
00052 #define KEY_CONF_FILE(name, format) \
00053 KEY_CONF_READ_##format(name) \
00054 KEY_CONF_OPS(name)
00055
00056 KEY_CONF_FILE(keylen, D);
00057 KEY_CONF_FILE(keyidx, D);
00058 KEY_CONF_FILE(hw_key_idx, D);
00059 KEY_FILE(flags, X);
00060 KEY_FILE(tx_rx_count, D);
00061 KEY_READ(ifindex, sdata->name, "%s\n");
00062 KEY_OPS(ifindex);
00063
00064 static ssize_t key_algorithm_read(struct file *file,
00065 char __user *userbuf,
00066 size_t count, loff_t *ppos)
00067 {
00068 char buf[15];
00069 struct ieee80211_key *key = file->private_data;
00070 u32 c = key->conf.cipher;
00071
00072 sprintf(buf, "%.2x-%.2x-%.2x:%d\n",
00073 c >> 24, (c >> 16) & 0xff, (c >> 8) & 0xff, c & 0xff);
00074 return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf));
00075 }
00076 KEY_OPS(algorithm);
00077
00078 static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf,
00079 size_t count, loff_t *ppos)
00080 {
00081 u64 pn;
00082 char buf[20];
00083 int len;
00084 struct ieee80211_key *key = file->private_data;
00085
00086 switch (key->conf.cipher) {
00087 case WLAN_CIPHER_SUITE_WEP40:
00088 case WLAN_CIPHER_SUITE_WEP104:
00089 len = scnprintf(buf, sizeof(buf), "\n");
00090 break;
00091 case WLAN_CIPHER_SUITE_TKIP:
00092 len = scnprintf(buf, sizeof(buf), "%08x %04x\n",
00093 key->u.tkip.tx.iv32,
00094 key->u.tkip.tx.iv16);
00095 break;
00096 case WLAN_CIPHER_SUITE_CCMP:
00097 pn = atomic64_read(&key->u.ccmp.tx_pn);
00098 len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n",
00099 (u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24),
00100 (u8)(pn >> 16), (u8)(pn >> 8), (u8)pn);
00101 break;
00102 case WLAN_CIPHER_SUITE_AES_CMAC:
00103 pn = atomic64_read(&key->u.aes_cmac.tx_pn);
00104 len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n",
00105 (u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24),
00106 (u8)(pn >> 16), (u8)(pn >> 8), (u8)pn);
00107 break;
00108 default:
00109 return 0;
00110 }
00111 return simple_read_from_buffer(userbuf, count, ppos, buf, len);
00112 }
00113 KEY_OPS(tx_spec);
00114
00115 static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf,
00116 size_t count, loff_t *ppos)
00117 {
00118 struct ieee80211_key *key = file->private_data;
00119 char buf[14*NUM_RX_DATA_QUEUES+1], *p = buf;
00120 int i, len;
00121 const u8 *rpn;
00122
00123 switch (key->conf.cipher) {
00124 case WLAN_CIPHER_SUITE_WEP40:
00125 case WLAN_CIPHER_SUITE_WEP104:
00126 len = scnprintf(buf, sizeof(buf), "\n");
00127 break;
00128 case WLAN_CIPHER_SUITE_TKIP:
00129 for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
00130 p += scnprintf(p, sizeof(buf)+buf-p,
00131 "%08x %04x\n",
00132 key->u.tkip.rx[i].iv32,
00133 key->u.tkip.rx[i].iv16);
00134 len = p - buf;
00135 break;
00136 case WLAN_CIPHER_SUITE_CCMP:
00137 for (i = 0; i < NUM_RX_DATA_QUEUES + 1; i++) {
00138 rpn = key->u.ccmp.rx_pn[i];
00139 p += scnprintf(p, sizeof(buf)+buf-p,
00140 "%02x%02x%02x%02x%02x%02x\n",
00141 rpn[0], rpn[1], rpn[2],
00142 rpn[3], rpn[4], rpn[5]);
00143 }
00144 len = p - buf;
00145 break;
00146 case WLAN_CIPHER_SUITE_AES_CMAC:
00147 rpn = key->u.aes_cmac.rx_pn;
00148 p += scnprintf(p, sizeof(buf)+buf-p,
00149 "%02x%02x%02x%02x%02x%02x\n",
00150 rpn[0], rpn[1], rpn[2],
00151 rpn[3], rpn[4], rpn[5]);
00152 len = p - buf;
00153 break;
00154 default:
00155 return 0;
00156 }
00157 return simple_read_from_buffer(userbuf, count, ppos, buf, len);
00158 }
00159 KEY_OPS(rx_spec);
00160
00161 static ssize_t key_replays_read(struct file *file, char __user *userbuf,
00162 size_t count, loff_t *ppos)
00163 {
00164 struct ieee80211_key *key = file->private_data;
00165 char buf[20];
00166 int len;
00167
00168 switch (key->conf.cipher) {
00169 case WLAN_CIPHER_SUITE_CCMP:
00170 len = scnprintf(buf, sizeof(buf), "%u\n", key->u.ccmp.replays);
00171 break;
00172 case WLAN_CIPHER_SUITE_AES_CMAC:
00173 len = scnprintf(buf, sizeof(buf), "%u\n",
00174 key->u.aes_cmac.replays);
00175 break;
00176 default:
00177 return 0;
00178 }
00179 return simple_read_from_buffer(userbuf, count, ppos, buf, len);
00180 }
00181 KEY_OPS(replays);
00182
00183 static ssize_t key_icverrors_read(struct file *file, char __user *userbuf,
00184 size_t count, loff_t *ppos)
00185 {
00186 struct ieee80211_key *key = file->private_data;
00187 char buf[20];
00188 int len;
00189
00190 switch (key->conf.cipher) {
00191 case WLAN_CIPHER_SUITE_AES_CMAC:
00192 len = scnprintf(buf, sizeof(buf), "%u\n",
00193 key->u.aes_cmac.icverrors);
00194 break;
00195 default:
00196 return 0;
00197 }
00198 return simple_read_from_buffer(userbuf, count, ppos, buf, len);
00199 }
00200 KEY_OPS(icverrors);
00201
00202 static ssize_t key_key_read(struct file *file, char __user *userbuf,
00203 size_t count, loff_t *ppos)
00204 {
00205 struct ieee80211_key *key = file->private_data;
00206 int i, bufsize = 2 * key->conf.keylen + 2;
00207 char *buf = kmalloc(bufsize, GFP_KERNEL);
00208 char *p = buf;
00209 ssize_t res;
00210
00211 if (!buf)
00212 return -ENOMEM;
00213
00214 for (i = 0; i < key->conf.keylen; i++)
00215 p += scnprintf(p, bufsize + buf - p, "%02x", key->conf.key[i]);
00216 p += scnprintf(p, bufsize+buf-p, "\n");
00217 res = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
00218 kfree(buf);
00219 return res;
00220 }
00221 KEY_OPS(key);
00222
00223 #define DEBUGFS_ADD(name) \
00224 debugfs_create_file(#name, 0400, key->debugfs.dir, \
00225 key, &key_##name##_ops);
00226
00227 void ieee80211_debugfs_key_add(struct ieee80211_key *key)
00228 {
00229 static int keycount;
00230 char buf[50];
00231 struct sta_info *sta;
00232
00233 if (!key->local->debugfs.keys)
00234 return;
00235
00236 sprintf(buf, "%d", keycount);
00237 key->debugfs.cnt = keycount;
00238 keycount++;
00239 key->debugfs.dir = debugfs_create_dir(buf,
00240 key->local->debugfs.keys);
00241
00242 if (!key->debugfs.dir)
00243 return;
00244
00245 sta = key->sta;
00246 if (sta) {
00247 sprintf(buf, "../../stations/%pM", sta->sta.addr);
00248 key->debugfs.stalink =
00249 debugfs_create_symlink("station", key->debugfs.dir, buf);
00250 }
00251
00252 DEBUGFS_ADD(keylen);
00253 DEBUGFS_ADD(flags);
00254 DEBUGFS_ADD(keyidx);
00255 DEBUGFS_ADD(hw_key_idx);
00256 DEBUGFS_ADD(tx_rx_count);
00257 DEBUGFS_ADD(algorithm);
00258 DEBUGFS_ADD(tx_spec);
00259 DEBUGFS_ADD(rx_spec);
00260 DEBUGFS_ADD(replays);
00261 DEBUGFS_ADD(icverrors);
00262 DEBUGFS_ADD(key);
00263 DEBUGFS_ADD(ifindex);
00264 };
00265
00266 void ieee80211_debugfs_key_remove(struct ieee80211_key *key)
00267 {
00268 if (!key)
00269 return;
00270
00271 debugfs_remove_recursive(key->debugfs.dir);
00272 key->debugfs.dir = NULL;
00273 }
00274
00275 void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata)
00276 {
00277 char buf[50];
00278 struct ieee80211_key *key;
00279
00280 if (!sdata->debugfs.dir)
00281 return;
00282
00283 lockdep_assert_held(&sdata->local->key_mtx);
00284
00285 if (sdata->default_unicast_key) {
00286 key = key_mtx_dereference(sdata->local,
00287 sdata->default_unicast_key);
00288 sprintf(buf, "../keys/%d", key->debugfs.cnt);
00289 sdata->debugfs.default_unicast_key =
00290 debugfs_create_symlink("default_unicast_key",
00291 sdata->debugfs.dir, buf);
00292 } else {
00293 debugfs_remove(sdata->debugfs.default_unicast_key);
00294 sdata->debugfs.default_unicast_key = NULL;
00295 }
00296
00297 if (sdata->default_multicast_key) {
00298 key = key_mtx_dereference(sdata->local,
00299 sdata->default_multicast_key);
00300 sprintf(buf, "../keys/%d", key->debugfs.cnt);
00301 sdata->debugfs.default_multicast_key =
00302 debugfs_create_symlink("default_multicast_key",
00303 sdata->debugfs.dir, buf);
00304 } else {
00305 debugfs_remove(sdata->debugfs.default_multicast_key);
00306 sdata->debugfs.default_multicast_key = NULL;
00307 }
00308 }
00309
00310 void ieee80211_debugfs_key_add_mgmt_default(struct ieee80211_sub_if_data *sdata)
00311 {
00312 char buf[50];
00313 struct ieee80211_key *key;
00314
00315 if (!sdata->debugfs.dir)
00316 return;
00317
00318 key = key_mtx_dereference(sdata->local,
00319 sdata->default_mgmt_key);
00320 if (key) {
00321 sprintf(buf, "../keys/%d", key->debugfs.cnt);
00322 sdata->debugfs.default_mgmt_key =
00323 debugfs_create_symlink("default_mgmt_key",
00324 sdata->debugfs.dir, buf);
00325 } else
00326 ieee80211_debugfs_key_remove_mgmt_default(sdata);
00327 }
00328
00329 void ieee80211_debugfs_key_remove_mgmt_default(struct ieee80211_sub_if_data *sdata)
00330 {
00331 if (!sdata)
00332 return;
00333
00334 debugfs_remove(sdata->debugfs.default_mgmt_key);
00335 sdata->debugfs.default_mgmt_key = NULL;
00336 }
00337
00338 void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
00339 struct sta_info *sta)
00340 {
00341 debugfs_remove(key->debugfs.stalink);
00342 key->debugfs.stalink = NULL;
00343 }