route: merge branch 'route-link-get-kernel-opnotsupp'
http://lists.infradead.org/pipermail/libnl/2014-November/001769.html Signed-off-by: Thomas Haller <thaller@redhat.com>
This commit is contained in:
commit
cb75576df0
5 changed files with 71 additions and 11 deletions
|
@ -87,6 +87,11 @@ extern int nl_pickup(struct nl_sock *,
|
|||
struct nlmsghdr *,
|
||||
struct nl_parser_param *),
|
||||
struct nl_object **);
|
||||
extern int nl_pickup_keep_syserr(struct nl_sock *sk,
|
||||
int (*parser)(struct nl_cache_ops *, struct sockaddr_nl *,
|
||||
struct nlmsghdr *, struct nl_parser_param *),
|
||||
struct nl_object **result,
|
||||
int *syserror);
|
||||
/* Netlink Family Translations */
|
||||
extern char * nl_nlfamily2str(int, char *, size_t);
|
||||
extern int nl_str2nlfamily(const char *);
|
||||
|
|
|
@ -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)
|
||||
};
|
||||
|
|
49
lib/nl.c
49
lib/nl.c
|
@ -867,7 +867,7 @@ continue_reading:
|
|||
interrupted = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Other side wishes to see an ack for this message */
|
||||
if (hdr->nlmsg_flags & NLM_F_ACK) {
|
||||
if (cb->cb_set[NL_CB_SEND_ACK])
|
||||
|
@ -955,7 +955,7 @@ skip:
|
|||
err = 0;
|
||||
hdr = nlmsg_next(hdr, &n);
|
||||
}
|
||||
|
||||
|
||||
nlmsg_free(msg);
|
||||
free(buf);
|
||||
free(creds);
|
||||
|
@ -1077,6 +1077,7 @@ struct pickup_param
|
|||
int (*parser)(struct nl_cache_ops *, struct sockaddr_nl *,
|
||||
struct nlmsghdr *, struct nl_parser_param *);
|
||||
struct nl_object *result;
|
||||
int *syserror;
|
||||
};
|
||||
|
||||
static int __store_answer(struct nl_object *obj, struct nl_parser_param *p)
|
||||
|
@ -1103,25 +1104,50 @@ static int __pickup_answer(struct nl_msg *msg, void *arg)
|
|||
return pp->parser(NULL, &msg->nm_src, msg->nm_nlh, &parse_arg);
|
||||
}
|
||||
|
||||
static int __pickup_answer_syserr(struct sockaddr_nl *nla, struct nlmsgerr *nlerr, void *arg)
|
||||
{
|
||||
*(((struct pickup_param *) arg)->syserror) = nlerr->error;
|
||||
|
||||
return -nl_syserr2nlerr(nlerr->error);
|
||||
}
|
||||
|
||||
/** @endcond */
|
||||
|
||||
/**
|
||||
* Pickup netlink answer, parse is and return object
|
||||
* @arg sk Netlink socket
|
||||
* @arg parser Parser function to parse answer
|
||||
* @arg result Result pointer to return parsed object
|
||||
* @arg sk Netlink socket
|
||||
* @arg parser Parser function to parse answer
|
||||
* @arg result Result pointer to return parsed object
|
||||
*
|
||||
* @return 0 on success or a negative error code.
|
||||
*/
|
||||
int nl_pickup(struct nl_sock *sk,
|
||||
int (*parser)(struct nl_cache_ops *, struct sockaddr_nl *,
|
||||
struct nlmsghdr *, struct nl_parser_param *),
|
||||
struct nl_object **result)
|
||||
int (*parser)(struct nl_cache_ops *, struct sockaddr_nl *,
|
||||
struct nlmsghdr *, struct nl_parser_param *),
|
||||
struct nl_object **result)
|
||||
{
|
||||
return nl_pickup_keep_syserr(sk, parser, result, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pickup netlink answer, parse is and return object with preserving system error
|
||||
* @arg sk Netlink socket
|
||||
* @arg parser Parser function to parse answer
|
||||
* @arg result Result pointer to return parsed object
|
||||
* @arg syserr Result pointer for the system error in case of failure
|
||||
*
|
||||
* @return 0 on success or a negative error code.
|
||||
*/
|
||||
int nl_pickup_keep_syserr(struct nl_sock *sk,
|
||||
int (*parser)(struct nl_cache_ops *, struct sockaddr_nl *,
|
||||
struct nlmsghdr *, struct nl_parser_param *),
|
||||
struct nl_object **result,
|
||||
int *syserror)
|
||||
{
|
||||
struct nl_cb *cb;
|
||||
int err;
|
||||
struct pickup_param pp = {
|
||||
.parser = parser,
|
||||
.parser = parser,
|
||||
};
|
||||
|
||||
cb = nl_cb_clone(sk->s_cb);
|
||||
|
@ -1129,6 +1155,11 @@ int nl_pickup(struct nl_sock *sk,
|
|||
return -NLE_NOMEM;
|
||||
|
||||
nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, __pickup_answer, &pp);
|
||||
if (syserror) {
|
||||
*syserror = 0;
|
||||
pp.syserror = syserror;
|
||||
nl_cb_err(cb, NL_CB_CUSTOM, __pickup_answer_syserr, &pp);
|
||||
}
|
||||
|
||||
err = nl_recvmsgs(sk, cb);
|
||||
if (err < 0)
|
||||
|
|
|
@ -1160,6 +1160,11 @@ nla_put_failure:
|
|||
* 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 +1174,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 +1184,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;
|
||||
|
|
|
@ -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),
|
||||
|
|
Loading…
Add table
Reference in a new issue