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