[PATCH 2/3] nl: add function nl_pickup_keep_syserr()

Thomas Haller thaller at redhat.com
Wed Nov 26 09:13:37 PST 2014


nl_pickup() converts error codes from netlink into
nl error codes using nl_syserr2nlerr(). The latter function
mangles different error codes to the same nl error code.

Add a new function, that returns both the nl error code
and the original error code.

Signed-off-by: Thomas Haller <thaller at redhat.com>
---
 include/netlink/netlink.h |  5 +++++
 lib/nl.c                  | 31 +++++++++++++++++++++++++++++++
 2 files changed, 36 insertions(+)

diff --git a/include/netlink/netlink.h b/include/netlink/netlink.h
index 61656b3..f8f2082 100644
--- a/include/netlink/netlink.h
+++ b/include/netlink/netlink.h
@@ -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 *);
diff --git a/lib/nl.c b/lib/nl.c
index 798262e..fade848 100644
--- a/lib/nl.c
+++ b/lib/nl.c
@@ -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,6 +1104,13 @@ 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 */
 
 /**
@@ -1118,6 +1126,24 @@ int nl_pickup(struct nl_sock *sk,
                             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 = {
@@ -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)
-- 
1.9.3




More information about the libnl mailing list