Blame SOURCES/0023-lib-libnetlink-update-rtnl_talk-to-support-malloc-bu.patch

be97f7
From 3d76c7eea3caaddcc0608ad35a9e6fab3df11f8e Mon Sep 17 00:00:00 2001
be97f7
From: Hangbin Liu <haliu@redhat.com>
be97f7
Date: Wed, 8 Nov 2017 14:39:13 +0800
be97f7
Subject: [PATCH] lib/libnetlink: update rtnl_talk to support malloc buff at
be97f7
 run time
be97f7
be97f7
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1380803
be97f7
Upstream Status: iproute2.git net-next commit 86bf43c7c2fd
be97f7
be97f7
Conflicts:
be97f7
- iplink_get@ip/iplink.c: no function open_json_object() due to missing
be97f7
  e4a1216aeb2a ("ip: iplink.c: open/close json obj for ip -brief -json link
be97f7
  show dev DEV"). Lack of last parameter for print_linkinfo_brief() due to
be97f7
  missing 63891c70137f ("ip address: Change print_linkinfo_brief to take
be97f7
  filter as an input")
be97f7
- gre_parse_opt@ip/link_gre.c: context conflicts due to missing new
be97f7
  flag IFLA_GRE_ERSPAN_INDEX.
be97f7
- gre_parse_opt@ip/link_gre6.c: context conflicts due to missing new
be97f7
  flag IFLA_GRE_FWMARK.
be97f7
- ip6tunnel_parse_opt@ip/link_ip6tnl.c: context conflicts due to missing new
be97f7
  flag IFLA_IPTUN_FWMARK.
be97f7
- iptunnel_parse_opt@ip/link_iptnl.c: context conflicts due to missing new
be97f7
  flag IFLA_IPTUN_FWMARK.
be97f7
- vti_parse_opt@ip/link_vti.c: context conflicts due to missing new flag
be97f7
  IFLA_VTI_FWMARK
be97f7
- vti6_parse_opt@ip/link_vti6.c: context conflicts due to missing new flag
be97f7
  IFLA_VTI_FWMARK
be97f7
be97f7
commit 86bf43c7c2fdc33d7c021b4a1add1c8facbca51c
be97f7
Author: Hangbin Liu <liuhangbin@gmail.com>
be97f7
Date:   Thu Oct 26 09:41:47 2017 +0800
be97f7
be97f7
    lib/libnetlink: update rtnl_talk to support malloc buff at run time
be97f7
be97f7
    This is an update for 460c03f3f3cc ("iplink: double the buffer size also in
be97f7
    iplink_get()"). After update, we will not need to double the buffer size
be97f7
    every time when VFs number increased.
be97f7
be97f7
    With call like rtnl_talk(&rth, &req.n, NULL, 0), we can simply remove the
be97f7
    length parameter.
be97f7
be97f7
    With call like rtnl_talk(&rth, nlh, nlh, sizeof(req), I add a new variable
be97f7
    answer to avoid overwrite data in nlh, because it may has more info after
be97f7
    nlh. also this will avoid nlh buffer not enough issue.
be97f7
be97f7
    We need to free answer after using.
be97f7
be97f7
    Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
be97f7
    Signed-off-by: Phil Sutter <phil@nwl.cc>
be97f7
be97f7
Signed-off-by: Hangbin Liu <haliu@redhat.com>
be97f7
---
be97f7
 bridge/fdb.c         |  2 +-
be97f7
 bridge/link.c        |  2 +-
be97f7
 bridge/mdb.c         |  2 +-
be97f7
 bridge/vlan.c        |  2 +-
be97f7
 genl/ctrl.c          | 19 ++++++++++++-------
be97f7
 include/libnetlink.h |  6 +++---
be97f7
 ip/ipaddress.c       |  4 ++--
be97f7
 ip/ipaddrlabel.c     |  4 ++--
be97f7
 ip/ipfou.c           |  4 ++--
be97f7
 ip/ipila.c           |  4 ++--
be97f7
 ip/ipl2tp.c          |  8 ++++----
be97f7
 ip/iplink.c          | 38 +++++++++++++++++++-------------------
be97f7
 ip/iplink_vrf.c      | 44 ++++++++++++++++++++------------------------
be97f7
 ip/ipmacsec.c        |  2 +-
be97f7
 ip/ipneigh.c         |  2 +-
be97f7
 ip/ipnetns.c         | 23 ++++++++++++++---------
be97f7
 ip/ipntable.c        |  2 +-
be97f7
 ip/iproute.c         | 26 +++++++++++++++++---------
be97f7
 ip/iprule.c          |  6 +++---
be97f7
 ip/iptoken.c         |  2 +-
be97f7
 ip/link_gre.c        | 11 +++++++----
be97f7
 ip/link_gre6.c       | 11 +++++++----
be97f7
 ip/link_ip6tnl.c     | 11 +++++++----
be97f7
 ip/link_iptnl.c      | 11 +++++++----
be97f7
 ip/link_vti.c        | 11 +++++++----
be97f7
 ip/link_vti6.c       | 11 +++++++----
be97f7
 ip/tcp_metrics.c     |  8 +++++---
be97f7
 ip/xfrm_policy.c     | 25 +++++++++++++------------
be97f7
 ip/xfrm_state.c      | 30 ++++++++++++++++--------------
be97f7
 lib/libgenl.c        |  9 +++++++--
be97f7
 lib/libnetlink.c     | 24 +++++++++++-------------
be97f7
 misc/ss.c            |  2 +-
be97f7
 tc/m_action.c        | 12 ++++++------
be97f7
 tc/tc_class.c        |  2 +-
be97f7
 tc/tc_filter.c       |  8 +++++---
be97f7
 tc/tc_qdisc.c        |  2 +-
be97f7
 36 files changed, 216 insertions(+), 174 deletions(-)
be97f7
be97f7
diff --git a/bridge/fdb.c b/bridge/fdb.c
be97f7
index a71a78f..4859edb 100644
be97f7
--- a/bridge/fdb.c
be97f7
+++ b/bridge/fdb.c
be97f7
@@ -529,7 +529,7 @@ static int fdb_modify(int cmd, int flags, int argc, char **argv)
be97f7
 		return -1;
be97f7
 	}
be97f7
 
be97f7
-	if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
be97f7
+	if (rtnl_talk(&rth, &req.n, NULL) < 0)
be97f7
 		return -1;
be97f7
 
be97f7
 	return 0;
be97f7
diff --git a/bridge/link.c b/bridge/link.c
be97f7
index 93472ad..cc29a2a 100644
be97f7
--- a/bridge/link.c
be97f7
+++ b/bridge/link.c
be97f7
@@ -426,7 +426,7 @@ static int brlink_modify(int argc, char **argv)
be97f7
 		addattr_nest_end(&req.n, nest);
be97f7
 	}
be97f7
 
be97f7
-	if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
be97f7
+	if (rtnl_talk(&rth, &req.n, NULL) < 0)
be97f7
 		return -1;
be97f7
 
be97f7
 	return 0;
be97f7
diff --git a/bridge/mdb.c b/bridge/mdb.c
be97f7
index e60ff3e..fbd8184 100644
be97f7
--- a/bridge/mdb.c
be97f7
+++ b/bridge/mdb.c
be97f7
@@ -298,7 +298,7 @@ static int mdb_modify(int cmd, int flags, int argc, char **argv)
be97f7
 	entry.vid = vid;
be97f7
 	addattr_l(&req.n, sizeof(req), MDBA_SET_ENTRY, &entry, sizeof(entry));
be97f7
 
be97f7
-	if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
be97f7
+	if (rtnl_talk(&rth, &req.n, NULL) < 0)
be97f7
 		return -1;
be97f7
 
be97f7
 	return 0;
be97f7
diff --git a/bridge/vlan.c b/bridge/vlan.c
be97f7
index ebcdace..5d68359 100644
be97f7
--- a/bridge/vlan.c
be97f7
+++ b/bridge/vlan.c
be97f7
@@ -133,7 +133,7 @@ static int vlan_modify(int cmd, int argc, char **argv)
be97f7
 
be97f7
 	addattr_nest_end(&req.n, afspec);
be97f7
 
be97f7
-	if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
be97f7
+	if (rtnl_talk(&rth, &req.n, NULL) < 0)
be97f7
 		return -1;
be97f7
 
be97f7
 	return 0;
be97f7
diff --git a/genl/ctrl.c b/genl/ctrl.c
be97f7
index 6abd525..21e857c 100644
be97f7
--- a/genl/ctrl.c
be97f7
+++ b/genl/ctrl.c
be97f7
@@ -55,6 +55,7 @@ int genl_ctrl_resolve_family(const char *family)
be97f7
 	};
be97f7
 	struct nlmsghdr *nlh = &req.n;
be97f7
 	struct genlmsghdr *ghdr = &req.g;
be97f7
+	struct nlmsghdr *answer = NULL;
be97f7
 
be97f7
 	if (rtnl_open_byproto(&rth, 0, NETLINK_GENERIC) < 0) {
be97f7
 		fprintf(stderr, "Cannot open generic netlink socket\n");
be97f7
@@ -63,19 +64,19 @@ int genl_ctrl_resolve_family(const char *family)
be97f7
 
be97f7
 	addattr_l(nlh, 128, CTRL_ATTR_FAMILY_NAME, family, strlen(family) + 1);
be97f7
 
be97f7
-	if (rtnl_talk(&rth, nlh, nlh, sizeof(req)) < 0) {
be97f7
+	if (rtnl_talk(&rth, nlh, &answer) < 0) {
be97f7
 		fprintf(stderr, "Error talking to the kernel\n");
be97f7
 		goto errout;
be97f7
 	}
be97f7
 
be97f7
 	{
be97f7
 		struct rtattr *tb[CTRL_ATTR_MAX + 1];
be97f7
-		int len = nlh->nlmsg_len;
be97f7
+		int len = answer->nlmsg_len;
be97f7
 		struct rtattr *attrs;
be97f7
 
be97f7
-		if (nlh->nlmsg_type !=  GENL_ID_CTRL) {
be97f7
+		if (answer->nlmsg_type !=  GENL_ID_CTRL) {
be97f7
 			fprintf(stderr, "Not a controller message, nlmsg_len=%d "
be97f7
-				"nlmsg_type=0x%x\n", nlh->nlmsg_len, nlh->nlmsg_type);
be97f7
+				"nlmsg_type=0x%x\n", answer->nlmsg_len, answer->nlmsg_type);
be97f7
 			goto errout;
be97f7
 		}
be97f7
 
be97f7
@@ -88,10 +89,11 @@ int genl_ctrl_resolve_family(const char *family)
be97f7
 
be97f7
 		if (len < 0) {
be97f7
 			fprintf(stderr, "wrong controller message len %d\n", len);
be97f7
+			free(answer);
be97f7
 			return -1;
be97f7
 		}
be97f7
 
be97f7
-		attrs = (struct rtattr *) ((char *) ghdr + GENL_HDRLEN);
be97f7
+		attrs = (struct rtattr *) ((char *) answer + NLMSG_LENGTH(GENL_HDRLEN));
be97f7
 		parse_rtattr(tb, CTRL_ATTR_MAX, attrs, len);
be97f7
 
be97f7
 		if (tb[CTRL_ATTR_FAMILY_ID] == NULL) {
be97f7
@@ -103,6 +105,7 @@ int genl_ctrl_resolve_family(const char *family)
be97f7
 	}
be97f7
 
be97f7
 errout:
be97f7
+	free(answer);
be97f7
 	rtnl_close(&rth);
be97f7
 	return ret;
be97f7
 }
be97f7
@@ -299,6 +302,7 @@ static int ctrl_list(int cmd, int argc, char **argv)
be97f7
 		.g.cmd = CTRL_CMD_GETFAMILY,
be97f7
 	};
be97f7
 	struct nlmsghdr *nlh = &req.n;
be97f7
+	struct nlmsghdr *answer = NULL;
be97f7
 
be97f7
 	if (rtnl_open_byproto(&rth, 0, NETLINK_GENERIC) < 0) {
be97f7
 		fprintf(stderr, "Cannot open generic netlink socket\n");
be97f7
@@ -331,12 +335,12 @@ static int ctrl_list(int cmd, int argc, char **argv)
be97f7
 			goto ctrl_done;
be97f7
 		}
be97f7
 
be97f7
-		if (rtnl_talk(&rth, nlh, nlh, sizeof(req)) < 0) {
be97f7
+		if (rtnl_talk(&rth, nlh, &answer) < 0) {
be97f7
 			fprintf(stderr, "Error talking to the kernel\n");
be97f7
 			goto ctrl_done;
be97f7
 		}
be97f7
 
be97f7
-		if (print_ctrl2(NULL, nlh, (void *) stdout) < 0) {
be97f7
+		if (print_ctrl2(NULL, answer, (void *) stdout) < 0) {
be97f7
 			fprintf(stderr, "Dump terminated\n");
be97f7
 			goto ctrl_done;
be97f7
 		}
be97f7
@@ -358,6 +362,7 @@ static int ctrl_list(int cmd, int argc, char **argv)
be97f7
 
be97f7
 	ret = 0;
be97f7
 ctrl_done:
be97f7
+	free(answer);
be97f7
 	rtnl_close(&rth);
be97f7
 	return ret;
be97f7
 }
be97f7
diff --git a/include/libnetlink.h b/include/libnetlink.h
be97f7
index 654aebc..2136d2b 100644
be97f7
--- a/include/libnetlink.h
be97f7
+++ b/include/libnetlink.h
be97f7
@@ -82,13 +82,13 @@ int rtnl_dump_filter_nc(struct rtnl_handle *rth,
be97f7
 #define rtnl_dump_filter(rth, filter, arg) \
be97f7
 	rtnl_dump_filter_nc(rth, filter, arg, 0)
be97f7
 int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n,
be97f7
-	      struct nlmsghdr *answer, size_t len)
be97f7
+	      struct nlmsghdr **answer)
be97f7
 	__attribute__((warn_unused_result));
be97f7
 int rtnl_talk_extack(struct rtnl_handle *rtnl, struct nlmsghdr *n,
be97f7
-	      struct nlmsghdr *answer, size_t len, nl_ext_ack_fn_t errfn)
be97f7
+	      struct nlmsghdr **answer, nl_ext_ack_fn_t errfn)
be97f7
 	__attribute__((warn_unused_result));
be97f7
 int rtnl_talk_suppress_rtnl_errmsg(struct rtnl_handle *rtnl, struct nlmsghdr *n,
be97f7
-				   struct nlmsghdr *answer, size_t len)
be97f7
+				   struct nlmsghdr **answer)
be97f7
 	__attribute__((warn_unused_result));
