From 61b9418784f27b799338ea5aeab02b39bbd39ad1 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 2 Jun 2020 17:13:22 +0200 Subject: [PATCH] s3:smbd: introduce smbXsrv_pending_break infrastructure MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This prepares support for oplock/lease break replay from the server to the client. We need some state in order to do replays later. BUG: https://bugzilla.samba.org/show_bug.cgi?id=11897 Signed-off-by: Stefan Metzmacher Reviewed-by: Günther Deschner --- source3/smbd/smb2_server.c | 81 +++++++++++++++++++++++++++++++------- 1 file changed, 67 insertions(+), 14 deletions(-) diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index 6eb95cb93b2..b54c17acee5 100644 --- a/source3/smbd/smb2_server.c +++ b/source3/smbd/smb2_server.c @@ -3590,24 +3590,72 @@ static NTSTATUS smbd_smb2_send_break(struct smbXsrv_connection *xconn, return NT_STATUS_OK; } +struct smbXsrv_pending_break { + struct smbXsrv_pending_break *prev, *next; + struct smbXsrv_client *client; + uint64_t session_id; + union { + uint8_t generic[1]; + uint8_t oplock[0x18]; + uint8_t lease[0x2c]; + } body; + size_t body_len; +}; + +static struct smbXsrv_pending_break *smbXsrv_pending_break_create( + struct smbXsrv_client *client, + uint64_t session_id) +{ + struct smbXsrv_pending_break *pb = NULL; + + pb = talloc_zero(client, struct smbXsrv_pending_break); + if (pb == NULL) { + return NULL; + } + pb->client = client; + pb->session_id = session_id; + + return pb; +} + +static NTSTATUS smbXsrv_pending_break_schedule(struct smbXsrv_pending_break *pb) +{ + struct smbXsrv_connection *xconn = pb->client->connections; + NTSTATUS status; + + status = smbd_smb2_send_break(xconn, + pb->session_id, + pb->body.generic, + pb->body_len); + + TALLOC_FREE(pb); + + return status; +} + NTSTATUS smbd_smb2_send_oplock_break(struct smbXsrv_client *client, struct smbXsrv_open *op, uint8_t oplock_level) { - struct smbXsrv_connection *xconn = client->connections; - uint8_t body[0x18]; + struct smbXsrv_pending_break *pb = NULL; + uint8_t *body = NULL; + + pb = smbXsrv_pending_break_create(client, + op->compat->vuid); + if (pb == NULL) { + return NT_STATUS_NO_MEMORY; + } + pb->body_len = sizeof(pb->body.oplock); + body = pb->body.oplock; - SSVAL(body, 0x00, sizeof(body)); + SSVAL(body, 0x00, pb->body_len); SCVAL(body, 0x02, oplock_level); SCVAL(body, 0x03, 0); /* reserved */ SIVAL(body, 0x04, 0); /* reserved */ SBVAL(body, 0x08, op->global->open_persistent_id); SBVAL(body, 0x10, op->global->open_volatile_id); - return smbd_smb2_send_break(xconn, - op->compat->vuid, - body, - sizeof(body)); + return smbXsrv_pending_break_schedule(pb); } NTSTATUS smbd_smb2_send_lease_break(struct smbXsrv_client *client, @@ -3617,10 +3665,18 @@ NTSTATUS smbd_smb2_send_lease_break(struct smbXsrv_client *client, uint32_t current_lease_state, uint32_t new_lease_state) { - struct smbXsrv_connection *xconn = client->connections; - uint8_t body[0x2c]; + struct smbXsrv_pending_break *pb = NULL; + uint8_t *body = NULL; + + pb = smbXsrv_pending_break_create(client, + 0); /* no session_id */ + if (pb == NULL) { + return NT_STATUS_NO_MEMORY; + } + pb->body_len = sizeof(pb->body.lease); + body = pb->body.lease; - SSVAL(body, 0x00, sizeof(body)); + SSVAL(body, 0x00, pb->body_len); SSVAL(body, 0x02, new_epoch); SIVAL(body, 0x04, lease_flags); SBVAL(body, 0x08, lease_key->data[0]); @@ -3631,10 +3687,7 @@ NTSTATUS smbd_smb2_send_lease_break(struct smbXsrv_client *client, SIVAL(body, 0x24, 0); /* AccessMaskHint, MUST be 0 */ SIVAL(body, 0x28, 0); /* ShareMaskHint, MUST be 0 */ - return smbd_smb2_send_break(xconn, - 0, /* no session_id */ - body, - sizeof(body)); + return smbXsrv_pending_break_schedule(pb); } static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state) -- 2.34.1