s3-server: tevent_req_post() in common ioctl handler
authorDavid Disseldorp <ddiss@suse.de>
Fri, 7 Oct 2011 18:20:08 +0000 (20:20 +0200)
committerDavid Disseldorp <ddiss@suse.de>
Tue, 11 Oct 2011 09:45:42 +0000 (11:45 +0200)
source3/smbd/smb2_ioctl.c

index b89748365cedff6e78dd05b5addb16f563aac0a5..b89937c5f328b7daec05a981ab17cd95fc0d9e87 100644 (file)
@@ -221,9 +221,9 @@ struct smbd_smb2_ioctl_state {
 static void smbd_smb2_ioctl_pipe_write_done(struct tevent_req *subreq);
 static void smbd_smb2_ioctl_pipe_read_done(struct tevent_req *subreq);
 
-static struct tevent_req *fsctl_dfs_get_refers_post(struct tevent_context *ev,
-                                                  struct tevent_req *req,
-                                       struct smbd_smb2_ioctl_state *state)
+static NTSTATUS fsctl_dfs_get_refers(struct tevent_context *ev,
+                                    struct tevent_req *req,
+                                    struct smbd_smb2_ioctl_state *state)
 {
        uint16_t in_max_referral_level;
        DATA_BLOB in_file_name_buffer;
@@ -236,18 +236,15 @@ static struct tevent_req *fsctl_dfs_get_refers_post(struct tevent_context *ev,
        char *dfs_data = NULL;
 
        if (!IS_IPC(state->smbreq->conn)) {
-               tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
-               return tevent_req_post(req, ev);
+               return NT_STATUS_INVALID_DEVICE_REQUEST;
        }
 
        if (!lp_host_msdfs()) {
-               tevent_req_nterror(req, NT_STATUS_FS_DRIVER_REQUIRED);
-               return tevent_req_post(req, ev);
+               return NT_STATUS_FS_DRIVER_REQUIRED;
        }
 
        if (state->in_input.length < (2 + 2)) {
-               tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
-               return tevent_req_post(req, ev);
+               return NT_STATUS_INVALID_PARAMETER;
        }
 
        in_max_referral_level = SVAL(state->in_input.data, 0);
@@ -260,8 +257,7 @@ static struct tevent_req *fsctl_dfs_get_refers_post(struct tevent_context *ev,
                                   &in_file_name_string,
                                   &in_file_name_string_size);
        if (!ok) {
-               tevent_req_nterror(req, NT_STATUS_ILLEGAL_CHARACTER);
-               return tevent_req_post(req, ev);
+               return NT_STATUS_ILLEGAL_CHARACTER;
        }
 
        dfs_size = setup_dfs_referral(state->smbreq->conn,
@@ -269,8 +265,7 @@ static struct tevent_req *fsctl_dfs_get_refers_post(struct tevent_context *ev,
                                      in_max_referral_level,
                                      &dfs_data, &status);
        if (dfs_size < 0) {
-               tevent_req_nterror(req, status);
-               return tevent_req_post(req, ev);
+               return status;
        }
 
        if (dfs_size > state->in_max_output) {
@@ -285,54 +280,14 @@ static struct tevent_req *fsctl_dfs_get_refers_post(struct tevent_context *ev,
                                             (uint8_t *)dfs_data,
                                             dfs_size);
        SAFE_FREE(dfs_data);
-       if (dfs_size > 0 &&
-           tevent_req_nomem(state->out_output.data, req)) {
-               return tevent_req_post(req, ev);
+       if ((dfs_size > 0) && (state->out_output.data == NULL)) {
+               return NT_STATUS_NO_MEMORY;
        }
 
        if (overflow) {
-               tevent_req_nterror(req, STATUS_BUFFER_OVERFLOW);
-       } else {
-               tevent_req_done(req);
-       }
-       return tevent_req_post(req, ev);
-}
-
-static struct tevent_req *fsctl_pipe_transceive_post(struct tevent_context *ev,
-                                                    struct tevent_req *req,
-                                       struct smbd_smb2_ioctl_state *state)
-{
-       struct tevent_req *subreq;
-
-       if (!IS_IPC(state->smbreq->conn)) {
-               tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED);
-               return tevent_req_post(req, ev);
-       }
-
-       if (state->fsp == NULL) {
-               tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
-               return tevent_req_post(req, ev);
-       }
-
-       if (!fsp_is_np(state->fsp)) {
-               tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
-               return tevent_req_post(req, ev);
+               return STATUS_BUFFER_OVERFLOW;
        }
-
-       DEBUG(10,("smbd_smb2_ioctl_send: np_write_send of size %u\n",
-               (unsigned int)state->in_input.length ));
-
-       subreq = np_write_send(state, ev,
-                              state->fsp->fake_file_handle,
-                              state->in_input.data,
-                              state->in_input.length);
-       if (tevent_req_nomem(subreq, req)) {
-               return tevent_req_post(req, ev);
-       }
-       tevent_req_set_callback(subreq,
-                               smbd_smb2_ioctl_pipe_write_done,
-                               req);
-       return req;
+       return NT_STATUS_OK;
 }
 
 #define COPYCHUNK_MAX_CHUNKS   INT_MAX
@@ -367,9 +322,9 @@ static bool copychunk_check_limits(struct srv_copychunk_copy *cc_copy)
        return true;
 }
 
-static struct tevent_req *fsctl_srv_copychunk_post(struct tevent_context *ev,
-                                                   struct tevent_req *req,
-                                       struct smbd_smb2_ioctl_state *state)
+static NTSTATUS fsctl_srv_copychunk(struct tevent_context *ev,
+                                   struct tevent_req *req,
+                                   struct smbd_smb2_ioctl_state *state)
 {
        struct srv_copychunk_copy cc_copy;
        enum ndr_err_code ndr_ret;
@@ -433,16 +388,10 @@ err_out:
        ndr_ret = ndr_push_struct_blob(&state->out_output, state, &cc_rsp,
                        (ndr_push_flags_fn_t)ndr_push_srv_copychunk_rsp);
        if (ndr_ret != NDR_ERR_SUCCESS) {
-               tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
-               return tevent_req_post(req, ev);
+               return NT_STATUS_INTERNAL_ERROR;
        }
 
-       if (!NT_STATUS_IS_OK(status)) {
-               tevent_req_nterror(req, status);
-       } else {
-               tevent_req_done(req);
-       }
-       return tevent_req_post(req, ev);
+       return status;
 }
 
 /*
@@ -455,9 +404,9 @@ err_out:
  * Allocate the correct amount and return the pointer to let
  * it be deallocated when we return.
  */
-static struct tevent_req *fsctl_srv_enum_snaps_post(struct tevent_context *ev,
-                                                   struct tevent_req *req,
-                                       struct smbd_smb2_ioctl_state *state)
+static NTSTATUS fsctl_srv_enum_snaps(struct tevent_context *ev,
+                                    struct tevent_req *req,
+                                    struct smbd_smb2_ioctl_state *state)
 {
        struct shadow_copy_data *shadow_data = NULL;
        bool labels = False;
@@ -468,16 +417,14 @@ static struct tevent_req *fsctl_srv_enum_snaps_post(struct tevent_context *ev,
        NTSTATUS status;
 
        if (state->fsp == NULL) {
-               tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
-               return tevent_req_post(req, ev);
+               return NT_STATUS_FILE_CLOSED;
        }
 
        if (state->in_max_output < 16) {
                DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: "
                         "state->in_max_output(%u) < 16 is invalid!\n",
                         state->in_max_output));
-               tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
-               return tevent_req_post(req, ev);
+               return NT_STATUS_INVALID_PARAMETER;
        }
 
        if (state->in_max_output > 16) {
@@ -486,9 +433,9 @@ static struct tevent_req *fsctl_srv_enum_snaps_post(struct tevent_context *ev,
 
        shadow_data = talloc_zero(talloc_tos(),
                                    struct shadow_copy_data);
-       if (tevent_req_nomem(shadow_data, req)) {
+       if (shadow_data == NULL) {
                DEBUG(0,("TALLOC_ZERO() failed!\n"));
-               return tevent_req_post(req, ev);
+               return NT_STATUS_NO_MEMORY;
        }
 
        /*
@@ -508,8 +455,7 @@ static struct tevent_req *fsctl_srv_enum_snaps_post(struct tevent_context *ev,
                        status = map_nt_error_from_unix(errno);
                }
                TALLOC_FREE(shadow_data);
-               tevent_req_nterror(req, status);
-               return tevent_req_post(req, ev);
+               return status;
        }
 
        labels_data_count =
@@ -527,13 +473,12 @@ static struct tevent_req *fsctl_srv_enum_snaps_post(struct tevent_context *ev,
                          "state->in_max_output(%u) too small (%u) bytes "
                          "needed!\n", state->in_max_output, data_count));
                TALLOC_FREE(shadow_data);
-               tevent_req_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
-               return tevent_req_post(req, ev);
+               return NT_STATUS_BUFFER_TOO_SMALL;
        }
 
        state->out_output = data_blob_talloc(state, NULL, data_count);
-       if (tevent_req_nomem(state->out_output.data, req)) {
-               return tevent_req_post(req, ev);
+       if (state->out_output.data == NULL) {
+               return NT_STATUS_NO_MEMORY;
        }
 
        pdata = (char *)state->out_output.data;
@@ -568,20 +513,18 @@ static struct tevent_req *fsctl_srv_enum_snaps_post(struct tevent_context *ev,
 
        TALLOC_FREE(shadow_data);
 
-       tevent_req_done(req);
-       return tevent_req_post(req, ev);
+       return NT_STATUS_OK;
 }
 
-static struct tevent_req *fsctl_srv_req_resume_key(struct tevent_context *ev,
-                                                  struct tevent_req *req,
-                                       struct smbd_smb2_ioctl_state *state)
+static NTSTATUS fsctl_srv_req_resume_key(struct tevent_context *ev,
+                                        struct tevent_req *req,
+                                        struct smbd_smb2_ioctl_state *state)
 {
        struct req_resume_key_rsp rkey_rsp;
        enum ndr_err_code ndr_ret;
 
        if (state->fsp == NULL) {
-               tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
-               return tevent_req_post(req, ev);
+               return NT_STATUS_FILE_CLOSED;
        }
 
        ZERO_STRUCT(rkey_rsp);
@@ -594,19 +537,16 @@ static struct tevent_req *fsctl_srv_req_resume_key(struct tevent_context *ev,
        ndr_ret = ndr_push_struct_blob(&state->out_output, state, &rkey_rsp,
                        (ndr_push_flags_fn_t)ndr_push_req_resume_key_rsp);
        if (ndr_ret != NDR_ERR_SUCCESS) {
-               tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
-               return tevent_req_post(req, ev);
+               return NT_STATUS_INTERNAL_ERROR;
        }
 
        if (state->in_max_output < state->out_output.length) {
                DEBUG(0,("max output %u too small for resume key rsp %zd\n",
                         state->in_max_output, state->out_output.length));
-               tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
-               return tevent_req_post(req, ev);
+               return NT_STATUS_INVALID_PARAMETER;
        }
 
-       tevent_req_done(req);
-       return tevent_req_post(req, ev);
+       return NT_STATUS_OK;
 }
 
 static struct tevent_req *smbd_smb2_ioctl_send(TALLOC_CTX *mem_ctx,
@@ -622,6 +562,7 @@ static struct tevent_req *smbd_smb2_ioctl_send(TALLOC_CTX *mem_ctx,
        struct smbd_smb2_ioctl_state *state;
        struct smb_request *smbreq;
        files_struct *fsp = NULL;
+       NTSTATUS status = NT_STATUS_INTERNAL_ERROR;
 
        req = tevent_req_create(mem_ctx, &state,
                                struct smbd_smb2_ioctl_state);
@@ -664,15 +605,53 @@ static struct tevent_req *smbd_smb2_ioctl_send(TALLOC_CTX *mem_ctx,
 
        switch (in_ctl_code) {
        case 0x00060194: /* FSCTL_DFS_GET_REFERRALS */
-               return fsctl_dfs_get_refers_post(ev, req, state);
+               status = fsctl_dfs_get_refers(ev, req, state);
+               break;
        case 0x0011C017: /* FSCTL_PIPE_TRANSCEIVE */
-               return fsctl_pipe_transceive_post(ev, req, state);
+       {
+               struct tevent_req *subreq;
+
+               if (!IS_IPC(state->smbreq->conn)) {
+                       status = NT_STATUS_NOT_SUPPORTED;
+                       break;
+               }
+
+               if (state->fsp == NULL) {
+                       status = NT_STATUS_FILE_CLOSED;
+                       break;
+               }
+
+               if (!fsp_is_np(state->fsp)) {
+                       status = NT_STATUS_FILE_CLOSED;
+                       break;
+               }
+
+               DEBUG(10,("smbd_smb2_ioctl_send: np_write_send of size %u\n",
+                       (unsigned int)state->in_input.length ));
+
+               subreq = np_write_send(state, ev,
+                                      state->fsp->fake_file_handle,
+                                      state->in_input.data,
+                                      state->in_input.length);
+               if (subreq == NULL) {
+                       status = NT_STATUS_FILE_CLOSED;
+                       break;
+               }
+               tevent_req_set_callback(subreq,
+                                       smbd_smb2_ioctl_pipe_write_done,
+                                       req);
+               status = NT_STATUS_OK;
+               break;
+       }
        case 0x001440F2: /* FSCTL_SRV_COPYCHUNK */
-               return fsctl_srv_copychunk_post(ev, req, state);
+               status = fsctl_srv_copychunk(ev, req, state);
+               break;
        case 0x00144064: /* FSCTL_SRV_ENUMERATE_SNAPSHOTS */
-               return fsctl_srv_enum_snaps_post(ev, req, state);
+               status = fsctl_srv_enum_snaps(ev, req, state);
+               break;
        case 0x00140078: /* FSCTL_SRV_REQUEST_RESUME_KEY */
-               return fsctl_srv_req_resume_key(ev, req, state);
+               status = fsctl_srv_req_resume_key(ev, req, state);
+               break;
        default:
                if (IS_IPC(smbreq->conn)) {
                        tevent_req_nterror(req, NT_STATUS_FS_DRIVER_REQUIRED);
@@ -682,7 +661,11 @@ static struct tevent_req *smbd_smb2_ioctl_send(TALLOC_CTX *mem_ctx,
                return tevent_req_post(req, ev);
        }
 
-       tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
+       if (!NT_STATUS_IS_OK(status)) {
+               tevent_req_nterror(req, status);
+       } else {
+               tevent_req_done(req);
+       }
        return tevent_req_post(req, ev);
 }