root/trunk/batman-adv-kernelland/proc.c @ 1589

Revision 1589, 23.7 kB (checked in by marek, 6 months ago)

batman-adv: Fix VIS output bug for secondary interfaces

TQ and HNA records for originators on secondary interfaces were
wrongly being included on the primary interface. Ensure we output a
line for each source interface on every node, so we correctly separate
primary and secondary interface records.

Signed-off-by: Linus Luessing <linus.luessing@…>

Line 
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"
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#include "gateway_common.h"
32#include "gateway_client.h"
33
34static struct proc_dir_entry *proc_batman_dir, *proc_interface_file;
35static struct proc_dir_entry *proc_orig_interval_file, *proc_originators_file;
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_srv_file, *proc_vis_data_file;
39static struct proc_dir_entry *proc_aggr_file, *proc_bond_file;
40static struct proc_dir_entry *proc_gw_mode_file, *proc_gw_srv_list_file;
41
42static int proc_interfaces_read(struct seq_file *seq, void *offset)
43{
44        struct batman_if *batman_if;
45
46        rcu_read_lock();
47        list_for_each_entry_rcu(batman_if, &if_list, list) {
48                seq_printf(seq, "[%8s] %s %s \n",
49                           (batman_if->if_active == IF_ACTIVE ?
50                            "active" : "inactive"),
51                           batman_if->dev,
52                           (batman_if->if_active == IF_ACTIVE ?
53                            batman_if->addr_str : " "));
54        }
55        rcu_read_unlock();
56
57        return 0;
58}
59
60static int proc_interfaces_open(struct inode *inode, struct file *file)
61{
62        return single_open(file, proc_interfaces_read, NULL);
63}
64
65static ssize_t proc_interfaces_write(struct file *instance,
66                                     const char __user *userbuffer,
67                                     size_t count, loff_t *data)
68{
69        char *if_string, *colon_ptr = NULL, *cr_ptr = NULL;
70        int not_copied = 0, if_num = 0, add_success;
71        struct batman_if *batman_if = NULL;
72
73        if_string = kmalloc(count, GFP_KERNEL);
74
75        if (!if_string)
76                return -ENOMEM;
77
78        if (count > IFNAMSIZ - 1) {
79                printk(KERN_WARNING "batman-adv:Can't add interface: device name is too long\n");
80                goto end;
81        }
82
83        not_copied = copy_from_user(if_string, userbuffer, count);
84        if_string[count - not_copied - 1] = 0;
85
86        colon_ptr = strchr(if_string, ':');
87        if (colon_ptr)
88                *colon_ptr = 0;
89
90        if (!colon_ptr) {
91                cr_ptr = strchr(if_string, '\n');
92                if (cr_ptr)
93                        *cr_ptr = 0;
94        }
95
96        if (strlen(if_string) == 0) {
97                shutdown_module();
98                num_ifs = 0;
99                goto end;
100        }
101
102        /* add interface */
103        rcu_read_lock();
104        list_for_each_entry_rcu(batman_if, &if_list, list) {
105                if (strncmp(batman_if->dev, if_string, count) == 0) {
106                        printk(KERN_ERR "batman-adv:Given interface is already active: %s\n", if_string);
107                        rcu_read_unlock();
108                        goto end;
109
110                }
111
112                if_num++;
113        }
114        rcu_read_unlock();
115
116        add_success = hardif_add_interface(if_string, if_num);
117        if (add_success < 0)
118                goto end;
119
120        num_ifs = if_num + 1;
121
122        if ((atomic_read(&module_state) == MODULE_INACTIVE) &&
123            (hardif_get_active_if_num() > 0))
124                activate_module();
125
126        return count;
127end:
128        kfree(if_string);
129        return count;
130}
131
132static int proc_orig_interval_read(struct seq_file *seq, void *offset)
133{
134        seq_printf(seq, "%i\n", atomic_read(&originator_interval));
135
136        return 0;
137}
138
139static ssize_t proc_orig_interval_write(struct file *file,
140                                        const char __user *buffer,
141                                        size_t count, loff_t *ppos)
142{
143        char *interval_string;
144        int not_copied = 0;
145        unsigned long originator_interval_tmp;
146        int retval;
147
148        interval_string = kmalloc(count, GFP_KERNEL);
149
150        if (!interval_string)
151                return -ENOMEM;
152
153        not_copied = copy_from_user(interval_string, buffer, count);
154        interval_string[count - not_copied - 1] = 0;
155
156        retval = strict_strtoul(interval_string, 10, &originator_interval_tmp);
157        if (retval) {
158                printk(KERN_ERR "batman-adv:New originator interval invalid\n");
159                goto end;
160        }
161
162        if (originator_interval_tmp <= JITTER * 2) {
163                printk(KERN_WARNING "batman-adv:New originator interval too small: %li (min: %i)\n",
164                       originator_interval_tmp, JITTER * 2);
165                goto end;
166        }
167
168        printk(KERN_INFO "batman-adv:Changing originator interval from: %i to: %li\n",
169               atomic_read(&originator_interval), originator_interval_tmp);
170
171        atomic_set(&originator_interval, originator_interval_tmp);
172
173end:
174        kfree(interval_string);
175        return count;
176}
177
178static int proc_orig_interval_open(struct inode *inode, struct file *file)
179{
180        return single_open(file, proc_orig_interval_read, NULL);
181}
182
183static int proc_originators_read(struct seq_file *seq, void *offset)
184{
185        HASHIT(hashit);
186        struct orig_node *orig_node;
187        struct neigh_node *neigh_node;
188        int batman_count = 0;
189        char orig_str[ETH_STR_LEN], router_str[ETH_STR_LEN];
190        unsigned long flags;
191
192        rcu_read_lock();
193        if (list_empty(&if_list)) {
194                rcu_read_unlock();
195                seq_printf(seq, "BATMAN disabled - please specify interfaces to enable it \n");
196                goto end;
197        }
198
199        if (((struct batman_if *)if_list.next)->if_active != IF_ACTIVE) {
200                rcu_read_unlock();
201                seq_printf(seq, "BATMAN disabled - primary interface not active \n");
202                goto end;
203        }
204
205        seq_printf(seq,
206                   "  %-14s (%s/%i) %17s [%10s]: %20s ... [B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%s] \n",
207                   "Originator", "#", TQ_MAX_VALUE, "Nexthop", "outgoingIF",
208                   "Potential nexthops", SOURCE_VERSION, REVISION_VERSION_STR,
209                   ((struct batman_if *)if_list.next)->dev,
210                   ((struct batman_if *)if_list.next)->addr_str);
211
212        rcu_read_unlock();
213        spin_lock_irqsave(&orig_hash_lock, flags);
214
215        while (hash_iterate(orig_hash, &hashit)) {
216
217                orig_node = hashit.bucket->data;
218
219                if (!orig_node->router)
220                        continue;
221
222                if (orig_node->router->tq_avg == 0)
223                        continue;
224
225                batman_count++;
226
227                addr_to_string(orig_str, orig_node->orig);
228                addr_to_string(router_str, orig_node->router->addr);
229
230                seq_printf(seq, "%-17s  (%3i) %17s [%10s]:",
231                           orig_str, orig_node->router->tq_avg,
232                           router_str, orig_node->router->if_incoming->dev);
233
234                list_for_each_entry(neigh_node, &orig_node->neigh_list, list) {
235                        addr_to_string(orig_str, neigh_node->addr);
236                        seq_printf(seq, " %17s (%3i)",
237                                   orig_str, neigh_node->tq_avg);
238                }
239
240                seq_printf(seq, "\n");
241
242        }
243
244        spin_unlock_irqrestore(&orig_hash_lock, flags);
245
246        if (batman_count == 0)
247                seq_printf(seq, "No batman nodes in range ... \n");
248
249end:
250        return 0;
251}
252
253static int proc_originators_open(struct inode *inode, struct file *file)
254{
255        return single_open(file, proc_originators_read, NULL);
256}
257
258static int proc_transt_local_read(struct seq_file *seq, void *offset)
259{
260        char *buf;
261
262        buf = kmalloc(4096, GFP_KERNEL);
263        if (!buf)
264                return 0;
265
266        rcu_read_lock();
267        if (list_empty(&if_list)) {
268                rcu_read_unlock();
269                seq_printf(seq, "BATMAN disabled - please specify interfaces to enable it \n");
270                goto end;
271        }
272
273        rcu_read_unlock();
274
275        seq_printf(seq, "Locally retrieved addresses (from %s) announced via HNA:\n", soft_device->name);
276
277        hna_local_fill_buffer_text(buf, 4096);
278        seq_printf(seq, "%s", buf);
279
280end:
281        kfree(buf);
282        return 0;
283}
284
285static int proc_transt_local_open(struct inode *inode, struct file *file)
286{
287        return single_open(file, proc_transt_local_read, NULL);
288}
289
290static int proc_transt_global_read(struct seq_file *seq, void *offset)
291{
292        char *buf;
293
294        buf = kmalloc(4096, GFP_KERNEL);
295        if (!buf)
296                return 0;
297
298        rcu_read_lock();
299        if (list_empty(&if_list)) {
300                rcu_read_unlock();
301                seq_printf(seq, "BATMAN disabled - please specify interfaces to enable it \n");
302                goto end;
303        }
304        rcu_read_unlock();
305
306
307        seq_printf(seq, "Globally announced HNAs received via the mesh (translation table):\n");
308
309        hna_global_fill_buffer_text(buf, 4096);
310        seq_printf(seq, "%s", buf);
311
312end:
313        kfree(buf);
314        return 0;
315}
316
317static int proc_transt_global_open(struct inode *inode, struct file *file)
318{
319        return single_open(file, proc_transt_global_read, NULL);
320}
321
322/* setting the mode of the vis server by the user */
323static ssize_t proc_vis_srv_write(struct file *file, const char __user * buffer,
324                              size_t count, loff_t *ppos)
325{
326        char *vis_mode_string;
327        int not_copied = 0;
328
329        vis_mode_string = kmalloc(count, GFP_KERNEL);
330
331        if (!vis_mode_string)
332                return -ENOMEM;
333
334        not_copied = copy_from_user(vis_mode_string, buffer, count);
335        vis_mode_string[count - not_copied - 1] = 0;
336
337        if ((strcmp(vis_mode_string, "client") == 0) ||
338                        (strcmp(vis_mode_string, "disabled") == 0)) {
339                printk(KERN_INFO "batman-adv:Setting VIS mode to client (disabling vis server)\n");
340                atomic_set(&vis_mode, VIS_TYPE_CLIENT_UPDATE);
341        } else if ((strcmp(vis_mode_string, "server") == 0) ||
342                        (strcmp(vis_mode_string, "enabled") == 0)) {
343                printk(KERN_INFO "batman-adv:Setting VIS mode to server (enabling vis server)\n");
344                atomic_set(&vis_mode, VIS_TYPE_SERVER_SYNC);
345        } else
346                printk(KERN_ERR "batman-adv:Unknown VIS mode: %s\n",
347                       vis_mode_string);
348
349        kfree(vis_mode_string);
350        return count;
351}
352
353static int proc_vis_srv_read(struct seq_file *seq, void *offset)
354{
355        int vis_server = atomic_read(&vis_mode);
356
357        seq_printf(seq, "[%c] client mode (server disabled) \n",
358                        (vis_server == VIS_TYPE_CLIENT_UPDATE) ? 'x' : ' ');
359        seq_printf(seq, "[%c] server mode (server enabled) \n",
360                        (vis_server == VIS_TYPE_SERVER_SYNC) ? 'x' : ' ');
361
362        return 0;
363}
364
365static int proc_vis_srv_open(struct inode *inode, struct file *file)
366{
367        return single_open(file, proc_vis_srv_read, NULL);
368}
369
370static int proc_vis_data_read(struct seq_file *seq, void *offset)
371{
372        HASHIT(hashit);
373        struct vis_info *info;
374        struct vis_info_entry *entries;
375        HLIST_HEAD(vis_if_list);
376        struct if_list_entry *entry;
377        struct hlist_node *pos, *n;
378        int i;
379        char tmp_addr_str[ETH_STR_LEN];
380        unsigned long flags;
381        int vis_server = atomic_read(&vis_mode);
382
383        rcu_read_lock();
384        if (list_empty(&if_list) || (vis_server == VIS_TYPE_CLIENT_UPDATE)) {
385                rcu_read_unlock();
386                goto end;
387        }
388
389        rcu_read_unlock();
390
391        spin_lock_irqsave(&vis_hash_lock, flags);
392        while (hash_iterate(vis_hash, &hashit)) {
393                info = hashit.bucket->data;
394                entries = (struct vis_info_entry *)
395                        ((char *)info + sizeof(struct vis_info));
396
397                for (i = 0; i < info->packet.entries; i++) {
398                        if (entries[i].quality == 0)
399                                continue;
400                        proc_vis_insert_interface(entries[i].src, &vis_if_list,
401                                compare_orig(entries[i].src,
402                                                info->packet.vis_orig));
403                }
404
405                hlist_for_each_entry(entry, pos, &vis_if_list, list) {
406                        addr_to_string(tmp_addr_str, entry->addr);
407                        seq_printf(seq, "%s,", tmp_addr_str);
408
409                        for (i = 0; i < info->packet.entries; i++)
410                                proc_vis_read_entry(seq, &entries[i],
411                                                entry->addr, entry->primary);
412
413                        /* add primary/secondary records */
414                        if (compare_orig(entry->addr, info->packet.vis_orig))
415                                proc_vis_read_prim_sec(seq, &vis_if_list);
416
417                        seq_printf(seq, "\n");
418                }
419
420                hlist_for_each_entry_safe(entry, pos, n, &vis_if_list, list) {
421                        hlist_del(&entry->list);
422                        kfree(entry);
423                }
424        }
425        spin_unlock_irqrestore(&vis_hash_lock, flags);
426
427end:
428        return 0;
429}
430
431static int proc_vis_data_open(struct inode *inode, struct file *file)
432{
433        return single_open(file, proc_vis_data_read, NULL);
434}
435
436static int proc_aggr_read(struct seq_file *seq, void *offset)
437{
438        seq_printf(seq, "%i\n", atomic_read(&aggregation_enabled));
439
440        return 0;
441}
442
443static ssize_t proc_aggr_write(struct file *file, const char __user *buffer,
444                               size_t count, loff_t *ppos)
445{
446        char *aggr_string;
447        int not_copied = 0;
448        unsigned long aggregation_enabled_tmp;
449        int retval;
450
451        aggr_string = kmalloc(count, GFP_KERNEL);
452
453        if (!aggr_string)
454                return -ENOMEM;
455
456        not_copied = copy_from_user(aggr_string, buffer, count);
457        aggr_string[count - not_copied - 1] = 0;
458
459        retval = strict_strtoul(aggr_string, 10, &aggregation_enabled_tmp);
460
461        if (retval || aggregation_enabled_tmp > 1) {
462                printk(KERN_ERR "batman-adv:Aggregation can only be enabled (1) or disabled (0), given value: %li\n", aggregation_enabled_tmp);
463        } else {
464                printk(KERN_INFO "batman-adv:Changing aggregation from: %s (%i) to: %s (%li)\n",
465                       (atomic_read(&aggregation_enabled) == 1 ?
466                        "enabled" : "disabled"),
467                       atomic_read(&aggregation_enabled),
468                       (aggregation_enabled_tmp == 1 ? "enabled" : "disabled"),
469                       aggregation_enabled_tmp);
470                atomic_set(&aggregation_enabled, 
471                                                (unsigned)aggregation_enabled_tmp);
472        }
473
474        kfree(aggr_string);
475        return count;
476}
477
478static int proc_aggr_open(struct inode *inode, struct file *file)
479{
480        return single_open(file, proc_aggr_read, NULL);
481}
482
483static int proc_gw_mode_read(struct seq_file *seq, void *offset)
484{
485        int down, up;
486        long gw_mode_curr = atomic_read(&gw_mode);
487        uint8_t gw_srv_class_curr = (uint8_t)atomic_read(&gw_srv_class);
488
489        gw_srv_class_to_kbit(gw_srv_class_curr, &down, &up);
490
491        seq_printf(seq, "[%c] %s\n",
492                   (gw_mode_curr == GW_MODE_OFF) ? 'x' : ' ',
493                   GW_MODE_OFF_NAME);
494
495        if (gw_mode_curr == GW_MODE_CLIENT)
496                seq_printf(seq, "[x] %s (gw_clnt_class: %i)\n",
497                           GW_MODE_CLIENT_NAME,
498                           atomic_read(&gw_clnt_class));
499        else
500                seq_printf(seq, "[ ] %s\n", GW_MODE_CLIENT_NAME);
501
502        if (gw_mode_curr == GW_MODE_SERVER)
503                seq_printf(seq,
504                           "[x] %s (gw_srv_class: %i -> propagating: %i%s/%i%s)\n",
505                           GW_MODE_SERVER_NAME,
506                           gw_srv_class_curr,
507                           (down > 2048 ? down / 1024 : down),
508                           (down > 2048 ? "MBit" : "KBit"),
509                           (up > 2048 ? up / 1024 : up),
510                           (up > 2048 ? "MBit" : "KBit"));
511        else
512                seq_printf(seq, "[ ] %s\n", GW_MODE_SERVER_NAME);
513
514        return 0;
515}
516
517static int proc_gw_mode_open(struct inode *inode, struct file *file)
518{
519        return single_open(file, proc_gw_mode_read, NULL);
520}
521
522static ssize_t proc_gw_mode_write(struct file *instance,
523                                    const char __user *userbuffer,
524                                    size_t count, loff_t *data)
525{
526        return gw_mode_set(userbuffer, count);
527}
528
529static int proc_gw_srv_list_read(struct seq_file *seq, void *offset)
530{
531        char *buff;
532        int buffsize = 4096;
533
534        buff = kmalloc(buffsize, GFP_KERNEL);
535        if (!buff)
536                return 0;
537
538        rcu_read_lock();
539        if (list_empty(&if_list)) {
540                rcu_read_unlock();
541                seq_printf(seq,
542                           "BATMAN disabled - please specify interfaces to enable it\n");
543                goto end;
544        }
545
546        if (((struct batman_if *)if_list.next)->if_active != IF_ACTIVE) {
547                rcu_read_unlock();
548                seq_printf(seq,
549                           "BATMAN disabled - primary interface not active\n");
550                goto end;
551        }
552
553        seq_printf(seq,
554                   "      %-12s (%s/%i) %17s [%10s]: gw_srv_class ... [B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%s] \n",
555                   "Gateway", "#", TQ_MAX_VALUE, "Nexthop",
556                   "outgoingIF", SOURCE_VERSION, REVISION_VERSION_STR,
557                   ((struct batman_if *)if_list.next)->dev,
558                   ((struct batman_if *)if_list.next)->addr_str);
559
560        rcu_read_unlock();
561
562        gw_client_fill_buffer_text(buff, buffsize);
563        seq_printf(seq, "%s", buff);
564
565end:
566        kfree(buff);
567        return 0;
568}
569
570static int proc_gw_srv_list_open(struct inode *inode, struct file *file)
571{
572        return single_open(file, proc_gw_srv_list_read, NULL);
573}
574
575
576static int proc_bond_read(struct seq_file *seq, void *offset)
577{
578        seq_printf(seq, "%i\n", atomic_read(&bonding_enabled));
579
580        return 0;
581}
582
583static ssize_t proc_bond_write(struct file *file, const char __user *buffer,
584                               size_t count, loff_t *ppos)
585{
586        char *bond_string;
587        int not_copied = 0;
588        unsigned long bonding_enabled_tmp;
589        int retval;
590
591        bond_string = kmalloc(count, GFP_KERNEL);
592
593        if (!bond_string)
594                return -ENOMEM;
595
596        not_copied = copy_from_user(bond_string, buffer, count);
597        bond_string[count - not_copied - 1] = 0;
598
599        retval = strict_strtoul(bond_string, 10, &bonding_enabled_tmp);
600
601        if (retval || bonding_enabled_tmp > 1) {
602                printk(KERN_ERR "batman-adv: Bonding can only be enabled (1) or disabled (0), given value: %li\n", bonding_enabled_tmp);
603        } else {
604                printk(KERN_INFO "batman-adv:Changing bonding from: %s (%i) to: %s (%li)\n",
605                       (atomic_read(&bonding_enabled) == 1 ?
606                        "enabled" : "disabled"),
607                       atomic_read(&bonding_enabled),
608                       (bonding_enabled_tmp == 1 ? "enabled" : "disabled"),
609                       bonding_enabled_tmp);
610                atomic_set(&bonding_enabled,
611                                                (unsigned)bonding_enabled_tmp);
612        }
613
614        kfree(bond_string);
615        return count;
616}
617
618static int proc_bond_open(struct inode *inode, struct file *file)
619{
620        return single_open(file, proc_bond_read, NULL);
621}
622
623/* satisfying different prototypes ... */
624static ssize_t proc_dummy_write(struct file *file, const char __user *buffer,
625                                size_t count, loff_t *ppos)
626{
627        return count;
628}
629
630static const struct file_operations proc_gw_srv_list_fops = {
631        .owner          = THIS_MODULE,
632        .open           = proc_gw_srv_list_open,
633        .read           = seq_read,
634        .write          = proc_dummy_write,
635        .llseek         = seq_lseek,
636        .release        = single_release,
637};
638
639static const struct file_operations proc_gw_mode_fops = {
640        .owner          = THIS_MODULE,
641        .open           = proc_gw_mode_open,
642        .read           = seq_read,
643        .write          = proc_gw_mode_write,
644        .llseek         = seq_lseek,
645        .release        = single_release,
646};
647
648static const struct file_operations proc_aggr_fops = {
649        .owner          = THIS_MODULE,
650        .open           = proc_aggr_open,
651        .read           = seq_read,
652        .write          = proc_aggr_write,
653        .llseek         = seq_lseek,
654        .release        = single_release,
655};
656
657static const struct file_operations proc_bond_fops = {
658        .owner          = THIS_MODULE,
659        .open           = proc_bond_open,
660        .read           = seq_read,
661        .write          = proc_bond_write,
662        .llseek         = seq_lseek,
663        .release        = single_release,
664};
665
666static const struct file_operations proc_vis_srv_fops = {
667        .owner          = THIS_MODULE,
668        .open           = proc_vis_srv_open,
669        .read           = seq_read,
670        .write          = proc_vis_srv_write,
671        .llseek         = seq_lseek,
672        .release        = single_release,
673};
674
675static const struct file_operations proc_vis_data_fops = {
676        .owner          = THIS_MODULE,
677        .open           = proc_vis_data_open,
678        .read           = seq_read,
679        .write          = proc_dummy_write,
680        .llseek         = seq_lseek,
681        .release        = single_release,
682};
683
684static const struct file_operations proc_originators_fops = {
685        .owner          = THIS_MODULE,
686        .open           = proc_originators_open,
687        .read           = seq_read,
688        .write          = proc_dummy_write,
689        .llseek         = seq_lseek,
690        .release        = single_release,
691};
692
693static const struct file_operations proc_transt_local_fops = {
694        .owner          = THIS_MODULE,
695        .open           = proc_transt_local_open,
696        .read           = seq_read,
697        .write          = proc_dummy_write,
698        .llseek         = seq_lseek,
699        .release        = single_release,
700};
701
702static const struct file_operations proc_transt_global_fops = {
703        .owner          = THIS_MODULE,
704        .open           = proc_transt_global_open,
705        .read           = seq_read,
706        .write          = proc_dummy_write,
707        .llseek         = seq_lseek,
708        .release        = single_release,
709};
710
711static const struct file_operations proc_interfaces_fops = {
712        .owner          = THIS_MODULE,
713        .open           = proc_interfaces_open,
714        .read           = seq_read,
715        .write          = proc_interfaces_write,
716        .llseek         = seq_lseek,
717        .release        = single_release,
718};
719
720static const struct file_operations proc_orig_interval_fops = {
721        .owner          = THIS_MODULE,
722        .open           = proc_orig_interval_open,
723        .read           = seq_read,
724        .write          = proc_orig_interval_write,
725        .llseek         = seq_lseek,
726        .release        = single_release,
727};
728
729void cleanup_procfs(void)
730{
731        if (proc_transt_global_file)
732                remove_proc_entry(PROC_FILE_TRANST_GLOBAL, proc_batman_dir);
733
734        if (proc_transt_local_file)
735                remove_proc_entry(PROC_FILE_TRANST_LOCAL, proc_batman_dir);
736
737        if (proc_originators_file)
738                remove_proc_entry(PROC_FILE_ORIGINATORS, proc_batman_dir);
739
740        if (proc_orig_interval_file)
741                remove_proc_entry(PROC_FILE_ORIG_INTERVAL, proc_batman_dir);
742
743        if (proc_interface_file)
744                remove_proc_entry(PROC_FILE_INTERFACES, proc_batman_dir);
745
746        if (proc_vis_data_file)
747                remove_proc_entry(PROC_FILE_VIS_DATA, proc_batman_dir);
748
749        if (proc_vis_srv_file)
750                remove_proc_entry(PROC_FILE_VIS_SRV, proc_batman_dir);
751
752        if (proc_aggr_file)
753                remove_proc_entry(PROC_FILE_AGGR, proc_batman_dir);
754
755        if (proc_gw_mode_file)
756                remove_proc_entry(PROC_FILE_GW_MODE, proc_batman_dir);
757
758        if (proc_gw_srv_list_file)
759                remove_proc_entry(PROC_FILE_GW_SRV_LIST, proc_batman_dir);
760
761        if (proc_bond_file)
762                remove_proc_entry(PROC_FILE_BOND, proc_batman_dir);
763
764
765        if (proc_batman_dir)
766#ifdef __NET_NET_NAMESPACE_H
767                remove_proc_entry(PROC_ROOT_DIR, init_net.proc_net);
768#else
769                remove_proc_entry(PROC_ROOT_DIR, proc_net);
770#endif
771}
772
773int setup_procfs(void)
774{
775#ifdef __NET_NET_NAMESPACE_H
776        proc_batman_dir = proc_mkdir(PROC_ROOT_DIR, init_net.proc_net);
777#else
778        proc_batman_dir = proc_mkdir(PROC_ROOT_DIR, proc_net);
779#endif
780
781        if (!proc_batman_dir) {
782                printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s' folder failed\n", PROC_ROOT_DIR);
783                return -EFAULT;
784        }
785
786        proc_interface_file = create_proc_entry(PROC_FILE_INTERFACES,
787                                                S_IWUSR | S_IRUGO,
788                                                proc_batman_dir);
789        if (proc_interface_file) {
790                proc_interface_file->proc_fops = &proc_interfaces_fops;
791        } else {
792                printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_INTERFACES);
793                cleanup_procfs();
794                return -EFAULT;
795        }
796
797        proc_orig_interval_file = create_proc_entry(PROC_FILE_ORIG_INTERVAL,
798                                                    S_IWUSR | S_IRUGO,
799                                                    proc_batman_dir);
800        if (proc_orig_interval_file) {
801                proc_orig_interval_file->proc_fops = &proc_orig_interval_fops;
802        } else {
803                printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_ORIG_INTERVAL);
804                cleanup_procfs();
805                return -EFAULT;
806        }
807
808        proc_originators_file = create_proc_entry(PROC_FILE_ORIGINATORS,
809                                                  S_IRUGO, proc_batman_dir);
810        if (proc_originators_file) {
811                proc_originators_file->proc_fops = &proc_originators_fops;
812        } else {
813                printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_ORIGINATORS);
814                cleanup_procfs();
815                return -EFAULT;
816        }
817
818        proc_transt_local_file = create_proc_entry(PROC_FILE_TRANST_LOCAL,
819                                                   S_IRUGO, proc_batman_dir);
820        if (proc_transt_local_file) {
821                proc_transt_local_file->proc_fops = &proc_transt_local_fops;
822        } else {
823                printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_TRANST_LOCAL);
824                cleanup_procfs();
825                return -EFAULT;
826        }
827
828        proc_transt_global_file = create_proc_entry(PROC_FILE_TRANST_GLOBAL,
829                                                    S_IRUGO, proc_batman_dir);
830        if (proc_transt_global_file) {
831                proc_transt_global_file->proc_fops = &proc_transt_global_fops;
832        } else {
833                printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_TRANST_GLOBAL);
834                cleanup_procfs();
835                return -EFAULT;
836        }
837
838        proc_vis_srv_file = create_proc_entry(PROC_FILE_VIS_SRV,
839                                                S_IWUSR | S_IRUGO,
840                                                proc_batman_dir);
841        if (proc_vis_srv_file) {
842                proc_vis_srv_file->proc_fops = &proc_vis_srv_fops;
843        } else {
844                printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_VIS_SRV);
845                cleanup_procfs();
846                return -EFAULT;
847        }
848
849        proc_vis_data_file = create_proc_entry(PROC_FILE_VIS_DATA, S_IRUGO,
850                                          proc_batman_dir);
851        if (proc_vis_data_file) {
852                proc_vis_data_file->proc_fops = &proc_vis_data_fops;
853        } else {
854                printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_VIS_DATA);
855                cleanup_procfs();
856                return -EFAULT;
857        }
858
859        proc_aggr_file = create_proc_entry(PROC_FILE_AGGR, S_IWUSR | S_IRUGO,
860                                           proc_batman_dir);
861        if (proc_aggr_file) {
862                proc_aggr_file->proc_fops = &proc_aggr_fops;
863        } else {
864                printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_AGGR);
865                cleanup_procfs();
866                return -EFAULT;
867        }
868
869        proc_gw_mode_file = create_proc_entry(PROC_FILE_GW_MODE,
870                                           S_IWUSR | S_IRUGO,
871                                           proc_batman_dir);
872        if (proc_gw_mode_file) {
873                proc_gw_mode_file->proc_fops = &proc_gw_mode_fops;
874        } else {
875                printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n",
876                       PROC_ROOT_DIR, PROC_FILE_GW_MODE);
877                cleanup_procfs();
878                return -EFAULT;
879        }
880
881        proc_gw_srv_list_file = create_proc_entry(PROC_FILE_GW_SRV_LIST,
882                                           S_IWUSR | S_IRUGO,
883                                           proc_batman_dir);
884        if (proc_gw_srv_list_file) {
885                proc_gw_srv_list_file->proc_fops = &proc_gw_srv_list_fops;
886        } else {
887                printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n",
888                       PROC_ROOT_DIR, PROC_FILE_GW_SRV_LIST);
889                cleanup_procfs();
890                return -EFAULT;
891        }
892
893        proc_bond_file = create_proc_entry(PROC_FILE_BOND, S_IWUSR | S_IRUGO,
894                                           proc_batman_dir);
895        if (proc_bond_file) {
896                proc_bond_file->proc_fops = &proc_bond_fops;
897        } else {
898                printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_BOND);
899                cleanup_procfs();
900                return -EFAULT;
901        }
902
903        return 0;
904}
Note: See TracBrowser for help on using the browser.