.. | .. |
---|
1 | 1 | // SPDX-License-Identifier: GPL-2.0 |
---|
2 | | -/* Copyright (C) 2016-2018 B.A.T.M.A.N. contributors: |
---|
| 2 | +/* Copyright (C) 2016-2020 B.A.T.M.A.N. contributors: |
---|
3 | 3 | * |
---|
4 | 4 | * Matthias Schiffer |
---|
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 "netlink.h" |
---|
20 | 8 | #include "main.h" |
---|
21 | 9 | |
---|
22 | 10 | #include <linux/atomic.h> |
---|
| 11 | +#include <linux/bitops.h> |
---|
| 12 | +#include <linux/bug.h> |
---|
23 | 13 | #include <linux/byteorder/generic.h> |
---|
24 | 14 | #include <linux/cache.h> |
---|
| 15 | +#include <linux/err.h> |
---|
25 | 16 | #include <linux/errno.h> |
---|
26 | 17 | #include <linux/export.h> |
---|
27 | 18 | #include <linux/genetlink.h> |
---|
28 | 19 | #include <linux/gfp.h> |
---|
29 | 20 | #include <linux/if_ether.h> |
---|
| 21 | +#include <linux/if_vlan.h> |
---|
30 | 22 | #include <linux/init.h> |
---|
31 | 23 | #include <linux/kernel.h> |
---|
| 24 | +#include <linux/limits.h> |
---|
| 25 | +#include <linux/list.h> |
---|
32 | 26 | #include <linux/netdevice.h> |
---|
33 | 27 | #include <linux/netlink.h> |
---|
34 | 28 | #include <linux/printk.h> |
---|
35 | | -#include <linux/rculist.h> |
---|
36 | | -#include <linux/rcupdate.h> |
---|
| 29 | +#include <linux/rtnetlink.h> |
---|
37 | 30 | #include <linux/skbuff.h> |
---|
38 | 31 | #include <linux/stddef.h> |
---|
39 | 32 | #include <linux/types.h> |
---|
40 | 33 | #include <net/genetlink.h> |
---|
| 34 | +#include <net/net_namespace.h> |
---|
41 | 35 | #include <net/netlink.h> |
---|
42 | 36 | #include <net/sock.h> |
---|
43 | 37 | #include <uapi/linux/batadv_packet.h> |
---|
.. | .. |
---|
47 | 41 | #include "bridge_loop_avoidance.h" |
---|
48 | 42 | #include "distributed-arp-table.h" |
---|
49 | 43 | #include "gateway_client.h" |
---|
| 44 | +#include "gateway_common.h" |
---|
50 | 45 | #include "hard-interface.h" |
---|
| 46 | +#include "log.h" |
---|
51 | 47 | #include "multicast.h" |
---|
| 48 | +#include "network-coding.h" |
---|
52 | 49 | #include "originator.h" |
---|
53 | 50 | #include "soft-interface.h" |
---|
54 | 51 | #include "tp_meter.h" |
---|
.. | .. |
---|
58 | 55 | |
---|
59 | 56 | /* multicast groups */ |
---|
60 | 57 | enum batadv_netlink_multicast_groups { |
---|
| 58 | + BATADV_NL_MCGRP_CONFIG, |
---|
61 | 59 | BATADV_NL_MCGRP_TPMETER, |
---|
62 | 60 | }; |
---|
63 | 61 | |
---|
| 62 | +/** |
---|
| 63 | + * enum batadv_genl_ops_flags - flags for genl_ops's internal_flags |
---|
| 64 | + */ |
---|
| 65 | +enum batadv_genl_ops_flags { |
---|
| 66 | + /** |
---|
| 67 | + * @BATADV_FLAG_NEED_MESH: request requires valid soft interface in |
---|
| 68 | + * attribute BATADV_ATTR_MESH_IFINDEX and expects a pointer to it to be |
---|
| 69 | + * saved in info->user_ptr[0] |
---|
| 70 | + */ |
---|
| 71 | + BATADV_FLAG_NEED_MESH = BIT(0), |
---|
| 72 | + |
---|
| 73 | + /** |
---|
| 74 | + * @BATADV_FLAG_NEED_HARDIF: request requires valid hard interface in |
---|
| 75 | + * attribute BATADV_ATTR_HARD_IFINDEX and expects a pointer to it to be |
---|
| 76 | + * saved in info->user_ptr[1] |
---|
| 77 | + */ |
---|
| 78 | + BATADV_FLAG_NEED_HARDIF = BIT(1), |
---|
| 79 | + |
---|
| 80 | + /** |
---|
| 81 | + * @BATADV_FLAG_NEED_VLAN: request requires valid vlan in |
---|
| 82 | + * attribute BATADV_ATTR_VLANID and expects a pointer to it to be |
---|
| 83 | + * saved in info->user_ptr[1] |
---|
| 84 | + */ |
---|
| 85 | + BATADV_FLAG_NEED_VLAN = BIT(2), |
---|
| 86 | +}; |
---|
| 87 | + |
---|
64 | 88 | static const struct genl_multicast_group batadv_netlink_mcgrps[] = { |
---|
| 89 | + [BATADV_NL_MCGRP_CONFIG] = { .name = BATADV_NL_MCAST_GROUP_CONFIG }, |
---|
65 | 90 | [BATADV_NL_MCGRP_TPMETER] = { .name = BATADV_NL_MCAST_GROUP_TPMETER }, |
---|
66 | 91 | }; |
---|
67 | 92 | |
---|
.. | .. |
---|
104 | 129 | [BATADV_ATTR_DAT_CACHE_VID] = { .type = NLA_U16 }, |
---|
105 | 130 | [BATADV_ATTR_MCAST_FLAGS] = { .type = NLA_U32 }, |
---|
106 | 131 | [BATADV_ATTR_MCAST_FLAGS_PRIV] = { .type = NLA_U32 }, |
---|
| 132 | + [BATADV_ATTR_VLANID] = { .type = NLA_U16 }, |
---|
| 133 | + [BATADV_ATTR_AGGREGATED_OGMS_ENABLED] = { .type = NLA_U8 }, |
---|
| 134 | + [BATADV_ATTR_AP_ISOLATION_ENABLED] = { .type = NLA_U8 }, |
---|
| 135 | + [BATADV_ATTR_ISOLATION_MARK] = { .type = NLA_U32 }, |
---|
| 136 | + [BATADV_ATTR_ISOLATION_MASK] = { .type = NLA_U32 }, |
---|
| 137 | + [BATADV_ATTR_BONDING_ENABLED] = { .type = NLA_U8 }, |
---|
| 138 | + [BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE_ENABLED] = { .type = NLA_U8 }, |
---|
| 139 | + [BATADV_ATTR_DISTRIBUTED_ARP_TABLE_ENABLED] = { .type = NLA_U8 }, |
---|
| 140 | + [BATADV_ATTR_FRAGMENTATION_ENABLED] = { .type = NLA_U8 }, |
---|
| 141 | + [BATADV_ATTR_GW_BANDWIDTH_DOWN] = { .type = NLA_U32 }, |
---|
| 142 | + [BATADV_ATTR_GW_BANDWIDTH_UP] = { .type = NLA_U32 }, |
---|
| 143 | + [BATADV_ATTR_GW_MODE] = { .type = NLA_U8 }, |
---|
| 144 | + [BATADV_ATTR_GW_SEL_CLASS] = { .type = NLA_U32 }, |
---|
| 145 | + [BATADV_ATTR_HOP_PENALTY] = { .type = NLA_U8 }, |
---|
| 146 | + [BATADV_ATTR_LOG_LEVEL] = { .type = NLA_U32 }, |
---|
| 147 | + [BATADV_ATTR_MULTICAST_FORCEFLOOD_ENABLED] = { .type = NLA_U8 }, |
---|
| 148 | + [BATADV_ATTR_MULTICAST_FANOUT] = { .type = NLA_U32 }, |
---|
| 149 | + [BATADV_ATTR_NETWORK_CODING_ENABLED] = { .type = NLA_U8 }, |
---|
| 150 | + [BATADV_ATTR_ORIG_INTERVAL] = { .type = NLA_U32 }, |
---|
| 151 | + [BATADV_ATTR_ELP_INTERVAL] = { .type = NLA_U32 }, |
---|
| 152 | + [BATADV_ATTR_THROUGHPUT_OVERRIDE] = { .type = NLA_U32 }, |
---|
107 | 153 | }; |
---|
108 | 154 | |
---|
109 | 155 | /** |
---|
.. | .. |
---|
122 | 168 | } |
---|
123 | 169 | |
---|
124 | 170 | /** |
---|
125 | | - * batadv_netlink_mesh_info_put() - fill in generic information about mesh |
---|
126 | | - * interface |
---|
127 | | - * @msg: netlink message to be sent back |
---|
128 | | - * @soft_iface: interface for which the data should be taken |
---|
| 171 | + * batadv_netlink_mesh_fill_ap_isolation() - Add ap_isolation softif attribute |
---|
| 172 | + * @msg: Netlink message to dump into |
---|
| 173 | + * @bat_priv: the bat priv with all the soft interface information |
---|
129 | 174 | * |
---|
130 | | - * Return: 0 on success, < 0 on error |
---|
| 175 | + * Return: 0 on success or negative error number in case of failure |
---|
131 | 176 | */ |
---|
132 | | -static int |
---|
133 | | -batadv_netlink_mesh_info_put(struct sk_buff *msg, struct net_device *soft_iface) |
---|
| 177 | +static int batadv_netlink_mesh_fill_ap_isolation(struct sk_buff *msg, |
---|
| 178 | + struct batadv_priv *bat_priv) |
---|
134 | 179 | { |
---|
135 | | - struct batadv_priv *bat_priv = netdev_priv(soft_iface); |
---|
| 180 | + struct batadv_softif_vlan *vlan; |
---|
| 181 | + u8 ap_isolation; |
---|
| 182 | + |
---|
| 183 | + vlan = batadv_softif_vlan_get(bat_priv, BATADV_NO_FLAGS); |
---|
| 184 | + if (!vlan) |
---|
| 185 | + return 0; |
---|
| 186 | + |
---|
| 187 | + ap_isolation = atomic_read(&vlan->ap_isolation); |
---|
| 188 | + batadv_softif_vlan_put(vlan); |
---|
| 189 | + |
---|
| 190 | + return nla_put_u8(msg, BATADV_ATTR_AP_ISOLATION_ENABLED, |
---|
| 191 | + !!ap_isolation); |
---|
| 192 | +} |
---|
| 193 | + |
---|
| 194 | +/** |
---|
| 195 | + * batadv_option_set_ap_isolation() - Set ap_isolation from genl msg |
---|
| 196 | + * @attr: parsed BATADV_ATTR_AP_ISOLATION_ENABLED attribute |
---|
| 197 | + * @bat_priv: the bat priv with all the soft interface information |
---|
| 198 | + * |
---|
| 199 | + * Return: 0 on success or negative error number in case of failure |
---|
| 200 | + */ |
---|
| 201 | +static int batadv_netlink_set_mesh_ap_isolation(struct nlattr *attr, |
---|
| 202 | + struct batadv_priv *bat_priv) |
---|
| 203 | +{ |
---|
| 204 | + struct batadv_softif_vlan *vlan; |
---|
| 205 | + |
---|
| 206 | + vlan = batadv_softif_vlan_get(bat_priv, BATADV_NO_FLAGS); |
---|
| 207 | + if (!vlan) |
---|
| 208 | + return -ENOENT; |
---|
| 209 | + |
---|
| 210 | + atomic_set(&vlan->ap_isolation, !!nla_get_u8(attr)); |
---|
| 211 | + batadv_softif_vlan_put(vlan); |
---|
| 212 | + |
---|
| 213 | + return 0; |
---|
| 214 | +} |
---|
| 215 | + |
---|
| 216 | +/** |
---|
| 217 | + * batadv_netlink_mesh_fill() - Fill message with mesh attributes |
---|
| 218 | + * @msg: Netlink message to dump into |
---|
| 219 | + * @bat_priv: the bat priv with all the soft interface information |
---|
| 220 | + * @cmd: type of message to generate |
---|
| 221 | + * @portid: Port making netlink request |
---|
| 222 | + * @seq: sequence number for message |
---|
| 223 | + * @flags: Additional flags for message |
---|
| 224 | + * |
---|
| 225 | + * Return: 0 on success or negative error number in case of failure |
---|
| 226 | + */ |
---|
| 227 | +static int batadv_netlink_mesh_fill(struct sk_buff *msg, |
---|
| 228 | + struct batadv_priv *bat_priv, |
---|
| 229 | + enum batadv_nl_commands cmd, |
---|
| 230 | + u32 portid, u32 seq, int flags) |
---|
| 231 | +{ |
---|
| 232 | + struct net_device *soft_iface = bat_priv->soft_iface; |
---|
136 | 233 | struct batadv_hard_iface *primary_if = NULL; |
---|
137 | 234 | struct net_device *hard_iface; |
---|
138 | | - int ret = -ENOBUFS; |
---|
| 235 | + void *hdr; |
---|
| 236 | + |
---|
| 237 | + hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, flags, cmd); |
---|
| 238 | + if (!hdr) |
---|
| 239 | + return -ENOBUFS; |
---|
139 | 240 | |
---|
140 | 241 | if (nla_put_string(msg, BATADV_ATTR_VERSION, BATADV_SOURCE_VERSION) || |
---|
141 | 242 | nla_put_string(msg, BATADV_ATTR_ALGO_NAME, |
---|
.. | .. |
---|
146 | 247 | soft_iface->dev_addr) || |
---|
147 | 248 | nla_put_u8(msg, BATADV_ATTR_TT_TTVN, |
---|
148 | 249 | (u8)atomic_read(&bat_priv->tt.vn))) |
---|
149 | | - goto out; |
---|
| 250 | + goto nla_put_failure; |
---|
150 | 251 | |
---|
151 | 252 | #ifdef CONFIG_BATMAN_ADV_BLA |
---|
152 | 253 | if (nla_put_u16(msg, BATADV_ATTR_BLA_CRC, |
---|
153 | 254 | ntohs(bat_priv->bla.claim_dest.group))) |
---|
154 | | - goto out; |
---|
| 255 | + goto nla_put_failure; |
---|
155 | 256 | #endif |
---|
156 | 257 | |
---|
157 | 258 | if (batadv_mcast_mesh_info_put(msg, bat_priv)) |
---|
158 | | - goto out; |
---|
| 259 | + goto nla_put_failure; |
---|
159 | 260 | |
---|
160 | 261 | primary_if = batadv_primary_if_get_selected(bat_priv); |
---|
161 | 262 | if (primary_if && primary_if->if_status == BATADV_IF_ACTIVE) { |
---|
.. | .. |
---|
167 | 268 | hard_iface->name) || |
---|
168 | 269 | nla_put(msg, BATADV_ATTR_HARD_ADDRESS, ETH_ALEN, |
---|
169 | 270 | hard_iface->dev_addr)) |
---|
170 | | - goto out; |
---|
| 271 | + goto nla_put_failure; |
---|
171 | 272 | } |
---|
172 | 273 | |
---|
173 | | - ret = 0; |
---|
| 274 | + if (nla_put_u8(msg, BATADV_ATTR_AGGREGATED_OGMS_ENABLED, |
---|
| 275 | + !!atomic_read(&bat_priv->aggregated_ogms))) |
---|
| 276 | + goto nla_put_failure; |
---|
174 | 277 | |
---|
175 | | - out: |
---|
| 278 | + if (batadv_netlink_mesh_fill_ap_isolation(msg, bat_priv)) |
---|
| 279 | + goto nla_put_failure; |
---|
| 280 | + |
---|
| 281 | + if (nla_put_u32(msg, BATADV_ATTR_ISOLATION_MARK, |
---|
| 282 | + bat_priv->isolation_mark)) |
---|
| 283 | + goto nla_put_failure; |
---|
| 284 | + |
---|
| 285 | + if (nla_put_u32(msg, BATADV_ATTR_ISOLATION_MASK, |
---|
| 286 | + bat_priv->isolation_mark_mask)) |
---|
| 287 | + goto nla_put_failure; |
---|
| 288 | + |
---|
| 289 | + if (nla_put_u8(msg, BATADV_ATTR_BONDING_ENABLED, |
---|
| 290 | + !!atomic_read(&bat_priv->bonding))) |
---|
| 291 | + goto nla_put_failure; |
---|
| 292 | + |
---|
| 293 | +#ifdef CONFIG_BATMAN_ADV_BLA |
---|
| 294 | + if (nla_put_u8(msg, BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE_ENABLED, |
---|
| 295 | + !!atomic_read(&bat_priv->bridge_loop_avoidance))) |
---|
| 296 | + goto nla_put_failure; |
---|
| 297 | +#endif /* CONFIG_BATMAN_ADV_BLA */ |
---|
| 298 | + |
---|
| 299 | +#ifdef CONFIG_BATMAN_ADV_DAT |
---|
| 300 | + if (nla_put_u8(msg, BATADV_ATTR_DISTRIBUTED_ARP_TABLE_ENABLED, |
---|
| 301 | + !!atomic_read(&bat_priv->distributed_arp_table))) |
---|
| 302 | + goto nla_put_failure; |
---|
| 303 | +#endif /* CONFIG_BATMAN_ADV_DAT */ |
---|
| 304 | + |
---|
| 305 | + if (nla_put_u8(msg, BATADV_ATTR_FRAGMENTATION_ENABLED, |
---|
| 306 | + !!atomic_read(&bat_priv->fragmentation))) |
---|
| 307 | + goto nla_put_failure; |
---|
| 308 | + |
---|
| 309 | + if (nla_put_u32(msg, BATADV_ATTR_GW_BANDWIDTH_DOWN, |
---|
| 310 | + atomic_read(&bat_priv->gw.bandwidth_down))) |
---|
| 311 | + goto nla_put_failure; |
---|
| 312 | + |
---|
| 313 | + if (nla_put_u32(msg, BATADV_ATTR_GW_BANDWIDTH_UP, |
---|
| 314 | + atomic_read(&bat_priv->gw.bandwidth_up))) |
---|
| 315 | + goto nla_put_failure; |
---|
| 316 | + |
---|
| 317 | + if (nla_put_u8(msg, BATADV_ATTR_GW_MODE, |
---|
| 318 | + atomic_read(&bat_priv->gw.mode))) |
---|
| 319 | + goto nla_put_failure; |
---|
| 320 | + |
---|
| 321 | + if (bat_priv->algo_ops->gw.get_best_gw_node && |
---|
| 322 | + bat_priv->algo_ops->gw.is_eligible) { |
---|
| 323 | + /* GW selection class is not available if the routing algorithm |
---|
| 324 | + * in use does not implement the GW API |
---|
| 325 | + */ |
---|
| 326 | + if (nla_put_u32(msg, BATADV_ATTR_GW_SEL_CLASS, |
---|
| 327 | + atomic_read(&bat_priv->gw.sel_class))) |
---|
| 328 | + goto nla_put_failure; |
---|
| 329 | + } |
---|
| 330 | + |
---|
| 331 | + if (nla_put_u8(msg, BATADV_ATTR_HOP_PENALTY, |
---|
| 332 | + atomic_read(&bat_priv->hop_penalty))) |
---|
| 333 | + goto nla_put_failure; |
---|
| 334 | + |
---|
| 335 | +#ifdef CONFIG_BATMAN_ADV_DEBUG |
---|
| 336 | + if (nla_put_u32(msg, BATADV_ATTR_LOG_LEVEL, |
---|
| 337 | + atomic_read(&bat_priv->log_level))) |
---|
| 338 | + goto nla_put_failure; |
---|
| 339 | +#endif /* CONFIG_BATMAN_ADV_DEBUG */ |
---|
| 340 | + |
---|
| 341 | +#ifdef CONFIG_BATMAN_ADV_MCAST |
---|
| 342 | + if (nla_put_u8(msg, BATADV_ATTR_MULTICAST_FORCEFLOOD_ENABLED, |
---|
| 343 | + !atomic_read(&bat_priv->multicast_mode))) |
---|
| 344 | + goto nla_put_failure; |
---|
| 345 | + |
---|
| 346 | + if (nla_put_u32(msg, BATADV_ATTR_MULTICAST_FANOUT, |
---|
| 347 | + atomic_read(&bat_priv->multicast_fanout))) |
---|
| 348 | + goto nla_put_failure; |
---|
| 349 | +#endif /* CONFIG_BATMAN_ADV_MCAST */ |
---|
| 350 | + |
---|
| 351 | +#ifdef CONFIG_BATMAN_ADV_NC |
---|
| 352 | + if (nla_put_u8(msg, BATADV_ATTR_NETWORK_CODING_ENABLED, |
---|
| 353 | + !!atomic_read(&bat_priv->network_coding))) |
---|
| 354 | + goto nla_put_failure; |
---|
| 355 | +#endif /* CONFIG_BATMAN_ADV_NC */ |
---|
| 356 | + |
---|
| 357 | + if (nla_put_u32(msg, BATADV_ATTR_ORIG_INTERVAL, |
---|
| 358 | + atomic_read(&bat_priv->orig_interval))) |
---|
| 359 | + goto nla_put_failure; |
---|
| 360 | + |
---|
176 | 361 | if (primary_if) |
---|
177 | 362 | batadv_hardif_put(primary_if); |
---|
| 363 | + |
---|
| 364 | + genlmsg_end(msg, hdr); |
---|
| 365 | + return 0; |
---|
| 366 | + |
---|
| 367 | +nla_put_failure: |
---|
| 368 | + if (primary_if) |
---|
| 369 | + batadv_hardif_put(primary_if); |
---|
| 370 | + |
---|
| 371 | + genlmsg_cancel(msg, hdr); |
---|
| 372 | + return -EMSGSIZE; |
---|
| 373 | +} |
---|
| 374 | + |
---|
| 375 | +/** |
---|
| 376 | + * batadv_netlink_notify_mesh() - send softif attributes to listener |
---|
| 377 | + * @bat_priv: the bat priv with all the soft interface information |
---|
| 378 | + * |
---|
| 379 | + * Return: 0 on success, < 0 on error |
---|
| 380 | + */ |
---|
| 381 | +int batadv_netlink_notify_mesh(struct batadv_priv *bat_priv) |
---|
| 382 | +{ |
---|
| 383 | + struct sk_buff *msg; |
---|
| 384 | + int ret; |
---|
| 385 | + |
---|
| 386 | + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
---|
| 387 | + if (!msg) |
---|
| 388 | + return -ENOMEM; |
---|
| 389 | + |
---|
| 390 | + ret = batadv_netlink_mesh_fill(msg, bat_priv, BATADV_CMD_SET_MESH, |
---|
| 391 | + 0, 0, 0); |
---|
| 392 | + if (ret < 0) { |
---|
| 393 | + nlmsg_free(msg); |
---|
| 394 | + return ret; |
---|
| 395 | + } |
---|
| 396 | + |
---|
| 397 | + genlmsg_multicast_netns(&batadv_netlink_family, |
---|
| 398 | + dev_net(bat_priv->soft_iface), msg, 0, |
---|
| 399 | + BATADV_NL_MCGRP_CONFIG, GFP_KERNEL); |
---|
| 400 | + |
---|
| 401 | + return 0; |
---|
| 402 | +} |
---|
| 403 | + |
---|
| 404 | +/** |
---|
| 405 | + * batadv_netlink_get_mesh() - Get softif attributes |
---|
| 406 | + * @skb: Netlink message with request data |
---|
| 407 | + * @info: receiver information |
---|
| 408 | + * |
---|
| 409 | + * Return: 0 on success or negative error number in case of failure |
---|
| 410 | + */ |
---|
| 411 | +static int batadv_netlink_get_mesh(struct sk_buff *skb, struct genl_info *info) |
---|
| 412 | +{ |
---|
| 413 | + struct batadv_priv *bat_priv = info->user_ptr[0]; |
---|
| 414 | + struct sk_buff *msg; |
---|
| 415 | + int ret; |
---|
| 416 | + |
---|
| 417 | + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
---|
| 418 | + if (!msg) |
---|
| 419 | + return -ENOMEM; |
---|
| 420 | + |
---|
| 421 | + ret = batadv_netlink_mesh_fill(msg, bat_priv, BATADV_CMD_GET_MESH, |
---|
| 422 | + info->snd_portid, info->snd_seq, 0); |
---|
| 423 | + if (ret < 0) { |
---|
| 424 | + nlmsg_free(msg); |
---|
| 425 | + return ret; |
---|
| 426 | + } |
---|
| 427 | + |
---|
| 428 | + ret = genlmsg_reply(msg, info); |
---|
178 | 429 | |
---|
179 | 430 | return ret; |
---|
180 | 431 | } |
---|
181 | 432 | |
---|
182 | 433 | /** |
---|
183 | | - * batadv_netlink_get_mesh_info() - handle incoming BATADV_CMD_GET_MESH_INFO |
---|
184 | | - * netlink request |
---|
185 | | - * @skb: received netlink message |
---|
| 434 | + * batadv_netlink_set_mesh() - Set softif attributes |
---|
| 435 | + * @skb: Netlink message with request data |
---|
186 | 436 | * @info: receiver information |
---|
187 | 437 | * |
---|
188 | | - * Return: 0 on success, < 0 on error |
---|
| 438 | + * Return: 0 on success or negative error number in case of failure |
---|
189 | 439 | */ |
---|
190 | | -static int |
---|
191 | | -batadv_netlink_get_mesh_info(struct sk_buff *skb, struct genl_info *info) |
---|
| 440 | +static int batadv_netlink_set_mesh(struct sk_buff *skb, struct genl_info *info) |
---|
192 | 441 | { |
---|
193 | | - struct net *net = genl_info_net(info); |
---|
194 | | - struct net_device *soft_iface; |
---|
195 | | - struct sk_buff *msg = NULL; |
---|
196 | | - void *msg_head; |
---|
197 | | - int ifindex; |
---|
198 | | - int ret; |
---|
| 442 | + struct batadv_priv *bat_priv = info->user_ptr[0]; |
---|
| 443 | + struct nlattr *attr; |
---|
199 | 444 | |
---|
200 | | - if (!info->attrs[BATADV_ATTR_MESH_IFINDEX]) |
---|
201 | | - return -EINVAL; |
---|
| 445 | + if (info->attrs[BATADV_ATTR_AGGREGATED_OGMS_ENABLED]) { |
---|
| 446 | + attr = info->attrs[BATADV_ATTR_AGGREGATED_OGMS_ENABLED]; |
---|
202 | 447 | |
---|
203 | | - ifindex = nla_get_u32(info->attrs[BATADV_ATTR_MESH_IFINDEX]); |
---|
204 | | - if (!ifindex) |
---|
205 | | - return -EINVAL; |
---|
206 | | - |
---|
207 | | - soft_iface = dev_get_by_index(net, ifindex); |
---|
208 | | - if (!soft_iface || !batadv_softif_is_valid(soft_iface)) { |
---|
209 | | - ret = -ENODEV; |
---|
210 | | - goto out; |
---|
| 448 | + atomic_set(&bat_priv->aggregated_ogms, !!nla_get_u8(attr)); |
---|
211 | 449 | } |
---|
212 | 450 | |
---|
213 | | - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
---|
214 | | - if (!msg) { |
---|
215 | | - ret = -ENOMEM; |
---|
216 | | - goto out; |
---|
| 451 | + if (info->attrs[BATADV_ATTR_AP_ISOLATION_ENABLED]) { |
---|
| 452 | + attr = info->attrs[BATADV_ATTR_AP_ISOLATION_ENABLED]; |
---|
| 453 | + |
---|
| 454 | + batadv_netlink_set_mesh_ap_isolation(attr, bat_priv); |
---|
217 | 455 | } |
---|
218 | 456 | |
---|
219 | | - msg_head = genlmsg_put(msg, info->snd_portid, info->snd_seq, |
---|
220 | | - &batadv_netlink_family, 0, |
---|
221 | | - BATADV_CMD_GET_MESH_INFO); |
---|
222 | | - if (!msg_head) { |
---|
223 | | - ret = -ENOBUFS; |
---|
224 | | - goto out; |
---|
| 457 | + if (info->attrs[BATADV_ATTR_ISOLATION_MARK]) { |
---|
| 458 | + attr = info->attrs[BATADV_ATTR_ISOLATION_MARK]; |
---|
| 459 | + |
---|
| 460 | + bat_priv->isolation_mark = nla_get_u32(attr); |
---|
225 | 461 | } |
---|
226 | 462 | |
---|
227 | | - ret = batadv_netlink_mesh_info_put(msg, soft_iface); |
---|
| 463 | + if (info->attrs[BATADV_ATTR_ISOLATION_MASK]) { |
---|
| 464 | + attr = info->attrs[BATADV_ATTR_ISOLATION_MASK]; |
---|
228 | 465 | |
---|
229 | | - out: |
---|
230 | | - if (soft_iface) |
---|
231 | | - dev_put(soft_iface); |
---|
232 | | - |
---|
233 | | - if (ret) { |
---|
234 | | - if (msg) |
---|
235 | | - nlmsg_free(msg); |
---|
236 | | - return ret; |
---|
| 466 | + bat_priv->isolation_mark_mask = nla_get_u32(attr); |
---|
237 | 467 | } |
---|
238 | 468 | |
---|
239 | | - genlmsg_end(msg, msg_head); |
---|
240 | | - return genlmsg_reply(msg, info); |
---|
| 469 | + if (info->attrs[BATADV_ATTR_BONDING_ENABLED]) { |
---|
| 470 | + attr = info->attrs[BATADV_ATTR_BONDING_ENABLED]; |
---|
| 471 | + |
---|
| 472 | + atomic_set(&bat_priv->bonding, !!nla_get_u8(attr)); |
---|
| 473 | + } |
---|
| 474 | + |
---|
| 475 | +#ifdef CONFIG_BATMAN_ADV_BLA |
---|
| 476 | + if (info->attrs[BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE_ENABLED]) { |
---|
| 477 | + attr = info->attrs[BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE_ENABLED]; |
---|
| 478 | + |
---|
| 479 | + atomic_set(&bat_priv->bridge_loop_avoidance, |
---|
| 480 | + !!nla_get_u8(attr)); |
---|
| 481 | + batadv_bla_status_update(bat_priv->soft_iface); |
---|
| 482 | + } |
---|
| 483 | +#endif /* CONFIG_BATMAN_ADV_BLA */ |
---|
| 484 | + |
---|
| 485 | +#ifdef CONFIG_BATMAN_ADV_DAT |
---|
| 486 | + if (info->attrs[BATADV_ATTR_DISTRIBUTED_ARP_TABLE_ENABLED]) { |
---|
| 487 | + attr = info->attrs[BATADV_ATTR_DISTRIBUTED_ARP_TABLE_ENABLED]; |
---|
| 488 | + |
---|
| 489 | + atomic_set(&bat_priv->distributed_arp_table, |
---|
| 490 | + !!nla_get_u8(attr)); |
---|
| 491 | + batadv_dat_status_update(bat_priv->soft_iface); |
---|
| 492 | + } |
---|
| 493 | +#endif /* CONFIG_BATMAN_ADV_DAT */ |
---|
| 494 | + |
---|
| 495 | + if (info->attrs[BATADV_ATTR_FRAGMENTATION_ENABLED]) { |
---|
| 496 | + attr = info->attrs[BATADV_ATTR_FRAGMENTATION_ENABLED]; |
---|
| 497 | + |
---|
| 498 | + atomic_set(&bat_priv->fragmentation, !!nla_get_u8(attr)); |
---|
| 499 | + |
---|
| 500 | + rtnl_lock(); |
---|
| 501 | + batadv_update_min_mtu(bat_priv->soft_iface); |
---|
| 502 | + rtnl_unlock(); |
---|
| 503 | + } |
---|
| 504 | + |
---|
| 505 | + if (info->attrs[BATADV_ATTR_GW_BANDWIDTH_DOWN]) { |
---|
| 506 | + attr = info->attrs[BATADV_ATTR_GW_BANDWIDTH_DOWN]; |
---|
| 507 | + |
---|
| 508 | + atomic_set(&bat_priv->gw.bandwidth_down, nla_get_u32(attr)); |
---|
| 509 | + batadv_gw_tvlv_container_update(bat_priv); |
---|
| 510 | + } |
---|
| 511 | + |
---|
| 512 | + if (info->attrs[BATADV_ATTR_GW_BANDWIDTH_UP]) { |
---|
| 513 | + attr = info->attrs[BATADV_ATTR_GW_BANDWIDTH_UP]; |
---|
| 514 | + |
---|
| 515 | + atomic_set(&bat_priv->gw.bandwidth_up, nla_get_u32(attr)); |
---|
| 516 | + batadv_gw_tvlv_container_update(bat_priv); |
---|
| 517 | + } |
---|
| 518 | + |
---|
| 519 | + if (info->attrs[BATADV_ATTR_GW_MODE]) { |
---|
| 520 | + u8 gw_mode; |
---|
| 521 | + |
---|
| 522 | + attr = info->attrs[BATADV_ATTR_GW_MODE]; |
---|
| 523 | + gw_mode = nla_get_u8(attr); |
---|
| 524 | + |
---|
| 525 | + if (gw_mode <= BATADV_GW_MODE_SERVER) { |
---|
| 526 | + /* Invoking batadv_gw_reselect() is not enough to really |
---|
| 527 | + * de-select the current GW. It will only instruct the |
---|
| 528 | + * gateway client code to perform a re-election the next |
---|
| 529 | + * time that this is needed. |
---|
| 530 | + * |
---|
| 531 | + * When gw client mode is being switched off the current |
---|
| 532 | + * GW must be de-selected explicitly otherwise no GW_ADD |
---|
| 533 | + * uevent is thrown on client mode re-activation. This |
---|
| 534 | + * is operation is performed in |
---|
| 535 | + * batadv_gw_check_client_stop(). |
---|
| 536 | + */ |
---|
| 537 | + batadv_gw_reselect(bat_priv); |
---|
| 538 | + |
---|
| 539 | + /* always call batadv_gw_check_client_stop() before |
---|
| 540 | + * changing the gateway state |
---|
| 541 | + */ |
---|
| 542 | + batadv_gw_check_client_stop(bat_priv); |
---|
| 543 | + atomic_set(&bat_priv->gw.mode, gw_mode); |
---|
| 544 | + batadv_gw_tvlv_container_update(bat_priv); |
---|
| 545 | + } |
---|
| 546 | + } |
---|
| 547 | + |
---|
| 548 | + if (info->attrs[BATADV_ATTR_GW_SEL_CLASS] && |
---|
| 549 | + bat_priv->algo_ops->gw.get_best_gw_node && |
---|
| 550 | + bat_priv->algo_ops->gw.is_eligible) { |
---|
| 551 | + /* setting the GW selection class is allowed only if the routing |
---|
| 552 | + * algorithm in use implements the GW API |
---|
| 553 | + */ |
---|
| 554 | + |
---|
| 555 | + u32 sel_class_max = 0xffffffffu; |
---|
| 556 | + u32 sel_class; |
---|
| 557 | + |
---|
| 558 | + attr = info->attrs[BATADV_ATTR_GW_SEL_CLASS]; |
---|
| 559 | + sel_class = nla_get_u32(attr); |
---|
| 560 | + |
---|
| 561 | + if (!bat_priv->algo_ops->gw.store_sel_class) |
---|
| 562 | + sel_class_max = BATADV_TQ_MAX_VALUE; |
---|
| 563 | + |
---|
| 564 | + if (sel_class >= 1 && sel_class <= sel_class_max) { |
---|
| 565 | + atomic_set(&bat_priv->gw.sel_class, sel_class); |
---|
| 566 | + batadv_gw_reselect(bat_priv); |
---|
| 567 | + } |
---|
| 568 | + } |
---|
| 569 | + |
---|
| 570 | + if (info->attrs[BATADV_ATTR_HOP_PENALTY]) { |
---|
| 571 | + attr = info->attrs[BATADV_ATTR_HOP_PENALTY]; |
---|
| 572 | + |
---|
| 573 | + atomic_set(&bat_priv->hop_penalty, nla_get_u8(attr)); |
---|
| 574 | + } |
---|
| 575 | + |
---|
| 576 | +#ifdef CONFIG_BATMAN_ADV_DEBUG |
---|
| 577 | + if (info->attrs[BATADV_ATTR_LOG_LEVEL]) { |
---|
| 578 | + attr = info->attrs[BATADV_ATTR_LOG_LEVEL]; |
---|
| 579 | + |
---|
| 580 | + atomic_set(&bat_priv->log_level, |
---|
| 581 | + nla_get_u32(attr) & BATADV_DBG_ALL); |
---|
| 582 | + } |
---|
| 583 | +#endif /* CONFIG_BATMAN_ADV_DEBUG */ |
---|
| 584 | + |
---|
| 585 | +#ifdef CONFIG_BATMAN_ADV_MCAST |
---|
| 586 | + if (info->attrs[BATADV_ATTR_MULTICAST_FORCEFLOOD_ENABLED]) { |
---|
| 587 | + attr = info->attrs[BATADV_ATTR_MULTICAST_FORCEFLOOD_ENABLED]; |
---|
| 588 | + |
---|
| 589 | + atomic_set(&bat_priv->multicast_mode, !nla_get_u8(attr)); |
---|
| 590 | + } |
---|
| 591 | + |
---|
| 592 | + if (info->attrs[BATADV_ATTR_MULTICAST_FANOUT]) { |
---|
| 593 | + attr = info->attrs[BATADV_ATTR_MULTICAST_FANOUT]; |
---|
| 594 | + |
---|
| 595 | + atomic_set(&bat_priv->multicast_fanout, nla_get_u32(attr)); |
---|
| 596 | + } |
---|
| 597 | +#endif /* CONFIG_BATMAN_ADV_MCAST */ |
---|
| 598 | + |
---|
| 599 | +#ifdef CONFIG_BATMAN_ADV_NC |
---|
| 600 | + if (info->attrs[BATADV_ATTR_NETWORK_CODING_ENABLED]) { |
---|
| 601 | + attr = info->attrs[BATADV_ATTR_NETWORK_CODING_ENABLED]; |
---|
| 602 | + |
---|
| 603 | + atomic_set(&bat_priv->network_coding, !!nla_get_u8(attr)); |
---|
| 604 | + batadv_nc_status_update(bat_priv->soft_iface); |
---|
| 605 | + } |
---|
| 606 | +#endif /* CONFIG_BATMAN_ADV_NC */ |
---|
| 607 | + |
---|
| 608 | + if (info->attrs[BATADV_ATTR_ORIG_INTERVAL]) { |
---|
| 609 | + u32 orig_interval; |
---|
| 610 | + |
---|
| 611 | + attr = info->attrs[BATADV_ATTR_ORIG_INTERVAL]; |
---|
| 612 | + orig_interval = nla_get_u32(attr); |
---|
| 613 | + |
---|
| 614 | + orig_interval = min_t(u32, orig_interval, INT_MAX); |
---|
| 615 | + orig_interval = max_t(u32, orig_interval, 2 * BATADV_JITTER); |
---|
| 616 | + |
---|
| 617 | + atomic_set(&bat_priv->orig_interval, orig_interval); |
---|
| 618 | + } |
---|
| 619 | + |
---|
| 620 | + batadv_netlink_notify_mesh(bat_priv); |
---|
| 621 | + |
---|
| 622 | + return 0; |
---|
241 | 623 | } |
---|
242 | 624 | |
---|
243 | 625 | /** |
---|
.. | .. |
---|
261 | 643 | * @bat_priv: the bat priv with all the soft interface information |
---|
262 | 644 | * @dst: destination of tp_meter session |
---|
263 | 645 | * @result: reason for tp meter session stop |
---|
264 | | - * @test_time: total time ot the tp_meter session |
---|
| 646 | + * @test_time: total time of the tp_meter session |
---|
265 | 647 | * @total_bytes: bytes acked to the receiver |
---|
266 | 648 | * @cookie: cookie of tp_meter session |
---|
267 | 649 | * |
---|
.. | .. |
---|
329 | 711 | static int |
---|
330 | 712 | batadv_netlink_tp_meter_start(struct sk_buff *skb, struct genl_info *info) |
---|
331 | 713 | { |
---|
332 | | - struct net *net = genl_info_net(info); |
---|
333 | | - struct net_device *soft_iface; |
---|
334 | | - struct batadv_priv *bat_priv; |
---|
| 714 | + struct batadv_priv *bat_priv = info->user_ptr[0]; |
---|
335 | 715 | struct sk_buff *msg = NULL; |
---|
336 | 716 | u32 test_length; |
---|
337 | 717 | void *msg_head; |
---|
338 | | - int ifindex; |
---|
339 | 718 | u32 cookie; |
---|
340 | 719 | u8 *dst; |
---|
341 | 720 | int ret; |
---|
342 | | - |
---|
343 | | - if (!info->attrs[BATADV_ATTR_MESH_IFINDEX]) |
---|
344 | | - return -EINVAL; |
---|
345 | 721 | |
---|
346 | 722 | if (!info->attrs[BATADV_ATTR_ORIG_ADDRESS]) |
---|
347 | 723 | return -EINVAL; |
---|
.. | .. |
---|
349 | 725 | if (!info->attrs[BATADV_ATTR_TPMETER_TEST_TIME]) |
---|
350 | 726 | return -EINVAL; |
---|
351 | 727 | |
---|
352 | | - ifindex = nla_get_u32(info->attrs[BATADV_ATTR_MESH_IFINDEX]); |
---|
353 | | - if (!ifindex) |
---|
354 | | - return -EINVAL; |
---|
355 | | - |
---|
356 | 728 | dst = nla_data(info->attrs[BATADV_ATTR_ORIG_ADDRESS]); |
---|
357 | 729 | |
---|
358 | 730 | test_length = nla_get_u32(info->attrs[BATADV_ATTR_TPMETER_TEST_TIME]); |
---|
359 | | - |
---|
360 | | - soft_iface = dev_get_by_index(net, ifindex); |
---|
361 | | - if (!soft_iface || !batadv_softif_is_valid(soft_iface)) { |
---|
362 | | - ret = -ENODEV; |
---|
363 | | - goto out; |
---|
364 | | - } |
---|
365 | 731 | |
---|
366 | 732 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
---|
367 | 733 | if (!msg) { |
---|
.. | .. |
---|
377 | 743 | goto out; |
---|
378 | 744 | } |
---|
379 | 745 | |
---|
380 | | - bat_priv = netdev_priv(soft_iface); |
---|
381 | 746 | batadv_tp_start(bat_priv, dst, test_length, &cookie); |
---|
382 | 747 | |
---|
383 | 748 | ret = batadv_netlink_tp_meter_put(msg, cookie); |
---|
384 | 749 | |
---|
385 | 750 | out: |
---|
386 | | - if (soft_iface) |
---|
387 | | - dev_put(soft_iface); |
---|
388 | | - |
---|
389 | 751 | if (ret) { |
---|
390 | 752 | if (msg) |
---|
391 | 753 | nlmsg_free(msg); |
---|
.. | .. |
---|
406 | 768 | static int |
---|
407 | 769 | batadv_netlink_tp_meter_cancel(struct sk_buff *skb, struct genl_info *info) |
---|
408 | 770 | { |
---|
409 | | - struct net *net = genl_info_net(info); |
---|
410 | | - struct net_device *soft_iface; |
---|
411 | | - struct batadv_priv *bat_priv; |
---|
412 | | - int ifindex; |
---|
| 771 | + struct batadv_priv *bat_priv = info->user_ptr[0]; |
---|
413 | 772 | u8 *dst; |
---|
414 | 773 | int ret = 0; |
---|
415 | | - |
---|
416 | | - if (!info->attrs[BATADV_ATTR_MESH_IFINDEX]) |
---|
417 | | - return -EINVAL; |
---|
418 | 774 | |
---|
419 | 775 | if (!info->attrs[BATADV_ATTR_ORIG_ADDRESS]) |
---|
420 | 776 | return -EINVAL; |
---|
421 | 777 | |
---|
422 | | - ifindex = nla_get_u32(info->attrs[BATADV_ATTR_MESH_IFINDEX]); |
---|
423 | | - if (!ifindex) |
---|
424 | | - return -EINVAL; |
---|
425 | | - |
---|
426 | 778 | dst = nla_data(info->attrs[BATADV_ATTR_ORIG_ADDRESS]); |
---|
427 | 779 | |
---|
428 | | - soft_iface = dev_get_by_index(net, ifindex); |
---|
429 | | - if (!soft_iface || !batadv_softif_is_valid(soft_iface)) { |
---|
430 | | - ret = -ENODEV; |
---|
431 | | - goto out; |
---|
432 | | - } |
---|
433 | | - |
---|
434 | | - bat_priv = netdev_priv(soft_iface); |
---|
435 | 780 | batadv_tp_stop(bat_priv, dst, BATADV_TP_REASON_CANCEL); |
---|
436 | | - |
---|
437 | | -out: |
---|
438 | | - if (soft_iface) |
---|
439 | | - dev_put(soft_iface); |
---|
440 | 781 | |
---|
441 | 782 | return ret; |
---|
442 | 783 | } |
---|
443 | 784 | |
---|
444 | 785 | /** |
---|
445 | | - * batadv_netlink_dump_hardif_entry() - Dump one hard interface into a message |
---|
| 786 | + * batadv_netlink_hardif_fill() - Fill message with hardif attributes |
---|
446 | 787 | * @msg: Netlink message to dump into |
---|
| 788 | + * @bat_priv: the bat priv with all the soft interface information |
---|
| 789 | + * @hard_iface: hard interface which was modified |
---|
| 790 | + * @cmd: type of message to generate |
---|
447 | 791 | * @portid: Port making netlink request |
---|
448 | | - * @seq: Sequence number of netlink message |
---|
449 | | - * @hard_iface: Hard interface to dump |
---|
| 792 | + * @seq: sequence number for message |
---|
| 793 | + * @flags: Additional flags for message |
---|
| 794 | + * @cb: Control block containing additional options |
---|
450 | 795 | * |
---|
451 | | - * Return: error code, or 0 on success |
---|
| 796 | + * Return: 0 on success or negative error number in case of failure |
---|
452 | 797 | */ |
---|
453 | | -static int |
---|
454 | | -batadv_netlink_dump_hardif_entry(struct sk_buff *msg, u32 portid, u32 seq, |
---|
455 | | - struct batadv_hard_iface *hard_iface) |
---|
| 798 | +static int batadv_netlink_hardif_fill(struct sk_buff *msg, |
---|
| 799 | + struct batadv_priv *bat_priv, |
---|
| 800 | + struct batadv_hard_iface *hard_iface, |
---|
| 801 | + enum batadv_nl_commands cmd, |
---|
| 802 | + u32 portid, u32 seq, int flags, |
---|
| 803 | + struct netlink_callback *cb) |
---|
456 | 804 | { |
---|
457 | 805 | struct net_device *net_dev = hard_iface->net_dev; |
---|
458 | 806 | void *hdr; |
---|
459 | 807 | |
---|
460 | | - hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, NLM_F_MULTI, |
---|
461 | | - BATADV_CMD_GET_HARDIFS); |
---|
| 808 | + hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, flags, cmd); |
---|
462 | 809 | if (!hdr) |
---|
463 | | - return -EMSGSIZE; |
---|
| 810 | + return -ENOBUFS; |
---|
| 811 | + |
---|
| 812 | + if (cb) |
---|
| 813 | + genl_dump_check_consistent(cb, hdr); |
---|
| 814 | + |
---|
| 815 | + if (nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX, |
---|
| 816 | + bat_priv->soft_iface->ifindex)) |
---|
| 817 | + goto nla_put_failure; |
---|
464 | 818 | |
---|
465 | 819 | if (nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX, |
---|
466 | 820 | net_dev->ifindex) || |
---|
.. | .. |
---|
475 | 829 | goto nla_put_failure; |
---|
476 | 830 | } |
---|
477 | 831 | |
---|
| 832 | + if (nla_put_u8(msg, BATADV_ATTR_HOP_PENALTY, |
---|
| 833 | + atomic_read(&hard_iface->hop_penalty))) |
---|
| 834 | + goto nla_put_failure; |
---|
| 835 | + |
---|
| 836 | +#ifdef CONFIG_BATMAN_ADV_BATMAN_V |
---|
| 837 | + if (nla_put_u32(msg, BATADV_ATTR_ELP_INTERVAL, |
---|
| 838 | + atomic_read(&hard_iface->bat_v.elp_interval))) |
---|
| 839 | + goto nla_put_failure; |
---|
| 840 | + |
---|
| 841 | + if (nla_put_u32(msg, BATADV_ATTR_THROUGHPUT_OVERRIDE, |
---|
| 842 | + atomic_read(&hard_iface->bat_v.throughput_override))) |
---|
| 843 | + goto nla_put_failure; |
---|
| 844 | +#endif /* CONFIG_BATMAN_ADV_BATMAN_V */ |
---|
| 845 | + |
---|
478 | 846 | genlmsg_end(msg, hdr); |
---|
479 | 847 | return 0; |
---|
480 | 848 | |
---|
481 | | - nla_put_failure: |
---|
| 849 | +nla_put_failure: |
---|
482 | 850 | genlmsg_cancel(msg, hdr); |
---|
483 | 851 | return -EMSGSIZE; |
---|
484 | 852 | } |
---|
485 | 853 | |
---|
486 | 854 | /** |
---|
487 | | - * batadv_netlink_dump_hardifs() - Dump all hard interface into a messages |
---|
| 855 | + * batadv_netlink_notify_hardif() - send hardif attributes to listener |
---|
| 856 | + * @bat_priv: the bat priv with all the soft interface information |
---|
| 857 | + * @hard_iface: hard interface which was modified |
---|
| 858 | + * |
---|
| 859 | + * Return: 0 on success, < 0 on error |
---|
| 860 | + */ |
---|
| 861 | +int batadv_netlink_notify_hardif(struct batadv_priv *bat_priv, |
---|
| 862 | + struct batadv_hard_iface *hard_iface) |
---|
| 863 | +{ |
---|
| 864 | + struct sk_buff *msg; |
---|
| 865 | + int ret; |
---|
| 866 | + |
---|
| 867 | + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
---|
| 868 | + if (!msg) |
---|
| 869 | + return -ENOMEM; |
---|
| 870 | + |
---|
| 871 | + ret = batadv_netlink_hardif_fill(msg, bat_priv, hard_iface, |
---|
| 872 | + BATADV_CMD_SET_HARDIF, 0, 0, 0, NULL); |
---|
| 873 | + if (ret < 0) { |
---|
| 874 | + nlmsg_free(msg); |
---|
| 875 | + return ret; |
---|
| 876 | + } |
---|
| 877 | + |
---|
| 878 | + genlmsg_multicast_netns(&batadv_netlink_family, |
---|
| 879 | + dev_net(bat_priv->soft_iface), msg, 0, |
---|
| 880 | + BATADV_NL_MCGRP_CONFIG, GFP_KERNEL); |
---|
| 881 | + |
---|
| 882 | + return 0; |
---|
| 883 | +} |
---|
| 884 | + |
---|
| 885 | +/** |
---|
| 886 | + * batadv_netlink_get_hardif() - Get hardif attributes |
---|
| 887 | + * @skb: Netlink message with request data |
---|
| 888 | + * @info: receiver information |
---|
| 889 | + * |
---|
| 890 | + * Return: 0 on success or negative error number in case of failure |
---|
| 891 | + */ |
---|
| 892 | +static int batadv_netlink_get_hardif(struct sk_buff *skb, |
---|
| 893 | + struct genl_info *info) |
---|
| 894 | +{ |
---|
| 895 | + struct batadv_hard_iface *hard_iface = info->user_ptr[1]; |
---|
| 896 | + struct batadv_priv *bat_priv = info->user_ptr[0]; |
---|
| 897 | + struct sk_buff *msg; |
---|
| 898 | + int ret; |
---|
| 899 | + |
---|
| 900 | + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
---|
| 901 | + if (!msg) |
---|
| 902 | + return -ENOMEM; |
---|
| 903 | + |
---|
| 904 | + ret = batadv_netlink_hardif_fill(msg, bat_priv, hard_iface, |
---|
| 905 | + BATADV_CMD_GET_HARDIF, |
---|
| 906 | + info->snd_portid, info->snd_seq, 0, |
---|
| 907 | + NULL); |
---|
| 908 | + if (ret < 0) { |
---|
| 909 | + nlmsg_free(msg); |
---|
| 910 | + return ret; |
---|
| 911 | + } |
---|
| 912 | + |
---|
| 913 | + ret = genlmsg_reply(msg, info); |
---|
| 914 | + |
---|
| 915 | + return ret; |
---|
| 916 | +} |
---|
| 917 | + |
---|
| 918 | +/** |
---|
| 919 | + * batadv_netlink_set_hardif() - Set hardif attributes |
---|
| 920 | + * @skb: Netlink message with request data |
---|
| 921 | + * @info: receiver information |
---|
| 922 | + * |
---|
| 923 | + * Return: 0 on success or negative error number in case of failure |
---|
| 924 | + */ |
---|
| 925 | +static int batadv_netlink_set_hardif(struct sk_buff *skb, |
---|
| 926 | + struct genl_info *info) |
---|
| 927 | +{ |
---|
| 928 | + struct batadv_hard_iface *hard_iface = info->user_ptr[1]; |
---|
| 929 | + struct batadv_priv *bat_priv = info->user_ptr[0]; |
---|
| 930 | + struct nlattr *attr; |
---|
| 931 | + |
---|
| 932 | + if (info->attrs[BATADV_ATTR_HOP_PENALTY]) { |
---|
| 933 | + attr = info->attrs[BATADV_ATTR_HOP_PENALTY]; |
---|
| 934 | + |
---|
| 935 | + atomic_set(&hard_iface->hop_penalty, nla_get_u8(attr)); |
---|
| 936 | + } |
---|
| 937 | + |
---|
| 938 | +#ifdef CONFIG_BATMAN_ADV_BATMAN_V |
---|
| 939 | + |
---|
| 940 | + if (info->attrs[BATADV_ATTR_ELP_INTERVAL]) { |
---|
| 941 | + attr = info->attrs[BATADV_ATTR_ELP_INTERVAL]; |
---|
| 942 | + |
---|
| 943 | + atomic_set(&hard_iface->bat_v.elp_interval, nla_get_u32(attr)); |
---|
| 944 | + } |
---|
| 945 | + |
---|
| 946 | + if (info->attrs[BATADV_ATTR_THROUGHPUT_OVERRIDE]) { |
---|
| 947 | + attr = info->attrs[BATADV_ATTR_THROUGHPUT_OVERRIDE]; |
---|
| 948 | + |
---|
| 949 | + atomic_set(&hard_iface->bat_v.throughput_override, |
---|
| 950 | + nla_get_u32(attr)); |
---|
| 951 | + } |
---|
| 952 | +#endif /* CONFIG_BATMAN_ADV_BATMAN_V */ |
---|
| 953 | + |
---|
| 954 | + batadv_netlink_notify_hardif(bat_priv, hard_iface); |
---|
| 955 | + |
---|
| 956 | + return 0; |
---|
| 957 | +} |
---|
| 958 | + |
---|
| 959 | +/** |
---|
| 960 | + * batadv_netlink_dump_hardif() - Dump all hard interface into a messages |
---|
488 | 961 | * @msg: Netlink message to dump into |
---|
489 | 962 | * @cb: Parameters from query |
---|
490 | 963 | * |
---|
491 | 964 | * Return: error code, or length of reply message on success |
---|
492 | 965 | */ |
---|
493 | 966 | static int |
---|
494 | | -batadv_netlink_dump_hardifs(struct sk_buff *msg, struct netlink_callback *cb) |
---|
| 967 | +batadv_netlink_dump_hardif(struct sk_buff *msg, struct netlink_callback *cb) |
---|
495 | 968 | { |
---|
496 | 969 | struct net *net = sock_net(cb->skb->sk); |
---|
497 | 970 | struct net_device *soft_iface; |
---|
498 | 971 | struct batadv_hard_iface *hard_iface; |
---|
| 972 | + struct batadv_priv *bat_priv; |
---|
499 | 973 | int ifindex; |
---|
500 | 974 | int portid = NETLINK_CB(cb->skb).portid; |
---|
501 | | - int seq = cb->nlh->nlmsg_seq; |
---|
502 | 975 | int skip = cb->args[0]; |
---|
503 | 976 | int i = 0; |
---|
504 | 977 | |
---|
.. | .. |
---|
516 | 989 | return -ENODEV; |
---|
517 | 990 | } |
---|
518 | 991 | |
---|
519 | | - rcu_read_lock(); |
---|
| 992 | + bat_priv = netdev_priv(soft_iface); |
---|
520 | 993 | |
---|
521 | | - list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) { |
---|
| 994 | + rtnl_lock(); |
---|
| 995 | + cb->seq = batadv_hardif_generation << 1 | 1; |
---|
| 996 | + |
---|
| 997 | + list_for_each_entry(hard_iface, &batadv_hardif_list, list) { |
---|
522 | 998 | if (hard_iface->soft_iface != soft_iface) |
---|
523 | 999 | continue; |
---|
524 | 1000 | |
---|
525 | 1001 | if (i++ < skip) |
---|
526 | 1002 | continue; |
---|
527 | 1003 | |
---|
528 | | - if (batadv_netlink_dump_hardif_entry(msg, portid, seq, |
---|
529 | | - hard_iface)) { |
---|
| 1004 | + if (batadv_netlink_hardif_fill(msg, bat_priv, hard_iface, |
---|
| 1005 | + BATADV_CMD_GET_HARDIF, |
---|
| 1006 | + portid, cb->nlh->nlmsg_seq, |
---|
| 1007 | + NLM_F_MULTI, cb)) { |
---|
530 | 1008 | i--; |
---|
531 | 1009 | break; |
---|
532 | 1010 | } |
---|
533 | 1011 | } |
---|
534 | 1012 | |
---|
535 | | - rcu_read_unlock(); |
---|
| 1013 | + rtnl_unlock(); |
---|
536 | 1014 | |
---|
537 | 1015 | dev_put(soft_iface); |
---|
538 | 1016 | |
---|
.. | .. |
---|
541 | 1019 | return msg->len; |
---|
542 | 1020 | } |
---|
543 | 1021 | |
---|
544 | | -static const struct genl_ops batadv_netlink_ops[] = { |
---|
| 1022 | +/** |
---|
| 1023 | + * batadv_netlink_vlan_fill() - Fill message with vlan attributes |
---|
| 1024 | + * @msg: Netlink message to dump into |
---|
| 1025 | + * @bat_priv: the bat priv with all the soft interface information |
---|
| 1026 | + * @vlan: vlan which was modified |
---|
| 1027 | + * @cmd: type of message to generate |
---|
| 1028 | + * @portid: Port making netlink request |
---|
| 1029 | + * @seq: sequence number for message |
---|
| 1030 | + * @flags: Additional flags for message |
---|
| 1031 | + * |
---|
| 1032 | + * Return: 0 on success or negative error number in case of failure |
---|
| 1033 | + */ |
---|
| 1034 | +static int batadv_netlink_vlan_fill(struct sk_buff *msg, |
---|
| 1035 | + struct batadv_priv *bat_priv, |
---|
| 1036 | + struct batadv_softif_vlan *vlan, |
---|
| 1037 | + enum batadv_nl_commands cmd, |
---|
| 1038 | + u32 portid, u32 seq, int flags) |
---|
| 1039 | +{ |
---|
| 1040 | + void *hdr; |
---|
| 1041 | + |
---|
| 1042 | + hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, flags, cmd); |
---|
| 1043 | + if (!hdr) |
---|
| 1044 | + return -ENOBUFS; |
---|
| 1045 | + |
---|
| 1046 | + if (nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX, |
---|
| 1047 | + bat_priv->soft_iface->ifindex)) |
---|
| 1048 | + goto nla_put_failure; |
---|
| 1049 | + |
---|
| 1050 | + if (nla_put_u32(msg, BATADV_ATTR_VLANID, vlan->vid & VLAN_VID_MASK)) |
---|
| 1051 | + goto nla_put_failure; |
---|
| 1052 | + |
---|
| 1053 | + if (nla_put_u8(msg, BATADV_ATTR_AP_ISOLATION_ENABLED, |
---|
| 1054 | + !!atomic_read(&vlan->ap_isolation))) |
---|
| 1055 | + goto nla_put_failure; |
---|
| 1056 | + |
---|
| 1057 | + genlmsg_end(msg, hdr); |
---|
| 1058 | + return 0; |
---|
| 1059 | + |
---|
| 1060 | +nla_put_failure: |
---|
| 1061 | + genlmsg_cancel(msg, hdr); |
---|
| 1062 | + return -EMSGSIZE; |
---|
| 1063 | +} |
---|
| 1064 | + |
---|
| 1065 | +/** |
---|
| 1066 | + * batadv_netlink_notify_vlan() - send vlan attributes to listener |
---|
| 1067 | + * @bat_priv: the bat priv with all the soft interface information |
---|
| 1068 | + * @vlan: vlan which was modified |
---|
| 1069 | + * |
---|
| 1070 | + * Return: 0 on success, < 0 on error |
---|
| 1071 | + */ |
---|
| 1072 | +int batadv_netlink_notify_vlan(struct batadv_priv *bat_priv, |
---|
| 1073 | + struct batadv_softif_vlan *vlan) |
---|
| 1074 | +{ |
---|
| 1075 | + struct sk_buff *msg; |
---|
| 1076 | + int ret; |
---|
| 1077 | + |
---|
| 1078 | + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
---|
| 1079 | + if (!msg) |
---|
| 1080 | + return -ENOMEM; |
---|
| 1081 | + |
---|
| 1082 | + ret = batadv_netlink_vlan_fill(msg, bat_priv, vlan, |
---|
| 1083 | + BATADV_CMD_SET_VLAN, 0, 0, 0); |
---|
| 1084 | + if (ret < 0) { |
---|
| 1085 | + nlmsg_free(msg); |
---|
| 1086 | + return ret; |
---|
| 1087 | + } |
---|
| 1088 | + |
---|
| 1089 | + genlmsg_multicast_netns(&batadv_netlink_family, |
---|
| 1090 | + dev_net(bat_priv->soft_iface), msg, 0, |
---|
| 1091 | + BATADV_NL_MCGRP_CONFIG, GFP_KERNEL); |
---|
| 1092 | + |
---|
| 1093 | + return 0; |
---|
| 1094 | +} |
---|
| 1095 | + |
---|
| 1096 | +/** |
---|
| 1097 | + * batadv_netlink_get_vlan() - Get vlan attributes |
---|
| 1098 | + * @skb: Netlink message with request data |
---|
| 1099 | + * @info: receiver information |
---|
| 1100 | + * |
---|
| 1101 | + * Return: 0 on success or negative error number in case of failure |
---|
| 1102 | + */ |
---|
| 1103 | +static int batadv_netlink_get_vlan(struct sk_buff *skb, struct genl_info *info) |
---|
| 1104 | +{ |
---|
| 1105 | + struct batadv_softif_vlan *vlan = info->user_ptr[1]; |
---|
| 1106 | + struct batadv_priv *bat_priv = info->user_ptr[0]; |
---|
| 1107 | + struct sk_buff *msg; |
---|
| 1108 | + int ret; |
---|
| 1109 | + |
---|
| 1110 | + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
---|
| 1111 | + if (!msg) |
---|
| 1112 | + return -ENOMEM; |
---|
| 1113 | + |
---|
| 1114 | + ret = batadv_netlink_vlan_fill(msg, bat_priv, vlan, BATADV_CMD_GET_VLAN, |
---|
| 1115 | + info->snd_portid, info->snd_seq, 0); |
---|
| 1116 | + if (ret < 0) { |
---|
| 1117 | + nlmsg_free(msg); |
---|
| 1118 | + return ret; |
---|
| 1119 | + } |
---|
| 1120 | + |
---|
| 1121 | + ret = genlmsg_reply(msg, info); |
---|
| 1122 | + |
---|
| 1123 | + return ret; |
---|
| 1124 | +} |
---|
| 1125 | + |
---|
| 1126 | +/** |
---|
| 1127 | + * batadv_netlink_set_vlan() - Get vlan attributes |
---|
| 1128 | + * @skb: Netlink message with request data |
---|
| 1129 | + * @info: receiver information |
---|
| 1130 | + * |
---|
| 1131 | + * Return: 0 on success or negative error number in case of failure |
---|
| 1132 | + */ |
---|
| 1133 | +static int batadv_netlink_set_vlan(struct sk_buff *skb, struct genl_info *info) |
---|
| 1134 | +{ |
---|
| 1135 | + struct batadv_softif_vlan *vlan = info->user_ptr[1]; |
---|
| 1136 | + struct batadv_priv *bat_priv = info->user_ptr[0]; |
---|
| 1137 | + struct nlattr *attr; |
---|
| 1138 | + |
---|
| 1139 | + if (info->attrs[BATADV_ATTR_AP_ISOLATION_ENABLED]) { |
---|
| 1140 | + attr = info->attrs[BATADV_ATTR_AP_ISOLATION_ENABLED]; |
---|
| 1141 | + |
---|
| 1142 | + atomic_set(&vlan->ap_isolation, !!nla_get_u8(attr)); |
---|
| 1143 | + } |
---|
| 1144 | + |
---|
| 1145 | + batadv_netlink_notify_vlan(bat_priv, vlan); |
---|
| 1146 | + |
---|
| 1147 | + return 0; |
---|
| 1148 | +} |
---|
| 1149 | + |
---|
| 1150 | +/** |
---|
| 1151 | + * batadv_get_softif_from_info() - Retrieve soft interface from genl attributes |
---|
| 1152 | + * @net: the applicable net namespace |
---|
| 1153 | + * @info: receiver information |
---|
| 1154 | + * |
---|
| 1155 | + * Return: Pointer to soft interface (with increased refcnt) on success, error |
---|
| 1156 | + * pointer on error |
---|
| 1157 | + */ |
---|
| 1158 | +static struct net_device * |
---|
| 1159 | +batadv_get_softif_from_info(struct net *net, struct genl_info *info) |
---|
| 1160 | +{ |
---|
| 1161 | + struct net_device *soft_iface; |
---|
| 1162 | + int ifindex; |
---|
| 1163 | + |
---|
| 1164 | + if (!info->attrs[BATADV_ATTR_MESH_IFINDEX]) |
---|
| 1165 | + return ERR_PTR(-EINVAL); |
---|
| 1166 | + |
---|
| 1167 | + ifindex = nla_get_u32(info->attrs[BATADV_ATTR_MESH_IFINDEX]); |
---|
| 1168 | + |
---|
| 1169 | + soft_iface = dev_get_by_index(net, ifindex); |
---|
| 1170 | + if (!soft_iface) |
---|
| 1171 | + return ERR_PTR(-ENODEV); |
---|
| 1172 | + |
---|
| 1173 | + if (!batadv_softif_is_valid(soft_iface)) |
---|
| 1174 | + goto err_put_softif; |
---|
| 1175 | + |
---|
| 1176 | + return soft_iface; |
---|
| 1177 | + |
---|
| 1178 | +err_put_softif: |
---|
| 1179 | + dev_put(soft_iface); |
---|
| 1180 | + |
---|
| 1181 | + return ERR_PTR(-EINVAL); |
---|
| 1182 | +} |
---|
| 1183 | + |
---|
| 1184 | +/** |
---|
| 1185 | + * batadv_get_hardif_from_info() - Retrieve hardif from genl attributes |
---|
| 1186 | + * @bat_priv: the bat priv with all the soft interface information |
---|
| 1187 | + * @net: the applicable net namespace |
---|
| 1188 | + * @info: receiver information |
---|
| 1189 | + * |
---|
| 1190 | + * Return: Pointer to hard interface (with increased refcnt) on success, error |
---|
| 1191 | + * pointer on error |
---|
| 1192 | + */ |
---|
| 1193 | +static struct batadv_hard_iface * |
---|
| 1194 | +batadv_get_hardif_from_info(struct batadv_priv *bat_priv, struct net *net, |
---|
| 1195 | + struct genl_info *info) |
---|
| 1196 | +{ |
---|
| 1197 | + struct batadv_hard_iface *hard_iface; |
---|
| 1198 | + struct net_device *hard_dev; |
---|
| 1199 | + unsigned int hardif_index; |
---|
| 1200 | + |
---|
| 1201 | + if (!info->attrs[BATADV_ATTR_HARD_IFINDEX]) |
---|
| 1202 | + return ERR_PTR(-EINVAL); |
---|
| 1203 | + |
---|
| 1204 | + hardif_index = nla_get_u32(info->attrs[BATADV_ATTR_HARD_IFINDEX]); |
---|
| 1205 | + |
---|
| 1206 | + hard_dev = dev_get_by_index(net, hardif_index); |
---|
| 1207 | + if (!hard_dev) |
---|
| 1208 | + return ERR_PTR(-ENODEV); |
---|
| 1209 | + |
---|
| 1210 | + hard_iface = batadv_hardif_get_by_netdev(hard_dev); |
---|
| 1211 | + if (!hard_iface) |
---|
| 1212 | + goto err_put_harddev; |
---|
| 1213 | + |
---|
| 1214 | + if (hard_iface->soft_iface != bat_priv->soft_iface) |
---|
| 1215 | + goto err_put_hardif; |
---|
| 1216 | + |
---|
| 1217 | + /* hard_dev is referenced by hard_iface and not needed here */ |
---|
| 1218 | + dev_put(hard_dev); |
---|
| 1219 | + |
---|
| 1220 | + return hard_iface; |
---|
| 1221 | + |
---|
| 1222 | +err_put_hardif: |
---|
| 1223 | + batadv_hardif_put(hard_iface); |
---|
| 1224 | +err_put_harddev: |
---|
| 1225 | + dev_put(hard_dev); |
---|
| 1226 | + |
---|
| 1227 | + return ERR_PTR(-EINVAL); |
---|
| 1228 | +} |
---|
| 1229 | + |
---|
| 1230 | +/** |
---|
| 1231 | + * batadv_get_vlan_from_info() - Retrieve vlan from genl attributes |
---|
| 1232 | + * @bat_priv: the bat priv with all the soft interface information |
---|
| 1233 | + * @net: the applicable net namespace |
---|
| 1234 | + * @info: receiver information |
---|
| 1235 | + * |
---|
| 1236 | + * Return: Pointer to vlan on success (with increased refcnt), error pointer |
---|
| 1237 | + * on error |
---|
| 1238 | + */ |
---|
| 1239 | +static struct batadv_softif_vlan * |
---|
| 1240 | +batadv_get_vlan_from_info(struct batadv_priv *bat_priv, struct net *net, |
---|
| 1241 | + struct genl_info *info) |
---|
| 1242 | +{ |
---|
| 1243 | + struct batadv_softif_vlan *vlan; |
---|
| 1244 | + u16 vid; |
---|
| 1245 | + |
---|
| 1246 | + if (!info->attrs[BATADV_ATTR_VLANID]) |
---|
| 1247 | + return ERR_PTR(-EINVAL); |
---|
| 1248 | + |
---|
| 1249 | + vid = nla_get_u16(info->attrs[BATADV_ATTR_VLANID]); |
---|
| 1250 | + |
---|
| 1251 | + vlan = batadv_softif_vlan_get(bat_priv, vid | BATADV_VLAN_HAS_TAG); |
---|
| 1252 | + if (!vlan) |
---|
| 1253 | + return ERR_PTR(-ENOENT); |
---|
| 1254 | + |
---|
| 1255 | + return vlan; |
---|
| 1256 | +} |
---|
| 1257 | + |
---|
| 1258 | +/** |
---|
| 1259 | + * batadv_pre_doit() - Prepare batman-adv genl doit request |
---|
| 1260 | + * @ops: requested netlink operation |
---|
| 1261 | + * @skb: Netlink message with request data |
---|
| 1262 | + * @info: receiver information |
---|
| 1263 | + * |
---|
| 1264 | + * Return: 0 on success or negative error number in case of failure |
---|
| 1265 | + */ |
---|
| 1266 | +static int batadv_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, |
---|
| 1267 | + struct genl_info *info) |
---|
| 1268 | +{ |
---|
| 1269 | + struct net *net = genl_info_net(info); |
---|
| 1270 | + struct batadv_hard_iface *hard_iface; |
---|
| 1271 | + struct batadv_priv *bat_priv = NULL; |
---|
| 1272 | + struct batadv_softif_vlan *vlan; |
---|
| 1273 | + struct net_device *soft_iface; |
---|
| 1274 | + u8 user_ptr1_flags; |
---|
| 1275 | + u8 mesh_dep_flags; |
---|
| 1276 | + int ret; |
---|
| 1277 | + |
---|
| 1278 | + user_ptr1_flags = BATADV_FLAG_NEED_HARDIF | BATADV_FLAG_NEED_VLAN; |
---|
| 1279 | + if (WARN_ON(hweight8(ops->internal_flags & user_ptr1_flags) > 1)) |
---|
| 1280 | + return -EINVAL; |
---|
| 1281 | + |
---|
| 1282 | + mesh_dep_flags = BATADV_FLAG_NEED_HARDIF | BATADV_FLAG_NEED_VLAN; |
---|
| 1283 | + if (WARN_ON((ops->internal_flags & mesh_dep_flags) && |
---|
| 1284 | + (~ops->internal_flags & BATADV_FLAG_NEED_MESH))) |
---|
| 1285 | + return -EINVAL; |
---|
| 1286 | + |
---|
| 1287 | + if (ops->internal_flags & BATADV_FLAG_NEED_MESH) { |
---|
| 1288 | + soft_iface = batadv_get_softif_from_info(net, info); |
---|
| 1289 | + if (IS_ERR(soft_iface)) |
---|
| 1290 | + return PTR_ERR(soft_iface); |
---|
| 1291 | + |
---|
| 1292 | + bat_priv = netdev_priv(soft_iface); |
---|
| 1293 | + info->user_ptr[0] = bat_priv; |
---|
| 1294 | + } |
---|
| 1295 | + |
---|
| 1296 | + if (ops->internal_flags & BATADV_FLAG_NEED_HARDIF) { |
---|
| 1297 | + hard_iface = batadv_get_hardif_from_info(bat_priv, net, info); |
---|
| 1298 | + if (IS_ERR(hard_iface)) { |
---|
| 1299 | + ret = PTR_ERR(hard_iface); |
---|
| 1300 | + goto err_put_softif; |
---|
| 1301 | + } |
---|
| 1302 | + |
---|
| 1303 | + info->user_ptr[1] = hard_iface; |
---|
| 1304 | + } |
---|
| 1305 | + |
---|
| 1306 | + if (ops->internal_flags & BATADV_FLAG_NEED_VLAN) { |
---|
| 1307 | + vlan = batadv_get_vlan_from_info(bat_priv, net, info); |
---|
| 1308 | + if (IS_ERR(vlan)) { |
---|
| 1309 | + ret = PTR_ERR(vlan); |
---|
| 1310 | + goto err_put_softif; |
---|
| 1311 | + } |
---|
| 1312 | + |
---|
| 1313 | + info->user_ptr[1] = vlan; |
---|
| 1314 | + } |
---|
| 1315 | + |
---|
| 1316 | + return 0; |
---|
| 1317 | + |
---|
| 1318 | +err_put_softif: |
---|
| 1319 | + if (bat_priv) |
---|
| 1320 | + dev_put(bat_priv->soft_iface); |
---|
| 1321 | + |
---|
| 1322 | + return ret; |
---|
| 1323 | +} |
---|
| 1324 | + |
---|
| 1325 | +/** |
---|
| 1326 | + * batadv_post_doit() - End batman-adv genl doit request |
---|
| 1327 | + * @ops: requested netlink operation |
---|
| 1328 | + * @skb: Netlink message with request data |
---|
| 1329 | + * @info: receiver information |
---|
| 1330 | + */ |
---|
| 1331 | +static void batadv_post_doit(const struct genl_ops *ops, struct sk_buff *skb, |
---|
| 1332 | + struct genl_info *info) |
---|
| 1333 | +{ |
---|
| 1334 | + struct batadv_hard_iface *hard_iface; |
---|
| 1335 | + struct batadv_softif_vlan *vlan; |
---|
| 1336 | + struct batadv_priv *bat_priv; |
---|
| 1337 | + |
---|
| 1338 | + if (ops->internal_flags & BATADV_FLAG_NEED_HARDIF && |
---|
| 1339 | + info->user_ptr[1]) { |
---|
| 1340 | + hard_iface = info->user_ptr[1]; |
---|
| 1341 | + |
---|
| 1342 | + batadv_hardif_put(hard_iface); |
---|
| 1343 | + } |
---|
| 1344 | + |
---|
| 1345 | + if (ops->internal_flags & BATADV_FLAG_NEED_VLAN && info->user_ptr[1]) { |
---|
| 1346 | + vlan = info->user_ptr[1]; |
---|
| 1347 | + batadv_softif_vlan_put(vlan); |
---|
| 1348 | + } |
---|
| 1349 | + |
---|
| 1350 | + if (ops->internal_flags & BATADV_FLAG_NEED_MESH && info->user_ptr[0]) { |
---|
| 1351 | + bat_priv = info->user_ptr[0]; |
---|
| 1352 | + dev_put(bat_priv->soft_iface); |
---|
| 1353 | + } |
---|
| 1354 | +} |
---|
| 1355 | + |
---|
| 1356 | +static const struct genl_small_ops batadv_netlink_ops[] = { |
---|
545 | 1357 | { |
---|
546 | | - .cmd = BATADV_CMD_GET_MESH_INFO, |
---|
547 | | - .flags = GENL_ADMIN_PERM, |
---|
548 | | - .policy = batadv_netlink_policy, |
---|
549 | | - .doit = batadv_netlink_get_mesh_info, |
---|
| 1358 | + .cmd = BATADV_CMD_GET_MESH, |
---|
| 1359 | + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, |
---|
| 1360 | + /* can be retrieved by unprivileged users */ |
---|
| 1361 | + .doit = batadv_netlink_get_mesh, |
---|
| 1362 | + .internal_flags = BATADV_FLAG_NEED_MESH, |
---|
550 | 1363 | }, |
---|
551 | 1364 | { |
---|
552 | 1365 | .cmd = BATADV_CMD_TP_METER, |
---|
553 | | - .flags = GENL_ADMIN_PERM, |
---|
554 | | - .policy = batadv_netlink_policy, |
---|
| 1366 | + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, |
---|
| 1367 | + .flags = GENL_UNS_ADMIN_PERM, |
---|
555 | 1368 | .doit = batadv_netlink_tp_meter_start, |
---|
| 1369 | + .internal_flags = BATADV_FLAG_NEED_MESH, |
---|
556 | 1370 | }, |
---|
557 | 1371 | { |
---|
558 | 1372 | .cmd = BATADV_CMD_TP_METER_CANCEL, |
---|
559 | | - .flags = GENL_ADMIN_PERM, |
---|
560 | | - .policy = batadv_netlink_policy, |
---|
| 1373 | + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, |
---|
| 1374 | + .flags = GENL_UNS_ADMIN_PERM, |
---|
561 | 1375 | .doit = batadv_netlink_tp_meter_cancel, |
---|
| 1376 | + .internal_flags = BATADV_FLAG_NEED_MESH, |
---|
562 | 1377 | }, |
---|
563 | 1378 | { |
---|
564 | 1379 | .cmd = BATADV_CMD_GET_ROUTING_ALGOS, |
---|
565 | | - .flags = GENL_ADMIN_PERM, |
---|
566 | | - .policy = batadv_netlink_policy, |
---|
| 1380 | + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, |
---|
| 1381 | + .flags = GENL_UNS_ADMIN_PERM, |
---|
567 | 1382 | .dumpit = batadv_algo_dump, |
---|
568 | 1383 | }, |
---|
569 | 1384 | { |
---|
570 | | - .cmd = BATADV_CMD_GET_HARDIFS, |
---|
571 | | - .flags = GENL_ADMIN_PERM, |
---|
572 | | - .policy = batadv_netlink_policy, |
---|
573 | | - .dumpit = batadv_netlink_dump_hardifs, |
---|
| 1385 | + .cmd = BATADV_CMD_GET_HARDIF, |
---|
| 1386 | + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, |
---|
| 1387 | + /* can be retrieved by unprivileged users */ |
---|
| 1388 | + .dumpit = batadv_netlink_dump_hardif, |
---|
| 1389 | + .doit = batadv_netlink_get_hardif, |
---|
| 1390 | + .internal_flags = BATADV_FLAG_NEED_MESH | |
---|
| 1391 | + BATADV_FLAG_NEED_HARDIF, |
---|
574 | 1392 | }, |
---|
575 | 1393 | { |
---|
576 | 1394 | .cmd = BATADV_CMD_GET_TRANSTABLE_LOCAL, |
---|
577 | | - .flags = GENL_ADMIN_PERM, |
---|
578 | | - .policy = batadv_netlink_policy, |
---|
| 1395 | + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, |
---|
| 1396 | + .flags = GENL_UNS_ADMIN_PERM, |
---|
579 | 1397 | .dumpit = batadv_tt_local_dump, |
---|
580 | 1398 | }, |
---|
581 | 1399 | { |
---|
582 | 1400 | .cmd = BATADV_CMD_GET_TRANSTABLE_GLOBAL, |
---|
583 | | - .flags = GENL_ADMIN_PERM, |
---|
584 | | - .policy = batadv_netlink_policy, |
---|
| 1401 | + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, |
---|
| 1402 | + .flags = GENL_UNS_ADMIN_PERM, |
---|
585 | 1403 | .dumpit = batadv_tt_global_dump, |
---|
586 | 1404 | }, |
---|
587 | 1405 | { |
---|
588 | 1406 | .cmd = BATADV_CMD_GET_ORIGINATORS, |
---|
589 | | - .flags = GENL_ADMIN_PERM, |
---|
590 | | - .policy = batadv_netlink_policy, |
---|
| 1407 | + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, |
---|
| 1408 | + .flags = GENL_UNS_ADMIN_PERM, |
---|
591 | 1409 | .dumpit = batadv_orig_dump, |
---|
592 | 1410 | }, |
---|
593 | 1411 | { |
---|
594 | 1412 | .cmd = BATADV_CMD_GET_NEIGHBORS, |
---|
595 | | - .flags = GENL_ADMIN_PERM, |
---|
596 | | - .policy = batadv_netlink_policy, |
---|
| 1413 | + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, |
---|
| 1414 | + .flags = GENL_UNS_ADMIN_PERM, |
---|
597 | 1415 | .dumpit = batadv_hardif_neigh_dump, |
---|
598 | 1416 | }, |
---|
599 | 1417 | { |
---|
600 | 1418 | .cmd = BATADV_CMD_GET_GATEWAYS, |
---|
601 | | - .flags = GENL_ADMIN_PERM, |
---|
602 | | - .policy = batadv_netlink_policy, |
---|
| 1419 | + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, |
---|
| 1420 | + .flags = GENL_UNS_ADMIN_PERM, |
---|
603 | 1421 | .dumpit = batadv_gw_dump, |
---|
604 | 1422 | }, |
---|
605 | 1423 | { |
---|
606 | 1424 | .cmd = BATADV_CMD_GET_BLA_CLAIM, |
---|
607 | | - .flags = GENL_ADMIN_PERM, |
---|
608 | | - .policy = batadv_netlink_policy, |
---|
| 1425 | + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, |
---|
| 1426 | + .flags = GENL_UNS_ADMIN_PERM, |
---|
609 | 1427 | .dumpit = batadv_bla_claim_dump, |
---|
610 | 1428 | }, |
---|
611 | 1429 | { |
---|
612 | 1430 | .cmd = BATADV_CMD_GET_BLA_BACKBONE, |
---|
613 | | - .flags = GENL_ADMIN_PERM, |
---|
614 | | - .policy = batadv_netlink_policy, |
---|
| 1431 | + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, |
---|
| 1432 | + .flags = GENL_UNS_ADMIN_PERM, |
---|
615 | 1433 | .dumpit = batadv_bla_backbone_dump, |
---|
616 | 1434 | }, |
---|
617 | 1435 | { |
---|
618 | 1436 | .cmd = BATADV_CMD_GET_DAT_CACHE, |
---|
619 | | - .flags = GENL_ADMIN_PERM, |
---|
620 | | - .policy = batadv_netlink_policy, |
---|
| 1437 | + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, |
---|
| 1438 | + .flags = GENL_UNS_ADMIN_PERM, |
---|
621 | 1439 | .dumpit = batadv_dat_cache_dump, |
---|
622 | 1440 | }, |
---|
623 | 1441 | { |
---|
624 | 1442 | .cmd = BATADV_CMD_GET_MCAST_FLAGS, |
---|
625 | | - .flags = GENL_ADMIN_PERM, |
---|
626 | | - .policy = batadv_netlink_policy, |
---|
| 1443 | + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, |
---|
| 1444 | + .flags = GENL_UNS_ADMIN_PERM, |
---|
627 | 1445 | .dumpit = batadv_mcast_flags_dump, |
---|
628 | 1446 | }, |
---|
629 | | - |
---|
| 1447 | + { |
---|
| 1448 | + .cmd = BATADV_CMD_SET_MESH, |
---|
| 1449 | + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, |
---|
| 1450 | + .flags = GENL_UNS_ADMIN_PERM, |
---|
| 1451 | + .doit = batadv_netlink_set_mesh, |
---|
| 1452 | + .internal_flags = BATADV_FLAG_NEED_MESH, |
---|
| 1453 | + }, |
---|
| 1454 | + { |
---|
| 1455 | + .cmd = BATADV_CMD_SET_HARDIF, |
---|
| 1456 | + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, |
---|
| 1457 | + .flags = GENL_UNS_ADMIN_PERM, |
---|
| 1458 | + .doit = batadv_netlink_set_hardif, |
---|
| 1459 | + .internal_flags = BATADV_FLAG_NEED_MESH | |
---|
| 1460 | + BATADV_FLAG_NEED_HARDIF, |
---|
| 1461 | + }, |
---|
| 1462 | + { |
---|
| 1463 | + .cmd = BATADV_CMD_GET_VLAN, |
---|
| 1464 | + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, |
---|
| 1465 | + /* can be retrieved by unprivileged users */ |
---|
| 1466 | + .doit = batadv_netlink_get_vlan, |
---|
| 1467 | + .internal_flags = BATADV_FLAG_NEED_MESH | |
---|
| 1468 | + BATADV_FLAG_NEED_VLAN, |
---|
| 1469 | + }, |
---|
| 1470 | + { |
---|
| 1471 | + .cmd = BATADV_CMD_SET_VLAN, |
---|
| 1472 | + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, |
---|
| 1473 | + .flags = GENL_UNS_ADMIN_PERM, |
---|
| 1474 | + .doit = batadv_netlink_set_vlan, |
---|
| 1475 | + .internal_flags = BATADV_FLAG_NEED_MESH | |
---|
| 1476 | + BATADV_FLAG_NEED_VLAN, |
---|
| 1477 | + }, |
---|
630 | 1478 | }; |
---|
631 | 1479 | |
---|
632 | 1480 | struct genl_family batadv_netlink_family __ro_after_init = { |
---|
.. | .. |
---|
634 | 1482 | .name = BATADV_NL_NAME, |
---|
635 | 1483 | .version = 1, |
---|
636 | 1484 | .maxattr = BATADV_ATTR_MAX, |
---|
| 1485 | + .policy = batadv_netlink_policy, |
---|
637 | 1486 | .netnsok = true, |
---|
| 1487 | + .pre_doit = batadv_pre_doit, |
---|
| 1488 | + .post_doit = batadv_post_doit, |
---|
638 | 1489 | .module = THIS_MODULE, |
---|
639 | | - .ops = batadv_netlink_ops, |
---|
640 | | - .n_ops = ARRAY_SIZE(batadv_netlink_ops), |
---|
| 1490 | + .small_ops = batadv_netlink_ops, |
---|
| 1491 | + .n_small_ops = ARRAY_SIZE(batadv_netlink_ops), |
---|
641 | 1492 | .mcgrps = batadv_netlink_mcgrps, |
---|
642 | 1493 | .n_mcgrps = ARRAY_SIZE(batadv_netlink_mcgrps), |
---|
643 | 1494 | }; |
---|