History

batman-adv: Prepare framework for vlan genl config

The batman-adv configuration interface was implemented solely using sysfs. This approach was condemned by non-batadv developers as "huge mistake". Instead a netlink/genl based implementation was suggested. Beside the mesh/soft-interface specific configuration, the VLANs on top of the mesh/soft-interface have configuration settings. The genl interface reflects this by allowing to get/set it using the vlan specific commands BATADV_CMD_GET_VLAN/BATADV_CMD_SET_VLAN. The set command BATADV_CMD_SET_MESH will also notify interested userspace listeners of the "config" mcast group using the BATADV_CMD_SET_VLAN command message type that settings might have been changed and what the current values are.

Sven Eckelmann committed 7 years ago

Commit 49e7e371 parent 5c55a402 files · +206 −2Browse files

Unified · Split

2 files
  1. include/uapi/linux/batman_adv.h +17 −0
  2. net/batman-adv/netlink.c +189 −2
include/uapi/linux/batman_adv.h+17−0
@@ -345,6 +345,11 @@ enum batadv_nl_attrs { · 344 unmodified lines
345 */345 */
346 BATADV_ATTR_MCAST_FLAGS_PRIV,346 BATADV_ATTR_MCAST_FLAGS_PRIV,
347 347
348 /**
349 * @BATADV_ATTR_VLANID: VLAN id on top of soft interface
350 */
351 BATADV_ATTR_VLANID,
352
348 /* add attributes above here, update the policy in netlink.c */353 /* add attributes above here, update the policy in netlink.c */
349 354
350 /**355 /**
@@ -465,6 +470,18 @@ enum batadv_nl_commands { · 114 unmodified lines
465 */470 */
466 BATADV_CMD_SET_HARDIF,471 BATADV_CMD_SET_HARDIF,
467 472
473 /**
474 * @BATADV_CMD_GET_VLAN: Get attributes from a VLAN of the
475 * current softif
476 */
477 BATADV_CMD_GET_VLAN,
478
479 /**
480 * @BATADV_CMD_SET_VLAN: Set attributes for VLAN of the
481 * current softif
482 */
483 BATADV_CMD_SET_VLAN,
484
468 /* add new commands above here */485 /* add new commands above here */
469 486
470 /**487 /**
net/batman-adv/netlink.c+189−2
@@ -30,6 +30,7 @@ · 29 unmodified lines
30#include <linux/genetlink.h>30#include <linux/genetlink.h>
31#include <linux/gfp.h>31#include <linux/gfp.h>
32#include <linux/if_ether.h>32#include <linux/if_ether.h>
33#include <linux/if_vlan.h>
33#include <linux/init.h>34#include <linux/init.h>
34#include <linux/kernel.h>35#include <linux/kernel.h>
35#include <linux/list.h>36#include <linux/list.h>
@@ -84,6 +85,13 @@ enum batadv_genl_ops_flags { · 48 unmodified lines
84 * saved in info->user_ptr[1]85 * saved in info->user_ptr[1]
85 */86 */
86 BATADV_FLAG_NEED_HARDIF = BIT(1),87 BATADV_FLAG_NEED_HARDIF = BIT(1),
88
89 /**
90 * @BATADV_FLAG_NEED_VLAN: request requires valid vlan in
91 * attribute BATADV_ATTR_VLANID and expects a pointer to it to be
92 * saved in info->user_ptr[1]
93 */
94 BATADV_FLAG_NEED_VLAN = BIT(2),
87};95};
88 96
89static const struct genl_multicast_group batadv_netlink_mcgrps[] = {97static const struct genl_multicast_group batadv_netlink_mcgrps[] = {
@@ -130,6 +138,7 @@ static const struct nla_policy batadv_netlink_policy[NUM_BATADV_ATTR] = { · 40 unmodified lines
130 [BATADV_ATTR_DAT_CACHE_VID] = { .type = NLA_U16 },138 [BATADV_ATTR_DAT_CACHE_VID] = { .type = NLA_U16 },
131 [BATADV_ATTR_MCAST_FLAGS] = { .type = NLA_U32 },139 [BATADV_ATTR_MCAST_FLAGS] = { .type = NLA_U32 },
132 [BATADV_ATTR_MCAST_FLAGS_PRIV] = { .type = NLA_U32 },140 [BATADV_ATTR_MCAST_FLAGS_PRIV] = { .type = NLA_U32 },
141 [BATADV_ATTR_VLANID] = { .type = NLA_U16 },
133};142};
134 143
135/**144/**
@@ -653,6 +662,123 @@ batadv_netlink_dump_hardif(struct sk_buff *msg, struct netlink_callback *cb) · 517 unmodified lines
653 return msg->len;662 return msg->len;
654}663}
655 664
665/**
666 * batadv_netlink_vlan_fill() - Fill message with vlan attributes
667 * @msg: Netlink message to dump into
668 * @bat_priv: the bat priv with all the soft interface information
669 * @vlan: vlan which was modified
670 * @cmd: type of message to generate
671 * @portid: Port making netlink request
672 * @seq: sequence number for message
673 * @flags: Additional flags for message
674 *
675 * Return: 0 on success or negative error number in case of failure
676 */
677static int batadv_netlink_vlan_fill(struct sk_buff *msg,
678 struct batadv_priv *bat_priv,
679 struct batadv_softif_vlan *vlan,
680 enum batadv_nl_commands cmd,
681 u32 portid, u32 seq, int flags)
682{
683 void *hdr;
684
685 hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, flags, cmd);
686 if (!hdr)
687 return -ENOBUFS;
688
689 if (nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX,
690 bat_priv->soft_iface->ifindex))
691 goto nla_put_failure;
692
693 if (nla_put_u32(msg, BATADV_ATTR_VLANID, vlan->vid & VLAN_VID_MASK))
694 goto nla_put_failure;
695
696 genlmsg_end(msg, hdr);
697 return 0;
698
699nla_put_failure:
700 genlmsg_cancel(msg, hdr);
701 return -EMSGSIZE;
702}
703
704/**
705 * batadv_netlink_notify_vlan() - send vlan attributes to listener
706 * @bat_priv: the bat priv with all the soft interface information
707 * @vlan: vlan which was modified
708 *
709 * Return: 0 on success, < 0 on error
710 */
711static int batadv_netlink_notify_vlan(struct batadv_priv *bat_priv,
712 struct batadv_softif_vlan *vlan)
713{
714 struct sk_buff *msg;
715 int ret;
716
717 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
718 if (!msg)
719 return -ENOMEM;
720
721 ret = batadv_netlink_vlan_fill(msg, bat_priv, vlan,
722 BATADV_CMD_SET_VLAN, 0, 0, 0);
723 if (ret < 0) {
724 nlmsg_free(msg);
725 return ret;
726 }
727
728 genlmsg_multicast_netns(&batadv_netlink_family,
729 dev_net(bat_priv->soft_iface), msg, 0,
730 BATADV_NL_MCGRP_CONFIG, GFP_KERNEL);
731
732 return 0;
733}
734
735/**
736 * batadv_netlink_get_vlan() - Get vlan attributes
737 * @skb: Netlink message with request data
738 * @info: receiver information
739 *
740 * Return: 0 on success or negative error number in case of failure
741 */
742static int batadv_netlink_get_vlan(struct sk_buff *skb, struct genl_info *info)
743{
744 struct batadv_softif_vlan *vlan = info->user_ptr[1];
745 struct batadv_priv *bat_priv = info->user_ptr[0];
746 struct sk_buff *msg;
747 int ret;
748
749 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
750 if (!msg)
751 return -ENOMEM;
752
753 ret = batadv_netlink_vlan_fill(msg, bat_priv, vlan, BATADV_CMD_GET_VLAN,
754 info->snd_portid, info->snd_seq, 0);
755 if (ret < 0) {
756 nlmsg_free(msg);
757 return ret;
758 }
759
760 ret = genlmsg_reply(msg, info);
761
762 return ret;
763}
764
765/**
766 * batadv_netlink_set_vlan() - Get vlan attributes
767 * @skb: Netlink message with request data
768 * @info: receiver information
769 *
770 * Return: 0 on success or negative error number in case of failure
771 */
772static int batadv_netlink_set_vlan(struct sk_buff *skb, struct genl_info *info)
773{
774 struct batadv_softif_vlan *vlan = info->user_ptr[1];
775 struct batadv_priv *bat_priv = info->user_ptr[0];
776
777 batadv_netlink_notify_vlan(bat_priv, vlan);
778
779 return 0;
780}
781
656/**782/**
657 * batadv_get_softif_from_info() - Retrieve soft interface from genl attributes783 * batadv_get_softif_from_info() - Retrieve soft interface from genl attributes
658 * @net: the applicable net namespace784 * @net: the applicable net namespace
@@ -733,6 +859,34 @@ err_put_harddev: · 74 unmodified lines
733 return ERR_PTR(-EINVAL);859 return ERR_PTR(-EINVAL);
734}860}
735 861
862/**
863 * batadv_get_vlan_from_info() - Retrieve vlan from genl attributes
864 * @bat_priv: the bat priv with all the soft interface information
865 * @net: the applicable net namespace
866 * @info: receiver information
867 *
868 * Return: Pointer to vlan on success (with increased refcnt), error pointer
869 * on error
870 */
871static struct batadv_softif_vlan *
872batadv_get_vlan_from_info(struct batadv_priv *bat_priv, struct net *net,
873 struct genl_info *info)
874{
875 struct batadv_softif_vlan *vlan;
876 u16 vid;
877
878 if (!info->attrs[BATADV_ATTR_VLANID])
879 return ERR_PTR(-EINVAL);
880
881 vid = nla_get_u16(info->attrs[BATADV_ATTR_VLANID]);
882
883 vlan = batadv_softif_vlan_get(bat_priv, vid | BATADV_VLAN_HAS_TAG);
884 if (!vlan)
885 return ERR_PTR(-ENOENT);
886
887 return vlan;
888}
889
736/**890/**
737 * batadv_pre_doit() - Prepare batman-adv genl doit request891 * batadv_pre_doit() - Prepare batman-adv genl doit request
738 * @ops: requested netlink operation892 * @ops: requested netlink operation
@@ -747,16 +901,17 @@ static int batadv_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, · 8 unmodified lines
747 struct net *net = genl_info_net(info);901 struct net *net = genl_info_net(info);
748 struct batadv_hard_iface *hard_iface;902 struct batadv_hard_iface *hard_iface;
749 struct batadv_priv *bat_priv = NULL;903 struct batadv_priv *bat_priv = NULL;
904 struct batadv_softif_vlan *vlan;
750 struct net_device *soft_iface;905 struct net_device *soft_iface;
751 u8 user_ptr1_flags;906 u8 user_ptr1_flags;
752 u8 mesh_dep_flags;907 u8 mesh_dep_flags;
753 int ret;908 int ret;
754 909
755 user_ptr1_flags = BATADV_FLAG_NEED_HARDIF;910 user_ptr1_flags = BATADV_FLAG_NEED_HARDIF | BATADV_FLAG_NEED_VLAN;
756 if (WARN_ON(hweight8(ops->internal_flags & user_ptr1_flags) > 1))911 if (WARN_ON(hweight8(ops->internal_flags & user_ptr1_flags) > 1))
757 return -EINVAL;912 return -EINVAL;
758 913
759 mesh_dep_flags = BATADV_FLAG_NEED_HARDIF;914 mesh_dep_flags = BATADV_FLAG_NEED_HARDIF | BATADV_FLAG_NEED_VLAN;
760 if (WARN_ON((ops->internal_flags & mesh_dep_flags) &&915 if (WARN_ON((ops->internal_flags & mesh_dep_flags) &&
761 (~ops->internal_flags & BATADV_FLAG_NEED_MESH)))916 (~ops->internal_flags & BATADV_FLAG_NEED_MESH)))
762 return -EINVAL;917 return -EINVAL;
@@ -780,6 +935,16 @@ static int batadv_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, · 17 unmodified lines
780 info->user_ptr[1] = hard_iface;935 info->user_ptr[1] = hard_iface;
781 }936 }
782 937
938 if (ops->internal_flags & BATADV_FLAG_NEED_VLAN) {
939 vlan = batadv_get_vlan_from_info(bat_priv, net, info);
940 if (IS_ERR(vlan)) {
941 ret = PTR_ERR(vlan);
942 goto err_put_softif;
943 }
944
945 info->user_ptr[1] = vlan;
946 }
947
783 return 0;948 return 0;
784 949
785err_put_softif:950err_put_softif:
@@ -799,6 +964,7 @@ static void batadv_post_doit(const struct genl_ops *ops, struct sk_buff *skb, · 13 unmodified lines
799 struct genl_info *info)964 struct genl_info *info)
800{965{
801 struct batadv_hard_iface *hard_iface;966 struct batadv_hard_iface *hard_iface;
967 struct batadv_softif_vlan *vlan;
802 struct batadv_priv *bat_priv;968 struct batadv_priv *bat_priv;
803 969
804 if (ops->internal_flags & BATADV_FLAG_NEED_HARDIF &&970 if (ops->internal_flags & BATADV_FLAG_NEED_HARDIF &&
@@ -808,6 +974,11 @@ static void batadv_post_doit(const struct genl_ops *ops, struct sk_buff *skb, · 3 unmodified lines
808 batadv_hardif_put(hard_iface);974 batadv_hardif_put(hard_iface);
809 }975 }
810 976
977 if (ops->internal_flags & BATADV_FLAG_NEED_VLAN && info->user_ptr[1]) {
978 vlan = info->user_ptr[1];
979 batadv_softif_vlan_put(vlan);
980 }
981
811 if (ops->internal_flags & BATADV_FLAG_NEED_MESH && info->user_ptr[0]) {982 if (ops->internal_flags & BATADV_FLAG_NEED_MESH && info->user_ptr[0]) {
812 bat_priv = info->user_ptr[0];983 bat_priv = info->user_ptr[0];
813 dev_put(bat_priv->soft_iface);984 dev_put(bat_priv->soft_iface);
@@ -920,6 +1091,22 @@ static const struct genl_ops batadv_netlink_ops[] = { · 106 unmodified lines
920 .internal_flags = BATADV_FLAG_NEED_MESH |1091 .internal_flags = BATADV_FLAG_NEED_MESH |
921 BATADV_FLAG_NEED_HARDIF,1092 BATADV_FLAG_NEED_HARDIF,
922 },1093 },
1094 {
1095 .cmd = BATADV_CMD_GET_VLAN,
1096 /* can be retrieved by unprivileged users */
1097 .policy = batadv_netlink_policy,
1098 .doit = batadv_netlink_get_vlan,
1099 .internal_flags = BATADV_FLAG_NEED_MESH |
1100 BATADV_FLAG_NEED_VLAN,
1101 },
1102 {
1103 .cmd = BATADV_CMD_SET_VLAN,
1104 .flags = GENL_ADMIN_PERM,
1105 .policy = batadv_netlink_policy,
1106 .doit = batadv_netlink_set_vlan,
1107 .internal_flags = BATADV_FLAG_NEED_MESH |
1108 BATADV_FLAG_NEED_VLAN,
1109 },
923};1110};
924 1111
925struct genl_family batadv_netlink_family __ro_after_init = {1112struct genl_family batadv_netlink_family __ro_after_init = {