.. | .. |
---|
1 | 1 | // SPDX-License-Identifier: GPL-2.0 |
---|
2 | | -/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors: |
---|
| 2 | +/* Copyright (C) 2007-2020 B.A.T.M.A.N. contributors: |
---|
3 | 3 | * |
---|
4 | 4 | * Marek Lindner, Simon Wunderlich, Antonio Quartulli |
---|
5 | | - * |
---|
6 | | - * This program is free software; you can redistribute it and/or |
---|
7 | | - * modify it under the terms of version 2 of the GNU General Public |
---|
8 | | - * License as published by the Free Software Foundation. |
---|
9 | | - * |
---|
10 | | - * This program is distributed in the hope that it will be useful, but |
---|
11 | | - * WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
12 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
13 | | - * General Public License for more details. |
---|
14 | | - * |
---|
15 | | - * You should have received a copy of the GNU General Public License |
---|
16 | | - * along with this program; if not, see <http://www.gnu.org/licenses/>. |
---|
17 | 5 | */ |
---|
18 | 6 | |
---|
19 | 7 | #include "translation-table.h" |
---|
.. | .. |
---|
205 | 193 | * Return: a pointer to the corresponding tt_global_entry struct if the client |
---|
206 | 194 | * is found, NULL otherwise. |
---|
207 | 195 | */ |
---|
208 | | -static struct batadv_tt_global_entry * |
---|
| 196 | +struct batadv_tt_global_entry * |
---|
209 | 197 | batadv_tt_global_hash_find(struct batadv_priv *bat_priv, const u8 *addr, |
---|
210 | 198 | unsigned short vid) |
---|
211 | 199 | { |
---|
.. | .. |
---|
260 | 248 | static void |
---|
261 | 249 | batadv_tt_local_entry_put(struct batadv_tt_local_entry *tt_local_entry) |
---|
262 | 250 | { |
---|
| 251 | + if (!tt_local_entry) |
---|
| 252 | + return; |
---|
| 253 | + |
---|
263 | 254 | kref_put(&tt_local_entry->common.refcount, |
---|
264 | 255 | batadv_tt_local_entry_release); |
---|
265 | 256 | } |
---|
.. | .. |
---|
283 | 274 | * queue for free after rcu grace period |
---|
284 | 275 | * @ref: kref pointer of the nc_node |
---|
285 | 276 | */ |
---|
286 | | -static void batadv_tt_global_entry_release(struct kref *ref) |
---|
| 277 | +void batadv_tt_global_entry_release(struct kref *ref) |
---|
287 | 278 | { |
---|
288 | 279 | struct batadv_tt_global_entry *tt_global_entry; |
---|
289 | 280 | |
---|
.. | .. |
---|
296 | 287 | } |
---|
297 | 288 | |
---|
298 | 289 | /** |
---|
299 | | - * batadv_tt_global_entry_put() - decrement the tt_global_entry refcounter and |
---|
300 | | - * possibly release it |
---|
301 | | - * @tt_global_entry: tt_global_entry to be free'd |
---|
302 | | - */ |
---|
303 | | -static void |
---|
304 | | -batadv_tt_global_entry_put(struct batadv_tt_global_entry *tt_global_entry) |
---|
305 | | -{ |
---|
306 | | - kref_put(&tt_global_entry->common.refcount, |
---|
307 | | - batadv_tt_global_entry_release); |
---|
308 | | -} |
---|
309 | | - |
---|
310 | | -/** |
---|
311 | 290 | * batadv_tt_global_hash_count() - count the number of orig entries |
---|
312 | 291 | * @bat_priv: the bat priv with all the soft interface information |
---|
313 | 292 | * @addr: the mac address of the client to count entries for |
---|
314 | 293 | * @vid: VLAN identifier |
---|
315 | 294 | * |
---|
316 | 295 | * Return: the number of originators advertising the given address/data |
---|
317 | | - * (excluding ourself). |
---|
| 296 | + * (excluding our self). |
---|
318 | 297 | */ |
---|
319 | 298 | int batadv_tt_global_hash_count(struct batadv_priv *bat_priv, |
---|
320 | 299 | const u8 *addr, unsigned short vid) |
---|
.. | .. |
---|
466 | 445 | static void |
---|
467 | 446 | batadv_tt_orig_list_entry_put(struct batadv_tt_orig_list_entry *orig_entry) |
---|
468 | 447 | { |
---|
| 448 | + if (!orig_entry) |
---|
| 449 | + return; |
---|
| 450 | + |
---|
469 | 451 | kref_put(&orig_entry->refcount, batadv_tt_orig_list_entry_release); |
---|
470 | 452 | } |
---|
471 | 453 | |
---|
.. | .. |
---|
793 | 775 | if (roamed_back) { |
---|
794 | 776 | batadv_tt_global_free(bat_priv, tt_global, |
---|
795 | 777 | "Roaming canceled"); |
---|
796 | | - tt_global = NULL; |
---|
797 | 778 | } else { |
---|
798 | 779 | /* The global entry has to be marked as ROAMING and |
---|
799 | 780 | * has to be kept for consistency purpose |
---|
.. | .. |
---|
855 | 836 | * table. In case of success the value is updated with the real amount of |
---|
856 | 837 | * reserved bytes |
---|
857 | 838 | * Allocate the needed amount of memory for the entire TT TVLV and write its |
---|
858 | | - * header made up by one tvlv_tt_data object and a series of tvlv_tt_vlan_data |
---|
| 839 | + * header made up of one tvlv_tt_data object and a series of tvlv_tt_vlan_data |
---|
859 | 840 | * objects, one per active VLAN served by the originator node. |
---|
860 | 841 | * |
---|
861 | 842 | * Return: the size of the allocated buffer or 0 in case of failure. |
---|
.. | .. |
---|
875 | 856 | u8 *tt_change_ptr; |
---|
876 | 857 | |
---|
877 | 858 | spin_lock_bh(&orig_node->vlan_list_lock); |
---|
878 | | - hlist_for_each_entry_rcu(vlan, &orig_node->vlan_list, list) { |
---|
| 859 | + hlist_for_each_entry(vlan, &orig_node->vlan_list, list) { |
---|
879 | 860 | num_vlan++; |
---|
880 | 861 | num_entries += atomic_read(&vlan->tt.num_entries); |
---|
881 | 862 | } |
---|
.. | .. |
---|
901 | 882 | (*tt_data)->num_vlan = htons(num_vlan); |
---|
902 | 883 | |
---|
903 | 884 | tt_vlan = (struct batadv_tvlv_tt_vlan_data *)(*tt_data + 1); |
---|
904 | | - hlist_for_each_entry_rcu(vlan, &orig_node->vlan_list, list) { |
---|
| 885 | + hlist_for_each_entry(vlan, &orig_node->vlan_list, list) { |
---|
905 | 886 | tt_vlan->vid = htons(vlan->vid); |
---|
906 | 887 | tt_vlan->crc = htonl(vlan->tt.crc); |
---|
907 | 888 | tt_vlan->reserved = 0; |
---|
.. | .. |
---|
951 | 932 | int change_offset; |
---|
952 | 933 | |
---|
953 | 934 | spin_lock_bh(&bat_priv->softif_vlan_list_lock); |
---|
954 | | - hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) { |
---|
| 935 | + hlist_for_each_entry(vlan, &bat_priv->softif_vlan_list, list) { |
---|
955 | 936 | vlan_entries = atomic_read(&vlan->tt.num_entries); |
---|
956 | 937 | if (vlan_entries < 1) |
---|
957 | 938 | continue; |
---|
.. | .. |
---|
981 | 962 | (*tt_data)->num_vlan = htons(num_vlan); |
---|
982 | 963 | |
---|
983 | 964 | tt_vlan = (struct batadv_tvlv_tt_vlan_data *)(*tt_data + 1); |
---|
984 | | - hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) { |
---|
| 965 | + hlist_for_each_entry(vlan, &bat_priv->softif_vlan_list, list) { |
---|
985 | 966 | vlan_entries = atomic_read(&vlan->tt.num_entries); |
---|
986 | 967 | if (vlan_entries < 1) |
---|
987 | 968 | continue; |
---|
.. | .. |
---|
1159 | 1140 | * batadv_tt_local_dump_entry() - Dump one TT local entry into a message |
---|
1160 | 1141 | * @msg :Netlink message to dump into |
---|
1161 | 1142 | * @portid: Port making netlink request |
---|
1162 | | - * @seq: Sequence number of netlink message |
---|
| 1143 | + * @cb: Control block containing additional options |
---|
1163 | 1144 | * @bat_priv: The bat priv with all the soft interface information |
---|
1164 | 1145 | * @common: tt local & tt global common data |
---|
1165 | 1146 | * |
---|
1166 | 1147 | * Return: Error code, or 0 on success |
---|
1167 | 1148 | */ |
---|
1168 | 1149 | static int |
---|
1169 | | -batadv_tt_local_dump_entry(struct sk_buff *msg, u32 portid, u32 seq, |
---|
| 1150 | +batadv_tt_local_dump_entry(struct sk_buff *msg, u32 portid, |
---|
| 1151 | + struct netlink_callback *cb, |
---|
1170 | 1152 | struct batadv_priv *bat_priv, |
---|
1171 | 1153 | struct batadv_tt_common_entry *common) |
---|
1172 | 1154 | { |
---|
.. | .. |
---|
1187 | 1169 | |
---|
1188 | 1170 | batadv_softif_vlan_put(vlan); |
---|
1189 | 1171 | |
---|
1190 | | - hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, |
---|
1191 | | - NLM_F_MULTI, |
---|
| 1172 | + hdr = genlmsg_put(msg, portid, cb->nlh->nlmsg_seq, |
---|
| 1173 | + &batadv_netlink_family, NLM_F_MULTI, |
---|
1192 | 1174 | BATADV_CMD_GET_TRANSTABLE_LOCAL); |
---|
1193 | 1175 | if (!hdr) |
---|
1194 | 1176 | return -ENOBUFS; |
---|
| 1177 | + |
---|
| 1178 | + genl_dump_check_consistent(cb, hdr); |
---|
1195 | 1179 | |
---|
1196 | 1180 | if (nla_put(msg, BATADV_ATTR_TT_ADDRESS, ETH_ALEN, common->addr) || |
---|
1197 | 1181 | nla_put_u32(msg, BATADV_ATTR_TT_CRC32, crc) || |
---|
.. | .. |
---|
1215 | 1199 | * batadv_tt_local_dump_bucket() - Dump one TT local bucket into a message |
---|
1216 | 1200 | * @msg: Netlink message to dump into |
---|
1217 | 1201 | * @portid: Port making netlink request |
---|
1218 | | - * @seq: Sequence number of netlink message |
---|
| 1202 | + * @cb: Control block containing additional options |
---|
1219 | 1203 | * @bat_priv: The bat priv with all the soft interface information |
---|
1220 | | - * @head: Pointer to the list containing the local tt entries |
---|
| 1204 | + * @hash: hash to dump |
---|
| 1205 | + * @bucket: bucket index to dump |
---|
1221 | 1206 | * @idx_s: Number of entries to skip |
---|
1222 | 1207 | * |
---|
1223 | 1208 | * Return: Error code, or 0 on success |
---|
1224 | 1209 | */ |
---|
1225 | 1210 | static int |
---|
1226 | | -batadv_tt_local_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq, |
---|
| 1211 | +batadv_tt_local_dump_bucket(struct sk_buff *msg, u32 portid, |
---|
| 1212 | + struct netlink_callback *cb, |
---|
1227 | 1213 | struct batadv_priv *bat_priv, |
---|
1228 | | - struct hlist_head *head, int *idx_s) |
---|
| 1214 | + struct batadv_hashtable *hash, unsigned int bucket, |
---|
| 1215 | + int *idx_s) |
---|
1229 | 1216 | { |
---|
1230 | 1217 | struct batadv_tt_common_entry *common; |
---|
1231 | 1218 | int idx = 0; |
---|
1232 | 1219 | |
---|
1233 | | - rcu_read_lock(); |
---|
1234 | | - hlist_for_each_entry_rcu(common, head, hash_entry) { |
---|
| 1220 | + spin_lock_bh(&hash->list_locks[bucket]); |
---|
| 1221 | + cb->seq = atomic_read(&hash->generation) << 1 | 1; |
---|
| 1222 | + |
---|
| 1223 | + hlist_for_each_entry(common, &hash->table[bucket], hash_entry) { |
---|
1235 | 1224 | if (idx++ < *idx_s) |
---|
1236 | 1225 | continue; |
---|
1237 | 1226 | |
---|
1238 | | - if (batadv_tt_local_dump_entry(msg, portid, seq, bat_priv, |
---|
| 1227 | + if (batadv_tt_local_dump_entry(msg, portid, cb, bat_priv, |
---|
1239 | 1228 | common)) { |
---|
1240 | | - rcu_read_unlock(); |
---|
| 1229 | + spin_unlock_bh(&hash->list_locks[bucket]); |
---|
1241 | 1230 | *idx_s = idx - 1; |
---|
1242 | 1231 | return -EMSGSIZE; |
---|
1243 | 1232 | } |
---|
1244 | 1233 | } |
---|
1245 | | - rcu_read_unlock(); |
---|
| 1234 | + spin_unlock_bh(&hash->list_locks[bucket]); |
---|
1246 | 1235 | |
---|
1247 | 1236 | *idx_s = 0; |
---|
1248 | 1237 | return 0; |
---|
.. | .. |
---|
1262 | 1251 | struct batadv_priv *bat_priv; |
---|
1263 | 1252 | struct batadv_hard_iface *primary_if = NULL; |
---|
1264 | 1253 | struct batadv_hashtable *hash; |
---|
1265 | | - struct hlist_head *head; |
---|
1266 | 1254 | int ret; |
---|
1267 | 1255 | int ifindex; |
---|
1268 | 1256 | int bucket = cb->args[0]; |
---|
.. | .. |
---|
1290 | 1278 | hash = bat_priv->tt.local_hash; |
---|
1291 | 1279 | |
---|
1292 | 1280 | while (bucket < hash->size) { |
---|
1293 | | - head = &hash->table[bucket]; |
---|
1294 | | - |
---|
1295 | | - if (batadv_tt_local_dump_bucket(msg, portid, cb->nlh->nlmsg_seq, |
---|
1296 | | - bat_priv, head, &idx)) |
---|
| 1281 | + if (batadv_tt_local_dump_bucket(msg, portid, cb, bat_priv, |
---|
| 1282 | + hash, bucket, &idx)) |
---|
1297 | 1283 | break; |
---|
1298 | 1284 | |
---|
1299 | 1285 | bucket++; |
---|
.. | .. |
---|
1684 | 1670 | * the function argument. |
---|
1685 | 1671 | * If a TT local entry exists for this non-mesh client remove it. |
---|
1686 | 1672 | * |
---|
1687 | | - * The caller must hold orig_node refcount. |
---|
| 1673 | + * The caller must hold the orig_node refcount. |
---|
1688 | 1674 | * |
---|
1689 | 1675 | * Return: true if the new entry has been added, false otherwise |
---|
1690 | 1676 | */ |
---|
.. | .. |
---|
1849 | 1835 | * @bat_priv: the bat priv with all the soft interface information |
---|
1850 | 1836 | * @tt_global_entry: global translation table entry to be analyzed |
---|
1851 | 1837 | * |
---|
1852 | | - * This functon assumes the caller holds rcu_read_lock(). |
---|
| 1838 | + * This function assumes the caller holds rcu_read_lock(). |
---|
1853 | 1839 | * Return: best originator list entry or NULL on errors. |
---|
1854 | 1840 | */ |
---|
1855 | 1841 | static struct batadv_tt_orig_list_entry * |
---|
.. | .. |
---|
1897 | 1883 | * @tt_global_entry: global translation table entry to be printed |
---|
1898 | 1884 | * @seq: debugfs table seq_file struct |
---|
1899 | 1885 | * |
---|
1900 | | - * This functon assumes the caller holds rcu_read_lock(). |
---|
| 1886 | + * This function assumes the caller holds rcu_read_lock(). |
---|
1901 | 1887 | */ |
---|
1902 | 1888 | static void |
---|
1903 | 1889 | batadv_tt_global_print_entry(struct batadv_priv *bat_priv, |
---|
.. | .. |
---|
2826 | 2812 | */ |
---|
2827 | 2813 | static void batadv_tt_req_node_put(struct batadv_tt_req_node *tt_req_node) |
---|
2828 | 2814 | { |
---|
| 2815 | + if (!tt_req_node) |
---|
| 2816 | + return; |
---|
| 2817 | + |
---|
2829 | 2818 | kref_put(&tt_req_node->refcount, batadv_tt_req_node_release); |
---|
2830 | 2819 | } |
---|
2831 | 2820 | |
---|