@@ -1,5 +1,5 @@
# nbd client library in userspace
-# Copyright (C) 2013-2020 Red Hat Inc.
+# Copyright (C) 2013-2021 Red Hat Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
@@ -30,6 +30,7 @@ states_code = \
states-issue-command.c \
states-magic.c \
states-newstyle-opt-export-name.c \
+ states-newstyle-opt-extended-headers.c \
states-newstyle-opt-list.c \
states-newstyle-opt-go.c \
states-newstyle-opt-meta-context.c \
@@ -295,6 +295,7 @@ and
* NEGOTIATING after OPT_STRUCTURED_REPLY or any failed OPT_GO.
*)
Group ("OPT_STARTTLS", newstyle_opt_starttls_state_machine);
+ Group ("OPT_EXTENDED_HEADERS", newstyle_opt_extended_headers_state_machine);
Group ("OPT_STRUCTURED_REPLY", newstyle_opt_structured_reply_state_machine);
Group ("OPT_META_CONTEXT", newstyle_opt_meta_context_state_machine);
Group ("OPT_GO", newstyle_opt_go_state_machine);
@@ -432,6 +433,46 @@ and
};
]
+(* Fixed newstyle NBD_OPT_EXTENDED_HEADERS option.
+ * Implementation: generator/states-newstyle-opt-extended-headers.c
+ *)
+and newstyle_opt_extended_headers_state_machine = [
+ State {
+ default_state with
+ name = "START";
+ comment = "Try to negotiate newstyle NBD_OPT_EXTENDED_HEADERS";
+ external_events = [];
+ };
+
+ State {
+ default_state with
+ name = "SEND";
+ comment = "Send newstyle NBD_OPT_EXTENDED_HEADERS negotiation request";
+ external_events = [ NotifyWrite, "" ];
+ };
+
+ State {
+ default_state with
+ name = "RECV_REPLY";
+ comment = "Receive newstyle NBD_OPT_EXTENDED_HEADERS option reply";
+ external_events = [ NotifyRead, "" ];
+ };
+
+ State {
+ default_state with
+ name = "RECV_REPLY_PAYLOAD";
+ comment = "Receive any newstyle NBD_OPT_EXTENDED_HEADERS reply payload";
+ external_events = [ NotifyRead, "" ];
+ };
+
+ State {
+ default_state with
+ name = "CHECK_REPLY";
+ comment = "Check newstyle NBD_OPT_EXTENDED_HEADERS option reply";
+ external_events = [];
+ };
+]
+
(* Fixed newstyle NBD_OPT_STRUCTURED_REPLY option.
* Implementation: generator/states-newstyle-opt-structured-reply.c
*)
new file mode 100644
@@ -0,0 +1,90 @@
+/* nbd client library in userspace: state machine
+ * Copyright (C) 2013-2021 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* State machine for negotiating NBD_OPT_EXTENDED_HEADERS. */
+
+STATE_MACHINE {
+ NEWSTYLE.OPT_EXTENDED_HEADERS.START:
+ assert (h->gflags & LIBNBD_HANDSHAKE_FLAG_FIXED_NEWSTYLE);
+ if (!h->request_eh) {
+ SET_NEXT_STATE (%^OPT_STRUCTURED_REPLY.START);
+ return 0;
+ }
+
+ h->sbuf.option.version = htobe64 (NBD_NEW_VERSION);
+ h->sbuf.option.option = htobe32 (NBD_OPT_EXTENDED_HEADERS);
+ h->sbuf.option.optlen = htobe32 (0);
+ h->wbuf = &h->sbuf;
+ h->wlen = sizeof h->sbuf.option;
+ SET_NEXT_STATE (%SEND);
+ return 0;
+
+ NEWSTYLE.OPT_EXTENDED_HEADERS.SEND:
+ switch (send_from_wbuf (h)) {
+ case -1: SET_NEXT_STATE (%.DEAD); return 0;
+ case 0:
+ h->rbuf = &h->sbuf;
+ h->rlen = sizeof h->sbuf.or.option_reply;
+ SET_NEXT_STATE (%RECV_REPLY);
+ }
+ return 0;
+
+ NEWSTYLE.OPT_EXTENDED_HEADERS.RECV_REPLY:
+ switch (recv_into_rbuf (h)) {
+ case -1: SET_NEXT_STATE (%.DEAD); return 0;
+ case 0:
+ if (prepare_for_reply_payload (h, NBD_OPT_EXTENDED_HEADERS) == -1) {
+ SET_NEXT_STATE (%.DEAD);
+ return 0;
+ }
+ SET_NEXT_STATE (%RECV_REPLY_PAYLOAD);
+ }
+ return 0;
+
+ NEWSTYLE.OPT_EXTENDED_HEADERS.RECV_REPLY_PAYLOAD:
+ switch (recv_into_rbuf (h)) {
+ case -1: SET_NEXT_STATE (%.DEAD); return 0;
+ case 0: SET_NEXT_STATE (%CHECK_REPLY);
+ }
+ return 0;
+
+ NEWSTYLE.OPT_EXTENDED_HEADERS.CHECK_REPLY:
+ uint32_t reply;
+
+ reply = be32toh (h->sbuf.or.option_reply.reply);
+ switch (reply) {
+ case NBD_REP_ACK:
+ debug (h, "negotiated extended headers on this connection");
+ h->extended_headers = true;
+ break;
+ default:
+ if (handle_reply_error (h) == -1) {
+ SET_NEXT_STATE (%.DEAD);
+ return 0;
+ }
+
+ debug (h, "extended headers are not supported by this server");
+ h->extended_headers = false;
+ break;
+ }
+
+ /* Next option. */
+ SET_NEXT_STATE (%^OPT_STRUCTURED_REPLY.START);
+ return 0;
+
+} /* END STATE MACHINE */
@@ -1,5 +1,5 @@
/* nbd client library in userspace: state machine
- * Copyright (C) 2013-2020 Red Hat Inc.
+ * Copyright (C) 2013-2021 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -23,7 +23,7 @@ STATE_MACHINE {
assert (h->gflags & LIBNBD_HANDSHAKE_FLAG_FIXED_NEWSTYLE);
/* If TLS was not requested we skip this option and go to the next one. */
if (h->tls == LIBNBD_TLS_DISABLE) {
- SET_NEXT_STATE (%^OPT_STRUCTURED_REPLY.START);
+ SET_NEXT_STATE (%^OPT_EXTENDED_HEADERS.START);
return 0;
}
@@ -102,7 +102,7 @@ STATE_MACHINE {
debug (h,
"server refused TLS (%s), continuing with unencrypted connection",
reply == NBD_REP_ERR_POLICY ? "policy" : "not supported");
- SET_NEXT_STATE (%^OPT_STRUCTURED_REPLY.START);
+ SET_NEXT_STATE (%^OPT_EXTENDED_HEADERS.START);
return 0;
}
return 0;
@@ -121,7 +121,7 @@ STATE_MACHINE {
nbd_internal_crypto_debug_tls_enabled (h);
/* Continue with option negotiation. */
- SET_NEXT_STATE (%^OPT_STRUCTURED_REPLY.START);
+ SET_NEXT_STATE (%^OPT_EXTENDED_HEADERS.START);
return 0;
}
/* Continue handshake. */
@@ -144,7 +144,7 @@ STATE_MACHINE {
debug (h, "connection is using TLS");
/* Continue with option negotiation. */
- SET_NEXT_STATE (%^OPT_STRUCTURED_REPLY.START);
+ SET_NEXT_STATE (%^OPT_EXTENDED_HEADERS.START);
return 0;
}
/* Continue handshake. */