blob: d8c5d3170676504ea845d200762ed26fc7122cba [file] [log] [blame]
Sven Eckelmann7db7d9f2017-11-19 15:05:11 +01001// SPDX-License-Identifier: GPL-2.0
Sven Eckelmann68e039f2020-01-01 00:00:01 +01002/* Copyright (C) 2011-2020 B.A.T.M.A.N. contributors:
Simon Wunderlich23721382012-01-22 20:00:19 +01003 *
4 * Simon Wunderlich
Simon Wunderlich23721382012-01-22 20:00:19 +01005 */
6
Simon Wunderlich23721382012-01-22 20:00:19 +01007#include "bridge_loop_avoidance.h"
Sven Eckelmann1e2c2a42015-04-17 19:40:28 +02008#include "main.h"
Simon Wunderlich23721382012-01-22 20:00:19 +01009
Sven Eckelmann1e2c2a42015-04-17 19:40:28 +020010#include <linux/atomic.h>
11#include <linux/byteorder/generic.h>
12#include <linux/compiler.h>
Simon Wunderlich23721382012-01-22 20:00:19 +010013#include <linux/crc16.h>
Sven Eckelmann1e2c2a42015-04-17 19:40:28 +020014#include <linux/errno.h>
15#include <linux/etherdevice.h>
Sven Eckelmannb92b94a2017-11-19 17:12:02 +010016#include <linux/gfp.h>
Simon Wunderlich23721382012-01-22 20:00:19 +010017#include <linux/if_arp.h>
Sven Eckelmann1e2c2a42015-04-17 19:40:28 +020018#include <linux/if_ether.h>
Simon Wunderlich23721382012-01-22 20:00:19 +010019#include <linux/if_vlan.h>
Sven Eckelmann1e2c2a42015-04-17 19:40:28 +020020#include <linux/jhash.h>
21#include <linux/jiffies.h>
22#include <linux/kernel.h>
Sven Eckelmann06e56de2016-01-16 10:29:43 +010023#include <linux/kref.h>
Sven Eckelmann1e2c2a42015-04-17 19:40:28 +020024#include <linux/list.h>
25#include <linux/lockdep.h>
26#include <linux/netdevice.h>
Andrew Lunn04f3f5b2016-07-03 13:31:45 +020027#include <linux/netlink.h>
Sven Eckelmann1e2c2a42015-04-17 19:40:28 +020028#include <linux/rculist.h>
29#include <linux/rcupdate.h>
30#include <linux/seq_file.h>
31#include <linux/skbuff.h>
32#include <linux/slab.h>
33#include <linux/spinlock.h>
34#include <linux/stddef.h>
35#include <linux/string.h>
36#include <linux/workqueue.h>
37#include <net/arp.h>
Andrew Lunn04f3f5b2016-07-03 13:31:45 +020038#include <net/genetlink.h>
39#include <net/netlink.h>
40#include <net/sock.h>
Sven Eckelmannfec149f2017-12-21 10:17:41 +010041#include <uapi/linux/batadv_packet.h>
Andrew Lunn04f3f5b2016-07-03 13:31:45 +020042#include <uapi/linux/batman_adv.h>
Sven Eckelmann1e2c2a42015-04-17 19:40:28 +020043
44#include "hard-interface.h"
45#include "hash.h"
Sven Eckelmannba412082016-05-15 23:48:31 +020046#include "log.h"
Andrew Lunn04f3f5b2016-07-03 13:31:45 +020047#include "netlink.h"
Sven Eckelmann1e2c2a42015-04-17 19:40:28 +020048#include "originator.h"
Andrew Lunn04f3f5b2016-07-03 13:31:45 +020049#include "soft-interface.h"
Sven Eckelmann1e2c2a42015-04-17 19:40:28 +020050#include "translation-table.h"
Simon Wunderlich23721382012-01-22 20:00:19 +010051
Sven Eckelmann6b5e9712015-05-26 18:34:26 +020052static const u8 batadv_announce_mac[4] = {0x43, 0x05, 0x43, 0x05};
Simon Wunderlich23721382012-01-22 20:00:19 +010053
Sven Eckelmann3b300de2012-05-12 18:33:53 +020054static void batadv_bla_periodic_work(struct work_struct *work);
Marek Lindnerbae98772012-12-25 17:03:24 +080055static void
56batadv_bla_send_announce(struct batadv_priv *bat_priv,
57 struct batadv_bla_backbone_gw *backbone_gw);
Simon Wunderlich23721382012-01-22 20:00:19 +010058
Sven Eckelmann62fe7102015-09-15 19:00:48 +020059/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +010060 * batadv_choose_claim() - choose the right bucket for a claim.
Simon Wunderlich04e14be2015-11-06 10:45:19 +010061 * @data: data to hash
62 * @size: size of the hash table
Sven Eckelmann62fe7102015-09-15 19:00:48 +020063 *
Simon Wunderlich04e14be2015-11-06 10:45:19 +010064 * Return: the hash index of the claim
Sven Eckelmann62fe7102015-09-15 19:00:48 +020065 */
Sven Eckelmann6b5e9712015-05-26 18:34:26 +020066static inline u32 batadv_choose_claim(const void *data, u32 size)
Simon Wunderlich23721382012-01-22 20:00:19 +010067{
Marek Lindner712bbfe42012-12-25 17:03:25 +080068 struct batadv_bla_claim *claim = (struct batadv_bla_claim *)data;
Sven Eckelmann6b5e9712015-05-26 18:34:26 +020069 u32 hash = 0;
Simon Wunderlich23721382012-01-22 20:00:19 +010070
Sven Eckelmann36fd61c2015-03-01 09:46:18 +010071 hash = jhash(&claim->addr, sizeof(claim->addr), hash);
72 hash = jhash(&claim->vid, sizeof(claim->vid), hash);
Simon Wunderlich23721382012-01-22 20:00:19 +010073
74 return hash % size;
75}
76
Sven Eckelmann62fe7102015-09-15 19:00:48 +020077/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +010078 * batadv_choose_backbone_gw() - choose the right bucket for a backbone gateway.
Simon Wunderlich04e14be2015-11-06 10:45:19 +010079 * @data: data to hash
80 * @size: size of the hash table
Sven Eckelmann62fe7102015-09-15 19:00:48 +020081 *
Simon Wunderlich04e14be2015-11-06 10:45:19 +010082 * Return: the hash index of the backbone gateway
Sven Eckelmann62fe7102015-09-15 19:00:48 +020083 */
Sven Eckelmann6b5e9712015-05-26 18:34:26 +020084static inline u32 batadv_choose_backbone_gw(const void *data, u32 size)
Simon Wunderlich23721382012-01-22 20:00:19 +010085{
Linus Lüssing097930e2020-08-27 17:34:48 +020086 const struct batadv_bla_backbone_gw *gw;
Sven Eckelmann6b5e9712015-05-26 18:34:26 +020087 u32 hash = 0;
Simon Wunderlich23721382012-01-22 20:00:19 +010088
Linus Lüssing097930e2020-08-27 17:34:48 +020089 gw = (struct batadv_bla_backbone_gw *)data;
90 hash = jhash(&gw->orig, sizeof(gw->orig), hash);
91 hash = jhash(&gw->vid, sizeof(gw->vid), hash);
Simon Wunderlich23721382012-01-22 20:00:19 +010092
93 return hash % size;
94}
95
Simon Wunderlich04e14be2015-11-06 10:45:19 +010096/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +010097 * batadv_compare_backbone_gw() - compare address and vid of two backbone gws
Simon Wunderlich04e14be2015-11-06 10:45:19 +010098 * @node: list node of the first entry to compare
99 * @data2: pointer to the second backbone gateway
100 *
Sven Eckelmann4b426b12016-02-22 21:02:39 +0100101 * Return: true if the backbones have the same data, false otherwise
Simon Wunderlich04e14be2015-11-06 10:45:19 +0100102 */
Sven Eckelmann4b426b12016-02-22 21:02:39 +0100103static bool batadv_compare_backbone_gw(const struct hlist_node *node,
104 const void *data2)
Simon Wunderlich23721382012-01-22 20:00:19 +0100105{
Marek Lindnerbae98772012-12-25 17:03:24 +0800106 const void *data1 = container_of(node, struct batadv_bla_backbone_gw,
Simon Wunderlich23721382012-01-22 20:00:19 +0100107 hash_entry);
Sven Eckelmann4f248cf2015-06-09 20:50:49 +0200108 const struct batadv_bla_backbone_gw *gw1 = data1;
109 const struct batadv_bla_backbone_gw *gw2 = data2;
Simon Wunderlich23721382012-01-22 20:00:19 +0100110
Simon Wunderlichc76d1522012-10-15 22:38:04 +0200111 if (!batadv_compare_eth(gw1->orig, gw2->orig))
Sven Eckelmann4b426b12016-02-22 21:02:39 +0100112 return false;
Simon Wunderlichc76d1522012-10-15 22:38:04 +0200113
114 if (gw1->vid != gw2->vid)
Sven Eckelmann4b426b12016-02-22 21:02:39 +0100115 return false;
Simon Wunderlichc76d1522012-10-15 22:38:04 +0200116
Sven Eckelmann4b426b12016-02-22 21:02:39 +0100117 return true;
Simon Wunderlich23721382012-01-22 20:00:19 +0100118}
119
Simon Wunderlich04e14be2015-11-06 10:45:19 +0100120/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100121 * batadv_compare_claim() - compare address and vid of two claims
Simon Wunderlich04e14be2015-11-06 10:45:19 +0100122 * @node: list node of the first entry to compare
123 * @data2: pointer to the second claims
124 *
Sven Eckelmann4b426b12016-02-22 21:02:39 +0100125 * Return: true if the claim have the same data, 0 otherwise
Simon Wunderlich04e14be2015-11-06 10:45:19 +0100126 */
Sven Eckelmann4b426b12016-02-22 21:02:39 +0100127static bool batadv_compare_claim(const struct hlist_node *node,
128 const void *data2)
Simon Wunderlich23721382012-01-22 20:00:19 +0100129{
Marek Lindner712bbfe42012-12-25 17:03:25 +0800130 const void *data1 = container_of(node, struct batadv_bla_claim,
Simon Wunderlich23721382012-01-22 20:00:19 +0100131 hash_entry);
Sven Eckelmann4f248cf2015-06-09 20:50:49 +0200132 const struct batadv_bla_claim *cl1 = data1;
133 const struct batadv_bla_claim *cl2 = data2;
Simon Wunderlich23721382012-01-22 20:00:19 +0100134
Simon Wunderlichc76d1522012-10-15 22:38:04 +0200135 if (!batadv_compare_eth(cl1->addr, cl2->addr))
Sven Eckelmann4b426b12016-02-22 21:02:39 +0100136 return false;
Simon Wunderlichc76d1522012-10-15 22:38:04 +0200137
138 if (cl1->vid != cl2->vid)
Sven Eckelmann4b426b12016-02-22 21:02:39 +0100139 return false;
Simon Wunderlichc76d1522012-10-15 22:38:04 +0200140
Sven Eckelmann4b426b12016-02-22 21:02:39 +0100141 return true;
Simon Wunderlich23721382012-01-22 20:00:19 +0100142}
143
Simon Wunderlich04e14be2015-11-06 10:45:19 +0100144/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100145 * batadv_backbone_gw_release() - release backbone gw from lists and queue for
Sven Eckelmann06e56de2016-01-16 10:29:43 +0100146 * free after rcu grace period
147 * @ref: kref pointer of the backbone gw
148 */
149static void batadv_backbone_gw_release(struct kref *ref)
150{
151 struct batadv_bla_backbone_gw *backbone_gw;
152
153 backbone_gw = container_of(ref, struct batadv_bla_backbone_gw,
154 refcount);
155
156 kfree_rcu(backbone_gw, rcu);
157}
158
159/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100160 * batadv_backbone_gw_put() - decrement the backbone gw refcounter and possibly
Sven Eckelmannc8b86c12016-01-17 11:01:15 +0100161 * release it
Simon Wunderlich04e14be2015-11-06 10:45:19 +0100162 * @backbone_gw: backbone gateway to be free'd
163 */
Sven Eckelmannc8b86c12016-01-17 11:01:15 +0100164static void batadv_backbone_gw_put(struct batadv_bla_backbone_gw *backbone_gw)
Simon Wunderlich23721382012-01-22 20:00:19 +0100165{
Sven Eckelmann06e56de2016-01-16 10:29:43 +0100166 kref_put(&backbone_gw->refcount, batadv_backbone_gw_release);
Simon Wunderlich23721382012-01-22 20:00:19 +0100167}
168
Simon Wunderlich04e14be2015-11-06 10:45:19 +0100169/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100170 * batadv_claim_release() - release claim from lists and queue for free after
171 * rcu grace period
Simon Wunderlich04e14be2015-11-06 10:45:19 +0100172 * @ref: kref pointer of the claim
173 */
Sven Eckelmann71b7e3d2016-01-16 10:29:44 +0100174static void batadv_claim_release(struct kref *ref)
Simon Wunderlich23721382012-01-22 20:00:19 +0100175{
Sven Eckelmann71b7e3d2016-01-16 10:29:44 +0100176 struct batadv_bla_claim *claim;
Sven Eckelmann3db0dec2016-07-01 15:49:43 +0200177 struct batadv_bla_backbone_gw *old_backbone_gw;
Sven Eckelmann71b7e3d2016-01-16 10:29:44 +0100178
179 claim = container_of(ref, struct batadv_bla_claim, refcount);
180
Sven Eckelmann3db0dec2016-07-01 15:49:43 +0200181 spin_lock_bh(&claim->backbone_lock);
182 old_backbone_gw = claim->backbone_gw;
183 claim->backbone_gw = NULL;
184 spin_unlock_bh(&claim->backbone_lock);
185
186 spin_lock_bh(&old_backbone_gw->crc_lock);
187 old_backbone_gw->crc ^= crc16(0, claim->addr, ETH_ALEN);
188 spin_unlock_bh(&old_backbone_gw->crc_lock);
189
190 batadv_backbone_gw_put(old_backbone_gw);
191
Sven Eckelmann63b39922016-01-14 15:28:19 +0100192 kfree_rcu(claim, rcu);
Simon Wunderlich23721382012-01-22 20:00:19 +0100193}
194
Simon Wunderlich04e14be2015-11-06 10:45:19 +0100195/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100196 * batadv_claim_put() - decrement the claim refcounter and possibly release it
Simon Wunderlich04e14be2015-11-06 10:45:19 +0100197 * @claim: claim to be free'd
198 */
Sven Eckelmann321e3e02016-01-17 11:01:16 +0100199static void batadv_claim_put(struct batadv_bla_claim *claim)
Simon Wunderlich23721382012-01-22 20:00:19 +0100200{
Sven Eckelmann71b7e3d2016-01-16 10:29:44 +0100201 kref_put(&claim->refcount, batadv_claim_release);
Simon Wunderlich23721382012-01-22 20:00:19 +0100202}
203
Simon Wunderlich1b371d12014-01-15 21:17:54 +0100204/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100205 * batadv_claim_hash_find() - looks for a claim in the claim hash
Simon Wunderlich1b371d12014-01-15 21:17:54 +0100206 * @bat_priv: the bat priv with all the soft interface information
Simon Wunderlich23721382012-01-22 20:00:19 +0100207 * @data: search data (may be local/static data)
208 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +0200209 * Return: claim if found or NULL otherwise.
Simon Wunderlich23721382012-01-22 20:00:19 +0100210 */
Sven Eckelmann6fc77a52016-03-05 15:56:01 +0100211static struct batadv_bla_claim *
212batadv_claim_hash_find(struct batadv_priv *bat_priv,
213 struct batadv_bla_claim *data)
Simon Wunderlich23721382012-01-22 20:00:19 +0100214{
Sven Eckelmann807736f2012-07-15 22:26:51 +0200215 struct batadv_hashtable *hash = bat_priv->bla.claim_hash;
Simon Wunderlich23721382012-01-22 20:00:19 +0100216 struct hlist_head *head;
Marek Lindner712bbfe42012-12-25 17:03:25 +0800217 struct batadv_bla_claim *claim;
218 struct batadv_bla_claim *claim_tmp = NULL;
Simon Wunderlich23721382012-01-22 20:00:19 +0100219 int index;
220
221 if (!hash)
222 return NULL;
223
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200224 index = batadv_choose_claim(data, hash->size);
Simon Wunderlich23721382012-01-22 20:00:19 +0100225 head = &hash->table[index];
226
227 rcu_read_lock();
Sasha Levinb67bfe02013-02-27 17:06:00 -0800228 hlist_for_each_entry_rcu(claim, head, hash_entry) {
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200229 if (!batadv_compare_claim(&claim->hash_entry, data))
Simon Wunderlich23721382012-01-22 20:00:19 +0100230 continue;
231
Sven Eckelmann71b7e3d2016-01-16 10:29:44 +0100232 if (!kref_get_unless_zero(&claim->refcount))
Simon Wunderlich23721382012-01-22 20:00:19 +0100233 continue;
234
235 claim_tmp = claim;
236 break;
237 }
238 rcu_read_unlock();
239
240 return claim_tmp;
241}
242
Ben Hutchings2c530402012-07-10 10:55:09 +0000243/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100244 * batadv_backbone_hash_find() - looks for a backbone gateway in the hash
Ben Hutchings2c530402012-07-10 10:55:09 +0000245 * @bat_priv: the bat priv with all the soft interface information
Simon Wunderlich23721382012-01-22 20:00:19 +0100246 * @addr: the address of the originator
247 * @vid: the VLAN ID
248 *
Simon Wunderlich04e14be2015-11-06 10:45:19 +0100249 * Return: backbone gateway if found or NULL otherwise
Simon Wunderlich23721382012-01-22 20:00:19 +0100250 */
Marek Lindnerbae98772012-12-25 17:03:24 +0800251static struct batadv_bla_backbone_gw *
Sven Eckelmann6b5e9712015-05-26 18:34:26 +0200252batadv_backbone_hash_find(struct batadv_priv *bat_priv, u8 *addr,
253 unsigned short vid)
Simon Wunderlich23721382012-01-22 20:00:19 +0100254{
Sven Eckelmann807736f2012-07-15 22:26:51 +0200255 struct batadv_hashtable *hash = bat_priv->bla.backbone_hash;
Simon Wunderlich23721382012-01-22 20:00:19 +0100256 struct hlist_head *head;
Marek Lindnerbae98772012-12-25 17:03:24 +0800257 struct batadv_bla_backbone_gw search_entry, *backbone_gw;
258 struct batadv_bla_backbone_gw *backbone_gw_tmp = NULL;
Simon Wunderlich23721382012-01-22 20:00:19 +0100259 int index;
260
261 if (!hash)
262 return NULL;
263
Antonio Quartulli8fdd0152014-01-22 00:42:11 +0100264 ether_addr_copy(search_entry.orig, addr);
Simon Wunderlich23721382012-01-22 20:00:19 +0100265 search_entry.vid = vid;
266
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200267 index = batadv_choose_backbone_gw(&search_entry, hash->size);
Simon Wunderlich23721382012-01-22 20:00:19 +0100268 head = &hash->table[index];
269
270 rcu_read_lock();
Sasha Levinb67bfe02013-02-27 17:06:00 -0800271 hlist_for_each_entry_rcu(backbone_gw, head, hash_entry) {
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200272 if (!batadv_compare_backbone_gw(&backbone_gw->hash_entry,
273 &search_entry))
Simon Wunderlich23721382012-01-22 20:00:19 +0100274 continue;
275
Sven Eckelmann06e56de2016-01-16 10:29:43 +0100276 if (!kref_get_unless_zero(&backbone_gw->refcount))
Simon Wunderlich23721382012-01-22 20:00:19 +0100277 continue;
278
279 backbone_gw_tmp = backbone_gw;
280 break;
281 }
282 rcu_read_unlock();
283
284 return backbone_gw_tmp;
285}
286
Simon Wunderlich04e14be2015-11-06 10:45:19 +0100287/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100288 * batadv_bla_del_backbone_claims() - delete all claims for a backbone
Simon Wunderlich04e14be2015-11-06 10:45:19 +0100289 * @backbone_gw: backbone gateway where the claims should be removed
290 */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200291static void
Marek Lindnerbae98772012-12-25 17:03:24 +0800292batadv_bla_del_backbone_claims(struct batadv_bla_backbone_gw *backbone_gw)
Simon Wunderlich23721382012-01-22 20:00:19 +0100293{
Sven Eckelmann5bf74e92012-06-05 22:31:28 +0200294 struct batadv_hashtable *hash;
Sasha Levinb67bfe02013-02-27 17:06:00 -0800295 struct hlist_node *node_tmp;
Simon Wunderlich23721382012-01-22 20:00:19 +0100296 struct hlist_head *head;
Marek Lindner712bbfe42012-12-25 17:03:25 +0800297 struct batadv_bla_claim *claim;
Simon Wunderlich23721382012-01-22 20:00:19 +0100298 int i;
299 spinlock_t *list_lock; /* protects write access to the hash lists */
300
Sven Eckelmann807736f2012-07-15 22:26:51 +0200301 hash = backbone_gw->bat_priv->bla.claim_hash;
Simon Wunderlich23721382012-01-22 20:00:19 +0100302 if (!hash)
303 return;
304
305 for (i = 0; i < hash->size; i++) {
306 head = &hash->table[i];
307 list_lock = &hash->list_locks[i];
308
309 spin_lock_bh(list_lock);
Sasha Levinb67bfe02013-02-27 17:06:00 -0800310 hlist_for_each_entry_safe(claim, node_tmp,
Simon Wunderlich23721382012-01-22 20:00:19 +0100311 head, hash_entry) {
Simon Wunderlich23721382012-01-22 20:00:19 +0100312 if (claim->backbone_gw != backbone_gw)
313 continue;
314
Sven Eckelmann321e3e02016-01-17 11:01:16 +0100315 batadv_claim_put(claim);
Sasha Levinb67bfe02013-02-27 17:06:00 -0800316 hlist_del_rcu(&claim->hash_entry);
Simon Wunderlich23721382012-01-22 20:00:19 +0100317 }
318 spin_unlock_bh(list_lock);
319 }
320
Antonio Quartulli3f687852014-11-02 11:29:56 +0100321 /* all claims gone, initialize CRC */
Simon Wunderlich5a1dd8a2015-09-11 18:04:13 +0200322 spin_lock_bh(&backbone_gw->crc_lock);
Sven Eckelmann3964f722012-06-03 22:19:10 +0200323 backbone_gw->crc = BATADV_BLA_CRC_INIT;
Simon Wunderlich5a1dd8a2015-09-11 18:04:13 +0200324 spin_unlock_bh(&backbone_gw->crc_lock);
Simon Wunderlich23721382012-01-22 20:00:19 +0100325}
326
Ben Hutchings2c530402012-07-10 10:55:09 +0000327/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100328 * batadv_bla_send_claim() - sends a claim frame according to the provided info
Ben Hutchings2c530402012-07-10 10:55:09 +0000329 * @bat_priv: the bat priv with all the soft interface information
Martin Hundebølle3357182014-07-15 09:41:06 +0200330 * @mac: the mac address to be announced within the claim
Simon Wunderlich23721382012-01-22 20:00:19 +0100331 * @vid: the VLAN ID
332 * @claimtype: the type of the claim (CLAIM, UNCLAIM, ANNOUNCE, ...)
Simon Wunderlich23721382012-01-22 20:00:19 +0100333 */
Sven Eckelmann6b5e9712015-05-26 18:34:26 +0200334static void batadv_bla_send_claim(struct batadv_priv *bat_priv, u8 *mac,
Antonio Quartullieb2deb62013-04-19 18:07:00 +0200335 unsigned short vid, int claimtype)
Simon Wunderlich23721382012-01-22 20:00:19 +0100336{
337 struct sk_buff *skb;
338 struct ethhdr *ethhdr;
Sven Eckelmann56303d32012-06-05 22:31:31 +0200339 struct batadv_hard_iface *primary_if;
Simon Wunderlich23721382012-01-22 20:00:19 +0100340 struct net_device *soft_iface;
Sven Eckelmann6b5e9712015-05-26 18:34:26 +0200341 u8 *hw_src;
Sven Eckelmann96412692012-06-05 22:31:30 +0200342 struct batadv_bla_claim_dst local_claim_dest;
Al Viro3e2f1a12012-04-22 07:47:50 +0100343 __be32 zeroip = 0;
Simon Wunderlich23721382012-01-22 20:00:19 +0100344
Sven Eckelmanne5d89252012-05-12 13:48:54 +0200345 primary_if = batadv_primary_if_get_selected(bat_priv);
Simon Wunderlich23721382012-01-22 20:00:19 +0100346 if (!primary_if)
347 return;
348
Sven Eckelmann807736f2012-07-15 22:26:51 +0200349 memcpy(&local_claim_dest, &bat_priv->bla.claim_dest,
Simon Wunderlich38ef3d12012-01-22 20:00:26 +0100350 sizeof(local_claim_dest));
Simon Wunderlich23721382012-01-22 20:00:19 +0100351 local_claim_dest.type = claimtype;
352
353 soft_iface = primary_if->soft_iface;
354
355 skb = arp_create(ARPOP_REPLY, ETH_P_ARP,
356 /* IP DST: 0.0.0.0 */
357 zeroip,
358 primary_if->soft_iface,
359 /* IP SRC: 0.0.0.0 */
360 zeroip,
361 /* Ethernet DST: Broadcast */
362 NULL,
363 /* Ethernet SRC/HW SRC: originator mac */
364 primary_if->net_dev->dev_addr,
Simon Wunderlich99e966f2012-06-23 12:34:17 +0200365 /* HW DST: FF:43:05:XX:YY:YY
Simon Wunderlich23721382012-01-22 20:00:19 +0100366 * with XX = claim type
Simon Wunderlich38ef3d12012-01-22 20:00:26 +0100367 * and YY:YY = group id
Simon Wunderlich23721382012-01-22 20:00:19 +0100368 */
Sven Eckelmann6b5e9712015-05-26 18:34:26 +0200369 (u8 *)&local_claim_dest);
Simon Wunderlich23721382012-01-22 20:00:19 +0100370
371 if (!skb)
372 goto out;
373
374 ethhdr = (struct ethhdr *)skb->data;
Sven Eckelmann6b5e9712015-05-26 18:34:26 +0200375 hw_src = (u8 *)ethhdr + ETH_HLEN + sizeof(struct arphdr);
Simon Wunderlich23721382012-01-22 20:00:19 +0100376
377 /* now we pretend that the client would have sent this ... */
378 switch (claimtype) {
Simon Wunderlich3eb87732012-06-23 12:34:18 +0200379 case BATADV_CLAIM_TYPE_CLAIM:
Simon Wunderlich23721382012-01-22 20:00:19 +0100380 /* normal claim frame
381 * set Ethernet SRC to the clients mac
382 */
Antonio Quartulli8fdd0152014-01-22 00:42:11 +0100383 ether_addr_copy(ethhdr->h_source, mac);
Sven Eckelmann39c75a52012-06-03 22:19:22 +0200384 batadv_dbg(BATADV_DBG_BLA, bat_priv,
Sven Eckelmann22f05022017-05-19 13:02:00 +0200385 "%s(): CLAIM %pM on vid %d\n", __func__, mac,
Sven Eckelmannf7a2bd62017-02-22 17:16:42 +0100386 batadv_print_vid(vid));
Simon Wunderlich23721382012-01-22 20:00:19 +0100387 break;
Simon Wunderlich3eb87732012-06-23 12:34:18 +0200388 case BATADV_CLAIM_TYPE_UNCLAIM:
Simon Wunderlich23721382012-01-22 20:00:19 +0100389 /* unclaim frame
390 * set HW SRC to the clients mac
391 */
Antonio Quartulli8fdd0152014-01-22 00:42:11 +0100392 ether_addr_copy(hw_src, mac);
Sven Eckelmann39c75a52012-06-03 22:19:22 +0200393 batadv_dbg(BATADV_DBG_BLA, bat_priv,
Sven Eckelmann22f05022017-05-19 13:02:00 +0200394 "%s(): UNCLAIM %pM on vid %d\n", __func__, mac,
Sven Eckelmannf7a2bd62017-02-22 17:16:42 +0100395 batadv_print_vid(vid));
Simon Wunderlich23721382012-01-22 20:00:19 +0100396 break;
Sven Eckelmannacd34af2012-06-03 22:19:21 +0200397 case BATADV_CLAIM_TYPE_ANNOUNCE:
Simon Wunderlich23721382012-01-22 20:00:19 +0100398 /* announcement frame
399 * set HW SRC to the special mac containg the crc
400 */
Antonio Quartulli8fdd0152014-01-22 00:42:11 +0100401 ether_addr_copy(hw_src, mac);
Sven Eckelmann39c75a52012-06-03 22:19:22 +0200402 batadv_dbg(BATADV_DBG_BLA, bat_priv,
Sven Eckelmann22f05022017-05-19 13:02:00 +0200403 "%s(): ANNOUNCE of %pM on vid %d\n", __func__,
Sven Eckelmannf7a2bd62017-02-22 17:16:42 +0100404 ethhdr->h_source, batadv_print_vid(vid));
Simon Wunderlich23721382012-01-22 20:00:19 +0100405 break;
Sven Eckelmannacd34af2012-06-03 22:19:21 +0200406 case BATADV_CLAIM_TYPE_REQUEST:
Simon Wunderlich23721382012-01-22 20:00:19 +0100407 /* request frame
Simon Wunderlich99e966f2012-06-23 12:34:17 +0200408 * set HW SRC and header destination to the receiving backbone
409 * gws mac
Simon Wunderlich23721382012-01-22 20:00:19 +0100410 */
Antonio Quartulli8fdd0152014-01-22 00:42:11 +0100411 ether_addr_copy(hw_src, mac);
412 ether_addr_copy(ethhdr->h_dest, mac);
Sven Eckelmann39c75a52012-06-03 22:19:22 +0200413 batadv_dbg(BATADV_DBG_BLA, bat_priv,
Sven Eckelmann22f05022017-05-19 13:02:00 +0200414 "%s(): REQUEST of %pM to %pM on vid %d\n", __func__,
Antonio Quartulli5f80df62013-04-19 18:07:01 +0200415 ethhdr->h_source, ethhdr->h_dest,
Sven Eckelmannf7a2bd62017-02-22 17:16:42 +0100416 batadv_print_vid(vid));
Simon Wunderlich23721382012-01-22 20:00:19 +0100417 break;
Simon Wunderlichcd9c7bf2016-03-12 10:49:33 +0100418 case BATADV_CLAIM_TYPE_LOOPDETECT:
419 ether_addr_copy(ethhdr->h_source, mac);
420 batadv_dbg(BATADV_DBG_BLA, bat_priv,
Sven Eckelmann22f05022017-05-19 13:02:00 +0200421 "%s(): LOOPDETECT of %pM to %pM on vid %d\n",
422 __func__, ethhdr->h_source, ethhdr->h_dest,
Sven Eckelmannf7a2bd62017-02-22 17:16:42 +0100423 batadv_print_vid(vid));
Simon Wunderlichcd9c7bf2016-03-12 10:49:33 +0100424
425 break;
Simon Wunderlich23721382012-01-22 20:00:19 +0100426 }
427
Sven Eckelmann10c78f52016-07-02 09:52:13 +0200428 if (vid & BATADV_VLAN_HAS_TAG) {
Antonio Quartullieb2deb62013-04-19 18:07:00 +0200429 skb = vlan_insert_tag(skb, htons(ETH_P_8021Q),
430 vid & VLAN_VID_MASK);
Sven Eckelmann10c78f52016-07-02 09:52:13 +0200431 if (!skb)
432 goto out;
433 }
Simon Wunderlich23721382012-01-22 20:00:19 +0100434
435 skb_reset_mac_header(skb);
436 skb->protocol = eth_type_trans(skb, soft_iface);
Marek Lindner1c9b0552012-06-23 11:47:53 +0200437 batadv_inc_counter(bat_priv, BATADV_CNT_RX);
438 batadv_add_counter(bat_priv, BATADV_CNT_RX_BYTES,
439 skb->len + ETH_HLEN);
Simon Wunderlich23721382012-01-22 20:00:19 +0100440
Jussi Kivilinna279e89b2020-08-18 17:46:10 +0300441 if (in_interrupt())
442 netif_rx(skb);
443 else
444 netif_rx_ni(skb);
Simon Wunderlich23721382012-01-22 20:00:19 +0100445out:
446 if (primary_if)
Sven Eckelmann82047ad2016-01-17 11:01:10 +0100447 batadv_hardif_put(primary_if);
Simon Wunderlich23721382012-01-22 20:00:19 +0100448}
449
Ben Hutchings2c530402012-07-10 10:55:09 +0000450/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100451 * batadv_bla_loopdetect_report() - worker for reporting the loop
Simon Wunderlichcd9c7bf2016-03-12 10:49:33 +0100452 * @work: work queue item
453 *
454 * Throws an uevent, as the loopdetect check function can't do that itself
455 * since the kernel may sleep while throwing uevents.
456 */
457static void batadv_bla_loopdetect_report(struct work_struct *work)
458{
459 struct batadv_bla_backbone_gw *backbone_gw;
460 struct batadv_priv *bat_priv;
461 char vid_str[6] = { '\0' };
462
463 backbone_gw = container_of(work, struct batadv_bla_backbone_gw,
464 report_work);
465 bat_priv = backbone_gw->bat_priv;
466
467 batadv_info(bat_priv->soft_iface,
468 "Possible loop on VLAN %d detected which can't be handled by BLA - please check your network setup!\n",
Sven Eckelmannf7a2bd62017-02-22 17:16:42 +0100469 batadv_print_vid(backbone_gw->vid));
Simon Wunderlichcd9c7bf2016-03-12 10:49:33 +0100470 snprintf(vid_str, sizeof(vid_str), "%d",
Sven Eckelmannf7a2bd62017-02-22 17:16:42 +0100471 batadv_print_vid(backbone_gw->vid));
Simon Wunderlichcd9c7bf2016-03-12 10:49:33 +0100472 vid_str[sizeof(vid_str) - 1] = 0;
473
474 batadv_throw_uevent(bat_priv, BATADV_UEV_BLA, BATADV_UEV_LOOPDETECT,
475 vid_str);
476
477 batadv_backbone_gw_put(backbone_gw);
478}
479
480/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100481 * batadv_bla_get_backbone_gw() - finds or creates a backbone gateway
Ben Hutchings2c530402012-07-10 10:55:09 +0000482 * @bat_priv: the bat priv with all the soft interface information
Simon Wunderlich23721382012-01-22 20:00:19 +0100483 * @orig: the mac address of the originator
484 * @vid: the VLAN ID
Martin Hundebølle3357182014-07-15 09:41:06 +0200485 * @own_backbone: set if the requested backbone is local
Simon Wunderlich23721382012-01-22 20:00:19 +0100486 *
Simon Wunderlich04e14be2015-11-06 10:45:19 +0100487 * Return: the (possibly created) backbone gateway or NULL on error
Simon Wunderlich23721382012-01-22 20:00:19 +0100488 */
Marek Lindnerbae98772012-12-25 17:03:24 +0800489static struct batadv_bla_backbone_gw *
Sven Eckelmann6b5e9712015-05-26 18:34:26 +0200490batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, u8 *orig,
Antonio Quartullieb2deb62013-04-19 18:07:00 +0200491 unsigned short vid, bool own_backbone)
Simon Wunderlich23721382012-01-22 20:00:19 +0100492{
Marek Lindnerbae98772012-12-25 17:03:24 +0800493 struct batadv_bla_backbone_gw *entry;
Sven Eckelmann56303d32012-06-05 22:31:31 +0200494 struct batadv_orig_node *orig_node;
Simon Wunderlich23721382012-01-22 20:00:19 +0100495 int hash_added;
496
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200497 entry = batadv_backbone_hash_find(bat_priv, orig, vid);
Simon Wunderlich23721382012-01-22 20:00:19 +0100498
499 if (entry)
500 return entry;
501
Sven Eckelmann39c75a52012-06-03 22:19:22 +0200502 batadv_dbg(BATADV_DBG_BLA, bat_priv,
Sven Eckelmann22f05022017-05-19 13:02:00 +0200503 "%s(): not found (%pM, %d), creating new entry\n", __func__,
Sven Eckelmannf7a2bd62017-02-22 17:16:42 +0100504 orig, batadv_print_vid(vid));
Simon Wunderlich23721382012-01-22 20:00:19 +0100505
506 entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
507 if (!entry)
508 return NULL;
509
510 entry->vid = vid;
511 entry->lasttime = jiffies;
Sven Eckelmann3964f722012-06-03 22:19:10 +0200512 entry->crc = BATADV_BLA_CRC_INIT;
Simon Wunderlich23721382012-01-22 20:00:19 +0100513 entry->bat_priv = bat_priv;
Simon Wunderlich5a1dd8a2015-09-11 18:04:13 +0200514 spin_lock_init(&entry->crc_lock);
Simon Wunderlich23721382012-01-22 20:00:19 +0100515 atomic_set(&entry->request_sent, 0);
Simon Wunderlich28709872012-09-13 18:18:46 +0200516 atomic_set(&entry->wait_periods, 0);
Antonio Quartulli8fdd0152014-01-22 00:42:11 +0100517 ether_addr_copy(entry->orig, orig);
Simon Wunderlichcd9c7bf2016-03-12 10:49:33 +0100518 INIT_WORK(&entry->report_work, batadv_bla_loopdetect_report);
Sven Eckelmann06e56de2016-01-16 10:29:43 +0100519 kref_init(&entry->refcount);
Simon Wunderlich23721382012-01-22 20:00:19 +0100520
Sven Eckelmann4e8389e2016-07-15 17:39:25 +0200521 kref_get(&entry->refcount);
Sven Eckelmann807736f2012-07-15 22:26:51 +0200522 hash_added = batadv_hash_add(bat_priv->bla.backbone_hash,
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200523 batadv_compare_backbone_gw,
524 batadv_choose_backbone_gw, entry,
525 &entry->hash_entry);
Simon Wunderlich23721382012-01-22 20:00:19 +0100526
527 if (unlikely(hash_added != 0)) {
528 /* hash failed, free the structure */
529 kfree(entry);
530 return NULL;
531 }
532
Antonio Quartulli95fb1302013-08-07 18:28:55 +0200533 /* this is a gateway now, remove any TT entry on this VLAN */
Sven Eckelmannda641192012-05-12 13:48:56 +0200534 orig_node = batadv_orig_hash_find(bat_priv, orig);
Simon Wunderlich20ff9d52012-01-22 20:00:23 +0100535 if (orig_node) {
Antonio Quartulli95fb1302013-08-07 18:28:55 +0200536 batadv_tt_global_del_orig(bat_priv, orig_node, vid,
Sven Eckelmann08c36d32012-05-12 02:09:39 +0200537 "became a backbone gateway");
Sven Eckelmann5d967312016-01-17 11:01:09 +0100538 batadv_orig_node_put(orig_node);
Simon Wunderlich20ff9d52012-01-22 20:00:23 +0100539 }
Simon Wunderlich52aebd62012-09-08 18:02:53 +0200540
Simon Wunderlichd807f272012-09-09 22:27:57 +0200541 if (own_backbone) {
Simon Wunderlich52aebd62012-09-08 18:02:53 +0200542 batadv_bla_send_announce(bat_priv, entry);
543
Simon Wunderlichd807f272012-09-09 22:27:57 +0200544 /* this will be decreased in the worker thread */
545 atomic_inc(&entry->request_sent);
Simon Wunderlich28709872012-09-13 18:18:46 +0200546 atomic_set(&entry->wait_periods, BATADV_BLA_WAIT_PERIODS);
Simon Wunderlichd807f272012-09-09 22:27:57 +0200547 atomic_inc(&bat_priv->bla.num_requests);
548 }
549
Simon Wunderlich23721382012-01-22 20:00:19 +0100550 return entry;
551}
552
Simon Wunderlich04e14be2015-11-06 10:45:19 +0100553/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100554 * batadv_bla_update_own_backbone_gw() - updates the own backbone gw for a VLAN
Simon Wunderlich04e14be2015-11-06 10:45:19 +0100555 * @bat_priv: the bat priv with all the soft interface information
556 * @primary_if: the selected primary interface
557 * @vid: VLAN identifier
558 *
559 * update or add the own backbone gw to make sure we announce
Simon Wunderlich23721382012-01-22 20:00:19 +0100560 * where we receive other backbone gws
561 */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200562static void
563batadv_bla_update_own_backbone_gw(struct batadv_priv *bat_priv,
564 struct batadv_hard_iface *primary_if,
Antonio Quartullieb2deb62013-04-19 18:07:00 +0200565 unsigned short vid)
Simon Wunderlich23721382012-01-22 20:00:19 +0100566{
Marek Lindnerbae98772012-12-25 17:03:24 +0800567 struct batadv_bla_backbone_gw *backbone_gw;
Simon Wunderlich23721382012-01-22 20:00:19 +0100568
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200569 backbone_gw = batadv_bla_get_backbone_gw(bat_priv,
570 primary_if->net_dev->dev_addr,
Simon Wunderlich52aebd62012-09-08 18:02:53 +0200571 vid, true);
Simon Wunderlich23721382012-01-22 20:00:19 +0100572 if (unlikely(!backbone_gw))
573 return;
574
575 backbone_gw->lasttime = jiffies;
Sven Eckelmannc8b86c12016-01-17 11:01:15 +0100576 batadv_backbone_gw_put(backbone_gw);
Simon Wunderlich23721382012-01-22 20:00:19 +0100577}
578
Simon Wunderlich1b371d12014-01-15 21:17:54 +0100579/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100580 * batadv_bla_answer_request() - answer a bla request by sending own claims
Simon Wunderlich1b371d12014-01-15 21:17:54 +0100581 * @bat_priv: the bat priv with all the soft interface information
Martin Hundebølle3357182014-07-15 09:41:06 +0200582 * @primary_if: interface where the request came on
Simon Wunderlich23721382012-01-22 20:00:19 +0100583 * @vid: the vid where the request came on
584 *
585 * Repeat all of our own claims, and finally send an ANNOUNCE frame
586 * to allow the requester another check if the CRC is correct now.
587 */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200588static void batadv_bla_answer_request(struct batadv_priv *bat_priv,
589 struct batadv_hard_iface *primary_if,
Antonio Quartullieb2deb62013-04-19 18:07:00 +0200590 unsigned short vid)
Simon Wunderlich23721382012-01-22 20:00:19 +0100591{
Simon Wunderlich23721382012-01-22 20:00:19 +0100592 struct hlist_head *head;
Sven Eckelmann5bf74e92012-06-05 22:31:28 +0200593 struct batadv_hashtable *hash;
Marek Lindner712bbfe42012-12-25 17:03:25 +0800594 struct batadv_bla_claim *claim;
Marek Lindnerbae98772012-12-25 17:03:24 +0800595 struct batadv_bla_backbone_gw *backbone_gw;
Simon Wunderlich23721382012-01-22 20:00:19 +0100596 int i;
597
Sven Eckelmann39c75a52012-06-03 22:19:22 +0200598 batadv_dbg(BATADV_DBG_BLA, bat_priv,
Sven Eckelmann22f05022017-05-19 13:02:00 +0200599 "%s(): received a claim request, send all of our own claims again\n",
600 __func__);
Simon Wunderlich23721382012-01-22 20:00:19 +0100601
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200602 backbone_gw = batadv_backbone_hash_find(bat_priv,
603 primary_if->net_dev->dev_addr,
604 vid);
Simon Wunderlich23721382012-01-22 20:00:19 +0100605 if (!backbone_gw)
606 return;
607
Sven Eckelmann807736f2012-07-15 22:26:51 +0200608 hash = bat_priv->bla.claim_hash;
Simon Wunderlich23721382012-01-22 20:00:19 +0100609 for (i = 0; i < hash->size; i++) {
610 head = &hash->table[i];
611
612 rcu_read_lock();
Sasha Levinb67bfe02013-02-27 17:06:00 -0800613 hlist_for_each_entry_rcu(claim, head, hash_entry) {
Simon Wunderlich23721382012-01-22 20:00:19 +0100614 /* only own claims are interesting */
615 if (claim->backbone_gw != backbone_gw)
616 continue;
617
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200618 batadv_bla_send_claim(bat_priv, claim->addr, claim->vid,
Simon Wunderlich3eb87732012-06-23 12:34:18 +0200619 BATADV_CLAIM_TYPE_CLAIM);
Simon Wunderlich23721382012-01-22 20:00:19 +0100620 }
621 rcu_read_unlock();
622 }
623
624 /* finally, send an announcement frame */
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200625 batadv_bla_send_announce(bat_priv, backbone_gw);
Sven Eckelmannc8b86c12016-01-17 11:01:15 +0100626 batadv_backbone_gw_put(backbone_gw);
Simon Wunderlich23721382012-01-22 20:00:19 +0100627}
628
Simon Wunderlich1b371d12014-01-15 21:17:54 +0100629/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100630 * batadv_bla_send_request() - send a request to repeat claims
Simon Wunderlich1b371d12014-01-15 21:17:54 +0100631 * @backbone_gw: the backbone gateway from whom we are out of sync
Simon Wunderlich23721382012-01-22 20:00:19 +0100632 *
633 * When the crc is wrong, ask the backbone gateway for a full table update.
634 * After the request, it will repeat all of his own claims and finally
635 * send an announcement claim with which we can check again.
636 */
Marek Lindnerbae98772012-12-25 17:03:24 +0800637static void batadv_bla_send_request(struct batadv_bla_backbone_gw *backbone_gw)
Simon Wunderlich23721382012-01-22 20:00:19 +0100638{
639 /* first, remove all old entries */
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200640 batadv_bla_del_backbone_claims(backbone_gw);
Simon Wunderlich23721382012-01-22 20:00:19 +0100641
Sven Eckelmann39c75a52012-06-03 22:19:22 +0200642 batadv_dbg(BATADV_DBG_BLA, backbone_gw->bat_priv,
643 "Sending REQUEST to %pM\n", backbone_gw->orig);
Simon Wunderlich23721382012-01-22 20:00:19 +0100644
645 /* send request */
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200646 batadv_bla_send_claim(backbone_gw->bat_priv, backbone_gw->orig,
Sven Eckelmannacd34af2012-06-03 22:19:21 +0200647 backbone_gw->vid, BATADV_CLAIM_TYPE_REQUEST);
Simon Wunderlich23721382012-01-22 20:00:19 +0100648
649 /* no local broadcasts should be sent or received, for now. */
650 if (!atomic_read(&backbone_gw->request_sent)) {
Sven Eckelmann807736f2012-07-15 22:26:51 +0200651 atomic_inc(&backbone_gw->bat_priv->bla.num_requests);
Simon Wunderlich23721382012-01-22 20:00:19 +0100652 atomic_set(&backbone_gw->request_sent, 1);
653 }
654}
655
Simon Wunderlich1b371d12014-01-15 21:17:54 +0100656/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100657 * batadv_bla_send_announce() - Send an announcement frame
Simon Wunderlich1b371d12014-01-15 21:17:54 +0100658 * @bat_priv: the bat priv with all the soft interface information
Simon Wunderlich23721382012-01-22 20:00:19 +0100659 * @backbone_gw: our backbone gateway which should be announced
Simon Wunderlich23721382012-01-22 20:00:19 +0100660 */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200661static void batadv_bla_send_announce(struct batadv_priv *bat_priv,
Marek Lindnerbae98772012-12-25 17:03:24 +0800662 struct batadv_bla_backbone_gw *backbone_gw)
Simon Wunderlich23721382012-01-22 20:00:19 +0100663{
Sven Eckelmann6b5e9712015-05-26 18:34:26 +0200664 u8 mac[ETH_ALEN];
Al Viro3e2f1a12012-04-22 07:47:50 +0100665 __be16 crc;
Simon Wunderlich23721382012-01-22 20:00:19 +0100666
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200667 memcpy(mac, batadv_announce_mac, 4);
Simon Wunderlich5a1dd8a2015-09-11 18:04:13 +0200668 spin_lock_bh(&backbone_gw->crc_lock);
Simon Wunderlich23721382012-01-22 20:00:19 +0100669 crc = htons(backbone_gw->crc);
Simon Wunderlich5a1dd8a2015-09-11 18:04:13 +0200670 spin_unlock_bh(&backbone_gw->crc_lock);
Al Viro1a5852d2012-04-22 07:50:29 +0100671 memcpy(&mac[4], &crc, 2);
Simon Wunderlich23721382012-01-22 20:00:19 +0100672
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200673 batadv_bla_send_claim(bat_priv, mac, backbone_gw->vid,
Sven Eckelmannacd34af2012-06-03 22:19:21 +0200674 BATADV_CLAIM_TYPE_ANNOUNCE);
Simon Wunderlich23721382012-01-22 20:00:19 +0100675}
676
Ben Hutchings2c530402012-07-10 10:55:09 +0000677/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100678 * batadv_bla_add_claim() - Adds a claim in the claim hash
Ben Hutchings2c530402012-07-10 10:55:09 +0000679 * @bat_priv: the bat priv with all the soft interface information
Simon Wunderlich23721382012-01-22 20:00:19 +0100680 * @mac: the mac address of the claim
681 * @vid: the VLAN ID of the frame
682 * @backbone_gw: the backbone gateway which claims it
Simon Wunderlich23721382012-01-22 20:00:19 +0100683 */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200684static void batadv_bla_add_claim(struct batadv_priv *bat_priv,
Sven Eckelmann6b5e9712015-05-26 18:34:26 +0200685 const u8 *mac, const unsigned short vid,
Marek Lindnerbae98772012-12-25 17:03:24 +0800686 struct batadv_bla_backbone_gw *backbone_gw)
Simon Wunderlich23721382012-01-22 20:00:19 +0100687{
Sven Eckelmann3db0dec2016-07-01 15:49:43 +0200688 struct batadv_bla_backbone_gw *old_backbone_gw;
Marek Lindner712bbfe42012-12-25 17:03:25 +0800689 struct batadv_bla_claim *claim;
690 struct batadv_bla_claim search_claim;
Sven Eckelmann3db0dec2016-07-01 15:49:43 +0200691 bool remove_crc = false;
Simon Wunderlich23721382012-01-22 20:00:19 +0100692 int hash_added;
693
Antonio Quartulli8fdd0152014-01-22 00:42:11 +0100694 ether_addr_copy(search_claim.addr, mac);
Simon Wunderlich23721382012-01-22 20:00:19 +0100695 search_claim.vid = vid;
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200696 claim = batadv_claim_hash_find(bat_priv, &search_claim);
Simon Wunderlich23721382012-01-22 20:00:19 +0100697
698 /* create a new claim entry if it does not exist yet. */
699 if (!claim) {
700 claim = kzalloc(sizeof(*claim), GFP_ATOMIC);
701 if (!claim)
702 return;
703
Antonio Quartulli8fdd0152014-01-22 00:42:11 +0100704 ether_addr_copy(claim->addr, mac);
Sven Eckelmann3db0dec2016-07-01 15:49:43 +0200705 spin_lock_init(&claim->backbone_lock);
Simon Wunderlich23721382012-01-22 20:00:19 +0100706 claim->vid = vid;
707 claim->lasttime = jiffies;
Sven Eckelmann3db0dec2016-07-01 15:49:43 +0200708 kref_get(&backbone_gw->refcount);
Simon Wunderlich23721382012-01-22 20:00:19 +0100709 claim->backbone_gw = backbone_gw;
Sven Eckelmann71b7e3d2016-01-16 10:29:44 +0100710 kref_init(&claim->refcount);
Sven Eckelmann7282ac32016-07-15 17:39:24 +0200711
Sven Eckelmann39c75a52012-06-03 22:19:22 +0200712 batadv_dbg(BATADV_DBG_BLA, bat_priv,
Sven Eckelmann22f05022017-05-19 13:02:00 +0200713 "%s(): adding new entry %pM, vid %d to hash ...\n",
714 __func__, mac, batadv_print_vid(vid));
Sven Eckelmann7282ac32016-07-15 17:39:24 +0200715
716 kref_get(&claim->refcount);
Sven Eckelmann807736f2012-07-15 22:26:51 +0200717 hash_added = batadv_hash_add(bat_priv->bla.claim_hash,
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200718 batadv_compare_claim,
719 batadv_choose_claim, claim,
720 &claim->hash_entry);
Simon Wunderlich23721382012-01-22 20:00:19 +0100721
722 if (unlikely(hash_added != 0)) {
723 /* only local changes happened. */
724 kfree(claim);
725 return;
726 }
727 } else {
728 claim->lasttime = jiffies;
729 if (claim->backbone_gw == backbone_gw)
730 /* no need to register a new backbone */
731 goto claim_free_ref;
732
Sven Eckelmann39c75a52012-06-03 22:19:22 +0200733 batadv_dbg(BATADV_DBG_BLA, bat_priv,
Sven Eckelmann22f05022017-05-19 13:02:00 +0200734 "%s(): changing ownership for %pM, vid %d to gw %pM\n",
735 __func__, mac, batadv_print_vid(vid),
736 backbone_gw->orig);
Simon Wunderlich23721382012-01-22 20:00:19 +0100737
Sven Eckelmann3db0dec2016-07-01 15:49:43 +0200738 remove_crc = true;
Simon Wunderlich23721382012-01-22 20:00:19 +0100739 }
Sven Eckelmann3db0dec2016-07-01 15:49:43 +0200740
741 /* replace backbone_gw atomically and adjust reference counters */
742 spin_lock_bh(&claim->backbone_lock);
743 old_backbone_gw = claim->backbone_gw;
Sven Eckelmann06e56de2016-01-16 10:29:43 +0100744 kref_get(&backbone_gw->refcount);
Simon Wunderlich23721382012-01-22 20:00:19 +0100745 claim->backbone_gw = backbone_gw;
Sven Eckelmann3db0dec2016-07-01 15:49:43 +0200746 spin_unlock_bh(&claim->backbone_lock);
Simon Wunderlich23721382012-01-22 20:00:19 +0100747
Sven Eckelmann3db0dec2016-07-01 15:49:43 +0200748 if (remove_crc) {
749 /* remove claim address from old backbone_gw */
750 spin_lock_bh(&old_backbone_gw->crc_lock);
751 old_backbone_gw->crc ^= crc16(0, claim->addr, ETH_ALEN);
752 spin_unlock_bh(&old_backbone_gw->crc_lock);
753 }
754
755 batadv_backbone_gw_put(old_backbone_gw);
756
757 /* add claim address to new backbone_gw */
Simon Wunderlich5a1dd8a2015-09-11 18:04:13 +0200758 spin_lock_bh(&backbone_gw->crc_lock);
Simon Wunderlich23721382012-01-22 20:00:19 +0100759 backbone_gw->crc ^= crc16(0, claim->addr, ETH_ALEN);
Simon Wunderlich5a1dd8a2015-09-11 18:04:13 +0200760 spin_unlock_bh(&backbone_gw->crc_lock);
Simon Wunderlich23721382012-01-22 20:00:19 +0100761 backbone_gw->lasttime = jiffies;
762
763claim_free_ref:
Sven Eckelmann321e3e02016-01-17 11:01:16 +0100764 batadv_claim_put(claim);
Simon Wunderlich23721382012-01-22 20:00:19 +0100765}
766
Simon Wunderlich04e14be2015-11-06 10:45:19 +0100767/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100768 * batadv_bla_claim_get_backbone_gw() - Get valid reference for backbone_gw of
Sven Eckelmann3db0dec2016-07-01 15:49:43 +0200769 * claim
770 * @claim: claim whose backbone_gw should be returned
771 *
772 * Return: valid reference to claim::backbone_gw
773 */
774static struct batadv_bla_backbone_gw *
775batadv_bla_claim_get_backbone_gw(struct batadv_bla_claim *claim)
776{
777 struct batadv_bla_backbone_gw *backbone_gw;
778
779 spin_lock_bh(&claim->backbone_lock);
780 backbone_gw = claim->backbone_gw;
781 kref_get(&backbone_gw->refcount);
782 spin_unlock_bh(&claim->backbone_lock);
783
784 return backbone_gw;
785}
786
787/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100788 * batadv_bla_del_claim() - delete a claim from the claim hash
Simon Wunderlich04e14be2015-11-06 10:45:19 +0100789 * @bat_priv: the bat priv with all the soft interface information
790 * @mac: mac address of the claim to be removed
791 * @vid: VLAN id for the claim to be removed
Simon Wunderlich23721382012-01-22 20:00:19 +0100792 */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200793static void batadv_bla_del_claim(struct batadv_priv *bat_priv,
Sven Eckelmann6b5e9712015-05-26 18:34:26 +0200794 const u8 *mac, const unsigned short vid)
Simon Wunderlich23721382012-01-22 20:00:19 +0100795{
Marek Lindner712bbfe42012-12-25 17:03:25 +0800796 struct batadv_bla_claim search_claim, *claim;
Sven Eckelmann4ba104f2019-02-23 14:27:10 +0100797 struct batadv_bla_claim *claim_removed_entry;
798 struct hlist_node *claim_removed_node;
Simon Wunderlich23721382012-01-22 20:00:19 +0100799
Antonio Quartulli8fdd0152014-01-22 00:42:11 +0100800 ether_addr_copy(search_claim.addr, mac);
Simon Wunderlich23721382012-01-22 20:00:19 +0100801 search_claim.vid = vid;
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200802 claim = batadv_claim_hash_find(bat_priv, &search_claim);
Simon Wunderlich23721382012-01-22 20:00:19 +0100803 if (!claim)
804 return;
805
Sven Eckelmann22f05022017-05-19 13:02:00 +0200806 batadv_dbg(BATADV_DBG_BLA, bat_priv, "%s(): %pM, vid %d\n", __func__,
Sven Eckelmannf7a2bd62017-02-22 17:16:42 +0100807 mac, batadv_print_vid(vid));
Simon Wunderlich23721382012-01-22 20:00:19 +0100808
Sven Eckelmann4ba104f2019-02-23 14:27:10 +0100809 claim_removed_node = batadv_hash_remove(bat_priv->bla.claim_hash,
810 batadv_compare_claim,
811 batadv_choose_claim, claim);
812 if (!claim_removed_node)
813 goto free_claim;
Simon Wunderlich23721382012-01-22 20:00:19 +0100814
Sven Eckelmann4ba104f2019-02-23 14:27:10 +0100815 /* reference from the hash is gone */
816 claim_removed_entry = hlist_entry(claim_removed_node,
817 struct batadv_bla_claim, hash_entry);
818 batadv_claim_put(claim_removed_entry);
819
820free_claim:
Simon Wunderlich23721382012-01-22 20:00:19 +0100821 /* don't need the reference from hash_find() anymore */
Sven Eckelmann321e3e02016-01-17 11:01:16 +0100822 batadv_claim_put(claim);
Simon Wunderlich23721382012-01-22 20:00:19 +0100823}
824
Sven Eckelmann62fe7102015-09-15 19:00:48 +0200825/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100826 * batadv_handle_announce() - check for ANNOUNCE frame
Simon Wunderlich04e14be2015-11-06 10:45:19 +0100827 * @bat_priv: the bat priv with all the soft interface information
828 * @an_addr: announcement mac address (ARP Sender HW address)
829 * @backbone_addr: originator address of the sender (Ethernet source MAC)
830 * @vid: the VLAN ID of the frame
Sven Eckelmann62fe7102015-09-15 19:00:48 +0200831 *
Sven Eckelmann4b426b12016-02-22 21:02:39 +0100832 * Return: true if handled
Sven Eckelmann62fe7102015-09-15 19:00:48 +0200833 */
Sven Eckelmann4b426b12016-02-22 21:02:39 +0100834static bool batadv_handle_announce(struct batadv_priv *bat_priv, u8 *an_addr,
835 u8 *backbone_addr, unsigned short vid)
Simon Wunderlich23721382012-01-22 20:00:19 +0100836{
Marek Lindnerbae98772012-12-25 17:03:24 +0800837 struct batadv_bla_backbone_gw *backbone_gw;
Simon Wunderlich5a1dd8a2015-09-11 18:04:13 +0200838 u16 backbone_crc, crc;
Simon Wunderlich23721382012-01-22 20:00:19 +0100839
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200840 if (memcmp(an_addr, batadv_announce_mac, 4) != 0)
Sven Eckelmann4b426b12016-02-22 21:02:39 +0100841 return false;
Simon Wunderlich23721382012-01-22 20:00:19 +0100842
Simon Wunderlich52aebd62012-09-08 18:02:53 +0200843 backbone_gw = batadv_bla_get_backbone_gw(bat_priv, backbone_addr, vid,
844 false);
Simon Wunderlich23721382012-01-22 20:00:19 +0100845
846 if (unlikely(!backbone_gw))
Sven Eckelmann4b426b12016-02-22 21:02:39 +0100847 return true;
Simon Wunderlich23721382012-01-22 20:00:19 +0100848
Simon Wunderlich23721382012-01-22 20:00:19 +0100849 /* handle as ANNOUNCE frame */
850 backbone_gw->lasttime = jiffies;
Sven Eckelmann61a29282019-11-28 11:26:06 +0100851 crc = ntohs(*((__force __be16 *)(&an_addr[4])));
Simon Wunderlich23721382012-01-22 20:00:19 +0100852
Sven Eckelmann39c75a52012-06-03 22:19:22 +0200853 batadv_dbg(BATADV_DBG_BLA, bat_priv,
Sven Eckelmann22f05022017-05-19 13:02:00 +0200854 "%s(): ANNOUNCE vid %d (sent by %pM)... CRC = %#.4x\n",
855 __func__, batadv_print_vid(vid), backbone_gw->orig, crc);
Simon Wunderlich23721382012-01-22 20:00:19 +0100856
Simon Wunderlich5a1dd8a2015-09-11 18:04:13 +0200857 spin_lock_bh(&backbone_gw->crc_lock);
858 backbone_crc = backbone_gw->crc;
859 spin_unlock_bh(&backbone_gw->crc_lock);
860
861 if (backbone_crc != crc) {
Sven Eckelmann39c75a52012-06-03 22:19:22 +0200862 batadv_dbg(BATADV_DBG_BLA, backbone_gw->bat_priv,
Sven Eckelmann22f05022017-05-19 13:02:00 +0200863 "%s(): CRC FAILED for %pM/%d (my = %#.4x, sent = %#.4x)\n",
864 __func__, backbone_gw->orig,
Sven Eckelmannf7a2bd62017-02-22 17:16:42 +0100865 batadv_print_vid(backbone_gw->vid),
Simon Wunderlich5a1dd8a2015-09-11 18:04:13 +0200866 backbone_crc, crc);
Simon Wunderlich23721382012-01-22 20:00:19 +0100867
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200868 batadv_bla_send_request(backbone_gw);
Simon Wunderlich23721382012-01-22 20:00:19 +0100869 } else {
870 /* if we have sent a request and the crc was OK,
871 * we can allow traffic again.
872 */
873 if (atomic_read(&backbone_gw->request_sent)) {
Sven Eckelmann807736f2012-07-15 22:26:51 +0200874 atomic_dec(&backbone_gw->bat_priv->bla.num_requests);
Simon Wunderlich23721382012-01-22 20:00:19 +0100875 atomic_set(&backbone_gw->request_sent, 0);
876 }
877 }
878
Sven Eckelmannc8b86c12016-01-17 11:01:15 +0100879 batadv_backbone_gw_put(backbone_gw);
Sven Eckelmann4b426b12016-02-22 21:02:39 +0100880 return true;
Simon Wunderlich23721382012-01-22 20:00:19 +0100881}
882
Sven Eckelmann62fe7102015-09-15 19:00:48 +0200883/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100884 * batadv_handle_request() - check for REQUEST frame
Simon Wunderlich04e14be2015-11-06 10:45:19 +0100885 * @bat_priv: the bat priv with all the soft interface information
886 * @primary_if: the primary hard interface of this batman soft interface
887 * @backbone_addr: backbone address to be requested (ARP sender HW MAC)
888 * @ethhdr: ethernet header of a packet
889 * @vid: the VLAN ID of the frame
Sven Eckelmann62fe7102015-09-15 19:00:48 +0200890 *
Sven Eckelmann4b426b12016-02-22 21:02:39 +0100891 * Return: true if handled
Sven Eckelmann62fe7102015-09-15 19:00:48 +0200892 */
Sven Eckelmann4b426b12016-02-22 21:02:39 +0100893static bool batadv_handle_request(struct batadv_priv *bat_priv,
894 struct batadv_hard_iface *primary_if,
895 u8 *backbone_addr, struct ethhdr *ethhdr,
896 unsigned short vid)
Simon Wunderlich23721382012-01-22 20:00:19 +0100897{
898 /* check for REQUEST frame */
Sven Eckelmann1eda58b2012-05-12 13:48:58 +0200899 if (!batadv_compare_eth(backbone_addr, ethhdr->h_dest))
Sven Eckelmann4b426b12016-02-22 21:02:39 +0100900 return false;
Simon Wunderlich23721382012-01-22 20:00:19 +0100901
902 /* sanity check, this should not happen on a normal switch,
903 * we ignore it in this case.
904 */
Sven Eckelmann1eda58b2012-05-12 13:48:58 +0200905 if (!batadv_compare_eth(ethhdr->h_dest, primary_if->net_dev->dev_addr))
Sven Eckelmann4b426b12016-02-22 21:02:39 +0100906 return true;
Simon Wunderlich23721382012-01-22 20:00:19 +0100907
Sven Eckelmann39c75a52012-06-03 22:19:22 +0200908 batadv_dbg(BATADV_DBG_BLA, bat_priv,
Sven Eckelmann22f05022017-05-19 13:02:00 +0200909 "%s(): REQUEST vid %d (sent by %pM)...\n",
910 __func__, batadv_print_vid(vid), ethhdr->h_source);
Simon Wunderlich23721382012-01-22 20:00:19 +0100911
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200912 batadv_bla_answer_request(bat_priv, primary_if, vid);
Sven Eckelmann4b426b12016-02-22 21:02:39 +0100913 return true;
Simon Wunderlich23721382012-01-22 20:00:19 +0100914}
915
Sven Eckelmann62fe7102015-09-15 19:00:48 +0200916/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100917 * batadv_handle_unclaim() - check for UNCLAIM frame
Simon Wunderlich04e14be2015-11-06 10:45:19 +0100918 * @bat_priv: the bat priv with all the soft interface information
919 * @primary_if: the primary hard interface of this batman soft interface
920 * @backbone_addr: originator address of the backbone (Ethernet source)
921 * @claim_addr: Client to be unclaimed (ARP sender HW MAC)
922 * @vid: the VLAN ID of the frame
Sven Eckelmann62fe7102015-09-15 19:00:48 +0200923 *
Sven Eckelmann4b426b12016-02-22 21:02:39 +0100924 * Return: true if handled
Sven Eckelmann62fe7102015-09-15 19:00:48 +0200925 */
Sven Eckelmann4b426b12016-02-22 21:02:39 +0100926static bool batadv_handle_unclaim(struct batadv_priv *bat_priv,
927 struct batadv_hard_iface *primary_if,
928 u8 *backbone_addr, u8 *claim_addr,
929 unsigned short vid)
Simon Wunderlich23721382012-01-22 20:00:19 +0100930{
Marek Lindnerbae98772012-12-25 17:03:24 +0800931 struct batadv_bla_backbone_gw *backbone_gw;
Simon Wunderlich23721382012-01-22 20:00:19 +0100932
933 /* unclaim in any case if it is our own */
Sven Eckelmann1eda58b2012-05-12 13:48:58 +0200934 if (primary_if && batadv_compare_eth(backbone_addr,
935 primary_if->net_dev->dev_addr))
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200936 batadv_bla_send_claim(bat_priv, claim_addr, vid,
Simon Wunderlich3eb87732012-06-23 12:34:18 +0200937 BATADV_CLAIM_TYPE_UNCLAIM);
Simon Wunderlich23721382012-01-22 20:00:19 +0100938
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200939 backbone_gw = batadv_backbone_hash_find(bat_priv, backbone_addr, vid);
Simon Wunderlich23721382012-01-22 20:00:19 +0100940
941 if (!backbone_gw)
Sven Eckelmann4b426b12016-02-22 21:02:39 +0100942 return true;
Simon Wunderlich23721382012-01-22 20:00:19 +0100943
944 /* this must be an UNCLAIM frame */
Sven Eckelmann39c75a52012-06-03 22:19:22 +0200945 batadv_dbg(BATADV_DBG_BLA, bat_priv,
Sven Eckelmann22f05022017-05-19 13:02:00 +0200946 "%s(): UNCLAIM %pM on vid %d (sent by %pM)...\n", __func__,
Sven Eckelmannf7a2bd62017-02-22 17:16:42 +0100947 claim_addr, batadv_print_vid(vid), backbone_gw->orig);
Simon Wunderlich23721382012-01-22 20:00:19 +0100948
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200949 batadv_bla_del_claim(bat_priv, claim_addr, vid);
Sven Eckelmannc8b86c12016-01-17 11:01:15 +0100950 batadv_backbone_gw_put(backbone_gw);
Sven Eckelmann4b426b12016-02-22 21:02:39 +0100951 return true;
Simon Wunderlich23721382012-01-22 20:00:19 +0100952}
953
Sven Eckelmann62fe7102015-09-15 19:00:48 +0200954/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100955 * batadv_handle_claim() - check for CLAIM frame
Simon Wunderlich04e14be2015-11-06 10:45:19 +0100956 * @bat_priv: the bat priv with all the soft interface information
957 * @primary_if: the primary hard interface of this batman soft interface
958 * @backbone_addr: originator address of the backbone (Ethernet Source)
959 * @claim_addr: client mac address to be claimed (ARP sender HW MAC)
960 * @vid: the VLAN ID of the frame
Sven Eckelmann62fe7102015-09-15 19:00:48 +0200961 *
Sven Eckelmann4b426b12016-02-22 21:02:39 +0100962 * Return: true if handled
Sven Eckelmann62fe7102015-09-15 19:00:48 +0200963 */
Sven Eckelmann4b426b12016-02-22 21:02:39 +0100964static bool batadv_handle_claim(struct batadv_priv *bat_priv,
965 struct batadv_hard_iface *primary_if,
966 u8 *backbone_addr, u8 *claim_addr,
967 unsigned short vid)
Simon Wunderlich23721382012-01-22 20:00:19 +0100968{
Marek Lindnerbae98772012-12-25 17:03:24 +0800969 struct batadv_bla_backbone_gw *backbone_gw;
Simon Wunderlich23721382012-01-22 20:00:19 +0100970
971 /* register the gateway if not yet available, and add the claim. */
972
Simon Wunderlich52aebd62012-09-08 18:02:53 +0200973 backbone_gw = batadv_bla_get_backbone_gw(bat_priv, backbone_addr, vid,
974 false);
Simon Wunderlich23721382012-01-22 20:00:19 +0100975
976 if (unlikely(!backbone_gw))
Sven Eckelmann4b426b12016-02-22 21:02:39 +0100977 return true;
Simon Wunderlich23721382012-01-22 20:00:19 +0100978
979 /* this must be a CLAIM frame */
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200980 batadv_bla_add_claim(bat_priv, claim_addr, vid, backbone_gw);
Sven Eckelmann1eda58b2012-05-12 13:48:58 +0200981 if (batadv_compare_eth(backbone_addr, primary_if->net_dev->dev_addr))
Sven Eckelmann3b300de2012-05-12 18:33:53 +0200982 batadv_bla_send_claim(bat_priv, claim_addr, vid,
Simon Wunderlich3eb87732012-06-23 12:34:18 +0200983 BATADV_CLAIM_TYPE_CLAIM);
Simon Wunderlich23721382012-01-22 20:00:19 +0100984
985 /* TODO: we could call something like tt_local_del() here. */
986
Sven Eckelmannc8b86c12016-01-17 11:01:15 +0100987 batadv_backbone_gw_put(backbone_gw);
Sven Eckelmann4b426b12016-02-22 21:02:39 +0100988 return true;
Simon Wunderlich23721382012-01-22 20:00:19 +0100989}
990
Ben Hutchings2c530402012-07-10 10:55:09 +0000991/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +0100992 * batadv_check_claim_group() - check for claim group membership
Ben Hutchings2c530402012-07-10 10:55:09 +0000993 * @bat_priv: the bat priv with all the soft interface information
Martin Hundebølle3357182014-07-15 09:41:06 +0200994 * @primary_if: the primary interface of this batman interface
Simon Wunderlich38ef3d12012-01-22 20:00:26 +0100995 * @hw_src: the Hardware source in the ARP Header
996 * @hw_dst: the Hardware destination in the ARP Header
997 * @ethhdr: pointer to the Ethernet header of the claim frame
998 *
Sven Eckelmannbccb48c2020-06-01 20:13:21 +0200999 * checks if it is a claim packet and if it's on the same group.
Simon Wunderlich38ef3d12012-01-22 20:00:26 +01001000 * This function also applies the group ID of the sender
1001 * if it is in the same mesh.
1002 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +02001003 * Return:
Simon Wunderlich38ef3d12012-01-22 20:00:26 +01001004 * 2 - if it is a claim packet and on the same group
1005 * 1 - if is a claim packet from another group
1006 * 0 - if it is not a claim packet
1007 */
Sven Eckelmann56303d32012-06-05 22:31:31 +02001008static int batadv_check_claim_group(struct batadv_priv *bat_priv,
1009 struct batadv_hard_iface *primary_if,
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02001010 u8 *hw_src, u8 *hw_dst,
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001011 struct ethhdr *ethhdr)
Simon Wunderlich38ef3d12012-01-22 20:00:26 +01001012{
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02001013 u8 *backbone_addr;
Sven Eckelmann56303d32012-06-05 22:31:31 +02001014 struct batadv_orig_node *orig_node;
Sven Eckelmann96412692012-06-05 22:31:30 +02001015 struct batadv_bla_claim_dst *bla_dst, *bla_dst_own;
Simon Wunderlich38ef3d12012-01-22 20:00:26 +01001016
Sven Eckelmann96412692012-06-05 22:31:30 +02001017 bla_dst = (struct batadv_bla_claim_dst *)hw_dst;
Sven Eckelmann807736f2012-07-15 22:26:51 +02001018 bla_dst_own = &bat_priv->bla.claim_dest;
Simon Wunderlich38ef3d12012-01-22 20:00:26 +01001019
Simon Wunderlich38ef3d12012-01-22 20:00:26 +01001020 /* if announcement packet, use the source,
1021 * otherwise assume it is in the hw_src
1022 */
1023 switch (bla_dst->type) {
Simon Wunderlich3eb87732012-06-23 12:34:18 +02001024 case BATADV_CLAIM_TYPE_CLAIM:
Simon Wunderlich38ef3d12012-01-22 20:00:26 +01001025 backbone_addr = hw_src;
1026 break;
Sven Eckelmannacd34af2012-06-03 22:19:21 +02001027 case BATADV_CLAIM_TYPE_REQUEST:
1028 case BATADV_CLAIM_TYPE_ANNOUNCE:
Simon Wunderlich3eb87732012-06-23 12:34:18 +02001029 case BATADV_CLAIM_TYPE_UNCLAIM:
Simon Wunderlich38ef3d12012-01-22 20:00:26 +01001030 backbone_addr = ethhdr->h_source;
1031 break;
1032 default:
1033 return 0;
1034 }
1035
1036 /* don't accept claim frames from ourselves */
Sven Eckelmann1eda58b2012-05-12 13:48:58 +02001037 if (batadv_compare_eth(backbone_addr, primary_if->net_dev->dev_addr))
Simon Wunderlich38ef3d12012-01-22 20:00:26 +01001038 return 0;
1039
1040 /* if its already the same group, it is fine. */
1041 if (bla_dst->group == bla_dst_own->group)
1042 return 2;
1043
1044 /* lets see if this originator is in our mesh */
Sven Eckelmannda641192012-05-12 13:48:56 +02001045 orig_node = batadv_orig_hash_find(bat_priv, backbone_addr);
Simon Wunderlich38ef3d12012-01-22 20:00:26 +01001046
1047 /* dont accept claims from gateways which are not in
1048 * the same mesh or group.
1049 */
1050 if (!orig_node)
1051 return 1;
1052
1053 /* if our mesh friends mac is bigger, use it for ourselves. */
1054 if (ntohs(bla_dst->group) > ntohs(bla_dst_own->group)) {
Sven Eckelmann39c75a52012-06-03 22:19:22 +02001055 batadv_dbg(BATADV_DBG_BLA, bat_priv,
Antonio Quartulli39a32992012-11-19 09:01:43 +01001056 "taking other backbones claim group: %#.4x\n",
Sven Eckelmann1eda58b2012-05-12 13:48:58 +02001057 ntohs(bla_dst->group));
Simon Wunderlich38ef3d12012-01-22 20:00:26 +01001058 bla_dst_own->group = bla_dst->group;
1059 }
1060
Sven Eckelmann5d967312016-01-17 11:01:09 +01001061 batadv_orig_node_put(orig_node);
Simon Wunderlich38ef3d12012-01-22 20:00:26 +01001062
1063 return 2;
1064}
1065
Simon Wunderlich1b371d12014-01-15 21:17:54 +01001066/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +01001067 * batadv_bla_process_claim() - Check if this is a claim frame, and process it
Simon Wunderlich1b371d12014-01-15 21:17:54 +01001068 * @bat_priv: the bat priv with all the soft interface information
Martin Hundebølle3357182014-07-15 09:41:06 +02001069 * @primary_if: the primary hard interface of this batman soft interface
Simon Wunderlich23721382012-01-22 20:00:19 +01001070 * @skb: the frame to be checked
1071 *
Sven Eckelmann4b426b12016-02-22 21:02:39 +01001072 * Return: true if it was a claim frame, otherwise return false to
Simon Wunderlich23721382012-01-22 20:00:19 +01001073 * tell the callee that it can use the frame on its own.
1074 */
Sven Eckelmann4b426b12016-02-22 21:02:39 +01001075static bool batadv_bla_process_claim(struct batadv_priv *bat_priv,
1076 struct batadv_hard_iface *primary_if,
1077 struct sk_buff *skb)
Simon Wunderlich23721382012-01-22 20:00:19 +01001078{
Simon Wunderlichd46b6bf2014-06-23 15:55:36 +02001079 struct batadv_bla_claim_dst *bla_dst, *bla_dst_own;
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02001080 u8 *hw_src, *hw_dst;
Simon Wunderlichd46b6bf2014-06-23 15:55:36 +02001081 struct vlan_hdr *vhdr, vhdr_buf;
Antonio Quartullic018ad32013-06-04 12:11:39 +02001082 struct ethhdr *ethhdr;
1083 struct arphdr *arphdr;
1084 unsigned short vid;
Simon Wunderlichd46b6bf2014-06-23 15:55:36 +02001085 int vlan_depth = 0;
Antonio Quartulli293e9332013-05-19 12:55:16 +02001086 __be16 proto;
Simon Wunderlich23721382012-01-22 20:00:19 +01001087 int headlen;
Simon Wunderlich38ef3d12012-01-22 20:00:26 +01001088 int ret;
Simon Wunderlich23721382012-01-22 20:00:19 +01001089
Antonio Quartullic018ad32013-06-04 12:11:39 +02001090 vid = batadv_get_vid(skb, 0);
Antonio Quartulli7ed4be92013-04-08 15:08:18 +02001091 ethhdr = eth_hdr(skb);
Simon Wunderlich23721382012-01-22 20:00:19 +01001092
Antonio Quartullic018ad32013-06-04 12:11:39 +02001093 proto = ethhdr->h_proto;
1094 headlen = ETH_HLEN;
1095 if (vid & BATADV_VLAN_HAS_TAG) {
Simon Wunderlichd46b6bf2014-06-23 15:55:36 +02001096 /* Traverse the VLAN/Ethertypes.
1097 *
1098 * At this point it is known that the first protocol is a VLAN
1099 * header, so start checking at the encapsulated protocol.
1100 *
1101 * The depth of the VLAN headers is recorded to drop BLA claim
1102 * frames encapsulated into multiple VLAN headers (QinQ).
1103 */
1104 do {
1105 vhdr = skb_header_pointer(skb, headlen, VLAN_HLEN,
1106 &vhdr_buf);
1107 if (!vhdr)
Sven Eckelmann4b426b12016-02-22 21:02:39 +01001108 return false;
Simon Wunderlichd46b6bf2014-06-23 15:55:36 +02001109
1110 proto = vhdr->h_vlan_encapsulated_proto;
1111 headlen += VLAN_HLEN;
1112 vlan_depth++;
1113 } while (proto == htons(ETH_P_8021Q));
Simon Wunderlich23721382012-01-22 20:00:19 +01001114 }
1115
Antonio Quartulli293e9332013-05-19 12:55:16 +02001116 if (proto != htons(ETH_P_ARP))
Sven Eckelmann4b426b12016-02-22 21:02:39 +01001117 return false; /* not a claim frame */
Simon Wunderlich23721382012-01-22 20:00:19 +01001118
1119 /* this must be a ARP frame. check if it is a claim. */
1120
1121 if (unlikely(!pskb_may_pull(skb, headlen + arp_hdr_len(skb->dev))))
Sven Eckelmann4b426b12016-02-22 21:02:39 +01001122 return false;
Simon Wunderlich23721382012-01-22 20:00:19 +01001123
1124 /* pskb_may_pull() may have modified the pointers, get ethhdr again */
Antonio Quartulli7ed4be92013-04-08 15:08:18 +02001125 ethhdr = eth_hdr(skb);
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02001126 arphdr = (struct arphdr *)((u8 *)ethhdr + headlen);
Simon Wunderlich23721382012-01-22 20:00:19 +01001127
1128 /* Check whether the ARP frame carries a valid
1129 * IP information
1130 */
Simon Wunderlich23721382012-01-22 20:00:19 +01001131 if (arphdr->ar_hrd != htons(ARPHRD_ETHER))
Sven Eckelmann4b426b12016-02-22 21:02:39 +01001132 return false;
Simon Wunderlich23721382012-01-22 20:00:19 +01001133 if (arphdr->ar_pro != htons(ETH_P_IP))
Sven Eckelmann4b426b12016-02-22 21:02:39 +01001134 return false;
Simon Wunderlich23721382012-01-22 20:00:19 +01001135 if (arphdr->ar_hln != ETH_ALEN)
Sven Eckelmann4b426b12016-02-22 21:02:39 +01001136 return false;
Simon Wunderlich23721382012-01-22 20:00:19 +01001137 if (arphdr->ar_pln != 4)
Sven Eckelmann4b426b12016-02-22 21:02:39 +01001138 return false;
Simon Wunderlich23721382012-01-22 20:00:19 +01001139
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02001140 hw_src = (u8 *)arphdr + sizeof(struct arphdr);
Simon Wunderlich23721382012-01-22 20:00:19 +01001141 hw_dst = hw_src + ETH_ALEN + 4;
Sven Eckelmann96412692012-06-05 22:31:30 +02001142 bla_dst = (struct batadv_bla_claim_dst *)hw_dst;
Simon Wunderlichd46b6bf2014-06-23 15:55:36 +02001143 bla_dst_own = &bat_priv->bla.claim_dest;
1144
1145 /* check if it is a claim frame in general */
1146 if (memcmp(bla_dst->magic, bla_dst_own->magic,
1147 sizeof(bla_dst->magic)) != 0)
Sven Eckelmann4b426b12016-02-22 21:02:39 +01001148 return false;
Simon Wunderlichd46b6bf2014-06-23 15:55:36 +02001149
1150 /* check if there is a claim frame encapsulated deeper in (QinQ) and
1151 * drop that, as this is not supported by BLA but should also not be
1152 * sent via the mesh.
1153 */
1154 if (vlan_depth > 1)
Sven Eckelmann4b426b12016-02-22 21:02:39 +01001155 return true;
Simon Wunderlich23721382012-01-22 20:00:19 +01001156
Simon Wunderlichcd9c7bf2016-03-12 10:49:33 +01001157 /* Let the loopdetect frames on the mesh in any case. */
1158 if (bla_dst->type == BATADV_CLAIM_TYPE_LOOPDETECT)
kbuild test robot4fd261b2016-07-06 10:49:29 +08001159 return false;
Simon Wunderlichcd9c7bf2016-03-12 10:49:33 +01001160
Simon Wunderlich23721382012-01-22 20:00:19 +01001161 /* check if it is a claim frame. */
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001162 ret = batadv_check_claim_group(bat_priv, primary_if, hw_src, hw_dst,
1163 ethhdr);
Simon Wunderlich38ef3d12012-01-22 20:00:26 +01001164 if (ret == 1)
Sven Eckelmann39c75a52012-06-03 22:19:22 +02001165 batadv_dbg(BATADV_DBG_BLA, bat_priv,
Sven Eckelmann22f05022017-05-19 13:02:00 +02001166 "%s(): received a claim frame from another group. From: %pM on vid %d ...(hw_src %pM, hw_dst %pM)\n",
1167 __func__, ethhdr->h_source, batadv_print_vid(vid),
1168 hw_src, hw_dst);
Simon Wunderlich38ef3d12012-01-22 20:00:26 +01001169
1170 if (ret < 2)
Sven Eckelmann4b426b12016-02-22 21:02:39 +01001171 return !!ret;
Simon Wunderlich23721382012-01-22 20:00:19 +01001172
1173 /* become a backbone gw ourselves on this vlan if not happened yet */
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001174 batadv_bla_update_own_backbone_gw(bat_priv, primary_if, vid);
Simon Wunderlich23721382012-01-22 20:00:19 +01001175
1176 /* check for the different types of claim frames ... */
1177 switch (bla_dst->type) {
Simon Wunderlich3eb87732012-06-23 12:34:18 +02001178 case BATADV_CLAIM_TYPE_CLAIM:
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001179 if (batadv_handle_claim(bat_priv, primary_if, hw_src,
1180 ethhdr->h_source, vid))
Sven Eckelmann4b426b12016-02-22 21:02:39 +01001181 return true;
Simon Wunderlich23721382012-01-22 20:00:19 +01001182 break;
Simon Wunderlich3eb87732012-06-23 12:34:18 +02001183 case BATADV_CLAIM_TYPE_UNCLAIM:
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001184 if (batadv_handle_unclaim(bat_priv, primary_if,
1185 ethhdr->h_source, hw_src, vid))
Sven Eckelmann4b426b12016-02-22 21:02:39 +01001186 return true;
Simon Wunderlich23721382012-01-22 20:00:19 +01001187 break;
1188
Sven Eckelmannacd34af2012-06-03 22:19:21 +02001189 case BATADV_CLAIM_TYPE_ANNOUNCE:
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001190 if (batadv_handle_announce(bat_priv, hw_src, ethhdr->h_source,
1191 vid))
Sven Eckelmann4b426b12016-02-22 21:02:39 +01001192 return true;
Simon Wunderlich23721382012-01-22 20:00:19 +01001193 break;
Sven Eckelmannacd34af2012-06-03 22:19:21 +02001194 case BATADV_CLAIM_TYPE_REQUEST:
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001195 if (batadv_handle_request(bat_priv, primary_if, hw_src, ethhdr,
1196 vid))
Sven Eckelmann4b426b12016-02-22 21:02:39 +01001197 return true;
Simon Wunderlich23721382012-01-22 20:00:19 +01001198 break;
1199 }
1200
Sven Eckelmann39c75a52012-06-03 22:19:22 +02001201 batadv_dbg(BATADV_DBG_BLA, bat_priv,
Sven Eckelmann22f05022017-05-19 13:02:00 +02001202 "%s(): ERROR - this looks like a claim frame, but is useless. eth src %pM on vid %d ...(hw_src %pM, hw_dst %pM)\n",
1203 __func__, ethhdr->h_source, batadv_print_vid(vid), hw_src,
1204 hw_dst);
Sven Eckelmann4b426b12016-02-22 21:02:39 +01001205 return true;
Simon Wunderlich23721382012-01-22 20:00:19 +01001206}
1207
Simon Wunderlich04e14be2015-11-06 10:45:19 +01001208/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +01001209 * batadv_bla_purge_backbone_gw() - Remove backbone gateways after a timeout or
Simon Wunderlich04e14be2015-11-06 10:45:19 +01001210 * immediately
1211 * @bat_priv: the bat priv with all the soft interface information
1212 * @now: whether the whole hash shall be wiped now
1213 *
1214 * Check when we last heard from other nodes, and remove them in case of
Simon Wunderlich23721382012-01-22 20:00:19 +01001215 * a time out, or clean all backbone gws if now is set.
1216 */
Sven Eckelmann56303d32012-06-05 22:31:31 +02001217static void batadv_bla_purge_backbone_gw(struct batadv_priv *bat_priv, int now)
Simon Wunderlich23721382012-01-22 20:00:19 +01001218{
Marek Lindnerbae98772012-12-25 17:03:24 +08001219 struct batadv_bla_backbone_gw *backbone_gw;
Sasha Levinb67bfe02013-02-27 17:06:00 -08001220 struct hlist_node *node_tmp;
Simon Wunderlich23721382012-01-22 20:00:19 +01001221 struct hlist_head *head;
Sven Eckelmann5bf74e92012-06-05 22:31:28 +02001222 struct batadv_hashtable *hash;
Simon Wunderlich23721382012-01-22 20:00:19 +01001223 spinlock_t *list_lock; /* protects write access to the hash lists */
1224 int i;
1225
Sven Eckelmann807736f2012-07-15 22:26:51 +02001226 hash = bat_priv->bla.backbone_hash;
Simon Wunderlich23721382012-01-22 20:00:19 +01001227 if (!hash)
1228 return;
1229
1230 for (i = 0; i < hash->size; i++) {
1231 head = &hash->table[i];
1232 list_lock = &hash->list_locks[i];
1233
1234 spin_lock_bh(list_lock);
Sasha Levinb67bfe02013-02-27 17:06:00 -08001235 hlist_for_each_entry_safe(backbone_gw, node_tmp,
Simon Wunderlich23721382012-01-22 20:00:19 +01001236 head, hash_entry) {
1237 if (now)
1238 goto purge_now;
Sven Eckelmann1eda58b2012-05-12 13:48:58 +02001239 if (!batadv_has_timed_out(backbone_gw->lasttime,
Sven Eckelmann42d0b042012-06-03 22:19:17 +02001240 BATADV_BLA_BACKBONE_TIMEOUT))
Simon Wunderlich23721382012-01-22 20:00:19 +01001241 continue;
1242
Sven Eckelmann39c75a52012-06-03 22:19:22 +02001243 batadv_dbg(BATADV_DBG_BLA, backbone_gw->bat_priv,
Sven Eckelmann22f05022017-05-19 13:02:00 +02001244 "%s(): backbone gw %pM timed out\n",
1245 __func__, backbone_gw->orig);
Simon Wunderlich23721382012-01-22 20:00:19 +01001246
1247purge_now:
1248 /* don't wait for the pending request anymore */
1249 if (atomic_read(&backbone_gw->request_sent))
Sven Eckelmann807736f2012-07-15 22:26:51 +02001250 atomic_dec(&bat_priv->bla.num_requests);
Simon Wunderlich23721382012-01-22 20:00:19 +01001251
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001252 batadv_bla_del_backbone_claims(backbone_gw);
Simon Wunderlich23721382012-01-22 20:00:19 +01001253
Sasha Levinb67bfe02013-02-27 17:06:00 -08001254 hlist_del_rcu(&backbone_gw->hash_entry);
Sven Eckelmannc8b86c12016-01-17 11:01:15 +01001255 batadv_backbone_gw_put(backbone_gw);
Simon Wunderlich23721382012-01-22 20:00:19 +01001256 }
1257 spin_unlock_bh(list_lock);
1258 }
1259}
1260
Ben Hutchings2c530402012-07-10 10:55:09 +00001261/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +01001262 * batadv_bla_purge_claims() - Remove claims after a timeout or immediately
Ben Hutchings2c530402012-07-10 10:55:09 +00001263 * @bat_priv: the bat priv with all the soft interface information
Simon Wunderlich23721382012-01-22 20:00:19 +01001264 * @primary_if: the selected primary interface, may be NULL if now is set
1265 * @now: whether the whole hash shall be wiped now
1266 *
1267 * Check when we heard last time from our own claims, and remove them in case of
1268 * a time out, or clean all claims if now is set
1269 */
Sven Eckelmann56303d32012-06-05 22:31:31 +02001270static void batadv_bla_purge_claims(struct batadv_priv *bat_priv,
1271 struct batadv_hard_iface *primary_if,
1272 int now)
Simon Wunderlich23721382012-01-22 20:00:19 +01001273{
Sven Eckelmann3db0dec2016-07-01 15:49:43 +02001274 struct batadv_bla_backbone_gw *backbone_gw;
Marek Lindner712bbfe42012-12-25 17:03:25 +08001275 struct batadv_bla_claim *claim;
Simon Wunderlich23721382012-01-22 20:00:19 +01001276 struct hlist_head *head;
Sven Eckelmann5bf74e92012-06-05 22:31:28 +02001277 struct batadv_hashtable *hash;
Simon Wunderlich23721382012-01-22 20:00:19 +01001278 int i;
1279
Sven Eckelmann807736f2012-07-15 22:26:51 +02001280 hash = bat_priv->bla.claim_hash;
Simon Wunderlich23721382012-01-22 20:00:19 +01001281 if (!hash)
1282 return;
1283
1284 for (i = 0; i < hash->size; i++) {
1285 head = &hash->table[i];
1286
1287 rcu_read_lock();
Sasha Levinb67bfe02013-02-27 17:06:00 -08001288 hlist_for_each_entry_rcu(claim, head, hash_entry) {
Sven Eckelmann3db0dec2016-07-01 15:49:43 +02001289 backbone_gw = batadv_bla_claim_get_backbone_gw(claim);
Simon Wunderlich23721382012-01-22 20:00:19 +01001290 if (now)
1291 goto purge_now;
Sven Eckelmann3db0dec2016-07-01 15:49:43 +02001292
1293 if (!batadv_compare_eth(backbone_gw->orig,
Sven Eckelmann1eda58b2012-05-12 13:48:58 +02001294 primary_if->net_dev->dev_addr))
Sven Eckelmann3db0dec2016-07-01 15:49:43 +02001295 goto skip;
1296
Sven Eckelmann1eda58b2012-05-12 13:48:58 +02001297 if (!batadv_has_timed_out(claim->lasttime,
Sven Eckelmann42d0b042012-06-03 22:19:17 +02001298 BATADV_BLA_CLAIM_TIMEOUT))
Sven Eckelmann3db0dec2016-07-01 15:49:43 +02001299 goto skip;
Simon Wunderlich23721382012-01-22 20:00:19 +01001300
Sven Eckelmann39c75a52012-06-03 22:19:22 +02001301 batadv_dbg(BATADV_DBG_BLA, bat_priv,
Sven Eckelmann22f05022017-05-19 13:02:00 +02001302 "%s(): timed out.\n", __func__);
Simon Wunderlich23721382012-01-22 20:00:19 +01001303
1304purge_now:
Andreas Pape4dd72f72016-09-05 13:20:28 +02001305 batadv_dbg(BATADV_DBG_BLA, bat_priv,
Sven Eckelmann22f05022017-05-19 13:02:00 +02001306 "%s(): %pM, vid %d\n", __func__,
Andreas Pape4dd72f72016-09-05 13:20:28 +02001307 claim->addr, claim->vid);
1308
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001309 batadv_handle_unclaim(bat_priv, primary_if,
Sven Eckelmann3db0dec2016-07-01 15:49:43 +02001310 backbone_gw->orig,
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001311 claim->addr, claim->vid);
Sven Eckelmann3db0dec2016-07-01 15:49:43 +02001312skip:
1313 batadv_backbone_gw_put(backbone_gw);
Simon Wunderlich23721382012-01-22 20:00:19 +01001314 }
1315 rcu_read_unlock();
1316 }
1317}
1318
Ben Hutchings2c530402012-07-10 10:55:09 +00001319/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +01001320 * batadv_bla_update_orig_address() - Update the backbone gateways when the own
Simon Wunderlich04e14be2015-11-06 10:45:19 +01001321 * originator address changes
Ben Hutchings2c530402012-07-10 10:55:09 +00001322 * @bat_priv: the bat priv with all the soft interface information
Simon Wunderlich23721382012-01-22 20:00:19 +01001323 * @primary_if: the new selected primary_if
1324 * @oldif: the old primary interface, may be NULL
Simon Wunderlich23721382012-01-22 20:00:19 +01001325 */
Sven Eckelmann56303d32012-06-05 22:31:31 +02001326void batadv_bla_update_orig_address(struct batadv_priv *bat_priv,
1327 struct batadv_hard_iface *primary_if,
1328 struct batadv_hard_iface *oldif)
Simon Wunderlich23721382012-01-22 20:00:19 +01001329{
Marek Lindnerbae98772012-12-25 17:03:24 +08001330 struct batadv_bla_backbone_gw *backbone_gw;
Simon Wunderlich23721382012-01-22 20:00:19 +01001331 struct hlist_head *head;
Sven Eckelmann5bf74e92012-06-05 22:31:28 +02001332 struct batadv_hashtable *hash;
Sven Eckelmann807736f2012-07-15 22:26:51 +02001333 __be16 group;
Simon Wunderlich23721382012-01-22 20:00:19 +01001334 int i;
1335
Simon Wunderlich38ef3d12012-01-22 20:00:26 +01001336 /* reset bridge loop avoidance group id */
Sven Eckelmann807736f2012-07-15 22:26:51 +02001337 group = htons(crc16(0, primary_if->net_dev->dev_addr, ETH_ALEN));
1338 bat_priv->bla.claim_dest.group = group;
Simon Wunderlich38ef3d12012-01-22 20:00:26 +01001339
Simon Wunderlichd5b4c932013-06-07 16:52:05 +02001340 /* purge everything when bridge loop avoidance is turned off */
1341 if (!atomic_read(&bat_priv->bridge_loop_avoidance))
1342 oldif = NULL;
1343
Simon Wunderlich23721382012-01-22 20:00:19 +01001344 if (!oldif) {
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001345 batadv_bla_purge_claims(bat_priv, NULL, 1);
1346 batadv_bla_purge_backbone_gw(bat_priv, 1);
Simon Wunderlich23721382012-01-22 20:00:19 +01001347 return;
1348 }
1349
Sven Eckelmann807736f2012-07-15 22:26:51 +02001350 hash = bat_priv->bla.backbone_hash;
Simon Wunderlich23721382012-01-22 20:00:19 +01001351 if (!hash)
1352 return;
1353
1354 for (i = 0; i < hash->size; i++) {
1355 head = &hash->table[i];
1356
1357 rcu_read_lock();
Sasha Levinb67bfe02013-02-27 17:06:00 -08001358 hlist_for_each_entry_rcu(backbone_gw, head, hash_entry) {
Simon Wunderlich23721382012-01-22 20:00:19 +01001359 /* own orig still holds the old value. */
Sven Eckelmann1eda58b2012-05-12 13:48:58 +02001360 if (!batadv_compare_eth(backbone_gw->orig,
1361 oldif->net_dev->dev_addr))
Simon Wunderlich23721382012-01-22 20:00:19 +01001362 continue;
1363
Antonio Quartulli8fdd0152014-01-22 00:42:11 +01001364 ether_addr_copy(backbone_gw->orig,
1365 primary_if->net_dev->dev_addr);
Simon Wunderlich23721382012-01-22 20:00:19 +01001366 /* send an announce frame so others will ask for our
1367 * claims and update their tables.
1368 */
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001369 batadv_bla_send_announce(bat_priv, backbone_gw);
Simon Wunderlich23721382012-01-22 20:00:19 +01001370 }
1371 rcu_read_unlock();
1372 }
1373}
1374
Simon Wunderlichd68081a2015-11-09 16:20:52 +01001375/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +01001376 * batadv_bla_send_loopdetect() - send a loopdetect frame
Simon Wunderlichcd9c7bf2016-03-12 10:49:33 +01001377 * @bat_priv: the bat priv with all the soft interface information
1378 * @backbone_gw: the backbone gateway for which a loop should be detected
1379 *
1380 * To detect loops that the bridge loop avoidance can't handle, send a loop
1381 * detection packet on the backbone. Unlike other BLA frames, this frame will
1382 * be allowed on the mesh by other nodes. If it is received on the mesh, this
1383 * indicates that there is a loop.
1384 */
1385static void
1386batadv_bla_send_loopdetect(struct batadv_priv *bat_priv,
1387 struct batadv_bla_backbone_gw *backbone_gw)
1388{
1389 batadv_dbg(BATADV_DBG_BLA, bat_priv, "Send loopdetect frame for vid %d\n",
1390 backbone_gw->vid);
1391 batadv_bla_send_claim(bat_priv, bat_priv->bla.loopdetect_addr,
1392 backbone_gw->vid, BATADV_CLAIM_TYPE_LOOPDETECT);
1393}
1394
1395/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +01001396 * batadv_bla_status_update() - purge bla interfaces if necessary
Simon Wunderlichd68081a2015-11-09 16:20:52 +01001397 * @net_dev: the soft interface net device
1398 */
1399void batadv_bla_status_update(struct net_device *net_dev)
1400{
1401 struct batadv_priv *bat_priv = netdev_priv(net_dev);
1402 struct batadv_hard_iface *primary_if;
1403
1404 primary_if = batadv_primary_if_get_selected(bat_priv);
1405 if (!primary_if)
1406 return;
1407
1408 /* this function already purges everything when bla is disabled,
1409 * so just call that one.
1410 */
1411 batadv_bla_update_orig_address(bat_priv, primary_if, primary_if);
Sven Eckelmann82047ad2016-01-17 11:01:10 +01001412 batadv_hardif_put(primary_if);
Simon Wunderlichd68081a2015-11-09 16:20:52 +01001413}
1414
Simon Wunderlich04e14be2015-11-06 10:45:19 +01001415/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +01001416 * batadv_bla_periodic_work() - performs periodic bla work
Simon Wunderlich04e14be2015-11-06 10:45:19 +01001417 * @work: kernel work struct
1418 *
1419 * periodic work to do:
Simon Wunderlich23721382012-01-22 20:00:19 +01001420 * * purge structures when they are too old
1421 * * send announcements
1422 */
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001423static void batadv_bla_periodic_work(struct work_struct *work)
Simon Wunderlich23721382012-01-22 20:00:19 +01001424{
Sven Eckelmannbbb1f902012-07-08 17:13:15 +02001425 struct delayed_work *delayed_work;
Sven Eckelmann56303d32012-06-05 22:31:31 +02001426 struct batadv_priv *bat_priv;
Sven Eckelmann807736f2012-07-15 22:26:51 +02001427 struct batadv_priv_bla *priv_bla;
Simon Wunderlich23721382012-01-22 20:00:19 +01001428 struct hlist_head *head;
Marek Lindnerbae98772012-12-25 17:03:24 +08001429 struct batadv_bla_backbone_gw *backbone_gw;
Sven Eckelmann5bf74e92012-06-05 22:31:28 +02001430 struct batadv_hashtable *hash;
Sven Eckelmann56303d32012-06-05 22:31:31 +02001431 struct batadv_hard_iface *primary_if;
Simon Wunderlichcd9c7bf2016-03-12 10:49:33 +01001432 bool send_loopdetect = false;
Simon Wunderlich23721382012-01-22 20:00:19 +01001433 int i;
1434
Geliang Tang4ba4bc02015-12-28 23:43:37 +08001435 delayed_work = to_delayed_work(work);
Sven Eckelmann807736f2012-07-15 22:26:51 +02001436 priv_bla = container_of(delayed_work, struct batadv_priv_bla, work);
1437 bat_priv = container_of(priv_bla, struct batadv_priv, bla);
Sven Eckelmanne5d89252012-05-12 13:48:54 +02001438 primary_if = batadv_primary_if_get_selected(bat_priv);
Simon Wunderlich23721382012-01-22 20:00:19 +01001439 if (!primary_if)
1440 goto out;
1441
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001442 batadv_bla_purge_claims(bat_priv, primary_if, 0);
1443 batadv_bla_purge_backbone_gw(bat_priv, 0);
Simon Wunderlich23721382012-01-22 20:00:19 +01001444
1445 if (!atomic_read(&bat_priv->bridge_loop_avoidance))
1446 goto out;
1447
Simon Wunderlichcd9c7bf2016-03-12 10:49:33 +01001448 if (atomic_dec_and_test(&bat_priv->bla.loopdetect_next)) {
1449 /* set a new random mac address for the next bridge loop
1450 * detection frames. Set the locally administered bit to avoid
1451 * collisions with users mac addresses.
1452 */
Joe Perches6c1f0a12018-06-22 10:51:00 -07001453 eth_random_addr(bat_priv->bla.loopdetect_addr);
Simon Wunderlichcd9c7bf2016-03-12 10:49:33 +01001454 bat_priv->bla.loopdetect_addr[0] = 0xba;
1455 bat_priv->bla.loopdetect_addr[1] = 0xbe;
1456 bat_priv->bla.loopdetect_lasttime = jiffies;
1457 atomic_set(&bat_priv->bla.loopdetect_next,
1458 BATADV_BLA_LOOPDETECT_PERIODS);
1459
1460 /* mark for sending loop detect on all VLANs */
1461 send_loopdetect = true;
1462 }
1463
Sven Eckelmann807736f2012-07-15 22:26:51 +02001464 hash = bat_priv->bla.backbone_hash;
Simon Wunderlich23721382012-01-22 20:00:19 +01001465 if (!hash)
1466 goto out;
1467
1468 for (i = 0; i < hash->size; i++) {
1469 head = &hash->table[i];
1470
1471 rcu_read_lock();
Sasha Levinb67bfe02013-02-27 17:06:00 -08001472 hlist_for_each_entry_rcu(backbone_gw, head, hash_entry) {
Sven Eckelmann1eda58b2012-05-12 13:48:58 +02001473 if (!batadv_compare_eth(backbone_gw->orig,
1474 primary_if->net_dev->dev_addr))
Simon Wunderlich23721382012-01-22 20:00:19 +01001475 continue;
1476
1477 backbone_gw->lasttime = jiffies;
1478
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001479 batadv_bla_send_announce(bat_priv, backbone_gw);
Simon Wunderlichcd9c7bf2016-03-12 10:49:33 +01001480 if (send_loopdetect)
1481 batadv_bla_send_loopdetect(bat_priv,
1482 backbone_gw);
Simon Wunderlichd807f272012-09-09 22:27:57 +02001483
1484 /* request_sent is only set after creation to avoid
1485 * problems when we are not yet known as backbone gw
1486 * in the backbone.
1487 *
Simon Wunderlich28709872012-09-13 18:18:46 +02001488 * We can reset this now after we waited some periods
1489 * to give bridge forward delays and bla group forming
1490 * some grace time.
Simon Wunderlichd807f272012-09-09 22:27:57 +02001491 */
1492
1493 if (atomic_read(&backbone_gw->request_sent) == 0)
1494 continue;
1495
Simon Wunderlich28709872012-09-13 18:18:46 +02001496 if (!atomic_dec_and_test(&backbone_gw->wait_periods))
1497 continue;
1498
Simon Wunderlichd807f272012-09-09 22:27:57 +02001499 atomic_dec(&backbone_gw->bat_priv->bla.num_requests);
1500 atomic_set(&backbone_gw->request_sent, 0);
Simon Wunderlich23721382012-01-22 20:00:19 +01001501 }
1502 rcu_read_unlock();
1503 }
1504out:
1505 if (primary_if)
Sven Eckelmann82047ad2016-01-17 11:01:10 +01001506 batadv_hardif_put(primary_if);
Simon Wunderlich23721382012-01-22 20:00:19 +01001507
Antonio Quartulli72414442012-12-25 13:14:37 +01001508 queue_delayed_work(batadv_event_workqueue, &bat_priv->bla.work,
1509 msecs_to_jiffies(BATADV_BLA_PERIOD_LENGTH));
Simon Wunderlich23721382012-01-22 20:00:19 +01001510}
1511
Sven Eckelmann5d52dad2012-03-29 12:38:20 +02001512/* The hash for claim and backbone hash receive the same key because they
1513 * are getting initialized by hash_new with the same key. Reinitializing
1514 * them with to different keys to allow nested locking without generating
1515 * lockdep warnings
1516 */
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001517static struct lock_class_key batadv_claim_hash_lock_class_key;
1518static struct lock_class_key batadv_backbone_hash_lock_class_key;
Sven Eckelmann5d52dad2012-03-29 12:38:20 +02001519
Simon Wunderlich04e14be2015-11-06 10:45:19 +01001520/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +01001521 * batadv_bla_init() - initialize all bla structures
Simon Wunderlich04e14be2015-11-06 10:45:19 +01001522 * @bat_priv: the bat priv with all the soft interface information
1523 *
1524 * Return: 0 on success, < 0 on error.
1525 */
Sven Eckelmann56303d32012-06-05 22:31:31 +02001526int batadv_bla_init(struct batadv_priv *bat_priv)
Simon Wunderlich23721382012-01-22 20:00:19 +01001527{
Simon Wunderlichfe2da6f2012-01-22 20:00:24 +01001528 int i;
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02001529 u8 claim_dest[ETH_ALEN] = {0xff, 0x43, 0x05, 0x00, 0x00, 0x00};
Sven Eckelmann56303d32012-06-05 22:31:31 +02001530 struct batadv_hard_iface *primary_if;
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02001531 u16 crc;
Sven Eckelmann807736f2012-07-15 22:26:51 +02001532 unsigned long entrytime;
Simon Wunderlichfe2da6f2012-01-22 20:00:24 +01001533
Linus Lüssing7dac7b72012-10-17 14:53:05 +02001534 spin_lock_init(&bat_priv->bla.bcast_duplist_lock);
1535
Sven Eckelmann39c75a52012-06-03 22:19:22 +02001536 batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla hash registering\n");
Simon Wunderlich23721382012-01-22 20:00:19 +01001537
Simon Wunderlich38ef3d12012-01-22 20:00:26 +01001538 /* setting claim destination address */
Sven Eckelmann807736f2012-07-15 22:26:51 +02001539 memcpy(&bat_priv->bla.claim_dest.magic, claim_dest, 3);
1540 bat_priv->bla.claim_dest.type = 0;
Sven Eckelmanne5d89252012-05-12 13:48:54 +02001541 primary_if = batadv_primary_if_get_selected(bat_priv);
Simon Wunderlich38ef3d12012-01-22 20:00:26 +01001542 if (primary_if) {
Sven Eckelmann807736f2012-07-15 22:26:51 +02001543 crc = crc16(0, primary_if->net_dev->dev_addr, ETH_ALEN);
1544 bat_priv->bla.claim_dest.group = htons(crc);
Sven Eckelmann82047ad2016-01-17 11:01:10 +01001545 batadv_hardif_put(primary_if);
Simon Wunderlich38ef3d12012-01-22 20:00:26 +01001546 } else {
Sven Eckelmann807736f2012-07-15 22:26:51 +02001547 bat_priv->bla.claim_dest.group = 0; /* will be set later */
Simon Wunderlich38ef3d12012-01-22 20:00:26 +01001548 }
1549
Simon Wunderlichfe2da6f2012-01-22 20:00:24 +01001550 /* initialize the duplicate list */
Sven Eckelmann807736f2012-07-15 22:26:51 +02001551 entrytime = jiffies - msecs_to_jiffies(BATADV_DUPLIST_TIMEOUT);
Sven Eckelmann42d0b042012-06-03 22:19:17 +02001552 for (i = 0; i < BATADV_DUPLIST_SIZE; i++)
Sven Eckelmann807736f2012-07-15 22:26:51 +02001553 bat_priv->bla.bcast_duplist[i].entrytime = entrytime;
1554 bat_priv->bla.bcast_duplist_curr = 0;
Simon Wunderlichfe2da6f2012-01-22 20:00:24 +01001555
Simon Wunderlichcd9c7bf2016-03-12 10:49:33 +01001556 atomic_set(&bat_priv->bla.loopdetect_next,
1557 BATADV_BLA_LOOPDETECT_PERIODS);
1558
Sven Eckelmann807736f2012-07-15 22:26:51 +02001559 if (bat_priv->bla.claim_hash)
Sven Eckelmann5346c352012-05-05 13:27:28 +02001560 return 0;
Simon Wunderlich23721382012-01-22 20:00:19 +01001561
Sven Eckelmann807736f2012-07-15 22:26:51 +02001562 bat_priv->bla.claim_hash = batadv_hash_new(128);
1563 bat_priv->bla.backbone_hash = batadv_hash_new(32);
Simon Wunderlich23721382012-01-22 20:00:19 +01001564
Sven Eckelmann807736f2012-07-15 22:26:51 +02001565 if (!bat_priv->bla.claim_hash || !bat_priv->bla.backbone_hash)
Sven Eckelmann5346c352012-05-05 13:27:28 +02001566 return -ENOMEM;
Simon Wunderlich23721382012-01-22 20:00:19 +01001567
Sven Eckelmann807736f2012-07-15 22:26:51 +02001568 batadv_hash_set_lock_class(bat_priv->bla.claim_hash,
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001569 &batadv_claim_hash_lock_class_key);
Sven Eckelmann807736f2012-07-15 22:26:51 +02001570 batadv_hash_set_lock_class(bat_priv->bla.backbone_hash,
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001571 &batadv_backbone_hash_lock_class_key);
Sven Eckelmann5d52dad2012-03-29 12:38:20 +02001572
Sven Eckelmann39c75a52012-06-03 22:19:22 +02001573 batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla hashes initialized\n");
Simon Wunderlich23721382012-01-22 20:00:19 +01001574
Antonio Quartulli72414442012-12-25 13:14:37 +01001575 INIT_DELAYED_WORK(&bat_priv->bla.work, batadv_bla_periodic_work);
1576
1577 queue_delayed_work(batadv_event_workqueue, &bat_priv->bla.work,
1578 msecs_to_jiffies(BATADV_BLA_PERIOD_LENGTH));
Sven Eckelmann5346c352012-05-05 13:27:28 +02001579 return 0;
Simon Wunderlich23721382012-01-22 20:00:19 +01001580}
1581
Ben Hutchings2c530402012-07-10 10:55:09 +00001582/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +01001583 * batadv_bla_check_bcast_duplist() - Check if a frame is in the broadcast dup.
Ben Hutchings2c530402012-07-10 10:55:09 +00001584 * @bat_priv: the bat priv with all the soft interface information
Simon Wunderlich004e86f2012-10-18 13:47:42 +02001585 * @skb: contains the bcast_packet to be checked
Simon Wunderlichfe2da6f2012-01-22 20:00:24 +01001586 *
1587 * check if it is on our broadcast list. Another gateway might
1588 * have sent the same packet because it is connected to the same backbone,
1589 * so we have to remove this duplicate.
1590 *
1591 * This is performed by checking the CRC, which will tell us
1592 * with a good chance that it is the same packet. If it is furthermore
1593 * sent by another host, drop it. We allow equal packets from
1594 * the same host however as this might be intended.
Simon Wunderlich04e14be2015-11-06 10:45:19 +01001595 *
Sven Eckelmann4b426b12016-02-22 21:02:39 +01001596 * Return: true if a packet is in the duplicate list, false otherwise.
Sven Eckelmann9cfc7bd2012-05-12 02:09:43 +02001597 */
Sven Eckelmann4b426b12016-02-22 21:02:39 +01001598bool batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
1599 struct sk_buff *skb)
Simon Wunderlichfe2da6f2012-01-22 20:00:24 +01001600{
Sven Eckelmann4b426b12016-02-22 21:02:39 +01001601 int i, curr;
Simon Wunderlich004e86f2012-10-18 13:47:42 +02001602 __be32 crc;
1603 struct batadv_bcast_packet *bcast_packet;
Sven Eckelmann56303d32012-06-05 22:31:31 +02001604 struct batadv_bcast_duplist_entry *entry;
Sven Eckelmann4b426b12016-02-22 21:02:39 +01001605 bool ret = false;
Simon Wunderlichfe2da6f2012-01-22 20:00:24 +01001606
Simon Wunderlich004e86f2012-10-18 13:47:42 +02001607 bcast_packet = (struct batadv_bcast_packet *)skb->data;
Simon Wunderlichfe2da6f2012-01-22 20:00:24 +01001608
1609 /* calculate the crc ... */
Simon Wunderlich004e86f2012-10-18 13:47:42 +02001610 crc = batadv_skb_crc32(skb, (u8 *)(bcast_packet + 1));
Simon Wunderlichfe2da6f2012-01-22 20:00:24 +01001611
Linus Lüssing7dac7b72012-10-17 14:53:05 +02001612 spin_lock_bh(&bat_priv->bla.bcast_duplist_lock);
1613
Sven Eckelmann42d0b042012-06-03 22:19:17 +02001614 for (i = 0; i < BATADV_DUPLIST_SIZE; i++) {
Sven Eckelmann807736f2012-07-15 22:26:51 +02001615 curr = (bat_priv->bla.bcast_duplist_curr + i);
1616 curr %= BATADV_DUPLIST_SIZE;
1617 entry = &bat_priv->bla.bcast_duplist[curr];
Simon Wunderlichfe2da6f2012-01-22 20:00:24 +01001618
1619 /* we can stop searching if the entry is too old ;
1620 * later entries will be even older
1621 */
Sven Eckelmann42d0b042012-06-03 22:19:17 +02001622 if (batadv_has_timed_out(entry->entrytime,
1623 BATADV_DUPLIST_TIMEOUT))
Simon Wunderlichfe2da6f2012-01-22 20:00:24 +01001624 break;
1625
1626 if (entry->crc != crc)
1627 continue;
1628
Sven Eckelmann1eda58b2012-05-12 13:48:58 +02001629 if (batadv_compare_eth(entry->orig, bcast_packet->orig))
Simon Wunderlichfe2da6f2012-01-22 20:00:24 +01001630 continue;
1631
1632 /* this entry seems to match: same crc, not too old,
Sven Eckelmann4b426b12016-02-22 21:02:39 +01001633 * and from another gw. therefore return true to forbid it.
Simon Wunderlichfe2da6f2012-01-22 20:00:24 +01001634 */
Sven Eckelmann4b426b12016-02-22 21:02:39 +01001635 ret = true;
Linus Lüssing7dac7b72012-10-17 14:53:05 +02001636 goto out;
Simon Wunderlichfe2da6f2012-01-22 20:00:24 +01001637 }
Linus Lüssing7dac7b72012-10-17 14:53:05 +02001638 /* not found, add a new entry (overwrite the oldest entry)
Antonio Quartulli3f687852014-11-02 11:29:56 +01001639 * and allow it, its the first occurrence.
Linus Lüssing7dac7b72012-10-17 14:53:05 +02001640 */
Sven Eckelmann807736f2012-07-15 22:26:51 +02001641 curr = (bat_priv->bla.bcast_duplist_curr + BATADV_DUPLIST_SIZE - 1);
Sven Eckelmann42d0b042012-06-03 22:19:17 +02001642 curr %= BATADV_DUPLIST_SIZE;
Sven Eckelmann807736f2012-07-15 22:26:51 +02001643 entry = &bat_priv->bla.bcast_duplist[curr];
Simon Wunderlichfe2da6f2012-01-22 20:00:24 +01001644 entry->crc = crc;
1645 entry->entrytime = jiffies;
Antonio Quartulli8fdd0152014-01-22 00:42:11 +01001646 ether_addr_copy(entry->orig, bcast_packet->orig);
Sven Eckelmann807736f2012-07-15 22:26:51 +02001647 bat_priv->bla.bcast_duplist_curr = curr;
Simon Wunderlichfe2da6f2012-01-22 20:00:24 +01001648
Linus Lüssing7dac7b72012-10-17 14:53:05 +02001649out:
1650 spin_unlock_bh(&bat_priv->bla.bcast_duplist_lock);
1651
1652 return ret;
Simon Wunderlichfe2da6f2012-01-22 20:00:24 +01001653}
1654
Simon Wunderlich1b371d12014-01-15 21:17:54 +01001655/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +01001656 * batadv_bla_is_backbone_gw_orig() - Check if the originator is a gateway for
Simon Wunderlich04e14be2015-11-06 10:45:19 +01001657 * the VLAN identified by vid.
Simon Wunderlich1b371d12014-01-15 21:17:54 +01001658 * @bat_priv: the bat priv with all the soft interface information
Simon Wunderlich20ff9d52012-01-22 20:00:23 +01001659 * @orig: originator mac address
Antonio Quartullicfd4f752013-08-07 18:28:56 +02001660 * @vid: VLAN identifier
Simon Wunderlich20ff9d52012-01-22 20:00:23 +01001661 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +02001662 * Return: true if orig is a backbone for this vid, false otherwise.
Simon Wunderlich20ff9d52012-01-22 20:00:23 +01001663 */
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02001664bool batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, u8 *orig,
Antonio Quartullicfd4f752013-08-07 18:28:56 +02001665 unsigned short vid)
Simon Wunderlich20ff9d52012-01-22 20:00:23 +01001666{
Sven Eckelmann807736f2012-07-15 22:26:51 +02001667 struct batadv_hashtable *hash = bat_priv->bla.backbone_hash;
Simon Wunderlich20ff9d52012-01-22 20:00:23 +01001668 struct hlist_head *head;
Marek Lindnerbae98772012-12-25 17:03:24 +08001669 struct batadv_bla_backbone_gw *backbone_gw;
Simon Wunderlich20ff9d52012-01-22 20:00:23 +01001670 int i;
1671
1672 if (!atomic_read(&bat_priv->bridge_loop_avoidance))
Antonio Quartullicfd4f752013-08-07 18:28:56 +02001673 return false;
Simon Wunderlich20ff9d52012-01-22 20:00:23 +01001674
1675 if (!hash)
Antonio Quartullicfd4f752013-08-07 18:28:56 +02001676 return false;
Simon Wunderlich20ff9d52012-01-22 20:00:23 +01001677
1678 for (i = 0; i < hash->size; i++) {
1679 head = &hash->table[i];
1680
1681 rcu_read_lock();
Sasha Levinb67bfe02013-02-27 17:06:00 -08001682 hlist_for_each_entry_rcu(backbone_gw, head, hash_entry) {
Antonio Quartullicfd4f752013-08-07 18:28:56 +02001683 if (batadv_compare_eth(backbone_gw->orig, orig) &&
1684 backbone_gw->vid == vid) {
Simon Wunderlich20ff9d52012-01-22 20:00:23 +01001685 rcu_read_unlock();
Antonio Quartullicfd4f752013-08-07 18:28:56 +02001686 return true;
Simon Wunderlich20ff9d52012-01-22 20:00:23 +01001687 }
1688 }
1689 rcu_read_unlock();
1690 }
1691
Antonio Quartullicfd4f752013-08-07 18:28:56 +02001692 return false;
Simon Wunderlich20ff9d52012-01-22 20:00:23 +01001693}
1694
Ben Hutchings2c530402012-07-10 10:55:09 +00001695/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +01001696 * batadv_bla_is_backbone_gw() - check if originator is a backbone gw for a VLAN
Ben Hutchings2c530402012-07-10 10:55:09 +00001697 * @skb: the frame to be checked
Simon Wunderlich23721382012-01-22 20:00:19 +01001698 * @orig_node: the orig_node of the frame
1699 * @hdr_size: maximum length of the frame
1700 *
Sven Eckelmann4b426b12016-02-22 21:02:39 +01001701 * Return: true if the orig_node is also a gateway on the soft interface,
1702 * otherwise it returns false.
Simon Wunderlich23721382012-01-22 20:00:19 +01001703 */
Sven Eckelmann4b426b12016-02-22 21:02:39 +01001704bool batadv_bla_is_backbone_gw(struct sk_buff *skb,
1705 struct batadv_orig_node *orig_node, int hdr_size)
Simon Wunderlich23721382012-01-22 20:00:19 +01001706{
Marek Lindnerbae98772012-12-25 17:03:24 +08001707 struct batadv_bla_backbone_gw *backbone_gw;
Antonio Quartullic018ad32013-06-04 12:11:39 +02001708 unsigned short vid;
Simon Wunderlich23721382012-01-22 20:00:19 +01001709
1710 if (!atomic_read(&orig_node->bat_priv->bridge_loop_avoidance))
Sven Eckelmann4b426b12016-02-22 21:02:39 +01001711 return false;
Simon Wunderlich23721382012-01-22 20:00:19 +01001712
1713 /* first, find out the vid. */
Antonio Quartulli0d125072012-02-18 11:27:34 +01001714 if (!pskb_may_pull(skb, hdr_size + ETH_HLEN))
Sven Eckelmann4b426b12016-02-22 21:02:39 +01001715 return false;
Simon Wunderlich23721382012-01-22 20:00:19 +01001716
Antonio Quartullic018ad32013-06-04 12:11:39 +02001717 vid = batadv_get_vid(skb, hdr_size);
Simon Wunderlich23721382012-01-22 20:00:19 +01001718
1719 /* see if this originator is a backbone gw for this VLAN */
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001720 backbone_gw = batadv_backbone_hash_find(orig_node->bat_priv,
1721 orig_node->orig, vid);
Simon Wunderlich23721382012-01-22 20:00:19 +01001722 if (!backbone_gw)
Sven Eckelmann4b426b12016-02-22 21:02:39 +01001723 return false;
Simon Wunderlich23721382012-01-22 20:00:19 +01001724
Sven Eckelmannc8b86c12016-01-17 11:01:15 +01001725 batadv_backbone_gw_put(backbone_gw);
Sven Eckelmann4b426b12016-02-22 21:02:39 +01001726 return true;
Simon Wunderlich23721382012-01-22 20:00:19 +01001727}
1728
Simon Wunderlich04e14be2015-11-06 10:45:19 +01001729/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +01001730 * batadv_bla_free() - free all bla structures
Simon Wunderlich04e14be2015-11-06 10:45:19 +01001731 * @bat_priv: the bat priv with all the soft interface information
1732 *
1733 * for softinterface free or module unload
1734 */
Sven Eckelmann56303d32012-06-05 22:31:31 +02001735void batadv_bla_free(struct batadv_priv *bat_priv)
Simon Wunderlich23721382012-01-22 20:00:19 +01001736{
Sven Eckelmann56303d32012-06-05 22:31:31 +02001737 struct batadv_hard_iface *primary_if;
Simon Wunderlich23721382012-01-22 20:00:19 +01001738
Sven Eckelmann807736f2012-07-15 22:26:51 +02001739 cancel_delayed_work_sync(&bat_priv->bla.work);
Sven Eckelmanne5d89252012-05-12 13:48:54 +02001740 primary_if = batadv_primary_if_get_selected(bat_priv);
Simon Wunderlich23721382012-01-22 20:00:19 +01001741
Sven Eckelmann807736f2012-07-15 22:26:51 +02001742 if (bat_priv->bla.claim_hash) {
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001743 batadv_bla_purge_claims(bat_priv, primary_if, 1);
Sven Eckelmann807736f2012-07-15 22:26:51 +02001744 batadv_hash_destroy(bat_priv->bla.claim_hash);
1745 bat_priv->bla.claim_hash = NULL;
Simon Wunderlich23721382012-01-22 20:00:19 +01001746 }
Sven Eckelmann807736f2012-07-15 22:26:51 +02001747 if (bat_priv->bla.backbone_hash) {
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001748 batadv_bla_purge_backbone_gw(bat_priv, 1);
Sven Eckelmann807736f2012-07-15 22:26:51 +02001749 batadv_hash_destroy(bat_priv->bla.backbone_hash);
1750 bat_priv->bla.backbone_hash = NULL;
Simon Wunderlich23721382012-01-22 20:00:19 +01001751 }
1752 if (primary_if)
Sven Eckelmann82047ad2016-01-17 11:01:10 +01001753 batadv_hardif_put(primary_if);
Simon Wunderlich23721382012-01-22 20:00:19 +01001754}
1755
Ben Hutchings2c530402012-07-10 10:55:09 +00001756/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +01001757 * batadv_bla_loopdetect_check() - check and handle a detected loop
Simon Wunderlichcd9c7bf2016-03-12 10:49:33 +01001758 * @bat_priv: the bat priv with all the soft interface information
1759 * @skb: the packet to check
1760 * @primary_if: interface where the request came on
1761 * @vid: the VLAN ID of the frame
1762 *
1763 * Checks if this packet is a loop detect frame which has been sent by us,
Sven Eckelmannbccb48c2020-06-01 20:13:21 +02001764 * throws an uevent and logs the event if that is the case.
Simon Wunderlichcd9c7bf2016-03-12 10:49:33 +01001765 *
1766 * Return: true if it is a loop detect frame which is to be dropped, false
1767 * otherwise.
1768 */
1769static bool
1770batadv_bla_loopdetect_check(struct batadv_priv *bat_priv, struct sk_buff *skb,
1771 struct batadv_hard_iface *primary_if,
1772 unsigned short vid)
1773{
1774 struct batadv_bla_backbone_gw *backbone_gw;
1775 struct ethhdr *ethhdr;
Marek Lindner5af96b92018-09-07 05:45:54 +08001776 bool ret;
Simon Wunderlichcd9c7bf2016-03-12 10:49:33 +01001777
1778 ethhdr = eth_hdr(skb);
1779
1780 /* Only check for the MAC address and skip more checks here for
1781 * performance reasons - this function is on the hotpath, after all.
1782 */
1783 if (!batadv_compare_eth(ethhdr->h_source,
1784 bat_priv->bla.loopdetect_addr))
1785 return false;
1786
1787 /* If the packet came too late, don't forward it on the mesh
1788 * but don't consider that as loop. It might be a coincidence.
1789 */
1790 if (batadv_has_timed_out(bat_priv->bla.loopdetect_lasttime,
1791 BATADV_BLA_LOOPDETECT_TIMEOUT))
1792 return true;
1793
1794 backbone_gw = batadv_bla_get_backbone_gw(bat_priv,
1795 primary_if->net_dev->dev_addr,
1796 vid, true);
1797 if (unlikely(!backbone_gw))
1798 return true;
1799
Marek Lindner5af96b92018-09-07 05:45:54 +08001800 ret = queue_work(batadv_event_workqueue, &backbone_gw->report_work);
1801
1802 /* backbone_gw is unreferenced in the report work function function
1803 * if queue_work() call was successful
1804 */
1805 if (!ret)
1806 batadv_backbone_gw_put(backbone_gw);
Simon Wunderlichcd9c7bf2016-03-12 10:49:33 +01001807
1808 return true;
1809}
1810
1811/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +01001812 * batadv_bla_rx() - check packets coming from the mesh.
Ben Hutchings2c530402012-07-10 10:55:09 +00001813 * @bat_priv: the bat priv with all the soft interface information
Simon Wunderlich23721382012-01-22 20:00:19 +01001814 * @skb: the frame to be checked
1815 * @vid: the VLAN ID of the frame
Simon Wunderlich2d3f6cc2012-07-04 20:38:19 +02001816 * @is_bcast: the packet came in a broadcast packet type.
Simon Wunderlich23721382012-01-22 20:00:19 +01001817 *
Simon Wunderlich04e14be2015-11-06 10:45:19 +01001818 * batadv_bla_rx avoidance checks if:
Simon Wunderlich23721382012-01-22 20:00:19 +01001819 * * we have to race for a claim
1820 * * if the frame is allowed on the LAN
1821 *
Sven Eckelmannbccb48c2020-06-01 20:13:21 +02001822 * In these cases, the skb is further handled by this function
Sven Eckelmann62fe7102015-09-15 19:00:48 +02001823 *
Sven Eckelmann4b426b12016-02-22 21:02:39 +01001824 * Return: true if handled, otherwise it returns false and the caller shall
1825 * further process the skb.
Simon Wunderlich23721382012-01-22 20:00:19 +01001826 */
Sven Eckelmann4b426b12016-02-22 21:02:39 +01001827bool batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb,
1828 unsigned short vid, bool is_bcast)
Simon Wunderlich23721382012-01-22 20:00:19 +01001829{
Sven Eckelmann3db0dec2016-07-01 15:49:43 +02001830 struct batadv_bla_backbone_gw *backbone_gw;
Simon Wunderlich23721382012-01-22 20:00:19 +01001831 struct ethhdr *ethhdr;
Marek Lindner712bbfe42012-12-25 17:03:25 +08001832 struct batadv_bla_claim search_claim, *claim = NULL;
Sven Eckelmann56303d32012-06-05 22:31:31 +02001833 struct batadv_hard_iface *primary_if;
Sven Eckelmann3db0dec2016-07-01 15:49:43 +02001834 bool own_claim;
Sven Eckelmann4b426b12016-02-22 21:02:39 +01001835 bool ret;
Simon Wunderlich23721382012-01-22 20:00:19 +01001836
Antonio Quartulli7ed4be92013-04-08 15:08:18 +02001837 ethhdr = eth_hdr(skb);
Simon Wunderlich23721382012-01-22 20:00:19 +01001838
Sven Eckelmanne5d89252012-05-12 13:48:54 +02001839 primary_if = batadv_primary_if_get_selected(bat_priv);
Simon Wunderlich23721382012-01-22 20:00:19 +01001840 if (!primary_if)
1841 goto handled;
1842
1843 if (!atomic_read(&bat_priv->bridge_loop_avoidance))
1844 goto allow;
1845
Simon Wunderlichcd9c7bf2016-03-12 10:49:33 +01001846 if (batadv_bla_loopdetect_check(bat_priv, skb, primary_if, vid))
1847 goto handled;
1848
Sven Eckelmann807736f2012-07-15 22:26:51 +02001849 if (unlikely(atomic_read(&bat_priv->bla.num_requests)))
Simon Wunderlich23721382012-01-22 20:00:19 +01001850 /* don't allow broadcasts while requests are in flight */
Simon Wunderlich2d3f6cc2012-07-04 20:38:19 +02001851 if (is_multicast_ether_addr(ethhdr->h_dest) && is_bcast)
Simon Wunderlich23721382012-01-22 20:00:19 +01001852 goto handled;
1853
Antonio Quartulli8fdd0152014-01-22 00:42:11 +01001854 ether_addr_copy(search_claim.addr, ethhdr->h_source);
Simon Wunderlich23721382012-01-22 20:00:19 +01001855 search_claim.vid = vid;
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001856 claim = batadv_claim_hash_find(bat_priv, &search_claim);
Simon Wunderlich23721382012-01-22 20:00:19 +01001857
1858 if (!claim) {
1859 /* possible optimization: race for a claim */
1860 /* No claim exists yet, claim it for us!
1861 */
Andreas Pape4dd72f72016-09-05 13:20:28 +02001862
1863 batadv_dbg(BATADV_DBG_BLA, bat_priv,
Sven Eckelmann22f05022017-05-19 13:02:00 +02001864 "%s(): Unclaimed MAC %pM found. Claim it. Local: %s\n",
1865 __func__, ethhdr->h_source,
Andreas Pape4dd72f72016-09-05 13:20:28 +02001866 batadv_is_my_client(bat_priv,
1867 ethhdr->h_source, vid) ?
1868 "yes" : "no");
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001869 batadv_handle_claim(bat_priv, primary_if,
1870 primary_if->net_dev->dev_addr,
1871 ethhdr->h_source, vid);
Simon Wunderlich23721382012-01-22 20:00:19 +01001872 goto allow;
1873 }
1874
1875 /* if it is our own claim ... */
Sven Eckelmann3db0dec2016-07-01 15:49:43 +02001876 backbone_gw = batadv_bla_claim_get_backbone_gw(claim);
1877 own_claim = batadv_compare_eth(backbone_gw->orig,
1878 primary_if->net_dev->dev_addr);
1879 batadv_backbone_gw_put(backbone_gw);
1880
1881 if (own_claim) {
Simon Wunderlich23721382012-01-22 20:00:19 +01001882 /* ... allow it in any case */
1883 claim->lasttime = jiffies;
1884 goto allow;
1885 }
1886
1887 /* if it is a broadcast ... */
Simon Wunderlich2d3f6cc2012-07-04 20:38:19 +02001888 if (is_multicast_ether_addr(ethhdr->h_dest) && is_bcast) {
1889 /* ... drop it. the responsible gateway is in charge.
1890 *
1891 * We need to check is_bcast because with the gateway
1892 * feature, broadcasts (like DHCP requests) may be sent
1893 * using a unicast packet type.
1894 */
Simon Wunderlich23721382012-01-22 20:00:19 +01001895 goto handled;
1896 } else {
1897 /* seems the client considers us as its best gateway.
1898 * send a claim and update the claim table
1899 * immediately.
1900 */
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001901 batadv_handle_claim(bat_priv, primary_if,
1902 primary_if->net_dev->dev_addr,
1903 ethhdr->h_source, vid);
Simon Wunderlich23721382012-01-22 20:00:19 +01001904 goto allow;
1905 }
1906allow:
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001907 batadv_bla_update_own_backbone_gw(bat_priv, primary_if, vid);
Sven Eckelmann4b426b12016-02-22 21:02:39 +01001908 ret = false;
Simon Wunderlich23721382012-01-22 20:00:19 +01001909 goto out;
1910
1911handled:
1912 kfree_skb(skb);
Sven Eckelmann4b426b12016-02-22 21:02:39 +01001913 ret = true;
Simon Wunderlich23721382012-01-22 20:00:19 +01001914
1915out:
1916 if (primary_if)
Sven Eckelmann82047ad2016-01-17 11:01:10 +01001917 batadv_hardif_put(primary_if);
Simon Wunderlich23721382012-01-22 20:00:19 +01001918 if (claim)
Sven Eckelmann321e3e02016-01-17 11:01:16 +01001919 batadv_claim_put(claim);
Simon Wunderlich23721382012-01-22 20:00:19 +01001920 return ret;
1921}
1922
Ben Hutchings2c530402012-07-10 10:55:09 +00001923/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +01001924 * batadv_bla_tx() - check packets going into the mesh
Ben Hutchings2c530402012-07-10 10:55:09 +00001925 * @bat_priv: the bat priv with all the soft interface information
Simon Wunderlich23721382012-01-22 20:00:19 +01001926 * @skb: the frame to be checked
1927 * @vid: the VLAN ID of the frame
1928 *
Simon Wunderlich04e14be2015-11-06 10:45:19 +01001929 * batadv_bla_tx checks if:
Simon Wunderlich23721382012-01-22 20:00:19 +01001930 * * a claim was received which has to be processed
1931 * * the frame is allowed on the mesh
1932 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +02001933 * in these cases, the skb is further handled by this function.
Linus Lüssing9d2c9482013-08-06 20:21:15 +02001934 *
1935 * This call might reallocate skb data.
Sven Eckelmann62fe7102015-09-15 19:00:48 +02001936 *
Sven Eckelmann4b426b12016-02-22 21:02:39 +01001937 * Return: true if handled, otherwise it returns false and the caller shall
1938 * further process the skb.
Simon Wunderlich23721382012-01-22 20:00:19 +01001939 */
Sven Eckelmann4b426b12016-02-22 21:02:39 +01001940bool batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb,
1941 unsigned short vid)
Simon Wunderlich23721382012-01-22 20:00:19 +01001942{
1943 struct ethhdr *ethhdr;
Marek Lindner712bbfe42012-12-25 17:03:25 +08001944 struct batadv_bla_claim search_claim, *claim = NULL;
Sven Eckelmann3db0dec2016-07-01 15:49:43 +02001945 struct batadv_bla_backbone_gw *backbone_gw;
Sven Eckelmann56303d32012-06-05 22:31:31 +02001946 struct batadv_hard_iface *primary_if;
Sven Eckelmann3db0dec2016-07-01 15:49:43 +02001947 bool client_roamed;
Sven Eckelmann4b426b12016-02-22 21:02:39 +01001948 bool ret = false;
Simon Wunderlich23721382012-01-22 20:00:19 +01001949
Sven Eckelmanne5d89252012-05-12 13:48:54 +02001950 primary_if = batadv_primary_if_get_selected(bat_priv);
Simon Wunderlich23721382012-01-22 20:00:19 +01001951 if (!primary_if)
1952 goto out;
1953
1954 if (!atomic_read(&bat_priv->bridge_loop_avoidance))
1955 goto allow;
1956
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001957 if (batadv_bla_process_claim(bat_priv, primary_if, skb))
Simon Wunderlich23721382012-01-22 20:00:19 +01001958 goto handled;
1959
Antonio Quartulli7ed4be92013-04-08 15:08:18 +02001960 ethhdr = eth_hdr(skb);
Simon Wunderlich23721382012-01-22 20:00:19 +01001961
Sven Eckelmann807736f2012-07-15 22:26:51 +02001962 if (unlikely(atomic_read(&bat_priv->bla.num_requests)))
Simon Wunderlich23721382012-01-22 20:00:19 +01001963 /* don't allow broadcasts while requests are in flight */
1964 if (is_multicast_ether_addr(ethhdr->h_dest))
1965 goto handled;
1966
Antonio Quartulli8fdd0152014-01-22 00:42:11 +01001967 ether_addr_copy(search_claim.addr, ethhdr->h_source);
Simon Wunderlich23721382012-01-22 20:00:19 +01001968 search_claim.vid = vid;
1969
Sven Eckelmann3b300de2012-05-12 18:33:53 +02001970 claim = batadv_claim_hash_find(bat_priv, &search_claim);
Simon Wunderlich23721382012-01-22 20:00:19 +01001971
1972 /* if no claim exists, allow it. */
1973 if (!claim)
1974 goto allow;
1975
1976 /* check if we are responsible. */
Sven Eckelmann3db0dec2016-07-01 15:49:43 +02001977 backbone_gw = batadv_bla_claim_get_backbone_gw(claim);
1978 client_roamed = batadv_compare_eth(backbone_gw->orig,
1979 primary_if->net_dev->dev_addr);
1980 batadv_backbone_gw_put(backbone_gw);
1981
1982 if (client_roamed) {
Simon Wunderlich23721382012-01-22 20:00:19 +01001983 /* if yes, the client has roamed and we have
1984 * to unclaim it.
1985 */
Andreas Papea3a51292016-09-05 13:20:29 +02001986 if (batadv_has_timed_out(claim->lasttime, 100)) {
1987 /* only unclaim if the last claim entry is
1988 * older than 100 ms to make sure we really
1989 * have a roaming client here.
1990 */
Sven Eckelmann22f05022017-05-19 13:02:00 +02001991 batadv_dbg(BATADV_DBG_BLA, bat_priv, "%s(): Roaming client %pM detected. Unclaim it.\n",
1992 __func__, ethhdr->h_source);
Andreas Papea3a51292016-09-05 13:20:29 +02001993 batadv_handle_unclaim(bat_priv, primary_if,
1994 primary_if->net_dev->dev_addr,
1995 ethhdr->h_source, vid);
1996 goto allow;
1997 } else {
Sven Eckelmann22f05022017-05-19 13:02:00 +02001998 batadv_dbg(BATADV_DBG_BLA, bat_priv, "%s(): Race for claim %pM detected. Drop packet.\n",
1999 __func__, ethhdr->h_source);
Andreas Papea3a51292016-09-05 13:20:29 +02002000 goto handled;
2001 }
Simon Wunderlich23721382012-01-22 20:00:19 +01002002 }
2003
2004 /* check if it is a multicast/broadcast frame */
2005 if (is_multicast_ether_addr(ethhdr->h_dest)) {
2006 /* drop it. the responsible gateway has forwarded it into
2007 * the backbone network.
2008 */
2009 goto handled;
2010 } else {
2011 /* we must allow it. at least if we are
2012 * responsible for the DESTINATION.
2013 */
2014 goto allow;
2015 }
2016allow:
Sven Eckelmann3b300de2012-05-12 18:33:53 +02002017 batadv_bla_update_own_backbone_gw(bat_priv, primary_if, vid);
Sven Eckelmann4b426b12016-02-22 21:02:39 +01002018 ret = false;
Simon Wunderlich23721382012-01-22 20:00:19 +01002019 goto out;
2020handled:
Sven Eckelmann4b426b12016-02-22 21:02:39 +01002021 ret = true;
Simon Wunderlich23721382012-01-22 20:00:19 +01002022out:
2023 if (primary_if)
Sven Eckelmann82047ad2016-01-17 11:01:10 +01002024 batadv_hardif_put(primary_if);
Simon Wunderlich23721382012-01-22 20:00:19 +01002025 if (claim)
Sven Eckelmann321e3e02016-01-17 11:01:16 +01002026 batadv_claim_put(claim);
Simon Wunderlich23721382012-01-22 20:00:19 +01002027 return ret;
2028}
Simon Wunderlich9bf8e4d2012-01-22 20:00:21 +01002029
Sven Eckelmanndc1cbd12016-07-16 09:31:20 +02002030#ifdef CONFIG_BATMAN_ADV_DEBUGFS
Simon Wunderlich04e14be2015-11-06 10:45:19 +01002031/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +01002032 * batadv_bla_claim_table_seq_print_text() - print the claim table in a seq file
Simon Wunderlich04e14be2015-11-06 10:45:19 +01002033 * @seq: seq file to print on
2034 * @offset: not used
2035 *
2036 * Return: always 0
2037 */
Sven Eckelmann08adf152012-05-12 13:38:47 +02002038int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset)
Simon Wunderlich9bf8e4d2012-01-22 20:00:21 +01002039{
2040 struct net_device *net_dev = (struct net_device *)seq->private;
Sven Eckelmann56303d32012-06-05 22:31:31 +02002041 struct batadv_priv *bat_priv = netdev_priv(net_dev);
Sven Eckelmann807736f2012-07-15 22:26:51 +02002042 struct batadv_hashtable *hash = bat_priv->bla.claim_hash;
Sven Eckelmann3db0dec2016-07-01 15:49:43 +02002043 struct batadv_bla_backbone_gw *backbone_gw;
Marek Lindner712bbfe42012-12-25 17:03:25 +08002044 struct batadv_bla_claim *claim;
Sven Eckelmann56303d32012-06-05 22:31:31 +02002045 struct batadv_hard_iface *primary_if;
Simon Wunderlich9bf8e4d2012-01-22 20:00:21 +01002046 struct hlist_head *head;
Simon Wunderlich5a1dd8a2015-09-11 18:04:13 +02002047 u16 backbone_crc;
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02002048 u32 i;
Simon Wunderlich9bf8e4d2012-01-22 20:00:21 +01002049 bool is_own;
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02002050 u8 *primary_addr;
Simon Wunderlich9bf8e4d2012-01-22 20:00:21 +01002051
Marek Lindner30da63a2012-08-03 17:15:46 +02002052 primary_if = batadv_seq_print_text_primary_if_get(seq);
2053 if (!primary_if)
Simon Wunderlich9bf8e4d2012-01-22 20:00:21 +01002054 goto out;
Simon Wunderlich9bf8e4d2012-01-22 20:00:21 +01002055
Sven Eckelmann1eda58b2012-05-12 13:48:58 +02002056 primary_addr = primary_if->net_dev->dev_addr;
Simon Wunderlich38ef3d12012-01-22 20:00:26 +01002057 seq_printf(seq,
Antonio Quartulli39a32992012-11-19 09:01:43 +01002058 "Claims announced for the mesh %s (orig %pM, group id %#.4x)\n",
Sven Eckelmann1eda58b2012-05-12 13:48:58 +02002059 net_dev->name, primary_addr,
Sven Eckelmann807736f2012-07-15 22:26:51 +02002060 ntohs(bat_priv->bla.claim_dest.group));
Antonio Quartulli925a6f32016-03-12 10:30:18 +01002061 seq_puts(seq,
2062 " Client VID Originator [o] (CRC )\n");
Simon Wunderlich9bf8e4d2012-01-22 20:00:21 +01002063 for (i = 0; i < hash->size; i++) {
2064 head = &hash->table[i];
2065
2066 rcu_read_lock();
Sasha Levinb67bfe02013-02-27 17:06:00 -08002067 hlist_for_each_entry_rcu(claim, head, hash_entry) {
Sven Eckelmann3db0dec2016-07-01 15:49:43 +02002068 backbone_gw = batadv_bla_claim_get_backbone_gw(claim);
2069
2070 is_own = batadv_compare_eth(backbone_gw->orig,
Sven Eckelmann1eda58b2012-05-12 13:48:58 +02002071 primary_addr);
Simon Wunderlich5a1dd8a2015-09-11 18:04:13 +02002072
Sven Eckelmann3db0dec2016-07-01 15:49:43 +02002073 spin_lock_bh(&backbone_gw->crc_lock);
2074 backbone_crc = backbone_gw->crc;
2075 spin_unlock_bh(&backbone_gw->crc_lock);
Antonio Quartullieb2deb62013-04-19 18:07:00 +02002076 seq_printf(seq, " * %pM on %5d by %pM [%c] (%#.4x)\n",
Sven Eckelmannf7a2bd62017-02-22 17:16:42 +01002077 claim->addr, batadv_print_vid(claim->vid),
Sven Eckelmann3db0dec2016-07-01 15:49:43 +02002078 backbone_gw->orig,
Simon Wunderlich9bf8e4d2012-01-22 20:00:21 +01002079 (is_own ? 'x' : ' '),
Simon Wunderlich5a1dd8a2015-09-11 18:04:13 +02002080 backbone_crc);
Sven Eckelmann3db0dec2016-07-01 15:49:43 +02002081
2082 batadv_backbone_gw_put(backbone_gw);
Simon Wunderlich9bf8e4d2012-01-22 20:00:21 +01002083 }
2084 rcu_read_unlock();
2085 }
2086out:
2087 if (primary_if)
Sven Eckelmann82047ad2016-01-17 11:01:10 +01002088 batadv_hardif_put(primary_if);
Marek Lindner30da63a2012-08-03 17:15:46 +02002089 return 0;
Simon Wunderlich9bf8e4d2012-01-22 20:00:21 +01002090}
Sven Eckelmanndc1cbd12016-07-16 09:31:20 +02002091#endif
Simon Wunderlich536a23f2012-06-18 18:39:26 +02002092
Simon Wunderlich04e14be2015-11-06 10:45:19 +01002093/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +01002094 * batadv_bla_claim_dump_entry() - dump one entry of the claim table
Andrew Lunn04f3f5b2016-07-03 13:31:45 +02002095 * to a netlink socket
2096 * @msg: buffer for the message
2097 * @portid: netlink port
Sven Eckelmann24d71b92018-10-30 22:01:27 +01002098 * @cb: Control block containing additional options
Andrew Lunn04f3f5b2016-07-03 13:31:45 +02002099 * @primary_if: primary interface
2100 * @claim: entry to dump
2101 *
2102 * Return: 0 or error code.
2103 */
2104static int
Sven Eckelmann24d71b92018-10-30 22:01:27 +01002105batadv_bla_claim_dump_entry(struct sk_buff *msg, u32 portid,
2106 struct netlink_callback *cb,
Andrew Lunn04f3f5b2016-07-03 13:31:45 +02002107 struct batadv_hard_iface *primary_if,
2108 struct batadv_bla_claim *claim)
2109{
2110 u8 *primary_addr = primary_if->net_dev->dev_addr;
2111 u16 backbone_crc;
2112 bool is_own;
2113 void *hdr;
2114 int ret = -EINVAL;
2115
Sven Eckelmann24d71b92018-10-30 22:01:27 +01002116 hdr = genlmsg_put(msg, portid, cb->nlh->nlmsg_seq,
2117 &batadv_netlink_family, NLM_F_MULTI,
2118 BATADV_CMD_GET_BLA_CLAIM);
Andrew Lunn04f3f5b2016-07-03 13:31:45 +02002119 if (!hdr) {
2120 ret = -ENOBUFS;
2121 goto out;
2122 }
2123
Sven Eckelmann24d71b92018-10-30 22:01:27 +01002124 genl_dump_check_consistent(cb, hdr);
2125
Andrew Lunn04f3f5b2016-07-03 13:31:45 +02002126 is_own = batadv_compare_eth(claim->backbone_gw->orig,
2127 primary_addr);
2128
2129 spin_lock_bh(&claim->backbone_gw->crc_lock);
2130 backbone_crc = claim->backbone_gw->crc;
2131 spin_unlock_bh(&claim->backbone_gw->crc_lock);
2132
2133 if (is_own)
2134 if (nla_put_flag(msg, BATADV_ATTR_BLA_OWN)) {
2135 genlmsg_cancel(msg, hdr);
2136 goto out;
2137 }
2138
2139 if (nla_put(msg, BATADV_ATTR_BLA_ADDRESS, ETH_ALEN, claim->addr) ||
2140 nla_put_u16(msg, BATADV_ATTR_BLA_VID, claim->vid) ||
2141 nla_put(msg, BATADV_ATTR_BLA_BACKBONE, ETH_ALEN,
2142 claim->backbone_gw->orig) ||
2143 nla_put_u16(msg, BATADV_ATTR_BLA_CRC,
2144 backbone_crc)) {
2145 genlmsg_cancel(msg, hdr);
2146 goto out;
2147 }
2148
2149 genlmsg_end(msg, hdr);
2150 ret = 0;
2151
2152out:
2153 return ret;
2154}
2155
2156/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +01002157 * batadv_bla_claim_dump_bucket() - dump one bucket of the claim table
Andrew Lunn04f3f5b2016-07-03 13:31:45 +02002158 * to a netlink socket
2159 * @msg: buffer for the message
2160 * @portid: netlink port
Sven Eckelmann24d71b92018-10-30 22:01:27 +01002161 * @cb: Control block containing additional options
Andrew Lunn04f3f5b2016-07-03 13:31:45 +02002162 * @primary_if: primary interface
Sven Eckelmann24d71b92018-10-30 22:01:27 +01002163 * @hash: hash to dump
2164 * @bucket: bucket index to dump
Andrew Lunn04f3f5b2016-07-03 13:31:45 +02002165 * @idx_skip: How many entries to skip
2166 *
2167 * Return: always 0.
2168 */
2169static int
Sven Eckelmann24d71b92018-10-30 22:01:27 +01002170batadv_bla_claim_dump_bucket(struct sk_buff *msg, u32 portid,
2171 struct netlink_callback *cb,
Andrew Lunn04f3f5b2016-07-03 13:31:45 +02002172 struct batadv_hard_iface *primary_if,
Sven Eckelmann24d71b92018-10-30 22:01:27 +01002173 struct batadv_hashtable *hash, unsigned int bucket,
2174 int *idx_skip)
Andrew Lunn04f3f5b2016-07-03 13:31:45 +02002175{
2176 struct batadv_bla_claim *claim;
2177 int idx = 0;
Sven Eckelmannb0264ec2018-02-24 12:03:36 +01002178 int ret = 0;
Andrew Lunn04f3f5b2016-07-03 13:31:45 +02002179
Sven Eckelmann24d71b92018-10-30 22:01:27 +01002180 spin_lock_bh(&hash->list_locks[bucket]);
2181 cb->seq = atomic_read(&hash->generation) << 1 | 1;
2182
2183 hlist_for_each_entry(claim, &hash->table[bucket], hash_entry) {
Andrew Lunn04f3f5b2016-07-03 13:31:45 +02002184 if (idx++ < *idx_skip)
2185 continue;
Sven Eckelmannb0264ec2018-02-24 12:03:36 +01002186
Sven Eckelmann24d71b92018-10-30 22:01:27 +01002187 ret = batadv_bla_claim_dump_entry(msg, portid, cb,
Sven Eckelmannb0264ec2018-02-24 12:03:36 +01002188 primary_if, claim);
2189 if (ret) {
Andrew Lunn04f3f5b2016-07-03 13:31:45 +02002190 *idx_skip = idx - 1;
2191 goto unlock;
2192 }
2193 }
2194
Sven Eckelmannb0264ec2018-02-24 12:03:36 +01002195 *idx_skip = 0;
Andrew Lunn04f3f5b2016-07-03 13:31:45 +02002196unlock:
Sven Eckelmann24d71b92018-10-30 22:01:27 +01002197 spin_unlock_bh(&hash->list_locks[bucket]);
Sven Eckelmannb0264ec2018-02-24 12:03:36 +01002198 return ret;
Andrew Lunn04f3f5b2016-07-03 13:31:45 +02002199}
2200
2201/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +01002202 * batadv_bla_claim_dump() - dump claim table to a netlink socket
Andrew Lunn04f3f5b2016-07-03 13:31:45 +02002203 * @msg: buffer for the message
2204 * @cb: callback structure containing arguments
2205 *
2206 * Return: message length.
2207 */
2208int batadv_bla_claim_dump(struct sk_buff *msg, struct netlink_callback *cb)
2209{
2210 struct batadv_hard_iface *primary_if = NULL;
2211 int portid = NETLINK_CB(cb->skb).portid;
2212 struct net *net = sock_net(cb->skb->sk);
2213 struct net_device *soft_iface;
2214 struct batadv_hashtable *hash;
2215 struct batadv_priv *bat_priv;
2216 int bucket = cb->args[0];
Andrew Lunn04f3f5b2016-07-03 13:31:45 +02002217 int idx = cb->args[1];
2218 int ifindex;
2219 int ret = 0;
2220
2221 ifindex = batadv_netlink_get_ifindex(cb->nlh,
2222 BATADV_ATTR_MESH_IFINDEX);
2223 if (!ifindex)
2224 return -EINVAL;
2225
2226 soft_iface = dev_get_by_index(net, ifindex);
2227 if (!soft_iface || !batadv_softif_is_valid(soft_iface)) {
2228 ret = -ENODEV;
2229 goto out;
2230 }
2231
2232 bat_priv = netdev_priv(soft_iface);
2233 hash = bat_priv->bla.claim_hash;
2234
2235 primary_if = batadv_primary_if_get_selected(bat_priv);
2236 if (!primary_if || primary_if->if_status != BATADV_IF_ACTIVE) {
2237 ret = -ENOENT;
2238 goto out;
2239 }
2240
2241 while (bucket < hash->size) {
Sven Eckelmann24d71b92018-10-30 22:01:27 +01002242 if (batadv_bla_claim_dump_bucket(msg, portid, cb, primary_if,
2243 hash, bucket, &idx))
Andrew Lunn04f3f5b2016-07-03 13:31:45 +02002244 break;
2245 bucket++;
2246 }
2247
2248 cb->args[0] = bucket;
2249 cb->args[1] = idx;
2250
2251 ret = msg->len;
2252
2253out:
2254 if (primary_if)
2255 batadv_hardif_put(primary_if);
2256
2257 if (soft_iface)
2258 dev_put(soft_iface);
2259
2260 return ret;
2261}
2262
Sven Eckelmanndc1cbd12016-07-16 09:31:20 +02002263#ifdef CONFIG_BATMAN_ADV_DEBUGFS
Andrew Lunn04f3f5b2016-07-03 13:31:45 +02002264/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +01002265 * batadv_bla_backbone_table_seq_print_text() - print the backbone table in a
2266 * seq file
Simon Wunderlich04e14be2015-11-06 10:45:19 +01002267 * @seq: seq file to print on
2268 * @offset: not used
2269 *
2270 * Return: always 0
2271 */
Simon Wunderlich536a23f2012-06-18 18:39:26 +02002272int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, void *offset)
2273{
2274 struct net_device *net_dev = (struct net_device *)seq->private;
2275 struct batadv_priv *bat_priv = netdev_priv(net_dev);
Sven Eckelmann807736f2012-07-15 22:26:51 +02002276 struct batadv_hashtable *hash = bat_priv->bla.backbone_hash;
Marek Lindnerbae98772012-12-25 17:03:24 +08002277 struct batadv_bla_backbone_gw *backbone_gw;
Simon Wunderlich536a23f2012-06-18 18:39:26 +02002278 struct batadv_hard_iface *primary_if;
Simon Wunderlich536a23f2012-06-18 18:39:26 +02002279 struct hlist_head *head;
2280 int secs, msecs;
Simon Wunderlich5a1dd8a2015-09-11 18:04:13 +02002281 u16 backbone_crc;
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02002282 u32 i;
Simon Wunderlich536a23f2012-06-18 18:39:26 +02002283 bool is_own;
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02002284 u8 *primary_addr;
Simon Wunderlich536a23f2012-06-18 18:39:26 +02002285
Marek Lindner30da63a2012-08-03 17:15:46 +02002286 primary_if = batadv_seq_print_text_primary_if_get(seq);
2287 if (!primary_if)
Simon Wunderlich536a23f2012-06-18 18:39:26 +02002288 goto out;
Simon Wunderlich536a23f2012-06-18 18:39:26 +02002289
2290 primary_addr = primary_if->net_dev->dev_addr;
2291 seq_printf(seq,
Antonio Quartulli39a32992012-11-19 09:01:43 +01002292 "Backbones announced for the mesh %s (orig %pM, group id %#.4x)\n",
Simon Wunderlich536a23f2012-06-18 18:39:26 +02002293 net_dev->name, primary_addr,
Sven Eckelmann807736f2012-07-15 22:26:51 +02002294 ntohs(bat_priv->bla.claim_dest.group));
Antonio Quartulli925a6f32016-03-12 10:30:18 +01002295 seq_puts(seq, " Originator VID last seen (CRC )\n");
Simon Wunderlich536a23f2012-06-18 18:39:26 +02002296 for (i = 0; i < hash->size; i++) {
2297 head = &hash->table[i];
2298
2299 rcu_read_lock();
Sasha Levinb67bfe02013-02-27 17:06:00 -08002300 hlist_for_each_entry_rcu(backbone_gw, head, hash_entry) {
Simon Wunderlich536a23f2012-06-18 18:39:26 +02002301 msecs = jiffies_to_msecs(jiffies -
2302 backbone_gw->lasttime);
2303 secs = msecs / 1000;
2304 msecs = msecs % 1000;
2305
2306 is_own = batadv_compare_eth(backbone_gw->orig,
2307 primary_addr);
2308 if (is_own)
2309 continue;
2310
Simon Wunderlich5a1dd8a2015-09-11 18:04:13 +02002311 spin_lock_bh(&backbone_gw->crc_lock);
2312 backbone_crc = backbone_gw->crc;
2313 spin_unlock_bh(&backbone_gw->crc_lock);
2314
Antonio Quartullieb2deb62013-04-19 18:07:00 +02002315 seq_printf(seq, " * %pM on %5d %4i.%03is (%#.4x)\n",
Antonio Quartulli5f80df62013-04-19 18:07:01 +02002316 backbone_gw->orig,
Sven Eckelmannf7a2bd62017-02-22 17:16:42 +01002317 batadv_print_vid(backbone_gw->vid), secs,
Simon Wunderlich5a1dd8a2015-09-11 18:04:13 +02002318 msecs, backbone_crc);
Simon Wunderlich536a23f2012-06-18 18:39:26 +02002319 }
2320 rcu_read_unlock();
2321 }
2322out:
2323 if (primary_if)
Sven Eckelmann82047ad2016-01-17 11:01:10 +01002324 batadv_hardif_put(primary_if);
Marek Lindner30da63a2012-08-03 17:15:46 +02002325 return 0;
Simon Wunderlich536a23f2012-06-18 18:39:26 +02002326}
Sven Eckelmanndc1cbd12016-07-16 09:31:20 +02002327#endif
Simon Wunderlichea4152e2016-07-03 13:31:47 +02002328
2329/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +01002330 * batadv_bla_backbone_dump_entry() - dump one entry of the backbone table to a
2331 * netlink socket
Simon Wunderlichea4152e2016-07-03 13:31:47 +02002332 * @msg: buffer for the message
2333 * @portid: netlink port
Sven Eckelmannb00d0e62018-10-30 22:01:26 +01002334 * @cb: Control block containing additional options
Simon Wunderlichea4152e2016-07-03 13:31:47 +02002335 * @primary_if: primary interface
2336 * @backbone_gw: entry to dump
2337 *
2338 * Return: 0 or error code.
2339 */
2340static int
Sven Eckelmannb00d0e62018-10-30 22:01:26 +01002341batadv_bla_backbone_dump_entry(struct sk_buff *msg, u32 portid,
2342 struct netlink_callback *cb,
Simon Wunderlichea4152e2016-07-03 13:31:47 +02002343 struct batadv_hard_iface *primary_if,
2344 struct batadv_bla_backbone_gw *backbone_gw)
2345{
2346 u8 *primary_addr = primary_if->net_dev->dev_addr;
2347 u16 backbone_crc;
2348 bool is_own;
2349 int msecs;
2350 void *hdr;
2351 int ret = -EINVAL;
2352
Sven Eckelmannb00d0e62018-10-30 22:01:26 +01002353 hdr = genlmsg_put(msg, portid, cb->nlh->nlmsg_seq,
2354 &batadv_netlink_family, NLM_F_MULTI,
2355 BATADV_CMD_GET_BLA_BACKBONE);
Simon Wunderlichea4152e2016-07-03 13:31:47 +02002356 if (!hdr) {
2357 ret = -ENOBUFS;
2358 goto out;
2359 }
2360
Sven Eckelmannb00d0e62018-10-30 22:01:26 +01002361 genl_dump_check_consistent(cb, hdr);
2362
Simon Wunderlichea4152e2016-07-03 13:31:47 +02002363 is_own = batadv_compare_eth(backbone_gw->orig, primary_addr);
2364
2365 spin_lock_bh(&backbone_gw->crc_lock);
2366 backbone_crc = backbone_gw->crc;
2367 spin_unlock_bh(&backbone_gw->crc_lock);
2368
2369 msecs = jiffies_to_msecs(jiffies - backbone_gw->lasttime);
2370
2371 if (is_own)
2372 if (nla_put_flag(msg, BATADV_ATTR_BLA_OWN)) {
2373 genlmsg_cancel(msg, hdr);
2374 goto out;
2375 }
2376
2377 if (nla_put(msg, BATADV_ATTR_BLA_BACKBONE, ETH_ALEN,
2378 backbone_gw->orig) ||
2379 nla_put_u16(msg, BATADV_ATTR_BLA_VID, backbone_gw->vid) ||
2380 nla_put_u16(msg, BATADV_ATTR_BLA_CRC,
2381 backbone_crc) ||
2382 nla_put_u32(msg, BATADV_ATTR_LAST_SEEN_MSECS, msecs)) {
2383 genlmsg_cancel(msg, hdr);
2384 goto out;
2385 }
2386
2387 genlmsg_end(msg, hdr);
2388 ret = 0;
2389
2390out:
2391 return ret;
2392}
2393
2394/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +01002395 * batadv_bla_backbone_dump_bucket() - dump one bucket of the backbone table to
2396 * a netlink socket
Simon Wunderlichea4152e2016-07-03 13:31:47 +02002397 * @msg: buffer for the message
2398 * @portid: netlink port
Sven Eckelmannb00d0e62018-10-30 22:01:26 +01002399 * @cb: Control block containing additional options
Simon Wunderlichea4152e2016-07-03 13:31:47 +02002400 * @primary_if: primary interface
Sven Eckelmannb00d0e62018-10-30 22:01:26 +01002401 * @hash: hash to dump
2402 * @bucket: bucket index to dump
Simon Wunderlichea4152e2016-07-03 13:31:47 +02002403 * @idx_skip: How many entries to skip
2404 *
2405 * Return: always 0.
2406 */
2407static int
Sven Eckelmannb00d0e62018-10-30 22:01:26 +01002408batadv_bla_backbone_dump_bucket(struct sk_buff *msg, u32 portid,
2409 struct netlink_callback *cb,
Simon Wunderlichea4152e2016-07-03 13:31:47 +02002410 struct batadv_hard_iface *primary_if,
Sven Eckelmannb00d0e62018-10-30 22:01:26 +01002411 struct batadv_hashtable *hash,
2412 unsigned int bucket, int *idx_skip)
Simon Wunderlichea4152e2016-07-03 13:31:47 +02002413{
2414 struct batadv_bla_backbone_gw *backbone_gw;
2415 int idx = 0;
Sven Eckelmannfce672d2018-02-24 12:03:37 +01002416 int ret = 0;
Simon Wunderlichea4152e2016-07-03 13:31:47 +02002417
Sven Eckelmannb00d0e62018-10-30 22:01:26 +01002418 spin_lock_bh(&hash->list_locks[bucket]);
2419 cb->seq = atomic_read(&hash->generation) << 1 | 1;
2420
2421 hlist_for_each_entry(backbone_gw, &hash->table[bucket], hash_entry) {
Simon Wunderlichea4152e2016-07-03 13:31:47 +02002422 if (idx++ < *idx_skip)
2423 continue;
Sven Eckelmannfce672d2018-02-24 12:03:37 +01002424
Sven Eckelmannb00d0e62018-10-30 22:01:26 +01002425 ret = batadv_bla_backbone_dump_entry(msg, portid, cb,
Sven Eckelmannfce672d2018-02-24 12:03:37 +01002426 primary_if, backbone_gw);
2427 if (ret) {
Simon Wunderlichea4152e2016-07-03 13:31:47 +02002428 *idx_skip = idx - 1;
2429 goto unlock;
2430 }
2431 }
2432
Sven Eckelmannfce672d2018-02-24 12:03:37 +01002433 *idx_skip = 0;
Simon Wunderlichea4152e2016-07-03 13:31:47 +02002434unlock:
Sven Eckelmannb00d0e62018-10-30 22:01:26 +01002435 spin_unlock_bh(&hash->list_locks[bucket]);
Sven Eckelmannfce672d2018-02-24 12:03:37 +01002436 return ret;
Simon Wunderlichea4152e2016-07-03 13:31:47 +02002437}
2438
2439/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +01002440 * batadv_bla_backbone_dump() - dump backbone table to a netlink socket
Simon Wunderlichea4152e2016-07-03 13:31:47 +02002441 * @msg: buffer for the message
2442 * @cb: callback structure containing arguments
2443 *
2444 * Return: message length.
2445 */
2446int batadv_bla_backbone_dump(struct sk_buff *msg, struct netlink_callback *cb)
2447{
2448 struct batadv_hard_iface *primary_if = NULL;
2449 int portid = NETLINK_CB(cb->skb).portid;
2450 struct net *net = sock_net(cb->skb->sk);
2451 struct net_device *soft_iface;
2452 struct batadv_hashtable *hash;
2453 struct batadv_priv *bat_priv;
2454 int bucket = cb->args[0];
Simon Wunderlichea4152e2016-07-03 13:31:47 +02002455 int idx = cb->args[1];
2456 int ifindex;
2457 int ret = 0;
2458
2459 ifindex = batadv_netlink_get_ifindex(cb->nlh,
2460 BATADV_ATTR_MESH_IFINDEX);
2461 if (!ifindex)
2462 return -EINVAL;
2463
2464 soft_iface = dev_get_by_index(net, ifindex);
2465 if (!soft_iface || !batadv_softif_is_valid(soft_iface)) {
2466 ret = -ENODEV;
2467 goto out;
2468 }
2469
2470 bat_priv = netdev_priv(soft_iface);
2471 hash = bat_priv->bla.backbone_hash;
2472
2473 primary_if = batadv_primary_if_get_selected(bat_priv);
2474 if (!primary_if || primary_if->if_status != BATADV_IF_ACTIVE) {
2475 ret = -ENOENT;
2476 goto out;
2477 }
2478
2479 while (bucket < hash->size) {
Sven Eckelmannb00d0e62018-10-30 22:01:26 +01002480 if (batadv_bla_backbone_dump_bucket(msg, portid, cb, primary_if,
2481 hash, bucket, &idx))
Simon Wunderlichea4152e2016-07-03 13:31:47 +02002482 break;
2483 bucket++;
2484 }
2485
2486 cb->args[0] = bucket;
2487 cb->args[1] = idx;
2488
2489 ret = msg->len;
2490
2491out:
2492 if (primary_if)
2493 batadv_hardif_put(primary_if);
2494
2495 if (soft_iface)
2496 dev_put(soft_iface);
2497
2498 return ret;
2499}
Andreas Pape00311de2016-09-05 13:20:25 +02002500
2501#ifdef CONFIG_BATMAN_ADV_DAT
2502/**
Sven Eckelmann7e9a8c22017-12-02 19:51:47 +01002503 * batadv_bla_check_claim() - check if address is claimed
Andreas Pape00311de2016-09-05 13:20:25 +02002504 *
2505 * @bat_priv: the bat priv with all the soft interface information
2506 * @addr: mac address of which the claim status is checked
2507 * @vid: the VLAN ID
2508 *
2509 * addr is checked if this address is claimed by the local device itself.
2510 *
2511 * Return: true if bla is disabled or the mac is claimed by the device,
2512 * false if the device addr is already claimed by another gateway
2513 */
2514bool batadv_bla_check_claim(struct batadv_priv *bat_priv,
2515 u8 *addr, unsigned short vid)
2516{
2517 struct batadv_bla_claim search_claim;
2518 struct batadv_bla_claim *claim = NULL;
2519 struct batadv_hard_iface *primary_if = NULL;
2520 bool ret = true;
2521
2522 if (!atomic_read(&bat_priv->bridge_loop_avoidance))
2523 return ret;
2524
2525 primary_if = batadv_primary_if_get_selected(bat_priv);
2526 if (!primary_if)
2527 return ret;
2528
2529 /* First look if the mac address is claimed */
2530 ether_addr_copy(search_claim.addr, addr);
2531 search_claim.vid = vid;
2532
2533 claim = batadv_claim_hash_find(bat_priv, &search_claim);
2534
2535 /* If there is a claim and we are not owner of the claim,
2536 * return false.
2537 */
2538 if (claim) {
2539 if (!batadv_compare_eth(claim->backbone_gw->orig,
2540 primary_if->net_dev->dev_addr))
2541 ret = false;
2542 batadv_claim_put(claim);
2543 }
2544
2545 batadv_hardif_put(primary_if);
2546 return ret;
2547}
2548#endif