socket: change debug callbacks to pass struct nl_msg
[project/libnl-tiny.git] / nl.c
diff --git a/nl.c b/nl.c
index 2fb866eca903910738e666e6b235a52552ce8736..7ab882238e577955e4eb37695c635549fe7360ab 100644 (file)
--- a/nl.c
+++ b/nl.c
 int nl_connect(struct nl_sock *sk, int protocol)
 {
        int err;
+       int flags = 0;
        socklen_t addrlen;
 
-       sk->s_fd = socket(AF_NETLINK, SOCK_RAW, protocol);
+#ifdef SOCK_CLOEXEC
+       flags = SOCK_CLOEXEC;
+#endif
+
+       sk->s_fd = socket(AF_NETLINK, SOCK_RAW | flags, protocol);
        if (sk->s_fd < 0) {
                err = -nl_syserr2nlerr(errno);
                goto errout;
@@ -222,6 +227,11 @@ int nl_sendmsg(struct nl_sock *sk, struct nl_msg *msg, struct msghdr *hdr)
                if (nl_cb_call(cb, NL_CB_MSG_OUT, msg) != NL_OK)
                        return 0;
 
+       if (sk->s_debug_tx_cb) {
+               nlmsg_set_proto(msg, sk->s_proto);
+               sk->s_debug_tx_cb(sk->s_debug_tx_priv, msg);
+       }
+
        ret = sendmsg(sk->s_fd, hdr, 0);
        if (ret < 0)
                return -nl_syserr2nlerr(errno);
@@ -400,7 +410,9 @@ int nl_recv(struct nl_sock *sk, struct sockaddr_nl *nla,
                page_size = getpagesize() * 4;
 
        iov.iov_len = page_size;
-       iov.iov_base = *buf = malloc(iov.iov_len);
+       iov.iov_base = *buf = calloc(1, iov.iov_len);
+       if (!*buf)
+               return -nl_syserr2nlerr(errno);
 
        if (sk->s_flags & NL_SOCK_PASSCRED) {
                msg.msg_controllen = CMSG_SPACE(sizeof(struct ucred));
@@ -421,11 +433,12 @@ retry:
                } else {
                        free(msg.msg_control);
                        free(*buf);
+                       *buf = NULL;
                        return -nl_syserr2nlerr(errno);
                }
        }
 
-       if (iov.iov_len < n ||
+       if (iov.iov_len < (size_t) n ||
            msg.msg_flags & MSG_TRUNC) {
                /* Provided buffer is not long enough, enlarge it
                 * and try again. */
@@ -445,6 +458,7 @@ retry:
        if (msg.msg_namelen != sizeof(struct sockaddr_nl)) {
                free(msg.msg_control);
                free(*buf);
+               *buf = NULL;
                return -NLE_NOADDR;
        }
 
@@ -463,6 +477,7 @@ retry:
 abort:
        free(msg.msg_control);
        free(*buf);
+       *buf = NULL;
        return 0;
 }
 
@@ -501,6 +516,9 @@ continue_reading:
        if (n <= 0)
                return n;
 
+       /* make clang analyzer happy */
+       assert(n > 0 && buf);
+
        NL_DBG(3, "recvmsgs(%p): Read %d bytes\n", sk, n);
 
        hdr = (struct nlmsghdr *) buf;
@@ -519,6 +537,9 @@ continue_reading:
                if (creds)
                        nlmsg_set_creds(msg, creds);
 
+               if (sk->s_debug_rx_cb)
+                       sk->s_debug_rx_cb(sk->s_debug_rx_priv, msg);
+
                /* Raw callback is the first, it gives the most control
                 * to the user and he can do his very own parsing. */
                if (cb->cb_set[NL_CB_MSG_IN])
@@ -599,7 +620,7 @@ continue_reading:
                else if (hdr->nlmsg_type == NLMSG_ERROR) {
                        struct nlmsgerr *e = nlmsg_data(hdr);
 
-                       if (hdr->nlmsg_len < nlmsg_msg_size(sizeof(*e))) {
+                       if (hdr->nlmsg_len < (unsigned) nlmsg_msg_size(sizeof(*e))) {
                                /* Truncated error message, the default action
                                 * is to stop parsing. The user may overrule
                                 * this action by returning NL_SKIP or
@@ -637,7 +658,6 @@ continue_reading:
                                NL_CB_CALL(cb, NL_CB_VALID, msg);
                }
 skip:
-               err = 0;
                hdr = nlmsg_next(hdr, &n);
        }