From: David Ahern Date: Mon, 12 Dec 2016 00:53:14 +0000 (-0800) Subject: libnetlink: Add variant of rtnl_talk that does not display RTNETLINK answers error X-Git-Tag: v4.10.0~64 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=463d9efaa258a466df706e8630f128055bf10bdc;p=thirdparty%2Fiproute2.git libnetlink: Add variant of rtnl_talk that does not display RTNETLINK answers error iplink_vrf has 2 functions used to validate a user given device name is a VRF device and to return the table id. If the user string is not a device name ip commands with a vrf keyword show a confusing error message: "RTNETLINK answers: No such device". Add a variant of rtnl_talk that does not display the "RTNETLINK answers" message and update iplink_vrf to use it. Signed-off-by: David Ahern --- diff --git a/include/libnetlink.h b/include/libnetlink.h index 751ebf186..bd0267dfc 100644 --- a/include/libnetlink.h +++ b/include/libnetlink.h @@ -81,6 +81,9 @@ int rtnl_dump_filter_nc(struct rtnl_handle *rth, int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, struct nlmsghdr *answer, size_t len) __attribute__((warn_unused_result)); +int rtnl_talk_suppress_rtnl_errmsg(struct rtnl_handle *rtnl, struct nlmsghdr *n, + struct nlmsghdr *answer, size_t len) + __attribute__((warn_unused_result)); int rtnl_send(struct rtnl_handle *rth, const void *buf, int) __attribute__((warn_unused_result)); int rtnl_send_check(struct rtnl_handle *rth, const void *buf, int) diff --git a/ip/iplink_vrf.c b/ip/iplink_vrf.c index c101ed770..917630e85 100644 --- a/ip/iplink_vrf.c +++ b/ip/iplink_vrf.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "rt_names.h" #include "utils.h" @@ -126,8 +127,14 @@ __u32 ipvrf_get_table(const char *name) addattr_l(&req.n, sizeof(req), IFLA_IFNAME, name, strlen(name) + 1); - if (rtnl_talk(&rth, &req.n, &answer.n, sizeof(answer)) < 0) - return 0; + if (rtnl_talk_suppress_rtnl_errmsg(&rth, &req.n, + &answer.n, sizeof(answer)) < 0) { + /* special case "default" vrf to be the main table */ + if (errno == ENODEV && !strcmp(name, "default")) + rtnl_rttable_a2n(&tb_id, "main"); + + return tb_id; + } ifi = NLMSG_DATA(&answer.n); len = answer.n.nlmsg_len - NLMSG_LENGTH(sizeof(*ifi)); @@ -186,7 +193,8 @@ int name_is_vrf(const char *name) addattr_l(&req.n, sizeof(req), IFLA_IFNAME, name, strlen(name) + 1); - if (rtnl_talk(&rth, &req.n, &answer.n, sizeof(answer)) < 0) + if (rtnl_talk_suppress_rtnl_errmsg(&rth, &req.n, + &answer.n, sizeof(answer)) < 0) return 0; ifi = NLMSG_DATA(&answer.n); diff --git a/lib/libnetlink.c b/lib/libnetlink.c index a5db168e5..9d7e89aeb 100644 --- a/lib/libnetlink.c +++ b/lib/libnetlink.c @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -397,8 +398,9 @@ int rtnl_dump_filter_nc(struct rtnl_handle *rth, return rtnl_dump_filter_l(rth, a); } -int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, - struct nlmsghdr *answer, size_t maxlen) +static int __rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, + struct nlmsghdr *answer, size_t maxlen, + bool show_rtnl_err) { int status; unsigned int seq; @@ -485,7 +487,7 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, return 0; } - if (rtnl->proto != NETLINK_SOCK_DIAG) + if (rtnl->proto != NETLINK_SOCK_DIAG && show_rtnl_err) fprintf(stderr, "RTNETLINK answers: %s\n", strerror(-err->error)); @@ -517,6 +519,18 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, } } +int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, + struct nlmsghdr *answer, size_t maxlen) +{ + return __rtnl_talk(rtnl, n, answer, maxlen, true); +} + +int rtnl_talk_suppress_rtnl_errmsg(struct rtnl_handle *rtnl, struct nlmsghdr *n, + struct nlmsghdr *answer, size_t maxlen) +{ + return __rtnl_talk(rtnl, n, answer, maxlen, false); +} + int rtnl_listen_all_nsid(struct rtnl_handle *rth) { unsigned int on = 1;