]> Pileus Git - ~andy/linux/blob - net/mac80211/debugfs_key.c
[MAC80211]: fix key debugfs
[~andy/linux] / 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 "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                 break;
81         case ALG_TKIP:
82                 len = scnprintf(buf, sizeof(buf), "%08x %04x\n",
83                                 key->u.tkip.iv32,
84                                 key->u.tkip.iv16);
85                 break;
86         case ALG_CCMP:
87                 tpn = key->u.ccmp.tx_pn;
88                 len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n",
89                                 tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], tpn[5]);
90                 break;
91         default:
92                 return 0;
93         }
94         return simple_read_from_buffer(userbuf, count, ppos, buf, len);
95 }
96 KEY_OPS(tx_spec);
97
98 static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf,
99                                 size_t count, loff_t *ppos)
100 {
101         struct ieee80211_key *key = file->private_data;
102         char buf[14*NUM_RX_DATA_QUEUES+1], *p = buf;
103         int i, len;
104         const u8 *rpn;
105
106         switch (key->alg) {
107         case ALG_WEP:
108                 len = scnprintf(buf, sizeof(buf), "\n");
109                 break;
110         case ALG_TKIP:
111                 for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
112                         p += scnprintf(p, sizeof(buf)+buf-p,
113                                        "%08x %04x\n",
114                                        key->u.tkip.iv32_rx[i],
115                                        key->u.tkip.iv16_rx[i]);
116                 len = p - buf;
117                 break;
118         case ALG_CCMP:
119                 for (i = 0; i < NUM_RX_DATA_QUEUES; i++) {
120                         rpn = key->u.ccmp.rx_pn[i];
121                         p += scnprintf(p, sizeof(buf)+buf-p,
122                                        "%02x%02x%02x%02x%02x%02x\n",
123                                        rpn[0], rpn[1], rpn[2],
124                                        rpn[3], rpn[4], rpn[5]);
125                 }
126                 len = p - buf;
127                 break;
128         default:
129                 return 0;
130         }
131         return simple_read_from_buffer(userbuf, count, ppos, buf, len);
132 }
133 KEY_OPS(rx_spec);
134
135 static ssize_t key_replays_read(struct file *file, char __user *userbuf,
136                                 size_t count, loff_t *ppos)
137 {
138         struct ieee80211_key *key = file->private_data;
139         char buf[20];
140         int len;
141
142         if (key->alg != ALG_CCMP)
143                 return 0;
144         len = scnprintf(buf, sizeof(buf), "%u\n", key->u.ccmp.replays);
145         return simple_read_from_buffer(userbuf, count, ppos, buf, len);
146 }
147 KEY_OPS(replays);
148
149 static ssize_t key_key_read(struct file *file, char __user *userbuf,
150                             size_t count, loff_t *ppos)
151 {
152         struct ieee80211_key *key = file->private_data;
153         int i, res, bufsize = 2*key->keylen+2;
154         char *buf = kmalloc(bufsize, GFP_KERNEL);
155         char *p = buf;
156
157         for (i = 0; i < key->keylen; i++)
158                 p += scnprintf(p, bufsize+buf-p, "%02x", key->key[i]);
159         p += scnprintf(p, bufsize+buf-p, "\n");
160         res = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
161         kfree(buf);
162         return res;
163 }
164 KEY_OPS(key);
165
166 #define DEBUGFS_ADD(name) \
167         key->debugfs.name = debugfs_create_file(#name, 0400,\
168                                 key->debugfs.dir, key, &key_##name##_ops);
169
170 void ieee80211_debugfs_key_add(struct ieee80211_local *local,
171                                struct ieee80211_key *key)
172 {
173         static int keycount;
174         char buf[20];
175
176         if (!local->debugfs.keys)
177                 return;
178
179         sprintf(buf, "%d", keycount);
180         keycount++;
181         key->debugfs.dir = debugfs_create_dir(buf,
182                                         local->debugfs.keys);
183
184         if (!key->debugfs.dir)
185                 return;
186
187         DEBUGFS_ADD(keylen);
188         DEBUGFS_ADD(force_sw_encrypt);
189         DEBUGFS_ADD(keyidx);
190         DEBUGFS_ADD(hw_key_idx);
191         DEBUGFS_ADD(tx_rx_count);
192         DEBUGFS_ADD(algorithm);
193         DEBUGFS_ADD(tx_spec);
194         DEBUGFS_ADD(rx_spec);
195         DEBUGFS_ADD(replays);
196         DEBUGFS_ADD(key);
197 };
198
199 #define DEBUGFS_DEL(name) \
200         debugfs_remove(key->debugfs.name); key->debugfs.name = NULL;
201
202 void ieee80211_debugfs_key_remove(struct ieee80211_key *key)
203 {
204         if (!key)
205                 return;
206
207         DEBUGFS_DEL(keylen);
208         DEBUGFS_DEL(force_sw_encrypt);
209         DEBUGFS_DEL(keyidx);
210         DEBUGFS_DEL(hw_key_idx);
211         DEBUGFS_DEL(tx_rx_count);
212         DEBUGFS_DEL(algorithm);
213         DEBUGFS_DEL(tx_spec);
214         DEBUGFS_DEL(rx_spec);
215         DEBUGFS_DEL(replays);
216         DEBUGFS_DEL(key);
217
218         debugfs_remove(key->debugfs.stalink);
219         key->debugfs.stalink = NULL;
220         debugfs_remove(key->debugfs.dir);
221         key->debugfs.dir = NULL;
222 }
223 void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata)
224 {
225         char buf[50];
226
227         if (!sdata->debugfsdir)
228                 return;
229
230         sprintf(buf, "../keys/%d", sdata->default_key->keyidx);
231         sdata->debugfs.default_key =
232                 debugfs_create_symlink("default_key", sdata->debugfsdir, buf);
233 }
234 void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata)
235 {
236         if (!sdata)
237                 return;
238
239         debugfs_remove(sdata->debugfs.default_key);
240         sdata->debugfs.default_key = NULL;
241 }
242 void ieee80211_debugfs_key_sta_link(struct ieee80211_key *key,
243                                     struct sta_info *sta)
244 {
245         char buf[50];
246
247         if (!key->debugfs.dir)
248                 return;
249
250         sprintf(buf, "../../stations/" MAC_FMT, MAC_ARG(sta->addr));
251         key->debugfs.stalink =
252                 debugfs_create_symlink("station", key->debugfs.dir, buf);
253 }
254
255 void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
256                                    struct sta_info *sta)
257 {
258         debugfs_remove(key->debugfs.stalink);
259         key->debugfs.stalink = NULL;
260 }