Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright (C) B.A.T.M.A.N. contributors:
0003  *
0004  * Marek Lindner, Simon Wunderlich
0005  */
0006 
0007 #include "originator.h"
0008 #include "main.h"
0009 
0010 #include <linux/atomic.h>
0011 #include <linux/container_of.h>
0012 #include <linux/errno.h>
0013 #include <linux/etherdevice.h>
0014 #include <linux/gfp.h>
0015 #include <linux/jiffies.h>
0016 #include <linux/kref.h>
0017 #include <linux/list.h>
0018 #include <linux/lockdep.h>
0019 #include <linux/netdevice.h>
0020 #include <linux/netlink.h>
0021 #include <linux/rculist.h>
0022 #include <linux/rcupdate.h>
0023 #include <linux/skbuff.h>
0024 #include <linux/slab.h>
0025 #include <linux/spinlock.h>
0026 #include <linux/stddef.h>
0027 #include <linux/workqueue.h>
0028 #include <net/sock.h>
0029 #include <uapi/linux/batadv_packet.h>
0030 #include <uapi/linux/batman_adv.h>
0031 
0032 #include "bat_algo.h"
0033 #include "distributed-arp-table.h"
0034 #include "fragmentation.h"
0035 #include "gateway_client.h"
0036 #include "hard-interface.h"
0037 #include "hash.h"
0038 #include "log.h"
0039 #include "multicast.h"
0040 #include "netlink.h"
0041 #include "network-coding.h"
0042 #include "routing.h"
0043 #include "soft-interface.h"
0044 #include "translation-table.h"
0045 
0046 /* hash class keys */
0047 static struct lock_class_key batadv_orig_hash_lock_class_key;
0048 
0049 /**
0050  * batadv_orig_hash_find() - Find and return originator from orig_hash
0051  * @bat_priv: the bat priv with all the soft interface information
0052  * @data: mac address of the originator
0053  *
0054  * Return: orig_node (with increased refcnt), NULL on errors
0055  */
0056 struct batadv_orig_node *
0057 batadv_orig_hash_find(struct batadv_priv *bat_priv, const void *data)
0058 {
0059     struct batadv_hashtable *hash = bat_priv->orig_hash;
0060     struct hlist_head *head;
0061     struct batadv_orig_node *orig_node, *orig_node_tmp = NULL;
0062     int index;
0063 
0064     if (!hash)
0065         return NULL;
0066 
0067     index = batadv_choose_orig(data, hash->size);
0068     head = &hash->table[index];
0069 
0070     rcu_read_lock();
0071     hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
0072         if (!batadv_compare_eth(orig_node, data))
0073             continue;
0074 
0075         if (!kref_get_unless_zero(&orig_node->refcount))
0076             continue;
0077 
0078         orig_node_tmp = orig_node;
0079         break;
0080     }
0081     rcu_read_unlock();
0082 
0083     return orig_node_tmp;
0084 }
0085 
0086 static void batadv_purge_orig(struct work_struct *work);
0087 
0088 /**
0089  * batadv_compare_orig() - comparing function used in the originator hash table
0090  * @node: node in the local table
0091  * @data2: second object to compare the node to
0092  *
0093  * Return: true if they are the same originator
0094  */
0095 bool batadv_compare_orig(const struct hlist_node *node, const void *data2)
0096 {
0097     const void *data1 = container_of(node, struct batadv_orig_node,
0098                      hash_entry);
0099 
0100     return batadv_compare_eth(data1, data2);
0101 }
0102 
0103 /**
0104  * batadv_orig_node_vlan_get() - get an orig_node_vlan object
0105  * @orig_node: the originator serving the VLAN
0106  * @vid: the VLAN identifier
0107  *
0108  * Return: the vlan object identified by vid and belonging to orig_node or NULL
0109  * if it does not exist.
0110  */
0111 struct batadv_orig_node_vlan *
0112 batadv_orig_node_vlan_get(struct batadv_orig_node *orig_node,
0113               unsigned short vid)
0114 {
0115     struct batadv_orig_node_vlan *vlan = NULL, *tmp;
0116 
0117     rcu_read_lock();
0118     hlist_for_each_entry_rcu(tmp, &orig_node->vlan_list, list) {
0119         if (tmp->vid != vid)
0120             continue;
0121 
0122         if (!kref_get_unless_zero(&tmp->refcount))
0123             continue;
0124 
0125         vlan = tmp;
0126 
0127         break;
0128     }
0129     rcu_read_unlock();
0130 
0131     return vlan;
0132 }
0133 
0134 /**
0135  * batadv_orig_node_vlan_new() - search and possibly create an orig_node_vlan
0136  *  object
0137  * @orig_node: the originator serving the VLAN
0138  * @vid: the VLAN identifier
0139  *
0140  * Return: NULL in case of failure or the vlan object identified by vid and
0141  * belonging to orig_node otherwise. The object is created and added to the list
0142  * if it does not exist.
0143  *
0144  * The object is returned with refcounter increased by 1.
0145  */
0146 struct batadv_orig_node_vlan *
0147 batadv_orig_node_vlan_new(struct batadv_orig_node *orig_node,
0148               unsigned short vid)
0149 {
0150     struct batadv_orig_node_vlan *vlan;
0151 
0152     spin_lock_bh(&orig_node->vlan_list_lock);
0153 
0154     /* first look if an object for this vid already exists */
0155     vlan = batadv_orig_node_vlan_get(orig_node, vid);
0156     if (vlan)
0157         goto out;
0158 
0159     vlan = kzalloc(sizeof(*vlan), GFP_ATOMIC);
0160     if (!vlan)
0161         goto out;
0162 
0163     kref_init(&vlan->refcount);
0164     vlan->vid = vid;
0165 
0166     kref_get(&vlan->refcount);
0167     hlist_add_head_rcu(&vlan->list, &orig_node->vlan_list);
0168 
0169 out:
0170     spin_unlock_bh(&orig_node->vlan_list_lock);
0171 
0172     return vlan;
0173 }
0174 
0175 /**
0176  * batadv_orig_node_vlan_release() - release originator-vlan object from lists
0177  *  and queue for free after rcu grace period
0178  * @ref: kref pointer of the originator-vlan object
0179  */
0180 void batadv_orig_node_vlan_release(struct kref *ref)
0181 {
0182     struct batadv_orig_node_vlan *orig_vlan;
0183 
0184     orig_vlan = container_of(ref, struct batadv_orig_node_vlan, refcount);
0185 
0186     kfree_rcu(orig_vlan, rcu);
0187 }
0188 
0189 /**
0190  * batadv_originator_init() - Initialize all originator structures
0191  * @bat_priv: the bat priv with all the soft interface information
0192  *
0193  * Return: 0 on success or negative error number in case of failure
0194  */
0195 int batadv_originator_init(struct batadv_priv *bat_priv)
0196 {
0197     if (bat_priv->orig_hash)
0198         return 0;
0199 
0200     bat_priv->orig_hash = batadv_hash_new(1024);
0201 
0202     if (!bat_priv->orig_hash)
0203         goto err;
0204 
0205     batadv_hash_set_lock_class(bat_priv->orig_hash,
0206                    &batadv_orig_hash_lock_class_key);
0207 
0208     INIT_DELAYED_WORK(&bat_priv->orig_work, batadv_purge_orig);
0209     queue_delayed_work(batadv_event_workqueue,
0210                &bat_priv->orig_work,
0211                msecs_to_jiffies(BATADV_ORIG_WORK_PERIOD));
0212 
0213     return 0;
0214 
0215 err:
0216     return -ENOMEM;
0217 }
0218 
0219 /**
0220  * batadv_neigh_ifinfo_release() - release neigh_ifinfo from lists and queue for
0221  *  free after rcu grace period
0222  * @ref: kref pointer of the neigh_ifinfo
0223  */
0224 void batadv_neigh_ifinfo_release(struct kref *ref)
0225 {
0226     struct batadv_neigh_ifinfo *neigh_ifinfo;
0227 
0228     neigh_ifinfo = container_of(ref, struct batadv_neigh_ifinfo, refcount);
0229 
0230     if (neigh_ifinfo->if_outgoing != BATADV_IF_DEFAULT)
0231         batadv_hardif_put(neigh_ifinfo->if_outgoing);
0232 
0233     kfree_rcu(neigh_ifinfo, rcu);
0234 }
0235 
0236 /**
0237  * batadv_hardif_neigh_release() - release hardif neigh node from lists and
0238  *  queue for free after rcu grace period
0239  * @ref: kref pointer of the neigh_node
0240  */
0241 void batadv_hardif_neigh_release(struct kref *ref)
0242 {
0243     struct batadv_hardif_neigh_node *hardif_neigh;
0244 
0245     hardif_neigh = container_of(ref, struct batadv_hardif_neigh_node,
0246                     refcount);
0247 
0248     spin_lock_bh(&hardif_neigh->if_incoming->neigh_list_lock);
0249     hlist_del_init_rcu(&hardif_neigh->list);
0250     spin_unlock_bh(&hardif_neigh->if_incoming->neigh_list_lock);
0251 
0252     batadv_hardif_put(hardif_neigh->if_incoming);
0253     kfree_rcu(hardif_neigh, rcu);
0254 }
0255 
0256 /**
0257  * batadv_neigh_node_release() - release neigh_node from lists and queue for
0258  *  free after rcu grace period
0259  * @ref: kref pointer of the neigh_node
0260  */
0261 void batadv_neigh_node_release(struct kref *ref)
0262 {
0263     struct hlist_node *node_tmp;
0264     struct batadv_neigh_node *neigh_node;
0265     struct batadv_neigh_ifinfo *neigh_ifinfo;
0266 
0267     neigh_node = container_of(ref, struct batadv_neigh_node, refcount);
0268 
0269     hlist_for_each_entry_safe(neigh_ifinfo, node_tmp,
0270                   &neigh_node->ifinfo_list, list) {
0271         batadv_neigh_ifinfo_put(neigh_ifinfo);
0272     }
0273 
0274     batadv_hardif_neigh_put(neigh_node->hardif_neigh);
0275 
0276     batadv_hardif_put(neigh_node->if_incoming);
0277 
0278     kfree_rcu(neigh_node, rcu);
0279 }
0280 
0281 /**
0282  * batadv_orig_router_get() - router to the originator depending on iface
0283  * @orig_node: the orig node for the router
0284  * @if_outgoing: the interface where the payload packet has been received or
0285  *  the OGM should be sent to
0286  *
0287  * Return: the neighbor which should be the router for this orig_node/iface.
0288  *
0289  * The object is returned with refcounter increased by 1.
0290  */
0291 struct batadv_neigh_node *
0292 batadv_orig_router_get(struct batadv_orig_node *orig_node,
0293                const struct batadv_hard_iface *if_outgoing)
0294 {
0295     struct batadv_orig_ifinfo *orig_ifinfo;
0296     struct batadv_neigh_node *router = NULL;
0297 
0298     rcu_read_lock();
0299     hlist_for_each_entry_rcu(orig_ifinfo, &orig_node->ifinfo_list, list) {
0300         if (orig_ifinfo->if_outgoing != if_outgoing)
0301             continue;
0302 
0303         router = rcu_dereference(orig_ifinfo->router);
0304         break;
0305     }
0306 
0307     if (router && !kref_get_unless_zero(&router->refcount))
0308         router = NULL;
0309 
0310     rcu_read_unlock();
0311     return router;
0312 }
0313 
0314 /**
0315  * batadv_orig_ifinfo_get() - find the ifinfo from an orig_node
0316  * @orig_node: the orig node to be queried
0317  * @if_outgoing: the interface for which the ifinfo should be acquired
0318  *
0319  * Return: the requested orig_ifinfo or NULL if not found.
0320  *
0321  * The object is returned with refcounter increased by 1.
0322  */
0323 struct batadv_orig_ifinfo *
0324 batadv_orig_ifinfo_get(struct batadv_orig_node *orig_node,
0325                struct batadv_hard_iface *if_outgoing)
0326 {
0327     struct batadv_orig_ifinfo *tmp, *orig_ifinfo = NULL;
0328 
0329     rcu_read_lock();
0330     hlist_for_each_entry_rcu(tmp, &orig_node->ifinfo_list,
0331                  list) {
0332         if (tmp->if_outgoing != if_outgoing)
0333             continue;
0334 
0335         if (!kref_get_unless_zero(&tmp->refcount))
0336             continue;
0337 
0338         orig_ifinfo = tmp;
0339         break;
0340     }
0341     rcu_read_unlock();
0342 
0343     return orig_ifinfo;
0344 }
0345 
0346 /**
0347  * batadv_orig_ifinfo_new() - search and possibly create an orig_ifinfo object
0348  * @orig_node: the orig node to be queried
0349  * @if_outgoing: the interface for which the ifinfo should be acquired
0350  *
0351  * Return: NULL in case of failure or the orig_ifinfo object for the if_outgoing
0352  * interface otherwise. The object is created and added to the list
0353  * if it does not exist.
0354  *
0355  * The object is returned with refcounter increased by 1.
0356  */
0357 struct batadv_orig_ifinfo *
0358 batadv_orig_ifinfo_new(struct batadv_orig_node *orig_node,
0359                struct batadv_hard_iface *if_outgoing)
0360 {
0361     struct batadv_orig_ifinfo *orig_ifinfo;
0362     unsigned long reset_time;
0363 
0364     spin_lock_bh(&orig_node->neigh_list_lock);
0365 
0366     orig_ifinfo = batadv_orig_ifinfo_get(orig_node, if_outgoing);
0367     if (orig_ifinfo)
0368         goto out;
0369 
0370     orig_ifinfo = kzalloc(sizeof(*orig_ifinfo), GFP_ATOMIC);
0371     if (!orig_ifinfo)
0372         goto out;
0373 
0374     if (if_outgoing != BATADV_IF_DEFAULT)
0375         kref_get(&if_outgoing->refcount);
0376 
0377     reset_time = jiffies - 1;
0378     reset_time -= msecs_to_jiffies(BATADV_RESET_PROTECTION_MS);
0379     orig_ifinfo->batman_seqno_reset = reset_time;
0380     orig_ifinfo->if_outgoing = if_outgoing;
0381     INIT_HLIST_NODE(&orig_ifinfo->list);
0382     kref_init(&orig_ifinfo->refcount);
0383 
0384     kref_get(&orig_ifinfo->refcount);
0385     hlist_add_head_rcu(&orig_ifinfo->list,
0386                &orig_node->ifinfo_list);
0387 out:
0388     spin_unlock_bh(&orig_node->neigh_list_lock);
0389     return orig_ifinfo;
0390 }
0391 
0392 /**
0393  * batadv_neigh_ifinfo_get() - find the ifinfo from an neigh_node
0394  * @neigh: the neigh node to be queried
0395  * @if_outgoing: the interface for which the ifinfo should be acquired
0396  *
0397  * The object is returned with refcounter increased by 1.
0398  *
0399  * Return: the requested neigh_ifinfo or NULL if not found
0400  */
0401 struct batadv_neigh_ifinfo *
0402 batadv_neigh_ifinfo_get(struct batadv_neigh_node *neigh,
0403             struct batadv_hard_iface *if_outgoing)
0404 {
0405     struct batadv_neigh_ifinfo *neigh_ifinfo = NULL,
0406                    *tmp_neigh_ifinfo;
0407 
0408     rcu_read_lock();
0409     hlist_for_each_entry_rcu(tmp_neigh_ifinfo, &neigh->ifinfo_list,
0410                  list) {
0411         if (tmp_neigh_ifinfo->if_outgoing != if_outgoing)
0412             continue;
0413 
0414         if (!kref_get_unless_zero(&tmp_neigh_ifinfo->refcount))
0415             continue;
0416 
0417         neigh_ifinfo = tmp_neigh_ifinfo;
0418         break;
0419     }
0420     rcu_read_unlock();
0421 
0422     return neigh_ifinfo;
0423 }
0424 
0425 /**
0426  * batadv_neigh_ifinfo_new() - search and possibly create an neigh_ifinfo object
0427  * @neigh: the neigh node to be queried
0428  * @if_outgoing: the interface for which the ifinfo should be acquired
0429  *
0430  * Return: NULL in case of failure or the neigh_ifinfo object for the
0431  * if_outgoing interface otherwise. The object is created and added to the list
0432  * if it does not exist.
0433  *
0434  * The object is returned with refcounter increased by 1.
0435  */
0436 struct batadv_neigh_ifinfo *
0437 batadv_neigh_ifinfo_new(struct batadv_neigh_node *neigh,
0438             struct batadv_hard_iface *if_outgoing)
0439 {
0440     struct batadv_neigh_ifinfo *neigh_ifinfo;
0441 
0442     spin_lock_bh(&neigh->ifinfo_lock);
0443 
0444     neigh_ifinfo = batadv_neigh_ifinfo_get(neigh, if_outgoing);
0445     if (neigh_ifinfo)
0446         goto out;
0447 
0448     neigh_ifinfo = kzalloc(sizeof(*neigh_ifinfo), GFP_ATOMIC);
0449     if (!neigh_ifinfo)
0450         goto out;
0451 
0452     if (if_outgoing)
0453         kref_get(&if_outgoing->refcount);
0454 
0455     INIT_HLIST_NODE(&neigh_ifinfo->list);
0456     kref_init(&neigh_ifinfo->refcount);
0457     neigh_ifinfo->if_outgoing = if_outgoing;
0458 
0459     kref_get(&neigh_ifinfo->refcount);
0460     hlist_add_head_rcu(&neigh_ifinfo->list, &neigh->ifinfo_list);
0461 
0462 out:
0463     spin_unlock_bh(&neigh->ifinfo_lock);
0464 
0465     return neigh_ifinfo;
0466 }
0467 
0468 /**
0469  * batadv_neigh_node_get() - retrieve a neighbour from the list
0470  * @orig_node: originator which the neighbour belongs to
0471  * @hard_iface: the interface where this neighbour is connected to
0472  * @addr: the address of the neighbour
0473  *
0474  * Looks for and possibly returns a neighbour belonging to this originator list
0475  * which is connected through the provided hard interface.
0476  *
0477  * Return: neighbor when found. Otherwise NULL
0478  */
0479 static struct batadv_neigh_node *
0480 batadv_neigh_node_get(const struct batadv_orig_node *orig_node,
0481               const struct batadv_hard_iface *hard_iface,
0482               const u8 *addr)
0483 {
0484     struct batadv_neigh_node *tmp_neigh_node, *res = NULL;
0485 
0486     rcu_read_lock();
0487     hlist_for_each_entry_rcu(tmp_neigh_node, &orig_node->neigh_list, list) {
0488         if (!batadv_compare_eth(tmp_neigh_node->addr, addr))
0489             continue;
0490 
0491         if (tmp_neigh_node->if_incoming != hard_iface)
0492             continue;
0493 
0494         if (!kref_get_unless_zero(&tmp_neigh_node->refcount))
0495             continue;
0496 
0497         res = tmp_neigh_node;
0498         break;
0499     }
0500     rcu_read_unlock();
0501 
0502     return res;
0503 }
0504 
0505 /**
0506  * batadv_hardif_neigh_create() - create a hardif neighbour node
0507  * @hard_iface: the interface this neighbour is connected to
0508  * @neigh_addr: the interface address of the neighbour to retrieve
0509  * @orig_node: originator object representing the neighbour
0510  *
0511  * Return: the hardif neighbour node if found or created or NULL otherwise.
0512  */
0513 static struct batadv_hardif_neigh_node *
0514 batadv_hardif_neigh_create(struct batadv_hard_iface *hard_iface,
0515                const u8 *neigh_addr,
0516                struct batadv_orig_node *orig_node)
0517 {
0518     struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
0519     struct batadv_hardif_neigh_node *hardif_neigh;
0520 
0521     spin_lock_bh(&hard_iface->neigh_list_lock);
0522 
0523     /* check if neighbor hasn't been added in the meantime */
0524     hardif_neigh = batadv_hardif_neigh_get(hard_iface, neigh_addr);
0525     if (hardif_neigh)
0526         goto out;
0527 
0528     hardif_neigh = kzalloc(sizeof(*hardif_neigh), GFP_ATOMIC);
0529     if (!hardif_neigh)
0530         goto out;
0531 
0532     kref_get(&hard_iface->refcount);
0533     INIT_HLIST_NODE(&hardif_neigh->list);
0534     ether_addr_copy(hardif_neigh->addr, neigh_addr);
0535     ether_addr_copy(hardif_neigh->orig, orig_node->orig);
0536     hardif_neigh->if_incoming = hard_iface;
0537     hardif_neigh->last_seen = jiffies;
0538 
0539     kref_init(&hardif_neigh->refcount);
0540 
0541     if (bat_priv->algo_ops->neigh.hardif_init)
0542         bat_priv->algo_ops->neigh.hardif_init(hardif_neigh);
0543 
0544     hlist_add_head_rcu(&hardif_neigh->list, &hard_iface->neigh_list);
0545 
0546 out:
0547     spin_unlock_bh(&hard_iface->neigh_list_lock);
0548     return hardif_neigh;
0549 }
0550 
0551 /**
0552  * batadv_hardif_neigh_get_or_create() - retrieve or create a hardif neighbour
0553  *  node
0554  * @hard_iface: the interface this neighbour is connected to
0555  * @neigh_addr: the interface address of the neighbour to retrieve
0556  * @orig_node: originator object representing the neighbour
0557  *
0558  * Return: the hardif neighbour node if found or created or NULL otherwise.
0559  */
0560 static struct batadv_hardif_neigh_node *
0561 batadv_hardif_neigh_get_or_create(struct batadv_hard_iface *hard_iface,
0562                   const u8 *neigh_addr,
0563                   struct batadv_orig_node *orig_node)
0564 {
0565     struct batadv_hardif_neigh_node *hardif_neigh;
0566 
0567     /* first check without locking to avoid the overhead */
0568     hardif_neigh = batadv_hardif_neigh_get(hard_iface, neigh_addr);
0569     if (hardif_neigh)
0570         return hardif_neigh;
0571 
0572     return batadv_hardif_neigh_create(hard_iface, neigh_addr, orig_node);
0573 }
0574 
0575 /**
0576  * batadv_hardif_neigh_get() - retrieve a hardif neighbour from the list
0577  * @hard_iface: the interface where this neighbour is connected to
0578  * @neigh_addr: the address of the neighbour
0579  *
0580  * Looks for and possibly returns a neighbour belonging to this hard interface.
0581  *
0582  * Return: neighbor when found. Otherwise NULL
0583  */
0584 struct batadv_hardif_neigh_node *
0585 batadv_hardif_neigh_get(const struct batadv_hard_iface *hard_iface,
0586             const u8 *neigh_addr)
0587 {
0588     struct batadv_hardif_neigh_node *tmp_hardif_neigh, *hardif_neigh = NULL;
0589 
0590     rcu_read_lock();
0591     hlist_for_each_entry_rcu(tmp_hardif_neigh,
0592                  &hard_iface->neigh_list, list) {
0593         if (!batadv_compare_eth(tmp_hardif_neigh->addr, neigh_addr))
0594             continue;
0595 
0596         if (!kref_get_unless_zero(&tmp_hardif_neigh->refcount))
0597             continue;
0598 
0599         hardif_neigh = tmp_hardif_neigh;
0600         break;
0601     }
0602     rcu_read_unlock();
0603 
0604     return hardif_neigh;
0605 }
0606 
0607 /**
0608  * batadv_neigh_node_create() - create a neigh node object
0609  * @orig_node: originator object representing the neighbour
0610  * @hard_iface: the interface where the neighbour is connected to
0611  * @neigh_addr: the mac address of the neighbour interface
0612  *
0613  * Allocates a new neigh_node object and initialises all the generic fields.
0614  *
0615  * Return: the neighbour node if found or created or NULL otherwise.
0616  */
0617 static struct batadv_neigh_node *
0618 batadv_neigh_node_create(struct batadv_orig_node *orig_node,
0619              struct batadv_hard_iface *hard_iface,
0620              const u8 *neigh_addr)
0621 {
0622     struct batadv_neigh_node *neigh_node;
0623     struct batadv_hardif_neigh_node *hardif_neigh = NULL;
0624 
0625     spin_lock_bh(&orig_node->neigh_list_lock);
0626 
0627     neigh_node = batadv_neigh_node_get(orig_node, hard_iface, neigh_addr);
0628     if (neigh_node)
0629         goto out;
0630 
0631     hardif_neigh = batadv_hardif_neigh_get_or_create(hard_iface,
0632                              neigh_addr, orig_node);
0633     if (!hardif_neigh)
0634         goto out;
0635 
0636     neigh_node = kzalloc(sizeof(*neigh_node), GFP_ATOMIC);
0637     if (!neigh_node)
0638         goto out;
0639 
0640     INIT_HLIST_NODE(&neigh_node->list);
0641     INIT_HLIST_HEAD(&neigh_node->ifinfo_list);
0642     spin_lock_init(&neigh_node->ifinfo_lock);
0643 
0644     kref_get(&hard_iface->refcount);
0645     ether_addr_copy(neigh_node->addr, neigh_addr);
0646     neigh_node->if_incoming = hard_iface;
0647     neigh_node->orig_node = orig_node;
0648     neigh_node->last_seen = jiffies;
0649 
0650     /* increment unique neighbor refcount */
0651     kref_get(&hardif_neigh->refcount);
0652     neigh_node->hardif_neigh = hardif_neigh;
0653 
0654     /* extra reference for return */
0655     kref_init(&neigh_node->refcount);
0656 
0657     kref_get(&neigh_node->refcount);
0658     hlist_add_head_rcu(&neigh_node->list, &orig_node->neigh_list);
0659 
0660     batadv_dbg(BATADV_DBG_BATMAN, orig_node->bat_priv,
0661            "Creating new neighbor %pM for orig_node %pM on interface %s\n",
0662            neigh_addr, orig_node->orig, hard_iface->net_dev->name);
0663 
0664 out:
0665     spin_unlock_bh(&orig_node->neigh_list_lock);
0666 
0667     batadv_hardif_neigh_put(hardif_neigh);
0668     return neigh_node;
0669 }
0670 
0671 /**
0672  * batadv_neigh_node_get_or_create() - retrieve or create a neigh node object
0673  * @orig_node: originator object representing the neighbour
0674  * @hard_iface: the interface where the neighbour is connected to
0675  * @neigh_addr: the mac address of the neighbour interface
0676  *
0677  * Return: the neighbour node if found or created or NULL otherwise.
0678  */
0679 struct batadv_neigh_node *
0680 batadv_neigh_node_get_or_create(struct batadv_orig_node *orig_node,
0681                 struct batadv_hard_iface *hard_iface,
0682                 const u8 *neigh_addr)
0683 {
0684     struct batadv_neigh_node *neigh_node;
0685 
0686     /* first check without locking to avoid the overhead */
0687     neigh_node = batadv_neigh_node_get(orig_node, hard_iface, neigh_addr);
0688     if (neigh_node)
0689         return neigh_node;
0690 
0691     return batadv_neigh_node_create(orig_node, hard_iface, neigh_addr);
0692 }
0693 
0694 /**
0695  * batadv_hardif_neigh_dump() - Dump to netlink the neighbor infos for a
0696  *  specific outgoing interface
0697  * @msg: message to dump into
0698  * @cb: parameters for the dump
0699  *
0700  * Return: 0 or error value
0701  */
0702 int batadv_hardif_neigh_dump(struct sk_buff *msg, struct netlink_callback *cb)
0703 {
0704     struct net *net = sock_net(cb->skb->sk);
0705     struct net_device *soft_iface;
0706     struct net_device *hard_iface = NULL;
0707     struct batadv_hard_iface *hardif = BATADV_IF_DEFAULT;
0708     struct batadv_priv *bat_priv;
0709     struct batadv_hard_iface *primary_if = NULL;
0710     int ret;
0711     int ifindex, hard_ifindex;
0712 
0713     ifindex = batadv_netlink_get_ifindex(cb->nlh, BATADV_ATTR_MESH_IFINDEX);
0714     if (!ifindex)
0715         return -EINVAL;
0716 
0717     soft_iface = dev_get_by_index(net, ifindex);
0718     if (!soft_iface || !batadv_softif_is_valid(soft_iface)) {
0719         ret = -ENODEV;
0720         goto out;
0721     }
0722 
0723     bat_priv = netdev_priv(soft_iface);
0724 
0725     primary_if = batadv_primary_if_get_selected(bat_priv);
0726     if (!primary_if || primary_if->if_status != BATADV_IF_ACTIVE) {
0727         ret = -ENOENT;
0728         goto out;
0729     }
0730 
0731     hard_ifindex = batadv_netlink_get_ifindex(cb->nlh,
0732                           BATADV_ATTR_HARD_IFINDEX);
0733     if (hard_ifindex) {
0734         hard_iface = dev_get_by_index(net, hard_ifindex);
0735         if (hard_iface)
0736             hardif = batadv_hardif_get_by_netdev(hard_iface);
0737 
0738         if (!hardif) {
0739             ret = -ENODEV;
0740             goto out;
0741         }
0742 
0743         if (hardif->soft_iface != soft_iface) {
0744             ret = -ENOENT;
0745             goto out;
0746         }
0747     }
0748 
0749     if (!bat_priv->algo_ops->neigh.dump) {
0750         ret = -EOPNOTSUPP;
0751         goto out;
0752     }
0753 
0754     bat_priv->algo_ops->neigh.dump(msg, cb, bat_priv, hardif);
0755 
0756     ret = msg->len;
0757 
0758  out:
0759     batadv_hardif_put(hardif);
0760     dev_put(hard_iface);
0761     batadv_hardif_put(primary_if);
0762     dev_put(soft_iface);
0763 
0764     return ret;
0765 }
0766 
0767 /**
0768  * batadv_orig_ifinfo_release() - release orig_ifinfo from lists and queue for
0769  *  free after rcu grace period
0770  * @ref: kref pointer of the orig_ifinfo
0771  */
0772 void batadv_orig_ifinfo_release(struct kref *ref)
0773 {
0774     struct batadv_orig_ifinfo *orig_ifinfo;
0775     struct batadv_neigh_node *router;
0776 
0777     orig_ifinfo = container_of(ref, struct batadv_orig_ifinfo, refcount);
0778 
0779     if (orig_ifinfo->if_outgoing != BATADV_IF_DEFAULT)
0780         batadv_hardif_put(orig_ifinfo->if_outgoing);
0781 
0782     /* this is the last reference to this object */
0783     router = rcu_dereference_protected(orig_ifinfo->router, true);
0784     batadv_neigh_node_put(router);
0785 
0786     kfree_rcu(orig_ifinfo, rcu);
0787 }
0788 
0789 /**
0790  * batadv_orig_node_free_rcu() - free the orig_node
0791  * @rcu: rcu pointer of the orig_node
0792  */
0793 static void batadv_orig_node_free_rcu(struct rcu_head *rcu)
0794 {
0795     struct batadv_orig_node *orig_node;
0796 
0797     orig_node = container_of(rcu, struct batadv_orig_node, rcu);
0798 
0799     batadv_mcast_purge_orig(orig_node);
0800 
0801     batadv_frag_purge_orig(orig_node, NULL);
0802 
0803     kfree(orig_node->tt_buff);
0804     kfree(orig_node);
0805 }
0806 
0807 /**
0808  * batadv_orig_node_release() - release orig_node from lists and queue for
0809  *  free after rcu grace period
0810  * @ref: kref pointer of the orig_node
0811  */
0812 void batadv_orig_node_release(struct kref *ref)
0813 {
0814     struct hlist_node *node_tmp;
0815     struct batadv_neigh_node *neigh_node;
0816     struct batadv_orig_node *orig_node;
0817     struct batadv_orig_ifinfo *orig_ifinfo;
0818     struct batadv_orig_node_vlan *vlan;
0819     struct batadv_orig_ifinfo *last_candidate;
0820 
0821     orig_node = container_of(ref, struct batadv_orig_node, refcount);
0822 
0823     spin_lock_bh(&orig_node->neigh_list_lock);
0824 
0825     /* for all neighbors towards this originator ... */
0826     hlist_for_each_entry_safe(neigh_node, node_tmp,
0827                   &orig_node->neigh_list, list) {
0828         hlist_del_rcu(&neigh_node->list);
0829         batadv_neigh_node_put(neigh_node);
0830     }
0831 
0832     hlist_for_each_entry_safe(orig_ifinfo, node_tmp,
0833                   &orig_node->ifinfo_list, list) {
0834         hlist_del_rcu(&orig_ifinfo->list);
0835         batadv_orig_ifinfo_put(orig_ifinfo);
0836     }
0837 
0838     last_candidate = orig_node->last_bonding_candidate;
0839     orig_node->last_bonding_candidate = NULL;
0840     spin_unlock_bh(&orig_node->neigh_list_lock);
0841 
0842     batadv_orig_ifinfo_put(last_candidate);
0843 
0844     spin_lock_bh(&orig_node->vlan_list_lock);
0845     hlist_for_each_entry_safe(vlan, node_tmp, &orig_node->vlan_list, list) {
0846         hlist_del_rcu(&vlan->list);
0847         batadv_orig_node_vlan_put(vlan);
0848     }
0849     spin_unlock_bh(&orig_node->vlan_list_lock);
0850 
0851     /* Free nc_nodes */
0852     batadv_nc_purge_orig(orig_node->bat_priv, orig_node, NULL);
0853 
0854     call_rcu(&orig_node->rcu, batadv_orig_node_free_rcu);
0855 }
0856 
0857 /**
0858  * batadv_originator_free() - Free all originator structures
0859  * @bat_priv: the bat priv with all the soft interface information
0860  */
0861 void batadv_originator_free(struct batadv_priv *bat_priv)
0862 {
0863     struct batadv_hashtable *hash = bat_priv->orig_hash;
0864     struct hlist_node *node_tmp;
0865     struct hlist_head *head;
0866     spinlock_t *list_lock; /* spinlock to protect write access */
0867     struct batadv_orig_node *orig_node;
0868     u32 i;
0869 
0870     if (!hash)
0871         return;
0872 
0873     cancel_delayed_work_sync(&bat_priv->orig_work);
0874 
0875     bat_priv->orig_hash = NULL;
0876 
0877     for (i = 0; i < hash->size; i++) {
0878         head = &hash->table[i];
0879         list_lock = &hash->list_locks[i];
0880 
0881         spin_lock_bh(list_lock);
0882         hlist_for_each_entry_safe(orig_node, node_tmp,
0883                       head, hash_entry) {
0884             hlist_del_rcu(&orig_node->hash_entry);
0885             batadv_orig_node_put(orig_node);
0886         }
0887         spin_unlock_bh(list_lock);
0888     }
0889 
0890     batadv_hash_destroy(hash);
0891 }
0892 
0893 /**
0894  * batadv_orig_node_new() - creates a new orig_node
0895  * @bat_priv: the bat priv with all the soft interface information
0896  * @addr: the mac address of the originator
0897  *
0898  * Creates a new originator object and initialises all the generic fields.
0899  * The new object is not added to the originator list.
0900  *
0901  * Return: the newly created object or NULL on failure.
0902  */
0903 struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv,
0904                           const u8 *addr)
0905 {
0906     struct batadv_orig_node *orig_node;
0907     struct batadv_orig_node_vlan *vlan;
0908     unsigned long reset_time;
0909     int i;
0910 
0911     batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
0912            "Creating new originator: %pM\n", addr);
0913 
0914     orig_node = kzalloc(sizeof(*orig_node), GFP_ATOMIC);
0915     if (!orig_node)
0916         return NULL;
0917 
0918     INIT_HLIST_HEAD(&orig_node->neigh_list);
0919     INIT_HLIST_HEAD(&orig_node->vlan_list);
0920     INIT_HLIST_HEAD(&orig_node->ifinfo_list);
0921     spin_lock_init(&orig_node->bcast_seqno_lock);
0922     spin_lock_init(&orig_node->neigh_list_lock);
0923     spin_lock_init(&orig_node->tt_buff_lock);
0924     spin_lock_init(&orig_node->tt_lock);
0925     spin_lock_init(&orig_node->vlan_list_lock);
0926 
0927     batadv_nc_init_orig(orig_node);
0928 
0929     /* extra reference for return */
0930     kref_init(&orig_node->refcount);
0931 
0932     orig_node->bat_priv = bat_priv;
0933     ether_addr_copy(orig_node->orig, addr);
0934     batadv_dat_init_orig_node_addr(orig_node);
0935     atomic_set(&orig_node->last_ttvn, 0);
0936     orig_node->tt_buff = NULL;
0937     orig_node->tt_buff_len = 0;
0938     orig_node->last_seen = jiffies;
0939     reset_time = jiffies - 1 - msecs_to_jiffies(BATADV_RESET_PROTECTION_MS);
0940     orig_node->bcast_seqno_reset = reset_time;
0941 
0942 #ifdef CONFIG_BATMAN_ADV_MCAST
0943     orig_node->mcast_flags = BATADV_MCAST_WANT_NO_RTR4;
0944     orig_node->mcast_flags |= BATADV_MCAST_WANT_NO_RTR6;
0945     INIT_HLIST_NODE(&orig_node->mcast_want_all_unsnoopables_node);
0946     INIT_HLIST_NODE(&orig_node->mcast_want_all_ipv4_node);
0947     INIT_HLIST_NODE(&orig_node->mcast_want_all_ipv6_node);
0948     spin_lock_init(&orig_node->mcast_handler_lock);
0949 #endif
0950 
0951     /* create a vlan object for the "untagged" LAN */
0952     vlan = batadv_orig_node_vlan_new(orig_node, BATADV_NO_FLAGS);
0953     if (!vlan)
0954         goto free_orig_node;
0955     /* batadv_orig_node_vlan_new() increases the refcounter.
0956      * Immediately release vlan since it is not needed anymore in this
0957      * context
0958      */
0959     batadv_orig_node_vlan_put(vlan);
0960 
0961     for (i = 0; i < BATADV_FRAG_BUFFER_COUNT; i++) {
0962         INIT_HLIST_HEAD(&orig_node->fragments[i].fragment_list);
0963         spin_lock_init(&orig_node->fragments[i].lock);
0964         orig_node->fragments[i].size = 0;
0965     }
0966 
0967     return orig_node;
0968 free_orig_node:
0969     kfree(orig_node);
0970     return NULL;
0971 }
0972 
0973 /**
0974  * batadv_purge_neigh_ifinfo() - purge obsolete ifinfo entries from neighbor
0975  * @bat_priv: the bat priv with all the soft interface information
0976  * @neigh: orig node which is to be checked
0977  */
0978 static void
0979 batadv_purge_neigh_ifinfo(struct batadv_priv *bat_priv,
0980               struct batadv_neigh_node *neigh)
0981 {
0982     struct batadv_neigh_ifinfo *neigh_ifinfo;
0983     struct batadv_hard_iface *if_outgoing;
0984     struct hlist_node *node_tmp;
0985 
0986     spin_lock_bh(&neigh->ifinfo_lock);
0987 
0988     /* for all ifinfo objects for this neighinator */
0989     hlist_for_each_entry_safe(neigh_ifinfo, node_tmp,
0990                   &neigh->ifinfo_list, list) {
0991         if_outgoing = neigh_ifinfo->if_outgoing;
0992 
0993         /* always keep the default interface */
0994         if (if_outgoing == BATADV_IF_DEFAULT)
0995             continue;
0996 
0997         /* don't purge if the interface is not (going) down */
0998         if (if_outgoing->if_status != BATADV_IF_INACTIVE &&
0999             if_outgoing->if_status != BATADV_IF_NOT_IN_USE &&
1000             if_outgoing->if_status != BATADV_IF_TO_BE_REMOVED)
1001             continue;
1002 
1003         batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
1004                "neighbor/ifinfo purge: neighbor %pM, iface: %s\n",
1005                neigh->addr, if_outgoing->net_dev->name);
1006 
1007         hlist_del_rcu(&neigh_ifinfo->list);
1008         batadv_neigh_ifinfo_put(neigh_ifinfo);
1009     }
1010 
1011     spin_unlock_bh(&neigh->ifinfo_lock);
1012 }
1013 
1014 /**
1015  * batadv_purge_orig_ifinfo() - purge obsolete ifinfo entries from originator
1016  * @bat_priv: the bat priv with all the soft interface information
1017  * @orig_node: orig node which is to be checked
1018  *
1019  * Return: true if any ifinfo entry was purged, false otherwise.
1020  */
1021 static bool
1022 batadv_purge_orig_ifinfo(struct batadv_priv *bat_priv,
1023              struct batadv_orig_node *orig_node)
1024 {
1025     struct batadv_orig_ifinfo *orig_ifinfo;
1026     struct batadv_hard_iface *if_outgoing;
1027     struct hlist_node *node_tmp;
1028     bool ifinfo_purged = false;
1029 
1030     spin_lock_bh(&orig_node->neigh_list_lock);
1031 
1032     /* for all ifinfo objects for this originator */
1033     hlist_for_each_entry_safe(orig_ifinfo, node_tmp,
1034                   &orig_node->ifinfo_list, list) {
1035         if_outgoing = orig_ifinfo->if_outgoing;
1036 
1037         /* always keep the default interface */
1038         if (if_outgoing == BATADV_IF_DEFAULT)
1039             continue;
1040 
1041         /* don't purge if the interface is not (going) down */
1042         if (if_outgoing->if_status != BATADV_IF_INACTIVE &&
1043             if_outgoing->if_status != BATADV_IF_NOT_IN_USE &&
1044             if_outgoing->if_status != BATADV_IF_TO_BE_REMOVED)
1045             continue;
1046 
1047         batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
1048                "router/ifinfo purge: originator %pM, iface: %s\n",
1049                orig_node->orig, if_outgoing->net_dev->name);
1050 
1051         ifinfo_purged = true;
1052 
1053         hlist_del_rcu(&orig_ifinfo->list);
1054         batadv_orig_ifinfo_put(orig_ifinfo);
1055         if (orig_node->last_bonding_candidate == orig_ifinfo) {
1056             orig_node->last_bonding_candidate = NULL;
1057             batadv_orig_ifinfo_put(orig_ifinfo);
1058         }
1059     }
1060 
1061     spin_unlock_bh(&orig_node->neigh_list_lock);
1062 
1063     return ifinfo_purged;
1064 }
1065 
1066 /**
1067  * batadv_purge_orig_neighbors() - purges neighbors from originator
1068  * @bat_priv: the bat priv with all the soft interface information
1069  * @orig_node: orig node which is to be checked
1070  *
1071  * Return: true if any neighbor was purged, false otherwise
1072  */
1073 static bool
1074 batadv_purge_orig_neighbors(struct batadv_priv *bat_priv,
1075                 struct batadv_orig_node *orig_node)
1076 {
1077     struct hlist_node *node_tmp;
1078     struct batadv_neigh_node *neigh_node;
1079     bool neigh_purged = false;
1080     unsigned long last_seen;
1081     struct batadv_hard_iface *if_incoming;
1082 
1083     spin_lock_bh(&orig_node->neigh_list_lock);
1084 
1085     /* for all neighbors towards this originator ... */
1086     hlist_for_each_entry_safe(neigh_node, node_tmp,
1087                   &orig_node->neigh_list, list) {
1088         last_seen = neigh_node->last_seen;
1089         if_incoming = neigh_node->if_incoming;
1090 
1091         if (batadv_has_timed_out(last_seen, BATADV_PURGE_TIMEOUT) ||
1092             if_incoming->if_status == BATADV_IF_INACTIVE ||
1093             if_incoming->if_status == BATADV_IF_NOT_IN_USE ||
1094             if_incoming->if_status == BATADV_IF_TO_BE_REMOVED) {
1095             if (if_incoming->if_status == BATADV_IF_INACTIVE ||
1096                 if_incoming->if_status == BATADV_IF_NOT_IN_USE ||
1097                 if_incoming->if_status == BATADV_IF_TO_BE_REMOVED)
1098                 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
1099                        "neighbor purge: originator %pM, neighbor: %pM, iface: %s\n",
1100                        orig_node->orig, neigh_node->addr,
1101                        if_incoming->net_dev->name);
1102             else
1103                 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
1104                        "neighbor timeout: originator %pM, neighbor: %pM, last_seen: %u\n",
1105                        orig_node->orig, neigh_node->addr,
1106                        jiffies_to_msecs(last_seen));
1107 
1108             neigh_purged = true;
1109 
1110             hlist_del_rcu(&neigh_node->list);
1111             batadv_neigh_node_put(neigh_node);
1112         } else {
1113             /* only necessary if not the whole neighbor is to be
1114              * deleted, but some interface has been removed.
1115              */
1116             batadv_purge_neigh_ifinfo(bat_priv, neigh_node);
1117         }
1118     }
1119 
1120     spin_unlock_bh(&orig_node->neigh_list_lock);
1121     return neigh_purged;
1122 }
1123 
1124 /**
1125  * batadv_find_best_neighbor() - finds the best neighbor after purging
1126  * @bat_priv: the bat priv with all the soft interface information
1127  * @orig_node: orig node which is to be checked
1128  * @if_outgoing: the interface for which the metric should be compared
1129  *
1130  * Return: the current best neighbor, with refcount increased.
1131  */
1132 static struct batadv_neigh_node *
1133 batadv_find_best_neighbor(struct batadv_priv *bat_priv,
1134               struct batadv_orig_node *orig_node,
1135               struct batadv_hard_iface *if_outgoing)
1136 {
1137     struct batadv_neigh_node *best = NULL, *neigh;
1138     struct batadv_algo_ops *bao = bat_priv->algo_ops;
1139 
1140     rcu_read_lock();
1141     hlist_for_each_entry_rcu(neigh, &orig_node->neigh_list, list) {
1142         if (best && (bao->neigh.cmp(neigh, if_outgoing, best,
1143                         if_outgoing) <= 0))
1144             continue;
1145 
1146         if (!kref_get_unless_zero(&neigh->refcount))
1147             continue;
1148 
1149         batadv_neigh_node_put(best);
1150 
1151         best = neigh;
1152     }
1153     rcu_read_unlock();
1154 
1155     return best;
1156 }
1157 
1158 /**
1159  * batadv_purge_orig_node() - purges obsolete information from an orig_node
1160  * @bat_priv: the bat priv with all the soft interface information
1161  * @orig_node: orig node which is to be checked
1162  *
1163  * This function checks if the orig_node or substructures of it have become
1164  * obsolete, and purges this information if that's the case.
1165  *
1166  * Return: true if the orig_node is to be removed, false otherwise.
1167  */
1168 static bool batadv_purge_orig_node(struct batadv_priv *bat_priv,
1169                    struct batadv_orig_node *orig_node)
1170 {
1171     struct batadv_neigh_node *best_neigh_node;
1172     struct batadv_hard_iface *hard_iface;
1173     bool changed_ifinfo, changed_neigh;
1174 
1175     if (batadv_has_timed_out(orig_node->last_seen,
1176                  2 * BATADV_PURGE_TIMEOUT)) {
1177         batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
1178                "Originator timeout: originator %pM, last_seen %u\n",
1179                orig_node->orig,
1180                jiffies_to_msecs(orig_node->last_seen));
1181         return true;
1182     }
1183     changed_ifinfo = batadv_purge_orig_ifinfo(bat_priv, orig_node);
1184     changed_neigh = batadv_purge_orig_neighbors(bat_priv, orig_node);
1185 
1186     if (!changed_ifinfo && !changed_neigh)
1187         return false;
1188 
1189     /* first for NULL ... */
1190     best_neigh_node = batadv_find_best_neighbor(bat_priv, orig_node,
1191                             BATADV_IF_DEFAULT);
1192     batadv_update_route(bat_priv, orig_node, BATADV_IF_DEFAULT,
1193                 best_neigh_node);
1194     batadv_neigh_node_put(best_neigh_node);
1195 
1196     /* ... then for all other interfaces. */
1197     rcu_read_lock();
1198     list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
1199         if (hard_iface->if_status != BATADV_IF_ACTIVE)
1200             continue;
1201 
1202         if (hard_iface->soft_iface != bat_priv->soft_iface)
1203             continue;
1204 
1205         if (!kref_get_unless_zero(&hard_iface->refcount))
1206             continue;
1207 
1208         best_neigh_node = batadv_find_best_neighbor(bat_priv,
1209                                 orig_node,
1210                                 hard_iface);
1211         batadv_update_route(bat_priv, orig_node, hard_iface,
1212                     best_neigh_node);
1213         batadv_neigh_node_put(best_neigh_node);
1214 
1215         batadv_hardif_put(hard_iface);
1216     }
1217     rcu_read_unlock();
1218 
1219     return false;
1220 }
1221 
1222 /**
1223  * batadv_purge_orig_ref() - Purge all outdated originators
1224  * @bat_priv: the bat priv with all the soft interface information
1225  */
1226 void batadv_purge_orig_ref(struct batadv_priv *bat_priv)
1227 {
1228     struct batadv_hashtable *hash = bat_priv->orig_hash;
1229     struct hlist_node *node_tmp;
1230     struct hlist_head *head;
1231     spinlock_t *list_lock; /* spinlock to protect write access */
1232     struct batadv_orig_node *orig_node;
1233     u32 i;
1234 
1235     if (!hash)
1236         return;
1237 
1238     /* for all origins... */
1239     for (i = 0; i < hash->size; i++) {
1240         head = &hash->table[i];
1241         list_lock = &hash->list_locks[i];
1242 
1243         spin_lock_bh(list_lock);
1244         hlist_for_each_entry_safe(orig_node, node_tmp,
1245                       head, hash_entry) {
1246             if (batadv_purge_orig_node(bat_priv, orig_node)) {
1247                 batadv_gw_node_delete(bat_priv, orig_node);
1248                 hlist_del_rcu(&orig_node->hash_entry);
1249                 batadv_tt_global_del_orig(orig_node->bat_priv,
1250                               orig_node, -1,
1251                               "originator timed out");
1252                 batadv_orig_node_put(orig_node);
1253                 continue;
1254             }
1255 
1256             batadv_frag_purge_orig(orig_node,
1257                            batadv_frag_check_entry);
1258         }
1259         spin_unlock_bh(list_lock);
1260     }
1261 
1262     batadv_gw_election(bat_priv);
1263 }
1264 
1265 static void batadv_purge_orig(struct work_struct *work)
1266 {
1267     struct delayed_work *delayed_work;
1268     struct batadv_priv *bat_priv;
1269 
1270     delayed_work = to_delayed_work(work);
1271     bat_priv = container_of(delayed_work, struct batadv_priv, orig_work);
1272     batadv_purge_orig_ref(bat_priv);
1273     queue_delayed_work(batadv_event_workqueue,
1274                &bat_priv->orig_work,
1275                msecs_to_jiffies(BATADV_ORIG_WORK_PERIOD));
1276 }
1277 
1278 /**
1279  * batadv_orig_dump() - Dump to netlink the originator infos for a specific
1280  *  outgoing interface
1281  * @msg: message to dump into
1282  * @cb: parameters for the dump
1283  *
1284  * Return: 0 or error value
1285  */
1286 int batadv_orig_dump(struct sk_buff *msg, struct netlink_callback *cb)
1287 {
1288     struct net *net = sock_net(cb->skb->sk);
1289     struct net_device *soft_iface;
1290     struct net_device *hard_iface = NULL;
1291     struct batadv_hard_iface *hardif = BATADV_IF_DEFAULT;
1292     struct batadv_priv *bat_priv;
1293     struct batadv_hard_iface *primary_if = NULL;
1294     int ret;
1295     int ifindex, hard_ifindex;
1296 
1297     ifindex = batadv_netlink_get_ifindex(cb->nlh, BATADV_ATTR_MESH_IFINDEX);
1298     if (!ifindex)
1299         return -EINVAL;
1300 
1301     soft_iface = dev_get_by_index(net, ifindex);
1302     if (!soft_iface || !batadv_softif_is_valid(soft_iface)) {
1303         ret = -ENODEV;
1304         goto out;
1305     }
1306 
1307     bat_priv = netdev_priv(soft_iface);
1308 
1309     primary_if = batadv_primary_if_get_selected(bat_priv);
1310     if (!primary_if || primary_if->if_status != BATADV_IF_ACTIVE) {
1311         ret = -ENOENT;
1312         goto out;
1313     }
1314 
1315     hard_ifindex = batadv_netlink_get_ifindex(cb->nlh,
1316                           BATADV_ATTR_HARD_IFINDEX);
1317     if (hard_ifindex) {
1318         hard_iface = dev_get_by_index(net, hard_ifindex);
1319         if (hard_iface)
1320             hardif = batadv_hardif_get_by_netdev(hard_iface);
1321 
1322         if (!hardif) {
1323             ret = -ENODEV;
1324             goto out;
1325         }
1326 
1327         if (hardif->soft_iface != soft_iface) {
1328             ret = -ENOENT;
1329             goto out;
1330         }
1331     }
1332 
1333     if (!bat_priv->algo_ops->orig.dump) {
1334         ret = -EOPNOTSUPP;
1335         goto out;
1336     }
1337 
1338     bat_priv->algo_ops->orig.dump(msg, cb, bat_priv, hardif);
1339 
1340     ret = msg->len;
1341 
1342  out:
1343     batadv_hardif_put(hardif);
1344     dev_put(hard_iface);
1345     batadv_hardif_put(primary_if);
1346     dev_put(soft_iface);
1347 
1348     return ret;
1349 }