at v3.4 685 lines 18 kB view raw
1/* 2 * Copyright (C) 2010-2012 B.A.T.M.A.N. contributors: 3 * 4 * Marek Lindner 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of version 2 of the GNU General Public 8 * License as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, but 11 * WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 18 * 02110-1301, USA 19 * 20 */ 21 22#include "main.h" 23#include "bat_sysfs.h" 24#include "translation-table.h" 25#include "originator.h" 26#include "hard-interface.h" 27#include "gateway_common.h" 28#include "gateway_client.h" 29#include "vis.h" 30 31static struct net_device *kobj_to_netdev(struct kobject *obj) 32{ 33 struct device *dev = container_of(obj->parent, struct device, kobj); 34 return to_net_dev(dev); 35} 36 37static struct bat_priv *kobj_to_batpriv(struct kobject *obj) 38{ 39 struct net_device *net_dev = kobj_to_netdev(obj); 40 return netdev_priv(net_dev); 41} 42 43#define UEV_TYPE_VAR "BATTYPE=" 44#define UEV_ACTION_VAR "BATACTION=" 45#define UEV_DATA_VAR "BATDATA=" 46 47static char *uev_action_str[] = { 48 "add", 49 "del", 50 "change" 51}; 52 53static char *uev_type_str[] = { 54 "gw" 55}; 56 57/* Use this, if you have customized show and store functions */ 58#define BAT_ATTR(_name, _mode, _show, _store) \ 59struct bat_attribute bat_attr_##_name = { \ 60 .attr = {.name = __stringify(_name), \ 61 .mode = _mode }, \ 62 .show = _show, \ 63 .store = _store, \ 64}; 65 66#define BAT_ATTR_STORE_BOOL(_name, _post_func) \ 67ssize_t store_##_name(struct kobject *kobj, struct attribute *attr, \ 68 char *buff, size_t count) \ 69{ \ 70 struct net_device *net_dev = kobj_to_netdev(kobj); \ 71 struct bat_priv *bat_priv = netdev_priv(net_dev); \ 72 return __store_bool_attr(buff, count, _post_func, attr, \ 73 &bat_priv->_name, net_dev); \ 74} 75 76#define BAT_ATTR_SHOW_BOOL(_name) \ 77ssize_t show_##_name(struct kobject *kobj, struct attribute *attr, \ 78 char *buff) \ 79{ \ 80 struct bat_priv *bat_priv = kobj_to_batpriv(kobj); \ 81 return sprintf(buff, "%s\n", \ 82 atomic_read(&bat_priv->_name) == 0 ? \ 83 "disabled" : "enabled"); \ 84} \ 85 86/* Use this, if you are going to turn a [name] in bat_priv on or off */ 87#define BAT_ATTR_BOOL(_name, _mode, _post_func) \ 88 static BAT_ATTR_STORE_BOOL(_name, _post_func) \ 89 static BAT_ATTR_SHOW_BOOL(_name) \ 90 static BAT_ATTR(_name, _mode, show_##_name, store_##_name) 91 92 93#define BAT_ATTR_STORE_UINT(_name, _min, _max, _post_func) \ 94ssize_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_SHOW_UINT(_name) \ 104ssize_t show_##_name(struct kobject *kobj, struct attribute *attr, \ 105 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 bat_priv to unsigned integer 112 * values only */ 113#define BAT_ATTR_UINT(_name, _mode, _min, _max, _post_func) \ 114 static BAT_ATTR_STORE_UINT(_name, _min, _max, _post_func) \ 115 static BAT_ATTR_SHOW_UINT(_name) \ 116 static BAT_ATTR(_name, _mode, show_##_name, store_##_name) 117 118 119static int store_bool_attr(char *buff, size_t count, 120 struct net_device *net_dev, 121 const char *attr_name, atomic_t *attr) 122{ 123 int enabled = -1; 124 125 if (buff[count - 1] == '\n') 126 buff[count - 1] = '\0'; 127 128 if ((strncmp(buff, "1", 2) == 0) || 129 (strncmp(buff, "enable", 7) == 0) || 130 (strncmp(buff, "enabled", 8) == 0)) 131 enabled = 1; 132 133 if ((strncmp(buff, "0", 2) == 0) || 134 (strncmp(buff, "disable", 8) == 0) || 135 (strncmp(buff, "disabled", 9) == 0)) 136 enabled = 0; 137 138 if (enabled < 0) { 139 bat_info(net_dev, 140 "%s: Invalid parameter received: %s\n", 141 attr_name, buff); 142 return -EINVAL; 143 } 144 145 if (atomic_read(attr) == enabled) 146 return count; 147 148 bat_info(net_dev, "%s: Changing from: %s to: %s\n", attr_name, 149 atomic_read(attr) == 1 ? "enabled" : "disabled", 150 enabled == 1 ? "enabled" : "disabled"); 151 152 atomic_set(attr, (unsigned)enabled); 153 return count; 154} 155 156static inline ssize_t __store_bool_attr(char *buff, size_t count, 157 void (*post_func)(struct net_device *), 158 struct attribute *attr, 159 atomic_t *attr_store, struct net_device *net_dev) 160{ 161 int ret; 162 163 ret = store_bool_attr(buff, count, net_dev, attr->name, attr_store); 164 if (post_func && ret) 165 post_func(net_dev); 166 167 return ret; 168} 169 170static int store_uint_attr(const char *buff, size_t count, 171 struct net_device *net_dev, const char *attr_name, 172 unsigned int min, unsigned int max, atomic_t *attr) 173{ 174 unsigned long uint_val; 175 int ret; 176 177 ret = kstrtoul(buff, 10, &uint_val); 178 if (ret) { 179 bat_info(net_dev, 180 "%s: Invalid parameter received: %s\n", 181 attr_name, buff); 182 return -EINVAL; 183 } 184 185 if (uint_val < min) { 186 bat_info(net_dev, "%s: Value is too small: %lu min: %u\n", 187 attr_name, uint_val, min); 188 return -EINVAL; 189 } 190 191 if (uint_val > max) { 192 bat_info(net_dev, "%s: Value is too big: %lu max: %u\n", 193 attr_name, uint_val, max); 194 return -EINVAL; 195 } 196 197 if (atomic_read(attr) == uint_val) 198 return count; 199 200 bat_info(net_dev, "%s: Changing from: %i to: %lu\n", 201 attr_name, atomic_read(attr), uint_val); 202 203 atomic_set(attr, uint_val); 204 return count; 205} 206 207static inline ssize_t __store_uint_attr(const char *buff, size_t count, 208 int min, int max, 209 void (*post_func)(struct net_device *), 210 const struct attribute *attr, 211 atomic_t *attr_store, struct net_device *net_dev) 212{ 213 int ret; 214 215 ret = store_uint_attr(buff, count, net_dev, attr->name, 216 min, max, attr_store); 217 if (post_func && ret) 218 post_func(net_dev); 219 220 return ret; 221} 222 223static ssize_t show_vis_mode(struct kobject *kobj, struct attribute *attr, 224 char *buff) 225{ 226 struct bat_priv *bat_priv = kobj_to_batpriv(kobj); 227 int vis_mode = atomic_read(&bat_priv->vis_mode); 228 229 return sprintf(buff, "%s\n", 230 vis_mode == VIS_TYPE_CLIENT_UPDATE ? 231 "client" : "server"); 232} 233 234static ssize_t store_vis_mode(struct kobject *kobj, struct attribute *attr, 235 char *buff, size_t count) 236{ 237 struct net_device *net_dev = kobj_to_netdev(kobj); 238 struct bat_priv *bat_priv = netdev_priv(net_dev); 239 unsigned long val; 240 int ret, vis_mode_tmp = -1; 241 242 ret = kstrtoul(buff, 10, &val); 243 244 if (((count == 2) && (!ret) && (val == VIS_TYPE_CLIENT_UPDATE)) || 245 (strncmp(buff, "client", 6) == 0) || 246 (strncmp(buff, "off", 3) == 0)) 247 vis_mode_tmp = VIS_TYPE_CLIENT_UPDATE; 248 249 if (((count == 2) && (!ret) && (val == VIS_TYPE_SERVER_SYNC)) || 250 (strncmp(buff, "server", 6) == 0)) 251 vis_mode_tmp = VIS_TYPE_SERVER_SYNC; 252 253 if (vis_mode_tmp < 0) { 254 if (buff[count - 1] == '\n') 255 buff[count - 1] = '\0'; 256 257 bat_info(net_dev, 258 "Invalid parameter for 'vis mode' setting received: %s\n", 259 buff); 260 return -EINVAL; 261 } 262 263 if (atomic_read(&bat_priv->vis_mode) == vis_mode_tmp) 264 return count; 265 266 bat_info(net_dev, "Changing vis mode from: %s to: %s\n", 267 atomic_read(&bat_priv->vis_mode) == VIS_TYPE_CLIENT_UPDATE ? 268 "client" : "server", vis_mode_tmp == VIS_TYPE_CLIENT_UPDATE ? 269 "client" : "server"); 270 271 atomic_set(&bat_priv->vis_mode, (unsigned)vis_mode_tmp); 272 return count; 273} 274 275static ssize_t show_bat_algo(struct kobject *kobj, struct attribute *attr, 276 char *buff) 277{ 278 struct bat_priv *bat_priv = kobj_to_batpriv(kobj); 279 return sprintf(buff, "%s\n", bat_priv->bat_algo_ops->name); 280} 281 282static void post_gw_deselect(struct net_device *net_dev) 283{ 284 struct bat_priv *bat_priv = netdev_priv(net_dev); 285 gw_deselect(bat_priv); 286} 287 288static ssize_t show_gw_mode(struct kobject *kobj, struct attribute *attr, 289 char *buff) 290{ 291 struct bat_priv *bat_priv = kobj_to_batpriv(kobj); 292 int bytes_written; 293 294 switch (atomic_read(&bat_priv->gw_mode)) { 295 case GW_MODE_CLIENT: 296 bytes_written = sprintf(buff, "%s\n", GW_MODE_CLIENT_NAME); 297 break; 298 case GW_MODE_SERVER: 299 bytes_written = sprintf(buff, "%s\n", GW_MODE_SERVER_NAME); 300 break; 301 default: 302 bytes_written = sprintf(buff, "%s\n", GW_MODE_OFF_NAME); 303 break; 304 } 305 306 return bytes_written; 307} 308 309static ssize_t store_gw_mode(struct kobject *kobj, struct attribute *attr, 310 char *buff, size_t count) 311{ 312 struct net_device *net_dev = kobj_to_netdev(kobj); 313 struct bat_priv *bat_priv = netdev_priv(net_dev); 314 char *curr_gw_mode_str; 315 int gw_mode_tmp = -1; 316 317 if (buff[count - 1] == '\n') 318 buff[count - 1] = '\0'; 319 320 if (strncmp(buff, GW_MODE_OFF_NAME, strlen(GW_MODE_OFF_NAME)) == 0) 321 gw_mode_tmp = GW_MODE_OFF; 322 323 if (strncmp(buff, GW_MODE_CLIENT_NAME, 324 strlen(GW_MODE_CLIENT_NAME)) == 0) 325 gw_mode_tmp = GW_MODE_CLIENT; 326 327 if (strncmp(buff, GW_MODE_SERVER_NAME, 328 strlen(GW_MODE_SERVER_NAME)) == 0) 329 gw_mode_tmp = GW_MODE_SERVER; 330 331 if (gw_mode_tmp < 0) { 332 bat_info(net_dev, 333 "Invalid parameter for 'gw mode' setting received: %s\n", 334 buff); 335 return -EINVAL; 336 } 337 338 if (atomic_read(&bat_priv->gw_mode) == gw_mode_tmp) 339 return count; 340 341 switch (atomic_read(&bat_priv->gw_mode)) { 342 case GW_MODE_CLIENT: 343 curr_gw_mode_str = GW_MODE_CLIENT_NAME; 344 break; 345 case GW_MODE_SERVER: 346 curr_gw_mode_str = GW_MODE_SERVER_NAME; 347 break; 348 default: 349 curr_gw_mode_str = GW_MODE_OFF_NAME; 350 break; 351 } 352 353 bat_info(net_dev, "Changing gw mode from: %s to: %s\n", 354 curr_gw_mode_str, buff); 355 356 gw_deselect(bat_priv); 357 atomic_set(&bat_priv->gw_mode, (unsigned)gw_mode_tmp); 358 return count; 359} 360 361static ssize_t show_gw_bwidth(struct kobject *kobj, struct attribute *attr, 362 char *buff) 363{ 364 struct bat_priv *bat_priv = kobj_to_batpriv(kobj); 365 int down, up; 366 int gw_bandwidth = atomic_read(&bat_priv->gw_bandwidth); 367 368 gw_bandwidth_to_kbit(gw_bandwidth, &down, &up); 369 return sprintf(buff, "%i%s/%i%s\n", 370 (down > 2048 ? down / 1024 : down), 371 (down > 2048 ? "MBit" : "KBit"), 372 (up > 2048 ? up / 1024 : up), 373 (up > 2048 ? "MBit" : "KBit")); 374} 375 376static ssize_t store_gw_bwidth(struct kobject *kobj, struct attribute *attr, 377 char *buff, size_t count) 378{ 379 struct net_device *net_dev = kobj_to_netdev(kobj); 380 381 if (buff[count - 1] == '\n') 382 buff[count - 1] = '\0'; 383 384 return gw_bandwidth_set(net_dev, buff, count); 385} 386 387BAT_ATTR_BOOL(aggregated_ogms, S_IRUGO | S_IWUSR, NULL); 388BAT_ATTR_BOOL(bonding, S_IRUGO | S_IWUSR, NULL); 389BAT_ATTR_BOOL(fragmentation, S_IRUGO | S_IWUSR, update_min_mtu); 390BAT_ATTR_BOOL(ap_isolation, S_IRUGO | S_IWUSR, NULL); 391static BAT_ATTR(vis_mode, S_IRUGO | S_IWUSR, show_vis_mode, store_vis_mode); 392static BAT_ATTR(routing_algo, S_IRUGO, show_bat_algo, NULL); 393static BAT_ATTR(gw_mode, S_IRUGO | S_IWUSR, show_gw_mode, store_gw_mode); 394BAT_ATTR_UINT(orig_interval, S_IRUGO | S_IWUSR, 2 * JITTER, INT_MAX, NULL); 395BAT_ATTR_UINT(hop_penalty, S_IRUGO | S_IWUSR, 0, TQ_MAX_VALUE, NULL); 396BAT_ATTR_UINT(gw_sel_class, S_IRUGO | S_IWUSR, 1, TQ_MAX_VALUE, 397 post_gw_deselect); 398static BAT_ATTR(gw_bandwidth, S_IRUGO | S_IWUSR, show_gw_bwidth, 399 store_gw_bwidth); 400#ifdef CONFIG_BATMAN_ADV_DEBUG 401BAT_ATTR_UINT(log_level, S_IRUGO | S_IWUSR, 0, 7, NULL); 402#endif 403 404static struct bat_attribute *mesh_attrs[] = { 405 &bat_attr_aggregated_ogms, 406 &bat_attr_bonding, 407 &bat_attr_fragmentation, 408 &bat_attr_ap_isolation, 409 &bat_attr_vis_mode, 410 &bat_attr_routing_algo, 411 &bat_attr_gw_mode, 412 &bat_attr_orig_interval, 413 &bat_attr_hop_penalty, 414 &bat_attr_gw_sel_class, 415 &bat_attr_gw_bandwidth, 416#ifdef CONFIG_BATMAN_ADV_DEBUG 417 &bat_attr_log_level, 418#endif 419 NULL, 420}; 421 422int sysfs_add_meshif(struct net_device *dev) 423{ 424 struct kobject *batif_kobject = &dev->dev.kobj; 425 struct bat_priv *bat_priv = netdev_priv(dev); 426 struct bat_attribute **bat_attr; 427 int err; 428 429 bat_priv->mesh_obj = kobject_create_and_add(SYSFS_IF_MESH_SUBDIR, 430 batif_kobject); 431 if (!bat_priv->mesh_obj) { 432 bat_err(dev, "Can't add sysfs directory: %s/%s\n", dev->name, 433 SYSFS_IF_MESH_SUBDIR); 434 goto out; 435 } 436 437 for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr) { 438 err = sysfs_create_file(bat_priv->mesh_obj, 439 &((*bat_attr)->attr)); 440 if (err) { 441 bat_err(dev, "Can't add sysfs file: %s/%s/%s\n", 442 dev->name, SYSFS_IF_MESH_SUBDIR, 443 ((*bat_attr)->attr).name); 444 goto rem_attr; 445 } 446 } 447 448 return 0; 449 450rem_attr: 451 for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr) 452 sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr)); 453 454 kobject_put(bat_priv->mesh_obj); 455 bat_priv->mesh_obj = NULL; 456out: 457 return -ENOMEM; 458} 459 460void sysfs_del_meshif(struct net_device *dev) 461{ 462 struct bat_priv *bat_priv = netdev_priv(dev); 463 struct bat_attribute **bat_attr; 464 465 for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr) 466 sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr)); 467 468 kobject_put(bat_priv->mesh_obj); 469 bat_priv->mesh_obj = NULL; 470} 471 472static ssize_t show_mesh_iface(struct kobject *kobj, struct attribute *attr, 473 char *buff) 474{ 475 struct net_device *net_dev = kobj_to_netdev(kobj); 476 struct hard_iface *hard_iface = hardif_get_by_netdev(net_dev); 477 ssize_t length; 478 479 if (!hard_iface) 480 return 0; 481 482 length = sprintf(buff, "%s\n", hard_iface->if_status == IF_NOT_IN_USE ? 483 "none" : hard_iface->soft_iface->name); 484 485 hardif_free_ref(hard_iface); 486 487 return length; 488} 489 490static ssize_t store_mesh_iface(struct kobject *kobj, struct attribute *attr, 491 char *buff, size_t count) 492{ 493 struct net_device *net_dev = kobj_to_netdev(kobj); 494 struct hard_iface *hard_iface = hardif_get_by_netdev(net_dev); 495 int status_tmp = -1; 496 int ret = count; 497 498 if (!hard_iface) 499 return count; 500 501 if (buff[count - 1] == '\n') 502 buff[count - 1] = '\0'; 503 504 if (strlen(buff) >= IFNAMSIZ) { 505 pr_err("Invalid parameter for 'mesh_iface' setting received: interface name too long '%s'\n", 506 buff); 507 hardif_free_ref(hard_iface); 508 return -EINVAL; 509 } 510 511 if (strncmp(buff, "none", 4) == 0) 512 status_tmp = IF_NOT_IN_USE; 513 else 514 status_tmp = IF_I_WANT_YOU; 515 516 if (hard_iface->if_status == status_tmp) 517 goto out; 518 519 if ((hard_iface->soft_iface) && 520 (strncmp(hard_iface->soft_iface->name, buff, IFNAMSIZ) == 0)) 521 goto out; 522 523 if (!rtnl_trylock()) { 524 ret = -ERESTARTSYS; 525 goto out; 526 } 527 528 if (status_tmp == IF_NOT_IN_USE) { 529 hardif_disable_interface(hard_iface); 530 goto unlock; 531 } 532 533 /* if the interface already is in use */ 534 if (hard_iface->if_status != IF_NOT_IN_USE) 535 hardif_disable_interface(hard_iface); 536 537 ret = hardif_enable_interface(hard_iface, buff); 538 539unlock: 540 rtnl_unlock(); 541out: 542 hardif_free_ref(hard_iface); 543 return ret; 544} 545 546static ssize_t show_iface_status(struct kobject *kobj, struct attribute *attr, 547 char *buff) 548{ 549 struct net_device *net_dev = kobj_to_netdev(kobj); 550 struct hard_iface *hard_iface = hardif_get_by_netdev(net_dev); 551 ssize_t length; 552 553 if (!hard_iface) 554 return 0; 555 556 switch (hard_iface->if_status) { 557 case IF_TO_BE_REMOVED: 558 length = sprintf(buff, "disabling\n"); 559 break; 560 case IF_INACTIVE: 561 length = sprintf(buff, "inactive\n"); 562 break; 563 case IF_ACTIVE: 564 length = sprintf(buff, "active\n"); 565 break; 566 case IF_TO_BE_ACTIVATED: 567 length = sprintf(buff, "enabling\n"); 568 break; 569 case IF_NOT_IN_USE: 570 default: 571 length = sprintf(buff, "not in use\n"); 572 break; 573 } 574 575 hardif_free_ref(hard_iface); 576 577 return length; 578} 579 580static BAT_ATTR(mesh_iface, S_IRUGO | S_IWUSR, 581 show_mesh_iface, store_mesh_iface); 582static BAT_ATTR(iface_status, S_IRUGO, show_iface_status, NULL); 583 584static struct bat_attribute *batman_attrs[] = { 585 &bat_attr_mesh_iface, 586 &bat_attr_iface_status, 587 NULL, 588}; 589 590int sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev) 591{ 592 struct kobject *hardif_kobject = &dev->dev.kobj; 593 struct bat_attribute **bat_attr; 594 int err; 595 596 *hardif_obj = kobject_create_and_add(SYSFS_IF_BAT_SUBDIR, 597 hardif_kobject); 598 599 if (!*hardif_obj) { 600 bat_err(dev, "Can't add sysfs directory: %s/%s\n", dev->name, 601 SYSFS_IF_BAT_SUBDIR); 602 goto out; 603 } 604 605 for (bat_attr = batman_attrs; *bat_attr; ++bat_attr) { 606 err = sysfs_create_file(*hardif_obj, &((*bat_attr)->attr)); 607 if (err) { 608 bat_err(dev, "Can't add sysfs file: %s/%s/%s\n", 609 dev->name, SYSFS_IF_BAT_SUBDIR, 610 ((*bat_attr)->attr).name); 611 goto rem_attr; 612 } 613 } 614 615 return 0; 616 617rem_attr: 618 for (bat_attr = batman_attrs; *bat_attr; ++bat_attr) 619 sysfs_remove_file(*hardif_obj, &((*bat_attr)->attr)); 620out: 621 return -ENOMEM; 622} 623 624void sysfs_del_hardif(struct kobject **hardif_obj) 625{ 626 kobject_put(*hardif_obj); 627 *hardif_obj = NULL; 628} 629 630int throw_uevent(struct bat_priv *bat_priv, enum uev_type type, 631 enum uev_action action, const char *data) 632{ 633 int ret = -1; 634 struct hard_iface *primary_if = NULL; 635 struct kobject *bat_kobj; 636 char *uevent_env[4] = { NULL, NULL, NULL, NULL }; 637 638 primary_if = primary_if_get_selected(bat_priv); 639 if (!primary_if) 640 goto out; 641 642 bat_kobj = &primary_if->soft_iface->dev.kobj; 643 644 uevent_env[0] = kmalloc(strlen(UEV_TYPE_VAR) + 645 strlen(uev_type_str[type]) + 1, 646 GFP_ATOMIC); 647 if (!uevent_env[0]) 648 goto out; 649 650 sprintf(uevent_env[0], "%s%s", UEV_TYPE_VAR, uev_type_str[type]); 651 652 uevent_env[1] = kmalloc(strlen(UEV_ACTION_VAR) + 653 strlen(uev_action_str[action]) + 1, 654 GFP_ATOMIC); 655 if (!uevent_env[1]) 656 goto out; 657 658 sprintf(uevent_env[1], "%s%s", UEV_ACTION_VAR, uev_action_str[action]); 659 660 /* If the event is DEL, ignore the data field */ 661 if (action != UEV_DEL) { 662 uevent_env[2] = kmalloc(strlen(UEV_DATA_VAR) + 663 strlen(data) + 1, GFP_ATOMIC); 664 if (!uevent_env[2]) 665 goto out; 666 667 sprintf(uevent_env[2], "%s%s", UEV_DATA_VAR, data); 668 } 669 670 ret = kobject_uevent_env(bat_kobj, KOBJ_CHANGE, uevent_env); 671out: 672 kfree(uevent_env[0]); 673 kfree(uevent_env[1]); 674 kfree(uevent_env[2]); 675 676 if (primary_if) 677 hardif_free_ref(primary_if); 678 679 if (ret) 680 bat_dbg(DBG_BATMAN, bat_priv, 681 "Impossible to send uevent for (%s,%s,%s) event (err: %d)\n", 682 uev_type_str[type], uev_action_str[action], 683 (action == UEV_DEL ? "NULL" : data), ret); 684 return ret; 685}