.. | .. |
---|
1 | 1 | // SPDX-License-Identifier: GPL-2.0 |
---|
2 | | -/* Copyright (C) 2011-2018 B.A.T.M.A.N. contributors: |
---|
| 2 | +/* Copyright (C) 2011-2020 B.A.T.M.A.N. contributors: |
---|
3 | 3 | * |
---|
4 | 4 | * Simon Wunderlich |
---|
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 "bridge_loop_avoidance.h" |
---|
.. | .. |
---|
60 | 48 | #include "netlink.h" |
---|
61 | 49 | #include "originator.h" |
---|
62 | 50 | #include "soft-interface.h" |
---|
63 | | -#include "sysfs.h" |
---|
64 | 51 | #include "translation-table.h" |
---|
65 | 52 | |
---|
66 | 53 | static const u8 batadv_announce_mac[4] = {0x43, 0x05, 0x43, 0x05}; |
---|
.. | .. |
---|
177 | 164 | */ |
---|
178 | 165 | static void batadv_backbone_gw_put(struct batadv_bla_backbone_gw *backbone_gw) |
---|
179 | 166 | { |
---|
| 167 | + if (!backbone_gw) |
---|
| 168 | + return; |
---|
| 169 | + |
---|
180 | 170 | kref_put(&backbone_gw->refcount, batadv_backbone_gw_release); |
---|
181 | 171 | } |
---|
182 | 172 | |
---|
.. | .. |
---|
212 | 202 | */ |
---|
213 | 203 | static void batadv_claim_put(struct batadv_bla_claim *claim) |
---|
214 | 204 | { |
---|
| 205 | + if (!claim) |
---|
| 206 | + return; |
---|
| 207 | + |
---|
215 | 208 | kref_put(&claim->refcount, batadv_claim_release); |
---|
216 | 209 | } |
---|
217 | 210 | |
---|
.. | .. |
---|
862 | 855 | |
---|
863 | 856 | /* handle as ANNOUNCE frame */ |
---|
864 | 857 | backbone_gw->lasttime = jiffies; |
---|
865 | | - crc = ntohs(*((__be16 *)(&an_addr[4]))); |
---|
| 858 | + crc = ntohs(*((__force __be16 *)(&an_addr[4]))); |
---|
866 | 859 | |
---|
867 | 860 | batadv_dbg(BATADV_DBG_BLA, bat_priv, |
---|
868 | 861 | "%s(): ANNOUNCE vid %d (sent by %pM)... CRC = %#.4x\n", |
---|
.. | .. |
---|
1010 | 1003 | * @hw_dst: the Hardware destination in the ARP Header |
---|
1011 | 1004 | * @ethhdr: pointer to the Ethernet header of the claim frame |
---|
1012 | 1005 | * |
---|
1013 | | - * checks if it is a claim packet and if its on the same group. |
---|
| 1006 | + * checks if it is a claim packet and if it's on the same group. |
---|
1014 | 1007 | * This function also applies the group ID of the sender |
---|
1015 | 1008 | * if it is in the same mesh. |
---|
1016 | 1009 | * |
---|
.. | .. |
---|
1842 | 1835 | * @vid: the VLAN ID of the frame |
---|
1843 | 1836 | * |
---|
1844 | 1837 | * Checks if this packet is a loop detect frame which has been sent by us, |
---|
1845 | | - * throw an uevent and log the event if that is the case. |
---|
| 1838 | + * throws an uevent and logs the event if that is the case. |
---|
1846 | 1839 | * |
---|
1847 | 1840 | * Return: true if it is a loop detect frame which is to be dropped, false |
---|
1848 | 1841 | * otherwise. |
---|
.. | .. |
---|
1880 | 1873 | |
---|
1881 | 1874 | ret = queue_work(batadv_event_workqueue, &backbone_gw->report_work); |
---|
1882 | 1875 | |
---|
1883 | | - /* backbone_gw is unreferenced in the report work function function |
---|
| 1876 | + /* backbone_gw is unreferenced in the report work function |
---|
1884 | 1877 | * if queue_work() call was successful |
---|
1885 | 1878 | */ |
---|
1886 | 1879 | if (!ret) |
---|
.. | .. |
---|
1900 | 1893 | * * we have to race for a claim |
---|
1901 | 1894 | * * if the frame is allowed on the LAN |
---|
1902 | 1895 | * |
---|
1903 | | - * in these cases, the skb is further handled by this function |
---|
| 1896 | + * In these cases, the skb is further handled by this function |
---|
1904 | 1897 | * |
---|
1905 | 1898 | * Return: true if handled, otherwise it returns false and the caller shall |
---|
1906 | 1899 | * further process the skb. |
---|
.. | .. |
---|
2200 | 2193 | * to a netlink socket |
---|
2201 | 2194 | * @msg: buffer for the message |
---|
2202 | 2195 | * @portid: netlink port |
---|
2203 | | - * @seq: Sequence number of netlink message |
---|
| 2196 | + * @cb: Control block containing additional options |
---|
2204 | 2197 | * @primary_if: primary interface |
---|
2205 | 2198 | * @claim: entry to dump |
---|
2206 | 2199 | * |
---|
2207 | 2200 | * Return: 0 or error code. |
---|
2208 | 2201 | */ |
---|
2209 | 2202 | static int |
---|
2210 | | -batadv_bla_claim_dump_entry(struct sk_buff *msg, u32 portid, u32 seq, |
---|
| 2203 | +batadv_bla_claim_dump_entry(struct sk_buff *msg, u32 portid, |
---|
| 2204 | + struct netlink_callback *cb, |
---|
2211 | 2205 | struct batadv_hard_iface *primary_if, |
---|
2212 | 2206 | struct batadv_bla_claim *claim) |
---|
2213 | 2207 | { |
---|
.. | .. |
---|
2217 | 2211 | void *hdr; |
---|
2218 | 2212 | int ret = -EINVAL; |
---|
2219 | 2213 | |
---|
2220 | | - hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, |
---|
2221 | | - NLM_F_MULTI, BATADV_CMD_GET_BLA_CLAIM); |
---|
| 2214 | + hdr = genlmsg_put(msg, portid, cb->nlh->nlmsg_seq, |
---|
| 2215 | + &batadv_netlink_family, NLM_F_MULTI, |
---|
| 2216 | + BATADV_CMD_GET_BLA_CLAIM); |
---|
2222 | 2217 | if (!hdr) { |
---|
2223 | 2218 | ret = -ENOBUFS; |
---|
2224 | 2219 | goto out; |
---|
2225 | 2220 | } |
---|
| 2221 | + |
---|
| 2222 | + genl_dump_check_consistent(cb, hdr); |
---|
2226 | 2223 | |
---|
2227 | 2224 | is_own = batadv_compare_eth(claim->backbone_gw->orig, |
---|
2228 | 2225 | primary_addr); |
---|
.. | .. |
---|
2259 | 2256 | * to a netlink socket |
---|
2260 | 2257 | * @msg: buffer for the message |
---|
2261 | 2258 | * @portid: netlink port |
---|
2262 | | - * @seq: Sequence number of netlink message |
---|
| 2259 | + * @cb: Control block containing additional options |
---|
2263 | 2260 | * @primary_if: primary interface |
---|
2264 | | - * @head: bucket to dump |
---|
| 2261 | + * @hash: hash to dump |
---|
| 2262 | + * @bucket: bucket index to dump |
---|
2265 | 2263 | * @idx_skip: How many entries to skip |
---|
2266 | 2264 | * |
---|
2267 | 2265 | * Return: always 0. |
---|
2268 | 2266 | */ |
---|
2269 | 2267 | static int |
---|
2270 | | -batadv_bla_claim_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq, |
---|
| 2268 | +batadv_bla_claim_dump_bucket(struct sk_buff *msg, u32 portid, |
---|
| 2269 | + struct netlink_callback *cb, |
---|
2271 | 2270 | struct batadv_hard_iface *primary_if, |
---|
2272 | | - struct hlist_head *head, int *idx_skip) |
---|
| 2271 | + struct batadv_hashtable *hash, unsigned int bucket, |
---|
| 2272 | + int *idx_skip) |
---|
2273 | 2273 | { |
---|
2274 | 2274 | struct batadv_bla_claim *claim; |
---|
2275 | 2275 | int idx = 0; |
---|
2276 | 2276 | int ret = 0; |
---|
2277 | 2277 | |
---|
2278 | | - rcu_read_lock(); |
---|
2279 | | - hlist_for_each_entry_rcu(claim, head, hash_entry) { |
---|
| 2278 | + spin_lock_bh(&hash->list_locks[bucket]); |
---|
| 2279 | + cb->seq = atomic_read(&hash->generation) << 1 | 1; |
---|
| 2280 | + |
---|
| 2281 | + hlist_for_each_entry(claim, &hash->table[bucket], hash_entry) { |
---|
2280 | 2282 | if (idx++ < *idx_skip) |
---|
2281 | 2283 | continue; |
---|
2282 | 2284 | |
---|
2283 | | - ret = batadv_bla_claim_dump_entry(msg, portid, seq, |
---|
| 2285 | + ret = batadv_bla_claim_dump_entry(msg, portid, cb, |
---|
2284 | 2286 | primary_if, claim); |
---|
2285 | 2287 | if (ret) { |
---|
2286 | 2288 | *idx_skip = idx - 1; |
---|
.. | .. |
---|
2290 | 2292 | |
---|
2291 | 2293 | *idx_skip = 0; |
---|
2292 | 2294 | unlock: |
---|
2293 | | - rcu_read_unlock(); |
---|
| 2295 | + spin_unlock_bh(&hash->list_locks[bucket]); |
---|
2294 | 2296 | return ret; |
---|
2295 | 2297 | } |
---|
2296 | 2298 | |
---|
.. | .. |
---|
2310 | 2312 | struct batadv_hashtable *hash; |
---|
2311 | 2313 | struct batadv_priv *bat_priv; |
---|
2312 | 2314 | int bucket = cb->args[0]; |
---|
2313 | | - struct hlist_head *head; |
---|
2314 | 2315 | int idx = cb->args[1]; |
---|
2315 | 2316 | int ifindex; |
---|
2316 | 2317 | int ret = 0; |
---|
.. | .. |
---|
2336 | 2337 | } |
---|
2337 | 2338 | |
---|
2338 | 2339 | while (bucket < hash->size) { |
---|
2339 | | - head = &hash->table[bucket]; |
---|
2340 | | - |
---|
2341 | | - if (batadv_bla_claim_dump_bucket(msg, portid, |
---|
2342 | | - cb->nlh->nlmsg_seq, |
---|
2343 | | - primary_if, head, &idx)) |
---|
| 2340 | + if (batadv_bla_claim_dump_bucket(msg, portid, cb, primary_if, |
---|
| 2341 | + hash, bucket, &idx)) |
---|
2344 | 2342 | break; |
---|
2345 | 2343 | bucket++; |
---|
2346 | 2344 | } |
---|
.. | .. |
---|
2431 | 2429 | * netlink socket |
---|
2432 | 2430 | * @msg: buffer for the message |
---|
2433 | 2431 | * @portid: netlink port |
---|
2434 | | - * @seq: Sequence number of netlink message |
---|
| 2432 | + * @cb: Control block containing additional options |
---|
2435 | 2433 | * @primary_if: primary interface |
---|
2436 | 2434 | * @backbone_gw: entry to dump |
---|
2437 | 2435 | * |
---|
2438 | 2436 | * Return: 0 or error code. |
---|
2439 | 2437 | */ |
---|
2440 | 2438 | static int |
---|
2441 | | -batadv_bla_backbone_dump_entry(struct sk_buff *msg, u32 portid, u32 seq, |
---|
| 2439 | +batadv_bla_backbone_dump_entry(struct sk_buff *msg, u32 portid, |
---|
| 2440 | + struct netlink_callback *cb, |
---|
2442 | 2441 | struct batadv_hard_iface *primary_if, |
---|
2443 | 2442 | struct batadv_bla_backbone_gw *backbone_gw) |
---|
2444 | 2443 | { |
---|
.. | .. |
---|
2449 | 2448 | void *hdr; |
---|
2450 | 2449 | int ret = -EINVAL; |
---|
2451 | 2450 | |
---|
2452 | | - hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, |
---|
2453 | | - NLM_F_MULTI, BATADV_CMD_GET_BLA_BACKBONE); |
---|
| 2451 | + hdr = genlmsg_put(msg, portid, cb->nlh->nlmsg_seq, |
---|
| 2452 | + &batadv_netlink_family, NLM_F_MULTI, |
---|
| 2453 | + BATADV_CMD_GET_BLA_BACKBONE); |
---|
2454 | 2454 | if (!hdr) { |
---|
2455 | 2455 | ret = -ENOBUFS; |
---|
2456 | 2456 | goto out; |
---|
2457 | 2457 | } |
---|
| 2458 | + |
---|
| 2459 | + genl_dump_check_consistent(cb, hdr); |
---|
2458 | 2460 | |
---|
2459 | 2461 | is_own = batadv_compare_eth(backbone_gw->orig, primary_addr); |
---|
2460 | 2462 | |
---|
.. | .. |
---|
2492 | 2494 | * a netlink socket |
---|
2493 | 2495 | * @msg: buffer for the message |
---|
2494 | 2496 | * @portid: netlink port |
---|
2495 | | - * @seq: Sequence number of netlink message |
---|
| 2497 | + * @cb: Control block containing additional options |
---|
2496 | 2498 | * @primary_if: primary interface |
---|
2497 | | - * @head: bucket to dump |
---|
| 2499 | + * @hash: hash to dump |
---|
| 2500 | + * @bucket: bucket index to dump |
---|
2498 | 2501 | * @idx_skip: How many entries to skip |
---|
2499 | 2502 | * |
---|
2500 | 2503 | * Return: always 0. |
---|
2501 | 2504 | */ |
---|
2502 | 2505 | static int |
---|
2503 | | -batadv_bla_backbone_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq, |
---|
| 2506 | +batadv_bla_backbone_dump_bucket(struct sk_buff *msg, u32 portid, |
---|
| 2507 | + struct netlink_callback *cb, |
---|
2504 | 2508 | struct batadv_hard_iface *primary_if, |
---|
2505 | | - struct hlist_head *head, int *idx_skip) |
---|
| 2509 | + struct batadv_hashtable *hash, |
---|
| 2510 | + unsigned int bucket, int *idx_skip) |
---|
2506 | 2511 | { |
---|
2507 | 2512 | struct batadv_bla_backbone_gw *backbone_gw; |
---|
2508 | 2513 | int idx = 0; |
---|
2509 | 2514 | int ret = 0; |
---|
2510 | 2515 | |
---|
2511 | | - rcu_read_lock(); |
---|
2512 | | - hlist_for_each_entry_rcu(backbone_gw, head, hash_entry) { |
---|
| 2516 | + spin_lock_bh(&hash->list_locks[bucket]); |
---|
| 2517 | + cb->seq = atomic_read(&hash->generation) << 1 | 1; |
---|
| 2518 | + |
---|
| 2519 | + hlist_for_each_entry(backbone_gw, &hash->table[bucket], hash_entry) { |
---|
2513 | 2520 | if (idx++ < *idx_skip) |
---|
2514 | 2521 | continue; |
---|
2515 | 2522 | |
---|
2516 | | - ret = batadv_bla_backbone_dump_entry(msg, portid, seq, |
---|
| 2523 | + ret = batadv_bla_backbone_dump_entry(msg, portid, cb, |
---|
2517 | 2524 | primary_if, backbone_gw); |
---|
2518 | 2525 | if (ret) { |
---|
2519 | 2526 | *idx_skip = idx - 1; |
---|
.. | .. |
---|
2523 | 2530 | |
---|
2524 | 2531 | *idx_skip = 0; |
---|
2525 | 2532 | unlock: |
---|
2526 | | - rcu_read_unlock(); |
---|
| 2533 | + spin_unlock_bh(&hash->list_locks[bucket]); |
---|
2527 | 2534 | return ret; |
---|
2528 | 2535 | } |
---|
2529 | 2536 | |
---|
.. | .. |
---|
2543 | 2550 | struct batadv_hashtable *hash; |
---|
2544 | 2551 | struct batadv_priv *bat_priv; |
---|
2545 | 2552 | int bucket = cb->args[0]; |
---|
2546 | | - struct hlist_head *head; |
---|
2547 | 2553 | int idx = cb->args[1]; |
---|
2548 | 2554 | int ifindex; |
---|
2549 | 2555 | int ret = 0; |
---|
.. | .. |
---|
2569 | 2575 | } |
---|
2570 | 2576 | |
---|
2571 | 2577 | while (bucket < hash->size) { |
---|
2572 | | - head = &hash->table[bucket]; |
---|
2573 | | - |
---|
2574 | | - if (batadv_bla_backbone_dump_bucket(msg, portid, |
---|
2575 | | - cb->nlh->nlmsg_seq, |
---|
2576 | | - primary_if, head, &idx)) |
---|
| 2578 | + if (batadv_bla_backbone_dump_bucket(msg, portid, cb, primary_if, |
---|
| 2579 | + hash, bucket, &idx)) |
---|
2577 | 2580 | break; |
---|
2578 | 2581 | bucket++; |
---|
2579 | 2582 | } |
---|