Commit | Line | Data |
---|---|---|
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" | |
5beef3c9 | 30 | |
5beef3c9 AL |
31 | static struct proc_dir_entry *proc_batman_dir, *proc_interface_file; |
32 | static struct proc_dir_entry *proc_orig_interval_file, *proc_originators_file; | |
5beef3c9 AL |
33 | static struct proc_dir_entry *proc_transt_local_file; |
34 | static struct proc_dir_entry *proc_transt_global_file; | |
e9b76450 | 35 | static struct proc_dir_entry *proc_vis_srv_file, *proc_vis_data_file; |
5beef3c9 AL |
36 | static struct proc_dir_entry *proc_aggr_file; |
37 | ||
38 | static int proc_interfaces_read(struct seq_file *seq, void *offset) | |
39 | { | |
40 | struct batman_if *batman_if; | |
41 | ||
42 | rcu_read_lock(); | |
43 | list_for_each_entry_rcu(batman_if, &if_list, list) { | |
44 | seq_printf(seq, "[%8s] %s %s \n", | |
45 | (batman_if->if_active == IF_ACTIVE ? | |
46 | "active" : "inactive"), | |
47 | batman_if->dev, | |
48 | (batman_if->if_active == IF_ACTIVE ? | |
49 | batman_if->addr_str : " ")); | |
50 | } | |
51 | rcu_read_unlock(); | |
52 | ||
53 | return 0; | |
54 | } | |
55 | ||
56 | static int proc_interfaces_open(struct inode *inode, struct file *file) | |
57 | { | |
58 | return single_open(file, proc_interfaces_read, NULL); | |
59 | } | |
60 | ||
61 | static ssize_t proc_interfaces_write(struct file *instance, | |
62 | const char __user *userbuffer, | |
63 | size_t count, loff_t *data) | |
64 | { | |
65 | char *if_string, *colon_ptr = NULL, *cr_ptr = NULL; | |
af71b816 | 66 | int not_copied = 0, if_num = 0, add_success; |
5beef3c9 AL |
67 | struct batman_if *batman_if = NULL; |
68 | ||
69 | if_string = kmalloc(count, GFP_KERNEL); | |
70 | ||
71 | if (!if_string) | |
72 | return -ENOMEM; | |
73 | ||
74 | if (count > IFNAMSIZ - 1) { | |
bad2239e | 75 | printk(KERN_WARNING "batman-adv:Can't add interface: device name is too long\n"); |
5beef3c9 AL |
76 | goto end; |
77 | } | |
78 | ||
79 | not_copied = copy_from_user(if_string, userbuffer, count); | |
80 | if_string[count - not_copied - 1] = 0; | |
81 | ||
82 | colon_ptr = strchr(if_string, ':'); | |
83 | if (colon_ptr) | |
84 | *colon_ptr = 0; | |
85 | ||
86 | if (!colon_ptr) { | |
87 | cr_ptr = strchr(if_string, '\n'); | |
88 | if (cr_ptr) | |
89 | *cr_ptr = 0; | |
90 | } | |
91 | ||
92 | if (strlen(if_string) == 0) { | |
93 | shutdown_module(); | |
94 | num_ifs = 0; | |
95 | goto end; | |
96 | } | |
97 | ||
98 | /* add interface */ | |
99 | rcu_read_lock(); | |
100 | list_for_each_entry_rcu(batman_if, &if_list, list) { | |
101 | if (strncmp(batman_if->dev, if_string, count) == 0) { | |
bad2239e | 102 | printk(KERN_ERR "batman-adv:Given interface is already active: %s\n", if_string); |
5beef3c9 AL |
103 | rcu_read_unlock(); |
104 | goto end; | |
105 | ||
106 | } | |
107 | ||
108 | if_num++; | |
109 | } | |
110 | rcu_read_unlock(); | |
111 | ||
af71b816 ML |
112 | add_success = hardif_add_interface(if_string, if_num); |
113 | if (add_success < 0) | |
114 | goto end; | |
115 | ||
116 | num_ifs = if_num + 1; | |
5beef3c9 AL |
117 | |
118 | if ((atomic_read(&module_state) == MODULE_INACTIVE) && | |
119 | (hardif_get_active_if_num() > 0)) | |
120 | activate_module(); | |
121 | ||
5beef3c9 | 122 | return count; |
5beef3c9 AL |
123 | end: |
124 | kfree(if_string); | |
125 | return count; | |
126 | } | |
127 | ||
128 | static int proc_orig_interval_read(struct seq_file *seq, void *offset) | |
129 | { | |
130 | seq_printf(seq, "%i\n", atomic_read(&originator_interval)); | |
131 | ||
132 | return 0; | |
133 | } | |
134 | ||
135 | static ssize_t proc_orig_interval_write(struct file *file, | |
136 | const char __user *buffer, | |
137 | size_t count, loff_t *ppos) | |
138 | { | |
139 | char *interval_string; | |
140 | int not_copied = 0; | |
141 | unsigned long originator_interval_tmp; | |
142 | int retval; | |
143 | ||
144 | interval_string = kmalloc(count, GFP_KERNEL); | |
145 | ||
146 | if (!interval_string) | |
147 | return -ENOMEM; | |
148 | ||
149 | not_copied = copy_from_user(interval_string, buffer, count); | |
150 | interval_string[count - not_copied - 1] = 0; | |
151 | ||
152 | retval = strict_strtoul(interval_string, 10, &originator_interval_tmp); | |
153 | if (retval) { | |
bad2239e | 154 | printk(KERN_ERR "batman-adv:New originator interval invalid\n"); |
5beef3c9 AL |
155 | goto end; |
156 | } | |
157 | ||
158 | if (originator_interval_tmp <= JITTER * 2) { | |
bad2239e AL |
159 | printk(KERN_WARNING "batman-adv:New originator interval too small: %li (min: %i)\n", |
160 | originator_interval_tmp, JITTER * 2); | |
5beef3c9 AL |
161 | goto end; |
162 | } | |
163 | ||
bad2239e AL |
164 | printk(KERN_INFO "batman-adv:Changing originator interval from: %i to: %li\n", |
165 | atomic_read(&originator_interval), originator_interval_tmp); | |
5beef3c9 AL |
166 | |
167 | atomic_set(&originator_interval, originator_interval_tmp); | |
168 | ||
169 | end: | |
170 | kfree(interval_string); | |
171 | return count; | |
172 | } | |
173 | ||
174 | static int proc_orig_interval_open(struct inode *inode, struct file *file) | |
175 | { | |
176 | return single_open(file, proc_orig_interval_read, NULL); | |
177 | } | |
178 | ||
179 | static int proc_originators_read(struct seq_file *seq, void *offset) | |
180 | { | |
b6c35976 | 181 | HASHIT(hashit); |
5beef3c9 AL |
182 | struct orig_node *orig_node; |
183 | struct neigh_node *neigh_node; | |
184 | int batman_count = 0; | |
185 | char orig_str[ETH_STR_LEN], router_str[ETH_STR_LEN]; | |
e7017195 | 186 | unsigned long flags; |
5beef3c9 AL |
187 | |
188 | rcu_read_lock(); | |
189 | if (list_empty(&if_list)) { | |
190 | rcu_read_unlock(); | |
191 | seq_printf(seq, "BATMAN disabled - please specify interfaces to enable it \n"); | |
192 | goto end; | |
193 | } | |
194 | ||
195 | if (((struct batman_if *)if_list.next)->if_active != IF_ACTIVE) { | |
196 | rcu_read_unlock(); | |
197 | seq_printf(seq, "BATMAN disabled - primary interface not active \n"); | |
198 | goto end; | |
199 | } | |
200 | ||
201 | seq_printf(seq, | |
202 | " %-14s (%s/%i) %17s [%10s]: %20s ... [B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%s] \n", | |
203 | "Originator", "#", TQ_MAX_VALUE, "Nexthop", "outgoingIF", | |
204 | "Potential nexthops", SOURCE_VERSION, REVISION_VERSION_STR, | |
205 | ((struct batman_if *)if_list.next)->dev, | |
206 | ((struct batman_if *)if_list.next)->addr_str); | |
207 | ||
208 | rcu_read_unlock(); | |
e7017195 | 209 | spin_lock_irqsave(&orig_hash_lock, flags); |
5beef3c9 | 210 | |
b6c35976 | 211 | while (hash_iterate(orig_hash, &hashit)) { |
5beef3c9 | 212 | |
b6c35976 | 213 | orig_node = hashit.bucket->data; |
5beef3c9 AL |
214 | |
215 | if (!orig_node->router) | |
216 | continue; | |
217 | ||
218 | if (orig_node->router->tq_avg == 0) | |
219 | continue; | |
220 | ||
221 | batman_count++; | |
222 | ||
223 | addr_to_string(orig_str, orig_node->orig); | |
224 | addr_to_string(router_str, orig_node->router->addr); | |
225 | ||
b665aac8 | 226 | seq_printf(seq, "%-17s (%3i) %17s [%10s]:", |
5beef3c9 AL |
227 | orig_str, orig_node->router->tq_avg, |
228 | router_str, orig_node->router->if_incoming->dev); | |
229 | ||
230 | list_for_each_entry(neigh_node, &orig_node->neigh_list, list) { | |
231 | addr_to_string(orig_str, neigh_node->addr); | |
232 | seq_printf(seq, " %17s (%3i)", | |
233 | orig_str, neigh_node->tq_avg); | |
234 | } | |
235 | ||
236 | seq_printf(seq, "\n"); | |
237 | ||
238 | } | |
239 | ||
e7017195 | 240 | spin_unlock_irqrestore(&orig_hash_lock, flags); |
5beef3c9 AL |
241 | |
242 | if (batman_count == 0) | |
243 | seq_printf(seq, "No batman nodes in range ... \n"); | |
244 | ||
245 | end: | |
246 | return 0; | |
247 | } | |
248 | ||
249 | static int proc_originators_open(struct inode *inode, struct file *file) | |
250 | { | |
251 | return single_open(file, proc_originators_read, NULL); | |
252 | } | |
253 | ||
5beef3c9 AL |
254 | static int proc_transt_local_read(struct seq_file *seq, void *offset) |
255 | { | |
256 | char *buf; | |
257 | ||
258 | buf = kmalloc(4096, GFP_KERNEL); | |
259 | if (!buf) | |
260 | return 0; | |
261 | ||
262 | rcu_read_lock(); | |
263 | if (list_empty(&if_list)) { | |
264 | rcu_read_unlock(); | |
265 | seq_printf(seq, "BATMAN disabled - please specify interfaces to enable it \n"); | |
266 | goto end; | |
267 | } | |
268 | ||
269 | rcu_read_unlock(); | |
270 | ||
271 | seq_printf(seq, "Locally retrieved addresses (from %s) announced via HNA:\n", soft_device->name); | |
272 | ||
273 | hna_local_fill_buffer_text(buf, 4096); | |
274 | seq_printf(seq, "%s", buf); | |
275 | ||
276 | end: | |
277 | kfree(buf); | |
278 | return 0; | |
279 | } | |
280 | ||
281 | static int proc_transt_local_open(struct inode *inode, struct file *file) | |
282 | { | |
283 | return single_open(file, proc_transt_local_read, NULL); | |
284 | } | |
285 | ||
286 | static int proc_transt_global_read(struct seq_file *seq, void *offset) | |
287 | { | |
288 | char *buf; | |
289 | ||
290 | buf = kmalloc(4096, GFP_KERNEL); | |
291 | if (!buf) | |
292 | return 0; | |
293 | ||
294 | rcu_read_lock(); | |
295 | if (list_empty(&if_list)) { | |
296 | rcu_read_unlock(); | |
297 | seq_printf(seq, "BATMAN disabled - please specify interfaces to enable it \n"); | |
298 | goto end; | |
299 | } | |
300 | rcu_read_unlock(); | |
301 | ||
302 | ||
303 | seq_printf(seq, "Globally announced HNAs received via the mesh (translation table):\n"); | |
304 | ||
305 | hna_global_fill_buffer_text(buf, 4096); | |
306 | seq_printf(seq, "%s", buf); | |
307 | ||
308 | end: | |
309 | kfree(buf); | |
310 | return 0; | |
311 | } | |
312 | ||
313 | static int proc_transt_global_open(struct inode *inode, struct file *file) | |
314 | { | |
315 | return single_open(file, proc_transt_global_read, NULL); | |
316 | } | |
317 | ||
e9b76450 ML |
318 | /* setting the mode of the vis server by the user */ |
319 | static ssize_t proc_vis_srv_write(struct file *file, const char __user * buffer, | |
320 | size_t count, loff_t *ppos) | |
5beef3c9 | 321 | { |
e9b76450 ML |
322 | char *vis_mode_string; |
323 | int not_copied = 0; | |
b801fede | 324 | |
e9b76450 | 325 | vis_mode_string = kmalloc(count, GFP_KERNEL); |
5beef3c9 | 326 | |
e9b76450 ML |
327 | if (!vis_mode_string) |
328 | return -ENOMEM; | |
329 | ||
330 | not_copied = copy_from_user(vis_mode_string, buffer, count); | |
331 | vis_mode_string[count - not_copied - 1] = 0; | |
332 | ||
333 | if ((strcmp(vis_mode_string, "client") == 0) || | |
334 | (strcmp(vis_mode_string, "disabled") == 0)) { | |
335 | printk(KERN_INFO "batman-adv:Setting VIS mode to client (disabling vis server)\n"); | |
837b8248 | 336 | atomic_set(&vis_mode, VIS_TYPE_CLIENT_UPDATE); |
e9b76450 ML |
337 | } else if ((strcmp(vis_mode_string, "server") == 0) || |
338 | (strcmp(vis_mode_string, "enabled") == 0)) { | |
339 | printk(KERN_INFO "batman-adv:Setting VIS mode to server (enabling vis server)\n"); | |
837b8248 | 340 | atomic_set(&vis_mode, VIS_TYPE_SERVER_SYNC); |
e9b76450 ML |
341 | } else |
342 | printk(KERN_ERR "batman-adv:Unknown VIS mode: %s\n", | |
343 | vis_mode_string); | |
344 | ||
345 | kfree(vis_mode_string); | |
346 | return count; | |
b801fede AL |
347 | } |
348 | ||
e9b76450 | 349 | static int proc_vis_srv_read(struct seq_file *seq, void *offset) |
b801fede | 350 | { |
837b8248 | 351 | int vis_server = atomic_read(&vis_mode); |
b801fede | 352 | |
e9b76450 | 353 | seq_printf(seq, "[%c] client mode (server disabled) \n", |
837b8248 | 354 | (vis_server == VIS_TYPE_CLIENT_UPDATE) ? 'x' : ' '); |
e9b76450 | 355 | seq_printf(seq, "[%c] server mode (server enabled) \n", |
837b8248 | 356 | (vis_server == VIS_TYPE_SERVER_SYNC) ? 'x' : ' '); |
b801fede | 357 | |
e9b76450 | 358 | return 0; |
5beef3c9 | 359 | } |
5beef3c9 | 360 | |
e9b76450 | 361 | static int proc_vis_srv_open(struct inode *inode, struct file *file) |
5beef3c9 | 362 | { |
e9b76450 | 363 | return single_open(file, proc_vis_srv_read, NULL); |
5beef3c9 AL |
364 | } |
365 | ||
e9b76450 | 366 | static int proc_vis_data_read(struct seq_file *seq, void *offset) |
5beef3c9 | 367 | { |
b6c35976 | 368 | HASHIT(hashit); |
5beef3c9 AL |
369 | struct vis_info *info; |
370 | struct vis_info_entry *entries; | |
b801fede | 371 | HLIST_HEAD(vis_if_list); |
5beef3c9 | 372 | int i; |
5beef3c9 | 373 | char tmp_addr_str[ETH_STR_LEN]; |
e7017195 | 374 | unsigned long flags; |
837b8248 | 375 | int vis_server = atomic_read(&vis_mode); |
5beef3c9 | 376 | |
5beef3c9 | 377 | rcu_read_lock(); |
837b8248 | 378 | if (list_empty(&if_list) || (vis_server == VIS_TYPE_CLIENT_UPDATE)) { |
5beef3c9 | 379 | rcu_read_unlock(); |
5beef3c9 AL |
380 | goto end; |
381 | } | |
382 | ||
383 | rcu_read_unlock(); | |
384 | ||
e7017195 | 385 | spin_lock_irqsave(&vis_hash_lock, flags); |
b6c35976 SW |
386 | while (hash_iterate(vis_hash, &hashit)) { |
387 | info = hashit.bucket->data; | |
5beef3c9 AL |
388 | entries = (struct vis_info_entry *) |
389 | ((char *)info + sizeof(struct vis_info)); | |
b801fede AL |
390 | addr_to_string(tmp_addr_str, info->packet.vis_orig); |
391 | seq_printf(seq, "%s,", tmp_addr_str); | |
5beef3c9 AL |
392 | |
393 | for (i = 0; i < info->packet.entries; i++) { | |
b801fede AL |
394 | proc_vis_read_entry(seq, &entries[i], &vis_if_list, |
395 | info->packet.vis_orig); | |
5beef3c9 AL |
396 | } |
397 | ||
b801fede AL |
398 | /* add primary/secondary records */ |
399 | proc_vis_read_prim_sec(seq, &vis_if_list); | |
400 | seq_printf(seq, "\n"); | |
5beef3c9 | 401 | } |
e7017195 | 402 | spin_unlock_irqrestore(&vis_hash_lock, flags); |
5beef3c9 | 403 | |
5beef3c9 AL |
404 | end: |
405 | return 0; | |
406 | } | |
407 | ||
e9b76450 | 408 | static int proc_vis_data_open(struct inode *inode, struct file *file) |
5beef3c9 | 409 | { |
e9b76450 | 410 | return single_open(file, proc_vis_data_read, NULL); |
5beef3c9 AL |
411 | } |
412 | ||
5beef3c9 AL |
413 | static int proc_aggr_read(struct seq_file *seq, void *offset) |
414 | { | |
415 | seq_printf(seq, "%i\n", atomic_read(&aggregation_enabled)); | |
416 | ||
417 | return 0; | |
418 | } | |
419 | ||
420 | static ssize_t proc_aggr_write(struct file *file, const char __user *buffer, | |
421 | size_t count, loff_t *ppos) | |
422 | { | |
423 | char *aggr_string; | |
424 | int not_copied = 0; | |
425 | unsigned long aggregation_enabled_tmp; | |
4230020c | 426 | int retval; |
5beef3c9 AL |
427 | |
428 | aggr_string = kmalloc(count, GFP_KERNEL); | |
429 | ||
430 | if (!aggr_string) | |
431 | return -ENOMEM; | |
432 | ||
433 | not_copied = copy_from_user(aggr_string, buffer, count); | |
434 | aggr_string[count - not_copied - 1] = 0; | |
435 | ||
4230020c | 436 | retval = strict_strtoul(aggr_string, 10, &aggregation_enabled_tmp); |
5beef3c9 | 437 | |
4230020c | 438 | if (retval || aggregation_enabled_tmp > 1) { |
bad2239e | 439 | printk(KERN_ERR "batman-adv:Aggregation can only be enabled (1) or disabled (0), given value: %li\n", aggregation_enabled_tmp); |
4230020c LL |
440 | } else { |
441 | printk(KERN_INFO "batman-adv:Changing aggregation from: %s (%i) to: %s (%li)\n", | |
442 | (atomic_read(&aggregation_enabled) == 1 ? | |
443 | "enabled" : "disabled"), | |
444 | atomic_read(&aggregation_enabled), | |
445 | (aggregation_enabled_tmp == 1 ? "enabled" : "disabled"), | |
446 | aggregation_enabled_tmp); | |
447 | atomic_set(&aggregation_enabled, | |
448 | (unsigned)aggregation_enabled_tmp); | |
5beef3c9 AL |
449 | } |
450 | ||
5beef3c9 AL |
451 | kfree(aggr_string); |
452 | return count; | |
453 | } | |
454 | ||
455 | static int proc_aggr_open(struct inode *inode, struct file *file) | |
456 | { | |
457 | return single_open(file, proc_aggr_read, NULL); | |
458 | } | |
459 | ||
460 | /* satisfying different prototypes ... */ | |
461 | static ssize_t proc_dummy_write(struct file *file, const char __user *buffer, | |
462 | size_t count, loff_t *ppos) | |
463 | { | |
464 | return count; | |
465 | } | |
466 | ||
467 | static const struct file_operations proc_aggr_fops = { | |
468 | .owner = THIS_MODULE, | |
469 | .open = proc_aggr_open, | |
470 | .read = seq_read, | |
471 | .write = proc_aggr_write, | |
472 | .llseek = seq_lseek, | |
473 | .release = single_release, | |
474 | }; | |
475 | ||
e9b76450 | 476 | static const struct file_operations proc_vis_srv_fops = { |
5beef3c9 | 477 | .owner = THIS_MODULE, |
e9b76450 | 478 | .open = proc_vis_srv_open, |
5beef3c9 | 479 | .read = seq_read, |
e9b76450 ML |
480 | .write = proc_vis_srv_write, |
481 | .llseek = seq_lseek, | |
482 | .release = single_release, | |
483 | }; | |
484 | ||
485 | static const struct file_operations proc_vis_data_fops = { | |
486 | .owner = THIS_MODULE, | |
487 | .open = proc_vis_data_open, | |
488 | .read = seq_read, | |
489 | .write = proc_dummy_write, | |
5beef3c9 AL |
490 | .llseek = seq_lseek, |
491 | .release = single_release, | |
492 | }; | |
493 | ||
494 | static const struct file_operations proc_originators_fops = { | |
495 | .owner = THIS_MODULE, | |
496 | .open = proc_originators_open, | |
497 | .read = seq_read, | |
498 | .write = proc_dummy_write, | |
499 | .llseek = seq_lseek, | |
500 | .release = single_release, | |
501 | }; | |
502 | ||
503 | static const struct file_operations proc_transt_local_fops = { | |
504 | .owner = THIS_MODULE, | |
505 | .open = proc_transt_local_open, | |
506 | .read = seq_read, | |
507 | .write = proc_dummy_write, | |
508 | .llseek = seq_lseek, | |
509 | .release = single_release, | |
510 | }; | |
511 | ||
512 | static const struct file_operations proc_transt_global_fops = { | |
513 | .owner = THIS_MODULE, | |
514 | .open = proc_transt_global_open, | |
515 | .read = seq_read, | |
516 | .write = proc_dummy_write, | |
517 | .llseek = seq_lseek, | |
518 | .release = single_release, | |
519 | }; | |
520 | ||
5beef3c9 AL |
521 | static const struct file_operations proc_interfaces_fops = { |
522 | .owner = THIS_MODULE, | |
523 | .open = proc_interfaces_open, | |
524 | .read = seq_read, | |
525 | .write = proc_interfaces_write, | |
526 | .llseek = seq_lseek, | |
527 | .release = single_release, | |
528 | }; | |
529 | ||
530 | static const struct file_operations proc_orig_interval_fops = { | |
531 | .owner = THIS_MODULE, | |
532 | .open = proc_orig_interval_open, | |
533 | .read = seq_read, | |
534 | .write = proc_orig_interval_write, | |
535 | .llseek = seq_lseek, | |
536 | .release = single_release, | |
537 | }; | |
538 | ||
539 | void cleanup_procfs(void) | |
540 | { | |
541 | if (proc_transt_global_file) | |
542 | remove_proc_entry(PROC_FILE_TRANST_GLOBAL, proc_batman_dir); | |
543 | ||
544 | if (proc_transt_local_file) | |
545 | remove_proc_entry(PROC_FILE_TRANST_LOCAL, proc_batman_dir); | |
546 | ||
5beef3c9 AL |
547 | if (proc_originators_file) |
548 | remove_proc_entry(PROC_FILE_ORIGINATORS, proc_batman_dir); | |
549 | ||
550 | if (proc_orig_interval_file) | |
551 | remove_proc_entry(PROC_FILE_ORIG_INTERVAL, proc_batman_dir); | |
552 | ||
553 | if (proc_interface_file) | |
554 | remove_proc_entry(PROC_FILE_INTERFACES, proc_batman_dir); | |
555 | ||
e9b76450 ML |
556 | if (proc_vis_data_file) |
557 | remove_proc_entry(PROC_FILE_VIS_DATA, proc_batman_dir); | |
558 | ||
559 | if (proc_vis_srv_file) | |
560 | remove_proc_entry(PROC_FILE_VIS_SRV, proc_batman_dir); | |
5beef3c9 | 561 | |
5beef3c9 AL |
562 | if (proc_aggr_file) |
563 | remove_proc_entry(PROC_FILE_AGGR, proc_batman_dir); | |
564 | ||
565 | if (proc_batman_dir) | |
566 | #ifdef __NET_NET_NAMESPACE_H | |
567 | remove_proc_entry(PROC_ROOT_DIR, init_net.proc_net); | |
568 | #else | |
569 | remove_proc_entry(PROC_ROOT_DIR, proc_net); | |
570 | #endif | |
571 | } | |
572 | ||
573 | int setup_procfs(void) | |
574 | { | |
575 | #ifdef __NET_NET_NAMESPACE_H | |
576 | proc_batman_dir = proc_mkdir(PROC_ROOT_DIR, init_net.proc_net); | |
577 | #else | |
578 | proc_batman_dir = proc_mkdir(PROC_ROOT_DIR, proc_net); | |
579 | #endif | |
580 | ||
581 | if (!proc_batman_dir) { | |
582 | printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s' folder failed\n", PROC_ROOT_DIR); | |
583 | return -EFAULT; | |
584 | } | |
585 | ||
586 | proc_interface_file = create_proc_entry(PROC_FILE_INTERFACES, | |
587 | S_IWUSR | S_IRUGO, | |
588 | proc_batman_dir); | |
589 | if (proc_interface_file) { | |
590 | proc_interface_file->proc_fops = &proc_interfaces_fops; | |
591 | } else { | |
592 | printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_INTERFACES); | |
593 | cleanup_procfs(); | |
594 | return -EFAULT; | |
595 | } | |
596 | ||
597 | proc_orig_interval_file = create_proc_entry(PROC_FILE_ORIG_INTERVAL, | |
598 | S_IWUSR | S_IRUGO, | |
599 | proc_batman_dir); | |
600 | if (proc_orig_interval_file) { | |
601 | proc_orig_interval_file->proc_fops = &proc_orig_interval_fops; | |
602 | } else { | |
603 | printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_ORIG_INTERVAL); | |
604 | cleanup_procfs(); | |
605 | return -EFAULT; | |
606 | } | |
607 | ||
5beef3c9 AL |
608 | proc_originators_file = create_proc_entry(PROC_FILE_ORIGINATORS, |
609 | S_IRUGO, proc_batman_dir); | |
610 | if (proc_originators_file) { | |
611 | proc_originators_file->proc_fops = &proc_originators_fops; | |
612 | } else { | |
613 | printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_ORIGINATORS); | |
614 | cleanup_procfs(); | |
615 | return -EFAULT; | |
616 | } | |
617 | ||
5beef3c9 AL |
618 | proc_transt_local_file = create_proc_entry(PROC_FILE_TRANST_LOCAL, |
619 | S_IRUGO, proc_batman_dir); | |
620 | if (proc_transt_local_file) { | |
621 | proc_transt_local_file->proc_fops = &proc_transt_local_fops; | |
622 | } else { | |
623 | printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_TRANST_LOCAL); | |
624 | cleanup_procfs(); | |
625 | return -EFAULT; | |
626 | } | |
627 | ||
628 | proc_transt_global_file = create_proc_entry(PROC_FILE_TRANST_GLOBAL, | |
629 | S_IRUGO, proc_batman_dir); | |
630 | if (proc_transt_global_file) { | |
631 | proc_transt_global_file->proc_fops = &proc_transt_global_fops; | |
632 | } else { | |
633 | printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_TRANST_GLOBAL); | |
634 | cleanup_procfs(); | |
635 | return -EFAULT; | |
636 | } | |
637 | ||
e9b76450 ML |
638 | proc_vis_srv_file = create_proc_entry(PROC_FILE_VIS_SRV, |
639 | S_IWUSR | S_IRUGO, | |
640 | proc_batman_dir); | |
641 | if (proc_vis_srv_file) { | |
642 | proc_vis_srv_file->proc_fops = &proc_vis_srv_fops; | |
643 | } else { | |
644 | printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_VIS_SRV); | |
645 | cleanup_procfs(); | |
646 | return -EFAULT; | |
647 | } | |
648 | ||
649 | proc_vis_data_file = create_proc_entry(PROC_FILE_VIS_DATA, S_IRUGO, | |
5beef3c9 | 650 | proc_batman_dir); |
e9b76450 ML |
651 | if (proc_vis_data_file) { |
652 | proc_vis_data_file->proc_fops = &proc_vis_data_fops; | |
5beef3c9 | 653 | } else { |
e9b76450 | 654 | printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_VIS_DATA); |
5beef3c9 AL |
655 | cleanup_procfs(); |
656 | return -EFAULT; | |
657 | } | |
658 | ||
5beef3c9 AL |
659 | proc_aggr_file = create_proc_entry(PROC_FILE_AGGR, S_IWUSR | S_IRUGO, |
660 | proc_batman_dir); | |
661 | if (proc_aggr_file) { | |
662 | proc_aggr_file->proc_fops = &proc_aggr_fops; | |
663 | } else { | |
664 | printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_AGGR); | |
665 | cleanup_procfs(); | |
666 | return -EFAULT; | |
667 | } | |
668 | ||
669 | return 0; | |
670 | } |