xref: /openbmc/linux/net/mac80211/debugfs_netdev.c (revision c21b37f6)
1 /*
2  * Copyright (c) 2006	Jiri Benc <jbenc@suse.cz>
3  * Copyright 2007	Johannes Berg <johannes@sipsolutions.net>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  */
9 
10 #include <linux/kernel.h>
11 #include <linux/device.h>
12 #include <linux/if.h>
13 #include <linux/interrupt.h>
14 #include <linux/netdevice.h>
15 #include <linux/rtnetlink.h>
16 #include <linux/notifier.h>
17 #include <net/mac80211.h>
18 #include <net/cfg80211.h>
19 #include "ieee80211_i.h"
20 #include "ieee80211_rate.h"
21 #include "debugfs.h"
22 #include "debugfs_netdev.h"
23 
24 static ssize_t ieee80211_if_read(
25 	struct ieee80211_sub_if_data *sdata,
26 	char __user *userbuf,
27 	size_t count, loff_t *ppos,
28 	ssize_t (*format)(const struct ieee80211_sub_if_data *, char *, int))
29 {
30 	char buf[70];
31 	ssize_t ret = -EINVAL;
32 
33 	read_lock(&dev_base_lock);
34 	if (sdata->dev->reg_state == NETREG_REGISTERED) {
35 		ret = (*format)(sdata, buf, sizeof(buf));
36 		ret = simple_read_from_buffer(userbuf, count, ppos, buf, ret);
37 	}
38 	read_unlock(&dev_base_lock);
39 	return ret;
40 }
41 
42 #define IEEE80211_IF_FMT(name, field, format_string)			\
43 static ssize_t ieee80211_if_fmt_##name(					\
44 	const struct ieee80211_sub_if_data *sdata, char *buf,		\
45 	int buflen)							\
46 {									\
47 	return scnprintf(buf, buflen, format_string, sdata->field);	\
48 }
49 #define IEEE80211_IF_FMT_DEC(name, field)				\
50 		IEEE80211_IF_FMT(name, field, "%d\n")
51 #define IEEE80211_IF_FMT_HEX(name, field)				\
52 		IEEE80211_IF_FMT(name, field, "%#x\n")
53 #define IEEE80211_IF_FMT_SIZE(name, field)				\
54 		IEEE80211_IF_FMT(name, field, "%zd\n")
55 
56 #define IEEE80211_IF_FMT_ATOMIC(name, field)				\
57 static ssize_t ieee80211_if_fmt_##name(					\
58 	const struct ieee80211_sub_if_data *sdata,			\
59 	char *buf, int buflen)						\
60 {									\
61 	return scnprintf(buf, buflen, "%d\n", atomic_read(&sdata->field));\
62 }
63 
64 #define IEEE80211_IF_FMT_MAC(name, field)				\
65 static ssize_t ieee80211_if_fmt_##name(					\
66 	const struct ieee80211_sub_if_data *sdata, char *buf,		\
67 	int buflen)							\
68 {									\
69 	return scnprintf(buf, buflen, MAC_FMT "\n", MAC_ARG(sdata->field));\
70 }
71 
72 #define __IEEE80211_IF_FILE(name)					\
73 static ssize_t ieee80211_if_read_##name(struct file *file,		\
74 					char __user *userbuf,		\
75 					size_t count, loff_t *ppos)	\
76 {									\
77 	return ieee80211_if_read(file->private_data,			\
78 				 userbuf, count, ppos,			\
79 				 ieee80211_if_fmt_##name);		\
80 }									\
81 static const struct file_operations name##_ops = {			\
82 	.read = ieee80211_if_read_##name,				\
83 	.open = mac80211_open_file_generic,				\
84 }
85 
86 #define IEEE80211_IF_FILE(name, field, format)				\
87 		IEEE80211_IF_FMT_##format(name, field)			\
88 		__IEEE80211_IF_FILE(name)
89 
90 /* common attributes */
91 IEEE80211_IF_FILE(channel_use, channel_use, DEC);
92 IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC);
93 IEEE80211_IF_FILE(eapol, eapol, DEC);
94 IEEE80211_IF_FILE(ieee8021_x, ieee802_1x, DEC);
95 
96 /* STA/IBSS attributes */
97 IEEE80211_IF_FILE(state, u.sta.state, DEC);
98 IEEE80211_IF_FILE(bssid, u.sta.bssid, MAC);
99 IEEE80211_IF_FILE(prev_bssid, u.sta.prev_bssid, MAC);
100 IEEE80211_IF_FILE(ssid_len, u.sta.ssid_len, SIZE);
101 IEEE80211_IF_FILE(aid, u.sta.aid, DEC);
102 IEEE80211_IF_FILE(ap_capab, u.sta.ap_capab, HEX);
103 IEEE80211_IF_FILE(capab, u.sta.capab, HEX);
104 IEEE80211_IF_FILE(extra_ie_len, u.sta.extra_ie_len, SIZE);
105 IEEE80211_IF_FILE(auth_tries, u.sta.auth_tries, DEC);
106 IEEE80211_IF_FILE(assoc_tries, u.sta.assoc_tries, DEC);
107 IEEE80211_IF_FILE(auth_algs, u.sta.auth_algs, HEX);
108 IEEE80211_IF_FILE(auth_alg, u.sta.auth_alg, DEC);
109 IEEE80211_IF_FILE(auth_transaction, u.sta.auth_transaction, DEC);
110 
111 static ssize_t ieee80211_if_fmt_flags(
112 	const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
113 {
114 	return scnprintf(buf, buflen, "%s%s%s%s%s%s%s\n",
115 			 sdata->u.sta.ssid_set ? "SSID\n" : "",
116 			 sdata->u.sta.bssid_set ? "BSSID\n" : "",
117 			 sdata->u.sta.prev_bssid_set ? "prev BSSID\n" : "",
118 			 sdata->u.sta.authenticated ? "AUTH\n" : "",
119 			 sdata->u.sta.associated ? "ASSOC\n" : "",
120 			 sdata->u.sta.probereq_poll ? "PROBEREQ POLL\n" : "",
121 			 sdata->use_protection ? "CTS prot\n" : "");
122 }
123 __IEEE80211_IF_FILE(flags);
124 
125 /* AP attributes */
126 IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC);
127 IEEE80211_IF_FILE(dtim_period, u.ap.dtim_period, DEC);
128 IEEE80211_IF_FILE(dtim_count, u.ap.dtim_count, DEC);
129 IEEE80211_IF_FILE(num_beacons, u.ap.num_beacons, DEC);
130 IEEE80211_IF_FILE(force_unicast_rateidx, u.ap.force_unicast_rateidx, DEC);
131 IEEE80211_IF_FILE(max_ratectrl_rateidx, u.ap.max_ratectrl_rateidx, DEC);
132 
133 static ssize_t ieee80211_if_fmt_num_buffered_multicast(
134 	const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
135 {
136 	return scnprintf(buf, buflen, "%u\n",
137 			 skb_queue_len(&sdata->u.ap.ps_bc_buf));
138 }
139 __IEEE80211_IF_FILE(num_buffered_multicast);
140 
141 static ssize_t ieee80211_if_fmt_beacon_head_len(
142 	const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
143 {
144 	if (sdata->u.ap.beacon_head)
145 		return scnprintf(buf, buflen, "%d\n",
146 				 sdata->u.ap.beacon_head_len);
147 	return scnprintf(buf, buflen, "\n");
148 }
149 __IEEE80211_IF_FILE(beacon_head_len);
150 
151 static ssize_t ieee80211_if_fmt_beacon_tail_len(
152 	const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
153 {
154 	if (sdata->u.ap.beacon_tail)
155 		return scnprintf(buf, buflen, "%d\n",
156 				 sdata->u.ap.beacon_tail_len);
157 	return scnprintf(buf, buflen, "\n");
158 }
159 __IEEE80211_IF_FILE(beacon_tail_len);
160 
161 /* WDS attributes */
162 IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC);
163 
164 /* VLAN attributes */
165 IEEE80211_IF_FILE(vlan_id, u.vlan.id, DEC);
166 
167 /* MONITOR attributes */
168 static ssize_t ieee80211_if_fmt_mode(
169 	const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
170 {
171 	struct ieee80211_local *local = sdata->local;
172 
173 	return scnprintf(buf, buflen, "%s\n",
174 			 ((local->hw.flags & IEEE80211_HW_MONITOR_DURING_OPER) ||
175 			  local->open_count == local->monitors) ?
176 			 "hard" : "soft");
177 }
178 __IEEE80211_IF_FILE(mode);
179 
180 
181 #define DEBUGFS_ADD(name, type)\
182 	sdata->debugfs.type.name = debugfs_create_file(#name, 0444,\
183 		sdata->debugfsdir, sdata, &name##_ops);
184 
185 static void add_sta_files(struct ieee80211_sub_if_data *sdata)
186 {
187 	DEBUGFS_ADD(channel_use, sta);
188 	DEBUGFS_ADD(drop_unencrypted, sta);
189 	DEBUGFS_ADD(eapol, sta);
190 	DEBUGFS_ADD(ieee8021_x, sta);
191 	DEBUGFS_ADD(state, sta);
192 	DEBUGFS_ADD(bssid, sta);
193 	DEBUGFS_ADD(prev_bssid, sta);
194 	DEBUGFS_ADD(ssid_len, sta);
195 	DEBUGFS_ADD(aid, sta);
196 	DEBUGFS_ADD(ap_capab, sta);
197 	DEBUGFS_ADD(capab, sta);
198 	DEBUGFS_ADD(extra_ie_len, sta);
199 	DEBUGFS_ADD(auth_tries, sta);
200 	DEBUGFS_ADD(assoc_tries, sta);
201 	DEBUGFS_ADD(auth_algs, sta);
202 	DEBUGFS_ADD(auth_alg, sta);
203 	DEBUGFS_ADD(auth_transaction, sta);
204 	DEBUGFS_ADD(flags, sta);
205 }
206 
207 static void add_ap_files(struct ieee80211_sub_if_data *sdata)
208 {
209 	DEBUGFS_ADD(channel_use, ap);
210 	DEBUGFS_ADD(drop_unencrypted, ap);
211 	DEBUGFS_ADD(eapol, ap);
212 	DEBUGFS_ADD(ieee8021_x, ap);
213 	DEBUGFS_ADD(num_sta_ps, ap);
214 	DEBUGFS_ADD(dtim_period, ap);
215 	DEBUGFS_ADD(dtim_count, ap);
216 	DEBUGFS_ADD(num_beacons, ap);
217 	DEBUGFS_ADD(force_unicast_rateidx, ap);
218 	DEBUGFS_ADD(max_ratectrl_rateidx, ap);
219 	DEBUGFS_ADD(num_buffered_multicast, ap);
220 	DEBUGFS_ADD(beacon_head_len, ap);
221 	DEBUGFS_ADD(beacon_tail_len, ap);
222 }
223 
224 static void add_wds_files(struct ieee80211_sub_if_data *sdata)
225 {
226 	DEBUGFS_ADD(channel_use, wds);
227 	DEBUGFS_ADD(drop_unencrypted, wds);
228 	DEBUGFS_ADD(eapol, wds);
229 	DEBUGFS_ADD(ieee8021_x, wds);
230 	DEBUGFS_ADD(peer, wds);
231 }
232 
233 static void add_vlan_files(struct ieee80211_sub_if_data *sdata)
234 {
235 	DEBUGFS_ADD(channel_use, vlan);
236 	DEBUGFS_ADD(drop_unencrypted, vlan);
237 	DEBUGFS_ADD(eapol, vlan);
238 	DEBUGFS_ADD(ieee8021_x, vlan);
239 	DEBUGFS_ADD(vlan_id, vlan);
240 }
241 
242 static void add_monitor_files(struct ieee80211_sub_if_data *sdata)
243 {
244 	DEBUGFS_ADD(mode, monitor);
245 }
246 
247 static void add_files(struct ieee80211_sub_if_data *sdata)
248 {
249 	if (!sdata->debugfsdir)
250 		return;
251 
252 	switch (sdata->type) {
253 	case IEEE80211_IF_TYPE_STA:
254 	case IEEE80211_IF_TYPE_IBSS:
255 		add_sta_files(sdata);
256 		break;
257 	case IEEE80211_IF_TYPE_AP:
258 		add_ap_files(sdata);
259 		break;
260 	case IEEE80211_IF_TYPE_WDS:
261 		add_wds_files(sdata);
262 		break;
263 	case IEEE80211_IF_TYPE_MNTR:
264 		add_monitor_files(sdata);
265 		break;
266 	case IEEE80211_IF_TYPE_VLAN:
267 		add_vlan_files(sdata);
268 		break;
269 	default:
270 		break;
271 	}
272 }
273 
274 #define DEBUGFS_DEL(name, type)\
275 	debugfs_remove(sdata->debugfs.type.name);\
276 	sdata->debugfs.type.name = NULL;
277 
278 static void del_sta_files(struct ieee80211_sub_if_data *sdata)
279 {
280 	DEBUGFS_DEL(channel_use, sta);
281 	DEBUGFS_DEL(drop_unencrypted, sta);
282 	DEBUGFS_DEL(eapol, sta);
283 	DEBUGFS_DEL(ieee8021_x, sta);
284 	DEBUGFS_DEL(state, sta);
285 	DEBUGFS_DEL(bssid, sta);
286 	DEBUGFS_DEL(prev_bssid, sta);
287 	DEBUGFS_DEL(ssid_len, sta);
288 	DEBUGFS_DEL(aid, sta);
289 	DEBUGFS_DEL(ap_capab, sta);
290 	DEBUGFS_DEL(capab, sta);
291 	DEBUGFS_DEL(extra_ie_len, sta);
292 	DEBUGFS_DEL(auth_tries, sta);
293 	DEBUGFS_DEL(assoc_tries, sta);
294 	DEBUGFS_DEL(auth_algs, sta);
295 	DEBUGFS_DEL(auth_alg, sta);
296 	DEBUGFS_DEL(auth_transaction, sta);
297 	DEBUGFS_DEL(flags, sta);
298 }
299 
300 static void del_ap_files(struct ieee80211_sub_if_data *sdata)
301 {
302 	DEBUGFS_DEL(channel_use, ap);
303 	DEBUGFS_DEL(drop_unencrypted, ap);
304 	DEBUGFS_DEL(eapol, ap);
305 	DEBUGFS_DEL(ieee8021_x, ap);
306 	DEBUGFS_DEL(num_sta_ps, ap);
307 	DEBUGFS_DEL(dtim_period, ap);
308 	DEBUGFS_DEL(dtim_count, ap);
309 	DEBUGFS_DEL(num_beacons, ap);
310 	DEBUGFS_DEL(force_unicast_rateidx, ap);
311 	DEBUGFS_DEL(max_ratectrl_rateidx, ap);
312 	DEBUGFS_DEL(num_buffered_multicast, ap);
313 	DEBUGFS_DEL(beacon_head_len, ap);
314 	DEBUGFS_DEL(beacon_tail_len, ap);
315 }
316 
317 static void del_wds_files(struct ieee80211_sub_if_data *sdata)
318 {
319 	DEBUGFS_DEL(channel_use, wds);
320 	DEBUGFS_DEL(drop_unencrypted, wds);
321 	DEBUGFS_DEL(eapol, wds);
322 	DEBUGFS_DEL(ieee8021_x, wds);
323 	DEBUGFS_DEL(peer, wds);
324 }
325 
326 static void del_vlan_files(struct ieee80211_sub_if_data *sdata)
327 {
328 	DEBUGFS_DEL(channel_use, vlan);
329 	DEBUGFS_DEL(drop_unencrypted, vlan);
330 	DEBUGFS_DEL(eapol, vlan);
331 	DEBUGFS_DEL(ieee8021_x, vlan);
332 	DEBUGFS_DEL(vlan_id, vlan);
333 }
334 
335 static void del_monitor_files(struct ieee80211_sub_if_data *sdata)
336 {
337 	DEBUGFS_DEL(mode, monitor);
338 }
339 
340 static void del_files(struct ieee80211_sub_if_data *sdata, int type)
341 {
342 	if (!sdata->debugfsdir)
343 		return;
344 
345 	switch (type) {
346 	case IEEE80211_IF_TYPE_STA:
347 	case IEEE80211_IF_TYPE_IBSS:
348 		del_sta_files(sdata);
349 		break;
350 	case IEEE80211_IF_TYPE_AP:
351 		del_ap_files(sdata);
352 		break;
353 	case IEEE80211_IF_TYPE_WDS:
354 		del_wds_files(sdata);
355 		break;
356 	case IEEE80211_IF_TYPE_MNTR:
357 		del_monitor_files(sdata);
358 		break;
359 	case IEEE80211_IF_TYPE_VLAN:
360 		del_vlan_files(sdata);
361 		break;
362 	default:
363 		break;
364 	}
365 }
366 
367 static int notif_registered;
368 
369 void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata)
370 {
371 	char buf[10+IFNAMSIZ];
372 
373 	if (!notif_registered)
374 		return;
375 
376 	sprintf(buf, "netdev:%s", sdata->dev->name);
377 	sdata->debugfsdir = debugfs_create_dir(buf,
378 		sdata->local->hw.wiphy->debugfsdir);
379 }
380 
381 void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata)
382 {
383 	del_files(sdata, sdata->type);
384 	debugfs_remove(sdata->debugfsdir);
385 	sdata->debugfsdir = NULL;
386 }
387 
388 void ieee80211_debugfs_change_if_type(struct ieee80211_sub_if_data *sdata,
389 				      int oldtype)
390 {
391 	del_files(sdata, oldtype);
392 	add_files(sdata);
393 }
394 
395 static int netdev_notify(struct notifier_block * nb,
396 			 unsigned long state,
397 			 void *ndev)
398 {
399 	struct net_device *dev = ndev;
400 	struct dentry *dir;
401 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
402 	char buf[10+IFNAMSIZ];
403 
404 	if (state != NETDEV_CHANGENAME)
405 		return 0;
406 
407 	if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy)
408 		return 0;
409 
410 	if (dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid)
411 		return 0;
412 
413 	sprintf(buf, "netdev:%s", dev->name);
414 	dir = sdata->debugfsdir;
415 	if (!debugfs_rename(dir->d_parent, dir, dir->d_parent, buf))
416 		printk(KERN_ERR "mac80211: debugfs: failed to rename debugfs "
417 		       "dir to %s\n", buf);
418 
419 	return 0;
420 }
421 
422 static struct notifier_block mac80211_debugfs_netdev_notifier = {
423 	.notifier_call = netdev_notify,
424 };
425 
426 void ieee80211_debugfs_netdev_init(void)
427 {
428 	int err;
429 
430 	err = register_netdevice_notifier(&mac80211_debugfs_netdev_notifier);
431 	if (err) {
432 		printk(KERN_ERR
433 		       "mac80211: failed to install netdev notifier,"
434 		       " disabling per-netdev debugfs!\n");
435 	} else
436 		notif_registered = 1;
437 }
438 
439 void ieee80211_debugfs_netdev_exit(void)
440 {
441 	unregister_netdevice_notifier(&mac80211_debugfs_netdev_notifier);
442 	notif_registered = 0;
443 }
444