From 0889a9441d98af7951c5377647413d79c84c9efa Mon Sep 17 00:00:00 2001 From: Steve French Date: Sat, 23 Sep 2006 22:11:07 +0000 Subject: CIFS: Use SEEK_END instead of hardcoded value Signed-off-by: Josef 'Jeff' Sipek Signed-off-by: Steve French --- fs/cifs/cifsfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index c3ef1c0d0e6..f5ba4113248 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -508,7 +508,7 @@ static ssize_t cifs_file_aio_write(struct kiocb *iocb, const char __user *buf, static loff_t cifs_llseek(struct file *file, loff_t offset, int origin) { /* origin == SEEK_END => we must revalidate the cached file length */ - if (origin == 2) { + if (origin == SEEK_END) { int retval = cifs_revalidate(file->f_dentry); if (retval < 0) return (loff_t)retval; -- cgit v1.2.3 From 1bd5bbcb6531776a8f73e2cc6287fc4dd542e1c7 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 28 Sep 2006 03:35:57 +0000 Subject: [CIFS] Legacy time handling for Win9x and OS/2 part 1 Signed-off-by: Steve French --- fs/cifs/cifsproto.h | 3 +++ fs/cifs/cifssmb.c | 10 +++++++++- fs/cifs/inode.c | 7 +++++-- fs/cifs/link.c | 6 +++++- fs/cifs/netmisc.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ fs/cifs/readdir.c | 7 +++++++ 6 files changed, 80 insertions(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index b35c55c3c8b..2fbc982aa13 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -80,6 +80,9 @@ extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16, extern void DeleteOplockQEntry(struct oplock_q_entry *); extern struct timespec cifs_NTtimeToUnix(u64 /* utc nanoseconds since 1601 */ ); extern u64 cifs_UnixTimeToNT(struct timespec); +extern __le64 cnvrtDosCifsTm(__u16 date, __u16 time); +extern struct timespec cnvrtDosUnixTm(__u16 date, __u16 time); + extern int cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path, FILE_ALL_INFO * pfile_info, diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 075d8fb3d37..2851d6e0d82 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -2856,7 +2856,6 @@ qsec_out: return rc; } - /* Legacy Query Path Information call for lookup to old servers such as Win9x/WinME */ int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon, @@ -2898,7 +2897,16 @@ QInfRetry: if (rc) { cFYI(1, ("Send error in QueryInfo = %d", rc)); } else if (pFinfo) { /* decode response */ + struct timespec ts; + __u32 time = le32_to_cpu(pSMBr->last_write_time); + /* BB FIXME - add time zone adjustment BB */ memset(pFinfo, 0, sizeof(FILE_ALL_INFO)); + ts.tv_nsec = 0; + ts.tv_sec = time; + /* decode time fields */ + pFinfo->ChangeTime = cifs_UnixTimeToNT(ts); + pFinfo->LastWriteTime = pFinfo->ChangeTime; + pFinfo->LastAccessTime = 0; pFinfo->AllocationSize = cpu_to_le64(le32_to_cpu(pSMBr->size)); pFinfo->EndOfFile = pFinfo->AllocationSize; diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index b88147c1dc2..06dbce3a181 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -432,8 +432,11 @@ int cifs_get_inode_info(struct inode **pinode, (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/ /* Linux can not store file creation time so ignore it */ - inode->i_atime = - cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime)); + if(pfindData->LastAccessTime) + inode->i_atime = cifs_NTtimeToUnix + (le64_to_cpu(pfindData->LastAccessTime)); + else /* do not need to use current_fs_time - time not stored */ + inode->i_atime = CURRENT_TIME; inode->i_mtime = cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime)); inode->i_ctime = diff --git a/fs/cifs/link.c b/fs/cifs/link.c index a57f5d6e621..0bee8b7e521 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c @@ -254,7 +254,11 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen) tmpbuffer, len - 1, cifs_sb->local_nls); - else { + else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { + cERROR(1,("SFU style symlinks not implemented yet")); + /* add open and read as in fs/cifs/inode.c */ + + } else { rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ, OPEN_REPARSE_POINT,&fid, &oplock, NULL, cifs_sb->local_nls, diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index ce87550e918..fa5124d9af1 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c @@ -909,3 +909,54 @@ cifs_UnixTimeToNT(struct timespec t) /* Convert to 100ns intervals and then add the NTFS time offset. */ return (u64) t.tv_sec * 10000000 + t.tv_nsec/100 + NTFS_TIME_OFFSET; } + +static int total_days_of_prev_months[] = +{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; + + +__le64 cnvrtDosCifsTm(__u16 date, __u16 time) +{ + return cpu_to_le64(cifs_UnixTimeToNT(cnvrtDosUnixTm(date, time))); +} +struct timespec cnvrtDosUnixTm(__u16 date, __u16 time) +{ + __u8 dt[2]; + __u8 tm[2]; + struct timespec ts; + int sec,min, days, month, year; + struct timespec removeme; /* BB removeme BB */ +/* SMB_TIME * st = (SMB_TIME *)&time;*/ + + cFYI(1,("date %d time %d",date, time)); + + dt[0] = date & 0xFF; + dt[1] = (date & 0xFF00) >> 8; + tm[0] = time & 0xFF; + tm[1] = (time & 0xFF00) >> 8; + + sec = tm[0] & 0x1F; + sec = 2 * sec; + min = ((tm[0] >>5)&0xFF) + ((tm[1] & 0x7)<<3); + + sec += (min * 60); + sec += 60 * 60 * ((tm[1] >> 3) &0xFF) /* hours */; + days = (dt[0] & 0x1F) - 1; + month = ((dt[0] >> 5) & 0xFF) + ((dt[1] & 0x1) <<3); + if(month > 12) + cERROR(1,("illegal month %d in date", month)); + month -= 1; + days += total_days_of_prev_months[month]; + days += 3653; /* account for difference in days between 1980 and 1970 */ + year = (dt[1]>>1) & 0xFF; + days += year * 365; + days += (year/4); /* leap year */ + /* adjust for leap year where we are still before leap day */ + days -= ((year & 0x03) == 0) && (month < 2 ? 1 : 0); + sec += 24 * 60 * 60 * days; + + removeme = CURRENT_TIME; /* BB removeme BB */ + ts.tv_sec = sec; + + ts.tv_nsec = 0; + return ts; +} diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 9aeb58a7d36..71e86c38e63 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -135,12 +135,19 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, tmp_inode->i_ctime = cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime)); } else { /* legacy, OS2 and DOS style */ +/* struct timespec ts;*/ FIND_FILE_STANDARD_INFO * pfindData = (FIND_FILE_STANDARD_INFO *)buf; +/* ts = cnvrtDosUnixTm( + le16_to_cpu(pfindData->LastWriteDate), + le16_to_cpu(pfindData->LastWriteTime));*/ attr = le16_to_cpu(pfindData->Attributes); allocation_size = le32_to_cpu(pfindData->AllocationSize); end_of_file = le32_to_cpu(pfindData->DataSize); + /* do not need to use current_fs_time helper function since + time not stored for this case so atime can not "go backwards" + by pulling newer older from disk when inode refrenshed */ tmp_inode->i_atime = CURRENT_TIME; /* tmp_inode->i_mtime = BB FIXME - add dos time handling tmp_inode->i_ctime = 0; BB FIXME */ -- cgit v1.2.3 From 2cd646a2d1d5e0e46aa4bb55b1847b0cb35bd855 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 28 Sep 2006 19:43:08 +0000 Subject: [CIFS] Remove static and unused symbols Most cases of the ones found by Shaggy by "make namespacecheck" could be removed or made static Ack: Dave Kleikamp Signed-off-by: Steve French --- fs/cifs/cifsacl.h | 4 ++-- fs/cifs/cifsencrypt.h | 2 -- fs/cifs/cifsfs.c | 5 +++-- fs/cifs/cifsfs.h | 2 +- fs/cifs/cifsglob.h | 4 ++-- fs/cifs/cifsproto.h | 6 ++---- fs/cifs/cifssmb.c | 6 ++++-- fs/cifs/connect.c | 20 ++++++++++++-------- fs/cifs/md5.c | 4 ++-- fs/cifs/md5.h | 8 ++++---- fs/cifs/misc.c | 2 +- fs/cifs/smbdes.c | 4 ++-- fs/cifs/smbencrypt.c | 4 ++-- 13 files changed, 37 insertions(+), 34 deletions(-) (limited to 'fs') diff --git a/fs/cifs/cifsacl.h b/fs/cifs/cifsacl.h index d0776ac2b80..5eff35d6e56 100644 --- a/fs/cifs/cifsacl.h +++ b/fs/cifs/cifsacl.h @@ -31,8 +31,8 @@ struct cifs_sid { } __attribute__((packed)); /* everyone */ -extern const struct cifs_sid sid_everyone; +/* extern const struct cifs_sid sid_everyone;*/ /* group users */ -extern const struct cifs_sid sid_user; +/* extern const struct cifs_sid sid_user;*/ #endif /* _CIFSACL_H */ diff --git a/fs/cifs/cifsencrypt.h b/fs/cifs/cifsencrypt.h index 03e359b3286..152fa2dcfc6 100644 --- a/fs/cifs/cifsencrypt.h +++ b/fs/cifs/cifsencrypt.h @@ -27,8 +27,6 @@ extern void mdfour(unsigned char *out, unsigned char *in, int n); /* smbdes.c */ extern void E_P16(unsigned char *p14, unsigned char *p16); extern void E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24); -extern void D_P16(unsigned char *p14, unsigned char *in, unsigned char *out); -extern void E_old_pw_hash(unsigned char *, unsigned char *, unsigned char *); diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index f5ba4113248..cd17d4b7817 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -442,7 +442,7 @@ static int cifs_remount(struct super_block *sb, int *flags, char *data) return 0; } -struct super_operations cifs_super_ops = { +static struct super_operations cifs_super_ops = { .read_inode = cifs_read_inode, .put_super = cifs_put_super, .statfs = cifs_statfs, @@ -930,7 +930,7 @@ init_cifs(void) #ifdef CONFIG_PROC_FS cifs_proc_init(); #endif - INIT_LIST_HEAD(&GlobalServerList); /* BB not implemented yet */ +/* INIT_LIST_HEAD(&GlobalServerList);*/ /* BB not implemented yet */ INIT_LIST_HEAD(&GlobalSMBSessionList); INIT_LIST_HEAD(&GlobalTreeConnectionList); INIT_LIST_HEAD(&GlobalOplock_Q); @@ -958,6 +958,7 @@ init_cifs(void) GlobalCurrentXid = 0; GlobalTotalActiveXid = 0; GlobalMaxActiveXid = 0; + memset(Local_System_Name, 0, 15); rwlock_init(&GlobalSMBSeslock); spin_lock_init(&GlobalMid_Lock); diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index bea875d9a46..a243f779b36 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -36,7 +36,7 @@ extern const struct address_space_operations cifs_addr_ops; extern const struct address_space_operations cifs_addr_ops_smallbuf; /* Functions related to super block operations */ -extern struct super_operations cifs_super_ops; +/* extern struct super_operations cifs_super_ops;*/ extern void cifs_read_inode(struct inode *); extern void cifs_delete_inode(struct inode *); /* extern void cifs_write_inode(struct inode *); *//* BB not needed yet */ diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index b24006c47df..441f8d2514f 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -512,7 +512,8 @@ require use of the stronger protocol */ * This list helps improve performance and eliminate the messages indicating * that we had a communications error talking to the server in this list. */ -GLOBAL_EXTERN struct servers_not_supported *NotSuppList; /*@z4a */ +/* Feature not supported */ +/* GLOBAL_EXTERN struct servers_not_supported *NotSuppList; */ /* * The following is a hash table of all the users we know about. @@ -568,7 +569,6 @@ GLOBAL_EXTERN unsigned int lookupCacheEnabled; GLOBAL_EXTERN unsigned int extended_security; /* if on, session setup sent with more secure ntlmssp2 challenge/resp */ GLOBAL_EXTERN unsigned int sign_CIFS_PDUs; /* enable smb packet signing */ -GLOBAL_EXTERN unsigned int secFlags; GLOBAL_EXTERN unsigned int linuxExtEnabled;/*enable Linux/Unix CIFS extensions*/ GLOBAL_EXTERN unsigned int CIFSMaxBufSize; /* max size not including hdr */ GLOBAL_EXTERN unsigned int cifs_min_rcv; /* min size of big ntwrk buf pool */ diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 2fbc982aa13..7dd2f48a407 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -50,11 +50,11 @@ extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *, extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *, struct kvec *, int /* nvec to send */, int * /* type of buf returned */ , const int long_op); -extern int SendReceiveBlockingLock(const unsigned int /* xid */ , struct cifsTconInfo *, +extern int SendReceiveBlockingLock(const unsigned int /* xid */ , + struct cifsTconInfo *, struct smb_hdr * /* input */ , struct smb_hdr * /* out */ , int * /* bytes returned */); -extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid); extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length); extern int is_valid_oplock_break(struct smb_hdr *smb, struct TCP_Server_Info *); extern int is_size_safe_to_change(struct cifsInodeInfo *); @@ -282,8 +282,6 @@ extern void sesInfoFree(struct cifsSesInfo *); extern struct cifsTconInfo *tconInfoAlloc(void); extern void tconInfoFree(struct cifsTconInfo *); -extern int cifs_reconnect(struct TCP_Server_Info *server); - extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *,__u32 *); extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *, __u32 *); diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 2851d6e0d82..dcd7087a1ae 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -2773,9 +2773,11 @@ GetExtAttrOut: /* security id for everyone */ -const struct cifs_sid sid_everyone = {1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}}; +const static struct cifs_sid sid_everyone = + {1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}}; /* group users */ -const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}}; +const static struct cifs_sid sid_user = + {1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}}; /* Convert CIFS ACL to POSIX form */ static int parse_sec_desc(struct cifs_sid * psec_desc, int acl_len) diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 0e9ba0b9d71..b3268e53ab9 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -109,7 +109,7 @@ static int ipv6_connect(struct sockaddr_in6 *psin_server, * wake up waiters on reconnection? - (not needed currently) */ -int +static int cifs_reconnect(struct TCP_Server_Info *server) { int rc = 0; @@ -771,13 +771,17 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) separator[0] = ','; separator[1] = 0; - memset(vol->source_rfc1001_name,0x20,15); - for(i=0;i < strnlen(system_utsname.nodename,15);i++) { - /* does not have to be a perfect mapping since the field is - informational, only used for servers that do not support - port 445 and it can be overridden at mount time */ - vol->source_rfc1001_name[i] = - toupper(system_utsname.nodename[i]); + if(Local_System_Name[0] != 0) + memcpy(vol->source_rfc1001_name, Local_System_Name,15); + else { + memset(vol->source_rfc1001_name,0x20,15); + for(i=0;i < strnlen(system_utsname.nodename,15);i++) { + /* does not have to be perfect mapping since field is + informational, only used for servers that do not support + port 445 and it can be overridden at mount time */ + vol->source_rfc1001_name[i] = + toupper(system_utsname.nodename[i]); + } } vol->source_rfc1001_name[15] = 0; /* null target name indicates to use *SMBSERVR default called name diff --git a/fs/cifs/md5.c b/fs/cifs/md5.c index 7aa23490541..273aa0383f2 100644 --- a/fs/cifs/md5.c +++ b/fs/cifs/md5.c @@ -255,7 +255,7 @@ MD5Transform(__u32 buf[4], __u32 const in[16]) /*********************************************************************** the rfc 2104 version of hmac_md5 initialisation. ***********************************************************************/ -void +static void hmac_md5_init_rfc2104(unsigned char *key, int key_len, struct HMACMD5Context *ctx) { @@ -350,7 +350,7 @@ hmac_md5_final(unsigned char *digest, struct HMACMD5Context *ctx) single function to calculate an HMAC MD5 digest from data. use the microsoft hmacmd5 init method because the key is 16 bytes. ************************************************************/ -void +static void hmac_md5(unsigned char key[16], unsigned char *data, int data_len, unsigned char *digest) { diff --git a/fs/cifs/md5.h b/fs/cifs/md5.h index 00e1c5394fe..f7d4f4197ba 100644 --- a/fs/cifs/md5.h +++ b/fs/cifs/md5.h @@ -27,12 +27,12 @@ void MD5Final(unsigned char digest[16], struct MD5Context *context); /* The following definitions come from lib/hmacmd5.c */ -void hmac_md5_init_rfc2104(unsigned char *key, int key_len, - struct HMACMD5Context *ctx); +/* void hmac_md5_init_rfc2104(unsigned char *key, int key_len, + struct HMACMD5Context *ctx);*/ void hmac_md5_init_limK_to_64(const unsigned char *key, int key_len, struct HMACMD5Context *ctx); void hmac_md5_update(const unsigned char *text, int text_len, struct HMACMD5Context *ctx); void hmac_md5_final(unsigned char *digest, struct HMACMD5Context *ctx); -void hmac_md5(unsigned char key[16], unsigned char *data, int data_len, - unsigned char *digest); +/* void hmac_md5(unsigned char key[16], unsigned char *data, int data_len, + unsigned char *digest);*/ diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 22c937e5884..ca6e9b1413f 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -389,7 +389,7 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ , return; } -int +static int checkSMBhdr(struct smb_hdr *smb, __u16 mid) { /* Make sure that this really is an SMB, that it is a response, diff --git a/fs/cifs/smbdes.c b/fs/cifs/smbdes.c index efaa044523a..2b193e422f8 100644 --- a/fs/cifs/smbdes.c +++ b/fs/cifs/smbdes.c @@ -364,14 +364,14 @@ E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24) smbhash(p24 + 16, c8, p21 + 14, 1); } -void +static void D_P16(unsigned char *p14, unsigned char *in, unsigned char *out) { smbhash(out, in, p14, 0); smbhash(out + 8, in + 8, p14 + 7, 0); } -void +static void E_old_pw_hash(unsigned char *p14, unsigned char *in, unsigned char *out) { smbhash(out, in, p14, 1); diff --git a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c index f518c5e4503..c7e55a940e2 100644 --- a/fs/cifs/smbencrypt.c +++ b/fs/cifs/smbencrypt.c @@ -145,7 +145,7 @@ E_md4hash(const unsigned char *passwd, unsigned char *p16) } /* Does both the NT and LM owfs of a user's password */ -void +static void nt_lm_owf_gen(char *pwd, unsigned char nt_p16[16], unsigned char p16[16]) { char passwd[514]; @@ -223,7 +223,7 @@ SMBOWFencrypt(unsigned char passwd[16], unsigned char *c8, } /* Does the des encryption from the FIRST 8 BYTES of the NT or LM MD4 hash. */ -void +static void NTLMSSPOWFencrypt(unsigned char passwd[8], unsigned char *ntlmchalresp, unsigned char p24[24]) { -- cgit v1.2.3 From e33c74d06e2b46a5f187ec7f60248da774c84e72 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 28 Sep 2006 20:35:48 +0000 Subject: [CIFS] Fix build break Signed-off-by: Steve French --- fs/cifs/cifsfs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'fs') diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index cd17d4b7817..51e888fcef2 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -63,6 +63,7 @@ extern struct task_struct * oplockThread; /* remove sparse warning */ struct task_struct * oplockThread = NULL; extern struct task_struct * dnotifyThread; /* remove sparse warning */ struct task_struct * dnotifyThread = NULL; +static struct super_operations cifs_super_ops; unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE; module_param(CIFSMaxBufSize, int, 0); MODULE_PARM_DESC(CIFSMaxBufSize,"Network buffer size (not including header). Default: 16384 Range: 8192 to 130048"); -- cgit v1.2.3 From 2eaf55862e8eb03999169d84f21eadffc88a36ce Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 28 Sep 2006 20:41:48 +0000 Subject: [CIFS] Remove unused prototypes Signed-off-by: Steve French --- fs/cifs/smbencrypt.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'fs') diff --git a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c index c7e55a940e2..48314e5e785 100644 --- a/fs/cifs/smbencrypt.c +++ b/fs/cifs/smbencrypt.c @@ -51,11 +51,8 @@ void SMBencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24); void E_md4hash(const unsigned char *passwd, unsigned char *p16); -void nt_lm_owf_gen(char *pwd, unsigned char nt_p16[16], unsigned char p16[16]); static void SMBOWFencrypt(unsigned char passwd[16], unsigned char *c8, unsigned char p24[24]); -void NTLMSSPOWFencrypt(unsigned char passwd[8], - unsigned char *ntlmchalresp, unsigned char p24[24]); void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24); /* -- cgit v1.2.3 From e10847ed499cb86bf8ce12f3a686be8a98f8e140 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 28 Sep 2006 20:49:01 +0000 Subject: [CIFS] More removing of unused functions Signed-off-by: Steve French --- fs/cifs/md5.c | 4 ++++ fs/cifs/smbdes.c | 2 +- fs/cifs/smbencrypt.c | 4 ++++ 3 files changed, 9 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/cifs/md5.c b/fs/cifs/md5.c index 273aa0383f2..e6a2097d836 100644 --- a/fs/cifs/md5.c +++ b/fs/cifs/md5.c @@ -252,6 +252,7 @@ MD5Transform(__u32 buf[4], __u32 const in[16]) buf[3] += d; } +#if 0 /* currently unused */ /*********************************************************************** the rfc 2104 version of hmac_md5 initialisation. ***********************************************************************/ @@ -289,6 +290,7 @@ hmac_md5_init_rfc2104(unsigned char *key, int key_len, MD5Init(&ctx->ctx); MD5Update(&ctx->ctx, ctx->k_ipad, 64); } +#endif /*********************************************************************** the microsoft version of hmac_md5 initialisation. @@ -333,6 +335,7 @@ hmac_md5_update(const unsigned char *text, int text_len, /*********************************************************************** finish off hmac_md5 "inner" buffer and generate outer one. ***********************************************************************/ +#if 0 /* currently unused */ void hmac_md5_final(unsigned char *digest, struct HMACMD5Context *ctx) { @@ -361,3 +364,4 @@ hmac_md5(unsigned char key[16], unsigned char *data, int data_len, } hmac_md5_final(digest, &ctx); } +#endif diff --git a/fs/cifs/smbdes.c b/fs/cifs/smbdes.c index 2b193e422f8..7a1b2b961ec 100644 --- a/fs/cifs/smbdes.c +++ b/fs/cifs/smbdes.c @@ -364,6 +364,7 @@ E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24) smbhash(p24 + 16, c8, p21 + 14, 1); } +#if 0 /* currently unsued */ static void D_P16(unsigned char *p14, unsigned char *in, unsigned char *out) { @@ -377,7 +378,6 @@ E_old_pw_hash(unsigned char *p14, unsigned char *in, unsigned char *out) smbhash(out, in, p14, 1); smbhash(out + 8, in + 8, p14 + 7, 1); } -#if 0 /* these routines are currently unneeded, but may be needed later */ void diff --git a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c index 48314e5e785..4b25ba92180 100644 --- a/fs/cifs/smbencrypt.c +++ b/fs/cifs/smbencrypt.c @@ -141,6 +141,7 @@ E_md4hash(const unsigned char *passwd, unsigned char *p16) memset(wpwd,0,129 * 2); } +#if 0 /* currently unused */ /* Does both the NT and LM owfs of a user's password */ static void nt_lm_owf_gen(char *pwd, unsigned char nt_p16[16], unsigned char p16[16]) @@ -168,6 +169,7 @@ nt_lm_owf_gen(char *pwd, unsigned char nt_p16[16], unsigned char p16[16]) /* clear out local copy of user's password (just being paranoid). */ memset(passwd, '\0', sizeof (passwd)); } +#endif /* Does the NTLMv2 owfs of a user's password */ #if 0 /* function not needed yet - but will be soon */ @@ -220,6 +222,7 @@ SMBOWFencrypt(unsigned char passwd[16], unsigned char *c8, } /* Does the des encryption from the FIRST 8 BYTES of the NT or LM MD4 hash. */ +#if 0 /* currently unused */ static void NTLMSSPOWFencrypt(unsigned char passwd[8], unsigned char *ntlmchalresp, unsigned char p24[24]) @@ -232,6 +235,7 @@ NTLMSSPOWFencrypt(unsigned char passwd[8], E_P24(p21, ntlmchalresp, p24); } +#endif /* Does the NT MD4 hash then des encryption. */ -- cgit v1.2.3 From a3ab41f10e2f5087e515da358680c88dd61d4832 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 28 Sep 2006 20:52:08 +0000 Subject: [CIFS] Fix build break ifdef in wrong place Signed-off-by: Steve French --- fs/cifs/md5.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/cifs/md5.c b/fs/cifs/md5.c index e6a2097d836..ccebf9b7eb8 100644 --- a/fs/cifs/md5.c +++ b/fs/cifs/md5.c @@ -335,7 +335,6 @@ hmac_md5_update(const unsigned char *text, int text_len, /*********************************************************************** finish off hmac_md5 "inner" buffer and generate outer one. ***********************************************************************/ -#if 0 /* currently unused */ void hmac_md5_final(unsigned char *digest, struct HMACMD5Context *ctx) { @@ -353,6 +352,7 @@ hmac_md5_final(unsigned char *digest, struct HMACMD5Context *ctx) single function to calculate an HMAC MD5 digest from data. use the microsoft hmacmd5 init method because the key is 16 bytes. ************************************************************/ +#if 0 /* currently unused */ static void hmac_md5(unsigned char key[16], unsigned char *data, int data_len, unsigned char *digest) -- cgit v1.2.3 From bf97d28711e2dc4dc947faa6477cd1b36b91a2da Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 28 Sep 2006 21:34:06 +0000 Subject: [CIFS] CIFS support for /proc//mountstats part 1 Signed-off-by: Steve French --- fs/cifs/cifsfs.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'fs') diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 51e888fcef2..7ecfcbf31e5 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -437,6 +437,14 @@ static void cifs_umount_begin(struct vfsmount * vfsmnt, int flags) return; } +#ifdef CONFIG_CIFS_STATS2 +static int cifs_show_stats(struct seq_file *s, struct vfsmount *mnt) +{ + /* BB FIXME */ + return 0; +} +#endif + static int cifs_remount(struct super_block *sb, int *flags, char *data) { *flags |= MS_NODIRATIME; @@ -456,6 +464,9 @@ static struct super_operations cifs_super_ops = { .show_options = cifs_show_options, .umount_begin = cifs_umount_begin, .remount_fs = cifs_remount, +#ifdef CONFIG_CIFS_STATS2 + cifs_show_stats, +#endif }; static int -- cgit v1.2.3 From 25ee4a98c662317a7973f3053567d4ec51857511 Mon Sep 17 00:00:00 2001 From: Steve French Date: Sat, 30 Sep 2006 00:54:23 +0000 Subject: [CIFS] Handle legacy servers which return undefined time zone Signed-off-by: Guenter Kukkukk Signed-off-by: Steve French --- fs/cifs/cifssmb.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index dcd7087a1ae..99718591ea2 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -447,6 +447,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) #ifdef CONFIG_CIFS_WEAK_PW_HASH } else if((pSMBr->hdr.WordCount == 13) && (pSMBr->DialectIndex == LANMAN_PROT)) { + int tmp, adjust; struct lanman_neg_rsp * rsp = (struct lanman_neg_rsp *)pSMBr; if((secFlags & CIFSSEC_MAY_LANMAN) || @@ -473,11 +474,36 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) server->capabilities = CAP_MPX_MODE; } server->timeZone = le16_to_cpu(rsp->ServerTimeZone); + tmp = le16_to_cpu(rsp->ServerTimeZone); + if (tmp == (int)0xffff) { + /* OS/2 often does not set timezone therefore + * we must use server time to calc time zone. + * Could deviate slightly from the right zone. Not easy + * to adjust, since timezones are not always a multiple + * of 60 (sometimes 30 minutes - are there smaller?) + */ + struct timespec ts, utc; + utc = CURRENT_TIME; + ts = cnvrtDosUnixTm(le16_to_cpu(rsp->SrvTime.Date), + le16_to_cpu(rsp->SrvTime.Time)); + cFYI(1,("SrvTime: %d sec since 1970 (utc: %d) diff: %d", + (int)ts.tv_sec, (int)utc.tv_sec, + (int)(utc.tv_sec - ts.tv_sec))); + tmp = (int)(utc.tv_sec - ts.tv_sec); + adjust = tmp < 0 ? -29 : 29; + tmp = ((tmp + adjust) / 60) * 60; + server->timeZone = tmp; + } else { + server->timeZone = tmp * 60; /* also in seconds */ + } + cFYI(1,("server->timeZone: %d seconds", server->timeZone)); + /* BB get server time for time conversions and add code to use it and timezone since this is not UTC */ - if (rsp->EncryptionKeyLength == cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) { + if (rsp->EncryptionKeyLength == + cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) { memcpy(server->cryptKey, rsp->EncryptionKey, CIFS_CRYPTO_KEY_SIZE); } else if (server->secMode & SECMODE_PW_ENCRYPT) { -- cgit v1.2.3 From 175ec9e11cf18f8373b32f7a33e75a4cf7ce25e3 Mon Sep 17 00:00:00 2001 From: Steve French Date: Sat, 30 Sep 2006 01:07:38 +0000 Subject: [CIFS] Rename server time zone field Server time zone is not really a time zone, rather a time adjustement in seconds. CC: Guenter Kukkukk Signed-off-by: Steve French --- fs/cifs/cifsfs.c | 2 +- fs/cifs/cifsglob.h | 2 +- fs/cifs/cifspdu.h | 5 ++++- fs/cifs/cifssmb.c | 9 ++++----- fs/cifs/connect.c | 9 +++++---- 5 files changed, 15 insertions(+), 12 deletions(-) (limited to 'fs') diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 7ecfcbf31e5..e7641f9a13b 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -465,7 +465,7 @@ static struct super_operations cifs_super_ops = { .umount_begin = cifs_umount_begin, .remount_fs = cifs_remount, #ifdef CONFIG_CIFS_STATS2 - cifs_show_stats, + .cifs_show_stats, #endif }; diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 441f8d2514f..98eb5446e8c 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -153,7 +153,7 @@ struct TCP_Server_Info { char sessid[4]; /* unique token id for this session */ /* (returned on Negotiate */ int capabilities; /* allow selective disabling of caps by smb sess */ - __u16 timeZone; + __u16 timeAdj; /* Adjust for difference in server time zone in sec */ __u16 CurrentMid; /* multiplex id - rotating counter */ char cryptKey[CIFS_CRYPTO_KEY_SIZE]; /* 16th byte of RFC1001 workstation name is always null */ diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index 81df2bf8e75..e5dd8708d63 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h @@ -417,7 +417,10 @@ typedef struct lanman_neg_rsp { __le16 MaxNumberVcs; __le16 RawMode; __le32 SessionKey; - __le32 ServerTime; + struct { + __le16 Time; + __le16 Date; + } __attribute__((packed)) SrvTime; __le16 ServerTimeZone; __le16 EncryptionKeyLength; __le16 Reserved; diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 99718591ea2..6e004587fa4 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -473,7 +473,6 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) server->maxRw = 0;/* we do not need to use raw anyway */ server->capabilities = CAP_MPX_MODE; } - server->timeZone = le16_to_cpu(rsp->ServerTimeZone); tmp = le16_to_cpu(rsp->ServerTimeZone); if (tmp == (int)0xffff) { /* OS/2 often does not set timezone therefore @@ -492,11 +491,11 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) tmp = (int)(utc.tv_sec - ts.tv_sec); adjust = tmp < 0 ? -29 : 29; tmp = ((tmp + adjust) / 60) * 60; - server->timeZone = tmp; + server->timeAdj = tmp; } else { - server->timeZone = tmp * 60; /* also in seconds */ + server->timeAdj = tmp * 60; /* also in seconds */ } - cFYI(1,("server->timeZone: %d seconds", server->timeZone)); + cFYI(1,("server->timeAdj: %d seconds", server->timeAdj)); /* BB get server time for time conversions and add @@ -557,7 +556,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) cFYI(0, ("Max buf = %d", ses->server->maxBuf)); GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey); server->capabilities = le32_to_cpu(pSMBr->Capabilities); - server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone); + server->timeAdj = le16_to_cpu(pSMBr->ServerTimeZone) * 60; if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) { memcpy(server->cryptKey, pSMBr->u.EncryptionKey, CIFS_CRYPTO_KEY_SIZE); diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index b3268e53ab9..083b2b2c157 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -3320,15 +3320,16 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, if(linuxExtEnabled == 0) pSesInfo->capabilities &= (~CAP_UNIX); /* pSesInfo->sequence_number = 0;*/ - cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d", + cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d", pSesInfo->server->secMode, pSesInfo->server->capabilities, - pSesInfo->server->timeZone)); + pSesInfo->server->timeAdj)); if(experimEnabled < 2) rc = CIFS_SessSetup(xid, pSesInfo, first_time, nls_info); else if (extended_security - && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) + && (pSesInfo->capabilities + & CAP_EXTENDED_SECURITY) && (pSesInfo->server->secType == NTLMSSP)) { rc = -EOPNOTSUPP; } else if (extended_security @@ -3342,7 +3343,7 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, if (!rc) { if(ntlmv2_flag) { char * v2_response; - cFYI(1,("Can use more secure NTLM version 2 password hash")); + cFYI(1,("more secure NTLM ver2 hash")); if(CalcNTLMv2_partial_mac_key(pSesInfo, nls_info)) { rc = -ENOMEM; -- cgit v1.2.3 From f46d3e11903e452924ef2996aa9aca2aae4427e2 Mon Sep 17 00:00:00 2001 From: Steve French Date: Sat, 30 Sep 2006 01:08:55 +0000 Subject: [CIFS] Fix typo in name of new cifs_show_stats Signed-off-by: Steve French --- fs/cifs/cifsfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index e7641f9a13b..ca53720fa5b 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -465,7 +465,7 @@ static struct super_operations cifs_super_ops = { .umount_begin = cifs_umount_begin, .remount_fs = cifs_remount, #ifdef CONFIG_CIFS_STATS2 - .cifs_show_stats, + .show_stats = cifs_show_stats, #endif }; -- cgit v1.2.3 From 9ac00b7d96045fa3ce573e0ad5cdc0350ad8e1d2 Mon Sep 17 00:00:00 2001 From: Steve French Date: Sat, 30 Sep 2006 04:13:17 +0000 Subject: [CIFS] Do not send newer QFSInfo to legacy servers which can not support it Fix dialect negotiation to save off when we have negotiated lanman. This allows us to avoid sending some somewhat newer requests that the server can not handle and go directly to the older version (infolevel) of the same call. Make sure we try to negotiate a level which allows us to get the server OS (which we check so we can detect Win9x vs. other legacy servers and eventually work around the Win9x DOS time bug (they reverse date/time fields). Signed-off-by: Steve French --- fs/cifs/cifsfs.c | 8 +++++--- fs/cifs/cifsglob.h | 9 +++++++-- fs/cifs/cifspdu.h | 3 ++- fs/cifs/cifssmb.c | 8 +++++--- fs/cifs/connect.c | 1 + fs/cifs/sess.c | 23 ++++++++++++----------- 6 files changed, 32 insertions(+), 20 deletions(-) (limited to 'fs') diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index ca53720fa5b..d6d226addde 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -199,10 +199,12 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf) /* Only need to call the old QFSInfo if failed on newer one */ if(rc) - rc = CIFSSMBQFSInfo(xid, pTcon, buf); + if((pTcon->ses->flags & CIFS_SES_LANMAN) == 0) + rc = CIFSSMBQFSInfo(xid, pTcon, buf); /* not supported by OS2 */ - /* Old Windows servers do not support level 103, retry with level - one if old server failed the previous call */ + /* Some old Windows servers also do not support level 103, retry with + older level one if old server failed the previous call or we + bypassed it because we detected that this was an older LANMAN sess */ if(rc) rc = SMBOldQFSInfo(xid, pTcon, buf); /* diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 98eb5446e8c..597afdf4c69 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -203,9 +203,14 @@ struct cifsSesInfo { char * domainName; char * password; }; -/* session flags */ +/* no more than one of the following three session flags may be set */ #define CIFS_SES_NT4 1 - +#define CIFS_SES_OS2 2 +#define CIFS_SES_W9X 4 +/* following flag is set for old servers such as OS2 (and Win95?) + which do not negotiate NTLM or POSIX dialects, but instead + negotiate one of the older LANMAN dialects */ +#define CIFS_SES_LANMAN 8 /* * there is one of these for each connection to a resource on a particular * session diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index e5dd8708d63..50505422dbb 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h @@ -26,7 +26,8 @@ #ifdef CONFIG_CIFS_WEAK_PW_HASH #define LANMAN_PROT 0 -#define CIFS_PROT 1 +#define LANMAN2_PROT 1 +#define CIFS_PROT 2 #else #define CIFS_PROT 0 #endif diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 6e004587fa4..f2fa05bbcb4 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -46,6 +46,7 @@ static struct { } protocols[] = { #ifdef CONFIG_CIFS_WEAK_PW_HASH {LANMAN_PROT, "\2LM1.2X002"}, + {LANMAN2_PROT, "\2LANMAN2.1"}, #endif /* weak password hashing for legacy clients */ {CIFS_PROT, "\2NT LM 0.12"}, {POSIX_PROT, "\2POSIX 2"}, @@ -67,13 +68,13 @@ static struct { /* define the number of elements in the cifs dialect array */ #ifdef CONFIG_CIFS_POSIX #ifdef CONFIG_CIFS_WEAK_PW_HASH -#define CIFS_NUM_PROT 3 +#define CIFS_NUM_PROT 4 #else #define CIFS_NUM_PROT 2 #endif /* CIFS_WEAK_PW_HASH */ #else /* not posix */ #ifdef CONFIG_CIFS_WEAK_PW_HASH -#define CIFS_NUM_PROT 2 +#define CIFS_NUM_PROT 3 #else #define CIFS_NUM_PROT 1 #endif /* CONFIG_CIFS_WEAK_PW_HASH */ @@ -446,7 +447,8 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) goto neg_err_exit; #ifdef CONFIG_CIFS_WEAK_PW_HASH } else if((pSMBr->hdr.WordCount == 13) - && (pSMBr->DialectIndex == LANMAN_PROT)) { + && ((pSMBr->DialectIndex == LANMAN_PROT) + || (pSMBr->DialectIndex == LANMAN2_PROT))) { int tmp, adjust; struct lanman_neg_rsp * rsp = (struct lanman_neg_rsp *)pSMBr; diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 083b2b2c157..c96f3edf1b9 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -3316,6 +3316,7 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, first_time = 1; } if (!rc) { + pSesInfo->flags = 0; pSesInfo->capabilities = pSesInfo->server->capabilities; if(linuxExtEnabled == 0) pSesInfo->capabilities &= (~CAP_UNIX); diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index d1705ab8136..e4c4e466e32 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c @@ -268,6 +268,10 @@ static int decode_ascii_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo ses->serverOS = kzalloc(len + 1, GFP_KERNEL); if(ses->serverOS) strncpy(ses->serverOS, bcc_ptr, len); + if(strncmp(ses->serverOS, "OS/2",4) == 0) { + cFYI(1,("OS/2 server")); + ses->flags |= CIFS_SES_OS2; + } bcc_ptr += len + 1; bleft -= len + 1; @@ -290,16 +294,11 @@ static int decode_ascii_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo if(len > bleft) return rc; - if(ses->serverDomain) - kfree(ses->serverDomain); - - ses->serverDomain = kzalloc(len + 1, GFP_KERNEL); - if(ses->serverOS) - strncpy(ses->serverOS, bcc_ptr, len); - - bcc_ptr += len + 1; - bleft -= len + 1; - + /* No domain field in LANMAN case. Domain is + returned by old servers in the SMB negprot response */ + /* BB For newer servers which do not support Unicode, + but thus do return domain here we could add parsing + for it later, but it is not very important */ cFYI(1,("ascii: bytes left %d",bleft)); return rc; @@ -366,6 +365,8 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, str_area = kmalloc(2000, GFP_KERNEL); bcc_ptr = str_area; + ses->flags &= ~CIFS_SES_LANMAN; + if(type == LANMAN) { #ifdef CONFIG_CIFS_WEAK_PW_HASH char lnm_session_key[CIFS_SESS_KEY_SIZE]; @@ -377,7 +378,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, /* and copy into bcc */ calc_lanman_hash(ses, lnm_session_key); - + ses->flags |= CIFS_SES_LANMAN; /* #ifdef CONFIG_CIFS_DEBUG2 cifs_dump_mem("cryptkey: ",ses->server->cryptKey, CIFS_SESS_KEY_SIZE); -- cgit v1.2.3 From de7ed55dbb2f2c44be669d56c4adf28cbffb26ce Mon Sep 17 00:00:00 2001 From: Steve French Date: Sat, 30 Sep 2006 13:25:52 +0000 Subject: [CIFS] Make use of newer QFSInfo dependent on capability bit instead of whether we negotiated legacy lanman dialect so we do not keep retrying for mount to WindowsME Signed-off-by: Steve French --- fs/cifs/cifsfs.c | 2 +- fs/cifs/cifsglob.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index d6d226addde..43364361276 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -199,7 +199,7 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf) /* Only need to call the old QFSInfo if failed on newer one */ if(rc) - if((pTcon->ses->flags & CIFS_SES_LANMAN) == 0) + if(pTcon->ses->capabilities & CAP_NT_SMBS) rc = CIFSSMBQFSInfo(xid, pTcon, buf); /* not supported by OS2 */ /* Some old Windows servers also do not support level 103, retry with diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 597afdf4c69..74d3ccbb103 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -153,7 +153,7 @@ struct TCP_Server_Info { char sessid[4]; /* unique token id for this session */ /* (returned on Negotiate */ int capabilities; /* allow selective disabling of caps by smb sess */ - __u16 timeAdj; /* Adjust for difference in server time zone in sec */ + int timeAdj; /* Adjust for difference in server time zone in sec */ __u16 CurrentMid; /* multiplex id - rotating counter */ char cryptKey[CIFS_CRYPTO_KEY_SIZE]; /* 16th byte of RFC1001 workstation name is always null */ -- cgit v1.2.3 From 18f75ca0dc0d5b6a2ec15d89d517b3c67e0f1c87 Mon Sep 17 00:00:00 2001 From: Steve French Date: Sun, 1 Oct 2006 03:13:01 +0000 Subject: [CIFS] Allow LANMAN21 support even in both POSIX non-POSIX path Signed-off-by: Guenter Kukkukk Signed-off-by: Steve French --- fs/cifs/cifssmb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'fs') diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index f2fa05bbcb4..75f060328e2 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -59,6 +59,7 @@ static struct { } protocols[] = { #ifdef CONFIG_CIFS_WEAK_PW_HASH {LANMAN_PROT, "\2LM1.2X002"}, + {LANMAN2_PROT, "\2LANMAN2.1"}, #endif /* weak password hashing for legacy clients */ {CIFS_PROT, "\2NT LM 0.12"}, {BAD_PROT, "\2"} -- cgit v1.2.3 From 203cf2fc13a5db1fb202c294948fa9cb43bf69fa Mon Sep 17 00:00:00 2001 From: Steve French Date: Sun, 1 Oct 2006 19:59:41 +0000 Subject: [CIFS] Fix readdir of large directories for backlevel servers (were not setting all of resume key) Signed-off-by: Steve French --- fs/cifs/readdir.c | 1 + 1 file changed, 1 insertion(+) (limited to 'fs') diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 71e86c38e63..b0e5db10664 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -946,6 +946,7 @@ static int cifs_save_resume_key(const char *current_entry, filename = &pFindData->FileName[0]; /* one byte length, no name conversion */ len = (unsigned int)pFindData->FileNameLength; + cifsFile->srch_inf.resume_key = pFindData->ResumeKey; } else { cFYI(1,("Unknown findfirst level %d",level)); return -EINVAL; -- cgit v1.2.3 From b815f1e559e7cbdf3e561cf0c7cffc4a4a57a013 Mon Sep 17 00:00:00 2001 From: Steve French Date: Mon, 2 Oct 2006 05:53:29 +0000 Subject: [CIFS] Allow for 15 minute TZs (e.g. Nepal) and be more explicit about not setting time on close Signed-off-by: Guenter Kukkukk Signed-off-by: Steve French --- fs/cifs/cifspdu.h | 4 +++- fs/cifs/cifssmb.c | 35 ++++++++++++++++++++++------------- 2 files changed, 25 insertions(+), 14 deletions(-) (limited to 'fs') diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index 50505422dbb..6df9dadba64 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h @@ -409,6 +409,8 @@ typedef struct negotiate_req { /* Dialect index is 13 for LANMAN */ +#define MIN_TZ_ADJ (15 * 60) /* minimum grid for timezones in seconds */ + typedef struct lanman_neg_rsp { struct smb_hdr hdr; /* wct = 13 */ __le16 DialectIndex; @@ -678,7 +680,7 @@ typedef union smb_com_tree_disconnect { /* as an altetnative can use flag on typedef struct smb_com_close_req { struct smb_hdr hdr; /* wct = 3 */ __u16 FileID; - __u32 LastWriteTime; /* should be zero */ + __u32 LastWriteTime; /* should be zero or -1 */ __u16 ByteCount; /* 0 */ } __attribute__((packed)) CLOSE_REQ; diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 75f060328e2..8d30a5c4f24 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -450,7 +450,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) } else if((pSMBr->hdr.WordCount == 13) && ((pSMBr->DialectIndex == LANMAN_PROT) || (pSMBr->DialectIndex == LANMAN2_PROT))) { - int tmp, adjust; + __s16 tmp; struct lanman_neg_rsp * rsp = (struct lanman_neg_rsp *)pSMBr; if((secFlags & CIFSSEC_MAY_LANMAN) || @@ -476,14 +476,16 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) server->maxRw = 0;/* we do not need to use raw anyway */ server->capabilities = CAP_MPX_MODE; } - tmp = le16_to_cpu(rsp->ServerTimeZone); - if (tmp == (int)0xffff) { + tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone); + if (tmp == 0xffff) { /* OS/2 often does not set timezone therefore * we must use server time to calc time zone. - * Could deviate slightly from the right zone. Not easy - * to adjust, since timezones are not always a multiple - * of 60 (sometimes 30 minutes - are there smaller?) + * Could deviate slightly from the right zone. + * Smallest defined timezone difference is 15 minutes + * (i.e. Nepal). Rounding up/down is done to match + * this requirement. */ + int val, seconds, remain, result; struct timespec ts, utc; utc = CURRENT_TIME; ts = cnvrtDosUnixTm(le16_to_cpu(rsp->SrvTime.Date), @@ -491,12 +493,18 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) cFYI(1,("SrvTime: %d sec since 1970 (utc: %d) diff: %d", (int)ts.tv_sec, (int)utc.tv_sec, (int)(utc.tv_sec - ts.tv_sec))); - tmp = (int)(utc.tv_sec - ts.tv_sec); - adjust = tmp < 0 ? -29 : 29; - tmp = ((tmp + adjust) / 60) * 60; - server->timeAdj = tmp; + val = (int)(utc.tv_sec - ts.tv_sec); + seconds = val < 0 ? -val : val; + result = (seconds / IN_TZ_ADJ) * MIN_TZ_ADJ; + remain = seconds % MIN_TZ_ADJ; + if(remain >= (MIN_TZ_ADJ / 2)) + result += MIN_TZ_ADJ; + if(val < 0) + result = - result; + server->timeAdj = result; } else { - server->timeAdj = tmp * 60; /* also in seconds */ + server->timeAdj = (int)tmp; + server->timeAdj *= 60; /* also in seconds */ } cFYI(1,("server->timeAdj: %d seconds", server->timeAdj)); @@ -559,7 +567,8 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) cFYI(0, ("Max buf = %d", ses->server->maxBuf)); GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey); server->capabilities = le32_to_cpu(pSMBr->Capabilities); - server->timeAdj = le16_to_cpu(pSMBr->ServerTimeZone) * 60; + server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone); + server->timeAdj *= 60; if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) { memcpy(server->cryptKey, pSMBr->u.EncryptionKey, CIFS_CRYPTO_KEY_SIZE); @@ -1645,7 +1654,7 @@ CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id) pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */ pSMB->FileID = (__u16) smb_file_id; - pSMB->LastWriteTime = 0; + pSMB->LastWriteTime = 0xFFFFFFFF; pSMB->ByteCount = 0; rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); -- cgit v1.2.3 From 947a50679570ef7a66e3e3107e95943a1cb14d08 Mon Sep 17 00:00:00 2001 From: Steve French Date: Mon, 2 Oct 2006 05:55:25 +0000 Subject: [CIFS] Fix typo Signed-off-by: Steve French --- fs/cifs/cifssmb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 8d30a5c4f24..005fb315477 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -495,7 +495,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) (int)(utc.tv_sec - ts.tv_sec))); val = (int)(utc.tv_sec - ts.tv_sec); seconds = val < 0 ? -val : val; - result = (seconds / IN_TZ_ADJ) * MIN_TZ_ADJ; + result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ; remain = seconds % MIN_TZ_ADJ; if(remain >= (MIN_TZ_ADJ / 2)) result += MIN_TZ_ADJ; -- cgit v1.2.3 From 1a70d6529ad9f5978af846440f8a809784d6e813 Mon Sep 17 00:00:00 2001 From: Steve French Date: Mon, 2 Oct 2006 05:59:18 +0000 Subject: [CIFS] Fix compiler warning with previous patch Signed-off-by: Steve French --- fs/cifs/cifssmb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 005fb315477..79a01d35a78 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -477,7 +477,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) server->capabilities = CAP_MPX_MODE; } tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone); - if (tmp == 0xffff) { + if (tmp == -1) { /* OS/2 often does not set timezone therefore * we must use server time to calc time zone. * Could deviate slightly from the right zone. -- cgit v1.2.3 From 268f3be177ce93791da38facc34126b5038cd851 Mon Sep 17 00:00:00 2001 From: Steve French Date: Fri, 6 Oct 2006 21:47:09 +0000 Subject: [CIFS] readdir (ffirst) enablement of accurate timestamps from legacy servers Signed-off-by: Steve French --- fs/cifs/netmisc.c | 39 ++++++++++++++++++--------------------- fs/cifs/readdir.c | 18 +++++++++--------- 2 files changed, 27 insertions(+), 30 deletions(-) (limited to 'fs') diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index fa5124d9af1..3d86b31cf2e 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c @@ -918,45 +918,42 @@ __le64 cnvrtDosCifsTm(__u16 date, __u16 time) { return cpu_to_le64(cifs_UnixTimeToNT(cnvrtDosUnixTm(date, time))); } + struct timespec cnvrtDosUnixTm(__u16 date, __u16 time) { - __u8 dt[2]; - __u8 tm[2]; struct timespec ts; - int sec,min, days, month, year; - struct timespec removeme; /* BB removeme BB */ -/* SMB_TIME * st = (SMB_TIME *)&time;*/ + int sec, min, days, month, year; + SMB_TIME * st = (SMB_TIME *)&time; + SMB_DATE * sd = (SMB_DATE *)&date; cFYI(1,("date %d time %d",date, time)); - dt[0] = date & 0xFF; - dt[1] = (date & 0xFF00) >> 8; - tm[0] = time & 0xFF; - tm[1] = (time & 0xFF00) >> 8; - - sec = tm[0] & 0x1F; - sec = 2 * sec; - min = ((tm[0] >>5)&0xFF) + ((tm[1] & 0x7)<<3); - + sec = 2 * st->TwoSeconds; + min = st->Minutes; + if((sec > 59) || (min > 59)) + cERROR(1,("illegal time min %d sec %d", min, sec)); sec += (min * 60); - sec += 60 * 60 * ((tm[1] >> 3) &0xFF) /* hours */; - days = (dt[0] & 0x1F) - 1; - month = ((dt[0] >> 5) & 0xFF) + ((dt[1] & 0x1) <<3); - if(month > 12) - cERROR(1,("illegal month %d in date", month)); + sec += 60 * 60 * st->Hours; + if(st->Hours > 24) + cERROR(1,("illegal hours %d",st->Hours)); + days = sd->Day; + month = sd->Month; + if((days > 31) || (month > 12)) + cERROR(1,("illegal date, month %d day: %d", month, days)); month -= 1; days += total_days_of_prev_months[month]; days += 3653; /* account for difference in days between 1980 and 1970 */ - year = (dt[1]>>1) & 0xFF; + year = sd->Year; days += year * 365; days += (year/4); /* leap year */ /* adjust for leap year where we are still before leap day */ days -= ((year & 0x03) == 0) && (month < 2 ? 1 : 0); sec += 24 * 60 * 60 * days; - removeme = CURRENT_TIME; /* BB removeme BB */ ts.tv_sec = sec; + /* cFYI(1,("sec after cnvrt dos to unix time %d",sec)); */ + ts.tv_nsec = 0; return ts; } diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index b0e5db10664..81e7b2e5fb4 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -139,19 +139,19 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, FIND_FILE_STANDARD_INFO * pfindData = (FIND_FILE_STANDARD_INFO *)buf; -/* ts = cnvrtDosUnixTm( + tmp_inode->i_mtime = cnvrtDosUnixTm( le16_to_cpu(pfindData->LastWriteDate), - le16_to_cpu(pfindData->LastWriteTime));*/ + le16_to_cpu(pfindData->LastWriteTime)); + tmp_inode->i_atime = cnvrtDosUnixTm( + le16_to_cpu(pfindData->LastAccessDate), + le16_to_cpu(pfindData->LastAccessTime)); + tmp_inode->i_ctime = cnvrtDosUnixTm( + le16_to_cpu(pfindData->LastWriteDate), + le16_to_cpu(pfindData->LastWriteTime)); + attr = le16_to_cpu(pfindData->Attributes); allocation_size = le32_to_cpu(pfindData->AllocationSize); end_of_file = le32_to_cpu(pfindData->DataSize); - /* do not need to use current_fs_time helper function since - time not stored for this case so atime can not "go backwards" - by pulling newer older from disk when inode refrenshed */ - tmp_inode->i_atime = CURRENT_TIME; - /* tmp_inode->i_mtime = BB FIXME - add dos time handling - tmp_inode->i_ctime = 0; BB FIXME */ - } /* Linux can not store file creation time unfortunately so ignore it */ -- cgit v1.2.3 From 438dd926260f11ff01fc3441ac6dd4c412d20ea4 Mon Sep 17 00:00:00 2001 From: Steve French Date: Wed, 11 Oct 2006 03:49:30 +0000 Subject: [CIFS] Fix leaps year calculation for years after 2100 Signed-off-by: Steve French --- fs/cifs/netmisc.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'fs') diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index 3d86b31cf2e..32562d19955 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c @@ -946,6 +946,15 @@ struct timespec cnvrtDosUnixTm(__u16 date, __u16 time) year = sd->Year; days += year * 365; days += (year/4); /* leap year */ + /* generalized leap year calculation is more complex, ie no leap year + for years/100 except for years/400, but since the maximum number for DOS + year is 2**7, the last year is 1980+127, which means we need only + consider 2 special case years, ie the years 2000 and 2100, and only + adjust for the lack of leap year for the year 2100, as 2000 was a + leap year (divisable by 400) */ + if(year >= 120) /* the year 2100 */ + days = days - 1; /* do not count leap year for the year 2100 */ + /* adjust for leap year where we are still before leap day */ days -= ((year & 0x03) == 0) && (month < 2 ? 1 : 0); sec += 24 * 60 * 60 * days; -- cgit v1.2.3 From 70903ca004fef17b0f6483714baefdb2f6ecceb0 Mon Sep 17 00:00:00 2001 From: Steve French Date: Wed, 11 Oct 2006 18:49:24 +0000 Subject: [CIFS] Do not need to adjust for Jan/Feb for leap day calculation in 2100 (year divisible by 100) Signed-off-by: Yehuda Sadeh Weinraub Signed-off-by: Steve French --- fs/cifs/netmisc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index 32562d19955..3adbd128e08 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c @@ -956,7 +956,8 @@ struct timespec cnvrtDosUnixTm(__u16 date, __u16 time) days = days - 1; /* do not count leap year for the year 2100 */ /* adjust for leap year where we are still before leap day */ - days -= ((year & 0x03) == 0) && (month < 2 ? 1 : 0); + if(year != 120) + days -= ((year & 0x03) == 0) && (month < 2 ? 1 : 0); sec += 24 * 60 * 60 * days; ts.tv_sec = sec; -- cgit v1.2.3 From 533f90af6d90b9e4859a158565385d1d84a79f75 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 12 Oct 2006 00:02:32 +0000 Subject: [CIFS] Fix old DOS time conversion to handle timezone Signed-off-by: Steve French --- fs/cifs/netmisc.c | 2 +- fs/cifs/readdir.c | 13 ++++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index 3adbd128e08..992e80edc72 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c @@ -942,7 +942,7 @@ struct timespec cnvrtDosUnixTm(__u16 date, __u16 time) cERROR(1,("illegal date, month %d day: %d", month, days)); month -= 1; days += total_days_of_prev_months[month]; - days += 3653; /* account for difference in days between 1980 and 1970 */ + days += 3652; /* account for difference in days between 1980 and 1970 */ year = sd->Year; days += year * 365; days += (year/4); /* leap year */ diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 81e7b2e5fb4..80e6ebd440a 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -106,6 +106,17 @@ static int construct_dentry(struct qstr *qstring, struct file *file, return rc; } +static void AdjustForTZ(struct cifsTconInfo * tcon, struct inode * inode) +{ + if((tcon) && (tcon->ses) && (tcon->ses->server)) { + inode->i_ctime.tv_sec += tcon->ses->server.timeAdj; + inode->i_mtime.tv_sec += tcon->ses->server.timeAdj; + inode->i_atime.tv_sec += tcon->ses->server.timeAdj; + } + return; +} + + static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, char * buf, int *pobject_type, int isNewInode) { @@ -148,7 +159,7 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, tmp_inode->i_ctime = cnvrtDosUnixTm( le16_to_cpu(pfindData->LastWriteDate), le16_to_cpu(pfindData->LastWriteTime)); - + AdjustForTZ(cifs_sb->tcon, tmp_inode); attr = le16_to_cpu(pfindData->Attributes); allocation_size = le32_to_cpu(pfindData->AllocationSize); end_of_file = le32_to_cpu(pfindData->DataSize); -- cgit v1.2.3 From ddae957da48cc381c1472a8909905e1818e4afdd Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 12 Oct 2006 01:23:29 +0000 Subject: [CIFS] fix typo in previous patch Signed-off-by: Steve French --- fs/cifs/readdir.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 80e6ebd440a..acbabc09543 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -109,9 +109,9 @@ static int construct_dentry(struct qstr *qstring, struct file *file, static void AdjustForTZ(struct cifsTconInfo * tcon, struct inode * inode) { if((tcon) && (tcon->ses) && (tcon->ses->server)) { - inode->i_ctime.tv_sec += tcon->ses->server.timeAdj; - inode->i_mtime.tv_sec += tcon->ses->server.timeAdj; - inode->i_atime.tv_sec += tcon->ses->server.timeAdj; + inode->i_ctime.tv_sec += tcon->ses->server->timeAdj; + inode->i_mtime.tv_sec += tcon->ses->server->timeAdj; + inode->i_atime.tv_sec += tcon->ses->server->timeAdj; } return; } -- cgit v1.2.3 From acf1a1b1043327b2179ea529730358e58c7c277e Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 12 Oct 2006 03:28:28 +0000 Subject: [CIFS] Level 1 QPathInfo needed for proper OS2 support Signed-off-by: Steve French --- fs/cifs/cifsproto.h | 1 + fs/cifs/cifssmb.c | 21 ++++++++++++++++++--- fs/cifs/inode.c | 5 ++++- 3 files changed, 23 insertions(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 7dd2f48a407..4a4fd2dbca6 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -119,6 +119,7 @@ extern int CIFSFindClose(const int, struct cifsTconInfo *tcon, extern int CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, const unsigned char *searchName, FILE_ALL_INFO * findData, + int legacy /* whether to use old info level */, const struct nls_table *nls_codepage, int remap); extern int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon, const unsigned char *searchName, diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 79a01d35a78..6f50f2bc887 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -2969,6 +2969,7 @@ int CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, const unsigned char *searchName, FILE_ALL_INFO * pFindData, + int legacy /* old style infolevel */, const struct nls_table *nls_codepage, int remap) { /* level 263 SMB_QUERY_FILE_ALL_INFO */ @@ -3017,7 +3018,10 @@ QPathInfoRetry: byte_count = params + 1 /* pad */ ; pSMB->TotalParameterCount = cpu_to_le16(params); pSMB->ParameterCount = pSMB->TotalParameterCount; - pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO); + if(legacy) + pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD); + else + pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO); pSMB->Reserved4 = 0; pSMB->hdr.smb_buf_length += byte_count; pSMB->ByteCount = cpu_to_le16(byte_count); @@ -3029,13 +3033,24 @@ QPathInfoRetry: } else { /* decode response */ rc = validate_t2((struct smb_t2_rsp *)pSMBr); - if (rc || (pSMBr->ByteCount < 40)) + if (rc) /* BB add auto retry on EOPNOTSUPP? */ + rc = -EIO; + else if (!legacy && (pSMBr->ByteCount < 40)) rc = -EIO; /* bad smb */ + else if(legacy && (pSMBr->ByteCount < 24)) + rc = -EIO; /* 24 or 26 expected but we do not read last field */ else if (pFindData){ + int size; __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); + if(legacy) /* we do not read the last field, EAsize, fortunately + since it varies by subdialect and on Set vs. Get, is + two bytes or 4 bytes depending but we don't care here */ + size = sizeof(FILE_INFO_STANDARD); + else + size = sizeof(FILE_ALL_INFO); memcpy((char *) pFindData, (char *) &pSMBr->hdr.Protocol + - data_offset, sizeof (FILE_ALL_INFO)); + data_offset, size); } else rc = -ENOMEM; } diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 06dbce3a181..fe6d21f9996 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -338,6 +338,7 @@ int cifs_get_inode_info(struct inode **pinode, pfindData = (FILE_ALL_INFO *)buf; /* could do find first instead but this returns more info */ rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData, + 0 /* not legacy */, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); /* BB optimize code so we do not make the above call @@ -385,8 +386,10 @@ int cifs_get_inode_info(struct inode **pinode, /* get new inode */ if (*pinode == NULL) { *pinode = new_inode(sb); - if (*pinode == NULL) + if (*pinode == NULL) { + kfree(buf); return -ENOMEM; + } /* Is an i_ino of zero legal? Can we use that to check if the server supports returning inode numbers? Are there other sanity checks we can use to ensure that -- cgit v1.2.3 From 230a03950ecd63bc613c6adeffbe9049189d9f05 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 12 Oct 2006 15:07:55 +0000 Subject: [CIFS] cifs Kconfig: don't select CONNECTOR `select' is a bit obnoxious: the option keeps on coming back and it's hard to work out what to do to make it go away again. The use of `depends on' is preferred (although it has usability problems too..) Signed-off-by: Andrew Morton Signed-off-by: Steve French --- fs/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/Kconfig b/fs/Kconfig index 53058162831..6865a33544d 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -1827,7 +1827,7 @@ config CIFS_EXPERIMENTAL config CIFS_UPCALL bool "Kerberos/SPNEGO advanced session setup (EXPERIMENTAL)" depends on CIFS_EXPERIMENTAL - select CONNECTOR + depends on CONNECTOR help Enables an upcall mechanism for CIFS which will be used to contact userspace helper utilities to provide SPNEGO packaged Kerberos -- cgit v1.2.3 From d103e164bee2f21d0efe7d713cbbb0a443ba480d Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 12 Oct 2006 17:49:24 +0000 Subject: [CIFS] Workaround incomplete byte length returned by some servers on small SMB responses Signed-off-by: Steve French --- fs/cifs/cifsproto.h | 2 +- fs/cifs/misc.c | 42 +++++++++++++++++++++++++++++------------- 2 files changed, 30 insertions(+), 14 deletions(-) (limited to 'fs') diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 4a4fd2dbca6..f1f8225102f 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -55,7 +55,7 @@ extern int SendReceiveBlockingLock(const unsigned int /* xid */ , struct smb_hdr * /* input */ , struct smb_hdr * /* out */ , int * /* bytes returned */); -extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length); +extern int checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length); extern int is_valid_oplock_break(struct smb_hdr *smb, struct TCP_Server_Info *); extern int is_size_safe_to_change(struct cifsInodeInfo *); extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *); diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index ca6e9b1413f..bbc9cd34b6e 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -418,26 +418,42 @@ checkSMBhdr(struct smb_hdr *smb, __u16 mid) } int -checkSMB(struct smb_hdr *smb, __u16 mid, int length) +checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length) { __u32 len = smb->smb_buf_length; __u32 clc_len; /* calculated length */ cFYI(0, ("checkSMB Length: 0x%x, smb_buf_length: 0x%x", length, len)); - if (((unsigned int)length < 2 + sizeof (struct smb_hdr)) || - (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)) { - if ((unsigned int)length < 2 + sizeof (struct smb_hdr)) { - if (((unsigned int)length >= - sizeof (struct smb_hdr) - 1) + + if (length < 2 + sizeof (struct smb_hdr)) { + if ((length >= sizeof (struct smb_hdr) - 1) && (smb->Status.CifsError != 0)) { - smb->WordCount = 0; - /* some error cases do not return wct and bcc */ + smb->WordCount = 0; + /* some error cases do not return wct and bcc */ + return 0; + } else if ((length == sizeof(struct smb_hdr) + 1) && + (smb->WordCount == 0)) { + char * tmp = (char *)smb; + /* Need to work around a bug in two servers here */ + /* First, check if the part of bcc they sent was zero */ + if (tmp[sizeof(struct smb_hdr)] == 0) { + /* some servers return only half of bcc + * on simple responses (wct, bcc both zero) + * in particular have seen this on + * ulogoffX and FindClose. This leaves + * one byte of bcc potentially unitialized + */ + /* zero rest of bcc */ + tmp[sizeof(struct smb_hdr)+1] = 0; return 0; - } else { - cERROR(1, ("Length less than smb header size")); } + cERROR(1,("rcvd invalid byte count (bcc)")); + } else { + cERROR(1, ("Length less than smb header size")); } - if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) - cERROR(1, ("smb length greater than MaxBufSize, mid=%d", + return 1; + } + if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { + cERROR(1, ("smb length greater than MaxBufSize, mid=%d", smb->Mid)); return 1; } @@ -446,7 +462,7 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length) return 1; clc_len = smbCalcSize_LE(smb); - if(4 + len != (unsigned int)length) { + if(4 + len != length) { cERROR(1, ("Length read does not match RFC1001 length %d",len)); return 1; } -- cgit v1.2.3 From 1a4e15a04ec69cb3552f4120079f5472377df5f7 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 12 Oct 2006 21:33:51 +0000 Subject: [CIFS] Missing flags2 for DFS Partly suggested by Igor Mammedov Signed-off-by: Steve French --- fs/cifs/cifssmb.c | 8 ++++++++ fs/cifs/connect.c | 4 +++- 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 6f50f2bc887..5dc5a966bd5 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -3675,6 +3675,14 @@ getDFSRetry: strncpy(pSMB->RequestFileName, searchName, name_len); } + if(ses->server) { + if(ses->server->secMode & + (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) + pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE; + } + + pSMB->hdr.Uid = ses->Suid; + params = 2 /* level */ + name_len /*includes null */ ; pSMB->TotalDataCount = 0; pSMB->DataCount = 0; diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index c96f3edf1b9..1d17691086c 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -3219,7 +3219,9 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, } /* else do not bother copying these informational fields */ } - if(smb_buffer_response->WordCount == 3) + if((smb_buffer_response->WordCount == 3) || + (smb_buffer_response->WordCount == 7)) + /* field is in same location */ tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport); else tcon->Flags = 0; -- cgit v1.2.3