26
26
#include <linux/netdevice.h>
27
27
#include <linux/netlink.h>
28
28
#include <linux/printk.h>
29
+ #include <linux/rculist.h>
30
+ #include <linux/rcupdate.h>
31
+ #include <linux/skbuff.h>
29
32
#include <linux/stddef.h>
30
33
#include <linux/types.h>
31
34
#include <net/genetlink.h>
32
35
#include <net/netlink.h>
36
+ #include <net/sock.h>
33
37
#include <uapi/linux/batman_adv.h>
34
38
35
39
#include "bat_algo.h"
36
40
#include "hard-interface.h"
37
41
#include "soft-interface.h"
38
42
#include "tp_meter.h"
39
43
40
- struct sk_buff ;
41
-
42
44
struct genl_family batadv_netlink_family = {
43
45
.id = GENL_ID_GENERATE ,
44
46
.hdrsize = 0 ,
@@ -70,8 +72,24 @@ static struct nla_policy batadv_netlink_policy[NUM_BATADV_ATTR] = {
70
72
[BATADV_ATTR_TPMETER_TEST_TIME ] = { .type = NLA_U32 },
71
73
[BATADV_ATTR_TPMETER_BYTES ] = { .type = NLA_U64 },
72
74
[BATADV_ATTR_TPMETER_COOKIE ] = { .type = NLA_U32 },
75
+ [BATADV_ATTR_ACTIVE ] = { .type = NLA_FLAG },
73
76
};
74
77
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
+
75
93
/**
76
94
* batadv_netlink_mesh_info_put - fill in generic information about mesh
77
95
* interface
@@ -381,6 +399,106 @@ batadv_netlink_tp_meter_cancel(struct sk_buff *skb, struct genl_info *info)
381
399
return ret ;
382
400
}
383
401
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
+
384
502
static struct genl_ops batadv_netlink_ops [] = {
385
503
{
386
504
.cmd = BATADV_CMD_GET_MESH_INFO ,
@@ -406,6 +524,12 @@ static struct genl_ops batadv_netlink_ops[] = {
406
524
.policy = batadv_netlink_policy ,
407
525
.dumpit = batadv_algo_dump ,
408
526
},
527
+ {
528
+ .cmd = BATADV_CMD_GET_HARDIFS ,
529
+ .flags = GENL_ADMIN_PERM ,
530
+ .policy = batadv_netlink_policy ,
531
+ .dumpit = batadv_netlink_dump_hardifs ,
532
+ },
409
533
};
410
534
411
535
/**
0 commit comments