be97f7
 int rtnl_send(struct rtnl_handle *rth, const void *buf, int)
be97f7
 	__attribute__((warn_unused_result));
be97f7
diff --git a/ip/ipaddress.c b/ip/ipaddress.c
be97f7
index b8d9c7d..7492075 100644
be97f7
--- a/ip/ipaddress.c
be97f7
+++ b/ip/ipaddress.c
be97f7
@@ -1356,7 +1356,7 @@ static int restore_handler(const struct sockaddr_nl *nl,
be97f7
 
be97f7
 	ll_init_map(&rth);
be97f7
 
be97f7
-	ret = rtnl_talk(&rth, n, n, sizeof(*n));
be97f7
+	ret = rtnl_talk(&rth, n, NULL);
be97f7
 	if ((ret < 0) && (errno == EEXIST))
be97f7
 		ret = 0;
be97f7
 
be97f7
@@ -2064,7 +2064,7 @@ static int ipaddr_modify(int cmd, int flags, int argc, char **argv)
be97f7
 		return -1;
be97f7
 	}
be97f7
 
be97f7
-	if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
be97f7
+	if (rtnl_talk(&rth, &req.n, NULL) < 0)
be97f7
 		return -2;
be97f7
 
be97f7
 	return 0;
be97f7
diff --git a/ip/ipaddrlabel.c b/ip/ipaddrlabel.c
be97f7
index 1d324da..6ea9bff 100644
be97f7
--- a/ip/ipaddrlabel.c
be97f7
+++ b/ip/ipaddrlabel.c
be97f7
@@ -176,7 +176,7 @@ static int ipaddrlabel_modify(int cmd, int argc, char **argv)
be97f7
 	if (req.ifal.ifal_family == AF_UNSPEC)
be97f7
 		req.ifal.ifal_family = AF_INET6;
be97f7
 
be97f7
-	if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
be97f7
+	if (rtnl_talk(&rth, &req.n, NULL) < 0)
be97f7
 		return -2;
be97f7
 
be97f7
 	return 0;
be97f7
@@ -203,7 +203,7 @@ static int flush_addrlabel(const struct sockaddr_nl *who, struct nlmsghdr *n, vo
be97f7
 		if (rtnl_open(&rth2, 0) < 0)
be97f7
 			return -1;
be97f7
 
be97f7
-		if (rtnl_talk(&rth2, n, NULL, 0) < 0)
be97f7
+		if (rtnl_talk(&rth2, n, NULL) < 0)
be97f7
 			return -2;
be97f7
 
be97f7
 		rtnl_close(&rth2;;
be97f7
diff --git a/ip/ipfou.c b/ip/ipfou.c
be97f7
index 00dbe15..23000dc 100644
be97f7
--- a/ip/ipfou.c
be97f7
+++ b/ip/ipfou.c
be97f7
@@ -116,7 +116,7 @@ static int do_add(int argc, char **argv)
be97f7
 
be97f7
 	fou_parse_opt(argc, argv, &req.n, true);
be97f7
 
be97f7
-	if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0)
be97f7
+	if (rtnl_talk(&genl_rth, &req.n, NULL) < 0)
be97f7
 		return -2;
be97f7
 
be97f7
 	return 0;
be97f7
@@ -128,7 +128,7 @@ static int do_del(int argc, char **argv)
be97f7
 
be97f7
 	fou_parse_opt(argc, argv, &req.n, false);
be97f7
 
be97f7
-	if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0)
be97f7
+	if (rtnl_talk(&genl_rth, &req.n, NULL) < 0)
be97f7
 		return -2;
be97f7
 
be97f7
 	return 0;
be97f7
diff --git a/ip/ipila.c b/ip/ipila.c
be97f7
index 843cc16..0403fc4 100644
be97f7
--- a/ip/ipila.c
be97f7
+++ b/ip/ipila.c
be97f7
@@ -220,7 +220,7 @@ static int do_add(int argc, char **argv)
be97f7
 
be97f7
 	ila_parse_opt(argc, argv, &req.n, true);
be97f7
 
be97f7
-	if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0)
be97f7
+	if (rtnl_talk(&genl_rth, &req.n, NULL) < 0)
be97f7
 		return -2;
be97f7
 
be97f7
 	return 0;
be97f7
@@ -232,7 +232,7 @@ static int do_del(int argc, char **argv)
be97f7
 
be97f7
 	ila_parse_opt(argc, argv, &req.n, false);
be97f7
 
be97f7
-	if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0)
be97f7
+	if (rtnl_talk(&genl_rth, &req.n, NULL) < 0)
be97f7
 		return -2;
be97f7
 
be97f7
 	return 0;
be97f7
diff --git a/ip/ipl2tp.c b/ip/ipl2tp.c
be97f7
index 88664c9..742adbe 100644
be97f7
--- a/ip/ipl2tp.c
be97f7
+++ b/ip/ipl2tp.c
be97f7
@@ -129,7 +129,7 @@ static int create_tunnel(struct l2tp_parm *p)
be97f7
 			addattr(&req.n, 1024, L2TP_ATTR_UDP_ZERO_CSUM6_RX);
be97f7
 	}
be97f7
 
be97f7
-	if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0)
be97f7
+	if (rtnl_talk(&genl_rth, &req.n, NULL) < 0)
be97f7
 		return -2;
be97f7
 
be97f7
 	return 0;
be97f7
@@ -142,7 +142,7 @@ static int delete_tunnel(struct l2tp_parm *p)
be97f7
 
be97f7
 	addattr32(&req.n, 128, L2TP_ATTR_CONN_ID, p->tunnel_id);
be97f7
 
be97f7
-	if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0)
be97f7
+	if (rtnl_talk(&genl_rth, &req.n, NULL) < 0)
be97f7
 		return -2;
be97f7
 
be97f7
 	return 0;
be97f7
@@ -185,7 +185,7 @@ static int create_session(struct l2tp_parm *p)
be97f7
 	if (p->ifname && p->ifname[0])
be97f7
 		addattrstrz(&req.n, 1024, L2TP_ATTR_IFNAME, p->ifname);
be97f7
 
be97f7
-	if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0)
be97f7
+	if (rtnl_talk(&genl_rth, &req.n, NULL) < 0)
be97f7
 		return -2;
be97f7
 
be97f7
 	return 0;
be97f7
@@ -198,7 +198,7 @@ static int delete_session(struct l2tp_parm *p)
be97f7
 
be97f7
 	addattr32(&req.n, 1024, L2TP_ATTR_CONN_ID, p->tunnel_id);
be97f7
 	addattr32(&req.n, 1024, L2TP_ATTR_SESSION_ID, p->session_id);
be97f7
-	if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0)
be97f7
+	if (rtnl_talk(&genl_rth, &req.n, NULL) < 0)
be97f7
 		return -2;
be97f7
 
be97f7
 	return 0;
