aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/cifspdu.h4
-rw-r--r--fs/cifs/cifssmb.c35
2 files changed, 25 insertions, 14 deletions
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index 50505422dbb4..6df9dadba647 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -409,6 +409,8 @@ typedef struct negotiate_req {
409 409
410/* Dialect index is 13 for LANMAN */ 410/* Dialect index is 13 for LANMAN */
411 411
412#define MIN_TZ_ADJ (15 * 60) /* minimum grid for timezones in seconds */
413
412typedef struct lanman_neg_rsp { 414typedef struct lanman_neg_rsp {
413 struct smb_hdr hdr; /* wct = 13 */ 415 struct smb_hdr hdr; /* wct = 13 */
414 __le16 DialectIndex; 416 __le16 DialectIndex;
@@ -678,7 +680,7 @@ typedef union smb_com_tree_disconnect { /* as an altetnative can use flag on
678typedef struct smb_com_close_req { 680typedef struct smb_com_close_req {
679 struct smb_hdr hdr; /* wct = 3 */ 681 struct smb_hdr hdr; /* wct = 3 */
680 __u16 FileID; 682 __u16 FileID;
681 __u32 LastWriteTime; /* should be zero */ 683 __u32 LastWriteTime; /* should be zero or -1 */
682 __u16 ByteCount; /* 0 */ 684 __u16 ByteCount; /* 0 */
683} __attribute__((packed)) CLOSE_REQ; 685} __attribute__((packed)) CLOSE_REQ;
684 686
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 75f060328e29..8d30a5c4f244 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -450,7 +450,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
450 } else if((pSMBr->hdr.WordCount == 13) 450 } else if((pSMBr->hdr.WordCount == 13)
451 && ((pSMBr->DialectIndex == LANMAN_PROT) 451 && ((pSMBr->DialectIndex == LANMAN_PROT)
452 || (pSMBr->DialectIndex == LANMAN2_PROT))) { 452 || (pSMBr->DialectIndex == LANMAN2_PROT))) {
453 int tmp, adjust; 453 __s16 tmp;
454 struct lanman_neg_rsp * rsp = (struct lanman_neg_rsp *)pSMBr; 454 struct lanman_neg_rsp * rsp = (struct lanman_neg_rsp *)pSMBr;
455 455
456 if((secFlags & CIFSSEC_MAY_LANMAN) || 456 if((secFlags & CIFSSEC_MAY_LANMAN) ||
@@ -476,14 +476,16 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
476 server->maxRw = 0;/* we do not need to use raw anyway */ 476 server->maxRw = 0;/* we do not need to use raw anyway */
477 server->capabilities = CAP_MPX_MODE; 477 server->capabilities = CAP_MPX_MODE;
478 } 478 }
479 tmp = le16_to_cpu(rsp->ServerTimeZone); 479 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
480 if (tmp == (int)0xffff) { 480 if (tmp == 0xffff) {
481 /* OS/2 often does not set timezone therefore 481 /* OS/2 often does not set timezone therefore
482 * we must use server time to calc time zone. 482 * we must use server time to calc time zone.
483 * Could deviate slightly from the right zone. Not easy 483 * Could deviate slightly from the right zone.
484 * to adjust, since timezones are not always a multiple 484 * Smallest defined timezone difference is 15 minutes
485 * of 60 (sometimes 30 minutes - are there smaller?) 485 * (i.e. Nepal). Rounding up/down is done to match
486 * this requirement.
486 */ 487 */
488 int val, seconds, remain, result;
487 struct timespec ts, utc; 489 struct timespec ts, utc;
488 utc = CURRENT_TIME; 490 utc = CURRENT_TIME;
489 ts = cnvrtDosUnixTm(le16_to_cpu(rsp->SrvTime.Date), 491 ts = cnvrtDosUnixTm(le16_to_cpu(rsp->SrvTime.Date),
@@ -491,12 +493,18 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
491 cFYI(1,("SrvTime: %d sec since 1970 (utc: %d) diff: %d", 493 cFYI(1,("SrvTime: %d sec since 1970 (utc: %d) diff: %d",
492 (int)ts.tv_sec, (int)utc.tv_sec, 494 (int)ts.tv_sec, (int)utc.tv_sec,
493 (int)(utc.tv_sec - ts.tv_sec))); 495 (int)(utc.tv_sec - ts.tv_sec)));
494 tmp = (int)(utc.tv_sec - ts.tv_sec); 496 val = (int)(utc.tv_sec - ts.tv_sec);
495 adjust = tmp < 0 ? -29 : 29; 497 seconds = val < 0 ? -val : val;
496 tmp = ((tmp + adjust) / 60) * 60; 498 result = (seconds / IN_TZ_ADJ) * MIN_TZ_ADJ;
497 server->timeAdj = tmp; 499 remain = seconds % MIN_TZ_ADJ;
500 if(remain >= (MIN_TZ_ADJ / 2))
501 result += MIN_TZ_ADJ;
502 if(val < 0)
503 result = - result;
504 server->timeAdj = result;
498 } else { 505 } else {
499 server->timeAdj = tmp * 60; /* also in seconds */ 506 server->timeAdj = (int)tmp;
507 server->timeAdj *= 60; /* also in seconds */
500 } 508 }
501 cFYI(1,("server->timeAdj: %d seconds", server->timeAdj)); 509 cFYI(1,("server->timeAdj: %d seconds", server->timeAdj));
502 510
@@ -559,7 +567,8 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
559 cFYI(0, ("Max buf = %d", ses->server->maxBuf)); 567 cFYI(0, ("Max buf = %d", ses->server->maxBuf));
560 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey); 568 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
561 server->capabilities = le32_to_cpu(pSMBr->Capabilities); 569 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
562 server->timeAdj = le16_to_cpu(pSMBr->ServerTimeZone) * 60; 570 server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
571 server->timeAdj *= 60;
563 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) { 572 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
564 memcpy(server->cryptKey, pSMBr->u.EncryptionKey, 573 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
565 CIFS_CRYPTO_KEY_SIZE); 574 CIFS_CRYPTO_KEY_SIZE);
@@ -1645,7 +1654,7 @@ CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1645 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */ 1654 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
1646 1655
1647 pSMB->FileID = (__u16) smb_file_id; 1656 pSMB->FileID = (__u16) smb_file_id;
1648 pSMB->LastWriteTime = 0; 1657 pSMB->LastWriteTime = 0xFFFFFFFF;
1649 pSMB->ByteCount = 0; 1658 pSMB->ByteCount = 0;
1650 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1659 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1651 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 1660 (struct smb_hdr *) pSMBr, &bytes_returned, 0);