Skip to content

Commit 53dd9a6

Browse files
T-Xsimonwunderlich
authored andcommitted
batman-adv: add multicast flags netlink support
Dump the list of multicast flags entries via the netlink socket. Signed-off-by: Linus Lüssing <[email protected]> Signed-off-by: Sven Eckelmann <[email protected]> Signed-off-by: Simon Wunderlich <[email protected]>
1 parent 41aeefc commit 53dd9a6

File tree

4 files changed

+329
-0
lines changed

4 files changed

+329
-0
lines changed

include/uapi/linux/batman_adv.h

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,53 @@ enum batadv_tt_client_flags {
9191
BATADV_TT_CLIENT_TEMP = (1 << 11),
9292
};
9393

94+
/**
95+
* enum batadv_mcast_flags_priv - Private, own multicast flags
96+
*
97+
* These are internal, multicast related flags. Currently they describe certain
98+
* multicast related attributes of the segment this originator bridges into the
99+
* mesh.
100+
*
101+
* Those attributes are used to determine the public multicast flags this
102+
* originator is going to announce via TT.
103+
*
104+
* For netlink, if BATADV_MCAST_FLAGS_BRIDGED is unset then all querier
105+
* related flags are undefined.
106+
*/
107+
enum batadv_mcast_flags_priv {
108+
/**
109+
* @BATADV_MCAST_FLAGS_BRIDGED: There is a bridge on top of the mesh
110+
* interface.
111+
*/
112+
BATADV_MCAST_FLAGS_BRIDGED = (1 << 0),
113+
114+
/**
115+
* @BATADV_MCAST_FLAGS_QUERIER_IPV4_EXISTS: Whether an IGMP querier
116+
* exists in the mesh
117+
*/
118+
BATADV_MCAST_FLAGS_QUERIER_IPV4_EXISTS = (1 << 1),
119+
120+
/**
121+
* @BATADV_MCAST_FLAGS_QUERIER_IPV6_EXISTS: Whether an MLD querier
122+
* exists in the mesh
123+
*/
124+
BATADV_MCAST_FLAGS_QUERIER_IPV6_EXISTS = (1 << 2),
125+
126+
/**
127+
* @BATADV_MCAST_FLAGS_QUERIER_IPV4_SHADOWING: If an IGMP querier
128+
* exists, whether it is potentially shadowing multicast listeners
129+
* (i.e. querier is behind our own bridge segment)
130+
*/
131+
BATADV_MCAST_FLAGS_QUERIER_IPV4_SHADOWING = (1 << 3),
132+
133+
/**
134+
* @BATADV_MCAST_FLAGS_QUERIER_IPV6_SHADOWING: If an MLD querier
135+
* exists, whether it is potentially shadowing multicast listeners
136+
* (i.e. querier is behind our own bridge segment)
137+
*/
138+
BATADV_MCAST_FLAGS_QUERIER_IPV6_SHADOWING = (1 << 4),
139+
};
140+
94141
/**
95142
* enum batadv_nl_attrs - batman-adv netlink attributes
96143
*/
@@ -287,6 +334,16 @@ enum batadv_nl_attrs {
287334
*/
288335
BATADV_ATTR_DAT_CACHE_VID,
289336

337+
/**
338+
* @BATADV_ATTR_MCAST_FLAGS: Per originator multicast flags
339+
*/
340+
BATADV_ATTR_MCAST_FLAGS,
341+
342+
/**
343+
* @BATADV_ATTR_MCAST_FLAGS_PRIV: Private, own multicast flags
344+
*/
345+
BATADV_ATTR_MCAST_FLAGS_PRIV,
346+
290347
/* add attributes above here, update the policy in netlink.c */
291348

292349
/**
@@ -381,6 +438,11 @@ enum batadv_nl_commands {
381438
*/
382439
BATADV_CMD_GET_DAT_CACHE,
383440

441+
/**
442+
* @BATADV_CMD_GET_MCAST_FLAGS: Query list of multicast flags
443+
*/
444+
BATADV_CMD_GET_MCAST_FLAGS,
445+
384446
/* add new commands above here */
385447

386448
/**

net/batman-adv/multicast.c

Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include <linux/list.h>
4141
#include <linux/lockdep.h>
4242
#include <linux/netdevice.h>
43+
#include <linux/netlink.h>
4344
#include <linux/printk.h>
4445
#include <linux/rculist.h>
4546
#include <linux/rcupdate.h>
@@ -52,14 +53,20 @@
5253
#include <linux/types.h>
5354
#include <linux/workqueue.h>
5455
#include <net/addrconf.h>
56+
#include <net/genetlink.h>
5557
#include <net/if_inet6.h>
5658
#include <net/ip.h>
5759
#include <net/ipv6.h>
60+
#include <net/netlink.h>
61+
#include <net/sock.h>
5862
#include <uapi/linux/batadv_packet.h>
63+
#include <uapi/linux/batman_adv.h>
5964

6065
#include "hard-interface.h"
6166
#include "hash.h"
6267
#include "log.h"
68+
#include "netlink.h"
69+
#include "soft-interface.h"
6370
#include "translation-table.h"
6471
#include "tvlv.h"
6572

@@ -1333,6 +1340,236 @@ int batadv_mcast_flags_seq_print_text(struct seq_file *seq, void *offset)
13331340
}
13341341
#endif
13351342

1343+
/**
1344+
* batadv_mcast_mesh_info_put() - put multicast info into a netlink message
1345+
* @msg: buffer for the message
1346+
* @bat_priv: the bat priv with all the soft interface information
1347+
*
1348+
* Return: 0 or error code.
1349+
*/
1350+
int batadv_mcast_mesh_info_put(struct sk_buff *msg,
1351+
struct batadv_priv *bat_priv)
1352+
{
1353+
u32 flags = bat_priv->mcast.flags;
1354+
u32 flags_priv = BATADV_NO_FLAGS;
1355+
1356+
if (bat_priv->mcast.bridged) {
1357+
flags_priv |= BATADV_MCAST_FLAGS_BRIDGED;
1358+
1359+
if (bat_priv->mcast.querier_ipv4.exists)
1360+
flags_priv |= BATADV_MCAST_FLAGS_QUERIER_IPV4_EXISTS;
1361+
if (bat_priv->mcast.querier_ipv6.exists)
1362+
flags_priv |= BATADV_MCAST_FLAGS_QUERIER_IPV6_EXISTS;
1363+
if (bat_priv->mcast.querier_ipv4.shadowing)
1364+
flags_priv |= BATADV_MCAST_FLAGS_QUERIER_IPV4_SHADOWING;
1365+
if (bat_priv->mcast.querier_ipv6.shadowing)
1366+
flags_priv |= BATADV_MCAST_FLAGS_QUERIER_IPV6_SHADOWING;
1367+
}
1368+
1369+
if (nla_put_u32(msg, BATADV_ATTR_MCAST_FLAGS, flags) ||
1370+
nla_put_u32(msg, BATADV_ATTR_MCAST_FLAGS_PRIV, flags_priv))
1371+
return -EMSGSIZE;
1372+
1373+
return 0;
1374+
}
1375+
1376+
/**
1377+
* batadv_mcast_flags_dump_entry() - dump one entry of the multicast flags table
1378+
* to a netlink socket
1379+
* @msg: buffer for the message
1380+
* @portid: netlink port
1381+
* @seq: Sequence number of netlink message
1382+
* @orig_node: originator to dump the multicast flags of
1383+
*
1384+
* Return: 0 or error code.
1385+
*/
1386+
static int
1387+
batadv_mcast_flags_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
1388+
struct batadv_orig_node *orig_node)
1389+
{
1390+
void *hdr;
1391+
1392+
hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family,
1393+
NLM_F_MULTI, BATADV_CMD_GET_MCAST_FLAGS);
1394+
if (!hdr)
1395+
return -ENOBUFS;
1396+
1397+
if (nla_put(msg, BATADV_ATTR_ORIG_ADDRESS, ETH_ALEN,
1398+
orig_node->orig)) {
1399+
genlmsg_cancel(msg, hdr);
1400+
return -EMSGSIZE;
1401+
}
1402+
1403+
if (test_bit(BATADV_ORIG_CAPA_HAS_MCAST,
1404+
&orig_node->capabilities)) {
1405+
if (nla_put_u32(msg, BATADV_ATTR_MCAST_FLAGS,
1406+
orig_node->mcast_flags)) {
1407+
genlmsg_cancel(msg, hdr);
1408+
return -EMSGSIZE;
1409+
}
1410+
}
1411+
1412+
genlmsg_end(msg, hdr);
1413+
return 0;
1414+
}
1415+
1416+
/**
1417+
* batadv_mcast_flags_dump_bucket() - dump one bucket of the multicast flags
1418+
* table to a netlink socket
1419+
* @msg: buffer for the message
1420+
* @portid: netlink port
1421+
* @seq: Sequence number of netlink message
1422+
* @head: bucket to dump
1423+
* @idx_skip: How many entries to skip
1424+
*
1425+
* Return: 0 or error code.
1426+
*/
1427+
static int
1428+
batadv_mcast_flags_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq,
1429+
struct hlist_head *head, long *idx_skip)
1430+
{
1431+
struct batadv_orig_node *orig_node;
1432+
long idx = 0;
1433+
1434+
rcu_read_lock();
1435+
hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
1436+
if (!test_bit(BATADV_ORIG_CAPA_HAS_MCAST,
1437+
&orig_node->capa_initialized))
1438+
continue;
1439+
1440+
if (idx < *idx_skip)
1441+
goto skip;
1442+
1443+
if (batadv_mcast_flags_dump_entry(msg, portid, seq,
1444+
orig_node)) {
1445+
rcu_read_unlock();
1446+
*idx_skip = idx;
1447+
1448+
return -EMSGSIZE;
1449+
}
1450+
1451+
skip:
1452+
idx++;
1453+
}
1454+
rcu_read_unlock();
1455+
1456+
return 0;
1457+
}
1458+
1459+
/**
1460+
* __batadv_mcast_flags_dump() - dump multicast flags table to a netlink socket
1461+
* @msg: buffer for the message
1462+
* @portid: netlink port
1463+
* @seq: Sequence number of netlink message
1464+
* @bat_priv: the bat priv with all the soft interface information
1465+
* @bucket: current bucket to dump
1466+
* @idx: index in current bucket to the next entry to dump
1467+
*
1468+
* Return: 0 or error code.
1469+
*/
1470+
static int
1471+
__batadv_mcast_flags_dump(struct sk_buff *msg, u32 portid, u32 seq,
1472+
struct batadv_priv *bat_priv, long *bucket, long *idx)
1473+
{
1474+
struct batadv_hashtable *hash = bat_priv->orig_hash;
1475+
long bucket_tmp = *bucket;
1476+
struct hlist_head *head;
1477+
long idx_tmp = *idx;
1478+
1479+
while (bucket_tmp < hash->size) {
1480+
head = &hash->table[bucket_tmp];
1481+
1482+
if (batadv_mcast_flags_dump_bucket(msg, portid, seq, head,
1483+
&idx_tmp))
1484+
break;
1485+
1486+
bucket_tmp++;
1487+
idx_tmp = 0;
1488+
}
1489+
1490+
*bucket = bucket_tmp;
1491+
*idx = idx_tmp;
1492+
1493+
return msg->len;
1494+
}
1495+
1496+
/**
1497+
* batadv_mcast_netlink_get_primary() - get primary interface from netlink
1498+
* callback
1499+
* @cb: netlink callback structure
1500+
* @primary_if: the primary interface pointer to return the result in
1501+
*
1502+
* Return: 0 or error code.
1503+
*/
1504+
static int
1505+
batadv_mcast_netlink_get_primary(struct netlink_callback *cb,
1506+
struct batadv_hard_iface **primary_if)
1507+
{
1508+
struct batadv_hard_iface *hard_iface = NULL;
1509+
struct net *net = sock_net(cb->skb->sk);
1510+
struct net_device *soft_iface;
1511+
struct batadv_priv *bat_priv;
1512+
int ifindex;
1513+
int ret = 0;
1514+
1515+
ifindex = batadv_netlink_get_ifindex(cb->nlh, BATADV_ATTR_MESH_IFINDEX);
1516+
if (!ifindex)
1517+
return -EINVAL;
1518+
1519+
soft_iface = dev_get_by_index(net, ifindex);
1520+
if (!soft_iface || !batadv_softif_is_valid(soft_iface)) {
1521+
ret = -ENODEV;
1522+
goto out;
1523+
}
1524+
1525+
bat_priv = netdev_priv(soft_iface);
1526+
1527+
hard_iface = batadv_primary_if_get_selected(bat_priv);
1528+
if (!hard_iface || hard_iface->if_status != BATADV_IF_ACTIVE) {
1529+
ret = -ENOENT;
1530+
goto out;
1531+
}
1532+
1533+
out:
1534+
if (soft_iface)
1535+
dev_put(soft_iface);
1536+
1537+
if (!ret && primary_if)
1538+
*primary_if = hard_iface;
1539+
else
1540+
batadv_hardif_put(hard_iface);
1541+
1542+
return ret;
1543+
}
1544+
1545+
/**
1546+
* batadv_mcast_flags_dump() - dump multicast flags table to a netlink socket
1547+
* @msg: buffer for the message
1548+
* @cb: callback structure containing arguments
1549+
*
1550+
* Return: message length.
1551+
*/
1552+
int batadv_mcast_flags_dump(struct sk_buff *msg, struct netlink_callback *cb)
1553+
{
1554+
struct batadv_hard_iface *primary_if = NULL;
1555+
int portid = NETLINK_CB(cb->skb).portid;
1556+
struct batadv_priv *bat_priv;
1557+
long *bucket = &cb->args[0];
1558+
long *idx = &cb->args[1];
1559+
int ret;
1560+
1561+
ret = batadv_mcast_netlink_get_primary(cb, &primary_if);
1562+
if (ret)
1563+
return ret;
1564+
1565+
bat_priv = netdev_priv(primary_if->soft_iface);
1566+
ret = __batadv_mcast_flags_dump(msg, portid, cb->nlh->nlmsg_seq,
1567+
bat_priv, bucket, idx);
1568+
1569+
batadv_hardif_put(primary_if);
1570+
return ret;
1571+
}
1572+
13361573
/**
13371574
* batadv_mcast_free() - free the multicast optimizations structures
13381575
* @bat_priv: the bat priv with all the soft interface information

net/batman-adv/multicast.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include "main.h"
2323

24+
struct netlink_callback;
2425
struct seq_file;
2526
struct sk_buff;
2627

@@ -54,6 +55,11 @@ void batadv_mcast_init(struct batadv_priv *bat_priv);
5455

5556
int batadv_mcast_flags_seq_print_text(struct seq_file *seq, void *offset);
5657

58+
int batadv_mcast_mesh_info_put(struct sk_buff *msg,
59+
struct batadv_priv *bat_priv);
60+
61+
int batadv_mcast_flags_dump(struct sk_buff *msg, struct netlink_callback *cb);
62+
5763
void batadv_mcast_free(struct batadv_priv *bat_priv);
5864

5965
void batadv_mcast_purge_orig(struct batadv_orig_node *orig_node);
@@ -72,6 +78,18 @@ static inline int batadv_mcast_init(struct batadv_priv *bat_priv)
7278
return 0;
7379
}
7480

81+
static inline int
82+
batadv_mcast_mesh_info_put(struct sk_buff *msg, struct batadv_priv *bat_priv)
83+
{
84+
return 0;
85+
}
86+
87+
static inline int batadv_mcast_flags_dump(struct sk_buff *msg,
88+
struct netlink_callback *cb)
89+
{
90+
return -EOPNOTSUPP;
91+
}
92+
7593
static inline void batadv_mcast_free(struct batadv_priv *bat_priv)
7694
{
7795
}

0 commit comments

Comments
 (0)