[PATCH 3/3 B] route/link: return NLE_OPNOTSUPP in rtnl_link_get_kernel() for old kernels
Thomas Haller
thaller at redhat.com
Wed Nov 26 09:17:16 PST 2014
Older kernels without patch a3d1289126e7b14307074b76bf1677015ea5036f do
not support rtnl_getlink() by ifname. Detect this situation in libnl3
and return NLE_OPNOTSUPP instead of NLE_INVAL.
Signed-off-by: Thomas Haller <thaller at redhat.com>
---
APPROACH 2, change behavior
include/netlink/utils.h | 8 ++++++++
lib/route/link.c | 17 ++++++++++++++++-
lib/utils.c | 2 +-
3 files changed, 25 insertions(+), 2 deletions(-)
diff --git a/include/netlink/utils.h b/include/netlink/utils.h
index 6b4b787..87cc9b1 100644
--- a/include/netlink/utils.h
+++ b/include/netlink/utils.h
@@ -113,6 +113,14 @@ enum {
NL_CAPABILITY_NL_CONNECT_RETRY_GENERATE_PORT_ON_ADDRINUSE = 4,
#define NL_CAPABILITY_NL_CONNECT_RETRY_GENERATE_PORT_ON_ADDRINUSE NL_CAPABILITY_NL_CONNECT_RETRY_GENERATE_PORT_ON_ADDRINUSE
+ /**
+ * Indicate that rtnl_link_get_kernel() fails with NLE_OPNOTSUPP in case
+ * of older kernals not supporting lookup by ifname. This changes behavior
+ * from returning NLE_INVAL to return NLE_OPNOTSUPP.
+ */
+ NL_CAPABILITY_ROUTE_LINK_GET_KERNEL_FAIL_OPNOTSUPP = 5,
+#define NL_CAPABILITY_ROUTE_LINK_GET_KERNEL_FAIL_OPNOTSUPP NL_CAPABILITY_ROUTE_LINK_GET_KERNEL_FAIL_OPNOTSUPP
+
__NL_CAPABILITY_MAX
#define NL_CAPABILITY_MAX (__NL_CAPABILITY_MAX - 1)
};
diff --git a/lib/route/link.c b/lib/route/link.c
index 7a53532..2274c58 100644
--- a/lib/route/link.c
+++ b/lib/route/link.c
@@ -1159,6 +1159,10 @@ nla_put_failure:
* parsed into a struct rtnl_link object and returned via the result
* pointer or -NLE_OBJ_NOTFOUND is returned if no matching link was
* found.
+ * Older kernels do not support lookup by name. In that case, libnl
+ * will fail with -NLE_OPNOTSUPP. Note that previous version of libnl
+ * failed in this case with -NLE_INVAL. You can check libnl behavior
+ * using NL_CAPABILITY_ROUTE_LINK_GET_KERNEL_FAIL_OPNOTSUPP capability.
*
* @route_doc{link_direct_lookup, Lookup Single Link (Direct Lookup)}
* @return 0 on success or a negative error code.
@@ -1169,6 +1173,7 @@ int rtnl_link_get_kernel(struct nl_sock *sk, int ifindex, const char *name,
struct nl_msg *msg = NULL;
struct nl_object *obj;
int err;
+ int syserr;
if ((err = rtnl_link_build_get_request(ifindex, name, &msg)) < 0)
return err;
@@ -1178,8 +1183,18 @@ int rtnl_link_get_kernel(struct nl_sock *sk, int ifindex, const char *name,
if (err < 0)
return err;
- if ((err = nl_pickup(sk, link_msg_parser, &obj)) < 0)
+ if ((err = nl_pickup_keep_syserr(sk, link_msg_parser, &obj, &syserr)) < 0) {
+ if (syserr == -EINVAL &&
+ ifindex <= 0 &&
+ name && *name) {
+ /* Older kernels do not support lookup by ifname. This was added
+ * by commit kernel a3d1289126e7b14307074b76bf1677015ea5036f .
+ * Detect this error case and return NLE_OPNOTSUPP instead of
+ * NLE_INVAL. */
+ return -NLE_OPNOTSUPP;
+ }
return err;
+ }
/* We have used link_msg_parser(), object is definitely a link */
*result = (struct rtnl_link *) obj;
diff --git a/lib/utils.c b/lib/utils.c
index 67612bd..795eeb7 100644
--- a/lib/utils.c
+++ b/lib/utils.c
@@ -1148,7 +1148,7 @@ int nl_has_capability (int capability)
NL_CAPABILITY_ROUTE_LINK_VETH_GET_PEER_OWN_REFERENCE,
NL_CAPABILITY_ROUTE_LINK_CLS_ADD_ACT_OWN_REFERENCE,
NL_CAPABILITY_NL_CONNECT_RETRY_GENERATE_PORT_ON_ADDRINUSE,
- 0,
+ NL_CAPABILITY_ROUTE_LINK_GET_KERNEL_FAIL_OPNOTSUPP,
0,
0,
0),
--
1.9.3
More information about the libnl
mailing list