summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2009-06-09 20:44:13 +0200
committerStefan Metzmacher <metze@samba.org>2009-06-24 21:04:56 +0200
commitbea384b2776c87c22e6c7e2ae6bca2d2321fd6e1 (patch)
tree3a52f9a1e5b70357058d7c53842998198f08521d
parentcf7c41b841d03ecbe09ee531f6dd73be17948ac1 (diff)
downloadsamba-bea384b2776c87c22e6c7e2ae6bca2d2321fd6e1.tar.gz
samba-bea384b2776c87c22e6c7e2ae6bca2d2321fd6e1.tar.bz2
samba-bea384b2776c87c22e6c7e2ae6bca2d2321fd6e1.zip
s3:smbd: add smbd_smb2_send_oplock_break()
metze
-rw-r--r--source3/smbd/globals.h5
-rw-r--r--source3/smbd/smb2_server.c88
2 files changed, 93 insertions, 0 deletions
diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index f002a6f51a..e101205417 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -195,6 +195,11 @@ NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
#define smbd_smb2_request_done(req, body, dyn) \
smbd_smb2_request_done_ex(req, NT_STATUS_OK, body, dyn, __location__)
+NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
+ uint64_t file_id_persistent,
+ uint64_t file_id_volatile,
+ uint8_t oplock_level);
+
NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req);
NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req);
diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c
index c889555a1c..f5282ed8ed 100644
--- a/source3/smbd/smb2_server.c
+++ b/source3/smbd/smb2_server.c
@@ -821,6 +821,94 @@ NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
return smbd_smb2_request_reply(req);
}
+struct smbd_smb2_send_oplock_break_state {
+ struct smbd_server_connection *sconn;
+ uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
+ struct iovec vector;
+};
+
+static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
+
+NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
+ uint64_t file_id_persistent,
+ uint64_t file_id_volatile,
+ uint8_t oplock_level)
+{
+ struct smbd_smb2_send_oplock_break_state *state;
+ struct tevent_req *subreq;
+ uint8_t *hdr;
+ uint8_t *body;
+
+ state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
+ if (state == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ state->sconn = sconn;
+
+ state->vector.iov_base = (void *)state->buf;
+ state->vector.iov_len = sizeof(state->buf);
+
+ _smb2_setlen(state->buf, sizeof(state->buf) - 4);
+ hdr = state->buf + 4;
+ body = hdr + SMB2_HDR_BODY;
+
+ SIVAL(hdr, 0, SMB2_MAGIC);
+ SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
+ SSVAL(hdr, SMB2_HDR_EPOCH, 0);
+ SIVAL(hdr, SMB2_HDR_STATUS, 0);
+ SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
+ SSVAL(hdr, SMB2_HDR_CREDIT, 0);
+ SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
+ SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
+ SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
+ SIVAL(hdr, SMB2_HDR_PID, 0);
+ SIVAL(hdr, SMB2_HDR_TID, 0);
+ SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
+ memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
+
+ SSVAL(body, 0x00, 0x18);
+
+ SCVAL(body, 0x02, oplock_level);
+ SCVAL(body, 0x03, 0); /* reserved */
+ SIVAL(body, 0x04, 0); /* reserved */
+ SBVAL(body, 0x08, file_id_persistent);
+ SBVAL(body, 0x10, file_id_volatile);
+
+ subreq = tstream_writev_queue_send(state,
+ sconn->smb2.event_ctx,
+ sconn->smb2.stream,
+ sconn->smb2.send_queue,
+ &state->vector, 1);
+ if (subreq == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ tevent_req_set_callback(subreq,
+ smbd_smb2_oplock_break_writev_done,
+ state);
+
+ return NT_STATUS_OK;
+}
+
+static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
+{
+ struct smbd_smb2_send_oplock_break_state *state =
+ tevent_req_callback_data(subreq,
+ struct smbd_smb2_send_oplock_break_state);
+ struct smbd_server_connection *sconn = state->sconn;
+ int ret;
+ int sys_errno;
+
+ ret = tstream_writev_queue_recv(subreq, &sys_errno);
+ TALLOC_FREE(subreq);
+ if (ret == -1) {
+ NTSTATUS status = map_nt_error_from_unix(sys_errno);
+ smbd_server_connection_terminate(sconn, nt_errstr(status));
+ return;
+ }
+
+ TALLOC_FREE(state);
+}
+
struct smbd_smb2_request_read_state {
size_t missing;
bool asked_for_header;