Blame view

net/mac80211/debugfs_key.c 8.93 KB
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
1
2
3
4
5
6
7
8
9
10
11
  /*
   * Copyright 2003-2005	Devicescape Software, Inc.
   * Copyright (c) 2006	Jiri Benc <jbenc@suse.cz>
   * Copyright 2007	Johannes Berg <johannes@sipsolutions.net>
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2 as
   * published by the Free Software Foundation.
   */
  
  #include <linux/kobject.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
12
  #include <linux/slab.h>
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
13
  #include "ieee80211_i.h"
2c8dccc77   Johannes Berg   mac80211: rename ...
14
  #include "key.h"
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
15
16
  #include "debugfs.h"
  #include "debugfs_key.h"
07caf9d6c   Eliad Peller   mac80211: refacto...
17
  #define KEY_READ(name, prop, format_string)				\
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
18
19
20
21
  static ssize_t key_##name##_read(struct file *file,			\
  				 char __user *userbuf,			\
  				 size_t count, loff_t *ppos)		\
  {									\
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
22
  	struct ieee80211_key *key = file->private_data;			\
07caf9d6c   Eliad Peller   mac80211: refacto...
23
24
  	return mac80211_format_buffer(userbuf, count, ppos, 		\
  				      format_string, key->prop);	\
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
25
  }
07caf9d6c   Eliad Peller   mac80211: refacto...
26
27
28
29
  #define KEY_READ_D(name) KEY_READ(name, name, "%d
  ")
  #define KEY_READ_X(name) KEY_READ(name, name, "0x%x
  ")
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
30
31
32
33
34
  
  #define KEY_OPS(name)							\
  static const struct file_operations key_ ##name## _ops = {		\
  	.read = key_##name##_read,					\
  	.open = mac80211_open_file_generic,				\
2b18ab36c   Arnd Bergmann   net/wireless: use...
35
  	.llseek = generic_file_llseek,					\
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
36
37
38
39
40
  }
  
  #define KEY_FILE(name, format)						\
  		 KEY_READ_##format(name)				\
  		 KEY_OPS(name)
07caf9d6c   Eliad Peller   mac80211: refacto...
41
42
43
44
  #define KEY_CONF_READ(name, format_string)				\
  	KEY_READ(conf_##name, conf.name, format_string)
  #define KEY_CONF_READ_D(name) KEY_CONF_READ(name, "%d
  ")
8f20fc249   Johannes Berg   [MAC80211]: embed...
45
46
47
48
49
  
  #define KEY_CONF_OPS(name)						\
  static const struct file_operations key_ ##name## _ops = {		\
  	.read = key_conf_##name##_read,					\
  	.open = mac80211_open_file_generic,				\
2b18ab36c   Arnd Bergmann   net/wireless: use...
50
  	.llseek = generic_file_llseek,					\
8f20fc249   Johannes Berg   [MAC80211]: embed...
51
52
53
54
55
56
57
58
59
  }
  
  #define KEY_CONF_FILE(name, format)					\
  		 KEY_CONF_READ_##format(name)				\
  		 KEY_CONF_OPS(name)
  
  KEY_CONF_FILE(keylen, D);
  KEY_CONF_FILE(keyidx, D);
  KEY_CONF_FILE(hw_key_idx, D);
11a843b7e   Johannes Berg   [MAC80211]: rewor...
60
  KEY_FILE(flags, X);
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
61
  KEY_FILE(tx_rx_count, D);
