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