diff mbox series

[iproute2-next,v2,7/7] iplink: Reduce number of arguments to iplink_parse()

Message ID 1519162649-22449-8-git-send-email-serhe.popovych@gmail.com
State Superseded, archived
Delegated to: David Ahern
Headers show
Series iplink: Improve iplink_parse() | expand

Commit Message

Serhey Popovych Feb. 20, 2018, 9:37 p.m. UTC
Introduce new @struct iplink_parse_args data structure to consolidate
arguments to iplink_parse(). This will reduce number of arguments
passed to it.

Pass this data structure to ->parse_opt() in iplink specific modules:
it may be used to get network device name and other information.

Signed-off-by: Serhey Popovych <serhe.popovych@gmail.com>
---
 ip/ip_common.h           |   16 +++++++++++++---
 ip/iplink.c              |   34 ++++++++++++++++++++++------------
 ip/iplink_bond.c         |    4 +++-
 ip/iplink_bond_slave.c   |    4 +++-
 ip/iplink_bridge.c       |    4 +++-
 ip/iplink_bridge_slave.c |    4 +++-
 ip/iplink_can.c          |    4 +++-
 ip/iplink_geneve.c       |    4 +++-
 ip/iplink_hsr.c          |    4 +++-
 ip/iplink_ipoib.c        |    4 +++-
 ip/iplink_ipvlan.c       |    4 +++-
 ip/iplink_macvlan.c      |    4 +++-
 ip/iplink_vlan.c         |    4 +++-
 ip/iplink_vrf.c          |    5 ++++-
 ip/iplink_vxcan.c        |   14 ++++++--------
 ip/iplink_vxlan.c        |    4 +++-
 ip/ipmacsec.c            |    4 +++-
 ip/link_gre.c            |    6 ++++--
 ip/link_gre6.c           |    6 ++++--
 ip/link_ip6tnl.c         |    6 ++++--
 ip/link_iptnl.c          |    6 ++++--
 ip/link_veth.c           |   14 ++++++--------
 ip/link_vti.c            |    6 ++++--
 ip/link_vti6.c           |    6 ++++--
 24 files changed, 114 insertions(+), 57 deletions(-)
diff mbox series

Patch

diff --git a/ip/ip_common.h b/ip/ip_common.h
index f762821..aef70de 100644
--- a/ip/ip_common.h
+++ b/ip/ip_common.h
@@ -112,12 +112,23 @@  struct iplink_req {
 	char			buf[1024];
 };
 
