[Libguestfs] [libnbd PATCH] opt-go: Better decoding of known errors

Eric Blake eblake at redhat.com
Fri Jun 28 01:13:19 UTC 2019


I'm easily able to provoke NBD_REP_ERR_TLS_REQD (use nbd_set_tls(0) to
talk to a server that requires encryption) and NBD_REP_ERR_UNKNOWN
(forget to use nbd_set_export_name for qemu-nbd); it's nice to display
a useful error for these rather than "unknown reply from NBD_OPT_GO:
0x80000005" or similar.  Other errors are less common, but as long as
we're decoding things, it doesn't hurt to decode everything in the
protocol.
---

I'm pushing this one now (I mentioned it on IRC earlier today).

 generator/states-newstyle-opt-go.c | 32 +++++++++++++++++++++++++++---
 lib/nbd-protocol.h                 | 22 +++++++++++---------
 2 files changed, 42 insertions(+), 12 deletions(-)

diff --git a/generator/states-newstyle-opt-go.c b/generator/states-newstyle-opt-go.c
index 91a85ef..e245c75 100644
--- a/generator/states-newstyle-opt-go.c
+++ b/generator/states-newstyle-opt-go.c
@@ -147,9 +147,35 @@
     SET_NEXT_STATE (%^OPT_EXPORT_NAME.START);
     return 0;
   default:
-    if (handle_reply_error (h) == 0)
-      set_error (0, "handshake: unknown reply from NBD_OPT_GO: 0x%" PRIx32,
-                 reply);
+    if (handle_reply_error (h) == 0) {
+      /* Decode expected known errors into a nicer string */
+      switch (reply) {
+      case NBD_REP_ERR_POLICY:
+      case NBD_REP_ERR_PLATFORM:
+        set_error (0, "handshake: server policy prevents NBD_OPT_GO");
+        break;
+      case NBD_REP_ERR_INVALID:
+      case NBD_REP_ERR_TOO_BIG:
+        set_error (EINVAL, "handshake: server rejected NBD_OPT_GO as invalid");
+        break;
+      case NBD_REP_ERR_TLS_REQD:
+        set_error (ENOTSUP, "handshake: server requires TLS encryption first");
+        break;
+      case NBD_REP_ERR_UNKNOWN:
+        set_error (ENOENT, "handshake: server has no export named '%s'",
+                   h->export_name);
+        break;
+      case NBD_REP_ERR_SHUTDOWN:
+        set_error (ESHUTDOWN, "handshake: server is shutting down");
+        break;
+      case NBD_REP_ERR_BLOCK_SIZE_REQD:
+        set_error (EINVAL, "handshake: server requires specific block sizes");
+        break;
+      default:
+        set_error (0, "handshake: unknown reply from NBD_OPT_GO: 0x%" PRIx32,
+                   reply);
+      }
+    }
     SET_NEXT_STATE (%.DEAD);
     return -1;
   }
diff --git a/lib/nbd-protocol.h b/lib/nbd-protocol.h
index 405af3e..3e3fb4e 100644
--- a/lib/nbd-protocol.h
+++ b/lib/nbd-protocol.h
@@ -123,15 +123,19 @@ struct nbd_fixed_new_option_reply {
 #define NBD_REP_ERR(val) (0x80000000 | (val))
 #define NBD_REP_IS_ERR(val) (!!((val) & 0x80000000))

-#define NBD_REP_ACK          1
-#define NBD_REP_SERVER       2
-#define NBD_REP_INFO         3
-#define NBD_REP_META_CONTEXT 4
-#define NBD_REP_ERR_UNSUP    NBD_REP_ERR (1)
-#define NBD_REP_ERR_POLICY   NBD_REP_ERR (2)
-#define NBD_REP_ERR_INVALID  NBD_REP_ERR (3)
-#define NBD_REP_ERR_PLATFORM NBD_REP_ERR (4)
-#define NBD_REP_ERR_TLS_REQD NBD_REP_ERR (5)
+#define NBD_REP_ACK                  1
+#define NBD_REP_SERVER               2
+#define NBD_REP_INFO                 3
+#define NBD_REP_META_CONTEXT         4
+#define NBD_REP_ERR_UNSUP            NBD_REP_ERR (1)
+#define NBD_REP_ERR_POLICY           NBD_REP_ERR (2)
+#define NBD_REP_ERR_INVALID          NBD_REP_ERR (3)
+#define NBD_REP_ERR_PLATFORM         NBD_REP_ERR (4)
+#define NBD_REP_ERR_TLS_REQD         NBD_REP_ERR (5)
+#define NBD_REP_ERR_UNKNOWN          NBD_REP_ERR (6)
+#define NBD_REP_ERR_SHUTDOWN         NBD_REP_ERR (7)
+#define NBD_REP_ERR_BLOCK_SIZE_REQD  NBD_REP_ERR (8)
+#define NBD_REP_ERR_TOO_BIG          NBD_REP_ERR (9)

 #define NBD_INFO_EXPORT      0

-- 
2.20.1




More information about the Libguestfs mailing list