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