8196fa6ff22e7672acb441dc93d7005070d09be8
[cascardo/linux.git] / net / batman-adv / bat_sysfs.c
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 "bat_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
29 static struct net_device *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
35 static struct bat_priv *kobj_to_batpriv(struct kobject *obj)
36 {
37         struct net_device *net_dev = kobj_to_netdev(obj);
38         return netdev_priv(net_dev);
39 }
40
41 #define UEV_TYPE_VAR    "BATTYPE="
42 #define UEV_ACTION_VAR  "BATACTION="
43 #define UEV_DATA_VAR    "BATDATA="
44
45 static char *uev_action_str[] = {
46         "add",
47         "del",
48         "change"
49 };
50
51 static char *uev_type_str[] = {
52         "gw"
53 };
54
55 /* Use this, if you have customized show and store functions */
56 #define BAT_ATTR(_name, _mode, _show, _store)   \
57 struct bat_attribute bat_attr_##_name = {       \
58         .attr = {.name = __stringify(_name),    \
59                  .mode = _mode },               \
60         .show   = _show,                        \
61         .store  = _store,                       \
62 };
63
64 #define BAT_ATTR_SIF_STORE_BOOL(_name, _post_func)                      \
65 ssize_t store_##_name(struct kobject *kobj, struct attribute *attr,     \
66                       char *buff, size_t count)                         \
67 {                                                                       \
68         struct net_device *net_dev = kobj_to_netdev(kobj);              \
69         struct bat_priv *bat_priv = netdev_priv(net_dev);               \
70         return __store_bool_attr(buff, count, _post_func, attr,         \
71                                  &bat_priv->_name, net_dev);            \
72 }
73
74 #define BAT_ATTR_SIF_SHOW_BOOL(_name)                                   \
75 ssize_t show_##_name(struct kobject *kobj,                              \
76                      struct attribute *attr, char *buff)                \
77 {                                                                       \
78         struct bat_priv *bat_priv = kobj_to_batpriv(kobj);              \
79         return sprintf(buff, "%s\n",                                    \
80                        atomic_read(&bat_priv->_name) == 0 ?             \
81                        "disabled" : "enabled");                         \
82 }                                                                       \
83
84 /* Use this, if you are going to turn a [name] in the soft-interface
85  * (bat_priv) on or off
86  */
87 #define BAT_ATTR_SIF_BOOL(_name, _mode, _post_func)                     \
88         static BAT_ATTR_SIF_STORE_BOOL(_name, _post_func)               \
89         static BAT_ATTR_SIF_SHOW_BOOL(_name)                            \
90         static BAT_ATTR(_name, _mode, show_##_name, store_##_name)
91
92
93 #define BAT_ATTR_SIF_STORE_UINT(_name, _min, _max, _post_func)          \
94 ssize_t store_##_name(struct kobject *kobj, struct attribute *attr,     \
95                       char *buff, size_t count)                         \
96 {                                                                       \
97         struct net_device *net_dev = kobj_to_netdev(kobj);              \
98         struct bat_priv *bat_priv = netdev_priv(net_dev);               \
99         return __store_uint_attr(buff, count, _min, _max, _post_func,   \
100                                  attr, &bat_priv->_name, net_dev);      \
101 }
102
103 #define BAT_ATTR_SIF_SHOW_UINT(_name)                                   \
104 ssize_t show_##_name(struct kobject *kobj,                              \
105                      struct attribute *attr, char *buff)                \
106 {                                                                       \
107         struct bat_priv *bat_priv = kobj_to_batpriv(kobj);              \
108         return sprintf(buff, "%i\n", atomic_read(&bat_priv->_name));    \
109 }                                                                       \
110
111 /* Use this, if you are going to set [name] in the soft-interface
112  * (bat_priv) to an unsigned integer value
113  */
114 #define BAT_ATTR_SIF_UINT(_name, _mode, _min, _max, _post_func)         \
115         static BAT_ATTR_SIF_STORE_UINT(_name, _min, _max, _post_func)   \
116         static BAT_ATTR_SIF_SHOW_UINT(_name)                            \
117         static BAT_ATTR(_name, _mode, show_##_name, store_##_name)
118
119
120 #define BAT_ATTR_HIF_STORE_UINT(_name, _min, _max, _post_func)          \
121 ssize_t store_##_name(struct kobject *kobj, struct attribute *attr,     \
122                       char *buff, size_t count)                         \
123 {                                                                       \
124         struct net_device *net_dev = kobj_to_netdev(kobj);              \
125         struct hard_iface *hard_iface;                                  \
126         ssize_t length;                                                 \
127                                                                         \
128         hard_iface = batadv_hardif_get_by_netdev(net_dev);              \
129         if (!hard_iface)                                                \
130                 return 0;                                               \
131                                                                         \
132         length = __store_uint_attr(buff, count, _min, _max, _post_func, \
133                                    attr, &hard_iface->_name, net_dev);  \
134                                                                         \
135         hardif_free_ref(hard_iface);                                    \
136         return length;                                                  \
137 }
138
139 #define BAT_ATTR_HIF_SHOW_UINT(_name)                                   \
140 ssize_t show_##_name(struct kobject *kobj,                              \
141                      struct attribute *attr, char *buff)                \
142 {                                                                       \
143         struct net_device *net_dev = kobj_to_netdev(kobj);              \
144         struct hard_iface *hard_iface;                                  \
145         ssize_t length;                                                 \
146                                                                         \
147         hard_iface = batadv_hardif_get_by_netdev(net_dev);              \
148         if (!hard_iface)                                                \
149                 return 0;                                               \
150                                                                         \
151         length = sprintf(buff, "%i\n", atomic_read(&hard_iface->_name));\
152                                                                         \
153         hardif_free_ref(hard_iface);                                    \
154         return length;                                                  \
155 }
156
157 /* Use this, if you are going to set [name] in hard_iface to an
158  * unsigned integer value
159  */
160 #define BAT_ATTR_HIF_UINT(_name, _mode, _min, _max, _post_func)         \
161         static BAT_ATTR_HIF_STORE_UINT(_name, _min, _max, _post_func)   \
162         static BAT_ATTR_HIF_SHOW_UINT(_name)                            \
163         static BAT_ATTR(_name, _mode, show_##_name, store_##_name)
164
165
166 static int store_bool_attr(char *buff, size_t count,
167                            struct net_device *net_dev,
168                            const char *attr_name, atomic_t *attr)
169 {
170         int enabled = -1;
171
172         if (buff[count - 1] == '\n')
173                 buff[count - 1] = '\0';
174
175         if ((strncmp(buff, "1", 2) == 0) ||
176             (strncmp(buff, "enable", 7) == 0) ||
177             (strncmp(buff, "enabled", 8) == 0))
178                 enabled = 1;
179
180         if ((strncmp(buff, "0", 2) == 0) ||
181             (strncmp(buff, "disable", 8) == 0) ||
182             (strncmp(buff, "disabled", 9) == 0))
183                 enabled = 0;
184
185         if (enabled < 0) {
186                 bat_info(net_dev,
187                          "%s: Invalid parameter received: %s\n",
188                          attr_name, buff);
189                 return -EINVAL;
190         }
191
192         if (atomic_read(attr) == enabled)
193                 return count;
194
195         bat_info(net_dev, "%s: Changing from: %s to: %s\n", attr_name,
196                  atomic_read(attr) == 1 ? "enabled" : "disabled",
197                  enabled == 1 ? "enabled" : "disabled");
198
199         atomic_set(attr, (unsigned int)enabled);
200         return count;
201 }
202
203 static inline ssize_t __store_bool_attr(char *buff, size_t count,
204                         void (*post_func)(struct net_device *),
205                         struct attribute *attr,
206                         atomic_t *attr_store, struct net_device *net_dev)
207 {
208         int ret;
209
210         ret = store_bool_attr(buff, count, net_dev, attr->name, attr_store);
211         if (post_func && ret)
212                 post_func(net_dev);
213
214         return ret;
215 }
216
217 static int store_uint_attr(const char *buff, size_t count,
218                            struct net_device *net_dev, const char *attr_name,
219                            unsigned int min, unsigned int max, atomic_t *attr)
220 {
221         unsigned long uint_val;
222         int ret;
223
224         ret = kstrtoul(buff, 10, &uint_val);
225         if (ret) {
226                 bat_info(net_dev,
227                          "%s: Invalid parameter received: %s\n",
228                          attr_name, buff);
229                 return -EINVAL;
230         }
231
232         if (uint_val < min) {
233                 bat_info(net_dev, "%s: Value is too small: %lu min: %u\n",
234                          attr_name, uint_val, min);
235                 return -EINVAL;
236         }
237
238         if (uint_val > max) {
239                 bat_info(net_dev, "%s: Value is too big: %lu max: %u\n",
240                          attr_name, uint_val, max);
241                 return -EINVAL;
242         }
243
244         if (atomic_read(attr) == uint_val)
245                 return count;
246
247         bat_info(net_dev, "%s: Changing from: %i to: %lu\n",
248                  attr_name, atomic_read(attr), uint_val);
249
250         atomic_set(attr, uint_val);
251         return count;
252 }
253
254 static inline ssize_t __store_uint_attr(const char *buff, size_t count,
255                         int min, int max,
256                         void (*post_func)(struct net_device *),
257                         const struct attribute *attr,
258                         atomic_t *attr_store, struct net_device *net_dev)
259 {
260         int ret;
261
262         ret = store_uint_attr(buff, count, net_dev, attr->name,
263                               min, max, attr_store);
264         if (post_func && ret)
265                 post_func(net_dev);
266
267         return ret;
268 }
269
270 static ssize_t show_vis_mode(struct kobject *kobj, struct attribute *attr,
271                              char *buff)
272 {
273         struct bat_priv *bat_priv = kobj_to_batpriv(kobj);
274         int vis_mode = atomic_read(&bat_priv->vis_mode);
275
276         return sprintf(buff, "%s\n",
277                        vis_mode == VIS_TYPE_CLIENT_UPDATE ?
278                                                         "client" : "server");
279 }
280
281 static ssize_t store_vis_mode(struct kobject *kobj, struct attribute *attr,
282                               char *buff, size_t count)
283 {
284         struct net_device *net_dev = kobj_to_netdev(kobj);
285         struct bat_priv *bat_priv = netdev_priv(net_dev);
286         unsigned long val;
287         int ret, vis_mode_tmp = -1;
288
289         ret = kstrtoul(buff, 10, &val);
290
291         if (((count == 2) && (!ret) && (val == VIS_TYPE_CLIENT_UPDATE)) ||
292             (strncmp(buff, "client", 6) == 0) ||
293             (strncmp(buff, "off", 3) == 0))
294                 vis_mode_tmp = VIS_TYPE_CLIENT_UPDATE;
295
296         if (((count == 2) && (!ret) && (val == VIS_TYPE_SERVER_SYNC)) ||
297             (strncmp(buff, "server", 6) == 0))
298                 vis_mode_tmp = VIS_TYPE_SERVER_SYNC;
299
300         if (vis_mode_tmp < 0) {
301                 if (buff[count - 1] == '\n')
302                         buff[count - 1] = '\0';
303
304                 bat_info(net_dev,
305                          "Invalid parameter for 'vis mode' setting received: %s\n",
306                          buff);
307                 return -EINVAL;
308         }
309
310         if (atomic_read(&bat_priv->vis_mode) == vis_mode_tmp)
311                 return count;
312
313         bat_info(net_dev, "Changing vis mode from: %s to: %s\n",
314                  atomic_read(&bat_priv->vis_mode) == VIS_TYPE_CLIENT_UPDATE ?
315                  "client" : "server", vis_mode_tmp == VIS_TYPE_CLIENT_UPDATE ?
316                  "client" : "server");
317
318         atomic_set(&bat_priv->vis_mode, (unsigned int)vis_mode_tmp);
319         return count;
320 }
321
322 static ssize_t show_bat_algo(struct kobject *kobj, struct attribute *attr,
323                             char *buff)
324 {
325         struct bat_priv *bat_priv = kobj_to_batpriv(kobj);
326         return sprintf(buff, "%s\n", bat_priv->bat_algo_ops->name);
327 }
328
329 static void post_gw_deselect(struct net_device *net_dev)
330 {
331         struct bat_priv *bat_priv = netdev_priv(net_dev);
332         batadv_gw_deselect(bat_priv);
333 }
334
335 static ssize_t show_gw_mode(struct kobject *kobj, struct attribute *attr,
336                             char *buff)
337 {
338         struct bat_priv *bat_priv = kobj_to_batpriv(kobj);
339         int bytes_written;
340
341         switch (atomic_read(&bat_priv->gw_mode)) {
342         case GW_MODE_CLIENT:
343                 bytes_written = sprintf(buff, "%s\n", GW_MODE_CLIENT_NAME);
344                 break;
345         case GW_MODE_SERVER:
346                 bytes_written = sprintf(buff, "%s\n", GW_MODE_SERVER_NAME);
347                 break;
348         default:
349                 bytes_written = sprintf(buff, "%s\n", GW_MODE_OFF_NAME);
350                 break;
351         }
352
353         return bytes_written;
354 }
355
356 static ssize_t store_gw_mode(struct kobject *kobj, struct attribute *attr,
357                              char *buff, size_t count)
358 {
359         struct net_device *net_dev = kobj_to_netdev(kobj);
360         struct bat_priv *bat_priv = netdev_priv(net_dev);
361         char *curr_gw_mode_str;
362         int gw_mode_tmp = -1;
363
364         if (buff[count - 1] == '\n')
365                 buff[count - 1] = '\0';
366
367         if (strncmp(buff, GW_MODE_OFF_NAME, strlen(GW_MODE_OFF_NAME)) == 0)
368                 gw_mode_tmp = GW_MODE_OFF;
369
370         if (strncmp(buff, GW_MODE_CLIENT_NAME,
371                     strlen(GW_MODE_CLIENT_NAME)) == 0)
372                 gw_mode_tmp = GW_MODE_CLIENT;
373
374         if (strncmp(buff, GW_MODE_SERVER_NAME,
375                     strlen(GW_MODE_SERVER_NAME)) == 0)
376                 gw_mode_tmp = GW_MODE_SERVER;
377
378         if (gw_mode_tmp < 0) {
379                 bat_info(net_dev,
380                          "Invalid parameter for 'gw mode' setting received: %s\n",
381                          buff);
382                 return -EINVAL;
383         }
384
385         if (atomic_read(&bat_priv->gw_mode) == gw_mode_tmp)
386                 return count;
387
388         switch (atomic_read(&bat_priv->gw_mode)) {
389         case GW_MODE_CLIENT:
390                 curr_gw_mode_str = GW_MODE_CLIENT_NAME;
391                 break;
392         case GW_MODE_SERVER:
393                 curr_gw_mode_str = GW_MODE_SERVER_NAME;
394                 break;
395         default:
396                 curr_gw_mode_str = GW_MODE_OFF_NAME;
397                 break;
398         }
399
400         bat_info(net_dev, "Changing gw mode from: %s to: %s\n",
401                  curr_gw_mode_str, buff);
402
403         batadv_gw_deselect(bat_priv);
404         atomic_set(&bat_priv->gw_mode, (unsigned int)gw_mode_tmp);
405         return count;
406 }
407
408 static ssize_t show_gw_bwidth(struct kobject *kobj, struct attribute *attr,
409                               char *buff)
410 {
411         struct bat_priv *bat_priv = kobj_to_batpriv(kobj);
412         int down, up;
413         int gw_bandwidth = atomic_read(&bat_priv->gw_bandwidth);
414
415         batadv_gw_bandwidth_to_kbit(gw_bandwidth, &down, &up);
416         return sprintf(buff, "%i%s/%i%s\n",
417                        (down > 2048 ? down / 1024 : down),
418                        (down > 2048 ? "MBit" : "KBit"),
419                        (up > 2048 ? up / 1024 : up),
420                        (up > 2048 ? "MBit" : "KBit"));
421 }
422
423 static ssize_t store_gw_bwidth(struct kobject *kobj, struct attribute *attr,
424                                char *buff, size_t count)
425 {
426         struct net_device *net_dev = kobj_to_netdev(kobj);
427
428         if (buff[count - 1] == '\n')
429                 buff[count - 1] = '\0';
430
431         return batadv_gw_bandwidth_set(net_dev, buff, count);
432 }
433
434 BAT_ATTR_SIF_BOOL(aggregated_ogms, S_IRUGO | S_IWUSR, NULL);
435 BAT_ATTR_SIF_BOOL(bonding, S_IRUGO | S_IWUSR, NULL);
436 #ifdef CONFIG_BATMAN_ADV_BLA
437 BAT_ATTR_SIF_BOOL(bridge_loop_avoidance, S_IRUGO | S_IWUSR, NULL);
438 #endif
439 BAT_ATTR_SIF_BOOL(fragmentation, S_IRUGO | S_IWUSR, batadv_update_min_mtu);
440 BAT_ATTR_SIF_BOOL(ap_isolation, S_IRUGO | S_IWUSR, NULL);
441 static BAT_ATTR(vis_mode, S_IRUGO | S_IWUSR, show_vis_mode, store_vis_mode);
442 static BAT_ATTR(routing_algo, S_IRUGO, show_bat_algo, NULL);
443 static BAT_ATTR(gw_mode, S_IRUGO | S_IWUSR, show_gw_mode, store_gw_mode);
444 BAT_ATTR_SIF_UINT(orig_interval, S_IRUGO | S_IWUSR, 2 * JITTER, INT_MAX, NULL);
445 BAT_ATTR_SIF_UINT(hop_penalty, S_IRUGO | S_IWUSR, 0, TQ_MAX_VALUE, NULL);
446 BAT_ATTR_SIF_UINT(gw_sel_class, S_IRUGO | S_IWUSR, 1, TQ_MAX_VALUE,
447                   post_gw_deselect);
448 static BAT_ATTR(gw_bandwidth, S_IRUGO | S_IWUSR, show_gw_bwidth,
449                 store_gw_bwidth);
450 #ifdef CONFIG_BATMAN_ADV_DEBUG
451 BAT_ATTR_SIF_UINT(log_level, S_IRUGO | S_IWUSR, 0, DBG_ALL, NULL);
452 #endif
453
454 static struct bat_attribute *mesh_attrs[] = {
455         &bat_attr_aggregated_ogms,
456         &bat_attr_bonding,
457 #ifdef CONFIG_BATMAN_ADV_BLA
458         &bat_attr_bridge_loop_avoidance,
459 #endif
460         &bat_attr_fragmentation,
461         &bat_attr_ap_isolation,
462         &bat_attr_vis_mode,
463         &bat_attr_routing_algo,
464         &bat_attr_gw_mode,
465         &bat_attr_orig_interval,
466         &bat_attr_hop_penalty,
467         &bat_attr_gw_sel_class,
468         &bat_attr_gw_bandwidth,
469 #ifdef CONFIG_BATMAN_ADV_DEBUG
470         &bat_attr_log_level,
471 #endif
472         NULL,
473 };
474
475 int batadv_sysfs_add_meshif(struct net_device *dev)
476 {
477         struct kobject *batif_kobject = &dev->dev.kobj;
478         struct bat_priv *bat_priv = netdev_priv(dev);
479         struct bat_attribute **bat_attr;
480         int err;
481
482         bat_priv->mesh_obj = kobject_create_and_add(SYSFS_IF_MESH_SUBDIR,
483                                                     batif_kobject);
484         if (!bat_priv->mesh_obj) {
485                 bat_err(dev, "Can't add sysfs directory: %s/%s\n", dev->name,
486                         SYSFS_IF_MESH_SUBDIR);
487                 goto out;
488         }
489
490         for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr) {
491                 err = sysfs_create_file(bat_priv->mesh_obj,
492                                         &((*bat_attr)->attr));
493                 if (err) {
494                         bat_err(dev, "Can't add sysfs file: %s/%s/%s\n",
495                                 dev->name, SYSFS_IF_MESH_SUBDIR,
496                                 ((*bat_attr)->attr).name);
497                         goto rem_attr;
498                 }
499         }
500
501         return 0;
502
503 rem_attr:
504         for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr)
505                 sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr));
506
507         kobject_put(bat_priv->mesh_obj);
508         bat_priv->mesh_obj = NULL;
509 out:
510         return -ENOMEM;
511 }
512
513 void batadv_sysfs_del_meshif(struct net_device *dev)
514 {
515         struct bat_priv *bat_priv = netdev_priv(dev);
516         struct bat_attribute **bat_attr;
517
518         for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr)
519                 sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr));
520
521         kobject_put(bat_priv->mesh_obj);
522         bat_priv->mesh_obj = NULL;
523 }
524
525 static ssize_t show_mesh_iface(struct kobject *kobj, struct attribute *attr,
526                                char *buff)
527 {
528         struct net_device *net_dev = kobj_to_netdev(kobj);
529         struct hard_iface *hard_iface = batadv_hardif_get_by_netdev(net_dev);
530         ssize_t length;
531
532         if (!hard_iface)
533                 return 0;
534
535         length = sprintf(buff, "%s\n", hard_iface->if_status == IF_NOT_IN_USE ?
536                          "none" : hard_iface->soft_iface->name);
537
538         hardif_free_ref(hard_iface);
539
540         return length;
541 }
542
543 static ssize_t store_mesh_iface(struct kobject *kobj, struct attribute *attr,
544                                 char *buff, size_t count)
545 {
546         struct net_device *net_dev = kobj_to_netdev(kobj);
547         struct hard_iface *hard_iface = batadv_hardif_get_by_netdev(net_dev);
548         int status_tmp = -1;
549         int ret = count;
550
551         if (!hard_iface)
552                 return count;
553
554         if (buff[count - 1] == '\n')
555                 buff[count - 1] = '\0';
556
557         if (strlen(buff) >= IFNAMSIZ) {
558                 pr_err("Invalid parameter for 'mesh_iface' setting received: interface name too long '%s'\n",
559                        buff);
560                 hardif_free_ref(hard_iface);
561                 return -EINVAL;
562         }
563
564         if (strncmp(buff, "none", 4) == 0)
565                 status_tmp = IF_NOT_IN_USE;
566         else
567                 status_tmp = IF_I_WANT_YOU;
568
569         if (hard_iface->if_status == status_tmp)
570                 goto out;
571
572         if ((hard_iface->soft_iface) &&
573             (strncmp(hard_iface->soft_iface->name, buff, IFNAMSIZ) == 0))
574                 goto out;
575
576         if (!rtnl_trylock()) {
577                 ret = -ERESTARTSYS;
578                 goto out;
579         }
580
581         if (status_tmp == IF_NOT_IN_USE) {
582                 batadv_hardif_disable_interface(hard_iface);
583                 goto unlock;
584         }
585
586         /* if the interface already is in use */
587         if (hard_iface->if_status != IF_NOT_IN_USE)
588                 batadv_hardif_disable_interface(hard_iface);
589
590         ret = batadv_hardif_enable_interface(hard_iface, buff);
591
592 unlock:
593         rtnl_unlock();
594 out:
595         hardif_free_ref(hard_iface);
596         return ret;
597 }
598
599 static ssize_t show_iface_status(struct kobject *kobj, struct attribute *attr,
600                                  char *buff)
601 {
602         struct net_device *net_dev = kobj_to_netdev(kobj);
603         struct hard_iface *hard_iface = batadv_hardif_get_by_netdev(net_dev);
604         ssize_t length;
605
606         if (!hard_iface)
607                 return 0;
608
609         switch (hard_iface->if_status) {
610         case IF_TO_BE_REMOVED:
611                 length = sprintf(buff, "disabling\n");
612                 break;
613         case IF_INACTIVE:
614                 length = sprintf(buff, "inactive\n");
615                 break;
616         case IF_ACTIVE:
617                 length = sprintf(buff, "active\n");
618                 break;
619         case IF_TO_BE_ACTIVATED:
620                 length = sprintf(buff, "enabling\n");
621                 break;
622         case IF_NOT_IN_USE:
623         default:
624                 length = sprintf(buff, "not in use\n");
625                 break;
626         }
627
628         hardif_free_ref(hard_iface);
629
630         return length;
631 }
632
633 static BAT_ATTR(mesh_iface, S_IRUGO | S_IWUSR,
634                 show_mesh_iface, store_mesh_iface);
635 static BAT_ATTR(iface_status, S_IRUGO, show_iface_status, NULL);
636
637 static struct bat_attribute *batman_attrs[] = {
638         &bat_attr_mesh_iface,
639         &bat_attr_iface_status,
640         NULL,
641 };
642
643 int batadv_sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev)
644 {
645         struct kobject *hardif_kobject = &dev->dev.kobj;
646         struct bat_attribute **bat_attr;
647         int err;
648
649         *hardif_obj = kobject_create_and_add(SYSFS_IF_BAT_SUBDIR,
650                                                     hardif_kobject);
651
652         if (!*hardif_obj) {
653                 bat_err(dev, "Can't add sysfs directory: %s/%s\n", dev->name,
654                         SYSFS_IF_BAT_SUBDIR);
655                 goto out;
656         }
657
658         for (bat_attr = batman_attrs; *bat_attr; ++bat_attr) {
659                 err = sysfs_create_file(*hardif_obj, &((*bat_attr)->attr));
660                 if (err) {
661                         bat_err(dev, "Can't add sysfs file: %s/%s/%s\n",
662                                 dev->name, SYSFS_IF_BAT_SUBDIR,
663                                 ((*bat_attr)->attr).name);
664                         goto rem_attr;
665                 }
666         }
667
668         return 0;
669
670 rem_attr:
671         for (bat_attr = batman_attrs; *bat_attr; ++bat_attr)
672                 sysfs_remove_file(*hardif_obj, &((*bat_attr)->attr));
673 out:
674         return -ENOMEM;
675 }
676
677 void batadv_sysfs_del_hardif(struct kobject **hardif_obj)
678 {
679         kobject_put(*hardif_obj);
680         *hardif_obj = NULL;
681 }
682
683 int batadv_throw_uevent(struct bat_priv *bat_priv, enum uev_type type,
684                         enum uev_action action, const char *data)
685 {
686         int ret = -ENOMEM;
687         struct hard_iface *primary_if = NULL;
688         struct kobject *bat_kobj;
689         char *uevent_env[4] = { NULL, NULL, NULL, NULL };
690
691         primary_if = primary_if_get_selected(bat_priv);
692         if (!primary_if)
693                 goto out;
694
695         bat_kobj = &primary_if->soft_iface->dev.kobj;
696
697         uevent_env[0] = kmalloc(strlen(UEV_TYPE_VAR) +
698                                 strlen(uev_type_str[type]) + 1,
699                                 GFP_ATOMIC);
700         if (!uevent_env[0])
701                 goto out;
702
703         sprintf(uevent_env[0], "%s%s", UEV_TYPE_VAR, uev_type_str[type]);
704
705         uevent_env[1] = kmalloc(strlen(UEV_ACTION_VAR) +
706                                 strlen(uev_action_str[action]) + 1,
707                                 GFP_ATOMIC);
708         if (!uevent_env[1])
709                 goto out;
710
711         sprintf(uevent_env[1], "%s%s", UEV_ACTION_VAR, uev_action_str[action]);
712
713         /* If the event is DEL, ignore the data field */
714         if (action != UEV_DEL) {
715                 uevent_env[2] = kmalloc(strlen(UEV_DATA_VAR) +
716                                         strlen(data) + 1, GFP_ATOMIC);
717                 if (!uevent_env[2])
718                         goto out;
719
720                 sprintf(uevent_env[2], "%s%s", UEV_DATA_VAR, data);
721         }
722
723         ret = kobject_uevent_env(bat_kobj, KOBJ_CHANGE, uevent_env);
724 out:
725         kfree(uevent_env[0]);
726         kfree(uevent_env[1]);
727         kfree(uevent_env[2]);
728
729         if (primary_if)
730                 hardif_free_ref(primary_if);
731
732         if (ret)
733                 bat_dbg(DBG_BATMAN, bat_priv,
734                         "Impossible to send uevent for (%s,%s,%s) event (err: %d)\n",
735                         uev_type_str[type], uev_action_str[action],
736                         (action == UEV_DEL ? "NULL" : data), ret);
737         return ret;
738 }