]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blobdiff - fs/cifs/smb2misc.c
mnt: Tuck mounts under others instead of creating shadow/side mounts.
[mirror_ubuntu-zesty-kernel.git] / fs / cifs / smb2misc.c
index 3d383489b9cf313395e94a0bff4a719501b4b309..fd516ea8b8f89c46cb1d9977d53fbbb9d16de9d3 100644 (file)
 #include "cifs_debug.h"
 #include "cifs_unicode.h"
 #include "smb2status.h"
+#include "smb2glob.h"
 
 static int
-check_smb2_hdr(struct smb2_hdr *hdr, __u64 mid)
+check_smb2_hdr(struct smb2_sync_hdr *shdr, __u64 mid)
 {
-       __u64 wire_mid = le64_to_cpu(hdr->MessageId);
+       __u64 wire_mid = le64_to_cpu(shdr->MessageId);
 
        /*
         * Make sure that this really is an SMB, that it is a response,
         * and that the message ids match.
         */
-       if ((hdr->ProtocolId == SMB2_PROTO_NUMBER) &&
+       if ((shdr->ProtocolId == SMB2_PROTO_NUMBER) &&
            (mid == wire_mid)) {
-               if (hdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR)
+               if (shdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR)
                        return 0;
                else {
                        /* only one valid case where server sends us request */
-                       if (hdr->Command == SMB2_OPLOCK_BREAK)
+                       if (shdr->Command == SMB2_OPLOCK_BREAK)
                                return 0;
                        else
                                cifs_dbg(VFS, "Received Request not response\n");
                }
        } else { /* bad signature or mid */
-               if (hdr->ProtocolId != SMB2_PROTO_NUMBER)
+               if (shdr->ProtocolId != SMB2_PROTO_NUMBER)
                        cifs_dbg(VFS, "Bad protocol string signature header %x\n",
-                                le32_to_cpu(hdr->ProtocolId));
+                                le32_to_cpu(shdr->ProtocolId));
                if (mid != wire_mid)
                        cifs_dbg(VFS, "Mids do not match: %llu and %llu\n",
                                 mid, wire_mid);
@@ -95,8 +96,9 @@ static const __le16 smb2_rsp_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = {
 int
 smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
 {
-       struct smb2_hdr *hdr = (struct smb2_hdr *)buf;
-       struct smb2_pdu *pdu = (struct smb2_pdu *)hdr;
+       struct smb2_pdu *pdu = (struct smb2_pdu *)buf;
+       struct smb2_hdr *hdr = &pdu->hdr;
+       struct smb2_sync_hdr *shdr = get_sync_hdr(buf);
        __u64 mid;
        __u32 len = get_rfc1002_length(buf);
        __u32 clc_len;  /* calculated length */
@@ -111,7 +113,7 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
         * ie Validate the wct via smb2_struct_sizes table above
         */
 
-       if (hdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) {
+       if (shdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) {
                struct smb2_transform_hdr *thdr =
                        (struct smb2_transform_hdr *)buf;
                struct cifs_ses *ses = NULL;
@@ -133,10 +135,10 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
                }
        }
 
-
-       mid = le64_to_cpu(hdr->MessageId);
+       mid = le64_to_cpu(shdr->MessageId);
        if (length < sizeof(struct smb2_pdu)) {
-               if ((length >= sizeof(struct smb2_hdr)) && (hdr->Status != 0)) {
+               if ((length >= sizeof(struct smb2_hdr))
+                   && (shdr->Status != 0)) {
                        pdu->StructureSize2 = 0;
                        /*
                         * As with SMB/CIFS, on some error cases servers may
@@ -154,29 +156,30 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
                return 1;
        }
 
-       if (check_smb2_hdr(hdr, mid))
+       if (check_smb2_hdr(shdr, mid))
                return 1;
 
-       if (hdr->StructureSize != SMB2_HEADER_STRUCTURE_SIZE) {
+       if (shdr->StructureSize != SMB2_HEADER_STRUCTURE_SIZE) {
                cifs_dbg(VFS, "Illegal structure size %u\n",
-                        le16_to_cpu(hdr->StructureSize));
+                        le16_to_cpu(shdr->StructureSize));
                return 1;
        }
 
-       command = le16_to_cpu(hdr->Command);
+       command = le16_to_cpu(shdr->Command);
        if (command >= NUMBER_OF_SMB2_COMMANDS) {
                cifs_dbg(VFS, "Illegal SMB2 command %d\n", command);
                return 1;
        }
 
        if (smb2_rsp_struct_sizes[command] != pdu->StructureSize2) {
-               if (command != SMB2_OPLOCK_BREAK_HE && (hdr->Status == 0 ||
+               if (command != SMB2_OPLOCK_BREAK_HE && (shdr->Status == 0 ||
                    pdu->StructureSize2 != SMB2_ERROR_STRUCTURE_SIZE2)) {
                        /* error packets have 9 byte structure size */
                        cifs_dbg(VFS, "Illegal response size %u for command %d\n",
                                 le16_to_cpu(pdu->StructureSize2), command);
                        return 1;
-               } else if (command == SMB2_OPLOCK_BREAK_HE && (hdr->Status == 0)
+               } else if (command == SMB2_OPLOCK_BREAK_HE
+                          && (shdr->Status == 0)
                           && (le16_to_cpu(pdu->StructureSize2) != 44)
                           && (le16_to_cpu(pdu->StructureSize2) != 36)) {
                        /* special case for SMB2.1 lease break message */
@@ -199,7 +202,7 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
                         clc_len, 4 + len, mid);
                /* create failed on symlink */
                if (command == SMB2_CREATE_HE &&
-                   hdr->Status == STATUS_STOPPED_ON_SYMLINK)
+                   shdr->Status == STATUS_STOPPED_ON_SYMLINK)
                        return 0;
                /* Windows 7 server returns 24 bytes more */
                if (clc_len + 20 == len && command == SMB2_OPLOCK_BREAK_HE)
@@ -261,11 +264,12 @@ static const bool has_smb2_data_area[NUMBER_OF_SMB2_COMMANDS] = {
 char *
 smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr)
 {
+       struct smb2_sync_hdr *shdr = get_sync_hdr(hdr);
        *off = 0;
        *len = 0;
 
        /* error responses do not have data area */
-       if (hdr->Status && hdr->Status != STATUS_MORE_PROCESSING_REQUIRED &&
+       if (shdr->Status && shdr->Status != STATUS_MORE_PROCESSING_REQUIRED &&
            (((struct smb2_err_rsp *)hdr)->StructureSize) ==
                                                SMB2_ERROR_STRUCTURE_SIZE2)
                return NULL;
@@ -275,7 +279,7 @@ smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr)
         * of the data buffer offset and data buffer length for the particular
         * command.
         */
-       switch (hdr->Command) {
+       switch (shdr->Command) {
        case SMB2_NEGOTIATE:
                *off = le16_to_cpu(
                    ((struct smb2_negotiate_rsp *)hdr)->SecurityBufferOffset);
@@ -346,7 +350,7 @@ smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr)
 
        /* return pointer to beginning of data area, ie offset from SMB start */
        if ((*off != 0) && (*len != 0))
-               return (char *)(&hdr->ProtocolId) + *off;
+               return (char *)shdr + *off;
        else
                return NULL;
 }
@@ -358,12 +362,13 @@ smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr)
 unsigned int
 smb2_calc_size(void *buf)
 {
-       struct smb2_hdr *hdr = (struct smb2_hdr *)buf;
-       struct smb2_pdu *pdu = (struct smb2_pdu *)hdr;
+       struct smb2_pdu *pdu = (struct smb2_pdu *)buf;
+       struct smb2_hdr *hdr = &pdu->hdr;
+       struct smb2_sync_hdr *shdr = get_sync_hdr(hdr);
        int offset; /* the offset from the beginning of SMB to data area */
        int data_length; /* the length of the variable length data area */
        /* Structure Size has already been checked to make sure it is 64 */
-       int len = 4 + le16_to_cpu(pdu->hdr.StructureSize);
+       int len = 4 + le16_to_cpu(shdr->StructureSize);
 
        /*
         * StructureSize2, ie length of fixed parameter area has already
@@ -371,7 +376,7 @@ smb2_calc_size(void *buf)
         */
        len += le16_to_cpu(pdu->StructureSize2);
 
-       if (has_smb2_data_area[le16_to_cpu(hdr->Command)] == false)
+       if (has_smb2_data_area[le16_to_cpu(shdr->Command)] == false)
                goto calc_size_exit;
 
        smb2_get_data_area_len(&offset, &data_length, hdr);
@@ -582,7 +587,7 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
 
        cifs_dbg(FYI, "Checking for oplock break\n");
 
-       if (rsp->hdr.Command != SMB2_OPLOCK_BREAK)
+       if (rsp->hdr.sync_hdr.Command != SMB2_OPLOCK_BREAK)
                return false;
 
        if (rsp->StructureSize !=