07caf9d6c   Eliad Peller   mac80211: refacto...
62
63
  KEY_READ(ifindex, sdata->name, "%s
  ");
e7a64f12a   Johannes Berg   [MAC80211]: add i...
64
  KEY_OPS(ifindex);
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
65
66
67
68
69
  
  static ssize_t key_algorithm_read(struct file *file,
  				  char __user *userbuf,
  				  size_t count, loff_t *ppos)
  {
97359d123   Johannes Berg   mac80211: use cip...
70
  	char buf[15];
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
71
  	struct ieee80211_key *key = file->private_data;
97359d123   Johannes Berg   mac80211: use cip...
72
  	u32 c = key->conf.cipher;
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
73

97359d123   Johannes Berg   mac80211: use cip...
74
75
76
77
  	sprintf(buf, "%.2x-%.2x-%.2x:%d
  ",
  		c >> 24, (c >> 16) & 0xff, (c >> 8) & 0xff, c & 0xff);
  	return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf));
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
78
79
80
81
82
83
  }
  KEY_OPS(algorithm);
  
  static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf,
  				size_t count, loff_t *ppos)
  {
aba83a0b3   Johannes Berg   mac80211: fix CCM...
84
  	u64 pn;
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
85
86
87
  	char buf[20];
  	int len;
  	struct ieee80211_key *key = file->private_data;
97359d123   Johannes Berg   mac80211: use cip...
88
89
90
  	switch (key->conf.cipher) {
  	case WLAN_CIPHER_SUITE_WEP40:
  	case WLAN_CIPHER_SUITE_WEP104:
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
91
92
  		len = scnprintf(buf, sizeof(buf), "
  ");
50339a67e   Johannes Berg   [MAC80211]: fix k...
93
  		break;
97359d123   Johannes Berg   mac80211: use cip...
94
  	case WLAN_CIPHER_SUITE_TKIP:
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
95
96
  		len = scnprintf(buf, sizeof(buf), "%08x %04x
  ",
b0f76b335   Harvey Harrison   mac80211: add a s...
97
98
  				key->u.tkip.tx.iv32,
  				key->u.tkip.tx.iv16);
50339a67e   Johannes Berg   [MAC80211]: fix k...
99
  		break;
97359d123   Johannes Berg   mac80211: use cip...
100
  	case WLAN_CIPHER_SUITE_CCMP:
aba83a0b3   Johannes Berg   mac80211: fix CCM...
101
  		pn = atomic64_read(&key->u.ccmp.tx_pn);
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
102
103
  		len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x
  ",
aba83a0b3   Johannes Berg   mac80211: fix CCM...
104
105
  				(u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24),
  				(u8)(pn >> 16), (u8)(pn >> 8), (u8)pn);
50339a67e   Johannes Berg   [MAC80211]: fix k...
106
  		break;
97359d123   Johannes Berg   mac80211: use cip...
107
  	case WLAN_CIPHER_SUITE_AES_CMAC:
75396ae6d   Johannes Berg   mac80211: fix CMA...
108
  		pn = atomic64_read(&key->u.aes_cmac.tx_pn);
3cfcf6ac6   Jouni Malinen   mac80211: 802.11w...
109
110
  		len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x
  ",
75396ae6d   Johannes Berg   mac80211: fix CMA...
111
112
  				(u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24),
  				(u8)(pn >> 16), (u8)(pn >> 8), (u8)pn);
3cfcf6ac6   Jouni Malinen   mac80211: 802.11w...
113
  		break;
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
114
115
116
117
118
119
120
121
122
123
124
125
126
127
  	default:
  		return 0;
  	}
  	return simple_read_from_buffer(userbuf, count, ppos, buf, len);
  }
  KEY_OPS(tx_spec);
  
  static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf,
  				size_t count, loff_t *ppos)
  {
  	struct ieee80211_key *key = file->private_data;
  	char buf[14*NUM_RX_DATA_QUEUES+1], *p = buf;
  	int i, len;
  	const u8 *rpn;
97359d123   Johannes Berg   mac80211: use cip...
128
129
130
  	switch (key->conf.cipher) {
  	case WLAN_CIPHER_SUITE_WEP40:
  	case WLAN_CIPHER_SUITE_WEP104:
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
131
132
  		len = scnprintf(buf, sizeof(buf), "
  ");
50339a67e   Johannes Berg   [MAC80211]: fix k...
133
  		break;
97359d123   Johannes Berg   mac80211: use cip...
134
  	case WLAN_CIPHER_SUITE_TKIP:
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
135
136
137
138
  		for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
  			p += scnprintf(p, sizeof(buf)+buf-p,
  				       "%08x %04x
  ",
b0f76b335   Harvey Harrison   mac80211: add a s...
139
140
  				       key->u.tkip.rx[i].iv32,
  				       key->u.tkip.rx[i].iv16);
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
141
  		len = p - buf;
50339a67e   Johannes Berg   [MAC80211]: fix k...
142
  		break;
97359d123   Johannes Berg   mac80211: use cip...
143
  	case WLAN_CIPHER_SUITE_CCMP:
9190252c9   Jouni Malinen   mac80211: Use a s...
144
  		for (i = 0; i < NUM_RX_DATA_QUEUES + 1; i++) {
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
145
146
147
148
149
150
151
152
  			rpn = key->u.ccmp.rx_pn[i];
  			p += scnprintf(p, sizeof(buf)+buf-p,
  				       "%02x%02x%02x%02x%02x%02x
  ",
  				       rpn[0], rpn[1], rpn[2],
  				       rpn[3], rpn[4], rpn[5]);
  		}
  		len = p - buf;
50339a67e   Johannes Berg   [MAC80211]: fix k...
153
  		break;
97359d123   Johannes Berg   mac80211: use cip...
154
  	case WLAN_CIPHER_SUITE_AES_CMAC:
3cfcf6ac6   Jouni Malinen   mac80211: 802.11w...
155
156
157
158
159
160
161
162
  		rpn = key->u.aes_cmac.rx_pn;
  		p += scnprintf(p, sizeof(buf)+buf-p,
  			       "%02x%02x%02x%02x%02x%02x
  ",
  			       rpn[0], rpn[1], rpn[2],
  			       rpn[3], rpn[4], rpn[5]);
  		len = p - buf;
  		break;
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
163
164
165
166
167
168
169
170
171
172
173
174
175
  	default:
  		return 0;
  	}
  	return simple_read_from_buffer(userbuf, count, ppos, buf, len);
  }
  KEY_OPS(rx_spec);
  
  static ssize_t key_replays_read(struct file *file, char __user *userbuf,
  				size_t count, loff_t *ppos)
  {
  	struct ieee80211_key *key = file->private_data;
  	char buf[20];
  	int len;
97359d123   Johannes Berg   mac80211: use cip...
176
177
  	switch (key->conf.cipher) {
  	case WLAN_CIPHER_SUITE_CCMP:
3cfcf6ac6   Jouni Malinen   mac80211: 802.11w...
178
179
180
  		len = scnprintf(buf, sizeof(buf), "%u
  ", key->u.ccmp.replays);
  		break;
97359d123   Johannes Berg   mac80211: use cip...
181
  	case WLAN_CIPHER_SUITE_AES_CMAC:
3cfcf6ac6   Jouni Malinen   mac80211: 802.11w...
182
183
184
185
186
  		len = scnprintf(buf, sizeof(buf), "%u
  ",
  				key->u.aes_cmac.replays);
  		break;
  	default:
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
187
  		return 0;
3cfcf6ac6   Jouni Malinen   mac80211: 802.11w...
188
  	}
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
189
190
191
  	return simple_read_from_buffer(userbuf, count, ppos, buf, len);
  }
  KEY_OPS(replays);
3cfcf6ac6   Jouni Malinen   mac80211: 802.11w...
192
193
194
195
196
197
  static ssize_t key_icverrors_read(struct file *file, char __user *userbuf,
  				  size_t count, loff_t *ppos)
  {
  	struct ieee80211_key *key = file->private_data;
  	char buf[20];
  	int len;
97359d123   Johannes Berg   mac80211: use cip...
198
199
  	switch (key->conf.cipher) {
  	case WLAN_CIPHER_SUITE_AES_CMAC:
3cfcf6ac6   Jouni Malinen   mac80211: 802.11w...
200
201
202
203
204
205
206
207
208
209
  		len = scnprintf(buf, sizeof(buf), "%u
  ",
  				key->u.aes_cmac.icverrors);
  		break;
  	default:
  		return 0;
  	}
  	return simple_read_from_buffer(userbuf, count, ppos, buf, len);
  }
  KEY_OPS(icverrors);
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
210
211
212
213
  static ssize_t key_key_read(struct file *file, char __user *userbuf,
  			    size_t count, loff_t *ppos)
  {
  	struct ieee80211_key *key = file->private_data;
520efd1ac   Jesper Juhl   mac80211: fix fai...
214
  	int i, bufsize = 2 * key->conf.keylen + 2;
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
215
216
  	char *buf = kmalloc(bufsize, GFP_KERNEL);
  	char *p = buf;
520efd1ac   Jesper Juhl   mac80211: fix fai...
217
218
219
220
  	ssize_t res;
  
  	if (!buf)
  		return -ENOMEM;
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
221

8f20fc249   Johannes Berg   [MAC80211]: embed...
222
223
  	for (i = 0; i < key->conf.keylen; i++)
  		p += scnprintf(p, bufsize + buf - p, "%02x", key->conf.key[i]);
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
224
225
226
227
228
229
230
231
232
  	p += scnprintf(p, bufsize+buf-p, "
  ");
  	res = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
  	kfree(buf);
  	return res;
  }
  KEY_OPS(key);
  
  #define DEBUGFS_ADD(name) \
7bcfaf2f4   Johannes Berg   cfg80211/mac80211...
233
234
  	debugfs_create_file(#name, 0400, key->debugfs.dir, \
  			    key, &key_##name##_ops);
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
235

3b96766f0   Johannes Berg   mac80211: fix key...
236
237
  void ieee80211_debugfs_key_add(struct ieee80211_key *key)
    {
50339a67e   Johannes Berg   [MAC80211]: fix k...
238
  	static int keycount;
3b96766f0   Johannes Berg   mac80211: fix key...
239
  	char buf[50];
3b96766f0   Johannes Berg   mac80211: fix key...
240
  	struct sta_info *sta;
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
241

3b96766f0   Johannes Berg   mac80211: fix key...
242
  	if (!key->local->debugfs.keys)
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
243
  		return;
50339a67e   Johannes Berg   [MAC80211]: fix k...
244
  	sprintf(buf, "%d", keycount);
d9c58f30b   Johannes Berg   mac80211: fix key...
245
  	key->debugfs.cnt = keycount;
50339a67e   Johannes Berg   [MAC80211]: fix k...
246
  	keycount++;
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
247
  	key->debugfs.dir = debugfs_create_dir(buf,
3b96766f0   Johannes Berg   mac80211: fix key...
248
  					key->local->debugfs.keys);
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
249
250
251
  
  	if (!key->debugfs.dir)
  		return;
40b275b69   Johannes Berg   mac80211: sparse ...
252
253
  	sta = key->sta;
  	if (sta) {
0c68ae260   Johannes Berg   mac80211: convert...
254
  		sprintf(buf, "../../stations/%pM", sta->sta.addr);
3b96766f0   Johannes Berg   mac80211: fix key...
255
256
  		key->debugfs.stalink =
  			debugfs_create_symlink("station", key->debugfs.dir, buf);
40b275b69   Johannes Berg   mac80211: sparse ...
257
  	}
3b96766f0   Johannes Berg   mac80211: fix key...
258

e9f207f0f   Jiri Benc   [MAC80211]: Add d...
259
  	DEBUGFS_ADD(keylen);
8f20fc249   Johannes Berg   [MAC80211]: embed...
260
  	DEBUGFS_ADD(flags);
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
261
262
263
264
265
266
267
  	DEBUGFS_ADD(keyidx);
  	DEBUGFS_ADD(hw_key_idx);
  	DEBUGFS_ADD(tx_rx_count);
  	DEBUGFS_ADD(algorithm);
  	DEBUGFS_ADD(tx_spec);
  	DEBUGFS_ADD(rx_spec);
  	DEBUGFS_ADD(replays);
3cfcf6ac6   Jouni Malinen   mac80211: 802.11w...
268
  	DEBUGFS_ADD(icverrors);
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
269
  	DEBUGFS_ADD(key);
e7a64f12a   Johannes Berg   [MAC80211]: add i...
270
  	DEBUGFS_ADD(ifindex);
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
271
  };
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
272
273
274
275
  void ieee80211_debugfs_key_remove(struct ieee80211_key *key)
  {
  	if (!key)
  		return;
7bcfaf2f4   Johannes Berg   cfg80211/mac80211...
276
  	debugfs_remove_recursive(key->debugfs.dir);
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
277
278
  	key->debugfs.dir = NULL;
  }
f7e0104c1   Johannes Berg   mac80211: support...
279
280
  
  void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata)
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
281
282
  {
  	char buf[50];
78520cad4   Johannes Berg   mac80211: fix deb...
283
  	struct ieee80211_key *key;
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
284

7bcfaf2f4   Johannes Berg   cfg80211/mac80211...
285
  	if (!sdata->debugfs.dir)
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
286
  		return;
f7e0104c1   Johannes Berg   mac80211: support...
287
  	lockdep_assert_held(&sdata->local->key_mtx);
78520cad4   Johannes Berg   mac80211: fix deb...
288

f7e0104c1   Johannes Berg   mac80211: support...
289
  	if (sdata->default_unicast_key) {
40b275b69   Johannes Berg   mac80211: sparse ...
290
291
  		key = key_mtx_dereference(sdata->local,
  					  sdata->default_unicast_key);
78520cad4   Johannes Berg   mac80211: fix deb...
292
  		sprintf(buf, "../keys/%d", key->debugfs.cnt);
f7e0104c1   Johannes Berg   mac80211: support...
293
294
  		sdata->debugfs.default_unicast_key =
  			debugfs_create_symlink("default_unicast_key",
7bcfaf2f4   Johannes Berg   cfg80211/mac80211...
295
  					       sdata->debugfs.dir, buf);
f7e0104c1   Johannes Berg   mac80211: support...
296
297
298
299
  	} else {
  		debugfs_remove(sdata->debugfs.default_unicast_key);
  		sdata->debugfs.default_unicast_key = NULL;
  	}
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
300

f7e0104c1   Johannes Berg   mac80211: support...
301
  	if (sdata->default_multicast_key) {
40b275b69   Johannes Berg   mac80211: sparse ...
302
303
  		key = key_mtx_dereference(sdata->local,
  					  sdata->default_multicast_key);
f7e0104c1   Johannes Berg   mac80211: support...
304
305
306
307
308
309
310
311
  		sprintf(buf, "../keys/%d", key->debugfs.cnt);
  		sdata->debugfs.default_multicast_key =
  			debugfs_create_symlink("default_multicast_key",
  					       sdata->debugfs.dir, buf);
  	} else {
  		debugfs_remove(sdata->debugfs.default_multicast_key);
  		sdata->debugfs.default_multicast_key = NULL;
  	}
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
312
  }
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
313

3cfcf6ac6   Jouni Malinen   mac80211: 802.11w...
314
315
316
317
  void ieee80211_debugfs_key_add_mgmt_default(struct ieee80211_sub_if_data *sdata)
  {
  	char buf[50];
  	struct ieee80211_key *key;
7bcfaf2f4   Johannes Berg   cfg80211/mac80211...
318
  	if (!sdata->debugfs.dir)
3cfcf6ac6   Jouni Malinen   mac80211: 802.11w...
319
  		return;
40b275b69   Johannes Berg   mac80211: sparse ...
320
321
  	key = key_mtx_dereference(sdata->local,
  				  sdata->default_mgmt_key);
3cfcf6ac6   Jouni Malinen   mac80211: 802.11w...
322
323
  	if (key) {
  		sprintf(buf, "../keys/%d", key->debugfs.cnt);
7bcfaf2f4   Johannes Berg   cfg80211/mac80211...
324
  		sdata->debugfs.default_mgmt_key =
3cfcf6ac6   Jouni Malinen   mac80211: 802.11w...
325
  			debugfs_create_symlink("default_mgmt_key",
7bcfaf2f4   Johannes Berg   cfg80211/mac80211...
326
  					       sdata->debugfs.dir, buf);
3cfcf6ac6   Jouni Malinen   mac80211: 802.11w...
327
328
329
330
331
332
333
334
  	} else
  		ieee80211_debugfs_key_remove_mgmt_default(sdata);
  }
  
  void ieee80211_debugfs_key_remove_mgmt_default(struct ieee80211_sub_if_data *sdata)
  {
  	if (!sdata)
  		return;
7bcfaf2f4   Johannes Berg   cfg80211/mac80211...
335
336
  	debugfs_remove(sdata->debugfs.default_mgmt_key);
  	sdata->debugfs.default_mgmt_key = NULL;
3cfcf6ac6   Jouni Malinen   mac80211: 802.11w...
337
  }
e9f207f0f   Jiri Benc   [MAC80211]: Add d...
338
339
340
341
342
343
  void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
  				   struct sta_info *sta)
  {
  	debugfs_remove(key->debugfs.stalink);
  	key->debugfs.stalink = NULL;
  }