be97f7
diff --git a/ip/iplink.c b/ip/iplink.c
be97f7
index 5afbadf..b08d227 100644
be97f7
--- a/ip/iplink.c
be97f7
+++ b/ip/iplink.c
be97f7
@@ -247,19 +247,26 @@ static int nl_get_ll_addr_len(unsigned int dev_index)
be97f7
 			.ifi_index = dev_index,
be97f7
 		}
be97f7
 	};
be97f7
+	struct nlmsghdr *answer;
be97f7
 	struct rtattr *tb[IFLA_MAX+1];
be97f7
 
be97f7
-	if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0)
be97f7
+	if (rtnl_talk(&rth, &req.n, &answer) < 0)
be97f7
 		return -1;
be97f7
 
be97f7
-	len = req.n.nlmsg_len - NLMSG_LENGTH(sizeof(req.i));
be97f7
-	if (len < 0)
be97f7
+	len = answer->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifinfomsg));
be97f7
+	if (len < 0) {
be97f7
+		free(answer);
be97f7
 		return -1;
be97f7
+	}
be97f7
 
be97f7
-	parse_rtattr_flags(tb, IFLA_MAX, IFLA_RTA(&req.i), len, NLA_F_NESTED);
be97f7
-	if (!tb[IFLA_ADDRESS])
be97f7
+	parse_rtattr_flags(tb, IFLA_MAX, IFLA_RTA(NLMSG_DATA(answer)),
be97f7
+			   len, NLA_F_NESTED);
be97f7
+	if (!tb[IFLA_ADDRESS]) {
be97f7
+		free(answer);
be97f7
 		return -1;
be97f7
+	}
be97f7
 
be97f7
+	free(answer);
be97f7
 	return RTA_PAYLOAD(tb[IFLA_ADDRESS]);
be97f7
 }
be97f7
 
be97f7
@@ -903,7 +910,7 @@ static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv)
be97f7
 
be97f7
 			req.i.ifi_index = 0;
be97f7
 			addattr32(&req.n, sizeof(req), IFLA_GROUP, group);
be97f7
-			if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
be97f7
+			if (rtnl_talk(&rth, &req.n, NULL) < 0)
be97f7
 				return -2;
be97f7
 			return 0;
be97f7
 		}
be97f7
@@ -998,7 +1005,7 @@ static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv)
be97f7
 		return -1;
be97f7
 	}
be97f7
 
be97f7
-	if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
be97f7
+	if (rtnl_talk(&rth, &req.n, NULL) < 0)
be97f7
 		return -2;
be97f7
 
be97f7
 	return 0;
be97f7
@@ -1013,10 +1020,7 @@ int iplink_get(unsigned int flags, char *name, __u32 filt_mask)
be97f7
 		.n.nlmsg_type = RTM_GETLINK,
be97f7
 		.i.ifi_family = preferred_family,
be97f7
 	};
be97f7
-	struct {
be97f7
-		struct nlmsghdr n;
be97f7
-		char buf[32768];
be97f7
-	} answer;
be97f7
+	struct nlmsghdr *answer;
be97f7
 
be97f7
 	if (name) {
be97f7
 		len = strlen(name) + 1;
be97f7
@@ -1029,19 +1033,15 @@ int iplink_get(unsigned int flags, char *name, __u32 filt_mask)
be97f7
 	}
be97f7
 	addattr32(&req.n, sizeof(req), IFLA_EXT_MASK, filt_mask);
be97f7
 
be97f7
-	if (rtnl_talk(&rth, &req.n, &answer.n, sizeof(answer)) < 0)
be97f7
-		return -2;
be97f7
-	if (answer.n.nlmsg_len > sizeof(answer.buf)) {
be97f7
-		fprintf(stderr, "Message truncated from %u to %lu\n",
be97f7
-			answer.n.nlmsg_len, sizeof(answer.buf));
be97f7
+	if (rtnl_talk(&rth, &req.n, &answer) < 0)
be97f7
 		return -2;
be97f7
-	}
be97f7
 
be97f7
 	if (brief)
be97f7
-		print_linkinfo_brief(NULL, &answer.n, stdout);
be97f7
+		print_linkinfo_brief(NULL, answer, stdout);
be97f7
 	else
be97f7
-		print_linkinfo(NULL, &answer.n, stdout);
be97f7
+		print_linkinfo(NULL, answer, stdout);
be97f7
 
be97f7
+	free(answer);
be97f7
 	return 0;
be97f7
 }
be97f7
 
be97f7
diff --git a/ip/iplink_vrf.c b/ip/iplink_vrf.c
be97f7
index 917630e..370bb86 100644
be97f7
--- a/ip/iplink_vrf.c
be97f7
+++ b/ip/iplink_vrf.c
be97f7
@@ -114,10 +114,7 @@ __u32 ipvrf_get_table(const char *name)
be97f7
 			.ifi_family  = preferred_family,
be97f7
 		},
be97f7
 	};
be97f7
-	struct {
be97f7
-		struct nlmsghdr n;
be97f7
-		char buf[8192];
be97f7
-	} answer;
be97f7
+	struct nlmsghdr *answer;
be97f7
 	struct rtattr *tb[IFLA_MAX+1];
be97f7
 	struct rtattr *li[IFLA_INFO_MAX+1];
be97f7
 	struct rtattr *vrf_attr[IFLA_VRF_MAX + 1];
be97f7
@@ -127,8 +124,7 @@ __u32 ipvrf_get_table(const char *name)
be97f7
 
be97f7
 	addattr_l(&req.n, sizeof(req), IFLA_IFNAME, name, strlen(name) + 1);
be97f7
 
be97f7
-	if (rtnl_talk_suppress_rtnl_errmsg(&rth, &req.n,
be97f7
-					   &answer.n, sizeof(answer)) < 0) {
be97f7
+	if (rtnl_talk_suppress_rtnl_errmsg(&rth, &req.n, &answer) < 0) {
be97f7
 		/* special case "default" vrf to be the main table */
be97f7
 		if (errno == ENODEV && !strcmp(name, "default"))
be97f7
 			rtnl_rttable_a2n(&tb_id, "main");
be97f7
@@ -136,25 +132,25 @@ __u32 ipvrf_get_table(const char *name)
be97f7
 		return tb_id;
be97f7
 	}
be97f7
 
be97f7
-	ifi = NLMSG_DATA(&answer.n);
be97f7
-	len = answer.n.nlmsg_len - NLMSG_LENGTH(sizeof(*ifi));
be97f7
+	ifi = NLMSG_DATA(answer);
be97f7
+	len = answer->nlmsg_len - NLMSG_LENGTH(sizeof(*ifi));
be97f7
 	if (len < 0) {
be97f7
 		fprintf(stderr, "BUG: Invalid response to link query.\n");
be97f7
-		return 0;
be97f7
+		goto out;
be97f7
 	}
be97f7
 
be97f7
 	parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
be97f7
 
be97f7
 	if (!tb[IFLA_LINKINFO])
be97f7
-		return 0;
be97f7
+		goto out;
be97f7
 
be97f7
 	parse_rtattr_nested(li, IFLA_INFO_MAX, tb[IFLA_LINKINFO]);
be97f7
 
be97f7
 	if (!li[IFLA_INFO_KIND] || !li[IFLA_INFO_DATA])
be97f7
-		return 0;
be97f7
+		goto out;
be97f7
 
be97f7
 	if (strcmp(RTA_DATA(li[IFLA_INFO_KIND]), "vrf"))
be97f7
-		return 0;
be97f7
+		goto out;
be97f7
 
be97f7
 	parse_rtattr_nested(vrf_attr, IFLA_VRF_MAX, li[IFLA_INFO_DATA]);
be97f7
 	if (vrf_attr[IFLA_VRF_TABLE])
be97f7
@@ -163,6 +159,8 @@ __u32 ipvrf_get_table(const char *name)
be97f7
 	if (!tb_id)
be97f7
 		fprintf(stderr, "BUG: VRF %s is missing table id\n", name);
be97f7
 
be97f7
+out:
be97f7
+	free(answer);
be97f7
 	return tb_id;
be97f7
 }
be97f7
 
be97f7
@@ -182,10 +180,7 @@ int name_is_vrf(const char *name)
be97f7
 			.ifi_family  = preferred_family,
be97f7
 		},
be97f7
 	};
be97f7
-	struct {
be97f7
-		struct nlmsghdr n;
be97f7
-		char buf[8192];
be97f7
-	} answer;
be97f7
+	struct nlmsghdr *answer;
be97f7
 	struct rtattr *tb[IFLA_MAX+1];
be97f7
 	struct rtattr *li[IFLA_INFO_MAX+1];
be97f7
 	struct ifinfomsg *ifi;
be97f7
@@ -193,29 +188,30 @@ int name_is_vrf(const char *name)
be97f7
 
be97f7
 	addattr_l(&req.n, sizeof(req), IFLA_IFNAME, name, strlen(name) + 1);
be97f7
 
be97f7
-	if (rtnl_talk_suppress_rtnl_errmsg(&rth, &req.n,
be97f7
-					   &answer.n, sizeof(answer)) < 0)
be97f7
+	if (rtnl_talk_suppress_rtnl_errmsg(&rth, &req.n, &answer) < 0)
be97f7
 		return 0;
be97f7
 
be97f7
-	ifi = NLMSG_DATA(&answer.n);
be97f7
-	len = answer.n.nlmsg_len - NLMSG_LENGTH(sizeof(*ifi));
be97f7
+	ifi = NLMSG_DATA(answer);
be97f7
+	len = answer->nlmsg_len - NLMSG_LENGTH(sizeof(*ifi));
be97f7
 	if (len < 0) {
be97f7
 		fprintf(stderr, "BUG: Invalid response to link query.\n");
be97f7
-		return 0;
be97f7
+		goto out;
be97f7
 	}
be97f7
 
be97f7
 	parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
be97f7
 
be97f7
 	if (!tb[IFLA_LINKINFO])
be97f7
-		return 0;
be97f7
+		goto out;
be97f7
 
be97f7
 	parse_rtattr_nested(li, IFLA_INFO_MAX, tb[IFLA_LINKINFO]);
be97f7
 
be97f7
 	if (!li[IFLA_INFO_KIND])
be97f7
-		return 0;
be97f7
+		goto out;
be97f7
 
be97f7
 	if (strcmp(RTA_DATA(li[IFLA_INFO_KIND]), "vrf"))
be97f7
-		return 0;
be97f7
+		goto out;
be97f7
 
be97f7
+out:
be97f7
+	free(answer);
be97f7
 	return ifi->ifi_index;
be97f7
 }
