1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (C) 2010-2018 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, see <http://www.gnu.org/licenses/>. 17 */ 18 19 #include "sysfs.h" 20 #include "main.h" 21 22 #include <linux/atomic.h> 23 #include <linux/compiler.h> 24 #include <linux/device.h> 25 #include <linux/errno.h> 26 #include <linux/gfp.h> 27 #include <linux/if.h> 28 #include <linux/if_vlan.h> 29 #include <linux/kernel.h> 30 #include <linux/kobject.h> 31 #include <linux/kref.h> 32 #include <linux/netdevice.h> 33 #include <linux/printk.h> 34 #include <linux/rculist.h> 35 #include <linux/rcupdate.h> 36 #include <linux/rtnetlink.h> 37 #include <linux/slab.h> 38 #include <linux/stddef.h> 39 #include <linux/string.h> 40 #include <linux/stringify.h> 41 #include <linux/workqueue.h> 42 #include <uapi/linux/batadv_packet.h> 43 44 #include "bridge_loop_avoidance.h" 45 #include "distributed-arp-table.h" 46 #include "gateway_client.h" 47 #include "gateway_common.h" 48 #include "hard-interface.h" 49 #include "log.h" 50 #include "network-coding.h" 51 #include "soft-interface.h" 52 53 static struct net_device *batadv_kobj_to_netdev(struct kobject *obj) 54 { 55 struct device *dev = container_of(obj->parent, struct device, kobj); 56 57 return to_net_dev(dev); 58 } 59 60 static struct batadv_priv *batadv_kobj_to_batpriv(struct kobject *obj) 61 { 62 struct net_device *net_dev = batadv_kobj_to_netdev(obj); 63 64 return netdev_priv(net_dev); 65 } 66 67 /** 68 * batadv_vlan_kobj_to_batpriv() - convert a vlan kobj in the associated batpriv 69 * @obj: kobject to covert 70 * 71 * Return: the associated batadv_priv struct. 72 */ 73 static struct batadv_priv *batadv_vlan_kobj_to_batpriv(struct kobject *obj) 74 { 75 /* VLAN specific attributes are located in the root sysfs folder if they 76 * refer to the untagged VLAN.. 77 */ 78 if (!strcmp(BATADV_SYSFS_IF_MESH_SUBDIR, obj->name)) 79 return batadv_kobj_to_batpriv(obj); 80 81 /* ..while the attributes for the tagged vlans are located in 82 * the in the corresponding "vlan%VID" subfolder 83 */ 84 return batadv_kobj_to_batpriv(obj->parent); 85 } 86 87 /** 88 * batadv_kobj_to_vlan() - convert a kobj in the associated softif_vlan struct 89 * @bat_priv: the bat priv with all the soft interface information 90 * @obj: kobject to covert 91 * 92 * Return: the associated softif_vlan struct if found, NULL otherwise. 93 */ 94 static struct batadv_softif_vlan * 95 batadv_kobj_to_vlan(struct batadv_priv *bat_priv, struct kobject *obj) 96 { 97 struct batadv_softif_vlan *vlan_tmp, *vlan = NULL; 98 99 rcu_read_lock(); 100 hlist_for_each_entry_rcu(vlan_tmp, &bat_priv->softif_vlan_list, list) { 101 if (vlan_tmp->kobj != obj) 102 continue; 103 104 if (!kref_get_unless_zero(&vlan_tmp->refcount)) 105 continue; 106 107 vlan = vlan_tmp; 108 break; 109 } 110 rcu_read_unlock(); 111 112 return vlan; 113 } 114 115 #define BATADV_UEV_TYPE_VAR "BATTYPE=" 116 #define BATADV_UEV_ACTION_VAR "BATACTION=" 117 #define BATADV_UEV_DATA_VAR "BATDATA=" 118 119 static char *batadv_uev_action_str[] = { 120 "add", 121 "del", 122 "change", 123 "loopdetect", 124 }; 125 126 static char *batadv_uev_type_str[] = { 127 "gw", 128 "bla", 129 }; 130 131 /* Use this, if you have customized show and store functions for vlan attrs */ 132 #define BATADV_ATTR_VLAN(_name, _mode, _show, _store) \ 133 struct batadv_attribute batadv_attr_vlan_##_name = { \ 134 .attr = {.name = __stringify(_name), \ 135 .mode = _mode }, \ 136 .show = _show, \ 137 .store = _store, \ 138 } 139 140 /* Use this, if you have customized show and store functions */ 141 #define BATADV_ATTR(_name, _mode, _show, _store) \ 142 struct batadv_attribute batadv_attr_##_name = { \ 143 .attr = {.name = __stringify(_name), \ 144 .mode = _mode }, \ 145 .show = _show, \ 146 .store = _store, \ 147 } 148 149 #define BATADV_ATTR_SIF_STORE_BOOL(_name, _post_func) \ 150 ssize_t batadv_store_##_name(struct kobject *kobj, \ 151 struct attribute *attr, char *buff, \ 152 size_t count) \ 153 { \ 154 struct net_device *net_dev = batadv_kobj_to_netdev(kobj); \ 155 struct batadv_priv *bat_priv = netdev_priv(net_dev); \ 156 \ 157 return __batadv_store_bool_attr(buff, count, _post_func, attr, \ 158 &bat_priv->_name, net_dev); \ 159 } 160 161 #define BATADV_ATTR_SIF_SHOW_BOOL(_name) \ 162 ssize_t batadv_show_##_name(struct kobject *kobj, \ 163 struct attribute *attr, char *buff) \ 164 { \ 165 struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj); \ 166 \ 167 return sprintf(buff, "%s\n", \ 168 atomic_read(&bat_priv->_name) == 0 ? \ 169 "disabled" : "enabled"); \ 170 } \ 171 172 /* Use this, if you are going to turn a [name] in the soft-interface 173 * (bat_priv) on or off 174 */ 175 #define BATADV_ATTR_SIF_BOOL(_name, _mode, _post_func) \ 176 static BATADV_ATTR_SIF_STORE_BOOL(_name, _post_func) \ 177 static BATADV_ATTR_SIF_SHOW_BOOL(_name) \ 178 static BATADV_ATTR(_name, _mode, batadv_show_##_name, \ 179 batadv_store_##_name) 180 181 #define BATADV_ATTR_SIF_STORE_UINT(_name, _var, _min, _max, _post_func) \ 182 ssize_t batadv_store_##_name(struct kobject *kobj, \ 183 struct attribute *attr, char *buff, \ 184 size_t count) \ 185 { \ 186 struct net_device *net_dev = batadv_kobj_to_netdev(kobj); \ 187 struct batadv_priv *bat_priv = netdev_priv(net_dev); \ 188 \ 189 return __batadv_store_uint_attr(buff, count, _min, _max, \ 190 _post_func, attr, \ 191 &bat_priv->_var, net_dev); \ 192 } 193 194 #define BATADV_ATTR_SIF_SHOW_UINT(_name, _var) \ 195 ssize_t batadv_show_##_name(struct kobject *kobj, \ 196 struct attribute *attr, char *buff) \ 197 { \ 198 struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj); \ 199 \ 200 return sprintf(buff, "%i\n", atomic_read(&bat_priv->_var)); \ 201 } \ 202 203 /* Use this, if you are going to set [name] in the soft-interface 204 * (bat_priv) to an unsigned integer value 205 */ 206 #define BATADV_ATTR_SIF_UINT(_name, _var, _mode, _min, _max, _post_func)\ 207 static BATADV_ATTR_SIF_STORE_UINT(_name, _var, _min, _max, _post_func)\ 208 static BATADV_ATTR_SIF_SHOW_UINT(_name, _var) \ 209 static BATADV_ATTR(_name, _mode, batadv_show_##_name, \ 210 batadv_store_##_name) 211 212 #define BATADV_ATTR_VLAN_STORE_BOOL(_name, _post_func) \ 213 ssize_t batadv_store_vlan_##_name(struct kobject *kobj, \ 214 struct attribute *attr, char *buff, \ 215 size_t count) \ 216 { \ 217 struct batadv_priv *bat_priv = batadv_vlan_kobj_to_batpriv(kobj);\ 218 struct batadv_softif_vlan *vlan = batadv_kobj_to_vlan(bat_priv, \ 219 kobj); \ 220 size_t res = __batadv_store_bool_attr(buff, count, _post_func, \ 221 attr, &vlan->_name, \ 222 bat_priv->soft_iface); \ 223 \ 224 batadv_softif_vlan_put(vlan); \ 225 return res; \ 226 } 227 228 #define BATADV_ATTR_VLAN_SHOW_BOOL(_name) \ 229 ssize_t batadv_show_vlan_##_name(struct kobject *kobj, \ 230 struct attribute *attr, char *buff) \ 231 { \ 232 struct batadv_priv *bat_priv = batadv_vlan_kobj_to_batpriv(kobj);\ 233 struct batadv_softif_vlan *vlan = batadv_kobj_to_vlan(bat_priv, \ 234 kobj); \ 235 size_t res = sprintf(buff, "%s\n", \ 236 atomic_read(&vlan->_name) == 0 ? \ 237 "disabled" : "enabled"); \ 238 \ 239 batadv_softif_vlan_put(vlan); \ 240 return res; \ 241 } 242 243 /* Use this, if you are going to turn a [name] in the vlan struct on or off */ 244 #define BATADV_ATTR_VLAN_BOOL(_name, _mode, _post_func) \ 245 static BATADV_ATTR_VLAN_STORE_BOOL(_name, _post_func) \ 246 static BATADV_ATTR_VLAN_SHOW_BOOL(_name) \ 247 static BATADV_ATTR_VLAN(_name, _mode, batadv_show_vlan_##_name, \ 248 batadv_store_vlan_##_name) 249 250 #define BATADV_ATTR_HIF_STORE_UINT(_name, _var, _min, _max, _post_func) \ 251 ssize_t batadv_store_##_name(struct kobject *kobj, \ 252 struct attribute *attr, char *buff, \ 253 size_t count) \ 254 { \ 255 struct net_device *net_dev = batadv_kobj_to_netdev(kobj); \ 256 struct batadv_hard_iface *hard_iface; \ 257 ssize_t length; \ 258 \ 259 hard_iface = batadv_hardif_get_by_netdev(net_dev); \ 260 if (!hard_iface) \ 261 return 0; \ 262 \ 263 length = __batadv_store_uint_attr(buff, count, _min, _max, \ 264 _post_func, attr, \ 265 &hard_iface->_var, net_dev); \ 266 \ 267 batadv_hardif_put(hard_iface); \ 268 return length; \ 269 } 270 271 #define BATADV_ATTR_HIF_SHOW_UINT(_name, _var) \ 272 ssize_t batadv_show_##_name(struct kobject *kobj, \ 273 struct attribute *attr, char *buff) \ 274 { \ 275 struct net_device *net_dev = batadv_kobj_to_netdev(kobj); \ 276 struct batadv_hard_iface *hard_iface; \ 277 ssize_t length; \ 278 \ 279 hard_iface = batadv_hardif_get_by_netdev(net_dev); \ 280 if (!hard_iface) \ 281 return 0; \ 282 \ 283 length = sprintf(buff, "%i\n", atomic_read(&hard_iface->_var)); \ 284 \ 285 batadv_hardif_put(hard_iface); \ 286 return length; \ 287 } 288 289 /* Use this, if you are going to set [name] in hard_iface to an 290 * unsigned integer value 291 */ 292 #define BATADV_ATTR_HIF_UINT(_name, _var, _mode, _min, _max, _post_func)\ 293 static BATADV_ATTR_HIF_STORE_UINT(_name, _var, _min, \ 294 _max, _post_func) \ 295 static BATADV_ATTR_HIF_SHOW_UINT(_name, _var) \ 296 static BATADV_ATTR(_name, _mode, batadv_show_##_name, \ 297 batadv_store_##_name) 298 299 static int batadv_store_bool_attr(char *buff, size_t count, 300 struct net_device *net_dev, 301 const char *attr_name, atomic_t *attr, 302 bool *changed) 303 { 304 int enabled = -1; 305 306 *changed = false; 307 308 if (buff[count - 1] == '\n') 309 buff[count - 1] = '\0'; 310 311 if ((strncmp(buff, "1", 2) == 0) || 312 (strncmp(buff, "enable", 7) == 0) || 313 (strncmp(buff, "enabled", 8) == 0)) 314 enabled = 1; 315 316 if ((strncmp(buff, "", 2) == 0) || 317 (strncmp(buff, "disable", 8) == 0) || 318 (strncmp(buff, "disabled", 9) == 0)) 319 enabled = 0; 320 321 if (enabled < 0) { 322 batadv_info(net_dev, "%s: Invalid parameter received: %s\n", 323 attr_name, buff); 324 return -EINVAL; 325 } 326 327 if (atomic_read(attr) == enabled) 328 return count; 329 330 batadv_info(net_dev, "%s: Changing from: %s to: %s\n", attr_name, 331 atomic_read(attr) == 1 ? "enabled" : "disabled", 332 enabled == 1 ? "enabled" : "disabled"); 333 334 *changed = true; 335 336 atomic_set(attr, (unsigned int)enabled); 337 return count; 338 } 339 340 static inline ssize_t 341 __batadv_store_bool_attr(char *buff, size_t count, 342 void (*post_func)(struct net_device *), 343 struct attribute *attr, 344 atomic_t *attr_store, struct net_device *net_dev) 345 { 346 bool changed; 347 int ret; 348 349 ret = batadv_store_bool_attr(buff, count, net_dev, attr->name, 350 attr_store, &changed); 351 if (post_func && changed) 352 post_func(net_dev); 353 354 return ret; 355 } 356 357 static int batadv_store_uint_attr(const char *buff, size_t count, 358 struct net_device *net_dev, 359 const char *attr_name, 360 unsigned int min, unsigned int max, 361 atomic_t *attr) 362 { 363 unsigned long uint_val; 364 int ret; 365 366 ret = kstrtoul(buff, 10, &uint_val); 367 if (ret) { 368 batadv_info(net_dev, "%s: Invalid parameter received: %s\n", 369 attr_name, buff); 370 return -EINVAL; 371 } 372 373 if (uint_val < min) { 374 batadv_info(net_dev, "%s: Value is too small: %lu min: %u\n", 375 attr_name, uint_val, min); 376 return -EINVAL; 377 } 378 379 if (uint_val > max) { 380 batadv_info(net_dev, "%s: Value is too big: %lu max: %u\n", 381 attr_name, uint_val, max); 382 return -EINVAL; 383 } 384 385 if (atomic_read(attr) == uint_val) 386 return count; 387 388 batadv_info(net_dev, "%s: Changing from: %i to: %lu\n", 389 attr_name, atomic_read(attr), uint_val); 390 391 atomic_set(attr, uint_val); 392 return count; 393 } 394 395 static ssize_t __batadv_store_uint_attr(const char *buff, size_t count, 396 int min, int max, 397 void (*post_func)(struct net_device *), 398 const struct attribute *attr, 399 atomic_t *attr_store, 400 struct net_device *net_dev) 401 { 402 int ret; 403 404 ret = batadv_store_uint_attr(buff, count, net_dev, attr->name, min, max, 405 attr_store); 406 if (post_func && ret) 407 post_func(net_dev); 408 409 return ret; 410 } 411 412 static ssize_t batadv_show_bat_algo(struct kobject *kobj, 413 struct attribute *attr, char *buff) 414 { 415 struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj); 416 417 return sprintf(buff, "%s\n", bat_priv->algo_ops->name); 418 } 419 420 static void batadv_post_gw_reselect(struct net_device *net_dev) 421 { 422 struct batadv_priv *bat_priv = netdev_priv(net_dev); 423 424 batadv_gw_reselect(bat_priv); 425 } 426 427 static ssize_t batadv_show_gw_mode(struct kobject *kobj, struct attribute *attr, 428 char *buff) 429 { 430 struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj); 431 int bytes_written; 432 433 /* GW mode is not available if the routing algorithm in use does not 434 * implement the GW API 435 */ 436 if (!bat_priv->algo_ops->gw.get_best_gw_node || 437 !bat_priv->algo_ops->gw.is_eligible) 438 return -ENOENT; 439 440 switch (atomic_read(&bat_priv->gw.mode)) { 441 case BATADV_GW_MODE_CLIENT: 442 bytes_written = sprintf(buff, "%s\n", 443 BATADV_GW_MODE_CLIENT_NAME); 444 break; 445 case BATADV_GW_MODE_SERVER: 446 bytes_written = sprintf(buff, "%s\n", 447 BATADV_GW_MODE_SERVER_NAME); 448 break; 449 default: 450 bytes_written = sprintf(buff, "%s\n", 451 BATADV_GW_MODE_OFF_NAME); 452 break; 453 } 454 455 return bytes_written; 456 } 457 458 static ssize_t batadv_store_gw_mode(struct kobject *kobj, 459 struct attribute *attr, char *buff, 460 size_t count) 461 { 462 struct net_device *net_dev = batadv_kobj_to_netdev(kobj); 463 struct batadv_priv *bat_priv = netdev_priv(net_dev); 464 char *curr_gw_mode_str; 465 int gw_mode_tmp = -1; 466 467 /* toggling GW mode is allowed only if the routing algorithm in use 468 * provides the GW API 469 */ 470 if (!bat_priv->algo_ops->gw.get_best_gw_node || 471 !bat_priv->algo_ops->gw.is_eligible) 472 return -EINVAL; 473 474 if (buff[count - 1] == '\n') 475 buff[count - 1] = '\0'; 476 477 if (strncmp(buff, BATADV_GW_MODE_OFF_NAME, 478 strlen(BATADV_GW_MODE_OFF_NAME)) == 0) 479 gw_mode_tmp = BATADV_GW_MODE_OFF; 480 481 if (strncmp(buff, BATADV_GW_MODE_CLIENT_NAME, 482 strlen(BATADV_GW_MODE_CLIENT_NAME)) == 0) 483 gw_mode_tmp = BATADV_GW_MODE_CLIENT; 484 485 if (strncmp(buff, BATADV_GW_MODE_SERVER_NAME, 486 strlen(BATADV_GW_MODE_SERVER_NAME)) == 0) 487 gw_mode_tmp = BATADV_GW_MODE_SERVER; 488 489 if (gw_mode_tmp < 0) { 490 batadv_info(net_dev, 491 "Invalid parameter for 'gw mode' setting received: %s\n", 492 buff); 493 return -EINVAL; 494 } 495 496 if (atomic_read(&bat_priv->gw.mode) == gw_mode_tmp) 497 return count; 498 499 switch (atomic_read(&bat_priv->gw.mode)) { 500 case BATADV_GW_MODE_CLIENT: 501 curr_gw_mode_str = BATADV_GW_MODE_CLIENT_NAME; 502 break; 503 case BATADV_GW_MODE_SERVER: 504 curr_gw_mode_str = BATADV_GW_MODE_SERVER_NAME; 505 break; 506 default: 507 curr_gw_mode_str = BATADV_GW_MODE_OFF_NAME; 508 break; 509 } 510 511 batadv_info(net_dev, "Changing gw mode from: %s to: %s\n", 512 curr_gw_mode_str, buff); 513 514 /* Invoking batadv_gw_reselect() is not enough to really de-select the 515 * current GW. It will only instruct the gateway client code to perform 516 * a re-election the next time that this is needed. 517 * 518 * When gw client mode is being switched off the current GW must be 519 * de-selected explicitly otherwise no GW_ADD uevent is thrown on 520 * client mode re-activation. This is operation is performed in 521 * batadv_gw_check_client_stop(). 522 */ 523 batadv_gw_reselect(bat_priv); 524 /* always call batadv_gw_check_client_stop() before changing the gateway 525 * state 526 */ 527 batadv_gw_check_client_stop(bat_priv); 528 atomic_set(&bat_priv->gw.mode, (unsigned int)gw_mode_tmp); 529 batadv_gw_tvlv_container_update(bat_priv); 530 return count; 531 } 532 533 static ssize_t batadv_show_gw_sel_class(struct kobject *kobj, 534 struct attribute *attr, char *buff) 535 { 536 struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj); 537 538 /* GW selection class is not available if the routing algorithm in use 539 * does not implement the GW API 540 */ 541 if (!bat_priv->algo_ops->gw.get_best_gw_node || 542 !bat_priv->algo_ops->gw.is_eligible) 543 return -ENOENT; 544 545 if (bat_priv->algo_ops->gw.show_sel_class) 546 return bat_priv->algo_ops->gw.show_sel_class(bat_priv, buff); 547 548 return sprintf(buff, "%i\n", atomic_read(&bat_priv->gw.sel_class)); 549 } 550 551 static ssize_t batadv_store_gw_sel_class(struct kobject *kobj, 552 struct attribute *attr, char *buff, 553 size_t count) 554 { 555 struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj); 556 557 /* setting the GW selection class is allowed only if the routing 558 * algorithm in use implements the GW API 559 */ 560 if (!bat_priv->algo_ops->gw.get_best_gw_node || 561 !bat_priv->algo_ops->gw.is_eligible) 562 return -EINVAL; 563 564 if (buff[count - 1] == '\n') 565 buff[count - 1] = '\0'; 566 567 if (bat_priv->algo_ops->gw.store_sel_class) 568 return bat_priv->algo_ops->gw.store_sel_class(bat_priv, buff, 569 count); 570 571 return __batadv_store_uint_attr(buff, count, 1, BATADV_TQ_MAX_VALUE, 572 batadv_post_gw_reselect, attr, 573 &bat_priv->gw.sel_class, 574 bat_priv->soft_iface); 575 } 576 577 static ssize_t batadv_show_gw_bwidth(struct kobject *kobj, 578 struct attribute *attr, char *buff) 579 { 580 struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj); 581 u32 down, up; 582 583 down = atomic_read(&bat_priv->gw.bandwidth_down); 584 up = atomic_read(&bat_priv->gw.bandwidth_up); 585 586 return sprintf(buff, "%u.%u/%u.%u MBit\n", down / 10, 587 down % 10, up / 10, up % 10); 588 } 589 590 static ssize_t batadv_store_gw_bwidth(struct kobject *kobj, 591 struct attribute *attr, char *buff, 592 size_t count) 593 { 594 struct net_device *net_dev = batadv_kobj_to_netdev(kobj); 595 596 if (buff[count - 1] == '\n') 597 buff[count - 1] = '\0'; 598 599 return batadv_gw_bandwidth_set(net_dev, buff, count); 600 } 601 602 /** 603 * batadv_show_isolation_mark() - print the current isolation mark/mask 604 * @kobj: kobject representing the private mesh sysfs directory 605 * @attr: the batman-adv attribute the user is interacting with 606 * @buff: the buffer that will contain the data to send back to the user 607 * 608 * Return: the number of bytes written into 'buff' on success or a negative 609 * error code in case of failure 610 */ 611 static ssize_t batadv_show_isolation_mark(struct kobject *kobj, 612 struct attribute *attr, char *buff) 613 { 614 struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj); 615 616 return sprintf(buff, "%#.8x/%#.8x\n", bat_priv->isolation_mark, 617 bat_priv->isolation_mark_mask); 618 } 619 620 /** 621 * batadv_store_isolation_mark() - parse and store the isolation mark/mask 622 * entered by the user 623 * @kobj: kobject representing the private mesh sysfs directory 624 * @attr: the batman-adv attribute the user is interacting with 625 * @buff: the buffer containing the user data 626 * @count: number of bytes in the buffer 627 * 628 * Return: 'count' on success or a negative error code in case of failure 629 */ 630 static ssize_t batadv_store_isolation_mark(struct kobject *kobj, 631 struct attribute *attr, char *buff, 632 size_t count) 633 { 634 struct net_device *net_dev = batadv_kobj_to_netdev(kobj); 635 struct batadv_priv *bat_priv = netdev_priv(net_dev); 636 u32 mark, mask; 637 char *mask_ptr; 638 639 /* parse the mask if it has been specified, otherwise assume the mask is 640 * the biggest possible 641 */ 642 mask = 0xFFFFFFFF; 643 mask_ptr = strchr(buff, '/'); 644 if (mask_ptr) { 645 *mask_ptr = '\0'; 646 mask_ptr++; 647 648 /* the mask must be entered in hex base as it is going to be a 649 * bitmask and not a prefix length 650 */ 651 if (kstrtou32(mask_ptr, 16, &mask) < 0) 652 return -EINVAL; 653 } 654 655 /* the mark can be entered in any base */ 656 if (kstrtou32(buff, 0, &mark) < 0) 657 return -EINVAL; 658 659 bat_priv->isolation_mark_mask = mask; 660 /* erase bits not covered by the mask */ 661 bat_priv->isolation_mark = mark & bat_priv->isolation_mark_mask; 662 663 batadv_info(net_dev, 664 "New skb mark for extended isolation: %#.8x/%#.8x\n", 665 bat_priv->isolation_mark, bat_priv->isolation_mark_mask); 666 667 return count; 668 } 669 670 BATADV_ATTR_SIF_BOOL(aggregated_ogms, 0644, NULL); 671 BATADV_ATTR_SIF_BOOL(bonding, 0644, NULL); 672 #ifdef CONFIG_BATMAN_ADV_BLA 673 BATADV_ATTR_SIF_BOOL(bridge_loop_avoidance, 0644, batadv_bla_status_update); 674 #endif 675 #ifdef CONFIG_BATMAN_ADV_DAT 676 BATADV_ATTR_SIF_BOOL(distributed_arp_table, 0644, batadv_dat_status_update); 677 #endif 678 BATADV_ATTR_SIF_BOOL(fragmentation, 0644, batadv_update_min_mtu); 679 static BATADV_ATTR(routing_algo, 0444, batadv_show_bat_algo, NULL); 680 static BATADV_ATTR(gw_mode, 0644, batadv_show_gw_mode, batadv_store_gw_mode); 681 BATADV_ATTR_SIF_UINT(orig_interval, orig_interval, 0644, 2 * BATADV_JITTER, 682 INT_MAX, NULL); 683 BATADV_ATTR_SIF_UINT(hop_penalty, hop_penalty, 0644, 0, BATADV_TQ_MAX_VALUE, 684 NULL); 685 static BATADV_ATTR(gw_sel_class, 0644, batadv_show_gw_sel_class, 686 batadv_store_gw_sel_class); 687 static BATADV_ATTR(gw_bandwidth, 0644, batadv_show_gw_bwidth, 688 batadv_store_gw_bwidth); 689 #ifdef CONFIG_BATMAN_ADV_MCAST 690 BATADV_ATTR_SIF_BOOL(multicast_mode, 0644, NULL); 691 #endif 692 #ifdef CONFIG_BATMAN_ADV_DEBUG 693 BATADV_ATTR_SIF_UINT(log_level, log_level, 0644, 0, BATADV_DBG_ALL, NULL); 694 #endif 695 #ifdef CONFIG_BATMAN_ADV_NC 696 BATADV_ATTR_SIF_BOOL(network_coding, 0644, batadv_nc_status_update); 697 #endif 698 static BATADV_ATTR(isolation_mark, 0644, batadv_show_isolation_mark, 699 batadv_store_isolation_mark); 700 701 static struct batadv_attribute *batadv_mesh_attrs[] = { 702 &batadv_attr_aggregated_ogms, 703 &batadv_attr_bonding, 704 #ifdef CONFIG_BATMAN_ADV_BLA 705 &batadv_attr_bridge_loop_avoidance, 706 #endif 707 #ifdef CONFIG_BATMAN_ADV_DAT 708 &batadv_attr_distributed_arp_table, 709 #endif 710 #ifdef CONFIG_BATMAN_ADV_MCAST 711 &batadv_attr_multicast_mode, 712 #endif 713 &batadv_attr_fragmentation, 714 &batadv_attr_routing_algo, 715 &batadv_attr_gw_mode, 716 &batadv_attr_orig_interval, 717 &batadv_attr_hop_penalty, 718 &batadv_attr_gw_sel_class, 719 &batadv_attr_gw_bandwidth, 720 #ifdef CONFIG_BATMAN_ADV_DEBUG 721 &batadv_attr_log_level, 722 #endif 723 #ifdef CONFIG_BATMAN_ADV_NC 724 &batadv_attr_network_coding, 725 #endif 726 &batadv_attr_isolation_mark, 727 NULL, 728 }; 729 730 BATADV_ATTR_VLAN_BOOL(ap_isolation, 0644, NULL); 731 732 /* array of vlan specific sysfs attributes */ 733 static struct batadv_attribute *batadv_vlan_attrs[] = { 734 &batadv_attr_vlan_ap_isolation, 735 NULL, 736 }; 737 738 /** 739 * batadv_sysfs_add_meshif() - Add soft interface specific sysfs entries 740 * @dev: netdev struct of the soft interface 741 * 742 * Return: 0 on success or negative error number in case of failure 743 */ 744 int batadv_sysfs_add_meshif(struct net_device *dev) 745 { 746 struct kobject *batif_kobject = &dev->dev.kobj; 747 struct batadv_priv *bat_priv = netdev_priv(dev); 748 struct batadv_attribute **bat_attr; 749 int err; 750 751 bat_priv->mesh_obj = kobject_create_and_add(BATADV_SYSFS_IF_MESH_SUBDIR, 752 batif_kobject); 753 if (!bat_priv->mesh_obj) { 754 batadv_err(dev, "Can't add sysfs directory: %s/%s\n", dev->name, 755 BATADV_SYSFS_IF_MESH_SUBDIR); 756 goto out; 757 } 758 759 for (bat_attr = batadv_mesh_attrs; *bat_attr; ++bat_attr) { 760 err = sysfs_create_file(bat_priv->mesh_obj, 761 &((*bat_attr)->attr)); 762 if (err) { 763 batadv_err(dev, "Can't add sysfs file: %s/%s/%s\n", 764 dev->name, BATADV_SYSFS_IF_MESH_SUBDIR, 765 ((*bat_attr)->attr).name); 766 goto rem_attr; 767 } 768 } 769 770 return 0; 771 772 rem_attr: 773 for (bat_attr = batadv_mesh_attrs; *bat_attr; ++bat_attr) 774 sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr)); 775 776 kobject_uevent(bat_priv->mesh_obj, KOBJ_REMOVE); 777 kobject_del(bat_priv->mesh_obj); 778 kobject_put(bat_priv->mesh_obj); 779 bat_priv->mesh_obj = NULL; 780 out: 781 return -ENOMEM; 782 } 783 784 /** 785 * batadv_sysfs_del_meshif() - Remove soft interface specific sysfs entries 786 * @dev: netdev struct of the soft interface 787 */ 788 void batadv_sysfs_del_meshif(struct net_device *dev) 789 { 790 struct batadv_priv *bat_priv = netdev_priv(dev); 791 struct batadv_attribute **bat_attr; 792 793 for (bat_attr = batadv_mesh_attrs; *bat_attr; ++bat_attr) 794 sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr)); 795 796 kobject_uevent(bat_priv->mesh_obj, KOBJ_REMOVE); 797 kobject_del(bat_priv->mesh_obj); 798 kobject_put(bat_priv->mesh_obj); 799 bat_priv->mesh_obj = NULL; 800 } 801 802 /** 803 * batadv_sysfs_add_vlan() - add all the needed sysfs objects for the new vlan 804 * @dev: netdev of the mesh interface 805 * @vlan: private data of the newly added VLAN interface 806 * 807 * Return: 0 on success and -ENOMEM if any of the structure allocations fails. 808 */ 809 int batadv_sysfs_add_vlan(struct net_device *dev, 810 struct batadv_softif_vlan *vlan) 811 { 812 char vlan_subdir[sizeof(BATADV_SYSFS_VLAN_SUBDIR_PREFIX) + 5]; 813 struct batadv_priv *bat_priv = netdev_priv(dev); 814 struct batadv_attribute **bat_attr; 815 int err; 816 817 if (vlan->vid & BATADV_VLAN_HAS_TAG) { 818 sprintf(vlan_subdir, BATADV_SYSFS_VLAN_SUBDIR_PREFIX "%hu", 819 vlan->vid & VLAN_VID_MASK); 820 821 vlan->kobj = kobject_create_and_add(vlan_subdir, 822 bat_priv->mesh_obj); 823 if (!vlan->kobj) { 824 batadv_err(dev, "Can't add sysfs directory: %s/%s\n", 825 dev->name, vlan_subdir); 826 goto out; 827 } 828 } else { 829 /* the untagged LAN uses the root folder to store its "VLAN 830 * specific attributes" 831 */ 832 vlan->kobj = bat_priv->mesh_obj; 833 kobject_get(bat_priv->mesh_obj); 834 } 835 836 for (bat_attr = batadv_vlan_attrs; *bat_attr; ++bat_attr) { 837 err = sysfs_create_file(vlan->kobj, 838 &((*bat_attr)->attr)); 839 if (err) { 840 batadv_err(dev, "Can't add sysfs file: %s/%s/%s\n", 841 dev->name, vlan_subdir, 842 ((*bat_attr)->attr).name); 843 goto rem_attr; 844 } 845 } 846 847 return 0; 848 849 rem_attr: 850 for (bat_attr = batadv_vlan_attrs; *bat_attr; ++bat_attr) 851 sysfs_remove_file(vlan->kobj, &((*bat_attr)->attr)); 852 853 if (vlan->kobj != bat_priv->mesh_obj) { 854 kobject_uevent(vlan->kobj, KOBJ_REMOVE); 855 kobject_del(vlan->kobj); 856 } 857 kobject_put(vlan->kobj); 858 vlan->kobj = NULL; 859 out: 860 return -ENOMEM; 861 } 862 863 /** 864 * batadv_sysfs_del_vlan() - remove all the sysfs objects for a given VLAN 865 * @bat_priv: the bat priv with all the soft interface information 866 * @vlan: the private data of the VLAN to destroy 867 */ 868 void batadv_sysfs_del_vlan(struct batadv_priv *bat_priv, 869 struct batadv_softif_vlan *vlan) 870 { 871 struct batadv_attribute **bat_attr; 872 873 for (bat_attr = batadv_vlan_attrs; *bat_attr; ++bat_attr) 874 sysfs_remove_file(vlan->kobj, &((*bat_attr)->attr)); 875 876 if (vlan->kobj != bat_priv->mesh_obj) { 877 kobject_uevent(vlan->kobj, KOBJ_REMOVE); 878 kobject_del(vlan->kobj); 879 } 880 kobject_put(vlan->kobj); 881 vlan->kobj = NULL; 882 } 883 884 static ssize_t batadv_show_mesh_iface(struct kobject *kobj, 885 struct attribute *attr, char *buff) 886 { 887 struct net_device *net_dev = batadv_kobj_to_netdev(kobj); 888 struct batadv_hard_iface *hard_iface; 889 ssize_t length; 890 const char *ifname; 891 892 hard_iface = batadv_hardif_get_by_netdev(net_dev); 893 if (!hard_iface) 894 return 0; 895 896 if (hard_iface->if_status == BATADV_IF_NOT_IN_USE) 897 ifname = "none"; 898 else 899 ifname = hard_iface->soft_iface->name; 900 901 length = sprintf(buff, "%s\n", ifname); 902 903 batadv_hardif_put(hard_iface); 904 905 return length; 906 } 907 908 /** 909 * batadv_store_mesh_iface_finish() - store new hardif mesh_iface state 910 * @net_dev: netdevice to add/remove to/from batman-adv soft-interface 911 * @ifname: name of soft-interface to modify 912 * 913 * Changes the parts of the hard+soft interface which can not be modified under 914 * sysfs lock (to prevent deadlock situations). 915 * 916 * Return: 0 on success, 0 < on failure 917 */ 918 static int batadv_store_mesh_iface_finish(struct net_device *net_dev, 919 char ifname[IFNAMSIZ]) 920 { 921 struct net *net = dev_net(net_dev); 922 struct batadv_hard_iface *hard_iface; 923 int status_tmp; 924 int ret = 0; 925 926 ASSERT_RTNL(); 927 928 hard_iface = batadv_hardif_get_by_netdev(net_dev); 929 if (!hard_iface) 930 return 0; 931 932 if (strncmp(ifname, "none", 4) == 0) 933 status_tmp = BATADV_IF_NOT_IN_USE; 934 else 935 status_tmp = BATADV_IF_I_WANT_YOU; 936 937 if (hard_iface->if_status == status_tmp) 938 goto out; 939 940 if (hard_iface->soft_iface && 941 strncmp(hard_iface->soft_iface->name, ifname, IFNAMSIZ) == 0) 942 goto out; 943 944 if (status_tmp == BATADV_IF_NOT_IN_USE) { 945 batadv_hardif_disable_interface(hard_iface, 946 BATADV_IF_CLEANUP_AUTO); 947 goto out; 948 } 949 950 /* if the interface already is in use */ 951 if (hard_iface->if_status != BATADV_IF_NOT_IN_USE) 952 batadv_hardif_disable_interface(hard_iface, 953 BATADV_IF_CLEANUP_AUTO); 954 955 ret = batadv_hardif_enable_interface(hard_iface, net, ifname); 956 out: 957 batadv_hardif_put(hard_iface); 958 return ret; 959 } 960 961 /** 962 * batadv_store_mesh_iface_work() - store new hardif mesh_iface state 963 * @work: work queue item 964 * 965 * Changes the parts of the hard+soft interface which can not be modified under 966 * sysfs lock (to prevent deadlock situations). 967 */ 968 static void batadv_store_mesh_iface_work(struct work_struct *work) 969 { 970 struct batadv_store_mesh_work *store_work; 971 int ret; 972 973 store_work = container_of(work, struct batadv_store_mesh_work, work); 974 975 rtnl_lock(); 976 ret = batadv_store_mesh_iface_finish(store_work->net_dev, 977 store_work->soft_iface_name); 978 rtnl_unlock(); 979 980 if (ret < 0) 981 pr_err("Failed to store new mesh_iface state %s for %s: %d\n", 982 store_work->soft_iface_name, store_work->net_dev->name, 983 ret); 984 985 dev_put(store_work->net_dev); 986 kfree(store_work); 987 } 988 989 static ssize_t batadv_store_mesh_iface(struct kobject *kobj, 990 struct attribute *attr, char *buff, 991 size_t count) 992 { 993 struct net_device *net_dev = batadv_kobj_to_netdev(kobj); 994 struct batadv_store_mesh_work *store_work; 995 996 if (buff[count - 1] == '\n') 997 buff[count - 1] = '\0'; 998 999 if (strlen(buff) >= IFNAMSIZ) { 1000 pr_err("Invalid parameter for 'mesh_iface' setting received: interface name too long '%s'\n", 1001 buff); 1002 return -EINVAL; 1003 } 1004 1005 store_work = kmalloc(sizeof(*store_work), GFP_KERNEL); 1006 if (!store_work) 1007 return -ENOMEM; 1008 1009 dev_hold(net_dev); 1010 INIT_WORK(&store_work->work, batadv_store_mesh_iface_work); 1011 store_work->net_dev = net_dev; 1012 strlcpy(store_work->soft_iface_name, buff, 1013 sizeof(store_work->soft_iface_name)); 1014 1015 queue_work(batadv_event_workqueue, &store_work->work); 1016 1017 return count; 1018 } 1019 1020 static ssize_t batadv_show_iface_status(struct kobject *kobj, 1021 struct attribute *attr, char *buff) 1022 { 1023 struct net_device *net_dev = batadv_kobj_to_netdev(kobj); 1024 struct batadv_hard_iface *hard_iface; 1025 ssize_t length; 1026 1027 hard_iface = batadv_hardif_get_by_netdev(net_dev); 1028 if (!hard_iface) 1029 return 0; 1030 1031 switch (hard_iface->if_status) { 1032 case BATADV_IF_TO_BE_REMOVED: 1033 length = sprintf(buff, "disabling\n"); 1034 break; 1035 case BATADV_IF_INACTIVE: 1036 length = sprintf(buff, "inactive\n"); 1037 break; 1038 case BATADV_IF_ACTIVE: 1039 length = sprintf(buff, "active\n"); 1040 break; 1041 case BATADV_IF_TO_BE_ACTIVATED: 1042 length = sprintf(buff, "enabling\n"); 1043 break; 1044 case BATADV_IF_NOT_IN_USE: 1045 default: 1046 length = sprintf(buff, "not in use\n"); 1047 break; 1048 } 1049 1050 batadv_hardif_put(hard_iface); 1051 1052 return length; 1053 } 1054 1055 #ifdef CONFIG_BATMAN_ADV_BATMAN_V 1056 1057 /** 1058 * batadv_store_throughput_override() - parse and store throughput override 1059 * entered by the user 1060 * @kobj: kobject representing the private mesh sysfs directory 1061 * @attr: the batman-adv attribute the user is interacting with 1062 * @buff: the buffer containing the user data 1063 * @count: number of bytes in the buffer 1064 * 1065 * Return: 'count' on success or a negative error code in case of failure 1066 */ 1067 static ssize_t batadv_store_throughput_override(struct kobject *kobj, 1068 struct attribute *attr, 1069 char *buff, size_t count) 1070 { 1071 struct net_device *net_dev = batadv_kobj_to_netdev(kobj); 1072 struct batadv_hard_iface *hard_iface; 1073 u32 tp_override; 1074 u32 old_tp_override; 1075 bool ret; 1076 1077 hard_iface = batadv_hardif_get_by_netdev(net_dev); 1078 if (!hard_iface) 1079 return -EINVAL; 1080 1081 if (buff[count - 1] == '\n') 1082 buff[count - 1] = '\0'; 1083 1084 ret = batadv_parse_throughput(net_dev, buff, "throughput_override", 1085 &tp_override); 1086 if (!ret) 1087 return count; 1088 1089 old_tp_override = atomic_read(&hard_iface->bat_v.throughput_override); 1090 if (old_tp_override == tp_override) 1091 goto out; 1092 1093 batadv_info(net_dev, "%s: Changing from: %u.%u MBit to: %u.%u MBit\n", 1094 "throughput_override", 1095 old_tp_override / 10, old_tp_override % 10, 1096 tp_override / 10, tp_override % 10); 1097 1098 atomic_set(&hard_iface->bat_v.throughput_override, tp_override); 1099 1100 out: 1101 batadv_hardif_put(hard_iface); 1102 return count; 1103 } 1104 1105 static ssize_t batadv_show_throughput_override(struct kobject *kobj, 1106 struct attribute *attr, 1107 char *buff) 1108 { 1109 struct net_device *net_dev = batadv_kobj_to_netdev(kobj); 1110 struct batadv_hard_iface *hard_iface; 1111 u32 tp_override; 1112 1113 hard_iface = batadv_hardif_get_by_netdev(net_dev); 1114 if (!hard_iface) 1115 return -EINVAL; 1116 1117 tp_override = atomic_read(&hard_iface->bat_v.throughput_override); 1118 1119 return sprintf(buff, "%u.%u MBit\n", tp_override / 10, 1120 tp_override % 10); 1121 } 1122 1123 #endif 1124 1125 static BATADV_ATTR(mesh_iface, 0644, batadv_show_mesh_iface, 1126 batadv_store_mesh_iface); 1127 static BATADV_ATTR(iface_status, 0444, batadv_show_iface_status, NULL); 1128 #ifdef CONFIG_BATMAN_ADV_BATMAN_V 1129 BATADV_ATTR_HIF_UINT(elp_interval, bat_v.elp_interval, 0644, 1130 2 * BATADV_JITTER, INT_MAX, NULL); 1131 static BATADV_ATTR(throughput_override, 0644, batadv_show_throughput_override, 1132 batadv_store_throughput_override); 1133 #endif 1134 1135 static struct batadv_attribute *batadv_batman_attrs[] = { 1136 &batadv_attr_mesh_iface, 1137 &batadv_attr_iface_status, 1138 #ifdef CONFIG_BATMAN_ADV_BATMAN_V 1139 &batadv_attr_elp_interval, 1140 &batadv_attr_throughput_override, 1141 #endif 1142 NULL, 1143 }; 1144 1145 /** 1146 * batadv_sysfs_add_hardif() - Add hard interface specific sysfs entries 1147 * @hardif_obj: address where to store the pointer to new sysfs folder 1148 * @dev: netdev struct of the hard interface 1149 * 1150 * Return: 0 on success or negative error number in case of failure 1151 */ 1152 int batadv_sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev) 1153 { 1154 struct kobject *hardif_kobject = &dev->dev.kobj; 1155 struct batadv_attribute **bat_attr; 1156 int err; 1157 1158 *hardif_obj = kobject_create_and_add(BATADV_SYSFS_IF_BAT_SUBDIR, 1159 hardif_kobject); 1160 1161 if (!*hardif_obj) { 1162 batadv_err(dev, "Can't add sysfs directory: %s/%s\n", dev->name, 1163 BATADV_SYSFS_IF_BAT_SUBDIR); 1164 goto out; 1165 } 1166 1167 for (bat_attr = batadv_batman_attrs; *bat_attr; ++bat_attr) { 1168 err = sysfs_create_file(*hardif_obj, &((*bat_attr)->attr)); 1169 if (err) { 1170 batadv_err(dev, "Can't add sysfs file: %s/%s/%s\n", 1171 dev->name, BATADV_SYSFS_IF_BAT_SUBDIR, 1172 ((*bat_attr)->attr).name); 1173 goto rem_attr; 1174 } 1175 } 1176 1177 return 0; 1178 1179 rem_attr: 1180 for (bat_attr = batadv_batman_attrs; *bat_attr; ++bat_attr) 1181 sysfs_remove_file(*hardif_obj, &((*bat_attr)->attr)); 1182 out: 1183 return -ENOMEM; 1184 } 1185 1186 /** 1187 * batadv_sysfs_del_hardif() - Remove hard interface specific sysfs entries 1188 * @hardif_obj: address to the pointer to which stores batman-adv sysfs folder 1189 * of the hard interface 1190 */ 1191 void batadv_sysfs_del_hardif(struct kobject **hardif_obj) 1192 { 1193 kobject_uevent(*hardif_obj, KOBJ_REMOVE); 1194 kobject_del(*hardif_obj); 1195 kobject_put(*hardif_obj); 1196 *hardif_obj = NULL; 1197 } 1198 1199 /** 1200 * batadv_throw_uevent() - Send an uevent with batman-adv specific env data 1201 * @bat_priv: the bat priv with all the soft interface information 1202 * @type: subsystem type of event. Stored in uevent's BATTYPE 1203 * @action: action type of event. Stored in uevent's BATACTION 1204 * @data: string with additional information to the event (ignored for 1205 * BATADV_UEV_DEL). Stored in uevent's BATDATA 1206 * 1207 * Return: 0 on success or negative error number in case of failure 1208 */ 1209 int batadv_throw_uevent(struct batadv_priv *bat_priv, enum batadv_uev_type type, 1210 enum batadv_uev_action action, const char *data) 1211 { 1212 int ret = -ENOMEM; 1213 struct kobject *bat_kobj; 1214 char *uevent_env[4] = { NULL, NULL, NULL, NULL }; 1215 1216 bat_kobj = &bat_priv->soft_iface->dev.kobj; 1217 1218 uevent_env[0] = kasprintf(GFP_ATOMIC, 1219 "%s%s", BATADV_UEV_TYPE_VAR, 1220 batadv_uev_type_str[type]); 1221 if (!uevent_env[0]) 1222 goto out; 1223 1224 uevent_env[1] = kasprintf(GFP_ATOMIC, 1225 "%s%s", BATADV_UEV_ACTION_VAR, 1226 batadv_uev_action_str[action]); 1227 if (!uevent_env[1]) 1228 goto out; 1229 1230 /* If the event is DEL, ignore the data field */ 1231 if (action != BATADV_UEV_DEL) { 1232 uevent_env[2] = kasprintf(GFP_ATOMIC, 1233 "%s%s", BATADV_UEV_DATA_VAR, data); 1234 if (!uevent_env[2]) 1235 goto out; 1236 } 1237 1238 ret = kobject_uevent_env(bat_kobj, KOBJ_CHANGE, uevent_env); 1239 out: 1240 kfree(uevent_env[0]); 1241 kfree(uevent_env[1]); 1242 kfree(uevent_env[2]); 1243 1244 if (ret) 1245 batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 1246 "Impossible to send uevent for (%s,%s,%s) event (err: %d)\n", 1247 batadv_uev_type_str[type], 1248 batadv_uev_action_str[action], 1249 (action == BATADV_UEV_DEL ? "NULL" : data), ret); 1250 return ret; 1251 } 1252
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.