Skip to content

Commit b60620c

Browse files
neocturnesimonwunderlich
authored andcommitted
batman-adv: netlink: hardif query
BATADV_CMD_GET_HARDIFS will return the list of hardifs (including index, name and MAC address) of all hardifs for a given softif. Signed-off-by: Matthias Schiffer <[email protected]> Signed-off-by: Andrew Lunn <[email protected]> [[email protected]: Reduce the number of changes to BATADV_CMD_GET_HARDIFS, add policy for attributes] Signed-off-by: Sven Eckelmann <[email protected]> Signed-off-by: Simon Wunderlich <[email protected]> Signed-off-by: Marek Lindner <[email protected]>
1 parent 07a3061 commit b60620c

File tree

2 files changed

+130
-2
lines changed

2 files changed

+130
-2
lines changed

include/uapi/linux/batman_adv.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
* @BATADV_ATTR_TPMETER_BYTES: amount of acked bytes during run
4141
* @BATADV_ATTR_TPMETER_COOKIE: session cookie to match tp_meter session
4242
* @BATADV_ATTR_PAD: attribute used for padding for 64-bit alignment
43+
* @BATADV_ATTR_ACTIVE: Flag indicating if the hard interface is active
4344
* @__BATADV_ATTR_AFTER_LAST: internal use
4445
* @NUM_BATADV_ATTR: total number of batadv_nl_attrs available
4546
* @BATADV_ATTR_MAX: highest attribute number currently defined
@@ -60,6 +61,7 @@ enum batadv_nl_attrs {
6061
BATADV_ATTR_TPMETER_BYTES,
6162
BATADV_ATTR_TPMETER_COOKIE,
6263
BATADV_ATTR_PAD,
64+
BATADV_ATTR_ACTIVE,
6365
/* add attributes above here, update the policy in netlink.c */
6466
__BATADV_ATTR_AFTER_LAST,
6567
NUM_BATADV_ATTR = __BATADV_ATTR_AFTER_LAST,
@@ -74,6 +76,7 @@ enum batadv_nl_attrs {
7476
* @BATADV_CMD_TP_METER: Start a tp meter session
7577
* @BATADV_CMD_TP_METER_CANCEL: Cancel a tp meter session
7678
* @BATADV_CMD_GET_ROUTING_ALGOS: Query the list of routing algorithms.
79+
* @BATADV_CMD_GET_HARDIFS: Query list of hard interfaces
7780
* @__BATADV_CMD_AFTER_LAST: internal use
7881
* @BATADV_CMD_MAX: highest used command number
7982
*/
@@ -83,6 +86,7 @@ enum batadv_nl_commands {
8386
BATADV_CMD_TP_METER,
8487
BATADV_CMD_TP_METER_CANCEL,
8588
BATADV_CMD_GET_ROUTING_ALGOS,
89+
BATADV_CMD_GET_HARDIFS,
8690
/* add new commands above here */
8791
__BATADV_CMD_AFTER_LAST,
8892
BATADV_CMD_MAX = __BATADV_CMD_AFTER_LAST - 1

net/batman-adv/netlink.c

Lines changed: 126 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,21 @@
2626
#include <linux/netdevice.h>
2727
#include <linux/netlink.h>
2828
#include <linux/printk.h>
29+
#include <linux/rculist.h>
30+
#include <linux/rcupdate.h>
31+
#include <linux/skbuff.h>
2932
#include <linux/stddef.h>
3033
#include <linux/types.h>
3134
#include <net/genetlink.h>
3235
#include <net/netlink.h>
36+
#include <net/sock.h>
3337
#include <uapi/linux/batman_adv.h>
3438

3539
#include "bat_algo.h"
3640
#include "hard-interface.h"
3741
#include "soft-interface.h"
3842
#include "tp_meter.h"
3943

40-
struct sk_buff;
41-
4244
struct genl_family batadv_netlink_family = {
4345
.id = GENL_ID_GENERATE,
4446
.hdrsize = 0,
@@ -70,8 +72,24 @@ static struct nla_policy batadv_netlink_policy[NUM_BATADV_ATTR] = {
7072
[BATADV_ATTR_TPMETER_TEST_TIME] = { .type = NLA_U32 },
7173
[BATADV_ATTR_TPMETER_BYTES] = { .type = NLA_U64 },
7274
[BATADV_ATTR_TPMETER_COOKIE] = { .type = NLA_U32 },
75+
[BATADV_ATTR_ACTIVE] = { .type = NLA_FLAG },
7376
};
7477

78+
/**
79+
* batadv_netlink_get_ifindex - Extract an interface index from a message
80+
* @nlh: Message header
81+
* @attrtype: Attribute which holds an interface index
82+
*
83+
* Return: interface index, or 0.
84+
*/
85+
static int
86+
batadv_netlink_get_ifindex(const struct nlmsghdr *nlh, int attrtype)
87+
{
88+
struct nlattr *attr = nlmsg_find_attr(nlh, GENL_HDRLEN, attrtype);
89+
90+
return attr ? nla_get_u32(attr) : 0;
91+
}
92+
7593
/**
7694
* batadv_netlink_mesh_info_put - fill in generic information about mesh
7795
* interface
@@ -381,6 +399,106 @@ batadv_netlink_tp_meter_cancel(struct sk_buff *skb, struct genl_info *info)
381399
return ret;
382400
}
383401

402+
/**
403+
* batadv_netlink_dump_hardif_entry - Dump one hard interface into a message
404+
* @msg: Netlink message to dump into
405+
* @portid: Port making netlink request
406+
* @seq: Sequence number of netlink message
407+
* @hard_iface: Hard interface to dump
408+
*
409+
* Return: error code, or 0 on success
410+
*/
411+
static int
412+
batadv_netlink_dump_hardif_entry(struct sk_buff *msg, u32 portid, u32 seq,
413+
struct batadv_hard_iface *hard_iface)
414+
{
415+
struct net_device *net_dev = hard_iface->net_dev;
416+
void *hdr;
417+
418+
hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, NLM_F_MULTI,
419+
BATADV_CMD_GET_HARDIFS);
420+
if (!hdr)
421+
return -EMSGSIZE;
422+
423+
if (nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX,
424+
net_dev->ifindex) ||
425+
nla_put_string(msg, BATADV_ATTR_HARD_IFNAME,
426+
net_dev->name) ||
427+
nla_put(msg, BATADV_ATTR_HARD_ADDRESS, ETH_ALEN,
428+
net_dev->dev_addr))
429+
goto nla_put_failure;
430+
431+
if (hard_iface->if_status == BATADV_IF_ACTIVE) {
432+
if (nla_put_flag(msg, BATADV_ATTR_ACTIVE))
433+
goto nla_put_failure;
434+
}
435+
436+
genlmsg_end(msg, hdr);
437+
return 0;
438+
439+
nla_put_failure:
440+
genlmsg_cancel(msg, hdr);
441+
return -EMSGSIZE;
442+
}
443+
444+
/**
445+
* batadv_netlink_dump_hardifs - Dump all hard interface into a messages
446+
* @msg: Netlink message to dump into
447+
* @cb: Parameters from query
448+
*
449+
* Return: error code, or length of reply message on success
450+
*/
451+
static int
452+
batadv_netlink_dump_hardifs(struct sk_buff *msg, struct netlink_callback *cb)
453+
{
454+
struct net *net = sock_net(cb->skb->sk);
455+
struct net_device *soft_iface;
456+
struct batadv_hard_iface *hard_iface;
457+
int ifindex;
458+
int portid = NETLINK_CB(cb->skb).portid;
459+
int seq = cb->nlh->nlmsg_seq;
460+
int skip = cb->args[0];
461+
int i = 0;
462+
463+
ifindex = batadv_netlink_get_ifindex(cb->nlh,
464+
BATADV_ATTR_MESH_IFINDEX);
465+
if (!ifindex)
466+
return -EINVAL;
467+
468+
soft_iface = dev_get_by_index(net, ifindex);
469+
if (!soft_iface)
470+
return -ENODEV;
471+
472+
if (!batadv_softif_is_valid(soft_iface)) {
473+
dev_put(soft_iface);
474+
return -ENODEV;
475+
}
476+
477+
rcu_read_lock();
478+
479+
list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
480+
if (hard_iface->soft_iface != soft_iface)
481+
continue;
482+
483+
if (i++ < skip)
484+
continue;
485+
486+
if (batadv_netlink_dump_hardif_entry(msg, portid, seq,
487+
hard_iface)) {
488+
i--;
489+
break;
490+
}
491+
}
492+
493+
rcu_read_unlock();
494+
495+
dev_put(soft_iface);
496+
497+
cb->args[0] = i;
498+
499+
return msg->len;
500+
}
501+
384502
static struct genl_ops batadv_netlink_ops[] = {
385503
{
386504
.cmd = BATADV_CMD_GET_MESH_INFO,
@@ -406,6 +524,12 @@ static struct genl_ops batadv_netlink_ops[] = {
406524
.policy = batadv_netlink_policy,
407525
.dumpit = batadv_algo_dump,
408526
},
527+
{
528+
.cmd = BATADV_CMD_GET_HARDIFS,
529+
.flags = GENL_ADMIN_PERM,
530+
.policy = batadv_netlink_policy,
531+
.dumpit = batadv_netlink_dump_hardifs,
532+
},
409533
};
410534

411535
/**

0 commit comments

Comments
 (0)