be97f7
diff --git a/ip/ipmacsec.c b/ip/ipmacsec.c
be97f7
index aa89a00..9a2d0eb 100644
be97f7
--- a/ip/ipmacsec.c
be97f7
+++ b/ip/ipmacsec.c
be97f7
@@ -421,7 +421,7 @@ static int do_modify_nl(enum cmd c, enum macsec_nl_commands cmd, int ifindex,
be97f7
 	addattr_nest_end(&req.n, attr_sa);
be97f7
 
be97f7
 talk:
be97f7
-	if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0)
be97f7
+	if (rtnl_talk(&genl_rth, &req.n, NULL) < 0)
be97f7
 		return -2;
be97f7
 
be97f7
 	return 0;
be97f7
diff --git a/ip/ipneigh.c b/ip/ipneigh.c
be97f7
index 9c38a60..32f2d55 100644
be97f7
--- a/ip/ipneigh.c
be97f7
+++ b/ip/ipneigh.c
be97f7
@@ -184,7 +184,7 @@ static int ipneigh_modify(int cmd, int flags, int argc, char **argv)
be97f7
 		return -1;
be97f7
 	}
be97f7
 
be97f7
-	if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
be97f7
+	if (rtnl_talk(&rth, &req.n, NULL) < 0)
be97f7
 		exit(2);
be97f7
 
be97f7
 	return 0;
be97f7
diff --git a/ip/ipnetns.c b/ip/ipnetns.c
be97f7
index 4254994..1c0ade9 100644
be97f7
--- a/ip/ipnetns.c
be97f7
+++ b/ip/ipnetns.c
be97f7
@@ -95,12 +95,13 @@ static int get_netnsid_from_name(const char *name)
be97f7
 		struct nlmsghdr n;
be97f7
 		struct rtgenmsg g;
be97f7
 		char            buf[1024];
be97f7
-	} answer, req = {
be97f7
+	} req = {
be97f7
 		.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)),
be97f7
 		.n.nlmsg_flags = NLM_F_REQUEST,
be97f7
 		.n.nlmsg_type = RTM_GETNSID,
be97f7
 		.g.rtgen_family = AF_UNSPEC,
be97f7
 	};
be97f7
+	struct nlmsghdr *answer;
be97f7
 	struct rtattr *tb[NETNSA_MAX + 1];
be97f7
 	struct rtgenmsg *rthdr;
be97f7
 	int len, fd;
be97f7
@@ -110,26 +111,30 @@ static int get_netnsid_from_name(const char *name)
be97f7
 		return fd;
be97f7
 
be97f7
 	addattr32(&req.n, 1024, NETNSA_FD, fd);
be97f7
-	if (rtnl_talk(&rtnsh, &req.n, &answer.n, sizeof(answer)) < 0) {
be97f7
+	if (rtnl_talk(&rtnsh, &req.n, &answer) < 0) {
be97f7
 		close(fd);
be97f7
 		return -2;
be97f7
 	}
be97f7
 	close(fd);
be97f7
 
be97f7
 	/* Validate message and parse attributes */
be97f7
-	if (answer.n.nlmsg_type == NLMSG_ERROR)
be97f7
-		return -1;
be97f7
+	if (answer->nlmsg_type == NLMSG_ERROR)
be97f7
+		goto err_out;
be97f7
 
be97f7
-	rthdr = NLMSG_DATA(&answer.n);
be97f7
-	len = answer.n.nlmsg_len - NLMSG_SPACE(sizeof(*rthdr));
be97f7
+	rthdr = NLMSG_DATA(answer);
be97f7
+	len = answer->nlmsg_len - NLMSG_SPACE(sizeof(*rthdr));
be97f7
 	if (len < 0)
be97f7
-		return -1;
be97f7
+		goto err_out;
be97f7
 
be97f7
 	parse_rtattr(tb, NETNSA_MAX, NETNS_RTA(rthdr), len);
be97f7
 
be97f7
-	if (tb[NETNSA_NSID])
be97f7
+	if (tb[NETNSA_NSID]) {
be97f7
+		free(answer);
be97f7
 		return rta_getattr_u32(tb[NETNSA_NSID]);
be97f7
+	}
be97f7
 
be97f7
+err_out:
be97f7
+	free(answer);
be97f7
 	return -1;
be97f7
 }
be97f7
 
be97f7
@@ -690,7 +695,7 @@ static int set_netnsid_from_name(const char *name, int nsid)
be97f7
 
be97f7
 	addattr32(&req.n, 1024, NETNSA_FD, fd);
be97f7
 	addattr32(&req.n, 1024, NETNSA_NSID, nsid);
be97f7
-	if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
be97f7
+	if (rtnl_talk(&rth, &req.n, NULL) < 0)
be97f7
 		err = -2;
be97f7
 
be97f7
 	close(fd);
be97f7
diff --git a/ip/ipntable.c b/ip/ipntable.c
be97f7
index 879626e..6506332 100644
be97f7
--- a/ip/ipntable.c
be97f7
+++ b/ip/ipntable.c
be97f7
@@ -306,7 +306,7 @@ static int ipntable_modify(int cmd, int flags, int argc, char **argv)
be97f7
 			  RTA_PAYLOAD(parms_rta));
be97f7
 	}
be97f7
 
be97f7
-	if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
be97f7
+	if (rtnl_talk(&rth, &req.n, NULL) < 0)
be97f7
 		exit(2);
be97f7
 
be97f7
 	return 0;
be97f7
diff --git a/ip/iproute.c b/ip/iproute.c
be97f7
index 5e23613..35fdce8 100644
be97f7
--- a/ip/iproute.c
be97f7
+++ b/ip/iproute.c
be97f7
@@ -1271,7 +1271,7 @@ static int iproute_modify(int cmd, unsigned int flags, int argc, char **argv)
be97f7
 	if (!type_ok && req.r.rtm_family == AF_MPLS)
be97f7
 		req.r.rtm_type = RTN_UNICAST;
be97f7
 
be97f7
-	if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
be97f7
+	if (rtnl_talk(&rth, &req.n, NULL) < 0)
be97f7
 		return -2;
be97f7
 
be97f7
 	return 0;
be97f7
@@ -1649,6 +1649,7 @@ static int iproute_get(int argc, char **argv)
be97f7
 	};
be97f7
 	char  *idev = NULL;
be97f7
 	char  *odev = NULL;
be97f7
+	struct nlmsghdr *answer;
be97f7
 	int connected = 0;
be97f7
 	int from_ok = 0;
be97f7
 	unsigned int mark = 0;
be97f7
@@ -1753,26 +1754,29 @@ static int iproute_get(int argc, char **argv)
be97f7
 
be97f7
 	req.r.rtm_flags |= RTM_F_LOOKUP_TABLE;
be97f7
 
be97f7
-	if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0)
be97f7
+	if (rtnl_talk(&rth, &req.n, &answer) < 0)
be97f7
 		return -2;
be97f7
 
be97f7
 	if (connected && !from_ok) {
be97f7
-		struct rtmsg *r = NLMSG_DATA(&req.n);
be97f7
-		int len = req.n.nlmsg_len;
be97f7
+		struct rtmsg *r = NLMSG_DATA(answer);
be97f7
+		int len = answer->nlmsg_len;
be97f7
 		struct rtattr *tb[RTA_MAX+1];
be97f7
 
be97f7
-		if (print_route(NULL, &req.n, (void *)stdout) < 0) {
be97f7
+		if (print_route(NULL, answer, (void *)stdout) < 0) {
be97f7
 			fprintf(stderr, "An error :-)\n");
be97f7
+			free(answer);
be97f7
 			return -1;
be97f7
 		}
be97f7
 
be97f7
-		if (req.n.nlmsg_type != RTM_NEWROUTE) {
be97f7
+		if (answer->nlmsg_type != RTM_NEWROUTE) {
be97f7
 			fprintf(stderr, "Not a route?\n");
be97f7
+			free(answer);
be97f7
 			return -1;
be97f7
 		}
be97f7
 		len -= NLMSG_LENGTH(sizeof(*r));
be97f7
 		if (len < 0) {
be97f7
 			fprintf(stderr, "Wrong len %d\n", len);
be97f7
+			free(answer);
be97f7
 			return -1;
be97f7
 		}
be97f7
 
be97f7
@@ -1783,6 +1787,7 @@ static int iproute_get(int argc, char **argv)
be97f7
 			r->rtm_src_len = 8*RTA_PAYLOAD(tb[RTA_PREFSRC]);
be97f7
 		} else if (!tb[RTA_SRC]) {
be97f7
 			fprintf(stderr, "Failed to connect the route\n");
be97f7
+			free(answer);
be97f7
 			return -1;
be97f7
 		}
be97f7
 		if (!odev && tb[RTA_OIF])
be97f7
@@ -1796,15 +1801,18 @@ static int iproute_get(int argc, char **argv)
be97f7
 		req.n.nlmsg_flags = NLM_F_REQUEST;
be97f7
 		req.n.nlmsg_type = RTM_GETROUTE;
be97f7
 
be97f7
-		if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0)
be97f7
+		free(answer);
be97f7
+		if (rtnl_talk(&rth, &req.n, &answer) < 0)
be97f7
 			return -2;
be97f7
 	}
be97f7
 
be97f7
-	if (print_route(NULL, &req.n, (void *)stdout) < 0) {
be97f7
+	if (print_route(NULL, answer, (void *)stdout) < 0) {
be97f7
 		fprintf(stderr, "An error :-)\n");
be97f7
+		free(answer);
be97f7
 		return -1;
be97f7
 	}
be97f7
 
be97f7
+	free(answer);
be97f7
 	return 0;
be97f7
 }
be97f7
 
be97f7
@@ -1848,7 +1856,7 @@ restore:
be97f7
 
be97f7
 	ll_init_map(&rth);
be97f7
 
be97f7
-	ret = rtnl_talk(&rth, n, n, sizeof(*n));
be97f7
+	ret = rtnl_talk(&rth, n, NULL);
be97f7
 	if ((ret < 0) && (errno == EEXIST))
be97f7
 		ret = 0;
be97f7
 
