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
345345 */
346346 BATADV_ATTR_MCAST_FLAGS_PRIV,
347347
348+ /**
349+ * @BATADV_ATTR_VLANID: VLAN id on top of soft interface
350+ */
351+ BATADV_ATTR_VLANID,
352+
348353 /* add attributes above here, update the policy in netlink.c */
349354
350355 /**
@@ -465,6 +470,18 @@ enum batadv_nl_commands { · 114 unmodified lines
465470 */
466471 BATADV_CMD_SET_HARDIF,
467472
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+
468485 /* add new commands above here */
469486
470487 /**
net/batman-adv/netlink.c+189−2
@@ -30,6 +30,7 @@ · 29 unmodified lines
3030 #include <linux/genetlink.h>
3131 #include <linux/gfp.h>
3232 #include <linux/if_ether.h>
33+#include <linux/if_vlan.h>
3334 #include <linux/init.h>
3435 #include <linux/kernel.h>
3536 #include <linux/list.h>
@@ -84,6 +85,13 @@ enum batadv_genl_ops_flags { · 48 unmodified lines
8485 * saved in info->user_ptr[1]
8586 */
8687 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),
8795 };
8896
8997 static 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
130138 [BATADV_ATTR_DAT_CACHE_VID] = { .type = NLA_U16 },
131139 [BATADV_ATTR_MCAST_FLAGS] = { .type = NLA_U32 },
132140 [BATADV_ATTR_MCAST_FLAGS_PRIV] = { .type = NLA_U32 },
141+ [BATADV_ATTR_VLANID] = { .type = NLA_U16 },
133142 };
134143
135144 /**
@@ -653,6 +662,123 @@ batadv_netlink_dump_hardif(struct sk_buff *msg, struct netlink_callback *cb) · 517 unmodified lines
653662 return msg->len;
654663 }
655664
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+ */
677+static 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+
699+nla_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+ */
711+static 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+ */
742+static 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+ */
772+static 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+
656782 /**
657783 * batadv_get_softif_from_info() - Retrieve soft interface from genl attributes
658784 * @net: the applicable net namespace
@@ -733,6 +859,34 @@ err_put_harddev: · 74 unmodified lines
733859 return ERR_PTR(-EINVAL);
734860 }
735861
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+ */
871+static struct batadv_softif_vlan *
872+batadv_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+
736890 /**
737891 * batadv_pre_doit() - Prepare batman-adv genl doit request
738892 * @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
747901 struct net *net = genl_info_net(info);
748902 struct batadv_hard_iface *hard_iface;
749903 struct batadv_priv *bat_priv = NULL;
904+ struct batadv_softif_vlan *vlan;
750905 struct net_device *soft_iface;
751906 u8 user_ptr1_flags;
752907 u8 mesh_dep_flags;
753908 int ret;
754909
755− user_ptr1_flags = BATADV_FLAG_NEED_HARDIF;
910+ user_ptr1_flags = BATADV_FLAG_NEED_HARDIF | BATADV_FLAG_NEED_VLAN;
756911 if (WARN_ON(hweight8(ops->internal_flags & user_ptr1_flags) > 1))
757912 return -EINVAL;
758913
759− mesh_dep_flags = BATADV_FLAG_NEED_HARDIF;
914+ mesh_dep_flags = BATADV_FLAG_NEED_HARDIF | BATADV_FLAG_NEED_VLAN;
760915 if (WARN_ON((ops->internal_flags & mesh_dep_flags) &&
761916 (~ops->internal_flags & BATADV_FLAG_NEED_MESH)))
762917 return -EINVAL;
@@ -780,6 +935,16 @@ static int batadv_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, · 17 unmodified lines
780935 info->user_ptr[1] = hard_iface;
781936 }
782937
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+
783948 return 0;
784949
785950 err_put_softif:
@@ -799,6 +964,7 @@ static void batadv_post_doit(const struct genl_ops *ops, struct sk_buff *skb, · 13 unmodified lines
799964 struct genl_info *info)
800965 {
801966 struct batadv_hard_iface *hard_iface;
967+ struct batadv_softif_vlan *vlan;
802968 struct batadv_priv *bat_priv;
803969
804970 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
808974 batadv_hardif_put(hard_iface);
809975 }
810976
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+
811982 if (ops->internal_flags & BATADV_FLAG_NEED_MESH && info->user_ptr[0]) {
812983 bat_priv = info->user_ptr[0];
813984 dev_put(bat_priv->soft_iface);
@@ -920,6 +1091,22 @@ static const struct genl_ops batadv_netlink_ops[] = { · 106 unmodified lines
9201091 .internal_flags = BATADV_FLAG_NEED_MESH |
9211092 BATADV_FLAG_NEED_HARDIF,
9221093 },
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+ },
9231110 };
9241111
9251112 struct genl_family batadv_netlink_family __ro_after_init = {