naccyde / rpms / iproute

Forked from rpms/iproute 5 months ago
Clone

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

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