Merge tag 'drm-msm-fixes-2021-06-10' of https://gitlab.freedesktop.org/drm/msm into...
[linux-2.6-microblaze.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         if (primary_if)
363                 batadv_hardif_put(primary_if);
364
365         genlmsg_end(msg, hdr);
366         return 0;
367
368 nla_put_failure:
369         if (primary_if)
370                 batadv_hardif_put(primary_if);
371
372         genlmsg_cancel(msg, hdr);
373         return -EMSGSIZE;
374 }
375
376 /**
377  * batadv_netlink_notify_mesh() - send softif attributes to listener
378  * @bat_priv: the bat priv with all the soft interface information
379  *
380  * Return: 0 on success, < 0 on error
381  */
382 int batadv_netlink_notify_mesh(struct batadv_priv *bat_priv)
383 {
384         struct sk_buff *msg;
385         int ret;
386
387         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
388         if (!msg)
389                 return -ENOMEM;
390
391         ret = batadv_netlink_mesh_fill(msg, bat_priv, BATADV_CMD_SET_MESH,
392                                        0, 0, 0);
393         if (ret < 0) {
394                 nlmsg_free(msg);
395                 return ret;
396         }
397
398         genlmsg_multicast_netns(&batadv_netlink_family,
399                                 dev_net(bat_priv->soft_iface), msg, 0,
400                                 BATADV_NL_MCGRP_CONFIG, GFP_KERNEL);
401
402         return 0;
403 }
404
405 /**
406  * batadv_netlink_get_mesh() - Get softif attributes
407  * @skb: Netlink message with request data
408  * @info: receiver information
409  *
410  * Return: 0 on success or negative error number in case of failure
411  */
412 static int batadv_netlink_get_mesh(struct sk_buff *skb, struct genl_info *info)
413 {
414         struct batadv_priv *bat_priv = info->user_ptr[0];
415         struct sk_buff *msg;
416         int ret;
417
418         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
419         if (!msg)
420                 return -ENOMEM;
421
422         ret = batadv_netlink_mesh_fill(msg, bat_priv, BATADV_CMD_GET_MESH,
423                                        info->snd_portid, info->snd_seq, 0);
424         if (ret < 0) {
425                 nlmsg_free(msg);
426                 return ret;
427         }
428
429         ret = genlmsg_reply(msg, info);
430
431         return ret;
432 }
433
434 /**
435  * batadv_netlink_set_mesh() - Set softif attributes
436  * @skb: Netlink message with request data
437  * @info: receiver information
438  *
439  * Return: 0 on success or negative error number in case of failure
440  */
441 static int batadv_netlink_set_mesh(struct sk_buff *skb, struct genl_info *info)
442 {
443         struct batadv_priv *bat_priv = info->user_ptr[0];
444         struct nlattr *attr;
445
446         if (info->attrs[BATADV_ATTR_AGGREGATED_OGMS_ENABLED]) {
447                 attr = info->attrs[BATADV_ATTR_AGGREGATED_OGMS_ENABLED];
448
449                 atomic_set(&bat_priv->aggregated_ogms, !!nla_get_u8(attr));
450         }
451
452         if (info->attrs[BATADV_ATTR_AP_ISOLATION_ENABLED]) {
453                 attr = info->attrs[BATADV_ATTR_AP_ISOLATION_ENABLED];
454
455                 batadv_netlink_set_mesh_ap_isolation(attr, bat_priv);
456         }
457
458         if (info->attrs[BATADV_ATTR_ISOLATION_MARK]) {
459                 attr = info->attrs[BATADV_ATTR_ISOLATION_MARK];
460
461                 bat_priv->isolation_mark = nla_get_u32(attr);
462         }
463
464         if (info->attrs[BATADV_ATTR_ISOLATION_MASK]) {
465                 attr = info->attrs[BATADV_ATTR_ISOLATION_MASK];
466
467                 bat_priv->isolation_mark_mask = nla_get_u32(attr);
468         }
469
470         if (info->attrs[BATADV_ATTR_BONDING_ENABLED]) {
471                 attr = info->attrs[BATADV_ATTR_BONDING_ENABLED];
472
473                 atomic_set(&bat_priv->bonding, !!nla_get_u8(attr));
474         }
475
476 #ifdef CONFIG_BATMAN_ADV_BLA
477         if (info->attrs[BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE_ENABLED]) {
478                 attr = info->attrs[BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE_ENABLED];
479
480                 atomic_set(&bat_priv->bridge_loop_avoidance,
481                            !!nla_get_u8(attr));
482                 batadv_bla_status_update(bat_priv->soft_iface);
483         }
484 #endif /* CONFIG_BATMAN_ADV_BLA */
485
486 #ifdef CONFIG_BATMAN_ADV_DAT
487         if (info->attrs[BATADV_ATTR_DISTRIBUTED_ARP_TABLE_ENABLED]) {
488                 attr = info->attrs[BATADV_ATTR_DISTRIBUTED_ARP_TABLE_ENABLED];
489
490                 atomic_set(&bat_priv->distributed_arp_table,
491                            !!nla_get_u8(attr));
492                 batadv_dat_status_update(bat_priv->soft_iface);
493         }
494 #endif /* CONFIG_BATMAN_ADV_DAT */
495
496         if (info->attrs[BATADV_ATTR_FRAGMENTATION_ENABLED]) {
497                 attr = info->attrs[BATADV_ATTR_FRAGMENTATION_ENABLED];
498
499                 atomic_set(&bat_priv->fragmentation, !!nla_get_u8(attr));
500                 batadv_update_min_mtu(bat_priv->soft_iface);
501         }
502
503         if (info->attrs[BATADV_ATTR_GW_BANDWIDTH_DOWN]) {
504                 attr = info->attrs[BATADV_ATTR_GW_BANDWIDTH_DOWN];
505
506                 atomic_set(&bat_priv->gw.bandwidth_down, nla_get_u32(attr));
507                 batadv_gw_tvlv_container_update(bat_priv);
508         }
509
510         if (info->attrs[BATADV_ATTR_GW_BANDWIDTH_UP]) {
511                 attr = info->attrs[BATADV_ATTR_GW_BANDWIDTH_UP];
512
513                 atomic_set(&bat_priv->gw.bandwidth_up, nla_get_u32(attr));
514                 batadv_gw_tvlv_container_update(bat_priv);
515         }
516
517         if (info->attrs[BATADV_ATTR_GW_MODE]) {
518                 u8 gw_mode;
519
520                 attr = info->attrs[BATADV_ATTR_GW_MODE];
521                 gw_mode = nla_get_u8(attr);
522
523                 if (gw_mode <= BATADV_GW_MODE_SERVER) {
524                         /* Invoking batadv_gw_reselect() is not enough to really
525                          * de-select the current GW. It will only instruct the
526                          * gateway client code to perform a re-election the next
527                          * time that this is needed.
528                          *
529                          * When gw client mode is being switched off the current
530                          * GW must be de-selected explicitly otherwise no GW_ADD
531                          * uevent is thrown on client mode re-activation. This
532                          * is operation is performed in
533                          * batadv_gw_check_client_stop().
534                          */
535                         batadv_gw_reselect(bat_priv);
536
537                         /* always call batadv_gw_check_client_stop() before
538                          * changing the gateway state
539                          */
540                         batadv_gw_check_client_stop(bat_priv);
541                         atomic_set(&bat_priv->gw.mode, gw_mode);
542                         batadv_gw_tvlv_container_update(bat_priv);
543                 }
544         }
545
546         if (info->attrs[BATADV_ATTR_GW_SEL_CLASS] &&
547             bat_priv->algo_ops->gw.get_best_gw_node &&
548             bat_priv->algo_ops->gw.is_eligible) {
549                 /* setting the GW selection class is allowed only if the routing
550                  * algorithm in use implements the GW API
551                  */
552
553                 u32 sel_class_max = 0xffffffffu;
554                 u32 sel_class;
555
556                 attr = info->attrs[BATADV_ATTR_GW_SEL_CLASS];
557                 sel_class = nla_get_u32(attr);
558
559                 if (!bat_priv->algo_ops->gw.store_sel_class)
560                         sel_class_max = BATADV_TQ_MAX_VALUE;
561
562                 if (sel_class >= 1 && sel_class <= sel_class_max) {
563                         atomic_set(&bat_priv->gw.sel_class, sel_class);
564                         batadv_gw_reselect(bat_priv);
565                 }
566         }
567
568         if (info->attrs[BATADV_ATTR_HOP_PENALTY]) {
569                 attr = info->attrs[BATADV_ATTR_HOP_PENALTY];
570
571                 atomic_set(&bat_priv->hop_penalty, nla_get_u8(attr));
572         }
573
574 #ifdef CONFIG_BATMAN_ADV_DEBUG
575         if (info->attrs[BATADV_ATTR_LOG_LEVEL]) {
576                 attr = info->attrs[BATADV_ATTR_LOG_LEVEL];
577
578                 atomic_set(&bat_priv->log_level,
579                            nla_get_u32(attr) & BATADV_DBG_ALL);
580         }
581 #endif /* CONFIG_BATMAN_ADV_DEBUG */
582
583 #ifdef CONFIG_BATMAN_ADV_MCAST
584         if (info->attrs[BATADV_ATTR_MULTICAST_FORCEFLOOD_ENABLED]) {
585                 attr = info->attrs[BATADV_ATTR_MULTICAST_FORCEFLOOD_ENABLED];
586
587                 atomic_set(&bat_priv->multicast_mode, !nla_get_u8(attr));
588         }
589
590         if (info->attrs[BATADV_ATTR_MULTICAST_FANOUT]) {
591                 attr = info->attrs[BATADV_ATTR_MULTICAST_FANOUT];
592
593                 atomic_set(&bat_priv->multicast_fanout, nla_get_u32(attr));
594         }
595 #endif /* CONFIG_BATMAN_ADV_MCAST */
596
597 #ifdef CONFIG_BATMAN_ADV_NC
598         if (info->attrs[BATADV_ATTR_NETWORK_CODING_ENABLED]) {
599                 attr = info->attrs[BATADV_ATTR_NETWORK_CODING_ENABLED];
600
601                 atomic_set(&bat_priv->network_coding, !!nla_get_u8(attr));
602                 batadv_nc_status_update(bat_priv->soft_iface);
603         }
604 #endif /* CONFIG_BATMAN_ADV_NC */
605
606         if (info->attrs[BATADV_ATTR_ORIG_INTERVAL]) {
607                 u32 orig_interval;
608
609                 attr = info->attrs[BATADV_ATTR_ORIG_INTERVAL];
610                 orig_interval = nla_get_u32(attr);
611
612                 orig_interval = min_t(u32, orig_interval, INT_MAX);
613                 orig_interval = max_t(u32, orig_interval, 2 * BATADV_JITTER);
614
615                 atomic_set(&bat_priv->orig_interval, orig_interval);
616         }
617
618         batadv_netlink_notify_mesh(bat_priv);
619
620         return 0;
621 }
622
623 /**
624  * batadv_netlink_tp_meter_put() - Fill information of started tp_meter session
625  * @msg: netlink message to be sent back
626  * @cookie: tp meter session cookie
627  *
628  *  Return: 0 on success, < 0 on error
629  */
630 static int
631 batadv_netlink_tp_meter_put(struct sk_buff *msg, u32 cookie)
632 {
633         if (nla_put_u32(msg, BATADV_ATTR_TPMETER_COOKIE, cookie))
634                 return -ENOBUFS;
635
636         return 0;
637 }
638
639 /**
640  * batadv_netlink_tpmeter_notify() - send tp_meter result via netlink to client
641  * @bat_priv: the bat priv with all the soft interface information
642  * @dst: destination of tp_meter session
643  * @result: reason for tp meter session stop
644  * @test_time: total time of the tp_meter session
645  * @total_bytes: bytes acked to the receiver
646  * @cookie: cookie of tp_meter session
647  *
648  * Return: 0 on success, < 0 on error
649  */
650 int batadv_netlink_tpmeter_notify(struct batadv_priv *bat_priv, const u8 *dst,
651                                   u8 result, u32 test_time, u64 total_bytes,
652                                   u32 cookie)
653 {
654         struct sk_buff *msg;
655         void *hdr;
656         int ret;
657
658         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
659         if (!msg)
660                 return -ENOMEM;
661
662         hdr = genlmsg_put(msg, 0, 0, &batadv_netlink_family, 0,
663                           BATADV_CMD_TP_METER);
664         if (!hdr) {
665                 ret = -ENOBUFS;
666                 goto err_genlmsg;
667         }
668
669         if (nla_put_u32(msg, BATADV_ATTR_TPMETER_COOKIE, cookie))
670                 goto nla_put_failure;
671
672         if (nla_put_u32(msg, BATADV_ATTR_TPMETER_TEST_TIME, test_time))
673                 goto nla_put_failure;
674
675         if (nla_put_u64_64bit(msg, BATADV_ATTR_TPMETER_BYTES, total_bytes,
676                               BATADV_ATTR_PAD))
677                 goto nla_put_failure;
678
679         if (nla_put_u8(msg, BATADV_ATTR_TPMETER_RESULT, result))
680                 goto nla_put_failure;
681
682         if (nla_put(msg, BATADV_ATTR_ORIG_ADDRESS, ETH_ALEN, dst))
683                 goto nla_put_failure;
684
685         genlmsg_end(msg, hdr);
686
687         genlmsg_multicast_netns(&batadv_netlink_family,
688                                 dev_net(bat_priv->soft_iface), msg, 0,
689                                 BATADV_NL_MCGRP_TPMETER, GFP_KERNEL);
690
691         return 0;
692
693 nla_put_failure:
694         genlmsg_cancel(msg, hdr);
695         ret = -EMSGSIZE;
696
697 err_genlmsg:
698         nlmsg_free(msg);
699         return ret;
700 }
701
702 /**
703  * batadv_netlink_tp_meter_start() - Start a new tp_meter session
704  * @skb: received netlink message
705  * @info: receiver information
706  *
707  * Return: 0 on success, < 0 on error
708  */
709 static int
710 batadv_netlink_tp_meter_start(struct sk_buff *skb, struct genl_info *info)
711 {
712         struct batadv_priv *bat_priv = info->user_ptr[0];
713         struct sk_buff *msg = NULL;
714         u32 test_length;
715         void *msg_head;
716         u32 cookie;
717         u8 *dst;
718         int ret;
719
720         if (!info->attrs[BATADV_ATTR_ORIG_ADDRESS])
721                 return -EINVAL;
722
723         if (!info->attrs[BATADV_ATTR_TPMETER_TEST_TIME])
724                 return -EINVAL;
725
726         dst = nla_data(info->attrs[BATADV_ATTR_ORIG_ADDRESS]);
727
728         test_length = nla_get_u32(info->attrs[BATADV_ATTR_TPMETER_TEST_TIME]);
729
730         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
731         if (!msg) {
732                 ret = -ENOMEM;
733                 goto out;
734         }
735
736         msg_head = genlmsg_put(msg, info->snd_portid, info->snd_seq,
737                                &batadv_netlink_family, 0,
738                                BATADV_CMD_TP_METER);
739         if (!msg_head) {
740                 ret = -ENOBUFS;
741                 goto out;
742         }
743
744         batadv_tp_start(bat_priv, dst, test_length, &cookie);
745
746         ret = batadv_netlink_tp_meter_put(msg, cookie);
747
748  out:
749         if (ret) {
750                 if (msg)
751                         nlmsg_free(msg);
752                 return ret;
753         }
754
755         genlmsg_end(msg, msg_head);
756         return genlmsg_reply(msg, info);
757 }
758
759 /**
760  * batadv_netlink_tp_meter_cancel() - Cancel a running tp_meter session
761  * @skb: received netlink message
762  * @info: receiver information
763  *
764  * Return: 0 on success, < 0 on error
765  */
766 static int
767 batadv_netlink_tp_meter_cancel(struct sk_buff *skb, struct genl_info *info)
768 {
769         struct batadv_priv *bat_priv = info->user_ptr[0];
770         u8 *dst;
771         int ret = 0;
772
773         if (!info->attrs[BATADV_ATTR_ORIG_ADDRESS])
774                 return -EINVAL;
775
776         dst = nla_data(info->attrs[BATADV_ATTR_ORIG_ADDRESS]);
777
778         batadv_tp_stop(bat_priv, dst, BATADV_TP_REASON_CANCEL);
779
780         return ret;
781 }
782
783 /**
784  * batadv_netlink_hardif_fill() - Fill message with hardif attributes
785  * @msg: Netlink message to dump into
786  * @bat_priv: the bat priv with all the soft interface information
787  * @hard_iface: hard interface which was modified
788  * @cmd: type of message to generate
789  * @portid: Port making netlink request
790  * @seq: sequence number for message
791  * @flags: Additional flags for message
792  * @cb: Control block containing additional options
793  *
794  * Return: 0 on success or negative error number in case of failure
795  */
796 static int batadv_netlink_hardif_fill(struct sk_buff *msg,
797                                       struct batadv_priv *bat_priv,
798                                       struct batadv_hard_iface *hard_iface,
799                                       enum batadv_nl_commands cmd,
800                                       u32 portid, u32 seq, int flags,
801                                       struct netlink_callback *cb)
802 {
803         struct net_device *net_dev = hard_iface->net_dev;
804         void *hdr;
805
806         hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, flags, cmd);
807         if (!hdr)
808                 return -ENOBUFS;
809
810         if (cb)
811                 genl_dump_check_consistent(cb, hdr);
812
813         if (nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX,
814                         bat_priv->soft_iface->ifindex))
815                 goto nla_put_failure;
816
817         if (nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX,
818                         net_dev->ifindex) ||
819             nla_put_string(msg, BATADV_ATTR_HARD_IFNAME,
820                            net_dev->name) ||
821             nla_put(msg, BATADV_ATTR_HARD_ADDRESS, ETH_ALEN,
822                     net_dev->dev_addr))
823                 goto nla_put_failure;
824
825         if (hard_iface->if_status == BATADV_IF_ACTIVE) {
826                 if (nla_put_flag(msg, BATADV_ATTR_ACTIVE))
827                         goto nla_put_failure;
828         }
829
830         if (nla_put_u8(msg, BATADV_ATTR_HOP_PENALTY,
831                        atomic_read(&hard_iface->hop_penalty)))
832                 goto nla_put_failure;
833
834 #ifdef CONFIG_BATMAN_ADV_BATMAN_V
835         if (nla_put_u32(msg, BATADV_ATTR_ELP_INTERVAL,
836                         atomic_read(&hard_iface->bat_v.elp_interval)))
837                 goto nla_put_failure;
838
839         if (nla_put_u32(msg, BATADV_ATTR_THROUGHPUT_OVERRIDE,
840                         atomic_read(&hard_iface->bat_v.throughput_override)))
841                 goto nla_put_failure;
842 #endif /* CONFIG_BATMAN_ADV_BATMAN_V */
843
844         genlmsg_end(msg, hdr);
845         return 0;
846
847 nla_put_failure:
848         genlmsg_cancel(msg, hdr);
849         return -EMSGSIZE;
850 }
851
852 /**
853  * batadv_netlink_notify_hardif() - send hardif attributes to listener
854  * @bat_priv: the bat priv with all the soft interface information
855  * @hard_iface: hard interface which was modified
856  *
857  * Return: 0 on success, < 0 on error
858  */
859 int batadv_netlink_notify_hardif(struct batadv_priv *bat_priv,
860                                  struct batadv_hard_iface *hard_iface)
861 {
862         struct sk_buff *msg;
863         int ret;
864
865         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
866         if (!msg)
867                 return -ENOMEM;
868
869         ret = batadv_netlink_hardif_fill(msg, bat_priv, hard_iface,
870                                          BATADV_CMD_SET_HARDIF, 0, 0, 0, NULL);
871         if (ret < 0) {
872                 nlmsg_free(msg);
873                 return ret;
874         }
875
876         genlmsg_multicast_netns(&batadv_netlink_family,
877                                 dev_net(bat_priv->soft_iface), msg, 0,
878                                 BATADV_NL_MCGRP_CONFIG, GFP_KERNEL);
879
880         return 0;
881 }
882
883 /**
884  * batadv_netlink_get_hardif() - Get hardif attributes
885  * @skb: Netlink message with request data
886  * @info: receiver information
887  *
888  * Return: 0 on success or negative error number in case of failure
889  */
890 static int batadv_netlink_get_hardif(struct sk_buff *skb,
891                                      struct genl_info *info)
892 {
893         struct batadv_hard_iface *hard_iface = info->user_ptr[1];
894         struct batadv_priv *bat_priv = info->user_ptr[0];
895         struct sk_buff *msg;
896         int ret;
897
898         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
899         if (!msg)
900                 return -ENOMEM;
901
902         ret = batadv_netlink_hardif_fill(msg, bat_priv, hard_iface,
903                                          BATADV_CMD_GET_HARDIF,
904                                          info->snd_portid, info->snd_seq, 0,
905                                          NULL);
906         if (ret < 0) {
907                 nlmsg_free(msg);
908                 return ret;
909         }
910
911         ret = genlmsg_reply(msg, info);
912
913         return ret;
914 }
915
916 /**
917  * batadv_netlink_set_hardif() - Set hardif attributes
918  * @skb: Netlink message with request data
919  * @info: receiver information
920  *
921  * Return: 0 on success or negative error number in case of failure
922  */
923 static int batadv_netlink_set_hardif(struct sk_buff *skb,
924                                      struct genl_info *info)
925 {
926         struct batadv_hard_iface *hard_iface = info->user_ptr[1];
927         struct batadv_priv *bat_priv = info->user_ptr[0];
928         struct nlattr *attr;
929
930         if (info->attrs[BATADV_ATTR_HOP_PENALTY]) {
931                 attr = info->attrs[BATADV_ATTR_HOP_PENALTY];
932
933                 atomic_set(&hard_iface->hop_penalty, nla_get_u8(attr));
934         }
935
936 #ifdef CONFIG_BATMAN_ADV_BATMAN_V
937
938         if (info->attrs[BATADV_ATTR_ELP_INTERVAL]) {
939                 attr = info->attrs[BATADV_ATTR_ELP_INTERVAL];
940
941                 atomic_set(&hard_iface->bat_v.elp_interval, nla_get_u32(attr));
942         }
943
944         if (info->attrs[BATADV_ATTR_THROUGHPUT_OVERRIDE]) {
945                 attr = info->attrs[BATADV_ATTR_THROUGHPUT_OVERRIDE];
946
947                 atomic_set(&hard_iface->bat_v.throughput_override,
948                            nla_get_u32(attr));
949         }
950 #endif /* CONFIG_BATMAN_ADV_BATMAN_V */
951
952         batadv_netlink_notify_hardif(bat_priv, hard_iface);
953
954         return 0;
955 }
956
957 /**
958  * batadv_netlink_dump_hardif() - Dump all hard interface into a messages
959  * @msg: Netlink message to dump into
960  * @cb: Parameters from query
961  *
962  * Return: error code, or length of reply message on success
963  */
964 static int
965 batadv_netlink_dump_hardif(struct sk_buff *msg, struct netlink_callback *cb)
966 {
967         struct net *net = sock_net(cb->skb->sk);
968         struct net_device *soft_iface;
969         struct batadv_hard_iface *hard_iface;
970         struct batadv_priv *bat_priv;
971         int ifindex;
972         int portid = NETLINK_CB(cb->skb).portid;
973         int skip = cb->args[0];
974         int i = 0;
975
976         ifindex = batadv_netlink_get_ifindex(cb->nlh,
977                                              BATADV_ATTR_MESH_IFINDEX);
978         if (!ifindex)
979                 return -EINVAL;
980
981         soft_iface = dev_get_by_index(net, ifindex);
982         if (!soft_iface)
983                 return -ENODEV;
984
985         if (!batadv_softif_is_valid(soft_iface)) {
986                 dev_put(soft_iface);
987                 return -ENODEV;
988         }
989
990         bat_priv = netdev_priv(soft_iface);
991
992         rtnl_lock();
993         cb->seq = batadv_hardif_generation << 1 | 1;
994
995         list_for_each_entry(hard_iface, &batadv_hardif_list, list) {
996                 if (hard_iface->soft_iface != soft_iface)
997                         continue;
998
999                 if (i++ < skip)
1000                         continue;
1001
1002                 if (batadv_netlink_hardif_fill(msg, bat_priv, hard_iface,
1003                                                BATADV_CMD_GET_HARDIF,
1004                                                portid, cb->nlh->nlmsg_seq,
1005                                                NLM_F_MULTI, cb)) {
1006                         i--;
1007                         break;
1008                 }
1009         }
1010
1011         rtnl_unlock();
1012
1013         dev_put(soft_iface);
1014
1015         cb->args[0] = i;
1016
1017         return msg->len;
1018 }
1019
1020 /**
1021  * batadv_netlink_vlan_fill() - Fill message with vlan attributes
1022  * @msg: Netlink message to dump into
1023  * @bat_priv: the bat priv with all the soft interface information
1024  * @vlan: vlan which was modified
1025  * @cmd: type of message to generate
1026  * @portid: Port making netlink request
1027  * @seq: sequence number for message
1028  * @flags: Additional flags for message
1029  *
1030  * Return: 0 on success or negative error number in case of failure
1031  */
1032 static int batadv_netlink_vlan_fill(struct sk_buff *msg,
1033                                     struct batadv_priv *bat_priv,
1034                                     struct batadv_softif_vlan *vlan,
1035                                     enum batadv_nl_commands cmd,
1036                                     u32 portid, u32 seq, int flags)
1037 {
1038         void *hdr;
1039
1040         hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, flags, cmd);
1041         if (!hdr)
1042                 return -ENOBUFS;
1043
1044         if (nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX,
1045                         bat_priv->soft_iface->ifindex))
1046                 goto nla_put_failure;
1047
1048         if (nla_put_u32(msg, BATADV_ATTR_VLANID, vlan->vid & VLAN_VID_MASK))
1049                 goto nla_put_failure;
1050
1051         if (nla_put_u8(msg, BATADV_ATTR_AP_ISOLATION_ENABLED,
1052                        !!atomic_read(&vlan->ap_isolation)))
1053                 goto nla_put_failure;
1054
1055         genlmsg_end(msg, hdr);
1056         return 0;
1057
1058 nla_put_failure:
1059         genlmsg_cancel(msg, hdr);
1060         return -EMSGSIZE;
1061 }
1062
1063 /**
1064  * batadv_netlink_notify_vlan() - send vlan attributes to listener
1065  * @bat_priv: the bat priv with all the soft interface information
1066  * @vlan: vlan which was modified
1067  *
1068  * Return: 0 on success, < 0 on error
1069  */
1070 int batadv_netlink_notify_vlan(struct batadv_priv *bat_priv,
1071                                struct batadv_softif_vlan *vlan)
1072 {
1073         struct sk_buff *msg;
1074         int ret;
1075
1076         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1077         if (!msg)
1078                 return -ENOMEM;
1079
1080         ret = batadv_netlink_vlan_fill(msg, bat_priv, vlan,
1081                                        BATADV_CMD_SET_VLAN, 0, 0, 0);
1082         if (ret < 0) {
1083                 nlmsg_free(msg);
1084                 return ret;
1085         }
1086
1087         genlmsg_multicast_netns(&batadv_netlink_family,
1088                                 dev_net(bat_priv->soft_iface), msg, 0,
1089                                 BATADV_NL_MCGRP_CONFIG, GFP_KERNEL);
1090
1091         return 0;
1092 }
1093
1094 /**
1095  * batadv_netlink_get_vlan() - Get vlan attributes
1096  * @skb: Netlink message with request data
1097  * @info: receiver information
1098  *
1099  * Return: 0 on success or negative error number in case of failure
1100  */
1101 static int batadv_netlink_get_vlan(struct sk_buff *skb, struct genl_info *info)
1102 {
1103         struct batadv_softif_vlan *vlan = info->user_ptr[1];
1104         struct batadv_priv *bat_priv = info->user_ptr[0];
1105         struct sk_buff *msg;
1106         int ret;
1107
1108         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1109         if (!msg)
1110                 return -ENOMEM;
1111
1112         ret = batadv_netlink_vlan_fill(msg, bat_priv, vlan, BATADV_CMD_GET_VLAN,
1113                                        info->snd_portid, info->snd_seq, 0);
1114         if (ret < 0) {
1115                 nlmsg_free(msg);
1116                 return ret;
1117         }
1118
1119         ret = genlmsg_reply(msg, info);
1120
1121         return ret;
1122 }
1123
1124 /**
1125  * batadv_netlink_set_vlan() - Get vlan attributes
1126  * @skb: Netlink message with request data
1127  * @info: receiver information
1128  *
1129  * Return: 0 on success or negative error number in case of failure
1130  */
1131 static int batadv_netlink_set_vlan(struct sk_buff *skb, struct genl_info *info)
1132 {
1133         struct batadv_softif_vlan *vlan = info->user_ptr[1];
1134         struct batadv_priv *bat_priv = info->user_ptr[0];
1135         struct nlattr *attr;
1136
1137         if (info->attrs[BATADV_ATTR_AP_ISOLATION_ENABLED]) {
1138                 attr = info->attrs[BATADV_ATTR_AP_ISOLATION_ENABLED];
1139
1140                 atomic_set(&vlan->ap_isolation, !!nla_get_u8(attr));
1141         }
1142
1143         batadv_netlink_notify_vlan(bat_priv, vlan);
1144
1145         return 0;
1146 }
1147
1148 /**
1149  * batadv_get_softif_from_info() - Retrieve soft interface from genl attributes
1150  * @net: the applicable net namespace
1151  * @info: receiver information
1152  *
1153  * Return: Pointer to soft interface (with increased refcnt) on success, error
1154  *  pointer on error
1155  */
1156 static struct net_device *
1157 batadv_get_softif_from_info(struct net *net, struct genl_info *info)
1158 {
1159         struct net_device *soft_iface;
1160         int ifindex;
1161
1162         if (!info->attrs[BATADV_ATTR_MESH_IFINDEX])
1163                 return ERR_PTR(-EINVAL);
1164
1165         ifindex = nla_get_u32(info->attrs[BATADV_ATTR_MESH_IFINDEX]);
1166
1167         soft_iface = dev_get_by_index(net, ifindex);
1168         if (!soft_iface)
1169                 return ERR_PTR(-ENODEV);
1170
1171         if (!batadv_softif_is_valid(soft_iface))
1172                 goto err_put_softif;
1173
1174         return soft_iface;
1175
1176 err_put_softif:
1177         dev_put(soft_iface);
1178
1179         return ERR_PTR(-EINVAL);
1180 }
1181
1182 /**
1183  * batadv_get_hardif_from_info() - Retrieve hardif from genl attributes
1184  * @bat_priv: the bat priv with all the soft interface information
1185  * @net: the applicable net namespace
1186  * @info: receiver information
1187  *
1188  * Return: Pointer to hard interface (with increased refcnt) on success, error
1189  *  pointer on error
1190  */
1191 static struct batadv_hard_iface *
1192 batadv_get_hardif_from_info(struct batadv_priv *bat_priv, struct net *net,
1193                             struct genl_info *info)
1194 {
1195         struct batadv_hard_iface *hard_iface;
1196         struct net_device *hard_dev;
1197         unsigned int hardif_index;
1198
1199         if (!info->attrs[BATADV_ATTR_HARD_IFINDEX])
1200                 return ERR_PTR(-EINVAL);
1201
1202         hardif_index = nla_get_u32(info->attrs[BATADV_ATTR_HARD_IFINDEX]);
1203
1204         hard_dev = dev_get_by_index(net, hardif_index);
1205         if (!hard_dev)
1206                 return ERR_PTR(-ENODEV);
1207
1208         hard_iface = batadv_hardif_get_by_netdev(hard_dev);
1209         if (!hard_iface)
1210                 goto err_put_harddev;
1211
1212         if (hard_iface->soft_iface != bat_priv->soft_iface)
1213                 goto err_put_hardif;
1214
1215         /* hard_dev is referenced by hard_iface and not needed here */
1216         dev_put(hard_dev);
1217
1218         return hard_iface;
1219
1220 err_put_hardif:
1221         batadv_hardif_put(hard_iface);
1222 err_put_harddev:
1223         dev_put(hard_dev);
1224
1225         return ERR_PTR(-EINVAL);
1226 }
1227
1228 /**
1229  * batadv_get_vlan_from_info() - Retrieve vlan from genl attributes
1230  * @bat_priv: the bat priv with all the soft interface information
1231  * @net: the applicable net namespace
1232  * @info: receiver information
1233  *
1234  * Return: Pointer to vlan on success (with increased refcnt), error pointer
1235  *  on error
1236  */
1237 static struct batadv_softif_vlan *
1238 batadv_get_vlan_from_info(struct batadv_priv *bat_priv, struct net *net,
1239                           struct genl_info *info)
1240 {
1241         struct batadv_softif_vlan *vlan;
1242         u16 vid;
1243
1244         if (!info->attrs[BATADV_ATTR_VLANID])
1245                 return ERR_PTR(-EINVAL);
1246
1247         vid = nla_get_u16(info->attrs[BATADV_ATTR_VLANID]);
1248
1249         vlan = batadv_softif_vlan_get(bat_priv, vid | BATADV_VLAN_HAS_TAG);
1250         if (!vlan)
1251                 return ERR_PTR(-ENOENT);
1252
1253         return vlan;
1254 }
1255
1256 /**
1257  * batadv_pre_doit() - Prepare batman-adv genl doit request
1258  * @ops: requested netlink operation
1259  * @skb: Netlink message with request data
1260  * @info: receiver information
1261  *
1262  * Return: 0 on success or negative error number in case of failure
1263  */
1264 static int batadv_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
1265                            struct genl_info *info)
1266 {
1267         struct net *net = genl_info_net(info);
1268         struct batadv_hard_iface *hard_iface;
1269         struct batadv_priv *bat_priv = NULL;
1270         struct batadv_softif_vlan *vlan;
1271         struct net_device *soft_iface;
1272         u8 user_ptr1_flags;
1273         u8 mesh_dep_flags;
1274         int ret;
1275
1276         user_ptr1_flags = BATADV_FLAG_NEED_HARDIF | BATADV_FLAG_NEED_VLAN;
1277         if (WARN_ON(hweight8(ops->internal_flags & user_ptr1_flags) > 1))
1278                 return -EINVAL;
1279
1280         mesh_dep_flags = BATADV_FLAG_NEED_HARDIF | BATADV_FLAG_NEED_VLAN;
1281         if (WARN_ON((ops->internal_flags & mesh_dep_flags) &&
1282                     (~ops->internal_flags & BATADV_FLAG_NEED_MESH)))
1283                 return -EINVAL;
1284
1285         if (ops->internal_flags & BATADV_FLAG_NEED_MESH) {
1286                 soft_iface = batadv_get_softif_from_info(net, info);
1287                 if (IS_ERR(soft_iface))
1288                         return PTR_ERR(soft_iface);
1289
1290                 bat_priv = netdev_priv(soft_iface);
1291                 info->user_ptr[0] = bat_priv;
1292         }
1293
1294         if (ops->internal_flags & BATADV_FLAG_NEED_HARDIF) {
1295                 hard_iface = batadv_get_hardif_from_info(bat_priv, net, info);
1296                 if (IS_ERR(hard_iface)) {
1297                         ret = PTR_ERR(hard_iface);
1298                         goto err_put_softif;
1299                 }
1300
1301                 info->user_ptr[1] = hard_iface;
1302         }
1303
1304         if (ops->internal_flags & BATADV_FLAG_NEED_VLAN) {
1305                 vlan = batadv_get_vlan_from_info(bat_priv, net, info);
1306                 if (IS_ERR(vlan)) {
1307                         ret = PTR_ERR(vlan);
1308                         goto err_put_softif;
1309                 }
1310
1311                 info->user_ptr[1] = vlan;
1312         }
1313
1314         return 0;
1315
1316 err_put_softif:
1317         if (bat_priv)
1318                 dev_put(bat_priv->soft_iface);
1319
1320         return ret;
1321 }
1322
1323 /**
1324  * batadv_post_doit() - End batman-adv genl doit request
1325  * @ops: requested netlink operation
1326  * @skb: Netlink message with request data
1327  * @info: receiver information
1328  */
1329 static void batadv_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
1330                              struct genl_info *info)
1331 {
1332         struct batadv_hard_iface *hard_iface;
1333         struct batadv_softif_vlan *vlan;
1334         struct batadv_priv *bat_priv;
1335
1336         if (ops->internal_flags & BATADV_FLAG_NEED_HARDIF &&
1337             info->user_ptr[1]) {
1338                 hard_iface = info->user_ptr[1];
1339
1340                 batadv_hardif_put(hard_iface);
1341         }
1342
1343         if (ops->internal_flags & BATADV_FLAG_NEED_VLAN && info->user_ptr[1]) {
1344                 vlan = info->user_ptr[1];
1345                 batadv_softif_vlan_put(vlan);
1346         }
1347
1348         if (ops->internal_flags & BATADV_FLAG_NEED_MESH && info->user_ptr[0]) {
1349                 bat_priv = info->user_ptr[0];
1350                 dev_put(bat_priv->soft_iface);
1351         }
1352 }
1353
1354 static const struct genl_small_ops batadv_netlink_ops[] = {
1355         {
1356                 .cmd = BATADV_CMD_GET_MESH,
1357                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1358                 /* can be retrieved by unprivileged users */
1359                 .doit = batadv_netlink_get_mesh,
1360                 .internal_flags = BATADV_FLAG_NEED_MESH,
1361         },
1362         {
1363                 .cmd = BATADV_CMD_TP_METER,
1364                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1365                 .flags = GENL_ADMIN_PERM,
1366                 .doit = batadv_netlink_tp_meter_start,
1367                 .internal_flags = BATADV_FLAG_NEED_MESH,
1368         },
1369         {
1370                 .cmd = BATADV_CMD_TP_METER_CANCEL,
1371                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1372                 .flags = GENL_ADMIN_PERM,
1373                 .doit = batadv_netlink_tp_meter_cancel,
1374                 .internal_flags = BATADV_FLAG_NEED_MESH,
1375         },
1376         {
1377                 .cmd = BATADV_CMD_GET_ROUTING_ALGOS,
1378                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1379                 .flags = GENL_ADMIN_PERM,
1380                 .dumpit = batadv_algo_dump,
1381         },
1382         {
1383                 .cmd = BATADV_CMD_GET_HARDIF,
1384                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1385                 /* can be retrieved by unprivileged users */
1386                 .dumpit = batadv_netlink_dump_hardif,
1387                 .doit = batadv_netlink_get_hardif,
1388                 .internal_flags = BATADV_FLAG_NEED_MESH |
1389                                   BATADV_FLAG_NEED_HARDIF,
1390         },
1391         {
1392                 .cmd = BATADV_CMD_GET_TRANSTABLE_LOCAL,
1393                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1394                 .flags = GENL_ADMIN_PERM,
1395                 .dumpit = batadv_tt_local_dump,
1396         },
1397         {
1398                 .cmd = BATADV_CMD_GET_TRANSTABLE_GLOBAL,
1399                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1400                 .flags = GENL_ADMIN_PERM,
1401                 .dumpit = batadv_tt_global_dump,
1402         },
1403         {
1404                 .cmd = BATADV_CMD_GET_ORIGINATORS,
1405                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1406                 .flags = GENL_ADMIN_PERM,
1407                 .dumpit = batadv_orig_dump,
1408         },
1409         {
1410                 .cmd = BATADV_CMD_GET_NEIGHBORS,
1411                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1412                 .flags = GENL_ADMIN_PERM,
1413                 .dumpit = batadv_hardif_neigh_dump,
1414         },
1415         {
1416                 .cmd = BATADV_CMD_GET_GATEWAYS,
1417                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1418                 .flags = GENL_ADMIN_PERM,
1419                 .dumpit = batadv_gw_dump,
1420         },
1421         {
1422                 .cmd = BATADV_CMD_GET_BLA_CLAIM,
1423                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1424                 .flags = GENL_ADMIN_PERM,
1425                 .dumpit = batadv_bla_claim_dump,
1426         },
1427         {
1428                 .cmd = BATADV_CMD_GET_BLA_BACKBONE,
1429                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1430                 .flags = GENL_ADMIN_PERM,
1431                 .dumpit = batadv_bla_backbone_dump,
1432         },
1433         {
1434                 .cmd = BATADV_CMD_GET_DAT_CACHE,
1435                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1436                 .flags = GENL_ADMIN_PERM,
1437                 .dumpit = batadv_dat_cache_dump,
1438         },
1439         {
1440                 .cmd = BATADV_CMD_GET_MCAST_FLAGS,
1441                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1442                 .flags = GENL_ADMIN_PERM,
1443                 .dumpit = batadv_mcast_flags_dump,
1444         },
1445         {
1446                 .cmd = BATADV_CMD_SET_MESH,
1447                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1448                 .flags = GENL_ADMIN_PERM,
1449                 .doit = batadv_netlink_set_mesh,
1450                 .internal_flags = BATADV_FLAG_NEED_MESH,
1451         },
1452         {
1453                 .cmd = BATADV_CMD_SET_HARDIF,
1454                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1455                 .flags = GENL_ADMIN_PERM,
1456                 .doit = batadv_netlink_set_hardif,
1457                 .internal_flags = BATADV_FLAG_NEED_MESH |
1458                                   BATADV_FLAG_NEED_HARDIF,
1459         },
1460         {
1461                 .cmd = BATADV_CMD_GET_VLAN,
1462                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1463                 /* can be retrieved by unprivileged users */
1464                 .doit = batadv_netlink_get_vlan,
1465                 .internal_flags = BATADV_FLAG_NEED_MESH |
1466                                   BATADV_FLAG_NEED_VLAN,
1467         },
1468         {
1469                 .cmd = BATADV_CMD_SET_VLAN,
1470                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1471                 .flags = GENL_ADMIN_PERM,
1472                 .doit = batadv_netlink_set_vlan,
1473                 .internal_flags = BATADV_FLAG_NEED_MESH |
1474                                   BATADV_FLAG_NEED_VLAN,
1475         },
1476 };
1477
1478 struct genl_family batadv_netlink_family __ro_after_init = {
1479         .hdrsize = 0,
1480         .name = BATADV_NL_NAME,
1481         .version = 1,
1482         .maxattr = BATADV_ATTR_MAX,
1483         .policy = batadv_netlink_policy,
1484         .netnsok = true,
1485         .pre_doit = batadv_pre_doit,
1486         .post_doit = batadv_post_doit,
1487         .module = THIS_MODULE,
1488         .small_ops = batadv_netlink_ops,
1489         .n_small_ops = ARRAY_SIZE(batadv_netlink_ops),
1490         .mcgrps = batadv_netlink_mcgrps,
1491         .n_mcgrps = ARRAY_SIZE(batadv_netlink_mcgrps),
1492 };
1493
1494 /**
1495  * batadv_netlink_register() - register batadv genl netlink family
1496  */
1497 void __init batadv_netlink_register(void)
1498 {
1499         int ret;
1500
1501         ret = genl_register_family(&batadv_netlink_family);
1502         if (ret)
1503                 pr_warn("unable to register netlink family");
1504 }
1505
1506 /**
1507  * batadv_netlink_unregister() - unregister batadv genl netlink family
1508  */
1509 void batadv_netlink_unregister(void)
1510 {
1511         genl_unregister_family(&batadv_netlink_family);
1512 }