be97f7
diff --git a/ip/iprule.c b/ip/iprule.c
be97f7
index 8313138..e64b4d7 100644
be97f7
--- a/ip/iprule.c
be97f7
+++ b/ip/iprule.c
be97f7
@@ -393,7 +393,7 @@ static int flush_rule(const struct sockaddr_nl *who, struct nlmsghdr *n,
be97f7
 		if (rtnl_open(&rth2, 0) < 0)
be97f7
 			return -1;
be97f7
 
be97f7
-		if (rtnl_talk(&rth2, n, NULL, 0) < 0)
be97f7
+		if (rtnl_talk(&rth2, n, NULL) < 0)
be97f7
 			return -2;
be97f7
 
be97f7
 		rtnl_close(&rth2;;
be97f7
@@ -553,7 +553,7 @@ static int restore_handler(const struct sockaddr_nl *nl,
be97f7
 
be97f7
 	ll_init_map(&rth);
be97f7
 
be97f7
-	ret = rtnl_talk(&rth, n, n, sizeof(*n));
be97f7
+	ret = rtnl_talk(&rth, n, NULL);
be97f7
 	if ((ret < 0) && (errno == EEXIST))
be97f7
 		ret = 0;
be97f7
 
be97f7
@@ -760,7 +760,7 @@ static int iprule_modify(int cmd, int argc, char **argv)
be97f7
 	if (!table_ok && cmd == RTM_NEWRULE)
be97f7
 		req.r.rtm_table = RT_TABLE_MAIN;
be97f7
 
be97f7
-	if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
be97f7
+	if (rtnl_talk(&rth, &req.n, NULL) < 0)
be97f7
 		return -2;
be97f7
 
be97f7
 	return 0;
be97f7
diff --git a/ip/iptoken.c b/ip/iptoken.c
be97f7
index 1869f76..0528bad 100644
be97f7
--- a/ip/iptoken.c
be97f7
+++ b/ip/iptoken.c
be97f7
@@ -166,7 +166,7 @@ static int iptoken_set(int argc, char **argv, bool delete)
be97f7
 	addattr_nest_end(&req.n, afs6);
be97f7
 	addattr_nest_end(&req.n, afs);
be97f7
 
be97f7
-	if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
be97f7
+	if (rtnl_talk(&rth, &req.n, NULL) < 0)
be97f7
 		return -2;
be97f7
 
be97f7
 	return 0;
be97f7
diff --git a/ip/link_gre.c b/ip/link_gre.c
be97f7
index 35d437a..ced9936 100644
be97f7
--- a/ip/link_gre.c
be97f7
+++ b/ip/link_gre.c
be97f7
@@ -64,7 +64,6 @@ static int gre_parse_opt(struct link_util *lu, int argc, char **argv,
be97f7
 	struct {
be97f7
 		struct nlmsghdr n;
be97f7
 		struct ifinfomsg i;
be97f7
-		char buf[16384];
be97f7
 	} req = {
be97f7
 		.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi)),
be97f7
 		.n.nlmsg_flags = NLM_F_REQUEST,
be97f7
@@ -72,6 +71,7 @@ static int gre_parse_opt(struct link_util *lu, int argc, char **argv,
be97f7
 		.i.ifi_family = preferred_family,
be97f7
 		.i.ifi_index = ifi->ifi_index,
be97f7
 	};
be97f7
+	struct nlmsghdr *answer = NULL;
be97f7
 	struct rtattr *tb[IFLA_MAX + 1];
be97f7
 	struct rtattr *linkinfo[IFLA_INFO_MAX+1];
be97f7
 	struct rtattr *greinfo[IFLA_GRE_MAX + 1];
be97f7
@@ -93,19 +93,20 @@ static int gre_parse_opt(struct link_util *lu, int argc, char **argv,
be97f7
 	__u8 metadata = 0;
be97f7
 
be97f7
 	if (!(n->nlmsg_flags & NLM_F_CREATE)) {
be97f7
-		if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) {
be97f7
+		if (rtnl_talk(&rth, &req.n, &answer) < 0) {
be97f7
 get_failed:
be97f7
 			fprintf(stderr,
be97f7
 				"Failed to get existing tunnel info.\n");
be97f7
+			free(answer);
be97f7
 			return -1;
be97f7
 		}
be97f7
 
be97f7
-		len = req.n.nlmsg_len;
be97f7
+		len = answer->nlmsg_len;
be97f7
 		len -= NLMSG_LENGTH(sizeof(*ifi));
be97f7
 		if (len < 0)
be97f7
 			goto get_failed;
be97f7
 
be97f7
-		parse_rtattr(tb, IFLA_MAX, IFLA_RTA(&req.i), len);
be97f7
+		parse_rtattr(tb, IFLA_MAX, IFLA_RTA(NLMSG_DATA(answer)), len);
be97f7
 
be97f7
 		if (!tb[IFLA_LINKINFO])
be97f7
 			goto get_failed;
be97f7
@@ -160,6 +161,8 @@ get_failed:
be97f7
 
be97f7
 		if (greinfo[IFLA_GRE_COLLECT_METADATA])
be97f7
 			metadata = 1;
be97f7
+
be97f7
+		free(answer);
be97f7
 	}
be97f7
 
be97f7
 	while (argc > 0) {
be97f7
diff --git a/ip/link_gre6.c b/ip/link_gre6.c
be97f7
index fe3ab64..932f9ee 100644
be97f7
--- a/ip/link_gre6.c
be97f7
+++ b/ip/link_gre6.c
be97f7
@@ -76,7 +76,6 @@ static int gre_parse_opt(struct link_util *lu, int argc, char **argv,
be97f7
 	struct {
be97f7
 		struct nlmsghdr n;
be97f7
 		struct ifinfomsg i;
be97f7
-		char buf[1024];
be97f7
 	} req = {
be97f7
 		.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi)),
be97f7
 		.n.nlmsg_flags = NLM_F_REQUEST,
be97f7
@@ -84,6 +83,7 @@ static int gre_parse_opt(struct link_util *lu, int argc, char **argv,
be97f7
 		.i.ifi_family = preferred_family,
be97f7
 		.i.ifi_index = ifi->ifi_index,
be97f7
 	};
be97f7
+	struct nlmsghdr *answer = NULL;
be97f7
 	struct rtattr *tb[IFLA_MAX + 1];
be97f7
 	struct rtattr *linkinfo[IFLA_INFO_MAX+1];
be97f7
 	struct rtattr *greinfo[IFLA_GRE_MAX + 1];
be97f7
@@ -105,19 +105,20 @@ static int gre_parse_opt(struct link_util *lu, int argc, char **argv,
be97f7
 	int len;
be97f7
 
be97f7
 	if (!(n->nlmsg_flags & NLM_F_CREATE)) {
be97f7
-		if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) {
be97f7
+		if (rtnl_talk(&rth, &req.n, &answer) < 0) {
be97f7
 get_failed:
be97f7
 			fprintf(stderr,
be97f7
 				"Failed to get existing tunnel info.\n");
be97f7
+			free(answer);
be97f7
 			return -1;
be97f7
 		}
be97f7
 
be97f7
-		len = req.n.nlmsg_len;
be97f7
+		len = answer->nlmsg_len;
be97f7
 		len -= NLMSG_LENGTH(sizeof(*ifi));
be97f7
 		if (len < 0)
be97f7
 			goto get_failed;
be97f7
 
be97f7
-		parse_rtattr(tb, IFLA_MAX, IFLA_RTA(&req.i), len);
be97f7
+		parse_rtattr(tb, IFLA_MAX, IFLA_RTA(NLMSG_DATA(answer)), len);
be97f7
 
be97f7
 		if (!tb[IFLA_LINKINFO])
be97f7
 			goto get_failed;
be97f7
@@ -174,6 +175,8 @@ get_failed:
be97f7
 
be97f7
 		if (greinfo[IFLA_GRE_ENCAP_DPORT])
be97f7
 			encapdport = rta_getattr_u16(greinfo[IFLA_GRE_ENCAP_DPORT]);
be97f7
+
be97f7
+		free(answer);
be97f7
 	}
be97f7
 
be97f7
 	while (argc > 0) {
be97f7
diff --git a/ip/link_ip6tnl.c b/ip/link_ip6tnl.c
be97f7
index 6bb968d..2304364 100644
be97f7
--- a/ip/link_ip6tnl.c
be97f7
+++ b/ip/link_ip6tnl.c
be97f7
@@ -74,7 +74,6 @@ static int ip6tunnel_parse_opt(struct link_util *lu, int argc, char **argv,
be97f7
 	struct {
be97f7
 		struct nlmsghdr n;
be97f7
 		struct ifinfomsg i;
be97f7
-		char buf[2048];
be97f7
 	} req = {
be97f7
 		.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi)),
be97f7
 		.n.nlmsg_flags = NLM_F_REQUEST,
be97f7
@@ -82,6 +81,7 @@ static int ip6tunnel_parse_opt(struct link_util *lu, int argc, char **argv,
be97f7
 		.i.ifi_family = preferred_family,
be97f7
 		.i.ifi_index = ifi->ifi_index,
be97f7
 	};
be97f7
+	struct nlmsghdr *answer = NULL;
be97f7
 	struct rtattr *tb[IFLA_MAX + 1];
be97f7
 	struct rtattr *linkinfo[IFLA_INFO_MAX+1];
be97f7
 	struct rtattr *iptuninfo[IFLA_IPTUN_MAX + 1];
be97f7
@@ -101,19 +101,20 @@ static int ip6tunnel_parse_opt(struct link_util *lu, int argc, char **argv,
be97f7
 	__u8 metadata = 0;
be97f7
 
be97f7
 	if (!(n->nlmsg_flags & NLM_F_CREATE)) {
be97f7
-		if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) {
be97f7
+		if (rtnl_talk(&rth, &req.n, &answer) < 0) {
be97f7
 get_failed:
be97f7
 			fprintf(stderr,
be97f7
 				"Failed to get existing tunnel info.\n");
be97f7
+			free(answer);
be97f7
 			return -1;
be97f7
 		}
be97f7
 
be97f7
-		len = req.n.nlmsg_len;
be97f7
+		len = answer->nlmsg_len;
be97f7
 		len -= NLMSG_LENGTH(sizeof(*ifi));
be97f7
 		if (len < 0)
be97f7
 			goto get_failed;
be97f7
 
be97f7
-		parse_rtattr(tb, IFLA_MAX, IFLA_RTA(&req.i), len);
be97f7
+		parse_rtattr(tb, IFLA_MAX, IFLA_RTA(NLMSG_DATA(answer)), len);
be97f7
 
be97f7
 		if (!tb[IFLA_LINKINFO])
be97f7
 			goto get_failed;
be97f7
@@ -153,6 +154,8 @@ get_failed:
be97f7
 			proto = rta_getattr_u8(iptuninfo[IFLA_IPTUN_PROTO]);
be97f7
 		if (iptuninfo[IFLA_IPTUN_COLLECT_METADATA])
be97f7
 			metadata = 1;
be97f7
+
be97f7
+		free(answer);
be97f7
 	}
be97f7
 
be97f7
 	while (argc > 0) {
be97f7
diff --git a/ip/link_iptnl.c b/ip/link_iptnl.c
be97f7
index f180b92..528e287 100644
be97f7
--- a/ip/link_iptnl.c
be97f7
+++ b/ip/link_iptnl.c
be97f7
@@ -72,7 +72,6 @@ static int iptunnel_parse_opt(struct link_util *lu, int argc, char **argv,
be97f7
 	struct {
be97f7
 		struct nlmsghdr n;
be97f7
 		struct ifinfomsg i;
be97f7
-		char buf[2048];
be97f7
 	} req = {
be97f7
 		.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi)),
be97f7
 		.n.nlmsg_flags = NLM_F_REQUEST,
be97f7
@@ -80,6 +79,7 @@ static int iptunnel_parse_opt(struct link_util *lu, int argc, char **argv,
be97f7
 		.i.ifi_family = preferred_family,
be97f7
 		.i.ifi_index = ifi->ifi_index,
be97f7
 	};
be97f7
+	struct nlmsghdr *answer = NULL;
be97f7
 	struct rtattr *tb[IFLA_MAX + 1];
be97f7
 	struct rtattr *linkinfo[IFLA_INFO_MAX+1];
be97f7
 	struct rtattr *iptuninfo[IFLA_IPTUN_MAX + 1];
be97f7
@@ -103,19 +103,20 @@ static int iptunnel_parse_opt(struct link_util *lu, int argc, char **argv,
be97f7
 	__u8 metadata = 0;
be97f7
 
be97f7
 	if (!(n->nlmsg_flags & NLM_F_CREATE)) {
be97f7
-		if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) {
be97f7
+		if (rtnl_talk(&rth, &req.n, &answer) < 0) {
be97f7
 get_failed:
be97f7
 			fprintf(stderr,
be97f7
 				"Failed to get existing tunnel info.\n");
be97f7
+			free(answer);
be97f7
 			return -1;
be97f7
 		}
be97f7
 
be97f7
-		len = req.n.nlmsg_len;
be97f7
+		len = answer->nlmsg_len;
be97f7
 		len -= NLMSG_LENGTH(sizeof(*ifi));
be97f7
 		if (len < 0)
be97f7
 			goto get_failed;
be97f7
 
be97f7
-		parse_rtattr(tb, IFLA_MAX, IFLA_RTA(&req.i), len);
be97f7
+		parse_rtattr(tb, IFLA_MAX, IFLA_RTA(NLMSG_DATA(answer)), len);
be97f7
 
be97f7
 		if (!tb[IFLA_LINKINFO])
be97f7
 			goto get_failed;
be97f7
@@ -179,6 +180,8 @@ get_failed:
be97f7
 				rta_getattr_u16(iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]);
be97f7
 		if (iptuninfo[IFLA_IPTUN_COLLECT_METADATA])
be97f7
 			metadata = 1;
be97f7
+
be97f7
+		free(answer);
be97f7
 	}
be97f7
 
be97f7
 	while (argc > 0) {
be97f7
diff --git a/ip/link_vti.c b/ip/link_vti.c
be97f7
index 95bc23e..d2aacbe 100644
be97f7
--- a/ip/link_vti.c
be97f7
+++ b/ip/link_vti.c
be97f7
@@ -51,7 +51,6 @@ static int vti_parse_opt(struct link_util *lu, int argc, char **argv,
be97f7
 	struct {
be97f7
 		struct nlmsghdr n;
be97f7
 		struct ifinfomsg i;
be97f7
-		char buf[1024];
be97f7
 	} req = {
be97f7
 		.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi)),
be97f7
 		.n.nlmsg_flags = NLM_F_REQUEST,
be97f7
@@ -59,6 +58,7 @@ static int vti_parse_opt(struct link_util *lu, int argc, char **argv,
be97f7
 		.i.ifi_family = preferred_family,
be97f7
 		.i.ifi_index = ifi->ifi_index,
be97f7
 	};
be97f7
+	struct nlmsghdr *answer = NULL;
be97f7
 	struct rtattr *tb[IFLA_MAX + 1];
be97f7
 	struct rtattr *linkinfo[IFLA_INFO_MAX+1];
be97f7
 	struct rtattr *vtiinfo[IFLA_VTI_MAX + 1];
be97f7
@@ -70,19 +70,20 @@ static int vti_parse_opt(struct link_util *lu, int argc, char **argv,
be97f7
 	int len;
be97f7
 
be97f7
 	if (!(n->nlmsg_flags & NLM_F_CREATE)) {
be97f7
-		if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) {
be97f7
+		if (rtnl_talk(&rth, &req.n, &answer) < 0) {
be97f7
 get_failed:
be97f7
 			fprintf(stderr,
be97f7
 				"Failed to get existing tunnel info.\n");
be97f7
+			free(answer);
be97f7
 			return -1;
be97f7
 		}
be97f7
 
be97f7
-		len = req.n.nlmsg_len;
be97f7
+		len = answer->nlmsg_len;
be97f7
 		len -= NLMSG_LENGTH(sizeof(*ifi));
be97f7
 		if (len < 0)
be97f7
 			goto get_failed;
be97f7
 
be97f7
-		parse_rtattr(tb, IFLA_MAX, IFLA_RTA(&req.i), len);
be97f7
+		parse_rtattr(tb, IFLA_MAX, IFLA_RTA(NLMSG_DATA(answer)), len);
be97f7
 
be97f7
 		if (!tb[IFLA_LINKINFO])
be97f7
 			goto get_failed;
be97f7
@@ -109,6 +110,8 @@ get_failed:
be97f7
 
be97f7
 		if (vtiinfo[IFLA_VTI_LINK])
be97f7
 			link = rta_getattr_u8(vtiinfo[IFLA_VTI_LINK]);
be97f7
+
be97f7
+		free(answer);
be97f7
 	}
be97f7
 
be97f7
 	while (argc > 0) {
be97f7
diff --git a/ip/link_vti6.c b/ip/link_vti6.c
be97f7
index 9ca127a..aedfbea 100644
be97f7
--- a/ip/link_vti6.c
be97f7
+++ b/ip/link_vti6.c
be97f7
@@ -46,7 +46,6 @@ static int vti6_parse_opt(struct link_util *lu, int argc, char **argv,
be97f7
 	struct {
be97f7
 		struct nlmsghdr n;
be97f7
 		struct ifinfomsg i;
be97f7
-		char buf[1024];
be97f7
 	} req = {
be97f7
 		.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi)),
be97f7
 		.n.nlmsg_flags = NLM_F_REQUEST,
be97f7
@@ -54,6 +53,7 @@ static int vti6_parse_opt(struct link_util *lu, int argc, char **argv,
be97f7
 		.i.ifi_family = preferred_family,
be97f7
 		.i.ifi_index = ifi->ifi_index,
be97f7
 	};
be97f7
+	struct nlmsghdr *answer = NULL;
be97f7
 	struct rtattr *tb[IFLA_MAX + 1];
be97f7
 	struct rtattr *linkinfo[IFLA_INFO_MAX+1];
be97f7
 	struct rtattr *vtiinfo[IFLA_VTI_MAX + 1];
be97f7
@@ -65,19 +65,20 @@ static int vti6_parse_opt(struct link_util *lu, int argc, char **argv,
be97f7
 	int len;
be97f7
 
be97f7
 	if (!(n->nlmsg_flags & NLM_F_CREATE)) {
be97f7
-		if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) {
be97f7
+		if (rtnl_talk(&rth, &req.n, &answer) < 0) {
be97f7
 get_failed:
be97f7
 			fprintf(stderr,
be97f7
 				"Failed to get existing tunnel info.\n");
be97f7
+			free(answer);
be97f7
 			return -1;
be97f7
 		}
be97f7
 
be97f7
-		len = req.n.nlmsg_len;
be97f7
+		len = answer->nlmsg_len;
be97f7
 		len -= NLMSG_LENGTH(sizeof(*ifi));
be97f7
 		if (len < 0)
be97f7
 			goto get_failed;
be97f7
 
be97f7
-		parse_rtattr(tb, IFLA_MAX, IFLA_RTA(&req.i), len);
be97f7
+		parse_rtattr(tb, IFLA_MAX, IFLA_RTA(NLMSG_DATA(answer)), len);
be97f7
 
be97f7
 		if (!tb[IFLA_LINKINFO])
be97f7
 			goto get_failed;
be97f7
@@ -104,6 +105,8 @@ get_failed:
be97f7
 
be97f7
 		if (vtiinfo[IFLA_VTI_LINK])
be97f7
 			link = rta_getattr_u8(vtiinfo[IFLA_VTI_LINK]);
be97f7
+
be97f7
+		free(answer);
be97f7
 	}
be97f7
 
be97f7
 	while (argc > 0) {
be97f7
diff --git a/ip/tcp_metrics.c b/ip/tcp_metrics.c
be97f7
index 8972acd..3f9790e 100644
be97f7
--- a/ip/tcp_metrics.c
be97f7
+++ b/ip/tcp_metrics.c
be97f7
@@ -306,6 +306,7 @@ static int process_msg(const struct sockaddr_nl *who, struct nlmsghdr *n,
be97f7
 static int tcpm_do_cmd(int cmd, int argc, char **argv)
be97f7
 {
be97f7
 	TCPM_REQUEST(req, 1024, TCP_METRICS_CMD_GET, NLM_F_REQUEST);
be97f7
+	struct nlmsghdr *answer;
be97f7
 	int atype = -1, stype = -1;
be97f7
 	int ack;
be97f7
 
be97f7
@@ -457,15 +458,16 @@ static int tcpm_do_cmd(int cmd, int argc, char **argv)
be97f7
 	}
be97f7
 
be97f7
 	if (ack) {
be97f7
-		if (rtnl_talk(&grth, &req.n, NULL, 0) < 0)
be97f7
+		if (rtnl_talk(&grth, &req.n, NULL) < 0)
be97f7
 			return -2;
be97f7
 	} else if (atype >= 0) {
be97f7
-		if (rtnl_talk(&grth, &req.n, &req.n, sizeof(req)) < 0)
be97f7
+		if (rtnl_talk(&grth, &req.n, &answer) < 0)
be97f7
 			return -2;
be97f7
-		if (process_msg(NULL, &req.n, stdout) < 0) {
be97f7
+		if (process_msg(NULL, answer, stdout) < 0) {
be97f7
 			fprintf(stderr, "Dump terminated\n");
be97f7
 			exit(1);
be97f7
 		}
be97f7
+		free(answer);
be97f7
 	} else {
be97f7
 		req.n.nlmsg_seq = grth.dump = ++grth.seq;
be97f7
 		if (rtnl_send(&grth, &req, req.n.nlmsg_len) < 0) {
be97f7
diff --git a/ip/xfrm_policy.c b/ip/xfrm_policy.c
be97f7
index de689c4..98460a0 100644
be97f7
--- a/ip/xfrm_policy.c
be97f7
+++ b/ip/xfrm_policy.c
be97f7
@@ -386,7 +386,7 @@ static int xfrm_policy_modify(int cmd, unsigned int flags, int argc, char **argv
be97f7
 	if (req.xpinfo.sel.family == AF_UNSPEC)
be97f7
 		req.xpinfo.sel.family = AF_INET;
be97f7
 
be97f7
-	if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
be97f7
+	if (rtnl_talk(&rth, &req.n, NULL) < 0)
be97f7
 		exit(2);
be97f7
 
be97f7
 	rtnl_close(&rth);
be97f7
@@ -548,7 +548,7 @@ int xfrm_policy_print(const struct sockaddr_nl *who, struct nlmsghdr *n,
be97f7
 }
be97f7
 
be97f7
 static int xfrm_policy_get_or_delete(int argc, char **argv, int delete,
be97f7
-				     void *res_nlbuf, size_t res_size)
be97f7
+				     struct nlmsghdr **answer)
be97f7
 {
be97f7
 	struct rtnl_handle rth;
be97f7
 	struct {
be97f7
@@ -659,7 +659,7 @@ static int xfrm_policy_get_or_delete(int argc, char **argv, int delete,
be97f7
 			  (void *)&ctx, ctx.sctx.len);
be97f7
 	}
be97f7
 
be97f7
-	if (rtnl_talk(&rth, &req.n, res_nlbuf, res_size) < 0)
be97f7
+	if (rtnl_talk(&rth, &req.n, answer) < 0)
be97f7
 		exit(2);
be97f7
 
be97f7
 	rtnl_close(&rth);
be97f7
@@ -669,21 +669,21 @@ static int xfrm_policy_get_or_delete(int argc, char **argv, int delete,
be97f7
 
be97f7
 static int xfrm_policy_delete(int argc, char **argv)
be97f7
 {
be97f7
-	return xfrm_policy_get_or_delete(argc, argv, 1, NULL, 0);
be97f7
+	return xfrm_policy_get_or_delete(argc, argv, 1, NULL);
be97f7
 }
be97f7
 
be97f7
 static int xfrm_policy_get(int argc, char **argv)
be97f7
 {
be97f7
-	char buf[NLMSG_BUF_SIZE] = {};
be97f7
-	struct nlmsghdr *n = (struct nlmsghdr *)buf;
be97f7
+	struct nlmsghdr *n = NULL;
be97f7
 
be97f7
-	xfrm_policy_get_or_delete(argc, argv, 0, n, sizeof(buf));
be97f7
+	xfrm_policy_get_or_delete(argc, argv, 0, &n);
be97f7
 
be97f7
 	if (xfrm_policy_print(NULL, n, (void *)stdout) < 0) {
be97f7
 		fprintf(stderr, "An error :-)\n");
be97f7
 		exit(1);
be97f7
 	}
be97f7
 
be97f7
+	free(n);
be97f7
 	return 0;
be97f7
 }
be97f7
 
be97f7
@@ -1049,7 +1049,7 @@ static int xfrm_spd_setinfo(int argc, char **argv)
be97f7
 	if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
be97f7
 		exit(1);
be97f7
 
be97f7
-	if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
be97f7
+	if (rtnl_talk(&rth, &req.n, NULL) < 0)
be97f7
 		exit(2);
be97f7
 
be97f7
 	rtnl_close(&rth);
be97f7
@@ -1063,22 +1063,23 @@ static int xfrm_spd_getinfo(int argc, char **argv)
be97f7
 	struct {
be97f7
 		struct nlmsghdr			n;
be97f7
 		__u32				flags;
be97f7
-		char				ans[128];
be97f7
 	} req = {
be97f7
 		.n.nlmsg_len = NLMSG_LENGTH(sizeof(__u32)),
be97f7
 		.n.nlmsg_flags = NLM_F_REQUEST,
be97f7
 		.n.nlmsg_type = XFRM_MSG_GETSPDINFO,
be97f7
 		.flags = 0XFFFFFFFF,
be97f7
 	};
be97f7
+	struct nlmsghdr *answer;
be97f7
 
be97f7
 	if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
be97f7
 		exit(1);
be97f7
 
be97f7
-	if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0)
be97f7
+	if (rtnl_talk(&rth, &req.n, &answer) < 0)
be97f7
 		exit(2);
be97f7
 
be97f7
-	print_spdinfo(&req.n, (void *)stdout);
be97f7
+	print_spdinfo(answer, (void *)stdout);
be97f7
 
be97f7
+	free(answer);
be97f7
 	rtnl_close(&rth);
be97f7
 
be97f7
 	return 0;
be97f7
@@ -1123,7 +1124,7 @@ static int xfrm_policy_flush(int argc, char **argv)
be97f7
 	if (show_stats > 1)
be97f7
 		fprintf(stderr, "Flush policy\n");
be97f7
 
be97f7
-	if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
be97f7
+	if (rtnl_talk(&rth, &req.n, NULL) < 0)
be97f7
 		exit(2);
be97f7
 
be97f7
 	rtnl_close(&rth);
be97f7
diff --git a/ip/xfrm_state.c b/ip/xfrm_state.c
be97f7
index ea7d4f3..04ed349 100644
be97f7
--- a/ip/xfrm_state.c
be97f7
+++ b/ip/xfrm_state.c
be97f7
@@ -677,7 +677,7 @@ static int xfrm_state_modify(int cmd, unsigned int flags, int argc, char **argv)
be97f7
 	if (req.xsinfo.family == AF_UNSPEC)
be97f7
 		req.xsinfo.family = AF_INET;
be97f7
 
be97f7
-	if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
be97f7
+	if (rtnl_talk(&rth, &req.n, NULL) < 0)
be97f7
 		exit(2);
be97f7
 
be97f7
 	rtnl_close(&rth);
be97f7
@@ -708,8 +708,7 @@ static int xfrm_state_allocspi(int argc, char **argv)
be97f7
 	char *minp = NULL;
be97f7
 	char *maxp = NULL;
be97f7
 	struct xfrm_mark mark = {0, 0};
be97f7
-	char res_buf[NLMSG_BUF_SIZE] = {};
be97f7
-	struct nlmsghdr *res_n = (struct nlmsghdr *)res_buf;
be97f7
+	struct nlmsghdr *answer;
be97f7
 
be97f7
 	while (argc > 0) {
be97f7
 		if (strcmp(*argv, "mode") == 0) {
be97f7
@@ -809,14 +808,15 @@ static int xfrm_state_allocspi(int argc, char **argv)
be97f7
 		req.xspi.info.family = AF_INET;
be97f7
 
be97f7
 
be97f7
-	if (rtnl_talk(&rth, &req.n, res_n, sizeof(res_buf)) < 0)
be97f7
+	if (rtnl_talk(&rth, &req.n, &answer) < 0)
be97f7
 		exit(2);
be97f7
 
be97f7
-	if (xfrm_state_print(NULL, res_n, (void *)stdout) < 0) {
be97f7
+	if (xfrm_state_print(NULL, answer, (void *)stdout) < 0) {
be97f7
 		fprintf(stderr, "An error :-)\n");
be97f7
 		exit(1);
be97f7
 	}
be97f7
 
be97f7
+	free(answer);
be97f7
 	rtnl_close(&rth);
be97f7
 
be97f7
 	return 0;
be97f7
@@ -997,19 +997,20 @@ static int xfrm_state_get_or_delete(int argc, char **argv, int delete)
be97f7
 		req.xsid.family = AF_INET;
be97f7
 
be97f7
 	if (delete) {
be97f7
-		if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
be97f7
+		if (rtnl_talk(&rth, &req.n, NULL) < 0)
be97f7
 			exit(2);
be97f7
 	} else {
be97f7
-		char buf[NLMSG_BUF_SIZE] = {};
be97f7
-		struct nlmsghdr *res_n = (struct nlmsghdr *)buf;
be97f7
+		struct nlmsghdr *answer;
be97f7
 
be97f7
-		if (rtnl_talk(&rth, &req.n, res_n, sizeof(req)) < 0)
be97f7
+		if (rtnl_talk(&rth, &req.n, &answer) < 0)
be97f7
 			exit(2);
be97f7
 
be97f7
-		if (xfrm_state_print(NULL, res_n, (void *)stdout) < 0) {
be97f7
+		if (xfrm_state_print(NULL, answer, (void *)stdout) < 0) {
be97f7
 			fprintf(stderr, "An error :-)\n");
be97f7
 			exit(1);
be97f7
 		}
be97f7
+
be97f7
+		free(answer);
be97f7
 	}
be97f7
 
be97f7
 	rtnl_close(&rth);
be97f7
@@ -1265,22 +1266,23 @@ static int xfrm_sad_getinfo(int argc, char **argv)
be97f7
 	struct {
be97f7
 		struct nlmsghdr			n;
be97f7
 		__u32				flags;
be97f7
-		char				ans[64];
be97f7
 	} req = {
be97f7
 		.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.flags)),
be97f7
 		.n.nlmsg_flags = NLM_F_REQUEST,
be97f7
 		.n.nlmsg_type = XFRM_MSG_GETSADINFO,
be97f7
 		.flags = 0XFFFFFFFF,
be97f7
 	};
be97f7
+	struct nlmsghdr *answer;
be97f7
 
be97f7
 	if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
be97f7
 		exit(1);
be97f7
 
be97f7
-	if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0)
be97f7
+	if (rtnl_talk(&rth, &req.n, &answer) < 0)
be97f7
 		exit(2);
be97f7
 
be97f7
-	print_sadinfo(&req.n, (void *)stdout);
be97f7
+	print_sadinfo(answer, (void *)stdout);
be97f7
 
be97f7
+	free(answer);
be97f7
 	rtnl_close(&rth);
be97f7
 
be97f7
 	return 0;
be97f7
@@ -1327,7 +1329,7 @@ static int xfrm_state_flush(int argc, char **argv)
be97f7
 		fprintf(stderr, "Flush state with XFRM-PROTO value \"%s\"\n",
be97f7
 			strxf_xfrmproto(req.xsf.proto));
be97f7
 
be97f7
-	if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
be97f7
+	if (rtnl_talk(&rth, &req.n, NULL) < 0)
be97f7
 		exit(2);
be97f7
 
be97f7
 	rtnl_close(&rth);
be97f7
diff --git a/lib/libgenl.c b/lib/libgenl.c
be97f7
index 50d2d92..bb5fbb5 100644
be97f7
--- a/lib/libgenl.c
be97f7
+++ b/lib/libgenl.c
be97f7
@@ -49,16 +49,21 @@ int genl_resolve_family(struct rtnl_handle *grth, const char *family)
be97f7
 {
be97f7
 	GENL_REQUEST(req, 1024, GENL_ID_CTRL, 0, 0, CTRL_CMD_GETFAMILY,
be97f7
 		     NLM_F_REQUEST);
be97f7
+	struct nlmsghdr *answer;
be97f7
+	int fnum;
be97f7
 
be97f7
 	addattr_l(&req.n, sizeof(req), CTRL_ATTR_FAMILY_NAME,
be97f7
 		  family, strlen(family) + 1);
be97f7
 
be97f7
-	if (rtnl_talk(grth, &req.n, &req.n, sizeof(req)) < 0) {
be97f7
+	if (rtnl_talk(grth, &req.n, &answer) < 0) {
be97f7
 		fprintf(stderr, "Error talking to the kernel\n");
be97f7
 		return -2;
be97f7
 	}
be97f7
 
be97f7
-	return genl_parse_getfamily(&req.n);
be97f7
+	fnum = genl_parse_getfamily(answer);
be97f7
+	free(answer);
be97f7
+
be97f7
+	return fnum;
be97f7
 }
be97f7
 
be97f7
 int genl_init_handle(struct rtnl_handle *grth, const char *family,
be97f7
diff --git a/lib/libnetlink.c b/lib/libnetlink.c
be97f7
index 446c960..75e20ab 100644
be97f7
--- a/lib/libnetlink.c
be97f7
+++ b/lib/libnetlink.c
be97f7
@@ -561,7 +561,7 @@ static void rtnl_talk_error(struct nlmsghdr *h, struct nlmsgerr *err,
be97f7
 }
be97f7
 
be97f7
 static int __rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n,
be97f7
-		       struct nlmsghdr *answer, size_t maxlen,
be97f7
+		       struct nlmsghdr **answer,
be97f7
 		       bool show_rtnl_err, nl_ext_ack_fn_t errfn)
be97f7
 {
be97f7
 	int status;
be97f7
@@ -635,9 +635,9 @@ static int __rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n,
be97f7
 					fprintf(stderr, "ERROR truncated\n");
be97f7
 				} else if (!err->error) {
be97f7
 					if (answer)
be97f7
-						memcpy(answer, h,
be97f7
-						       MIN(maxlen, h->nlmsg_len));
be97f7
-					free(buf);
be97f7
+						*answer = (struct nlmsghdr *)buf;
be97f7
+					else
be97f7
+						free(buf);
be97f7
 					return 0;
be97f7
 				}
be97f7
 
be97f7
@@ -651,9 +651,7 @@ static int __rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n,
be97f7
 			}
be97f7
 
be97f7
 			if (answer) {
be97f7
-				memcpy(answer, h,
be97f7
-				       MIN(maxlen, h->nlmsg_len));
be97f7
-				free(buf);
be97f7
+				*answer = (struct nlmsghdr *)buf;
be97f7
 				return 0;
be97f7
 			}
be97f7
 
be97f7
@@ -677,22 +675,22 @@ static int __rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n,
be97f7
 }
be97f7
 
be97f7
 int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n,
be97f7
-	      struct nlmsghdr *answer, size_t maxlen)
be97f7
+	      struct nlmsghdr **answer)
be97f7
 {
be97f7
-	return __rtnl_talk(rtnl, n, answer, maxlen, true, NULL);
be97f7
+	return __rtnl_talk(rtnl, n, answer, true, NULL);
be97f7
 }
be97f7
 
be97f7
 int rtnl_talk_extack(struct rtnl_handle *rtnl, struct nlmsghdr *n,
be97f7
-		     struct nlmsghdr *answer, size_t maxlen,
be97f7
+		     struct nlmsghdr **answer,
be97f7
 		     nl_ext_ack_fn_t errfn)
be97f7
 {
be97f7
-	return __rtnl_talk(rtnl, n, answer, maxlen, true, errfn);
be97f7
+	return __rtnl_talk(rtnl, n, answer, true, errfn);
be97f7
 }
be97f7
 
be97f7
 int rtnl_talk_suppress_rtnl_errmsg(struct rtnl_handle *rtnl, struct nlmsghdr *n,
be97f7
-				   struct nlmsghdr *answer, size_t maxlen)
be97f7
+				   struct nlmsghdr **answer)
be97f7
 {
be97f7
-	return __rtnl_talk(rtnl, n, answer, maxlen, false, NULL);
be97f7
+	return __rtnl_talk(rtnl, n, answer, false, NULL);
be97f7
 }
be97f7
 
be97f7
 int rtnl_listen_all_nsid(struct rtnl_handle *rth)
be97f7
diff --git a/misc/ss.c b/misc/ss.c
be97f7
index b84baf3..d3fb9a7 100644
be97f7
--- a/misc/ss.c
be97f7
+++ b/misc/ss.c
be97f7
@@ -2588,7 +2588,7 @@ static int kill_inet_sock(struct nlmsghdr *h, void *arg, struct sockstat *s)
be97f7
 		raw->sdiag_raw_protocol = s->raw_prot;
be97f7
 	}
be97f7
 
be97f7
-	return rtnl_talk(rth, &req.nlh, NULL, 0);
be97f7
+	return rtnl_talk(rth, &req.nlh, NULL);
be97f7
 }
be97f7
 
be97f7
 static int show_one_inet_sock(const struct sockaddr_nl *addr,
be97f7
diff --git a/tc/m_action.c b/tc/m_action.c
be97f7
index 6ebe85e..90b2a11 100644
be97f7
--- a/tc/m_action.c
be97f7
+++ b/tc/m_action.c
be97f7
@@ -506,18 +506,18 @@ static int tc_action_gd(int cmd, unsigned int flags, int *argc_p, char ***argv_p
be97f7
 	tail->rta_len = (void *) NLMSG_TAIL(&req.n) - (void *) tail;
be97f7
 
be97f7
 	req.n.nlmsg_seq = rth.dump = ++rth.seq;
be97f7
-	if (cmd == RTM_GETACTION)
be97f7
-		ans = &req.n;
be97f7
 
be97f7
-	if (rtnl_talk(&rth, &req.n, ans, MAX_MSG) < 0) {
be97f7
+	if (rtnl_talk(&rth, &req.n, &ans) < 0) {
be97f7
 		fprintf(stderr, "We have an error talking to the kernel\n");
be97f7
 		return 1;
be97f7
 	}
be97f7
 
be97f7
-	if (ans && print_action(NULL, &req.n, (void *)stdout) < 0) {
be97f7
+	if (cmd == RTM_GETACTION && print_action(NULL, ans, stdout) < 0) {
be97f7
 		fprintf(stderr, "Dump terminated\n");
be97f7
+		free(ans);
be97f7
 		return 1;
be97f7
 	}
be97f7
+	free(ans);
be97f7
 
be97f7
 	*argc_p = argc;
be97f7
 	*argv_p = argv;
be97f7
@@ -550,7 +550,7 @@ static int tc_action_modify(int cmd, unsigned int flags, int *argc_p, char ***ar
be97f7
 	}
be97f7
 	tail->rta_len = (void *) NLMSG_TAIL(&req.n) - (void *) tail;
be97f7
 
be97f7
-	if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) {
be97f7
+	if (rtnl_talk(&rth, &req.n, NULL) < 0) {
be97f7
 		fprintf(stderr, "We have an error talking to the kernel\n");
be97f7
 		ret = -1;
be97f7
 	}
be97f7
@@ -617,7 +617,7 @@ static int tc_act_list_or_flush(int argc, char **argv, int event)
be97f7
 		req.n.nlmsg_type = RTM_DELACTION;
be97f7
 		req.n.nlmsg_flags |= NLM_F_ROOT;
be97f7
 		req.n.nlmsg_flags |= NLM_F_REQUEST;
be97f7
-		if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) {
be97f7
+		if (rtnl_talk(&rth, &req.n, NULL) < 0) {
be97f7
 			fprintf(stderr, "We have an error flushing\n");
be97f7
 			return 1;
be97f7
 		}
be97f7
diff --git a/tc/tc_class.c b/tc/tc_class.c
be97f7
index 1a1f1fa..0214775 100644
be97f7
--- a/tc/tc_class.c
be97f7
+++ b/tc/tc_class.c
be97f7
@@ -149,7 +149,7 @@ static int tc_class_modify(int cmd, unsigned int flags, int argc, char **argv)
be97f7
 		}
be97f7
 	}
be97f7
 
be97f7
-	if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
be97f7
+	if (rtnl_talk(&rth, &req.n, NULL) < 0)
be97f7
 		return 2;
be97f7
 
be97f7
 	return 0;
be97f7
diff --git a/tc/tc_filter.c b/tc/tc_filter.c
be97f7
index ff8713b..e640492 100644
be97f7
--- a/tc/tc_filter.c
be97f7
+++ b/tc/tc_filter.c
be97f7
@@ -181,7 +181,7 @@ static int tc_filter_modify(int cmd, unsigned int flags, int argc, char **argv)
be97f7
 		}
be97f7
 	}
be97f7
 
be97f7
-	if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) {
be97f7
+	if (rtnl_talk(&rth, &req.n, NULL) < 0) {
be97f7
 		fprintf(stderr, "We have an error talking to the kernel\n");
be97f7
 		return 2;
be97f7
 	}
be97f7
@@ -307,6 +307,7 @@ static int tc_filter_get(int cmd, unsigned int flags, int argc, char **argv)
be97f7
 		.t.tcm_parent = TC_H_UNSPEC,
be97f7
 		.t.tcm_family = AF_UNSPEC,
be97f7
 	};
be97f7
+	struct nlmsghdr *answer;
be97f7
 	struct filter_util *q = NULL;
be97f7
 	__u32 prio = 0;
be97f7
 	__u32 protocol = 0;
be97f7
@@ -445,13 +446,14 @@ static int tc_filter_get(int cmd, unsigned int flags, int argc, char **argv)
be97f7
 		return -1;
be97f7
 	}
be97f7
 
be97f7
-	if (rtnl_talk(&rth, &req.n, &req.n, MAX_MSG) < 0) {
be97f7
+	if (rtnl_talk(&rth, &req.n, &answer) < 0) {
be97f7
 		fprintf(stderr, "We have an error talking to the kernel\n");
be97f7
 		return 2;
be97f7
 	}
be97f7
 
be97f7
-	print_filter(NULL, &req.n, (void *)stdout);
be97f7
+	print_filter(NULL, answer, (void *)stdout);
be97f7
 
be97f7
+	free(answer);
be97f7
 	return 0;
be97f7
 }
be97f7
 
be97f7
diff --git a/tc/tc_qdisc.c b/tc/tc_qdisc.c
be97f7
index 3a3701c..8b0c5c7 100644
be97f7
--- a/tc/tc_qdisc.c
be97f7
+++ b/tc/tc_qdisc.c
be97f7
@@ -190,7 +190,7 @@ static int tc_qdisc_modify(int cmd, unsigned int flags, int argc, char **argv)
be97f7
 		req.t.tcm_ifindex = idx;
be97f7
 	}
be97f7
 
be97f7
-	if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
be97f7
+	if (rtnl_talk(&rth, &req.n, NULL) < 0)
be97f7
 		return 2;
be97f7
 
be97f7
 	return 0;
be97f7
-- 
be97f7
1.8.3.1
be97f7