diff options
author | Jeremy Allison <jra@samba.org> | 2010-04-18 20:23:54 -0700 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2010-04-18 20:23:54 -0700 |
commit | 59fa1e1890e0a007f56776d9539bf3f1ce074a34 (patch) | |
tree | d0a19706135a161f4a195ef08159a58b0f6d71e6 | |
parent | 058d4a21afa843241c6a91a251fb46a327037194 (diff) | |
download | samba-59fa1e1890e0a007f56776d9539bf3f1ce074a34.tar.gz samba-59fa1e1890e0a007f56776d9539bf3f1ce074a34.tar.bz2 samba-59fa1e1890e0a007f56776d9539bf3f1ce074a34.zip |
Final fix for #7331 - Compound async SMB 2 requests don't work right.
Don't free the cancelled SMB2 req early, let the cancelation
function take care of it. Return a NT_STATUS_CANCELLED when
we find and cancel a request. Fix our SMB2 error returns to
correctly set the structuresize to 9, and add the expected
zero byte (see section 2.2.2 in the SMB2 spec.).
This causes Samba to pass the test program in this bug report
that W2K8R2 fails (heh heh :-). This is because we always cause
compound requests to get to a cancelation point before dealing
with a cancel request.
Jeremy.
-rw-r--r-- | source3/smbd/smb2_notify.c | 7 | ||||
-rw-r--r-- | source3/smbd/smb2_server.c | 17 |
2 files changed, 20 insertions, 4 deletions
diff --git a/source3/smbd/smb2_notify.c b/source3/smbd/smb2_notify.c index 3d60ffb39c..460e6293f5 100644 --- a/source3/smbd/smb2_notify.c +++ b/source3/smbd/smb2_notify.c @@ -113,6 +113,13 @@ static void smbd_smb2_request_notify_done(struct tevent_req *subreq) uint64_t mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID); DEBUG(10,("smbd_smb2_request_notify_done: cancelled mid %llu\n", (unsigned long long)mid )); + error = smbd_smb2_request_error(req, NT_STATUS_CANCELLED); + if (!NT_STATUS_IS_OK(error)) { + smbd_server_connection_terminate(req->sconn, + nt_errstr(error)); + return; + } + TALLOC_FREE(subreq); return; } diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index b697cb924b..0b3222e6ab 100644 --- a/source3/smbd/smb2_server.c +++ b/source3/smbd/smb2_server.c @@ -682,6 +682,12 @@ NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req, message_id = BVAL(reqhdr, SMB2_HDR_MESSAGE_ID); async_id = message_id; /* keep it simple for now... */ + /* + * What we send is identical to a smbd_smb2_request_error + * packet with an error status of STATUS_PENDING. Make use + * of this fact sometime when refactoring. JRA. + */ + state = talloc_zero(req->sconn, struct smbd_smb2_request_pending_state); if (state == NULL) { return NT_STATUS_NO_MEMORY; @@ -886,8 +892,6 @@ static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req) smb2_opcode_name((uint16_t)IVAL(inhdr, SMB2_HDR_OPCODE)), (unsigned long long)found_id )); tevent_req_cancel(cur->subreq); - TALLOC_FREE(cur->subreq); - TALLOC_FREE(cur); } return NT_STATUS_OK; @@ -1246,6 +1250,7 @@ NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req, SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status)); outbody = outhdr + SMB2_HDR_BODY; + SSVAL(outbody, 0, 9); req->out.vector[i+1].iov_base = (void *)outbody; req->out.vector[i+1].iov_len = 8; @@ -1255,8 +1260,12 @@ NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req, req->out.vector[i+2].iov_base = (void *)info->data; req->out.vector[i+2].iov_len = info->length; } else { - req->out.vector[i+2].iov_base = NULL; - req->out.vector[i+2].iov_len = 0; + req->out.vector[i+2].iov_base = talloc_array(req, uint8_t, 1); + if (!req->out.vector[i+2].iov_base) { + return NT_STATUS_NO_MEMORY; + } + SCVAL(req->out.vector[i+2].iov_base, 0, 0); + req->out.vector[i+2].iov_len = 1; } /* |