1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (C) B.A.T.M.A.N. contributors: 3 * 4 * Marek Lindner, Simon Wunderlich 5 */ 6 7 #include "originator.h" 8 #include "main.h" 9 10 #include <linux/atomic.h> 11 #include <linux/container_of.h> 12 #include <linux/errno.h> 13 #include <linux/etherdevice.h> 14 #include <linux/gfp.h> 15 #include <linux/if_vlan.h> 16 #include <linux/jiffies.h> 17 #include <linux/kref.h> 18 #include <linux/list.h> 19 #include <linux/lockdep.h> 20 #include <linux/netdevice.h> 21 #include <linux/netlink.h> 22 #include <linux/rculist.h> 23 #include <linux/rcupdate.h> 24 #include <linux/skbuff.h> 25 #include <linux/slab.h> 26 #include <linux/spinlock.h> 27 #include <linux/stddef.h> 28 #include <linux/workqueue.h> 29 #include <net/sock.h> 30 #include <uapi/linux/batadv_packet.h> 31 #include <uapi/linux/batman_adv.h> 32 33 #include "bat_algo.h" 34 #include "distributed-arp-table.h" 35 #include "fragmentation.h" 36 #include "gateway_client.h" 37 #include "hard-interface.h" 38 #include "hash.h" 39 #include "log.h" 40 #include "multicast.h" 41 #include "netlink.h" 42 #include "network-coding.h" 43 #include "routing.h" 44 #include "soft-interface.h" 45 #include "translation-table.h" 46 47 /* hash class keys */ 48 static struct lock_class_key batadv_orig_hash_lock_class_key; 49 50 /** 51 * batadv_orig_hash_find() - Find and return originator from orig_hash 52 * @bat_priv: the bat priv with all the soft interface information 53 * @data: mac address of the originator 54 * 55 * Return: orig_node (with increased refcnt), NULL on errors 56 */ 57 struct batadv_orig_node * 58 batadv_orig_hash_find(struct batadv_priv *bat_priv, const void *data) 59 { 60 struct batadv_hashtable *hash = bat_priv->orig_hash; 61 struct hlist_head *head; 62 struct batadv_orig_node *orig_node, *orig_node_tmp = NULL; 63 int index; 64 65 if (!hash) 66 return NULL; 67 68 index = batadv_choose_orig(data, hash->size); 69 head = &hash->table[index]; 70 71 rcu_read_lock(); 72 hlist_for_each_entry_rcu(orig_node, head, hash_entry) { 73 if (!batadv_compare_eth(orig_node, data)) 74 continue; 75 76 if (!kref_get_unless_zero(&orig_node->refcount)) 77 continue; 78 79 orig_node_tmp = orig_node; 80 break; 81 } 82 rcu_read_unlock(); 83 84 return orig_node_tmp; 85 } 86 87 static void batadv_purge_orig(struct work_struct *work); 88 89 /** 90 * batadv_compare_orig() - comparing function used in the originator hash table 91 * @node: node in the local table 92 * @data2: second object to compare the node to 93 * 94 * Return: true if they are the same originator 95 */ 96 bool batadv_compare_orig(const struct hlist_node *node, const void *data2) 97 { 98 const void *data1 = container_of(node, struct batadv_orig_node, 99 hash_entry); 100 101 return batadv_compare_eth(data1, data2); 102 } 103 104 /** 105 * batadv_orig_node_vlan_get() - get an orig_node_vlan object 106 * @orig_node: the originator serving the VLAN 107 * @vid: the VLAN identifier 108 * 109 * Return: the vlan object identified by vid and belonging to orig_node or NULL 110 * if it does not exist. 111 */ 112 struct batadv_orig_node_vlan * 113 batadv_orig_node_vlan_get(struct batadv_orig_node *orig_node, 114 unsigned short vid) 115 { 116 struct batadv_orig_node_vlan *vlan = NULL, *tmp; 117 118 rcu_read_lock(); 119 hlist_for_each_entry_rcu(tmp, &orig_node->vlan_list, list) { 120 if (tmp->vid != vid) 121 continue; 122 123 if (!kref_get_unless_zero(&tmp->refcount)) 124 continue; 125 126 vlan = tmp; 127 128 break; 129 } 130 rcu_read_unlock(); 131 132 return vlan; 133 } 134 135 /** 136 * batadv_vlan_id_valid() - check if vlan id is in valid batman-adv encoding 137 * @vid: the VLAN identifier 138 * 139 * Return: true when either no vlan is set or if VLAN is in correct range, 140 * false otherwise 141 */ 142 static bool batadv_vlan_id_valid(unsigned short vid) 143 { 144 unsigned short non_vlan = vid & ~(BATADV_VLAN_HAS_TAG | VLAN_VID_MASK); 145 146 if (vid == 0) 147 return true; 148 149 if (!(vid & BATADV_VLAN_HAS_TAG)) 150 return false; 151 152 if (non_vlan) 153 return false; 154 155 return true; 156 } 157 158 /** 159 * batadv_orig_node_vlan_new() - search and possibly create an orig_node_vlan 160 * object 161 * @orig_node: the originator serving the VLAN 162 * @vid: the VLAN identifier 163 * 164 * Return: NULL in case of failure or the vlan object identified by vid and 165 * belonging to orig_node otherwise. The object is created and added to the list 166 * if it does not exist. 167 * 168 * The object is returned with refcounter increased by 1. 169 */ 170 struct batadv_orig_node_vlan * 171 batadv_orig_node_vlan_new(struct batadv_orig_node *orig_node, 172 unsigned short vid) 173 { 174 struct batadv_orig_node_vlan *vlan; 175 176 if (!batadv_vlan_id_valid(vid)) 177 return NULL; 178 179 spin_lock_bh(&orig_node->vlan_list_lock); 180 181 /* first look if an object for this vid already exists */ 182 vlan = batadv_orig_node_vlan_get(orig_node, vid); 183 if (vlan) 184 goto out; 185 186 vlan = kzalloc(sizeof(*vlan), GFP_ATOMIC); 187 if (!vlan) 188 goto out; 189 190 kref_init(&vlan->refcount); 191 vlan->vid = vid; 192 193 kref_get(&vlan->refcount); 194 hlist_add_head_rcu(&vlan->list, &orig_node->vlan_list); 195 196 out: 197 spin_unlock_bh(&orig_node->vlan_list_lock); 198 199 return vlan; 200 } 201 202 /** 203 * batadv_orig_node_vlan_release() - release originator-vlan object from lists 204 * and queue for free after rcu grace period 205 * @ref: kref pointer of the originator-vlan object 206 */ 207 void batadv_orig_node_vlan_release(struct kref *ref) 208 { 209 struct batadv_orig_node_vlan *orig_vlan; 210 211 orig_vlan = container_of(ref, struct batadv_orig_node_vlan, refcount); 212 213 kfree_rcu(orig_vlan, rcu); 214 } 215 216 /** 217 * batadv_originator_init() - Initialize all originator structures 218 * @bat_priv: the bat priv with all the soft interface information 219 * 220 * Return: 0 on success or negative error number in case of failure 221 */ 222 int batadv_originator_init(struct batadv_priv *bat_priv) 223 { 224 if (bat_priv->orig_hash) 225 return 0; 226 227 bat_priv->orig_hash = batadv_hash_new(1024); 228 229 if (!bat_priv->orig_hash) 230 goto err; 231 232 batadv_hash_set_lock_class(bat_priv->orig_hash, 233 &batadv_orig_hash_lock_class_key); 234 235 INIT_DELAYED_WORK(&bat_priv->orig_work, batadv_purge_orig); 236 queue_delayed_work(batadv_event_workqueue, 237 &bat_priv->orig_work, 238 msecs_to_jiffies(BATADV_ORIG_WORK_PERIOD)); 239 240 return 0; 241 242 err: 243 return -ENOMEM; 244 } 245 246 /** 247 * batadv_neigh_ifinfo_release() - release neigh_ifinfo from lists and queue for 248 * free after rcu grace period 249 * @ref: kref pointer of the neigh_ifinfo 250 */ 251 void batadv_neigh_ifinfo_release(struct kref *ref) 252 { 253 struct batadv_neigh_ifinfo *neigh_ifinfo; 254 255 neigh_ifinfo = container_of(ref, struct batadv_neigh_ifinfo, refcount); 256 257 if (neigh_ifinfo->if_outgoing != BATADV_IF_DEFAULT) 258 batadv_hardif_put(neigh_ifinfo->if_outgoing); 259 260 kfree_rcu(neigh_ifinfo, rcu); 261 } 262 263 /** 264 * batadv_hardif_neigh_release() - release hardif neigh node from lists and 265 * queue for free after rcu grace period 266 * @ref: kref pointer of the neigh_node 267 */ 268 void batadv_hardif_neigh_release(struct kref *ref) 269 { 270 struct batadv_hardif_neigh_node *hardif_neigh; 271 272 hardif_neigh = container_of(ref, struct batadv_hardif_neigh_node, 273 refcount); 274 275 spin_lock_bh(&hardif_neigh->if_incoming->neigh_list_lock); 276 hlist_del_init_rcu(&hardif_neigh->list); 277 spin_unlock_bh(&hardif_neigh->if_incoming->neigh_list_lock); 278 279 batadv_hardif_put(hardif_neigh->if_incoming); 280 kfree_rcu(hardif_neigh, rcu); 281 } 282 283 /** 284 * batadv_neigh_node_release() - release neigh_node from lists and queue for 285 * free after rcu grace period 286 * @ref: kref pointer of the neigh_node 287 */ 288 void batadv_neigh_node_release(struct kref *ref) 289 { 290 struct hlist_node *node_tmp; 291 struct batadv_neigh_node *neigh_node; 292 struct batadv_neigh_ifinfo *neigh_ifinfo; 293 294 neigh_node = container_of(ref, struct batadv_neigh_node, refcount); 295 296 hlist_for_each_entry_safe(neigh_ifinfo, node_tmp, 297 &neigh_node->ifinfo_list, list) { 298 batadv_neigh_ifinfo_put(neigh_ifinfo); 299 } 300 301 batadv_hardif_neigh_put(neigh_node->hardif_neigh); 302 303 batadv_hardif_put(neigh_node->if_incoming); 304 305 kfree_rcu(neigh_node, rcu); 306 } 307 308 /** 309 * batadv_orig_router_get() - router to the originator depending on iface 310 * @orig_node: the orig node for the router 311 * @if_outgoing: the interface where the payload packet has been received or 312 * the OGM should be sent to 313 * 314 * Return: the neighbor which should be the router for this orig_node/iface. 315 * 316 * The object is returned with refcounter increased by 1. 317 */ 318 struct batadv_neigh_node * 319 batadv_orig_router_get(struct batadv_orig_node *orig_node, 320 const struct batadv_hard_iface *if_outgoing) 321 { 322 struct batadv_orig_ifinfo *orig_ifinfo; 323 struct batadv_neigh_node *router = NULL; 324 325 rcu_read_lock(); 326 hlist_for_each_entry_rcu(orig_ifinfo, &orig_node->ifinfo_list, list) { 327 if (orig_ifinfo->if_outgoing != if_outgoing) 328 continue; 329 330 router = rcu_dereference(orig_ifinfo->router); 331 break; 332 } 333 334 if (router && !kref_get_unless_zero(&router->refcount)) 335 router = NULL; 336 337 rcu_read_unlock(); 338 return router; 339 } 340 341 /** 342 * batadv_orig_to_router() - get next hop neighbor to an orig address 343 * @bat_priv: the bat priv with all the soft interface information 344 * @orig_addr: the originator MAC address to search the best next hop router for 345 * @if_outgoing: the interface where the payload packet has been received or 346 * the OGM should be sent to 347 * 348 * Return: A neighbor node which is the best router towards the given originator 349 * address. 350 */ 351 struct batadv_neigh_node * 352 batadv_orig_to_router(struct batadv_priv *bat_priv, u8 *orig_addr, 353 struct batadv_hard_iface *if_outgoing) 354 { 355 struct batadv_neigh_node *neigh_node; 356 struct batadv_orig_node *orig_node; 357 358 orig_node = batadv_orig_hash_find(bat_priv, orig_addr); 359 if (!orig_node) 360 return NULL; 361 362 neigh_node = batadv_find_router(bat_priv, orig_node, if_outgoing); 363 batadv_orig_node_put(orig_node); 364 365 return neigh_node; 366 } 367 368 /** 369 * batadv_orig_ifinfo_get() - find the ifinfo from an orig_node 370 * @orig_node: the orig node to be queried 371 * @if_outgoing: the interface for which the ifinfo should be acquired 372 * 373 * Return: the requested orig_ifinfo or NULL if not found. 374 * 375 * The object is returned with refcounter increased by 1. 376 */ 377 struct batadv_orig_ifinfo * 378 batadv_orig_ifinfo_get(struct batadv_orig_node *orig_node, 379 struct batadv_hard_iface *if_outgoing) 380 { 381 struct batadv_orig_ifinfo *tmp, *orig_ifinfo = NULL; 382 383 rcu_read_lock(); 384 hlist_for_each_entry_rcu(tmp, &orig_node->ifinfo_list, 385 list) { 386 if (tmp->if_outgoing != if_outgoing) 387 continue; 388 389 if (!kref_get_unless_zero(&tmp->refcount)) 390 continue; 391 392 orig_ifinfo = tmp; 393 break; 394 } 395 rcu_read_unlock(); 396 397 return orig_ifinfo; 398 } 399 400 /** 401 * batadv_orig_ifinfo_new() - search and possibly create an orig_ifinfo object 402 * @orig_node: the orig node to be queried 403 * @if_outgoing: the interface for which the ifinfo should be acquired 404 * 405 * Return: NULL in case of failure or the orig_ifinfo object for the if_outgoing 406 * interface otherwise. The object is created and added to the list 407 * if it does not exist. 408 * 409 * The object is returned with refcounter increased by 1. 410 */ 411 struct batadv_orig_ifinfo * 412 batadv_orig_ifinfo_new(struct batadv_orig_node *orig_node, 413 struct batadv_hard_iface *if_outgoing) 414 { 415 struct batadv_orig_ifinfo *orig_ifinfo; 416 unsigned long reset_time; 417 418 spin_lock_bh(&orig_node->neigh_list_lock); 419 420 orig_ifinfo = batadv_orig_ifinfo_get(orig_node, if_outgoing); 421 if (orig_ifinfo) 422 goto out; 423 424 orig_ifinfo = kzalloc(sizeof(*orig_ifinfo), GFP_ATOMIC); 425 if (!orig_ifinfo) 426 goto out; 427 428 if (if_outgoing != BATADV_IF_DEFAULT) 429 kref_get(&if_outgoing->refcount); 430 431 reset_time = jiffies - 1; 432 reset_time -= msecs_to_jiffies(BATADV_RESET_PROTECTION_MS); 433 orig_ifinfo->batman_seqno_reset = reset_time; 434 orig_ifinfo->if_outgoing = if_outgoing; 435 INIT_HLIST_NODE(&orig_ifinfo->list); 436 kref_init(&orig_ifinfo->refcount); 437 438 kref_get(&orig_ifinfo->refcount); 439 hlist_add_head_rcu(&orig_ifinfo->list, 440 &orig_node->ifinfo_list); 441 out: 442 spin_unlock_bh(&orig_node->neigh_list_lock); 443 return orig_ifinfo; 444 } 445 446 /** 447 * batadv_neigh_ifinfo_get() - find the ifinfo from an neigh_node 448 * @neigh: the neigh node to be queried 449 * @if_outgoing: the interface for which the ifinfo should be acquired 450 * 451 * The object is returned with refcounter increased by 1. 452 * 453 * Return: the requested neigh_ifinfo or NULL if not found 454 */ 455 struct batadv_neigh_ifinfo * 456 batadv_neigh_ifinfo_get(struct batadv_neigh_node *neigh, 457 struct batadv_hard_iface *if_outgoing) 458 { 459 struct batadv_neigh_ifinfo *neigh_ifinfo = NULL, 460 *tmp_neigh_ifinfo; 461 462 rcu_read_lock(); 463 hlist_for_each_entry_rcu(tmp_neigh_ifinfo, &neigh->ifinfo_list, 464 list) { 465 if (tmp_neigh_ifinfo->if_outgoing != if_outgoing) 466 continue; 467 468 if (!kref_get_unless_zero(&tmp_neigh_ifinfo->refcount)) 469 continue; 470 471 neigh_ifinfo = tmp_neigh_ifinfo; 472 break; 473 } 474 rcu_read_unlock(); 475 476 return neigh_ifinfo; 477 } 478 479 /** 480 * batadv_neigh_ifinfo_new() - search and possibly create an neigh_ifinfo object 481 * @neigh: the neigh node to be queried 482 * @if_outgoing: the interface for which the ifinfo should be acquired 483 * 484 * Return: NULL in case of failure or the neigh_ifinfo object for the 485 * if_outgoing interface otherwise. The object is created and added to the list 486 * if it does not exist. 487 * 488 * The object is returned with refcounter increased by 1. 489 */ 490 struct batadv_neigh_ifinfo * 491 batadv_neigh_ifinfo_new(struct batadv_neigh_node *neigh, 492 struct batadv_hard_iface *if_outgoing) 493 { 494 struct batadv_neigh_ifinfo *neigh_ifinfo; 495 496 spin_lock_bh(&neigh->ifinfo_lock); 497 498 neigh_ifinfo = batadv_neigh_ifinfo_get(neigh, if_outgoing); 499 if (neigh_ifinfo) 500 goto out; 501 502 neigh_ifinfo = kzalloc(sizeof(*neigh_ifinfo), GFP_ATOMIC); 503 if (!neigh_ifinfo) 504 goto out; 505 506 if (if_outgoing) 507 kref_get(&if_outgoing->refcount); 508 509 INIT_HLIST_NODE(&neigh_ifinfo->list); 510 kref_init(&neigh_ifinfo->refcount); 511 neigh_ifinfo->if_outgoing = if_outgoing; 512 513 kref_get(&neigh_ifinfo->refcount); 514 hlist_add_head_rcu(&neigh_ifinfo->list, &neigh->ifinfo_list); 515 516 out: 517 spin_unlock_bh(&neigh->ifinfo_lock); 518 519 return neigh_ifinfo; 520 } 521 522 /** 523 * batadv_neigh_node_get() - retrieve a neighbour from the list 524 * @orig_node: originator which the neighbour belongs to 525 * @hard_iface: the interface where this neighbour is connected to 526 * @addr: the address of the neighbour 527 * 528 * Looks for and possibly returns a neighbour belonging to this originator list 529 * which is connected through the provided hard interface. 530 * 531 * Return: neighbor when found. Otherwise NULL 532 */ 533 static struct batadv_neigh_node * 534 batadv_neigh_node_get(const struct batadv_orig_node *orig_node, 535 const struct batadv_hard_iface *hard_iface, 536 const u8 *addr) 537 { 538 struct batadv_neigh_node *tmp_neigh_node, *res = NULL; 539 540 rcu_read_lock(); 541 hlist_for_each_entry_rcu(tmp_neigh_node, &orig_node->neigh_list, list) { 542 if (!batadv_compare_eth(tmp_neigh_node->addr, addr)) 543 continue; 544 545 if (tmp_neigh_node->if_incoming != hard_iface) 546 continue; 547 548 if (!kref_get_unless_zero(&tmp_neigh_node->refcount)) 549 continue; 550 551 res = tmp_neigh_node; 552 break; 553 } 554 rcu_read_unlock(); 555 556 return res; 557 } 558 559 /** 560 * batadv_hardif_neigh_create() - create a hardif neighbour node 561 * @hard_iface: the interface this neighbour is connected to 562 * @neigh_addr: the interface address of the neighbour to retrieve 563 * @orig_node: originator object representing the neighbour 564 * 565 * Return: the hardif neighbour node if found or created or NULL otherwise. 566 */ 567 static struct batadv_hardif_neigh_node * 568 batadv_hardif_neigh_create(struct batadv_hard_iface *hard_iface, 569 const u8 *neigh_addr, 570 struct batadv_orig_node *orig_node) 571 { 572 struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); 573 struct batadv_hardif_neigh_node *hardif_neigh; 574 575 spin_lock_bh(&hard_iface->neigh_list_lock); 576 577 /* check if neighbor hasn't been added in the meantime */ 578 hardif_neigh = batadv_hardif_neigh_get(hard_iface, neigh_addr); 579 if (hardif_neigh) 580 goto out; 581 582 hardif_neigh = kzalloc(sizeof(*hardif_neigh), GFP_ATOMIC); 583 if (!hardif_neigh) 584 goto out; 585 586 kref_get(&hard_iface->refcount); 587 INIT_HLIST_NODE(&hardif_neigh->list); 588 ether_addr_copy(hardif_neigh->addr, neigh_addr); 589 ether_addr_copy(hardif_neigh->orig, orig_node->orig); 590 hardif_neigh->if_incoming = hard_iface; 591 hardif_neigh->last_seen = jiffies; 592 593 kref_init(&hardif_neigh->refcount); 594 595 if (bat_priv->algo_ops->neigh.hardif_init) 596 bat_priv->algo_ops->neigh.hardif_init(hardif_neigh); 597 598 hlist_add_head_rcu(&hardif_neigh->list, &hard_iface->neigh_list); 599 600 out: 601 spin_unlock_bh(&hard_iface->neigh_list_lock); 602 return hardif_neigh; 603 } 604 605 /** 606 * batadv_hardif_neigh_get_or_create() - retrieve or create a hardif neighbour 607 * node 608 * @hard_iface: the interface this neighbour is connected to 609 * @neigh_addr: the interface address of the neighbour to retrieve 610 * @orig_node: originator object representing the neighbour 611 * 612 * Return: the hardif neighbour node if found or created or NULL otherwise. 613 */ 614 static struct batadv_hardif_neigh_node * 615 batadv_hardif_neigh_get_or_create(struct batadv_hard_iface *hard_iface, 616 const u8 *neigh_addr, 617 struct batadv_orig_node *orig_node) 618 { 619 struct batadv_hardif_neigh_node *hardif_neigh; 620 621 /* first check without locking to avoid the overhead */ 622 hardif_neigh = batadv_hardif_neigh_get(hard_iface, neigh_addr); 623 if (hardif_neigh) 624 return hardif_neigh; 625 626 return batadv_hardif_neigh_create(hard_iface, neigh_addr, orig_node); 627 } 628 629 /** 630 * batadv_hardif_neigh_get() - retrieve a hardif neighbour from the list 631 * @hard_iface: the interface where this neighbour is connected to 632 * @neigh_addr: the address of the neighbour 633 * 634 * Looks for and possibly returns a neighbour belonging to this hard interface. 635 * 636 * Return: neighbor when found. Otherwise NULL 637 */ 638 struct batadv_hardif_neigh_node * 639 batadv_hardif_neigh_get(const struct batadv_hard_iface *hard_iface, 640 const u8 *neigh_addr) 641 { 642 struct batadv_hardif_neigh_node *tmp_hardif_neigh, *hardif_neigh = NULL; 643 644 rcu_read_lock(); 645 hlist_for_each_entry_rcu(tmp_hardif_neigh, 646 &hard_iface->neigh_list, list) { 647 if (!batadv_compare_eth(tmp_hardif_neigh->addr, neigh_addr)) 648 continue; 649 650 if (!kref_get_unless_zero(&tmp_hardif_neigh->refcount)) 651 continue; 652 653 hardif_neigh = tmp_hardif_neigh; 654 break; 655 } 656 rcu_read_unlock(); 657 658 return hardif_neigh; 659 } 660 661 /** 662 * batadv_neigh_node_create() - create a neigh node object 663 * @orig_node: originator object representing the neighbour 664 * @hard_iface: the interface where the neighbour is connected to 665 * @neigh_addr: the mac address of the neighbour interface 666 * 667 * Allocates a new neigh_node object and initialises all the generic fields. 668 * 669 * Return: the neighbour node if found or created or NULL otherwise. 670 */ 671 static struct batadv_neigh_node * 672 batadv_neigh_node_create(struct batadv_orig_node *orig_node, 673 struct batadv_hard_iface *hard_iface, 674 const u8 *neigh_addr) 675 { 676 struct batadv_neigh_node *neigh_node; 677 struct batadv_hardif_neigh_node *hardif_neigh = NULL; 678 679 spin_lock_bh(&orig_node->neigh_list_lock); 680 681 neigh_node = batadv_neigh_node_get(orig_node, hard_iface, neigh_addr); 682 if (neigh_node) 683 goto out; 684 685 hardif_neigh = batadv_hardif_neigh_get_or_create(hard_iface, 686 neigh_addr, orig_node); 687 if (!hardif_neigh) 688 goto out; 689 690 neigh_node = kzalloc(sizeof(*neigh_node), GFP_ATOMIC); 691 if (!neigh_node) 692 goto out; 693 694 INIT_HLIST_NODE(&neigh_node->list); 695 INIT_HLIST_HEAD(&neigh_node->ifinfo_list); 696 spin_lock_init(&neigh_node->ifinfo_lock); 697 698 kref_get(&hard_iface->refcount); 699 ether_addr_copy(neigh_node->addr, neigh_addr); 700 neigh_node->if_incoming = hard_iface; 701 neigh_node->orig_node = orig_node; 702 neigh_node->last_seen = jiffies; 703 704 /* increment unique neighbor refcount */ 705 kref_get(&hardif_neigh->refcount); 706 neigh_node->hardif_neigh = hardif_neigh; 707 708 /* extra reference for return */ 709 kref_init(&neigh_node->refcount); 710 711 kref_get(&neigh_node->refcount); 712 hlist_add_head_rcu(&neigh_node->list, &orig_node->neigh_list); 713 714 batadv_dbg(BATADV_DBG_BATMAN, orig_node->bat_priv, 715 "Creating new neighbor %pM for orig_node %pM on interface %s\n", 716 neigh_addr, orig_node->orig, hard_iface->net_dev->name); 717 718 out: 719 spin_unlock_bh(&orig_node->neigh_list_lock); 720 721 batadv_hardif_neigh_put(hardif_neigh); 722 return neigh_node; 723 } 724 725 /** 726 * batadv_neigh_node_get_or_create() - retrieve or create a neigh node object 727 * @orig_node: originator object representing the neighbour 728 * @hard_iface: the interface where the neighbour is connected to 729 * @neigh_addr: the mac address of the neighbour interface 730 * 731 * Return: the neighbour node if found or created or NULL otherwise. 732 */ 733 struct batadv_neigh_node * 734 batadv_neigh_node_get_or_create(struct batadv_orig_node *orig_node, 735 struct batadv_hard_iface *hard_iface, 736 const u8 *neigh_addr) 737 { 738 struct batadv_neigh_node *neigh_node; 739 740 /* first check without locking to avoid the overhead */ 741 neigh_node = batadv_neigh_node_get(orig_node, hard_iface, neigh_addr); 742 if (neigh_node) 743 return neigh_node; 744 745 return batadv_neigh_node_create(orig_node, hard_iface, neigh_addr); 746 } 747 748 /** 749 * batadv_hardif_neigh_dump() - Dump to netlink the neighbor infos for a 750 * specific outgoing interface 751 * @msg: message to dump into 752 * @cb: parameters for the dump 753 * 754 * Return: 0 or error value 755 */ 756 int batadv_hardif_neigh_dump(struct sk_buff *msg, struct netlink_callback *cb) 757 { 758 struct net *net = sock_net(cb->skb->sk); 759 struct net_device *soft_iface; 760 struct net_device *hard_iface = NULL; 761 struct batadv_hard_iface *hardif = BATADV_IF_DEFAULT; 762 struct batadv_priv *bat_priv; 763 struct batadv_hard_iface *primary_if = NULL; 764 int ret; 765 int ifindex, hard_ifindex; 766 767 ifindex = batadv_netlink_get_ifindex(cb->nlh, BATADV_ATTR_MESH_IFINDEX); 768 if (!ifindex) 769 return -EINVAL; 770 771 soft_iface = dev_get_by_index(net, ifindex); 772 if (!soft_iface || !batadv_softif_is_valid(soft_iface)) { 773 ret = -ENODEV; 774 goto out; 775 } 776 777 bat_priv = netdev_priv(soft_iface); 778 779 primary_if = batadv_primary_if_get_selected(bat_priv); 780 if (!primary_if || primary_if->if_status != BATADV_IF_ACTIVE) { 781 ret = -ENOENT; 782 goto out; 783 } 784 785 hard_ifindex = batadv_netlink_get_ifindex(cb->nlh, 786 BATADV_ATTR_HARD_IFINDEX); 787 if (hard_ifindex) { 788 hard_iface = dev_get_by_index(net, hard_ifindex); 789 if (hard_iface) 790 hardif = batadv_hardif_get_by_netdev(hard_iface); 791 792 if (!hardif) { 793 ret = -ENODEV; 794 goto out; 795 } 796 797 if (hardif->soft_iface != soft_iface) { 798 ret = -ENOENT; 799 goto out; 800 } 801 } 802 803 if (!bat_priv->algo_ops->neigh.dump) { 804 ret = -EOPNOTSUPP; 805 goto out; 806 } 807 808 bat_priv->algo_ops->neigh.dump(msg, cb, bat_priv, hardif); 809 810 ret = msg->len; 811 812 out: 813 batadv_hardif_put(hardif); 814 dev_put(hard_iface); 815 batadv_hardif_put(primary_if); 816 dev_put(soft_iface); 817 818 return ret; 819 } 820 821 /** 822 * batadv_orig_ifinfo_release() - release orig_ifinfo from lists and queue for 823 * free after rcu grace period 824 * @ref: kref pointer of the orig_ifinfo 825 */ 826 void batadv_orig_ifinfo_release(struct kref *ref) 827 { 828 struct batadv_orig_ifinfo *orig_ifinfo; 829 struct batadv_neigh_node *router; 830 831 orig_ifinfo = container_of(ref, struct batadv_orig_ifinfo, refcount); 832 833 if (orig_ifinfo->if_outgoing != BATADV_IF_DEFAULT) 834 batadv_hardif_put(orig_ifinfo->if_outgoing); 835 836 /* this is the last reference to this object */ 837 router = rcu_dereference_protected(orig_ifinfo->router, true); 838 batadv_neigh_node_put(router); 839 840 kfree_rcu(orig_ifinfo, rcu); 841 } 842 843 /** 844 * batadv_orig_node_free_rcu() - free the orig_node 845 * @rcu: rcu pointer of the orig_node 846 */ 847 static void batadv_orig_node_free_rcu(struct rcu_head *rcu) 848 { 849 struct batadv_orig_node *orig_node; 850 851 orig_node = container_of(rcu, struct batadv_orig_node, rcu); 852 853 batadv_mcast_purge_orig(orig_node); 854 855 batadv_frag_purge_orig(orig_node, NULL); 856 857 kfree(orig_node->tt_buff); 858 kfree(orig_node); 859 } 860 861 /** 862 * batadv_orig_node_release() - release orig_node from lists and queue for 863 * free after rcu grace period 864 * @ref: kref pointer of the orig_node 865 */ 866 void batadv_orig_node_release(struct kref *ref) 867 { 868 struct hlist_node *node_tmp; 869 struct batadv_neigh_node *neigh_node; 870 struct batadv_orig_node *orig_node; 871 struct batadv_orig_ifinfo *orig_ifinfo; 872 struct batadv_orig_node_vlan *vlan; 873 struct batadv_orig_ifinfo *last_candidate; 874 875 orig_node = container_of(ref, struct batadv_orig_node, refcount); 876 877 spin_lock_bh(&orig_node->neigh_list_lock); 878 879 /* for all neighbors towards this originator ... */ 880 hlist_for_each_entry_safe(neigh_node, node_tmp, 881 &orig_node->neigh_list, list) { 882 hlist_del_rcu(&neigh_node->list); 883 batadv_neigh_node_put(neigh_node); 884 } 885 886 hlist_for_each_entry_safe(orig_ifinfo, node_tmp, 887 &orig_node->ifinfo_list, list) { 888 hlist_del_rcu(&orig_ifinfo->list); 889 batadv_orig_ifinfo_put(orig_ifinfo); 890 } 891 892 last_candidate = orig_node->last_bonding_candidate; 893 orig_node->last_bonding_candidate = NULL; 894 spin_unlock_bh(&orig_node->neigh_list_lock); 895 896 batadv_orig_ifinfo_put(last_candidate); 897 898 spin_lock_bh(&orig_node->vlan_list_lock); 899 hlist_for_each_entry_safe(vlan, node_tmp, &orig_node->vlan_list, list) { 900 hlist_del_rcu(&vlan->list); 901 batadv_orig_node_vlan_put(vlan); 902 } 903 spin_unlock_bh(&orig_node->vlan_list_lock); 904 905 /* Free nc_nodes */ 906 batadv_nc_purge_orig(orig_node->bat_priv, orig_node, NULL); 907 908 call_rcu(&orig_node->rcu, batadv_orig_node_free_rcu); 909 } 910 911 /** 912 * batadv_originator_free() - Free all originator structures 913 * @bat_priv: the bat priv with all the soft interface information 914 */ 915 void batadv_originator_free(struct batadv_priv *bat_priv) 916 { 917 struct batadv_hashtable *hash = bat_priv->orig_hash; 918 struct hlist_node *node_tmp; 919 struct hlist_head *head; 920 spinlock_t *list_lock; /* spinlock to protect write access */ 921 struct batadv_orig_node *orig_node; 922 u32 i; 923 924 if (!hash) 925 return; 926 927 cancel_delayed_work_sync(&bat_priv->orig_work); 928 929 bat_priv->orig_hash = NULL; 930 931 for (i = 0; i < hash->size; i++) { 932 head = &hash->table[i]; 933 list_lock = &hash->list_locks[i]; 934 935 spin_lock_bh(list_lock); 936 hlist_for_each_entry_safe(orig_node, node_tmp, 937 head, hash_entry) { 938 hlist_del_rcu(&orig_node->hash_entry); 939 batadv_orig_node_put(orig_node); 940 } 941 spin_unlock_bh(list_lock); 942 } 943 944 batadv_hash_destroy(hash); 945 } 946 947 /** 948 * batadv_orig_node_new() - creates a new orig_node 949 * @bat_priv: the bat priv with all the soft interface information 950 * @addr: the mac address of the originator 951 * 952 * Creates a new originator object and initialises all the generic fields. 953 * The new object is not added to the originator list. 954 * 955 * Return: the newly created object or NULL on failure. 956 */ 957 struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv, 958 const u8 *addr) 959 { 960 struct batadv_orig_node *orig_node; 961 struct batadv_orig_node_vlan *vlan; 962 unsigned long reset_time; 963 int i; 964 965 batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 966 "Creating new originator: %pM\n", addr); 967 968 orig_node = kzalloc(sizeof(*orig_node), GFP_ATOMIC); 969 if (!orig_node) 970 return NULL; 971 972 INIT_HLIST_HEAD(&orig_node->neigh_list); 973 INIT_HLIST_HEAD(&orig_node->vlan_list); 974 INIT_HLIST_HEAD(&orig_node->ifinfo_list); 975 spin_lock_init(&orig_node->bcast_seqno_lock); 976 spin_lock_init(&orig_node->neigh_list_lock); 977 spin_lock_init(&orig_node->tt_buff_lock); 978 spin_lock_init(&orig_node->tt_lock); 979 spin_lock_init(&orig_node->vlan_list_lock); 980 981 batadv_nc_init_orig(orig_node); 982 983 /* extra reference for return */ 984 kref_init(&orig_node->refcount); 985 986 orig_node->bat_priv = bat_priv; 987 ether_addr_copy(orig_node->orig, addr); 988 batadv_dat_init_orig_node_addr(orig_node); 989 atomic_set(&orig_node->last_ttvn, 0); 990 orig_node->tt_buff = NULL; 991 orig_node->tt_buff_len = 0; 992 orig_node->last_seen = jiffies; 993 reset_time = jiffies - 1 - msecs_to_jiffies(BATADV_RESET_PROTECTION_MS); 994 orig_node->bcast_seqno_reset = reset_time; 995 996 #ifdef CONFIG_BATMAN_ADV_MCAST 997 orig_node->mcast_flags = BATADV_MCAST_WANT_NO_RTR4; 998 orig_node->mcast_flags |= BATADV_MCAST_WANT_NO_RTR6; 999 orig_node->mcast_flags |= BATADV_MCAST_HAVE_MC_PTYPE_CAPA; 1000 INIT_HLIST_NODE(&orig_node->mcast_want_all_unsnoopables_node); 1001 INIT_HLIST_NODE(&orig_node->mcast_want_all_ipv4_node); 1002 INIT_HLIST_NODE(&orig_node->mcast_want_all_ipv6_node); 1003 spin_lock_init(&orig_node->mcast_handler_lock); 1004 #endif 1005 1006 /* create a vlan object for the "untagged" LAN */ 1007 vlan = batadv_orig_node_vlan_new(orig_node, BATADV_NO_FLAGS); 1008 if (!vlan) 1009 goto free_orig_node; 1010 /* batadv_orig_node_vlan_new() increases the refcounter. 1011 * Immediately release vlan since it is not needed anymore in this 1012 * context 1013 */ 1014 batadv_orig_node_vlan_put(vlan); 1015 1016 for (i = 0; i < BATADV_FRAG_BUFFER_COUNT; i++) { 1017 INIT_HLIST_HEAD(&orig_node->fragments[i].fragment_list); 1018 spin_lock_init(&orig_node->fragments[i].lock); 1019 orig_node->fragments[i].size = 0; 1020 } 1021 1022 return orig_node; 1023 free_orig_node: 1024 kfree(orig_node); 1025 return NULL; 1026 } 1027 1028 /** 1029 * batadv_purge_neigh_ifinfo() - purge obsolete ifinfo entries from neighbor 1030 * @bat_priv: the bat priv with all the soft interface information 1031 * @neigh: orig node which is to be checked 1032 */ 1033 static void 1034 batadv_purge_neigh_ifinfo(struct batadv_priv *bat_priv, 1035 struct batadv_neigh_node *neigh) 1036 { 1037 struct batadv_neigh_ifinfo *neigh_ifinfo; 1038 struct batadv_hard_iface *if_outgoing; 1039 struct hlist_node *node_tmp; 1040 1041 spin_lock_bh(&neigh->ifinfo_lock); 1042 1043 /* for all ifinfo objects for this neighinator */ 1044 hlist_for_each_entry_safe(neigh_ifinfo, node_tmp, 1045 &neigh->ifinfo_list, list) { 1046 if_outgoing = neigh_ifinfo->if_outgoing; 1047 1048 /* always keep the default interface */ 1049 if (if_outgoing == BATADV_IF_DEFAULT) 1050 continue; 1051 1052 /* don't purge if the interface is not (going) down */ 1053 if (if_outgoing->if_status != BATADV_IF_INACTIVE && 1054 if_outgoing->if_status != BATADV_IF_NOT_IN_USE && 1055 if_outgoing->if_status != BATADV_IF_TO_BE_REMOVED) 1056 continue; 1057 1058 batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 1059 "neighbor/ifinfo purge: neighbor %pM, iface: %s\n", 1060 neigh->addr, if_outgoing->net_dev->name); 1061 1062 hlist_del_rcu(&neigh_ifinfo->list); 1063 batadv_neigh_ifinfo_put(neigh_ifinfo); 1064 } 1065 1066 spin_unlock_bh(&neigh->ifinfo_lock); 1067 } 1068 1069 /** 1070 * batadv_purge_orig_ifinfo() - purge obsolete ifinfo entries from originator 1071 * @bat_priv: the bat priv with all the soft interface information 1072 * @orig_node: orig node which is to be checked 1073 * 1074 * Return: true if any ifinfo entry was purged, false otherwise. 1075 */ 1076 static bool 1077 batadv_purge_orig_ifinfo(struct batadv_priv *bat_priv, 1078 struct batadv_orig_node *orig_node) 1079 { 1080 struct batadv_orig_ifinfo *orig_ifinfo; 1081 struct batadv_hard_iface *if_outgoing; 1082 struct hlist_node *node_tmp; 1083 bool ifinfo_purged = false; 1084 1085 spin_lock_bh(&orig_node->neigh_list_lock); 1086 1087 /* for all ifinfo objects for this originator */ 1088 hlist_for_each_entry_safe(orig_ifinfo, node_tmp, 1089 &orig_node->ifinfo_list, list) { 1090 if_outgoing = orig_ifinfo->if_outgoing; 1091 1092 /* always keep the default interface */ 1093 if (if_outgoing == BATADV_IF_DEFAULT) 1094 continue; 1095 1096 /* don't purge if the interface is not (going) down */ 1097 if (if_outgoing->if_status != BATADV_IF_INACTIVE && 1098 if_outgoing->if_status != BATADV_IF_NOT_IN_USE && 1099 if_outgoing->if_status != BATADV_IF_TO_BE_REMOVED) 1100 continue; 1101 1102 batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 1103 "router/ifinfo purge: originator %pM, iface: %s\n", 1104 orig_node->orig, if_outgoing->net_dev->name); 1105 1106 ifinfo_purged = true; 1107 1108 hlist_del_rcu(&orig_ifinfo->list); 1109 batadv_orig_ifinfo_put(orig_ifinfo); 1110 if (orig_node->last_bonding_candidate == orig_ifinfo) { 1111 orig_node->last_bonding_candidate = NULL; 1112 batadv_orig_ifinfo_put(orig_ifinfo); 1113 } 1114 } 1115 1116 spin_unlock_bh(&orig_node->neigh_list_lock); 1117 1118 return ifinfo_purged; 1119 } 1120 1121 /** 1122 * batadv_purge_orig_neighbors() - purges neighbors from originator 1123 * @bat_priv: the bat priv with all the soft interface information 1124 * @orig_node: orig node which is to be checked 1125 * 1126 * Return: true if any neighbor was purged, false otherwise 1127 */ 1128 static bool 1129 batadv_purge_orig_neighbors(struct batadv_priv *bat_priv, 1130 struct batadv_orig_node *orig_node) 1131 { 1132 struct hlist_node *node_tmp; 1133 struct batadv_neigh_node *neigh_node; 1134 bool neigh_purged = false; 1135 unsigned long last_seen; 1136 struct batadv_hard_iface *if_incoming; 1137 1138 spin_lock_bh(&orig_node->neigh_list_lock); 1139 1140 /* for all neighbors towards this originator ... */ 1141 hlist_for_each_entry_safe(neigh_node, node_tmp, 1142 &orig_node->neigh_list, list) { 1143 last_seen = neigh_node->last_seen; 1144 if_incoming = neigh_node->if_incoming; 1145 1146 if (batadv_has_timed_out(last_seen, BATADV_PURGE_TIMEOUT) || 1147 if_incoming->if_status == BATADV_IF_INACTIVE || 1148 if_incoming->if_status == BATADV_IF_NOT_IN_USE || 1149 if_incoming->if_status == BATADV_IF_TO_BE_REMOVED) { 1150 if (if_incoming->if_status == BATADV_IF_INACTIVE || 1151 if_incoming->if_status == BATADV_IF_NOT_IN_USE || 1152 if_incoming->if_status == BATADV_IF_TO_BE_REMOVED) 1153 batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 1154 "neighbor purge: originator %pM, neighbor: %pM, iface: %s\n", 1155 orig_node->orig, neigh_node->addr, 1156 if_incoming->net_dev->name); 1157 else 1158 batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 1159 "neighbor timeout: originator %pM, neighbor: %pM, last_seen: %u\n", 1160 orig_node->orig, neigh_node->addr, 1161 jiffies_to_msecs(last_seen)); 1162 1163 neigh_purged = true; 1164 1165 hlist_del_rcu(&neigh_node->list); 1166 batadv_neigh_node_put(neigh_node); 1167 } else { 1168 /* only necessary if not the whole neighbor is to be 1169 * deleted, but some interface has been removed. 1170 */ 1171 batadv_purge_neigh_ifinfo(bat_priv, neigh_node); 1172 } 1173 } 1174 1175 spin_unlock_bh(&orig_node->neigh_list_lock); 1176 return neigh_purged; 1177 } 1178 1179 /** 1180 * batadv_find_best_neighbor() - finds the best neighbor after purging 1181 * @bat_priv: the bat priv with all the soft interface information 1182 * @orig_node: orig node which is to be checked 1183 * @if_outgoing: the interface for which the metric should be compared 1184 * 1185 * Return: the current best neighbor, with refcount increased. 1186 */ 1187 static struct batadv_neigh_node * 1188 batadv_find_best_neighbor(struct batadv_priv *bat_priv, 1189 struct batadv_orig_node *orig_node, 1190 struct batadv_hard_iface *if_outgoing) 1191 { 1192 struct batadv_neigh_node *best = NULL, *neigh; 1193 struct batadv_algo_ops *bao = bat_priv->algo_ops; 1194 1195 rcu_read_lock(); 1196 hlist_for_each_entry_rcu(neigh, &orig_node->neigh_list, list) { 1197 if (best && (bao->neigh.cmp(neigh, if_outgoing, best, 1198 if_outgoing) <= 0)) 1199 continue; 1200 1201 if (!kref_get_unless_zero(&neigh->refcount)) 1202 continue; 1203 1204 batadv_neigh_node_put(best); 1205 1206 best = neigh; 1207 } 1208 rcu_read_unlock(); 1209 1210 return best; 1211 } 1212 1213 /** 1214 * batadv_purge_orig_node() - purges obsolete information from an orig_node 1215 * @bat_priv: the bat priv with all the soft interface information 1216 * @orig_node: orig node which is to be checked 1217 * 1218 * This function checks if the orig_node or substructures of it have become 1219 * obsolete, and purges this information if that's the case. 1220 * 1221 * Return: true if the orig_node is to be removed, false otherwise. 1222 */ 1223 static bool batadv_purge_orig_node(struct batadv_priv *bat_priv, 1224 struct batadv_orig_node *orig_node) 1225 { 1226 struct batadv_neigh_node *best_neigh_node; 1227 struct batadv_hard_iface *hard_iface; 1228 bool changed_ifinfo, changed_neigh; 1229 1230 if (batadv_has_timed_out(orig_node->last_seen, 1231 2 * BATADV_PURGE_TIMEOUT)) { 1232 batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 1233 "Originator timeout: originator %pM, last_seen %u\n", 1234 orig_node->orig, 1235 jiffies_to_msecs(orig_node->last_seen)); 1236 return true; 1237 } 1238 changed_ifinfo = batadv_purge_orig_ifinfo(bat_priv, orig_node); 1239 changed_neigh = batadv_purge_orig_neighbors(bat_priv, orig_node); 1240 1241 if (!changed_ifinfo && !changed_neigh) 1242 return false; 1243 1244 /* first for NULL ... */ 1245 best_neigh_node = batadv_find_best_neighbor(bat_priv, orig_node, 1246 BATADV_IF_DEFAULT); 1247 batadv_update_route(bat_priv, orig_node, BATADV_IF_DEFAULT, 1248 best_neigh_node); 1249 batadv_neigh_node_put(best_neigh_node); 1250 1251 /* ... then for all other interfaces. */ 1252 rcu_read_lock(); 1253 list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) { 1254 if (hard_iface->if_status != BATADV_IF_ACTIVE) 1255 continue; 1256 1257 if (hard_iface->soft_iface != bat_priv->soft_iface) 1258 continue; 1259 1260 if (!kref_get_unless_zero(&hard_iface->refcount)) 1261 continue; 1262 1263 best_neigh_node = batadv_find_best_neighbor(bat_priv, 1264 orig_node, 1265 hard_iface); 1266 batadv_update_route(bat_priv, orig_node, hard_iface, 1267 best_neigh_node); 1268 batadv_neigh_node_put(best_neigh_node); 1269 1270 batadv_hardif_put(hard_iface); 1271 } 1272 rcu_read_unlock(); 1273 1274 return false; 1275 } 1276 1277 /** 1278 * batadv_purge_orig_ref() - Purge all outdated originators 1279 * @bat_priv: the bat priv with all the soft interface information 1280 */ 1281 void batadv_purge_orig_ref(struct batadv_priv *bat_priv) 1282 { 1283 struct batadv_hashtable *hash = bat_priv->orig_hash; 1284 struct hlist_node *node_tmp; 1285 struct hlist_head *head; 1286 spinlock_t *list_lock; /* spinlock to protect write access */ 1287 struct batadv_orig_node *orig_node; 1288 u32 i; 1289 1290 if (!hash) 1291 return; 1292 1293 /* for all origins... */ 1294 for (i = 0; i < hash->size; i++) { 1295 head = &hash->table[i]; 1296 if (hlist_empty(head)) 1297 continue; 1298 list_lock = &hash->list_locks[i]; 1299 1300 spin_lock_bh(list_lock); 1301 hlist_for_each_entry_safe(orig_node, node_tmp, 1302 head, hash_entry) { 1303 if (batadv_purge_orig_node(bat_priv, orig_node)) { 1304 batadv_gw_node_delete(bat_priv, orig_node); 1305 hlist_del_rcu(&orig_node->hash_entry); 1306 batadv_tt_global_del_orig(orig_node->bat_priv, 1307 orig_node, -1, 1308 "originator timed out"); 1309 batadv_orig_node_put(orig_node); 1310 continue; 1311 } 1312 1313 batadv_frag_purge_orig(orig_node, 1314 batadv_frag_check_entry); 1315 } 1316 spin_unlock_bh(list_lock); 1317 } 1318 1319 batadv_gw_election(bat_priv); 1320 } 1321 1322 static void batadv_purge_orig(struct work_struct *work) 1323 { 1324 struct delayed_work *delayed_work; 1325 struct batadv_priv *bat_priv; 1326 1327 delayed_work = to_delayed_work(work); 1328 bat_priv = container_of(delayed_work, struct batadv_priv, orig_work); 1329 batadv_purge_orig_ref(bat_priv); 1330 queue_delayed_work(batadv_event_workqueue, 1331 &bat_priv->orig_work, 1332 msecs_to_jiffies(BATADV_ORIG_WORK_PERIOD)); 1333 } 1334 1335 /** 1336 * batadv_orig_dump() - Dump to netlink the originator infos for a specific 1337 * outgoing interface 1338 * @msg: message to dump into 1339 * @cb: parameters for the dump 1340 * 1341 * Return: 0 or error value 1342 */ 1343 int batadv_orig_dump(struct sk_buff *msg, struct netlink_callback *cb) 1344 { 1345 struct net *net = sock_net(cb->skb->sk); 1346 struct net_device *soft_iface; 1347 struct net_device *hard_iface = NULL; 1348 struct batadv_hard_iface *hardif = BATADV_IF_DEFAULT; 1349 struct batadv_priv *bat_priv; 1350 struct batadv_hard_iface *primary_if = NULL; 1351 int ret; 1352 int ifindex, hard_ifindex; 1353 1354 ifindex = batadv_netlink_get_ifindex(cb->nlh, BATADV_ATTR_MESH_IFINDEX); 1355 if (!ifindex) 1356 return -EINVAL; 1357 1358 soft_iface = dev_get_by_index(net, ifindex); 1359 if (!soft_iface || !batadv_softif_is_valid(soft_iface)) { 1360 ret = -ENODEV; 1361 goto out; 1362 } 1363 1364 bat_priv = netdev_priv(soft_iface); 1365 1366 primary_if = batadv_primary_if_get_selected(bat_priv); 1367 if (!primary_if || primary_if->if_status != BATADV_IF_ACTIVE) { 1368 ret = -ENOENT; 1369 goto out; 1370 } 1371 1372 hard_ifindex = batadv_netlink_get_ifindex(cb->nlh, 1373 BATADV_ATTR_HARD_IFINDEX); 1374 if (hard_ifindex) { 1375 hard_iface = dev_get_by_index(net, hard_ifindex); 1376 if (hard_iface) 1377 hardif = batadv_hardif_get_by_netdev(hard_iface); 1378 1379 if (!hardif) { 1380 ret = -ENODEV; 1381 goto out; 1382 } 1383 1384 if (hardif->soft_iface != soft_iface) { 1385 ret = -ENOENT; 1386 goto out; 1387 } 1388 } 1389 1390 if (!bat_priv->algo_ops->orig.dump) { 1391 ret = -EOPNOTSUPP; 1392 goto out; 1393 } 1394 1395 bat_priv->algo_ops->orig.dump(msg, cb, bat_priv, hardif); 1396 1397 ret = msg->len; 1398 1399 out: 1400 batadv_hardif_put(hardif); 1401 dev_put(hard_iface); 1402 batadv_hardif_put(primary_if); 1403 dev_put(soft_iface); 1404 1405 return ret; 1406 } 1407
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.