xref: /linux/net/mac80211/debugfs_key.c (revision a17627ef8833ac30622a7b39b7be390e1b174405)
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, 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->name);	\
25 	return simple_read_from_buffer(userbuf, count, ppos, buf, res);	\
26 }
27 #define KEY_READ_D(name) KEY_READ(name, 20, "%d\n")
28 
29 #define KEY_OPS(name)							\
30 static const struct file_operations key_ ##name## _ops = {		\
31 	.read = key_##name##_read,					\
32 	.open = mac80211_open_file_generic,				\
33 }
34 
35 #define KEY_FILE(name, format)						\
36 		 KEY_READ_##format(name)				\
37 		 KEY_OPS(name)
38 
39 KEY_FILE(keylen, D);
40 KEY_FILE(force_sw_encrypt, D);
41 KEY_FILE(keyidx, D);
42 KEY_FILE(hw_key_idx, D);
43 KEY_FILE(tx_rx_count, D);
44 
45 static ssize_t key_algorithm_read(struct file *file,
46 				  char __user *userbuf,
47 				  size_t count, loff_t *ppos)
48 {
49 	char *alg;
50 	struct ieee80211_key *key = file->private_data;
51 
52 	switch (key->alg) {
53 	case ALG_WEP:
54 		alg = "WEP\n";
55 		break;
56 	case ALG_TKIP:
57 		alg = "TKIP\n";
58 		break;
59 	case ALG_CCMP:
60 		alg = "CCMP\n";
61 		break;
62 	default:
63 		return 0;
64 	}
65 	return simple_read_from_buffer(userbuf, count, ppos, alg, strlen(alg));
66 }
67 KEY_OPS(algorithm);
68 
69 static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf,
70 				size_t count, loff_t *ppos)
71 {
72 	const u8 *tpn;
73 	char buf[20];
74 	int len;
75 	struct ieee80211_key *key = file->private_data;
76 
77 	switch (key->alg) {
78 	case ALG_WEP:
79 		len = scnprintf(buf, sizeof(buf), "\n");
80 	case ALG_TKIP:
81 		len = scnprintf(buf, sizeof(buf), "%08x %04x\n",
82 				key->u.tkip.iv32,
83 				key->u.tkip.iv16);
84 	case ALG_CCMP:
85 		tpn = key->u.ccmp.tx_pn;
86 		len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n",
87 				tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], tpn[5]);
88 	default:
89 		return 0;
90 	}
91 	return simple_read_from_buffer(userbuf, count, ppos, buf, len);
92 }
93 KEY_OPS(tx_spec);
94 
95 static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf,
96 				size_t count, loff_t *ppos)
97 {
98 	struct ieee80211_key *key = file->private_data;
99 	char buf[14*NUM_RX_DATA_QUEUES+1], *p = buf;
100 	int i, len;
101 	const u8 *rpn;
102 
103 	switch (key->alg) {
104 	case ALG_WEP:
105 		len = scnprintf(buf, sizeof(buf), "\n");
106 	case ALG_TKIP:
107 		for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
108 			p += scnprintf(p, sizeof(buf)+buf-p,
109 				       "%08x %04x\n",
110 				       key->u.tkip.iv32_rx[i],
111 				       key->u.tkip.iv16_rx[i]);
112 		len = p - buf;
113 	case ALG_CCMP:
114 		for (i = 0; i < NUM_RX_DATA_QUEUES; i++) {
115 			rpn = key->u.ccmp.rx_pn[i];
116 			p += scnprintf(p, sizeof(buf)+buf-p,
117 				       "%02x%02x%02x%02x%02x%02x\n",
118 				       rpn[0], rpn[1], rpn[2],
119 				       rpn[3], rpn[4], rpn[5]);
120 		}
121 		len = p - buf;
122 	default:
123 		return 0;
124 	}
125 	return simple_read_from_buffer(userbuf, count, ppos, buf, len);
126 }
127 KEY_OPS(rx_spec);
128 
129 static ssize_t key_replays_read(struct file *file, char __user *userbuf,
130 				size_t count, loff_t *ppos)
131 {
132 	struct ieee80211_key *key = file->private_data;
133 	char buf[20];
134 	int len;
135 
136 	if (key->alg != ALG_CCMP)
137 		return 0;
138 	len = scnprintf(buf, sizeof(buf), "%u\n", key->u.ccmp.replays);
139 	return simple_read_from_buffer(userbuf, count, ppos, buf, len);
140 }
141 KEY_OPS(replays);
142 
143 static ssize_t key_key_read(struct file *file, char __user *userbuf,
144 			    size_t count, loff_t *ppos)
145 {
146 	struct ieee80211_key *key = file->private_data;
147 	int i, res, bufsize = 2*key->keylen+2;
148 	char *buf = kmalloc(bufsize, GFP_KERNEL);
149 	char *p = buf;
150 
151 	for (i = 0; i < key->keylen; i++)
152 		p += scnprintf(p, bufsize+buf-p, "%02x", key->key[i]);
153 	p += scnprintf(p, bufsize+buf-p, "\n");
154 	res = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
155 	kfree(buf);
156 	return res;
157 }
158 KEY_OPS(key);
159 
160 #define DEBUGFS_ADD(name) \
161 	key->debugfs.name = debugfs_create_file(#name, 0400,\
162 				key->debugfs.dir, key, &key_##name##_ops);
163 
164 void ieee80211_debugfs_key_add(struct ieee80211_local *local,
165 			       struct ieee80211_key *key)
166 {
167 	char buf[20];
168 
169 	if (!local->debugfs.keys)
170 		return;
171 
172 	sprintf(buf, "%d", key->keyidx);
173 	key->debugfs.dir = debugfs_create_dir(buf,
174 					local->debugfs.keys);
175 
176 	if (!key->debugfs.dir)
177 		return;
178 
179 	DEBUGFS_ADD(keylen);
180 	DEBUGFS_ADD(force_sw_encrypt);
181 	DEBUGFS_ADD(keyidx);
182 	DEBUGFS_ADD(hw_key_idx);
183 	DEBUGFS_ADD(tx_rx_count);
184 	DEBUGFS_ADD(algorithm);
185 	DEBUGFS_ADD(tx_spec);
186 	DEBUGFS_ADD(rx_spec);
187 	DEBUGFS_ADD(replays);
188 	DEBUGFS_ADD(key);
189 };
190 
191 #define DEBUGFS_DEL(name) \
192 	debugfs_remove(key->debugfs.name); key->debugfs.name = NULL;
193 
194 void ieee80211_debugfs_key_remove(struct ieee80211_key *key)
195 {
196 	if (!key)
197 		return;
198 
199 	DEBUGFS_DEL(keylen);
200 	DEBUGFS_DEL(force_sw_encrypt);
201 	DEBUGFS_DEL(keyidx);
202 	DEBUGFS_DEL(hw_key_idx);
203 	DEBUGFS_DEL(tx_rx_count);
204 	DEBUGFS_DEL(algorithm);
205 	DEBUGFS_DEL(tx_spec);
206 	DEBUGFS_DEL(rx_spec);
207 	DEBUGFS_DEL(replays);
208 	DEBUGFS_DEL(key);
209 
210 	debugfs_remove(key->debugfs.stalink);
211 	key->debugfs.stalink = NULL;
212 	debugfs_remove(key->debugfs.dir);
213 	key->debugfs.dir = NULL;
214 }
215 void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata)
216 {
217 	char buf[50];
218 
219 	if (!sdata->debugfsdir)
220 		return;
221 
222 	sprintf(buf, "../keys/%d", sdata->default_key->keyidx);
223 	sdata->debugfs.default_key =
224 		debugfs_create_symlink("default_key", sdata->debugfsdir, buf);
225 }
226 void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata)
227 {
228 	if (!sdata)
229 		return;
230 
231 	debugfs_remove(sdata->debugfs.default_key);
232 	sdata->debugfs.default_key = NULL;
233 }
234 void ieee80211_debugfs_key_sta_link(struct ieee80211_key *key,
235 				    struct sta_info *sta)
236 {
237 	char buf[50];
238 
239 	if (!key->debugfs.dir)
240 		return;
241 
242 	sprintf(buf, "../sta/" MAC_FMT, MAC_ARG(sta->addr));
243 	key->debugfs.stalink =
244 		debugfs_create_symlink("station", key->debugfs.dir, buf);
245 }
246 
247 void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
248 				   struct sta_info *sta)
249 {
250 	debugfs_remove(key->debugfs.stalink);
251 	key->debugfs.stalink = NULL;
252 }
253