aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorTim Gardner <tim.gardner@canonical.com>2013-11-02 13:50:34 -0400
committerSteve French <smfrench@gmail.com>2013-11-02 13:51:53 -0400
commit3d378d3fd82a759d59c60d89b4559bf325d7e668 (patch)
tree1fc4634672bc18c7af79f1029d42e99869beb2c4 /fs/cifs
parent944d6f1a5b8f42a780a65378e5f52bea3ae0ce07 (diff)
cifs: Make big endian multiplex ID sequences monotonic on the wire
The multiplex identifier (MID) in the SMB header is only ever used by the client, in conjunction with PID, to match responses from the server. As such, the endianess of the MID is not important. However, When tracing packet sequences on the wire, protocol analyzers such as wireshark display MID as little endian. It is much more informative for the on-the-wire MID sequences to match debug information emitted by the CIFS driver. Therefore, one should write and read MID in the SMB header assuming it is always little endian. Observed from wireshark during the protocol negotiation and session setup: Multiplex ID: 256 Multiplex ID: 256 Multiplex ID: 512 Multiplex ID: 512 Multiplex ID: 768 Multiplex ID: 768 After this patch on-the-wire MID values begin at 1 and increase monotonically. Introduce get_next_mid64() for the internal consumers that use the full 64 bit multiplex identifier. Introduce the helpers get_mid() and compare_mid() to make the endian translation clear. Reviewed-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Tim Gardner <timg@tpi.com> Signed-off-by: Steve French <smfrench@gmail.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/cifsglob.h25
-rw-r--r--fs/cifs/cifspdu.h2
-rw-r--r--fs/cifs/misc.c10
-rw-r--r--fs/cifs/smb1ops.c4
-rw-r--r--fs/cifs/smb2transport.c2
-rw-r--r--fs/cifs/transport.c2
6 files changed, 35 insertions, 10 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 06e8947fc370..670da1e55be7 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -622,11 +622,34 @@ set_credits(struct TCP_Server_Info *server, const int val)
622} 622}
623 623
624static inline __u64 624static inline __u64
625get_next_mid(struct TCP_Server_Info *server) 625get_next_mid64(struct TCP_Server_Info *server)
626{ 626{
627 return server->ops->get_next_mid(server); 627 return server->ops->get_next_mid(server);
628} 628}
629 629
630static inline __le16
631get_next_mid(struct TCP_Server_Info *server)
632{
633 __u16 mid = get_next_mid64(server);
634 /*
635 * The value in the SMB header should be little endian for easy
636 * on-the-wire decoding.
637 */
638 return cpu_to_le16(mid);
639}
640
641static inline __u16
642get_mid(const struct smb_hdr *smb)
643{
644 return le16_to_cpu(smb->Mid);
645}
646
647static inline bool
648compare_mid(__u16 mid, const struct smb_hdr *smb)
649{
650 return mid == le16_to_cpu(smb->Mid);
651}
652
630/* 653/*
631 * When the server supports very large reads and writes via POSIX extensions, 654 * When the server supports very large reads and writes via POSIX extensions,
632 * we can allow up to 2^24-1, minus the size of a READ/WRITE_AND_X header, not 655 * we can allow up to 2^24-1, minus the size of a READ/WRITE_AND_X header, not
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index d40bd77a2392..f80f98f5ef9c 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -428,7 +428,7 @@ struct smb_hdr {
428 __u16 Tid; 428 __u16 Tid;
429 __le16 Pid; 429 __le16 Pid;
430 __u16 Uid; 430 __u16 Uid;
431 __u16 Mid; 431 __le16 Mid;
432 __u8 WordCount; 432 __u8 WordCount;
433} __attribute__((packed)); 433} __attribute__((packed));
434 434
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 298e31e3bdc6..2f9f3790679d 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -295,7 +295,8 @@ check_smb_hdr(struct smb_hdr *smb)
295 if (smb->Command == SMB_COM_LOCKING_ANDX) 295 if (smb->Command == SMB_COM_LOCKING_ANDX)
296 return 0; 296 return 0;
297 297
298 cifs_dbg(VFS, "Server sent request, not response. mid=%u\n", smb->Mid); 298 cifs_dbg(VFS, "Server sent request, not response. mid=%u\n",
299 get_mid(smb));
299 return 1; 300 return 1;
300} 301}
301 302
@@ -351,6 +352,7 @@ checkSMB(char *buf, unsigned int total_read)
351 } 352 }
352 353
353 if (4 + rfclen != clc_len) { 354 if (4 + rfclen != clc_len) {
355 __u16 mid = get_mid(smb);
354 /* check if bcc wrapped around for large read responses */ 356 /* check if bcc wrapped around for large read responses */
355 if ((rfclen > 64 * 1024) && (rfclen > clc_len)) { 357 if ((rfclen > 64 * 1024) && (rfclen > clc_len)) {
356 /* check if lengths match mod 64K */ 358 /* check if lengths match mod 64K */
@@ -358,11 +360,11 @@ checkSMB(char *buf, unsigned int total_read)
358 return 0; /* bcc wrapped */ 360 return 0; /* bcc wrapped */
359 } 361 }
360 cifs_dbg(FYI, "Calculated size %u vs length %u mismatch for mid=%u\n", 362 cifs_dbg(FYI, "Calculated size %u vs length %u mismatch for mid=%u\n",
361 clc_len, 4 + rfclen, smb->Mid); 363 clc_len, 4 + rfclen, mid);
362 364
363 if (4 + rfclen < clc_len) { 365 if (4 + rfclen < clc_len) {
364 cifs_dbg(VFS, "RFC1001 size %u smaller than SMB for mid=%u\n", 366 cifs_dbg(VFS, "RFC1001 size %u smaller than SMB for mid=%u\n",
365 rfclen, smb->Mid); 367 rfclen, mid);
366 return -EIO; 368 return -EIO;
367 } else if (rfclen > clc_len + 512) { 369 } else if (rfclen > clc_len + 512) {
368 /* 370 /*
@@ -375,7 +377,7 @@ checkSMB(char *buf, unsigned int total_read)
375 * data to 512 bytes. 377 * data to 512 bytes.
376 */ 378 */
377 cifs_dbg(VFS, "RFC1001 size %u more than 512 bytes larger than SMB for mid=%u\n", 379 cifs_dbg(VFS, "RFC1001 size %u more than 512 bytes larger than SMB for mid=%u\n",
378 rfclen, smb->Mid); 380 rfclen, mid);
379 return -EIO; 381 return -EIO;
380 } 382 }
381 } 383 }
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
index 8233b174de3d..09ef8f322c2a 100644
--- a/fs/cifs/smb1ops.c
+++ b/fs/cifs/smb1ops.c
@@ -67,7 +67,7 @@ send_nt_cancel(struct TCP_Server_Info *server, void *buf,
67 mutex_unlock(&server->srv_mutex); 67 mutex_unlock(&server->srv_mutex);
68 68
69 cifs_dbg(FYI, "issued NT_CANCEL for mid %u, rc = %d\n", 69 cifs_dbg(FYI, "issued NT_CANCEL for mid %u, rc = %d\n",
70 in_buf->Mid, rc); 70 get_mid(in_buf), rc);
71 71
72 return rc; 72 return rc;
73} 73}
@@ -101,7 +101,7 @@ cifs_find_mid(struct TCP_Server_Info *server, char *buffer)
101 101
102 spin_lock(&GlobalMid_Lock); 102 spin_lock(&GlobalMid_Lock);
103 list_for_each_entry(mid, &server->pending_mid_q, qhead) { 103 list_for_each_entry(mid, &server->pending_mid_q, qhead) {
104 if (mid->mid == buf->Mid && 104 if (compare_mid(mid->mid, buf) &&
105 mid->mid_state == MID_REQUEST_SUBMITTED && 105 mid->mid_state == MID_REQUEST_SUBMITTED &&
106 le16_to_cpu(mid->command) == buf->Command) { 106 le16_to_cpu(mid->command) == buf->Command) {
107 spin_unlock(&GlobalMid_Lock); 107 spin_unlock(&GlobalMid_Lock);
diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c
index 340abca3aa52..c523617eade2 100644
--- a/fs/cifs/smb2transport.c
+++ b/fs/cifs/smb2transport.c
@@ -466,7 +466,7 @@ smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
466static inline void 466static inline void
467smb2_seq_num_into_buf(struct TCP_Server_Info *server, struct smb2_hdr *hdr) 467smb2_seq_num_into_buf(struct TCP_Server_Info *server, struct smb2_hdr *hdr)
468{ 468{
469 hdr->MessageId = get_next_mid(server); 469 hdr->MessageId = get_next_mid64(server);
470} 470}
471 471
472static struct mid_q_entry * 472static struct mid_q_entry *
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 800b938e4061..0ee6d249ef6f 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -58,7 +58,7 @@ AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
58 return temp; 58 return temp;
59 else { 59 else {
60 memset(temp, 0, sizeof(struct mid_q_entry)); 60 memset(temp, 0, sizeof(struct mid_q_entry));
61 temp->mid = smb_buffer->Mid; /* always LE */ 61 temp->mid = get_mid(smb_buffer);
62 temp->pid = current->pid; 62 temp->pid = current->pid;
63 temp->command = cpu_to_le16(smb_buffer->Command); 63 temp->command = cpu_to_le16(smb_buffer->Command);
64 cifs_dbg(FYI, "For smb_command %d\n", smb_buffer->Command); 64 cifs_dbg(FYI, "For smb_command %d\n", smb_buffer->Command);