bnx2/bnx2x: Unsupported Ethtool operations should return -EINVAL.
[pandora-kernel.git] / net / mac80211 / debugfs_key.c
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 <linux/slab.h>
13 #include "ieee80211_i.h"
14 #include "key.h"
15 #include "debugfs.h"
16 #include "debugfs_key.h"
17
18 #define KEY_READ(name, prop, buflen, format_string)                     \
19 static ssize_t key_##name##_read(struct file *file,                     \
20                                  char __user *userbuf,                  \
21                                  size_t count, loff_t *ppos)            \
22 {                                                                       \
23         char buf[buflen];                                               \
24         struct ieee80211_key *key = file->private_data;                 \
25         int res = scnprintf(buf, buflen, format_string, key->prop);     \
26         return simple_read_from_buffer(userbuf, count, ppos, buf, res); \
27 }
28 #define KEY_READ_D(name) KEY_READ(name, name, 20, "%d\n")
29 #define KEY_READ_X(name) KEY_READ(name, name, 20, "0x%x\n")
30
31 #define KEY_OPS(name)                                                   \
32 static const struct file_operations key_ ##name## _ops = {              \
33         .read = key_##name##_read,                                      \
34         .open = mac80211_open_file_generic,                             \
35 }
36
37 #define KEY_FILE(name, format)                                          \
38                  KEY_READ_##format(name)                                \
39                  KEY_OPS(name)
40
41 #define KEY_CONF_READ(name, buflen, format_string)                      \
42         KEY_READ(conf_##name, conf.name, buflen, format_string)
43 #define KEY_CONF_READ_D(name) KEY_CONF_READ(name, 20, "%d\n")
44
45 #define KEY_CONF_OPS(name)                                              \
46 static const struct file_operations key_ ##name## _ops = {              \
47         .read = key_conf_##name##_read,                                 \
48         .open = mac80211_open_file_generic,                             \
49 }
50
51 #define KEY_CONF_FILE(name, format)                                     \
52                  KEY_CONF_READ_##format(name)                           \
53                  KEY_CONF_OPS(name)
54
55 KEY_CONF_FILE(keylen, D);
56 KEY_CONF_FILE(keyidx, D);
57 KEY_CONF_FILE(hw_key_idx, D);
58 KEY_FILE(flags, X);
59 KEY_FILE(tx_rx_count, D);
60 KEY_READ(ifindex, sdata->name, IFNAMSIZ + 2, "%s\n");
61 KEY_OPS(ifindex);
62
63 static ssize_t key_algorithm_read(struct file *file,
64                                   char __user *userbuf,
65                                   size_t count, loff_t *ppos)
66 {
67         char buf[15];
68         struct ieee80211_key *key = file->private_data;
69         u32 c = key->conf.cipher;
70
71         sprintf(buf, "%.2x-%.2x-%.2x:%d\n",
72                 c >> 24, (c >> 16) & 0xff, (c >> 8) & 0xff, c & 0xff);
73         return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf));
74 }
75 KEY_OPS(algorithm);
76
77 static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf,
78                                 size_t count, loff_t *ppos)
79 {
80         const u8 *tpn;
81         char buf[20];
82         int len;
83         struct ieee80211_key *key = file->private_data;
84
85         switch (key->conf.cipher) {
86         case WLAN_CIPHER_SUITE_WEP40:
87         case WLAN_CIPHER_SUITE_WEP104:
88                 len = scnprintf(buf, sizeof(buf), "\n");
89                 break;
90         case WLAN_CIPHER_SUITE_TKIP:
91                 len = scnprintf(buf, sizeof(buf), "%08x %04x\n",
92                                 key->u.tkip.tx.iv32,
93                                 key->u.tkip.tx.iv16);
94                 break;
95         case WLAN_CIPHER_SUITE_CCMP:
96                 tpn = key->u.ccmp.tx_pn;
97                 len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n",
98                                 tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], tpn[5]);
99                 break;
100         case WLAN_CIPHER_SUITE_AES_CMAC:
101                 tpn = key->u.aes_cmac.tx_pn;
102                 len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n",
103                                 tpn[0], tpn[1], tpn[2], tpn[3], tpn[4],
104                                 tpn[5]);
105                 break;
106         default:
107                 return 0;
108         }
109         return simple_read_from_buffer(userbuf, count, ppos, buf, len);
110 }
111 KEY_OPS(tx_spec);
112
113 static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf,
114                                 size_t count, loff_t *ppos)
115 {
116         struct ieee80211_key *key = file->private_data;
117         char buf[14*NUM_RX_DATA_QUEUES+1], *p = buf;
118         int i, len;
119         const u8 *rpn;
120
121         switch (key->conf.cipher) {
122         case WLAN_CIPHER_SUITE_WEP40:
123         case WLAN_CIPHER_SUITE_WEP104:
124                 len = scnprintf(buf, sizeof(buf), "\n");
125                 break;
126         case WLAN_CIPHER_SUITE_TKIP:
127                 for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
128                         p += scnprintf(p, sizeof(buf)+buf-p,
129                                        "%08x %04x\n",
130                                        key->u.tkip.rx[i].iv32,
131                                        key->u.tkip.rx[i].iv16);
132                 len = p - buf;
133                 break;
134         case WLAN_CIPHER_SUITE_CCMP:
135                 for (i = 0; i < NUM_RX_DATA_QUEUES + 1; i++) {
136                         rpn = key->u.ccmp.rx_pn[i];
137                         p += scnprintf(p, sizeof(buf)+buf-p,
138                                        "%02x%02x%02x%02x%02x%02x\n",
139                                        rpn[0], rpn[1], rpn[2],
140                                        rpn[3], rpn[4], rpn[5]);
141                 }
142                 len = p - buf;
143                 break;
144         case WLAN_CIPHER_SUITE_AES_CMAC:
145                 rpn = key->u.aes_cmac.rx_pn;
146                 p += scnprintf(p, sizeof(buf)+buf-p,
147                                "%02x%02x%02x%02x%02x%02x\n",
148                                rpn[0], rpn[1], rpn[2],
149                                rpn[3], rpn[4], rpn[5]);
150                 len = p - buf;
151                 break;
152         default:
153                 return 0;
154         }
155         return simple_read_from_buffer(userbuf, count, ppos, buf, len);
156 }
157 KEY_OPS(rx_spec);
158
159 static ssize_t key_replays_read(struct file *file, char __user *userbuf,
160                                 size_t count, loff_t *ppos)
161 {
162         struct ieee80211_key *key = file->private_data;
163         char buf[20];
164         int len;
165
166         switch (key->conf.cipher) {
167         case WLAN_CIPHER_SUITE_CCMP:
168                 len = scnprintf(buf, sizeof(buf), "%u\n", key->u.ccmp.replays);
169                 break;
170         case WLAN_CIPHER_SUITE_AES_CMAC:
171                 len = scnprintf(buf, sizeof(buf), "%u\n",
172                                 key->u.aes_cmac.replays);
173                 break;
174         default:
175                 return 0;
176         }
177         return simple_read_from_buffer(userbuf, count, ppos, buf, len);
178 }
179 KEY_OPS(replays);
180
181 static ssize_t key_icverrors_read(struct file *file, char __user *userbuf,
182                                   size_t count, loff_t *ppos)
183 {
184         struct ieee80211_key *key = file->private_data;
185         char buf[20];
186         int len;
187
188         switch (key->conf.cipher) {
189         case WLAN_CIPHER_SUITE_AES_CMAC:
190                 len = scnprintf(buf, sizeof(buf), "%u\n",
191                                 key->u.aes_cmac.icverrors);
192                 break;
193         default:
194                 return 0;
195         }
196         return simple_read_from_buffer(userbuf, count, ppos, buf, len);
197 }
198 KEY_OPS(icverrors);
199
200 static ssize_t key_key_read(struct file *file, char __user *userbuf,
201                             size_t count, loff_t *ppos)
202 {
203         struct ieee80211_key *key = file->private_data;
204         int i, res, bufsize = 2 * key->conf.keylen + 2;
205         char *buf = kmalloc(bufsize, GFP_KERNEL);
206         char *p = buf;
207
208         for (i = 0; i < key->conf.keylen; i++)
209                 p += scnprintf(p, bufsize + buf - p, "%02x", key->conf.key[i]);
210         p += scnprintf(p, bufsize+buf-p, "\n");
211         res = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
212         kfree(buf);
213         return res;
214 }
215 KEY_OPS(key);
216
217 #define DEBUGFS_ADD(name) \
218         debugfs_create_file(#name, 0400, key->debugfs.dir, \
219                             key, &key_##name##_ops);
220
221 void ieee80211_debugfs_key_add(struct ieee80211_key *key)
222   {
223         static int keycount;
224         char buf[50];
225         struct sta_info *sta;
226
227         if (!key->local->debugfs.keys)
228                 return;
229
230         sprintf(buf, "%d", keycount);
231         key->debugfs.cnt = keycount;
232         keycount++;
233         key->debugfs.dir = debugfs_create_dir(buf,
234                                         key->local->debugfs.keys);
235
236         if (!key->debugfs.dir)
237                 return;
238
239         rcu_read_lock();
240         sta = rcu_dereference(key->sta);
241         if (sta)
242                 sprintf(buf, "../../stations/%pM", sta->sta.addr);
243         rcu_read_unlock();
244
245         /* using sta as a boolean is fine outside RCU lock */
246         if (sta)
247                 key->debugfs.stalink =
248                         debugfs_create_symlink("station", key->debugfs.dir, buf);
249
250         DEBUGFS_ADD(keylen);
251         DEBUGFS_ADD(flags);
252         DEBUGFS_ADD(keyidx);
253         DEBUGFS_ADD(hw_key_idx);
254         DEBUGFS_ADD(tx_rx_count);
255         DEBUGFS_ADD(algorithm);
256         DEBUGFS_ADD(tx_spec);
257         DEBUGFS_ADD(rx_spec);
258         DEBUGFS_ADD(replays);
259         DEBUGFS_ADD(icverrors);
260         DEBUGFS_ADD(key);
261         DEBUGFS_ADD(ifindex);
262 };
263
264 void ieee80211_debugfs_key_remove(struct ieee80211_key *key)
265 {
266         if (!key)
267                 return;
268
269         debugfs_remove_recursive(key->debugfs.dir);
270         key->debugfs.dir = NULL;
271 }
272 void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata)
273 {
274         char buf[50];
275         struct ieee80211_key *key;
276
277         if (!sdata->debugfs.dir)
278                 return;
279
280         /* this is running under the key lock */
281
282         key = sdata->default_key;
283         if (key) {
284                 sprintf(buf, "../keys/%d", key->debugfs.cnt);
285                 sdata->debugfs.default_key =
286                         debugfs_create_symlink("default_key",
287                                                sdata->debugfs.dir, buf);
288         } else
289                 ieee80211_debugfs_key_remove_default(sdata);
290 }
291
292 void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata)
293 {
294         if (!sdata)
295                 return;
296
297         debugfs_remove(sdata->debugfs.default_key);
298         sdata->debugfs.default_key = NULL;
299 }
300
301 void ieee80211_debugfs_key_add_mgmt_default(struct ieee80211_sub_if_data *sdata)
302 {
303         char buf[50];
304         struct ieee80211_key *key;
305
306         if (!sdata->debugfs.dir)
307                 return;
308
309         /* this is running under the key lock */
310
311         key = sdata->default_mgmt_key;
312         if (key) {
313                 sprintf(buf, "../keys/%d", key->debugfs.cnt);
314                 sdata->debugfs.default_mgmt_key =
315                         debugfs_create_symlink("default_mgmt_key",
316                                                sdata->debugfs.dir, buf);
317         } else
318                 ieee80211_debugfs_key_remove_mgmt_default(sdata);
319 }
320
321 void ieee80211_debugfs_key_remove_mgmt_default(struct ieee80211_sub_if_data *sdata)
322 {
323         if (!sdata)
324                 return;
325
326         debugfs_remove(sdata->debugfs.default_mgmt_key);
327         sdata->debugfs.default_mgmt_key = NULL;
328 }
329
330 void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
331                                    struct sta_info *sta)
332 {
333         debugfs_remove(key->debugfs.stalink);
334         key->debugfs.stalink = NULL;
335 }