]> granicus.if.org Git - libnl/commitdiff
nl: add function nl_pickup_keep_syserr()
authorThomas Haller <thaller@redhat.com>
Wed, 26 Nov 2014 17:13:37 +0000 (18:13 +0100)
committerThomas Haller <thaller@redhat.com>
Thu, 27 Nov 2014 09:24:03 +0000 (10:24 +0100)
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.

Acked-by: Thomas Graf <tgraf@suug.ch>
Signed-off-by: Thomas Haller <thaller@redhat.com>
include/netlink/netlink.h
lib/nl.c

index 61656b397352695e01f763a7dfbf5890fda3e728..f8f2082f282f11d85cb8920b26936c6808108b26 100644 (file)
@@ -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 *);
index 798262edc2d86f27d2fd359763acf213447885c8..fade84818a431d068c8ca9bb4a67d2a2e92c4efb 100644 (file)
--- 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 */
 
 /**
@@ -1117,6 +1125,24 @@ 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)
+{
+       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;
@@ -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)