From 02706ec0fb133392a6c49c4fa45ce65831e160a4 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Jun 23 2016 14:56:51 +0000 Subject: import iproute-3.10.0-54.el7_2.1 --- diff --git a/SOURCES/iproute2-ipaddress-fix-ipaddr_flush-for-Linux-3.1.patch b/SOURCES/iproute2-ipaddress-fix-ipaddr_flush-for-Linux-3.1.patch new file mode 100644 index 0000000..fd108c8 --- /dev/null +++ b/SOURCES/iproute2-ipaddress-fix-ipaddr_flush-for-Linux-3.1.patch @@ -0,0 +1,167 @@ +From 1a47c83cc1e59314c318f29b7cec49a58c6d1af8 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Wed, 17 Feb 2016 14:03:59 +0100 +Subject: [PATCH] ipaddress: fix ipaddr_flush for Linux >= 3.1 + +This is a combination of 3 commits: + +commit 8e72880f6bfa39f439b9c4a88eb84b635b991687 +Author: Phil Sutter +Date: Tue Nov 24 15:31:01 2015 +0100 + + libnetlink: introduce nc_flags + + Allow for a filter to ignore certain nlmsg_flags. + + Signed-off-by: Phil Sutter + +commit c6995c48025233902a5b0c5fe88654e17ea934f6 +Author: Phil Sutter +Date: Tue Nov 24 15:31:00 2015 +0100 + + ipaddress: simplify ipaddr_flush() + + Since it's no longer relevant whether an IP address is primary or + secondary when flushing, ipaddr_flush() can be simplified a bit. + + Signed-off-by: Phil Sutter + +commit d25ec03e1dce4cf22093a9f7106e9401ab5bf066 +Author: Phil Sutter +Date: Tue Nov 24 15:31:02 2015 +0100 + + ipaddress: fix ipaddr_flush for Linux >= 3.1 + + Linux version 3.1 introduced a consistency check for netlink dumps in + commit 670dc28 ("netlink: advertise incomplete dumps"). This bites + iproute2 when flushing more addresses than can fit into a single + RTM_GETADDR response. To silence the spurious error message "Dump was + interrupted and may be inconsistent.", advise rtnl_dump_filter_l() to + not care about NLM_F_DUMP_INTR. + + Signed-off-by: Phil Sutter +--- + include/libnetlink.h | 8 ++++++-- + ip/ipaddress.c | 39 ++------------------------------------- + lib/libnetlink.c | 10 ++++++---- + 3 files changed, 14 insertions(+), 43 deletions(-) + +diff --git a/include/libnetlink.h b/include/libnetlink.h +index 95f41d979828f..b008b93f4e65e 100644 +--- a/include/libnetlink.h ++++ b/include/libnetlink.h +@@ -48,12 +48,16 @@ struct rtnl_dump_filter_arg + { + rtnl_filter_t filter; + void *arg1; ++ __u16 nc_flags; + }; + + extern int rtnl_dump_filter_l(struct rtnl_handle *rth, + const struct rtnl_dump_filter_arg *arg); +-extern int rtnl_dump_filter(struct rtnl_handle *rth, rtnl_filter_t filter, +- void *arg); ++int rtnl_dump_filter_nc(struct rtnl_handle *rth, ++ rtnl_filter_t filter, ++ void *arg, __u16 nc_flags); ++#define rtnl_dump_filter(rth, filter, arg) \ ++ rtnl_dump_filter_nc(rth, filter, arg, 0) + extern int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, + struct nlmsghdr *answer, size_t len); + extern int rtnl_send(struct rtnl_handle *rth, const void *buf, int); +diff --git a/ip/ipaddress.c b/ip/ipaddress.c +index 94ff53898a915..533c72c5b1c0f 100644 +--- a/ip/ipaddress.c ++++ b/ip/ipaddress.c +@@ -875,28 +875,6 @@ int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n, + return 0; + } + +-static int print_addrinfo_primary(const struct sockaddr_nl *who, +- struct nlmsghdr *n, void *arg) +-{ +- struct ifaddrmsg *ifa = NLMSG_DATA(n); +- +- if (ifa->ifa_flags & IFA_F_SECONDARY) +- return 0; +- +- return print_addrinfo(who, n, arg); +-} +- +-static int print_addrinfo_secondary(const struct sockaddr_nl *who, +- struct nlmsghdr *n, void *arg) +-{ +- struct ifaddrmsg *ifa = NLMSG_DATA(n); +- +- if (!(ifa->ifa_flags & IFA_F_SECONDARY)) +- return 0; +- +- return print_addrinfo(who, n, arg); +-} +- + struct nlmsg_list + { + struct nlmsg_list *next; +@@ -1139,26 +1117,13 @@ static int ipaddr_flush(void) + filter.flushe = sizeof(flushb); + + while ((max_flush_loops == 0) || (round < max_flush_loops)) { +- const struct rtnl_dump_filter_arg a[3] = { +- { +- .filter = print_addrinfo_secondary, +- .arg1 = stdout, +- }, +- { +- .filter = print_addrinfo_primary, +- .arg1 = stdout, +- }, +- { +- .filter = NULL, +- .arg1 = NULL, +- }, +- }; + if (rtnl_wilddump_request(&rth, filter.family, RTM_GETADDR) < 0) { + perror("Cannot send dump request"); + exit(1); + } + filter.flushed = 0; +- if (rtnl_dump_filter_l(&rth, a) < 0) { ++ if (rtnl_dump_filter_nc(&rth, print_addrinfo, ++ stdout, NLM_F_DUMP_INTR) < 0) { + fprintf(stderr, "Flush terminated\n"); + exit(1); + } +diff --git a/lib/libnetlink.c b/lib/libnetlink.c +index c455a41eccfdd..ebe3c120aa96b 100644 +--- a/lib/libnetlink.c ++++ b/lib/libnetlink.c +@@ -234,6 +234,8 @@ int rtnl_dump_filter_l(struct rtnl_handle *rth, + while (NLMSG_OK(h, msglen)) { + int err; + ++ h->nlmsg_flags &= ~a->nc_flags; ++ + if (nladdr.nl_pid != 0 || + h->nlmsg_pid != rth->local.nl_pid || + h->nlmsg_seq != rth->dump) +@@ -284,13 +286,13 @@ skip_it: + } + } + +-int rtnl_dump_filter(struct rtnl_handle *rth, ++int rtnl_dump_filter_nc(struct rtnl_handle *rth, + rtnl_filter_t filter, +- void *arg1) ++ void *arg1, __u16 nc_flags) + { + const struct rtnl_dump_filter_arg a[2] = { +- { .filter = filter, .arg1 = arg1, }, +- { .filter = NULL, .arg1 = NULL, }, ++ { .filter = filter, .arg1 = arg1, .nc_flags = nc_flags, }, ++ { .filter = NULL, .arg1 = NULL, .nc_flags = 0, }, + }; + + return rtnl_dump_filter_l(rth, a); +-- +2.8.2 + diff --git a/SOURCES/iproute2-libnetlink-add-size-argument-to-rtnl_talk.patch b/SOURCES/iproute2-libnetlink-add-size-argument-to-rtnl_talk.patch new file mode 100644 index 0000000..a58eaf9 --- /dev/null +++ b/SOURCES/iproute2-libnetlink-add-size-argument-to-rtnl_talk.patch @@ -0,0 +1,804 @@ +From 59e3f63d49e544e62f6ff51786594dace8aa9175 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 11 Feb 2016 15:17:02 +0100 +Subject: [PATCH] libnetlink: add size argument to rtnl_talk + +This is a combination of 2 commits: + +commit c079e121a73af5eb49e003b13607e8a690331df6 +Author: Stephen Hemminger +Date: Wed May 27 12:26:14 2015 -0700 + + libnetlink: add size argument to rtnl_talk + + There have been several instances where response from kernel + has overrun the stack buffer from the caller. Avoid future problems + by passing a size argument. + + Also drop the unused peer and group arguments to rtnl_talk. + +commit ed108cfc0260b6b751647982b77d6363b1defb15 +Author: Nicolas Dichtel +Date: Thu Dec 3 17:13:48 2015 +0100 + + libnetlink: don't confuse variables in rtnl_talk() + + There is two variables named 'len' in rtnl_talk. In fact, commit + c079e121a73a didn't work. For example, it was possible to trigger + a seg fault with this command: + $ ip link set gre2 type ip6gre hoplimit 32 + + Let's rename the argument len to maxlen. + + Fixes: c079e121a73a ("libnetlink: add size argument to rtnl_talk") + Reported-by: Thomas Faivre + Signed-off-by: Nicolas Dichtel +--- + bridge/fdb.c | 2 +- + bridge/link.c | 2 +- + bridge/mdb.c | 2 +- + bridge/vlan.c | 2 +- + genl/ctrl.c | 4 ++-- + include/libnetlink.h | 4 ++-- + ip/ipaddress.c | 4 ++-- + ip/ipaddrlabel.c | 4 ++-- + ip/ipl2tp.c | 8 ++++---- + ip/iplink.c | 4 ++-- + ip/ipneigh.c | 2 +- + ip/ipnetns.c | 4 ++-- + ip/ipntable.c | 2 +- + ip/iproute.c | 8 ++++---- + ip/iprule.c | 4 ++-- + ip/iptoken.c | 2 +- + ip/link_gre.c | 2 +- + ip/link_gre6.c | 2 +- + ip/link_ip6tnl.c | 2 +- + ip/link_iptnl.c | 2 +- + ip/link_vti.c | 2 +- + ip/link_vti6.c | 2 +- + ip/tcp_metrics.c | 4 ++-- + ip/xfrm_policy.c | 14 +++++++------- + ip/xfrm_state.c | 12 ++++++------ + lib/libgenl.c | 2 +- + lib/libnetlink.c | 40 ++++++++++++++++++++++------------------ + tc/m_action.c | 6 +++--- + tc/tc_class.c | 2 +- + tc/tc_filter.c | 2 +- + tc/tc_qdisc.c | 2 +- + 31 files changed, 79 insertions(+), 75 deletions(-) + +diff --git a/bridge/fdb.c b/bridge/fdb.c +index 615541e2cea2e..3c6c371c02552 100644 +--- a/bridge/fdb.c ++++ b/bridge/fdb.c +@@ -326,7 +326,7 @@ static int fdb_modify(int cmd, int flags, int argc, char **argv) + return -1; + } + +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) + exit(2); + + return 0; +diff --git a/bridge/link.c b/bridge/link.c +index 38dfaea2e1808..19d06420aa818 100644 +--- a/bridge/link.c ++++ b/bridge/link.c +@@ -364,7 +364,7 @@ static int brlink_modify(int argc, char **argv) + addattr_nest_end(&req.n, nest); + } + +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) + exit(2); + + return 0; +diff --git a/bridge/mdb.c b/bridge/mdb.c +index 81d479b9a3407..1cd03e011ded0 100644 +--- a/bridge/mdb.c ++++ b/bridge/mdb.c +@@ -224,7 +224,7 @@ static int mdb_modify(int cmd, int flags, int argc, char **argv) + + addattr_l(&req.n, sizeof(req), MDBA_SET_ENTRY, &entry, sizeof(entry)); + +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) + exit(2); + + return 0; +diff --git a/bridge/vlan.c b/bridge/vlan.c +index 83c40880f0425..54e10d0d94b22 100644 +--- a/bridge/vlan.c ++++ b/bridge/vlan.c +@@ -95,7 +95,7 @@ static int vlan_modify(int cmd, int argc, char **argv) + + addattr_nest_end(&req.n, afspec); + +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) + exit(2); + + return 0; +diff --git a/genl/ctrl.c b/genl/ctrl.c +index 48cbc3562ad8d..25968839a91b5 100644 +--- a/genl/ctrl.c ++++ b/genl/ctrl.c +@@ -67,7 +67,7 @@ int genl_ctrl_resolve_family(const char *family) + + addattr_l(nlh, 128, CTRL_ATTR_FAMILY_NAME, family, strlen(family) + 1); + +- if (rtnl_talk(&rth, nlh, 0, 0, nlh) < 0) { ++ if (rtnl_talk(&rth, nlh, nlh, sizeof(req)) < 0) { + fprintf(stderr, "Error talking to the kernel\n"); + goto errout; + } +@@ -341,7 +341,7 @@ static int ctrl_list(int cmd, int argc, char **argv) + goto ctrl_done; + } + +- if (rtnl_talk(&rth, nlh, 0, 0, nlh) < 0) { ++ if (rtnl_talk(&rth, nlh, nlh, sizeof(req)) < 0) { + fprintf(stderr, "Error talking to the kernel\n"); + goto ctrl_done; + } +diff --git a/include/libnetlink.h b/include/libnetlink.h +index ae933364761c1..95f41d979828f 100644 +--- a/include/libnetlink.h ++++ b/include/libnetlink.h +@@ -54,8 +54,8 @@ extern int rtnl_dump_filter_l(struct rtnl_handle *rth, + const struct rtnl_dump_filter_arg *arg); + extern int rtnl_dump_filter(struct rtnl_handle *rth, rtnl_filter_t filter, + void *arg); +-extern int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, +- unsigned groups, struct nlmsghdr *answer); ++extern int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, ++ struct nlmsghdr *answer, size_t len); + extern int rtnl_send(struct rtnl_handle *rth, const void *buf, int); + extern int rtnl_send_check(struct rtnl_handle *rth, const void *buf, int); + +diff --git a/ip/ipaddress.c b/ip/ipaddress.c +index 30fda4f8b30ec..94ff53898a915 100644 +--- a/ip/ipaddress.c ++++ b/ip/ipaddress.c +@@ -1036,7 +1036,7 @@ static int restore_handler(const struct sockaddr_nl *nl, + + ll_init_map(&rth); + +- ret = rtnl_talk(&rth, n, 0, 0, n); ++ ret = rtnl_talk(&rth, n, n, sizeof(*n)); + if ((ret < 0) && (errno == EEXIST)) + ret = 0; + +@@ -1590,7 +1590,7 @@ static int ipaddr_modify(int cmd, int flags, int argc, char **argv) + sizeof(cinfo)); + } + +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) + return -2; + + return 0; +diff --git a/ip/ipaddrlabel.c b/ip/ipaddrlabel.c +index db4dc28df6d29..564bd4203ab3b 100644 +--- a/ip/ipaddrlabel.c ++++ b/ip/ipaddrlabel.c +@@ -182,7 +182,7 @@ static int ipaddrlabel_modify(int cmd, int argc, char **argv) + if (req.ifal.ifal_family == AF_UNSPEC) + req.ifal.ifal_family = AF_INET6; + +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) + return 2; + + return 0; +@@ -209,7 +209,7 @@ static int flush_addrlabel(const struct sockaddr_nl *who, struct nlmsghdr *n, vo + if (rtnl_open(&rth2, 0) < 0) + return -1; + +- if (rtnl_talk(&rth2, n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth2, n, NULL, 0) < 0) + return -2; + + rtnl_close(&rth2); +diff --git a/ip/ipl2tp.c b/ip/ipl2tp.c +index 5cd863224fda0..2f7c9bf1c737f 100644 +--- a/ip/ipl2tp.c ++++ b/ip/ipl2tp.c +@@ -119,7 +119,7 @@ static int create_tunnel(struct l2tp_parm *p) + addattr16(&req.n, 1024, L2TP_ATTR_UDP_DPORT, p->peer_udp_port); + } + +- if (rtnl_talk(&genl_rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0) + return -2; + + return 0; +@@ -132,7 +132,7 @@ static int delete_tunnel(struct l2tp_parm *p) + + addattr32(&req.n, 128, L2TP_ATTR_CONN_ID, p->tunnel_id); + +- if (rtnl_talk(&genl_rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0) + return -2; + + return 0; +@@ -166,7 +166,7 @@ static int create_session(struct l2tp_parm *p) + if (p->ifname && p->ifname[0]) + addattrstrz(&req.n, 1024, L2TP_ATTR_IFNAME, p->ifname); + +- if (rtnl_talk(&genl_rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0) + return -2; + + return 0; +@@ -179,7 +179,7 @@ static int delete_session(struct l2tp_parm *p) + + addattr32(&req.n, 1024, L2TP_ATTR_CONN_ID, p->tunnel_id); + addattr32(&req.n, 1024, L2TP_ATTR_SESSION_ID, p->session_id); +- if (rtnl_talk(&genl_rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0) + return -2; + + return 0; +diff --git a/ip/iplink.c b/ip/iplink.c +index 86ea23e6beaf7..052f0474bc1c1 100644 +--- a/ip/iplink.c ++++ b/ip/iplink.c +@@ -605,7 +605,7 @@ static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv) + + req.i.ifi_index = 0; + addattr32(&req.n, sizeof(req), IFLA_GROUP, group); +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) + exit(2); + return 0; + } +@@ -680,7 +680,7 @@ static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv) + return -1; + } + +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) + exit(2); + + return 0; +diff --git a/ip/ipneigh.c b/ip/ipneigh.c +index d76e035c449c9..39a8b4b236e37 100644 +--- a/ip/ipneigh.c ++++ b/ip/ipneigh.c +@@ -174,7 +174,7 @@ static int ipneigh_modify(int cmd, int flags, int argc, char **argv) + return -1; + } + +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) + exit(2); + + return 0; +diff --git a/ip/ipnetns.c b/ip/ipnetns.c +index 00b6cc488b3b5..2c848bc0f14b2 100644 +--- a/ip/ipnetns.c ++++ b/ip/ipnetns.c +@@ -113,7 +113,7 @@ static int get_netnsid_from_name(const char *name) + return fd; + + addattr32(&req.n, 1024, NETNSA_FD, fd); +- if (rtnl_talk(&rtnsh, &req.n, 0, 0, &answer.n) < 0) { ++ if (rtnl_talk(&rtnsh, &req.n, &answer.n, sizeof(answer)) < 0) { + close(fd); + return -2; + } +@@ -698,7 +698,7 @@ static int set_netnsid_from_name(const char *name, int nsid) + + addattr32(&req.n, 1024, NETNSA_FD, fd); + addattr32(&req.n, 1024, NETNSA_NSID, nsid); +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) + err = -2; + + close(fd); +diff --git a/ip/ipntable.c b/ip/ipntable.c +index 4aeb71f7f4f89..b88c67b3fa9ab 100644 +--- a/ip/ipntable.c ++++ b/ip/ipntable.c +@@ -313,7 +313,7 @@ static int ipntable_modify(int cmd, int flags, int argc, char **argv) + RTA_PAYLOAD(parms_rta)); + } + +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) + exit(2); + + return 0; +diff --git a/ip/iproute.c b/ip/iproute.c +index 20980aba45bdc..4e63f3780237e 100644 +--- a/ip/iproute.c ++++ b/ip/iproute.c +@@ -1029,7 +1029,7 @@ static int iproute_modify(int cmd, unsigned flags, int argc, char **argv) + if (req.r.rtm_family == AF_UNSPEC) + req.r.rtm_family = AF_INET; + +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) + exit(2); + + return 0; +@@ -1486,7 +1486,7 @@ static int iproute_get(int argc, char **argv) + if (req.r.rtm_family == AF_UNSPEC) + req.r.rtm_family = AF_INET; + +- if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) ++ if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) + exit(2); + + if (connected && !from_ok) { +@@ -1527,7 +1527,7 @@ static int iproute_get(int argc, char **argv) + req.n.nlmsg_flags = NLM_F_REQUEST; + req.n.nlmsg_type = RTM_GETROUTE; + +- if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) ++ if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) + exit(2); + } + +@@ -1549,7 +1549,7 @@ static int restore_handler(const struct sockaddr_nl *nl, + + ll_init_map(&rth); + +- ret = rtnl_talk(&rth, n, 0, 0, n); ++ ret = rtnl_talk(&rth, n, n, sizeof(*n)); + if ((ret < 0) && (errno == EEXIST)) + ret = 0; + +diff --git a/ip/iprule.c b/ip/iprule.c +index 167e753bde7b2..475ddc424e46d 100644 +--- a/ip/iprule.c ++++ b/ip/iprule.c +@@ -355,7 +355,7 @@ static int iprule_modify(int cmd, int argc, char **argv) + if (!table_ok && cmd == RTM_NEWRULE) + req.r.rtm_table = RT_TABLE_MAIN; + +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) + return 2; + + return 0; +@@ -382,7 +382,7 @@ static int flush_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, void *a + if (rtnl_open(&rth2, 0) < 0) + return -1; + +- if (rtnl_talk(&rth2, n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth2, n, NULL, 0) < 0) + return -2; + + rtnl_close(&rth2); +diff --git a/ip/iptoken.c b/ip/iptoken.c +index 5689c2ece5816..0d265e6da8711 100644 +--- a/ip/iptoken.c ++++ b/ip/iptoken.c +@@ -182,7 +182,7 @@ static int iptoken_set(int argc, char **argv) + return -1; + } + +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) + return -2; + + return 0; +diff --git a/ip/link_gre.c b/ip/link_gre.c +index fda84d832f542..91ac299da1658 100644 +--- a/ip/link_gre.c ++++ b/ip/link_gre.c +@@ -72,7 +72,7 @@ static int gre_parse_opt(struct link_util *lu, int argc, char **argv, + req.i.ifi_family = preferred_family; + req.i.ifi_index = ifi->ifi_index; + +- if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) { ++ if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) { + get_failed: + fprintf(stderr, + "Failed to get existing tunnel info.\n"); +diff --git a/ip/link_gre6.c b/ip/link_gre6.c +index c7183e2fd4e75..d604f558df6ca 100644 +--- a/ip/link_gre6.c ++++ b/ip/link_gre6.c +@@ -86,7 +86,7 @@ static int gre_parse_opt(struct link_util *lu, int argc, char **argv, + req.i.ifi_family = preferred_family; + req.i.ifi_index = ifi->ifi_index; + +- if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) { ++ if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) { + get_failed: + fprintf(stderr, + "Failed to get existing tunnel info.\n"); +diff --git a/ip/link_ip6tnl.c b/ip/link_ip6tnl.c +index f5b12454cf5f0..3efe2f4553203 100644 +--- a/ip/link_ip6tnl.c ++++ b/ip/link_ip6tnl.c +@@ -84,7 +84,7 @@ static int ip6tunnel_parse_opt(struct link_util *lu, int argc, char **argv, + req.i.ifi_family = preferred_family; + req.i.ifi_index = ifi->ifi_index; + +- if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) { ++ if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) { + get_failed: + fprintf(stderr, + "Failed to get existing tunnel info.\n"); +diff --git a/ip/link_iptnl.c b/ip/link_iptnl.c +index 768c4efd4c26d..439c6e160b9ca 100644 +--- a/ip/link_iptnl.c ++++ b/ip/link_iptnl.c +@@ -76,7 +76,7 @@ static int iptunnel_parse_opt(struct link_util *lu, int argc, char **argv, + req.i.ifi_family = preferred_family; + req.i.ifi_index = ifi->ifi_index; + +- if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) { ++ if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) { + get_failed: + fprintf(stderr, + "Failed to get existing tunnel info.\n"); +diff --git a/ip/link_vti.c b/ip/link_vti.c +index 6274c836cb944..0c0f5ba770d75 100644 +--- a/ip/link_vti.c ++++ b/ip/link_vti.c +@@ -66,7 +66,7 @@ static int vti_parse_opt(struct link_util *lu, int argc, char **argv, + req.i.ifi_family = preferred_family; + req.i.ifi_index = ifi->ifi_index; + +- if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) { ++ if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) { + get_failed: + fprintf(stderr, + "Failed to get existing tunnel info.\n"); +diff --git a/ip/link_vti6.c b/ip/link_vti6.c +index 282896df917a0..c146f791abaaa 100644 +--- a/ip/link_vti6.c ++++ b/ip/link_vti6.c +@@ -67,7 +67,7 @@ static int vti6_parse_opt(struct link_util *lu, int argc, char **argv, + req.i.ifi_family = preferred_family; + req.i.ifi_index = ifi->ifi_index; + +- if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) { ++ if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) { + get_failed: + fprintf(stderr, + "Failed to get existing tunnel info.\n"); +diff --git a/ip/tcp_metrics.c b/ip/tcp_metrics.c +index c6be3c94415ff..8fa4b26a4965c 100644 +--- a/ip/tcp_metrics.c ++++ b/ip/tcp_metrics.c +@@ -386,10 +386,10 @@ static int tcpm_do_cmd(int cmd, int argc, char **argv) + } + + if (ack) { +- if (rtnl_talk(&grth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&grth, &req.n, NULL, 0) < 0) + return -2; + } else if (atype >= 0) { +- if (rtnl_talk(&grth, &req.n, 0, 0, &req.n) < 0) ++ if (rtnl_talk(&grth, &req.n, &req.n, sizeof(req)) < 0) + return -2; + if (process_msg(NULL, &req.n, stdout) < 0) { + fprintf(stderr, "Dump terminated\n"); +diff --git a/ip/xfrm_policy.c b/ip/xfrm_policy.c +index a0a9ce14036be..5ff581a2b868b 100644 +--- a/ip/xfrm_policy.c ++++ b/ip/xfrm_policy.c +@@ -392,7 +392,7 @@ static int xfrm_policy_modify(int cmd, unsigned flags, int argc, char **argv) + if (req.xpinfo.sel.family == AF_UNSPEC) + req.xpinfo.sel.family = AF_INET; + +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) + exit(2); + + rtnl_close(&rth); +@@ -554,7 +554,7 @@ int xfrm_policy_print(const struct sockaddr_nl *who, struct nlmsghdr *n, + } + + static int xfrm_policy_get_or_delete(int argc, char **argv, int delete, +- void *res_nlbuf) ++ void *res_nlbuf, size_t res_size) + { + struct rtnl_handle rth; + struct { +@@ -669,7 +669,7 @@ static int xfrm_policy_get_or_delete(int argc, char **argv, int delete, + (void *)&ctx, ctx.sctx.len); + } + +- if (rtnl_talk(&rth, &req.n, 0, 0, res_nlbuf) < 0) ++ if (rtnl_talk(&rth, &req.n, res_nlbuf, res_size) < 0) + exit(2); + + rtnl_close(&rth); +@@ -679,7 +679,7 @@ static int xfrm_policy_get_or_delete(int argc, char **argv, int delete, + + static int xfrm_policy_delete(int argc, char **argv) + { +- return xfrm_policy_get_or_delete(argc, argv, 1, NULL); ++ return xfrm_policy_get_or_delete(argc, argv, 1, NULL, 0); + } + + static int xfrm_policy_get(int argc, char **argv) +@@ -689,7 +689,7 @@ static int xfrm_policy_get(int argc, char **argv) + + memset(buf, 0, sizeof(buf)); + +- xfrm_policy_get_or_delete(argc, argv, 0, n); ++ xfrm_policy_get_or_delete(argc, argv, 0, n, sizeof(buf)); + + if (xfrm_policy_print(NULL, n, (void*)stdout) < 0) { + fprintf(stderr, "An error :-)\n"); +@@ -974,7 +974,7 @@ static int xfrm_spd_getinfo(int argc, char **argv) + if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0) + exit(1); + +- if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) ++ if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) + exit(2); + + print_spdinfo(&req.n, (void*)stdout); +@@ -1026,7 +1026,7 @@ static int xfrm_policy_flush(int argc, char **argv) + if (show_stats > 1) + fprintf(stderr, "Flush policy\n"); + +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) + exit(2); + + rtnl_close(&rth); +diff --git a/ip/xfrm_state.c b/ip/xfrm_state.c +index dc6993ef26ca9..68884af14772e 100644 +--- a/ip/xfrm_state.c ++++ b/ip/xfrm_state.c +@@ -647,7 +647,7 @@ static int xfrm_state_modify(int cmd, unsigned flags, int argc, char **argv) + if (req.xsinfo.family == AF_UNSPEC) + req.xsinfo.family = AF_INET; + +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) + exit(2); + + rtnl_close(&rth); +@@ -784,7 +784,7 @@ static int xfrm_state_allocspi(int argc, char **argv) + req.xspi.info.family = AF_INET; + + +- if (rtnl_talk(&rth, &req.n, 0, 0, res_n) < 0) ++ if (rtnl_talk(&rth, &req.n, res_n, sizeof(res_buf)) < 0) + exit(2); + + if (xfrm_state_print(NULL, res_n, (void*)stdout) < 0) { +@@ -974,7 +974,7 @@ static int xfrm_state_get_or_delete(int argc, char **argv, int delete) + req.xsid.family = AF_INET; + + if (delete) { +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) + exit(2); + } else { + char buf[NLMSG_BUF_SIZE]; +@@ -982,7 +982,7 @@ static int xfrm_state_get_or_delete(int argc, char **argv, int delete) + + memset(buf, 0, sizeof(buf)); + +- if (rtnl_talk(&rth, &req.n, 0, 0, res_n) < 0) ++ if (rtnl_talk(&rth, &req.n, res_n, sizeof(req)) < 0) + exit(2); + + if (xfrm_state_print(NULL, res_n, (void*)stdout) < 0) { +@@ -1223,7 +1223,7 @@ static int xfrm_sad_getinfo(int argc, char **argv) + if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0) + exit(1); + +- if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) ++ if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) + exit(2); + + print_sadinfo(&req.n, (void*)stdout); +@@ -1277,7 +1277,7 @@ static int xfrm_state_flush(int argc, char **argv) + fprintf(stderr, "Flush state with XFRM-PROTO value \"%s\"\n", + strxf_xfrmproto(req.xsf.proto)); + +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) + exit(2); + + rtnl_close(&rth); +diff --git a/lib/libgenl.c b/lib/libgenl.c +index ef3e5db60c8cb..acb1478389476 100644 +--- a/lib/libgenl.c ++++ b/lib/libgenl.c +@@ -53,7 +53,7 @@ int genl_resolve_family(struct rtnl_handle *grth, const char *family) + addattr_l(&req.n, sizeof(req), CTRL_ATTR_FAMILY_NAME, + family, strlen(family) + 1); + +- if (rtnl_talk(grth, &req.n, 0, 0, &req.n) < 0) { ++ if (rtnl_talk(grth, &req.n, &req.n, sizeof(req)) < 0) { + fprintf(stderr, "Error talking to the kernel\n"); + return -2; + } +diff --git a/lib/libnetlink.c b/lib/libnetlink.c +index 0a989f46fa519..c455a41eccfdd 100644 +--- a/lib/libnetlink.c ++++ b/lib/libnetlink.c +@@ -29,6 +29,10 @@ + #define SOL_NETLINK 270 + #endif + ++#ifndef MIN ++#define MIN(a, b) ((a) < (b) ? (a) : (b)) ++#endif ++ + int rcvbuf = 1024 * 1024; + + void rtnl_close(struct rtnl_handle *rth) +@@ -292,8 +296,8 @@ int rtnl_dump_filter(struct rtnl_handle *rth, + return rtnl_dump_filter_l(rth, a); + } + +-int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, +- unsigned groups, struct nlmsghdr *answer) ++int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, ++ struct nlmsghdr *answer, size_t maxlen) + { + int status; + unsigned seq; +@@ -309,12 +313,10 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, + .msg_iov = &iov, + .msg_iovlen = 1, + }; +- char buf[16384]; ++ char buf[32768]; + + memset(&nladdr, 0, sizeof(nladdr)); + nladdr.nl_family = AF_NETLINK; +- nladdr.nl_pid = peer; +- nladdr.nl_groups = groups; + + n->nlmsg_seq = seq = ++rtnl->seq; + +@@ -322,7 +324,6 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, + n->nlmsg_flags |= NLM_F_ACK; + + status = sendmsg(rtnl->fd, &msg, 0); +- + if (status < 0) { + perror("Cannot talk to rtnetlink"); + return -1; +@@ -331,7 +332,6 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, + memset(buf,0,sizeof(buf)); + + iov.iov_base = buf; +- + while (1) { + iov.iov_len = sizeof(buf); + status = recvmsg(rtnl->fd, &msg, 0); +@@ -364,7 +364,7 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, + exit(1); + } + +- if (nladdr.nl_pid != peer || ++ if (nladdr.nl_pid != 0 || + h->nlmsg_pid != rtnl->local.nl_pid || + h->nlmsg_seq != seq) { + /* Don't forget to skip that message. */ +@@ -377,20 +377,22 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, + struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h); + if (l < sizeof(struct nlmsgerr)) { + fprintf(stderr, "ERROR truncated\n"); +- } else { +- if (!err->error) { +- if (answer) +- memcpy(answer, h, h->nlmsg_len); +- return 0; +- } +- +- fprintf(stderr, "RTNETLINK answers: %s\n", strerror(-err->error)); +- errno = -err->error; ++ } else if (!err->error) { ++ if (answer) ++ memcpy(answer, h, ++ MIN(maxlen, h->nlmsg_len)); ++ return 0; + } ++ ++ fprintf(stderr, "RTNETLINK answers: %s\n", ++ strerror(-err->error)); ++ errno = -err->error; + return -1; + } ++ + if (answer) { +- memcpy(answer, h, h->nlmsg_len); ++ memcpy(answer, h, ++ MIN(maxlen, h->nlmsg_len)); + return 0; + } + +@@ -399,10 +401,12 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, + status -= NLMSG_ALIGN(len); + h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len)); + } ++ + if (msg.msg_flags & MSG_TRUNC) { + fprintf(stderr, "Message truncated\n"); + continue; + } ++ + if (status) { + fprintf(stderr, "!!!Remnant of size %d\n", status); + exit(1); +diff --git a/tc/m_action.c b/tc/m_action.c +index 4acabef056db1..7cbf37740c3ba 100644 +--- a/tc/m_action.c ++++ b/tc/m_action.c +@@ -451,7 +451,7 @@ static int tc_action_gd(int cmd, unsigned flags, int *argc_p, char ***argv_p) + if (cmd == RTM_GETACTION) + ans = &req.n; + +- if (rtnl_talk(&rth, &req.n, 0, 0, ans) < 0) { ++ if (rtnl_talk(&rth, &req.n, ans, MAX_MSG) < 0) { + fprintf(stderr, "We have an error talking to the kernel\n"); + return 1; + } +@@ -496,7 +496,7 @@ static int tc_action_modify(int cmd, unsigned flags, int *argc_p, char ***argv_p + } + tail->rta_len = (void *) NLMSG_TAIL(&req.n) - (void *) tail; + +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) { ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) { + fprintf(stderr, "We have an error talking to the kernel\n"); + ret = -1; + } +@@ -566,7 +566,7 @@ static int tc_act_list_or_flush(int argc, char **argv, int event) + req.n.nlmsg_type = RTM_DELACTION; + req.n.nlmsg_flags |= NLM_F_ROOT; + req.n.nlmsg_flags |= NLM_F_REQUEST; +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) { ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) { + fprintf(stderr, "We have an error flushing\n"); + return 1; + } +diff --git a/tc/tc_class.c b/tc/tc_class.c +index 6c0850d09f874..8f6908b85a956 100644 +--- a/tc/tc_class.c ++++ b/tc/tc_class.c +@@ -138,7 +138,7 @@ static int tc_class_modify(int cmd, unsigned flags, int argc, char **argv) + } + } + +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) + return 2; + + return 0; +diff --git a/tc/tc_filter.c b/tc/tc_filter.c +index c3f2d5fa863e9..de1a73f470773 100644 +--- a/tc/tc_filter.c ++++ b/tc/tc_filter.c +@@ -167,7 +167,7 @@ static int tc_filter_modify(int cmd, unsigned flags, int argc, char **argv) + } + } + +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) { ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) { + fprintf(stderr, "We have an error talking to the kernel\n"); + return 2; + } +diff --git a/tc/tc_qdisc.c b/tc/tc_qdisc.c +index e304858044cbb..984f1359a40e0 100644 +--- a/tc/tc_qdisc.c ++++ b/tc/tc_qdisc.c +@@ -187,7 +187,7 @@ static int tc_qdisc_modify(int cmd, unsigned flags, int argc, char **argv) + req.t.tcm_ifindex = idx; + } + +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) + return 2; + + return 0; +-- +2.6.4 + diff --git a/SPECS/iproute.spec b/SPECS/iproute.spec index fdfafb9..f4a8243 100644 --- a/SPECS/iproute.spec +++ b/SPECS/iproute.spec @@ -2,7 +2,7 @@ Summary: Advanced IP routing and network device configuration tools Name: iproute Version: 3.10.0 -Release: 54%{?dist} +Release: 54%{?dist}.1 Group: Applications/System URL: http://kernel.org/pub/linux/utils/net/%{name}2/ Source0: http://kernel.org/pub/linux/utils/net/%{name}2/%{name}2-%{version}.tar.gz @@ -121,6 +121,9 @@ Patch56: iproute2-3.10.0-tc-fix-for-qdiscs-without-options.patch Patch57: iproute2-3.10.0-Revert-Changes-for-BZ-1212026.patch # https://bugzilla.redhat.com/show_bug.cgi?id=1241486 Patch58: iproute-3.10.0-man-tc.8-mention-Fair-Queue-scheduler.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=1327582 +Patch59: iproute2-libnetlink-add-size-argument-to-rtnl_talk.patch +Patch60: iproute2-ipaddress-fix-ipaddr_flush-for-Linux-3.1.patch License: GPLv2+ and Public Domain BuildRequires: bison @@ -212,6 +215,8 @@ sed -i "s/_VERSION_/%{version}/" man/man8/ss.8 %patch56 -p1 %patch57 -p1 %patch58 -p1 +%patch59 -p1 +%patch60 -p1 sed -i 's/^LIBDIR=/LIBDIR?=/' Makefile sed -i 's/iproute-doc/%{name}-%{version}/' man/man8/lnstat.8 @@ -313,6 +318,10 @@ done %{_includedir}/libnetlink.h %changelog +* Tue May 31 2016 Phil Sutter - 3.10.0-54.1 +- Resolves: #1327582 - ip link show command adds extra "Message Truncated" to + output + * Thu Sep 17 2015 Phil Sutter - 3.10.0-54 - Related: #1241486 - backport: tc: fq scheduler - add missing documentation