linux/net/batman-adv/translation-table.c
<<
>>
Prefs
   1/* Copyright (C) 2007-2013 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, write to the Free Software
  16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  17 * 02110-1301, USA
  18 */
  19
  20#include "main.h"
  21#include "translation-table.h"
  22#include "soft-interface.h"
  23#include "hard-interface.h"
  24#include "send.h"
  25#include "hash.h"
  26#include "originator.h"
  27#include "routing.h"
  28#include "bridge_loop_avoidance.h"
  29
  30#include <linux/crc16.h>
  31
  32/* hash class keys */
  33static struct lock_class_key batadv_tt_local_hash_lock_class_key;
  34static struct lock_class_key batadv_tt_global_hash_lock_class_key;
  35
  36static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client,
  37                                 struct batadv_orig_node *orig_node);
  38static void batadv_tt_purge(struct work_struct *work);
  39static void
  40batadv_tt_global_del_orig_list(struct batadv_tt_global_entry *tt_global_entry);
  41static void batadv_tt_global_del(struct batadv_priv *bat_priv,
  42                                 struct batadv_orig_node *orig_node,
  43                                 const unsigned char *addr,
  44                                 const char *message, bool roaming);
  45
  46/* returns 1 if they are the same mac addr */
  47static int batadv_compare_tt(const struct hlist_node *node, const void *data2)
  48{
  49        const void *data1 = container_of(node, struct batadv_tt_common_entry,
  50                                         hash_entry);
  51
  52        return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
  53}
  54
  55static struct batadv_tt_common_entry *
  56batadv_tt_hash_find(struct batadv_hashtable *hash, const void *data)
  57{
  58        struct hlist_head *head;
  59        struct batadv_tt_common_entry *tt_common_entry;
  60        struct batadv_tt_common_entry *tt_common_entry_tmp = NULL;
  61        uint32_t index;
  62
  63        if (!hash)
  64                return NULL;
  65
  66        index = batadv_choose_orig(data, hash->size);
  67        head = &hash->table[index];
  68
  69        rcu_read_lock();
  70        hlist_for_each_entry_rcu(tt_common_entry, head, hash_entry) {
  71                if (!batadv_compare_eth(tt_common_entry, data))
  72                        continue;
  73
  74                if (!atomic_inc_not_zero(&tt_common_entry->refcount))
  75                        continue;
  76
  77                tt_common_entry_tmp = tt_common_entry;
  78                break;
  79        }
  80        rcu_read_unlock();
  81
  82        return tt_common_entry_tmp;
  83}
  84
  85static struct batadv_tt_local_entry *
  86batadv_tt_local_hash_find(struct batadv_priv *bat_priv, const void *data)
  87{
  88        struct batadv_tt_common_entry *tt_common_entry;
  89        struct batadv_tt_local_entry *tt_local_entry = NULL;
  90
  91        tt_common_entry = batadv_tt_hash_find(bat_priv->tt.local_hash, data);
  92        if (tt_common_entry)
  93                tt_local_entry = container_of(tt_common_entry,
  94                                              struct batadv_tt_local_entry,
  95                                              common);
  96        return tt_local_entry;
  97}
  98
  99static struct batadv_tt_global_entry *
 100batadv_tt_global_hash_find(struct batadv_priv *bat_priv, const void *data)
 101{
 102        struct batadv_tt_common_entry *tt_common_entry;
 103        struct batadv_tt_global_entry *tt_global_entry = NULL;
 104
 105        tt_common_entry = batadv_tt_hash_find(bat_priv->tt.global_hash, data);
 106        if (tt_common_entry)
 107                tt_global_entry = container_of(tt_common_entry,
 108                                               struct batadv_tt_global_entry,
 109                                               common);
 110        return tt_global_entry;
 111}
 112
 113static void
 114batadv_tt_local_entry_free_ref(struct batadv_tt_local_entry *tt_local_entry)
 115{
 116        if (atomic_dec_and_test(&tt_local_entry->common.refcount))
 117                kfree_rcu(tt_local_entry, common.rcu);
 118}
 119
 120static void batadv_tt_global_entry_free_rcu(struct rcu_head *rcu)
 121{
 122        struct batadv_tt_common_entry *tt_common_entry;
 123        struct batadv_tt_global_entry *tt_global_entry;
 124
 125        tt_common_entry = container_of(rcu, struct batadv_tt_common_entry, rcu);
 126        tt_global_entry = container_of(tt_common_entry,
 127                                       struct batadv_tt_global_entry, common);
 128
 129        kfree(tt_global_entry);
 130}
 131
 132static void
 133batadv_tt_global_entry_free_ref(struct batadv_tt_global_entry *tt_global_entry)
 134{
 135        if (atomic_dec_and_test(&tt_global_entry->common.refcount)) {
 136                batadv_tt_global_del_orig_list(tt_global_entry);
 137                call_rcu(&tt_global_entry->common.rcu,
 138                         batadv_tt_global_entry_free_rcu);
 139        }
 140}
 141
 142static void batadv_tt_orig_list_entry_free_rcu(struct rcu_head *rcu)
 143{
 144        struct batadv_tt_orig_list_entry *orig_entry;
 145
 146        orig_entry = container_of(rcu, struct batadv_tt_orig_list_entry, rcu);
 147
 148        /* We are in an rcu callback here, therefore we cannot use
 149         * batadv_orig_node_free_ref() and its call_rcu():
 150         * An rcu_barrier() wouldn't wait for that to finish
 151         */
 152        batadv_orig_node_free_ref_now(orig_entry->orig_node);
 153        kfree(orig_entry);
 154}
 155
 156static void
 157batadv_tt_orig_list_entry_free_ref(struct batadv_tt_orig_list_entry *orig_entry)
 158{
 159        if (!atomic_dec_and_test(&orig_entry->refcount))
 160                return;
 161        /* to avoid race conditions, immediately decrease the tt counter */
 162        atomic_dec(&orig_entry->orig_node->tt_size);
 163        call_rcu(&orig_entry->rcu, batadv_tt_orig_list_entry_free_rcu);
 164}
 165
 166static void batadv_tt_local_event(struct batadv_priv *bat_priv,
 167                                  const uint8_t *addr, uint8_t flags)
 168{
 169        struct batadv_tt_change_node *tt_change_node, *entry, *safe;
 170        bool event_removed = false;
 171        bool del_op_requested, del_op_entry;
 172
 173        tt_change_node = kmalloc(sizeof(*tt_change_node), GFP_ATOMIC);
 174
 175        if (!tt_change_node)
 176                return;
 177
 178        tt_change_node->change.flags = flags;
 179        memcpy(tt_change_node->change.addr, addr, ETH_ALEN);
 180
 181        del_op_requested = flags & BATADV_TT_CLIENT_DEL;
 182
 183        /* check for ADD+DEL or DEL+ADD events */
 184        spin_lock_bh(&bat_priv->tt.changes_list_lock);
 185        list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list,
 186                                 list) {
 187                if (!batadv_compare_eth(entry->change.addr, addr))
 188                        continue;
 189
 190                /* DEL+ADD in the same orig interval have no effect and can be
 191                 * removed to avoid silly behaviour on the receiver side. The
 192                 * other way around (ADD+DEL) can happen in case of roaming of
 193                 * a client still in the NEW state. Roaming of NEW clients is
 194                 * now possible due to automatically recognition of "temporary"
 195                 * clients
 196                 */
 197                del_op_entry = entry->change.flags & BATADV_TT_CLIENT_DEL;
 198                if (!del_op_requested && del_op_entry)
 199                        goto del;
 200                if (del_op_requested && !del_op_entry)
 201                        goto del;
 202                continue;
 203del:
 204                list_del(&entry->list);
 205                kfree(entry);
 206                kfree(tt_change_node);
 207                event_removed = true;
 208                goto unlock;
 209        }
 210
 211        /* track the change in the OGMinterval list */
 212        list_add_tail(&tt_change_node->list, &bat_priv->tt.changes_list);
 213
 214unlock:
 215        spin_unlock_bh(&bat_priv->tt.changes_list_lock);
 216
 217        if (event_removed)
 218                atomic_dec(&bat_priv->tt.local_changes);
 219        else
 220                atomic_inc(&bat_priv->tt.local_changes);
 221}
 222
 223int batadv_tt_len(int changes_num)
 224{
 225        return changes_num * sizeof(struct batadv_tt_change);
 226}
 227
 228static int batadv_tt_local_init(struct batadv_priv *bat_priv)
 229{
 230        if (bat_priv->tt.local_hash)
 231                return 0;
 232
 233        bat_priv->tt.local_hash = batadv_hash_new(1024);
 234
 235        if (!bat_priv->tt.local_hash)
 236                return -ENOMEM;
 237
 238        batadv_hash_set_lock_class(bat_priv->tt.local_hash,
 239                                   &batadv_tt_local_hash_lock_class_key);
 240
 241        return 0;
 242}
 243
 244static void batadv_tt_global_free(struct batadv_priv *bat_priv,
 245                                  struct batadv_tt_global_entry *tt_global,
 246                                  const char *message)
 247{
 248        batadv_dbg(BATADV_DBG_TT, bat_priv,
 249                   "Deleting global tt entry %pM: %s\n",
 250                   tt_global->common.addr, message);
 251
 252        batadv_hash_remove(bat_priv->tt.global_hash, batadv_compare_tt,
 253                           batadv_choose_orig, tt_global->common.addr);
 254        batadv_tt_global_entry_free_ref(tt_global);
 255}
 256
 257void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
 258                         int ifindex)
 259{
 260        struct batadv_priv *bat_priv = netdev_priv(soft_iface);
 261        struct batadv_tt_local_entry *tt_local;
 262        struct batadv_tt_global_entry *tt_global;
 263        struct hlist_head *head;
 264        struct batadv_tt_orig_list_entry *orig_entry;
 265        int hash_added;
 266        bool roamed_back = false;
 267
 268        tt_local = batadv_tt_local_hash_find(bat_priv, addr);
 269        tt_global = batadv_tt_global_hash_find(bat_priv, addr);
 270
 271        if (tt_local) {
 272                tt_local->last_seen = jiffies;
 273                if (tt_local->common.flags & BATADV_TT_CLIENT_PENDING) {
 274                        batadv_dbg(BATADV_DBG_TT, bat_priv,
 275                                   "Re-adding pending client %pM\n", addr);
 276                        /* whatever the reason why the PENDING flag was set,
 277                         * this is a client which was enqueued to be removed in
 278                         * this orig_interval. Since it popped up again, the
 279                         * flag can be reset like it was never enqueued
 280                         */
 281                        tt_local->common.flags &= ~BATADV_TT_CLIENT_PENDING;
 282                        goto add_event;
 283                }
 284
 285                if (tt_local->common.flags & BATADV_TT_CLIENT_ROAM) {
 286                        batadv_dbg(BATADV_DBG_TT, bat_priv,
 287                                   "Roaming client %pM came back to its original location\n",
 288                                   addr);
 289                        /* the ROAM flag is set because this client roamed away
 290                         * and the node got a roaming_advertisement message. Now
 291                         * that the client popped up again at its original
 292                         * location such flag can be unset
 293                         */
 294                        tt_local->common.flags &= ~BATADV_TT_CLIENT_ROAM;
 295                        roamed_back = true;
 296                }
 297                goto check_roaming;
 298        }
 299
 300        tt_local = kmalloc(sizeof(*tt_local), GFP_ATOMIC);
 301        if (!tt_local)
 302                goto out;
 303
 304        batadv_dbg(BATADV_DBG_TT, bat_priv,
 305                   "Creating new local tt entry: %pM (ttvn: %d)\n", addr,
 306                   (uint8_t)atomic_read(&bat_priv->tt.vn));
 307
 308        memcpy(tt_local->common.addr, addr, ETH_ALEN);
 309        /* The local entry has to be marked as NEW to avoid to send it in
 310         * a full table response going out before the next ttvn increment
 311         * (consistency check)
 312         */
 313        tt_local->common.flags = BATADV_TT_CLIENT_NEW;
 314        if (batadv_is_wifi_iface(ifindex))
 315                tt_local->common.flags |= BATADV_TT_CLIENT_WIFI;
 316        atomic_set(&tt_local->common.refcount, 2);
 317        tt_local->last_seen = jiffies;
 318        tt_local->common.added_at = tt_local->last_seen;
 319
 320        /* the batman interface mac address should never be purged */
 321        if (batadv_compare_eth(addr, soft_iface->dev_addr))
 322                tt_local->common.flags |= BATADV_TT_CLIENT_NOPURGE;
 323
 324        hash_added = batadv_hash_add(bat_priv->tt.local_hash, batadv_compare_tt,
 325                                     batadv_choose_orig, &tt_local->common,
 326                                     &tt_local->common.hash_entry);
 327
 328        if (unlikely(hash_added != 0)) {
 329                /* remove the reference for the hash */
 330                batadv_tt_local_entry_free_ref(tt_local);
 331                goto out;
 332        }
 333
 334add_event:
 335        batadv_tt_local_event(bat_priv, addr, tt_local->common.flags);
 336
 337check_roaming:
 338        /* Check whether it is a roaming, but don't do anything if the roaming
 339         * process has already been handled
 340         */
 341        if (tt_global && !(tt_global->common.flags & BATADV_TT_CLIENT_ROAM)) {
 342                /* These node are probably going to update their tt table */
 343                head = &tt_global->orig_list;
 344                rcu_read_lock();
 345                hlist_for_each_entry_rcu(orig_entry, head, list) {
 346                        batadv_send_roam_adv(bat_priv, tt_global->common.addr,
 347                                             orig_entry->orig_node);
 348                }
 349                rcu_read_unlock();
 350                if (roamed_back) {
 351                        batadv_tt_global_free(bat_priv, tt_global,
 352                                              "Roaming canceled");
 353                        tt_global = NULL;
 354                } else {
 355                        /* The global entry has to be marked as ROAMING and
 356                         * has to be kept for consistency purpose
 357                         */
 358                        tt_global->common.flags |= BATADV_TT_CLIENT_ROAM;
 359                        tt_global->roam_at = jiffies;
 360                }
 361        }
 362
 363out:
 364        if (tt_local)
 365                batadv_tt_local_entry_free_ref(tt_local);
 366        if (tt_global)
 367                batadv_tt_global_entry_free_ref(tt_global);
 368}
 369
 370static void batadv_tt_realloc_packet_buff(unsigned char **packet_buff,
 371                                          int *packet_buff_len,
 372                                          int min_packet_len,
 373                                          int new_packet_len)
 374{
 375        unsigned char *new_buff;
 376
 377        new_buff = kmalloc(new_packet_len, GFP_ATOMIC);
 378
 379        /* keep old buffer if kmalloc should fail */
 380        if (new_buff) {
 381                memcpy(new_buff, *packet_buff, min_packet_len);
 382                kfree(*packet_buff);
 383                *packet_buff = new_buff;
 384                *packet_buff_len = new_packet_len;
 385        }
 386}
 387
 388static void batadv_tt_prepare_packet_buff(struct batadv_priv *bat_priv,
 389                                          unsigned char **packet_buff,
 390                                          int *packet_buff_len,
 391                                          int min_packet_len)
 392{
 393        int req_len;
 394
 395        req_len = min_packet_len;
 396        req_len += batadv_tt_len(atomic_read(&bat_priv->tt.local_changes));
 397
 398        /* if we have too many changes for one packet don't send any
 399         * and wait for the tt table request which will be fragmented
 400         */
 401        if (req_len > bat_priv->soft_iface->mtu)
 402                req_len = min_packet_len;
 403
 404        batadv_tt_realloc_packet_buff(packet_buff, packet_buff_len,
 405                                      min_packet_len, req_len);
 406}
 407
 408static int batadv_tt_changes_fill_buff(struct batadv_priv *bat_priv,
 409                                       unsigned char **packet_buff,
 410                                       int *packet_buff_len,
 411                                       int min_packet_len)
 412{
 413        struct batadv_tt_change_node *entry, *safe;
 414        int count = 0, tot_changes = 0, new_len;
 415        unsigned char *tt_buff;
 416
 417        batadv_tt_prepare_packet_buff(bat_priv, packet_buff,
 418                                      packet_buff_len, min_packet_len);
 419
 420        new_len = *packet_buff_len - min_packet_len;
 421        tt_buff = *packet_buff + min_packet_len;
 422
 423        if (new_len > 0)
 424                tot_changes = new_len / batadv_tt_len(1);
 425
 426        spin_lock_bh(&bat_priv->tt.changes_list_lock);
 427        atomic_set(&bat_priv->tt.local_changes, 0);
 428
 429        list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list,
 430                                 list) {
 431                if (count < tot_changes) {
 432                        memcpy(tt_buff + batadv_tt_len(count),
 433                               &entry->change, sizeof(struct batadv_tt_change));
 434                        count++;
 435                }
 436                list_del(&entry->list);
 437                kfree(entry);
 438        }
 439        spin_unlock_bh(&bat_priv->tt.changes_list_lock);
 440
 441        /* Keep the buffer for possible tt_request */
 442        spin_lock_bh(&bat_priv->tt.last_changeset_lock);
 443        kfree(bat_priv->tt.last_changeset);
 444        bat_priv->tt.last_changeset_len = 0;
 445        bat_priv->tt.last_changeset = NULL;
 446        /* check whether this new OGM has no changes due to size problems */
 447        if (new_len > 0) {
 448                /* if kmalloc() fails we will reply with the full table
 449                 * instead of providing the diff
 450                 */
 451                bat_priv->tt.last_changeset = kmalloc(new_len, GFP_ATOMIC);
 452                if (bat_priv->tt.last_changeset) {
 453                        memcpy(bat_priv->tt.last_changeset, tt_buff, new_len);
 454                        bat_priv->tt.last_changeset_len = new_len;
 455                }
 456        }
 457        spin_unlock_bh(&bat_priv->tt.last_changeset_lock);
 458
 459        return count;
 460}
 461
 462int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
 463{
 464        struct net_device *net_dev = (struct net_device *)seq->private;
 465        struct batadv_priv *bat_priv = netdev_priv(net_dev);
 466        struct batadv_hashtable *hash = bat_priv->tt.local_hash;
 467        struct batadv_tt_common_entry *tt_common_entry;
 468        struct batadv_tt_local_entry *tt_local;
 469        struct batadv_hard_iface *primary_if;
 470        struct hlist_head *head;
 471        uint32_t i;
 472        int last_seen_secs;
 473        int last_seen_msecs;
 474        unsigned long last_seen_jiffies;
 475        bool no_purge;
 476        uint16_t np_flag = BATADV_TT_CLIENT_NOPURGE;
 477
 478        primary_if = batadv_seq_print_text_primary_if_get(seq);
 479        if (!primary_if)
 480                goto out;
 481
 482        seq_printf(seq,
 483                   "Locally retrieved addresses (from %s) announced via TT (TTVN: %u CRC: %#.4x):\n",
 484                   net_dev->name, (uint8_t)atomic_read(&bat_priv->tt.vn),
 485                   bat_priv->tt.local_crc);
 486        seq_printf(seq, "       %-13s %-7s %-10s\n", "Client", "Flags",
 487                   "Last seen");
 488
 489        for (i = 0; i < hash->size; i++) {
 490                head = &hash->table[i];
 491
 492                rcu_read_lock();
 493                hlist_for_each_entry_rcu(tt_common_entry,
 494                                         head, hash_entry) {
 495                        tt_local = container_of(tt_common_entry,
 496                                                struct batadv_tt_local_entry,
 497                                                common);
 498                        last_seen_jiffies = jiffies - tt_local->last_seen;
 499                        last_seen_msecs = jiffies_to_msecs(last_seen_jiffies);
 500                        last_seen_secs = last_seen_msecs / 1000;
 501                        last_seen_msecs = last_seen_msecs % 1000;
 502
 503                        no_purge = tt_common_entry->flags & np_flag;
 504
 505                        seq_printf(seq, " * %pM [%c%c%c%c%c] %3u.%03u\n",
 506                                   tt_common_entry->addr,
 507                                   (tt_common_entry->flags &
 508                                    BATADV_TT_CLIENT_ROAM ? 'R' : '.'),
 509                                   no_purge ? 'P' : '.',
 510                                   (tt_common_entry->flags &
 511                                    BATADV_TT_CLIENT_NEW ? 'N' : '.'),
 512                                   (tt_common_entry->flags &
 513                                    BATADV_TT_CLIENT_PENDING ? 'X' : '.'),
 514                                   (tt_common_entry->flags &
 515                                    BATADV_TT_CLIENT_WIFI ? 'W' : '.'),
 516                                   no_purge ? 0 : last_seen_secs,
 517                                   no_purge ? 0 : last_seen_msecs);
 518                }
 519                rcu_read_unlock();
 520        }
 521out:
 522        if (primary_if)
 523                batadv_hardif_free_ref(primary_if);
 524        return 0;
 525}
 526
 527static void
 528batadv_tt_local_set_pending(struct batadv_priv *bat_priv,
 529                            struct batadv_tt_local_entry *tt_local_entry,
 530                            uint16_t flags, const char *message)
 531{
 532        batadv_tt_local_event(bat_priv, tt_local_entry->common.addr,
 533                              tt_local_entry->common.flags | flags);
 534
 535        /* The local client has to be marked as "pending to be removed" but has
 536         * to be kept in the table in order to send it in a full table
 537         * response issued before the net ttvn increment (consistency check)
 538         */
 539        tt_local_entry->common.flags |= BATADV_TT_CLIENT_PENDING;
 540
 541        batadv_dbg(BATADV_DBG_TT, bat_priv,
 542                   "Local tt entry (%pM) pending to be removed: %s\n",
 543                   tt_local_entry->common.addr, message);
 544}
 545
 546/**
 547 * batadv_tt_local_remove - logically remove an entry from the local table
 548 * @bat_priv: the bat priv with all the soft interface information
 549 * @addr: the MAC address of the client to remove
 550 * @message: message to append to the log on deletion
 551 * @roaming: true if the deletion is due to a roaming event
 552 *
 553 * Returns the flags assigned to the local entry before being deleted
 554 */
 555uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv,
 556                                const uint8_t *addr, const char *message,
 557                                bool roaming)
 558{
 559        struct batadv_tt_local_entry *tt_local_entry;
 560        uint16_t flags, curr_flags = BATADV_NO_FLAGS;
 561
 562        tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr);
 563        if (!tt_local_entry)
 564                goto out;
 565
 566        curr_flags = tt_local_entry->common.flags;
 567
 568        flags = BATADV_TT_CLIENT_DEL;
 569        /* if this global entry addition is due to a roaming, the node has to
 570         * mark the local entry as "roamed" in order to correctly reroute
 571         * packets later
 572         */
 573        if (roaming) {
 574                flags |= BATADV_TT_CLIENT_ROAM;
 575                /* mark the local client as ROAMed */
 576                tt_local_entry->common.flags |= BATADV_TT_CLIENT_ROAM;
 577        }
 578
 579        if (!(tt_local_entry->common.flags & BATADV_TT_CLIENT_NEW)) {
 580                batadv_tt_local_set_pending(bat_priv, tt_local_entry, flags,
 581                                            message);
 582                goto out;
 583        }
 584        /* if this client has been added right now, it is possible to
 585         * immediately purge it
 586         */
 587        batadv_tt_local_event(bat_priv, tt_local_entry->common.addr,
 588                              curr_flags | BATADV_TT_CLIENT_DEL);
 589        hlist_del_rcu(&tt_local_entry->common.hash_entry);
 590        batadv_tt_local_entry_free_ref(tt_local_entry);
 591
 592out:
 593        if (tt_local_entry)
 594                batadv_tt_local_entry_free_ref(tt_local_entry);
 595
 596        return curr_flags;
 597}
 598
 599static void batadv_tt_local_purge_list(struct batadv_priv *bat_priv,
 600                                       struct hlist_head *head)
 601{
 602        struct batadv_tt_local_entry *tt_local_entry;
 603        struct batadv_tt_common_entry *tt_common_entry;
 604        struct hlist_node *node_tmp;
 605
 606        hlist_for_each_entry_safe(tt_common_entry, node_tmp, head,
 607                                  hash_entry) {
 608                tt_local_entry = container_of(tt_common_entry,
 609                                              struct batadv_tt_local_entry,
 610                                              common);
 611                if (tt_local_entry->common.flags & BATADV_TT_CLIENT_NOPURGE)
 612                        continue;
 613
 614                /* entry already marked for deletion */
 615                if (tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING)
 616                        continue;
 617
 618                if (!batadv_has_timed_out(tt_local_entry->last_seen,
 619                                          BATADV_TT_LOCAL_TIMEOUT))
 620                        continue;
 621
 622                batadv_tt_local_set_pending(bat_priv, tt_local_entry,
 623                                            BATADV_TT_CLIENT_DEL, "timed out");
 624        }
 625}
 626
 627static void batadv_tt_local_purge(struct batadv_priv *bat_priv)
 628{
 629        struct batadv_hashtable *hash = bat_priv->tt.local_hash;
 630        struct hlist_head *head;
 631        spinlock_t *list_lock; /* protects write access to the hash lists */
 632        uint32_t i;
 633
 634        for (i = 0; i < hash->size; i++) {
 635                head = &hash->table[i];
 636                list_lock = &hash->list_locks[i];
 637
 638                spin_lock_bh(list_lock);
 639                batadv_tt_local_purge_list(bat_priv, head);
 640                spin_unlock_bh(list_lock);
 641        }
 642}
 643
 644static void batadv_tt_local_table_free(struct batadv_priv *bat_priv)
 645{
 646        struct batadv_hashtable *hash;
 647        spinlock_t *list_lock; /* protects write access to the hash lists */
 648        struct batadv_tt_common_entry *tt_common_entry;
 649        struct batadv_tt_local_entry *tt_local;
 650        struct hlist_node *node_tmp;
 651        struct hlist_head *head;
 652        uint32_t i;
 653
 654        if (!bat_priv->tt.local_hash)
 655                return;
 656
 657        hash = bat_priv->tt.local_hash;
 658
 659        for (i = 0; i < hash->size; i++) {
 660                head = &hash->table[i];
 661                list_lock = &hash->list_locks[i];
 662
 663                spin_lock_bh(list_lock);
 664                hlist_for_each_entry_safe(tt_common_entry, node_tmp,
 665                                          head, hash_entry) {
 666                        hlist_del_rcu(&tt_common_entry->hash_entry);
 667                        tt_local = container_of(tt_common_entry,
 668                                                struct batadv_tt_local_entry,
 669                                                common);
 670                        batadv_tt_local_entry_free_ref(tt_local);
 671                }
 672                spin_unlock_bh(list_lock);
 673        }
 674
 675        batadv_hash_destroy(hash);
 676
 677        bat_priv->tt.local_hash = NULL;
 678}
 679
 680static int batadv_tt_global_init(struct batadv_priv *bat_priv)
 681{
 682        if (bat_priv->tt.global_hash)
 683                return 0;
 684
 685        bat_priv->tt.global_hash = batadv_hash_new(1024);
 686
 687        if (!bat_priv->tt.global_hash)
 688                return -ENOMEM;
 689
 690        batadv_hash_set_lock_class(bat_priv->tt.global_hash,
 691                                   &batadv_tt_global_hash_lock_class_key);
 692
 693        return 0;
 694}
 695
 696static void batadv_tt_changes_list_free(struct batadv_priv *bat_priv)
 697{
 698        struct batadv_tt_change_node *entry, *safe;
 699
 700        spin_lock_bh(&bat_priv->tt.changes_list_lock);
 701
 702        list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list,
 703                                 list) {
 704                list_del(&entry->list);
 705                kfree(entry);
 706        }
 707
 708        atomic_set(&bat_priv->tt.local_changes, 0);
 709        spin_unlock_bh(&bat_priv->tt.changes_list_lock);
 710}
 711
 712/* retrieves the orig_tt_list_entry belonging to orig_node from the
 713 * batadv_tt_global_entry list
 714 *
 715 * returns it with an increased refcounter, NULL if not found
 716 */
 717static struct batadv_tt_orig_list_entry *
 718batadv_tt_global_orig_entry_find(const struct batadv_tt_global_entry *entry,
 719                                 const struct batadv_orig_node *orig_node)
 720{
 721        struct batadv_tt_orig_list_entry *tmp_orig_entry, *orig_entry = NULL;
 722        const struct hlist_head *head;
 723
 724        rcu_read_lock();
 725        head = &entry->orig_list;
 726        hlist_for_each_entry_rcu(tmp_orig_entry, head, list) {
 727                if (tmp_orig_entry->orig_node != orig_node)
 728                        continue;
 729                if (!atomic_inc_not_zero(&tmp_orig_entry->refcount))
 730                        continue;
 731
 732                orig_entry = tmp_orig_entry;
 733                break;
 734        }
 735        rcu_read_unlock();
 736
 737        return orig_entry;
 738}
 739
 740/* find out if an orig_node is already in the list of a tt_global_entry.
 741 * returns true if found, false otherwise
 742 */
 743static bool
 744batadv_tt_global_entry_has_orig(const struct batadv_tt_global_entry *entry,
 745                                const struct batadv_orig_node *orig_node)
 746{
 747        struct batadv_tt_orig_list_entry *orig_entry;
 748        bool found = false;
 749
 750        orig_entry = batadv_tt_global_orig_entry_find(entry, orig_node);
 751        if (orig_entry) {
 752                found = true;
 753                batadv_tt_orig_list_entry_free_ref(orig_entry);
 754        }
 755
 756        return found;
 757}
 758
 759static void
 760batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global,
 761                                struct batadv_orig_node *orig_node, int ttvn)
 762{
 763        struct batadv_tt_orig_list_entry *orig_entry;
 764
 765        orig_entry = batadv_tt_global_orig_entry_find(tt_global, orig_node);
 766        if (orig_entry) {
 767                /* refresh the ttvn: the current value could be a bogus one that
 768                 * was added during a "temporary client detection"
 769                 */
 770                orig_entry->ttvn = ttvn;
 771                goto out;
 772        }
 773
 774        orig_entry = kzalloc(sizeof(*orig_entry), GFP_ATOMIC);
 775        if (!orig_entry)
 776                goto out;
 777
 778        INIT_HLIST_NODE(&orig_entry->list);
 779        atomic_inc(&orig_node->refcount);
 780        atomic_inc(&orig_node->tt_size);
 781        orig_entry->orig_node = orig_node;
 782        orig_entry->ttvn = ttvn;
 783        atomic_set(&orig_entry->refcount, 2);
 784
 785        spin_lock_bh(&tt_global->list_lock);
 786        hlist_add_head_rcu(&orig_entry->list,
 787                           &tt_global->orig_list);
 788        spin_unlock_bh(&tt_global->list_lock);
 789out:
 790        if (orig_entry)
 791                batadv_tt_orig_list_entry_free_ref(orig_entry);
 792}
 793
 794/* caller must hold orig_node refcount */
 795int batadv_tt_global_add(struct batadv_priv *bat_priv,
 796                         struct batadv_orig_node *orig_node,
 797                         const unsigned char *tt_addr, uint8_t flags,
 798                         uint8_t ttvn)
 799{
 800        struct batadv_tt_global_entry *tt_global_entry;
 801        struct batadv_tt_local_entry *tt_local_entry;
 802        int ret = 0;
 803        int hash_added;
 804        struct batadv_tt_common_entry *common;
 805        uint16_t local_flags;
 806
 807        tt_global_entry = batadv_tt_global_hash_find(bat_priv, tt_addr);
 808        tt_local_entry = batadv_tt_local_hash_find(bat_priv, tt_addr);
 809
 810        /* if the node already has a local client for this entry, it has to wait
 811         * for a roaming advertisement instead of manually messing up the global
 812         * table
 813         */
 814        if ((flags & BATADV_TT_CLIENT_TEMP) && tt_local_entry &&
 815            !(tt_local_entry->common.flags & BATADV_TT_CLIENT_NEW))
 816                goto out;
 817
 818        if (!tt_global_entry) {
 819                tt_global_entry = kzalloc(sizeof(*tt_global_entry), GFP_ATOMIC);
 820                if (!tt_global_entry)
 821                        goto out;
 822
 823                common = &tt_global_entry->common;
 824                memcpy(common->addr, tt_addr, ETH_ALEN);
 825
 826                common->flags = flags;
 827                tt_global_entry->roam_at = 0;
 828                /* node must store current time in case of roaming. This is
 829                 * needed to purge this entry out on timeout (if nobody claims
 830                 * it)
 831                 */
 832                if (flags & BATADV_TT_CLIENT_ROAM)
 833                        tt_global_entry->roam_at = jiffies;
 834                atomic_set(&common->refcount, 2);
 835                common->added_at = jiffies;
 836
 837                INIT_HLIST_HEAD(&tt_global_entry->orig_list);
 838                spin_lock_init(&tt_global_entry->list_lock);
 839
 840                hash_added = batadv_hash_add(bat_priv->tt.global_hash,
 841                                             batadv_compare_tt,
 842                                             batadv_choose_orig, common,
 843                                             &common->hash_entry);
 844
 845                if (unlikely(hash_added != 0)) {
 846                        /* remove the reference for the hash */
 847                        batadv_tt_global_entry_free_ref(tt_global_entry);
 848                        goto out_remove;
 849                }
 850        } else {
 851                common = &tt_global_entry->common;
 852                /* If there is already a global entry, we can use this one for
 853                 * our processing.
 854                 * But if we are trying to add a temporary client then here are
 855                 * two options at this point:
 856                 * 1) the global client is not a temporary client: the global
 857                 *    client has to be left as it is, temporary information
 858                 *    should never override any already known client state
 859                 * 2) the global client is a temporary client: purge the
 860                 *    originator list and add the new one orig_entry
 861                 */
 862                if (flags & BATADV_TT_CLIENT_TEMP) {
 863                        if (!(common->flags & BATADV_TT_CLIENT_TEMP))
 864                                goto out;
 865                        if (batadv_tt_global_entry_has_orig(tt_global_entry,
 866                                                            orig_node))
 867                                goto out_remove;
 868                        batadv_tt_global_del_orig_list(tt_global_entry);
 869                        goto add_orig_entry;
 870                }
 871
 872                /* if the client was temporary added before receiving the first
 873                 * OGM announcing it, we have to clear the TEMP flag
 874                 */
 875                common->flags &= ~BATADV_TT_CLIENT_TEMP;
 876
 877                /* the change can carry possible "attribute" flags like the
 878                 * TT_CLIENT_WIFI, therefore they have to be copied in the
 879                 * client entry
 880                 */
 881                tt_global_entry->common.flags |= flags;
 882
 883                /* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only
 884                 * one originator left in the list and we previously received a
 885                 * delete + roaming change for this originator.
 886                 *
 887                 * We should first delete the old originator before adding the
 888                 * new one.
 889                 */
 890                if (common->flags & BATADV_TT_CLIENT_ROAM) {
 891                        batadv_tt_global_del_orig_list(tt_global_entry);
 892                        common->flags &= ~BATADV_TT_CLIENT_ROAM;
 893                        tt_global_entry->roam_at = 0;
 894                }
 895        }
 896add_orig_entry:
 897        /* add the new orig_entry (if needed) or update it */
 898        batadv_tt_global_orig_entry_add(tt_global_entry, orig_node, ttvn);
 899
 900        batadv_dbg(BATADV_DBG_TT, bat_priv,
 901                   "Creating new global tt entry: %pM (via %pM)\n",
 902                   common->addr, orig_node->orig);
 903        ret = 1;
 904
 905out_remove:
 906
 907        /* remove address from local hash if present */
 908        local_flags = batadv_tt_local_remove(bat_priv, tt_addr,
 909                                             "global tt received",
 910                                             flags & BATADV_TT_CLIENT_ROAM);
 911        tt_global_entry->common.flags |= local_flags & BATADV_TT_CLIENT_WIFI;
 912
 913        if (!(flags & BATADV_TT_CLIENT_ROAM))
 914                /* this is a normal global add. Therefore the client is not in a
 915                 * roaming state anymore.
 916                 */
 917                tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_ROAM;
 918
 919out:
 920        if (tt_global_entry)
 921                batadv_tt_global_entry_free_ref(tt_global_entry);
 922        if (tt_local_entry)
 923                batadv_tt_local_entry_free_ref(tt_local_entry);
 924        return ret;
 925}
 926
 927/* batadv_transtable_best_orig - Get best originator list entry from tt entry
 928 * @tt_global_entry: global translation table entry to be analyzed
 929 *
 930 * This functon assumes the caller holds rcu_read_lock().
 931 * Returns best originator list entry or NULL on errors.
 932 */
 933static struct batadv_tt_orig_list_entry *
 934batadv_transtable_best_orig(struct batadv_tt_global_entry *tt_global_entry)
 935{
 936        struct batadv_neigh_node *router = NULL;
 937        struct hlist_head *head;
 938        struct batadv_tt_orig_list_entry *orig_entry, *best_entry = NULL;
 939        int best_tq = 0;
 940
 941        head = &tt_global_entry->orig_list;
 942        hlist_for_each_entry_rcu(orig_entry, head, list) {
 943                router = batadv_orig_node_get_router(orig_entry->orig_node);
 944                if (!router)
 945                        continue;
 946
 947                if (router->tq_avg > best_tq) {
 948                        best_entry = orig_entry;
 949                        best_tq = router->tq_avg;
 950                }
 951
 952                batadv_neigh_node_free_ref(router);
 953        }
 954
 955        return best_entry;
 956}
 957
 958/* batadv_tt_global_print_entry - print all orig nodes who announce the address
 959 * for this global entry
 960 * @tt_global_entry: global translation table entry to be printed
 961 * @seq: debugfs table seq_file struct
 962 *
 963 * This functon assumes the caller holds rcu_read_lock().
 964 */
 965static void
 966batadv_tt_global_print_entry(struct batadv_tt_global_entry *tt_global_entry,
 967                             struct seq_file *seq)
 968{
 969        struct hlist_head *head;
 970        struct batadv_tt_orig_list_entry *orig_entry, *best_entry;
 971        struct batadv_tt_common_entry *tt_common_entry;
 972        uint16_t flags;
 973        uint8_t last_ttvn;
 974
 975        tt_common_entry = &tt_global_entry->common;
 976        flags = tt_common_entry->flags;
 977
 978        best_entry = batadv_transtable_best_orig(tt_global_entry);
 979        if (best_entry) {
 980                last_ttvn = atomic_read(&best_entry->orig_node->last_ttvn);
 981                seq_printf(seq,
 982                           " %c %pM  (%3u) via %pM     (%3u)   (%#.4x) [%c%c%c]\n",
 983                           '*', tt_global_entry->common.addr,
 984                           best_entry->ttvn, best_entry->orig_node->orig,
 985                           last_ttvn, best_entry->orig_node->tt_crc,
 986                           (flags & BATADV_TT_CLIENT_ROAM ? 'R' : '.'),
 987                           (flags & BATADV_TT_CLIENT_WIFI ? 'W' : '.'),
 988                           (flags & BATADV_TT_CLIENT_TEMP ? 'T' : '.'));
 989        }
 990
 991        head = &tt_global_entry->orig_list;
 992
 993        hlist_for_each_entry_rcu(orig_entry, head, list) {
 994                if (best_entry == orig_entry)
 995                        continue;
 996
 997                last_ttvn = atomic_read(&orig_entry->orig_node->last_ttvn);
 998                seq_printf(seq, " %c %pM  (%3u) via %pM     (%3u)   [%c%c%c]\n",
 999                           '+', tt_global_entry->common.addr,
1000                           orig_entry->ttvn, orig_entry->orig_node->orig,
1001                           last_ttvn,
1002                           (flags & BATADV_TT_CLIENT_ROAM ? 'R' : '.'),
1003                           (flags & BATADV_TT_CLIENT_WIFI ? 'W' : '.'),
1004                           (flags & BATADV_TT_CLIENT_TEMP ? 'T' : '.'));
1005        }
1006}
1007
1008int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset)
1009{
1010        struct net_device *net_dev = (struct net_device *)seq->private;
1011        struct batadv_priv *bat_priv = netdev_priv(net_dev);
1012        struct batadv_hashtable *hash = bat_priv->tt.global_hash;
1013        struct batadv_tt_common_entry *tt_common_entry;
1014        struct batadv_tt_global_entry *tt_global;
1015        struct batadv_hard_iface *primary_if;
1016        struct hlist_head *head;
1017        uint32_t i;
1018
1019        primary_if = batadv_seq_print_text_primary_if_get(seq);
1020        if (!primary_if)
1021                goto out;
1022
1023        seq_printf(seq,
1024                   "Globally announced TT entries received via the mesh %s\n",
1025                   net_dev->name);
1026        seq_printf(seq, "       %-13s %s       %-15s %s (%-6s) %s\n",
1027                   "Client", "(TTVN)", "Originator", "(Curr TTVN)", "CRC",
1028                   "Flags");
1029
1030        for (i = 0; i < hash->size; i++) {
1031                head = &hash->table[i];
1032
1033                rcu_read_lock();
1034                hlist_for_each_entry_rcu(tt_common_entry,
1035                                         head, hash_entry) {
1036                        tt_global = container_of(tt_common_entry,
1037                                                 struct batadv_tt_global_entry,
1038                                                 common);
1039                        batadv_tt_global_print_entry(tt_global, seq);
1040                }
1041                rcu_read_unlock();
1042        }
1043out:
1044        if (primary_if)
1045                batadv_hardif_free_ref(primary_if);
1046        return 0;
1047}
1048
1049/* deletes the orig list of a tt_global_entry */
1050static void
1051batadv_tt_global_del_orig_list(struct batadv_tt_global_entry *tt_global_entry)
1052{
1053        struct hlist_head *head;
1054        struct hlist_node *safe;
1055        struct batadv_tt_orig_list_entry *orig_entry;
1056
1057        spin_lock_bh(&tt_global_entry->list_lock);
1058        head = &tt_global_entry->orig_list;
1059        hlist_for_each_entry_safe(orig_entry, safe, head, list) {
1060                hlist_del_rcu(&orig_entry->list);
1061                batadv_tt_orig_list_entry_free_ref(orig_entry);
1062        }
1063        spin_unlock_bh(&tt_global_entry->list_lock);
1064}
1065
1066static void
1067batadv_tt_global_del_orig_entry(struct batadv_priv *bat_priv,
1068                                struct batadv_tt_global_entry *tt_global_entry,
1069                                struct batadv_orig_node *orig_node,
1070                                const char *message)
1071{
1072        struct hlist_head *head;
1073        struct hlist_node *safe;
1074        struct batadv_tt_orig_list_entry *orig_entry;
1075
1076        spin_lock_bh(&tt_global_entry->list_lock);
1077        head = &tt_global_entry->orig_list;
1078        hlist_for_each_entry_safe(orig_entry, safe, head, list) {
1079                if (orig_entry->orig_node == orig_node) {
1080                        batadv_dbg(BATADV_DBG_TT, bat_priv,
1081                                   "Deleting %pM from global tt entry %pM: %s\n",
1082                                   orig_node->orig,
1083                                   tt_global_entry->common.addr, message);
1084                        hlist_del_rcu(&orig_entry->list);
1085                        batadv_tt_orig_list_entry_free_ref(orig_entry);
1086                }
1087        }
1088        spin_unlock_bh(&tt_global_entry->list_lock);
1089}
1090
1091/* If the client is to be deleted, we check if it is the last origantor entry
1092 * within tt_global entry. If yes, we set the BATADV_TT_CLIENT_ROAM flag and the
1093 * timer, otherwise we simply remove the originator scheduled for deletion.
1094 */
1095static void
1096batadv_tt_global_del_roaming(struct batadv_priv *bat_priv,
1097                             struct batadv_tt_global_entry *tt_global_entry,
1098                             struct batadv_orig_node *orig_node,
1099                             const char *message)
1100{
1101        bool last_entry = true;
1102        struct hlist_head *head;
1103        struct batadv_tt_orig_list_entry *orig_entry;
1104
1105        /* no local entry exists, case 1:
1106         * Check if this is the last one or if other entries exist.
1107         */
1108
1109        rcu_read_lock();
1110        head = &tt_global_entry->orig_list;
1111        hlist_for_each_entry_rcu(orig_entry, head, list) {
1112                if (orig_entry->orig_node != orig_node) {
1113                        last_entry = false;
1114                        break;
1115                }
1116        }
1117        rcu_read_unlock();
1118
1119        if (last_entry) {
1120                /* its the last one, mark for roaming. */
1121                tt_global_entry->common.flags |= BATADV_TT_CLIENT_ROAM;
1122                tt_global_entry->roam_at = jiffies;
1123        } else
1124                /* there is another entry, we can simply delete this
1125                 * one and can still use the other one.
1126                 */
1127                batadv_tt_global_del_orig_entry(bat_priv, tt_global_entry,
1128                                                orig_node, message);
1129}
1130
1131
1132
1133static void batadv_tt_global_del(struct batadv_priv *bat_priv,
1134                                 struct batadv_orig_node *orig_node,
1135                                 const unsigned char *addr,
1136                                 const char *message, bool roaming)
1137{
1138        struct batadv_tt_global_entry *tt_global_entry;
1139        struct batadv_tt_local_entry *local_entry = NULL;
1140
1141        tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr);
1142        if (!tt_global_entry)
1143                goto out;
1144
1145        if (!roaming) {
1146                batadv_tt_global_del_orig_entry(bat_priv, tt_global_entry,
1147                                                orig_node, message);
1148
1149                if (hlist_empty(&tt_global_entry->orig_list))
1150                        batadv_tt_global_free(bat_priv, tt_global_entry,
1151                                              message);
1152
1153                goto out;
1154        }
1155
1156        /* if we are deleting a global entry due to a roam
1157         * event, there are two possibilities:
1158         * 1) the client roamed from node A to node B => if there
1159         *    is only one originator left for this client, we mark
1160         *    it with BATADV_TT_CLIENT_ROAM, we start a timer and we
1161         *    wait for node B to claim it. In case of timeout
1162         *    the entry is purged.
1163         *
1164         *    If there are other originators left, we directly delete
1165         *    the originator.
1166         * 2) the client roamed to us => we can directly delete
1167         *    the global entry, since it is useless now.
1168         */
1169        local_entry = batadv_tt_local_hash_find(bat_priv,
1170                                                tt_global_entry->common.addr);
1171        if (local_entry) {
1172                /* local entry exists, case 2: client roamed to us. */
1173                batadv_tt_global_del_orig_list(tt_global_entry);
1174                batadv_tt_global_free(bat_priv, tt_global_entry, message);
1175        } else
1176                /* no local entry exists, case 1: check for roaming */
1177                batadv_tt_global_del_roaming(bat_priv, tt_global_entry,
1178                                             orig_node, message);
1179
1180
1181out:
1182        if (tt_global_entry)
1183                batadv_tt_global_entry_free_ref(tt_global_entry);
1184        if (local_entry)
1185                batadv_tt_local_entry_free_ref(local_entry);
1186}
1187
1188void batadv_tt_global_del_orig(struct batadv_priv *bat_priv,
1189                               struct batadv_orig_node *orig_node,
1190                               const char *message)
1191{
1192        struct batadv_tt_global_entry *tt_global;
1193        struct batadv_tt_common_entry *tt_common_entry;
1194        uint32_t i;
1195        struct batadv_hashtable *hash = bat_priv->tt.global_hash;
1196        struct hlist_node *safe;
1197        struct hlist_head *head;
1198        spinlock_t *list_lock; /* protects write access to the hash lists */
1199
1200        if (!hash)
1201                return;
1202
1203        for (i = 0; i < hash->size; i++) {
1204                head = &hash->table[i];
1205                list_lock = &hash->list_locks[i];
1206
1207                spin_lock_bh(list_lock);
1208                hlist_for_each_entry_safe(tt_common_entry, safe,
1209                                          head, hash_entry) {
1210                        tt_global = container_of(tt_common_entry,
1211                                                 struct batadv_tt_global_entry,
1212                                                 common);
1213
1214                        batadv_tt_global_del_orig_entry(bat_priv, tt_global,
1215                                                        orig_node, message);
1216
1217                        if (hlist_empty(&tt_global->orig_list)) {
1218                                batadv_dbg(BATADV_DBG_TT, bat_priv,
1219                                           "Deleting global tt entry %pM: %s\n",
1220                                           tt_global->common.addr, message);
1221                                hlist_del_rcu(&tt_common_entry->hash_entry);
1222                                batadv_tt_global_entry_free_ref(tt_global);
1223                        }
1224                }
1225                spin_unlock_bh(list_lock);
1226        }
1227        orig_node->tt_initialised = false;
1228}
1229
1230static bool batadv_tt_global_to_purge(struct batadv_tt_global_entry *tt_global,
1231                                      char **msg)
1232{
1233        bool purge = false;
1234        unsigned long roam_timeout = BATADV_TT_CLIENT_ROAM_TIMEOUT;
1235        unsigned long temp_timeout = BATADV_TT_CLIENT_TEMP_TIMEOUT;
1236
1237        if ((tt_global->common.flags & BATADV_TT_CLIENT_ROAM) &&
1238            batadv_has_timed_out(tt_global->roam_at, roam_timeout)) {
1239                purge = true;
1240                *msg = "Roaming timeout\n";
1241        }
1242
1243        if ((tt_global->common.flags & BATADV_TT_CLIENT_TEMP) &&
1244            batadv_has_timed_out(tt_global->common.added_at, temp_timeout)) {
1245                purge = true;
1246                *msg = "Temporary client timeout\n";
1247        }
1248
1249        return purge;
1250}
1251
1252static void batadv_tt_global_purge(struct batadv_priv *bat_priv)
1253{
1254        struct batadv_hashtable *hash = bat_priv->tt.global_hash;
1255        struct hlist_head *head;
1256        struct hlist_node *node_tmp;
1257        spinlock_t *list_lock; /* protects write access to the hash lists */
1258        uint32_t i;
1259        char *msg = NULL;
1260        struct batadv_tt_common_entry *tt_common;
1261        struct batadv_tt_global_entry *tt_global;
1262
1263        for (i = 0; i < hash->size; i++) {
1264                head = &hash->table[i];
1265                list_lock = &hash->list_locks[i];
1266
1267                spin_lock_bh(list_lock);
1268                hlist_for_each_entry_safe(tt_common, node_tmp, head,
1269                                          hash_entry) {
1270                        tt_global = container_of(tt_common,
1271                                                 struct batadv_tt_global_entry,
1272                                                 common);
1273
1274                        if (!batadv_tt_global_to_purge(tt_global, &msg))
1275                                continue;
1276
1277                        batadv_dbg(BATADV_DBG_TT, bat_priv,
1278                                   "Deleting global tt entry (%pM): %s\n",
1279                                   tt_global->common.addr, msg);
1280
1281                        hlist_del_rcu(&tt_common->hash_entry);
1282
1283                        batadv_tt_global_entry_free_ref(tt_global);
1284                }
1285                spin_unlock_bh(list_lock);
1286        }
1287}
1288
1289static void batadv_tt_global_table_free(struct batadv_priv *bat_priv)
1290{
1291        struct batadv_hashtable *hash;
1292        spinlock_t *list_lock; /* protects write access to the hash lists */
1293        struct batadv_tt_common_entry *tt_common_entry;
1294        struct batadv_tt_global_entry *tt_global;
1295        struct hlist_node *node_tmp;
1296        struct hlist_head *head;
1297        uint32_t i;
1298
1299        if (!bat_priv->tt.global_hash)
1300                return;
1301
1302        hash = bat_priv->tt.global_hash;
1303
1304        for (i = 0; i < hash->size; i++) {
1305                head = &hash->table[i];
1306                list_lock = &hash->list_locks[i];
1307
1308                spin_lock_bh(list_lock);
1309                hlist_for_each_entry_safe(tt_common_entry, node_tmp,
1310                                          head, hash_entry) {
1311                        hlist_del_rcu(&tt_common_entry->hash_entry);
1312                        tt_global = container_of(tt_common_entry,
1313                                                 struct batadv_tt_global_entry,
1314                                                 common);
1315                        batadv_tt_global_entry_free_ref(tt_global);
1316                }
1317                spin_unlock_bh(list_lock);
1318        }
1319
1320        batadv_hash_destroy(hash);
1321
1322        bat_priv->tt.global_hash = NULL;
1323}
1324
1325static bool
1326_batadv_is_ap_isolated(struct batadv_tt_local_entry *tt_local_entry,
1327                       struct batadv_tt_global_entry *tt_global_entry)
1328{
1329        bool ret = false;
1330
1331        if (tt_local_entry->common.flags & BATADV_TT_CLIENT_WIFI &&
1332            tt_global_entry->common.flags & BATADV_TT_CLIENT_WIFI)
1333                ret = true;
1334
1335        return ret;
1336}
1337
1338struct batadv_orig_node *batadv_transtable_search(struct batadv_priv *bat_priv,
1339                                                  const uint8_t *src,
1340                                                  const uint8_t *addr)
1341{
1342        struct batadv_tt_local_entry *tt_local_entry = NULL;
1343        struct batadv_tt_global_entry *tt_global_entry = NULL;
1344        struct batadv_orig_node *orig_node = NULL;
1345        struct batadv_tt_orig_list_entry *best_entry;
1346
1347        if (src && atomic_read(&bat_priv->ap_isolation)) {
1348                tt_local_entry = batadv_tt_local_hash_find(bat_priv, src);
1349                if (!tt_local_entry ||
1350                    (tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING))
1351                        goto out;
1352        }
1353
1354        tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr);
1355        if (!tt_global_entry)
1356                goto out;
1357
1358        /* check whether the clients should not communicate due to AP
1359         * isolation
1360         */
1361        if (tt_local_entry &&
1362            _batadv_is_ap_isolated(tt_local_entry, tt_global_entry))
1363                goto out;
1364
1365        rcu_read_lock();
1366        best_entry = batadv_transtable_best_orig(tt_global_entry);
1367        /* found anything? */
1368        if (best_entry)
1369                orig_node = best_entry->orig_node;
1370        if (orig_node && !atomic_inc_not_zero(&orig_node->refcount))
1371                orig_node = NULL;
1372        rcu_read_unlock();
1373
1374out:
1375        if (tt_global_entry)
1376                batadv_tt_global_entry_free_ref(tt_global_entry);
1377        if (tt_local_entry)
1378                batadv_tt_local_entry_free_ref(tt_local_entry);
1379
1380        return orig_node;
1381}
1382
1383/* Calculates the checksum of the local table of a given orig_node */
1384static uint16_t batadv_tt_global_crc(struct batadv_priv *bat_priv,
1385                                     struct batadv_orig_node *orig_node)
1386{
1387        uint16_t total = 0, total_one;
1388        struct batadv_hashtable *hash = bat_priv->tt.global_hash;
1389        struct batadv_tt_common_entry *tt_common;
1390        struct batadv_tt_global_entry *tt_global;
1391        struct hlist_head *head;
1392        uint32_t i;
1393        int j;
1394
1395        for (i = 0; i < hash->size; i++) {
1396                head = &hash->table[i];
1397
1398                rcu_read_lock();
1399                hlist_for_each_entry_rcu(tt_common, head, hash_entry) {
1400                        tt_global = container_of(tt_common,
1401                                                 struct batadv_tt_global_entry,
1402                                                 common);
1403                        /* Roaming clients are in the global table for
1404                         * consistency only. They don't have to be
1405                         * taken into account while computing the
1406                         * global crc
1407                         */
1408                        if (tt_common->flags & BATADV_TT_CLIENT_ROAM)
1409                                continue;
1410                        /* Temporary clients have not been announced yet, so
1411                         * they have to be skipped while computing the global
1412                         * crc
1413                         */
1414                        if (tt_common->flags & BATADV_TT_CLIENT_TEMP)
1415                                continue;
1416
1417                        /* find out if this global entry is announced by this
1418                         * originator
1419                         */
1420                        if (!batadv_tt_global_entry_has_orig(tt_global,
1421                                                             orig_node))
1422                                continue;
1423
1424                        total_one = 0;
1425                        for (j = 0; j < ETH_ALEN; j++)
1426                                total_one = crc16_byte(total_one,
1427                                                       tt_common->addr[j]);
1428                        total ^= total_one;
1429                }
1430                rcu_read_unlock();
1431        }
1432
1433        return total;
1434}
1435
1436/* Calculates the checksum of the local table */
1437static uint16_t batadv_tt_local_crc(struct batadv_priv *bat_priv)
1438{
1439        uint16_t total = 0, total_one;
1440        struct batadv_hashtable *hash = bat_priv->tt.local_hash;
1441        struct batadv_tt_common_entry *tt_common;
1442        struct hlist_head *head;
1443        uint32_t i;
1444        int j;
1445
1446        for (i = 0; i < hash->size; i++) {
1447                head = &hash->table[i];
1448
1449                rcu_read_lock();
1450                hlist_for_each_entry_rcu(tt_common, head, hash_entry) {
1451                        /* not yet committed clients have not to be taken into
1452                         * account while computing the CRC
1453                         */
1454                        if (tt_common->flags & BATADV_TT_CLIENT_NEW)
1455                                continue;
1456                        total_one = 0;
1457                        for (j = 0; j < ETH_ALEN; j++)
1458                                total_one = crc16_byte(total_one,
1459                                                       tt_common->addr[j]);
1460                        total ^= total_one;
1461                }
1462                rcu_read_unlock();
1463        }
1464
1465        return total;
1466}
1467
1468static void batadv_tt_req_list_free(struct batadv_priv *bat_priv)
1469{
1470        struct batadv_tt_req_node *node, *safe;
1471
1472        spin_lock_bh(&bat_priv->tt.req_list_lock);
1473
1474        list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) {
1475                list_del(&node->list);
1476                kfree(node);
1477        }
1478
1479        spin_unlock_bh(&bat_priv->tt.req_list_lock);
1480}
1481
1482static void batadv_tt_save_orig_buffer(struct batadv_priv *bat_priv,
1483                                       struct batadv_orig_node *orig_node,
1484                                       const unsigned char *tt_buff,
1485                                       uint8_t tt_num_changes)
1486{
1487        uint16_t tt_buff_len = batadv_tt_len(tt_num_changes);
1488
1489        /* Replace the old buffer only if I received something in the
1490         * last OGM (the OGM could carry no changes)
1491         */
1492        spin_lock_bh(&orig_node->tt_buff_lock);
1493        if (tt_buff_len > 0) {
1494                kfree(orig_node->tt_buff);
1495                orig_node->tt_buff_len = 0;
1496                orig_node->tt_buff = kmalloc(tt_buff_len, GFP_ATOMIC);
1497                if (orig_node->tt_buff) {
1498                        memcpy(orig_node->tt_buff, tt_buff, tt_buff_len);
1499                        orig_node->tt_buff_len = tt_buff_len;
1500                }
1501        }
1502        spin_unlock_bh(&orig_node->tt_buff_lock);
1503}
1504
1505static void batadv_tt_req_purge(struct batadv_priv *bat_priv)
1506{
1507        struct batadv_tt_req_node *node, *safe;
1508
1509        spin_lock_bh(&bat_priv->tt.req_list_lock);
1510        list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) {
1511                if (batadv_has_timed_out(node->issued_at,
1512                                         BATADV_TT_REQUEST_TIMEOUT)) {
1513                        list_del(&node->list);
1514                        kfree(node);
1515                }
1516        }
1517        spin_unlock_bh(&bat_priv->tt.req_list_lock);
1518}
1519
1520/* returns the pointer to the new tt_req_node struct if no request
1521 * has already been issued for this orig_node, NULL otherwise
1522 */
1523static struct batadv_tt_req_node *
1524batadv_new_tt_req_node(struct batadv_priv *bat_priv,
1525                       struct batadv_orig_node *orig_node)
1526{
1527        struct batadv_tt_req_node *tt_req_node_tmp, *tt_req_node = NULL;
1528
1529        spin_lock_bh(&bat_priv->tt.req_list_lock);
1530        list_for_each_entry(tt_req_node_tmp, &bat_priv->tt.req_list, list) {
1531                if (batadv_compare_eth(tt_req_node_tmp, orig_node) &&
1532                    !batadv_has_timed_out(tt_req_node_tmp->issued_at,
1533                                          BATADV_TT_REQUEST_TIMEOUT))
1534                        goto unlock;
1535        }
1536
1537        tt_req_node = kmalloc(sizeof(*tt_req_node), GFP_ATOMIC);
1538        if (!tt_req_node)
1539                goto unlock;
1540
1541        memcpy(tt_req_node->addr, orig_node->orig, ETH_ALEN);
1542        tt_req_node->issued_at = jiffies;
1543
1544        list_add(&tt_req_node->list, &bat_priv->tt.req_list);
1545unlock:
1546        spin_unlock_bh(&bat_priv->tt.req_list_lock);
1547        return tt_req_node;
1548}
1549
1550/* data_ptr is useless here, but has to be kept to respect the prototype */
1551static int batadv_tt_local_valid_entry(const void *entry_ptr,
1552                                       const void *data_ptr)
1553{
1554        const struct batadv_tt_common_entry *tt_common_entry = entry_ptr;
1555
1556        if (tt_common_entry->flags & BATADV_TT_CLIENT_NEW)
1557                return 0;
1558        return 1;
1559}
1560
1561static int batadv_tt_global_valid(const void *entry_ptr,
1562                                  const void *data_ptr)
1563{
1564        const struct batadv_tt_common_entry *tt_common_entry = entry_ptr;
1565        const struct batadv_tt_global_entry *tt_global_entry;
1566        const struct batadv_orig_node *orig_node = data_ptr;
1567
1568        if (tt_common_entry->flags & BATADV_TT_CLIENT_ROAM ||
1569            tt_common_entry->flags & BATADV_TT_CLIENT_TEMP)
1570                return 0;
1571
1572        tt_global_entry = container_of(tt_common_entry,
1573                                       struct batadv_tt_global_entry,
1574                                       common);
1575
1576        return batadv_tt_global_entry_has_orig(tt_global_entry, orig_node);
1577}
1578
1579static struct sk_buff *
1580batadv_tt_response_fill_table(uint16_t tt_len, uint8_t ttvn,
1581                              struct batadv_hashtable *hash,
1582                              struct batadv_priv *bat_priv,
1583                              int (*valid_cb)(const void *, const void *),
1584                              void *cb_data)
1585{
1586        struct batadv_tt_common_entry *tt_common_entry;
1587        struct batadv_tt_query_packet *tt_response;
1588        struct batadv_tt_change *tt_change;
1589        struct hlist_head *head;
1590        struct sk_buff *skb = NULL;
1591        uint16_t tt_tot, tt_count;
1592        ssize_t tt_query_size = sizeof(struct batadv_tt_query_packet);
1593        uint32_t i;
1594        size_t len;
1595
1596        if (tt_query_size + tt_len > bat_priv->soft_iface->mtu) {
1597                tt_len = bat_priv->soft_iface->mtu - tt_query_size;
1598                tt_len -= tt_len % sizeof(struct batadv_tt_change);
1599        }
1600        tt_tot = tt_len / sizeof(struct batadv_tt_change);
1601
1602        len = tt_query_size + tt_len;
1603        skb = dev_alloc_skb(len + ETH_HLEN + NET_IP_ALIGN);
1604        if (!skb)
1605                goto out;
1606
1607        skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
1608        tt_response = (struct batadv_tt_query_packet *)skb_put(skb, len);
1609        tt_response->ttvn = ttvn;
1610
1611        tt_change = (struct batadv_tt_change *)(skb->data + tt_query_size);
1612        tt_count = 0;
1613
1614        rcu_read_lock();
1615        for (i = 0; i < hash->size; i++) {
1616                head = &hash->table[i];
1617
1618                hlist_for_each_entry_rcu(tt_common_entry,
1619                                         head, hash_entry) {
1620                        if (tt_count == tt_tot)
1621                                break;
1622
1623                        if ((valid_cb) && (!valid_cb(tt_common_entry, cb_data)))
1624                                continue;
1625
1626                        memcpy(tt_change->addr, tt_common_entry->addr,
1627                               ETH_ALEN);
1628                        tt_change->flags = tt_common_entry->flags;
1629
1630                        tt_count++;
1631                        tt_change++;
1632                }
1633        }
1634        rcu_read_unlock();
1635
1636        /* store in the message the number of entries we have successfully
1637         * copied
1638         */
1639        tt_response->tt_data = htons(tt_count);
1640
1641out:
1642        return skb;
1643}
1644
1645static int batadv_send_tt_request(struct batadv_priv *bat_priv,
1646                                  struct batadv_orig_node *dst_orig_node,
1647                                  uint8_t ttvn, uint16_t tt_crc,
1648                                  bool full_table)
1649{
1650        struct sk_buff *skb = NULL;
1651        struct batadv_tt_query_packet *tt_request;
1652        struct batadv_hard_iface *primary_if;
1653        struct batadv_tt_req_node *tt_req_node = NULL;
1654        int ret = 1;
1655        size_t tt_req_len;
1656
1657        primary_if = batadv_primary_if_get_selected(bat_priv);
1658        if (!primary_if)
1659                goto out;
1660
1661        /* The new tt_req will be issued only if I'm not waiting for a
1662         * reply from the same orig_node yet
1663         */
1664        tt_req_node = batadv_new_tt_req_node(bat_priv, dst_orig_node);
1665        if (!tt_req_node)
1666                goto out;
1667
1668        skb = dev_alloc_skb(sizeof(*tt_request) + ETH_HLEN + NET_IP_ALIGN);
1669        if (!skb)
1670                goto out;
1671
1672        skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
1673
1674        tt_req_len = sizeof(*tt_request);
1675        tt_request = (struct batadv_tt_query_packet *)skb_put(skb, tt_req_len);
1676
1677        tt_request->header.packet_type = BATADV_TT_QUERY;
1678        tt_request->header.version = BATADV_COMPAT_VERSION;
1679        memcpy(tt_request->src, primary_if->net_dev->dev_addr, ETH_ALEN);
1680        memcpy(tt_request->dst, dst_orig_node->orig, ETH_ALEN);
1681        tt_request->header.ttl = BATADV_TTL;
1682        tt_request->ttvn = ttvn;
1683        tt_request->tt_data = htons(tt_crc);
1684        tt_request->flags = BATADV_TT_REQUEST;
1685
1686        if (full_table)
1687                tt_request->flags |= BATADV_TT_FULL_TABLE;
1688
1689        batadv_dbg(BATADV_DBG_TT, bat_priv, "Sending TT_REQUEST to %pM [%c]\n",
1690                   dst_orig_node->orig, (full_table ? 'F' : '.'));
1691
1692        batadv_inc_counter(bat_priv, BATADV_CNT_TT_REQUEST_TX);
1693
1694        if (batadv_send_skb_to_orig(skb, dst_orig_node, NULL))
1695                ret = 0;
1696
1697out:
1698        if (primary_if)
1699                batadv_hardif_free_ref(primary_if);
1700        if (ret)
1701                kfree_skb(skb);
1702        if (ret && tt_req_node) {
1703                spin_lock_bh(&bat_priv->tt.req_list_lock);
1704                list_del(&tt_req_node->list);
1705                spin_unlock_bh(&bat_priv->tt.req_list_lock);
1706                kfree(tt_req_node);
1707        }
1708        return ret;
1709}
1710
1711static bool
1712batadv_send_other_tt_response(struct batadv_priv *bat_priv,
1713                              struct batadv_tt_query_packet *tt_request)
1714{
1715        struct batadv_orig_node *req_dst_orig_node;
1716        struct batadv_orig_node *res_dst_orig_node = NULL;
1717        uint8_t orig_ttvn, req_ttvn, ttvn;
1718        int ret = false;
1719        unsigned char *tt_buff;
1720        bool full_table;
1721        uint16_t tt_len, tt_tot;
1722        struct sk_buff *skb = NULL;
1723        struct batadv_tt_query_packet *tt_response;
1724        uint8_t *packet_pos;
1725        size_t len;
1726
1727        batadv_dbg(BATADV_DBG_TT, bat_priv,
1728                   "Received TT_REQUEST from %pM for ttvn: %u (%pM) [%c]\n",
1729                   tt_request->src, tt_request->ttvn, tt_request->dst,
1730                   (tt_request->flags & BATADV_TT_FULL_TABLE ? 'F' : '.'));
1731
1732        /* Let's get the orig node of the REAL destination */
1733        req_dst_orig_node = batadv_orig_hash_find(bat_priv, tt_request->dst);
1734        if (!req_dst_orig_node)
1735                goto out;
1736
1737        res_dst_orig_node = batadv_orig_hash_find(bat_priv, tt_request->src);
1738        if (!res_dst_orig_node)
1739                goto out;
1740
1741        orig_ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn);
1742        req_ttvn = tt_request->ttvn;
1743
1744        /* I don't have the requested data */
1745        if (orig_ttvn != req_ttvn ||
1746            tt_request->tt_data != htons(req_dst_orig_node->tt_crc))
1747                goto out;
1748
1749        /* If the full table has been explicitly requested */
1750        if (tt_request->flags & BATADV_TT_FULL_TABLE ||
1751            !req_dst_orig_node->tt_buff)
1752                full_table = true;
1753        else
1754                full_table = false;
1755
1756        /* In this version, fragmentation is not implemented, then
1757         * I'll send only one packet with as much TT entries as I can
1758         */
1759        if (!full_table) {
1760                spin_lock_bh(&req_dst_orig_node->tt_buff_lock);
1761                tt_len = req_dst_orig_node->tt_buff_len;
1762                tt_tot = tt_len / sizeof(struct batadv_tt_change);
1763
1764                len = sizeof(*tt_response) + tt_len;
1765                skb = dev_alloc_skb(len + ETH_HLEN + NET_IP_ALIGN);
1766                if (!skb)
1767                        goto unlock;
1768
1769                skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
1770                packet_pos = skb_put(skb, len);
1771                tt_response = (struct batadv_tt_query_packet *)packet_pos;
1772                tt_response->ttvn = req_ttvn;
1773                tt_response->tt_data = htons(tt_tot);
1774
1775                tt_buff = skb->data + sizeof(*tt_response);
1776                /* Copy the last orig_node's OGM buffer */
1777                memcpy(tt_buff, req_dst_orig_node->tt_buff,
1778                       req_dst_orig_node->tt_buff_len);
1779
1780                spin_unlock_bh(&req_dst_orig_node->tt_buff_lock);
1781        } else {
1782                tt_len = (uint16_t)atomic_read(&req_dst_orig_node->tt_size);
1783                tt_len *= sizeof(struct batadv_tt_change);
1784                ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn);
1785
1786                skb = batadv_tt_response_fill_table(tt_len, ttvn,
1787                                                    bat_priv->tt.global_hash,
1788                                                    bat_priv,
1789                                                    batadv_tt_global_valid,
1790                                                    req_dst_orig_node);
1791                if (!skb)
1792                        goto out;
1793
1794                tt_response = (struct batadv_tt_query_packet *)skb->data;
1795        }
1796
1797        tt_response->header.packet_type = BATADV_TT_QUERY;
1798        tt_response->header.version = BATADV_COMPAT_VERSION;
1799        tt_response->header.ttl = BATADV_TTL;
1800        memcpy(tt_response->src, req_dst_orig_node->orig, ETH_ALEN);
1801        memcpy(tt_response->dst, tt_request->src, ETH_ALEN);
1802        tt_response->flags = BATADV_TT_RESPONSE;
1803
1804        if (full_table)
1805                tt_response->flags |= BATADV_TT_FULL_TABLE;
1806
1807        batadv_dbg(BATADV_DBG_TT, bat_priv,
1808                   "Sending TT_RESPONSE %pM for %pM (ttvn: %u)\n",
1809                   res_dst_orig_node->orig, req_dst_orig_node->orig, req_ttvn);
1810
1811        batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX);
1812
1813        if (batadv_send_skb_to_orig(skb, res_dst_orig_node, NULL))
1814                ret = true;
1815        goto out;
1816
1817unlock:
1818        spin_unlock_bh(&req_dst_orig_node->tt_buff_lock);
1819
1820out:
1821        if (res_dst_orig_node)
1822                batadv_orig_node_free_ref(res_dst_orig_node);
1823        if (req_dst_orig_node)
1824                batadv_orig_node_free_ref(req_dst_orig_node);
1825        if (!ret)
1826                kfree_skb(skb);
1827        return ret;
1828}
1829
1830static bool
1831batadv_send_my_tt_response(struct batadv_priv *bat_priv,
1832                           struct batadv_tt_query_packet *tt_request)
1833{
1834        struct batadv_orig_node *orig_node;
1835        struct batadv_hard_iface *primary_if = NULL;
1836        uint8_t my_ttvn, req_ttvn, ttvn;
1837        int ret = false;
1838        unsigned char *tt_buff;
1839        bool full_table;
1840        uint16_t tt_len, tt_tot;
1841        struct sk_buff *skb = NULL;
1842        struct batadv_tt_query_packet *tt_response;
1843        uint8_t *packet_pos;
1844        size_t len;
1845
1846        batadv_dbg(BATADV_DBG_TT, bat_priv,
1847                   "Received TT_REQUEST from %pM for ttvn: %u (me) [%c]\n",
1848                   tt_request->src, tt_request->ttvn,
1849                   (tt_request->flags & BATADV_TT_FULL_TABLE ? 'F' : '.'));
1850
1851
1852        my_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn);
1853        req_ttvn = tt_request->ttvn;
1854
1855        orig_node = batadv_orig_hash_find(bat_priv, tt_request->src);
1856        if (!orig_node)
1857                goto out;
1858
1859        primary_if = batadv_primary_if_get_selected(bat_priv);
1860        if (!primary_if)
1861                goto out;
1862
1863        /* If the full table has been explicitly requested or the gap
1864         * is too big send the whole local translation table
1865         */
1866        if (tt_request->flags & BATADV_TT_FULL_TABLE || my_ttvn != req_ttvn ||
1867            !bat_priv->tt.last_changeset)
1868                full_table = true;
1869        else
1870                full_table = false;
1871
1872        /* In this version, fragmentation is not implemented, then
1873         * I'll send only one packet with as much TT entries as I can
1874         */
1875        if (!full_table) {
1876                spin_lock_bh(&bat_priv->tt.last_changeset_lock);
1877                tt_len = bat_priv->tt.last_changeset_len;
1878                tt_tot = tt_len / sizeof(struct batadv_tt_change);
1879
1880                len = sizeof(*tt_response) + tt_len;
1881                skb = dev_alloc_skb(len + ETH_HLEN + NET_IP_ALIGN);
1882                if (!skb)
1883                        goto unlock;
1884
1885                skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
1886                packet_pos = skb_put(skb, len);
1887                tt_response = (struct batadv_tt_query_packet *)packet_pos;
1888                tt_response->ttvn = req_ttvn;
1889                tt_response->tt_data = htons(tt_tot);
1890
1891                tt_buff = skb->data + sizeof(*tt_response);
1892                memcpy(tt_buff, bat_priv->tt.last_changeset,
1893                       bat_priv->tt.last_changeset_len);
1894                spin_unlock_bh(&bat_priv->tt.last_changeset_lock);
1895        } else {
1896                tt_len = (uint16_t)atomic_read(&bat_priv->tt.local_entry_num);
1897                tt_len *= sizeof(struct batadv_tt_change);
1898                ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn);
1899
1900                skb = batadv_tt_response_fill_table(tt_len, ttvn,
1901                                                    bat_priv->tt.local_hash,
1902                                                    bat_priv,
1903                                                    batadv_tt_local_valid_entry,
1904                                                    NULL);
1905                if (!skb)
1906                        goto out;
1907
1908                tt_response = (struct batadv_tt_query_packet *)skb->data;
1909        }
1910
1911        tt_response->header.packet_type = BATADV_TT_QUERY;
1912        tt_response->header.version = BATADV_COMPAT_VERSION;
1913        tt_response->header.ttl = BATADV_TTL;
1914        memcpy(tt_response->src, primary_if->net_dev->dev_addr, ETH_ALEN);
1915        memcpy(tt_response->dst, tt_request->src, ETH_ALEN);
1916        tt_response->flags = BATADV_TT_RESPONSE;
1917
1918        if (full_table)
1919                tt_response->flags |= BATADV_TT_FULL_TABLE;
1920
1921        batadv_dbg(BATADV_DBG_TT, bat_priv,
1922                   "Sending TT_RESPONSE to %pM [%c]\n",
1923                   orig_node->orig,
1924                   (tt_response->flags & BATADV_TT_FULL_TABLE ? 'F' : '.'));
1925
1926        batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX);
1927
1928        if (batadv_send_skb_to_orig(skb, orig_node, NULL))
1929                ret = true;
1930        goto out;
1931
1932unlock:
1933        spin_unlock_bh(&bat_priv->tt.last_changeset_lock);
1934out:
1935        if (orig_node)
1936                batadv_orig_node_free_ref(orig_node);
1937        if (primary_if)
1938                batadv_hardif_free_ref(primary_if);
1939        if (!ret)
1940                kfree_skb(skb);
1941        /* This packet was for me, so it doesn't need to be re-routed */
1942        return true;
1943}
1944
1945bool batadv_send_tt_response(struct batadv_priv *bat_priv,
1946                             struct batadv_tt_query_packet *tt_request)
1947{
1948        if (batadv_is_my_mac(bat_priv, tt_request->dst)) {
1949                /* don't answer backbone gws! */
1950                if (batadv_bla_is_backbone_gw_orig(bat_priv, tt_request->src))
1951                        return true;
1952
1953                return batadv_send_my_tt_response(bat_priv, tt_request);
1954        } else {
1955                return batadv_send_other_tt_response(bat_priv, tt_request);
1956        }
1957}
1958
1959static void _batadv_tt_update_changes(struct batadv_priv *bat_priv,
1960                                      struct batadv_orig_node *orig_node,
1961                                      struct batadv_tt_change *tt_change,
1962                                      uint16_t tt_num_changes, uint8_t ttvn)
1963{
1964        int i;
1965        int roams;
1966
1967        for (i = 0; i < tt_num_changes; i++) {
1968                if ((tt_change + i)->flags & BATADV_TT_CLIENT_DEL) {
1969                        roams = (tt_change + i)->flags & BATADV_TT_CLIENT_ROAM;
1970                        batadv_tt_global_del(bat_priv, orig_node,
1971                                             (tt_change + i)->addr,
1972                                             "tt removed by changes",
1973                                             roams);
1974                } else {
1975                        if (!batadv_tt_global_add(bat_priv, orig_node,
1976                                                  (tt_change + i)->addr,
1977                                                  (tt_change + i)->flags, ttvn))
1978                                /* In case of problem while storing a
1979                                 * global_entry, we stop the updating
1980                                 * procedure without committing the
1981                                 * ttvn change. This will avoid to send
1982                                 * corrupted data on tt_request
1983                                 */
1984                                return;
1985                }
1986        }
1987        orig_node->tt_initialised = true;
1988}
1989
1990static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv,
1991                                  struct batadv_tt_query_packet *tt_response)
1992{
1993        struct batadv_orig_node *orig_node;
1994
1995        orig_node = batadv_orig_hash_find(bat_priv, tt_response->src);
1996        if (!orig_node)
1997                goto out;
1998
1999        /* Purge the old table first.. */
2000        batadv_tt_global_del_orig(bat_priv, orig_node, "Received full table");
2001
2002        _batadv_tt_update_changes(bat_priv, orig_node,
2003                                  (struct batadv_tt_change *)(tt_response + 1),
2004                                  ntohs(tt_response->tt_data),
2005                                  tt_response->ttvn);
2006
2007        spin_lock_bh(&orig_node->tt_buff_lock);
2008        kfree(orig_node->tt_buff);
2009        orig_node->tt_buff_len = 0;
2010        orig_node->tt_buff = NULL;
2011        spin_unlock_bh(&orig_node->tt_buff_lock);
2012
2013        atomic_set(&orig_node->last_ttvn, tt_response->ttvn);
2014
2015out:
2016        if (orig_node)
2017                batadv_orig_node_free_ref(orig_node);
2018}
2019
2020static void batadv_tt_update_changes(struct batadv_priv *bat_priv,
2021                                     struct batadv_orig_node *orig_node,
2022                                     uint16_t tt_num_changes, uint8_t ttvn,
2023                                     struct batadv_tt_change *tt_change)
2024{
2025        _batadv_tt_update_changes(bat_priv, orig_node, tt_change,
2026                                  tt_num_changes, ttvn);
2027
2028        batadv_tt_save_orig_buffer(bat_priv, orig_node,
2029                                   (unsigned char *)tt_change, tt_num_changes);
2030        atomic_set(&orig_node->last_ttvn, ttvn);
2031}
2032
2033bool batadv_is_my_client(struct batadv_priv *bat_priv, const uint8_t *addr)
2034{
2035        struct batadv_tt_local_entry *tt_local_entry;
2036        bool ret = false;
2037
2038        tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr);
2039        if (!tt_local_entry)
2040                goto out;
2041        /* Check if the client has been logically deleted (but is kept for
2042         * consistency purpose)
2043         */
2044        if ((tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING) ||
2045            (tt_local_entry->common.flags & BATADV_TT_CLIENT_ROAM))
2046                goto out;
2047        ret = true;
2048out:
2049        if (tt_local_entry)
2050                batadv_tt_local_entry_free_ref(tt_local_entry);
2051        return ret;
2052}
2053
2054void batadv_handle_tt_response(struct batadv_priv *bat_priv,
2055                               struct batadv_tt_query_packet *tt_response)
2056{
2057        struct batadv_tt_req_node *node, *safe;
2058        struct batadv_orig_node *orig_node = NULL;
2059        struct batadv_tt_change *tt_change;
2060
2061        batadv_dbg(BATADV_DBG_TT, bat_priv,
2062                   "Received TT_RESPONSE from %pM for ttvn %d t_size: %d [%c]\n",
2063                   tt_response->src, tt_response->ttvn,
2064                   ntohs(tt_response->tt_data),
2065                   (tt_response->flags & BATADV_TT_FULL_TABLE ? 'F' : '.'));
2066
2067        /* we should have never asked a backbone gw */
2068        if (batadv_bla_is_backbone_gw_orig(bat_priv, tt_response->src))
2069                goto out;
2070
2071        orig_node = batadv_orig_hash_find(bat_priv, tt_response->src);
2072        if (!orig_node)
2073                goto out;
2074
2075        if (tt_response->flags & BATADV_TT_FULL_TABLE) {
2076                batadv_tt_fill_gtable(bat_priv, tt_response);
2077        } else {
2078                tt_change = (struct batadv_tt_change *)(tt_response + 1);
2079                batadv_tt_update_changes(bat_priv, orig_node,
2080                                         ntohs(tt_response->tt_data),
2081                                         tt_response->ttvn, tt_change);
2082        }
2083
2084        /* Delete the tt_req_node from pending tt_requests list */
2085        spin_lock_bh(&bat_priv->tt.req_list_lock);
2086        list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) {
2087                if (!batadv_compare_eth(node->addr, tt_response->src))
2088                        continue;
2089                list_del(&node->list);
2090                kfree(node);
2091        }
2092        spin_unlock_bh(&bat_priv->tt.req_list_lock);
2093
2094        /* Recalculate the CRC for this orig_node and store it */
2095        orig_node->tt_crc = batadv_tt_global_crc(bat_priv, orig_node);
2096out:
2097        if (orig_node)
2098                batadv_orig_node_free_ref(orig_node);
2099}
2100
2101int batadv_tt_init(struct batadv_priv *bat_priv)
2102{
2103        int ret;
2104
2105        ret = batadv_tt_local_init(bat_priv);
2106        if (ret < 0)
2107                return ret;
2108
2109        ret = batadv_tt_global_init(bat_priv);
2110        if (ret < 0)
2111                return ret;
2112
2113        INIT_DELAYED_WORK(&bat_priv->tt.work, batadv_tt_purge);
2114        queue_delayed_work(batadv_event_workqueue, &bat_priv->tt.work,
2115                           msecs_to_jiffies(BATADV_TT_WORK_PERIOD));
2116
2117        return 1;
2118}
2119
2120static void batadv_tt_roam_list_free(struct batadv_priv *bat_priv)
2121{
2122        struct batadv_tt_roam_node *node, *safe;
2123
2124        spin_lock_bh(&bat_priv->tt.roam_list_lock);
2125
2126        list_for_each_entry_safe(node, safe, &bat_priv->tt.roam_list, list) {
2127                list_del(&node->list);
2128                kfree(node);
2129        }
2130
2131        spin_unlock_bh(&bat_priv->tt.roam_list_lock);
2132}
2133
2134static void batadv_tt_roam_purge(struct batadv_priv *bat_priv)
2135{
2136        struct batadv_tt_roam_node *node, *safe;
2137
2138        spin_lock_bh(&bat_priv->tt.roam_list_lock);
2139        list_for_each_entry_safe(node, safe, &bat_priv->tt.roam_list, list) {
2140                if (!batadv_has_timed_out(node->first_time,
2141                                          BATADV_ROAMING_MAX_TIME))
2142                        continue;
2143
2144                list_del(&node->list);
2145                kfree(node);
2146        }
2147        spin_unlock_bh(&bat_priv->tt.roam_list_lock);
2148}
2149
2150/* This function checks whether the client already reached the
2151 * maximum number of possible roaming phases. In this case the ROAMING_ADV
2152 * will not be sent.
2153 *
2154 * returns true if the ROAMING_ADV can be sent, false otherwise
2155 */
2156static bool batadv_tt_check_roam_count(struct batadv_priv *bat_priv,
2157                                       uint8_t *client)
2158{
2159        struct batadv_tt_roam_node *tt_roam_node;
2160        bool ret = false;
2161
2162        spin_lock_bh(&bat_priv->tt.roam_list_lock);
2163        /* The new tt_req will be issued only if I'm not waiting for a
2164         * reply from the same orig_node yet
2165         */
2166        list_for_each_entry(tt_roam_node, &bat_priv->tt.roam_list, list) {
2167                if (!batadv_compare_eth(tt_roam_node->addr, client))
2168                        continue;
2169
2170                if (batadv_has_timed_out(tt_roam_node->first_time,
2171                                         BATADV_ROAMING_MAX_TIME))
2172                        continue;
2173
2174                if (!batadv_atomic_dec_not_zero(&tt_roam_node->counter))
2175                        /* Sorry, you roamed too many times! */
2176                        goto unlock;
2177                ret = true;
2178                break;
2179        }
2180
2181        if (!ret) {
2182                tt_roam_node = kmalloc(sizeof(*tt_roam_node), GFP_ATOMIC);
2183                if (!tt_roam_node)
2184                        goto unlock;
2185
2186                tt_roam_node->first_time = jiffies;
2187                atomic_set(&tt_roam_node->counter,
2188                           BATADV_ROAMING_MAX_COUNT - 1);
2189                memcpy(tt_roam_node->addr, client, ETH_ALEN);
2190
2191                list_add(&tt_roam_node->list, &bat_priv->tt.roam_list);
2192                ret = true;
2193        }
2194
2195unlock:
2196        spin_unlock_bh(&bat_priv->tt.roam_list_lock);
2197        return ret;
2198}
2199
2200static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client,
2201                                 struct batadv_orig_node *orig_node)
2202{
2203        struct sk_buff *skb = NULL;
2204        struct batadv_roam_adv_packet *roam_adv_packet;
2205        int ret = 1;
2206        struct batadv_hard_iface *primary_if;
2207        size_t len = sizeof(*roam_adv_packet);
2208
2209        /* before going on we have to check whether the client has
2210         * already roamed to us too many times
2211         */
2212        if (!batadv_tt_check_roam_count(bat_priv, client))
2213                goto out;
2214
2215        skb = dev_alloc_skb(sizeof(*roam_adv_packet) + ETH_HLEN + NET_IP_ALIGN);
2216        if (!skb)
2217                goto out;
2218
2219        skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
2220
2221        roam_adv_packet = (struct batadv_roam_adv_packet *)skb_put(skb, len);
2222
2223        roam_adv_packet->header.packet_type = BATADV_ROAM_ADV;
2224        roam_adv_packet->header.version = BATADV_COMPAT_VERSION;
2225        roam_adv_packet->header.ttl = BATADV_TTL;
2226        roam_adv_packet->reserved = 0;
2227        primary_if = batadv_primary_if_get_selected(bat_priv);
2228        if (!primary_if)
2229                goto out;
2230        memcpy(roam_adv_packet->src, primary_if->net_dev->dev_addr, ETH_ALEN);
2231        batadv_hardif_free_ref(primary_if);
2232        memcpy(roam_adv_packet->dst, orig_node->orig, ETH_ALEN);
2233        memcpy(roam_adv_packet->client, client, ETH_ALEN);
2234
2235        batadv_dbg(BATADV_DBG_TT, bat_priv,
2236                   "Sending ROAMING_ADV to %pM (client %pM)\n",
2237                   orig_node->orig, client);
2238
2239        batadv_inc_counter(bat_priv, BATADV_CNT_TT_ROAM_ADV_TX);
2240
2241        if (batadv_send_skb_to_orig(skb, orig_node, NULL))
2242                ret = 0;
2243
2244out:
2245        if (ret && skb)
2246                kfree_skb(skb);
2247        return;
2248}
2249
2250static void batadv_tt_purge(struct work_struct *work)
2251{
2252        struct delayed_work *delayed_work;
2253        struct batadv_priv_tt *priv_tt;
2254        struct batadv_priv *bat_priv;
2255
2256        delayed_work = container_of(work, struct delayed_work, work);
2257        priv_tt = container_of(delayed_work, struct batadv_priv_tt, work);
2258        bat_priv = container_of(priv_tt, struct batadv_priv, tt);
2259
2260        batadv_tt_local_purge(bat_priv);
2261        batadv_tt_global_purge(bat_priv);
2262        batadv_tt_req_purge(bat_priv);
2263        batadv_tt_roam_purge(bat_priv);
2264
2265        queue_delayed_work(batadv_event_workqueue, &bat_priv->tt.work,
2266                           msecs_to_jiffies(BATADV_TT_WORK_PERIOD));
2267}
2268
2269void batadv_tt_free(struct batadv_priv *bat_priv)
2270{
2271        cancel_delayed_work_sync(&bat_priv->tt.work);
2272
2273        batadv_tt_local_table_free(bat_priv);
2274        batadv_tt_global_table_free(bat_priv);
2275        batadv_tt_req_list_free(bat_priv);
2276        batadv_tt_changes_list_free(bat_priv);
2277        batadv_tt_roam_list_free(bat_priv);
2278
2279        kfree(bat_priv->tt.last_changeset);
2280}
2281
2282/* This function will enable or disable the specified flags for all the entries
2283 * in the given hash table and returns the number of modified entries
2284 */
2285static uint16_t batadv_tt_set_flags(struct batadv_hashtable *hash,
2286                                    uint16_t flags, bool enable)
2287{
2288        uint32_t i;
2289        uint16_t changed_num = 0;
2290        struct hlist_head *head;
2291        struct batadv_tt_common_entry *tt_common_entry;
2292
2293        if (!hash)
2294                goto out;
2295
2296        for (i = 0; i < hash->size; i++) {
2297                head = &hash->table[i];
2298
2299                rcu_read_lock();
2300                hlist_for_each_entry_rcu(tt_common_entry,
2301                                         head, hash_entry) {
2302                        if (enable) {
2303                                if ((tt_common_entry->flags & flags) == flags)
2304                                        continue;
2305                                tt_common_entry->flags |= flags;
2306                        } else {
2307                                if (!(tt_common_entry->flags & flags))
2308                                        continue;
2309                                tt_common_entry->flags &= ~flags;
2310                        }
2311                        changed_num++;
2312                }
2313                rcu_read_unlock();
2314        }
2315out:
2316        return changed_num;
2317}
2318
2319/* Purge out all the tt local entries marked with BATADV_TT_CLIENT_PENDING */
2320static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv)
2321{
2322        struct batadv_hashtable *hash = bat_priv->tt.local_hash;
2323        struct batadv_tt_common_entry *tt_common;
2324        struct batadv_tt_local_entry *tt_local;
2325        struct hlist_node *node_tmp;
2326        struct hlist_head *head;
2327        spinlock_t *list_lock; /* protects write access to the hash lists */
2328        uint32_t i;
2329
2330        if (!hash)
2331                return;
2332
2333        for (i = 0; i < hash->size; i++) {
2334                head = &hash->table[i];
2335                list_lock = &hash->list_locks[i];
2336
2337                spin_lock_bh(list_lock);
2338                hlist_for_each_entry_safe(tt_common, node_tmp, head,
2339                                          hash_entry) {
2340                        if (!(tt_common->flags & BATADV_TT_CLIENT_PENDING))
2341                                continue;
2342
2343                        batadv_dbg(BATADV_DBG_TT, bat_priv,
2344                                   "Deleting local tt entry (%pM): pending\n",
2345                                   tt_common->addr);
2346
2347                        atomic_dec(&bat_priv->tt.local_entry_num);
2348                        hlist_del_rcu(&tt_common->hash_entry);
2349                        tt_local = container_of(tt_common,
2350                                                struct batadv_tt_local_entry,
2351                                                common);
2352                        batadv_tt_local_entry_free_ref(tt_local);
2353                }
2354                spin_unlock_bh(list_lock);
2355        }
2356}
2357
2358static int batadv_tt_commit_changes(struct batadv_priv *bat_priv,
2359                                    unsigned char **packet_buff,
2360                                    int *packet_buff_len, int packet_min_len)
2361{
2362        uint16_t changed_num = 0;
2363
2364        if (atomic_read(&bat_priv->tt.local_changes) < 1)
2365                return -ENOENT;
2366
2367        changed_num = batadv_tt_set_flags(bat_priv->tt.local_hash,
2368                                          BATADV_TT_CLIENT_NEW, false);
2369
2370        /* all reset entries have to be counted as local entries */
2371        atomic_add(changed_num, &bat_priv->tt.local_entry_num);
2372        batadv_tt_local_purge_pending_clients(bat_priv);
2373        bat_priv->tt.local_crc = batadv_tt_local_crc(bat_priv);
2374
2375        /* Increment the TTVN only once per OGM interval */
2376        atomic_inc(&bat_priv->tt.vn);
2377        batadv_dbg(BATADV_DBG_TT, bat_priv,
2378                   "Local changes committed, updating to ttvn %u\n",
2379                   (uint8_t)atomic_read(&bat_priv->tt.vn));
2380
2381        /* reset the sending counter */
2382        atomic_set(&bat_priv->tt.ogm_append_cnt, BATADV_TT_OGM_APPEND_MAX);
2383
2384        return batadv_tt_changes_fill_buff(bat_priv, packet_buff,
2385                                           packet_buff_len, packet_min_len);
2386}
2387
2388/* when calling this function (hard_iface == primary_if) has to be true */
2389int batadv_tt_append_diff(struct batadv_priv *bat_priv,
2390                          unsigned char **packet_buff, int *packet_buff_len,
2391                          int packet_min_len)
2392{
2393        int tt_num_changes;
2394
2395        /* if at least one change happened */
2396        tt_num_changes = batadv_tt_commit_changes(bat_priv, packet_buff,
2397                                                  packet_buff_len,
2398                                                  packet_min_len);
2399
2400        /* if the changes have been sent often enough */
2401        if ((tt_num_changes < 0) &&
2402            (!batadv_atomic_dec_not_zero(&bat_priv->tt.ogm_append_cnt))) {
2403                batadv_tt_realloc_packet_buff(packet_buff, packet_buff_len,
2404                                              packet_min_len, packet_min_len);
2405                tt_num_changes = 0;
2406        }
2407
2408        return tt_num_changes;
2409}
2410
2411bool batadv_is_ap_isolated(struct batadv_priv *bat_priv, uint8_t *src,
2412                           uint8_t *dst)
2413{
2414        struct batadv_tt_local_entry *tt_local_entry = NULL;
2415        struct batadv_tt_global_entry *tt_global_entry = NULL;
2416        bool ret = false;
2417
2418        if (!atomic_read(&bat_priv->ap_isolation))
2419                goto out;
2420
2421        tt_local_entry = batadv_tt_local_hash_find(bat_priv, dst);
2422        if (!tt_local_entry)
2423                goto out;
2424
2425        tt_global_entry = batadv_tt_global_hash_find(bat_priv, src);
2426        if (!tt_global_entry)
2427                goto out;
2428
2429        if (!_batadv_is_ap_isolated(tt_local_entry, tt_global_entry))
2430                goto out;
2431
2432        ret = true;
2433
2434out:
2435        if (tt_global_entry)
2436                batadv_tt_global_entry_free_ref(tt_global_entry);
2437        if (tt_local_entry)
2438                batadv_tt_local_entry_free_ref(tt_local_entry);
2439        return ret;
2440}
2441
2442void batadv_tt_update_orig(struct batadv_priv *bat_priv,
2443                           struct batadv_orig_node *orig_node,
2444                           const unsigned char *tt_buff, uint8_t tt_num_changes,
2445                           uint8_t ttvn, uint16_t tt_crc)
2446{
2447        uint8_t orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
2448        bool full_table = true;
2449        struct batadv_tt_change *tt_change;
2450
2451        /* don't care about a backbone gateways updates. */
2452        if (batadv_bla_is_backbone_gw_orig(bat_priv, orig_node->orig))
2453                return;
2454
2455        /* orig table not initialised AND first diff is in the OGM OR the ttvn
2456         * increased by one -> we can apply the attached changes
2457         */
2458        if ((!orig_node->tt_initialised && ttvn == 1) ||
2459            ttvn - orig_ttvn == 1) {
2460                /* the OGM could not contain the changes due to their size or
2461                 * because they have already been sent BATADV_TT_OGM_APPEND_MAX
2462                 * times.
2463                 * In this case send a tt request
2464                 */
2465                if (!tt_num_changes) {
2466                        full_table = false;
2467                        goto request_table;
2468                }
2469
2470                tt_change = (struct batadv_tt_change *)tt_buff;
2471                batadv_tt_update_changes(bat_priv, orig_node, tt_num_changes,
2472                                         ttvn, tt_change);
2473
2474                /* Even if we received the precomputed crc with the OGM, we
2475                 * prefer to recompute it to spot any possible inconsistency
2476                 * in the global table
2477                 */
2478                orig_node->tt_crc = batadv_tt_global_crc(bat_priv, orig_node);
2479
2480                /* The ttvn alone is not enough to guarantee consistency
2481                 * because a single value could represent different states
2482                 * (due to the wrap around). Thus a node has to check whether
2483                 * the resulting table (after applying the changes) is still
2484                 * consistent or not. E.g. a node could disconnect while its
2485                 * ttvn is X and reconnect on ttvn = X + TTVN_MAX: in this case
2486                 * checking the CRC value is mandatory to detect the
2487                 * inconsistency
2488                 */
2489                if (orig_node->tt_crc != tt_crc)
2490                        goto request_table;
2491        } else {
2492                /* if we missed more than one change or our tables are not
2493                 * in sync anymore -> request fresh tt data
2494                 */
2495                if (!orig_node->tt_initialised || ttvn != orig_ttvn ||
2496                    orig_node->tt_crc != tt_crc) {
2497request_table:
2498                        batadv_dbg(BATADV_DBG_TT, bat_priv,
2499                                   "TT inconsistency for %pM. Need to retrieve the correct information (ttvn: %u last_ttvn: %u crc: %#.4x last_crc: %#.4x num_changes: %u)\n",
2500                                   orig_node->orig, ttvn, orig_ttvn, tt_crc,
2501                                   orig_node->tt_crc, tt_num_changes);
2502                        batadv_send_tt_request(bat_priv, orig_node, ttvn,
2503                                               tt_crc, full_table);
2504                        return;
2505                }
2506        }
2507}
2508
2509/* returns true whether we know that the client has moved from its old
2510 * originator to another one. This entry is kept is still kept for consistency
2511 * purposes
2512 */
2513bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv,
2514                                        uint8_t *addr)
2515{
2516        struct batadv_tt_global_entry *tt_global_entry;
2517        bool ret = false;
2518
2519        tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr);
2520        if (!tt_global_entry)
2521                goto out;
2522
2523        ret = tt_global_entry->common.flags & BATADV_TT_CLIENT_ROAM;
2524        batadv_tt_global_entry_free_ref(tt_global_entry);
2525out:
2526        return ret;
2527}
2528
2529/**
2530 * batadv_tt_local_client_is_roaming - tells whether the client is roaming
2531 * @bat_priv: the bat priv with all the soft interface information
2532 * @addr: the MAC address of the local client to query
2533 *
2534 * Returns true if the local client is known to be roaming (it is not served by
2535 * this node anymore) or not. If yes, the client is still present in the table
2536 * to keep the latter consistent with the node TTVN
2537 */
2538bool batadv_tt_local_client_is_roaming(struct batadv_priv *bat_priv,
2539                                       uint8_t *addr)
2540{
2541        struct batadv_tt_local_entry *tt_local_entry;
2542        bool ret = false;
2543
2544        tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr);
2545        if (!tt_local_entry)
2546                goto out;
2547
2548        ret = tt_local_entry->common.flags & BATADV_TT_CLIENT_ROAM;
2549        batadv_tt_local_entry_free_ref(tt_local_entry);
2550out:
2551        return ret;
2552}
2553
2554bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv,
2555                                          struct batadv_orig_node *orig_node,
2556                                          const unsigned char *addr)
2557{
2558        bool ret = false;
2559
2560        /* if the originator is a backbone node (meaning it belongs to the same
2561         * LAN of this node) the temporary client must not be added because to
2562         * reach such destination the node must use the LAN instead of the mesh
2563         */
2564        if (batadv_bla_is_backbone_gw_orig(bat_priv, orig_node->orig))
2565                goto out;
2566
2567        if (!batadv_tt_global_add(bat_priv, orig_node, addr,
2568                                  BATADV_TT_CLIENT_TEMP,
2569                                  atomic_read(&orig_node->last_ttvn)))
2570                goto out;
2571
2572        batadv_dbg(BATADV_DBG_TT, bat_priv,
2573                   "Added temporary global client (addr: %pM orig: %pM)\n",
2574                   addr, orig_node->orig);
2575        ret = true;
2576out:
2577        return ret;
2578}
2579