+struct iplink_parse_args {
+	const char *dev;
+	const char *name;
+	const char *type;
+
+	/* This definitely must be the last one and initialized
+	 * by the caller of iplink_parse() that will initialize rest.
+	 */
+	struct iplink_req *req;
+};
+
 struct link_util {
 	struct link_util	*next;
 	const char		*id;
 	int			maxattr;
 	int			(*parse_opt)(struct link_util *, int, char **,
-					     struct nlmsghdr *);
+					     struct iplink_parse_args *);
 	void			(*print_opt)(struct link_util *, FILE *,
 					     struct rtattr *[]);
 	void			(*print_xstats)(struct link_util *, FILE *,
@@ -132,8 +143,7 @@  struct link_util {
 
 struct link_util *get_link_kind(const char *kind);
 
-int iplink_parse(int argc, char **argv, struct iplink_req *req,
-		 char **name, char **type, char **dev);
+int iplink_parse(int argc, char **argv, struct iplink_parse_args *pa);
 
 /* iplink_bridge.c */
 void br_dump_bridge_id(const struct ifla_bridge_id *id, char *buf, size_t len);
diff --git a/ip/iplink.c b/ip/iplink.c
index e53d890..837e2b0 100644
--- a/ip/iplink.c
+++ b/ip/iplink.c
@@ -10,6 +10,7 @@ 
  *
  */
 
+#include <stddef.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -577,9 +578,12 @@  static void has_dev(const char *dev, int dev_index)
 		exit(nodev(dev));
 }
 
-int iplink_parse(int argc, char **argv, struct iplink_req *req,
-		 char **name, char **type, char **dev)
+int iplink_parse(int argc, char **argv, struct iplink_parse_args *pa)
 {
+	struct iplink_req *req = pa->req;
+	const char **dev = &pa->dev;
+	const char **name = &pa->name;
+	const char **type = &pa->type;
 	char *link = NULL;
 	int ret, len;
 	char abuf[32];
@@ -597,6 +601,8 @@  int iplink_parse(int argc, char **argv, struct iplink_req *req,
 
 	ret = argc;
 
+	memset(pa, 0, offsetof(struct iplink_parse_args, req));
+
 	while (argc > 0) {
 		if (strcmp(*argv, "up") == 0) {
 			req->i.ifi_change |= IFF_UP;
@@ -1016,32 +1022,32 @@  out:
 
 static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv)
 {
-	char *dev = NULL;
-	char *name = NULL;
-	char *type = NULL;
 	struct iplink_req req = {
 		.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
 		.n.nlmsg_flags = NLM_F_REQUEST | flags,
 		.n.nlmsg_type = cmd,
 		.i.ifi_family = preferred_family,
 	};
+	struct iplink_parse_args pa;
 	int ret;
 
-	ret = iplink_parse(argc, argv, &req, &name, &type, &dev);
+	pa.req = &req;
+
+	ret = iplink_parse(argc, argv, &pa);
 	if (ret < 0)
 		return ret;
 
-	if (type) {
+	if (pa.type) {
 		struct link_util *lu;
 		struct rtattr *linkinfo;
-		char *ulinep = strchr(type, '_');
+		char *ulinep = strchr(pa.type, '_');
 		int iflatype;
 
 		linkinfo = addattr_nest(&req.n, sizeof(req), IFLA_LINKINFO);
-		addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, type,
-			 strlen(type));
+		addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, pa.type,
+			  strlen(pa.type));
 
-		lu = get_link_kind(type);
+		lu = get_link_kind(pa.type);
 		if (ulinep && !strcmp(ulinep, "_slave"))
 			iflatype = IFLA_INFO_SLAVE_DATA;
 		else
@@ -1056,9 +1062,13 @@  static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv)
 			data = addattr_nest(&req.n, sizeof(req), iflatype);
 
 			if (lu->parse_opt &&
-			    lu->parse_opt(lu, argc, argv, &req.n))
+			    lu->parse_opt(lu, argc, argv, &pa))
 				return -1;
 
+			/* Must not assume that anything except pa.req is valid
+			 * after calling ->parse_opt() as one might reuse pa
+			 * with iplink_parse(). See link_veth.c as an example.
+			 */
 			addattr_nest_end(&req.n, data);
 		} else if (argc) {
 			if (matches(*argv, "help") == 0)
diff --git a/ip/iplink_bond.c b/ip/iplink_bond.c
index f906e7f..bf03a6e 100644
--- a/ip/iplink_bond.c
+++ b/ip/iplink_bond.c
@@ -157,8 +157,10 @@  static void explain(void)
 }
 
 static int bond_parse_opt(struct link_util *lu, int argc, char **argv,
-			  struct nlmsghdr *n)
+			  struct iplink_parse_args *pa)
 {
+	struct iplink_req *req = pa->req;
+	struct nlmsghdr *n = &req->n;
 	__u8 mode, use_carrier, primary_reselect, fail_over_mac;
 	__u8 xmit_hash_policy, num_peer_notif, all_slaves_active;
 	__u8 lacp_rate, ad_select, tlb_dynamic_lb;
diff --git a/ip/iplink_bond_slave.c b/ip/iplink_bond_slave.c
index 67219c6..d7e2a1e 100644
--- a/ip/iplink_bond_slave.c
+++ b/ip/iplink_bond_slave.c
@@ -120,8 +120,10 @@  static void bond_slave_print_opt(struct link_util *lu, FILE *f, struct rtattr *t
 }
 
 static int bond_slave_parse_opt(struct link_util *lu, int argc, char **argv,
-				struct nlmsghdr *n)
+				struct iplink_parse_args *pa)
 {
+	struct iplink_req *req = pa->req;
+	struct nlmsghdr *n = &req->n;
 	__u16 queue_id;
 
 	while (argc > 0) {
diff --git a/ip/iplink_bridge.c b/ip/iplink_bridge.c
index 3008e44..9a8560a 100644
--- a/ip/iplink_bridge.c
+++ b/ip/iplink_bridge.c
@@ -80,8 +80,10 @@  void br_dump_bridge_id(const struct ifla_bridge_id *id, char *buf, size_t len)
 }
 
 static int bridge_parse_opt(struct link_util *lu, int argc, char **argv,
-			    struct nlmsghdr *n)
+			    struct iplink_parse_args *pa)
 {
+	struct iplink_req *req = pa->req;
+	struct nlmsghdr *n = &req->n;
 	__u32 val;
 
 	while (argc > 0) {
diff --git a/ip/iplink_bridge_slave.c b/ip/iplink_bridge_slave.c
index 3fbfb87..31fde1c 100644
--- a/ip/iplink_bridge_slave.c
+++ b/ip/iplink_bridge_slave.c
@@ -292,8 +292,10 @@  static void bridge_slave_parse_on_off(char *arg_name, char *arg_val,
 }
 
 static int bridge_slave_parse_opt(struct link_util *lu, int argc, char **argv,
-				  struct nlmsghdr *n)
+				  struct iplink_parse_args *pa)
 {
+	struct iplink_req *req = pa->req;
+	struct nlmsghdr *n = &req->n;
 	__u8 state;
 	__u16 priority;
 	__u32 cost;
diff --git a/ip/iplink_can.c b/ip/iplink_can.c
index 587413d..36ef917 100644
--- a/ip/iplink_can.c
+++ b/ip/iplink_can.c
@@ -110,8 +110,10 @@  static void print_ctrlmode(FILE *f, __u32 cm)
 }
 
 static int can_parse_opt(struct link_util *lu, int argc, char **argv,
-			 struct nlmsghdr *n)
+			 struct iplink_parse_args *pa)
 {
+	struct iplink_req *req = pa->req;
+	struct nlmsghdr *n = &req->n;
 	struct can_bittiming bt = {}, dbt = {};
 	struct can_ctrlmode cm = {0, 0};
 
diff --git a/ip/iplink_geneve.c b/ip/iplink_geneve.c
index 1fcdd83..4b2bf29 100644
--- a/ip/iplink_geneve.c
+++ b/ip/iplink_geneve.c
@@ -55,8 +55,10 @@  static void check_duparg(__u64 *attrs, int type, const char *key,
 }
 
 static int geneve_parse_opt(struct link_util *lu, int argc, char **argv,
-			  struct nlmsghdr *n)
+			    struct iplink_parse_args *pa)
 {
+	struct iplink_req *req = pa->req;
+	struct nlmsghdr *n = &req->n;
 	inet_prefix daddr;
 	__u32 vni = 0;
 	__u32 label = 0;
diff --git a/ip/iplink_hsr.c b/ip/iplink_hsr.c
index c673ccf..d020676 100644
--- a/ip/iplink_hsr.c
+++ b/ip/iplink_hsr.c
@@ -44,8 +44,10 @@  static void usage(void)
 }
 
 static int hsr_parse_opt(struct link_util *lu, int argc, char **argv,
-			 struct nlmsghdr *n)
+			 struct iplink_parse_args *pa)
 {
+	struct iplink_req *req = pa->req;
+	struct nlmsghdr *n = &req->n;
 	int ifindex;
 	unsigned char multicast_spec;
 	unsigned char protocol_version;
diff --git a/ip/iplink_ipoib.c b/ip/iplink_ipoib.c
index e69bda0..f95c79c 100644
--- a/ip/iplink_ipoib.c
+++ b/ip/iplink_ipoib.c
@@ -42,8 +42,10 @@  static int mode_arg(void)
 }
 
 static int ipoib_parse_opt(struct link_util *lu, int argc, char **argv,
-			  struct nlmsghdr *n)
+			   struct iplink_parse_args *pa)
 {
+	struct iplink_req *req = pa->req;
+	struct nlmsghdr *n = &req->n;
 	__u16 pkey, mode, umcast;
 
 	while (argc > 0) {
diff --git a/ip/iplink_ipvlan.c b/ip/iplink_ipvlan.c
index 8889808..2b8a3cc 100644
--- a/ip/iplink_ipvlan.c
+++ b/ip/iplink_ipvlan.c
@@ -30,8 +30,10 @@  static void ipvlan_explain(FILE *f)
 }
 
 static int ipvlan_parse_opt(struct link_util *lu, int argc, char **argv,
-			    struct nlmsghdr *n)
+			    struct iplink_parse_args *pa)
 {
+	struct iplink_req *req = pa->req;
+	struct nlmsghdr *n = &req->n;
 	__u16 flags = 0;
 	bool mflag_given = false;
 
diff --git a/ip/iplink_macvlan.c b/ip/iplink_macvlan.c
index b966a61..6f97415 100644
--- a/ip/iplink_macvlan.c
+++ b/ip/iplink_macvlan.c
@@ -63,8 +63,10 @@  static int flag_arg(const char *arg)
 }
 
 static int macvlan_parse_opt(struct link_util *lu, int argc, char **argv,
-			  struct nlmsghdr *n)
+			     struct iplink_parse_args *pa)
 {
+	struct iplink_req *req = pa->req;
+	struct nlmsghdr *n = &req->n;
 	__u32 mode = 0;
 	__u16 flags = 0;
 	__u32 mac_mode = 0;
diff --git a/ip/iplink_vlan.c b/ip/iplink_vlan.c
index 74f4614..6c0c12d 100644
--- a/ip/iplink_vlan.c
+++ b/ip/iplink_vlan.c
@@ -82,8 +82,10 @@  static int vlan_parse_qos_map(int *argcp, char ***argvp, struct nlmsghdr *n,
 }
 
 static int vlan_parse_opt(struct link_util *lu, int argc, char **argv,
-			  struct nlmsghdr *n)
+			  struct iplink_parse_args *pa)
 {
+	struct iplink_req *req = pa->req;
+	struct nlmsghdr *n = &req->n;
 	struct ifla_vlan_flags flags = { 0 };
 	__u16 id, proto;
 
diff --git a/ip/iplink_vrf.c b/ip/iplink_vrf.c
index e9dd0df..b943ed9 100644
--- a/ip/iplink_vrf.c
+++ b/ip/iplink_vrf.c
@@ -30,8 +30,11 @@  static void explain(void)
 }
 
 static int vrf_parse_opt(struct link_util *lu, int argc, char **argv,
-			    struct nlmsghdr *n)
+			 struct iplink_parse_args *pa)
 {
+	struct iplink_req *req = pa->req;
+	struct nlmsghdr *n = &req->n;
+
 	while (argc > 0) {
 		if (matches(*argv, "table") == 0) {
 			__u32 table;
diff --git a/ip/iplink_vxcan.c b/ip/iplink_vxcan.c
index 43c80e7..a234e34 100644
--- a/ip/iplink_vxcan.c
+++ b/ip/iplink_vxcan.c
@@ -31,11 +31,10 @@  static void usage(void)
 }
 
 static int vxcan_parse_opt(struct link_util *lu, int argc, char **argv,
-			  struct nlmsghdr *n)
+			   struct iplink_parse_args *pa)
 {
-	char *dev = NULL;
-	char *name = NULL;
-	char *type = NULL;
+	struct iplink_req *req = pa->req;
+	struct nlmsghdr *n = &req->n;
 	int err;
 	struct rtattr *data;
 	struct ifinfomsg ifm_save, *ifm, *peer_ifm;
@@ -45,7 +44,7 @@  static int vxcan_parse_opt(struct link_util *lu, int argc, char **argv,
 		return -1;
 	}
 
-	ifm = NLMSG_DATA(n);
+	ifm = &req->i;
 	memcpy(&ifm_save, ifm, sizeof(*ifm));
 	ifm->ifi_index = 0;
 	ifm->ifi_flags = 0;
@@ -55,12 +54,11 @@  static int vxcan_parse_opt(struct link_util *lu, int argc, char **argv,
 
 	n->nlmsg_len += sizeof(struct ifinfomsg);
 
-	err = iplink_parse(argc - 1, argv + 1, (struct iplink_req *)n,
-			   &name, &type, &dev);
+	err = iplink_parse(argc - 1, argv + 1, pa);
 	if (err < 0)
 		return err;
 
-	if (type)
+	if (pa->type)
 		duparg("type", argv[err]);
 
 	peer_ifm = RTA_DATA(data);
diff --git a/ip/iplink_vxlan.c b/ip/iplink_vxlan.c
index be9f35e..f76a2c4 100644
--- a/ip/iplink_vxlan.c
+++ b/ip/iplink_vxlan.c
@@ -72,8 +72,10 @@  static void check_duparg(__u64 *attrs, int type, const char *key,
 }
 
 static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
-			  struct nlmsghdr *n)
+			   struct iplink_parse_args *pa)
 {
+	struct iplink_req *req = pa->req;
+	struct nlmsghdr *n = &req->n;
 	inet_prefix saddr, daddr;
 	__u32 vni = 0;
 	__u8 learning = 1;
diff --git a/ip/ipmacsec.c b/ip/ipmacsec.c
index c0b45f5..144141f 100644
--- a/ip/ipmacsec.c
+++ b/ip/ipmacsec.c
@@ -1132,8 +1132,10 @@  static void usage(FILE *f)
 }
 
 static int macsec_parse_opt(struct link_util *lu, int argc, char **argv,
-			    struct nlmsghdr *n)
+			    struct iplink_parse_args *pa)
 {
+	struct iplink_req *req = pa->req;
+	struct nlmsghdr *n = &req->n;
 	int ret;
 	__u8 encoding_sa = 0xff;
 	__u32 window = -1;
diff --git a/ip/link_gre.c b/ip/link_gre.c
index 6654525..f7b194f 100644
--- a/ip/link_gre.c
+++ b/ip/link_gre.c
@@ -64,8 +64,10 @@  static void gre_print_help(struct link_util *lu, int argc, char **argv, FILE *f)
 }
 
 static int gre_parse_opt(struct link_util *lu, int argc, char **argv,
-			 struct nlmsghdr *n)
+			 struct iplink_parse_args *pa)
 {
+	struct iplink_req *req = pa->req;
+	struct nlmsghdr *n = &req->n;
 	__u16 iflags = 0;
 	__u16 oflags = 0;
 	__be32 ikey = 0;
@@ -91,7 +93,7 @@  static int gre_parse_opt(struct link_util *lu, int argc, char **argv,
 	inet_prefix_reset(&daddr);
 
 	if (!(n->nlmsg_flags & NLM_F_CREATE)) {
-		struct ifinfomsg *ifi = NLMSG_DATA(n);
+		struct ifinfomsg *ifi = &req->i;
 		struct {
 			struct nlmsghdr n;
 			struct ifinfomsg i;
diff --git a/ip/link_gre6.c b/ip/link_gre6.c
index a92854d..fb3e259 100644
--- a/ip/link_gre6.c
+++ b/ip/link_gre6.c
@@ -75,8 +75,10 @@  static void gre_print_help(struct link_util *lu, int argc, char **argv, FILE *f)
 }
 
 static int gre_parse_opt(struct link_util *lu, int argc, char **argv,
-			 struct nlmsghdr *n)
+			 struct iplink_parse_args *pa)
 {
+	struct iplink_req *req = pa->req;
+	struct nlmsghdr *n = &req->n;
 	__u16 iflags = 0;
 	__u16 oflags = 0;
 	__be32 ikey = 0;
@@ -102,7 +104,7 @@  static int gre_parse_opt(struct link_util *lu, int argc, char **argv,
 	inet_prefix_reset(&daddr);
 
 	if (!(n->nlmsg_flags & NLM_F_CREATE)) {
-		struct ifinfomsg *ifi = NLMSG_DATA(n);
+		struct ifinfomsg *ifi = &req->i;
 		struct {
 			struct nlmsghdr n;
 			struct ifinfomsg i;
diff --git a/ip/link_ip6tnl.c b/ip/link_ip6tnl.c
index edd7632..6d9361c 100644
--- a/ip/link_ip6tnl.c
+++ b/ip/link_ip6tnl.c
@@ -75,8 +75,10 @@  static void ip6tunnel_print_help(struct link_util *lu, int argc, char **argv,
 }
 
 static int ip6tunnel_parse_opt(struct link_util *lu, int argc, char **argv,
-			       struct nlmsghdr *n)
+			       struct iplink_parse_args *pa)
 {
+	struct iplink_req *req = pa->req;
+	struct nlmsghdr *n = &req->n;
 	inet_prefix saddr, daddr;
 	__u8 hop_limit = DEFAULT_TNL_HOP_LIMIT;
 	__u8 encap_limit = IPV6_DEFAULT_TNL_ENCAP_LIMIT;
@@ -95,7 +97,7 @@  static int ip6tunnel_parse_opt(struct link_util *lu, int argc, char **argv,
 	inet_prefix_reset(&daddr);
 
 	if (!(n->nlmsg_flags & NLM_F_CREATE)) {
-		struct ifinfomsg *ifi = NLMSG_DATA(n);
+		struct ifinfomsg *ifi = &req->i;
 		struct {
 			struct nlmsghdr n;
 			struct ifinfomsg i;
diff --git a/ip/link_iptnl.c b/ip/link_iptnl.c
index 0dc0db0..6df4dca 100644
--- a/ip/link_iptnl.c
+++ b/ip/link_iptnl.c
@@ -72,8 +72,10 @@  static void iptunnel_print_help(struct link_util *lu, int argc, char **argv,
 }
 
 static int iptunnel_parse_opt(struct link_util *lu, int argc, char **argv,
-			      struct nlmsghdr *n)
+			      struct iplink_parse_args *pa)
 {
+	struct iplink_req *req = pa->req;
+	struct nlmsghdr *n = &req->n;
 	inet_prefix saddr, daddr, ip6rdprefix, ip6rdrelayprefix;
 	__u8 pmtudisc = 1;
 	__u8 tos = 0;
@@ -95,7 +97,7 @@  static int iptunnel_parse_opt(struct link_util *lu, int argc, char **argv,
 	inet_prefix_reset(&ip6rdrelayprefix);
 
 	if (!(n->nlmsg_flags & NLM_F_CREATE)) {
-		struct ifinfomsg *ifi = NLMSG_DATA(n);
+		struct ifinfomsg *ifi = &req->i;
 		struct {
 			struct nlmsghdr n;
 			struct ifinfomsg i;
diff --git a/ip/link_veth.c b/ip/link_veth.c
index bd8f36e..00d5cf7 100644
--- a/ip/link_veth.c
+++ b/ip/link_veth.c
@@ -29,11 +29,10 @@  static void usage(void)
 }
 
 static int veth_parse_opt(struct link_util *lu, int argc, char **argv,
-			  struct nlmsghdr *n)
+			  struct iplink_parse_args *pa)
 {
-	char *dev = NULL;
-	char *name = NULL;
-	char *type = NULL;
+	struct iplink_req *req = pa->req;
+	struct nlmsghdr *n = &req->n;
 	int err;
 	struct rtattr *data;
 	struct ifinfomsg ifm_save, *ifm, *peer_ifm;
@@ -43,7 +42,7 @@  static int veth_parse_opt(struct link_util *lu, int argc, char **argv,
 		return -1;
 	}
 
-	ifm = NLMSG_DATA(n);
+	ifm = &req->i;
 	memcpy(&ifm_save, ifm, sizeof(*ifm));
 	ifm->ifi_index = 0;
 	ifm->ifi_flags = 0;
@@ -53,12 +52,11 @@  static int veth_parse_opt(struct link_util *lu, int argc, char **argv,
 
 	n->nlmsg_len += sizeof(struct ifinfomsg);
 
-	err = iplink_parse(argc - 1, argv + 1, (struct iplink_req *)n,
-			   &name, &type, &dev);
+	err = iplink_parse(argc - 1, argv + 1, pa);
 	if (err < 0)
 		return err;
 
-	if (type)
+	if (pa->type)
 		duparg("type", argv[err]);
 
 	peer_ifm = RTA_DATA(data);
diff --git a/ip/link_vti.c b/ip/link_vti.c
index 47c3b7f..10508e6 100644
--- a/ip/link_vti.c
+++ b/ip/link_vti.c
@@ -45,8 +45,10 @@  static void vti_print_help(struct link_util *lu, int argc, char **argv, FILE *f)
 }
 
 static int vti_parse_opt(struct link_util *lu, int argc, char **argv,
-			 struct nlmsghdr *n)
+			 struct iplink_parse_args *pa)
 {
+	struct iplink_req *req = pa->req;
+	struct nlmsghdr *n = &req->n;
 	__be32 ikey = 0;
 	__be32 okey = 0;
 	inet_prefix saddr, daddr;
@@ -57,7 +59,7 @@  static int vti_parse_opt(struct link_util *lu, int argc, char **argv,
 	inet_prefix_reset(&daddr);
 
 	if (!(n->nlmsg_flags & NLM_F_CREATE)) {
-		struct ifinfomsg *ifi = NLMSG_DATA(n);
+		struct ifinfomsg *ifi = &req->i;
 		struct {
 			struct nlmsghdr n;
 			struct ifinfomsg i;
diff --git a/ip/link_vti6.c b/ip/link_vti6.c
index 48c67b0..91c8521 100644
--- a/ip/link_vti6.c
+++ b/ip/link_vti6.c
@@ -47,8 +47,10 @@  static void vti6_print_help(struct link_util *lu, int argc, char **argv,
 }
 
 static int vti6_parse_opt(struct link_util *lu, int argc, char **argv,
-			  struct nlmsghdr *n)
+			  struct iplink_parse_args *pa)
 {
+	struct iplink_req *req = pa->req;
+	struct nlmsghdr *n = &req->n;
 	__be32 ikey = 0;
 	__be32 okey = 0;
 	inet_prefix saddr, daddr;
@@ -59,7 +61,7 @@  static int vti6_parse_opt(struct link_util *lu, int argc, char **argv,
 	inet_prefix_reset(&daddr);
 
 	if (!(n->nlmsg_flags & NLM_F_CREATE)) {
-		struct ifinfomsg *ifi = NLMSG_DATA(n);
+		struct ifinfomsg *ifi = &req->i;
 		struct {
 			struct nlmsghdr n;
 			struct ifinfomsg i;