1e9f207f0SJiri Benc /* 2e9f207f0SJiri Benc * Copyright 2003-2005 Devicescape Software, Inc. 3e9f207f0SJiri Benc * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz> 4e9f207f0SJiri Benc * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> 5e9f207f0SJiri Benc * 6e9f207f0SJiri Benc * This program is free software; you can redistribute it and/or modify 7e9f207f0SJiri Benc * it under the terms of the GNU General Public License version 2 as 8e9f207f0SJiri Benc * published by the Free Software Foundation. 9e9f207f0SJiri Benc */ 10e9f207f0SJiri Benc 11e9f207f0SJiri Benc #include <linux/kobject.h> 125a0e3ad6STejun Heo #include <linux/slab.h> 13e9f207f0SJiri Benc #include "ieee80211_i.h" 142c8dccc7SJohannes Berg #include "key.h" 15e9f207f0SJiri Benc #include "debugfs.h" 16e9f207f0SJiri Benc #include "debugfs_key.h" 17e9f207f0SJiri Benc 1807caf9d6SEliad Peller #define KEY_READ(name, prop, format_string) \ 19e9f207f0SJiri Benc static ssize_t key_##name##_read(struct file *file, \ 20e9f207f0SJiri Benc char __user *userbuf, \ 21e9f207f0SJiri Benc size_t count, loff_t *ppos) \ 22e9f207f0SJiri Benc { \ 23e9f207f0SJiri Benc struct ieee80211_key *key = file->private_data; \ 2407caf9d6SEliad Peller return mac80211_format_buffer(userbuf, count, ppos, \ 2507caf9d6SEliad Peller format_string, key->prop); \ 26e9f207f0SJiri Benc } 2707caf9d6SEliad Peller #define KEY_READ_D(name) KEY_READ(name, name, "%d\n") 2807caf9d6SEliad Peller #define KEY_READ_X(name) KEY_READ(name, name, "0x%x\n") 29e9f207f0SJiri Benc 30e9f207f0SJiri Benc #define KEY_OPS(name) \ 31e9f207f0SJiri Benc static const struct file_operations key_ ##name## _ops = { \ 32e9f207f0SJiri Benc .read = key_##name##_read, \ 33234e3405SStephen Boyd .open = simple_open, \ 342b18ab36SArnd Bergmann .llseek = generic_file_llseek, \ 35e9f207f0SJiri Benc } 36e9f207f0SJiri Benc 37e9f207f0SJiri Benc #define KEY_FILE(name, format) \ 38e9f207f0SJiri Benc KEY_READ_##format(name) \ 39e9f207f0SJiri Benc KEY_OPS(name) 40e9f207f0SJiri Benc 4107caf9d6SEliad Peller #define KEY_CONF_READ(name, format_string) \ 4207caf9d6SEliad Peller KEY_READ(conf_##name, conf.name, format_string) 4307caf9d6SEliad Peller #define KEY_CONF_READ_D(name) KEY_CONF_READ(name, "%d\n") 448f20fc24SJohannes Berg 458f20fc24SJohannes Berg #define KEY_CONF_OPS(name) \ 468f20fc24SJohannes Berg static const struct file_operations key_ ##name## _ops = { \ 478f20fc24SJohannes Berg .read = key_conf_##name##_read, \ 48234e3405SStephen Boyd .open = simple_open, \ 492b18ab36SArnd Bergmann .llseek = generic_file_llseek, \ 508f20fc24SJohannes Berg } 518f20fc24SJohannes Berg 528f20fc24SJohannes Berg #define KEY_CONF_FILE(name, format) \ 538f20fc24SJohannes Berg KEY_CONF_READ_##format(name) \ 548f20fc24SJohannes Berg KEY_CONF_OPS(name) 558f20fc24SJohannes Berg 568f20fc24SJohannes Berg KEY_CONF_FILE(keylen, D); 578f20fc24SJohannes Berg KEY_CONF_FILE(keyidx, D); 588f20fc24SJohannes Berg KEY_CONF_FILE(hw_key_idx, D); 5911a843b7SJohannes Berg KEY_FILE(flags, X); 60e9f207f0SJiri Benc KEY_FILE(tx_rx_count, D); 6107caf9d6SEliad Peller KEY_READ(ifindex, sdata->name, "%s\n"); 62e7a64f12SJohannes Berg KEY_OPS(ifindex); 63e9f207f0SJiri Benc 64e9f207f0SJiri Benc static ssize_t key_algorithm_read(struct file *file, 65e9f207f0SJiri Benc char __user *userbuf, 66e9f207f0SJiri Benc size_t count, loff_t *ppos) 67e9f207f0SJiri Benc { 6897359d12SJohannes Berg char buf[15]; 69e9f207f0SJiri Benc struct ieee80211_key *key = file->private_data; 7097359d12SJohannes Berg u32 c = key->conf.cipher; 71e9f207f0SJiri Benc 7297359d12SJohannes Berg sprintf(buf, "%.2x-%.2x-%.2x:%d\n", 7397359d12SJohannes Berg c >> 24, (c >> 16) & 0xff, (c >> 8) & 0xff, c & 0xff); 7497359d12SJohannes Berg return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf)); 75e9f207f0SJiri Benc } 76e9f207f0SJiri Benc KEY_OPS(algorithm); 77e9f207f0SJiri Benc 78e9f207f0SJiri Benc static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf, 79e9f207f0SJiri Benc size_t count, loff_t *ppos) 80e9f207f0SJiri Benc { 81aba83a0bSJohannes Berg u64 pn; 82e9f207f0SJiri Benc char buf[20]; 83e9f207f0SJiri Benc int len; 84e9f207f0SJiri Benc struct ieee80211_key *key = file->private_data; 85e9f207f0SJiri Benc 8697359d12SJohannes Berg switch (key->conf.cipher) { 8797359d12SJohannes Berg case WLAN_CIPHER_SUITE_WEP40: 8897359d12SJohannes Berg case WLAN_CIPHER_SUITE_WEP104: 89e9f207f0SJiri Benc len = scnprintf(buf, sizeof(buf), "\n"); 9050339a67SJohannes Berg break; 9197359d12SJohannes Berg case WLAN_CIPHER_SUITE_TKIP: 92e9f207f0SJiri Benc len = scnprintf(buf, sizeof(buf), "%08x %04x\n", 93b0f76b33SHarvey Harrison key->u.tkip.tx.iv32, 94b0f76b33SHarvey Harrison key->u.tkip.tx.iv16); 9550339a67SJohannes Berg break; 9697359d12SJohannes Berg case WLAN_CIPHER_SUITE_CCMP: 972b2ba0dbSJouni Malinen case WLAN_CIPHER_SUITE_CCMP_256: 98aba83a0bSJohannes Berg pn = atomic64_read(&key->u.ccmp.tx_pn); 99e9f207f0SJiri Benc len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", 100aba83a0bSJohannes Berg (u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24), 101aba83a0bSJohannes Berg (u8)(pn >> 16), (u8)(pn >> 8), (u8)pn); 10250339a67SJohannes Berg break; 10397359d12SJohannes Berg case WLAN_CIPHER_SUITE_AES_CMAC: 10475396ae6SJohannes Berg pn = atomic64_read(&key->u.aes_cmac.tx_pn); 1053cfcf6acSJouni Malinen len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", 10675396ae6SJohannes Berg (u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24), 10775396ae6SJohannes Berg (u8)(pn >> 16), (u8)(pn >> 8), (u8)pn); 1083cfcf6acSJouni Malinen break; 10900b9cfa3SJouni Malinen case WLAN_CIPHER_SUITE_GCMP: 11000b9cfa3SJouni Malinen case WLAN_CIPHER_SUITE_GCMP_256: 11100b9cfa3SJouni Malinen pn = atomic64_read(&key->u.gcmp.tx_pn); 11200b9cfa3SJouni Malinen len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", 11300b9cfa3SJouni Malinen (u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24), 11400b9cfa3SJouni Malinen (u8)(pn >> 16), (u8)(pn >> 8), (u8)pn); 11500b9cfa3SJouni Malinen break; 116e9f207f0SJiri Benc default: 117e9f207f0SJiri Benc return 0; 118e9f207f0SJiri Benc } 119e9f207f0SJiri Benc return simple_read_from_buffer(userbuf, count, ppos, buf, len); 120e9f207f0SJiri Benc } 121e9f207f0SJiri Benc KEY_OPS(tx_spec); 122e9f207f0SJiri Benc 123e9f207f0SJiri Benc static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf, 124e9f207f0SJiri Benc size_t count, loff_t *ppos) 125e9f207f0SJiri Benc { 126e9f207f0SJiri Benc struct ieee80211_key *key = file->private_data; 1275a306f58SJohannes Berg char buf[14*IEEE80211_NUM_TIDS+1], *p = buf; 128e9f207f0SJiri Benc int i, len; 129e9f207f0SJiri Benc const u8 *rpn; 130e9f207f0SJiri Benc 13197359d12SJohannes Berg switch (key->conf.cipher) { 13297359d12SJohannes Berg case WLAN_CIPHER_SUITE_WEP40: 13397359d12SJohannes Berg case WLAN_CIPHER_SUITE_WEP104: 134e9f207f0SJiri Benc len = scnprintf(buf, sizeof(buf), "\n"); 13550339a67SJohannes Berg break; 13697359d12SJohannes Berg case WLAN_CIPHER_SUITE_TKIP: 1375a306f58SJohannes Berg for (i = 0; i < IEEE80211_NUM_TIDS; i++) 138e9f207f0SJiri Benc p += scnprintf(p, sizeof(buf)+buf-p, 139e9f207f0SJiri Benc "%08x %04x\n", 140b0f76b33SHarvey Harrison key->u.tkip.rx[i].iv32, 141b0f76b33SHarvey Harrison key->u.tkip.rx[i].iv16); 142e9f207f0SJiri Benc len = p - buf; 14350339a67SJohannes Berg break; 14497359d12SJohannes Berg case WLAN_CIPHER_SUITE_CCMP: 1452b2ba0dbSJouni Malinen case WLAN_CIPHER_SUITE_CCMP_256: 1465a306f58SJohannes Berg for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) { 147e9f207f0SJiri Benc rpn = key->u.ccmp.rx_pn[i]; 148e9f207f0SJiri Benc p += scnprintf(p, sizeof(buf)+buf-p, 149e9f207f0SJiri Benc "%02x%02x%02x%02x%02x%02x\n", 150e9f207f0SJiri Benc rpn[0], rpn[1], rpn[2], 151e9f207f0SJiri Benc rpn[3], rpn[4], rpn[5]); 152e9f207f0SJiri Benc } 153e9f207f0SJiri Benc len = p - buf; 15450339a67SJohannes Berg break; 15597359d12SJohannes Berg case WLAN_CIPHER_SUITE_AES_CMAC: 1563cfcf6acSJouni Malinen rpn = key->u.aes_cmac.rx_pn; 1573cfcf6acSJouni Malinen p += scnprintf(p, sizeof(buf)+buf-p, 1583cfcf6acSJouni Malinen "%02x%02x%02x%02x%02x%02x\n", 1593cfcf6acSJouni Malinen rpn[0], rpn[1], rpn[2], 1603cfcf6acSJouni Malinen rpn[3], rpn[4], rpn[5]); 1613cfcf6acSJouni Malinen len = p - buf; 1623cfcf6acSJouni Malinen break; 16300b9cfa3SJouni Malinen case WLAN_CIPHER_SUITE_GCMP: 16400b9cfa3SJouni Malinen case WLAN_CIPHER_SUITE_GCMP_256: 16500b9cfa3SJouni Malinen for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) { 16600b9cfa3SJouni Malinen rpn = key->u.gcmp.rx_pn[i]; 16700b9cfa3SJouni Malinen p += scnprintf(p, sizeof(buf)+buf-p, 16800b9cfa3SJouni Malinen "%02x%02x%02x%02x%02x%02x\n", 16900b9cfa3SJouni Malinen rpn[0], rpn[1], rpn[2], 17000b9cfa3SJouni Malinen rpn[3], rpn[4], rpn[5]); 17100b9cfa3SJouni Malinen } 17200b9cfa3SJouni Malinen len = p - buf; 17300b9cfa3SJouni Malinen break; 174e9f207f0SJiri Benc default: 175e9f207f0SJiri Benc return 0; 176e9f207f0SJiri Benc } 177e9f207f0SJiri Benc return simple_read_from_buffer(userbuf, count, ppos, buf, len); 178e9f207f0SJiri Benc } 179e9f207f0SJiri Benc KEY_OPS(rx_spec); 180e9f207f0SJiri Benc 181e9f207f0SJiri Benc static ssize_t key_replays_read(struct file *file, char __user *userbuf, 182e9f207f0SJiri Benc size_t count, loff_t *ppos) 183e9f207f0SJiri Benc { 184e9f207f0SJiri Benc struct ieee80211_key *key = file->private_data; 185e9f207f0SJiri Benc char buf[20]; 186e9f207f0SJiri Benc int len; 187e9f207f0SJiri Benc 18897359d12SJohannes Berg switch (key->conf.cipher) { 18997359d12SJohannes Berg case WLAN_CIPHER_SUITE_CCMP: 1902b2ba0dbSJouni Malinen case WLAN_CIPHER_SUITE_CCMP_256: 191e9f207f0SJiri Benc len = scnprintf(buf, sizeof(buf), "%u\n", key->u.ccmp.replays); 1923cfcf6acSJouni Malinen break; 19397359d12SJohannes Berg case WLAN_CIPHER_SUITE_AES_CMAC: 1943cfcf6acSJouni Malinen len = scnprintf(buf, sizeof(buf), "%u\n", 1953cfcf6acSJouni Malinen key->u.aes_cmac.replays); 1963cfcf6acSJouni Malinen break; 19700b9cfa3SJouni Malinen case WLAN_CIPHER_SUITE_GCMP: 19800b9cfa3SJouni Malinen case WLAN_CIPHER_SUITE_GCMP_256: 19900b9cfa3SJouni Malinen len = scnprintf(buf, sizeof(buf), "%u\n", key->u.gcmp.replays); 20000b9cfa3SJouni Malinen break; 2013cfcf6acSJouni Malinen default: 2023cfcf6acSJouni Malinen return 0; 2033cfcf6acSJouni Malinen } 204e9f207f0SJiri Benc return simple_read_from_buffer(userbuf, count, ppos, buf, len); 205e9f207f0SJiri Benc } 206e9f207f0SJiri Benc KEY_OPS(replays); 207e9f207f0SJiri Benc 2083cfcf6acSJouni Malinen static ssize_t key_icverrors_read(struct file *file, char __user *userbuf, 2093cfcf6acSJouni Malinen size_t count, loff_t *ppos) 2103cfcf6acSJouni Malinen { 2113cfcf6acSJouni Malinen struct ieee80211_key *key = file->private_data; 2123cfcf6acSJouni Malinen char buf[20]; 2133cfcf6acSJouni Malinen int len; 2143cfcf6acSJouni Malinen 21597359d12SJohannes Berg switch (key->conf.cipher) { 21697359d12SJohannes Berg case WLAN_CIPHER_SUITE_AES_CMAC: 2173cfcf6acSJouni Malinen len = scnprintf(buf, sizeof(buf), "%u\n", 2183cfcf6acSJouni Malinen key->u.aes_cmac.icverrors); 2193cfcf6acSJouni Malinen break; 2203cfcf6acSJouni Malinen default: 2213cfcf6acSJouni Malinen return 0; 2223cfcf6acSJouni Malinen } 2233cfcf6acSJouni Malinen return simple_read_from_buffer(userbuf, count, ppos, buf, len); 2243cfcf6acSJouni Malinen } 2253cfcf6acSJouni Malinen KEY_OPS(icverrors); 2263cfcf6acSJouni Malinen 227b98ea058SSaravana static ssize_t key_mic_failures_read(struct file *file, char __user *userbuf, 228b98ea058SSaravana size_t count, loff_t *ppos) 229b98ea058SSaravana { 230b98ea058SSaravana struct ieee80211_key *key = file->private_data; 231b98ea058SSaravana char buf[20]; 232b98ea058SSaravana int len; 233b98ea058SSaravana 234b98ea058SSaravana if (key->conf.cipher != WLAN_CIPHER_SUITE_TKIP) 235b98ea058SSaravana return -EINVAL; 236b98ea058SSaravana 237b98ea058SSaravana len = scnprintf(buf, sizeof(buf), "%u\n", key->u.tkip.mic_failures); 238b98ea058SSaravana 239b98ea058SSaravana return simple_read_from_buffer(userbuf, count, ppos, buf, len); 240b98ea058SSaravana } 241b98ea058SSaravana KEY_OPS(mic_failures); 242b98ea058SSaravana 243e9f207f0SJiri Benc static ssize_t key_key_read(struct file *file, char __user *userbuf, 244e9f207f0SJiri Benc size_t count, loff_t *ppos) 245e9f207f0SJiri Benc { 246e9f207f0SJiri Benc struct ieee80211_key *key = file->private_data; 247520efd1aSJesper Juhl int i, bufsize = 2 * key->conf.keylen + 2; 248e9f207f0SJiri Benc char *buf = kmalloc(bufsize, GFP_KERNEL); 249e9f207f0SJiri Benc char *p = buf; 250520efd1aSJesper Juhl ssize_t res; 251520efd1aSJesper Juhl 252520efd1aSJesper Juhl if (!buf) 253520efd1aSJesper Juhl return -ENOMEM; 254e9f207f0SJiri Benc 2558f20fc24SJohannes Berg for (i = 0; i < key->conf.keylen; i++) 2568f20fc24SJohannes Berg p += scnprintf(p, bufsize + buf - p, "%02x", key->conf.key[i]); 257e9f207f0SJiri Benc p += scnprintf(p, bufsize+buf-p, "\n"); 258e9f207f0SJiri Benc res = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf); 259e9f207f0SJiri Benc kfree(buf); 260e9f207f0SJiri Benc return res; 261e9f207f0SJiri Benc } 262e9f207f0SJiri Benc KEY_OPS(key); 263e9f207f0SJiri Benc 264e9f207f0SJiri Benc #define DEBUGFS_ADD(name) \ 2657bcfaf2fSJohannes Berg debugfs_create_file(#name, 0400, key->debugfs.dir, \ 2667bcfaf2fSJohannes Berg key, &key_##name##_ops); 267e9f207f0SJiri Benc 2683b96766fSJohannes Berg void ieee80211_debugfs_key_add(struct ieee80211_key *key) 269e9f207f0SJiri Benc { 27050339a67SJohannes Berg static int keycount; 2719446f3efSJohannes Berg char buf[100]; 2723b96766fSJohannes Berg struct sta_info *sta; 273e9f207f0SJiri Benc 2743b96766fSJohannes Berg if (!key->local->debugfs.keys) 275e9f207f0SJiri Benc return; 276e9f207f0SJiri Benc 27750339a67SJohannes Berg sprintf(buf, "%d", keycount); 278d9c58f30SJohannes Berg key->debugfs.cnt = keycount; 27950339a67SJohannes Berg keycount++; 280e9f207f0SJiri Benc key->debugfs.dir = debugfs_create_dir(buf, 2813b96766fSJohannes Berg key->local->debugfs.keys); 282e9f207f0SJiri Benc 283e9f207f0SJiri Benc if (!key->debugfs.dir) 284e9f207f0SJiri Benc return; 285e9f207f0SJiri Benc 28640b275b6SJohannes Berg sta = key->sta; 28740b275b6SJohannes Berg if (sta) { 2889446f3efSJohannes Berg sprintf(buf, "../../netdev:%s/stations/%pM", 2899446f3efSJohannes Berg sta->sdata->name, sta->sta.addr); 2903b96766fSJohannes Berg key->debugfs.stalink = 2913b96766fSJohannes Berg debugfs_create_symlink("station", key->debugfs.dir, buf); 29240b275b6SJohannes Berg } 2933b96766fSJohannes Berg 294e9f207f0SJiri Benc DEBUGFS_ADD(keylen); 2958f20fc24SJohannes Berg DEBUGFS_ADD(flags); 296e9f207f0SJiri Benc DEBUGFS_ADD(keyidx); 297e9f207f0SJiri Benc DEBUGFS_ADD(hw_key_idx); 298e9f207f0SJiri Benc DEBUGFS_ADD(tx_rx_count); 299e9f207f0SJiri Benc DEBUGFS_ADD(algorithm); 300e9f207f0SJiri Benc DEBUGFS_ADD(tx_spec); 301e9f207f0SJiri Benc DEBUGFS_ADD(rx_spec); 302e9f207f0SJiri Benc DEBUGFS_ADD(replays); 3033cfcf6acSJouni Malinen DEBUGFS_ADD(icverrors); 304b98ea058SSaravana DEBUGFS_ADD(mic_failures); 305e9f207f0SJiri Benc DEBUGFS_ADD(key); 306e7a64f12SJohannes Berg DEBUGFS_ADD(ifindex); 307e9f207f0SJiri Benc }; 308e9f207f0SJiri Benc 309e9f207f0SJiri Benc void ieee80211_debugfs_key_remove(struct ieee80211_key *key) 310e9f207f0SJiri Benc { 311e9f207f0SJiri Benc if (!key) 312e9f207f0SJiri Benc return; 313e9f207f0SJiri Benc 3147bcfaf2fSJohannes Berg debugfs_remove_recursive(key->debugfs.dir); 315e9f207f0SJiri Benc key->debugfs.dir = NULL; 316e9f207f0SJiri Benc } 317f7e0104cSJohannes Berg 318f7e0104cSJohannes Berg void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata) 319e9f207f0SJiri Benc { 320e9f207f0SJiri Benc char buf[50]; 32178520cadSJohannes Berg struct ieee80211_key *key; 322e9f207f0SJiri Benc 323ddbfe860SStanislaw Gruszka if (!sdata->vif.debugfs_dir) 324e9f207f0SJiri Benc return; 325e9f207f0SJiri Benc 326f7e0104cSJohannes Berg lockdep_assert_held(&sdata->local->key_mtx); 32778520cadSJohannes Berg 328135792ecSJohannes Berg debugfs_remove(sdata->debugfs.default_unicast_key); 329135792ecSJohannes Berg sdata->debugfs.default_unicast_key = NULL; 330135792ecSJohannes Berg 331f7e0104cSJohannes Berg if (sdata->default_unicast_key) { 33240b275b6SJohannes Berg key = key_mtx_dereference(sdata->local, 33340b275b6SJohannes Berg sdata->default_unicast_key); 33478520cadSJohannes Berg sprintf(buf, "../keys/%d", key->debugfs.cnt); 335f7e0104cSJohannes Berg sdata->debugfs.default_unicast_key = 336f7e0104cSJohannes Berg debugfs_create_symlink("default_unicast_key", 337ddbfe860SStanislaw Gruszka sdata->vif.debugfs_dir, buf); 338135792ecSJohannes Berg } 339135792ecSJohannes Berg 340135792ecSJohannes Berg debugfs_remove(sdata->debugfs.default_multicast_key); 341135792ecSJohannes Berg sdata->debugfs.default_multicast_key = NULL; 34278520cadSJohannes Berg 343f7e0104cSJohannes Berg if (sdata->default_multicast_key) { 34440b275b6SJohannes Berg key = key_mtx_dereference(sdata->local, 34540b275b6SJohannes Berg sdata->default_multicast_key); 346f7e0104cSJohannes Berg sprintf(buf, "../keys/%d", key->debugfs.cnt); 347f7e0104cSJohannes Berg sdata->debugfs.default_multicast_key = 348f7e0104cSJohannes Berg debugfs_create_symlink("default_multicast_key", 349ddbfe860SStanislaw Gruszka sdata->vif.debugfs_dir, buf); 350f7e0104cSJohannes Berg } 351e9f207f0SJiri Benc } 352e9f207f0SJiri Benc 3533cfcf6acSJouni Malinen void ieee80211_debugfs_key_add_mgmt_default(struct ieee80211_sub_if_data *sdata) 3543cfcf6acSJouni Malinen { 3553cfcf6acSJouni Malinen char buf[50]; 3563cfcf6acSJouni Malinen struct ieee80211_key *key; 3573cfcf6acSJouni Malinen 358ddbfe860SStanislaw Gruszka if (!sdata->vif.debugfs_dir) 3593cfcf6acSJouni Malinen return; 3603cfcf6acSJouni Malinen 36140b275b6SJohannes Berg key = key_mtx_dereference(sdata->local, 36240b275b6SJohannes Berg sdata->default_mgmt_key); 3633cfcf6acSJouni Malinen if (key) { 3643cfcf6acSJouni Malinen sprintf(buf, "../keys/%d", key->debugfs.cnt); 3657bcfaf2fSJohannes Berg sdata->debugfs.default_mgmt_key = 3663cfcf6acSJouni Malinen debugfs_create_symlink("default_mgmt_key", 367ddbfe860SStanislaw Gruszka sdata->vif.debugfs_dir, buf); 3683cfcf6acSJouni Malinen } else 3693cfcf6acSJouni Malinen ieee80211_debugfs_key_remove_mgmt_default(sdata); 3703cfcf6acSJouni Malinen } 3713cfcf6acSJouni Malinen 3723cfcf6acSJouni Malinen void ieee80211_debugfs_key_remove_mgmt_default(struct ieee80211_sub_if_data *sdata) 3733cfcf6acSJouni Malinen { 3743cfcf6acSJouni Malinen if (!sdata) 3753cfcf6acSJouni Malinen return; 3763cfcf6acSJouni Malinen 3777bcfaf2fSJohannes Berg debugfs_remove(sdata->debugfs.default_mgmt_key); 3787bcfaf2fSJohannes Berg sdata->debugfs.default_mgmt_key = NULL; 3793cfcf6acSJouni Malinen } 3803cfcf6acSJouni Malinen 381e9f207f0SJiri Benc void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key, 382e9f207f0SJiri Benc struct sta_info *sta) 383e9f207f0SJiri Benc { 384e9f207f0SJiri Benc debugfs_remove(key->debugfs.stalink); 385e9f207f0SJiri Benc key->debugfs.stalink = NULL; 386e9f207f0SJiri Benc } 387