[5/9] cifs: update receive_encrypted_standard to handle compounded responses

Message ID 20180620011350.12328-6-lsahlber@redhat.com
State New
Headers show
Series
  • cifs: compounding
Related show

Commit Message

Ronnie Sahlberg June 20, 2018, 1:13 a.m.
Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
---
 fs/cifs/smb2ops.c | 39 ++++++++++++++++++++++++++++++++++++---
 1 file changed, 36 insertions(+), 3 deletions(-)

Patch

diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 687d9cdd3042..bbe4da12fdc7 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -2745,11 +2745,14 @@  static int
 receive_encrypted_standard(struct TCP_Server_Info *server,
 			   struct mid_q_entry **mid)
 {
-	int length;
+	int ret, length;
 	char *buf = server->smallbuf;
+	struct smb2_sync_hdr *shdr;
 	unsigned int pdu_length = server->pdu_size;
 	unsigned int buf_size;
 	struct mid_q_entry *mid_entry;
+	int next_is_large;
+	char *next_buffer = NULL;
 
 	/* switch to large buffer if too big for a small one */
 	if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE) {
@@ -2770,6 +2773,21 @@  receive_encrypted_standard(struct TCP_Server_Info *server,
 	if (length)
 		return length;
 
+	next_is_large = server->large_buf;
+ one_more:
+	shdr = (struct smb2_sync_hdr *)buf;
+	if (shdr->NextCommand) {
+		if (next_is_large) {
+			next_buffer = (char *)cifs_buf_get();
+			memcpy(next_buffer, server->bigbuf + shdr->NextCommand,
+			       pdu_length - shdr->NextCommand);
+		} else {
+			next_buffer = (char *)cifs_small_buf_get();
+			memcpy(next_buffer, server->smallbuf + shdr->NextCommand,
+			       pdu_length - shdr->NextCommand);
+		}
+	}
+
 	mid_entry = smb2_find_mid(server, buf);
 	if (mid_entry == NULL)
 		cifs_dbg(FYI, "mid not found\n");
@@ -2777,13 +2795,28 @@  receive_encrypted_standard(struct TCP_Server_Info *server,
 		cifs_dbg(FYI, "mid found\n");
 		mid_entry->decrypted = true;
 	}
+	mid_entry->resp_buf_size = server->pdu_size;
 
 	*mid = mid_entry;
 
 	if (mid_entry && mid_entry->handle)
-		return mid_entry->handle(server, mid_entry);
+		ret = mid_entry->handle(server, mid_entry);
+	else
+		ret = cifs_handle_standard(server, mid_entry);
+
+	if (ret == 0 && shdr->NextCommand) {
+		pdu_length -= shdr->NextCommand;
+		server->large_buf = next_is_large;
+		if (next_is_large) {
+			server->bigbuf = next_buffer;
+		} else {
+			server->smallbuf = next_buffer;
+		}
+		buf += shdr->NextCommand;
+		goto one_more;
+	}
 
-	return cifs_handle_standard(server, mid_entry);
+        return ret;
 }
 
 static int