at v3.7 787 lines 22 kB view raw
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}