1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (C) B.A.T.M.A.N. contributors:
3 *
4 * Marek Lindner, Simon Wunderlich, Antonio Quartulli
5 */
6
7 #include "translation-table.h"
8 #include "main.h"
9
10 #include <linux/atomic.h>
11 #include <linux/bitops.h>
12 #include <linux/bug.h>
13 #include <linux/build_bug.h>
14 #include <linux/byteorder/generic.h>
15 #include <linux/cache.h>
16 #include <linux/compiler.h>
17 #include <linux/container_of.h>
18 #include <linux/crc32.h>
19 #include <linux/err.h>
20 #include <linux/errno.h>
21 #include <linux/etherdevice.h>
22 #include <linux/gfp.h>
23 #include <linux/if_ether.h>
24 #include <linux/init.h>
25 #include <linux/jhash.h>
26 #include <linux/jiffies.h>
27 #include <linux/kref.h>
28 #include <linux/list.h>
29 #include <linux/lockdep.h>
30 #include <linux/net.h>
31 #include <linux/netdevice.h>
32 #include <linux/netlink.h>
33 #include <linux/overflow.h>
34 #include <linux/rculist.h>
35 #include <linux/rcupdate.h>
36 #include <linux/skbuff.h>
37 #include <linux/slab.h>
38 #include <linux/spinlock.h>
39 #include <linux/stddef.h>
40 #include <linux/string.h>
41 #include <linux/workqueue.h>
42 #include <net/genetlink.h>
43 #include <net/netlink.h>
44 #include <uapi/linux/batadv_packet.h>
45 #include <uapi/linux/batman_adv.h>
46
47 #include "bridge_loop_avoidance.h"
48 #include "hard-interface.h"
49 #include "hash.h"
50 #include "log.h"
51 #include "mesh-interface.h"
52 #include "netlink.h"
53 #include "originator.h"
54 #include "tvlv.h"
55
56 static struct kmem_cache *batadv_tl_cache __read_mostly;
57 static struct kmem_cache *batadv_tg_cache __read_mostly;
58 static struct kmem_cache *batadv_tt_orig_cache __read_mostly;
59 static struct kmem_cache *batadv_tt_change_cache __read_mostly;
60 static struct kmem_cache *batadv_tt_req_cache __read_mostly;
61 static struct kmem_cache *batadv_tt_roam_cache __read_mostly;
62
63 /* hash class keys */
64 static struct lock_class_key batadv_tt_local_hash_lock_class_key;
65 static struct lock_class_key batadv_tt_global_hash_lock_class_key;
66
67 static void batadv_send_roam_adv(struct batadv_priv *bat_priv, u8 *client,
68 unsigned short vid,
69 struct batadv_orig_node *orig_node);
70 static void batadv_tt_purge(struct work_struct *work);
71 static void
72 batadv_tt_global_del_orig_list(struct batadv_tt_global_entry *tt_global_entry);
73 static void batadv_tt_global_del(struct batadv_priv *bat_priv,
74 struct batadv_orig_node *orig_node,
75 const unsigned char *addr,
76 unsigned short vid, const char *message,
77 bool roaming);
78
79 /**
80 * batadv_compare_tt() - check if two TT entries are the same
81 * @node: the list element pointer of the first TT entry
82 * @data2: pointer to the tt_common_entry of the second TT entry
83 *
84 * Compare the MAC address and the VLAN ID of the two TT entries and check if
85 * they are the same TT client.
86 * Return: true if the two TT clients are the same, false otherwise
87 */
batadv_compare_tt(const struct hlist_node * node,const void * data2)88 static bool batadv_compare_tt(const struct hlist_node *node, const void *data2)
89 {
90 const void *data1 = container_of(node, struct batadv_tt_common_entry,
91 hash_entry);
92 const struct batadv_tt_common_entry *tt1 = data1;
93 const struct batadv_tt_common_entry *tt2 = data2;
94
95 return (tt1->vid == tt2->vid) && batadv_compare_eth(data1, data2);
96 }
97
98 /**
99 * batadv_choose_tt() - return the index of the tt entry in the hash table
100 * @data: pointer to the tt_common_entry object to map
101 * @size: the size of the hash table
102 *
103 * Return: the hash index where the object represented by 'data' should be
104 * stored at.
105 */
batadv_choose_tt(const void * data,u32 size)106 static inline u32 batadv_choose_tt(const void *data, u32 size)
107 {
108 const struct batadv_tt_common_entry *tt;
109 u32 hash = 0;
110
111 tt = data;
112 hash = jhash(&tt->addr, ETH_ALEN, hash);
113 hash = jhash(&tt->vid, sizeof(tt->vid), hash);
114
115 return hash % size;
116 }
117
118 /**
119 * batadv_tt_hash_find() - look for a client in the given hash table
120 * @hash: the hash table to search
121 * @addr: the mac address of the client to look for
122 * @vid: VLAN identifier
123 *
124 * Return: a pointer to the tt_common struct belonging to the searched client if
125 * found, NULL otherwise.
126 */
127 static struct batadv_tt_common_entry *
batadv_tt_hash_find(struct batadv_hashtable * hash,const u8 * addr,unsigned short vid)128 batadv_tt_hash_find(struct batadv_hashtable *hash, const u8 *addr,
129 unsigned short vid)
130 {
131 struct hlist_head *head;
132 struct batadv_tt_common_entry to_search, *tt, *tt_tmp = NULL;
133 u32 index;
134
135 if (!hash)
136 return NULL;
137
138 ether_addr_copy(to_search.addr, addr);
139 to_search.vid = vid;
140
141 index = batadv_choose_tt(&to_search, hash->size);
142 head = &hash->table[index];
143
144 rcu_read_lock();
145 hlist_for_each_entry_rcu(tt, head, hash_entry) {
146 if (!batadv_compare_eth(tt, addr))
147 continue;
148
149 if (tt->vid != vid)
150 continue;
151
152 if (!kref_get_unless_zero(&tt->refcount))
153 continue;
154
155 tt_tmp = tt;
156 break;
157 }
158 rcu_read_unlock();
159
160 return tt_tmp;
161 }
162
163 /**
164 * batadv_tt_local_hash_find() - search the local table for a given client
165 * @bat_priv: the bat priv with all the mesh interface information
166 * @addr: the mac address of the client to look for
167 * @vid: VLAN identifier
168 *
169 * Return: a pointer to the corresponding tt_local_entry struct if the client is
170 * found, NULL otherwise.
171 */
172 static struct batadv_tt_local_entry *
batadv_tt_local_hash_find(struct batadv_priv * bat_priv,const u8 * addr,unsigned short vid)173 batadv_tt_local_hash_find(struct batadv_priv *bat_priv, const u8 *addr,
174 unsigned short vid)
175 {
176 struct batadv_tt_common_entry *tt_common_entry;
177 struct batadv_tt_local_entry *tt_local_entry = NULL;
178
179 tt_common_entry = batadv_tt_hash_find(bat_priv->tt.local_hash, addr,
180 vid);
181 if (tt_common_entry)
182 tt_local_entry = container_of(tt_common_entry,
183 struct batadv_tt_local_entry,
184 common);
185 return tt_local_entry;
186 }
187
188 /**
189 * batadv_tt_global_hash_find() - search the global table for a given client
190 * @bat_priv: the bat priv with all the mesh interface information
191 * @addr: the mac address of the client to look for
192 * @vid: VLAN identifier
193 *
194 * Return: a pointer to the corresponding tt_global_entry struct if the client
195 * is found, NULL otherwise.
196 */
197 struct batadv_tt_global_entry *
batadv_tt_global_hash_find(struct batadv_priv * bat_priv,const u8 * addr,unsigned short vid)198 batadv_tt_global_hash_find(struct batadv_priv *bat_priv, const u8 *addr,
199 unsigned short vid)
200 {
201 struct batadv_tt_common_entry *tt_common_entry;
202 struct batadv_tt_global_entry *tt_global_entry = NULL;
203
204 tt_common_entry = batadv_tt_hash_find(bat_priv->tt.global_hash, addr,
205 vid);
206 if (tt_common_entry)
207 tt_global_entry = container_of(tt_common_entry,
208 struct batadv_tt_global_entry,
209 common);
210 return tt_global_entry;
211 }
212
213 /**
214 * batadv_tt_local_entry_release() - release tt_local_entry from lists and queue
215 * for free after rcu grace period
216 * @ref: kref pointer of the batadv_tt_local_entry
217 */
batadv_tt_local_entry_release(struct kref * ref)218 static void batadv_tt_local_entry_release(struct kref *ref)
219 {
220 struct batadv_tt_local_entry *tt_local_entry;
221
222 tt_local_entry = container_of(ref, struct batadv_tt_local_entry,
223 common.refcount);
224
225 batadv_meshif_vlan_put(tt_local_entry->vlan);
226
227 kfree_rcu(tt_local_entry, common.rcu);
228 }
229
230 /**
231 * batadv_tt_local_entry_put() - decrement the tt_local_entry refcounter and
232 * possibly release it
233 * @tt_local_entry: tt_local_entry to be free'd
234 */
235 static void
batadv_tt_local_entry_put(struct batadv_tt_local_entry * tt_local_entry)236 batadv_tt_local_entry_put(struct batadv_tt_local_entry *tt_local_entry)
237 {
238 if (!tt_local_entry)
239 return;
240
241 kref_put(&tt_local_entry->common.refcount,
242 batadv_tt_local_entry_release);
243 }
244
245 /**
246 * batadv_tt_global_entry_release() - release tt_global_entry from lists and
247 * queue for free after rcu grace period
248 * @ref: kref pointer of the batadv_tt_global_entry
249 */
batadv_tt_global_entry_release(struct kref * ref)250 void batadv_tt_global_entry_release(struct kref *ref)
251 {
252 struct batadv_tt_global_entry *tt_global_entry;
253
254 tt_global_entry = container_of(ref, struct batadv_tt_global_entry,
255 common.refcount);
256
257 batadv_tt_global_del_orig_list(tt_global_entry);
258
259 kfree_rcu(tt_global_entry, common.rcu);
260 }
261
262 /**
263 * batadv_tt_global_hash_count() - count the number of orig entries
264 * @bat_priv: the bat priv with all the mesh interface information
265 * @addr: the mac address of the client to count entries for
266 * @vid: VLAN identifier
267 *
268 * Return: the number of originators advertising the given address/data
269 * (excluding our self).
270 */
batadv_tt_global_hash_count(struct batadv_priv * bat_priv,const u8 * addr,unsigned short vid)271 int batadv_tt_global_hash_count(struct batadv_priv *bat_priv,
272 const u8 *addr, unsigned short vid)
273 {
274 struct batadv_tt_global_entry *tt_global_entry;
275 int count;
276
277 tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr, vid);
278 if (!tt_global_entry)
279 return 0;
280
281 count = atomic_read(&tt_global_entry->orig_list_count);
282 batadv_tt_global_entry_put(tt_global_entry);
283
284 return count;
285 }
286
287 /**
288 * batadv_tt_local_size_mod() - change the size by v of the local table
289 * identified by vid
290 * @bat_priv: the bat priv with all the mesh interface information
291 * @vid: the VLAN identifier of the sub-table to change
292 * @v: the amount to sum to the local table size
293 */
batadv_tt_local_size_mod(struct batadv_priv * bat_priv,unsigned short vid,int v)294 static void batadv_tt_local_size_mod(struct batadv_priv *bat_priv,
295 unsigned short vid, int v)
296 {
297 struct batadv_meshif_vlan *vlan;
298
299 vlan = batadv_meshif_vlan_get(bat_priv, vid);
300 if (!vlan)
301 return;
302
303 atomic_add(v, &vlan->tt.num_entries);
304
305 batadv_meshif_vlan_put(vlan);
306 }
307
308 /**
309 * batadv_tt_local_size_inc() - increase by one the local table size for the
310 * given vid
311 * @bat_priv: the bat priv with all the mesh interface information
312 * @vid: the VLAN identifier
313 */
batadv_tt_local_size_inc(struct batadv_priv * bat_priv,unsigned short vid)314 static void batadv_tt_local_size_inc(struct batadv_priv *bat_priv,
315 unsigned short vid)
316 {
317 batadv_tt_local_size_mod(bat_priv, vid, 1);
318 }
319
320 /**
321 * batadv_tt_local_size_dec() - decrease by one the local table size for the
322 * given vid
323 * @bat_priv: the bat priv with all the mesh interface information
324 * @vid: the VLAN identifier
325 */
batadv_tt_local_size_dec(struct batadv_priv * bat_priv,unsigned short vid)326 static void batadv_tt_local_size_dec(struct batadv_priv *bat_priv,
327 unsigned short vid)
328 {
329 batadv_tt_local_size_mod(bat_priv, vid, -1);
330 }
331
332 /**
333 * batadv_tt_global_size_mod() - change the size by v of the global table
334 * for orig_node identified by vid
335 * @orig_node: the originator for which the table has to be modified
336 * @vid: the VLAN identifier
337 * @v: the amount to sum to the global table size
338 */
batadv_tt_global_size_mod(struct batadv_orig_node * orig_node,unsigned short vid,int v)339 static void batadv_tt_global_size_mod(struct batadv_orig_node *orig_node,
340 unsigned short vid, int v)
341 {
342 struct batadv_orig_node_vlan *vlan;
343
344 vlan = batadv_orig_node_vlan_new(orig_node, vid);
345 if (!vlan)
346 return;
347
348 if (atomic_add_return(v, &vlan->tt.num_entries) == 0) {
349 spin_lock_bh(&orig_node->vlan_list_lock);
350 if (!hlist_unhashed(&vlan->list)) {
351 hlist_del_init_rcu(&vlan->list);
352 batadv_orig_node_vlan_put(vlan);
353 }
354 spin_unlock_bh(&orig_node->vlan_list_lock);
355 }
356
357 batadv_orig_node_vlan_put(vlan);
358 }
359
360 /**
361 * batadv_tt_global_size_inc() - increase by one the global table size for the
362 * given vid
363 * @orig_node: the originator which global table size has to be decreased
364 * @vid: the vlan identifier
365 */
batadv_tt_global_size_inc(struct batadv_orig_node * orig_node,unsigned short vid)366 static void batadv_tt_global_size_inc(struct batadv_orig_node *orig_node,
367 unsigned short vid)
368 {
369 batadv_tt_global_size_mod(orig_node, vid, 1);
370 }
371
372 /**
373 * batadv_tt_global_size_dec() - decrease by one the global table size for the
374 * given vid
375 * @orig_node: the originator which global table size has to be decreased
376 * @vid: the vlan identifier
377 */
batadv_tt_global_size_dec(struct batadv_orig_node * orig_node,unsigned short vid)378 static void batadv_tt_global_size_dec(struct batadv_orig_node *orig_node,
379 unsigned short vid)
380 {
381 batadv_tt_global_size_mod(orig_node, vid, -1);
382 }
383
384 /**
385 * batadv_tt_orig_list_entry_release() - release tt orig entry from lists and
386 * queue for free after rcu grace period
387 * @ref: kref pointer of the tt orig entry
388 */
batadv_tt_orig_list_entry_release(struct kref * ref)389 static void batadv_tt_orig_list_entry_release(struct kref *ref)
390 {
391 struct batadv_tt_orig_list_entry *orig_entry;
392
393 orig_entry = container_of(ref, struct batadv_tt_orig_list_entry,
394 refcount);
395
396 batadv_orig_node_put(orig_entry->orig_node);
397 kfree_rcu(orig_entry, rcu);
398 }
399
400 /**
401 * batadv_tt_orig_list_entry_put() - decrement the tt orig entry refcounter and
402 * possibly release it
403 * @orig_entry: tt orig entry to be free'd
404 */
405 static void
batadv_tt_orig_list_entry_put(struct batadv_tt_orig_list_entry * orig_entry)406 batadv_tt_orig_list_entry_put(struct batadv_tt_orig_list_entry *orig_entry)
407 {
408 if (!orig_entry)
409 return;
410
411 kref_put(&orig_entry->refcount, batadv_tt_orig_list_entry_release);
412 }
413
414 /**
415 * batadv_tt_local_event() - store a local TT event (ADD/DEL)
416 * @bat_priv: the bat priv with all the mesh interface information
417 * @tt_local_entry: the TT entry involved in the event
418 * @event_flags: flags to store in the event structure
419 */
batadv_tt_local_event(struct batadv_priv * bat_priv,struct batadv_tt_local_entry * tt_local_entry,u8 event_flags)420 static void batadv_tt_local_event(struct batadv_priv *bat_priv,
421 struct batadv_tt_local_entry *tt_local_entry,
422 u8 event_flags)
423 {
424 struct batadv_tt_change_node *tt_change_node, *entry, *safe;
425 struct batadv_tt_common_entry *common = &tt_local_entry->common;
426 u8 flags = common->flags | event_flags;
427 bool del_op_requested, del_op_entry;
428 size_t changes;
429
430 tt_change_node = kmem_cache_alloc(batadv_tt_change_cache, GFP_ATOMIC);
431 if (!tt_change_node)
432 return;
433
434 tt_change_node->change.flags = flags;
435 memset(tt_change_node->change.reserved, 0,
436 sizeof(tt_change_node->change.reserved));
437 ether_addr_copy(tt_change_node->change.addr, common->addr);
438 tt_change_node->change.vid = htons(common->vid);
439
440 del_op_requested = flags & BATADV_TT_CLIENT_DEL;
441
442 /* check for ADD+DEL, DEL+ADD, ADD+ADD or DEL+DEL events */
443 spin_lock_bh(&bat_priv->tt.changes_list_lock);
444 changes = READ_ONCE(bat_priv->tt.local_changes);
445 list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list,
446 list) {
447 if (!batadv_compare_eth(entry->change.addr, common->addr))
448 continue;
449
450 if (entry->change.vid != tt_change_node->change.vid)
451 continue;
452
453 del_op_entry = entry->change.flags & BATADV_TT_CLIENT_DEL;
454 if (del_op_requested != del_op_entry) {
455 /* DEL+ADD in the same orig interval have no effect and
456 * can be removed to avoid silly behaviour on the
457 * receiver side. The other way around (ADD+DEL) can
458 * happen in case of roaming of a client still in the
459 * NEW state. Roaming of NEW clients is now possible due
460 * to automatically recognition of "temporary" clients
461 */
462 list_del(&entry->list);
463 kmem_cache_free(batadv_tt_change_cache, entry);
464 changes--;
465 } else {
466 /* this is a second add or del in the same originator
467 * interval. It could mean that flags have been changed
468 * (e.g. double add): update them
469 */
470 entry->change.flags = flags;
471 }
472
473 kmem_cache_free(batadv_tt_change_cache, tt_change_node);
474 goto update_changes;
475 }
476
477 /* track the change in the OGMinterval list */
478 list_add_tail(&tt_change_node->list, &bat_priv->tt.changes_list);
479 changes++;
480
481 update_changes:
482 WRITE_ONCE(bat_priv->tt.local_changes, changes);
483 spin_unlock_bh(&bat_priv->tt.changes_list_lock);
484 }
485
486 /**
487 * batadv_tt_len() - compute length in bytes of given number of tt changes
488 * @changes_num: number of tt changes
489 *
490 * Return: computed length in bytes.
491 */
batadv_tt_len(int changes_num)492 static int batadv_tt_len(int changes_num)
493 {
494 return changes_num * sizeof(struct batadv_tvlv_tt_change);
495 }
496
497 /**
498 * batadv_tt_entries() - compute the number of entries fitting in tt_len bytes
499 * @tt_len: available space
500 *
501 * Return: the number of entries.
502 */
batadv_tt_entries(u16 tt_len)503 static u16 batadv_tt_entries(u16 tt_len)
504 {
505 return tt_len / batadv_tt_len(1);
506 }
507
508 /**
509 * batadv_tt_local_table_transmit_size() - calculates the local translation
510 * table size when transmitted over the air
511 * @bat_priv: the bat priv with all the mesh interface information
512 *
513 * Return: local translation table size in bytes.
514 */
batadv_tt_local_table_transmit_size(struct batadv_priv * bat_priv)515 static int batadv_tt_local_table_transmit_size(struct batadv_priv *bat_priv)
516 {
517 u16 num_vlan = 0;
518 u16 tt_local_entries = 0;
519 struct batadv_meshif_vlan *vlan;
520 int hdr_size;
521
522 rcu_read_lock();
523 hlist_for_each_entry_rcu(vlan, &bat_priv->meshif_vlan_list, list) {
524 num_vlan++;
525 tt_local_entries += atomic_read(&vlan->tt.num_entries);
526 }
527 rcu_read_unlock();
528
529 /* header size of tvlv encapsulated tt response payload */
530 hdr_size = sizeof(struct batadv_unicast_tvlv_packet);
531 hdr_size += sizeof(struct batadv_tvlv_hdr);
532 hdr_size += sizeof(struct batadv_tvlv_tt_data);
533 hdr_size += num_vlan * sizeof(struct batadv_tvlv_tt_vlan_data);
534
535 return hdr_size + batadv_tt_len(tt_local_entries);
536 }
537
batadv_tt_local_init(struct batadv_priv * bat_priv)538 static int batadv_tt_local_init(struct batadv_priv *bat_priv)
539 {
540 if (bat_priv->tt.local_hash)
541 return 0;
542
543 bat_priv->tt.local_hash = batadv_hash_new(1024);
544
545 if (!bat_priv->tt.local_hash)
546 return -ENOMEM;
547
548 batadv_hash_set_lock_class(bat_priv->tt.local_hash,
549 &batadv_tt_local_hash_lock_class_key);
550
551 return 0;
552 }
553
batadv_tt_global_free(struct batadv_priv * bat_priv,struct batadv_tt_global_entry * tt_global,const char * message)554 static void batadv_tt_global_free(struct batadv_priv *bat_priv,
555 struct batadv_tt_global_entry *tt_global,
556 const char *message)
557 {
558 struct batadv_tt_global_entry *tt_removed_entry;
559 struct hlist_node *tt_removed_node;
560
561 batadv_dbg(BATADV_DBG_TT, bat_priv,
562 "Deleting global tt entry %pM (vid: %d): %s\n",
563 tt_global->common.addr,
564 batadv_print_vid(tt_global->common.vid), message);
565
566 tt_removed_node = batadv_hash_remove(bat_priv->tt.global_hash,
567 batadv_compare_tt,
568 batadv_choose_tt,
569 &tt_global->common);
570 if (!tt_removed_node)
571 return;
572
573 /* drop reference of remove hash entry */
574 tt_removed_entry = hlist_entry(tt_removed_node,
575 struct batadv_tt_global_entry,
576 common.hash_entry);
577 batadv_tt_global_entry_put(tt_removed_entry);
578 }
579
580 /**
581 * batadv_tt_local_add() - add a new client to the local table or update an
582 * existing client
583 * @mesh_iface: netdev struct of the mesh interface
584 * @addr: the mac address of the client to add
585 * @vid: VLAN identifier
586 * @ifindex: index of the interface where the client is connected to (useful to
587 * identify wireless clients)
588 * @mark: the value contained in the skb->mark field of the received packet (if
589 * any)
590 *
591 * Return: true if the client was successfully added, false otherwise.
592 */
batadv_tt_local_add(struct net_device * mesh_iface,const u8 * addr,unsigned short vid,int ifindex,u32 mark)593 bool batadv_tt_local_add(struct net_device *mesh_iface, const u8 *addr,
594 unsigned short vid, int ifindex, u32 mark)
595 {
596 struct batadv_priv *bat_priv = netdev_priv(mesh_iface);
597 struct batadv_tt_local_entry *tt_local;
598 struct batadv_tt_global_entry *tt_global = NULL;
599 struct net *net = dev_net(mesh_iface);
600 struct batadv_meshif_vlan *vlan;
601 struct net_device *in_dev = NULL;
602 struct hlist_head *head;
603 struct batadv_tt_orig_list_entry *orig_entry;
604 int hash_added, table_size, packet_size_max;
605 bool ret = false;
606 bool roamed_back = false;
607 bool iif_is_wifi = false;
608 u8 remote_flags;
609 u32 match_mark;
610
611 if (ifindex != BATADV_NULL_IFINDEX)
612 in_dev = dev_get_by_index(net, ifindex);
613
614 if (in_dev) {
615 u32 wifi_flags = batadv_netdev_get_wifi_flags(in_dev);
616
617 iif_is_wifi = batadv_is_wifi(wifi_flags);
618 }
619
620 tt_local = batadv_tt_local_hash_find(bat_priv, addr, vid);
621
622 if (!is_multicast_ether_addr(addr))
623 tt_global = batadv_tt_global_hash_find(bat_priv, addr, vid);
624
625 if (tt_local) {
626 tt_local->last_seen = jiffies;
627 if (tt_local->common.flags & BATADV_TT_CLIENT_PENDING) {
628 batadv_dbg(BATADV_DBG_TT, bat_priv,
629 "Re-adding pending client %pM (vid: %d)\n",
630 addr, batadv_print_vid(vid));
631 /* whatever the reason why the PENDING flag was set,
632 * this is a client which was enqueued to be removed in
633 * this orig_interval. Since it popped up again, the
634 * flag can be reset like it was never enqueued
635 */
636 tt_local->common.flags &= ~BATADV_TT_CLIENT_PENDING;
637 goto add_event;
638 }
639
640 if (tt_local->common.flags & BATADV_TT_CLIENT_ROAM) {
641 batadv_dbg(BATADV_DBG_TT, bat_priv,
642 "Roaming client %pM (vid: %d) came back to its original location\n",
643 addr, batadv_print_vid(vid));
644 /* the ROAM flag is set because this client roamed away
645 * and the node got a roaming_advertisement message. Now
646 * that the client popped up again at its original
647 * location such flag can be unset
648 */
649 tt_local->common.flags &= ~BATADV_TT_CLIENT_ROAM;
650 roamed_back = true;
651 }
652 goto check_roaming;
653 }
654
655 /* Ignore the client if we cannot send it in a full table response. */
656 table_size = batadv_tt_local_table_transmit_size(bat_priv);
657 table_size += batadv_tt_len(1);
658 packet_size_max = READ_ONCE(bat_priv->packet_size_max);
659 if (table_size > packet_size_max) {
660 net_ratelimited_function(batadv_info, mesh_iface,
661 "Local translation table size (%i) exceeds maximum packet size (%i); Ignoring new local tt entry: %pM\n",
662 table_size, packet_size_max, addr);
663 goto out;
664 }
665
666 tt_local = kmem_cache_alloc(batadv_tl_cache, GFP_ATOMIC);
667 if (!tt_local)
668 goto out;
669
670 /* increase the refcounter of the related vlan */
671 vlan = batadv_meshif_vlan_get(bat_priv, vid);
672 if (!vlan) {
673 net_ratelimited_function(batadv_info, mesh_iface,
674 "adding TT local entry %pM to non-existent VLAN %d\n",
675 addr, batadv_print_vid(vid));
676 kmem_cache_free(batadv_tl_cache, tt_local);
677 tt_local = NULL;
678 goto out;
679 }
680
681 batadv_dbg(BATADV_DBG_TT, bat_priv,
682 "Creating new local tt entry: %pM (vid: %d, ttvn: %d)\n",
683 addr, batadv_print_vid(vid),
684 (u8)atomic_read(&bat_priv->tt.vn));
685
686 ether_addr_copy(tt_local->common.addr, addr);
687 /* The local entry has to be marked as NEW to avoid to send it in
688 * a full table response going out before the next ttvn increment
689 * (consistency check)
690 */
691 tt_local->common.flags = BATADV_TT_CLIENT_NEW;
692 tt_local->common.vid = vid;
693 if (iif_is_wifi)
694 tt_local->common.flags |= BATADV_TT_CLIENT_WIFI;
695 kref_init(&tt_local->common.refcount);
696 tt_local->last_seen = jiffies;
697 tt_local->common.added_at = tt_local->last_seen;
698 tt_local->vlan = vlan;
699
700 /* the batman interface mac and multicast addresses should never be
701 * purged
702 */
703 if (batadv_compare_eth(addr, mesh_iface->dev_addr) ||
704 is_multicast_ether_addr(addr))
705 tt_local->common.flags |= BATADV_TT_CLIENT_NOPURGE;
706
707 kref_get(&tt_local->common.refcount);
708 hash_added = batadv_hash_add(bat_priv->tt.local_hash, batadv_compare_tt,
709 batadv_choose_tt, &tt_local->common,
710 &tt_local->common.hash_entry);
711
712 if (unlikely(hash_added != 0)) {
713 /* remove the reference for the hash */
714 batadv_tt_local_entry_put(tt_local);
715 goto out;
716 }
717
718 add_event:
719 batadv_tt_local_event(bat_priv, tt_local, BATADV_NO_FLAGS);
720
721 check_roaming:
722 /* Check whether it is a roaming, but don't do anything if the roaming
723 * process has already been handled
724 */
725 if (tt_global && !(tt_global->common.flags & BATADV_TT_CLIENT_ROAM)) {
726 /* These node are probably going to update their tt table */
727 head = &tt_global->orig_list;
728 rcu_read_lock();
729 hlist_for_each_entry_rcu(orig_entry, head, list) {
730 batadv_send_roam_adv(bat_priv, tt_global->common.addr,
731 tt_global->common.vid,
732 orig_entry->orig_node);
733 }
734 rcu_read_unlock();
735 if (roamed_back) {
736 batadv_tt_global_free(bat_priv, tt_global,
737 "Roaming canceled");
738 } else {
739 /* The global entry has to be marked as ROAMING and
740 * has to be kept for consistency purpose
741 */
742 tt_global->common.flags |= BATADV_TT_CLIENT_ROAM;
743 tt_global->roam_at = jiffies;
744 }
745 }
746
747 /* store the current remote flags before altering them. This helps
748 * understanding is flags are changing or not
749 */
750 remote_flags = tt_local->common.flags & BATADV_TT_REMOTE_MASK;
751
752 if (iif_is_wifi)
753 tt_local->common.flags |= BATADV_TT_CLIENT_WIFI;
754 else
755 tt_local->common.flags &= ~BATADV_TT_CLIENT_WIFI;
756
757 /* check the mark in the skb: if it's equal to the configured
758 * isolation_mark, it means the packet is coming from an isolated
759 * non-mesh client
760 */
761 match_mark = (mark & bat_priv->isolation_mark_mask);
762 if (bat_priv->isolation_mark_mask &&
763 match_mark == bat_priv->isolation_mark)
764 tt_local->common.flags |= BATADV_TT_CLIENT_ISOLA;
765 else
766 tt_local->common.flags &= ~BATADV_TT_CLIENT_ISOLA;
767
768 /* if any "dynamic" flag has been modified, resend an ADD event for this
769 * entry so that all the nodes can get the new flags
770 */
771 if (remote_flags ^ (tt_local->common.flags & BATADV_TT_REMOTE_MASK))
772 batadv_tt_local_event(bat_priv, tt_local, BATADV_NO_FLAGS);
773
774 ret = true;
775 out:
776 dev_put(in_dev);
777 batadv_tt_local_entry_put(tt_local);
778 batadv_tt_global_entry_put(tt_global);
779 return ret;
780 }
781
782 /**
783 * batadv_tt_prepare_tvlv_global_data() - prepare the TVLV TT header to send
784 * within a TT Response directed to another node
785 * @orig_node: originator for which the TT data has to be prepared
786 * @tt_data: uninitialised pointer to the address of the TVLV buffer
787 * @tt_change: uninitialised pointer to the address of the area where the TT
788 * changed can be stored
789 * @tt_len: pointer to the length to reserve to the tt_change. if -1 this
790 * function reserves the amount of space needed to send the entire global TT
791 * table. In case of success the value is updated with the real amount of
792 * reserved bytes
793 * Allocate the needed amount of memory for the entire TT TVLV and write its
794 * header made up of one tvlv_tt_data object and a series of tvlv_tt_vlan_data
795 * objects, one per active VLAN served by the originator node.
796 *
797 * Return: the size of the allocated buffer or 0 in case of failure.
798 */
799 static u16
batadv_tt_prepare_tvlv_global_data(struct batadv_orig_node * orig_node,struct batadv_tvlv_tt_data ** tt_data,struct batadv_tvlv_tt_change ** tt_change,s32 * tt_len)800 batadv_tt_prepare_tvlv_global_data(struct batadv_orig_node *orig_node,
801 struct batadv_tvlv_tt_data **tt_data,
802 struct batadv_tvlv_tt_change **tt_change,
803 s32 *tt_len)
804 {
805 struct batadv_tvlv_tt_vlan_data *tt_vlan;
806 struct batadv_orig_node_vlan *vlan;
807 u16 total_entries = 0;
808 size_t change_offset;
809 u8 *tt_change_ptr;
810 u16 num_vlan = 0;
811 int vlan_entries;
812 u16 sum_entries;
813 u16 tvlv_len;
814
815 spin_lock_bh(&orig_node->vlan_list_lock);
816 hlist_for_each_entry(vlan, &orig_node->vlan_list, list) {
817 vlan_entries = atomic_read(&vlan->tt.num_entries);
818
819 if (check_add_overflow(vlan_entries, total_entries, &sum_entries)) {
820 tvlv_len = 0;
821 *tt_len = 0;
822 goto out;
823 }
824
825 total_entries = sum_entries;
826 num_vlan++;
827 }
828
829 change_offset = struct_size(*tt_data, vlan_data, num_vlan);
830
831 /* if tt_len is negative, allocate the space needed by the full table */
832 if (*tt_len < 0)
833 *tt_len = batadv_tt_len(total_entries);
834
835 if (check_add_overflow(*tt_len, change_offset, &tvlv_len)) {
836 tvlv_len = 0;
837 *tt_len = 0;
838 goto out;
839 }
840
841 *tt_data = kmalloc(tvlv_len, GFP_ATOMIC);
842 if (!*tt_data) {
843 tvlv_len = 0;
844 *tt_len = 0;
845 goto out;
846 }
847
848 (*tt_data)->flags = BATADV_NO_FLAGS;
849 (*tt_data)->ttvn = READ_ONCE(orig_node->last_ttvn);
850 (*tt_data)->num_vlan = htons(num_vlan);
851
852 tt_vlan = (*tt_data)->vlan_data;
853 num_vlan = 0;
854 hlist_for_each_entry(vlan, &orig_node->vlan_list, list) {
855 vlan_entries = atomic_read(&vlan->tt.num_entries);
856 if (vlan_entries < 1)
857 continue;
858
859 tt_vlan->vid = htons(vlan->vid);
860 tt_vlan->crc = htonl(vlan->tt.crc);
861 tt_vlan->reserved = 0;
862
863 tt_vlan++;
864 num_vlan++;
865 }
866
867 /* recalculate in case number of VLANs reduced */
868 change_offset = struct_size(*tt_data, vlan_data, num_vlan);
869 tvlv_len = *tt_len + change_offset;
870
871 (*tt_data)->num_vlan = htons(num_vlan);
872
873 tt_change_ptr = (u8 *)*tt_data + change_offset;
874 *tt_change = (struct batadv_tvlv_tt_change *)tt_change_ptr;
875
876 out:
877 spin_unlock_bh(&orig_node->vlan_list_lock);
878
879 return tvlv_len;
880 }
881
882 /**
883 * batadv_tt_prepare_tvlv_local_data() - allocate and prepare the TT TVLV for
884 * this node
885 * @bat_priv: the bat priv with all the mesh interface information
886 * @tt_data: uninitialised pointer to the address of the TVLV buffer
887 * @tt_change: uninitialised pointer to the address of the area where the TT
888 * changes can be stored
889 * @tt_len: pointer to the length to reserve to the tt_change. if -1 this
890 * function reserves the amount of space needed to send the entire local TT
891 * table. In case of success the value is updated with the real amount of
892 * reserved bytes
893 *
894 * Allocate the needed amount of memory for the entire TT TVLV and write its
895 * header made up by one tvlv_tt_data object and a series of tvlv_tt_vlan_data
896 * objects, one per active VLAN.
897 *
898 * Return: the size of the allocated buffer or 0 in case of failure.
899 */
900 static u16
batadv_tt_prepare_tvlv_local_data(struct batadv_priv * bat_priv,struct batadv_tvlv_tt_data ** tt_data,struct batadv_tvlv_tt_change ** tt_change,s32 * tt_len)901 batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv,
902 struct batadv_tvlv_tt_data **tt_data,
903 struct batadv_tvlv_tt_change **tt_change,
904 s32 *tt_len)
905 {
906 struct batadv_tvlv_tt_vlan_data *tt_vlan;
907 struct batadv_meshif_vlan *vlan;
908 u16 total_entries = 0;
909 size_t change_offset;
910 u8 *tt_change_ptr;
911 u16 num_vlan = 0;
912 int vlan_entries;
913 u16 sum_entries;
914 u16 tvlv_len;
915
916 spin_lock_bh(&bat_priv->meshif_vlan_list_lock);
917 hlist_for_each_entry(vlan, &bat_priv->meshif_vlan_list, list) {
918 vlan_entries = atomic_read(&vlan->tt.num_entries);
919
920 if (check_add_overflow(vlan_entries, total_entries, &sum_entries)) {
921 tvlv_len = 0;
922 *tt_len = 0;
923 goto out;
924 }
925
926 total_entries = sum_entries;
927 num_vlan++;
928 }
929
930 change_offset = struct_size(*tt_data, vlan_data, num_vlan);
931
932 /* if tt_len is negative, allocate the space needed by the full table */
933 if (*tt_len < 0)
934 *tt_len = batadv_tt_len(total_entries);
935
936 if (check_add_overflow(*tt_len, change_offset, &tvlv_len)) {
937 tvlv_len = 0;
938 *tt_len = 0;
939 goto out;
940 }
941
942 *tt_data = kmalloc(tvlv_len, GFP_ATOMIC);
943 if (!*tt_data) {
944 tvlv_len = 0;
945 *tt_len = 0;
946 goto out;
947 }
948
949 (*tt_data)->flags = BATADV_NO_FLAGS;
950 (*tt_data)->ttvn = atomic_read(&bat_priv->tt.vn);
951 (*tt_data)->num_vlan = htons(num_vlan);
952
953 tt_vlan = (*tt_data)->vlan_data;
954 num_vlan = 0;
955 hlist_for_each_entry(vlan, &bat_priv->meshif_vlan_list, list) {
956 vlan_entries = atomic_read(&vlan->tt.num_entries);
957 if (vlan_entries < 1)
958 continue;
959
960 tt_vlan->vid = htons(vlan->vid);
961 tt_vlan->crc = htonl(vlan->tt.crc);
962 tt_vlan->reserved = 0;
963
964 tt_vlan++;
965 num_vlan++;
966 }
967
968 /* recalculate in case number of VLANs reduced */
969 change_offset = struct_size(*tt_data, vlan_data, num_vlan);
970 tvlv_len = *tt_len + change_offset;
971
972 (*tt_data)->num_vlan = htons(num_vlan);
973
974 tt_change_ptr = (u8 *)*tt_data + change_offset;
975 *tt_change = (struct batadv_tvlv_tt_change *)tt_change_ptr;
976
977 out:
978 spin_unlock_bh(&bat_priv->meshif_vlan_list_lock);
979
980 return tvlv_len;
981 }
982
983 /**
984 * batadv_tt_tvlv_container_update() - update the translation table tvlv
985 * container after local tt changes have been committed
986 * @bat_priv: the bat priv with all the mesh interface information
987 */
batadv_tt_tvlv_container_update(struct batadv_priv * bat_priv)988 static void batadv_tt_tvlv_container_update(struct batadv_priv *bat_priv)
989 {
990 struct batadv_tt_change_node *entry, *safe;
991 struct batadv_tvlv_tt_data *tt_data;
992 struct batadv_tvlv_tt_change *tt_change;
993 int tt_diff_len, tt_change_len = 0;
994 int tt_diff_entries_num = 0;
995 int tt_diff_entries_count = 0;
996 bool drop_changes = false;
997 size_t tt_extra_len = 0;
998 u16 tvlv_len;
999
1000 tt_diff_entries_num = READ_ONCE(bat_priv->tt.local_changes);
1001 tt_diff_len = batadv_tt_len(tt_diff_entries_num);
1002
1003 /* if we have too many changes for one packet don't send any
1004 * and wait for the tt table request so we can reply with the full
1005 * (fragmented) table.
1006 *
1007 * The local change history should still be cleaned up so the next
1008 * TT round can start again with a clean state.
1009 */
1010 if (tt_diff_len > bat_priv->mesh_iface->mtu) {
1011 tt_diff_len = 0;
1012 tt_diff_entries_num = 0;
1013 drop_changes = true;
1014 }
1015
1016 tvlv_len = batadv_tt_prepare_tvlv_local_data(bat_priv, &tt_data,
1017 &tt_change, &tt_diff_len);
1018 if (!tvlv_len)
1019 return;
1020
1021 tt_data->flags = BATADV_TT_OGM_DIFF;
1022
1023 if (!drop_changes && tt_diff_len == 0)
1024 goto container_register;
1025
1026 spin_lock_bh(&bat_priv->tt.changes_list_lock);
1027 WRITE_ONCE(bat_priv->tt.local_changes, 0);
1028
1029 list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list,
1030 list) {
1031 if (tt_diff_entries_count < tt_diff_entries_num) {
1032 memcpy(tt_change + tt_diff_entries_count,
1033 &entry->change,
1034 sizeof(struct batadv_tvlv_tt_change));
1035 tt_diff_entries_count++;
1036 }
1037 list_del(&entry->list);
1038 kmem_cache_free(batadv_tt_change_cache, entry);
1039 }
1040 spin_unlock_bh(&bat_priv->tt.changes_list_lock);
1041
1042 tt_extra_len = batadv_tt_len(tt_diff_entries_num -
1043 tt_diff_entries_count);
1044
1045 /* Keep the buffer for possible tt_request */
1046 spin_lock_bh(&bat_priv->tt.last_changeset_lock);
1047 kfree(bat_priv->tt.last_changeset);
1048 bat_priv->tt.last_changeset_len = 0;
1049 bat_priv->tt.last_changeset = NULL;
1050 tt_change_len = batadv_tt_len(tt_diff_entries_count);
1051 /* check whether this new OGM has no changes due to size problems */
1052 if (tt_diff_entries_count > 0) {
1053 tt_diff_len -= tt_extra_len;
1054 /* if kmalloc() fails we will reply with the full table
1055 * instead of providing the diff
1056 */
1057 bat_priv->tt.last_changeset = kzalloc(tt_diff_len, GFP_ATOMIC);
1058 if (bat_priv->tt.last_changeset) {
1059 memcpy(bat_priv->tt.last_changeset,
1060 tt_change, tt_change_len);
1061 bat_priv->tt.last_changeset_len = tt_diff_len;
1062 }
1063 }
1064 spin_unlock_bh(&bat_priv->tt.last_changeset_lock);
1065
1066 /* Remove extra packet space for OGM */
1067 tvlv_len -= tt_extra_len;
1068 container_register:
1069 batadv_tvlv_container_register(bat_priv, BATADV_TVLV_TT, 1, tt_data,
1070 tvlv_len);
1071 kfree(tt_data);
1072 }
1073
1074 /**
1075 * batadv_tt_local_dump_entry() - Dump one TT local entry into a message
1076 * @msg :Netlink message to dump into
1077 * @portid: Port making netlink request
1078 * @cb: Control block containing additional options
1079 * @bat_priv: The bat priv with all the mesh interface information
1080 * @common: tt local & tt global common data
1081 *
1082 * Return: Error code, or 0 on success
1083 */
1084 static int
batadv_tt_local_dump_entry(struct sk_buff * msg,u32 portid,struct netlink_callback * cb,struct batadv_priv * bat_priv,struct batadv_tt_common_entry * common)1085 batadv_tt_local_dump_entry(struct sk_buff *msg, u32 portid,
1086 struct netlink_callback *cb,
1087 struct batadv_priv *bat_priv,
1088 struct batadv_tt_common_entry *common)
1089 {
1090 void *hdr;
1091 struct batadv_meshif_vlan *vlan;
1092 struct batadv_tt_local_entry *local;
1093 unsigned int last_seen_msecs;
1094 u32 crc;
1095
1096 local = container_of(common, struct batadv_tt_local_entry, common);
1097 last_seen_msecs = jiffies_to_msecs(jiffies - local->last_seen);
1098
1099 vlan = batadv_meshif_vlan_get(bat_priv, common->vid);
1100 if (!vlan)
1101 return 0;
1102
1103 crc = vlan->tt.crc;
1104
1105 batadv_meshif_vlan_put(vlan);
1106
1107 hdr = genlmsg_put(msg, portid, cb->nlh->nlmsg_seq,
1108 &batadv_netlink_family, NLM_F_MULTI,
1109 BATADV_CMD_GET_TRANSTABLE_LOCAL);
1110 if (!hdr)
1111 return -ENOBUFS;
1112
1113 genl_dump_check_consistent(cb, hdr);
1114
1115 if (nla_put(msg, BATADV_ATTR_TT_ADDRESS, ETH_ALEN, common->addr) ||
1116 nla_put_u32(msg, BATADV_ATTR_TT_CRC32, crc) ||
1117 nla_put_u16(msg, BATADV_ATTR_TT_VID, common->vid) ||
1118 nla_put_u32(msg, BATADV_ATTR_TT_FLAGS, common->flags))
1119 goto nla_put_failure;
1120
1121 if (!(common->flags & BATADV_TT_CLIENT_NOPURGE) &&
1122 nla_put_u32(msg, BATADV_ATTR_LAST_SEEN_MSECS, last_seen_msecs))
1123 goto nla_put_failure;
1124
1125 genlmsg_end(msg, hdr);
1126 return 0;
1127
1128 nla_put_failure:
1129 genlmsg_cancel(msg, hdr);
1130 return -EMSGSIZE;
1131 }
1132
1133 /**
1134 * batadv_tt_local_dump_bucket() - Dump one TT local bucket into a message
1135 * @msg: Netlink message to dump into
1136 * @portid: Port making netlink request
1137 * @cb: Control block containing additional options
1138 * @bat_priv: The bat priv with all the mesh interface information
1139 * @hash: hash to dump
1140 * @bucket: bucket index to dump
1141 * @idx_s: Number of entries to skip
1142 *
1143 * Return: Error code, or 0 on success
1144 */
1145 static int
batadv_tt_local_dump_bucket(struct sk_buff * msg,u32 portid,struct netlink_callback * cb,struct batadv_priv * bat_priv,struct batadv_hashtable * hash,unsigned int bucket,int * idx_s)1146 batadv_tt_local_dump_bucket(struct sk_buff *msg, u32 portid,
1147 struct netlink_callback *cb,
1148 struct batadv_priv *bat_priv,
1149 struct batadv_hashtable *hash, unsigned int bucket,
1150 int *idx_s)
1151 {
1152 struct batadv_tt_common_entry *common;
1153 int idx = 0;
1154
1155 spin_lock_bh(&hash->list_locks[bucket]);
1156 cb->seq = atomic_read(&hash->generation) << 1 | 1;
1157
1158 hlist_for_each_entry(common, &hash->table[bucket], hash_entry) {
1159 if (idx++ < *idx_s)
1160 continue;
1161
1162 if (batadv_tt_local_dump_entry(msg, portid, cb, bat_priv,
1163 common)) {
1164 spin_unlock_bh(&hash->list_locks[bucket]);
1165 *idx_s = idx - 1;
1166 return -EMSGSIZE;
1167 }
1168 }
1169 spin_unlock_bh(&hash->list_locks[bucket]);
1170
1171 *idx_s = 0;
1172 return 0;
1173 }
1174
1175 /**
1176 * batadv_tt_local_dump() - Dump TT local entries into a message
1177 * @msg: Netlink message to dump into
1178 * @cb: Parameters from query
1179 *
1180 * Return: Error code, or 0 on success
1181 */
batadv_tt_local_dump(struct sk_buff * msg,struct netlink_callback * cb)1182 int batadv_tt_local_dump(struct sk_buff *msg, struct netlink_callback *cb)
1183 {
1184 struct net_device *mesh_iface;
1185 struct batadv_priv *bat_priv;
1186 struct batadv_hard_iface *primary_if = NULL;
1187 struct batadv_hashtable *hash;
1188 int ret;
1189 int bucket = cb->args[0];
1190 int idx = cb->args[1];
1191 int portid = NETLINK_CB(cb->skb).portid;
1192
1193 mesh_iface = batadv_netlink_get_meshif(cb);
1194 if (IS_ERR(mesh_iface))
1195 return PTR_ERR(mesh_iface);
1196
1197 bat_priv = netdev_priv(mesh_iface);
1198
1199 primary_if = batadv_primary_if_get_selected(bat_priv);
1200 if (!primary_if || primary_if->if_status != BATADV_IF_ACTIVE) {
1201 ret = -ENOENT;
1202 goto out;
1203 }
1204
1205 hash = bat_priv->tt.local_hash;
1206
1207 while (bucket < hash->size) {
1208 if (batadv_tt_local_dump_bucket(msg, portid, cb, bat_priv,
1209 hash, bucket, &idx))
1210 break;
1211
1212 bucket++;
1213 }
1214
1215 ret = msg->len;
1216
1217 out:
1218 batadv_hardif_put(primary_if);
1219 dev_put(mesh_iface);
1220
1221 cb->args[0] = bucket;
1222 cb->args[1] = idx;
1223
1224 return ret;
1225 }
1226
1227 static void
batadv_tt_local_set_pending(struct batadv_priv * bat_priv,struct batadv_tt_local_entry * tt_local_entry,u16 flags,const char * message)1228 batadv_tt_local_set_pending(struct batadv_priv *bat_priv,
1229 struct batadv_tt_local_entry *tt_local_entry,
1230 u16 flags, const char *message)
1231 {
1232 batadv_tt_local_event(bat_priv, tt_local_entry, flags);
1233
1234 /* The local client has to be marked as "pending to be removed" but has
1235 * to be kept in the table in order to send it in a full table
1236 * response issued before the net ttvn increment (consistency check)
1237 */
1238 tt_local_entry->common.flags |= BATADV_TT_CLIENT_PENDING;
1239
1240 batadv_dbg(BATADV_DBG_TT, bat_priv,
1241 "Local tt entry (%pM, vid: %d) pending to be removed: %s\n",
1242 tt_local_entry->common.addr,
1243 batadv_print_vid(tt_local_entry->common.vid), message);
1244 }
1245
1246 /**
1247 * batadv_tt_local_remove() - logically remove an entry from the local table
1248 * @bat_priv: the bat priv with all the mesh interface information
1249 * @addr: the MAC address of the client to remove
1250 * @vid: VLAN identifier
1251 * @message: message to append to the log on deletion
1252 * @roaming: true if the deletion is due to a roaming event
1253 *
1254 * Return: the flags assigned to the local entry before being deleted
1255 */
batadv_tt_local_remove(struct batadv_priv * bat_priv,const u8 * addr,unsigned short vid,const char * message,bool roaming)1256 u16 batadv_tt_local_remove(struct batadv_priv *bat_priv, const u8 *addr,
1257 unsigned short vid, const char *message,
1258 bool roaming)
1259 {
1260 struct batadv_tt_local_entry *tt_removed_entry;
1261 struct batadv_tt_local_entry *tt_local_entry;
1262 u16 flags, curr_flags = BATADV_NO_FLAGS;
1263 struct hlist_node *tt_removed_node;
1264
1265 tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr, vid);
1266 if (!tt_local_entry)
1267 goto out;
1268
1269 curr_flags = tt_local_entry->common.flags;
1270
1271 flags = BATADV_TT_CLIENT_DEL;
1272 /* if this global entry addition is due to a roaming, the node has to
1273 * mark the local entry as "roamed" in order to correctly reroute
1274 * packets later
1275 */
1276 if (roaming) {
1277 flags |= BATADV_TT_CLIENT_ROAM;
1278 /* mark the local client as ROAMed */
1279 tt_local_entry->common.flags |= BATADV_TT_CLIENT_ROAM;
1280 }
1281
1282 if (!(tt_local_entry->common.flags & BATADV_TT_CLIENT_NEW)) {
1283 batadv_tt_local_set_pending(bat_priv, tt_local_entry, flags,
1284 message);
1285 goto out;
1286 }
1287 /* if this client has been added right now, it is possible to
1288 * immediately purge it
1289 */
1290 batadv_tt_local_event(bat_priv, tt_local_entry, BATADV_TT_CLIENT_DEL);
1291
1292 tt_removed_node = batadv_hash_remove(bat_priv->tt.local_hash,
1293 batadv_compare_tt,
1294 batadv_choose_tt,
1295 &tt_local_entry->common);
1296 if (!tt_removed_node)
1297 goto out;
1298
1299 /* drop reference of remove hash entry */
1300 tt_removed_entry = hlist_entry(tt_removed_node,
1301 struct batadv_tt_local_entry,
1302 common.hash_entry);
1303 batadv_tt_local_entry_put(tt_removed_entry);
1304
1305 out:
1306 batadv_tt_local_entry_put(tt_local_entry);
1307
1308 return curr_flags;
1309 }
1310
1311 /**
1312 * batadv_tt_local_purge_list() - purge inactive tt local entries
1313 * @bat_priv: the bat priv with all the mesh interface information
1314 * @head: pointer to the list containing the local tt entries
1315 * @timeout: parameter deciding whether a given tt local entry is considered
1316 * inactive or not
1317 */
batadv_tt_local_purge_list(struct batadv_priv * bat_priv,struct hlist_head * head,int timeout)1318 static void batadv_tt_local_purge_list(struct batadv_priv *bat_priv,
1319 struct hlist_head *head,
1320 int timeout)
1321 {
1322 struct batadv_tt_local_entry *tt_local_entry;
1323 struct batadv_tt_common_entry *tt_common_entry;
1324 struct hlist_node *node_tmp;
1325
1326 hlist_for_each_entry_safe(tt_common_entry, node_tmp, head,
1327 hash_entry) {
1328 tt_local_entry = container_of(tt_common_entry,
1329 struct batadv_tt_local_entry,
1330 common);
1331 if (tt_local_entry->common.flags & BATADV_TT_CLIENT_NOPURGE)
1332 continue;
1333
1334 /* entry already marked for deletion */
1335 if (tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING)
1336 continue;
1337
1338 if (!batadv_has_timed_out(tt_local_entry->last_seen, timeout))
1339 continue;
1340
1341 batadv_tt_local_set_pending(bat_priv, tt_local_entry,
1342 BATADV_TT_CLIENT_DEL, "timed out");
1343 }
1344 }
1345
1346 /**
1347 * batadv_tt_local_purge() - purge inactive tt local entries
1348 * @bat_priv: the bat priv with all the mesh interface information
1349 * @timeout: parameter deciding whether a given tt local entry is considered
1350 * inactive or not
1351 */
batadv_tt_local_purge(struct batadv_priv * bat_priv,int timeout)1352 static void batadv_tt_local_purge(struct batadv_priv *bat_priv,
1353 int timeout)
1354 {
1355 struct batadv_hashtable *hash = bat_priv->tt.local_hash;
1356 struct hlist_head *head;
1357 spinlock_t *list_lock; /* protects write access to the hash lists */
1358 u32 i;
1359
1360 for (i = 0; i < hash->size; i++) {
1361 head = &hash->table[i];
1362 list_lock = &hash->list_locks[i];
1363
1364 spin_lock_bh(list_lock);
1365 batadv_tt_local_purge_list(bat_priv, head, timeout);
1366 spin_unlock_bh(list_lock);
1367 }
1368 }
1369
batadv_tt_local_table_free(struct batadv_priv * bat_priv)1370 static void batadv_tt_local_table_free(struct batadv_priv *bat_priv)
1371 {
1372 struct batadv_hashtable *hash;
1373 spinlock_t *list_lock; /* protects write access to the hash lists */
1374 struct batadv_tt_common_entry *tt_common_entry;
1375 struct batadv_tt_local_entry *tt_local;
1376 struct hlist_node *node_tmp;
1377 struct hlist_head *head;
1378 u32 i;
1379
1380 if (!bat_priv->tt.local_hash)
1381 return;
1382
1383 hash = bat_priv->tt.local_hash;
1384
1385 for (i = 0; i < hash->size; i++) {
1386 head = &hash->table[i];
1387 list_lock = &hash->list_locks[i];
1388
1389 spin_lock_bh(list_lock);
1390 hlist_for_each_entry_safe(tt_common_entry, node_tmp,
1391 head, hash_entry) {
1392 hlist_del_rcu(&tt_common_entry->hash_entry);
1393 tt_local = container_of(tt_common_entry,
1394 struct batadv_tt_local_entry,
1395 common);
1396
1397 batadv_tt_local_entry_put(tt_local);
1398 }
1399 spin_unlock_bh(list_lock);
1400 }
1401
1402 batadv_hash_destroy(hash);
1403
1404 bat_priv->tt.local_hash = NULL;
1405 }
1406
batadv_tt_global_init(struct batadv_priv * bat_priv)1407 static int batadv_tt_global_init(struct batadv_priv *bat_priv)
1408 {
1409 if (bat_priv->tt.global_hash)
1410 return 0;
1411
1412 bat_priv->tt.global_hash = batadv_hash_new(1024);
1413
1414 if (!bat_priv->tt.global_hash)
1415 return -ENOMEM;
1416
1417 batadv_hash_set_lock_class(bat_priv->tt.global_hash,
1418 &batadv_tt_global_hash_lock_class_key);
1419
1420 return 0;
1421 }
1422
batadv_tt_changes_list_free(struct batadv_priv * bat_priv)1423 static void batadv_tt_changes_list_free(struct batadv_priv *bat_priv)
1424 {
1425 struct batadv_tt_change_node *entry, *safe;
1426
1427 spin_lock_bh(&bat_priv->tt.changes_list_lock);
1428
1429 list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list,
1430 list) {
1431 list_del(&entry->list);
1432 kmem_cache_free(batadv_tt_change_cache, entry);
1433 }
1434
1435 WRITE_ONCE(bat_priv->tt.local_changes, 0);
1436 spin_unlock_bh(&bat_priv->tt.changes_list_lock);
1437 }
1438
1439 /**
1440 * batadv_tt_global_orig_entry_find() - find a TT orig_list_entry
1441 * @entry: the TT global entry where the orig_list_entry has to be
1442 * extracted from
1443 * @orig_node: the originator for which the orig_list_entry has to be found
1444 *
1445 * retrieve the orig_tt_list_entry belonging to orig_node from the
1446 * batadv_tt_global_entry list
1447 *
1448 * Return: it with an increased refcounter, NULL if not found
1449 */
1450 static struct batadv_tt_orig_list_entry *
batadv_tt_global_orig_entry_find(const struct batadv_tt_global_entry * entry,const struct batadv_orig_node * orig_node)1451 batadv_tt_global_orig_entry_find(const struct batadv_tt_global_entry *entry,
1452 const struct batadv_orig_node *orig_node)
1453 {
1454 struct batadv_tt_orig_list_entry *tmp_orig_entry, *orig_entry = NULL;
1455 const struct hlist_head *head;
1456
1457 rcu_read_lock();
1458 head = &entry->orig_list;
1459 hlist_for_each_entry_rcu(tmp_orig_entry, head, list) {
1460 if (tmp_orig_entry->orig_node != orig_node)
1461 continue;
1462 if (!kref_get_unless_zero(&tmp_orig_entry->refcount))
1463 continue;
1464
1465 orig_entry = tmp_orig_entry;
1466 break;
1467 }
1468 rcu_read_unlock();
1469
1470 return orig_entry;
1471 }
1472
1473 /**
1474 * batadv_tt_global_entry_has_orig() - check if a TT global entry is also
1475 * handled by a given originator
1476 * @entry: the TT global entry to check
1477 * @orig_node: the originator to search in the list
1478 * @flags: a pointer to store TT flags for the given @entry received
1479 * from @orig_node
1480 *
1481 * find out if an orig_node is already in the list of a tt_global_entry.
1482 *
1483 * Return: true if found, false otherwise
1484 */
1485 static bool
batadv_tt_global_entry_has_orig(const struct batadv_tt_global_entry * entry,const struct batadv_orig_node * orig_node,u8 * flags)1486 batadv_tt_global_entry_has_orig(const struct batadv_tt_global_entry *entry,
1487 const struct batadv_orig_node *orig_node,
1488 u8 *flags)
1489 {
1490 struct batadv_tt_orig_list_entry *orig_entry;
1491 bool found = false;
1492
1493 orig_entry = batadv_tt_global_orig_entry_find(entry, orig_node);
1494 if (orig_entry) {
1495 found = true;
1496
1497 if (flags)
1498 *flags = orig_entry->flags;
1499
1500 batadv_tt_orig_list_entry_put(orig_entry);
1501 }
1502
1503 return found;
1504 }
1505
1506 /**
1507 * batadv_tt_global_sync_flags() - update TT sync flags
1508 * @tt_global: the TT global entry to update sync flags in
1509 *
1510 * Updates the sync flag bits in the tt_global flag attribute with a logical
1511 * OR of all sync flags from any of its TT orig entries.
1512 */
1513 static void
batadv_tt_global_sync_flags(struct batadv_tt_global_entry * tt_global)1514 batadv_tt_global_sync_flags(struct batadv_tt_global_entry *tt_global)
1515 {
1516 struct batadv_tt_orig_list_entry *orig_entry;
1517 const struct hlist_head *head;
1518 u16 flags = BATADV_NO_FLAGS;
1519
1520 rcu_read_lock();
1521 head = &tt_global->orig_list;
1522 hlist_for_each_entry_rcu(orig_entry, head, list)
1523 flags |= orig_entry->flags;
1524 rcu_read_unlock();
1525
1526 flags |= tt_global->common.flags & (~BATADV_TT_SYNC_MASK);
1527 tt_global->common.flags = flags;
1528 }
1529
1530 /**
1531 * batadv_tt_global_orig_entry_add() - add or update a TT orig entry
1532 * @tt_global: the TT global entry to add an orig entry in
1533 * @orig_node: the originator to add an orig entry for
1534 * @ttvn: translation table version number of this changeset
1535 * @flags: TT sync flags
1536 */
1537 static void
batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry * tt_global,struct batadv_orig_node * orig_node,int ttvn,u8 flags)1538 batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global,
1539 struct batadv_orig_node *orig_node, int ttvn,
1540 u8 flags)
1541 {
1542 struct batadv_tt_orig_list_entry *orig_entry;
1543
1544 spin_lock_bh(&tt_global->list_lock);
1545
1546 orig_entry = batadv_tt_global_orig_entry_find(tt_global, orig_node);
1547 if (orig_entry) {
1548 /* refresh the ttvn: the current value could be a bogus one that
1549 * was added during a "temporary client detection"
1550 */
1551 orig_entry->ttvn = ttvn;
1552 orig_entry->flags = flags;
1553 goto sync_flags;
1554 }
1555
1556 orig_entry = kmem_cache_zalloc(batadv_tt_orig_cache, GFP_ATOMIC);
1557 if (!orig_entry)
1558 goto out;
1559
1560 INIT_HLIST_NODE(&orig_entry->list);
1561 kref_get(&orig_node->refcount);
1562 batadv_tt_global_size_inc(orig_node, tt_global->common.vid);
1563 orig_entry->orig_node = orig_node;
1564 orig_entry->ttvn = ttvn;
1565 orig_entry->flags = flags;
1566 kref_init(&orig_entry->refcount);
1567
1568 kref_get(&orig_entry->refcount);
1569 hlist_add_head_rcu(&orig_entry->list,
1570 &tt_global->orig_list);
1571 atomic_inc(&tt_global->orig_list_count);
1572
1573 sync_flags:
1574 batadv_tt_global_sync_flags(tt_global);
1575 out:
1576 batadv_tt_orig_list_entry_put(orig_entry);
1577
1578 spin_unlock_bh(&tt_global->list_lock);
1579 }
1580
1581 /**
1582 * batadv_tt_global_add() - add a new TT global entry or update an existing one
1583 * @bat_priv: the bat priv with all the mesh interface information
1584 * @orig_node: the originator announcing the client
1585 * @tt_addr: the mac address of the non-mesh client
1586 * @vid: VLAN identifier
1587 * @flags: TT flags that have to be set for this non-mesh client
1588 * @ttvn: the tt version number ever announcing this non-mesh client
1589 *
1590 * Add a new TT global entry for the given originator. If the entry already
1591 * exists add a new reference to the given originator (a global entry can have
1592 * references to multiple originators) and adjust the flags attribute to reflect
1593 * the function argument.
1594 * If a TT local entry exists for this non-mesh client remove it.
1595 *
1596 * The caller must hold the orig_node refcount.
1597 *
1598 * Return: true if the new entry has been added, false otherwise
1599 */
batadv_tt_global_add(struct batadv_priv * bat_priv,struct batadv_orig_node * orig_node,const unsigned char * tt_addr,unsigned short vid,u16 flags,u8 ttvn)1600 static bool batadv_tt_global_add(struct batadv_priv *bat_priv,
1601 struct batadv_orig_node *orig_node,
1602 const unsigned char *tt_addr,
1603 unsigned short vid, u16 flags, u8 ttvn)
1604 {
1605 struct batadv_tt_global_entry *tt_global_entry;
1606 struct batadv_tt_local_entry *tt_local_entry;
1607 bool ret = false;
1608 int hash_added;
1609 struct batadv_tt_common_entry *common;
1610 u16 local_flags;
1611
1612 /* ignore global entries from backbone nodes */
1613 if (batadv_bla_is_backbone_gw_orig(bat_priv, orig_node->orig, vid))
1614 return true;
1615
1616 tt_global_entry = batadv_tt_global_hash_find(bat_priv, tt_addr, vid);
1617 tt_local_entry = batadv_tt_local_hash_find(bat_priv, tt_addr, vid);
1618
1619 /* if the node already has a local client for this entry, it has to wait
1620 * for a roaming advertisement instead of manually messing up the global
1621 * table
1622 */
1623 if ((flags & BATADV_TT_CLIENT_TEMP) && tt_local_entry &&
1624 !(tt_local_entry->common.flags & BATADV_TT_CLIENT_NEW))
1625 goto out;
1626
1627 if (!tt_global_entry) {
1628 tt_global_entry = kmem_cache_zalloc(batadv_tg_cache,
1629 GFP_ATOMIC);
1630 if (!tt_global_entry)
1631 goto out;
1632
1633 common = &tt_global_entry->common;
1634 ether_addr_copy(common->addr, tt_addr);
1635 common->vid = vid;
1636
1637 if (!is_multicast_ether_addr(common->addr))
1638 common->flags = flags & (~BATADV_TT_SYNC_MASK);
1639
1640 tt_global_entry->roam_at = 0;
1641 /* node must store current time in case of roaming. This is
1642 * needed to purge this entry out on timeout (if nobody claims
1643 * it)
1644 */
1645 if (flags & BATADV_TT_CLIENT_ROAM)
1646 tt_global_entry->roam_at = jiffies;
1647 kref_init(&common->refcount);
1648 common->added_at = jiffies;
1649
1650 INIT_HLIST_HEAD(&tt_global_entry->orig_list);
1651 atomic_set(&tt_global_entry->orig_list_count, 0);
1652 spin_lock_init(&tt_global_entry->list_lock);
1653
1654 kref_get(&common->refcount);
1655 hash_added = batadv_hash_add(bat_priv->tt.global_hash,
1656 batadv_compare_tt,
1657 batadv_choose_tt, common,
1658 &common->hash_entry);
1659
1660 if (unlikely(hash_added != 0)) {
1661 /* remove the reference for the hash */
1662 batadv_tt_global_entry_put(tt_global_entry);
1663 goto out_remove;
1664 }
1665 } else {
1666 common = &tt_global_entry->common;
1667 /* If there is already a global entry, we can use this one for
1668 * our processing.
1669 * But if we are trying to add a temporary client then here are
1670 * two options at this point:
1671 * 1) the global client is not a temporary client: the global
1672 * client has to be left as it is, temporary information
1673 * should never override any already known client state
1674 * 2) the global client is a temporary client: purge the
1675 * originator list and add the new one orig_entry
1676 */
1677 if (flags & BATADV_TT_CLIENT_TEMP) {
1678 if (!(common->flags & BATADV_TT_CLIENT_TEMP))
1679 goto out;
1680 if (batadv_tt_global_entry_has_orig(tt_global_entry,
1681 orig_node, NULL))
1682 goto out_remove;
1683 batadv_tt_global_del_orig_list(tt_global_entry);
1684 goto add_orig_entry;
1685 }
1686
1687 /* if the client was temporary added before receiving the first
1688 * OGM announcing it, we have to clear the TEMP flag. Also,
1689 * remove the previous temporary orig node and re-add it
1690 * if required. If the orig entry changed, the new one which
1691 * is a non-temporary entry is preferred.
1692 */
1693 if (common->flags & BATADV_TT_CLIENT_TEMP) {
1694 batadv_tt_global_del_orig_list(tt_global_entry);
1695 common->flags &= ~BATADV_TT_CLIENT_TEMP;
1696 }
1697
1698 /* the change can carry possible "attribute" flags like the
1699 * TT_CLIENT_TEMP, therefore they have to be copied in the
1700 * client entry
1701 */
1702 if (!is_multicast_ether_addr(common->addr))
1703 common->flags |= flags & (~BATADV_TT_SYNC_MASK);
1704
1705 /* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only
1706 * one originator left in the list and we previously received a
1707 * delete + roaming change for this originator.
1708 *
1709 * We should first delete the old originator before adding the
1710 * new one.
1711 */
1712 if (common->flags & BATADV_TT_CLIENT_ROAM) {
1713 batadv_tt_global_del_orig_list(tt_global_entry);
1714 common->flags &= ~BATADV_TT_CLIENT_ROAM;
1715 tt_global_entry->roam_at = 0;
1716 }
1717 }
1718 add_orig_entry:
1719 /* add the new orig_entry (if needed) or update it */
1720 batadv_tt_global_orig_entry_add(tt_global_entry, orig_node, ttvn,
1721 flags & BATADV_TT_SYNC_MASK);
1722
1723 batadv_dbg(BATADV_DBG_TT, bat_priv,
1724 "Creating new global tt entry: %pM (vid: %d, via %pM)\n",
1725 common->addr, batadv_print_vid(common->vid),
1726 orig_node->orig);
1727 ret = true;
1728
1729 out_remove:
1730 /* Do not remove multicast addresses from the local hash on
1731 * global additions
1732 */
1733 if (is_multicast_ether_addr(tt_addr))
1734 goto out;
1735
1736 /* remove address from local hash if present */
1737 local_flags = batadv_tt_local_remove(bat_priv, tt_addr, vid,
1738 "global tt received",
1739 flags & BATADV_TT_CLIENT_ROAM);
1740 tt_global_entry->common.flags |= local_flags & BATADV_TT_CLIENT_WIFI;
1741
1742 if (!(flags & BATADV_TT_CLIENT_ROAM))
1743 /* this is a normal global add. Therefore the client is not in a
1744 * roaming state anymore.
1745 */
1746 tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_ROAM;
1747
1748 out:
1749 batadv_tt_global_entry_put(tt_global_entry);
1750 batadv_tt_local_entry_put(tt_local_entry);
1751 return ret;
1752 }
1753
1754 /**
1755 * batadv_transtable_best_orig() - Get best originator list entry from tt entry
1756 * @bat_priv: the bat priv with all the mesh interface information
1757 * @tt_global_entry: global translation table entry to be analyzed
1758 *
1759 * This function assumes the caller holds rcu_read_lock().
1760 * Return: best originator list entry or NULL on errors.
1761 */
1762 static struct batadv_tt_orig_list_entry *
batadv_transtable_best_orig(struct batadv_priv * bat_priv,struct batadv_tt_global_entry * tt_global_entry)1763 batadv_transtable_best_orig(struct batadv_priv *bat_priv,
1764 struct batadv_tt_global_entry *tt_global_entry)
1765 {
1766 struct batadv_neigh_node *router, *best_router = NULL;
1767 struct batadv_algo_ops *bao = bat_priv->algo_ops;
1768 struct hlist_head *head;
1769 struct batadv_tt_orig_list_entry *orig_entry, *best_entry = NULL;
1770
1771 head = &tt_global_entry->orig_list;
1772 hlist_for_each_entry_rcu(orig_entry, head, list) {
1773 router = batadv_orig_router_get(orig_entry->orig_node,
1774 BATADV_IF_DEFAULT);
1775 if (!router)
1776 continue;
1777
1778 if (best_router &&
1779 bao->neigh.cmp(router, BATADV_IF_DEFAULT, best_router,
1780 BATADV_IF_DEFAULT) <= 0) {
1781 batadv_neigh_node_put(router);
1782 continue;
1783 }
1784
1785 /* release the refcount for the "old" best */
1786 batadv_neigh_node_put(best_router);
1787
1788 best_entry = orig_entry;
1789 best_router = router;
1790 }
1791
1792 batadv_neigh_node_put(best_router);
1793
1794 return best_entry;
1795 }
1796
1797 /**
1798 * batadv_tt_global_dump_subentry() - Dump all TT local entries into a message
1799 * @msg: Netlink message to dump into
1800 * @portid: Port making netlink request
1801 * @seq: Sequence number of netlink message
1802 * @common: tt local & tt global common data
1803 * @orig: Originator node announcing a non-mesh client
1804 * @best: Is the best originator for the TT entry
1805 *
1806 * Return: Error code, or 0 on success
1807 */
1808 static int
batadv_tt_global_dump_subentry(struct sk_buff * msg,u32 portid,u32 seq,struct batadv_tt_common_entry * common,struct batadv_tt_orig_list_entry * orig,bool best)1809 batadv_tt_global_dump_subentry(struct sk_buff *msg, u32 portid, u32 seq,
1810 struct batadv_tt_common_entry *common,
1811 struct batadv_tt_orig_list_entry *orig,
1812 bool best)
1813 {
1814 u16 flags = (common->flags & (~BATADV_TT_SYNC_MASK)) | orig->flags;
1815 void *hdr;
1816 struct batadv_orig_node_vlan *vlan;
1817 u8 last_ttvn;
1818 u32 crc;
1819
1820 vlan = batadv_orig_node_vlan_get(orig->orig_node,
1821 common->vid);
1822 if (!vlan)
1823 return 0;
1824
1825 crc = vlan->tt.crc;
1826
1827 batadv_orig_node_vlan_put(vlan);
1828
1829 hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family,
1830 NLM_F_MULTI,
1831 BATADV_CMD_GET_TRANSTABLE_GLOBAL);
1832 if (!hdr)
1833 return -ENOBUFS;
1834
1835 last_ttvn = READ_ONCE(orig->orig_node->last_ttvn);
1836
1837 if (nla_put(msg, BATADV_ATTR_TT_ADDRESS, ETH_ALEN, common->addr) ||
1838 nla_put(msg, BATADV_ATTR_ORIG_ADDRESS, ETH_ALEN,
1839 orig->orig_node->orig) ||
1840 nla_put_u8(msg, BATADV_ATTR_TT_TTVN, orig->ttvn) ||
1841 nla_put_u8(msg, BATADV_ATTR_TT_LAST_TTVN, last_ttvn) ||
1842 nla_put_u32(msg, BATADV_ATTR_TT_CRC32, crc) ||
1843 nla_put_u16(msg, BATADV_ATTR_TT_VID, common->vid) ||
1844 nla_put_u32(msg, BATADV_ATTR_TT_FLAGS, flags))
1845 goto nla_put_failure;
1846
1847 if (best && nla_put_flag(msg, BATADV_ATTR_FLAG_BEST))
1848 goto nla_put_failure;
1849
1850 genlmsg_end(msg, hdr);
1851 return 0;
1852
1853 nla_put_failure:
1854 genlmsg_cancel(msg, hdr);
1855 return -EMSGSIZE;
1856 }
1857
1858 /**
1859 * batadv_tt_global_dump_entry() - Dump one TT global entry into a message
1860 * @msg: Netlink message to dump into
1861 * @portid: Port making netlink request
1862 * @seq: Sequence number of netlink message
1863 * @bat_priv: The bat priv with all the mesh interface information
1864 * @common: tt local & tt global common data
1865 * @sub_s: Number of entries to skip
1866 *
1867 * This function assumes the caller holds rcu_read_lock().
1868 *
1869 * Return: Error code, or 0 on success
1870 */
1871 static int
batadv_tt_global_dump_entry(struct sk_buff * msg,u32 portid,u32 seq,struct batadv_priv * bat_priv,struct batadv_tt_common_entry * common,int * sub_s)1872 batadv_tt_global_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
1873 struct batadv_priv *bat_priv,
1874 struct batadv_tt_common_entry *common, int *sub_s)
1875 {
1876 struct batadv_tt_orig_list_entry *orig_entry, *best_entry;
1877 struct batadv_tt_global_entry *global;
1878 struct hlist_head *head;
1879 int sub = 0;
1880 bool best;
1881
1882 global = container_of(common, struct batadv_tt_global_entry, common);
1883 best_entry = batadv_transtable_best_orig(bat_priv, global);
1884 head = &global->orig_list;
1885
1886 hlist_for_each_entry_rcu(orig_entry, head, list) {
1887 if (sub++ < *sub_s)
1888 continue;
1889
1890 best = (orig_entry == best_entry);
1891
1892 if (batadv_tt_global_dump_subentry(msg, portid, seq, common,
1893 orig_entry, best)) {
1894 *sub_s = sub - 1;
1895 return -EMSGSIZE;
1896 }
1897 }
1898
1899 *sub_s = 0;
1900 return 0;
1901 }
1902
1903 /**
1904 * batadv_tt_global_dump_bucket() - Dump one TT local bucket into a message
1905 * @msg: Netlink message to dump into
1906 * @portid: Port making netlink request
1907 * @seq: Sequence number of netlink message
1908 * @bat_priv: The bat priv with all the mesh interface information
1909 * @head: Pointer to the list containing the global tt entries
1910 * @idx_s: Number of entries to skip
1911 * @sub: Number of entries to skip
1912 *
1913 * Return: Error code, or 0 on success
1914 */
1915 static int
batadv_tt_global_dump_bucket(struct sk_buff * msg,u32 portid,u32 seq,struct batadv_priv * bat_priv,struct hlist_head * head,int * idx_s,int * sub)1916 batadv_tt_global_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq,
1917 struct batadv_priv *bat_priv,
1918 struct hlist_head *head, int *idx_s, int *sub)
1919 {
1920 struct batadv_tt_common_entry *common;
1921 int idx = 0;
1922
1923 rcu_read_lock();
1924 hlist_for_each_entry_rcu(common, head, hash_entry) {
1925 if (idx++ < *idx_s)
1926 continue;
1927
1928 if (batadv_tt_global_dump_entry(msg, portid, seq, bat_priv,
1929 common, sub)) {
1930 rcu_read_unlock();
1931 *idx_s = idx - 1;
1932 return -EMSGSIZE;
1933 }
1934 }
1935 rcu_read_unlock();
1936
1937 *idx_s = 0;
1938 *sub = 0;
1939 return 0;
1940 }
1941
1942 /**
1943 * batadv_tt_global_dump() - Dump TT global entries into a message
1944 * @msg: Netlink message to dump into
1945 * @cb: Parameters from query
1946 *
1947 * Return: Error code, or length of message on success
1948 */
batadv_tt_global_dump(struct sk_buff * msg,struct netlink_callback * cb)1949 int batadv_tt_global_dump(struct sk_buff *msg, struct netlink_callback *cb)
1950 {
1951 struct net_device *mesh_iface;
1952 struct batadv_priv *bat_priv;
1953 struct batadv_hard_iface *primary_if = NULL;
1954 struct batadv_hashtable *hash;
1955 struct hlist_head *head;
1956 int ret;
1957 int bucket = cb->args[0];
1958 int idx = cb->args[1];
1959 int sub = cb->args[2];
1960 int portid = NETLINK_CB(cb->skb).portid;
1961
1962 mesh_iface = batadv_netlink_get_meshif(cb);
1963 if (IS_ERR(mesh_iface))
1964 return PTR_ERR(mesh_iface);
1965
1966 bat_priv = netdev_priv(mesh_iface);
1967
1968 primary_if = batadv_primary_if_get_selected(bat_priv);
1969 if (!primary_if || primary_if->if_status != BATADV_IF_ACTIVE) {
1970 ret = -ENOENT;
1971 goto out;
1972 }
1973
1974 hash = bat_priv->tt.global_hash;
1975
1976 while (bucket < hash->size) {
1977 head = &hash->table[bucket];
1978
1979 if (batadv_tt_global_dump_bucket(msg, portid,
1980 cb->nlh->nlmsg_seq, bat_priv,
1981 head, &idx, &sub))
1982 break;
1983
1984 bucket++;
1985 }
1986
1987 ret = msg->len;
1988
1989 out:
1990 batadv_hardif_put(primary_if);
1991 dev_put(mesh_iface);
1992
1993 cb->args[0] = bucket;
1994 cb->args[1] = idx;
1995 cb->args[2] = sub;
1996
1997 return ret;
1998 }
1999
2000 /**
2001 * _batadv_tt_global_del_orig_entry() - remove and free an orig_entry
2002 * @tt_global_entry: the global entry to remove the orig_entry from
2003 * @orig_entry: the orig entry to remove and free
2004 *
2005 * Remove an orig_entry from its list in the given tt_global_entry and
2006 * free this orig_entry afterwards.
2007 *
2008 * Caller must hold tt_global_entry->list_lock and ensure orig_entry->list is
2009 * part of a list.
2010 */
2011 static void
_batadv_tt_global_del_orig_entry(struct batadv_tt_global_entry * tt_global_entry,struct batadv_tt_orig_list_entry * orig_entry)2012 _batadv_tt_global_del_orig_entry(struct batadv_tt_global_entry *tt_global_entry,
2013 struct batadv_tt_orig_list_entry *orig_entry)
2014 {
2015 lockdep_assert_held(&tt_global_entry->list_lock);
2016
2017 batadv_tt_global_size_dec(orig_entry->orig_node,
2018 tt_global_entry->common.vid);
2019 atomic_dec(&tt_global_entry->orig_list_count);
2020 /* requires holding tt_global_entry->list_lock and orig_entry->list
2021 * being part of a list
2022 */
2023 hlist_del_rcu(&orig_entry->list);
2024 batadv_tt_orig_list_entry_put(orig_entry);
2025 }
2026
2027 /* deletes the orig list of a tt_global_entry */
2028 static void
batadv_tt_global_del_orig_list(struct batadv_tt_global_entry * tt_global_entry)2029 batadv_tt_global_del_orig_list(struct batadv_tt_global_entry *tt_global_entry)
2030 {
2031 struct hlist_head *head;
2032 struct hlist_node *safe;
2033 struct batadv_tt_orig_list_entry *orig_entry;
2034
2035 spin_lock_bh(&tt_global_entry->list_lock);
2036 head = &tt_global_entry->orig_list;
2037 hlist_for_each_entry_safe(orig_entry, safe, head, list)
2038 _batadv_tt_global_del_orig_entry(tt_global_entry, orig_entry);
2039 spin_unlock_bh(&tt_global_entry->list_lock);
2040 }
2041
2042 /**
2043 * batadv_tt_global_del_orig_node() - remove orig_node from a global tt entry
2044 * @bat_priv: the bat priv with all the mesh interface information
2045 * @tt_global_entry: the global entry to remove the orig_node from
2046 * @orig_node: the originator announcing the client
2047 * @message: message to append to the log on deletion
2048 *
2049 * Remove the given orig_node and its according orig_entry from the given
2050 * global tt entry.
2051 */
2052 static void
batadv_tt_global_del_orig_node(struct batadv_priv * bat_priv,struct batadv_tt_global_entry * tt_global_entry,struct batadv_orig_node * orig_node,const char * message)2053 batadv_tt_global_del_orig_node(struct batadv_priv *bat_priv,
2054 struct batadv_tt_global_entry *tt_global_entry,
2055 struct batadv_orig_node *orig_node,
2056 const char *message)
2057 {
2058 struct hlist_head *head;
2059 struct hlist_node *safe;
2060 struct batadv_tt_orig_list_entry *orig_entry;
2061 unsigned short vid;
2062
2063 spin_lock_bh(&tt_global_entry->list_lock);
2064 head = &tt_global_entry->orig_list;
2065 hlist_for_each_entry_safe(orig_entry, safe, head, list) {
2066 if (orig_entry->orig_node == orig_node) {
2067 vid = tt_global_entry->common.vid;
2068 batadv_dbg(BATADV_DBG_TT, bat_priv,
2069 "Deleting %pM from global tt entry %pM (vid: %d): %s\n",
2070 orig_node->orig,
2071 tt_global_entry->common.addr,
2072 batadv_print_vid(vid), message);
2073 _batadv_tt_global_del_orig_entry(tt_global_entry,
2074 orig_entry);
2075 }
2076 }
2077 spin_unlock_bh(&tt_global_entry->list_lock);
2078 }
2079
2080 /* If the client is to be deleted, we check if it is the last origantor entry
2081 * within tt_global entry. If yes, we set the BATADV_TT_CLIENT_ROAM flag and the
2082 * timer, otherwise we simply remove the originator scheduled for deletion.
2083 */
2084 static void
batadv_tt_global_del_roaming(struct batadv_priv * bat_priv,struct batadv_tt_global_entry * tt_global_entry,struct batadv_orig_node * orig_node,const char * message)2085 batadv_tt_global_del_roaming(struct batadv_priv *bat_priv,
2086 struct batadv_tt_global_entry *tt_global_entry,
2087 struct batadv_orig_node *orig_node,
2088 const char *message)
2089 {
2090 bool last_entry = true;
2091 struct hlist_head *head;
2092 struct batadv_tt_orig_list_entry *orig_entry;
2093
2094 /* no local entry exists, case 1:
2095 * Check if this is the last one or if other entries exist.
2096 */
2097
2098 rcu_read_lock();
2099 head = &tt_global_entry->orig_list;
2100 hlist_for_each_entry_rcu(orig_entry, head, list) {
2101 if (orig_entry->orig_node != orig_node) {
2102 last_entry = false;
2103 break;
2104 }
2105 }
2106 rcu_read_unlock();
2107
2108 if (last_entry) {
2109 /* its the last one, mark for roaming. */
2110 tt_global_entry->common.flags |= BATADV_TT_CLIENT_ROAM;
2111 tt_global_entry->roam_at = jiffies;
2112 } else {
2113 /* there is another entry, we can simply delete this
2114 * one and can still use the other one.
2115 */
2116 batadv_tt_global_del_orig_node(bat_priv, tt_global_entry,
2117 orig_node, message);
2118 }
2119 }
2120
2121 /**
2122 * batadv_tt_global_del() - remove a client from the global table
2123 * @bat_priv: the bat priv with all the mesh interface information
2124 * @orig_node: an originator serving this client
2125 * @addr: the mac address of the client
2126 * @vid: VLAN identifier
2127 * @message: a message explaining the reason for deleting the client to print
2128 * for debugging purpose
2129 * @roaming: true if the deletion has been triggered by a roaming event
2130 */
batadv_tt_global_del(struct batadv_priv * bat_priv,struct batadv_orig_node * orig_node,const unsigned char * addr,unsigned short vid,const char * message,bool roaming)2131 static void batadv_tt_global_del(struct batadv_priv *bat_priv,
2132 struct batadv_orig_node *orig_node,
2133 const unsigned char *addr, unsigned short vid,
2134 const char *message, bool roaming)
2135 {
2136 struct batadv_tt_global_entry *tt_global_entry;
2137 struct batadv_tt_local_entry *local_entry = NULL;
2138
2139 tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr, vid);
2140 if (!tt_global_entry)
2141 goto out;
2142
2143 if (!roaming) {
2144 batadv_tt_global_del_orig_node(bat_priv, tt_global_entry,
2145 orig_node, message);
2146
2147 if (hlist_empty(&tt_global_entry->orig_list))
2148 batadv_tt_global_free(bat_priv, tt_global_entry,
2149 message);
2150
2151 goto out;
2152 }
2153
2154 /* if we are deleting a global entry due to a roam
2155 * event, there are two possibilities:
2156 * 1) the client roamed from node A to node B => if there
2157 * is only one originator left for this client, we mark
2158 * it with BATADV_TT_CLIENT_ROAM, we start a timer and we
2159 * wait for node B to claim it. In case of timeout
2160 * the entry is purged.
2161 *
2162 * If there are other originators left, we directly delete
2163 * the originator.
2164 * 2) the client roamed to us => we can directly delete
2165 * the global entry, since it is useless now.
2166 */
2167 local_entry = batadv_tt_local_hash_find(bat_priv,
2168 tt_global_entry->common.addr,
2169 vid);
2170 if (local_entry) {
2171 /* local entry exists, case 2: client roamed to us. */
2172 batadv_tt_global_del_orig_list(tt_global_entry);
2173 batadv_tt_global_free(bat_priv, tt_global_entry, message);
2174 } else {
2175 /* no local entry exists, case 1: check for roaming */
2176 batadv_tt_global_del_roaming(bat_priv, tt_global_entry,
2177 orig_node, message);
2178 }
2179
2180 out:
2181 batadv_tt_global_entry_put(tt_global_entry);
2182 batadv_tt_local_entry_put(local_entry);
2183 }
2184
2185 /**
2186 * batadv_tt_global_del_orig() - remove all the TT global entries belonging to
2187 * the given originator matching the provided vid
2188 * @bat_priv: the bat priv with all the mesh interface information
2189 * @orig_node: the originator owning the entries to remove
2190 * @match_vid: the VLAN identifier to match. If negative all the entries will be
2191 * removed
2192 * @message: debug message to print as "reason"
2193 */
batadv_tt_global_del_orig(struct batadv_priv * bat_priv,struct batadv_orig_node * orig_node,s32 match_vid,const char * message)2194 void batadv_tt_global_del_orig(struct batadv_priv *bat_priv,
2195 struct batadv_orig_node *orig_node,
2196 s32 match_vid,
2197 const char *message)
2198 {
2199 struct batadv_tt_global_entry *tt_global;
2200 struct batadv_tt_common_entry *tt_common_entry;
2201 u32 i;
2202 struct batadv_hashtable *hash = bat_priv->tt.global_hash;
2203 struct hlist_node *safe;
2204 struct hlist_head *head;
2205 spinlock_t *list_lock; /* protects write access to the hash lists */
2206 unsigned short vid;
2207
2208 if (!hash)
2209 return;
2210
2211 for (i = 0; i < hash->size; i++) {
2212 head = &hash->table[i];
2213 list_lock = &hash->list_locks[i];
2214
2215 spin_lock_bh(list_lock);
2216 hlist_for_each_entry_safe(tt_common_entry, safe,
2217 head, hash_entry) {
2218 /* remove only matching entries */
2219 if (match_vid >= 0 && tt_common_entry->vid != match_vid)
2220 continue;
2221
2222 tt_global = container_of(tt_common_entry,
2223 struct batadv_tt_global_entry,
2224 common);
2225
2226 batadv_tt_global_del_orig_node(bat_priv, tt_global,
2227 orig_node, message);
2228
2229 if (hlist_empty(&tt_global->orig_list)) {
2230 vid = tt_global->common.vid;
2231 batadv_dbg(BATADV_DBG_TT, bat_priv,
2232 "Deleting global tt entry %pM (vid: %d): %s\n",
2233 tt_global->common.addr,
2234 batadv_print_vid(vid), message);
2235 hlist_del_rcu(&tt_common_entry->hash_entry);
2236 batadv_tt_global_entry_put(tt_global);
2237 }
2238 }
2239 spin_unlock_bh(list_lock);
2240 }
2241 clear_bit(BATADV_ORIG_CAPA_HAS_TT, &orig_node->capa_initialized);
2242 }
2243
batadv_tt_global_to_purge(struct batadv_tt_global_entry * tt_global,char ** msg)2244 static bool batadv_tt_global_to_purge(struct batadv_tt_global_entry *tt_global,
2245 char **msg)
2246 {
2247 bool purge = false;
2248 unsigned long roam_timeout = BATADV_TT_CLIENT_ROAM_TIMEOUT;
2249 unsigned long temp_timeout = BATADV_TT_CLIENT_TEMP_TIMEOUT;
2250
2251 if ((tt_global->common.flags & BATADV_TT_CLIENT_ROAM) &&
2252 batadv_has_timed_out(tt_global->roam_at, roam_timeout)) {
2253 purge = true;
2254 *msg = "Roaming timeout\n";
2255 }
2256
2257 if ((tt_global->common.flags & BATADV_TT_CLIENT_TEMP) &&
2258 batadv_has_timed_out(tt_global->common.added_at, temp_timeout)) {
2259 purge = true;
2260 *msg = "Temporary client timeout\n";
2261 }
2262
2263 return purge;
2264 }
2265
batadv_tt_global_purge(struct batadv_priv * bat_priv)2266 static void batadv_tt_global_purge(struct batadv_priv *bat_priv)
2267 {
2268 struct batadv_hashtable *hash = bat_priv->tt.global_hash;
2269 struct hlist_head *head;
2270 struct hlist_node *node_tmp;
2271 spinlock_t *list_lock; /* protects write access to the hash lists */
2272 u32 i;
2273 char *msg = NULL;
2274 struct batadv_tt_common_entry *tt_common;
2275 struct batadv_tt_global_entry *tt_global;
2276
2277 for (i = 0; i < hash->size; i++) {
2278 head = &hash->table[i];
2279 list_lock = &hash->list_locks[i];
2280
2281 spin_lock_bh(list_lock);
2282 hlist_for_each_entry_safe(tt_common, node_tmp, head,
2283 hash_entry) {
2284 tt_global = container_of(tt_common,
2285 struct batadv_tt_global_entry,
2286 common);
2287
2288 if (!batadv_tt_global_to_purge(tt_global, &msg))
2289 continue;
2290
2291 batadv_dbg(BATADV_DBG_TT, bat_priv,
2292 "Deleting global tt entry %pM (vid: %d): %s\n",
2293 tt_global->common.addr,
2294 batadv_print_vid(tt_global->common.vid),
2295 msg);
2296
2297 hlist_del_rcu(&tt_common->hash_entry);
2298
2299 batadv_tt_global_entry_put(tt_global);
2300 }
2301 spin_unlock_bh(list_lock);
2302 }
2303 }
2304
batadv_tt_global_table_free(struct batadv_priv * bat_priv)2305 static void batadv_tt_global_table_free(struct batadv_priv *bat_priv)
2306 {
2307 struct batadv_hashtable *hash;
2308 spinlock_t *list_lock; /* protects write access to the hash lists */
2309 struct batadv_tt_common_entry *tt_common_entry;
2310 struct batadv_tt_global_entry *tt_global;
2311 struct hlist_node *node_tmp;
2312 struct hlist_head *head;
2313 u32 i;
2314
2315 if (!bat_priv->tt.global_hash)
2316 return;
2317
2318 hash = bat_priv->tt.global_hash;
2319
2320 for (i = 0; i < hash->size; i++) {
2321 head = &hash->table[i];
2322 list_lock = &hash->list_locks[i];
2323
2324 spin_lock_bh(list_lock);
2325 hlist_for_each_entry_safe(tt_common_entry, node_tmp,
2326 head, hash_entry) {
2327 hlist_del_rcu(&tt_common_entry->hash_entry);
2328 tt_global = container_of(tt_common_entry,
2329 struct batadv_tt_global_entry,
2330 common);
2331 batadv_tt_global_entry_put(tt_global);
2332 }
2333 spin_unlock_bh(list_lock);
2334 }
2335
2336 batadv_hash_destroy(hash);
2337
2338 bat_priv->tt.global_hash = NULL;
2339 }
2340
2341 static bool
_batadv_is_ap_isolated(struct batadv_tt_local_entry * tt_local_entry,struct batadv_tt_global_entry * tt_global_entry)2342 _batadv_is_ap_isolated(struct batadv_tt_local_entry *tt_local_entry,
2343 struct batadv_tt_global_entry *tt_global_entry)
2344 {
2345 if (tt_local_entry->common.flags & BATADV_TT_CLIENT_WIFI &&
2346 tt_global_entry->common.flags & BATADV_TT_CLIENT_WIFI)
2347 return true;
2348
2349 /* check if the two clients are marked as isolated */
2350 if (tt_local_entry->common.flags & BATADV_TT_CLIENT_ISOLA &&
2351 tt_global_entry->common.flags & BATADV_TT_CLIENT_ISOLA)
2352 return true;
2353
2354 return false;
2355 }
2356
2357 /**
2358 * batadv_transtable_search() - get the mesh destination for a given client
2359 * @bat_priv: the bat priv with all the mesh interface information
2360 * @src: mac address of the source client
2361 * @addr: mac address of the destination client
2362 * @vid: VLAN identifier
2363 *
2364 * Return: a pointer to the originator that was selected as destination in the
2365 * mesh for contacting the client 'addr', NULL otherwise.
2366 * In case of multiple originators serving the same client, the function returns
2367 * the best one (best in terms of metric towards the destination node).
2368 *
2369 * If the two clients are AP isolated the function returns NULL.
2370 */
batadv_transtable_search(struct batadv_priv * bat_priv,const u8 * src,const u8 * addr,unsigned short vid)2371 struct batadv_orig_node *batadv_transtable_search(struct batadv_priv *bat_priv,
2372 const u8 *src,
2373 const u8 *addr,
2374 unsigned short vid)
2375 {
2376 struct batadv_tt_local_entry *tt_local_entry = NULL;
2377 struct batadv_tt_global_entry *tt_global_entry = NULL;
2378 struct batadv_orig_node *orig_node = NULL;
2379 struct batadv_tt_orig_list_entry *best_entry;
2380
2381 if (src && batadv_vlan_ap_isola_get(bat_priv, vid)) {
2382 tt_local_entry = batadv_tt_local_hash_find(bat_priv, src, vid);
2383 if (!tt_local_entry ||
2384 (tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING))
2385 goto out;
2386 }
2387
2388 tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr, vid);
2389 if (!tt_global_entry)
2390 goto out;
2391
2392 /* check whether the clients should not communicate due to AP
2393 * isolation
2394 */
2395 if (tt_local_entry &&
2396 _batadv_is_ap_isolated(tt_local_entry, tt_global_entry))
2397 goto out;
2398
2399 rcu_read_lock();
2400 best_entry = batadv_transtable_best_orig(bat_priv, tt_global_entry);
2401 /* found anything? */
2402 if (best_entry)
2403 orig_node = best_entry->orig_node;
2404 if (orig_node && !kref_get_unless_zero(&orig_node->refcount))
2405 orig_node = NULL;
2406 rcu_read_unlock();
2407
2408 out:
2409 batadv_tt_global_entry_put(tt_global_entry);
2410 batadv_tt_local_entry_put(tt_local_entry);
2411
2412 return orig_node;
2413 }
2414
2415 /**
2416 * batadv_tt_global_crc() - calculates the checksum of the local table belonging
2417 * to the given orig_node
2418 * @bat_priv: the bat priv with all the mesh interface information
2419 * @orig_node: originator for which the CRC should be computed
2420 * @vid: VLAN identifier for which the CRC32 has to be computed
2421 *
2422 * This function computes the checksum for the global table corresponding to a
2423 * specific originator. In particular, the checksum is computed as follows: For
2424 * each client connected to the originator the CRC32C of the MAC address and the
2425 * VID is computed and then all the CRC32Cs of the various clients are xor'ed
2426 * together.
2427 *
2428 * The idea behind is that CRC32C should be used as much as possible in order to
2429 * produce a unique hash of the table, but since the order which is used to feed
2430 * the CRC32C function affects the result and since every node in the network
2431 * probably sorts the clients differently, the hash function cannot be directly
2432 * computed over the entire table. Hence the CRC32C is used only on
2433 * the single client entry, while all the results are then xor'ed together
2434 * because the XOR operation can combine them all while trying to reduce the
2435 * noise as much as possible.
2436 *
2437 * Return: the checksum of the global table of a given originator.
2438 */
batadv_tt_global_crc(struct batadv_priv * bat_priv,struct batadv_orig_node * orig_node,unsigned short vid)2439 static u32 batadv_tt_global_crc(struct batadv_priv *bat_priv,
2440 struct batadv_orig_node *orig_node,
2441 unsigned short vid)
2442 {
2443 struct batadv_hashtable *hash = bat_priv->tt.global_hash;
2444 struct batadv_tt_orig_list_entry *tt_orig;
2445 struct batadv_tt_common_entry *tt_common;
2446 struct batadv_tt_global_entry *tt_global;
2447 struct hlist_head *head;
2448 u32 i, crc_tmp, crc = 0;
2449 u8 flags;
2450 __be16 tmp_vid;
2451
2452 for (i = 0; i < hash->size; i++) {
2453 head = &hash->table[i];
2454
2455 rcu_read_lock();
2456 hlist_for_each_entry_rcu(tt_common, head, hash_entry) {
2457 tt_global = container_of(tt_common,
2458 struct batadv_tt_global_entry,
2459 common);
2460 /* compute the CRC only for entries belonging to the
2461 * VLAN identified by the vid passed as parameter
2462 */
2463 if (tt_common->vid != vid)
2464 continue;
2465
2466 /* Roaming clients are in the global table for
2467 * consistency only. They don't have to be
2468 * taken into account while computing the
2469 * global crc
2470 */
2471 if (tt_common->flags & BATADV_TT_CLIENT_ROAM)
2472 continue;
2473 /* Temporary clients have not been announced yet, so
2474 * they have to be skipped while computing the global
2475 * crc
2476 */
2477 if (tt_common->flags & BATADV_TT_CLIENT_TEMP)
2478 continue;
2479
2480 /* find out if this global entry is announced by this
2481 * originator
2482 */
2483 tt_orig = batadv_tt_global_orig_entry_find(tt_global,
2484 orig_node);
2485 if (!tt_orig)
2486 continue;
2487
2488 /* use network order to read the VID: this ensures that
2489 * every node reads the bytes in the same order.
2490 */
2491 tmp_vid = htons(tt_common->vid);
2492 crc_tmp = crc32c(0, &tmp_vid, sizeof(tmp_vid));
2493
2494 /* compute the CRC on flags that have to be kept in sync
2495 * among nodes
2496 */
2497 flags = tt_orig->flags;
2498 crc_tmp = crc32c(crc_tmp, &flags, sizeof(flags));
2499
2500 crc ^= crc32c(crc_tmp, tt_common->addr, ETH_ALEN);
2501
2502 batadv_tt_orig_list_entry_put(tt_orig);
2503 }
2504 rcu_read_unlock();
2505 }
2506
2507 return crc;
2508 }
2509
2510 /**
2511 * batadv_tt_local_crc() - calculates the checksum of the local table
2512 * @bat_priv: the bat priv with all the mesh interface information
2513 * @vid: VLAN identifier for which the CRC32 has to be computed
2514 *
2515 * For details about the computation, please refer to the documentation for
2516 * batadv_tt_global_crc().
2517 *
2518 * Return: the checksum of the local table
2519 */
batadv_tt_local_crc(struct batadv_priv * bat_priv,unsigned short vid)2520 static u32 batadv_tt_local_crc(struct batadv_priv *bat_priv,
2521 unsigned short vid)
2522 {
2523 struct batadv_hashtable *hash = bat_priv->tt.local_hash;
2524 struct batadv_tt_common_entry *tt_common;
2525 struct hlist_head *head;
2526 u32 i, crc_tmp, crc = 0;
2527 u8 flags;
2528 __be16 tmp_vid;
2529
2530 for (i = 0; i < hash->size; i++) {
2531 head = &hash->table[i];
2532
2533 rcu_read_lock();
2534 hlist_for_each_entry_rcu(tt_common, head, hash_entry) {
2535 /* compute the CRC only for entries belonging to the
2536 * VLAN identified by vid
2537 */
2538 if (tt_common->vid != vid)
2539 continue;
2540
2541 /* not yet committed clients have not to be taken into
2542 * account while computing the CRC
2543 */
2544 if (tt_common->flags & BATADV_TT_CLIENT_NEW)
2545 continue;
2546
2547 /* use network order to read the VID: this ensures that
2548 * every node reads the bytes in the same order.
2549 */
2550 tmp_vid = htons(tt_common->vid);
2551 crc_tmp = crc32c(0, &tmp_vid, sizeof(tmp_vid));
2552
2553 /* compute the CRC on flags that have to be kept in sync
2554 * among nodes
2555 */
2556 flags = tt_common->flags & BATADV_TT_SYNC_MASK;
2557 crc_tmp = crc32c(crc_tmp, &flags, sizeof(flags));
2558
2559 crc ^= crc32c(crc_tmp, tt_common->addr, ETH_ALEN);
2560 }
2561 rcu_read_unlock();
2562 }
2563
2564 return crc;
2565 }
2566
2567 /**
2568 * batadv_tt_req_node_release() - free tt_req node entry
2569 * @ref: kref pointer of the tt req_node entry
2570 */
batadv_tt_req_node_release(struct kref * ref)2571 static void batadv_tt_req_node_release(struct kref *ref)
2572 {
2573 struct batadv_tt_req_node *tt_req_node;
2574
2575 tt_req_node = container_of(ref, struct batadv_tt_req_node, refcount);
2576
2577 kmem_cache_free(batadv_tt_req_cache, tt_req_node);
2578 }
2579
2580 /**
2581 * batadv_tt_req_node_put() - decrement the tt_req_node refcounter and
2582 * possibly release it
2583 * @tt_req_node: tt_req_node to be free'd
2584 */
batadv_tt_req_node_put(struct batadv_tt_req_node * tt_req_node)2585 static void batadv_tt_req_node_put(struct batadv_tt_req_node *tt_req_node)
2586 {
2587 if (!tt_req_node)
2588 return;
2589
2590 kref_put(&tt_req_node->refcount, batadv_tt_req_node_release);
2591 }
2592
batadv_tt_req_list_free(struct batadv_priv * bat_priv)2593 static void batadv_tt_req_list_free(struct batadv_priv *bat_priv)
2594 {
2595 struct batadv_tt_req_node *node;
2596 struct hlist_node *safe;
2597
2598 spin_lock_bh(&bat_priv->tt.req_list_lock);
2599
2600 hlist_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) {
2601 hlist_del_init(&node->list);
2602 batadv_tt_req_node_put(node);
2603 }
2604
2605 spin_unlock_bh(&bat_priv->tt.req_list_lock);
2606 }
2607
batadv_tt_save_orig_buffer(struct batadv_priv * bat_priv,struct batadv_orig_node * orig_node,const void * tt_buff,u16 tt_buff_len)2608 static void batadv_tt_save_orig_buffer(struct batadv_priv *bat_priv,
2609 struct batadv_orig_node *orig_node,
2610 const void *tt_buff,
2611 u16 tt_buff_len)
2612 {
2613 /* Replace the old buffer only if I received something in the
2614 * last OGM (the OGM could carry no changes)
2615 */
2616 spin_lock_bh(&orig_node->tt_buff_lock);
2617 if (tt_buff_len > 0) {
2618 kfree(orig_node->tt_buff);
2619 orig_node->tt_buff_len = 0;
2620 orig_node->tt_buff = kmalloc(tt_buff_len, GFP_ATOMIC);
2621 if (orig_node->tt_buff) {
2622 memcpy(orig_node->tt_buff, tt_buff, tt_buff_len);
2623 orig_node->tt_buff_len = tt_buff_len;
2624 }
2625 }
2626 spin_unlock_bh(&orig_node->tt_buff_lock);
2627 }
2628
batadv_tt_req_purge(struct batadv_priv * bat_priv)2629 static void batadv_tt_req_purge(struct batadv_priv *bat_priv)
2630 {
2631 struct batadv_tt_req_node *node;
2632 struct hlist_node *safe;
2633
2634 spin_lock_bh(&bat_priv->tt.req_list_lock);
2635 hlist_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) {
2636 if (batadv_has_timed_out(node->issued_at,
2637 BATADV_TT_REQUEST_TIMEOUT)) {
2638 hlist_del_init(&node->list);
2639 batadv_tt_req_node_put(node);
2640 }
2641 }
2642 spin_unlock_bh(&bat_priv->tt.req_list_lock);
2643 }
2644
2645 /**
2646 * batadv_tt_req_node_new() - search and possibly create a tt_req_node object
2647 * @bat_priv: the bat priv with all the mesh interface information
2648 * @orig_node: orig node this request is being issued for
2649 *
2650 * Return: the pointer to the new tt_req_node struct if no request
2651 * has already been issued for this orig_node, NULL otherwise.
2652 */
2653 static struct batadv_tt_req_node *
batadv_tt_req_node_new(struct batadv_priv * bat_priv,struct batadv_orig_node * orig_node)2654 batadv_tt_req_node_new(struct batadv_priv *bat_priv,
2655 struct batadv_orig_node *orig_node)
2656 {
2657 struct batadv_tt_req_node *tt_req_node_tmp, *tt_req_node = NULL;
2658
2659 spin_lock_bh(&bat_priv->tt.req_list_lock);
2660 hlist_for_each_entry(tt_req_node_tmp, &bat_priv->tt.req_list, list) {
2661 if (batadv_compare_eth(tt_req_node_tmp, orig_node) &&
2662 !batadv_has_timed_out(tt_req_node_tmp->issued_at,
2663 BATADV_TT_REQUEST_TIMEOUT))
2664 goto unlock;
2665 }
2666
2667 tt_req_node = kmem_cache_alloc(batadv_tt_req_cache, GFP_ATOMIC);
2668 if (!tt_req_node)
2669 goto unlock;
2670
2671 kref_init(&tt_req_node->refcount);
2672 ether_addr_copy(tt_req_node->addr, orig_node->orig);
2673 tt_req_node->issued_at = jiffies;
2674
2675 kref_get(&tt_req_node->refcount);
2676 hlist_add_head(&tt_req_node->list, &bat_priv->tt.req_list);
2677 unlock:
2678 spin_unlock_bh(&bat_priv->tt.req_list_lock);
2679 return tt_req_node;
2680 }
2681
2682 /**
2683 * batadv_tt_local_valid() - verify local tt entry and get flags
2684 * @entry_ptr: to be checked local tt entry
2685 * @data_ptr: not used but definition required to satisfy the callback prototype
2686 * @flags: a pointer to store TT flags for this client to
2687 *
2688 * Checks the validity of the given local TT entry. If it is, then the provided
2689 * flags pointer is updated.
2690 *
2691 * Return: true if the entry is a valid, false otherwise.
2692 */
batadv_tt_local_valid(const void * entry_ptr,const void * data_ptr,u8 * flags)2693 static bool batadv_tt_local_valid(const void *entry_ptr,
2694 const void *data_ptr,
2695 u8 *flags)
2696 {
2697 const struct batadv_tt_common_entry *tt_common_entry = entry_ptr;
2698
2699 if (tt_common_entry->flags & BATADV_TT_CLIENT_NEW)
2700 return false;
2701
2702 if (flags)
2703 *flags = tt_common_entry->flags;
2704
2705 return true;
2706 }
2707
2708 /**
2709 * batadv_tt_global_valid() - verify global tt entry and get flags
2710 * @entry_ptr: to be checked global tt entry
2711 * @data_ptr: an orig_node object (may be NULL)
2712 * @flags: a pointer to store TT flags for this client to
2713 *
2714 * Checks the validity of the given global TT entry. If it is, then the provided
2715 * flags pointer is updated either with the common (summed) TT flags if data_ptr
2716 * is NULL or the specific, per originator TT flags otherwise.
2717 *
2718 * Return: true if the entry is a valid, false otherwise.
2719 */
batadv_tt_global_valid(const void * entry_ptr,const void * data_ptr,u8 * flags)2720 static bool batadv_tt_global_valid(const void *entry_ptr,
2721 const void *data_ptr,
2722 u8 *flags)
2723 {
2724 const struct batadv_tt_common_entry *tt_common_entry = entry_ptr;
2725 const struct batadv_tt_global_entry *tt_global_entry;
2726 const struct batadv_orig_node *orig_node = data_ptr;
2727
2728 if (tt_common_entry->flags & BATADV_TT_CLIENT_ROAM ||
2729 tt_common_entry->flags & BATADV_TT_CLIENT_TEMP)
2730 return false;
2731
2732 tt_global_entry = container_of(tt_common_entry,
2733 struct batadv_tt_global_entry,
2734 common);
2735
2736 return batadv_tt_global_entry_has_orig(tt_global_entry, orig_node,
2737 flags);
2738 }
2739
2740 /**
2741 * batadv_tt_tvlv_generate() - fill the tvlv buff with the tt entries from the
2742 * specified tt hash
2743 * @bat_priv: the bat priv with all the mesh interface information
2744 * @hash: hash table containing the tt entries
2745 * @tt_len: expected tvlv tt data buffer length in number of bytes
2746 * @tvlv_buff: pointer to the buffer to fill with the TT data
2747 * @valid_cb: function to filter tt change entries and to return TT flags
2748 * @cb_data: data passed to the filter function as argument
2749 *
2750 * Fills the tvlv buff with the tt entries from the specified hash. If valid_cb
2751 * is not provided then this becomes a no-op.
2752 *
2753 * Return: Remaining unused length in tvlv_buff.
2754 */
batadv_tt_tvlv_generate(struct batadv_priv * bat_priv,struct batadv_hashtable * hash,void * tvlv_buff,u16 tt_len,bool (* valid_cb)(const void *,const void *,u8 * flags),void * cb_data)2755 static u16 batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
2756 struct batadv_hashtable *hash,
2757 void *tvlv_buff, u16 tt_len,
2758 bool (*valid_cb)(const void *,
2759 const void *,
2760 u8 *flags),
2761 void *cb_data)
2762 {
2763 struct batadv_tt_common_entry *tt_common_entry;
2764 struct batadv_tvlv_tt_change *tt_change;
2765 struct hlist_head *head;
2766 u16 tt_tot, tt_num_entries = 0;
2767 u8 flags;
2768 bool ret;
2769 u32 i;
2770
2771 tt_tot = batadv_tt_entries(tt_len);
2772 tt_change = tvlv_buff;
2773
2774 if (!valid_cb)
2775 return tt_len;
2776
2777 rcu_read_lock();
2778 for (i = 0; i < hash->size; i++) {
2779 head = &hash->table[i];
2780
2781 hlist_for_each_entry_rcu(tt_common_entry,
2782 head, hash_entry) {
2783 if (tt_tot == tt_num_entries)
2784 break;
2785
2786 ret = valid_cb(tt_common_entry, cb_data, &flags);
2787 if (!ret)
2788 continue;
2789
2790 ether_addr_copy(tt_change->addr, tt_common_entry->addr);
2791 tt_change->flags = flags;
2792 tt_change->vid = htons(tt_common_entry->vid);
2793 memset(tt_change->reserved, 0,
2794 sizeof(tt_change->reserved));
2795
2796 tt_num_entries++;
2797 tt_change++;
2798 }
2799 }
2800 rcu_read_unlock();
2801
2802 return batadv_tt_len(tt_tot - tt_num_entries);
2803 }
2804
2805 /**
2806 * batadv_tt_global_check_crc() - check if all the CRCs are correct
2807 * @orig_node: originator for which the CRCs have to be checked
2808 * @tt_vlan: pointer to the first tvlv VLAN entry
2809 * @num_vlan: number of tvlv VLAN entries
2810 *
2811 * Return: true if all the received CRCs match the locally stored ones, false
2812 * otherwise
2813 */
batadv_tt_global_check_crc(struct batadv_orig_node * orig_node,struct batadv_tvlv_tt_vlan_data * tt_vlan,u16 num_vlan)2814 static bool batadv_tt_global_check_crc(struct batadv_orig_node *orig_node,
2815 struct batadv_tvlv_tt_vlan_data *tt_vlan,
2816 u16 num_vlan)
2817 {
2818 struct batadv_tvlv_tt_vlan_data *tt_vlan_tmp;
2819 struct batadv_orig_node_vlan *vlan;
2820 int i, orig_num_vlan;
2821 u32 crc;
2822
2823 /* check if each received CRC matches the locally stored one */
2824 for (i = 0; i < num_vlan; i++) {
2825 tt_vlan_tmp = tt_vlan + i;
2826
2827 /* if orig_node is a backbone node for this VLAN, don't check
2828 * the CRC as we ignore all the global entries over it
2829 */
2830 if (batadv_bla_is_backbone_gw_orig(orig_node->bat_priv,
2831 orig_node->orig,
2832 ntohs(tt_vlan_tmp->vid)))
2833 continue;
2834
2835 vlan = batadv_orig_node_vlan_get(orig_node,
2836 ntohs(tt_vlan_tmp->vid));
2837 if (!vlan)
2838 return false;
2839
2840 crc = vlan->tt.crc;
2841 batadv_orig_node_vlan_put(vlan);
2842
2843 if (crc != ntohl(tt_vlan_tmp->crc))
2844 return false;
2845 }
2846
2847 /* check if any excess VLANs exist locally for the originator
2848 * which are not mentioned in the TVLV from the originator.
2849 */
2850 rcu_read_lock();
2851 orig_num_vlan = 0;
2852 hlist_for_each_entry_rcu(vlan, &orig_node->vlan_list, list)
2853 orig_num_vlan++;
2854 rcu_read_unlock();
2855
2856 if (orig_num_vlan > num_vlan)
2857 return false;
2858
2859 return true;
2860 }
2861
2862 /**
2863 * batadv_tt_local_update_crc() - update all the local CRCs
2864 * @bat_priv: the bat priv with all the mesh interface information
2865 */
batadv_tt_local_update_crc(struct batadv_priv * bat_priv)2866 static void batadv_tt_local_update_crc(struct batadv_priv *bat_priv)
2867 {
2868 struct batadv_meshif_vlan *vlan;
2869
2870 /* recompute the global CRC for each VLAN */
2871 rcu_read_lock();
2872 hlist_for_each_entry_rcu(vlan, &bat_priv->meshif_vlan_list, list) {
2873 vlan->tt.crc = batadv_tt_local_crc(bat_priv, vlan->vid);
2874 }
2875 rcu_read_unlock();
2876 }
2877
2878 /**
2879 * batadv_tt_global_update_crc() - update all the global CRCs for this orig_node
2880 * @bat_priv: the bat priv with all the mesh interface information
2881 * @orig_node: the orig_node for which the CRCs have to be updated
2882 */
batadv_tt_global_update_crc(struct batadv_priv * bat_priv,struct batadv_orig_node * orig_node)2883 static void batadv_tt_global_update_crc(struct batadv_priv *bat_priv,
2884 struct batadv_orig_node *orig_node)
2885 {
2886 struct batadv_orig_node_vlan *vlan;
2887 u32 crc;
2888
2889 /* recompute the global CRC for each VLAN */
2890 rcu_read_lock();
2891 hlist_for_each_entry_rcu(vlan, &orig_node->vlan_list, list) {
2892 /* if orig_node is a backbone node for this VLAN, don't compute
2893 * the CRC as we ignore all the global entries over it
2894 */
2895 if (batadv_bla_is_backbone_gw_orig(bat_priv, orig_node->orig,
2896 vlan->vid))
2897 continue;
2898
2899 crc = batadv_tt_global_crc(bat_priv, orig_node, vlan->vid);
2900 vlan->tt.crc = crc;
2901 }
2902 rcu_read_unlock();
2903 }
2904
2905 /**
2906 * batadv_send_tt_request() - send a TT Request message to a given node
2907 * @bat_priv: the bat priv with all the mesh interface information
2908 * @dst_orig_node: the destination of the message
2909 * @ttvn: the version number that the source of the message is looking for
2910 * @tt_vlan: pointer to the first tvlv VLAN object to request
2911 * @num_vlan: number of tvlv VLAN entries
2912 * @full_table: ask for the entire translation table if true, while only for the
2913 * last TT diff otherwise
2914 *
2915 * Return: true if the TT Request was sent, false otherwise
2916 */
batadv_send_tt_request(struct batadv_priv * bat_priv,struct batadv_orig_node * dst_orig_node,u8 ttvn,struct batadv_tvlv_tt_vlan_data * tt_vlan,u16 num_vlan,bool full_table)2917 static bool batadv_send_tt_request(struct batadv_priv *bat_priv,
2918 struct batadv_orig_node *dst_orig_node,
2919 u8 ttvn,
2920 struct batadv_tvlv_tt_vlan_data *tt_vlan,
2921 u16 num_vlan, bool full_table)
2922 {
2923 struct batadv_tvlv_tt_data *tvlv_tt_data = NULL;
2924 struct batadv_tt_req_node *tt_req_node = NULL;
2925 struct batadv_hard_iface *primary_if;
2926 bool ret = false;
2927 int i, size;
2928
2929 primary_if = batadv_primary_if_get_selected(bat_priv);
2930 if (!primary_if)
2931 goto out;
2932
2933 /* The new tt_req will be issued only if I'm not waiting for a
2934 * reply from the same orig_node yet
2935 */
2936 tt_req_node = batadv_tt_req_node_new(bat_priv, dst_orig_node);
2937 if (!tt_req_node)
2938 goto out;
2939
2940 size = struct_size(tvlv_tt_data, vlan_data, num_vlan);
2941 tvlv_tt_data = kzalloc(size, GFP_ATOMIC);
2942 if (!tvlv_tt_data)
2943 goto out;
2944
2945 tvlv_tt_data->flags = BATADV_TT_REQUEST;
2946 tvlv_tt_data->ttvn = ttvn;
2947 tvlv_tt_data->num_vlan = htons(num_vlan);
2948
2949 /* send all the CRCs within the request. This is needed by intermediate
2950 * nodes to ensure they have the correct table before replying
2951 */
2952 for (i = 0; i < num_vlan; i++) {
2953 tvlv_tt_data->vlan_data[i].vid = tt_vlan->vid;
2954 tvlv_tt_data->vlan_data[i].crc = tt_vlan->crc;
2955
2956 tt_vlan++;
2957 }
2958
2959 if (full_table)
2960 tvlv_tt_data->flags |= BATADV_TT_FULL_TABLE;
2961
2962 batadv_dbg(BATADV_DBG_TT, bat_priv, "Sending TT_REQUEST to %pM [%c]\n",
2963 dst_orig_node->orig, full_table ? 'F' : '.');
2964
2965 batadv_inc_counter(bat_priv, BATADV_CNT_TT_REQUEST_TX);
2966 batadv_tvlv_unicast_send(bat_priv, primary_if->net_dev->dev_addr,
2967 dst_orig_node->orig, BATADV_TVLV_TT, 1,
2968 tvlv_tt_data, size);
2969 ret = true;
2970
2971 out:
2972 batadv_hardif_put(primary_if);
2973
2974 if (ret && tt_req_node) {
2975 spin_lock_bh(&bat_priv->tt.req_list_lock);
2976 if (!hlist_unhashed(&tt_req_node->list)) {
2977 hlist_del_init(&tt_req_node->list);
2978 batadv_tt_req_node_put(tt_req_node);
2979 }
2980 spin_unlock_bh(&bat_priv->tt.req_list_lock);
2981 }
2982
2983 batadv_tt_req_node_put(tt_req_node);
2984
2985 kfree(tvlv_tt_data);
2986 return ret;
2987 }
2988
2989 /**
2990 * batadv_send_other_tt_response() - send reply to tt request concerning another
2991 * node's translation table
2992 * @bat_priv: the bat priv with all the mesh interface information
2993 * @tt_data: tt data containing the tt request information
2994 * @req_src: mac address of tt request sender
2995 * @req_dst: mac address of tt request recipient
2996 *
2997 * Return: true if tt request reply was sent, false otherwise.
2998 */
batadv_send_other_tt_response(struct batadv_priv * bat_priv,struct batadv_tvlv_tt_data * tt_data,u8 * req_src,u8 * req_dst)2999 static bool batadv_send_other_tt_response(struct batadv_priv *bat_priv,
3000 struct batadv_tvlv_tt_data *tt_data,
3001 u8 *req_src, u8 *req_dst)
3002 {
3003 struct batadv_orig_node *req_dst_orig_node;
3004 struct batadv_orig_node *res_dst_orig_node = NULL;
3005 struct batadv_tvlv_tt_change *tt_change;
3006 struct batadv_tvlv_tt_data *tvlv_tt_data = NULL;
3007 bool ret = false, full_table;
3008 u8 orig_ttvn, req_ttvn;
3009 u16 tvlv_len;
3010 s32 tt_len;
3011
3012 batadv_dbg(BATADV_DBG_TT, bat_priv,
3013 "Received TT_REQUEST from %pM for ttvn: %u (%pM) [%c]\n",
3014 req_src, tt_data->ttvn, req_dst,
3015 ((tt_data->flags & BATADV_TT_FULL_TABLE) ? 'F' : '.'));
3016
3017 /* Let's get the orig node of the REAL destination */
3018 req_dst_orig_node = batadv_orig_hash_find(bat_priv, req_dst);
3019 if (!req_dst_orig_node)
3020 goto out;
3021
3022 res_dst_orig_node = batadv_orig_hash_find(bat_priv, req_src);
3023 if (!res_dst_orig_node)
3024 goto out;
3025
3026 orig_ttvn = READ_ONCE(req_dst_orig_node->last_ttvn);
3027 req_ttvn = tt_data->ttvn;
3028
3029 /* this node doesn't have the requested data */
3030 if (orig_ttvn != req_ttvn ||
3031 !batadv_tt_global_check_crc(req_dst_orig_node, tt_data->vlan_data,
3032 ntohs(tt_data->num_vlan)))
3033 goto out;
3034
3035 /* If the full table has been explicitly requested */
3036 if (tt_data->flags & BATADV_TT_FULL_TABLE ||
3037 !req_dst_orig_node->tt_buff)
3038 full_table = true;
3039 else
3040 full_table = false;
3041
3042 /* TT fragmentation hasn't been implemented yet, so send as many
3043 * TT entries fit a single packet as possible only
3044 */
3045 if (!full_table) {
3046 spin_lock_bh(&req_dst_orig_node->tt_buff_lock);
3047 tt_len = req_dst_orig_node->tt_buff_len;
3048
3049 tvlv_len = batadv_tt_prepare_tvlv_global_data(req_dst_orig_node,
3050 &tvlv_tt_data,
3051 &tt_change,
3052 &tt_len);
3053 if (!tt_len)
3054 goto unlock;
3055
3056 /* Copy the last orig_node's OGM buffer */
3057 memcpy(tt_change, req_dst_orig_node->tt_buff,
3058 req_dst_orig_node->tt_buff_len);
3059 spin_unlock_bh(&req_dst_orig_node->tt_buff_lock);
3060 } else {
3061 /* allocate the tvlv, put the tt_data and all the tt_vlan_data
3062 * in the initial part
3063 */
3064 tt_len = -1;
3065 tvlv_len = batadv_tt_prepare_tvlv_global_data(req_dst_orig_node,
3066 &tvlv_tt_data,
3067 &tt_change,
3068 &tt_len);
3069 if (!tt_len)
3070 goto out;
3071
3072 /* fill the rest of the tvlv with the real TT entries */
3073 tvlv_len -= batadv_tt_tvlv_generate(bat_priv,
3074 bat_priv->tt.global_hash,
3075 tt_change, tt_len,
3076 batadv_tt_global_valid,
3077 req_dst_orig_node);
3078 }
3079
3080 /* Don't send the response, if larger than fragmented packet. */
3081 tt_len = sizeof(struct batadv_unicast_tvlv_packet) + tvlv_len;
3082 if (tt_len > READ_ONCE(bat_priv->packet_size_max)) {
3083 net_ratelimited_function(batadv_info, bat_priv->mesh_iface,
3084 "Ignoring TT_REQUEST from %pM; Response size exceeds max packet size.\n",
3085 res_dst_orig_node->orig);
3086 goto out;
3087 }
3088
3089 tvlv_tt_data->flags = BATADV_TT_RESPONSE;
3090 tvlv_tt_data->ttvn = req_ttvn;
3091
3092 if (full_table)
3093 tvlv_tt_data->flags |= BATADV_TT_FULL_TABLE;
3094
3095 batadv_dbg(BATADV_DBG_TT, bat_priv,
3096 "Sending TT_RESPONSE %pM for %pM [%c] (ttvn: %u)\n",
3097 res_dst_orig_node->orig, req_dst_orig_node->orig,
3098 full_table ? 'F' : '.', req_ttvn);
3099
3100 batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX);
3101
3102 batadv_tvlv_unicast_send(bat_priv, req_dst_orig_node->orig,
3103 req_src, BATADV_TVLV_TT, 1, tvlv_tt_data,
3104 tvlv_len);
3105
3106 ret = true;
3107 goto out;
3108
3109 unlock:
3110 spin_unlock_bh(&req_dst_orig_node->tt_buff_lock);
3111
3112 out:
3113 batadv_orig_node_put(res_dst_orig_node);
3114 batadv_orig_node_put(req_dst_orig_node);
3115 kfree(tvlv_tt_data);
3116 return ret;
3117 }
3118
3119 /**
3120 * batadv_send_my_tt_response() - send reply to tt request concerning this
3121 * node's translation table
3122 * @bat_priv: the bat priv with all the mesh interface information
3123 * @tt_data: tt data containing the tt request information
3124 * @req_src: mac address of tt request sender
3125 *
3126 * Return: true if tt request reply was sent, false otherwise.
3127 */
batadv_send_my_tt_response(struct batadv_priv * bat_priv,struct batadv_tvlv_tt_data * tt_data,u8 * req_src)3128 static bool batadv_send_my_tt_response(struct batadv_priv *bat_priv,
3129 struct batadv_tvlv_tt_data *tt_data,
3130 u8 *req_src)
3131 {
3132 struct batadv_tvlv_tt_data *tvlv_tt_data = NULL;
3133 struct batadv_hard_iface *primary_if = NULL;
3134 struct batadv_tvlv_tt_change *tt_change;
3135 struct batadv_orig_node *orig_node;
3136 u8 my_ttvn, req_ttvn;
3137 u16 tvlv_len;
3138 bool full_table;
3139 s32 tt_len;
3140
3141 batadv_dbg(BATADV_DBG_TT, bat_priv,
3142 "Received TT_REQUEST from %pM for ttvn: %u (me) [%c]\n",
3143 req_src, tt_data->ttvn,
3144 ((tt_data->flags & BATADV_TT_FULL_TABLE) ? 'F' : '.'));
3145
3146 spin_lock_bh(&bat_priv->tt.commit_lock);
3147
3148 my_ttvn = (u8)atomic_read(&bat_priv->tt.vn);
3149 req_ttvn = tt_data->ttvn;
3150
3151 orig_node = batadv_orig_hash_find(bat_priv, req_src);
3152 if (!orig_node)
3153 goto out;
3154
3155 primary_if = batadv_primary_if_get_selected(bat_priv);
3156 if (!primary_if)
3157 goto out;
3158
3159 /* If the full table has been explicitly requested or the gap
3160 * is too big send the whole local translation table
3161 */
3162 if (tt_data->flags & BATADV_TT_FULL_TABLE || my_ttvn != req_ttvn ||
3163 !bat_priv->tt.last_changeset)
3164 full_table = true;
3165 else
3166 full_table = false;
3167
3168 /* TT fragmentation hasn't been implemented yet, so send as many
3169 * TT entries fit a single packet as possible only
3170 */
3171 if (!full_table) {
3172 spin_lock_bh(&bat_priv->tt.last_changeset_lock);
3173
3174 tt_len = bat_priv->tt.last_changeset_len;
3175 tvlv_len = batadv_tt_prepare_tvlv_local_data(bat_priv,
3176 &tvlv_tt_data,
3177 &tt_change,
3178 &tt_len);
3179 if (!tt_len || !tvlv_len)
3180 goto unlock;
3181
3182 /* Copy the last orig_node's OGM buffer */
3183 memcpy(tt_change, bat_priv->tt.last_changeset,
3184 bat_priv->tt.last_changeset_len);
3185 spin_unlock_bh(&bat_priv->tt.last_changeset_lock);
3186 } else {
3187 req_ttvn = (u8)atomic_read(&bat_priv->tt.vn);
3188
3189 /* allocate the tvlv, put the tt_data and all the tt_vlan_data
3190 * in the initial part
3191 */
3192 tt_len = -1;
3193 tvlv_len = batadv_tt_prepare_tvlv_local_data(bat_priv,
3194 &tvlv_tt_data,
3195 &tt_change,
3196 &tt_len);
3197 if (!tt_len || !tvlv_len)
3198 goto out;
3199
3200 /* fill the rest of the tvlv with the real TT entries */
3201 tvlv_len -= batadv_tt_tvlv_generate(bat_priv,
3202 bat_priv->tt.local_hash,
3203 tt_change, tt_len,
3204 batadv_tt_local_valid,
3205 NULL);
3206 }
3207
3208 tvlv_tt_data->flags = BATADV_TT_RESPONSE;
3209 tvlv_tt_data->ttvn = req_ttvn;
3210
3211 if (full_table)
3212 tvlv_tt_data->flags |= BATADV_TT_FULL_TABLE;
3213
3214 batadv_dbg(BATADV_DBG_TT, bat_priv,
3215 "Sending TT_RESPONSE to %pM [%c] (ttvn: %u)\n",
3216 orig_node->orig, full_table ? 'F' : '.', req_ttvn);
3217
3218 batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX);
3219
3220 batadv_tvlv_unicast_send(bat_priv, primary_if->net_dev->dev_addr,
3221 req_src, BATADV_TVLV_TT, 1, tvlv_tt_data,
3222 tvlv_len);
3223
3224 goto out;
3225
3226 unlock:
3227 spin_unlock_bh(&bat_priv->tt.last_changeset_lock);
3228 out:
3229 spin_unlock_bh(&bat_priv->tt.commit_lock);
3230 batadv_orig_node_put(orig_node);
3231 batadv_hardif_put(primary_if);
3232 kfree(tvlv_tt_data);
3233 /* The packet was for this host, so it doesn't need to be re-routed */
3234 return true;
3235 }
3236
3237 /**
3238 * batadv_send_tt_response() - send reply to tt request
3239 * @bat_priv: the bat priv with all the mesh interface information
3240 * @tt_data: tt data containing the tt request information
3241 * @req_src: mac address of tt request sender
3242 * @req_dst: mac address of tt request recipient
3243 *
3244 * Return: true if tt request reply was sent, false otherwise.
3245 */
batadv_send_tt_response(struct batadv_priv * bat_priv,struct batadv_tvlv_tt_data * tt_data,u8 * req_src,u8 * req_dst)3246 static bool batadv_send_tt_response(struct batadv_priv *bat_priv,
3247 struct batadv_tvlv_tt_data *tt_data,
3248 u8 *req_src, u8 *req_dst)
3249 {
3250 if (batadv_is_my_mac(bat_priv, req_dst))
3251 return batadv_send_my_tt_response(bat_priv, tt_data, req_src);
3252 return batadv_send_other_tt_response(bat_priv, tt_data, req_src,
3253 req_dst);
3254 }
3255
_batadv_tt_update_changes(struct batadv_priv * bat_priv,struct batadv_orig_node * orig_node,struct batadv_tvlv_tt_change * tt_change,u16 tt_num_changes,u8 ttvn)3256 static void _batadv_tt_update_changes(struct batadv_priv *bat_priv,
3257 struct batadv_orig_node *orig_node,
3258 struct batadv_tvlv_tt_change *tt_change,
3259 u16 tt_num_changes, u8 ttvn)
3260 {
3261 int i;
3262 int roams;
3263
3264 for (i = 0; i < tt_num_changes; i++) {
3265 if ((tt_change + i)->flags & BATADV_TT_CLIENT_DEL) {
3266 roams = (tt_change + i)->flags & BATADV_TT_CLIENT_ROAM;
3267 batadv_tt_global_del(bat_priv, orig_node,
3268 (tt_change + i)->addr,
3269 ntohs((tt_change + i)->vid),
3270 "tt removed by changes",
3271 roams);
3272 } else {
3273 if (!batadv_tt_global_add(bat_priv, orig_node,
3274 (tt_change + i)->addr,
3275 ntohs((tt_change + i)->vid),
3276 (tt_change + i)->flags, ttvn))
3277 /* In case of problem while storing a
3278 * global_entry, we stop the updating
3279 * procedure without committing the
3280 * ttvn change. This will avoid to send
3281 * corrupted data on tt_request
3282 */
3283 return;
3284 }
3285 }
3286 set_bit(BATADV_ORIG_CAPA_HAS_TT, &orig_node->capa_initialized);
3287 }
3288
batadv_tt_fill_gtable(struct batadv_priv * bat_priv,struct batadv_tvlv_tt_change * tt_change,u8 ttvn,u8 * resp_src,u16 num_entries)3289 static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv,
3290 struct batadv_tvlv_tt_change *tt_change,
3291 u8 ttvn, u8 *resp_src,
3292 u16 num_entries)
3293 {
3294 struct batadv_orig_node *orig_node;
3295
3296 orig_node = batadv_orig_hash_find(bat_priv, resp_src);
3297 if (!orig_node)
3298 goto out;
3299
3300 /* Purge the old table first.. */
3301 batadv_tt_global_del_orig(bat_priv, orig_node, -1,
3302 "Received full table");
3303
3304 _batadv_tt_update_changes(bat_priv, orig_node, tt_change, num_entries,
3305 ttvn);
3306
3307 spin_lock_bh(&orig_node->tt_buff_lock);
3308 kfree(orig_node->tt_buff);
3309 orig_node->tt_buff_len = 0;
3310 orig_node->tt_buff = NULL;
3311 spin_unlock_bh(&orig_node->tt_buff_lock);
3312
3313 WRITE_ONCE(orig_node->last_ttvn, ttvn);
3314
3315 out:
3316 batadv_orig_node_put(orig_node);
3317 }
3318
batadv_tt_update_changes(struct batadv_priv * bat_priv,struct batadv_orig_node * orig_node,u16 tt_num_changes,u8 ttvn,struct batadv_tvlv_tt_change * tt_change)3319 static void batadv_tt_update_changes(struct batadv_priv *bat_priv,
3320 struct batadv_orig_node *orig_node,
3321 u16 tt_num_changes, u8 ttvn,
3322 struct batadv_tvlv_tt_change *tt_change)
3323 {
3324 _batadv_tt_update_changes(bat_priv, orig_node, tt_change,
3325 tt_num_changes, ttvn);
3326
3327 batadv_tt_save_orig_buffer(bat_priv, orig_node, tt_change,
3328 batadv_tt_len(tt_num_changes));
3329 WRITE_ONCE(orig_node->last_ttvn, ttvn);
3330 }
3331
3332 /**
3333 * batadv_is_my_client() - check if a client is served by the local node
3334 * @bat_priv: the bat priv with all the mesh interface information
3335 * @addr: the mac address of the client to check
3336 * @vid: VLAN identifier
3337 *
3338 * Return: true if the client is served by this node, false otherwise.
3339 */
batadv_is_my_client(struct batadv_priv * bat_priv,const u8 * addr,unsigned short vid)3340 bool batadv_is_my_client(struct batadv_priv *bat_priv, const u8 *addr,
3341 unsigned short vid)
3342 {
3343 struct batadv_tt_local_entry *tt_local_entry;
3344 bool ret = false;
3345
3346 tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr, vid);
3347 if (!tt_local_entry)
3348 goto out;
3349 /* Check if the client has been logically deleted (but is kept for
3350 * consistency purpose)
3351 */
3352 if ((tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING) ||
3353 (tt_local_entry->common.flags & BATADV_TT_CLIENT_ROAM))
3354 goto out;
3355 ret = true;
3356 out:
3357 batadv_tt_local_entry_put(tt_local_entry);
3358 return ret;
3359 }
3360
3361 /**
3362 * batadv_handle_tt_response() - process incoming tt reply
3363 * @bat_priv: the bat priv with all the mesh interface information
3364 * @tt_data: tt data containing the tt request information
3365 * @resp_src: mac address of tt reply sender
3366 * @num_entries: number of tt change entries appended to the tt data
3367 */
batadv_handle_tt_response(struct batadv_priv * bat_priv,struct batadv_tvlv_tt_data * tt_data,u8 * resp_src,u16 num_entries)3368 static void batadv_handle_tt_response(struct batadv_priv *bat_priv,
3369 struct batadv_tvlv_tt_data *tt_data,
3370 u8 *resp_src, u16 num_entries)
3371 {
3372 struct batadv_tt_req_node *node;
3373 struct hlist_node *safe;
3374 struct batadv_orig_node *orig_node = NULL;
3375 struct batadv_tvlv_tt_change *tt_change;
3376 u8 *tvlv_ptr = (u8 *)tt_data;
3377
3378 batadv_dbg(BATADV_DBG_TT, bat_priv,
3379 "Received TT_RESPONSE from %pM for ttvn %d t_size: %d [%c]\n",
3380 resp_src, tt_data->ttvn, num_entries,
3381 ((tt_data->flags & BATADV_TT_FULL_TABLE) ? 'F' : '.'));
3382
3383 orig_node = batadv_orig_hash_find(bat_priv, resp_src);
3384 if (!orig_node)
3385 goto out;
3386
3387 spin_lock_bh(&orig_node->tt_lock);
3388
3389 tvlv_ptr += struct_size(tt_data, vlan_data, ntohs(tt_data->num_vlan));
3390
3391 tt_change = (struct batadv_tvlv_tt_change *)tvlv_ptr;
3392 if (tt_data->flags & BATADV_TT_FULL_TABLE) {
3393 batadv_tt_fill_gtable(bat_priv, tt_change, tt_data->ttvn,
3394 resp_src, num_entries);
3395 } else {
3396 batadv_tt_update_changes(bat_priv, orig_node, num_entries,
3397 tt_data->ttvn, tt_change);
3398 }
3399
3400 /* Recalculate the CRC for this orig_node and store it */
3401 batadv_tt_global_update_crc(bat_priv, orig_node);
3402
3403 spin_unlock_bh(&orig_node->tt_lock);
3404
3405 /* Delete the tt_req_node from pending tt_requests list */
3406 spin_lock_bh(&bat_priv->tt.req_list_lock);
3407 hlist_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) {
3408 if (!batadv_compare_eth(node->addr, resp_src))
3409 continue;
3410 hlist_del_init(&node->list);
3411 batadv_tt_req_node_put(node);
3412 }
3413
3414 spin_unlock_bh(&bat_priv->tt.req_list_lock);
3415 out:
3416 batadv_orig_node_put(orig_node);
3417 }
3418
batadv_tt_roam_list_free(struct batadv_priv * bat_priv)3419 static void batadv_tt_roam_list_free(struct batadv_priv *bat_priv)
3420 {
3421 struct batadv_tt_roam_node *node, *safe;
3422
3423 spin_lock_bh(&bat_priv->tt.roam_list_lock);
3424
3425 list_for_each_entry_safe(node, safe, &bat_priv->tt.roam_list, list) {
3426 list_del(&node->list);
3427 kmem_cache_free(batadv_tt_roam_cache, node);
3428 }
3429
3430 spin_unlock_bh(&bat_priv->tt.roam_list_lock);
3431 }
3432
batadv_tt_roam_purge(struct batadv_priv * bat_priv)3433 static void batadv_tt_roam_purge(struct batadv_priv *bat_priv)
3434 {
3435 struct batadv_tt_roam_node *node, *safe;
3436
3437 spin_lock_bh(&bat_priv->tt.roam_list_lock);
3438 list_for_each_entry_safe(node, safe, &bat_priv->tt.roam_list, list) {
3439 if (!batadv_has_timed_out(node->first_time,
3440 BATADV_ROAMING_MAX_TIME))
3441 continue;
3442
3443 list_del(&node->list);
3444 kmem_cache_free(batadv_tt_roam_cache, node);
3445 }
3446 spin_unlock_bh(&bat_priv->tt.roam_list_lock);
3447 }
3448
3449 /**
3450 * batadv_tt_check_roam_count() - check if a client has roamed too frequently
3451 * @bat_priv: the bat priv with all the mesh interface information
3452 * @client: mac address of the roaming client
3453 * @vid: VLAN identifier
3454 *
3455 * This function checks whether the client already reached the
3456 * maximum number of possible roaming phases. In this case the ROAMING_ADV
3457 * will not be sent.
3458 *
3459 * Return: true if the ROAMING_ADV can be sent, false otherwise
3460 */
batadv_tt_check_roam_count(struct batadv_priv * bat_priv,u8 * client,u16 vid)3461 static bool batadv_tt_check_roam_count(struct batadv_priv *bat_priv, u8 *client, u16 vid)
3462 {
3463 struct batadv_tt_roam_node *tt_roam_node;
3464 bool ret = false;
3465
3466 spin_lock_bh(&bat_priv->tt.roam_list_lock);
3467 /* The new tt_req will be issued only if I'm not waiting for a
3468 * reply from the same orig_node yet
3469 */
3470 list_for_each_entry(tt_roam_node, &bat_priv->tt.roam_list, list) {
3471 if (!batadv_compare_eth(tt_roam_node->addr, client))
3472 continue;
3473
3474 if (tt_roam_node->vid != vid)
3475 continue;
3476
3477 if (batadv_has_timed_out(tt_roam_node->first_time,
3478 BATADV_ROAMING_MAX_TIME))
3479 continue;
3480
3481 if (!batadv_atomic_dec_not_zero(&tt_roam_node->counter))
3482 /* Sorry, you roamed too many times! */
3483 goto unlock;
3484 ret = true;
3485 break;
3486 }
3487
3488 if (!ret) {
3489 tt_roam_node = kmem_cache_alloc(batadv_tt_roam_cache,
3490 GFP_ATOMIC);
3491 if (!tt_roam_node)
3492 goto unlock;
3493
3494 tt_roam_node->first_time = jiffies;
3495 atomic_set(&tt_roam_node->counter,
3496 BATADV_ROAMING_MAX_COUNT - 1);
3497 ether_addr_copy(tt_roam_node->addr, client);
3498 tt_roam_node->vid = vid;
3499
3500 list_add(&tt_roam_node->list, &bat_priv->tt.roam_list);
3501 ret = true;
3502 }
3503
3504 unlock:
3505 spin_unlock_bh(&bat_priv->tt.roam_list_lock);
3506 return ret;
3507 }
3508
3509 /**
3510 * batadv_send_roam_adv() - send a roaming advertisement message
3511 * @bat_priv: the bat priv with all the mesh interface information
3512 * @client: mac address of the roaming client
3513 * @vid: VLAN identifier
3514 * @orig_node: message destination
3515 *
3516 * Send a ROAMING_ADV message to the node which was previously serving this
3517 * client. This is done to inform the node that from now on all traffic destined
3518 * for this particular roamed client has to be forwarded to the sender of the
3519 * roaming message.
3520 */
batadv_send_roam_adv(struct batadv_priv * bat_priv,u8 * client,unsigned short vid,struct batadv_orig_node * orig_node)3521 static void batadv_send_roam_adv(struct batadv_priv *bat_priv, u8 *client,
3522 unsigned short vid,
3523 struct batadv_orig_node *orig_node)
3524 {
3525 struct batadv_hard_iface *primary_if;
3526 struct batadv_tvlv_roam_adv tvlv_roam;
3527
3528 primary_if = batadv_primary_if_get_selected(bat_priv);
3529 if (!primary_if)
3530 goto out;
3531
3532 /* before going on we have to check whether the client has
3533 * already roamed to us too many times
3534 */
3535 if (!batadv_tt_check_roam_count(bat_priv, client, vid))
3536 goto out;
3537
3538 batadv_dbg(BATADV_DBG_TT, bat_priv,
3539 "Sending ROAMING_ADV to %pM (client %pM, vid: %d)\n",
3540 orig_node->orig, client, batadv_print_vid(vid));
3541
3542 batadv_inc_counter(bat_priv, BATADV_CNT_TT_ROAM_ADV_TX);
3543
3544 memcpy(tvlv_roam.client, client, sizeof(tvlv_roam.client));
3545 tvlv_roam.vid = htons(vid);
3546
3547 batadv_tvlv_unicast_send(bat_priv, primary_if->net_dev->dev_addr,
3548 orig_node->orig, BATADV_TVLV_ROAM, 1,
3549 &tvlv_roam, sizeof(tvlv_roam));
3550
3551 out:
3552 batadv_hardif_put(primary_if);
3553 }
3554
batadv_tt_purge(struct work_struct * work)3555 static void batadv_tt_purge(struct work_struct *work)
3556 {
3557 struct delayed_work *delayed_work;
3558 struct batadv_priv_tt *priv_tt;
3559 struct batadv_priv *bat_priv;
3560
3561 delayed_work = to_delayed_work(work);
3562 priv_tt = container_of(delayed_work, struct batadv_priv_tt, work);
3563 bat_priv = container_of(priv_tt, struct batadv_priv, tt);
3564
3565 batadv_tt_local_purge(bat_priv, BATADV_TT_LOCAL_TIMEOUT);
3566 batadv_tt_global_purge(bat_priv);
3567 batadv_tt_req_purge(bat_priv);
3568 batadv_tt_roam_purge(bat_priv);
3569
3570 queue_delayed_work(batadv_event_workqueue, &bat_priv->tt.work,
3571 msecs_to_jiffies(BATADV_TT_WORK_PERIOD));
3572 }
3573
3574 /**
3575 * batadv_tt_free() - Free translation table of mesh interface
3576 * @bat_priv: the bat priv with all the mesh interface information
3577 */
batadv_tt_free(struct batadv_priv * bat_priv)3578 void batadv_tt_free(struct batadv_priv *bat_priv)
3579 {
3580 batadv_tvlv_handler_unregister(bat_priv, BATADV_TVLV_ROAM, 1);
3581
3582 batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_TT, 1);
3583 batadv_tvlv_handler_unregister(bat_priv, BATADV_TVLV_TT, 1);
3584
3585 disable_delayed_work_sync(&bat_priv->tt.work);
3586
3587 batadv_tt_local_table_free(bat_priv);
3588 batadv_tt_global_table_free(bat_priv);
3589 batadv_tt_req_list_free(bat_priv);
3590 batadv_tt_changes_list_free(bat_priv);
3591 batadv_tt_roam_list_free(bat_priv);
3592
3593 kfree(bat_priv->tt.last_changeset);
3594 }
3595
3596 /**
3597 * batadv_tt_local_set_flags() - set or unset the specified flags on the local
3598 * table and possibly count them in the TT size
3599 * @bat_priv: the bat priv with all the mesh interface information
3600 * @flags: the flag to switch
3601 * @enable: whether to set or unset the flag
3602 * @count: whether to increase the TT size by the number of changed entries
3603 */
batadv_tt_local_set_flags(struct batadv_priv * bat_priv,u16 flags,bool enable,bool count)3604 static void batadv_tt_local_set_flags(struct batadv_priv *bat_priv, u16 flags,
3605 bool enable, bool count)
3606 {
3607 struct batadv_hashtable *hash = bat_priv->tt.local_hash;
3608 struct batadv_tt_common_entry *tt_common_entry;
3609 struct hlist_head *head;
3610 u32 i;
3611
3612 if (!hash)
3613 return;
3614
3615 for (i = 0; i < hash->size; i++) {
3616 head = &hash->table[i];
3617
3618 rcu_read_lock();
3619 hlist_for_each_entry_rcu(tt_common_entry,
3620 head, hash_entry) {
3621 if (enable) {
3622 if ((tt_common_entry->flags & flags) == flags)
3623 continue;
3624 tt_common_entry->flags |= flags;
3625 } else {
3626 if (!(tt_common_entry->flags & flags))
3627 continue;
3628 tt_common_entry->flags &= ~flags;
3629 }
3630
3631 if (!count)
3632 continue;
3633
3634 batadv_tt_local_size_inc(bat_priv,
3635 tt_common_entry->vid);
3636 }
3637 rcu_read_unlock();
3638 }
3639 }
3640
3641 /* Purge out all the tt local entries marked with BATADV_TT_CLIENT_PENDING */
batadv_tt_local_purge_pending_clients(struct batadv_priv * bat_priv)3642 static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv)
3643 {
3644 struct batadv_hashtable *hash = bat_priv->tt.local_hash;
3645 struct batadv_tt_common_entry *tt_common;
3646 struct batadv_tt_local_entry *tt_local;
3647 struct hlist_node *node_tmp;
3648 struct hlist_head *head;
3649 spinlock_t *list_lock; /* protects write access to the hash lists */
3650 u32 i;
3651
3652 if (!hash)
3653 return;
3654
3655 for (i = 0; i < hash->size; i++) {
3656 head = &hash->table[i];
3657 list_lock = &hash->list_locks[i];
3658
3659 spin_lock_bh(list_lock);
3660 hlist_for_each_entry_safe(tt_common, node_tmp, head,
3661 hash_entry) {
3662 if (!(tt_common->flags & BATADV_TT_CLIENT_PENDING))
3663 continue;
3664
3665 batadv_dbg(BATADV_DBG_TT, bat_priv,
3666 "Deleting local tt entry (%pM, vid: %d): pending\n",
3667 tt_common->addr,
3668 batadv_print_vid(tt_common->vid));
3669
3670 batadv_tt_local_size_dec(bat_priv, tt_common->vid);
3671 hlist_del_rcu(&tt_common->hash_entry);
3672 tt_local = container_of(tt_common,
3673 struct batadv_tt_local_entry,
3674 common);
3675
3676 batadv_tt_local_entry_put(tt_local);
3677 }
3678 spin_unlock_bh(list_lock);
3679 }
3680 }
3681
3682 /**
3683 * batadv_tt_local_commit_changes_nolock() - commit all pending local tt changes
3684 * which have been queued in the time since the last commit
3685 * @bat_priv: the bat priv with all the mesh interface information
3686 *
3687 * Caller must hold tt->commit_lock.
3688 */
batadv_tt_local_commit_changes_nolock(struct batadv_priv * bat_priv)3689 static void batadv_tt_local_commit_changes_nolock(struct batadv_priv *bat_priv)
3690 {
3691 lockdep_assert_held(&bat_priv->tt.commit_lock);
3692
3693 if (READ_ONCE(bat_priv->tt.local_changes) == 0) {
3694 if (!batadv_atomic_dec_not_zero(&bat_priv->tt.ogm_append_cnt))
3695 batadv_tt_tvlv_container_update(bat_priv);
3696 return;
3697 }
3698
3699 batadv_tt_local_set_flags(bat_priv, BATADV_TT_CLIENT_NEW, false, true);
3700
3701 batadv_tt_local_purge_pending_clients(bat_priv);
3702 batadv_tt_local_update_crc(bat_priv);
3703
3704 /* Increment the TTVN only once per OGM interval */
3705 atomic_inc(&bat_priv->tt.vn);
3706 batadv_dbg(BATADV_DBG_TT, bat_priv,
3707 "Local changes committed, updating to ttvn %u\n",
3708 (u8)atomic_read(&bat_priv->tt.vn));
3709
3710 /* reset the sending counter */
3711 atomic_set(&bat_priv->tt.ogm_append_cnt, BATADV_TT_OGM_APPEND_MAX);
3712 batadv_tt_tvlv_container_update(bat_priv);
3713 }
3714
3715 /**
3716 * batadv_tt_local_commit_changes() - commit all pending local tt changes which
3717 * have been queued in the time since the last commit
3718 * @bat_priv: the bat priv with all the mesh interface information
3719 */
batadv_tt_local_commit_changes(struct batadv_priv * bat_priv)3720 void batadv_tt_local_commit_changes(struct batadv_priv *bat_priv)
3721 {
3722 spin_lock_bh(&bat_priv->tt.commit_lock);
3723 batadv_tt_local_commit_changes_nolock(bat_priv);
3724 spin_unlock_bh(&bat_priv->tt.commit_lock);
3725 }
3726
3727 /**
3728 * batadv_is_ap_isolated() - Check if packet from upper layer should be dropped
3729 * @bat_priv: the bat priv with all the mesh interface information
3730 * @src: source mac address of packet
3731 * @dst: destination mac address of packet
3732 * @vid: vlan id of packet
3733 *
3734 * Return: true when src+dst(+vid) pair should be isolated, false otherwise
3735 */
batadv_is_ap_isolated(struct batadv_priv * bat_priv,u8 * src,u8 * dst,unsigned short vid)3736 bool batadv_is_ap_isolated(struct batadv_priv *bat_priv, u8 *src, u8 *dst,
3737 unsigned short vid)
3738 {
3739 struct batadv_tt_local_entry *tt_local_entry;
3740 struct batadv_tt_global_entry *tt_global_entry;
3741 struct batadv_meshif_vlan *vlan;
3742 bool ret = false;
3743
3744 vlan = batadv_meshif_vlan_get(bat_priv, vid);
3745 if (!vlan)
3746 return false;
3747
3748 if (!READ_ONCE(vlan->ap_isolation))
3749 goto vlan_put;
3750
3751 tt_local_entry = batadv_tt_local_hash_find(bat_priv, dst, vid);
3752 if (!tt_local_entry)
3753 goto vlan_put;
3754
3755 tt_global_entry = batadv_tt_global_hash_find(bat_priv, src, vid);
3756 if (!tt_global_entry)
3757 goto local_entry_put;
3758
3759 if (_batadv_is_ap_isolated(tt_local_entry, tt_global_entry))
3760 ret = true;
3761
3762 batadv_tt_global_entry_put(tt_global_entry);
3763 local_entry_put:
3764 batadv_tt_local_entry_put(tt_local_entry);
3765 vlan_put:
3766 batadv_meshif_vlan_put(vlan);
3767 return ret;
3768 }
3769
3770 /**
3771 * batadv_tt_update_orig() - update global translation table with new tt
3772 * information received via ogms
3773 * @bat_priv: the bat priv with all the mesh interface information
3774 * @orig_node: the orig_node of the ogm
3775 * @tt_buff: pointer to the first tvlv VLAN entry
3776 * @tt_num_vlan: number of tvlv VLAN entries
3777 * @tt_change: pointer to the first entry in the TT buffer
3778 * @tt_num_changes: number of tt changes inside the tt buffer
3779 * @ttvn: translation table version number of this changeset
3780 */
batadv_tt_update_orig(struct batadv_priv * bat_priv,struct batadv_orig_node * orig_node,const void * tt_buff,u16 tt_num_vlan,struct batadv_tvlv_tt_change * tt_change,u16 tt_num_changes,u8 ttvn)3781 static void batadv_tt_update_orig(struct batadv_priv *bat_priv,
3782 struct batadv_orig_node *orig_node,
3783 const void *tt_buff, u16 tt_num_vlan,
3784 struct batadv_tvlv_tt_change *tt_change,
3785 u16 tt_num_changes, u8 ttvn)
3786 {
3787 u8 orig_ttvn = READ_ONCE(orig_node->last_ttvn);
3788 struct batadv_tvlv_tt_vlan_data *tt_vlan;
3789 bool full_table = true;
3790 bool has_tt_init;
3791
3792 tt_vlan = (struct batadv_tvlv_tt_vlan_data *)tt_buff;
3793 has_tt_init = test_bit(BATADV_ORIG_CAPA_HAS_TT,
3794 &orig_node->capa_initialized);
3795
3796 /* orig table not initialised AND first diff is in the OGM OR the ttvn
3797 * increased by one -> we can apply the attached changes
3798 */
3799 if ((!has_tt_init && ttvn == 1) || ttvn - orig_ttvn == 1) {
3800 /* the OGM could not contain the changes due to their size or
3801 * because they have already been sent BATADV_TT_OGM_APPEND_MAX
3802 * times.
3803 * In this case send a tt request
3804 */
3805 if (!tt_num_changes) {
3806 full_table = false;
3807 goto request_table;
3808 }
3809
3810 spin_lock_bh(&orig_node->tt_lock);
3811
3812 batadv_tt_update_changes(bat_priv, orig_node, tt_num_changes,
3813 ttvn, tt_change);
3814
3815 /* Even if we received the precomputed crc with the OGM, we
3816 * prefer to recompute it to spot any possible inconsistency
3817 * in the global table
3818 */
3819 batadv_tt_global_update_crc(bat_priv, orig_node);
3820
3821 spin_unlock_bh(&orig_node->tt_lock);
3822
3823 /* The ttvn alone is not enough to guarantee consistency
3824 * because a single value could represent different states
3825 * (due to the wrap around). Thus a node has to check whether
3826 * the resulting table (after applying the changes) is still
3827 * consistent or not. E.g. a node could disconnect while its
3828 * ttvn is X and reconnect on ttvn = X + TTVN_MAX: in this case
3829 * checking the CRC value is mandatory to detect the
3830 * inconsistency
3831 */
3832 if (!batadv_tt_global_check_crc(orig_node, tt_vlan,
3833 tt_num_vlan))
3834 goto request_table;
3835 } else {
3836 /* if we missed more than one change or our tables are not
3837 * in sync anymore -> request fresh tt data
3838 */
3839 if (!has_tt_init || ttvn != orig_ttvn ||
3840 !batadv_tt_global_check_crc(orig_node, tt_vlan,
3841 tt_num_vlan)) {
3842 request_table:
3843 batadv_dbg(BATADV_DBG_TT, bat_priv,
3844 "TT inconsistency for %pM. Need to retrieve the correct information (ttvn: %u last_ttvn: %u num_changes: %u)\n",
3845 orig_node->orig, ttvn, orig_ttvn,
3846 tt_num_changes);
3847 batadv_send_tt_request(bat_priv, orig_node, ttvn,
3848 tt_vlan, tt_num_vlan,
3849 full_table);
3850 return;
3851 }
3852 }
3853 }
3854
3855 /**
3856 * batadv_tt_global_client_is_roaming() - check if a client is marked as roaming
3857 * @bat_priv: the bat priv with all the mesh interface information
3858 * @addr: the mac address of the client to check
3859 * @vid: VLAN identifier
3860 *
3861 * Return: true if we know that the client has moved from its old originator
3862 * to another one. This entry is still kept for consistency purposes and will be
3863 * deleted later by a DEL or because of timeout
3864 */
batadv_tt_global_client_is_roaming(struct batadv_priv * bat_priv,u8 * addr,unsigned short vid)3865 bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv,
3866 u8 *addr, unsigned short vid)
3867 {
3868 struct batadv_tt_global_entry *tt_global_entry;
3869 bool ret = false;
3870
3871 tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr, vid);
3872 if (!tt_global_entry)
3873 goto out;
3874
3875 ret = tt_global_entry->common.flags & BATADV_TT_CLIENT_ROAM;
3876 batadv_tt_global_entry_put(tt_global_entry);
3877 out:
3878 return ret;
3879 }
3880
3881 /**
3882 * batadv_tt_local_client_is_roaming() - tells whether the client is roaming
3883 * @bat_priv: the bat priv with all the mesh interface information
3884 * @addr: the mac address of the local client to query
3885 * @vid: VLAN identifier
3886 *
3887 * Return: true if the local client is known to be roaming (it is not served by
3888 * this node anymore) or not. If yes, the client is still present in the table
3889 * to keep the latter consistent with the node TTVN
3890 */
batadv_tt_local_client_is_roaming(struct batadv_priv * bat_priv,u8 * addr,unsigned short vid)3891 bool batadv_tt_local_client_is_roaming(struct batadv_priv *bat_priv,
3892 u8 *addr, unsigned short vid)
3893 {
3894 struct batadv_tt_local_entry *tt_local_entry;
3895 bool ret = false;
3896
3897 tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr, vid);
3898 if (!tt_local_entry)
3899 goto out;
3900
3901 ret = tt_local_entry->common.flags & BATADV_TT_CLIENT_ROAM;
3902 batadv_tt_local_entry_put(tt_local_entry);
3903 out:
3904 return ret;
3905 }
3906
3907 /**
3908 * batadv_tt_add_temporary_global_entry() - Add temporary entry to global TT
3909 * @bat_priv: the bat priv with all the mesh interface information
3910 * @orig_node: orig node which the temporary entry should be associated with
3911 * @addr: mac address of the client
3912 * @vid: VLAN id of the new temporary global translation table
3913 *
3914 * Return: true when temporary tt entry could be added, false otherwise
3915 */
batadv_tt_add_temporary_global_entry(struct batadv_priv * bat_priv,struct batadv_orig_node * orig_node,const unsigned char * addr,unsigned short vid)3916 bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv,
3917 struct batadv_orig_node *orig_node,
3918 const unsigned char *addr,
3919 unsigned short vid)
3920 {
3921 /* ignore loop detect macs, they are not supposed to be in the tt local
3922 * data as well.
3923 */
3924 if (batadv_bla_is_loopdetect_mac(addr))
3925 return false;
3926
3927 if (!batadv_tt_global_add(bat_priv, orig_node, addr, vid,
3928 BATADV_TT_CLIENT_TEMP,
3929 READ_ONCE(orig_node->last_ttvn)))
3930 return false;
3931
3932 batadv_dbg(BATADV_DBG_TT, bat_priv,
3933 "Added temporary global client (addr: %pM, vid: %d, orig: %pM)\n",
3934 addr, batadv_print_vid(vid), orig_node->orig);
3935
3936 return true;
3937 }
3938
3939 /**
3940 * batadv_tt_local_resize_to_mtu() - resize the local translation table fit the
3941 * maximum packet size that can be transported through the mesh
3942 * @mesh_iface: netdev struct of the mesh interface
3943 *
3944 * Remove entries older than 'timeout' and half timeout if more entries need
3945 * to be removed.
3946 */
batadv_tt_local_resize_to_mtu(struct net_device * mesh_iface)3947 void batadv_tt_local_resize_to_mtu(struct net_device *mesh_iface)
3948 {
3949 struct batadv_priv *bat_priv = netdev_priv(mesh_iface);
3950 int packet_size_max = READ_ONCE(bat_priv->packet_size_max);
3951 int table_size, timeout = BATADV_TT_LOCAL_TIMEOUT / 2;
3952 bool reduced = false;
3953
3954 spin_lock_bh(&bat_priv->tt.commit_lock);
3955
3956 while (timeout) {
3957 table_size = batadv_tt_local_table_transmit_size(bat_priv);
3958 if (packet_size_max >= table_size)
3959 break;
3960
3961 batadv_tt_local_purge(bat_priv, timeout);
3962 batadv_tt_local_purge_pending_clients(bat_priv);
3963
3964 timeout /= 2;
3965 reduced = true;
3966 net_ratelimited_function(batadv_info, mesh_iface,
3967 "Forced to purge local tt entries to fit new maximum fragment MTU (%i)\n",
3968 packet_size_max);
3969 }
3970
3971 /* commit these changes immediately, to avoid synchronization problem
3972 * with the TTVN
3973 */
3974 if (reduced)
3975 batadv_tt_local_commit_changes_nolock(bat_priv);
3976
3977 spin_unlock_bh(&bat_priv->tt.commit_lock);
3978 }
3979
3980 /**
3981 * batadv_tt_tvlv_ogm_handler_v1() - process incoming tt tvlv container
3982 * @bat_priv: the bat priv with all the mesh interface information
3983 * @orig: the orig_node of the ogm
3984 * @flags: flags indicating the tvlv state (see batadv_tvlv_handler_flags)
3985 * @tvlv_value: tvlv buffer containing the gateway data
3986 * @tvlv_value_len: tvlv buffer length
3987 */
batadv_tt_tvlv_ogm_handler_v1(struct batadv_priv * bat_priv,struct batadv_orig_node * orig,u8 flags,void * tvlv_value,u16 tvlv_value_len)3988 static void batadv_tt_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv,
3989 struct batadv_orig_node *orig,
3990 u8 flags, void *tvlv_value,
3991 u16 tvlv_value_len)
3992 {
3993 struct batadv_tvlv_tt_change *tt_change;
3994 struct batadv_tvlv_tt_data *tt_data;
3995 u16 num_entries, num_vlan;
3996 size_t tt_data_sz;
3997
3998 if (tvlv_value_len < sizeof(*tt_data))
3999 return;
4000
4001 tt_data = tvlv_value;
4002 num_vlan = ntohs(tt_data->num_vlan);
4003
4004 tt_data_sz = struct_size(tt_data, vlan_data, num_vlan);
4005 if (tvlv_value_len < tt_data_sz)
4006 return;
4007
4008 tt_change = (struct batadv_tvlv_tt_change *)((void *)tt_data
4009 + tt_data_sz);
4010 tvlv_value_len -= tt_data_sz;
4011
4012 num_entries = batadv_tt_entries(tvlv_value_len);
4013
4014 batadv_tt_update_orig(bat_priv, orig, tt_data->vlan_data, num_vlan,
4015 tt_change, num_entries, tt_data->ttvn);
4016 }
4017
4018 /**
4019 * batadv_tt_tvlv_unicast_handler_v1() - process incoming (unicast) tt tvlv
4020 * container
4021 * @bat_priv: the bat priv with all the mesh interface information
4022 * @src: mac address of tt tvlv sender
4023 * @dst: mac address of tt tvlv recipient
4024 * @tvlv_value: tvlv buffer containing the tt data
4025 * @tvlv_value_len: tvlv buffer length
4026 *
4027 * Return: NET_RX_DROP if the tt tvlv is to be re-routed, NET_RX_SUCCESS
4028 * otherwise.
4029 */
batadv_tt_tvlv_unicast_handler_v1(struct batadv_priv * bat_priv,u8 * src,u8 * dst,void * tvlv_value,u16 tvlv_value_len)4030 static int batadv_tt_tvlv_unicast_handler_v1(struct batadv_priv *bat_priv,
4031 u8 *src, u8 *dst,
4032 void *tvlv_value,
4033 u16 tvlv_value_len)
4034 {
4035 struct batadv_tvlv_tt_data *tt_data;
4036 u16 tt_vlan_len, tt_num_entries;
4037 char tt_flag;
4038 bool ret;
4039
4040 if (tvlv_value_len < sizeof(*tt_data))
4041 return NET_RX_SUCCESS;
4042
4043 tt_data = tvlv_value;
4044 tvlv_value_len -= sizeof(*tt_data);
4045
4046 tt_vlan_len = flex_array_size(tt_data, vlan_data,
4047 ntohs(tt_data->num_vlan));
4048
4049 if (tvlv_value_len < tt_vlan_len)
4050 return NET_RX_SUCCESS;
4051
4052 tvlv_value_len -= tt_vlan_len;
4053 tt_num_entries = batadv_tt_entries(tvlv_value_len);
4054
4055 switch (tt_data->flags & BATADV_TT_DATA_TYPE_MASK) {
4056 case BATADV_TT_REQUEST:
4057 batadv_inc_counter(bat_priv, BATADV_CNT_TT_REQUEST_RX);
4058
4059 /* If this node cannot provide a TT response the tt_request is
4060 * forwarded
4061 */
4062 ret = batadv_send_tt_response(bat_priv, tt_data, src, dst);
4063 if (!ret) {
4064 if (tt_data->flags & BATADV_TT_FULL_TABLE)
4065 tt_flag = 'F';
4066 else
4067 tt_flag = '.';
4068
4069 batadv_dbg(BATADV_DBG_TT, bat_priv,
4070 "Routing TT_REQUEST to %pM [%c]\n",
4071 dst, tt_flag);
4072 /* tvlv API will re-route the packet */
4073 return NET_RX_DROP;
4074 }
4075 break;
4076 case BATADV_TT_RESPONSE:
4077 batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_RX);
4078
4079 if (batadv_is_my_mac(bat_priv, dst)) {
4080 batadv_handle_tt_response(bat_priv, tt_data,
4081 src, tt_num_entries);
4082 return NET_RX_SUCCESS;
4083 }
4084
4085 if (tt_data->flags & BATADV_TT_FULL_TABLE)
4086 tt_flag = 'F';
4087 else
4088 tt_flag = '.';
4089
4090 batadv_dbg(BATADV_DBG_TT, bat_priv,
4091 "Routing TT_RESPONSE to %pM [%c]\n", dst, tt_flag);
4092
4093 /* tvlv API will re-route the packet */
4094 return NET_RX_DROP;
4095 }
4096
4097 return NET_RX_SUCCESS;
4098 }
4099
4100 /**
4101 * batadv_roam_tvlv_unicast_handler_v1() - process incoming tt roam tvlv
4102 * container
4103 * @bat_priv: the bat priv with all the mesh interface information
4104 * @src: mac address of tt tvlv sender
4105 * @dst: mac address of tt tvlv recipient
4106 * @tvlv_value: tvlv buffer containing the tt data
4107 * @tvlv_value_len: tvlv buffer length
4108 *
4109 * Return: NET_RX_DROP if the tt roam tvlv is to be re-routed, NET_RX_SUCCESS
4110 * otherwise.
4111 */
batadv_roam_tvlv_unicast_handler_v1(struct batadv_priv * bat_priv,u8 * src,u8 * dst,void * tvlv_value,u16 tvlv_value_len)4112 static int batadv_roam_tvlv_unicast_handler_v1(struct batadv_priv *bat_priv,
4113 u8 *src, u8 *dst,
4114 void *tvlv_value,
4115 u16 tvlv_value_len)
4116 {
4117 struct batadv_tvlv_roam_adv *roaming_adv;
4118 struct batadv_orig_node *orig_node = NULL;
4119
4120 /* If this node is not the intended recipient of the
4121 * roaming advertisement the packet is forwarded
4122 * (the tvlv API will re-route the packet).
4123 */
4124 if (!batadv_is_my_mac(bat_priv, dst))
4125 return NET_RX_DROP;
4126
4127 if (tvlv_value_len < sizeof(*roaming_adv))
4128 goto out;
4129
4130 orig_node = batadv_orig_hash_find(bat_priv, src);
4131 if (!orig_node)
4132 goto out;
4133
4134 batadv_inc_counter(bat_priv, BATADV_CNT_TT_ROAM_ADV_RX);
4135 roaming_adv = tvlv_value;
4136
4137 batadv_dbg(BATADV_DBG_TT, bat_priv,
4138 "Received ROAMING_ADV from %pM (client %pM)\n",
4139 src, roaming_adv->client);
4140
4141 batadv_tt_global_add(bat_priv, orig_node, roaming_adv->client,
4142 ntohs(roaming_adv->vid), BATADV_TT_CLIENT_ROAM,
4143 READ_ONCE(orig_node->last_ttvn) + 1);
4144
4145 out:
4146 batadv_orig_node_put(orig_node);
4147 return NET_RX_SUCCESS;
4148 }
4149
4150 /**
4151 * batadv_tt_init() - initialise the translation table internals
4152 * @bat_priv: the bat priv with all the mesh interface information
4153 *
4154 * Return: 0 on success or negative error number in case of failure.
4155 */
batadv_tt_init(struct batadv_priv * bat_priv)4156 int batadv_tt_init(struct batadv_priv *bat_priv)
4157 {
4158 int ret;
4159
4160 /* synchronized flags must be remote */
4161 BUILD_BUG_ON(!(BATADV_TT_SYNC_MASK & BATADV_TT_REMOTE_MASK));
4162
4163 ret = batadv_tt_local_init(bat_priv);
4164 if (ret < 0)
4165 return ret;
4166
4167 ret = batadv_tt_global_init(bat_priv);
4168 if (ret < 0) {
4169 batadv_tt_local_table_free(bat_priv);
4170 return ret;
4171 }
4172
4173 batadv_tvlv_handler_register(bat_priv, batadv_tt_tvlv_ogm_handler_v1,
4174 batadv_tt_tvlv_unicast_handler_v1, NULL,
4175 BATADV_TVLV_TT, 1, BATADV_NO_FLAGS);
4176
4177 batadv_tvlv_handler_register(bat_priv, NULL,
4178 batadv_roam_tvlv_unicast_handler_v1, NULL,
4179 BATADV_TVLV_ROAM, 1, BATADV_NO_FLAGS);
4180
4181 INIT_DELAYED_WORK(&bat_priv->tt.work, batadv_tt_purge);
4182 queue_delayed_work(batadv_event_workqueue, &bat_priv->tt.work,
4183 msecs_to_jiffies(BATADV_TT_WORK_PERIOD));
4184
4185 return 1;
4186 }
4187
4188 /**
4189 * batadv_tt_global_is_isolated() - check if a client is marked as isolated
4190 * @bat_priv: the bat priv with all the mesh interface information
4191 * @addr: the mac address of the client
4192 * @vid: the identifier of the VLAN where this client is connected
4193 *
4194 * Return: true if the client is marked with the TT_CLIENT_ISOLA flag, false
4195 * otherwise
4196 */
batadv_tt_global_is_isolated(struct batadv_priv * bat_priv,const u8 * addr,unsigned short vid)4197 bool batadv_tt_global_is_isolated(struct batadv_priv *bat_priv,
4198 const u8 *addr, unsigned short vid)
4199 {
4200 struct batadv_tt_global_entry *tt;
4201 bool ret;
4202
4203 tt = batadv_tt_global_hash_find(bat_priv, addr, vid);
4204 if (!tt)
4205 return false;
4206
4207 ret = tt->common.flags & BATADV_TT_CLIENT_ISOLA;
4208
4209 batadv_tt_global_entry_put(tt);
4210
4211 return ret;
4212 }
4213
4214 /**
4215 * batadv_tt_cache_init() - Initialize tt memory object cache
4216 *
4217 * Return: 0 on success or negative error number in case of failure.
4218 */
batadv_tt_cache_init(void)4219 int __init batadv_tt_cache_init(void)
4220 {
4221 size_t tl_size = sizeof(struct batadv_tt_local_entry);
4222 size_t tg_size = sizeof(struct batadv_tt_global_entry);
4223 size_t tt_orig_size = sizeof(struct batadv_tt_orig_list_entry);
4224 size_t tt_change_size = sizeof(struct batadv_tt_change_node);
4225 size_t tt_req_size = sizeof(struct batadv_tt_req_node);
4226 size_t tt_roam_size = sizeof(struct batadv_tt_roam_node);
4227
4228 batadv_tl_cache = kmem_cache_create("batadv_tl_cache", tl_size, 0,
4229 SLAB_HWCACHE_ALIGN, NULL);
4230 if (!batadv_tl_cache)
4231 return -ENOMEM;
4232
4233 batadv_tg_cache = kmem_cache_create("batadv_tg_cache", tg_size, 0,
4234 SLAB_HWCACHE_ALIGN, NULL);
4235 if (!batadv_tg_cache)
4236 goto err_tt_tl_destroy;
4237
4238 batadv_tt_orig_cache = kmem_cache_create("batadv_tt_orig_cache",
4239 tt_orig_size, 0,
4240 SLAB_HWCACHE_ALIGN, NULL);
4241 if (!batadv_tt_orig_cache)
4242 goto err_tt_tg_destroy;
4243
4244 batadv_tt_change_cache = kmem_cache_create("batadv_tt_change_cache",
4245 tt_change_size, 0,
4246 SLAB_HWCACHE_ALIGN, NULL);
4247 if (!batadv_tt_change_cache)
4248 goto err_tt_orig_destroy;
4249
4250 batadv_tt_req_cache = kmem_cache_create("batadv_tt_req_cache",
4251 tt_req_size, 0,
4252 SLAB_HWCACHE_ALIGN, NULL);
4253 if (!batadv_tt_req_cache)
4254 goto err_tt_change_destroy;
4255
4256 batadv_tt_roam_cache = kmem_cache_create("batadv_tt_roam_cache",
4257 tt_roam_size, 0,
4258 SLAB_HWCACHE_ALIGN, NULL);
4259 if (!batadv_tt_roam_cache)
4260 goto err_tt_req_destroy;
4261
4262 return 0;
4263
4264 err_tt_req_destroy:
4265 kmem_cache_destroy(batadv_tt_req_cache);
4266 batadv_tt_req_cache = NULL;
4267 err_tt_change_destroy:
4268 kmem_cache_destroy(batadv_tt_change_cache);
4269 batadv_tt_change_cache = NULL;
4270 err_tt_orig_destroy:
4271 kmem_cache_destroy(batadv_tt_orig_cache);
4272 batadv_tt_orig_cache = NULL;
4273 err_tt_tg_destroy:
4274 kmem_cache_destroy(batadv_tg_cache);
4275 batadv_tg_cache = NULL;
4276 err_tt_tl_destroy:
4277 kmem_cache_destroy(batadv_tl_cache);
4278 batadv_tl_cache = NULL;
4279
4280 return -ENOMEM;
4281 }
4282
4283 /**
4284 * batadv_tt_cache_destroy() - Destroy tt memory object cache
4285 */
batadv_tt_cache_destroy(void)4286 void batadv_tt_cache_destroy(void)
4287 {
4288 kmem_cache_destroy(batadv_tl_cache);
4289 kmem_cache_destroy(batadv_tg_cache);
4290 kmem_cache_destroy(batadv_tt_orig_cache);
4291 kmem_cache_destroy(batadv_tt_change_cache);
4292 kmem_cache_destroy(batadv_tt_req_cache);
4293 kmem_cache_destroy(batadv_tt_roam_cache);
4294 }
4295