aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv/sysfs.c
diff options
context:
space:
mode:
authorSven Eckelmann <sven@narfation.org>2012-06-10 17:58:51 -0400
committerAntonio Quartulli <ordex@autistici.org>2012-07-01 16:47:22 -0400
commitb706b13b6cfde22d1f4adc540fd89426247c1e3e (patch)
treec729d6580d4a249f97317f210078b30db821c8cb /net/batman-adv/sysfs.c
parenta8a0a62d1f173620f150830db437ddd65a103d49 (diff)
batman-adv: Remove bat_ prefix from bat_{debugfs, sysfs}.{c, h}
The "bat_" prefix in the source files implementing the batman-adv sysfs and debugfs interface doesn't have a special meaning and are only used by these files and files that implement the actual B.A.T.M.A.N. path finding algorithm. The prefix is better suited to mark files that are used to implement the main part of the path finding. All other files should not use it and therefore gets renamed. Signed-off-by: Sven Eckelmann <sven@narfation.org>
Diffstat (limited to 'net/batman-adv/sysfs.c')
-rw-r--r--net/batman-adv/sysfs.c787
1 files changed, 787 insertions, 0 deletions
diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c
new file mode 100644
index 000000000000..66518c75c217
--- /dev/null
+++ b/net/batman-adv/sysfs.c
@@ -0,0 +1,787 @@
1/* Copyright (C) 2010-2012 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, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA
18 */
19
20#include "main.h"
21#include "sysfs.h"
22#include "translation-table.h"
23#include "originator.h"
24#include "hard-interface.h"
25#include "gateway_common.h"
26#include "gateway_client.h"
27#include "vis.h"
28
29static struct net_device *batadv_kobj_to_netdev(struct kobject *obj)
30{
31 struct device *dev = container_of(obj->parent, struct device, kobj);
32 return to_net_dev(dev);
33}
34
35static struct batadv_priv *batadv_kobj_to_batpriv(struct kobject *obj)
36{
37 struct net_device *net_dev = batadv_kobj_to_netdev(obj);
38 return netdev_priv(net_dev);
39}
40
41#define BATADV_UEV_TYPE_VAR "BATTYPE="
42#define BATADV_UEV_ACTION_VAR "BATACTION="
43#define BATADV_UEV_DATA_VAR "BATDATA="
44
45static char *batadv_uev_action_str[] = {
46 "add",
47 "del",
48 "change"
49};
50
51static char *batadv_uev_type_str[] = {
52 "gw"
53};
54
55/* Use this, if you have customized show and store functions */
56#define BATADV_ATTR(_name, _mode, _show, _store) \
57struct batadv_attribute batadv_attr_##_name = { \
58 .attr = {.name = __stringify(_name), \
59 .mode = _mode }, \
60 .show = _show, \
61 .store = _store, \
62};
63
64#define BATADV_ATTR_SIF_STORE_BOOL(_name, _post_func) \
65ssize_t batadv_store_##_name(struct kobject *kobj, \
66 struct attribute *attr, char *buff, \
67 size_t count) \
68{ \
69 struct net_device *net_dev = batadv_kobj_to_netdev(kobj); \
70 struct batadv_priv *bat_priv = netdev_priv(net_dev); \
71 return __batadv_store_bool_attr(buff, count, _post_func, attr, \
72 &bat_priv->_name, net_dev); \
73}
74
75#define BATADV_ATTR_SIF_SHOW_BOOL(_name) \
76ssize_t batadv_show_##_name(struct kobject *kobj, \
77 struct attribute *attr, char *buff) \
78{ \
79 struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj); \
80 return sprintf(buff, "%s\n", \
81 atomic_read(&bat_priv->_name) == 0 ? \
82 "disabled" : "enabled"); \
83} \
84
85/* Use this, if you are going to turn a [name] in the soft-interface
86 * (bat_priv) on or off
87 */
88#define BATADV_ATTR_SIF_BOOL(_name, _mode, _post_func) \
89 static BATADV_ATTR_SIF_STORE_BOOL(_name, _post_func) \
90 static BATADV_ATTR_SIF_SHOW_BOOL(_name) \
91 static BATADV_ATTR(_name, _mode, batadv_show_##_name, \
92 batadv_store_##_name)
93
94
95#define BATADV_ATTR_SIF_STORE_UINT(_name, _min, _max, _post_func) \
96ssize_t batadv_store_##_name(struct kobject *kobj, \
97 struct attribute *attr, char *buff, \
98 size_t count) \
99{ \
100 struct net_device *net_dev = batadv_kobj_to_netdev(kobj); \
101 struct batadv_priv *bat_priv = netdev_priv(net_dev); \
102 return __batadv_store_uint_attr(buff, count, _min, _max, \
103 _post_func, attr, \
104 &bat_priv->_name, net_dev); \
105}
106
107#define BATADV_ATTR_SIF_SHOW_UINT(_name) \
108ssize_t batadv_show_##_name(struct kobject *kobj, \
109 struct attribute *attr, char *buff) \
110{ \
111 struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj); \
112 return sprintf(buff, "%i\n", atomic_read(&bat_priv->_name)); \
113} \
114
115/* Use this, if you are going to set [name] in the soft-interface
116 * (bat_priv) to an unsigned integer value
117 */
118#define BATADV_ATTR_SIF_UINT(_name, _mode, _min, _max, _post_func) \
119 static BATADV_ATTR_SIF_STORE_UINT(_name, _min, _max, _post_func)\
120 static BATADV_ATTR_SIF_SHOW_UINT(_name) \
121 static BATADV_ATTR(_name, _mode, batadv_show_##_name, \
122 batadv_store_##_name)
123
124
125#define BATADV_ATTR_HIF_STORE_UINT(_name, _min, _max, _post_func) \
126ssize_t batadv_store_##_name(struct kobject *kobj, \
127 struct attribute *attr, char *buff, \
128 size_t count) \
129{ \
130 struct net_device *net_dev = batadv_kobj_to_netdev(kobj); \
131 struct batadv_hard_iface *hard_iface; \
132 ssize_t length; \
133 \
134 hard_iface = batadv_hardif_get_by_netdev(net_dev); \
135 if (!hard_iface) \
136 return 0; \
137 \
138 length = __batadv_store_uint_attr(buff, count, _min, _max, \
139 _post_func, attr, \
140 &hard_iface->_name, net_dev); \
141 \
142 batadv_hardif_free_ref(hard_iface); \
143 return length; \
144}
145
146#define BATADV_ATTR_HIF_SHOW_UINT(_name) \
147ssize_t batadv_show_##_name(struct kobject *kobj, \
148 struct attribute *attr, char *buff) \
149{ \
150 struct net_device *net_dev = batadv_kobj_to_netdev(kobj); \
151 struct batadv_hard_iface *hard_iface; \
152 ssize_t length; \
153 \
154 hard_iface = batadv_hardif_get_by_netdev(net_dev); \
155 if (!hard_iface) \
156 return 0; \
157 \
158 length = sprintf(buff, "%i\n", atomic_read(&hard_iface->_name));\
159 \
160 batadv_hardif_free_ref(hard_iface); \
161 return length; \
162}
163
164/* Use this, if you are going to set [name] in hard_iface to an
165 * unsigned integer value
166 */
167#define BATADV_ATTR_HIF_UINT(_name, _mode, _min, _max, _post_func) \
168 static BATADV_ATTR_HIF_STORE_UINT(_name, _min, _max, _post_func)\
169 static BATADV_ATTR_HIF_SHOW_UINT(_name) \
170 static BATADV_ATTR(_name, _mode, batadv_show_##_name, \
171 batadv_store_##_name)
172
173
174static int batadv_store_bool_attr(char *buff, size_t count,
175 struct net_device *net_dev,
176 const char *attr_name, atomic_t *attr)
177{
178 int enabled = -1;
179
180 if (buff[count - 1] == '\n')
181 buff[count - 1] = '\0';
182
183 if ((strncmp(buff, "1", 2) == 0) ||
184 (strncmp(buff, "enable", 7) == 0) ||
185 (strncmp(buff, "enabled", 8) == 0))
186 enabled = 1;
187
188 if ((strncmp(buff, "0", 2) == 0) ||
189 (strncmp(buff, "disable", 8) == 0) ||
190 (strncmp(buff, "disabled", 9) == 0))
191 enabled = 0;
192
193 if (enabled < 0) {
194 batadv_info(net_dev, "%s: Invalid parameter received: %s\n",
195 attr_name, buff);
196 return -EINVAL;
197 }
198
199 if (atomic_read(attr) == enabled)
200 return count;
201
202 batadv_info(net_dev, "%s: Changing from: %s to: %s\n", attr_name,
203 atomic_read(attr) == 1 ? "enabled" : "disabled",
204 enabled == 1 ? "enabled" : "disabled");
205
206 atomic_set(attr, (unsigned int)enabled);
207 return count;
208}
209
210static inline ssize_t
211__batadv_store_bool_attr(char *buff, size_t count,
212 void (*post_func)(struct net_device *),
213 struct attribute *attr,
214 atomic_t *attr_store, struct net_device *net_dev)
215{
216 int ret;
217
218 ret = batadv_store_bool_attr(buff, count, net_dev, attr->name,
219 attr_store);
220 if (post_func && ret)
221 post_func(net_dev);
222
223 return ret;
224}
225
226static int batadv_store_uint_attr(const char *buff, size_t count,
227 struct net_device *net_dev,
228 const char *attr_name,
229 unsigned int min, unsigned int max,
230 atomic_t *attr)
231{
232 unsigned long uint_val;
233 int ret;
234
235 ret = kstrtoul(buff, 10, &uint_val);
236 if (ret) {
237 batadv_info(net_dev, "%s: Invalid parameter received: %s\n",
238 attr_name, buff);
239 return -EINVAL;
240 }
241
242 if (uint_val < min) {
243 batadv_info(net_dev, "%s: Value is too small: %lu min: %u\n",
244 attr_name, uint_val, min);
245 return -EINVAL;
246 }
247
248 if (uint_val > max) {
249 batadv_info(net_dev, "%s: Value is too big: %lu max: %u\n",
250 attr_name, uint_val, max);
251 return -EINVAL;
252 }
253
254 if (atomic_read(attr) == uint_val)
255 return count;
256
257 batadv_info(net_dev, "%s: Changing from: %i to: %lu\n",
258 attr_name, atomic_read(attr), uint_val);
259
260 atomic_set(attr, uint_val);
261 return count;
262}
263
264static inline ssize_t
265__batadv_store_uint_attr(const char *buff, size_t count,
266 int min, int max,
267 void (*post_func)(struct net_device *),
268 const struct attribute *attr,
269 atomic_t *attr_store, struct net_device *net_dev)
270{
271 int ret;
272
273 ret = batadv_store_uint_attr(buff, count, net_dev, attr->name, min, max,
274 attr_store);
275 if (post_func && ret)
276 post_func(net_dev);
277
278 return ret;
279}
280
281static ssize_t batadv_show_vis_mode(struct kobject *kobj,
282 struct attribute *attr, char *buff)
283{
284 struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj);
285 int vis_mode = atomic_read(&bat_priv->vis_mode);
286 const char *mode;
287
288 if (vis_mode == BATADV_VIS_TYPE_CLIENT_UPDATE)
289 mode = "client";
290 else
291 mode = "server";
292
293 return sprintf(buff, "%s\n", mode);
294}
295
296static ssize_t batadv_store_vis_mode(struct kobject *kobj,
297 struct attribute *attr, char *buff,
298 size_t count)
299{
300 struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
301 struct batadv_priv *bat_priv = netdev_priv(net_dev);
302 unsigned long val;
303 int ret, vis_mode_tmp = -1;
304 const char *old_mode, *new_mode;
305
306 ret = kstrtoul(buff, 10, &val);
307
308 if (((count == 2) && (!ret) &&
309 (val == BATADV_VIS_TYPE_CLIENT_UPDATE)) ||
310 (strncmp(buff, "client", 6) == 0) ||
311 (strncmp(buff, "off", 3) == 0))
312 vis_mode_tmp = BATADV_VIS_TYPE_CLIENT_UPDATE;
313
314 if (((count == 2) && (!ret) &&
315 (val == BATADV_VIS_TYPE_SERVER_SYNC)) ||
316 (strncmp(buff, "server", 6) == 0))
317 vis_mode_tmp = BATADV_VIS_TYPE_SERVER_SYNC;
318
319 if (vis_mode_tmp < 0) {
320 if (buff[count - 1] == '\n')
321 buff[count - 1] = '\0';
322
323 batadv_info(net_dev,
324 "Invalid parameter for 'vis mode' setting received: %s\n",
325 buff);
326 return -EINVAL;
327 }
328
329 if (atomic_read(&bat_priv->vis_mode) == vis_mode_tmp)
330 return count;
331
332 if (atomic_read(&bat_priv->vis_mode) == BATADV_VIS_TYPE_CLIENT_UPDATE)
333 old_mode = "client";
334 else
335 old_mode = "server";
336
337 if (vis_mode_tmp == BATADV_VIS_TYPE_CLIENT_UPDATE)
338 new_mode = "client";
339 else
340 new_mode = "server";
341
342 batadv_info(net_dev, "Changing vis mode from: %s to: %s\n", old_mode,
343 new_mode);
344
345 atomic_set(&bat_priv->vis_mode, (unsigned int)vis_mode_tmp);
346 return count;
347}
348
349static ssize_t batadv_show_bat_algo(struct kobject *kobj,
350 struct attribute *attr, char *buff)
351{
352 struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj);
353 return sprintf(buff, "%s\n", bat_priv->bat_algo_ops->name);
354}
355
356static void batadv_post_gw_deselect(struct net_device *net_dev)
357{
358 struct batadv_priv *bat_priv = netdev_priv(net_dev);
359 batadv_gw_deselect(bat_priv);
360}
361
362static ssize_t batadv_show_gw_mode(struct kobject *kobj, struct attribute *attr,
363 char *buff)
364{
365 struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj);
366 int bytes_written;
367
368 switch (atomic_read(&bat_priv->gw_mode)) {
369 case BATADV_GW_MODE_CLIENT:
370 bytes_written = sprintf(buff, "%s\n",
371 BATADV_GW_MODE_CLIENT_NAME);
372 break;
373 case BATADV_GW_MODE_SERVER:
374 bytes_written = sprintf(buff, "%s\n",
375 BATADV_GW_MODE_SERVER_NAME);
376 break;
377 default:
378 bytes_written = sprintf(buff, "%s\n",
379 BATADV_GW_MODE_OFF_NAME);
380 break;
381 }
382
383 return bytes_written;
384}
385
386static ssize_t batadv_store_gw_mode(struct kobject *kobj,
387 struct attribute *attr, char *buff,
388 size_t count)
389{
390 struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
391 struct batadv_priv *bat_priv = netdev_priv(net_dev);
392 char *curr_gw_mode_str;
393 int gw_mode_tmp = -1;
394
395 if (buff[count - 1] == '\n')
396 buff[count - 1] = '\0';
397
398 if (strncmp(buff, BATADV_GW_MODE_OFF_NAME,
399 strlen(BATADV_GW_MODE_OFF_NAME)) == 0)
400 gw_mode_tmp = BATADV_GW_MODE_OFF;
401
402 if (strncmp(buff, BATADV_GW_MODE_CLIENT_NAME,
403 strlen(BATADV_GW_MODE_CLIENT_NAME)) == 0)
404 gw_mode_tmp = BATADV_GW_MODE_CLIENT;
405
406 if (strncmp(buff, BATADV_GW_MODE_SERVER_NAME,
407 strlen(BATADV_GW_MODE_SERVER_NAME)) == 0)
408 gw_mode_tmp = BATADV_GW_MODE_SERVER;
409
410 if (gw_mode_tmp < 0) {
411 batadv_info(net_dev,
412 "Invalid parameter for 'gw mode' setting received: %s\n",
413 buff);
414 return -EINVAL;
415 }
416
417 if (atomic_read(&bat_priv->gw_mode) == gw_mode_tmp)
418 return count;
419
420 switch (atomic_read(&bat_priv->gw_mode)) {
421 case BATADV_GW_MODE_CLIENT:
422 curr_gw_mode_str = BATADV_GW_MODE_CLIENT_NAME;
423 break;
424 case BATADV_GW_MODE_SERVER:
425 curr_gw_mode_str = BATADV_GW_MODE_SERVER_NAME;
426 break;
427 default:
428 curr_gw_mode_str = BATADV_GW_MODE_OFF_NAME;
429 break;
430 }
431
432 batadv_info(net_dev, "Changing gw mode from: %s to: %s\n",
433 curr_gw_mode_str, buff);
434
435 batadv_gw_deselect(bat_priv);
436 atomic_set(&bat_priv->gw_mode, (unsigned int)gw_mode_tmp);
437 return count;
438}
439
440static ssize_t batadv_show_gw_bwidth(struct kobject *kobj,
441 struct attribute *attr, char *buff)
442{
443 struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj);
444 int down, up;
445 int gw_bandwidth = atomic_read(&bat_priv->gw_bandwidth);
446
447 batadv_gw_bandwidth_to_kbit(gw_bandwidth, &down, &up);
448 return sprintf(buff, "%i%s/%i%s\n",
449 (down > 2048 ? down / 1024 : down),
450 (down > 2048 ? "MBit" : "KBit"),
451 (up > 2048 ? up / 1024 : up),
452 (up > 2048 ? "MBit" : "KBit"));
453}
454
455static ssize_t batadv_store_gw_bwidth(struct kobject *kobj,
456 struct attribute *attr, char *buff,
457 size_t count)
458{
459 struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
460
461 if (buff[count - 1] == '\n')
462 buff[count - 1] = '\0';
463
464 return batadv_gw_bandwidth_set(net_dev, buff, count);
465}
466
467BATADV_ATTR_SIF_BOOL(aggregated_ogms, S_IRUGO | S_IWUSR, NULL);
468BATADV_ATTR_SIF_BOOL(bonding, S_IRUGO | S_IWUSR, NULL);
469#ifdef CONFIG_BATMAN_ADV_BLA
470BATADV_ATTR_SIF_BOOL(bridge_loop_avoidance, S_IRUGO | S_IWUSR, NULL);
471#endif
472BATADV_ATTR_SIF_BOOL(fragmentation, S_IRUGO | S_IWUSR, batadv_update_min_mtu);
473BATADV_ATTR_SIF_BOOL(ap_isolation, S_IRUGO | S_IWUSR, NULL);
474static BATADV_ATTR(vis_mode, S_IRUGO | S_IWUSR, batadv_show_vis_mode,
475 batadv_store_vis_mode);
476static BATADV_ATTR(routing_algo, S_IRUGO, batadv_show_bat_algo, NULL);
477static BATADV_ATTR(gw_mode, S_IRUGO | S_IWUSR, batadv_show_gw_mode,
478 batadv_store_gw_mode);
479BATADV_ATTR_SIF_UINT(orig_interval, S_IRUGO | S_IWUSR, 2 * BATADV_JITTER,
480 INT_MAX, NULL);
481BATADV_ATTR_SIF_UINT(hop_penalty, S_IRUGO | S_IWUSR, 0, BATADV_TQ_MAX_VALUE,
482 NULL);
483BATADV_ATTR_SIF_UINT(gw_sel_class, S_IRUGO | S_IWUSR, 1, BATADV_TQ_MAX_VALUE,
484 batadv_post_gw_deselect);
485static BATADV_ATTR(gw_bandwidth, S_IRUGO | S_IWUSR, batadv_show_gw_bwidth,
486 batadv_store_gw_bwidth);
487#ifdef CONFIG_BATMAN_ADV_DEBUG
488BATADV_ATTR_SIF_UINT(log_level, S_IRUGO | S_IWUSR, 0, BATADV_DBG_ALL, NULL);
489#endif
490
491static struct batadv_attribute *batadv_mesh_attrs[] = {
492 &batadv_attr_aggregated_ogms,
493 &batadv_attr_bonding,
494#ifdef CONFIG_BATMAN_ADV_BLA
495 &batadv_attr_bridge_loop_avoidance,
496#endif
497 &batadv_attr_fragmentation,
498 &batadv_attr_ap_isolation,
499 &batadv_attr_vis_mode,
500 &batadv_attr_routing_algo,
501 &batadv_attr_gw_mode,
502 &batadv_attr_orig_interval,
503 &batadv_attr_hop_penalty,
504 &batadv_attr_gw_sel_class,
505 &batadv_attr_gw_bandwidth,
506#ifdef CONFIG_BATMAN_ADV_DEBUG
507 &batadv_attr_log_level,
508#endif
509 NULL,
510};
511
512int batadv_sysfs_add_meshif(struct net_device *dev)
513{
514 struct kobject *batif_kobject = &dev->dev.kobj;
515 struct batadv_priv *bat_priv = netdev_priv(dev);
516 struct batadv_attribute **bat_attr;
517 int err;
518
519 bat_priv->mesh_obj = kobject_create_and_add(BATADV_SYSFS_IF_MESH_SUBDIR,
520 batif_kobject);
521 if (!bat_priv->mesh_obj) {
522 batadv_err(dev, "Can't add sysfs directory: %s/%s\n", dev->name,
523 BATADV_SYSFS_IF_MESH_SUBDIR);
524 goto out;
525 }
526
527 for (bat_attr = batadv_mesh_attrs; *bat_attr; ++bat_attr) {
528 err = sysfs_create_file(bat_priv->mesh_obj,
529 &((*bat_attr)->attr));
530 if (err) {
531 batadv_err(dev, "Can't add sysfs file: %s/%s/%s\n",
532 dev->name, BATADV_SYSFS_IF_MESH_SUBDIR,
533 ((*bat_attr)->attr).name);
534 goto rem_attr;
535 }
536 }
537
538 return 0;
539
540rem_attr:
541 for (bat_attr = batadv_mesh_attrs; *bat_attr; ++bat_attr)
542 sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr));
543
544 kobject_put(bat_priv->mesh_obj);
545 bat_priv->mesh_obj = NULL;
546out:
547 return -ENOMEM;
548}
549
550void batadv_sysfs_del_meshif(struct net_device *dev)
551{
552 struct batadv_priv *bat_priv = netdev_priv(dev);
553 struct batadv_attribute **bat_attr;
554
555 for (bat_attr = batadv_mesh_attrs; *bat_attr; ++bat_attr)
556 sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr));
557
558 kobject_put(bat_priv->mesh_obj);
559 bat_priv->mesh_obj = NULL;
560}
561
562static ssize_t batadv_show_mesh_iface(struct kobject *kobj,
563 struct attribute *attr, char *buff)
564{
565 struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
566 struct batadv_hard_iface *hard_iface;
567 ssize_t length;
568 const char *ifname;
569
570 hard_iface = batadv_hardif_get_by_netdev(net_dev);
571 if (!hard_iface)
572 return 0;
573
574 if (hard_iface->if_status == BATADV_IF_NOT_IN_USE)
575 ifname = "none";
576 else
577 ifname = hard_iface->soft_iface->name;
578
579 length = sprintf(buff, "%s\n", ifname);
580
581 batadv_hardif_free_ref(hard_iface);
582
583 return length;
584}
585
586static ssize_t batadv_store_mesh_iface(struct kobject *kobj,
587 struct attribute *attr, char *buff,
588 size_t count)
589{
590 struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
591 struct batadv_hard_iface *hard_iface;
592 int status_tmp = -1;
593 int ret = count;
594
595 hard_iface = batadv_hardif_get_by_netdev(net_dev);
596 if (!hard_iface)
597 return count;
598
599 if (buff[count - 1] == '\n')
600 buff[count - 1] = '\0';
601
602 if (strlen(buff) >= IFNAMSIZ) {
603 pr_err("Invalid parameter for 'mesh_iface' setting received: interface name too long '%s'\n",
604 buff);
605 batadv_hardif_free_ref(hard_iface);
606 return -EINVAL;
607 }
608
609 if (strncmp(buff, "none", 4) == 0)
610 status_tmp = BATADV_IF_NOT_IN_USE;
611 else
612 status_tmp = BATADV_IF_I_WANT_YOU;
613
614 if (hard_iface->if_status == status_tmp)
615 goto out;
616
617 if ((hard_iface->soft_iface) &&
618 (strncmp(hard_iface->soft_iface->name, buff, IFNAMSIZ) == 0))
619 goto out;
620
621 if (!rtnl_trylock()) {
622 ret = -ERESTARTSYS;
623 goto out;
624 }
625
626 if (status_tmp == BATADV_IF_NOT_IN_USE) {
627 batadv_hardif_disable_interface(hard_iface);
628 goto unlock;
629 }
630
631 /* if the interface already is in use */
632 if (hard_iface->if_status != BATADV_IF_NOT_IN_USE)
633 batadv_hardif_disable_interface(hard_iface);
634
635 ret = batadv_hardif_enable_interface(hard_iface, buff);
636
637unlock:
638 rtnl_unlock();
639out:
640 batadv_hardif_free_ref(hard_iface);
641 return ret;
642}
643
644static ssize_t batadv_show_iface_status(struct kobject *kobj,
645 struct attribute *attr, char *buff)
646{
647 struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
648 struct batadv_hard_iface *hard_iface;
649 ssize_t length;
650
651 hard_iface = batadv_hardif_get_by_netdev(net_dev);
652 if (!hard_iface)
653 return 0;
654
655 switch (hard_iface->if_status) {
656 case BATADV_IF_TO_BE_REMOVED:
657 length = sprintf(buff, "disabling\n");
658 break;
659 case BATADV_IF_INACTIVE:
660 length = sprintf(buff, "inactive\n");
661 break;
662 case BATADV_IF_ACTIVE:
663 length = sprintf(buff, "active\n");
664 break;
665 case BATADV_IF_TO_BE_ACTIVATED:
666 length = sprintf(buff, "enabling\n");
667 break;
668 case BATADV_IF_NOT_IN_USE:
669 default:
670 length = sprintf(buff, "not in use\n");
671 break;
672 }
673
674 batadv_hardif_free_ref(hard_iface);
675
676 return length;
677}
678
679static BATADV_ATTR(mesh_iface, S_IRUGO | S_IWUSR, batadv_show_mesh_iface,
680 batadv_store_mesh_iface);
681static BATADV_ATTR(iface_status, S_IRUGO, batadv_show_iface_status, NULL);
682
683static struct batadv_attribute *batadv_batman_attrs[] = {
684 &batadv_attr_mesh_iface,
685 &batadv_attr_iface_status,
686 NULL,
687};
688
689int batadv_sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev)
690{
691 struct kobject *hardif_kobject = &dev->dev.kobj;
692 struct batadv_attribute **bat_attr;
693 int err;
694
695 *hardif_obj = kobject_create_and_add(BATADV_SYSFS_IF_BAT_SUBDIR,
696 hardif_kobject);
697
698 if (!*hardif_obj) {
699 batadv_err(dev, "Can't add sysfs directory: %s/%s\n", dev->name,
700 BATADV_SYSFS_IF_BAT_SUBDIR);
701 goto out;
702 }
703
704 for (bat_attr = batadv_batman_attrs; *bat_attr; ++bat_attr) {
705 err = sysfs_create_file(*hardif_obj, &((*bat_attr)->attr));
706 if (err) {
707 batadv_err(dev, "Can't add sysfs file: %s/%s/%s\n",
708 dev->name, BATADV_SYSFS_IF_BAT_SUBDIR,
709 ((*bat_attr)->attr).name);
710 goto rem_attr;
711 }
712 }
713
714 return 0;
715
716rem_attr:
717 for (bat_attr = batadv_batman_attrs; *bat_attr; ++bat_attr)
718 sysfs_remove_file(*hardif_obj, &((*bat_attr)->attr));
719out:
720 return -ENOMEM;
721}
722
723void batadv_sysfs_del_hardif(struct kobject **hardif_obj)
724{
725 kobject_put(*hardif_obj);
726 *hardif_obj = NULL;
727}
728
729int batadv_throw_uevent(struct batadv_priv *bat_priv, enum batadv_uev_type type,
730 enum batadv_uev_action action, const char *data)
731{
732 int ret = -ENOMEM;
733 struct batadv_hard_iface *primary_if = NULL;
734 struct kobject *bat_kobj;
735 char *uevent_env[4] = { NULL, NULL, NULL, NULL };
736
737 primary_if = batadv_primary_if_get_selected(bat_priv);
738 if (!primary_if)
739 goto out;
740
741 bat_kobj = &primary_if->soft_iface->dev.kobj;
742
743 uevent_env[0] = kmalloc(strlen(BATADV_UEV_TYPE_VAR) +
744 strlen(batadv_uev_type_str[type]) + 1,
745 GFP_ATOMIC);
746 if (!uevent_env[0])
747 goto out;
748
749 sprintf(uevent_env[0], "%s%s", BATADV_UEV_TYPE_VAR,
750 batadv_uev_type_str[type]);
751
752 uevent_env[1] = kmalloc(strlen(BATADV_UEV_ACTION_VAR) +
753 strlen(batadv_uev_action_str[action]) + 1,
754 GFP_ATOMIC);
755 if (!uevent_env[1])
756 goto out;
757
758 sprintf(uevent_env[1], "%s%s", BATADV_UEV_ACTION_VAR,
759 batadv_uev_action_str[action]);
760
761 /* If the event is DEL, ignore the data field */
762 if (action != BATADV_UEV_DEL) {
763 uevent_env[2] = kmalloc(strlen(BATADV_UEV_DATA_VAR) +
764 strlen(data) + 1, GFP_ATOMIC);
765 if (!uevent_env[2])
766 goto out;
767
768 sprintf(uevent_env[2], "%s%s", BATADV_UEV_DATA_VAR, data);
769 }
770
771 ret = kobject_uevent_env(bat_kobj, KOBJ_CHANGE, uevent_env);
772out:
773 kfree(uevent_env[0]);
774 kfree(uevent_env[1]);
775 kfree(uevent_env[2]);
776
777 if (primary_if)
778 batadv_hardif_free_ref(primary_if);
779
780 if (ret)
781 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
782 "Impossible to send uevent for (%s,%s,%s) event (err: %d)\n",
783 batadv_uev_type_str[type],
784 batadv_uev_action_str[action],
785 (action == BATADV_UEV_DEL ? "NULL" : data), ret);
786 return ret;
787}