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 "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 read_unlock(&dev_base_lock); 37 38 if (ret != -EINVAL) 39 ret = simple_read_from_buffer(userbuf, count, ppos, buf, ret); 40 41 return ret; 42 } 43 44 #define IEEE80211_IF_FMT(name, field, format_string) \ 45 static ssize_t ieee80211_if_fmt_##name( \ 46 const struct ieee80211_sub_if_data *sdata, char *buf, \ 47 int buflen) \ 48 { \ 49 return scnprintf(buf, buflen, format_string, sdata->field); \ 50 } 51 #define IEEE80211_IF_FMT_DEC(name, field) \ 52 IEEE80211_IF_FMT(name, field, "%d\n") 53 #define IEEE80211_IF_FMT_HEX(name, field) \ 54 IEEE80211_IF_FMT(name, field, "%#x\n") 55 #define IEEE80211_IF_FMT_SIZE(name, field) \ 56 IEEE80211_IF_FMT(name, field, "%zd\n") 57 58 #define IEEE80211_IF_FMT_ATOMIC(name, field) \ 59 static ssize_t ieee80211_if_fmt_##name( \ 60 const struct ieee80211_sub_if_data *sdata, \ 61 char *buf, int buflen) \ 62 { \ 63 return scnprintf(buf, buflen, "%d\n", atomic_read(&sdata->field));\ 64 } 65 66 #define IEEE80211_IF_FMT_MAC(name, field) \ 67 static ssize_t ieee80211_if_fmt_##name( \ 68 const struct ieee80211_sub_if_data *sdata, char *buf, \ 69 int buflen) \ 70 { \ 71 return scnprintf(buf, buflen, "%pM\n", sdata->field); \ 72 } 73 74 #define __IEEE80211_IF_FILE(name) \ 75 static ssize_t ieee80211_if_read_##name(struct file *file, \ 76 char __user *userbuf, \ 77 size_t count, loff_t *ppos) \ 78 { \ 79 return ieee80211_if_read(file->private_data, \ 80 userbuf, count, ppos, \ 81 ieee80211_if_fmt_##name); \ 82 } \ 83 static const struct file_operations name##_ops = { \ 84 .read = ieee80211_if_read_##name, \ 85 .open = mac80211_open_file_generic, \ 86 } 87 88 #define IEEE80211_IF_FILE(name, field, format) \ 89 IEEE80211_IF_FMT_##format(name, field) \ 90 __IEEE80211_IF_FILE(name) 91 92 /* common attributes */ 93 IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC); 94 IEEE80211_IF_FILE(force_unicast_rateidx, force_unicast_rateidx, DEC); 95 IEEE80211_IF_FILE(max_ratectrl_rateidx, max_ratectrl_rateidx, DEC); 96 97 /* STA/IBSS attributes */ 98 IEEE80211_IF_FILE(state, u.sta.state, DEC); 99 IEEE80211_IF_FILE(bssid, u.sta.bssid, MAC); 100 IEEE80211_IF_FILE(prev_bssid, u.sta.prev_bssid, MAC); 101 IEEE80211_IF_FILE(ssid_len, u.sta.ssid_len, SIZE); 102 IEEE80211_IF_FILE(aid, u.sta.aid, DEC); 103 IEEE80211_IF_FILE(ap_capab, u.sta.ap_capab, HEX); 104 IEEE80211_IF_FILE(capab, u.sta.capab, HEX); 105 IEEE80211_IF_FILE(extra_ie_len, u.sta.extra_ie_len, SIZE); 106 IEEE80211_IF_FILE(auth_tries, u.sta.auth_tries, DEC); 107 IEEE80211_IF_FILE(assoc_tries, u.sta.assoc_tries, DEC); 108 IEEE80211_IF_FILE(auth_algs, u.sta.auth_algs, HEX); 109 IEEE80211_IF_FILE(auth_alg, u.sta.auth_alg, DEC); 110 IEEE80211_IF_FILE(auth_transaction, u.sta.auth_transaction, DEC); 111 112 static ssize_t ieee80211_if_fmt_flags( 113 const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) 114 { 115 return scnprintf(buf, buflen, "%s%s%s%s%s%s%s\n", 116 sdata->u.sta.flags & IEEE80211_STA_SSID_SET ? "SSID\n" : "", 117 sdata->u.sta.flags & IEEE80211_STA_BSSID_SET ? "BSSID\n" : "", 118 sdata->u.sta.flags & IEEE80211_STA_PREV_BSSID_SET ? "prev BSSID\n" : "", 119 sdata->u.sta.flags & IEEE80211_STA_AUTHENTICATED ? "AUTH\n" : "", 120 sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED ? "ASSOC\n" : "", 121 sdata->u.sta.flags & IEEE80211_STA_PROBEREQ_POLL ? "PROBEREQ POLL\n" : "", 122 sdata->vif.bss_conf.use_cts_prot ? "CTS prot\n" : ""); 123 } 124 __IEEE80211_IF_FILE(flags); 125 126 /* AP attributes */ 127 IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC); 128 IEEE80211_IF_FILE(dtim_count, u.ap.dtim_count, DEC); 129 130 static ssize_t ieee80211_if_fmt_num_buffered_multicast( 131 const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) 132 { 133 return scnprintf(buf, buflen, "%u\n", 134 skb_queue_len(&sdata->u.ap.ps_bc_buf)); 135 } 136 __IEEE80211_IF_FILE(num_buffered_multicast); 137 138 /* WDS attributes */ 139 IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC); 140 141 #ifdef CONFIG_MAC80211_MESH 142 /* Mesh stats attributes */ 143 IEEE80211_IF_FILE(fwded_frames, u.mesh.mshstats.fwded_frames, DEC); 144 IEEE80211_IF_FILE(dropped_frames_ttl, u.mesh.mshstats.dropped_frames_ttl, DEC); 145 IEEE80211_IF_FILE(dropped_frames_no_route, 146 u.mesh.mshstats.dropped_frames_no_route, DEC); 147 IEEE80211_IF_FILE(estab_plinks, u.mesh.mshstats.estab_plinks, ATOMIC); 148 149 /* Mesh parameters */ 150 IEEE80211_IF_FILE(dot11MeshMaxRetries, 151 u.mesh.mshcfg.dot11MeshMaxRetries, DEC); 152 IEEE80211_IF_FILE(dot11MeshRetryTimeout, 153 u.mesh.mshcfg.dot11MeshRetryTimeout, DEC); 154 IEEE80211_IF_FILE(dot11MeshConfirmTimeout, 155 u.mesh.mshcfg.dot11MeshConfirmTimeout, DEC); 156 IEEE80211_IF_FILE(dot11MeshHoldingTimeout, 157 u.mesh.mshcfg.dot11MeshHoldingTimeout, DEC); 158 IEEE80211_IF_FILE(dot11MeshTTL, u.mesh.mshcfg.dot11MeshTTL, DEC); 159 IEEE80211_IF_FILE(auto_open_plinks, u.mesh.mshcfg.auto_open_plinks, DEC); 160 IEEE80211_IF_FILE(dot11MeshMaxPeerLinks, 161 u.mesh.mshcfg.dot11MeshMaxPeerLinks, DEC); 162 IEEE80211_IF_FILE(dot11MeshHWMPactivePathTimeout, 163 u.mesh.mshcfg.dot11MeshHWMPactivePathTimeout, DEC); 164 IEEE80211_IF_FILE(dot11MeshHWMPpreqMinInterval, 165 u.mesh.mshcfg.dot11MeshHWMPpreqMinInterval, DEC); 166 IEEE80211_IF_FILE(dot11MeshHWMPnetDiameterTraversalTime, 167 u.mesh.mshcfg.dot11MeshHWMPnetDiameterTraversalTime, DEC); 168 IEEE80211_IF_FILE(dot11MeshHWMPmaxPREQretries, 169 u.mesh.mshcfg.dot11MeshHWMPmaxPREQretries, DEC); 170 IEEE80211_IF_FILE(path_refresh_time, 171 u.mesh.mshcfg.path_refresh_time, DEC); 172 IEEE80211_IF_FILE(min_discovery_timeout, 173 u.mesh.mshcfg.min_discovery_timeout, DEC); 174 #endif 175 176 177 #define DEBUGFS_ADD(name, type)\ 178 sdata->debugfs.type.name = debugfs_create_file(#name, 0400,\ 179 sdata->debugfsdir, sdata, &name##_ops); 180 181 static void add_sta_files(struct ieee80211_sub_if_data *sdata) 182 { 183 DEBUGFS_ADD(drop_unencrypted, sta); 184 DEBUGFS_ADD(force_unicast_rateidx, sta); 185 DEBUGFS_ADD(max_ratectrl_rateidx, sta); 186 187 DEBUGFS_ADD(state, sta); 188 DEBUGFS_ADD(bssid, sta); 189 DEBUGFS_ADD(prev_bssid, sta); 190 DEBUGFS_ADD(ssid_len, sta); 191 DEBUGFS_ADD(aid, sta); 192 DEBUGFS_ADD(ap_capab, sta); 193 DEBUGFS_ADD(capab, sta); 194 DEBUGFS_ADD(extra_ie_len, sta); 195 DEBUGFS_ADD(auth_tries, sta); 196 DEBUGFS_ADD(assoc_tries, sta); 197 DEBUGFS_ADD(auth_algs, sta); 198 DEBUGFS_ADD(auth_alg, sta); 199 DEBUGFS_ADD(auth_transaction, sta); 200 DEBUGFS_ADD(flags, sta); 201 } 202 203 static void add_ap_files(struct ieee80211_sub_if_data *sdata) 204 { 205 DEBUGFS_ADD(drop_unencrypted, ap); 206 DEBUGFS_ADD(force_unicast_rateidx, ap); 207 DEBUGFS_ADD(max_ratectrl_rateidx, ap); 208 209 DEBUGFS_ADD(num_sta_ps, ap); 210 DEBUGFS_ADD(dtim_count, ap); 211 DEBUGFS_ADD(num_buffered_multicast, ap); 212 } 213 214 static void add_wds_files(struct ieee80211_sub_if_data *sdata) 215 { 216 DEBUGFS_ADD(drop_unencrypted, wds); 217 DEBUGFS_ADD(force_unicast_rateidx, wds); 218 DEBUGFS_ADD(max_ratectrl_rateidx, wds); 219 220 DEBUGFS_ADD(peer, wds); 221 } 222 223 static void add_vlan_files(struct ieee80211_sub_if_data *sdata) 224 { 225 DEBUGFS_ADD(drop_unencrypted, vlan); 226 DEBUGFS_ADD(force_unicast_rateidx, vlan); 227 DEBUGFS_ADD(max_ratectrl_rateidx, vlan); 228 } 229 230 static void add_monitor_files(struct ieee80211_sub_if_data *sdata) 231 { 232 } 233 234 #ifdef CONFIG_MAC80211_MESH 235 #define MESHSTATS_ADD(name)\ 236 sdata->mesh_stats.name = debugfs_create_file(#name, 0400,\ 237 sdata->mesh_stats_dir, sdata, &name##_ops); 238 239 static void add_mesh_stats(struct ieee80211_sub_if_data *sdata) 240 { 241 sdata->mesh_stats_dir = debugfs_create_dir("mesh_stats", 242 sdata->debugfsdir); 243 MESHSTATS_ADD(fwded_frames); 244 MESHSTATS_ADD(dropped_frames_ttl); 245 MESHSTATS_ADD(dropped_frames_no_route); 246 MESHSTATS_ADD(estab_plinks); 247 } 248 249 #define MESHPARAMS_ADD(name)\ 250 sdata->mesh_config.name = debugfs_create_file(#name, 0600,\ 251 sdata->mesh_config_dir, sdata, &name##_ops); 252 253 static void add_mesh_config(struct ieee80211_sub_if_data *sdata) 254 { 255 sdata->mesh_config_dir = debugfs_create_dir("mesh_config", 256 sdata->debugfsdir); 257 MESHPARAMS_ADD(dot11MeshMaxRetries); 258 MESHPARAMS_ADD(dot11MeshRetryTimeout); 259 MESHPARAMS_ADD(dot11MeshConfirmTimeout); 260 MESHPARAMS_ADD(dot11MeshHoldingTimeout); 261 MESHPARAMS_ADD(dot11MeshTTL); 262 MESHPARAMS_ADD(auto_open_plinks); 263 MESHPARAMS_ADD(dot11MeshMaxPeerLinks); 264 MESHPARAMS_ADD(dot11MeshHWMPactivePathTimeout); 265 MESHPARAMS_ADD(dot11MeshHWMPpreqMinInterval); 266 MESHPARAMS_ADD(dot11MeshHWMPnetDiameterTraversalTime); 267 MESHPARAMS_ADD(dot11MeshHWMPmaxPREQretries); 268 MESHPARAMS_ADD(path_refresh_time); 269 MESHPARAMS_ADD(min_discovery_timeout); 270 } 271 #endif 272 273 static void add_files(struct ieee80211_sub_if_data *sdata) 274 { 275 if (!sdata->debugfsdir) 276 return; 277 278 switch (sdata->vif.type) { 279 case NL80211_IFTYPE_MESH_POINT: 280 #ifdef CONFIG_MAC80211_MESH 281 add_mesh_stats(sdata); 282 add_mesh_config(sdata); 283 #endif 284 break; 285 case NL80211_IFTYPE_STATION: 286 case NL80211_IFTYPE_ADHOC: 287 add_sta_files(sdata); 288 break; 289 case NL80211_IFTYPE_AP: 290 add_ap_files(sdata); 291 break; 292 case NL80211_IFTYPE_WDS: 293 add_wds_files(sdata); 294 break; 295 case NL80211_IFTYPE_MONITOR: 296 add_monitor_files(sdata); 297 break; 298 case NL80211_IFTYPE_AP_VLAN: 299 add_vlan_files(sdata); 300 break; 301 default: 302 break; 303 } 304 } 305 306 #define DEBUGFS_DEL(name, type) \ 307 do { \ 308 debugfs_remove(sdata->debugfs.type.name); \ 309 sdata->debugfs.type.name = NULL; \ 310 } while (0) 311 312 static void del_sta_files(struct ieee80211_sub_if_data *sdata) 313 { 314 DEBUGFS_DEL(drop_unencrypted, sta); 315 DEBUGFS_DEL(force_unicast_rateidx, sta); 316 DEBUGFS_DEL(max_ratectrl_rateidx, sta); 317 318 DEBUGFS_DEL(state, sta); 319 DEBUGFS_DEL(bssid, sta); 320 DEBUGFS_DEL(prev_bssid, sta); 321 DEBUGFS_DEL(ssid_len, sta); 322 DEBUGFS_DEL(aid, sta); 323 DEBUGFS_DEL(ap_capab, sta); 324 DEBUGFS_DEL(capab, sta); 325 DEBUGFS_DEL(extra_ie_len, sta); 326 DEBUGFS_DEL(auth_tries, sta); 327 DEBUGFS_DEL(assoc_tries, sta); 328 DEBUGFS_DEL(auth_algs, sta); 329 DEBUGFS_DEL(auth_alg, sta); 330 DEBUGFS_DEL(auth_transaction, sta); 331 DEBUGFS_DEL(flags, sta); 332 } 333 334 static void del_ap_files(struct ieee80211_sub_if_data *sdata) 335 { 336 DEBUGFS_DEL(drop_unencrypted, ap); 337 DEBUGFS_DEL(force_unicast_rateidx, ap); 338 DEBUGFS_DEL(max_ratectrl_rateidx, ap); 339 340 DEBUGFS_DEL(num_sta_ps, ap); 341 DEBUGFS_DEL(dtim_count, ap); 342 DEBUGFS_DEL(num_buffered_multicast, ap); 343 } 344 345 static void del_wds_files(struct ieee80211_sub_if_data *sdata) 346 { 347 DEBUGFS_DEL(drop_unencrypted, wds); 348 DEBUGFS_DEL(force_unicast_rateidx, wds); 349 DEBUGFS_DEL(max_ratectrl_rateidx, wds); 350 351 DEBUGFS_DEL(peer, wds); 352 } 353 354 static void del_vlan_files(struct ieee80211_sub_if_data *sdata) 355 { 356 DEBUGFS_DEL(drop_unencrypted, vlan); 357 DEBUGFS_DEL(force_unicast_rateidx, vlan); 358 DEBUGFS_DEL(max_ratectrl_rateidx, vlan); 359 } 360 361 static void del_monitor_files(struct ieee80211_sub_if_data *sdata) 362 { 363 } 364 365 #ifdef CONFIG_MAC80211_MESH 366 #define MESHSTATS_DEL(name) \ 367 do { \ 368 debugfs_remove(sdata->mesh_stats.name); \ 369 sdata->mesh_stats.name = NULL; \ 370 } while (0) 371 372 static void del_mesh_stats(struct ieee80211_sub_if_data *sdata) 373 { 374 MESHSTATS_DEL(fwded_frames); 375 MESHSTATS_DEL(dropped_frames_ttl); 376 MESHSTATS_DEL(dropped_frames_no_route); 377 MESHSTATS_DEL(estab_plinks); 378 debugfs_remove(sdata->mesh_stats_dir); 379 sdata->mesh_stats_dir = NULL; 380 } 381 382 #define MESHPARAMS_DEL(name) \ 383 do { \ 384 debugfs_remove(sdata->mesh_config.name); \ 385 sdata->mesh_config.name = NULL; \ 386 } while (0) 387 388 static void del_mesh_config(struct ieee80211_sub_if_data *sdata) 389 { 390 MESHPARAMS_DEL(dot11MeshMaxRetries); 391 MESHPARAMS_DEL(dot11MeshRetryTimeout); 392 MESHPARAMS_DEL(dot11MeshConfirmTimeout); 393 MESHPARAMS_DEL(dot11MeshHoldingTimeout); 394 MESHPARAMS_DEL(dot11MeshTTL); 395 MESHPARAMS_DEL(auto_open_plinks); 396 MESHPARAMS_DEL(dot11MeshMaxPeerLinks); 397 MESHPARAMS_DEL(dot11MeshHWMPactivePathTimeout); 398 MESHPARAMS_DEL(dot11MeshHWMPpreqMinInterval); 399 MESHPARAMS_DEL(dot11MeshHWMPnetDiameterTraversalTime); 400 MESHPARAMS_DEL(dot11MeshHWMPmaxPREQretries); 401 MESHPARAMS_DEL(path_refresh_time); 402 MESHPARAMS_DEL(min_discovery_timeout); 403 debugfs_remove(sdata->mesh_config_dir); 404 sdata->mesh_config_dir = NULL; 405 } 406 #endif 407 408 static void del_files(struct ieee80211_sub_if_data *sdata) 409 { 410 if (!sdata->debugfsdir) 411 return; 412 413 switch (sdata->vif.type) { 414 case NL80211_IFTYPE_MESH_POINT: 415 #ifdef CONFIG_MAC80211_MESH 416 del_mesh_stats(sdata); 417 del_mesh_config(sdata); 418 #endif 419 break; 420 case NL80211_IFTYPE_STATION: 421 case NL80211_IFTYPE_ADHOC: 422 del_sta_files(sdata); 423 break; 424 case NL80211_IFTYPE_AP: 425 del_ap_files(sdata); 426 break; 427 case NL80211_IFTYPE_WDS: 428 del_wds_files(sdata); 429 break; 430 case NL80211_IFTYPE_MONITOR: 431 del_monitor_files(sdata); 432 break; 433 case NL80211_IFTYPE_AP_VLAN: 434 del_vlan_files(sdata); 435 break; 436 default: 437 break; 438 } 439 } 440 441 static int notif_registered; 442 443 void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata) 444 { 445 char buf[10+IFNAMSIZ]; 446 447 if (!notif_registered) 448 return; 449 450 sprintf(buf, "netdev:%s", sdata->dev->name); 451 sdata->debugfsdir = debugfs_create_dir(buf, 452 sdata->local->hw.wiphy->debugfsdir); 453 add_files(sdata); 454 } 455 456 void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata) 457 { 458 del_files(sdata); 459 debugfs_remove(sdata->debugfsdir); 460 sdata->debugfsdir = NULL; 461 } 462 463 static int netdev_notify(struct notifier_block *nb, 464 unsigned long state, 465 void *ndev) 466 { 467 struct net_device *dev = ndev; 468 struct dentry *dir; 469 struct ieee80211_sub_if_data *sdata; 470 char buf[10+IFNAMSIZ]; 471 472 if (state != NETDEV_CHANGENAME) 473 return 0; 474 475 if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy) 476 return 0; 477 478 if (dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid) 479 return 0; 480 481 sdata = IEEE80211_DEV_TO_SUB_IF(dev); 482 483 dir = sdata->debugfsdir; 484 485 if (!dir) 486 return 0; 487 488 sprintf(buf, "netdev:%s", dev->name); 489 if (!debugfs_rename(dir->d_parent, dir, dir->d_parent, buf)) 490 printk(KERN_ERR "mac80211: debugfs: failed to rename debugfs " 491 "dir to %s\n", buf); 492 493 return 0; 494 } 495 496 static struct notifier_block mac80211_debugfs_netdev_notifier = { 497 .notifier_call = netdev_notify, 498 }; 499 500 void ieee80211_debugfs_netdev_init(void) 501 { 502 int err; 503 504 err = register_netdevice_notifier(&mac80211_debugfs_netdev_notifier); 505 if (err) { 506 printk(KERN_ERR 507 "mac80211: failed to install netdev notifier," 508 " disabling per-netdev debugfs!\n"); 509 } else 510 notif_registered = 1; 511 } 512 513 void ieee80211_debugfs_netdev_exit(void) 514 { 515 unregister_netdevice_notifier(&mac80211_debugfs_netdev_notifier); 516 notif_registered = 0; 517 } 518