aboutsummaryrefslogtreecommitdiff
path: root/lib/netlink.c
diff options
context:
space:
mode:
authorBen Pfaff <blp@nicira.com>2010-05-20 15:57:36 -0700
committerBen Pfaff <blp@nicira.com>2010-06-17 10:30:18 -0700
commita35fbea5bb1b49bcdad696a62c3814e02c4df6e2 (patch)
tree3e585767ebc3b365dfed82a373b3bac4727be12c /lib/netlink.c
parentb4d73e97bae62b5eb18bcd216b603b69ce63297b (diff)
netlink: Make nl_sock_transact() always return a reply on success.
Until now, if nl_sock_transact() received a reply that merely acknowledged success, without providing any other payload, it would return success but not provide the reply to its caller. This is inconsistent and could easily cause a segfault in a caller that expects to see the reply on success, if kernel behavior changed, for whatever reason, so that a request that previously returned data now just returns an acknowledgment. In practice this kind of change should never happen, but it is still better to handle it properly.
Diffstat (limited to 'lib/netlink.c')
-rw-r--r--lib/netlink.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/lib/netlink.c b/lib/netlink.c
index de88a81e..334e45af 100644
--- a/lib/netlink.c
+++ b/lib/netlink.c
@@ -421,7 +421,14 @@ recv:
ofpbuf_delete(reply);
goto recv;
}
- if (nl_msg_nlmsgerr(reply, &retval)) {
+
+ /* If the reply is an error, discard the reply and return the error code.
+ *
+ * Except: if the reply is just an acknowledgement (error code of 0), and
+ * the caller is interested in the reply (replyp != NULL), pass the reply
+ * up to the caller. Otherwise the caller will get a return value of 0
+ * and null '*replyp', which makes unwary callers likely to segfault. */
+ if (nl_msg_nlmsgerr(reply, &retval) && (retval || !replyp)) {
ofpbuf_delete(reply);
if (retval) {
VLOG_DBG_RL(&rl, "received NAK error=%d (%s)",