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