STEP01x: dcerpc_submit_shutdown
authorStefan Metzmacher <metze@samba.org>
Thu, 20 Mar 2014 09:24:48 +0000 (10:24 +0100)
committerStefan Metzmacher <metze@samba.org>
Tue, 4 Jun 2019 10:58:04 +0000 (12:58 +0200)
librpc/rpc/dcerpc_connection.c

index 1a8379b9628a48bc48b3b02f0674cffe081477cc..978cbc1e987a6edca4751150e294d064a40a23f7 100644 (file)
@@ -2908,6 +2908,95 @@ static void dcerpc_submit_fault_done(struct tevent_req *subreq)
        TALLOC_FREE(frag);
 }
 
+struct dcerpc_submit_shutdown_frag {
+       struct dcerpc_connection *conn;
+       DATA_BLOB blob;
+       struct iovec vector;
+};
+
+static void dcerpc_submit_shutdown_done(struct tevent_req *subreq);
+
+static NTSTATUS dcerpc_submit_shutdown(struct dcerpc_connection *conn,
+                                      struct tevent_context *ev)
+{
+       struct dcerpc_submit_shutdown_frag *frag;
+       NTSTATUS error;
+       union dcerpc_payload u;
+       struct tevent_req *subreq;
+
+       if (!dcerpc_connection_is_connected(conn)) {
+               return NT_STATUS_OK;
+       }
+
+       TALLOC_FREE(conn->loop.subreq);
+
+       /*
+        * the fragment belongs to the connection instead of the request
+        * because it has to remain in case the request is canceled
+        */
+       frag = talloc_zero(conn, struct dcerpc_submit_shutdown_frag);
+       if (frag == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       frag->conn = conn;
+
+       ZERO_STRUCT(u.shutdown);
+
+       error = dcerpc_ncacn_packet_blob(frag,
+                                        DCERPC_PKT_SHUTDOWN,
+                                        DCERPC_PFC_FLAG_FIRST |
+                                        DCERPC_PFC_FLAG_LAST,
+                                        0, /* auth_length */
+                                        0, /* call_id */
+                                        &u,
+                                        &frag->blob);
+       if (!NT_STATUS_IS_OK(error)) {
+               TALLOC_FREE(frag);
+               return error;
+       }
+
+       /* explicitly set frag_len here as dcerpc_push_ncacn_packet() can't
+        * compute it right for requests because the auth trailer is missing
+        * at this stage */
+       //dcerpc_set_frag_length(&frag->blob, frag_len);
+
+       /*
+        * We need to add a dcerpc_write_fragment_queue_send/recv()
+        */
+
+       frag->vector.iov_base = frag->blob.data;
+       frag->vector.iov_len = frag->blob.length;
+       subreq = tstream_writev_queue_send(frag, ev,
+                                          conn->transport.stream,
+                                          conn->transport.write_queue,
+                                          &frag->vector, 1);
+       if (subreq == NULL) {
+               TALLOC_FREE(frag);
+               return NT_STATUS_NO_MEMORY;
+       }
+       tevent_req_set_callback(subreq,
+                               dcerpc_submit_shutdown_done,
+                               frag);
+
+       conn->loop.subreq = subreq;
+
+       return NT_STATUS_OK;
+}
+
+static void dcerpc_submit_shutdown_done(struct tevent_req *subreq)
+{
+       struct dcerpc_submit_shutdown_frag *frag =
+               tevent_req_callback_data(subreq,
+               struct dcerpc_submit_shutdown_frag);
+       struct dcerpc_connection *conn = frag->conn;
+
+       TALLOC_FREE(subreq);
+
+       TALLOC_FREE(frag);
+
+       dcerpc_connection_dead(conn, NT_STATUS_LOCAL_DISCONNECT);
+}
+
 struct dcerpc_server_connection_loop_state {
        struct tevent_context *ev;
        struct dcerpc_connection *conn;