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