]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - drivers/staging/batman-adv/proc.c
Staging: batman-adv: initialize static hash iterators
[mirror_ubuntu-bionic-kernel.git] / drivers / staging / batman-adv / proc.c
CommitLineData
5beef3c9
AL
1/*
2 * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
3 *
4 * Marek Lindner, Simon Wunderlich
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22#include "main.h"
23#include "proc.h"
5beef3c9
AL
24#include "routing.h"
25#include "translation-table.h"
26#include "hard-interface.h"
27#include "types.h"
28#include "hash.h"
29#include "vis.h"
30#include "compat.h"
31
32static uint8_t vis_format = DOT_DRAW;
33
34static struct proc_dir_entry *proc_batman_dir, *proc_interface_file;
35static struct proc_dir_entry *proc_orig_interval_file, *proc_originators_file;
5beef3c9
AL
36static struct proc_dir_entry *proc_transt_local_file;
37static struct proc_dir_entry *proc_transt_global_file;
38static struct proc_dir_entry *proc_vis_file, *proc_vis_format_file;
39static struct proc_dir_entry *proc_aggr_file;
40
41static int proc_interfaces_read(struct seq_file *seq, void *offset)
42{
43 struct batman_if *batman_if;
44
45 rcu_read_lock();
46 list_for_each_entry_rcu(batman_if, &if_list, list) {
47 seq_printf(seq, "[%8s] %s %s \n",
48 (batman_if->if_active == IF_ACTIVE ?
49 "active" : "inactive"),
50 batman_if->dev,
51 (batman_if->if_active == IF_ACTIVE ?
52 batman_if->addr_str : " "));
53 }
54 rcu_read_unlock();
55
56 return 0;
57}
58
59static int proc_interfaces_open(struct inode *inode, struct file *file)
60{
61 return single_open(file, proc_interfaces_read, NULL);
62}
63
64static ssize_t proc_interfaces_write(struct file *instance,
65 const char __user *userbuffer,
66 size_t count, loff_t *data)
67{
68 char *if_string, *colon_ptr = NULL, *cr_ptr = NULL;
69 int not_copied = 0, if_num = 0;
70 struct batman_if *batman_if = NULL;
71
72 if_string = kmalloc(count, GFP_KERNEL);
73
74 if (!if_string)
75 return -ENOMEM;
76
77 if (count > IFNAMSIZ - 1) {
bad2239e 78 printk(KERN_WARNING "batman-adv:Can't add interface: device name is too long\n");
5beef3c9
AL
79 goto end;
80 }
81
82 not_copied = copy_from_user(if_string, userbuffer, count);
83 if_string[count - not_copied - 1] = 0;
84
85 colon_ptr = strchr(if_string, ':');
86 if (colon_ptr)
87 *colon_ptr = 0;
88
89 if (!colon_ptr) {
90 cr_ptr = strchr(if_string, '\n');
91 if (cr_ptr)
92 *cr_ptr = 0;
93 }
94
95 if (strlen(if_string) == 0) {
96 shutdown_module();
97 num_ifs = 0;
98 goto end;
99 }
100
101 /* add interface */
102 rcu_read_lock();
103 list_for_each_entry_rcu(batman_if, &if_list, list) {
104 if (strncmp(batman_if->dev, if_string, count) == 0) {
bad2239e 105 printk(KERN_ERR "batman-adv:Given interface is already active: %s\n", if_string);
5beef3c9
AL
106 rcu_read_unlock();
107 goto end;
108
109 }
110
111 if_num++;
112 }
113 rcu_read_unlock();
114
115 hardif_add_interface(if_string, if_num);
116
117 if ((atomic_read(&module_state) == MODULE_INACTIVE) &&
118 (hardif_get_active_if_num() > 0))
119 activate_module();
120
121 rcu_read_lock();
122 if (list_empty(&if_list)) {
123 rcu_read_unlock();
124 goto end;
125 }
126 rcu_read_unlock();
127
128 num_ifs = if_num + 1;
129 return count;
130
131end:
132 kfree(if_string);
133 return count;
134}
135
136static int proc_orig_interval_read(struct seq_file *seq, void *offset)
137{
138 seq_printf(seq, "%i\n", atomic_read(&originator_interval));
139
140 return 0;
141}
142
143static ssize_t proc_orig_interval_write(struct file *file,
144 const char __user *buffer,
145 size_t count, loff_t *ppos)
146{
147 char *interval_string;
148 int not_copied = 0;
149 unsigned long originator_interval_tmp;
150 int retval;
151
152 interval_string = kmalloc(count, GFP_KERNEL);
153
154 if (!interval_string)
155 return -ENOMEM;
156
157 not_copied = copy_from_user(interval_string, buffer, count);
158 interval_string[count - not_copied - 1] = 0;
159
160 retval = strict_strtoul(interval_string, 10, &originator_interval_tmp);
161 if (retval) {
bad2239e 162 printk(KERN_ERR "batman-adv:New originator interval invalid\n");
5beef3c9
AL
163 goto end;
164 }
165
166 if (originator_interval_tmp <= JITTER * 2) {
bad2239e
AL
167 printk(KERN_WARNING "batman-adv:New originator interval too small: %li (min: %i)\n",
168 originator_interval_tmp, JITTER * 2);
5beef3c9
AL
169 goto end;
170 }
171
bad2239e
AL
172 printk(KERN_INFO "batman-adv:Changing originator interval from: %i to: %li\n",
173 atomic_read(&originator_interval), originator_interval_tmp);
5beef3c9
AL
174
175 atomic_set(&originator_interval, originator_interval_tmp);
176
177end:
178 kfree(interval_string);
179 return count;
180}
181
182static int proc_orig_interval_open(struct inode *inode, struct file *file)
183{
184 return single_open(file, proc_orig_interval_read, NULL);
185}
186
187static int proc_originators_read(struct seq_file *seq, void *offset)
188{
b6c35976 189 HASHIT(hashit);
5beef3c9
AL
190 struct orig_node *orig_node;
191 struct neigh_node *neigh_node;
192 int batman_count = 0;
193 char orig_str[ETH_STR_LEN], router_str[ETH_STR_LEN];
194
195 rcu_read_lock();
196 if (list_empty(&if_list)) {
197 rcu_read_unlock();
198 seq_printf(seq, "BATMAN disabled - please specify interfaces to enable it \n");
199 goto end;
200 }
201
202 if (((struct batman_if *)if_list.next)->if_active != IF_ACTIVE) {
203 rcu_read_unlock();
204 seq_printf(seq, "BATMAN disabled - primary interface not active \n");
205 goto end;
206 }
207
208 seq_printf(seq,
209 " %-14s (%s/%i) %17s [%10s]: %20s ... [B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%s] \n",
210 "Originator", "#", TQ_MAX_VALUE, "Nexthop", "outgoingIF",
211 "Potential nexthops", SOURCE_VERSION, REVISION_VERSION_STR,
212 ((struct batman_if *)if_list.next)->dev,
213 ((struct batman_if *)if_list.next)->addr_str);
214
215 rcu_read_unlock();
216 spin_lock(&orig_hash_lock);
217
b6c35976 218 while (hash_iterate(orig_hash, &hashit)) {
5beef3c9 219
b6c35976 220 orig_node = hashit.bucket->data;
5beef3c9
AL
221
222 if (!orig_node->router)
223 continue;
224
225 if (orig_node->router->tq_avg == 0)
226 continue;
227
228 batman_count++;
229
230 addr_to_string(orig_str, orig_node->orig);
231 addr_to_string(router_str, orig_node->router->addr);
232
bad2239e 233 seq_printf(seq, "%-17s (%3i) %17s [%10s]:",
5beef3c9
AL
234 orig_str, orig_node->router->tq_avg,
235 router_str, orig_node->router->if_incoming->dev);
236
237 list_for_each_entry(neigh_node, &orig_node->neigh_list, list) {
238 addr_to_string(orig_str, neigh_node->addr);
239 seq_printf(seq, " %17s (%3i)",
240 orig_str, neigh_node->tq_avg);
241 }
242
243 seq_printf(seq, "\n");
244
245 }
246
247 spin_unlock(&orig_hash_lock);
248
249 if (batman_count == 0)
250 seq_printf(seq, "No batman nodes in range ... \n");
251
252end:
253 return 0;
254}
255
256static int proc_originators_open(struct inode *inode, struct file *file)
257{
258 return single_open(file, proc_originators_read, NULL);
259}
260
5beef3c9
AL
261static int proc_transt_local_read(struct seq_file *seq, void *offset)
262{
263 char *buf;
264
265 buf = kmalloc(4096, GFP_KERNEL);
266 if (!buf)
267 return 0;
268
269 rcu_read_lock();
270 if (list_empty(&if_list)) {
271 rcu_read_unlock();
272 seq_printf(seq, "BATMAN disabled - please specify interfaces to enable it \n");
273 goto end;
274 }
275
276 rcu_read_unlock();
277
278 seq_printf(seq, "Locally retrieved addresses (from %s) announced via HNA:\n", soft_device->name);
279
280 hna_local_fill_buffer_text(buf, 4096);
281 seq_printf(seq, "%s", buf);
282
283end:
284 kfree(buf);
285 return 0;
286}
287
288static int proc_transt_local_open(struct inode *inode, struct file *file)
289{
290 return single_open(file, proc_transt_local_read, NULL);
291}
292
293static int proc_transt_global_read(struct seq_file *seq, void *offset)
294{
295 char *buf;
296
297 buf = kmalloc(4096, GFP_KERNEL);
298 if (!buf)
299 return 0;
300
301 rcu_read_lock();
302 if (list_empty(&if_list)) {
303 rcu_read_unlock();
304 seq_printf(seq, "BATMAN disabled - please specify interfaces to enable it \n");
305 goto end;
306 }
307 rcu_read_unlock();
308
309
310 seq_printf(seq, "Globally announced HNAs received via the mesh (translation table):\n");
311
312 hna_global_fill_buffer_text(buf, 4096);
313 seq_printf(seq, "%s", buf);
314
315end:
316 kfree(buf);
317 return 0;
318}
319
320static int proc_transt_global_open(struct inode *inode, struct file *file)
321{
322 return single_open(file, proc_transt_global_read, NULL);
323}
324
325/* insert interface to the list of interfaces of one originator */
326
327static void proc_vis_insert_interface(const uint8_t *interface,
328 struct vis_if_list **if_entry,
329 bool primary)
330{
331 /* Did we get an empty list? (then insert imediately) */
bad2239e 332 if (*if_entry == NULL) {
5beef3c9
AL
333 *if_entry = kmalloc(sizeof(struct vis_if_list), GFP_KERNEL);
334 if (*if_entry == NULL)
335 return;
336
337 (*if_entry)->primary = primary;
338 (*if_entry)->next = NULL;
339 memcpy((*if_entry)->addr, interface, ETH_ALEN);
340 } else {
341 struct vis_if_list *head_if_entry = *if_entry;
342 /* Do we already have this interface in our list? */
343 while (!compare_orig((*if_entry)->addr, (void *)interface)) {
344
345 /* Or did we reach the end (then append the interface) */
346 if ((*if_entry)->next == NULL) {
347 (*if_entry)->next = kmalloc(sizeof(struct vis_if_list), GFP_KERNEL);
348 if ((*if_entry)->next == NULL)
349 return;
350
351 memcpy((*if_entry)->next->addr, interface, ETH_ALEN);
352 (*if_entry)->next->primary = primary;
353 (*if_entry)->next->next = NULL;
354 break;
355 }
356 *if_entry = (*if_entry)->next;
357 }
358 /* Rewind the list to its head */
359 *if_entry = head_if_entry;
360 }
361}
362/* read an entry */
363
364static void proc_vis_read_entry(struct seq_file *seq,
365 struct vis_info_entry *entry,
366 struct vis_if_list **if_entry,
367 uint8_t *vis_orig,
368 uint8_t current_format,
369 uint8_t first_line)
370{
371 char from[40];
372 char to[40];
373 int int_part, frac_part;
374
375 addr_to_string(to, entry->dest);
376 if (entry->quality == 0) {
377#ifndef VIS_SUBCLUSTERS_DISABLED
378 proc_vis_insert_interface(vis_orig, if_entry, true);
379#endif /* VIS_SUBCLUSTERS_DISABLED */
380 addr_to_string(from, vis_orig);
381 if (current_format == DOT_DRAW) {
382 seq_printf(seq, "\t\"%s\" -> \"%s\" [label=\"HNA\"]\n",
383 from, to);
384 } else {
385 seq_printf(seq,
386 "%s\t{ router : \"%s\", gateway : \"%s\", label : \"HNA\" }",
387 (first_line ? "" : ",\n"), from, to);
388 }
389 } else {
390#ifndef VIS_SUBCLUSTERS_DISABLED
391 proc_vis_insert_interface(entry->src, if_entry, compare_orig(entry->src, vis_orig));
392#endif /* VIS_SUBCLUSTERS_DISABLED */
393 addr_to_string(from, entry->src);
394
395 /* kernel has no printf-support for %f? it'd be better to return
396 * this in float. */
397
398 int_part = TQ_MAX_VALUE / entry->quality;
399 frac_part = 1000 * TQ_MAX_VALUE / entry->quality - int_part * 1000;
400
401 if (current_format == DOT_DRAW) {
402 seq_printf(seq,
403 "\t\"%s\" -> \"%s\" [label=\"%d.%d\"]\n",
404 from, to, int_part, frac_part);
405 } else {
406 seq_printf(seq,
407 "%s\t{ router : \"%s\", neighbour : \"%s\", label : %d.%d }",
408 (first_line ? "" : ",\n"), from, to, int_part, frac_part);
409 }
410 }
411}
412
413
414static int proc_vis_read(struct seq_file *seq, void *offset)
415{
b6c35976 416 HASHIT(hashit);
5beef3c9
AL
417 struct vis_info *info;
418 struct vis_info_entry *entries;
419 struct vis_if_list *if_entries = NULL;
420 int i;
421 uint8_t current_format, first_line = 1;
422#ifndef VIS_SUBCLUSTERS_DISABLED
423 char tmp_addr_str[ETH_STR_LEN];
424 struct vis_if_list *tmp_if_next;
425#endif /* VIS_SUBCLUSTERS_DISABLED */
426
427 current_format = vis_format;
428
429 rcu_read_lock();
430 if (list_empty(&if_list) || (!is_vis_server())) {
431 rcu_read_unlock();
432 if (current_format == DOT_DRAW)
433 seq_printf(seq, "digraph {\n}\n");
434 goto end;
435 }
436
437 rcu_read_unlock();
438
439 if (current_format == DOT_DRAW)
440 seq_printf(seq, "digraph {\n");
441
442 spin_lock(&vis_hash_lock);
b6c35976
SW
443 while (hash_iterate(vis_hash, &hashit)) {
444 info = hashit.bucket->data;
5beef3c9
AL
445 entries = (struct vis_info_entry *)
446 ((char *)info + sizeof(struct vis_info));
447
448 for (i = 0; i < info->packet.entries; i++) {
449 proc_vis_read_entry(seq, &entries[i], &if_entries,
450 info->packet.vis_orig,
451 current_format, first_line);
452 if (first_line)
453 first_line = 0;
454 }
455
456#ifndef VIS_SUBCLUSTERS_DISABLED
457 /* Generate subgraphs from the collected items */
458 if (current_format == DOT_DRAW) {
459
460 addr_to_string(tmp_addr_str, info->packet.vis_orig);
461 seq_printf(seq, "\tsubgraph \"cluster_%s\" {\n", tmp_addr_str);
462 while (if_entries != NULL) {
463
464 addr_to_string(tmp_addr_str, if_entries->addr);
465 if (if_entries->primary)
466 seq_printf(seq, "\t\t\"%s\" [peripheries=2]\n", tmp_addr_str);
467 else
468 seq_printf(seq, "\t\t\"%s\"\n", tmp_addr_str);
469
470 /* ... and empty the list while doing this */
471 tmp_if_next = if_entries->next;
472 kfree(if_entries);
473 if_entries = tmp_if_next;
474 }
475 seq_printf(seq, "\t}\n");
476 }
477#endif /* VIS_SUBCLUSTERS_DISABLED */
478 }
479 spin_unlock(&vis_hash_lock);
480
481 if (current_format == DOT_DRAW)
482 seq_printf(seq, "}\n");
483 else
484 seq_printf(seq, "\n");
485end:
486 return 0;
487}
488
489/* setting the mode of the vis server by the user */
490static ssize_t proc_vis_write(struct file *file, const char __user * buffer,
491 size_t count, loff_t *ppos)
492{
493 char *vis_mode_string;
494 int not_copied = 0;
495
496 vis_mode_string = kmalloc(count, GFP_KERNEL);
497
498 if (!vis_mode_string)
499 return -ENOMEM;
500
501 not_copied = copy_from_user(vis_mode_string, buffer, count);
502 vis_mode_string[count - not_copied - 1] = 0;
503
504 if (strcmp(vis_mode_string, "client") == 0) {
bad2239e 505 printk(KERN_INFO "batman-adv:Setting VIS mode to client\n");
5beef3c9
AL
506 vis_set_mode(VIS_TYPE_CLIENT_UPDATE);
507 } else if (strcmp(vis_mode_string, "server") == 0) {
bad2239e 508 printk(KERN_INFO "batman-adv:Setting VIS mode to server\n");
5beef3c9
AL
509 vis_set_mode(VIS_TYPE_SERVER_SYNC);
510 } else
bad2239e
AL
511 printk(KERN_ERR "batman-adv:Unknown VIS mode: %s\n",
512 vis_mode_string);
5beef3c9
AL
513
514 kfree(vis_mode_string);
515 return count;
516}
517
518static int proc_vis_open(struct inode *inode, struct file *file)
519{
520 return single_open(file, proc_vis_read, NULL);
521}
522
523static int proc_vis_format_read(struct seq_file *seq, void *offset)
524{
525 uint8_t current_format = vis_format;
526
527 seq_printf(seq, "[%c] %s\n",
528 (current_format == DOT_DRAW) ? 'x' : ' ',
529 VIS_FORMAT_DD_NAME);
530 seq_printf(seq, "[%c] %s\n",
531 (current_format == JSON) ? 'x' : ' ',
532 VIS_FORMAT_JSON_NAME);
533 return 0;
534}
535
536static int proc_vis_format_open(struct inode *inode, struct file *file)
537{
538 return single_open(file, proc_vis_format_read, NULL);
539}
540
541static ssize_t proc_vis_format_write(struct file *file,
542 const char __user *buffer,
543 size_t count, loff_t *ppos)
544{
545 char *vis_format_string;
546 int not_copied = 0;
547
548 vis_format_string = kmalloc(count, GFP_KERNEL);
549
550 if (!vis_format_string)
551 return -ENOMEM;
552
553 not_copied = copy_from_user(vis_format_string, buffer, count);
554 vis_format_string[count - not_copied - 1] = 0;
555
556 if (strcmp(vis_format_string, VIS_FORMAT_DD_NAME) == 0) {
bad2239e
AL
557 printk(KERN_INFO "batman-adv:Setting VIS output format to: %s\n",
558 VIS_FORMAT_DD_NAME);
5beef3c9
AL
559 vis_format = DOT_DRAW;
560 } else if (strcmp(vis_format_string, VIS_FORMAT_JSON_NAME) == 0) {
bad2239e
AL
561 printk(KERN_INFO "batman-adv:Setting VIS output format to: %s\n",
562 VIS_FORMAT_JSON_NAME);
5beef3c9
AL
563 vis_format = JSON;
564 } else
bad2239e
AL
565 printk(KERN_ERR "batman-adv:Unknown VIS output format: %s\n",
566 vis_format_string);
5beef3c9
AL
567
568 kfree(vis_format_string);
569 return count;
570}
571
572static int proc_aggr_read(struct seq_file *seq, void *offset)
573{
574 seq_printf(seq, "%i\n", atomic_read(&aggregation_enabled));
575
576 return 0;
577}
578
579static ssize_t proc_aggr_write(struct file *file, const char __user *buffer,
580 size_t count, loff_t *ppos)
581{
582 char *aggr_string;
583 int not_copied = 0;
584 unsigned long aggregation_enabled_tmp;
585
586 aggr_string = kmalloc(count, GFP_KERNEL);
587
588 if (!aggr_string)
589 return -ENOMEM;
590
591 not_copied = copy_from_user(aggr_string, buffer, count);
592 aggr_string[count - not_copied - 1] = 0;
593
594 strict_strtoul(aggr_string, 10, &aggregation_enabled_tmp);
595
596 if ((aggregation_enabled_tmp != 0) && (aggregation_enabled_tmp != 1)) {
bad2239e 597 printk(KERN_ERR "batman-adv:Aggregation can only be enabled (1) or disabled (0), given value: %li\n", aggregation_enabled_tmp);
5beef3c9
AL
598 goto end;
599 }
600
bad2239e
AL
601 printk(KERN_INFO "batman-adv:Changing aggregation from: %s (%i) to: %s (%li)\n",
602 (atomic_read(&aggregation_enabled) == 1 ?
603 "enabled" : "disabled"),
604 atomic_read(&aggregation_enabled),
605 (aggregation_enabled_tmp == 1 ? "enabled" : "disabled"),
606 aggregation_enabled_tmp);
5beef3c9
AL
607
608 atomic_set(&aggregation_enabled, (unsigned)aggregation_enabled_tmp);
609end:
610 kfree(aggr_string);
611 return count;
612}
613
614static int proc_aggr_open(struct inode *inode, struct file *file)
615{
616 return single_open(file, proc_aggr_read, NULL);
617}
618
619/* satisfying different prototypes ... */
620static ssize_t proc_dummy_write(struct file *file, const char __user *buffer,
621 size_t count, loff_t *ppos)
622{
623 return count;
624}
625
626static const struct file_operations proc_aggr_fops = {
627 .owner = THIS_MODULE,
628 .open = proc_aggr_open,
629 .read = seq_read,
630 .write = proc_aggr_write,
631 .llseek = seq_lseek,
632 .release = single_release,
633};
634
635static const struct file_operations proc_vis_format_fops = {
636 .owner = THIS_MODULE,
637 .open = proc_vis_format_open,
638 .read = seq_read,
639 .write = proc_vis_format_write,
640 .llseek = seq_lseek,
641 .release = single_release,
642};
643
644static const struct file_operations proc_vis_fops = {
645 .owner = THIS_MODULE,
646 .open = proc_vis_open,
647 .read = seq_read,
648 .write = proc_vis_write,
649 .llseek = seq_lseek,
650 .release = single_release,
651};
652
653static const struct file_operations proc_originators_fops = {
654 .owner = THIS_MODULE,
655 .open = proc_originators_open,
656 .read = seq_read,
657 .write = proc_dummy_write,
658 .llseek = seq_lseek,
659 .release = single_release,
660};
661
662static const struct file_operations proc_transt_local_fops = {
663 .owner = THIS_MODULE,
664 .open = proc_transt_local_open,
665 .read = seq_read,
666 .write = proc_dummy_write,
667 .llseek = seq_lseek,
668 .release = single_release,
669};
670
671static const struct file_operations proc_transt_global_fops = {
672 .owner = THIS_MODULE,
673 .open = proc_transt_global_open,
674 .read = seq_read,
675 .write = proc_dummy_write,
676 .llseek = seq_lseek,
677 .release = single_release,
678};
679
5beef3c9
AL
680static const struct file_operations proc_interfaces_fops = {
681 .owner = THIS_MODULE,
682 .open = proc_interfaces_open,
683 .read = seq_read,
684 .write = proc_interfaces_write,
685 .llseek = seq_lseek,
686 .release = single_release,
687};
688
689static const struct file_operations proc_orig_interval_fops = {
690 .owner = THIS_MODULE,
691 .open = proc_orig_interval_open,
692 .read = seq_read,
693 .write = proc_orig_interval_write,
694 .llseek = seq_lseek,
695 .release = single_release,
696};
697
698void cleanup_procfs(void)
699{
700 if (proc_transt_global_file)
701 remove_proc_entry(PROC_FILE_TRANST_GLOBAL, proc_batman_dir);
702
703 if (proc_transt_local_file)
704 remove_proc_entry(PROC_FILE_TRANST_LOCAL, proc_batman_dir);
705
5beef3c9
AL
706 if (proc_originators_file)
707 remove_proc_entry(PROC_FILE_ORIGINATORS, proc_batman_dir);
708
709 if (proc_orig_interval_file)
710 remove_proc_entry(PROC_FILE_ORIG_INTERVAL, proc_batman_dir);
711
712 if (proc_interface_file)
713 remove_proc_entry(PROC_FILE_INTERFACES, proc_batman_dir);
714
715 if (proc_vis_file)
716 remove_proc_entry(PROC_FILE_VIS, proc_batman_dir);
717
718 if (proc_vis_format_file)
719 remove_proc_entry(PROC_FILE_VIS_FORMAT, proc_batman_dir);
720
721 if (proc_aggr_file)
722 remove_proc_entry(PROC_FILE_AGGR, proc_batman_dir);
723
724 if (proc_batman_dir)
725#ifdef __NET_NET_NAMESPACE_H
726 remove_proc_entry(PROC_ROOT_DIR, init_net.proc_net);
727#else
728 remove_proc_entry(PROC_ROOT_DIR, proc_net);
729#endif
730}
731
732int setup_procfs(void)
733{
734#ifdef __NET_NET_NAMESPACE_H
735 proc_batman_dir = proc_mkdir(PROC_ROOT_DIR, init_net.proc_net);
736#else
737 proc_batman_dir = proc_mkdir(PROC_ROOT_DIR, proc_net);
738#endif
739
740 if (!proc_batman_dir) {
741 printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s' folder failed\n", PROC_ROOT_DIR);
742 return -EFAULT;
743 }
744
745 proc_interface_file = create_proc_entry(PROC_FILE_INTERFACES,
746 S_IWUSR | S_IRUGO,
747 proc_batman_dir);
748 if (proc_interface_file) {
749 proc_interface_file->proc_fops = &proc_interfaces_fops;
750 } else {
751 printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_INTERFACES);
752 cleanup_procfs();
753 return -EFAULT;
754 }
755
756 proc_orig_interval_file = create_proc_entry(PROC_FILE_ORIG_INTERVAL,
757 S_IWUSR | S_IRUGO,
758 proc_batman_dir);
759 if (proc_orig_interval_file) {
760 proc_orig_interval_file->proc_fops = &proc_orig_interval_fops;
761 } else {
762 printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_ORIG_INTERVAL);
763 cleanup_procfs();
764 return -EFAULT;
765 }
766
5beef3c9
AL
767 proc_originators_file = create_proc_entry(PROC_FILE_ORIGINATORS,
768 S_IRUGO, proc_batman_dir);
769 if (proc_originators_file) {
770 proc_originators_file->proc_fops = &proc_originators_fops;
771 } else {
772 printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_ORIGINATORS);
773 cleanup_procfs();
774 return -EFAULT;
775 }
776
5beef3c9
AL
777 proc_transt_local_file = create_proc_entry(PROC_FILE_TRANST_LOCAL,
778 S_IRUGO, proc_batman_dir);
779 if (proc_transt_local_file) {
780 proc_transt_local_file->proc_fops = &proc_transt_local_fops;
781 } else {
782 printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_TRANST_LOCAL);
783 cleanup_procfs();
784 return -EFAULT;
785 }
786
787 proc_transt_global_file = create_proc_entry(PROC_FILE_TRANST_GLOBAL,
788 S_IRUGO, proc_batman_dir);
789 if (proc_transt_global_file) {
790 proc_transt_global_file->proc_fops = &proc_transt_global_fops;
791 } else {
792 printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_TRANST_GLOBAL);
793 cleanup_procfs();
794 return -EFAULT;
795 }
796
797 proc_vis_file = create_proc_entry(PROC_FILE_VIS, S_IWUSR | S_IRUGO,
798 proc_batman_dir);
799 if (proc_vis_file) {
800 proc_vis_file->proc_fops = &proc_vis_fops;
801 } else {
802 printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_VIS);
803 cleanup_procfs();
804 return -EFAULT;
805 }
806
807 proc_vis_format_file = create_proc_entry(PROC_FILE_VIS_FORMAT,
808 S_IWUSR | S_IRUGO,
809 proc_batman_dir);
810 if (proc_vis_format_file) {
811 proc_vis_format_file->proc_fops = &proc_vis_format_fops;
812 } else {
813 printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_VIS_FORMAT);
814 cleanup_procfs();
815 return -EFAULT;
816 }
817
818 proc_aggr_file = create_proc_entry(PROC_FILE_AGGR, S_IWUSR | S_IRUGO,
819 proc_batman_dir);
820 if (proc_aggr_file) {
821 proc_aggr_file->proc_fops = &proc_aggr_fops;
822 } else {
823 printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_AGGR);
824 cleanup_procfs();
825 return -EFAULT;
826 }
827
828 return 0;
829}
830
831