linux/net/batman-adv/sysfs.c
<<
>>
Prefs
   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}
 788
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.