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 "key.h" 14 #include "debugfs.h" 15 #include "debugfs_key.h" 16 17 #define KEY_READ(name, prop, buflen, format_string) \ 18 static 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) \ 31 static 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) \ 45 static 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 54 KEY_CONF_FILE(keylen, D); 55 KEY_CONF_FILE(keyidx, D); 56 KEY_CONF_FILE(hw_key_idx, D); 57 KEY_FILE(flags, X); 58 KEY_FILE(tx_rx_count, D); 59 KEY_READ(ifindex, sdata->dev->ifindex, 20, "%d\n"); 60 KEY_OPS(ifindex); 61 62 static 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 case ALG_AES_CMAC: 80 alg = "AES-128-CMAC\n"; 81 break; 82 default: 83 return 0; 84 } 85 return simple_read_from_buffer(userbuf, count, ppos, alg, strlen(alg)); 86 } 87 KEY_OPS(algorithm); 88 89 static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf, 90 size_t count, loff_t *ppos) 91 { 92 const u8 *tpn; 93 char buf[20]; 94 int len; 95 struct ieee80211_key *key = file->private_data; 96 97 switch (key->conf.alg) { 98 case ALG_WEP: 99 len = scnprintf(buf, sizeof(buf), "\n"); 100 break; 101 case ALG_TKIP: 102 len = scnprintf(buf, sizeof(buf), "%08x %04x\n", 103 key->u.tkip.tx.iv32, 104 key->u.tkip.tx.iv16); 105 break; 106 case ALG_CCMP: 107 tpn = key->u.ccmp.tx_pn; 108 len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", 109 tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], tpn[5]); 110 break; 111 case ALG_AES_CMAC: 112 tpn = key->u.aes_cmac.tx_pn; 113 len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", 114 tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], 115 tpn[5]); 116 break; 117 default: 118 return 0; 119 } 120 return simple_read_from_buffer(userbuf, count, ppos, buf, len); 121 } 122 KEY_OPS(tx_spec); 123 124 static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf, 125 size_t count, loff_t *ppos) 126 { 127 struct ieee80211_key *key = file->private_data; 128 char buf[14*NUM_RX_DATA_QUEUES+1], *p = buf; 129 int i, len; 130 const u8 *rpn; 131 132 switch (key->conf.alg) { 133 case ALG_WEP: 134 len = scnprintf(buf, sizeof(buf), "\n"); 135 break; 136 case ALG_TKIP: 137 for (i = 0; i < NUM_RX_DATA_QUEUES; i++) 138 p += scnprintf(p, sizeof(buf)+buf-p, 139 "%08x %04x\n", 140 key->u.tkip.rx[i].iv32, 141 key->u.tkip.rx[i].iv16); 142 len = p - buf; 143 break; 144 case ALG_CCMP: 145 for (i = 0; i < NUM_RX_DATA_QUEUES; i++) { 146 rpn = key->u.ccmp.rx_pn[i]; 147 p += scnprintf(p, sizeof(buf)+buf-p, 148 "%02x%02x%02x%02x%02x%02x\n", 149 rpn[0], rpn[1], rpn[2], 150 rpn[3], rpn[4], rpn[5]); 151 } 152 len = p - buf; 153 break; 154 case ALG_AES_CMAC: 155 rpn = key->u.aes_cmac.rx_pn; 156 p += scnprintf(p, sizeof(buf)+buf-p, 157 "%02x%02x%02x%02x%02x%02x\n", 158 rpn[0], rpn[1], rpn[2], 159 rpn[3], rpn[4], rpn[5]); 160 len = p - buf; 161 break; 162 default: 163 return 0; 164 } 165 return simple_read_from_buffer(userbuf, count, ppos, buf, len); 166 } 167 KEY_OPS(rx_spec); 168 169 static ssize_t key_replays_read(struct file *file, char __user *userbuf, 170 size_t count, loff_t *ppos) 171 { 172 struct ieee80211_key *key = file->private_data; 173 char buf[20]; 174 int len; 175 176 switch (key->conf.alg) { 177 case ALG_CCMP: 178 len = scnprintf(buf, sizeof(buf), "%u\n", key->u.ccmp.replays); 179 break; 180 case ALG_AES_CMAC: 181 len = scnprintf(buf, sizeof(buf), "%u\n", 182 key->u.aes_cmac.replays); 183 break; 184 default: 185 return 0; 186 } 187 return simple_read_from_buffer(userbuf, count, ppos, buf, len); 188 } 189 KEY_OPS(replays); 190 191 static ssize_t key_icverrors_read(struct file *file, char __user *userbuf, 192 size_t count, loff_t *ppos) 193 { 194 struct ieee80211_key *key = file->private_data; 195 char buf[20]; 196 int len; 197 198 switch (key->conf.alg) { 199 case ALG_AES_CMAC: 200 len = scnprintf(buf, sizeof(buf), "%u\n", 201 key->u.aes_cmac.icverrors); 202 break; 203 default: 204 return 0; 205 } 206 return simple_read_from_buffer(userbuf, count, ppos, buf, len); 207 } 208 KEY_OPS(icverrors); 209 210 static ssize_t key_key_read(struct file *file, char __user *userbuf, 211 size_t count, loff_t *ppos) 212 { 213 struct ieee80211_key *key = file->private_data; 214 int i, res, bufsize = 2 * key->conf.keylen + 2; 215 char *buf = kmalloc(bufsize, GFP_KERNEL); 216 char *p = buf; 217 218 for (i = 0; i < key->conf.keylen; i++) 219 p += scnprintf(p, bufsize + buf - p, "%02x", key->conf.key[i]); 220 p += scnprintf(p, bufsize+buf-p, "\n"); 221 res = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf); 222 kfree(buf); 223 return res; 224 } 225 KEY_OPS(key); 226 227 #define DEBUGFS_ADD(name) \ 228 key->debugfs.name = debugfs_create_file(#name, 0400,\ 229 key->debugfs.dir, key, &key_##name##_ops); 230 231 void ieee80211_debugfs_key_add(struct ieee80211_key *key) 232 { 233 static int keycount; 234 char buf[50]; 235 struct sta_info *sta; 236 237 if (!key->local->debugfs.keys) 238 return; 239 240 sprintf(buf, "%d", keycount); 241 key->debugfs.cnt = keycount; 242 keycount++; 243 key->debugfs.dir = debugfs_create_dir(buf, 244 key->local->debugfs.keys); 245 246 if (!key->debugfs.dir) 247 return; 248 249 rcu_read_lock(); 250 sta = rcu_dereference(key->sta); 251 if (sta) 252 sprintf(buf, "../../stations/%pM", sta->sta.addr); 253 rcu_read_unlock(); 254 255 /* using sta as a boolean is fine outside RCU lock */ 256 if (sta) 257 key->debugfs.stalink = 258 debugfs_create_symlink("station", key->debugfs.dir, buf); 259 260 DEBUGFS_ADD(keylen); 261 DEBUGFS_ADD(flags); 262 DEBUGFS_ADD(keyidx); 263 DEBUGFS_ADD(hw_key_idx); 264 DEBUGFS_ADD(tx_rx_count); 265 DEBUGFS_ADD(algorithm); 266 DEBUGFS_ADD(tx_spec); 267 DEBUGFS_ADD(rx_spec); 268 DEBUGFS_ADD(replays); 269 DEBUGFS_ADD(icverrors); 270 DEBUGFS_ADD(key); 271 DEBUGFS_ADD(ifindex); 272 }; 273 274 #define DEBUGFS_DEL(name) \ 275 debugfs_remove(key->debugfs.name); key->debugfs.name = NULL; 276 277 void ieee80211_debugfs_key_remove(struct ieee80211_key *key) 278 { 279 if (!key) 280 return; 281 282 DEBUGFS_DEL(keylen); 283 DEBUGFS_DEL(flags); 284 DEBUGFS_DEL(keyidx); 285 DEBUGFS_DEL(hw_key_idx); 286 DEBUGFS_DEL(tx_rx_count); 287 DEBUGFS_DEL(algorithm); 288 DEBUGFS_DEL(tx_spec); 289 DEBUGFS_DEL(rx_spec); 290 DEBUGFS_DEL(replays); 291 DEBUGFS_DEL(icverrors); 292 DEBUGFS_DEL(key); 293 DEBUGFS_DEL(ifindex); 294 295 debugfs_remove(key->debugfs.stalink); 296 key->debugfs.stalink = NULL; 297 debugfs_remove(key->debugfs.dir); 298 key->debugfs.dir = NULL; 299 } 300 void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata) 301 { 302 char buf[50]; 303 struct ieee80211_key *key; 304 305 if (!sdata->debugfsdir) 306 return; 307 308 /* this is running under the key lock */ 309 310 key = sdata->default_key; 311 if (key) { 312 sprintf(buf, "../keys/%d", key->debugfs.cnt); 313 sdata->common_debugfs.default_key = 314 debugfs_create_symlink("default_key", 315 sdata->debugfsdir, buf); 316 } else 317 ieee80211_debugfs_key_remove_default(sdata); 318 } 319 320 void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata) 321 { 322 if (!sdata) 323 return; 324 325 debugfs_remove(sdata->common_debugfs.default_key); 326 sdata->common_debugfs.default_key = NULL; 327 } 328 329 void ieee80211_debugfs_key_add_mgmt_default(struct ieee80211_sub_if_data *sdata) 330 { 331 char buf[50]; 332 struct ieee80211_key *key; 333 334 if (!sdata->debugfsdir) 335 return; 336 337 /* this is running under the key lock */ 338 339 key = sdata->default_mgmt_key; 340 if (key) { 341 sprintf(buf, "../keys/%d", key->debugfs.cnt); 342 sdata->common_debugfs.default_mgmt_key = 343 debugfs_create_symlink("default_mgmt_key", 344 sdata->debugfsdir, buf); 345 } else 346 ieee80211_debugfs_key_remove_mgmt_default(sdata); 347 } 348 349 void ieee80211_debugfs_key_remove_mgmt_default(struct ieee80211_sub_if_data *sdata) 350 { 351 if (!sdata) 352 return; 353 354 debugfs_remove(sdata->common_debugfs.default_mgmt_key); 355 sdata->common_debugfs.default_mgmt_key = NULL; 356 } 357 358 void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key, 359 struct sta_info *sta) 360 { 361 debugfs_remove(key->debugfs.stalink); 362 key->debugfs.stalink = NULL; 363 } 364