aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2018-05-25 14:54:19 -0400
committerDavid S. Miller <davem@davemloft.net>2018-05-25 14:54:19 -0400
commite3ffec48b22f3427a576ab6ca58ba5e9c46923f2 (patch)
tree2632770c11d4cc3aaafdb07f426a8519351b8188 /net
parent1383cb8103bb166e50cbab1543bb3b5118fccf82 (diff)
parent16116dac23396e73c01eeee97b102e4833a4b205 (diff)
Merge tag 'batadv-net-for-davem-20180524' of git://git.open-mesh.org/linux-merge
Simon Wunderlich says: ==================== Here are some batman-adv bugfixes: - prevent hardif_put call with NULL parameter, by Colin Ian King - Avoid race in Translation Table allocator, by Sven Eckelmann - Fix Translation Table sync flags for intermediate Responses, by Linus Luessing - prevent sending inconsistent Translation Table TVLVs, by Marek Lindner ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/batman-adv/multicast.c2
-rw-r--r--net/batman-adv/translation-table.c84
2 files changed, 68 insertions, 18 deletions
diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c
index a11d3d89f012..a35f597e8c8b 100644
--- a/net/batman-adv/multicast.c
+++ b/net/batman-adv/multicast.c
@@ -1536,7 +1536,7 @@ out:
1536 1536
1537 if (!ret && primary_if) 1537 if (!ret && primary_if)
1538 *primary_if = hard_iface; 1538 *primary_if = hard_iface;
1539 else 1539 else if (hard_iface)
1540 batadv_hardif_put(hard_iface); 1540 batadv_hardif_put(hard_iface);
1541 1541
1542 return ret; 1542 return ret;
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index 0225616d5771..3986551397ca 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -862,7 +862,7 @@ batadv_tt_prepare_tvlv_global_data(struct batadv_orig_node *orig_node,
862 struct batadv_orig_node_vlan *vlan; 862 struct batadv_orig_node_vlan *vlan;
863 u8 *tt_change_ptr; 863 u8 *tt_change_ptr;
864 864
865 rcu_read_lock(); 865 spin_lock_bh(&orig_node->vlan_list_lock);
866 hlist_for_each_entry_rcu(vlan, &orig_node->vlan_list, list) { 866 hlist_for_each_entry_rcu(vlan, &orig_node->vlan_list, list) {
867 num_vlan++; 867 num_vlan++;
868 num_entries += atomic_read(&vlan->tt.num_entries); 868 num_entries += atomic_read(&vlan->tt.num_entries);
@@ -900,7 +900,7 @@ batadv_tt_prepare_tvlv_global_data(struct batadv_orig_node *orig_node,
900 *tt_change = (struct batadv_tvlv_tt_change *)tt_change_ptr; 900 *tt_change = (struct batadv_tvlv_tt_change *)tt_change_ptr;
901 901
902out: 902out:
903 rcu_read_unlock(); 903 spin_unlock_bh(&orig_node->vlan_list_lock);
904 return tvlv_len; 904 return tvlv_len;
905} 905}
906 906
@@ -931,15 +931,20 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv,
931 struct batadv_tvlv_tt_vlan_data *tt_vlan; 931 struct batadv_tvlv_tt_vlan_data *tt_vlan;
932 struct batadv_softif_vlan *vlan; 932 struct batadv_softif_vlan *vlan;
933 u16 num_vlan = 0; 933 u16 num_vlan = 0;
934 u16 num_entries = 0; 934 u16 vlan_entries = 0;
935 u16 total_entries = 0;
935 u16 tvlv_len; 936 u16 tvlv_len;
936 u8 *tt_change_ptr; 937 u8 *tt_change_ptr;
937 int change_offset; 938 int change_offset;
938 939
939 rcu_read_lock(); 940 spin_lock_bh(&bat_priv->softif_vlan_list_lock);
940 hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) { 941 hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) {
942 vlan_entries = atomic_read(&vlan->tt.num_entries);
943 if (vlan_entries < 1)
944 continue;
945
941 num_vlan++; 946 num_vlan++;
942 num_entries += atomic_read(&vlan->tt.num_entries); 947 total_entries += vlan_entries;
943 } 948 }
944 949
945 change_offset = sizeof(**tt_data); 950 change_offset = sizeof(**tt_data);
@@ -947,7 +952,7 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv,
947 952
948 /* if tt_len is negative, allocate the space needed by the full table */ 953 /* if tt_len is negative, allocate the space needed by the full table */
949 if (*tt_len < 0) 954 if (*tt_len < 0)
950 *tt_len = batadv_tt_len(num_entries); 955 *tt_len = batadv_tt_len(total_entries);
951 956
952 tvlv_len = *tt_len; 957 tvlv_len = *tt_len;
953 tvlv_len += change_offset; 958 tvlv_len += change_offset;
@@ -964,6 +969,10 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv,
964 969
965 tt_vlan = (struct batadv_tvlv_tt_vlan_data *)(*tt_data + 1); 970 tt_vlan = (struct batadv_tvlv_tt_vlan_data *)(*tt_data + 1);
966 hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) { 971 hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) {
972 vlan_entries = atomic_read(&vlan->tt.num_entries);
973 if (vlan_entries < 1)
974 continue;
975
967 tt_vlan->vid = htons(vlan->vid); 976 tt_vlan->vid = htons(vlan->vid);
968 tt_vlan->crc = htonl(vlan->tt.crc); 977 tt_vlan->crc = htonl(vlan->tt.crc);
969 978
@@ -974,7 +983,7 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv,
974 *tt_change = (struct batadv_tvlv_tt_change *)tt_change_ptr; 983 *tt_change = (struct batadv_tvlv_tt_change *)tt_change_ptr;
975 984
976out: 985out:
977 rcu_read_unlock(); 986 spin_unlock_bh(&bat_priv->softif_vlan_list_lock);
978 return tvlv_len; 987 return tvlv_len;
979} 988}
980 989
@@ -1538,6 +1547,8 @@ batadv_tt_global_orig_entry_find(const struct batadv_tt_global_entry *entry,
1538 * handled by a given originator 1547 * handled by a given originator
1539 * @entry: the TT global entry to check 1548 * @entry: the TT global entry to check
1540 * @orig_node: the originator to search in the list 1549 * @orig_node: the originator to search in the list
1550 * @flags: a pointer to store TT flags for the given @entry received
1551 * from @orig_node
1541 * 1552 *
1542 * find out if an orig_node is already in the list of a tt_global_entry. 1553 * find out if an orig_node is already in the list of a tt_global_entry.
1543 * 1554 *
@@ -1545,7 +1556,8 @@ batadv_tt_global_orig_entry_find(const struct batadv_tt_global_entry *entry,
1545 */ 1556 */
1546static bool 1557static bool
1547batadv_tt_global_entry_has_orig(const struct batadv_tt_global_entry *entry, 1558batadv_tt_global_entry_has_orig(const struct batadv_tt_global_entry *entry,
1548 const struct batadv_orig_node *orig_node) 1559 const struct batadv_orig_node *orig_node,
1560 u8 *flags)
1549{ 1561{
1550 struct batadv_tt_orig_list_entry *orig_entry; 1562 struct batadv_tt_orig_list_entry *orig_entry;
1551 bool found = false; 1563 bool found = false;
@@ -1553,6 +1565,10 @@ batadv_tt_global_entry_has_orig(const struct batadv_tt_global_entry *entry,
1553 orig_entry = batadv_tt_global_orig_entry_find(entry, orig_node); 1565 orig_entry = batadv_tt_global_orig_entry_find(entry, orig_node);
1554 if (orig_entry) { 1566 if (orig_entry) {
1555 found = true; 1567 found = true;
1568
1569 if (flags)
1570 *flags = orig_entry->flags;
1571
1556 batadv_tt_orig_list_entry_put(orig_entry); 1572 batadv_tt_orig_list_entry_put(orig_entry);
1557 } 1573 }
1558 1574
@@ -1731,7 +1747,7 @@ static bool batadv_tt_global_add(struct batadv_priv *bat_priv,
1731 if (!(common->flags & BATADV_TT_CLIENT_TEMP)) 1747 if (!(common->flags & BATADV_TT_CLIENT_TEMP))
1732 goto out; 1748 goto out;
1733 if (batadv_tt_global_entry_has_orig(tt_global_entry, 1749 if (batadv_tt_global_entry_has_orig(tt_global_entry,
1734 orig_node)) 1750 orig_node, NULL))
1735 goto out_remove; 1751 goto out_remove;
1736 batadv_tt_global_del_orig_list(tt_global_entry); 1752 batadv_tt_global_del_orig_list(tt_global_entry);
1737 goto add_orig_entry; 1753 goto add_orig_entry;
@@ -2880,23 +2896,46 @@ unlock:
2880} 2896}
2881 2897
2882/** 2898/**
2883 * batadv_tt_local_valid() - verify that given tt entry is a valid one 2899 * batadv_tt_local_valid() - verify local tt entry and get flags
2884 * @entry_ptr: to be checked local tt entry 2900 * @entry_ptr: to be checked local tt entry
2885 * @data_ptr: not used but definition required to satisfy the callback prototype 2901 * @data_ptr: not used but definition required to satisfy the callback prototype
2902 * @flags: a pointer to store TT flags for this client to
2903 *
2904 * Checks the validity of the given local TT entry. If it is, then the provided
2905 * flags pointer is updated.
2886 * 2906 *
2887 * Return: true if the entry is a valid, false otherwise. 2907 * Return: true if the entry is a valid, false otherwise.
2888 */ 2908 */
2889static bool batadv_tt_local_valid(const void *entry_ptr, const void *data_ptr) 2909static bool batadv_tt_local_valid(const void *entry_ptr,
2910 const void *data_ptr,
2911 u8 *flags)
2890{ 2912{
2891 const struct batadv_tt_common_entry *tt_common_entry = entry_ptr; 2913 const struct batadv_tt_common_entry *tt_common_entry = entry_ptr;
2892 2914
2893 if (tt_common_entry->flags & BATADV_TT_CLIENT_NEW) 2915 if (tt_common_entry->flags & BATADV_TT_CLIENT_NEW)
2894 return false; 2916 return false;
2917
2918 if (flags)
2919 *flags = tt_common_entry->flags;
2920
2895 return true; 2921 return true;
2896} 2922}
2897 2923
2924/**
2925 * batadv_tt_global_valid() - verify global tt entry and get flags
2926 * @entry_ptr: to be checked global tt entry
2927 * @data_ptr: an orig_node object (may be NULL)
2928 * @flags: a pointer to store TT flags for this client to
2929 *
2930 * Checks the validity of the given global TT entry. If it is, then the provided
2931 * flags pointer is updated either with the common (summed) TT flags if data_ptr
2932 * is NULL or the specific, per originator TT flags otherwise.
2933 *
2934 * Return: true if the entry is a valid, false otherwise.
2935 */
2898static bool batadv_tt_global_valid(const void *entry_ptr, 2936static bool batadv_tt_global_valid(const void *entry_ptr,
2899 const void *data_ptr) 2937 const void *data_ptr,
2938 u8 *flags)
2900{ 2939{
2901 const struct batadv_tt_common_entry *tt_common_entry = entry_ptr; 2940 const struct batadv_tt_common_entry *tt_common_entry = entry_ptr;
2902 const struct batadv_tt_global_entry *tt_global_entry; 2941 const struct batadv_tt_global_entry *tt_global_entry;
@@ -2910,7 +2949,8 @@ static bool batadv_tt_global_valid(const void *entry_ptr,
2910 struct batadv_tt_global_entry, 2949 struct batadv_tt_global_entry,
2911 common); 2950 common);
2912 2951
2913 return batadv_tt_global_entry_has_orig(tt_global_entry, orig_node); 2952 return batadv_tt_global_entry_has_orig(tt_global_entry, orig_node,
2953 flags);
2914} 2954}
2915 2955
2916/** 2956/**
@@ -2920,25 +2960,34 @@ static bool batadv_tt_global_valid(const void *entry_ptr,
2920 * @hash: hash table containing the tt entries 2960 * @hash: hash table containing the tt entries
2921 * @tt_len: expected tvlv tt data buffer length in number of bytes 2961 * @tt_len: expected tvlv tt data buffer length in number of bytes
2922 * @tvlv_buff: pointer to the buffer to fill with the TT data 2962 * @tvlv_buff: pointer to the buffer to fill with the TT data
2923 * @valid_cb: function to filter tt change entries 2963 * @valid_cb: function to filter tt change entries and to return TT flags
2924 * @cb_data: data passed to the filter function as argument 2964 * @cb_data: data passed to the filter function as argument
2965 *
2966 * Fills the tvlv buff with the tt entries from the specified hash. If valid_cb
2967 * is not provided then this becomes a no-op.
2925 */ 2968 */
2926static void batadv_tt_tvlv_generate(struct batadv_priv *bat_priv, 2969static void batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
2927 struct batadv_hashtable *hash, 2970 struct batadv_hashtable *hash,
2928 void *tvlv_buff, u16 tt_len, 2971 void *tvlv_buff, u16 tt_len,
2929 bool (*valid_cb)(const void *, 2972 bool (*valid_cb)(const void *,
2930 const void *), 2973 const void *,
2974 u8 *flags),
2931 void *cb_data) 2975 void *cb_data)
2932{ 2976{
2933 struct batadv_tt_common_entry *tt_common_entry; 2977 struct batadv_tt_common_entry *tt_common_entry;
2934 struct batadv_tvlv_tt_change *tt_change; 2978 struct batadv_tvlv_tt_change *tt_change;
2935 struct hlist_head *head; 2979 struct hlist_head *head;
2936 u16 tt_tot, tt_num_entries = 0; 2980 u16 tt_tot, tt_num_entries = 0;
2981 u8 flags;
2982 bool ret;
2937 u32 i; 2983 u32 i;
2938 2984
2939 tt_tot = batadv_tt_entries(tt_len); 2985 tt_tot = batadv_tt_entries(tt_len);
2940 tt_change = (struct batadv_tvlv_tt_change *)tvlv_buff; 2986 tt_change = (struct batadv_tvlv_tt_change *)tvlv_buff;
2941 2987
2988 if (!valid_cb)
2989 return;
2990
2942 rcu_read_lock(); 2991 rcu_read_lock();
2943 for (i = 0; i < hash->size; i++) { 2992 for (i = 0; i < hash->size; i++) {
2944 head = &hash->table[i]; 2993 head = &hash->table[i];
@@ -2948,11 +2997,12 @@ static void batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
2948 if (tt_tot == tt_num_entries) 2997 if (tt_tot == tt_num_entries)
2949 break; 2998 break;
2950 2999
2951 if ((valid_cb) && (!valid_cb(tt_common_entry, cb_data))) 3000 ret = valid_cb(tt_common_entry, cb_data, &flags);
3001 if (!ret)
2952 continue; 3002 continue;
2953 3003
2954 ether_addr_copy(tt_change->addr, tt_common_entry->addr); 3004 ether_addr_copy(tt_change->addr, tt_common_entry->addr);
2955 tt_change->flags = tt_common_entry->flags; 3005 tt_change->flags = flags;
2956 tt_change->vid = htons(tt_common_entry->vid); 3006 tt_change->vid = htons(tt_common_entry->vid);
2957 memset(tt_change->reserved, 0, 3007 memset(tt_change->reserved, 0,
2958 sizeof(tt_change->reserved)); 3008 sizeof(tt_change->reserved));