1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (C) B.A.T.M.A.N. contributors:
10 #include <linux/array_size.h>
11 #include <linux/atomic.h>
12 #include <linux/bitops.h>
13 #include <linux/bug.h>
14 #include <linux/byteorder/generic.h>
15 #include <linux/cache.h>
16 #include <linux/err.h>
17 #include <linux/errno.h>
18 #include <linux/gfp.h>
19 #include <linux/if_ether.h>
20 #include <linux/if_vlan.h>
21 #include <linux/init.h>
22 #include <linux/limits.h>
23 #include <linux/list.h>
24 #include <linux/minmax.h>
25 #include <linux/netdevice.h>
26 #include <linux/netlink.h>
27 #include <linux/printk.h>
28 #include <linux/rtnetlink.h>
29 #include <linux/skbuff.h>
30 #include <linux/stddef.h>
31 #include <linux/types.h>
32 #include <net/genetlink.h>
33 #include <net/net_namespace.h>
34 #include <net/netlink.h>
36 #include <uapi/linux/batadv_packet.h>
37 #include <uapi/linux/batman_adv.h>
40 #include "bridge_loop_avoidance.h"
41 #include "distributed-arp-table.h"
42 #include "gateway_client.h"
43 #include "gateway_common.h"
44 #include "hard-interface.h"
46 #include "multicast.h"
47 #include "network-coding.h"
48 #include "originator.h"
49 #include "soft-interface.h"
51 #include "translation-table.h"
53 struct genl_family batadv_netlink_family
;
55 /* multicast groups */
56 enum batadv_netlink_multicast_groups
{
57 BATADV_NL_MCGRP_CONFIG
,
58 BATADV_NL_MCGRP_TPMETER
,
62 * enum batadv_genl_ops_flags - flags for genl_ops's internal_flags
64 enum batadv_genl_ops_flags
{
66 * @BATADV_FLAG_NEED_MESH: request requires valid soft interface in
67 * attribute BATADV_ATTR_MESH_IFINDEX and expects a pointer to it to be
68 * saved in info->user_ptr[0]
70 BATADV_FLAG_NEED_MESH
= BIT(0),
73 * @BATADV_FLAG_NEED_HARDIF: request requires valid hard interface in
74 * attribute BATADV_ATTR_HARD_IFINDEX and expects a pointer to it to be
75 * saved in info->user_ptr[1]
77 BATADV_FLAG_NEED_HARDIF
= BIT(1),
80 * @BATADV_FLAG_NEED_VLAN: request requires valid vlan in
81 * attribute BATADV_ATTR_VLANID and expects a pointer to it to be
82 * saved in info->user_ptr[1]
84 BATADV_FLAG_NEED_VLAN
= BIT(2),
87 static const struct genl_multicast_group batadv_netlink_mcgrps
[] = {
88 [BATADV_NL_MCGRP_CONFIG
] = { .name
= BATADV_NL_MCAST_GROUP_CONFIG
},
89 [BATADV_NL_MCGRP_TPMETER
] = { .name
= BATADV_NL_MCAST_GROUP_TPMETER
},
92 static const struct nla_policy batadv_netlink_policy
[NUM_BATADV_ATTR
] = {
93 [BATADV_ATTR_VERSION
] = { .type
= NLA_STRING
},
94 [BATADV_ATTR_ALGO_NAME
] = { .type
= NLA_STRING
},
95 [BATADV_ATTR_MESH_IFINDEX
] = { .type
= NLA_U32
},
96 [BATADV_ATTR_MESH_IFNAME
] = { .type
= NLA_STRING
},
97 [BATADV_ATTR_MESH_ADDRESS
] = { .len
= ETH_ALEN
},
98 [BATADV_ATTR_HARD_IFINDEX
] = { .type
= NLA_U32
},
99 [BATADV_ATTR_HARD_IFNAME
] = { .type
= NLA_STRING
},
100 [BATADV_ATTR_HARD_ADDRESS
] = { .len
= ETH_ALEN
},
101 [BATADV_ATTR_ORIG_ADDRESS
] = { .len
= ETH_ALEN
},
102 [BATADV_ATTR_TPMETER_RESULT
] = { .type
= NLA_U8
},
103 [BATADV_ATTR_TPMETER_TEST_TIME
] = { .type
= NLA_U32
},
104 [BATADV_ATTR_TPMETER_BYTES
] = { .type
= NLA_U64
},
105 [BATADV_ATTR_TPMETER_COOKIE
] = { .type
= NLA_U32
},
106 [BATADV_ATTR_ACTIVE
] = { .type
= NLA_FLAG
},
107 [BATADV_ATTR_TT_ADDRESS
] = { .len
= ETH_ALEN
},
108 [BATADV_ATTR_TT_TTVN
] = { .type
= NLA_U8
},
109 [BATADV_ATTR_TT_LAST_TTVN
] = { .type
= NLA_U8
},
110 [BATADV_ATTR_TT_CRC32
] = { .type
= NLA_U32
},
111 [BATADV_ATTR_TT_VID
] = { .type
= NLA_U16
},
112 [BATADV_ATTR_TT_FLAGS
] = { .type
= NLA_U32
},
113 [BATADV_ATTR_FLAG_BEST
] = { .type
= NLA_FLAG
},
114 [BATADV_ATTR_LAST_SEEN_MSECS
] = { .type
= NLA_U32
},
115 [BATADV_ATTR_NEIGH_ADDRESS
] = { .len
= ETH_ALEN
},
116 [BATADV_ATTR_TQ
] = { .type
= NLA_U8
},
117 [BATADV_ATTR_THROUGHPUT
] = { .type
= NLA_U32
},
118 [BATADV_ATTR_BANDWIDTH_UP
] = { .type
= NLA_U32
},
119 [BATADV_ATTR_BANDWIDTH_DOWN
] = { .type
= NLA_U32
},
120 [BATADV_ATTR_ROUTER
] = { .len
= ETH_ALEN
},
121 [BATADV_ATTR_BLA_OWN
] = { .type
= NLA_FLAG
},
122 [BATADV_ATTR_BLA_ADDRESS
] = { .len
= ETH_ALEN
},
123 [BATADV_ATTR_BLA_VID
] = { .type
= NLA_U16
},
124 [BATADV_ATTR_BLA_BACKBONE
] = { .len
= ETH_ALEN
},
125 [BATADV_ATTR_BLA_CRC
] = { .type
= NLA_U16
},
126 [BATADV_ATTR_DAT_CACHE_IP4ADDRESS
] = { .type
= NLA_U32
},
127 [BATADV_ATTR_DAT_CACHE_HWADDRESS
] = { .len
= ETH_ALEN
},
128 [BATADV_ATTR_DAT_CACHE_VID
] = { .type
= NLA_U16
},
129 [BATADV_ATTR_MCAST_FLAGS
] = { .type
= NLA_U32
},
130 [BATADV_ATTR_MCAST_FLAGS_PRIV
] = { .type
= NLA_U32
},
131 [BATADV_ATTR_VLANID
] = { .type
= NLA_U16
},
132 [BATADV_ATTR_AGGREGATED_OGMS_ENABLED
] = { .type
= NLA_U8
},
133 [BATADV_ATTR_AP_ISOLATION_ENABLED
] = { .type
= NLA_U8
},
134 [BATADV_ATTR_ISOLATION_MARK
] = { .type
= NLA_U32
},
135 [BATADV_ATTR_ISOLATION_MASK
] = { .type
= NLA_U32
},
136 [BATADV_ATTR_BONDING_ENABLED
] = { .type
= NLA_U8
},
137 [BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE_ENABLED
] = { .type
= NLA_U8
},
138 [BATADV_ATTR_DISTRIBUTED_ARP_TABLE_ENABLED
] = { .type
= NLA_U8
},
139 [BATADV_ATTR_FRAGMENTATION_ENABLED
] = { .type
= NLA_U8
},
140 [BATADV_ATTR_GW_BANDWIDTH_DOWN
] = { .type
= NLA_U32
},
141 [BATADV_ATTR_GW_BANDWIDTH_UP
] = { .type
= NLA_U32
},
142 [BATADV_ATTR_GW_MODE
] = { .type
= NLA_U8
},
143 [BATADV_ATTR_GW_SEL_CLASS
] = { .type
= NLA_U32
},
144 [BATADV_ATTR_HOP_PENALTY
] = { .type
= NLA_U8
},
145 [BATADV_ATTR_LOG_LEVEL
] = { .type
= NLA_U32
},
146 [BATADV_ATTR_MULTICAST_FORCEFLOOD_ENABLED
] = { .type
= NLA_U8
},
147 [BATADV_ATTR_MULTICAST_FANOUT
] = { .type
= NLA_U32
},
148 [BATADV_ATTR_NETWORK_CODING_ENABLED
] = { .type
= NLA_U8
},
149 [BATADV_ATTR_ORIG_INTERVAL
] = { .type
= NLA_U32
},
150 [BATADV_ATTR_ELP_INTERVAL
] = { .type
= NLA_U32
},
151 [BATADV_ATTR_THROUGHPUT_OVERRIDE
] = { .type
= NLA_U32
},
155 * batadv_netlink_get_ifindex() - Extract an interface index from a message
156 * @nlh: Message header
157 * @attrtype: Attribute which holds an interface index
159 * Return: interface index, or 0.
161 static int batadv_netlink_get_ifindex(const struct nlmsghdr
*nlh
, int attrtype
)
163 struct nlattr
*attr
= nlmsg_find_attr(nlh
, GENL_HDRLEN
, attrtype
);
165 return (attr
&& nla_len(attr
) == sizeof(u32
)) ? nla_get_u32(attr
) : 0;
169 * batadv_netlink_mesh_fill_ap_isolation() - Add ap_isolation softif attribute
170 * @msg: Netlink message to dump into
171 * @bat_priv: the bat priv with all the soft interface information
173 * Return: 0 on success or negative error number in case of failure
175 static int batadv_netlink_mesh_fill_ap_isolation(struct sk_buff
*msg
,
176 struct batadv_priv
*bat_priv
)
178 struct batadv_softif_vlan
*vlan
;
181 vlan
= batadv_softif_vlan_get(bat_priv
, BATADV_NO_FLAGS
);
185 ap_isolation
= atomic_read(&vlan
->ap_isolation
);
186 batadv_softif_vlan_put(vlan
);
188 return nla_put_u8(msg
, BATADV_ATTR_AP_ISOLATION_ENABLED
,
193 * batadv_netlink_set_mesh_ap_isolation() - Set ap_isolation from genl msg
194 * @attr: parsed BATADV_ATTR_AP_ISOLATION_ENABLED attribute
195 * @bat_priv: the bat priv with all the soft interface information
197 * Return: 0 on success or negative error number in case of failure
199 static int batadv_netlink_set_mesh_ap_isolation(struct nlattr
*attr
,
200 struct batadv_priv
*bat_priv
)
202 struct batadv_softif_vlan
*vlan
;
204 vlan
= batadv_softif_vlan_get(bat_priv
, BATADV_NO_FLAGS
);
208 atomic_set(&vlan
->ap_isolation
, !!nla_get_u8(attr
));
209 batadv_softif_vlan_put(vlan
);
215 * batadv_netlink_mesh_fill() - Fill message with mesh attributes
216 * @msg: Netlink message to dump into
217 * @bat_priv: the bat priv with all the soft interface information
218 * @cmd: type of message to generate
219 * @portid: Port making netlink request
220 * @seq: sequence number for message
221 * @flags: Additional flags for message
223 * Return: 0 on success or negative error number in case of failure
225 static int batadv_netlink_mesh_fill(struct sk_buff
*msg
,
226 struct batadv_priv
*bat_priv
,
227 enum batadv_nl_commands cmd
,
228 u32 portid
, u32 seq
, int flags
)
230 struct net_device
*soft_iface
= bat_priv
->soft_iface
;
231 struct batadv_hard_iface
*primary_if
= NULL
;
232 struct net_device
*hard_iface
;
235 hdr
= genlmsg_put(msg
, portid
, seq
, &batadv_netlink_family
, flags
, cmd
);
239 if (nla_put_string(msg
, BATADV_ATTR_VERSION
, BATADV_SOURCE_VERSION
) ||
240 nla_put_string(msg
, BATADV_ATTR_ALGO_NAME
,
241 bat_priv
->algo_ops
->name
) ||
242 nla_put_u32(msg
, BATADV_ATTR_MESH_IFINDEX
, soft_iface
->ifindex
) ||
243 nla_put_string(msg
, BATADV_ATTR_MESH_IFNAME
, soft_iface
->name
) ||
244 nla_put(msg
, BATADV_ATTR_MESH_ADDRESS
, ETH_ALEN
,
245 soft_iface
->dev_addr
) ||
246 nla_put_u8(msg
, BATADV_ATTR_TT_TTVN
,
247 (u8
)atomic_read(&bat_priv
->tt
.vn
)))
248 goto nla_put_failure
;
250 #ifdef CONFIG_BATMAN_ADV_BLA
251 if (nla_put_u16(msg
, BATADV_ATTR_BLA_CRC
,
252 ntohs(bat_priv
->bla
.claim_dest
.group
)))
253 goto nla_put_failure
;
256 if (batadv_mcast_mesh_info_put(msg
, bat_priv
))
257 goto nla_put_failure
;
259 primary_if
= batadv_primary_if_get_selected(bat_priv
);
260 if (primary_if
&& primary_if
->if_status
== BATADV_IF_ACTIVE
) {
261 hard_iface
= primary_if
->net_dev
;
263 if (nla_put_u32(msg
, BATADV_ATTR_HARD_IFINDEX
,
264 hard_iface
->ifindex
) ||
265 nla_put_string(msg
, BATADV_ATTR_HARD_IFNAME
,
267 nla_put(msg
, BATADV_ATTR_HARD_ADDRESS
, ETH_ALEN
,
268 hard_iface
->dev_addr
))
269 goto nla_put_failure
;
272 if (nla_put_u8(msg
, BATADV_ATTR_AGGREGATED_OGMS_ENABLED
,
273 !!atomic_read(&bat_priv
->aggregated_ogms
)))
274 goto nla_put_failure
;
276 if (batadv_netlink_mesh_fill_ap_isolation(msg
, bat_priv
))
277 goto nla_put_failure
;
279 if (nla_put_u32(msg
, BATADV_ATTR_ISOLATION_MARK
,
280 bat_priv
->isolation_mark
))
281 goto nla_put_failure
;
283 if (nla_put_u32(msg
, BATADV_ATTR_ISOLATION_MASK
,
284 bat_priv
->isolation_mark_mask
))
285 goto nla_put_failure
;
287 if (nla_put_u8(msg
, BATADV_ATTR_BONDING_ENABLED
,
288 !!atomic_read(&bat_priv
->bonding
)))
289 goto nla_put_failure
;
291 #ifdef CONFIG_BATMAN_ADV_BLA
292 if (nla_put_u8(msg
, BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE_ENABLED
,
293 !!atomic_read(&bat_priv
->bridge_loop_avoidance
)))
294 goto nla_put_failure
;
295 #endif /* CONFIG_BATMAN_ADV_BLA */
297 #ifdef CONFIG_BATMAN_ADV_DAT
298 if (nla_put_u8(msg
, BATADV_ATTR_DISTRIBUTED_ARP_TABLE_ENABLED
,
299 !!atomic_read(&bat_priv
->distributed_arp_table
)))
300 goto nla_put_failure
;
301 #endif /* CONFIG_BATMAN_ADV_DAT */
303 if (nla_put_u8(msg
, BATADV_ATTR_FRAGMENTATION_ENABLED
,
304 !!atomic_read(&bat_priv
->fragmentation
)))
305 goto nla_put_failure
;
307 if (nla_put_u32(msg
, BATADV_ATTR_GW_BANDWIDTH_DOWN
,
308 atomic_read(&bat_priv
->gw
.bandwidth_down
)))
309 goto nla_put_failure
;
311 if (nla_put_u32(msg
, BATADV_ATTR_GW_BANDWIDTH_UP
,
312 atomic_read(&bat_priv
->gw
.bandwidth_up
)))
313 goto nla_put_failure
;
315 if (nla_put_u8(msg
, BATADV_ATTR_GW_MODE
,
316 atomic_read(&bat_priv
->gw
.mode
)))
317 goto nla_put_failure
;
319 if (bat_priv
->algo_ops
->gw
.get_best_gw_node
&&
320 bat_priv
->algo_ops
->gw
.is_eligible
) {
321 /* GW selection class is not available if the routing algorithm
322 * in use does not implement the GW API
324 if (nla_put_u32(msg
, BATADV_ATTR_GW_SEL_CLASS
,
325 atomic_read(&bat_priv
->gw
.sel_class
)))
326 goto nla_put_failure
;
329 if (nla_put_u8(msg
, BATADV_ATTR_HOP_PENALTY
,
330 atomic_read(&bat_priv
->hop_penalty
)))
331 goto nla_put_failure
;
333 #ifdef CONFIG_BATMAN_ADV_DEBUG
334 if (nla_put_u32(msg
, BATADV_ATTR_LOG_LEVEL
,
335 atomic_read(&bat_priv
->log_level
)))
336 goto nla_put_failure
;
337 #endif /* CONFIG_BATMAN_ADV_DEBUG */
339 #ifdef CONFIG_BATMAN_ADV_MCAST
340 if (nla_put_u8(msg
, BATADV_ATTR_MULTICAST_FORCEFLOOD_ENABLED
,
341 !atomic_read(&bat_priv
->multicast_mode
)))
342 goto nla_put_failure
;
344 if (nla_put_u32(msg
, BATADV_ATTR_MULTICAST_FANOUT
,
345 atomic_read(&bat_priv
->multicast_fanout
)))
346 goto nla_put_failure
;
347 #endif /* CONFIG_BATMAN_ADV_MCAST */
349 #ifdef CONFIG_BATMAN_ADV_NC
350 if (nla_put_u8(msg
, BATADV_ATTR_NETWORK_CODING_ENABLED
,
351 !!atomic_read(&bat_priv
->network_coding
)))
352 goto nla_put_failure
;
353 #endif /* CONFIG_BATMAN_ADV_NC */
355 if (nla_put_u32(msg
, BATADV_ATTR_ORIG_INTERVAL
,
356 atomic_read(&bat_priv
->orig_interval
)))
357 goto nla_put_failure
;
359 batadv_hardif_put(primary_if
);
361 genlmsg_end(msg
, hdr
);
365 batadv_hardif_put(primary_if
);
367 genlmsg_cancel(msg
, hdr
);
372 * batadv_netlink_notify_mesh() - send softif attributes to listener
373 * @bat_priv: the bat priv with all the soft interface information
375 * Return: 0 on success, < 0 on error
377 static int batadv_netlink_notify_mesh(struct batadv_priv
*bat_priv
)
382 msg
= nlmsg_new(NLMSG_DEFAULT_SIZE
, GFP_KERNEL
);
386 ret
= batadv_netlink_mesh_fill(msg
, bat_priv
, BATADV_CMD_SET_MESH
,
393 genlmsg_multicast_netns(&batadv_netlink_family
,
394 dev_net(bat_priv
->soft_iface
), msg
, 0,
395 BATADV_NL_MCGRP_CONFIG
, GFP_KERNEL
);
401 * batadv_netlink_get_mesh() - Get softif attributes
402 * @skb: Netlink message with request data
403 * @info: receiver information
405 * Return: 0 on success or negative error number in case of failure
407 static int batadv_netlink_get_mesh(struct sk_buff
*skb
, struct genl_info
*info
)
409 struct batadv_priv
*bat_priv
= info
->user_ptr
[0];
413 msg
= nlmsg_new(NLMSG_DEFAULT_SIZE
, GFP_KERNEL
);
417 ret
= batadv_netlink_mesh_fill(msg
, bat_priv
, BATADV_CMD_GET_MESH
,
418 info
->snd_portid
, info
->snd_seq
, 0);
424 ret
= genlmsg_reply(msg
, info
);
430 * batadv_netlink_set_mesh() - Set softif attributes
431 * @skb: Netlink message with request data
432 * @info: receiver information
434 * Return: 0 on success or negative error number in case of failure
436 static int batadv_netlink_set_mesh(struct sk_buff
*skb
, struct genl_info
*info
)
438 struct batadv_priv
*bat_priv
= info
->user_ptr
[0];
441 if (info
->attrs
[BATADV_ATTR_AGGREGATED_OGMS_ENABLED
]) {
442 attr
= info
->attrs
[BATADV_ATTR_AGGREGATED_OGMS_ENABLED
];
444 atomic_set(&bat_priv
->aggregated_ogms
, !!nla_get_u8(attr
));
447 if (info
->attrs
[BATADV_ATTR_AP_ISOLATION_ENABLED
]) {
448 attr
= info
->attrs
[BATADV_ATTR_AP_ISOLATION_ENABLED
];
450 batadv_netlink_set_mesh_ap_isolation(attr
, bat_priv
);
453 if (info
->attrs
[BATADV_ATTR_ISOLATION_MARK
]) {
454 attr
= info
->attrs
[BATADV_ATTR_ISOLATION_MARK
];
456 bat_priv
->isolation_mark
= nla_get_u32(attr
);
459 if (info
->attrs
[BATADV_ATTR_ISOLATION_MASK
]) {
460 attr
= info
->attrs
[BATADV_ATTR_ISOLATION_MASK
];
462 bat_priv
->isolation_mark_mask
= nla_get_u32(attr
);
465 if (info
->attrs
[BATADV_ATTR_BONDING_ENABLED
]) {
466 attr
= info
->attrs
[BATADV_ATTR_BONDING_ENABLED
];
468 atomic_set(&bat_priv
->bonding
, !!nla_get_u8(attr
));
471 #ifdef CONFIG_BATMAN_ADV_BLA
472 if (info
->attrs
[BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE_ENABLED
]) {
473 attr
= info
->attrs
[BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE_ENABLED
];
475 atomic_set(&bat_priv
->bridge_loop_avoidance
,
477 batadv_bla_status_update(bat_priv
->soft_iface
);
479 #endif /* CONFIG_BATMAN_ADV_BLA */
481 #ifdef CONFIG_BATMAN_ADV_DAT
482 if (info
->attrs
[BATADV_ATTR_DISTRIBUTED_ARP_TABLE_ENABLED
]) {
483 attr
= info
->attrs
[BATADV_ATTR_DISTRIBUTED_ARP_TABLE_ENABLED
];
485 atomic_set(&bat_priv
->distributed_arp_table
,
487 batadv_dat_status_update(bat_priv
->soft_iface
);
489 #endif /* CONFIG_BATMAN_ADV_DAT */
491 if (info
->attrs
[BATADV_ATTR_FRAGMENTATION_ENABLED
]) {
492 attr
= info
->attrs
[BATADV_ATTR_FRAGMENTATION_ENABLED
];
494 atomic_set(&bat_priv
->fragmentation
, !!nla_get_u8(attr
));
497 batadv_update_min_mtu(bat_priv
->soft_iface
);
501 if (info
->attrs
[BATADV_ATTR_GW_BANDWIDTH_DOWN
]) {
502 attr
= info
->attrs
[BATADV_ATTR_GW_BANDWIDTH_DOWN
];
504 atomic_set(&bat_priv
->gw
.bandwidth_down
, nla_get_u32(attr
));
505 batadv_gw_tvlv_container_update(bat_priv
);
508 if (info
->attrs
[BATADV_ATTR_GW_BANDWIDTH_UP
]) {
509 attr
= info
->attrs
[BATADV_ATTR_GW_BANDWIDTH_UP
];
511 atomic_set(&bat_priv
->gw
.bandwidth_up
, nla_get_u32(attr
));
512 batadv_gw_tvlv_container_update(bat_priv
);
515 if (info
->attrs
[BATADV_ATTR_GW_MODE
]) {
518 attr
= info
->attrs
[BATADV_ATTR_GW_MODE
];
519 gw_mode
= nla_get_u8(attr
);
521 if (gw_mode
<= BATADV_GW_MODE_SERVER
) {
522 /* Invoking batadv_gw_reselect() is not enough to really
523 * de-select the current GW. It will only instruct the
524 * gateway client code to perform a re-election the next
525 * time that this is needed.
527 * When gw client mode is being switched off the current
528 * GW must be de-selected explicitly otherwise no GW_ADD
529 * uevent is thrown on client mode re-activation. This
530 * is operation is performed in
531 * batadv_gw_check_client_stop().
533 batadv_gw_reselect(bat_priv
);
535 /* always call batadv_gw_check_client_stop() before
536 * changing the gateway state
538 batadv_gw_check_client_stop(bat_priv
);
539 atomic_set(&bat_priv
->gw
.mode
, gw_mode
);
540 batadv_gw_tvlv_container_update(bat_priv
);
544 if (info
->attrs
[BATADV_ATTR_GW_SEL_CLASS
] &&
545 bat_priv
->algo_ops
->gw
.get_best_gw_node
&&
546 bat_priv
->algo_ops
->gw
.is_eligible
) {
547 /* setting the GW selection class is allowed only if the routing
548 * algorithm in use implements the GW API
551 u32 sel_class_max
= bat_priv
->algo_ops
->gw
.sel_class_max
;
554 attr
= info
->attrs
[BATADV_ATTR_GW_SEL_CLASS
];
555 sel_class
= nla_get_u32(attr
);
557 if (sel_class
>= 1 && sel_class
<= sel_class_max
) {
558 atomic_set(&bat_priv
->gw
.sel_class
, sel_class
);
559 batadv_gw_reselect(bat_priv
);
563 if (info
->attrs
[BATADV_ATTR_HOP_PENALTY
]) {
564 attr
= info
->attrs
[BATADV_ATTR_HOP_PENALTY
];
566 atomic_set(&bat_priv
->hop_penalty
, nla_get_u8(attr
));
569 #ifdef CONFIG_BATMAN_ADV_DEBUG
570 if (info
->attrs
[BATADV_ATTR_LOG_LEVEL
]) {
571 attr
= info
->attrs
[BATADV_ATTR_LOG_LEVEL
];
573 atomic_set(&bat_priv
->log_level
,
574 nla_get_u32(attr
) & BATADV_DBG_ALL
);
576 #endif /* CONFIG_BATMAN_ADV_DEBUG */
578 #ifdef CONFIG_BATMAN_ADV_MCAST
579 if (info
->attrs
[BATADV_ATTR_MULTICAST_FORCEFLOOD_ENABLED
]) {
580 attr
= info
->attrs
[BATADV_ATTR_MULTICAST_FORCEFLOOD_ENABLED
];
582 atomic_set(&bat_priv
->multicast_mode
, !nla_get_u8(attr
));
585 if (info
->attrs
[BATADV_ATTR_MULTICAST_FANOUT
]) {
586 attr
= info
->attrs
[BATADV_ATTR_MULTICAST_FANOUT
];
588 atomic_set(&bat_priv
->multicast_fanout
, nla_get_u32(attr
));
590 #endif /* CONFIG_BATMAN_ADV_MCAST */
592 #ifdef CONFIG_BATMAN_ADV_NC
593 if (info
->attrs
[BATADV_ATTR_NETWORK_CODING_ENABLED
]) {
594 attr
= info
->attrs
[BATADV_ATTR_NETWORK_CODING_ENABLED
];
596 atomic_set(&bat_priv
->network_coding
, !!nla_get_u8(attr
));
597 batadv_nc_status_update(bat_priv
->soft_iface
);
599 #endif /* CONFIG_BATMAN_ADV_NC */
601 if (info
->attrs
[BATADV_ATTR_ORIG_INTERVAL
]) {
604 attr
= info
->attrs
[BATADV_ATTR_ORIG_INTERVAL
];
605 orig_interval
= nla_get_u32(attr
);
607 orig_interval
= min_t(u32
, orig_interval
, INT_MAX
);
608 orig_interval
= max_t(u32
, orig_interval
, 2 * BATADV_JITTER
);
610 atomic_set(&bat_priv
->orig_interval
, orig_interval
);
613 batadv_netlink_notify_mesh(bat_priv
);
619 * batadv_netlink_tp_meter_put() - Fill information of started tp_meter session
620 * @msg: netlink message to be sent back
621 * @cookie: tp meter session cookie
623 * Return: 0 on success, < 0 on error
626 batadv_netlink_tp_meter_put(struct sk_buff
*msg
, u32 cookie
)
628 if (nla_put_u32(msg
, BATADV_ATTR_TPMETER_COOKIE
, cookie
))
635 * batadv_netlink_tpmeter_notify() - send tp_meter result via netlink to client
636 * @bat_priv: the bat priv with all the soft interface information
637 * @dst: destination of tp_meter session
638 * @result: reason for tp meter session stop
639 * @test_time: total time of the tp_meter session
640 * @total_bytes: bytes acked to the receiver
641 * @cookie: cookie of tp_meter session
643 * Return: 0 on success, < 0 on error
645 int batadv_netlink_tpmeter_notify(struct batadv_priv
*bat_priv
, const u8
*dst
,
646 u8 result
, u32 test_time
, u64 total_bytes
,
653 msg
= nlmsg_new(NLMSG_DEFAULT_SIZE
, GFP_KERNEL
);
657 hdr
= genlmsg_put(msg
, 0, 0, &batadv_netlink_family
, 0,
658 BATADV_CMD_TP_METER
);
664 if (nla_put_u32(msg
, BATADV_ATTR_TPMETER_COOKIE
, cookie
))
665 goto nla_put_failure
;
667 if (nla_put_u32(msg
, BATADV_ATTR_TPMETER_TEST_TIME
, test_time
))
668 goto nla_put_failure
;
670 if (nla_put_u64_64bit(msg
, BATADV_ATTR_TPMETER_BYTES
, total_bytes
,
672 goto nla_put_failure
;
674 if (nla_put_u8(msg
, BATADV_ATTR_TPMETER_RESULT
, result
))
675 goto nla_put_failure
;
677 if (nla_put(msg
, BATADV_ATTR_ORIG_ADDRESS
, ETH_ALEN
, dst
))
678 goto nla_put_failure
;
680 genlmsg_end(msg
, hdr
);
682 genlmsg_multicast_netns(&batadv_netlink_family
,
683 dev_net(bat_priv
->soft_iface
), msg
, 0,
684 BATADV_NL_MCGRP_TPMETER
, GFP_KERNEL
);
689 genlmsg_cancel(msg
, hdr
);
698 * batadv_netlink_tp_meter_start() - Start a new tp_meter session
699 * @skb: received netlink message
700 * @info: receiver information
702 * Return: 0 on success, < 0 on error
705 batadv_netlink_tp_meter_start(struct sk_buff
*skb
, struct genl_info
*info
)
707 struct batadv_priv
*bat_priv
= info
->user_ptr
[0];
708 struct sk_buff
*msg
= NULL
;
715 if (!info
->attrs
[BATADV_ATTR_ORIG_ADDRESS
])
718 if (!info
->attrs
[BATADV_ATTR_TPMETER_TEST_TIME
])
721 dst
= nla_data(info
->attrs
[BATADV_ATTR_ORIG_ADDRESS
]);
723 test_length
= nla_get_u32(info
->attrs
[BATADV_ATTR_TPMETER_TEST_TIME
]);
725 msg
= nlmsg_new(NLMSG_DEFAULT_SIZE
, GFP_KERNEL
);
731 msg_head
= genlmsg_put(msg
, info
->snd_portid
, info
->snd_seq
,
732 &batadv_netlink_family
, 0,
733 BATADV_CMD_TP_METER
);
739 batadv_tp_start(bat_priv
, dst
, test_length
, &cookie
);
741 ret
= batadv_netlink_tp_meter_put(msg
, cookie
);
750 genlmsg_end(msg
, msg_head
);
751 return genlmsg_reply(msg
, info
);
755 * batadv_netlink_tp_meter_cancel() - Cancel a running tp_meter session
756 * @skb: received netlink message
757 * @info: receiver information
759 * Return: 0 on success, < 0 on error
762 batadv_netlink_tp_meter_cancel(struct sk_buff
*skb
, struct genl_info
*info
)
764 struct batadv_priv
*bat_priv
= info
->user_ptr
[0];
768 if (!info
->attrs
[BATADV_ATTR_ORIG_ADDRESS
])
771 dst
= nla_data(info
->attrs
[BATADV_ATTR_ORIG_ADDRESS
]);
773 batadv_tp_stop(bat_priv
, dst
, BATADV_TP_REASON_CANCEL
);
779 * batadv_netlink_hardif_fill() - Fill message with hardif attributes
780 * @msg: Netlink message to dump into
781 * @bat_priv: the bat priv with all the soft interface information
782 * @hard_iface: hard interface which was modified
783 * @cmd: type of message to generate
784 * @portid: Port making netlink request
785 * @seq: sequence number for message
786 * @flags: Additional flags for message
787 * @cb: Control block containing additional options
789 * Return: 0 on success or negative error number in case of failure
791 static int batadv_netlink_hardif_fill(struct sk_buff
*msg
,
792 struct batadv_priv
*bat_priv
,
793 struct batadv_hard_iface
*hard_iface
,
794 enum batadv_nl_commands cmd
,
795 u32 portid
, u32 seq
, int flags
,
796 struct netlink_callback
*cb
)
798 struct net_device
*net_dev
= hard_iface
->net_dev
;
801 hdr
= genlmsg_put(msg
, portid
, seq
, &batadv_netlink_family
, flags
, cmd
);
806 genl_dump_check_consistent(cb
, hdr
);
808 if (nla_put_u32(msg
, BATADV_ATTR_MESH_IFINDEX
,
809 bat_priv
->soft_iface
->ifindex
))
810 goto nla_put_failure
;
812 if (nla_put_string(msg
, BATADV_ATTR_MESH_IFNAME
,
813 bat_priv
->soft_iface
->name
))
814 goto nla_put_failure
;
816 if (nla_put_u32(msg
, BATADV_ATTR_HARD_IFINDEX
,
818 nla_put_string(msg
, BATADV_ATTR_HARD_IFNAME
,
820 nla_put(msg
, BATADV_ATTR_HARD_ADDRESS
, ETH_ALEN
,
822 goto nla_put_failure
;
824 if (hard_iface
->if_status
== BATADV_IF_ACTIVE
) {
825 if (nla_put_flag(msg
, BATADV_ATTR_ACTIVE
))
826 goto nla_put_failure
;
829 if (nla_put_u8(msg
, BATADV_ATTR_HOP_PENALTY
,
830 atomic_read(&hard_iface
->hop_penalty
)))
831 goto nla_put_failure
;
833 #ifdef CONFIG_BATMAN_ADV_BATMAN_V
834 if (nla_put_u32(msg
, BATADV_ATTR_ELP_INTERVAL
,
835 atomic_read(&hard_iface
->bat_v
.elp_interval
)))
836 goto nla_put_failure
;
838 if (nla_put_u32(msg
, BATADV_ATTR_THROUGHPUT_OVERRIDE
,
839 atomic_read(&hard_iface
->bat_v
.throughput_override
)))
840 goto nla_put_failure
;
841 #endif /* CONFIG_BATMAN_ADV_BATMAN_V */
843 genlmsg_end(msg
, hdr
);
847 genlmsg_cancel(msg
, hdr
);
852 * batadv_netlink_notify_hardif() - send hardif attributes to listener
853 * @bat_priv: the bat priv with all the soft interface information
854 * @hard_iface: hard interface which was modified
856 * Return: 0 on success, < 0 on error
858 static int batadv_netlink_notify_hardif(struct batadv_priv
*bat_priv
,
859 struct batadv_hard_iface
*hard_iface
)
864 msg
= nlmsg_new(NLMSG_DEFAULT_SIZE
, GFP_KERNEL
);
868 ret
= batadv_netlink_hardif_fill(msg
, bat_priv
, hard_iface
,
869 BATADV_CMD_SET_HARDIF
, 0, 0, 0, NULL
);
875 genlmsg_multicast_netns(&batadv_netlink_family
,
876 dev_net(bat_priv
->soft_iface
), msg
, 0,
877 BATADV_NL_MCGRP_CONFIG
, GFP_KERNEL
);
883 * batadv_netlink_cmd_get_hardif() - Get hardif attributes
884 * @skb: Netlink message with request data
885 * @info: receiver information
887 * Return: 0 on success or negative error number in case of failure
889 static int batadv_netlink_cmd_get_hardif(struct sk_buff
*skb
,
890 struct genl_info
*info
)
892 struct batadv_hard_iface
*hard_iface
= info
->user_ptr
[1];
893 struct batadv_priv
*bat_priv
= info
->user_ptr
[0];
897 msg
= nlmsg_new(NLMSG_DEFAULT_SIZE
, GFP_KERNEL
);
901 ret
= batadv_netlink_hardif_fill(msg
, bat_priv
, hard_iface
,
902 BATADV_CMD_GET_HARDIF
,
903 info
->snd_portid
, info
->snd_seq
, 0,
910 ret
= genlmsg_reply(msg
, info
);
916 * batadv_netlink_set_hardif() - Set hardif attributes
917 * @skb: Netlink message with request data
918 * @info: receiver information
920 * Return: 0 on success or negative error number in case of failure
922 static int batadv_netlink_set_hardif(struct sk_buff
*skb
,
923 struct genl_info
*info
)
925 struct batadv_hard_iface
*hard_iface
= info
->user_ptr
[1];
926 struct batadv_priv
*bat_priv
= info
->user_ptr
[0];
929 if (info
->attrs
[BATADV_ATTR_HOP_PENALTY
]) {
930 attr
= info
->attrs
[BATADV_ATTR_HOP_PENALTY
];
932 atomic_set(&hard_iface
->hop_penalty
, nla_get_u8(attr
));
935 #ifdef CONFIG_BATMAN_ADV_BATMAN_V
937 if (info
->attrs
[BATADV_ATTR_ELP_INTERVAL
]) {
938 attr
= info
->attrs
[BATADV_ATTR_ELP_INTERVAL
];
940 atomic_set(&hard_iface
->bat_v
.elp_interval
, nla_get_u32(attr
));
943 if (info
->attrs
[BATADV_ATTR_THROUGHPUT_OVERRIDE
]) {
944 attr
= info
->attrs
[BATADV_ATTR_THROUGHPUT_OVERRIDE
];
946 atomic_set(&hard_iface
->bat_v
.throughput_override
,
949 #endif /* CONFIG_BATMAN_ADV_BATMAN_V */
951 batadv_netlink_notify_hardif(bat_priv
, hard_iface
);
957 * batadv_netlink_dump_hardif() - Dump all hard interface into a messages
958 * @msg: Netlink message to dump into
959 * @cb: Parameters from query
961 * Return: error code, or length of reply message on success
964 batadv_netlink_dump_hardif(struct sk_buff
*msg
, struct netlink_callback
*cb
)
966 struct net_device
*soft_iface
;
967 struct batadv_hard_iface
*hard_iface
;
968 struct batadv_priv
*bat_priv
;
969 int portid
= NETLINK_CB(cb
->skb
).portid
;
970 int skip
= cb
->args
[0];
973 soft_iface
= batadv_netlink_get_softif(cb
);
974 if (IS_ERR(soft_iface
))
975 return PTR_ERR(soft_iface
);
977 bat_priv
= netdev_priv(soft_iface
);
980 cb
->seq
= batadv_hardif_generation
<< 1 | 1;
982 list_for_each_entry(hard_iface
, &batadv_hardif_list
, list
) {
983 if (hard_iface
->soft_iface
!= soft_iface
)
989 if (batadv_netlink_hardif_fill(msg
, bat_priv
, hard_iface
,
990 BATADV_CMD_GET_HARDIF
,
991 portid
, cb
->nlh
->nlmsg_seq
,
1000 dev_put(soft_iface
);
1008 * batadv_netlink_vlan_fill() - Fill message with vlan attributes
1009 * @msg: Netlink message to dump into
1010 * @bat_priv: the bat priv with all the soft interface information
1011 * @vlan: vlan which was modified
1012 * @cmd: type of message to generate
1013 * @portid: Port making netlink request
1014 * @seq: sequence number for message
1015 * @flags: Additional flags for message
1017 * Return: 0 on success or negative error number in case of failure
1019 static int batadv_netlink_vlan_fill(struct sk_buff
*msg
,
1020 struct batadv_priv
*bat_priv
,
1021 struct batadv_softif_vlan
*vlan
,
1022 enum batadv_nl_commands cmd
,
1023 u32 portid
, u32 seq
, int flags
)
1027 hdr
= genlmsg_put(msg
, portid
, seq
, &batadv_netlink_family
, flags
, cmd
);
1031 if (nla_put_u32(msg
, BATADV_ATTR_MESH_IFINDEX
,
1032 bat_priv
->soft_iface
->ifindex
))
1033 goto nla_put_failure
;
1035 if (nla_put_string(msg
, BATADV_ATTR_MESH_IFNAME
,
1036 bat_priv
->soft_iface
->name
))
1037 goto nla_put_failure
;
1039 if (nla_put_u32(msg
, BATADV_ATTR_VLANID
, vlan
->vid
& VLAN_VID_MASK
))
1040 goto nla_put_failure
;
1042 if (nla_put_u8(msg
, BATADV_ATTR_AP_ISOLATION_ENABLED
,
1043 !!atomic_read(&vlan
->ap_isolation
)))
1044 goto nla_put_failure
;
1046 genlmsg_end(msg
, hdr
);
1050 genlmsg_cancel(msg
, hdr
);
1055 * batadv_netlink_notify_vlan() - send vlan attributes to listener
1056 * @bat_priv: the bat priv with all the soft interface information
1057 * @vlan: vlan which was modified
1059 * Return: 0 on success, < 0 on error
1061 static int batadv_netlink_notify_vlan(struct batadv_priv
*bat_priv
,
1062 struct batadv_softif_vlan
*vlan
)
1064 struct sk_buff
*msg
;
1067 msg
= nlmsg_new(NLMSG_DEFAULT_SIZE
, GFP_KERNEL
);
1071 ret
= batadv_netlink_vlan_fill(msg
, bat_priv
, vlan
,
1072 BATADV_CMD_SET_VLAN
, 0, 0, 0);
1078 genlmsg_multicast_netns(&batadv_netlink_family
,
1079 dev_net(bat_priv
->soft_iface
), msg
, 0,
1080 BATADV_NL_MCGRP_CONFIG
, GFP_KERNEL
);
1086 * batadv_netlink_get_vlan() - Get vlan attributes
1087 * @skb: Netlink message with request data
1088 * @info: receiver information
1090 * Return: 0 on success or negative error number in case of failure
1092 static int batadv_netlink_get_vlan(struct sk_buff
*skb
, struct genl_info
*info
)
1094 struct batadv_softif_vlan
*vlan
= info
->user_ptr
[1];
1095 struct batadv_priv
*bat_priv
= info
->user_ptr
[0];
1096 struct sk_buff
*msg
;
1099 msg
= nlmsg_new(NLMSG_DEFAULT_SIZE
, GFP_KERNEL
);
1103 ret
= batadv_netlink_vlan_fill(msg
, bat_priv
, vlan
, BATADV_CMD_GET_VLAN
,
1104 info
->snd_portid
, info
->snd_seq
, 0);
1110 ret
= genlmsg_reply(msg
, info
);
1116 * batadv_netlink_set_vlan() - Get vlan attributes
1117 * @skb: Netlink message with request data
1118 * @info: receiver information
1120 * Return: 0 on success or negative error number in case of failure
1122 static int batadv_netlink_set_vlan(struct sk_buff
*skb
, struct genl_info
*info
)
1124 struct batadv_softif_vlan
*vlan
= info
->user_ptr
[1];
1125 struct batadv_priv
*bat_priv
= info
->user_ptr
[0];
1126 struct nlattr
*attr
;
1128 if (info
->attrs
[BATADV_ATTR_AP_ISOLATION_ENABLED
]) {
1129 attr
= info
->attrs
[BATADV_ATTR_AP_ISOLATION_ENABLED
];
1131 atomic_set(&vlan
->ap_isolation
, !!nla_get_u8(attr
));
1134 batadv_netlink_notify_vlan(bat_priv
, vlan
);
1140 * batadv_netlink_get_softif_from_ifindex() - Get soft-iface from ifindex
1141 * @net: the applicable net namespace
1142 * @ifindex: index of the soft interface
1144 * Return: Pointer to soft interface (with increased refcnt) on success, error
1147 static struct net_device
*
1148 batadv_netlink_get_softif_from_ifindex(struct net
*net
, int ifindex
)
1150 struct net_device
*soft_iface
;
1152 soft_iface
= dev_get_by_index(net
, ifindex
);
1154 return ERR_PTR(-ENODEV
);
1156 if (!batadv_softif_is_valid(soft_iface
))
1157 goto err_put_softif
;
1162 dev_put(soft_iface
);
1164 return ERR_PTR(-EINVAL
);
1168 * batadv_netlink_get_softif_from_info() - Get soft-iface from genl attributes
1169 * @net: the applicable net namespace
1170 * @info: receiver information
1172 * Return: Pointer to soft interface (with increased refcnt) on success, error
1175 static struct net_device
*
1176 batadv_netlink_get_softif_from_info(struct net
*net
, struct genl_info
*info
)
1180 if (!info
->attrs
[BATADV_ATTR_MESH_IFINDEX
])
1181 return ERR_PTR(-EINVAL
);
1183 ifindex
= nla_get_u32(info
->attrs
[BATADV_ATTR_MESH_IFINDEX
]);
1185 return batadv_netlink_get_softif_from_ifindex(net
, ifindex
);
1189 * batadv_netlink_get_softif() - Retrieve soft interface from netlink callback
1190 * @cb: callback structure containing arguments
1192 * Return: Pointer to soft interface (with increased refcnt) on success, error
1195 struct net_device
*batadv_netlink_get_softif(struct netlink_callback
*cb
)
1197 int ifindex
= batadv_netlink_get_ifindex(cb
->nlh
,
1198 BATADV_ATTR_MESH_IFINDEX
);
1200 return ERR_PTR(-ENONET
);
1202 return batadv_netlink_get_softif_from_ifindex(sock_net(cb
->skb
->sk
),
1207 * batadv_netlink_get_hardif_from_ifindex() - Get hard-iface from ifindex
1208 * @bat_priv: the bat priv with all the soft interface information
1209 * @net: the applicable net namespace
1210 * @ifindex: index of the hard interface
1212 * Return: Pointer to hard interface (with increased refcnt) on success, error
1215 static struct batadv_hard_iface
*
1216 batadv_netlink_get_hardif_from_ifindex(struct batadv_priv
*bat_priv
,
1217 struct net
*net
, int ifindex
)
1219 struct batadv_hard_iface
*hard_iface
;
1220 struct net_device
*hard_dev
;
1222 hard_dev
= dev_get_by_index(net
, ifindex
);
1224 return ERR_PTR(-ENODEV
);
1226 hard_iface
= batadv_hardif_get_by_netdev(hard_dev
);
1228 goto err_put_harddev
;
1230 if (hard_iface
->soft_iface
!= bat_priv
->soft_iface
)
1231 goto err_put_hardif
;
1233 /* hard_dev is referenced by hard_iface and not needed here */
1239 batadv_hardif_put(hard_iface
);
1243 return ERR_PTR(-EINVAL
);
1247 * batadv_netlink_get_hardif_from_info() - Get hard-iface from genl attributes
1248 * @bat_priv: the bat priv with all the soft interface information
1249 * @net: the applicable net namespace
1250 * @info: receiver information
1252 * Return: Pointer to hard interface (with increased refcnt) on success, error
1255 static struct batadv_hard_iface
*
1256 batadv_netlink_get_hardif_from_info(struct batadv_priv
*bat_priv
,
1257 struct net
*net
, struct genl_info
*info
)
1261 if (!info
->attrs
[BATADV_ATTR_HARD_IFINDEX
])
1262 return ERR_PTR(-EINVAL
);
1264 ifindex
= nla_get_u32(info
->attrs
[BATADV_ATTR_HARD_IFINDEX
]);
1266 return batadv_netlink_get_hardif_from_ifindex(bat_priv
, net
, ifindex
);
1270 * batadv_netlink_get_hardif() - Retrieve hard interface from netlink callback
1271 * @bat_priv: the bat priv with all the soft interface information
1272 * @cb: callback structure containing arguments
1274 * Return: Pointer to hard interface (with increased refcnt) on success, error
1277 struct batadv_hard_iface
*
1278 batadv_netlink_get_hardif(struct batadv_priv
*bat_priv
,
1279 struct netlink_callback
*cb
)
1281 int ifindex
= batadv_netlink_get_ifindex(cb
->nlh
,
1282 BATADV_ATTR_HARD_IFINDEX
);
1284 return ERR_PTR(-ENONET
);
1286 return batadv_netlink_get_hardif_from_ifindex(bat_priv
,
1287 sock_net(cb
->skb
->sk
),
1292 * batadv_get_vlan_from_info() - Retrieve vlan from genl attributes
1293 * @bat_priv: the bat priv with all the soft interface information
1294 * @net: the applicable net namespace
1295 * @info: receiver information
1297 * Return: Pointer to vlan on success (with increased refcnt), error pointer
1300 static struct batadv_softif_vlan
*
1301 batadv_get_vlan_from_info(struct batadv_priv
*bat_priv
, struct net
*net
,
1302 struct genl_info
*info
)
1304 struct batadv_softif_vlan
*vlan
;
1307 if (!info
->attrs
[BATADV_ATTR_VLANID
])
1308 return ERR_PTR(-EINVAL
);
1310 vid
= nla_get_u16(info
->attrs
[BATADV_ATTR_VLANID
]);
1312 vlan
= batadv_softif_vlan_get(bat_priv
, vid
| BATADV_VLAN_HAS_TAG
);
1314 return ERR_PTR(-ENOENT
);
1320 * batadv_pre_doit() - Prepare batman-adv genl doit request
1321 * @ops: requested netlink operation
1322 * @skb: Netlink message with request data
1323 * @info: receiver information
1325 * Return: 0 on success or negative error number in case of failure
1327 static int batadv_pre_doit(const struct genl_split_ops
*ops
,
1328 struct sk_buff
*skb
,
1329 struct genl_info
*info
)
1331 struct net
*net
= genl_info_net(info
);
1332 struct batadv_hard_iface
*hard_iface
;
1333 struct batadv_priv
*bat_priv
= NULL
;
1334 struct batadv_softif_vlan
*vlan
;
1335 struct net_device
*soft_iface
;
1340 user_ptr1_flags
= BATADV_FLAG_NEED_HARDIF
| BATADV_FLAG_NEED_VLAN
;
1341 if (WARN_ON(hweight8(ops
->internal_flags
& user_ptr1_flags
) > 1))
1344 mesh_dep_flags
= BATADV_FLAG_NEED_HARDIF
| BATADV_FLAG_NEED_VLAN
;
1345 if (WARN_ON((ops
->internal_flags
& mesh_dep_flags
) &&
1346 (~ops
->internal_flags
& BATADV_FLAG_NEED_MESH
)))
1349 if (ops
->internal_flags
& BATADV_FLAG_NEED_MESH
) {
1350 soft_iface
= batadv_netlink_get_softif_from_info(net
, info
);
1351 if (IS_ERR(soft_iface
))
1352 return PTR_ERR(soft_iface
);
1354 bat_priv
= netdev_priv(soft_iface
);
1355 info
->user_ptr
[0] = bat_priv
;
1358 if (ops
->internal_flags
& BATADV_FLAG_NEED_HARDIF
) {
1359 hard_iface
= batadv_netlink_get_hardif_from_info(bat_priv
, net
,
1361 if (IS_ERR(hard_iface
)) {
1362 ret
= PTR_ERR(hard_iface
);
1363 goto err_put_softif
;
1366 info
->user_ptr
[1] = hard_iface
;
1369 if (ops
->internal_flags
& BATADV_FLAG_NEED_VLAN
) {
1370 vlan
= batadv_get_vlan_from_info(bat_priv
, net
, info
);
1372 ret
= PTR_ERR(vlan
);
1373 goto err_put_softif
;
1376 info
->user_ptr
[1] = vlan
;
1383 dev_put(bat_priv
->soft_iface
);
1389 * batadv_post_doit() - End batman-adv genl doit request
1390 * @ops: requested netlink operation
1391 * @skb: Netlink message with request data
1392 * @info: receiver information
1394 static void batadv_post_doit(const struct genl_split_ops
*ops
,
1395 struct sk_buff
*skb
,
1396 struct genl_info
*info
)
1398 struct batadv_hard_iface
*hard_iface
;
1399 struct batadv_softif_vlan
*vlan
;
1400 struct batadv_priv
*bat_priv
;
1402 if (ops
->internal_flags
& BATADV_FLAG_NEED_HARDIF
&&
1403 info
->user_ptr
[1]) {
1404 hard_iface
= info
->user_ptr
[1];
1406 batadv_hardif_put(hard_iface
);
1409 if (ops
->internal_flags
& BATADV_FLAG_NEED_VLAN
&& info
->user_ptr
[1]) {
1410 vlan
= info
->user_ptr
[1];
1411 batadv_softif_vlan_put(vlan
);
1414 if (ops
->internal_flags
& BATADV_FLAG_NEED_MESH
&& info
->user_ptr
[0]) {
1415 bat_priv
= info
->user_ptr
[0];
1416 dev_put(bat_priv
->soft_iface
);
1420 static const struct genl_small_ops batadv_netlink_ops
[] = {
1422 .cmd
= BATADV_CMD_GET_MESH
,
1423 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
1424 /* can be retrieved by unprivileged users */
1425 .doit
= batadv_netlink_get_mesh
,
1426 .internal_flags
= BATADV_FLAG_NEED_MESH
,
1429 .cmd
= BATADV_CMD_TP_METER
,
1430 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
1431 .flags
= GENL_UNS_ADMIN_PERM
,
1432 .doit
= batadv_netlink_tp_meter_start
,
1433 .internal_flags
= BATADV_FLAG_NEED_MESH
,
1436 .cmd
= BATADV_CMD_TP_METER_CANCEL
,
1437 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
1438 .flags
= GENL_UNS_ADMIN_PERM
,
1439 .doit
= batadv_netlink_tp_meter_cancel
,
1440 .internal_flags
= BATADV_FLAG_NEED_MESH
,
1443 .cmd
= BATADV_CMD_GET_ROUTING_ALGOS
,
1444 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
1445 .flags
= GENL_UNS_ADMIN_PERM
,
1446 .dumpit
= batadv_algo_dump
,
1449 .cmd
= BATADV_CMD_GET_HARDIF
,
1450 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
1451 /* can be retrieved by unprivileged users */
1452 .dumpit
= batadv_netlink_dump_hardif
,
1453 .doit
= batadv_netlink_cmd_get_hardif
,
1454 .internal_flags
= BATADV_FLAG_NEED_MESH
|
1455 BATADV_FLAG_NEED_HARDIF
,
1458 .cmd
= BATADV_CMD_GET_TRANSTABLE_LOCAL
,
1459 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
1460 .flags
= GENL_UNS_ADMIN_PERM
,
1461 .dumpit
= batadv_tt_local_dump
,
1464 .cmd
= BATADV_CMD_GET_TRANSTABLE_GLOBAL
,
1465 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
1466 .flags
= GENL_UNS_ADMIN_PERM
,
1467 .dumpit
= batadv_tt_global_dump
,
1470 .cmd
= BATADV_CMD_GET_ORIGINATORS
,
1471 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
1472 .flags
= GENL_UNS_ADMIN_PERM
,
1473 .dumpit
= batadv_orig_dump
,
1476 .cmd
= BATADV_CMD_GET_NEIGHBORS
,
1477 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
1478 .flags
= GENL_UNS_ADMIN_PERM
,
1479 .dumpit
= batadv_hardif_neigh_dump
,
1482 .cmd
= BATADV_CMD_GET_GATEWAYS
,
1483 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
1484 .flags
= GENL_UNS_ADMIN_PERM
,
1485 .dumpit
= batadv_gw_dump
,
1488 .cmd
= BATADV_CMD_GET_BLA_CLAIM
,
1489 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
1490 .flags
= GENL_UNS_ADMIN_PERM
,
1491 .dumpit
= batadv_bla_claim_dump
,
1494 .cmd
= BATADV_CMD_GET_BLA_BACKBONE
,
1495 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
1496 .flags
= GENL_UNS_ADMIN_PERM
,
1497 .dumpit
= batadv_bla_backbone_dump
,
1500 .cmd
= BATADV_CMD_GET_DAT_CACHE
,
1501 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
1502 .flags
= GENL_UNS_ADMIN_PERM
,
1503 .dumpit
= batadv_dat_cache_dump
,
1506 .cmd
= BATADV_CMD_GET_MCAST_FLAGS
,
1507 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
1508 .flags
= GENL_UNS_ADMIN_PERM
,
1509 .dumpit
= batadv_mcast_flags_dump
,
1512 .cmd
= BATADV_CMD_SET_MESH
,
1513 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
1514 .flags
= GENL_UNS_ADMIN_PERM
,
1515 .doit
= batadv_netlink_set_mesh
,
1516 .internal_flags
= BATADV_FLAG_NEED_MESH
,
1519 .cmd
= BATADV_CMD_SET_HARDIF
,
1520 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
1521 .flags
= GENL_UNS_ADMIN_PERM
,
1522 .doit
= batadv_netlink_set_hardif
,
1523 .internal_flags
= BATADV_FLAG_NEED_MESH
|
1524 BATADV_FLAG_NEED_HARDIF
,
1527 .cmd
= BATADV_CMD_GET_VLAN
,
1528 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
1529 /* can be retrieved by unprivileged users */
1530 .doit
= batadv_netlink_get_vlan
,
1531 .internal_flags
= BATADV_FLAG_NEED_MESH
|
1532 BATADV_FLAG_NEED_VLAN
,
1535 .cmd
= BATADV_CMD_SET_VLAN
,
1536 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
1537 .flags
= GENL_UNS_ADMIN_PERM
,
1538 .doit
= batadv_netlink_set_vlan
,
1539 .internal_flags
= BATADV_FLAG_NEED_MESH
|
1540 BATADV_FLAG_NEED_VLAN
,
1544 struct genl_family batadv_netlink_family __ro_after_init
= {
1546 .name
= BATADV_NL_NAME
,
1548 .maxattr
= BATADV_ATTR_MAX
,
1549 .policy
= batadv_netlink_policy
,
1551 .pre_doit
= batadv_pre_doit
,
1552 .post_doit
= batadv_post_doit
,
1553 .module
= THIS_MODULE
,
1554 .small_ops
= batadv_netlink_ops
,
1555 .n_small_ops
= ARRAY_SIZE(batadv_netlink_ops
),
1556 .resv_start_op
= BATADV_CMD_SET_VLAN
+ 1,
1557 .mcgrps
= batadv_netlink_mcgrps
,
1558 .n_mcgrps
= ARRAY_SIZE(batadv_netlink_mcgrps
),
1562 * batadv_netlink_register() - register batadv genl netlink family
1564 void __init
batadv_netlink_register(void)
1568 ret
= genl_register_family(&batadv_netlink_family
);
1570 pr_warn("unable to register netlink family");
1574 * batadv_netlink_unregister() - unregister batadv genl netlink family
1576 void batadv_netlink_unregister(void)
1578 genl_unregister_family(&batadv_netlink_family
);