[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

[PATCH 4/4] Implement negotiation of structured replies



From: Wouter Verhelst <w@uter.be>

This should make it possible for us to use structured replies!

Signed-off-by: Wouter Verhelst <w@uter.be>
---
 cliserv.h    | 13 +++++++------
 nbd-server.c | 28 ++++++++++++++++++++++++++++
 nbd.h        |  1 +
 3 files changed, 36 insertions(+), 6 deletions(-)

diff --git a/cliserv.h b/cliserv.h
index 1333802..8a89c04 100644
--- a/cliserv.h
+++ b/cliserv.h
@@ -95,12 +95,13 @@ int writeit(int f, void *buf, size_t len);
 					 * served */
 
 /* Options that the client can select to the server */
-#define NBD_OPT_EXPORT_NAME	(1)	/**< Client wants to select a named export (is followed by name of export) */
-#define NBD_OPT_ABORT		(2)	/**< Client wishes to abort negotiation */
-#define NBD_OPT_LIST		(3)	/**< Client request list of supported exports (not followed by data) */
-#define NBD_OPT_STARTTLS	(5)	/**< Client wishes to initiate TLS */
-#define NBD_OPT_INFO		(6)	/**< Client wants information about the given export */
-#define NBD_OPT_GO		(7)	/**< Client wants to select the given and move to the transmission phase */
+#define NBD_OPT_EXPORT_NAME	 (1)	/**< Client wants to select a named export (is followed by name of export) */
+#define NBD_OPT_ABORT		 (2)	/**< Client wishes to abort negotiation */
+#define NBD_OPT_LIST		 (3)	/**< Client request list of supported exports (not followed by data) */
+#define NBD_OPT_STARTTLS	 (5)	/**< Client wishes to initiate TLS */
+#define NBD_OPT_INFO		 (6)	/**< Client wants information about the given export */
+#define NBD_OPT_GO		 (7)	/**< Client wants to select the given and move to the transmission phase */
+#define NBD_OPT_STRUCTURED_REPLY (8)	/**< Client wants to see structured replies */
 
 /* Replies the server can send during negotiation */
 #define NBD_REP_ACK		(1)	/**< ACK a request. Data: option number to be acked */
diff --git a/nbd-server.c b/nbd-server.c
index 8c84f93..0b269d7 100644
--- a/nbd-server.c
+++ b/nbd-server.c
@@ -2181,6 +2181,8 @@ void send_export_info(CLIENT* client, SERVER* server, bool maybe_zeroes) {
 		flags |= NBD_FLAG_SEND_TRIM;
 	if (!(server->flags & F_COPYONWRITE))
 		flags |= NBD_FLAG_CAN_MULTI_CONN;
+	if (client->clientflags & F_STRUCTURED)
+		flags |= NBD_FLAG_SEND_DF;
 	flags = htons(flags);
 	socket_write(client, &flags, sizeof(flags));
 	if (!(glob_flags & F_NO_ZEROES) && maybe_zeroes) {
@@ -2521,6 +2523,27 @@ exit:
 }
 #endif
 
+/**
+  * Handle an NBD_OPT_STRUCTURED_REPLY message
+  */
+static void handle_structured_reply(CLIENT *client, uint32_t opt, GArray *servers, uint32_t cflags) {
+	uint32_t len;
+	int i;
+
+	socket_read(client, &len, sizeof(len));
+	len = ntohl(len);
+	if(len) {
+		send_reply(client, opt, NBD_REP_ERR_INVALID, -1, "NBD_OPT_STRUCTURED_REPLY with nonzero data length is not a valid request");
+		char buf[1024];
+		consume(client, len, buf, sizeof buf);
+	}
+	if(client->clientflags & F_STRUCTURED) {
+		send_reply(client, opt, NBD_REP_ERR_INVALID, -1, "NBD_OPT_STRUCTURED_REPLY has already been called");
+	}
+	client->clientflags |= F_STRUCTURED;
+	send_reply(client, opt, NBD_REP_ACK, 0, NULL);
+}
+
 /**
   * Handle an NBD_OPT_INFO or NBD_OPT_GO request.
   */
@@ -2700,6 +2723,8 @@ CLIENT* negotiate(int net, GArray* servers, struct generic_conf *genconf) {
 				// can't recover from failed TLS negotiation.
 				goto handler_err;
 			}
+			// once TLS has been negotiated, any state must be cleared
+			client->clientflags = 0;
 #endif
 			break;
 		case NBD_OPT_GO:
@@ -2708,6 +2733,9 @@ CLIENT* negotiate(int net, GArray* servers, struct generic_conf *genconf) {
 				return client;
 			}
 			break;
+		case NBD_OPT_STRUCTURED_REPLY:
+			handle_structured_reply(client, opt, servers, cflags);
+			break;
 		default:
 			consume_len(client);
 			send_reply(client, opt, NBD_REP_ERR_UNSUP, -1, "The given option is unknown to this server implementation");
diff --git a/nbd.h b/nbd.h
index 4cf692a..4985e51 100644
--- a/nbd.h
+++ b/nbd.h
@@ -55,6 +55,7 @@ enum {
 #define NBD_FLAG_ROTATIONAL	(1 << 4)	/* Use elevator algorithm - rotational media */
 #define NBD_FLAG_SEND_TRIM	(1 << 5)	/* Send TRIM (discard) */
 #define NBD_FLAG_SEND_WRITE_ZEROES (1 << 6) 	/* Send NBD_CMD_WRITE_ZEROES */
+#define NBD_FLAG_SEND_DF	(1 << 7)	/* Send NBD_CMD_FLAG_DF */
 #define NBD_FLAG_CAN_MULTI_CONN	(1 << 8)	/* multiple connections are okay */
 
 #define nbd_cmd(req) ((req)->cmd[0])
-- 
2.39.2


Reply to: