at v4.3 574 lines 14 kB view raw
1/* Copyright (C) 2010-2015 B.A.T.M.A.N. contributors: 2 * 3 * Marek Lindner 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of version 2 of the GNU General Public 7 * License as published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it will be useful, but 10 * WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, see <http://www.gnu.org/licenses/>. 16 */ 17 18#include "debugfs.h" 19#include "main.h" 20 21#include <linux/compiler.h> 22#include <linux/debugfs.h> 23#include <linux/device.h> 24#include <linux/errno.h> 25#include <linux/export.h> 26#include <linux/fcntl.h> 27#include <linux/fs.h> 28#include <linux/jiffies.h> 29#include <linux/kernel.h> 30#include <linux/module.h> 31#include <linux/netdevice.h> 32#include <linux/poll.h> 33#include <linux/printk.h> 34#include <linux/sched.h> /* for linux/wait.h */ 35#include <linux/seq_file.h> 36#include <linux/slab.h> 37#include <linux/spinlock.h> 38#include <linux/stat.h> 39#include <linux/stddef.h> 40#include <linux/stringify.h> 41#include <linux/sysfs.h> 42#include <linux/types.h> 43#include <linux/uaccess.h> 44#include <linux/wait.h> 45#include <stdarg.h> 46 47#include "bridge_loop_avoidance.h" 48#include "distributed-arp-table.h" 49#include "gateway_client.h" 50#include "icmp_socket.h" 51#include "network-coding.h" 52#include "originator.h" 53#include "translation-table.h" 54 55static struct dentry *batadv_debugfs; 56 57#ifdef CONFIG_BATMAN_ADV_DEBUG 58#define BATADV_LOG_BUFF_MASK (batadv_log_buff_len - 1) 59 60static const int batadv_log_buff_len = BATADV_LOG_BUF_LEN; 61 62static char *batadv_log_char_addr(struct batadv_priv_debug_log *debug_log, 63 size_t idx) 64{ 65 return &debug_log->log_buff[idx & BATADV_LOG_BUFF_MASK]; 66} 67 68static void batadv_emit_log_char(struct batadv_priv_debug_log *debug_log, 69 char c) 70{ 71 char *char_addr; 72 73 char_addr = batadv_log_char_addr(debug_log, debug_log->log_end); 74 *char_addr = c; 75 debug_log->log_end++; 76 77 if (debug_log->log_end - debug_log->log_start > batadv_log_buff_len) 78 debug_log->log_start = debug_log->log_end - batadv_log_buff_len; 79} 80 81__printf(2, 3) 82static int batadv_fdebug_log(struct batadv_priv_debug_log *debug_log, 83 const char *fmt, ...) 84{ 85 va_list args; 86 static char debug_log_buf[256]; 87 char *p; 88 89 if (!debug_log) 90 return 0; 91 92 spin_lock_bh(&debug_log->lock); 93 va_start(args, fmt); 94 vscnprintf(debug_log_buf, sizeof(debug_log_buf), fmt, args); 95 va_end(args); 96 97 for (p = debug_log_buf; *p != 0; p++) 98 batadv_emit_log_char(debug_log, *p); 99 100 spin_unlock_bh(&debug_log->lock); 101 102 wake_up(&debug_log->queue_wait); 103 104 return 0; 105} 106 107int batadv_debug_log(struct batadv_priv *bat_priv, const char *fmt, ...) 108{ 109 va_list args; 110 char tmp_log_buf[256]; 111 112 va_start(args, fmt); 113 vscnprintf(tmp_log_buf, sizeof(tmp_log_buf), fmt, args); 114 batadv_fdebug_log(bat_priv->debug_log, "[%10u] %s", 115 jiffies_to_msecs(jiffies), tmp_log_buf); 116 va_end(args); 117 118 return 0; 119} 120 121static int batadv_log_open(struct inode *inode, struct file *file) 122{ 123 if (!try_module_get(THIS_MODULE)) 124 return -EBUSY; 125 126 nonseekable_open(inode, file); 127 file->private_data = inode->i_private; 128 return 0; 129} 130 131static int batadv_log_release(struct inode *inode, struct file *file) 132{ 133 module_put(THIS_MODULE); 134 return 0; 135} 136 137static int batadv_log_empty(struct batadv_priv_debug_log *debug_log) 138{ 139 return !(debug_log->log_start - debug_log->log_end); 140} 141 142static ssize_t batadv_log_read(struct file *file, char __user *buf, 143 size_t count, loff_t *ppos) 144{ 145 struct batadv_priv *bat_priv = file->private_data; 146 struct batadv_priv_debug_log *debug_log = bat_priv->debug_log; 147 int error, i = 0; 148 char *char_addr; 149 char c; 150 151 if ((file->f_flags & O_NONBLOCK) && batadv_log_empty(debug_log)) 152 return -EAGAIN; 153 154 if (!buf) 155 return -EINVAL; 156 157 if (count == 0) 158 return 0; 159 160 if (!access_ok(VERIFY_WRITE, buf, count)) 161 return -EFAULT; 162 163 error = wait_event_interruptible(debug_log->queue_wait, 164 (!batadv_log_empty(debug_log))); 165 166 if (error) 167 return error; 168 169 spin_lock_bh(&debug_log->lock); 170 171 while ((!error) && (i < count) && 172 (debug_log->log_start != debug_log->log_end)) { 173 char_addr = batadv_log_char_addr(debug_log, 174 debug_log->log_start); 175 c = *char_addr; 176 177 debug_log->log_start++; 178 179 spin_unlock_bh(&debug_log->lock); 180 181 error = __put_user(c, buf); 182 183 spin_lock_bh(&debug_log->lock); 184 185 buf++; 186 i++; 187 } 188 189 spin_unlock_bh(&debug_log->lock); 190 191 if (!error) 192 return i; 193 194 return error; 195} 196 197static unsigned int batadv_log_poll(struct file *file, poll_table *wait) 198{ 199 struct batadv_priv *bat_priv = file->private_data; 200 struct batadv_priv_debug_log *debug_log = bat_priv->debug_log; 201 202 poll_wait(file, &debug_log->queue_wait, wait); 203 204 if (!batadv_log_empty(debug_log)) 205 return POLLIN | POLLRDNORM; 206 207 return 0; 208} 209 210static const struct file_operations batadv_log_fops = { 211 .open = batadv_log_open, 212 .release = batadv_log_release, 213 .read = batadv_log_read, 214 .poll = batadv_log_poll, 215 .llseek = no_llseek, 216}; 217 218static int batadv_debug_log_setup(struct batadv_priv *bat_priv) 219{ 220 struct dentry *d; 221 222 if (!bat_priv->debug_dir) 223 goto err; 224 225 bat_priv->debug_log = kzalloc(sizeof(*bat_priv->debug_log), GFP_ATOMIC); 226 if (!bat_priv->debug_log) 227 goto err; 228 229 spin_lock_init(&bat_priv->debug_log->lock); 230 init_waitqueue_head(&bat_priv->debug_log->queue_wait); 231 232 d = debugfs_create_file("log", S_IFREG | S_IRUSR, 233 bat_priv->debug_dir, bat_priv, 234 &batadv_log_fops); 235 if (!d) 236 goto err; 237 238 return 0; 239 240err: 241 return -ENOMEM; 242} 243 244static void batadv_debug_log_cleanup(struct batadv_priv *bat_priv) 245{ 246 kfree(bat_priv->debug_log); 247 bat_priv->debug_log = NULL; 248} 249#else /* CONFIG_BATMAN_ADV_DEBUG */ 250static int batadv_debug_log_setup(struct batadv_priv *bat_priv) 251{ 252 return 0; 253} 254 255static void batadv_debug_log_cleanup(struct batadv_priv *bat_priv) 256{ 257} 258#endif 259 260static int batadv_algorithms_open(struct inode *inode, struct file *file) 261{ 262 return single_open(file, batadv_algo_seq_print_text, NULL); 263} 264 265static int batadv_originators_open(struct inode *inode, struct file *file) 266{ 267 struct net_device *net_dev = (struct net_device *)inode->i_private; 268 269 return single_open(file, batadv_orig_seq_print_text, net_dev); 270} 271 272/** 273 * batadv_originators_hardif_open - handles debugfs output for the 274 * originator table of an hard interface 275 * @inode: inode pointer to debugfs file 276 * @file: pointer to the seq_file 277 */ 278static int batadv_originators_hardif_open(struct inode *inode, 279 struct file *file) 280{ 281 struct net_device *net_dev = (struct net_device *)inode->i_private; 282 283 return single_open(file, batadv_orig_hardif_seq_print_text, net_dev); 284} 285 286static int batadv_gateways_open(struct inode *inode, struct file *file) 287{ 288 struct net_device *net_dev = (struct net_device *)inode->i_private; 289 290 return single_open(file, batadv_gw_client_seq_print_text, net_dev); 291} 292 293static int batadv_transtable_global_open(struct inode *inode, struct file *file) 294{ 295 struct net_device *net_dev = (struct net_device *)inode->i_private; 296 297 return single_open(file, batadv_tt_global_seq_print_text, net_dev); 298} 299 300#ifdef CONFIG_BATMAN_ADV_BLA 301static int batadv_bla_claim_table_open(struct inode *inode, struct file *file) 302{ 303 struct net_device *net_dev = (struct net_device *)inode->i_private; 304 305 return single_open(file, batadv_bla_claim_table_seq_print_text, 306 net_dev); 307} 308 309static int batadv_bla_backbone_table_open(struct inode *inode, 310 struct file *file) 311{ 312 struct net_device *net_dev = (struct net_device *)inode->i_private; 313 314 return single_open(file, batadv_bla_backbone_table_seq_print_text, 315 net_dev); 316} 317 318#endif 319 320#ifdef CONFIG_BATMAN_ADV_DAT 321/** 322 * batadv_dat_cache_open - Prepare file handler for reads from dat_chache 323 * @inode: inode which was opened 324 * @file: file handle to be initialized 325 */ 326static int batadv_dat_cache_open(struct inode *inode, struct file *file) 327{ 328 struct net_device *net_dev = (struct net_device *)inode->i_private; 329 330 return single_open(file, batadv_dat_cache_seq_print_text, net_dev); 331} 332#endif 333 334static int batadv_transtable_local_open(struct inode *inode, struct file *file) 335{ 336 struct net_device *net_dev = (struct net_device *)inode->i_private; 337 338 return single_open(file, batadv_tt_local_seq_print_text, net_dev); 339} 340 341struct batadv_debuginfo { 342 struct attribute attr; 343 const struct file_operations fops; 344}; 345 346#ifdef CONFIG_BATMAN_ADV_NC 347static int batadv_nc_nodes_open(struct inode *inode, struct file *file) 348{ 349 struct net_device *net_dev = (struct net_device *)inode->i_private; 350 351 return single_open(file, batadv_nc_nodes_seq_print_text, net_dev); 352} 353#endif 354 355#define BATADV_DEBUGINFO(_name, _mode, _open) \ 356struct batadv_debuginfo batadv_debuginfo_##_name = { \ 357 .attr = { .name = __stringify(_name), \ 358 .mode = _mode, }, \ 359 .fops = { .owner = THIS_MODULE, \ 360 .open = _open, \ 361 .read = seq_read, \ 362 .llseek = seq_lseek, \ 363 .release = single_release, \ 364 } \ 365} 366 367/* the following attributes are general and therefore they will be directly 368 * placed in the BATADV_DEBUGFS_SUBDIR subdirectory of debugfs 369 */ 370static BATADV_DEBUGINFO(routing_algos, S_IRUGO, batadv_algorithms_open); 371 372static struct batadv_debuginfo *batadv_general_debuginfos[] = { 373 &batadv_debuginfo_routing_algos, 374 NULL, 375}; 376 377/* The following attributes are per soft interface */ 378static BATADV_DEBUGINFO(originators, S_IRUGO, batadv_originators_open); 379static BATADV_DEBUGINFO(gateways, S_IRUGO, batadv_gateways_open); 380static BATADV_DEBUGINFO(transtable_global, S_IRUGO, 381 batadv_transtable_global_open); 382#ifdef CONFIG_BATMAN_ADV_BLA 383static BATADV_DEBUGINFO(bla_claim_table, S_IRUGO, batadv_bla_claim_table_open); 384static BATADV_DEBUGINFO(bla_backbone_table, S_IRUGO, 385 batadv_bla_backbone_table_open); 386#endif 387#ifdef CONFIG_BATMAN_ADV_DAT 388static BATADV_DEBUGINFO(dat_cache, S_IRUGO, batadv_dat_cache_open); 389#endif 390static BATADV_DEBUGINFO(transtable_local, S_IRUGO, 391 batadv_transtable_local_open); 392#ifdef CONFIG_BATMAN_ADV_NC 393static BATADV_DEBUGINFO(nc_nodes, S_IRUGO, batadv_nc_nodes_open); 394#endif 395 396static struct batadv_debuginfo *batadv_mesh_debuginfos[] = { 397 &batadv_debuginfo_originators, 398 &batadv_debuginfo_gateways, 399 &batadv_debuginfo_transtable_global, 400#ifdef CONFIG_BATMAN_ADV_BLA 401 &batadv_debuginfo_bla_claim_table, 402 &batadv_debuginfo_bla_backbone_table, 403#endif 404#ifdef CONFIG_BATMAN_ADV_DAT 405 &batadv_debuginfo_dat_cache, 406#endif 407 &batadv_debuginfo_transtable_local, 408#ifdef CONFIG_BATMAN_ADV_NC 409 &batadv_debuginfo_nc_nodes, 410#endif 411 NULL, 412}; 413 414#define BATADV_HARDIF_DEBUGINFO(_name, _mode, _open) \ 415struct batadv_debuginfo batadv_hardif_debuginfo_##_name = { \ 416 .attr = { \ 417 .name = __stringify(_name), \ 418 .mode = _mode, \ 419 }, \ 420 .fops = { \ 421 .owner = THIS_MODULE, \ 422 .open = _open, \ 423 .read = seq_read, \ 424 .llseek = seq_lseek, \ 425 .release = single_release, \ 426 }, \ 427} 428 429static BATADV_HARDIF_DEBUGINFO(originators, S_IRUGO, 430 batadv_originators_hardif_open); 431 432static struct batadv_debuginfo *batadv_hardif_debuginfos[] = { 433 &batadv_hardif_debuginfo_originators, 434 NULL, 435}; 436 437void batadv_debugfs_init(void) 438{ 439 struct batadv_debuginfo **bat_debug; 440 struct dentry *file; 441 442 batadv_debugfs = debugfs_create_dir(BATADV_DEBUGFS_SUBDIR, NULL); 443 if (batadv_debugfs == ERR_PTR(-ENODEV)) 444 batadv_debugfs = NULL; 445 446 if (!batadv_debugfs) 447 goto err; 448 449 for (bat_debug = batadv_general_debuginfos; *bat_debug; ++bat_debug) { 450 file = debugfs_create_file(((*bat_debug)->attr).name, 451 S_IFREG | ((*bat_debug)->attr).mode, 452 batadv_debugfs, NULL, 453 &(*bat_debug)->fops); 454 if (!file) { 455 pr_err("Can't add general debugfs file: %s\n", 456 ((*bat_debug)->attr).name); 457 goto err; 458 } 459 } 460 461 return; 462err: 463 debugfs_remove_recursive(batadv_debugfs); 464 batadv_debugfs = NULL; 465} 466 467void batadv_debugfs_destroy(void) 468{ 469 debugfs_remove_recursive(batadv_debugfs); 470 batadv_debugfs = NULL; 471} 472 473/** 474 * batadv_debugfs_add_hardif - creates the base directory for a hard interface 475 * in debugfs. 476 * @hard_iface: hard interface which should be added. 477 */ 478int batadv_debugfs_add_hardif(struct batadv_hard_iface *hard_iface) 479{ 480 struct batadv_debuginfo **bat_debug; 481 struct dentry *file; 482 483 if (!batadv_debugfs) 484 goto out; 485 486 hard_iface->debug_dir = debugfs_create_dir(hard_iface->net_dev->name, 487 batadv_debugfs); 488 if (!hard_iface->debug_dir) 489 goto out; 490 491 for (bat_debug = batadv_hardif_debuginfos; *bat_debug; ++bat_debug) { 492 file = debugfs_create_file(((*bat_debug)->attr).name, 493 S_IFREG | ((*bat_debug)->attr).mode, 494 hard_iface->debug_dir, 495 hard_iface->net_dev, 496 &(*bat_debug)->fops); 497 if (!file) 498 goto rem_attr; 499 } 500 501 return 0; 502rem_attr: 503 debugfs_remove_recursive(hard_iface->debug_dir); 504 hard_iface->debug_dir = NULL; 505out: 506 return -ENOMEM; 507} 508 509/** 510 * batadv_debugfs_del_hardif - delete the base directory for a hard interface 511 * in debugfs. 512 * @hard_iface: hard interface which is deleted. 513 */ 514void batadv_debugfs_del_hardif(struct batadv_hard_iface *hard_iface) 515{ 516 if (batadv_debugfs) { 517 debugfs_remove_recursive(hard_iface->debug_dir); 518 hard_iface->debug_dir = NULL; 519 } 520} 521 522int batadv_debugfs_add_meshif(struct net_device *dev) 523{ 524 struct batadv_priv *bat_priv = netdev_priv(dev); 525 struct batadv_debuginfo **bat_debug; 526 struct dentry *file; 527 528 if (!batadv_debugfs) 529 goto out; 530 531 bat_priv->debug_dir = debugfs_create_dir(dev->name, batadv_debugfs); 532 if (!bat_priv->debug_dir) 533 goto out; 534 535 if (batadv_socket_setup(bat_priv) < 0) 536 goto rem_attr; 537 538 if (batadv_debug_log_setup(bat_priv) < 0) 539 goto rem_attr; 540 541 for (bat_debug = batadv_mesh_debuginfos; *bat_debug; ++bat_debug) { 542 file = debugfs_create_file(((*bat_debug)->attr).name, 543 S_IFREG | ((*bat_debug)->attr).mode, 544 bat_priv->debug_dir, 545 dev, &(*bat_debug)->fops); 546 if (!file) { 547 batadv_err(dev, "Can't add debugfs file: %s/%s\n", 548 dev->name, ((*bat_debug)->attr).name); 549 goto rem_attr; 550 } 551 } 552 553 if (batadv_nc_init_debugfs(bat_priv) < 0) 554 goto rem_attr; 555 556 return 0; 557rem_attr: 558 debugfs_remove_recursive(bat_priv->debug_dir); 559 bat_priv->debug_dir = NULL; 560out: 561 return -ENOMEM; 562} 563 564void batadv_debugfs_del_meshif(struct net_device *dev) 565{ 566 struct batadv_priv *bat_priv = netdev_priv(dev); 567 568 batadv_debug_log_cleanup(bat_priv); 569 570 if (batadv_debugfs) { 571 debugfs_remove_recursive(bat_priv->debug_dir); 572 bat_priv->debug_dir = NULL; 573 } 574}