libcli/smb: Add smbXcli_conn_samba_suicide
authorVolker Lendecke <vl@samba.org>
Wed, 4 Jan 2012 12:28:07 +0000 (13:28 +0100)
committerVolker Lendecke <vl@samba.org>
Thu, 5 Jan 2012 12:09:36 +0000 (13:09 +0100)
This is a pure test tool against Samba servers

libcli/smb/smbXcli_base.c
libcli/smb/smbXcli_base.h

index 6a2547050e0a057ff163b41d8bed0d272b5a847a..ba40ef7bf1a98ace0b1cce57387c363242e4a8a4 100644 (file)
@@ -424,6 +424,103 @@ const struct GUID *smbXcli_conn_server_guid(struct smbXcli_conn *conn)
        return &conn->smb1.server.guid;
 }
 
+struct smbXcli_conn_samba_suicide_state {
+       struct smbXcli_conn *conn;
+       struct iovec iov;
+       uint8_t buf[9];
+};
+
+static void smbXcli_conn_samba_suicide_done(struct tevent_req *subreq);
+
+struct tevent_req *smbXcli_conn_samba_suicide_send(TALLOC_CTX *mem_ctx,
+                                                  struct tevent_context *ev,
+                                                  struct smbXcli_conn *conn,
+                                                  uint8_t exitcode)
+{
+       struct tevent_req *req, *subreq;
+       struct smbXcli_conn_samba_suicide_state *state;
+
+       req = tevent_req_create(mem_ctx, &state,
+                               struct smbXcli_conn_samba_suicide_state);
+       if (req == NULL) {
+               return NULL;
+       }
+       state->conn = conn;
+       SIVAL(state->buf, 4, 0x74697865);
+       SCVAL(state->buf, 8, exitcode);
+       _smb_setlen_nbt(state->buf, sizeof(state->buf)-4);
+
+       state->iov.iov_base = state->buf;
+       state->iov.iov_len = sizeof(state->buf);
+
+       subreq = writev_send(state, ev, conn->outgoing, conn->write_fd,
+                            false, &state->iov, 1);
+       if (tevent_req_nomem(subreq, req)) {
+               return tevent_req_post(req, ev);
+       }
+       tevent_req_set_callback(subreq, smbXcli_conn_samba_suicide_done, req);
+       return req;
+}
+
+static void smbXcli_conn_samba_suicide_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+               subreq, struct tevent_req);
+       struct smbXcli_conn_samba_suicide_state *state = tevent_req_data(
+               req, struct smbXcli_conn_samba_suicide_state);
+       ssize_t nwritten;
+       int err;
+
+       nwritten = writev_recv(subreq, &err);
+       TALLOC_FREE(subreq);
+       if (nwritten == -1) {
+               NTSTATUS status = map_nt_error_from_unix_common(err);
+               smbXcli_conn_disconnect(state->conn, status);
+               return;
+       }
+       tevent_req_done(req);
+}
+
+NTSTATUS smbXcli_conn_samba_suicide_recv(struct tevent_req *req)
+{
+       return tevent_req_simple_recv_ntstatus(req);
+}
+
+NTSTATUS smbXcli_conn_samba_suicide(struct smbXcli_conn *conn,
+                                   uint8_t exitcode)
+{
+       TALLOC_CTX *frame = talloc_stackframe();
+       struct tevent_context *ev;
+       struct tevent_req *req;
+       NTSTATUS status = NT_STATUS_NO_MEMORY;
+       bool ok;
+
+       if (smbXcli_conn_has_async_calls(conn)) {
+               /*
+                * Can't use sync call while an async call is in flight
+                */
+               status = NT_STATUS_INVALID_PARAMETER_MIX;
+               goto fail;
+       }
+       ev = tevent_context_init(frame);
+       if (ev == NULL) {
+               goto fail;
+       }
+       req = smbXcli_conn_samba_suicide_send(frame, ev, conn, exitcode);
+       if (req == NULL) {
+               goto fail;
+       }
+       ok = tevent_req_poll(req, ev);
+       if (!ok) {
+               status = map_nt_error_from_unix_common(errno);
+               goto fail;
+       }
+       status = smbXcli_conn_samba_suicide_recv(req);
+ fail:
+       TALLOC_FREE(frame);
+       return status;
+}
+
 uint32_t smb1cli_conn_capabilities(struct smbXcli_conn *conn)
 {
        return conn->smb1.capabilities;
index 0eaf797936fca839c17c0060ad2d8fc59e094f1c..a2b64b1e6f9f1f4bd1017b677b365d70b7785eed 100644 (file)
@@ -51,6 +51,14 @@ NTTIME smbXcli_conn_server_system_time(struct smbXcli_conn *conn);
 const DATA_BLOB *smbXcli_conn_server_gss_blob(struct smbXcli_conn *conn);
 const struct GUID *smbXcli_conn_server_guid(struct smbXcli_conn *conn);
 
+struct tevent_req *smbXcli_conn_samba_suicide_send(TALLOC_CTX *mem_ctx,
+                                                  struct tevent_context *ev,
+                                                  struct smbXcli_conn *conn,
+                                                  uint8_t exitcode);
+NTSTATUS smbXcli_conn_samba_suicide_recv(struct tevent_req *req);
+NTSTATUS smbXcli_conn_samba_suicide(struct smbXcli_conn *conn,
+                                   uint8_t exitcode);
+
 void smbXcli_req_unset_pending(struct tevent_req *req);
 bool smbXcli_req_set_pending(struct tevent_req *req);