Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6: (24 commits) [CIFS] merge conflict in fs/cifs/export.c [CIFS] Allow disabling CIFS Unix Extensions as mount option [CIFS] More whitespace/formatting fixes (noticed by checkpatch) [CIFS] Typo in previous patch [CIFS] zero_user_page() conversions [CIFS] use simple_prepare_write to zero page data [CIFS] Fix build break - inet.h not included when experimental ifdef off [CIFS] Add support for new POSIX unlink [CIFS] whitespace/formatting fixes [CIFS] Fix oops in cifs_create when nfsd server exports cifs mount [CIFS] whitespace cleanup [CIFS] Fix packet signatures for NTLMv2 case [CIFS] more whitespace fixes [CIFS] more whitespace cleanup [CIFS] whitespace cleanup [CIFS] whitespace cleanup [CIFS] ipv6 support no longer experimental [CIFS] Mount should fail if server signing off but client mount option requires it [CIFS] whitespace fixes [CIFS] Fix sign mount option and sign proc config setting ...
This commit is contained in:
commit
789c56b7f7
38 changed files with 3435 additions and 3151 deletions
|
@ -1,3 +1,10 @@
|
||||||
|
Version 1.50
|
||||||
|
------------
|
||||||
|
Fix NTLMv2 signing. NFS server mounted over cifs works (if cifs mount is
|
||||||
|
done with "serverino" mount option). Add support for POSIX Unlink
|
||||||
|
(helps with certain sharing violation cases when server such as
|
||||||
|
Samba supports newer POSIX CIFS Protocol Extensions).
|
||||||
|
|
||||||
Version 1.49
|
Version 1.49
|
||||||
------------
|
------------
|
||||||
IPv6 support. Enable ipv6 addresses to be passed on mount (put the ipv6
|
IPv6 support. Enable ipv6 addresses to be passed on mount (put the ipv6
|
||||||
|
@ -8,7 +15,11 @@ when Unix Extensions were ignored). This allows users to override the
|
||||||
default uid and gid for files when they are certain that the uids or
|
default uid and gid for files when they are certain that the uids or
|
||||||
gids on the server do not match those of the client. Make "sec=none"
|
gids on the server do not match those of the client. Make "sec=none"
|
||||||
mount override username (so that null user connection is attempted)
|
mount override username (so that null user connection is attempted)
|
||||||
to match what documentation said.
|
to match what documentation said. Support for very large reads, over 127K,
|
||||||
|
available to some newer servers (such as Samba 3.0.26 and later but
|
||||||
|
note that it also requires setting CIFSMaxBufSize at module install
|
||||||
|
time to a larger value which may hurt performance in some cases).
|
||||||
|
Make sign option force signing (or fail if server does not support it).
|
||||||
|
|
||||||
Version 1.48
|
Version 1.48
|
||||||
------------
|
------------
|
||||||
|
|
|
@ -301,10 +301,21 @@ A partial list of the supported mount options follows:
|
||||||
during the local client kernel build will be used.
|
during the local client kernel build will be used.
|
||||||
If server does not support Unicode, this parameter is
|
If server does not support Unicode, this parameter is
|
||||||
unused.
|
unused.
|
||||||
rsize default read size (usually 16K)
|
rsize default read size (usually 16K). The client currently
|
||||||
wsize default write size (usually 16K, 32K is often better over GigE)
|
can not use rsize larger than CIFSMaxBufSize. CIFSMaxBufSize
|
||||||
maximum wsize currently allowed by CIFS is 57344 (14 4096 byte
|
defaults to 16K and may be changed (from 8K to the maximum
|
||||||
pages)
|
kmalloc size allowed by your kernel) at module install time
|
||||||
|
for cifs.ko. Setting CIFSMaxBufSize to a very large value
|
||||||
|
will cause cifs to use more memory and may reduce performance
|
||||||
|
in some cases. To use rsize greater than 127K (the original
|
||||||
|
cifs protocol maximum) also requires that the server support
|
||||||
|
a new Unix Capability flag (for very large read) which some
|
||||||
|
newer servers (e.g. Samba 3.0.26 or later) do. rsize can be
|
||||||
|
set from a minimum of 2048 to a maximum of 130048 (127K or
|
||||||
|
CIFSMaxBufSize, whichever is smaller)
|
||||||
|
wsize default write size (default 57344)
|
||||||
|
maximum wsize currently allowed by CIFS is 57344 (fourteen
|
||||||
|
4096 byte pages)
|
||||||
rw mount the network share read-write (note that the
|
rw mount the network share read-write (note that the
|
||||||
server may still consider the share read-only)
|
server may still consider the share read-only)
|
||||||
ro mount network share read-only
|
ro mount network share read-only
|
||||||
|
@ -359,7 +370,7 @@ A partial list of the supported mount options follows:
|
||||||
Note that this does not affect the normal ACL check on the
|
Note that this does not affect the normal ACL check on the
|
||||||
target machine done by the server software (of the server
|
target machine done by the server software (of the server
|
||||||
ACL against the user name provided at mount time).
|
ACL against the user name provided at mount time).
|
||||||
serverino Use servers inode numbers instead of generating automatically
|
serverino Use server's inode numbers instead of generating automatically
|
||||||
incrementing inode numbers on the client. Although this will
|
incrementing inode numbers on the client. Although this will
|
||||||
make it easier to spot hardlinked files (as they will have
|
make it easier to spot hardlinked files (as they will have
|
||||||
the same inode numbers) and inode numbers may be persistent,
|
the same inode numbers) and inode numbers may be persistent,
|
||||||
|
@ -367,12 +378,11 @@ A partial list of the supported mount options follows:
|
||||||
are unique if multiple server side mounts are exported under a
|
are unique if multiple server side mounts are exported under a
|
||||||
single share (since inode numbers on the servers might not
|
single share (since inode numbers on the servers might not
|
||||||
be unique if multiple filesystems are mounted under the same
|
be unique if multiple filesystems are mounted under the same
|
||||||
shared higher level directory). Note that this requires that
|
shared higher level directory). Note that some older
|
||||||
the server support the CIFS Unix Extensions as other servers
|
(e.g. pre-Windows 2000) do not support returning UniqueIDs
|
||||||
do not return a unique IndexNumber on SMB FindFirst (most
|
or the CIFS Unix Extensions equivalent and for those
|
||||||
servers return zero as the IndexNumber). Parameter has no
|
this mount option will have no effect. Exporting cifs mounts
|
||||||
effect to Windows servers and others which do not support the
|
under nfsd requires this mount option on the cifs mount.
|
||||||
CIFS Unix Extensions.
|
|
||||||
noserverino Client generates inode numbers (rather than using the actual one
|
noserverino Client generates inode numbers (rather than using the actual one
|
||||||
from the server) by default.
|
from the server) by default.
|
||||||
setuids If the CIFS Unix extensions are negotiated with the server
|
setuids If the CIFS Unix extensions are negotiated with the server
|
||||||
|
@ -582,10 +592,10 @@ the start of smb requests and responses can be enabled via:
|
||||||
|
|
||||||
echo 1 > /proc/fs/cifs/traceSMB
|
echo 1 > /proc/fs/cifs/traceSMB
|
||||||
|
|
||||||
Two other experimental features are under development and to test
|
Two other experimental features are under development. To test these
|
||||||
require enabling CONFIG_CIFS_EXPERIMENTAL
|
requires enabling CONFIG_CIFS_EXPERIMENTAL
|
||||||
|
|
||||||
More efficient write operations
|
ipv6 enablement
|
||||||
|
|
||||||
DNOTIFY fcntl: needed for support of directory change
|
DNOTIFY fcntl: needed for support of directory change
|
||||||
notification and perhaps later for file leases)
|
notification and perhaps later for file leases)
|
||||||
|
|
12
fs/cifs/TODO
12
fs/cifs/TODO
|
@ -18,9 +18,9 @@ better)
|
||||||
|
|
||||||
d) Kerberos/SPNEGO session setup support - (started)
|
d) Kerberos/SPNEGO session setup support - (started)
|
||||||
|
|
||||||
e) More testing of NTLMv2 authentication (mostly implemented - double check
|
e) Cleanup now unneeded SessSetup code in
|
||||||
that NTLMv2 signing works, also need to cleanup now unneeded SessSetup code in
|
fs/cifs/connect.c and add back in NTLMSSP code if any servers
|
||||||
fs/cifs/connect.c)
|
need it
|
||||||
|
|
||||||
f) MD5-HMAC signing SMB PDUs when SPNEGO style SessionSetup
|
f) MD5-HMAC signing SMB PDUs when SPNEGO style SessionSetup
|
||||||
used (Kerberos or NTLMSSP). Signing alreadyimplemented for NTLM
|
used (Kerberos or NTLMSSP). Signing alreadyimplemented for NTLM
|
||||||
|
@ -106,6 +106,12 @@ but recognizes them
|
||||||
succeed but still return access denied (appears to be Windows
|
succeed but still return access denied (appears to be Windows
|
||||||
server not cifs client problem) and has not been reproduced recently.
|
server not cifs client problem) and has not been reproduced recently.
|
||||||
NTFS partitions do not have this problem.
|
NTFS partitions do not have this problem.
|
||||||
|
4) Unix/POSIX capabilities are reset after reconnection, and affect
|
||||||
|
a few fields in the tree connection but we do do not know which
|
||||||
|
superblocks to apply these changes to. We should probably walk
|
||||||
|
the list of superblocks to set these. Also need to check the
|
||||||
|
flags on the second mount to the same share, and see if we
|
||||||
|
can do the same trick that NFS does to remount duplicate shares.
|
||||||
|
|
||||||
Misc testing to do
|
Misc testing to do
|
||||||
==================
|
==================
|
||||||
|
|
|
@ -498,7 +498,8 @@ decode_negTokenInit(unsigned char *security_blob, int length,
|
||||||
return 0;
|
return 0;
|
||||||
} else if ((cls != ASN1_CTX) || (con != ASN1_CON)
|
} else if ((cls != ASN1_CTX) || (con != ASN1_CON)
|
||||||
|| (tag != ASN1_EOC)) {
|
|| (tag != ASN1_EOC)) {
|
||||||
cFYI(1,("cls = %d con = %d tag = %d end = %p (%d) exit 0",
|
cFYI(1,
|
||||||
|
("cls = %d con = %d tag = %d end = %p (%d) exit 0",
|
||||||
cls, con, tag, end, *end));
|
cls, con, tag, end, *end));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -508,7 +509,8 @@ decode_negTokenInit(unsigned char *security_blob, int length,
|
||||||
return 0;
|
return 0;
|
||||||
} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
|
} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
|
||||||
|| (tag != ASN1_SEQ)) {
|
|| (tag != ASN1_SEQ)) {
|
||||||
cFYI(1,("cls = %d con = %d tag = %d end = %p (%d) exit 1",
|
cFYI(1,
|
||||||
|
("cls = %d con = %d tag = %d end = %p (%d) exit 1",
|
||||||
cls, con, tag, end, *end));
|
cls, con, tag, end, *end));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -540,32 +542,34 @@ decode_negTokenInit(unsigned char *security_blob, int length,
|
||||||
rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag);
|
rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag);
|
||||||
if (!rc) {
|
if (!rc) {
|
||||||
cFYI(1,
|
cFYI(1,
|
||||||
("Error 1 decoding negTokenInit header exit 2"));
|
("Error decoding negTokenInit hdr exit2"));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if ((tag == ASN1_OJI) && (con == ASN1_PRI)) {
|
if ((tag == ASN1_OJI) && (con == ASN1_PRI)) {
|
||||||
rc = asn1_oid_decode(&ctx, end, &oid, &oidlen);
|
rc = asn1_oid_decode(&ctx, end, &oid, &oidlen);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
cFYI(1,
|
cFYI(1,
|
||||||
("OID len = %d oid = 0x%lx 0x%lx 0x%lx 0x%lx",
|
("OID len = %d oid = 0x%lx 0x%lx "
|
||||||
oidlen, *oid, *(oid + 1), *(oid + 2),
|
"0x%lx 0x%lx",
|
||||||
*(oid + 3)));
|
oidlen, *oid, *(oid + 1),
|
||||||
rc = compare_oid(oid, oidlen, NTLMSSP_OID,
|
*(oid + 2), *(oid + 3)));
|
||||||
NTLMSSP_OID_LEN);
|
rc = compare_oid(oid, oidlen,
|
||||||
|
NTLMSSP_OID, NTLMSSP_OID_LEN);
|
||||||
kfree(oid);
|
kfree(oid);
|
||||||
if (rc)
|
if (rc)
|
||||||
use_ntlmssp = TRUE;
|
use_ntlmssp = TRUE;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
cFYI(1,("This should be an oid what is going on? "));
|
cFYI(1, ("Should be an oid what is going on?"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
|
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
|
||||||
cFYI(1,
|
cFYI(1,
|
||||||
("Error decoding last part of negTokenInit exit 3"));
|
("Error decoding last part negTokenInit exit3"));
|
||||||
return 0;
|
return 0;
|
||||||
} else if ((cls != ASN1_CTX) || (con != ASN1_CON)) { /* tag = 3 indicating mechListMIC */
|
} else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
|
||||||
|
/* tag = 3 indicating mechListMIC */
|
||||||
cFYI(1,
|
cFYI(1,
|
||||||
("Exit 4 cls = %d con = %d tag = %d end = %p (%d)",
|
("Exit 4 cls = %d con = %d tag = %d end = %p (%d)",
|
||||||
cls, con, tag, end, *end));
|
cls, con, tag, end, *end));
|
||||||
|
@ -573,7 +577,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
|
||||||
}
|
}
|
||||||
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
|
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
|
||||||
cFYI(1,
|
cFYI(1,
|
||||||
("Error decoding last part of negTokenInit exit 5"));
|
("Error decoding last part negTokenInit exit5"));
|
||||||
return 0;
|
return 0;
|
||||||
} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
|
} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
|
||||||
|| (tag != ASN1_SEQ)) {
|
|| (tag != ASN1_SEQ)) {
|
||||||
|
@ -584,7 +588,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
|
||||||
|
|
||||||
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
|
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
|
||||||
cFYI(1,
|
cFYI(1,
|
||||||
("Error decoding last part of negTokenInit exit 7"));
|
("Error decoding last part negTokenInit exit 7"));
|
||||||
return 0;
|
return 0;
|
||||||
} else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
|
} else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
|
||||||
cFYI(1,
|
cFYI(1,
|
||||||
|
@ -594,7 +598,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
|
||||||
}
|
}
|
||||||
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
|
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
|
||||||
cFYI(1,
|
cFYI(1,
|
||||||
("Error decoding last part of negTokenInit exit 9"));
|
("Error decoding last part negTokenInit exit9"));
|
||||||
return 0;
|
return 0;
|
||||||
} else if ((cls != ASN1_UNI) || (con != ASN1_PRI)
|
} else if ((cls != ASN1_UNI) || (con != ASN1_PRI)
|
||||||
|| (tag != ASN1_GENSTR)) {
|
|| (tag != ASN1_GENSTR)) {
|
||||||
|
@ -603,7 +607,8 @@ decode_negTokenInit(unsigned char *security_blob, int length,
|
||||||
cls, con, tag, end, *end));
|
cls, con, tag, end, *end));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
cFYI(1, ("Need to call asn1_octets_decode() function for this %s", ctx.pointer)); /* is this UTF-8 or ASCII? */
|
cFYI(1, ("Need to call asn1_octets_decode() function for %s",
|
||||||
|
ctx.pointer)); /* is this UTF-8 or ASCII? */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if (use_kerberos)
|
/* if (use_kerberos)
|
||||||
|
|
|
@ -145,7 +145,6 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
|
||||||
(ses->serverNOS == NULL)) {
|
(ses->serverNOS == NULL)) {
|
||||||
buf += sprintf(buf, "\nentry for %s not fully "
|
buf += sprintf(buf, "\nentry for %s not fully "
|
||||||
"displayed\n\t", ses->serverName);
|
"displayed\n\t", ses->serverName);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
length =
|
length =
|
||||||
sprintf(buf,
|
sprintf(buf,
|
||||||
|
@ -901,90 +900,14 @@ security_flags_write(struct file *file, const char __user *buffer,
|
||||||
}
|
}
|
||||||
/* flags look ok - update the global security flags for cifs module */
|
/* flags look ok - update the global security flags for cifs module */
|
||||||
extended_security = flags;
|
extended_security = flags;
|
||||||
|
if (extended_security & CIFSSEC_MUST_SIGN) {
|
||||||
|
/* requiring signing implies signing is allowed */
|
||||||
|
extended_security |= CIFSSEC_MAY_SIGN;
|
||||||
|
cFYI(1, ("packet signing now required"));
|
||||||
|
} else if ((extended_security & CIFSSEC_MAY_SIGN) == 0) {
|
||||||
|
cFYI(1, ("packet signing disabled"));
|
||||||
|
}
|
||||||
|
/* BB should we turn on MAY flags for other MUST options? */
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static int
|
|
||||||
ntlmv2_enabled_read(char *page, char **start, off_t off,
|
|
||||||
int count, int *eof, void *data)
|
|
||||||
{
|
|
||||||
int len;
|
|
||||||
|
|
||||||
len = sprintf(page, "%d\n", ntlmv2_support);
|
|
||||||
|
|
||||||
len -= off;
|
|
||||||
*start = page + off;
|
|
||||||
|
|
||||||
if (len > count)
|
|
||||||
len = count;
|
|
||||||
else
|
|
||||||
*eof = 1;
|
|
||||||
|
|
||||||
if (len < 0)
|
|
||||||
len = 0;
|
|
||||||
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
static int
|
|
||||||
ntlmv2_enabled_write(struct file *file, const char __user *buffer,
|
|
||||||
unsigned long count, void *data)
|
|
||||||
{
|
|
||||||
char c;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
rc = get_user(c, buffer);
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
if (c == '0' || c == 'n' || c == 'N')
|
|
||||||
ntlmv2_support = 0;
|
|
||||||
else if (c == '1' || c == 'y' || c == 'Y')
|
|
||||||
ntlmv2_support = 1;
|
|
||||||
else if (c == '2')
|
|
||||||
ntlmv2_support = 2;
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
packet_signing_enabled_read(char *page, char **start, off_t off,
|
|
||||||
int count, int *eof, void *data)
|
|
||||||
{
|
|
||||||
int len;
|
|
||||||
|
|
||||||
len = sprintf(page, "%d\n", sign_CIFS_PDUs);
|
|
||||||
|
|
||||||
len -= off;
|
|
||||||
*start = page + off;
|
|
||||||
|
|
||||||
if (len > count)
|
|
||||||
len = count;
|
|
||||||
else
|
|
||||||
*eof = 1;
|
|
||||||
|
|
||||||
if (len < 0)
|
|
||||||
len = 0;
|
|
||||||
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
static int
|
|
||||||
packet_signing_enabled_write(struct file *file, const char __user *buffer,
|
|
||||||
unsigned long count, void *data)
|
|
||||||
{
|
|
||||||
char c;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
rc = get_user(c, buffer);
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
if (c == '0' || c == 'n' || c == 'N')
|
|
||||||
sign_CIFS_PDUs = 0;
|
|
||||||
else if (c == '1' || c == 'y' || c == 'Y')
|
|
||||||
sign_CIFS_PDUs = 1;
|
|
||||||
else if (c == '2')
|
|
||||||
sign_CIFS_PDUs = 2;
|
|
||||||
|
|
||||||
return count;
|
|
||||||
} */
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
* Convert a unicode character to upper or lower case using
|
* Convert a unicode character to upper or lower case using
|
||||||
* compressed tables.
|
* compressed tables.
|
||||||
*
|
*
|
||||||
* Copyright (c) International Business Machines Corp., 2000,2005555555555555555555555555555555555555555555555555555555
|
* Copyright (c) International Business Machines Corp., 2000,2007
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -142,7 +142,8 @@ UniStrlen(const wchar_t * ucs1)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* UniStrnlen: Return the length (in 16 bit Unicode chars not bytes) of a string (length limited)
|
* UniStrnlen: Return the length (in 16 bit Unicode chars not bytes) of a
|
||||||
|
* string (length limited)
|
||||||
*/
|
*/
|
||||||
static inline size_t
|
static inline size_t
|
||||||
UniStrnlen(const wchar_t *ucs1, int maxlen)
|
UniStrnlen(const wchar_t *ucs1, int maxlen)
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
#include <linux/ctype.h>
|
#include <linux/ctype.h>
|
||||||
#include <linux/random.h>
|
#include <linux/random.h>
|
||||||
|
|
||||||
/* Calculate and return the CIFS signature based on the mac key and the smb pdu */
|
/* Calculate and return the CIFS signature based on the mac key and SMB PDU */
|
||||||
/* the 16 byte signature must be allocated by the caller */
|
/* the 16 byte signature must be allocated by the caller */
|
||||||
/* Note we only use the 1st eight bytes */
|
/* Note we only use the 1st eight bytes */
|
||||||
/* Note that the smb header signature field on input contains the
|
/* Note that the smb header signature field on input contains the
|
||||||
|
@ -41,16 +41,17 @@ extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
|
||||||
unsigned char *p24);
|
unsigned char *p24);
|
||||||
|
|
||||||
static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu,
|
static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu,
|
||||||
const char * key, char * signature)
|
const struct mac_key *key, char *signature)
|
||||||
{
|
{
|
||||||
struct MD5Context context;
|
struct MD5Context context;
|
||||||
|
|
||||||
if((cifs_pdu == NULL) || (signature == NULL))
|
if ((cifs_pdu == NULL) || (signature == NULL) || (key == NULL))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
MD5Init(&context);
|
MD5Init(&context);
|
||||||
MD5Update(&context,key,CIFS_SESS_KEY_SIZE+16);
|
MD5Update(&context, (char *)&key->data, key->len);
|
||||||
MD5Update(&context, cifs_pdu->Protocol, cifs_pdu->smb_buf_length);
|
MD5Update(&context, cifs_pdu->Protocol, cifs_pdu->smb_buf_length);
|
||||||
|
|
||||||
MD5Final(signature, &context);
|
MD5Final(signature, &context);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -68,14 +69,16 @@ int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct TCP_Server_Info * server,
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
spin_lock(&GlobalMid_Lock);
|
spin_lock(&GlobalMid_Lock);
|
||||||
cifs_pdu->Signature.Sequence.SequenceNumber = cpu_to_le32(server->sequence_number);
|
cifs_pdu->Signature.Sequence.SequenceNumber =
|
||||||
|
cpu_to_le32(server->sequence_number);
|
||||||
cifs_pdu->Signature.Sequence.Reserved = 0;
|
cifs_pdu->Signature.Sequence.Reserved = 0;
|
||||||
|
|
||||||
*pexpected_response_sequence_number = server->sequence_number++;
|
*pexpected_response_sequence_number = server->sequence_number++;
|
||||||
server->sequence_number++;
|
server->sequence_number++;
|
||||||
spin_unlock(&GlobalMid_Lock);
|
spin_unlock(&GlobalMid_Lock);
|
||||||
|
|
||||||
rc = cifs_calculate_signature(cifs_pdu, server->mac_signing_key,smb_signature);
|
rc = cifs_calculate_signature(cifs_pdu, &server->mac_signing_key,
|
||||||
|
smb_signature);
|
||||||
if (rc)
|
if (rc)
|
||||||
memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
|
memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
|
||||||
else
|
else
|
||||||
|
@ -85,16 +88,16 @@ int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct TCP_Server_Info * server,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cifs_calc_signature2(const struct kvec *iov, int n_vec,
|
static int cifs_calc_signature2(const struct kvec *iov, int n_vec,
|
||||||
const char * key, char * signature)
|
const struct mac_key *key, char *signature)
|
||||||
{
|
{
|
||||||
struct MD5Context context;
|
struct MD5Context context;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if((iov == NULL) || (signature == NULL))
|
if ((iov == NULL) || (signature == NULL) || (key == NULL))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
MD5Init(&context);
|
MD5Init(&context);
|
||||||
MD5Update(&context,key,CIFS_SESS_KEY_SIZE+16);
|
MD5Update(&context, (char *)&key->data, key->len);
|
||||||
for (i = 0; i < n_vec; i++) {
|
for (i = 0; i < n_vec; i++) {
|
||||||
if (iov[i].iov_base == NULL) {
|
if (iov[i].iov_base == NULL) {
|
||||||
cERROR(1, ("null iovec entry"));
|
cERROR(1, ("null iovec entry"));
|
||||||
|
@ -106,7 +109,8 @@ static int cifs_calc_signature2(const struct kvec * iov, int n_vec,
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
if (iov[0].iov_len <= 8 ) /* cmd field at offset 9 */
|
if (iov[0].iov_len <= 8 ) /* cmd field at offset 9 */
|
||||||
break; /* nothing to sign or corrupt header */
|
break; /* nothing to sign or corrupt header */
|
||||||
MD5Update(&context,iov[0].iov_base+4, iov[0].iov_len-4);
|
MD5Update(&context, iov[0].iov_base+4,
|
||||||
|
iov[0].iov_len-4);
|
||||||
} else
|
} else
|
||||||
MD5Update(&context, iov[i].iov_base, iov[i].iov_len);
|
MD5Update(&context, iov[i].iov_base, iov[i].iov_len);
|
||||||
}
|
}
|
||||||
|
@ -139,7 +143,7 @@ int cifs_sign_smb2(struct kvec * iov, int n_vec, struct TCP_Server_Info *server,
|
||||||
server->sequence_number++;
|
server->sequence_number++;
|
||||||
spin_unlock(&GlobalMid_Lock);
|
spin_unlock(&GlobalMid_Lock);
|
||||||
|
|
||||||
rc = cifs_calc_signature2(iov, n_vec, server->mac_signing_key,
|
rc = cifs_calc_signature2(iov, n_vec, &server->mac_signing_key,
|
||||||
smb_signature);
|
smb_signature);
|
||||||
if (rc)
|
if (rc)
|
||||||
memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
|
memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
|
||||||
|
@ -147,10 +151,10 @@ int cifs_sign_smb2(struct kvec * iov, int n_vec, struct TCP_Server_Info *server,
|
||||||
memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8);
|
memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int cifs_verify_signature(struct smb_hdr * cifs_pdu, const char * mac_key,
|
int cifs_verify_signature(struct smb_hdr *cifs_pdu,
|
||||||
|
const struct mac_key *mac_key,
|
||||||
__u32 expected_sequence_number)
|
__u32 expected_sequence_number)
|
||||||
{
|
{
|
||||||
unsigned int rc;
|
unsigned int rc;
|
||||||
|
@ -164,23 +168,26 @@ int cifs_verify_signature(struct smb_hdr * cifs_pdu, const char * mac_key,
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (cifs_pdu->Command == SMB_COM_LOCKING_ANDX) {
|
if (cifs_pdu->Command == SMB_COM_LOCKING_ANDX) {
|
||||||
struct smb_com_lock_req * pSMB = (struct smb_com_lock_req *)cifs_pdu;
|
struct smb_com_lock_req *pSMB =
|
||||||
|
(struct smb_com_lock_req *)cifs_pdu;
|
||||||
if (pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE)
|
if (pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* BB what if signatures are supposed to be on for session but server does not
|
/* BB what if signatures are supposed to be on for session but
|
||||||
send one? BB */
|
server does not send one? BB */
|
||||||
|
|
||||||
/* Do not need to verify session setups with signature "BSRSPYL " */
|
/* Do not need to verify session setups with signature "BSRSPYL " */
|
||||||
if (memcmp(cifs_pdu->Signature.SecuritySignature, "BSRSPYL ", 8) == 0)
|
if (memcmp(cifs_pdu->Signature.SecuritySignature, "BSRSPYL ", 8) == 0)
|
||||||
cFYI(1,("dummy signature received for smb command 0x%x",cifs_pdu->Command));
|
cFYI(1, ("dummy signature received for smb command 0x%x",
|
||||||
|
cifs_pdu->Command));
|
||||||
|
|
||||||
/* save off the origiginal signature so we can modify the smb and check
|
/* save off the origiginal signature so we can modify the smb and check
|
||||||
its signature against what the server sent */
|
its signature against what the server sent */
|
||||||
memcpy(server_response_sig, cifs_pdu->Signature.SecuritySignature, 8);
|
memcpy(server_response_sig, cifs_pdu->Signature.SecuritySignature, 8);
|
||||||
|
|
||||||
cifs_pdu->Signature.Sequence.SequenceNumber = cpu_to_le32(expected_sequence_number);
|
cifs_pdu->Signature.Sequence.SequenceNumber =
|
||||||
|
cpu_to_le32(expected_sequence_number);
|
||||||
cifs_pdu->Signature.Sequence.Reserved = 0;
|
cifs_pdu->Signature.Sequence.Reserved = 0;
|
||||||
|
|
||||||
rc = cifs_calculate_signature(cifs_pdu, mac_key,
|
rc = cifs_calculate_signature(cifs_pdu, mac_key,
|
||||||
|
@ -189,8 +196,8 @@ int cifs_verify_signature(struct smb_hdr * cifs_pdu, const char * mac_key,
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
|
/* cifs_dump_mem("what we think it should be: ",
|
||||||
/* cifs_dump_mem("what we think it should be: ",what_we_think_sig_should_be,16); */
|
what_we_think_sig_should_be, 16); */
|
||||||
|
|
||||||
if (memcmp(server_response_sig, what_we_think_sig_should_be, 8))
|
if (memcmp(server_response_sig, what_we_think_sig_should_be, 8))
|
||||||
return -EACCES;
|
return -EACCES;
|
||||||
|
@ -200,15 +207,17 @@ int cifs_verify_signature(struct smb_hdr * cifs_pdu, const char * mac_key,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We fill in key by putting in 40 byte array which was allocated by caller */
|
/* We fill in key by putting in 40 byte array which was allocated by caller */
|
||||||
int cifs_calculate_mac_key(char * key, const char * rn, const char * password)
|
int cifs_calculate_mac_key(struct mac_key *key, const char *rn,
|
||||||
|
const char *password)
|
||||||
{
|
{
|
||||||
char temp_key[16];
|
char temp_key[16];
|
||||||
if ((key == NULL) || (rn == NULL))
|
if ((key == NULL) || (rn == NULL))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
E_md4hash(password, temp_key);
|
E_md4hash(password, temp_key);
|
||||||
mdfour(key,temp_key,16);
|
mdfour(key->data.ntlm, temp_key, 16);
|
||||||
memcpy(key+16,rn, CIFS_SESS_KEY_SIZE);
|
memcpy(key->data.ntlm+16, rn, CIFS_SESS_KEY_SIZE);
|
||||||
|
key->len = 40;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,20 +257,22 @@ int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses,
|
||||||
for (i = 0; i < user_name_len; i++)
|
for (i = 0; i < user_name_len; i++)
|
||||||
ucase_buf[i] = nls_info->charset2upper[(int)ses->userName[i]];
|
ucase_buf[i] = nls_info->charset2upper[(int)ses->userName[i]];
|
||||||
ucase_buf[i] = 0;
|
ucase_buf[i] = 0;
|
||||||
user_name_len = cifs_strtoUCS(unicode_buf, ucase_buf, MAX_USERNAME_SIZE*2, nls_info);
|
user_name_len = cifs_strtoUCS(unicode_buf, ucase_buf,
|
||||||
|
MAX_USERNAME_SIZE*2, nls_info);
|
||||||
unicode_buf[user_name_len] = 0;
|
unicode_buf[user_name_len] = 0;
|
||||||
user_name_len++;
|
user_name_len++;
|
||||||
|
|
||||||
for (i = 0; i < dom_name_len; i++)
|
for (i = 0; i < dom_name_len; i++)
|
||||||
ucase_buf[i] = nls_info->charset2upper[(int)ses->domainName[i]];
|
ucase_buf[i] = nls_info->charset2upper[(int)ses->domainName[i]];
|
||||||
ucase_buf[i] = 0;
|
ucase_buf[i] = 0;
|
||||||
dom_name_len = cifs_strtoUCS(unicode_buf+user_name_len, ucase_buf, MAX_USERNAME_SIZE*2, nls_info);
|
dom_name_len = cifs_strtoUCS(unicode_buf+user_name_len, ucase_buf,
|
||||||
|
MAX_USERNAME_SIZE*2, nls_info);
|
||||||
|
|
||||||
unicode_buf[user_name_len + dom_name_len] = 0;
|
unicode_buf[user_name_len + dom_name_len] = 0;
|
||||||
hmac_md5_update((const unsigned char *) unicode_buf,
|
hmac_md5_update((const unsigned char *) unicode_buf,
|
||||||
(user_name_len+dom_name_len)*2, &ctx);
|
(user_name_len+dom_name_len)*2, &ctx);
|
||||||
|
|
||||||
hmac_md5_final(ses->server->mac_signing_key,&ctx);
|
hmac_md5_final(ses->server->ntlmv2_hash, &ctx);
|
||||||
kfree(ucase_buf);
|
kfree(ucase_buf);
|
||||||
kfree(unicode_buf);
|
kfree(unicode_buf);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -282,7 +293,8 @@ void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key)
|
||||||
|
|
||||||
if ((ses->server->secMode & SECMODE_PW_ENCRYPT) == 0)
|
if ((ses->server->secMode & SECMODE_PW_ENCRYPT) == 0)
|
||||||
if (extended_security & CIFSSEC_MAY_PLNTXT) {
|
if (extended_security & CIFSSEC_MAY_PLNTXT) {
|
||||||
memcpy(lnm_session_key, password_with_pad, CIFS_ENCPWD_SIZE);
|
memcpy(lnm_session_key, password_with_pad,
|
||||||
|
CIFS_ENCPWD_SIZE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -345,7 +357,10 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
|
||||||
if (domain == NULL)
|
if (domain == NULL)
|
||||||
goto calc_exit_1;
|
goto calc_exit_1;
|
||||||
len = cifs_strtoUCS(domain, ses->domainName, len, nls_cp);
|
len = cifs_strtoUCS(domain, ses->domainName, len, nls_cp);
|
||||||
UniStrupr(domain);
|
/* the following line was removed since it didn't work well
|
||||||
|
with lower cased domain name that passed as an option.
|
||||||
|
Maybe converting the domain name earlier makes sense */
|
||||||
|
/* UniStrupr(domain); */
|
||||||
|
|
||||||
hmac_md5_update((char *)domain, 2*len, pctxt);
|
hmac_md5_update((char *)domain, 2*len, pctxt);
|
||||||
|
|
||||||
|
@ -356,7 +371,7 @@ calc_exit_1:
|
||||||
calc_exit_2:
|
calc_exit_2:
|
||||||
/* BB FIXME what about bytes 24 through 40 of the signing key?
|
/* BB FIXME what about bytes 24 through 40 of the signing key?
|
||||||
compare with the NTLM example */
|
compare with the NTLM example */
|
||||||
hmac_md5_final(ses->server->mac_signing_key, pctxt);
|
hmac_md5_final(ses->server->ntlmv2_hash, pctxt);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -366,6 +381,7 @@ void setup_ntlmv2_rsp(struct cifsSesInfo * ses, char * resp_buf,
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
struct ntlmv2_resp *buf = (struct ntlmv2_resp *)resp_buf;
|
struct ntlmv2_resp *buf = (struct ntlmv2_resp *)resp_buf;
|
||||||
|
struct HMACMD5Context context;
|
||||||
|
|
||||||
buf->blob_signature = cpu_to_le32(0x00000101);
|
buf->blob_signature = cpu_to_le32(0x00000101);
|
||||||
buf->reserved = 0;
|
buf->reserved = 0;
|
||||||
|
@ -382,14 +398,24 @@ void setup_ntlmv2_rsp(struct cifsSesInfo * ses, char * resp_buf,
|
||||||
if (rc)
|
if (rc)
|
||||||
cERROR(1, ("could not get v2 hash rc %d", rc));
|
cERROR(1, ("could not get v2 hash rc %d", rc));
|
||||||
CalcNTLMv2_response(ses, resp_buf);
|
CalcNTLMv2_response(ses, resp_buf);
|
||||||
|
|
||||||
|
/* now calculate the MAC key for NTLMv2 */
|
||||||
|
hmac_md5_init_limK_to_64(ses->server->ntlmv2_hash, 16, &context);
|
||||||
|
hmac_md5_update(resp_buf, 16, &context);
|
||||||
|
hmac_md5_final(ses->server->mac_signing_key.data.ntlmv2.key, &context);
|
||||||
|
|
||||||
|
memcpy(&ses->server->mac_signing_key.data.ntlmv2.resp, resp_buf,
|
||||||
|
sizeof(struct ntlmv2_resp));
|
||||||
|
ses->server->mac_signing_key.len = 16 + sizeof(struct ntlmv2_resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CalcNTLMv2_response(const struct cifsSesInfo * ses, char * v2_session_response)
|
void CalcNTLMv2_response(const struct cifsSesInfo *ses,
|
||||||
|
char *v2_session_response)
|
||||||
{
|
{
|
||||||
struct HMACMD5Context context;
|
struct HMACMD5Context context;
|
||||||
/* rest of v2 struct already generated */
|
/* rest of v2 struct already generated */
|
||||||
memcpy(v2_session_response + 8, ses->server->cryptKey, 8);
|
memcpy(v2_session_response + 8, ses->server->cryptKey, 8);
|
||||||
hmac_md5_init_limK_to_64(ses->server->mac_signing_key, 16, &context);
|
hmac_md5_init_limK_to_64(ses->server->ntlmv2_hash, 16, &context);
|
||||||
|
|
||||||
hmac_md5_update(v2_session_response+8,
|
hmac_md5_update(v2_session_response+8,
|
||||||
sizeof(struct ntlmv2_resp) - 8, &context);
|
sizeof(struct ntlmv2_resp) - 8, &context);
|
||||||
|
|
|
@ -71,16 +71,20 @@ static struct task_struct * dnotifyThread = NULL;
|
||||||
static const struct super_operations cifs_super_ops;
|
static const struct super_operations cifs_super_ops;
|
||||||
unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE;
|
unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE;
|
||||||
module_param(CIFSMaxBufSize, int, 0);
|
module_param(CIFSMaxBufSize, int, 0);
|
||||||
MODULE_PARM_DESC(CIFSMaxBufSize,"Network buffer size (not including header). Default: 16384 Range: 8192 to 130048");
|
MODULE_PARM_DESC(CIFSMaxBufSize, "Network buffer size (not including header). "
|
||||||
|
"Default: 16384 Range: 8192 to 130048");
|
||||||
unsigned int cifs_min_rcv = CIFS_MIN_RCV_POOL;
|
unsigned int cifs_min_rcv = CIFS_MIN_RCV_POOL;
|
||||||
module_param(cifs_min_rcv, int, 0);
|
module_param(cifs_min_rcv, int, 0);
|
||||||
MODULE_PARM_DESC(cifs_min_rcv,"Network buffers in pool. Default: 4 Range: 1 to 64");
|
MODULE_PARM_DESC(cifs_min_rcv, "Network buffers in pool. Default: 4 Range: "
|
||||||
|
"1 to 64");
|
||||||
unsigned int cifs_min_small = 30;
|
unsigned int cifs_min_small = 30;
|
||||||
module_param(cifs_min_small, int, 0);
|
module_param(cifs_min_small, int, 0);
|
||||||
MODULE_PARM_DESC(cifs_min_small,"Small network buffers in pool. Default: 30 Range: 2 to 256");
|
MODULE_PARM_DESC(cifs_min_small, "Small network buffers in pool. Default: 30 "
|
||||||
|
"Range: 2 to 256");
|
||||||
unsigned int cifs_max_pending = CIFS_MAX_REQ;
|
unsigned int cifs_max_pending = CIFS_MAX_REQ;
|
||||||
module_param(cifs_max_pending, int, 0);
|
module_param(cifs_max_pending, int, 0);
|
||||||
MODULE_PARM_DESC(cifs_max_pending,"Simultaneous requests to server. Default: 50 Range: 2 to 256");
|
MODULE_PARM_DESC(cifs_max_pending, "Simultaneous requests to server. "
|
||||||
|
"Default: 50 Range: 2 to 256");
|
||||||
|
|
||||||
extern mempool_t *cifs_sm_req_poolp;
|
extern mempool_t *cifs_sm_req_poolp;
|
||||||
extern mempool_t *cifs_req_poolp;
|
extern mempool_t *cifs_req_poolp;
|
||||||
|
@ -114,12 +118,9 @@ cifs_read_super(struct super_block *sb, void *data,
|
||||||
|
|
||||||
sb->s_magic = CIFS_MAGIC_NUMBER;
|
sb->s_magic = CIFS_MAGIC_NUMBER;
|
||||||
sb->s_op = &cifs_super_ops;
|
sb->s_op = &cifs_super_ops;
|
||||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
|
||||||
if (experimEnabled != 0)
|
|
||||||
sb->s_export_op = &cifs_export_ops;
|
|
||||||
#endif /* EXPERIMENTAL */
|
|
||||||
/* if (cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512)
|
/* if (cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512)
|
||||||
sb->s_blocksize = cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; */
|
sb->s_blocksize =
|
||||||
|
cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; */
|
||||||
#ifdef CONFIG_CIFS_QUOTA
|
#ifdef CONFIG_CIFS_QUOTA
|
||||||
sb->s_qcop = &cifs_quotactl_ops;
|
sb->s_qcop = &cifs_quotactl_ops;
|
||||||
#endif
|
#endif
|
||||||
|
@ -139,6 +140,13 @@ cifs_read_super(struct super_block *sb, void *data,
|
||||||
goto out_no_root;
|
goto out_no_root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
||||||
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
|
||||||
|
cFYI(1, ("export ops supported"));
|
||||||
|
sb->s_export_op = &cifs_export_ops;
|
||||||
|
}
|
||||||
|
#endif /* EXPERIMENTAL */
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_no_root:
|
out_no_root:
|
||||||
|
@ -217,8 +225,7 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
|
||||||
bypassed it because we detected that this was an older LANMAN sess */
|
bypassed it because we detected that this was an older LANMAN sess */
|
||||||
if (rc)
|
if (rc)
|
||||||
rc = SMBOldQFSInfo(xid, pTcon, buf);
|
rc = SMBOldQFSInfo(xid, pTcon, buf);
|
||||||
/*
|
/* int f_type;
|
||||||
int f_type;
|
|
||||||
__fsid_t f_fsid;
|
__fsid_t f_fsid;
|
||||||
int f_namelen; */
|
int f_namelen; */
|
||||||
/* BB get from info in tcon struct at mount time call to QFSAttrInfo */
|
/* BB get from info in tcon struct at mount time call to QFSAttrInfo */
|
||||||
|
@ -309,10 +316,10 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)
|
||||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
|
||||||
seq_printf(s, ",posixpaths");
|
seq_printf(s, ",posixpaths");
|
||||||
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) ||
|
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) ||
|
||||||
!(cifs_sb->tcon->ses->capabilities & CAP_UNIX))
|
!(cifs_sb->tcon->unix_ext))
|
||||||
seq_printf(s, ",uid=%d", cifs_sb->mnt_uid);
|
seq_printf(s, ",uid=%d", cifs_sb->mnt_uid);
|
||||||
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) ||
|
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) ||
|
||||||
!(cifs_sb->tcon->ses->capabilities & CAP_UNIX))
|
!(cifs_sb->tcon->unix_ext))
|
||||||
seq_printf(s, ",gid=%d", cifs_sb->mnt_gid);
|
seq_printf(s, ",gid=%d", cifs_sb->mnt_gid);
|
||||||
seq_printf(s, ",rsize=%d", cifs_sb->rsize);
|
seq_printf(s, ",rsize=%d", cifs_sb->rsize);
|
||||||
seq_printf(s, ",wsize=%d", cifs_sb->wsize);
|
seq_printf(s, ",wsize=%d", cifs_sb->wsize);
|
||||||
|
@ -445,8 +452,7 @@ static void cifs_umount_begin(struct vfsmount * vfsmnt, int flags)
|
||||||
|
|
||||||
/* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */
|
/* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */
|
||||||
/* cancel_notify_requests(tcon); */
|
/* cancel_notify_requests(tcon); */
|
||||||
if (tcon->ses && tcon->ses->server)
|
if (tcon->ses && tcon->ses->server) {
|
||||||
{
|
|
||||||
cFYI(1, ("wake up tasks now - umount begin not complete"));
|
cFYI(1, ("wake up tasks now - umount begin not complete"));
|
||||||
wake_up_all(&tcon->ses->server->request_q);
|
wake_up_all(&tcon->ses->server->request_q);
|
||||||
wake_up_all(&tcon->ses->server->response_q);
|
wake_up_all(&tcon->ses->server->response_q);
|
||||||
|
@ -481,9 +487,10 @@ static const struct super_operations cifs_super_ops = {
|
||||||
.alloc_inode = cifs_alloc_inode,
|
.alloc_inode = cifs_alloc_inode,
|
||||||
.destroy_inode = cifs_destroy_inode,
|
.destroy_inode = cifs_destroy_inode,
|
||||||
/* .drop_inode = generic_delete_inode,
|
/* .drop_inode = generic_delete_inode,
|
||||||
.delete_inode = cifs_delete_inode, *//* Do not need the above two functions
|
.delete_inode = cifs_delete_inode, */ /* Do not need above two
|
||||||
unless later we add lazy close of inodes or unless the kernel forgets to call
|
functions unless later we add lazy close of inodes or unless the
|
||||||
us with the same number of releases (closes) as opens */
|
kernel forgets to call us with the same number of releases (closes)
|
||||||
|
as opens */
|
||||||
.show_options = cifs_show_options,
|
.show_options = cifs_show_options,
|
||||||
.umount_begin = cifs_umount_begin,
|
.umount_begin = cifs_umount_begin,
|
||||||
.remount_fs = cifs_remount,
|
.remount_fs = cifs_remount,
|
||||||
|
@ -876,7 +883,8 @@ static int cifs_oplock_thread(void * dummyarg)
|
||||||
/* mutex_lock(&inode->i_mutex);*/
|
/* mutex_lock(&inode->i_mutex);*/
|
||||||
if (S_ISREG(inode->i_mode)) {
|
if (S_ISREG(inode->i_mode)) {
|
||||||
rc = filemap_fdatawrite(inode->i_mapping);
|
rc = filemap_fdatawrite(inode->i_mapping);
|
||||||
if (CIFS_I(inode)->clientCanCacheRead == 0) {
|
if (CIFS_I(inode)->clientCanCacheRead
|
||||||
|
== 0) {
|
||||||
filemap_fdatawait(inode->i_mapping);
|
filemap_fdatawait(inode->i_mapping);
|
||||||
invalidate_remote_inode(inode);
|
invalidate_remote_inode(inode);
|
||||||
}
|
}
|
||||||
|
@ -885,9 +893,10 @@ static int cifs_oplock_thread(void * dummyarg)
|
||||||
/* mutex_unlock(&inode->i_mutex);*/
|
/* mutex_unlock(&inode->i_mutex);*/
|
||||||
if (rc)
|
if (rc)
|
||||||
CIFS_I(inode)->write_behind_rc = rc;
|
CIFS_I(inode)->write_behind_rc = rc;
|
||||||
cFYI(1,("Oplock flush inode %p rc %d",inode,rc));
|
cFYI(1, ("Oplock flush inode %p rc %d",
|
||||||
|
inode, rc));
|
||||||
|
|
||||||
/* releasing a stale oplock after recent reconnection
|
/* releasing stale oplock after recent reconnect
|
||||||
of smb session using a now incorrect file
|
of smb session using a now incorrect file
|
||||||
handle is not a data integrity issue but do
|
handle is not a data integrity issue but do
|
||||||
not bother sending an oplock release if session
|
not bother sending an oplock release if session
|
||||||
|
@ -898,7 +907,8 @@ static int cifs_oplock_thread(void * dummyarg)
|
||||||
0 /* len */ , 0 /* offset */, 0,
|
0 /* len */ , 0 /* offset */, 0,
|
||||||
0, LOCKING_ANDX_OPLOCK_RELEASE,
|
0, LOCKING_ANDX_OPLOCK_RELEASE,
|
||||||
0 /* wait flag */);
|
0 /* wait flag */);
|
||||||
cFYI(1,("Oplock release rc = %d ",rc));
|
cFYI(1,
|
||||||
|
("Oplock release rc = %d ", rc));
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
spin_unlock(&GlobalMid_Lock);
|
spin_unlock(&GlobalMid_Lock);
|
||||||
|
@ -1036,7 +1046,7 @@ init_cifs(void)
|
||||||
static void __exit
|
static void __exit
|
||||||
exit_cifs(void)
|
exit_cifs(void)
|
||||||
{
|
{
|
||||||
cFYI(0, ("In unregister ie exit_cifs"));
|
cFYI(0, ("exit_cifs"));
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
cifs_proc_clean();
|
cifs_proc_clean();
|
||||||
#endif
|
#endif
|
||||||
|
@ -1051,7 +1061,8 @@ exit_cifs(void)
|
||||||
MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>");
|
MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>");
|
||||||
MODULE_LICENSE("GPL"); /* combination of LGPL + GPL source behaves as GPL */
|
MODULE_LICENSE("GPL"); /* combination of LGPL + GPL source behaves as GPL */
|
||||||
MODULE_DESCRIPTION
|
MODULE_DESCRIPTION
|
||||||
("VFS to access servers complying with the SNIA CIFS Specification e.g. Samba and Windows");
|
("VFS to access servers complying with the SNIA CIFS Specification "
|
||||||
|
"e.g. Samba and Windows");
|
||||||
MODULE_VERSION(CIFS_VERSION);
|
MODULE_VERSION(CIFS_VERSION);
|
||||||
module_init(init_cifs)
|
module_init(init_cifs)
|
||||||
module_exit(exit_cifs)
|
module_exit(exit_cifs)
|
||||||
|
|
|
@ -63,9 +63,9 @@ extern const struct inode_operations cifs_symlink_inode_ops;
|
||||||
|
|
||||||
/* Functions related to files and directories */
|
/* Functions related to files and directories */
|
||||||
extern const struct file_operations cifs_file_ops;
|
extern const struct file_operations cifs_file_ops;
|
||||||
extern const struct file_operations cifs_file_direct_ops; /* if directio mount */
|
extern const struct file_operations cifs_file_direct_ops; /* if directio mnt */
|
||||||
extern const struct file_operations cifs_file_nobrl_ops;
|
extern const struct file_operations cifs_file_nobrl_ops;
|
||||||
extern const struct file_operations cifs_file_direct_nobrl_ops; /* if directio mount */
|
extern const struct file_operations cifs_file_direct_nobrl_ops; /* no brlocks */
|
||||||
extern int cifs_open(struct inode *inode, struct file *file);
|
extern int cifs_open(struct inode *inode, struct file *file);
|
||||||
extern int cifs_close(struct inode *inode, struct file *file);
|
extern int cifs_close(struct inode *inode, struct file *file);
|
||||||
extern int cifs_closedir(struct inode *inode, struct file *file);
|
extern int cifs_closedir(struct inode *inode, struct file *file);
|
||||||
|
@ -88,7 +88,8 @@ extern struct dentry_operations cifs_ci_dentry_ops;
|
||||||
|
|
||||||
/* Functions related to symlinks */
|
/* Functions related to symlinks */
|
||||||
extern void *cifs_follow_link(struct dentry *direntry, struct nameidata *nd);
|
extern void *cifs_follow_link(struct dentry *direntry, struct nameidata *nd);
|
||||||
extern void cifs_put_link(struct dentry *direntry, struct nameidata *nd, void *);
|
extern void cifs_put_link(struct dentry *direntry,
|
||||||
|
struct nameidata *nd, void *);
|
||||||
extern int cifs_readlink(struct dentry *direntry, char __user *buffer,
|
extern int cifs_readlink(struct dentry *direntry, char __user *buffer,
|
||||||
int buflen);
|
int buflen);
|
||||||
extern int cifs_symlink(struct inode *inode, struct dentry *direntry,
|
extern int cifs_symlink(struct inode *inode, struct dentry *direntry,
|
||||||
|
@ -100,5 +101,5 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
|
||||||
extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
|
extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
|
||||||
extern int cifs_ioctl (struct inode *inode, struct file *filep,
|
extern int cifs_ioctl (struct inode *inode, struct file *filep,
|
||||||
unsigned int command, unsigned long arg);
|
unsigned int command, unsigned long arg);
|
||||||
#define CIFS_VERSION "1.49"
|
#define CIFS_VERSION "1.50"
|
||||||
#endif /* _CIFSFS_H */
|
#endif /* _CIFSFS_H */
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* fs/cifs/cifsglob.h
|
* fs/cifs/cifsglob.h
|
||||||
*
|
*
|
||||||
* Copyright (C) International Business Machines Corp., 2002,2006
|
* Copyright (C) International Business Machines Corp., 2002,2007
|
||||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||||
* Jeremy Allison (jra@samba.org)
|
* Jeremy Allison (jra@samba.org)
|
||||||
*
|
*
|
||||||
|
@ -28,7 +28,7 @@
|
||||||
|
|
||||||
#define MAX_TREE_SIZE 2 + MAX_SERVER_SIZE + 1 + MAX_SHARE_SIZE + 1
|
#define MAX_TREE_SIZE 2 + MAX_SERVER_SIZE + 1 + MAX_SHARE_SIZE + 1
|
||||||
#define MAX_SERVER_SIZE 15
|
#define MAX_SERVER_SIZE 15
|
||||||
#define MAX_SHARE_SIZE 64 /* used to be 20 - this should still be enough */
|
#define MAX_SHARE_SIZE 64 /* used to be 20, this should still be enough */
|
||||||
#define MAX_USERNAME_SIZE 32 /* 32 is to allow for 15 char names + null
|
#define MAX_USERNAME_SIZE 32 /* 32 is to allow for 15 char names + null
|
||||||
termination then *2 for unicode versions */
|
termination then *2 for unicode versions */
|
||||||
#define MAX_PASSWORD_SIZE 16
|
#define MAX_PASSWORD_SIZE 16
|
||||||
|
@ -104,6 +104,17 @@ enum protocolEnum {
|
||||||
/* Netbios frames protocol not supported at this time */
|
/* Netbios frames protocol not supported at this time */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct mac_key {
|
||||||
|
unsigned int len;
|
||||||
|
union {
|
||||||
|
char ntlm[CIFS_SESS_KEY_SIZE + 16];
|
||||||
|
struct {
|
||||||
|
char key[16];
|
||||||
|
struct ntlmv2_resp resp;
|
||||||
|
} ntlmv2;
|
||||||
|
} data;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*****************************************************************
|
*****************************************************************
|
||||||
* Except the CIFS PDUs themselves all the
|
* Except the CIFS PDUs themselves all the
|
||||||
|
@ -159,7 +170,8 @@ struct TCP_Server_Info {
|
||||||
/* 16th byte of RFC1001 workstation name is always null */
|
/* 16th byte of RFC1001 workstation name is always null */
|
||||||
char workstation_RFC1001_name[SERVER_NAME_LEN_WITH_NULL];
|
char workstation_RFC1001_name[SERVER_NAME_LEN_WITH_NULL];
|
||||||
__u32 sequence_number; /* needed for CIFS PDU signature */
|
__u32 sequence_number; /* needed for CIFS PDU signature */
|
||||||
char mac_signing_key[CIFS_SESS_KEY_SIZE + 16];
|
struct mac_key mac_signing_key;
|
||||||
|
char ntlmv2_hash[16];
|
||||||
unsigned long lstrp; /* when we got last response from this server */
|
unsigned long lstrp; /* when we got last response from this server */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -269,7 +281,9 @@ struct cifsTconInfo {
|
||||||
FILE_SYSTEM_UNIX_INFO fsUnixInfo;
|
FILE_SYSTEM_UNIX_INFO fsUnixInfo;
|
||||||
unsigned retry:1;
|
unsigned retry:1;
|
||||||
unsigned nocase:1;
|
unsigned nocase:1;
|
||||||
/* BB add field for back pointer to sb struct? */
|
unsigned unix_ext:1; /* if off disable Linux extensions to CIFS protocol
|
||||||
|
for this mount even if server would support */
|
||||||
|
/* BB add field for back pointer to sb struct(s)? */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -327,7 +341,7 @@ struct cifsFileInfo {
|
||||||
|
|
||||||
struct cifsInodeInfo {
|
struct cifsInodeInfo {
|
||||||
struct list_head lockList;
|
struct list_head lockList;
|
||||||
/* BB add in lists for dirty pages - i.e. write caching info for oplock */
|
/* BB add in lists for dirty pages i.e. write caching info for oplock */
|
||||||
struct list_head openFileList;
|
struct list_head openFileList;
|
||||||
int write_behind_rc;
|
int write_behind_rc;
|
||||||
__u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */
|
__u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */
|
||||||
|
|
|
@ -366,17 +366,19 @@ struct smb_hdr {
|
||||||
#define pByteArea(smb_var) ((unsigned char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) + 2 )
|
#define pByteArea(smb_var) ((unsigned char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) + 2 )
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Computer Name Length
|
* Computer Name Length (since Netbios name was length 16 with last byte 0x20)
|
||||||
|
* No longer as important, now that TCP names are more commonly used to
|
||||||
|
* resolve hosts.
|
||||||
*/
|
*/
|
||||||
#define CNLEN 15
|
#define CNLEN 15
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Share Name Length @S8A
|
* Share Name Length (SNLEN)
|
||||||
* Note: This length is limited by the SMB used to get @S8A
|
* Note: This length was limited by the SMB used to get
|
||||||
* the Share info. NetShareEnum only returns 13 @S8A
|
* the Share info. NetShareEnum only returned 13
|
||||||
* chars, including the null termination. @S8A
|
* chars, including the null termination.
|
||||||
|
* This was removed because it no longer is limiting.
|
||||||
*/
|
*/
|
||||||
#define SNLEN 12 /*@S8A */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Comment Length
|
* Comment Length
|
||||||
|
@ -712,6 +714,7 @@ typedef struct smb_com_findclose_req {
|
||||||
#define REQ_OPLOCK 0x00000002
|
#define REQ_OPLOCK 0x00000002
|
||||||
#define REQ_BATCHOPLOCK 0x00000004
|
#define REQ_BATCHOPLOCK 0x00000004
|
||||||
#define REQ_OPENDIRONLY 0x00000008
|
#define REQ_OPENDIRONLY 0x00000008
|
||||||
|
#define REQ_EXTENDED_INFO 0x00000010
|
||||||
|
|
||||||
typedef struct smb_com_open_req { /* also handles create */
|
typedef struct smb_com_open_req { /* also handles create */
|
||||||
struct smb_hdr hdr; /* wct = 24 */
|
struct smb_hdr hdr; /* wct = 24 */
|
||||||
|
@ -818,7 +821,8 @@ typedef struct smb_com_writex_req {
|
||||||
__le16 DataLengthLow;
|
__le16 DataLengthLow;
|
||||||
__le16 DataOffset;
|
__le16 DataOffset;
|
||||||
__le16 ByteCount;
|
__le16 ByteCount;
|
||||||
__u8 Pad; /* BB check for whether padded to DWORD boundary and optimum performance here */
|
__u8 Pad; /* BB check for whether padded to DWORD
|
||||||
|
boundary and optimum performance here */
|
||||||
char Data[0];
|
char Data[0];
|
||||||
} __attribute__((packed)) WRITEX_REQ;
|
} __attribute__((packed)) WRITEX_REQ;
|
||||||
|
|
||||||
|
@ -837,7 +841,8 @@ typedef struct smb_com_write_req {
|
||||||
__le16 DataOffset;
|
__le16 DataOffset;
|
||||||
__le32 OffsetHigh;
|
__le32 OffsetHigh;
|
||||||
__le16 ByteCount;
|
__le16 ByteCount;
|
||||||
__u8 Pad; /* BB check for whether padded to DWORD boundary and optimum performance here */
|
__u8 Pad; /* BB check for whether padded to DWORD
|
||||||
|
boundary and optimum performance here */
|
||||||
char Data[0];
|
char Data[0];
|
||||||
} __attribute__((packed)) WRITE_REQ;
|
} __attribute__((packed)) WRITE_REQ;
|
||||||
|
|
||||||
|
@ -896,7 +901,8 @@ typedef struct smb_com_read_rsp {
|
||||||
__le16 DataLengthHigh;
|
__le16 DataLengthHigh;
|
||||||
__u64 Reserved2;
|
__u64 Reserved2;
|
||||||
__u16 ByteCount;
|
__u16 ByteCount;
|
||||||
__u8 Pad; /* BB check for whether padded to DWORD boundary and optimum performance here */
|
__u8 Pad; /* BB check for whether padded to DWORD
|
||||||
|
boundary and optimum performance here */
|
||||||
char Data[1];
|
char Data[1];
|
||||||
} __attribute__((packed)) READ_RSP;
|
} __attribute__((packed)) READ_RSP;
|
||||||
|
|
||||||
|
@ -1743,7 +1749,9 @@ typedef struct smb_com_transaction2_get_dfs_refer_req {
|
||||||
__u8 Reserved3;
|
__u8 Reserved3;
|
||||||
__le16 SubCommand; /* one setup word */
|
__le16 SubCommand; /* one setup word */
|
||||||
__le16 ByteCount;
|
__le16 ByteCount;
|
||||||
__u8 Pad[3]; /* Win2K has sent 0x0F01 (max resp length perhaps?) followed by one byte pad - doesn't seem to matter though */
|
__u8 Pad[3]; /* Win2K has sent 0x0F01 (max response length
|
||||||
|
perhaps?) followed by one byte pad - doesn't
|
||||||
|
seem to matter though */
|
||||||
__le16 MaxReferralLevel;
|
__le16 MaxReferralLevel;
|
||||||
char RequestFileName[1];
|
char RequestFileName[1];
|
||||||
} __attribute__((packed)) TRANSACTION2_GET_DFS_REFER_REQ;
|
} __attribute__((packed)) TRANSACTION2_GET_DFS_REFER_REQ;
|
||||||
|
@ -1752,7 +1760,10 @@ typedef struct dfs_referral_level_3 {
|
||||||
__le16 VersionNumber;
|
__le16 VersionNumber;
|
||||||
__le16 ReferralSize;
|
__le16 ReferralSize;
|
||||||
__le16 ServerType; /* 0x0001 = CIFS server */
|
__le16 ServerType; /* 0x0001 = CIFS server */
|
||||||
__le16 ReferralFlags; /* or proximity - not clear which since always set to zero - SNIA spec says 0x01 means strip off PathConsumed chars before submitting RequestFileName to remote node */
|
__le16 ReferralFlags; /* or proximity - not clear which since it is
|
||||||
|
always set to zero - SNIA spec says 0x01
|
||||||
|
means strip off PathConsumed chars before
|
||||||
|
submitting RequestFileName to remote node */
|
||||||
__le16 TimeToLive;
|
__le16 TimeToLive;
|
||||||
__le16 Proximity;
|
__le16 Proximity;
|
||||||
__le16 DfsPathOffset;
|
__le16 DfsPathOffset;
|
||||||
|
@ -1778,11 +1789,13 @@ typedef struct smb_com_transaction_get_dfs_refer_rsp {
|
||||||
#define DFSREF_STORAGE_SERVER 0x0002
|
#define DFSREF_STORAGE_SERVER 0x0002
|
||||||
|
|
||||||
/* IOCTL information */
|
/* IOCTL information */
|
||||||
/* List of ioctl function codes that look to be of interest to remote clients like this. */
|
/*
|
||||||
/* Need to do some experimentation to make sure they all work remotely. */
|
* List of ioctl function codes that look to be of interest to remote clients
|
||||||
/* Some of the following such as the encryption/compression ones would be */
|
* like this one. Need to do some experimentation to make sure they all work
|
||||||
/* invoked from tools via a specialized hook into the VFS rather than via the */
|
* remotely. Some of the following, such as the encryption/compression ones
|
||||||
/* standard vfs entry points */
|
* would be invoked from tools via a specialized hook into the VFS rather
|
||||||
|
* than via the standard vfs entry points
|
||||||
|
*/
|
||||||
#define FSCTL_REQUEST_OPLOCK_LEVEL_1 0x00090000
|
#define FSCTL_REQUEST_OPLOCK_LEVEL_1 0x00090000
|
||||||
#define FSCTL_REQUEST_OPLOCK_LEVEL_2 0x00090004
|
#define FSCTL_REQUEST_OPLOCK_LEVEL_2 0x00090004
|
||||||
#define FSCTL_REQUEST_BATCH_OPLOCK 0x00090008
|
#define FSCTL_REQUEST_BATCH_OPLOCK 0x00090008
|
||||||
|
@ -1871,7 +1884,7 @@ typedef struct {
|
||||||
__le16 MajorVersionNumber;
|
__le16 MajorVersionNumber;
|
||||||
__le16 MinorVersionNumber;
|
__le16 MinorVersionNumber;
|
||||||
__le64 Capability;
|
__le64 Capability;
|
||||||
} __attribute__((packed)) FILE_SYSTEM_UNIX_INFO; /* Unix extensions info, level 0x200 */
|
} __attribute__((packed)) FILE_SYSTEM_UNIX_INFO; /* Unix extension level 0x200*/
|
||||||
|
|
||||||
/* Version numbers for CIFS UNIX major and minor. */
|
/* Version numbers for CIFS UNIX major and minor. */
|
||||||
#define CIFS_UNIX_MAJOR_VERSION 1
|
#define CIFS_UNIX_MAJOR_VERSION 1
|
||||||
|
@ -1886,14 +1899,18 @@ typedef struct {
|
||||||
#define CIFS_UNIX_POSIX_PATH_OPS_CAP 0x00000020 /* Allow new POSIX path based
|
#define CIFS_UNIX_POSIX_PATH_OPS_CAP 0x00000020 /* Allow new POSIX path based
|
||||||
calls including posix open
|
calls including posix open
|
||||||
and posix unlink */
|
and posix unlink */
|
||||||
|
#define CIFS_UNIX_LARGE_READ_CAP 0x00000040 /* support reads >128K (up
|
||||||
|
to 0xFFFF00 */
|
||||||
|
#define CIFS_UNIX_LARGE_WRITE_CAP 0x00000080
|
||||||
|
|
||||||
#ifdef CONFIG_CIFS_POSIX
|
#ifdef CONFIG_CIFS_POSIX
|
||||||
/* Can not set pathnames cap yet until we send new posix create SMB since
|
/* Can not set pathnames cap yet until we send new posix create SMB since
|
||||||
otherwise server can treat such handles opened with older ntcreatex
|
otherwise server can treat such handles opened with older ntcreatex
|
||||||
(by a new client which knows how to send posix path ops)
|
(by a new client which knows how to send posix path ops)
|
||||||
as non-posix handles (can affect write behavior with byte range locks.
|
as non-posix handles (can affect write behavior with byte range locks.
|
||||||
We can add back in POSIX_PATH_OPS cap when Posix Create/Mkdir finished */
|
We can add back in POSIX_PATH_OPS cap when Posix Create/Mkdir finished */
|
||||||
/* #define CIFS_UNIX_CAP_MASK 0x0000003b */
|
/* #define CIFS_UNIX_CAP_MASK 0x000000fb */
|
||||||
#define CIFS_UNIX_CAP_MASK 0x0000001b
|
#define CIFS_UNIX_CAP_MASK 0x000000db
|
||||||
#else
|
#else
|
||||||
#define CIFS_UNIX_CAP_MASK 0x00000013
|
#define CIFS_UNIX_CAP_MASK 0x00000013
|
||||||
#endif /* CONFIG_CIFS_POSIX */
|
#endif /* CONFIG_CIFS_POSIX */
|
||||||
|
@ -2138,6 +2155,12 @@ typedef struct {
|
||||||
/* struct following varies based on requested level */
|
/* struct following varies based on requested level */
|
||||||
} __attribute__((packed)) OPEN_PSX_RSP; /* level 0x209 SetPathInfo data */
|
} __attribute__((packed)) OPEN_PSX_RSP; /* level 0x209 SetPathInfo data */
|
||||||
|
|
||||||
|
#define SMB_POSIX_UNLINK_FILE_TARGET 0
|
||||||
|
#define SMB_POSIX_UNLINK_DIRECTORY_TARGET 1
|
||||||
|
|
||||||
|
struct unlink_psx_rq { /* level 0x20a SetPathInfo */
|
||||||
|
__le16 type;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
struct file_internal_info {
|
struct file_internal_info {
|
||||||
__u64 UniqueId; /* inode number */
|
__u64 UniqueId; /* inode number */
|
||||||
|
@ -2357,8 +2380,10 @@ struct data_blob {
|
||||||
T2 SET_PATH_INFO (SMB_SET_FILE_UNIX_LINK) for symlinks
|
T2 SET_PATH_INFO (SMB_SET_FILE_UNIX_LINK) for symlinks
|
||||||
T2 SET_PATH_INFO (SMB_SET_FILE_BASIC_INFO2)
|
T2 SET_PATH_INFO (SMB_SET_FILE_BASIC_INFO2)
|
||||||
T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_LINK)
|
T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_LINK)
|
||||||
T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_BASIC) - BB check for missing inode fields
|
T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_BASIC) BB check for missing
|
||||||
Actually need QUERY_FILE_UNIX_INFO since has inode num
|
inode fields
|
||||||
|
Actually a need QUERY_FILE_UNIX_INFO
|
||||||
|
since has inode num
|
||||||
BB what about a) blksize/blkbits/blocks
|
BB what about a) blksize/blkbits/blocks
|
||||||
b) i_version
|
b) i_version
|
||||||
c) i_rdev
|
c) i_rdev
|
||||||
|
@ -2368,8 +2393,6 @@ struct data_blob {
|
||||||
T2 FIND_FIRST/FIND_NEXT FIND_FILE_UNIX
|
T2 FIND_FIRST/FIND_NEXT FIND_FILE_UNIX
|
||||||
TRANS2_GET_DFS_REFERRAL - OPTIONAL but recommended
|
TRANS2_GET_DFS_REFERRAL - OPTIONAL but recommended
|
||||||
T2_QFS_INFO QueryDevice/AttributeInfo - OPTIONAL
|
T2_QFS_INFO QueryDevice/AttributeInfo - OPTIONAL
|
||||||
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* xsymlink is a symlink format (used by MacOS) that can be used
|
/* xsymlink is a symlink format (used by MacOS) that can be used
|
||||||
|
@ -2405,7 +2428,8 @@ typedef struct file_xattr_info {
|
||||||
__u32 xattr_value_len;
|
__u32 xattr_value_len;
|
||||||
char xattr_name[0];
|
char xattr_name[0];
|
||||||
/* followed by xattr_value[xattr_value_len], no pad */
|
/* followed by xattr_value[xattr_value_len], no pad */
|
||||||
} __attribute__((packed)) FILE_XATTR_INFO; /* extended attribute, info level 0x205 */
|
} __attribute__((packed)) FILE_XATTR_INFO; /* extended attribute info
|
||||||
|
level 0x205 */
|
||||||
|
|
||||||
|
|
||||||
/* flags for chattr command */
|
/* flags for chattr command */
|
||||||
|
@ -2431,7 +2455,8 @@ typedef struct file_xattr_info {
|
||||||
typedef struct file_chattr_info {
|
typedef struct file_chattr_info {
|
||||||
__le64 mask; /* list of all possible attribute bits */
|
__le64 mask; /* list of all possible attribute bits */
|
||||||
__le64 mode; /* list of actual attribute bits on this inode */
|
__le64 mode; /* list of actual attribute bits on this inode */
|
||||||
} __attribute__((packed)) FILE_CHATTR_INFO; /* ext attributes (chattr, chflags) level 0x206 */
|
} __attribute__((packed)) FILE_CHATTR_INFO; /* ext attributes
|
||||||
|
(chattr, chflags) level 0x206 */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -196,7 +196,10 @@ extern int CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
|
||||||
extern int CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
|
extern int CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
|
||||||
const char *name, const struct nls_table *nls_codepage,
|
const char *name, const struct nls_table *nls_codepage,
|
||||||
int remap_special_chars);
|
int remap_special_chars);
|
||||||
|
extern int CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon,
|
||||||
|
const char *name, __u16 type,
|
||||||
|
const struct nls_table *nls_codepage,
|
||||||
|
int remap_special_chars);
|
||||||
extern int CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon,
|
extern int CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon,
|
||||||
const char *name,
|
const char *name,
|
||||||
const struct nls_table *nls_codepage,
|
const struct nls_table *nls_codepage,
|
||||||
|
@ -294,9 +297,11 @@ extern void tconInfoFree(struct cifsTconInfo *);
|
||||||
extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *, __u32 *);
|
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 *,
|
extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *,
|
||||||
__u32 *);
|
__u32 *);
|
||||||
extern int cifs_verify_signature(struct smb_hdr *, const char * mac_key,
|
extern int cifs_verify_signature(struct smb_hdr *,
|
||||||
|
const struct mac_key *mac_key,
|
||||||
__u32 expected_sequence_number);
|
__u32 expected_sequence_number);
|
||||||
extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass);
|
extern int cifs_calculate_mac_key(struct mac_key *key, const char *rn,
|
||||||
|
const char *pass);
|
||||||
extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *,
|
extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *,
|
||||||
const struct nls_table *);
|
const struct nls_table *);
|
||||||
extern void CalcNTLMv2_response(const struct cifsSesInfo *, char * );
|
extern void CalcNTLMv2_response(const struct cifsSesInfo *, char * );
|
||||||
|
|
|
@ -132,21 +132,24 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
|
||||||
/* Give Demultiplex thread up to 10 seconds to
|
/* Give Demultiplex thread up to 10 seconds to
|
||||||
reconnect, should be greater than cifs socket
|
reconnect, should be greater than cifs socket
|
||||||
timeout which is 7 seconds */
|
timeout which is 7 seconds */
|
||||||
while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
|
while (tcon->ses->server->tcpStatus ==
|
||||||
|
CifsNeedReconnect) {
|
||||||
wait_event_interruptible_timeout(tcon->ses->server->response_q,
|
wait_event_interruptible_timeout(tcon->ses->server->response_q,
|
||||||
(tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
|
(tcon->ses->server->tcpStatus ==
|
||||||
if(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
|
CifsGood), 10 * HZ);
|
||||||
|
if (tcon->ses->server->tcpStatus ==
|
||||||
|
CifsNeedReconnect) {
|
||||||
/* on "soft" mounts we wait once */
|
/* on "soft" mounts we wait once */
|
||||||
if ((tcon->retry == FALSE) ||
|
if ((tcon->retry == FALSE) ||
|
||||||
(tcon->ses->status == CifsExiting)) {
|
(tcon->ses->status == CifsExiting)) {
|
||||||
cFYI(1,("gave up waiting on reconnect in smb_init"));
|
cFYI(1, ("gave up waiting on "
|
||||||
|
"reconnect in smb_init"));
|
||||||
return -EHOSTDOWN;
|
return -EHOSTDOWN;
|
||||||
} /* else "hard" mount - keep retrying
|
} /* else "hard" mount - keep retrying
|
||||||
until process is killed or server
|
until process is killed or server
|
||||||
comes back on-line */
|
comes back on-line */
|
||||||
} else /* TCP session is reestablished now */
|
} else /* TCP session is reestablished now */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nls_codepage = load_nls_default();
|
nls_codepage = load_nls_default();
|
||||||
|
@ -174,8 +177,8 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
|
||||||
atomic_inc(&tconInfoReconnectCount);
|
atomic_inc(&tconInfoReconnectCount);
|
||||||
|
|
||||||
cFYI(1, ("reconnect tcon rc = %d", rc));
|
cFYI(1, ("reconnect tcon rc = %d", rc));
|
||||||
/* Removed call to reopen open files here -
|
/* Removed call to reopen open files here.
|
||||||
it is safer (and faster) to reopen files
|
It is safer (and faster) to reopen files
|
||||||
one at a time as needed in read and write */
|
one at a time as needed in read and write */
|
||||||
|
|
||||||
/* Check if handle based operation so we
|
/* Check if handle based operation so we
|
||||||
|
@ -209,7 +212,8 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,wct);
|
header_assemble((struct smb_hdr *) *request_buf, smb_command,
|
||||||
|
tcon, wct);
|
||||||
|
|
||||||
if (tcon != NULL)
|
if (tcon != NULL)
|
||||||
cifs_stats_inc(&tcon->num_smbs_sent);
|
cifs_stats_inc(&tcon->num_smbs_sent);
|
||||||
|
@ -274,24 +278,25 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
|
||||||
/* Give Demultiplex thread up to 10 seconds to
|
/* Give Demultiplex thread up to 10 seconds to
|
||||||
reconnect, should be greater than cifs socket
|
reconnect, should be greater than cifs socket
|
||||||
timeout which is 7 seconds */
|
timeout which is 7 seconds */
|
||||||
while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
|
while (tcon->ses->server->tcpStatus ==
|
||||||
|
CifsNeedReconnect) {
|
||||||
wait_event_interruptible_timeout(tcon->ses->server->response_q,
|
wait_event_interruptible_timeout(tcon->ses->server->response_q,
|
||||||
(tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
|
(tcon->ses->server->tcpStatus ==
|
||||||
|
CifsGood), 10 * HZ);
|
||||||
if (tcon->ses->server->tcpStatus ==
|
if (tcon->ses->server->tcpStatus ==
|
||||||
CifsNeedReconnect) {
|
CifsNeedReconnect) {
|
||||||
/* on "soft" mounts we wait once */
|
/* on "soft" mounts we wait once */
|
||||||
if ((tcon->retry == FALSE) ||
|
if ((tcon->retry == FALSE) ||
|
||||||
(tcon->ses->status == CifsExiting)) {
|
(tcon->ses->status == CifsExiting)) {
|
||||||
cFYI(1,("gave up waiting on reconnect in smb_init"));
|
cFYI(1, ("gave up waiting on "
|
||||||
|
"reconnect in smb_init"));
|
||||||
return -EHOSTDOWN;
|
return -EHOSTDOWN;
|
||||||
} /* else "hard" mount - keep retrying
|
} /* else "hard" mount - keep retrying
|
||||||
until process is killed or server
|
until process is killed or server
|
||||||
comes on-line */
|
comes on-line */
|
||||||
} else /* TCP session is reestablished now */
|
} else /* TCP session is reestablished now */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nls_codepage = load_nls_default();
|
nls_codepage = load_nls_default();
|
||||||
/* need to prevent multiple threads trying to
|
/* need to prevent multiple threads trying to
|
||||||
simultaneously reconnect the same SMB session */
|
simultaneously reconnect the same SMB session */
|
||||||
|
@ -317,8 +322,8 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
|
||||||
atomic_inc(&tconInfoReconnectCount);
|
atomic_inc(&tconInfoReconnectCount);
|
||||||
|
|
||||||
cFYI(1, ("reconnect tcon rc = %d", rc));
|
cFYI(1, ("reconnect tcon rc = %d", rc));
|
||||||
/* Removed call to reopen open files here -
|
/* Removed call to reopen open files here.
|
||||||
it is safer (and faster) to reopen files
|
It is safer (and faster) to reopen files
|
||||||
one at a time as needed in read and write */
|
one at a time as needed in read and write */
|
||||||
|
|
||||||
/* Check if handle based operation so we
|
/* Check if handle based operation so we
|
||||||
|
@ -382,7 +387,8 @@ static int validate_t2(struct smb_t2_rsp * pSMB)
|
||||||
/* check that bcc is less than negotiated smb buffer */
|
/* check that bcc is less than negotiated smb buffer */
|
||||||
total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
|
total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
|
||||||
if (total_size < 512) {
|
if (total_size < 512) {
|
||||||
total_size+=le16_to_cpu(pSMB->t2_rsp.DataCount);
|
total_size +=
|
||||||
|
le16_to_cpu(pSMB->t2_rsp.DataCount);
|
||||||
/* BCC le converted in SendReceive */
|
/* BCC le converted in SendReceive */
|
||||||
pBCC = (pSMB->hdr.WordCount * 2) +
|
pBCC = (pSMB->hdr.WordCount * 2) +
|
||||||
sizeof(struct smb_hdr) +
|
sizeof(struct smb_hdr) +
|
||||||
|
@ -392,7 +398,6 @@ static int validate_t2(struct smb_t2_rsp * pSMB)
|
||||||
CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
|
CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -426,7 +431,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
|
||||||
|
|
||||||
/* if any of auth flags (ie not sign or seal) are overriden use them */
|
/* if any of auth flags (ie not sign or seal) are overriden use them */
|
||||||
if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
|
if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
|
||||||
secFlags = ses->overrideSecFlg;
|
secFlags = ses->overrideSecFlg; /* BB FIXME fix sign flags? */
|
||||||
else /* if override flags set only sign/seal OR them with global auth */
|
else /* if override flags set only sign/seal OR them with global auth */
|
||||||
secFlags = extended_security | ses->overrideSecFlg;
|
secFlags = extended_security | ses->overrideSecFlg;
|
||||||
|
|
||||||
|
@ -504,7 +509,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
|
||||||
utc = CURRENT_TIME;
|
utc = CURRENT_TIME;
|
||||||
ts = cnvrtDosUnixTm(le16_to_cpu(rsp->SrvTime.Date),
|
ts = cnvrtDosUnixTm(le16_to_cpu(rsp->SrvTime.Date),
|
||||||
le16_to_cpu(rsp->SrvTime.Time));
|
le16_to_cpu(rsp->SrvTime.Time));
|
||||||
cFYI(1,("SrvTime: %d sec since 1970 (utc: %d) diff: %d",
|
cFYI(1, ("SrvTime %d sec since 1970 (utc: %d) diff: %d",
|
||||||
(int)ts.tv_sec, (int)utc.tv_sec,
|
(int)ts.tv_sec, (int)utc.tv_sec,
|
||||||
(int)(utc.tv_sec - ts.tv_sec)));
|
(int)(utc.tv_sec - ts.tv_sec)));
|
||||||
val = (int)(utc.tv_sec - ts.tv_sec);
|
val = (int)(utc.tv_sec - ts.tv_sec);
|
||||||
|
@ -633,22 +638,33 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
|
||||||
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
||||||
signing_check:
|
signing_check:
|
||||||
#endif
|
#endif
|
||||||
if(sign_CIFS_PDUs == FALSE) {
|
if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
|
||||||
|
/* MUST_SIGN already includes the MAY_SIGN FLAG
|
||||||
|
so if this is zero it means that signing is disabled */
|
||||||
|
cFYI(1, ("Signing disabled"));
|
||||||
if (server->secMode & SECMODE_SIGN_REQUIRED)
|
if (server->secMode & SECMODE_SIGN_REQUIRED)
|
||||||
cERROR(1, ("Server requires "
|
cERROR(1, ("Server requires "
|
||||||
"/proc/fs/cifs/PacketSigningEnabled to be on"));
|
"/proc/fs/cifs/PacketSigningEnabled "
|
||||||
|
"to be on"));
|
||||||
server->secMode &=
|
server->secMode &=
|
||||||
~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
|
~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
|
||||||
} else if(sign_CIFS_PDUs == 1) {
|
} else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
|
||||||
|
/* signing required */
|
||||||
|
cFYI(1, ("Must sign - secFlags 0x%x", secFlags));
|
||||||
|
if ((server->secMode &
|
||||||
|
(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
|
||||||
|
cERROR(1,
|
||||||
|
("signing required but server lacks support"));
|
||||||
|
rc = -EOPNOTSUPP;
|
||||||
|
} else
|
||||||
|
server->secMode |= SECMODE_SIGN_REQUIRED;
|
||||||
|
} else {
|
||||||
|
/* signing optional ie CIFSSEC_MAY_SIGN */
|
||||||
if ((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
|
if ((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
|
||||||
server->secMode &=
|
server->secMode &=
|
||||||
~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
|
~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
|
||||||
} else if(sign_CIFS_PDUs == 2) {
|
|
||||||
if((server->secMode &
|
|
||||||
(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
|
|
||||||
cERROR(1,("signing required but server lacks support"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
neg_err_exit:
|
neg_err_exit:
|
||||||
cifs_buf_release(pSMB);
|
cifs_buf_release(pSMB);
|
||||||
|
|
||||||
|
@ -779,6 +795,82 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
|
||||||
|
__u16 type, const struct nls_table *nls_codepage, int remap)
|
||||||
|
{
|
||||||
|
TRANSACTION2_SPI_REQ *pSMB = NULL;
|
||||||
|
TRANSACTION2_SPI_RSP *pSMBr = NULL;
|
||||||
|
struct unlink_psx_rq *pRqD;
|
||||||
|
int name_len;
|
||||||
|
int rc = 0;
|
||||||
|
int bytes_returned = 0;
|
||||||
|
__u16 params, param_offset, offset, byte_count;
|
||||||
|
|
||||||
|
cFYI(1, ("In POSIX delete"));
|
||||||
|
PsxDelete:
|
||||||
|
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
|
||||||
|
(void **) &pSMBr);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||||
|
name_len =
|
||||||
|
cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
|
||||||
|
PATH_MAX, nls_codepage, remap);
|
||||||
|
name_len++; /* trailing null */
|
||||||
|
name_len *= 2;
|
||||||
|
} else { /* BB add path length overrun check */
|
||||||
|
name_len = strnlen(fileName, PATH_MAX);
|
||||||
|
name_len++; /* trailing null */
|
||||||
|
strncpy(pSMB->FileName, fileName, name_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
params = 6 + name_len;
|
||||||
|
pSMB->MaxParameterCount = cpu_to_le16(2);
|
||||||
|
pSMB->MaxDataCount = 0; /* BB double check this with jra */
|
||||||
|
pSMB->MaxSetupCount = 0;
|
||||||
|
pSMB->Reserved = 0;
|
||||||
|
pSMB->Flags = 0;
|
||||||
|
pSMB->Timeout = 0;
|
||||||
|
pSMB->Reserved2 = 0;
|
||||||
|
param_offset = offsetof(struct smb_com_transaction2_spi_req,
|
||||||
|
InformationLevel) - 4;
|
||||||
|
offset = param_offset + params;
|
||||||
|
|
||||||
|
/* Setup pointer to Request Data (inode type) */
|
||||||
|
pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
|
||||||
|
pRqD->type = cpu_to_le16(type);
|
||||||
|
pSMB->ParameterOffset = cpu_to_le16(param_offset);
|
||||||
|
pSMB->DataOffset = cpu_to_le16(offset);
|
||||||
|
pSMB->SetupCount = 1;
|
||||||
|
pSMB->Reserved3 = 0;
|
||||||
|
pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
|
||||||
|
byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
|
||||||
|
|
||||||
|
pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
|
||||||
|
pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
|
||||||
|
pSMB->ParameterCount = cpu_to_le16(params);
|
||||||
|
pSMB->TotalParameterCount = pSMB->ParameterCount;
|
||||||
|
pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
|
||||||
|
pSMB->Reserved4 = 0;
|
||||||
|
pSMB->hdr.smb_buf_length += byte_count;
|
||||||
|
pSMB->ByteCount = cpu_to_le16(byte_count);
|
||||||
|
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
|
||||||
|
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
|
||||||
|
if (rc) {
|
||||||
|
cFYI(1, ("Posix delete returned %d", rc));
|
||||||
|
}
|
||||||
|
cifs_buf_release(pSMB);
|
||||||
|
|
||||||
|
cifs_stats_inc(&tcon->num_deletes);
|
||||||
|
|
||||||
|
if (rc == -EAGAIN)
|
||||||
|
goto PsxDelete;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
|
CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
|
||||||
const struct nls_table *nls_codepage, int remap)
|
const struct nls_table *nls_codepage, int remap)
|
||||||
|
@ -924,7 +1016,6 @@ CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
|
||||||
int name_len;
|
int name_len;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
int bytes_returned = 0;
|
int bytes_returned = 0;
|
||||||
char *data_offset;
|
|
||||||
__u16 params, param_offset, offset, byte_count, count;
|
__u16 params, param_offset, offset, byte_count, count;
|
||||||
OPEN_PSX_REQ * pdata;
|
OPEN_PSX_REQ * pdata;
|
||||||
OPEN_PSX_RSP * psx_rsp;
|
OPEN_PSX_RSP * psx_rsp;
|
||||||
|
@ -960,7 +1051,6 @@ PsxCreat:
|
||||||
param_offset = offsetof(struct smb_com_transaction2_spi_req,
|
param_offset = offsetof(struct smb_com_transaction2_spi_req,
|
||||||
InformationLevel) - 4;
|
InformationLevel) - 4;
|
||||||
offset = param_offset + params;
|
offset = param_offset + params;
|
||||||
data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
|
|
||||||
pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
|
pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
|
||||||
pdata->Level = SMB_QUERY_FILE_UNIX_BASIC;
|
pdata->Level = SMB_QUERY_FILE_UNIX_BASIC;
|
||||||
pdata->Permissions = cpu_to_le64(mode);
|
pdata->Permissions = cpu_to_le64(mode);
|
||||||
|
@ -1025,7 +1115,6 @@ PsxCreat:
|
||||||
sizeof (FILE_UNIX_BASIC_INFO));
|
sizeof (FILE_UNIX_BASIC_INFO));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
psx_create_err:
|
psx_create_err:
|
||||||
cifs_buf_release(pSMB);
|
cifs_buf_release(pSMB);
|
||||||
|
|
||||||
|
@ -1132,7 +1221,8 @@ OldOpenRetry:
|
||||||
being created */
|
being created */
|
||||||
|
|
||||||
/* BB FIXME BB */
|
/* BB FIXME BB */
|
||||||
/* pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK); */
|
/* pSMB->CreateOptions = cpu_to_le32(create_options &
|
||||||
|
CREATE_OPTIONS_MASK); */
|
||||||
/* BB FIXME END BB */
|
/* BB FIXME END BB */
|
||||||
|
|
||||||
pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
|
pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
|
||||||
|
@ -1285,10 +1375,9 @@ openRetry:
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
|
CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
|
||||||
const int netfid, const unsigned int count,
|
const unsigned int count, const __u64 lseek, unsigned int *nbytes,
|
||||||
const __u64 lseek, unsigned int *nbytes, char **buf,
|
char **buf, int *pbuf_type)
|
||||||
int * pbuf_type)
|
|
||||||
{
|
{
|
||||||
int rc = -EACCES;
|
int rc = -EACCES;
|
||||||
READ_REQ *pSMB = NULL;
|
READ_REQ *pSMB = NULL;
|
||||||
|
@ -1351,7 +1440,8 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
|
||||||
/*check that DataLength would not go beyond end of SMB */
|
/*check that DataLength would not go beyond end of SMB */
|
||||||
if ((data_length > CIFSMaxBufSize)
|
if ((data_length > CIFSMaxBufSize)
|
||||||
|| (data_length > count)) {
|
|| (data_length > count)) {
|
||||||
cFYI(1,("bad length %d for count %d",data_length,count));
|
cFYI(1, ("bad length %d for count %d",
|
||||||
|
data_length, count));
|
||||||
rc = -EIO;
|
rc = -EIO;
|
||||||
*nbytes = 0;
|
*nbytes = 0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1422,14 +1512,14 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
|
||||||
pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
|
pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
|
||||||
if (wct == 14)
|
if (wct == 14)
|
||||||
pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
|
pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
|
||||||
else if((offset >> 32) > 0) /* can not handle this big offset for old */
|
else if ((offset >> 32) > 0) /* can not handle big offset for old srv */
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
pSMB->Reserved = 0xFFFFFFFF;
|
pSMB->Reserved = 0xFFFFFFFF;
|
||||||
pSMB->WriteMode = 0;
|
pSMB->WriteMode = 0;
|
||||||
pSMB->Remaining = 0;
|
pSMB->Remaining = 0;
|
||||||
|
|
||||||
/* Can increase buffer size if buffer is big enough in some cases - ie we
|
/* Can increase buffer size if buffer is big enough in some cases ie we
|
||||||
can send more if LARGE_WRITE_X capability returned by the server and if
|
can send more if LARGE_WRITE_X capability returned by the server and if
|
||||||
our buffer is big enough or if we convert to iovecs on socket writes
|
our buffer is big enough or if we convert to iovecs on socket writes
|
||||||
and eliminate the copy to the CIFS buffer */
|
and eliminate the copy to the CIFS buffer */
|
||||||
|
@ -1467,7 +1557,8 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
|
||||||
|
|
||||||
if (wct == 14)
|
if (wct == 14)
|
||||||
pSMB->ByteCount = cpu_to_le16(byte_count);
|
pSMB->ByteCount = cpu_to_le16(byte_count);
|
||||||
else { /* old style write has byte count 4 bytes earlier so 4 bytes pad */
|
else { /* old style write has byte count 4 bytes earlier
|
||||||
|
so 4 bytes pad */
|
||||||
struct smb_com_writex_req *pSMBW =
|
struct smb_com_writex_req *pSMBW =
|
||||||
(struct smb_com_writex_req *)pSMB;
|
(struct smb_com_writex_req *)pSMB;
|
||||||
pSMBW->ByteCount = cpu_to_le16(byte_count);
|
pSMBW->ByteCount = cpu_to_le16(byte_count);
|
||||||
|
@ -1523,7 +1614,7 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
|
||||||
pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
|
pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
|
||||||
if (wct == 14)
|
if (wct == 14)
|
||||||
pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
|
pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
|
||||||
else if((offset >> 32) > 0) /* can not handle this big offset for old */
|
else if ((offset >> 32) > 0) /* can not handle big offset for old srv */
|
||||||
return -EIO;
|
return -EIO;
|
||||||
pSMB->Reserved = 0xFFFFFFFF;
|
pSMB->Reserved = 0xFFFFFFFF;
|
||||||
pSMB->WriteMode = 0;
|
pSMB->WriteMode = 0;
|
||||||
|
@ -1661,7 +1752,6 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
|
||||||
{
|
{
|
||||||
struct smb_com_transaction2_sfi_req *pSMB = NULL;
|
struct smb_com_transaction2_sfi_req *pSMB = NULL;
|
||||||
struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
|
struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
|
||||||
char *data_offset;
|
|
||||||
struct cifs_posix_lock *parm_data;
|
struct cifs_posix_lock *parm_data;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
int timeout = 0;
|
int timeout = 0;
|
||||||
|
@ -1688,8 +1778,6 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
|
||||||
param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
|
param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
|
||||||
offset = param_offset + params;
|
offset = param_offset + params;
|
||||||
|
|
||||||
data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
|
|
||||||
|
|
||||||
count = sizeof(struct cifs_posix_lock);
|
count = sizeof(struct cifs_posix_lock);
|
||||||
pSMB->MaxParameterCount = cpu_to_le16(2);
|
pSMB->MaxParameterCount = cpu_to_le16(2);
|
||||||
pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
|
pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
|
||||||
|
@ -1933,7 +2021,8 @@ int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
|
||||||
dummy_string, 24, nls_codepage, remap);
|
dummy_string, 24, nls_codepage, remap);
|
||||||
} else {
|
} else {
|
||||||
len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
|
len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
|
||||||
target_name, PATH_MAX, nls_codepage, remap);
|
target_name, PATH_MAX, nls_codepage,
|
||||||
|
remap);
|
||||||
}
|
}
|
||||||
rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
|
rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
|
||||||
count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
|
count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
|
||||||
|
@ -1994,7 +2083,8 @@ copyRetry:
|
||||||
pSMB->OldFileName[name_len] = 0x04; /* pad */
|
pSMB->OldFileName[name_len] = 0x04; /* pad */
|
||||||
/* protocol requires ASCII signature byte on Unicode string */
|
/* protocol requires ASCII signature byte on Unicode string */
|
||||||
pSMB->OldFileName[name_len + 1] = 0x00;
|
pSMB->OldFileName[name_len + 1] = 0x00;
|
||||||
name_len2 = cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
|
name_len2 =
|
||||||
|
cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
|
||||||
toName, PATH_MAX, nls_codepage, remap);
|
toName, PATH_MAX, nls_codepage, remap);
|
||||||
name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
|
name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
|
||||||
name_len2 *= 2; /* convert to bytes */
|
name_len2 *= 2; /* convert to bytes */
|
||||||
|
@ -2108,9 +2198,7 @@ createSymLinkRetry:
|
||||||
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
|
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
|
||||||
cifs_stats_inc(&tcon->num_symlinks);
|
cifs_stats_inc(&tcon->num_symlinks);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
cFYI(1,
|
cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc));
|
||||||
("Send error in SetPathInfo (create symlink) = %d",
|
|
||||||
rc));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pSMB)
|
if (pSMB)
|
||||||
|
@ -2302,9 +2390,8 @@ querySymLinkRetry:
|
||||||
|
|
||||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||||
name_len =
|
name_len =
|
||||||
cifs_strtoUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
|
cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
|
||||||
/* find define for this maxpathcomponent */
|
PATH_MAX, nls_codepage);
|
||||||
, nls_codepage);
|
|
||||||
name_len++; /* trailing null */
|
name_len++; /* trailing null */
|
||||||
name_len *= 2;
|
name_len *= 2;
|
||||||
} else { /* BB improve the check for buffer overruns BB */
|
} else { /* BB improve the check for buffer overruns BB */
|
||||||
|
@ -2359,8 +2446,8 @@ querySymLinkRetry:
|
||||||
min_t(const int, buflen, count) / 2);
|
min_t(const int, buflen, count) / 2);
|
||||||
/* BB FIXME investigate remapping reserved chars here */
|
/* BB FIXME investigate remapping reserved chars here */
|
||||||
cifs_strfromUCS_le(symlinkinfo,
|
cifs_strfromUCS_le(symlinkinfo,
|
||||||
(__le16 *) ((char *)&pSMBr->hdr.Protocol +
|
(__le16 *) ((char *)&pSMBr->hdr.Protocol
|
||||||
data_offset),
|
+ data_offset),
|
||||||
name_len, nls_codepage);
|
name_len, nls_codepage);
|
||||||
} else {
|
} else {
|
||||||
strncpy(symlinkinfo,
|
strncpy(symlinkinfo,
|
||||||
|
@ -2432,7 +2519,6 @@ validate_ntransact(char * buf, char ** ppparm, char ** ppdata,
|
||||||
end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
|
end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
|
||||||
(char *)&pSMBr->ByteCount;
|
(char *)&pSMBr->ByteCount;
|
||||||
|
|
||||||
|
|
||||||
data_offset = le32_to_cpu(pSMBr->DataOffset);
|
data_offset = le32_to_cpu(pSMBr->DataOffset);
|
||||||
data_count = le32_to_cpu(pSMBr->DataCount);
|
data_count = le32_to_cpu(pSMBr->DataCount);
|
||||||
parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
|
parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
|
||||||
|
@ -2453,7 +2539,8 @@ validate_ntransact(char * buf, char ** ppparm, char ** ppdata,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
} else if (data_count + *ppdata > end_of_smb) {
|
} else if (data_count + *ppdata > end_of_smb) {
|
||||||
cFYI(1,("data %p + count %d (%p) ends after end of smb %p start %p",
|
cFYI(1,("data %p + count %d (%p) ends after end of smb %p start %p",
|
||||||
*ppdata, data_count, (data_count + *ppdata), end_of_smb, pSMBr)); /* BB FIXME */
|
*ppdata, data_count, (data_count + *ppdata),
|
||||||
|
end_of_smb, pSMBr));
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
} else if (parm_count + data_count > pSMBr->ByteCount) {
|
} else if (parm_count + data_count > pSMBr->ByteCount) {
|
||||||
cFYI(1, ("parm count and data count larger than SMB"));
|
cFYI(1, ("parm count and data count larger than SMB"));
|
||||||
|
@ -2516,8 +2603,10 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
|
||||||
pSMBr->ByteCount +
|
pSMBr->ByteCount +
|
||||||
(char *)&pSMBr->ByteCount;
|
(char *)&pSMBr->ByteCount;
|
||||||
|
|
||||||
struct reparse_data * reparse_buf = (struct reparse_data *)
|
struct reparse_data *reparse_buf =
|
||||||
((char *)&pSMBr->hdr.Protocol + data_offset);
|
(struct reparse_data *)
|
||||||
|
((char *)&pSMBr->hdr.Protocol
|
||||||
|
+ data_offset);
|
||||||
if ((char *)reparse_buf >= end_of_smb) {
|
if ((char *)reparse_buf >= end_of_smb) {
|
||||||
rc = -EIO;
|
rc = -EIO;
|
||||||
goto qreparse_out;
|
goto qreparse_out;
|
||||||
|
@ -2526,7 +2615,7 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
|
||||||
reparse_buf->TargetNameOffset +
|
reparse_buf->TargetNameOffset +
|
||||||
reparse_buf->TargetNameLen) >
|
reparse_buf->TargetNameLen) >
|
||||||
end_of_smb) {
|
end_of_smb) {
|
||||||
cFYI(1,("reparse buf extended beyond SMB"));
|
cFYI(1,("reparse buf goes beyond SMB"));
|
||||||
rc = -EIO;
|
rc = -EIO;
|
||||||
goto qreparse_out;
|
goto qreparse_out;
|
||||||
}
|
}
|
||||||
|
@ -2535,19 +2624,23 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
|
||||||
name_len = UniStrnlen((wchar_t *)
|
name_len = UniStrnlen((wchar_t *)
|
||||||
(reparse_buf->LinkNamesBuf +
|
(reparse_buf->LinkNamesBuf +
|
||||||
reparse_buf->TargetNameOffset),
|
reparse_buf->TargetNameOffset),
|
||||||
min(buflen/2, reparse_buf->TargetNameLen / 2));
|
min(buflen/2,
|
||||||
|
reparse_buf->TargetNameLen / 2));
|
||||||
cifs_strfromUCS_le(symlinkinfo,
|
cifs_strfromUCS_le(symlinkinfo,
|
||||||
(__le16 *) (reparse_buf->LinkNamesBuf +
|
(__le16 *) (reparse_buf->LinkNamesBuf +
|
||||||
reparse_buf->TargetNameOffset),
|
reparse_buf->TargetNameOffset),
|
||||||
name_len, nls_codepage);
|
name_len, nls_codepage);
|
||||||
} else { /* ASCII names */
|
} else { /* ASCII names */
|
||||||
strncpy(symlinkinfo,reparse_buf->LinkNamesBuf +
|
strncpy(symlinkinfo,
|
||||||
|
reparse_buf->LinkNamesBuf +
|
||||||
reparse_buf->TargetNameOffset,
|
reparse_buf->TargetNameOffset,
|
||||||
min_t(const int, buflen, reparse_buf->TargetNameLen));
|
min_t(const int, buflen,
|
||||||
|
reparse_buf->TargetNameLen));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rc = -EIO;
|
rc = -EIO;
|
||||||
cFYI(1,("Invalid return data count on get reparse info ioctl"));
|
cFYI(1, ("Invalid return data count on "
|
||||||
|
"get reparse info ioctl"));
|
||||||
}
|
}
|
||||||
symlinkinfo[buflen] = 0; /* just in case so the caller
|
symlinkinfo[buflen] = 0; /* just in case so the caller
|
||||||
does not go off the end of the buffer */
|
does not go off the end of the buffer */
|
||||||
|
@ -2566,7 +2659,8 @@ qreparse_out:
|
||||||
#ifdef CONFIG_CIFS_POSIX
|
#ifdef CONFIG_CIFS_POSIX
|
||||||
|
|
||||||
/*Convert an Access Control Entry from wire format to local POSIX xattr format*/
|
/*Convert an Access Control Entry from wire format to local POSIX xattr format*/
|
||||||
static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace)
|
static void cifs_convert_ace(posix_acl_xattr_entry *ace,
|
||||||
|
struct cifs_posix_ace *cifs_ace)
|
||||||
{
|
{
|
||||||
/* u8 cifs fields do not need le conversion */
|
/* u8 cifs fields do not need le conversion */
|
||||||
ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
|
ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
|
||||||
|
@ -2598,7 +2692,8 @@ static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,
|
||||||
size += sizeof(struct cifs_posix_ace) * count;
|
size += sizeof(struct cifs_posix_ace) * count;
|
||||||
/* check if we would go beyond end of SMB */
|
/* check if we would go beyond end of SMB */
|
||||||
if (size_of_data_area < size) {
|
if (size_of_data_area < size) {
|
||||||
cFYI(1,("bad CIFS POSIX ACL size %d vs. %d",size_of_data_area,size));
|
cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
|
||||||
|
size_of_data_area, size));
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
} else if (acl_type & ACL_TYPE_DEFAULT) {
|
} else if (acl_type & ACL_TYPE_DEFAULT) {
|
||||||
|
@ -2650,8 +2745,8 @@ static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
|
/* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
|
||||||
static __u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int buflen,
|
static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
|
||||||
const int acl_type)
|
const int buflen, const int acl_type)
|
||||||
{
|
{
|
||||||
__u16 rc = 0;
|
__u16 rc = 0;
|
||||||
struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
|
struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
|
||||||
|
@ -2663,7 +2758,8 @@ static __u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int bufl
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
count = posix_acl_xattr_count((size_t)buflen);
|
count = posix_acl_xattr_count((size_t)buflen);
|
||||||
cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
|
cFYI(1, ("setting acl with %d entries from buf of length %d and "
|
||||||
|
"version of %d",
|
||||||
count, buflen, le32_to_cpu(local_acl->a_version)));
|
count, buflen, le32_to_cpu(local_acl->a_version)));
|
||||||
if (le32_to_cpu(local_acl->a_version) != 2) {
|
if (le32_to_cpu(local_acl->a_version) != 2) {
|
||||||
cFYI(1, ("unknown POSIX ACL version %d",
|
cFYI(1, ("unknown POSIX ACL version %d",
|
||||||
|
@ -2742,7 +2838,8 @@ queryAclRetry:
|
||||||
pSMB->Timeout = 0;
|
pSMB->Timeout = 0;
|
||||||
pSMB->Reserved2 = 0;
|
pSMB->Reserved2 = 0;
|
||||||
pSMB->ParameterOffset = cpu_to_le16(
|
pSMB->ParameterOffset = cpu_to_le16(
|
||||||
offsetof(struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
|
offsetof(struct smb_com_transaction2_qpi_req,
|
||||||
|
InformationLevel) - 4);
|
||||||
pSMB->DataCount = 0;
|
pSMB->DataCount = 0;
|
||||||
pSMB->DataOffset = 0;
|
pSMB->DataOffset = 0;
|
||||||
pSMB->SetupCount = 1;
|
pSMB->SetupCount = 1;
|
||||||
|
@ -2943,7 +3040,6 @@ GetExtAttrOut:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif /* CONFIG_POSIX */
|
#endif /* CONFIG_POSIX */
|
||||||
|
|
||||||
|
|
||||||
|
@ -3005,12 +3101,12 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
|
||||||
rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
|
rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
|
||||||
(char **)&psec_desc,
|
(char **)&psec_desc,
|
||||||
&parm_len, &data_len);
|
&parm_len, &data_len);
|
||||||
|
|
||||||
if (rc)
|
if (rc)
|
||||||
goto qsec_out;
|
goto qsec_out;
|
||||||
pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
|
pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
|
||||||
|
|
||||||
cERROR(1,("smb %p parm %p data %p",pSMBr,parm,psec_desc)); /* BB removeme BB */
|
cERROR(1, ("smb %p parm %p data %p",
|
||||||
|
pSMBr, parm, psec_desc)); /* BB removeme BB */
|
||||||
|
|
||||||
if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
|
if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
|
||||||
rc = -EIO; /* bad smb */
|
rc = -EIO; /* bad smb */
|
||||||
|
@ -3176,13 +3272,15 @@ QPathInfoRetry:
|
||||||
else if (!legacy && (pSMBr->ByteCount < 40))
|
else if (!legacy && (pSMBr->ByteCount < 40))
|
||||||
rc = -EIO; /* bad smb */
|
rc = -EIO; /* bad smb */
|
||||||
else if (legacy && (pSMBr->ByteCount < 24))
|
else if (legacy && (pSMBr->ByteCount < 24))
|
||||||
rc = -EIO; /* 24 or 26 expected but we do not read last field */
|
rc = -EIO; /* 24 or 26 expected but we do not read
|
||||||
|
last field */
|
||||||
else if (pFindData) {
|
else if (pFindData) {
|
||||||
int size;
|
int size;
|
||||||
__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
|
__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
|
||||||
if(legacy) /* we do not read the last field, EAsize, fortunately
|
if (legacy) /* we do not read the last field, EAsize,
|
||||||
since it varies by subdialect and on Set vs. Get, is
|
fortunately since it varies by subdialect
|
||||||
two bytes or 4 bytes depending but we don't care here */
|
and on Set vs. Get, is two bytes or 4
|
||||||
|
bytes depending but we don't care here */
|
||||||
size = sizeof(FILE_INFO_STANDARD);
|
size = sizeof(FILE_INFO_STANDARD);
|
||||||
else
|
else
|
||||||
size = sizeof(FILE_ALL_INFO);
|
size = sizeof(FILE_ALL_INFO);
|
||||||
|
@ -3303,9 +3401,8 @@ findUniqueRetry:
|
||||||
|
|
||||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||||
name_len =
|
name_len =
|
||||||
cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
|
cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
|
||||||
/* find define for this maxpathcomponent */
|
PATH_MAX, nls_codepage);
|
||||||
, nls_codepage);
|
|
||||||
name_len++; /* trailing null */
|
name_len++; /* trailing null */
|
||||||
name_len *= 2;
|
name_len *= 2;
|
||||||
} else { /* BB improve the check for buffer overruns BB */
|
} else { /* BB improve the check for buffer overruns BB */
|
||||||
|
@ -3485,7 +3582,8 @@ findFirstRetry:
|
||||||
else
|
else
|
||||||
psrch_inf->endOfSearch = FALSE;
|
psrch_inf->endOfSearch = FALSE;
|
||||||
|
|
||||||
psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
|
psrch_inf->entries_in_buffer =
|
||||||
|
le16_to_cpu(parms->SearchCount);
|
||||||
psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
|
psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
|
||||||
psrch_inf->entries_in_buffer;
|
psrch_inf->entries_in_buffer;
|
||||||
*pnetfid = parms->SearchHandle;
|
*pnetfid = parms->SearchHandle;
|
||||||
|
@ -3523,7 +3621,8 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
|
||||||
pSMB->TotalDataCount = 0; /* no EAs */
|
pSMB->TotalDataCount = 0; /* no EAs */
|
||||||
pSMB->MaxParameterCount = cpu_to_le16(8);
|
pSMB->MaxParameterCount = cpu_to_le16(8);
|
||||||
pSMB->MaxDataCount =
|
pSMB->MaxDataCount =
|
||||||
cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
|
cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
|
||||||
|
0xFFFFFF00);
|
||||||
pSMB->MaxSetupCount = 0;
|
pSMB->MaxSetupCount = 0;
|
||||||
pSMB->Reserved = 0;
|
pSMB->Reserved = 0;
|
||||||
pSMB->Flags = 0;
|
pSMB->Flags = 0;
|
||||||
|
@ -3539,15 +3638,6 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
|
||||||
pSMB->SearchHandle = searchHandle; /* always kept as le */
|
pSMB->SearchHandle = searchHandle; /* always kept as le */
|
||||||
pSMB->SearchCount =
|
pSMB->SearchCount =
|
||||||
cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
|
cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
|
||||||
/* test for Unix extensions */
|
|
||||||
/* if (tcon->ses->capabilities & CAP_UNIX) {
|
|
||||||
pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
|
|
||||||
psrch_inf->info_level = SMB_FIND_FILE_UNIX;
|
|
||||||
} else {
|
|
||||||
pSMB->InformationLevel =
|
|
||||||
cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
|
|
||||||
psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
|
|
||||||
} */
|
|
||||||
pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
|
pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
|
||||||
pSMB->ResumeKey = psrch_inf->resume_key;
|
pSMB->ResumeKey = psrch_inf->resume_key;
|
||||||
pSMB->SearchFlags =
|
pSMB->SearchFlags =
|
||||||
|
@ -3577,7 +3667,7 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
|
||||||
if (rc) {
|
if (rc) {
|
||||||
if (rc == -EBADF) {
|
if (rc == -EBADF) {
|
||||||
psrch_inf->endOfSearch = TRUE;
|
psrch_inf->endOfSearch = TRUE;
|
||||||
rc = 0; /* search probably was closed at end of search above */
|
rc = 0; /* search probably was closed at end of search*/
|
||||||
} else
|
} else
|
||||||
cFYI(1, ("FindNext returned = %d", rc));
|
cFYI(1, ("FindNext returned = %d", rc));
|
||||||
} else { /* decode response */
|
} else { /* decode response */
|
||||||
|
@ -3606,11 +3696,12 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
|
||||||
psrch_inf->endOfSearch = TRUE;
|
psrch_inf->endOfSearch = TRUE;
|
||||||
else
|
else
|
||||||
psrch_inf->endOfSearch = FALSE;
|
psrch_inf->endOfSearch = FALSE;
|
||||||
|
psrch_inf->entries_in_buffer =
|
||||||
psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
|
le16_to_cpu(parms->SearchCount);
|
||||||
psrch_inf->index_of_last_entry +=
|
psrch_inf->index_of_last_entry +=
|
||||||
psrch_inf->entries_in_buffer;
|
psrch_inf->entries_in_buffer;
|
||||||
/* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
|
/* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",
|
||||||
|
psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */
|
||||||
|
|
||||||
/* BB fixme add unlock here */
|
/* BB fixme add unlock here */
|
||||||
}
|
}
|
||||||
|
@ -3625,12 +3716,12 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
|
||||||
FNext2_err_exit:
|
FNext2_err_exit:
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
cifs_buf_release(pSMB);
|
cifs_buf_release(pSMB);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
|
CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
|
||||||
|
const __u16 searchHandle)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
FINDCLOSE_REQ *pSMB = NULL;
|
FINDCLOSE_REQ *pSMB = NULL;
|
||||||
|
@ -3687,7 +3778,6 @@ GetInodeNumberRetry:
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
|
|
||||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||||
name_len =
|
name_len =
|
||||||
cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
|
cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
|
||||||
|
@ -3852,26 +3942,35 @@ getDFSRetry:
|
||||||
/* BB Add logic to parse referrals here */
|
/* BB Add logic to parse referrals here */
|
||||||
rc = validate_t2((struct smb_t2_rsp *)pSMBr);
|
rc = validate_t2((struct smb_t2_rsp *)pSMBr);
|
||||||
|
|
||||||
if (rc || (pSMBr->ByteCount < 17)) /* BB also check enough total bytes returned */
|
/* BB Also check if enough total bytes returned? */
|
||||||
|
if (rc || (pSMBr->ByteCount < 17))
|
||||||
rc = -EIO; /* bad smb */
|
rc = -EIO; /* bad smb */
|
||||||
else {
|
else {
|
||||||
__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
|
__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
|
||||||
__u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
|
__u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
|
||||||
|
|
||||||
cFYI(1,
|
cFYI(1,
|
||||||
("Decoding GetDFSRefer response. BCC: %d Offset %d",
|
("Decoding GetDFSRefer response BCC: %d Offset %d",
|
||||||
pSMBr->ByteCount, data_offset));
|
pSMBr->ByteCount, data_offset));
|
||||||
referrals =
|
referrals =
|
||||||
(struct dfs_referral_level_3 *)
|
(struct dfs_referral_level_3 *)
|
||||||
(8 /* sizeof start of data block */ +
|
(8 /* sizeof start of data block */ +
|
||||||
data_offset +
|
data_offset +
|
||||||
(char *) &pSMBr->hdr.Protocol);
|
(char *) &pSMBr->hdr.Protocol);
|
||||||
cFYI(1,("num_referrals: %d dfs flags: 0x%x ... \nfor referral one refer size: 0x%x srv type: 0x%x refer flags: 0x%x ttl: 0x%x",
|
cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n"
|
||||||
le16_to_cpu(pSMBr->NumberOfReferrals),le16_to_cpu(pSMBr->DFSFlags), le16_to_cpu(referrals->ReferralSize),le16_to_cpu(referrals->ServerType),le16_to_cpu(referrals->ReferralFlags),le16_to_cpu(referrals->TimeToLive)));
|
"for referral one refer size: 0x%x srv "
|
||||||
|
"type: 0x%x refer flags: 0x%x ttl: 0x%x",
|
||||||
|
le16_to_cpu(pSMBr->NumberOfReferrals),
|
||||||
|
le16_to_cpu(pSMBr->DFSFlags),
|
||||||
|
le16_to_cpu(referrals->ReferralSize),
|
||||||
|
le16_to_cpu(referrals->ServerType),
|
||||||
|
le16_to_cpu(referrals->ReferralFlags),
|
||||||
|
le16_to_cpu(referrals->TimeToLive)));
|
||||||
/* BB This field is actually two bytes in from start of
|
/* BB This field is actually two bytes in from start of
|
||||||
data block so we could do safety check that DataBlock
|
data block so we could do safety check that DataBlock
|
||||||
begins at address of pSMBr->NumberOfReferrals */
|
begins at address of pSMBr->NumberOfReferrals */
|
||||||
*number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
|
*number_of_UNC_in_array =
|
||||||
|
le16_to_cpu(pSMBr->NumberOfReferrals);
|
||||||
|
|
||||||
/* BB Fix below so can return more than one referral */
|
/* BB Fix below so can return more than one referral */
|
||||||
if (*number_of_UNC_in_array > 1)
|
if (*number_of_UNC_in_array > 1)
|
||||||
|
@ -3881,7 +3980,8 @@ getDFSRetry:
|
||||||
name_len = 0;
|
name_len = 0;
|
||||||
for (i = 0; i < *number_of_UNC_in_array; i++) {
|
for (i = 0; i < *number_of_UNC_in_array; i++) {
|
||||||
/* make sure that DfsPathOffset not past end */
|
/* make sure that DfsPathOffset not past end */
|
||||||
__u16 offset = le16_to_cpu(referrals->DfsPathOffset);
|
__u16 offset =
|
||||||
|
le16_to_cpu(referrals->DfsPathOffset);
|
||||||
if (offset > data_count) {
|
if (offset > data_count) {
|
||||||
/* if invalid referral, stop here and do
|
/* if invalid referral, stop here and do
|
||||||
not try to copy any more */
|
not try to copy any more */
|
||||||
|
@ -3891,33 +3991,36 @@ getDFSRetry:
|
||||||
temp = ((char *)referrals) + offset;
|
temp = ((char *)referrals) + offset;
|
||||||
|
|
||||||
if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
|
if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||||
name_len += UniStrnlen((wchar_t *)temp,data_count);
|
name_len += UniStrnlen((wchar_t *)temp,
|
||||||
|
data_count);
|
||||||
} else {
|
} else {
|
||||||
name_len += strnlen(temp, data_count);
|
name_len += strnlen(temp, data_count);
|
||||||
}
|
}
|
||||||
referrals++;
|
referrals++;
|
||||||
/* BB add check that referral pointer does not fall off end PDU */
|
/* BB add check that referral pointer does
|
||||||
|
not fall off end PDU */
|
||||||
}
|
}
|
||||||
/* BB add check for name_len bigger than bcc */
|
/* BB add check for name_len bigger than bcc */
|
||||||
*targetUNCs =
|
*targetUNCs =
|
||||||
kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
|
kmalloc(name_len+1+(*number_of_UNC_in_array),
|
||||||
|
GFP_KERNEL);
|
||||||
if (*targetUNCs == NULL) {
|
if (*targetUNCs == NULL) {
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
goto GetDFSRefExit;
|
goto GetDFSRefExit;
|
||||||
}
|
}
|
||||||
/* copy the ref strings */
|
/* copy the ref strings */
|
||||||
referrals =
|
referrals = (struct dfs_referral_level_3 *)
|
||||||
(struct dfs_referral_level_3 *)
|
(8 /* sizeof data hdr */ + data_offset +
|
||||||
(8 /* sizeof data hdr */ +
|
|
||||||
data_offset +
|
|
||||||
(char *) &pSMBr->hdr.Protocol);
|
(char *) &pSMBr->hdr.Protocol);
|
||||||
|
|
||||||
for (i = 0; i < *number_of_UNC_in_array; i++) {
|
for (i = 0; i < *number_of_UNC_in_array; i++) {
|
||||||
temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset);
|
temp = ((char *)referrals) +
|
||||||
|
le16_to_cpu(referrals->DfsPathOffset);
|
||||||
if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
|
if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||||
cifs_strfromUCS_le(*targetUNCs,
|
cifs_strfromUCS_le(*targetUNCs,
|
||||||
(__le16 *) temp, name_len, nls_codepage);
|
(__le16 *) temp,
|
||||||
|
name_len,
|
||||||
|
nls_codepage);
|
||||||
} else {
|
} else {
|
||||||
strncpy(*targetUNCs, temp, name_len);
|
strncpy(*targetUNCs, temp, name_len);
|
||||||
}
|
}
|
||||||
|
@ -3999,8 +4102,7 @@ oldQFSInfoRetry:
|
||||||
cFYI(1, ("qfsinf resp BCC: %d Offset %d",
|
cFYI(1, ("qfsinf resp BCC: %d Offset %d",
|
||||||
pSMBr->ByteCount, data_offset));
|
pSMBr->ByteCount, data_offset));
|
||||||
|
|
||||||
response_data =
|
response_data = (FILE_SYSTEM_ALLOC_INFO *)
|
||||||
(FILE_SYSTEM_ALLOC_INFO *)
|
|
||||||
(((char *) &pSMBr->hdr.Protocol) + data_offset);
|
(((char *) &pSMBr->hdr.Protocol) + data_offset);
|
||||||
FSData->f_bsize =
|
FSData->f_bsize =
|
||||||
le16_to_cpu(response_data->BytesPerSector) *
|
le16_to_cpu(response_data->BytesPerSector) *
|
||||||
|
@ -4153,7 +4255,8 @@ QFSAttributeRetry:
|
||||||
} else { /* decode response */
|
} else { /* decode response */
|
||||||
rc = validate_t2((struct smb_t2_rsp *)pSMBr);
|
rc = validate_t2((struct smb_t2_rsp *)pSMBr);
|
||||||
|
|
||||||
if (rc || (pSMBr->ByteCount < 13)) { /* BB also check enough bytes returned */
|
if (rc || (pSMBr->ByteCount < 13)) {
|
||||||
|
/* BB also check if enough bytes returned */
|
||||||
rc = -EIO; /* bad smb */
|
rc = -EIO; /* bad smb */
|
||||||
} else {
|
} else {
|
||||||
__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
|
__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
|
||||||
|
@ -4335,7 +4438,8 @@ SETFSUnixRetry:
|
||||||
pSMB->Flags = 0;
|
pSMB->Flags = 0;
|
||||||
pSMB->Timeout = 0;
|
pSMB->Timeout = 0;
|
||||||
pSMB->Reserved2 = 0;
|
pSMB->Reserved2 = 0;
|
||||||
param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - 4;
|
param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
|
||||||
|
- 4;
|
||||||
offset = param_offset + params;
|
offset = param_offset + params;
|
||||||
|
|
||||||
pSMB->MaxParameterCount = cpu_to_le16(4);
|
pSMB->MaxParameterCount = cpu_to_le16(4);
|
||||||
|
@ -4614,8 +4718,8 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
|
||||||
pSMB->TotalParameterCount = pSMB->ParameterCount;
|
pSMB->TotalParameterCount = pSMB->ParameterCount;
|
||||||
pSMB->ParameterOffset = cpu_to_le16(param_offset);
|
pSMB->ParameterOffset = cpu_to_le16(param_offset);
|
||||||
parm_data =
|
parm_data =
|
||||||
(struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
|
(struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
|
||||||
offset);
|
+ offset);
|
||||||
pSMB->DataOffset = cpu_to_le16(offset);
|
pSMB->DataOffset = cpu_to_le16(offset);
|
||||||
parm_data->FileSize = cpu_to_le64(size);
|
parm_data->FileSize = cpu_to_le64(size);
|
||||||
pSMB->Fid = fid;
|
pSMB->Fid = fid;
|
||||||
|
@ -4661,8 +4765,8 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
|
||||||
time and resort to the original setpathinfo level which takes the ancient
|
time and resort to the original setpathinfo level which takes the ancient
|
||||||
DOS time format with 2 second granularity */
|
DOS time format with 2 second granularity */
|
||||||
int
|
int
|
||||||
CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_INFO * data,
|
CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon,
|
||||||
__u16 fid)
|
const FILE_BASIC_INFO *data, __u16 fid)
|
||||||
{
|
{
|
||||||
struct smb_com_transaction2_sfi_req *pSMB = NULL;
|
struct smb_com_transaction2_sfi_req *pSMB = NULL;
|
||||||
struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
|
struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
|
||||||
|
@ -5131,7 +5235,7 @@ QAllEAsRetry:
|
||||||
struct fealist *ea_response_data;
|
struct fealist *ea_response_data;
|
||||||
rc = 0;
|
rc = 0;
|
||||||
/* validate_trans2_offsets() */
|
/* validate_trans2_offsets() */
|
||||||
/* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
|
/* BB check if start of smb + data_offset > &bcc+ bcc */
|
||||||
ea_response_data = (struct fealist *)
|
ea_response_data = (struct fealist *)
|
||||||
(((char *) &pSMBr->hdr.Protocol) +
|
(((char *) &pSMBr->hdr.Protocol) +
|
||||||
data_offset);
|
data_offset);
|
||||||
|
@ -5155,7 +5259,8 @@ QAllEAsRetry:
|
||||||
if (rc < (int)buf_size) {
|
if (rc < (int)buf_size) {
|
||||||
memcpy(EAData, "user.", 5);
|
memcpy(EAData, "user.", 5);
|
||||||
EAData += 5;
|
EAData += 5;
|
||||||
memcpy(EAData,temp_ptr,temp_fea->name_len);
|
memcpy(EAData, temp_ptr,
|
||||||
|
temp_fea->name_len);
|
||||||
EAData += temp_fea->name_len;
|
EAData += temp_fea->name_len;
|
||||||
/* null terminate name */
|
/* null terminate name */
|
||||||
*EAData = 0;
|
*EAData = 0;
|
||||||
|
@ -5172,11 +5277,15 @@ QAllEAsRetry:
|
||||||
/* account for trailing null */
|
/* account for trailing null */
|
||||||
name_len--;
|
name_len--;
|
||||||
temp_ptr++;
|
temp_ptr++;
|
||||||
value_len = le16_to_cpu(temp_fea->value_len);
|
value_len =
|
||||||
|
le16_to_cpu(temp_fea->value_len);
|
||||||
name_len -= value_len;
|
name_len -= value_len;
|
||||||
temp_ptr += value_len;
|
temp_ptr += value_len;
|
||||||
/* BB check that temp_ptr is still within smb BB*/
|
/* BB check that temp_ptr is still
|
||||||
/* no trailing null to account for in value len */
|
within the SMB BB*/
|
||||||
|
|
||||||
|
/* no trailing null to account for
|
||||||
|
in value len */
|
||||||
/* go on to next EA */
|
/* go on to next EA */
|
||||||
temp_fea = (struct fea *)temp_ptr;
|
temp_fea = (struct fea *)temp_ptr;
|
||||||
}
|
}
|
||||||
|
@ -5274,7 +5383,7 @@ QEARetry:
|
||||||
struct fealist *ea_response_data;
|
struct fealist *ea_response_data;
|
||||||
rc = -ENODATA;
|
rc = -ENODATA;
|
||||||
/* validate_trans2_offsets() */
|
/* validate_trans2_offsets() */
|
||||||
/* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
|
/* BB check if start of smb + data_offset > &bcc+ bcc*/
|
||||||
ea_response_data = (struct fealist *)
|
ea_response_data = (struct fealist *)
|
||||||
(((char *) &pSMBr->hdr.Protocol) +
|
(((char *) &pSMBr->hdr.Protocol) +
|
||||||
data_offset);
|
data_offset);
|
||||||
|
@ -5294,7 +5403,8 @@ QEARetry:
|
||||||
__u16 value_len;
|
__u16 value_len;
|
||||||
name_len -= 4;
|
name_len -= 4;
|
||||||
temp_ptr += 4;
|
temp_ptr += 4;
|
||||||
value_len = le16_to_cpu(temp_fea->value_len);
|
value_len =
|
||||||
|
le16_to_cpu(temp_fea->value_len);
|
||||||
/* BB validate that value_len falls within SMB,
|
/* BB validate that value_len falls within SMB,
|
||||||
even though maximum for name_len is 255 */
|
even though maximum for name_len is 255 */
|
||||||
if (memcmp(temp_fea->name, ea_name,
|
if (memcmp(temp_fea->name, ea_name,
|
||||||
|
@ -5306,8 +5416,9 @@ QEARetry:
|
||||||
memcpy(ea_value,
|
memcpy(ea_value,
|
||||||
temp_fea->name+temp_fea->name_len+1,
|
temp_fea->name+temp_fea->name_len+1,
|
||||||
rc);
|
rc);
|
||||||
/* ea values, unlike ea names,
|
/* ea values, unlike ea
|
||||||
are not null terminated */
|
names, are not null
|
||||||
|
terminated */
|
||||||
} else if (buf_size == 0) {
|
} else if (buf_size == 0) {
|
||||||
/* skip copy - calc size only */
|
/* skip copy - calc size only */
|
||||||
} else {
|
} else {
|
||||||
|
@ -5323,8 +5434,8 @@ QEARetry:
|
||||||
temp_ptr++;
|
temp_ptr++;
|
||||||
name_len -= value_len;
|
name_len -= value_len;
|
||||||
temp_ptr += value_len;
|
temp_ptr += value_len;
|
||||||
/* no trailing null to account for in value len */
|
/* No trailing null to account for in
|
||||||
/* go on to next EA */
|
value_len. Go on to next EA */
|
||||||
temp_fea = (struct fea *)temp_ptr;
|
temp_fea = (struct fea *)temp_ptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5417,10 +5528,12 @@ SetEARetry:
|
||||||
/* caller ensures that ea_value_len is less than 64K but
|
/* caller ensures that ea_value_len is less than 64K but
|
||||||
we need to ensure that it fits within the smb */
|
we need to ensure that it fits within the smb */
|
||||||
|
|
||||||
/*BB add length check that it would fit in negotiated SMB buffer size BB */
|
/*BB add length check to see if it would fit in
|
||||||
|
negotiated SMB buffer size BB */
|
||||||
/* if (ea_value_len > buffer_size - 512 (enough for header)) */
|
/* if (ea_value_len > buffer_size - 512 (enough for header)) */
|
||||||
if (ea_value_len)
|
if (ea_value_len)
|
||||||
memcpy(parm_data->list[0].name+name_len+1,ea_value,ea_value_len);
|
memcpy(parm_data->list[0].name+name_len+1,
|
||||||
|
ea_value, ea_value_len);
|
||||||
|
|
||||||
pSMB->TotalDataCount = pSMB->DataCount;
|
pSMB->TotalDataCount = pSMB->DataCount;
|
||||||
pSMB->ParameterCount = cpu_to_le16(params);
|
pSMB->ParameterCount = cpu_to_le16(params);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* fs/cifs/connect.c
|
* fs/cifs/connect.c
|
||||||
*
|
*
|
||||||
* Copyright (C) International Business Machines Corp., 2002,2006
|
* Copyright (C) International Business Machines Corp., 2002,2007
|
||||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or modify
|
* This library is free software; you can redistribute it and/or modify
|
||||||
|
@ -85,6 +85,7 @@ struct smb_vol {
|
||||||
unsigned direct_io:1;
|
unsigned direct_io:1;
|
||||||
unsigned remap:1; /* set to remap seven reserved chars in filenames */
|
unsigned remap:1; /* set to remap seven reserved chars in filenames */
|
||||||
unsigned posix_paths:1; /* unset to not ask for posix pathnames. */
|
unsigned posix_paths:1; /* unset to not ask for posix pathnames. */
|
||||||
|
unsigned no_linux_ext:1;
|
||||||
unsigned sfu_emul:1;
|
unsigned sfu_emul:1;
|
||||||
unsigned nullauth:1; /* attempt to authenticate with null user */
|
unsigned nullauth:1; /* attempt to authenticate with null user */
|
||||||
unsigned nocase; /* request case insensitive filenames */
|
unsigned nocase; /* request case insensitive filenames */
|
||||||
|
@ -161,7 +162,8 @@ cifs_reconnect(struct TCP_Server_Info *server)
|
||||||
cFYI(1, ("State: 0x%x Flags: 0x%lx", server->ssocket->state,
|
cFYI(1, ("State: 0x%x Flags: 0x%lx", server->ssocket->state,
|
||||||
server->ssocket->flags));
|
server->ssocket->flags));
|
||||||
server->ssocket->ops->shutdown(server->ssocket, SEND_SHUTDOWN);
|
server->ssocket->ops->shutdown(server->ssocket, SEND_SHUTDOWN);
|
||||||
cFYI(1,("Post shutdown state: 0x%x Flags: 0x%lx", server->ssocket->state,
|
cFYI(1, ("Post shutdown state: 0x%x Flags: 0x%lx",
|
||||||
|
server->ssocket->state,
|
||||||
server->ssocket->flags));
|
server->ssocket->flags));
|
||||||
sock_release(server->ssocket);
|
sock_release(server->ssocket);
|
||||||
server->ssocket = NULL;
|
server->ssocket = NULL;
|
||||||
|
@ -185,11 +187,11 @@ cifs_reconnect(struct TCP_Server_Info *server)
|
||||||
spin_unlock(&GlobalMid_Lock);
|
spin_unlock(&GlobalMid_Lock);
|
||||||
up(&server->tcpSem);
|
up(&server->tcpSem);
|
||||||
|
|
||||||
while ( (!kthread_should_stop()) && (server->tcpStatus != CifsGood))
|
while ( (!kthread_should_stop()) && (server->tcpStatus != CifsGood)) {
|
||||||
{
|
|
||||||
try_to_freeze();
|
try_to_freeze();
|
||||||
if (server->protocolType == IPV6) {
|
if (server->protocolType == IPV6) {
|
||||||
rc = ipv6_connect(&server->addr.sockAddr6,&server->ssocket);
|
rc = ipv6_connect(&server->addr.sockAddr6,
|
||||||
|
&server->ssocket);
|
||||||
} else {
|
} else {
|
||||||
rc = ipv4_connect(&server->addr.sockAddr,
|
rc = ipv4_connect(&server->addr.sockAddr,
|
||||||
&server->ssocket,
|
&server->ssocket,
|
||||||
|
@ -277,7 +279,7 @@ static int coalesce_t2(struct smb_hdr * psecond, struct smb_hdr *pTargetSMB)
|
||||||
total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
|
total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
|
||||||
|
|
||||||
if (total_data_size != le16_to_cpu(pSMB2->t2_rsp.TotalDataCount)) {
|
if (total_data_size != le16_to_cpu(pSMB2->t2_rsp.TotalDataCount)) {
|
||||||
cFYI(1,("total data sizes of primary and secondary t2 differ"));
|
cFYI(1, ("total data size of primary and secondary t2 differ"));
|
||||||
}
|
}
|
||||||
|
|
||||||
total_in_buf = le16_to_cpu(pSMBt->t2_rsp.DataCount);
|
total_in_buf = le16_to_cpu(pSMBt->t2_rsp.DataCount);
|
||||||
|
@ -348,7 +350,6 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
|
||||||
int isMultiRsp;
|
int isMultiRsp;
|
||||||
int reconnect;
|
int reconnect;
|
||||||
|
|
||||||
allow_signal(SIGKILL);
|
|
||||||
current->flags |= PF_MEMALLOC;
|
current->flags |= PF_MEMALLOC;
|
||||||
server->tsk = current; /* save process info to wake at shutdown */
|
server->tsk = current; /* save process info to wake at shutdown */
|
||||||
cFYI(1, ("Demultiplex PID: %d", current->pid));
|
cFYI(1, ("Demultiplex PID: %d", current->pid));
|
||||||
|
@ -459,7 +460,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
|
||||||
pdu_length = ntohl(smb_buffer->smb_buf_length);
|
pdu_length = ntohl(smb_buffer->smb_buf_length);
|
||||||
smb_buffer->smb_buf_length = pdu_length;
|
smb_buffer->smb_buf_length = pdu_length;
|
||||||
|
|
||||||
cFYI(1,("rfc1002 length 0x%x)", pdu_length+4));
|
cFYI(1, ("rfc1002 length 0x%x", pdu_length+4));
|
||||||
|
|
||||||
if (temp == (char) RFC1002_SESSION_KEEP_ALIVE) {
|
if (temp == (char) RFC1002_SESSION_KEEP_ALIVE) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -638,7 +639,8 @@ multi_t2_fnd:
|
||||||
wake_up_process(task_to_wake);
|
wake_up_process(task_to_wake);
|
||||||
} else if ((is_valid_oplock_break(smb_buffer, server) == FALSE)
|
} else if ((is_valid_oplock_break(smb_buffer, server) == FALSE)
|
||||||
&& (isMultiRsp == FALSE)) {
|
&& (isMultiRsp == FALSE)) {
|
||||||
cERROR(1, ("No task to wake, unknown frame rcvd! NumMids %d", midCount.counter));
|
cERROR(1, ("No task to wake, unknown frame received! "
|
||||||
|
"NumMids %d", midCount.counter));
|
||||||
cifs_dump_mem("Received Data is: ", (char *)smb_buffer,
|
cifs_dump_mem("Received Data is: ", (char *)smb_buffer,
|
||||||
sizeof(struct smb_hdr));
|
sizeof(struct smb_hdr));
|
||||||
#ifdef CONFIG_CIFS_DEBUG2
|
#ifdef CONFIG_CIFS_DEBUG2
|
||||||
|
@ -709,8 +711,8 @@ multi_t2_fnd:
|
||||||
list_for_each(tmp, &server->pending_mid_q) {
|
list_for_each(tmp, &server->pending_mid_q) {
|
||||||
mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
|
mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
|
||||||
if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
|
if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
|
||||||
cFYI(1,
|
cFYI(1, ("Clearing Mid 0x%x - waking up ",
|
||||||
("Clearing Mid 0x%x - waking up ",mid_entry->mid));
|
mid_entry->mid));
|
||||||
task_to_wake = mid_entry->tsk;
|
task_to_wake = mid_entry->tsk;
|
||||||
if (task_to_wake) {
|
if (task_to_wake) {
|
||||||
wake_up_process(task_to_wake);
|
wake_up_process(task_to_wake);
|
||||||
|
@ -764,7 +766,8 @@ multi_t2_fnd:
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
|
cifs_parse_mount_options(char *options, const char *devname,
|
||||||
|
struct smb_vol *vol)
|
||||||
{
|
{
|
||||||
char *value;
|
char *value;
|
||||||
char *data;
|
char *data;
|
||||||
|
@ -820,7 +823,8 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
|
||||||
if ((value = strchr(data, '=')) != NULL)
|
if ((value = strchr(data, '=')) != NULL)
|
||||||
*value++ = '\0';
|
*value++ = '\0';
|
||||||
|
|
||||||
if (strnicmp(data, "user_xattr",10) == 0) {/*parse before user*/
|
/* Have to parse this before we parse for "user" */
|
||||||
|
if (strnicmp(data, "user_xattr", 10) == 0) {
|
||||||
vol->no_xattr = 0;
|
vol->no_xattr = 0;
|
||||||
} else if (strnicmp(data, "nouser_xattr", 12) == 0) {
|
} else if (strnicmp(data, "nouser_xattr", 12) == 0) {
|
||||||
vol->no_xattr = 1;
|
vol->no_xattr = 1;
|
||||||
|
@ -871,7 +875,7 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
|
||||||
(value[temp_len+1] == separator[0])) {
|
(value[temp_len+1] == separator[0])) {
|
||||||
/* reinsert comma */
|
/* reinsert comma */
|
||||||
value[temp_len] = separator[0];
|
value[temp_len] = separator[0];
|
||||||
temp_len+=2; /* move after the second comma */
|
temp_len += 2; /* move after second comma */
|
||||||
while (value[temp_len] != 0) {
|
while (value[temp_len] != 0) {
|
||||||
if (value[temp_len] == separator[0]) {
|
if (value[temp_len] == separator[0]) {
|
||||||
if (value[temp_len+1] ==
|
if (value[temp_len+1] ==
|
||||||
|
@ -898,7 +902,8 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
|
||||||
allocating a few bytes too many, which is ok */
|
allocating a few bytes too many, which is ok */
|
||||||
vol->password = kzalloc(temp_len, GFP_KERNEL);
|
vol->password = kzalloc(temp_len, GFP_KERNEL);
|
||||||
if (vol->password == NULL) {
|
if (vol->password == NULL) {
|
||||||
printk("CIFS: no memory for pass\n");
|
printk(KERN_WARNING "CIFS: no memory "
|
||||||
|
"for password\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
for (i = 0, j = 0; i < temp_len; i++, j++) {
|
for (i = 0, j = 0; i < temp_len; i++, j++) {
|
||||||
|
@ -913,7 +918,8 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
|
||||||
} else {
|
} else {
|
||||||
vol->password = kzalloc(temp_len+1, GFP_KERNEL);
|
vol->password = kzalloc(temp_len+1, GFP_KERNEL);
|
||||||
if (vol->password == NULL) {
|
if (vol->password == NULL) {
|
||||||
printk("CIFS: no memory for pass\n");
|
printk(KERN_WARNING "CIFS: no memory "
|
||||||
|
"for password\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
strcpy(vol->password, value);
|
strcpy(vol->password, value);
|
||||||
|
@ -924,7 +930,8 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
|
||||||
} else if (strnlen(value, 35) < 35) {
|
} else if (strnlen(value, 35) < 35) {
|
||||||
vol->UNCip = value;
|
vol->UNCip = value;
|
||||||
} else {
|
} else {
|
||||||
printk(KERN_WARNING "CIFS: ip address too long\n");
|
printk(KERN_WARNING "CIFS: ip address "
|
||||||
|
"too long\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
} else if (strnicmp(data, "sec", 3) == 0) {
|
} else if (strnicmp(data, "sec", 3) == 0) {
|
||||||
|
@ -969,8 +976,8 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
|
||||||
|| (strnicmp(data, "target", 6) == 0)
|
|| (strnicmp(data, "target", 6) == 0)
|
||||||
|| (strnicmp(data, "path", 4) == 0)) {
|
|| (strnicmp(data, "path", 4) == 0)) {
|
||||||
if (!value || !*value) {
|
if (!value || !*value) {
|
||||||
printk(KERN_WARNING
|
printk(KERN_WARNING "CIFS: invalid path to "
|
||||||
"CIFS: invalid path to network resource\n");
|
"network resource\n");
|
||||||
return 1; /* needs_arg; */
|
return 1; /* needs_arg; */
|
||||||
}
|
}
|
||||||
if ((temp_len = strnlen(value, 300)) < 300) {
|
if ((temp_len = strnlen(value, 300)) < 300) {
|
||||||
|
@ -983,7 +990,8 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
|
||||||
vol->UNC[1] = '\\';
|
vol->UNC[1] = '\\';
|
||||||
} else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
|
} else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
|
||||||
printk(KERN_WARNING
|
printk(KERN_WARNING
|
||||||
"CIFS: UNC Path does not begin with // or \\\\ \n");
|
"CIFS: UNC Path does not begin "
|
||||||
|
"with // or \\\\ \n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1002,14 +1010,15 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
|
||||||
vol->domainname = value;
|
vol->domainname = value;
|
||||||
cFYI(1, ("Domain name set"));
|
cFYI(1, ("Domain name set"));
|
||||||
} else {
|
} else {
|
||||||
printk(KERN_WARNING "CIFS: domain name too long\n");
|
printk(KERN_WARNING "CIFS: domain name too "
|
||||||
|
"long\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
} else if (strnicmp(data, "prefixpath", 10) == 0) {
|
} else if (strnicmp(data, "prefixpath", 10) == 0) {
|
||||||
if (!value || !*value) {
|
if (!value || !*value) {
|
||||||
printk(KERN_WARNING
|
printk(KERN_WARNING
|
||||||
"CIFS: invalid path prefix\n");
|
"CIFS: invalid path prefix\n");
|
||||||
return 1; /* needs_arg; */
|
return 1; /* needs_argument */
|
||||||
}
|
}
|
||||||
if ((temp_len = strnlen(value, 1024)) < 1024) {
|
if ((temp_len = strnlen(value, 1024)) < 1024) {
|
||||||
if (value[0] != '/')
|
if (value[0] != '/')
|
||||||
|
@ -1029,16 +1038,19 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
|
||||||
}
|
}
|
||||||
} else if (strnicmp(data, "iocharset", 9) == 0) {
|
} else if (strnicmp(data, "iocharset", 9) == 0) {
|
||||||
if (!value || !*value) {
|
if (!value || !*value) {
|
||||||
printk(KERN_WARNING "CIFS: invalid iocharset specified\n");
|
printk(KERN_WARNING "CIFS: invalid iocharset "
|
||||||
|
"specified\n");
|
||||||
return 1; /* needs_arg; */
|
return 1; /* needs_arg; */
|
||||||
}
|
}
|
||||||
if (strnlen(value, 65) < 65) {
|
if (strnlen(value, 65) < 65) {
|
||||||
if (strnicmp(value, "default", 7))
|
if (strnicmp(value, "default", 7))
|
||||||
vol->iocharset = value;
|
vol->iocharset = value;
|
||||||
/* if iocharset not set load_nls_default used by caller */
|
/* if iocharset not set then load_nls_default
|
||||||
|
is used by caller */
|
||||||
cFYI(1, ("iocharset set to %s", value));
|
cFYI(1, ("iocharset set to %s", value));
|
||||||
} else {
|
} else {
|
||||||
printk(KERN_WARNING "CIFS: iocharset name too long.\n");
|
printk(KERN_WARNING "CIFS: iocharset name "
|
||||||
|
"too long.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
} else if (strnicmp(data, "uid", 3) == 0) {
|
} else if (strnicmp(data, "uid", 3) == 0) {
|
||||||
|
@ -1090,7 +1102,7 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
|
||||||
}
|
}
|
||||||
} else if (strnicmp(data, "netbiosname", 4) == 0) {
|
} else if (strnicmp(data, "netbiosname", 4) == 0) {
|
||||||
if (!value || !*value || (*value == ' ')) {
|
if (!value || !*value || (*value == ' ')) {
|
||||||
cFYI(1,("invalid (empty) netbiosname specified"));
|
cFYI(1, ("invalid (empty) netbiosname"));
|
||||||
} else {
|
} else {
|
||||||
memset(vol->source_rfc1001_name, 0x20, 15);
|
memset(vol->source_rfc1001_name, 0x20, 15);
|
||||||
for (i = 0; i < 15; i++) {
|
for (i = 0; i < 15; i++) {
|
||||||
|
@ -1102,12 +1114,14 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
|
||||||
if (value[i] == 0)
|
if (value[i] == 0)
|
||||||
break;
|
break;
|
||||||
else
|
else
|
||||||
vol->source_rfc1001_name[i] = value[i];
|
vol->source_rfc1001_name[i] =
|
||||||
|
value[i];
|
||||||
}
|
}
|
||||||
/* The string has 16th byte zero still from
|
/* The string has 16th byte zero still from
|
||||||
set at top of the function */
|
set at top of the function */
|
||||||
if ((i == 15) && (value[i] != 0))
|
if ((i == 15) && (value[i] != 0))
|
||||||
printk(KERN_WARNING "CIFS: netbiosname longer than 15 truncated.\n");
|
printk(KERN_WARNING "CIFS: netbiosname"
|
||||||
|
" longer than 15 truncated.\n");
|
||||||
}
|
}
|
||||||
} else if (strnicmp(data, "servern", 7) == 0) {
|
} else if (strnicmp(data, "servern", 7) == 0) {
|
||||||
/* servernetbiosname specified override *SMBSERVER */
|
/* servernetbiosname specified override *SMBSERVER */
|
||||||
|
@ -1119,19 +1133,22 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
|
||||||
|
|
||||||
for (i = 0; i < 15; i++) {
|
for (i = 0; i < 15; i++) {
|
||||||
/* BB are there cases in which a comma can be
|
/* BB are there cases in which a comma can be
|
||||||
valid in this workstation netbios name (and need
|
valid in this workstation netbios name
|
||||||
special handling)? */
|
(and need special handling)? */
|
||||||
|
|
||||||
/* user or mount helper must uppercase netbiosname */
|
/* user or mount helper must uppercase
|
||||||
|
the netbiosname */
|
||||||
if (value[i] == 0)
|
if (value[i] == 0)
|
||||||
break;
|
break;
|
||||||
else
|
else
|
||||||
vol->target_rfc1001_name[i] = value[i];
|
vol->target_rfc1001_name[i] =
|
||||||
|
value[i];
|
||||||
}
|
}
|
||||||
/* The string has 16th byte zero still from
|
/* The string has 16th byte zero still from
|
||||||
set at top of the function */
|
set at top of the function */
|
||||||
if ((i == 15) && (value[i] != 0))
|
if ((i == 15) && (value[i] != 0))
|
||||||
printk(KERN_WARNING "CIFS: server netbiosname longer than 15 truncated.\n");
|
printk(KERN_WARNING "CIFS: server net"
|
||||||
|
"biosname longer than 15 truncated.\n");
|
||||||
}
|
}
|
||||||
} else if (strnicmp(data, "credentials", 4) == 0) {
|
} else if (strnicmp(data, "credentials", 4) == 0) {
|
||||||
/* ignore */
|
/* ignore */
|
||||||
|
@ -1177,6 +1194,10 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
|
||||||
vol->posix_paths = 1;
|
vol->posix_paths = 1;
|
||||||
} else if (strnicmp(data, "noposixpaths", 12) == 0) {
|
} else if (strnicmp(data, "noposixpaths", 12) == 0) {
|
||||||
vol->posix_paths = 0;
|
vol->posix_paths = 0;
|
||||||
|
} else if (strnicmp(data, "nounix", 6) == 0) {
|
||||||
|
vol->no_linux_ext = 1;
|
||||||
|
} else if (strnicmp(data, "nolinux", 7) == 0) {
|
||||||
|
vol->no_linux_ext = 1;
|
||||||
} else if ((strnicmp(data, "nocase", 6) == 0) ||
|
} else if ((strnicmp(data, "nocase", 6) == 0) ||
|
||||||
(strnicmp(data, "ignorecase", 10) == 0)) {
|
(strnicmp(data, "ignorecase", 10) == 0)) {
|
||||||
vol->nocase = 1;
|
vol->nocase = 1;
|
||||||
|
@ -1188,7 +1209,8 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
|
||||||
/* turn off mandatory locking in mode
|
/* turn off mandatory locking in mode
|
||||||
if remote locking is turned off since the
|
if remote locking is turned off since the
|
||||||
local vfs will do advisory */
|
local vfs will do advisory */
|
||||||
if(vol->file_mode == (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
|
if (vol->file_mode ==
|
||||||
|
(S_IALLUGO & ~(S_ISUID | S_IXGRP)))
|
||||||
vol->file_mode = S_IALLUGO;
|
vol->file_mode = S_IALLUGO;
|
||||||
} else if (strnicmp(data, "setuids", 7) == 0) {
|
} else if (strnicmp(data, "setuids", 7) == 0) {
|
||||||
vol->setuids = 1;
|
vol->setuids = 1;
|
||||||
|
@ -1228,17 +1250,22 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
|
||||||
} else if (strnlen(value, 49) == 48) {
|
} else if (strnlen(value, 49) == 48) {
|
||||||
vol->in6_addr = value;
|
vol->in6_addr = value;
|
||||||
} else {
|
} else {
|
||||||
printk(KERN_WARNING "CIFS: ip v6 address not 48 characters long\n");
|
printk(KERN_WARNING "CIFS: ip v6 address not "
|
||||||
|
"48 characters long\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
} else if (strnicmp(data, "noac", 4) == 0) {
|
} else if (strnicmp(data, "noac", 4) == 0) {
|
||||||
printk(KERN_WARNING "CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
|
printk(KERN_WARNING "CIFS: Mount option noac not "
|
||||||
|
"supported. Instead set "
|
||||||
|
"/proc/fs/cifs/LookupCacheEnabled to 0\n");
|
||||||
} else
|
} else
|
||||||
printk(KERN_WARNING "CIFS: Unknown mount option %s\n",data);
|
printk(KERN_WARNING "CIFS: Unknown mount option %s\n",
|
||||||
|
data);
|
||||||
}
|
}
|
||||||
if (vol->UNC == NULL) {
|
if (vol->UNC == NULL) {
|
||||||
if (devname == NULL) {
|
if (devname == NULL) {
|
||||||
printk(KERN_WARNING "CIFS: Missing UNC name for mount target\n");
|
printk(KERN_WARNING "CIFS: Missing UNC name for mount "
|
||||||
|
"target\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if ((temp_len = strnlen(devname, 300)) < 300) {
|
if ((temp_len = strnlen(devname, 300)) < 300) {
|
||||||
|
@ -1250,7 +1277,8 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
|
||||||
vol->UNC[0] = '\\';
|
vol->UNC[0] = '\\';
|
||||||
vol->UNC[1] = '\\';
|
vol->UNC[1] = '\\';
|
||||||
} else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
|
} else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
|
||||||
printk(KERN_WARNING "CIFS: UNC Path does not begin with // or \\\\ \n");
|
printk(KERN_WARNING "CIFS: UNC Path does not "
|
||||||
|
"begin with // or \\\\ \n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1282,14 +1310,20 @@ cifs_find_tcp_session(struct in_addr * target_ip_addr,
|
||||||
== target_ip_addr->s_addr)) || (target_ip6_addr
|
== target_ip_addr->s_addr)) || (target_ip6_addr
|
||||||
&& memcmp(&ses->server->addr.sockAddr6.sin6_addr,
|
&& memcmp(&ses->server->addr.sockAddr6.sin6_addr,
|
||||||
target_ip6_addr, sizeof(*target_ip6_addr)))) {
|
target_ip6_addr, sizeof(*target_ip6_addr)))) {
|
||||||
/* BB lock server and tcp session and increment use count here?? */
|
/* BB lock server and tcp session and increment
|
||||||
*psrvTcp = ses->server; /* found a match on the TCP session */
|
use count here?? */
|
||||||
|
|
||||||
|
/* found a match on the TCP session */
|
||||||
|
*psrvTcp = ses->server;
|
||||||
|
|
||||||
/* BB check if reconnection needed */
|
/* BB check if reconnection needed */
|
||||||
if (strncmp
|
if (strncmp
|
||||||
(ses->userName, userName,
|
(ses->userName, userName,
|
||||||
MAX_USERNAME_SIZE) == 0){
|
MAX_USERNAME_SIZE) == 0){
|
||||||
read_unlock(&GlobalSMBSeslock);
|
read_unlock(&GlobalSMBSeslock);
|
||||||
return ses; /* found exact match on both tcp and SMB sessions */
|
/* Found exact match on both TCP and
|
||||||
|
SMB sessions */
|
||||||
|
return ses;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1320,7 +1354,8 @@ find_unc(__be32 new_target_ip_addr, char *uncName, char *userName)
|
||||||
/* BB lock tcon, server and tcp session and increment use count here? */
|
/* BB lock tcon, server and tcp session and increment use count here? */
|
||||||
/* found a match on the TCP session */
|
/* found a match on the TCP session */
|
||||||
/* BB check if reconnection needed */
|
/* BB check if reconnection needed */
|
||||||
cFYI(1,("IP match, old UNC: %s new: %s",
|
cFYI(1,
|
||||||
|
("IP match, old UNC: %s new: %s",
|
||||||
tcon->treeName, uncName));
|
tcon->treeName, uncName));
|
||||||
if (strncmp
|
if (strncmp
|
||||||
(tcon->treeName, uncName,
|
(tcon->treeName, uncName,
|
||||||
|
@ -1368,9 +1403,8 @@ connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
|
get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path,
|
||||||
const char *old_path, const struct nls_table *nls_codepage,
|
const struct nls_table *nls_codepage, unsigned int *pnum_referrals,
|
||||||
unsigned int *pnum_referrals,
|
|
||||||
unsigned char **preferrals, int remap)
|
unsigned char **preferrals, int remap)
|
||||||
{
|
{
|
||||||
char *temp_unc;
|
char *temp_unc;
|
||||||
|
@ -1380,7 +1414,8 @@ get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
|
||||||
|
|
||||||
if (pSesInfo->ipc_tid == 0) {
|
if (pSesInfo->ipc_tid == 0) {
|
||||||
temp_unc = kmalloc(2 /* for slashes */ +
|
temp_unc = kmalloc(2 /* for slashes */ +
|
||||||
strnlen(pSesInfo->serverName,SERVER_NAME_LEN_WITH_NULL * 2)
|
strnlen(pSesInfo->serverName,
|
||||||
|
SERVER_NAME_LEN_WITH_NULL * 2)
|
||||||
+ 1 + 4 /* slash IPC$ */ + 2,
|
+ 1 + 4 /* slash IPC$ */ + 2,
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (temp_unc == NULL)
|
if (temp_unc == NULL)
|
||||||
|
@ -1425,7 +1460,8 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
|
||||||
__be16 orig_port = 0;
|
__be16 orig_port = 0;
|
||||||
|
|
||||||
if (*csocket == NULL) {
|
if (*csocket == NULL) {
|
||||||
rc = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
|
rc = sock_create_kern(PF_INET, SOCK_STREAM,
|
||||||
|
IPPROTO_TCP, csocket);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
cERROR(1, ("Error %d creating socket", rc));
|
cERROR(1, ("Error %d creating socket", rc));
|
||||||
*csocket = NULL;
|
*csocket = NULL;
|
||||||
|
@ -1465,7 +1501,8 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
|
||||||
if (!connected) {
|
if (!connected) {
|
||||||
psin_server->sin_port = htons(RFC1001_PORT);
|
psin_server->sin_port = htons(RFC1001_PORT);
|
||||||
rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
|
rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
|
||||||
psin_server, sizeof (struct sockaddr_in),0);
|
psin_server,
|
||||||
|
sizeof (struct sockaddr_in), 0);
|
||||||
if (rc >= 0)
|
if (rc >= 0)
|
||||||
connected = 1;
|
connected = 1;
|
||||||
}
|
}
|
||||||
|
@ -1483,7 +1520,8 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
|
||||||
/* Eventually check for other socket options to change from
|
/* Eventually check for other socket options to change from
|
||||||
the default. sock_setsockopt not used because it expects
|
the default. sock_setsockopt not used because it expects
|
||||||
user space buffer */
|
user space buffer */
|
||||||
cFYI(1,("sndbuf %d rcvbuf %d rcvtimeo 0x%lx",(*csocket)->sk->sk_sndbuf,
|
cFYI(1, ("sndbuf %d rcvbuf %d rcvtimeo 0x%lx",
|
||||||
|
(*csocket)->sk->sk_sndbuf,
|
||||||
(*csocket)->sk->sk_rcvbuf, (*csocket)->sk->sk_rcvtimeo));
|
(*csocket)->sk->sk_rcvbuf, (*csocket)->sk->sk_rcvtimeo));
|
||||||
(*csocket)->sk->sk_rcvtimeo = 7 * HZ;
|
(*csocket)->sk->sk_rcvtimeo = 7 * HZ;
|
||||||
/* make the bufsizes depend on wsize/rsize and max requests */
|
/* make the bufsizes depend on wsize/rsize and max requests */
|
||||||
|
@ -1499,7 +1537,8 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
|
||||||
sessinit is sent but no second negprot */
|
sessinit is sent but no second negprot */
|
||||||
struct rfc1002_session_packet *ses_init_buf;
|
struct rfc1002_session_packet *ses_init_buf;
|
||||||
struct smb_hdr *smb_buf;
|
struct smb_hdr *smb_buf;
|
||||||
ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet), GFP_KERNEL);
|
ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
|
||||||
|
GFP_KERNEL);
|
||||||
if (ses_init_buf) {
|
if (ses_init_buf) {
|
||||||
ses_init_buf->trailer.session_req.called_len = 32;
|
ses_init_buf->trailer.session_req.called_len = 32;
|
||||||
if (target_name && (target_name[0] != 0)) {
|
if (target_name && (target_name[0] != 0)) {
|
||||||
|
@ -1553,7 +1592,8 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
|
||||||
__be16 orig_port = 0;
|
__be16 orig_port = 0;
|
||||||
|
|
||||||
if (*csocket == NULL) {
|
if (*csocket == NULL) {
|
||||||
rc = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
|
rc = sock_create_kern(PF_INET6, SOCK_STREAM,
|
||||||
|
IPPROTO_TCP, csocket);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
cERROR(1, ("Error %d creating ipv6 socket", rc));
|
cERROR(1, ("Error %d creating ipv6 socket", rc));
|
||||||
*csocket = NULL;
|
*csocket = NULL;
|
||||||
|
@ -1631,6 +1671,18 @@ void reset_cifs_unix_caps(int xid, struct cifsTconInfo * tcon,
|
||||||
* and once without posixacls or posix paths? */
|
* and once without posixacls or posix paths? */
|
||||||
__u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
|
__u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
|
||||||
|
|
||||||
|
if (vol_info && vol_info->no_linux_ext) {
|
||||||
|
tcon->fsUnixInfo.Capability = 0;
|
||||||
|
tcon->unix_ext = 0; /* Unix Extensions disabled */
|
||||||
|
cFYI(1, ("Linux protocol extensions disabled"));
|
||||||
|
return;
|
||||||
|
} else if (vol_info)
|
||||||
|
tcon->unix_ext = 1; /* Unix Extensions supported */
|
||||||
|
|
||||||
|
if (tcon->unix_ext == 0) {
|
||||||
|
cFYI(1, ("Unix extensions disabled so not set on reconnect"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
|
if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
|
||||||
__u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
|
__u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
|
||||||
|
@ -1644,10 +1696,6 @@ void reset_cifs_unix_caps(int xid, struct cifsTconInfo * tcon,
|
||||||
cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
|
cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
|
||||||
if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0)
|
if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0)
|
||||||
cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
|
cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cap &= CIFS_UNIX_CAP_MASK;
|
cap &= CIFS_UNIX_CAP_MASK;
|
||||||
|
@ -1674,6 +1722,16 @@ void reset_cifs_unix_caps(int xid, struct cifsTconInfo * tcon,
|
||||||
if (sb && (CIFS_SB(sb)->prepathlen > 0))
|
if (sb && (CIFS_SB(sb)->prepathlen > 0))
|
||||||
CIFS_SB(sb)->prepath[0] = CIFS_DIR_SEP(CIFS_SB(sb));
|
CIFS_SB(sb)->prepath[0] = CIFS_DIR_SEP(CIFS_SB(sb));
|
||||||
|
|
||||||
|
if (sb && (CIFS_SB(sb)->rsize > 127 * 1024)) {
|
||||||
|
if ((cap & CIFS_UNIX_LARGE_READ_CAP) == 0) {
|
||||||
|
CIFS_SB(sb)->rsize = 127 * 1024;
|
||||||
|
#ifdef CONFIG_CIFS_DEBUG2
|
||||||
|
cFYI(1, ("larger reads not supported by srv"));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
cFYI(1, ("Negotiate caps 0x%x", (int)cap));
|
cFYI(1, ("Negotiate caps 0x%x", (int)cap));
|
||||||
#ifdef CONFIG_CIFS_DEBUG2
|
#ifdef CONFIG_CIFS_DEBUG2
|
||||||
if (cap & CIFS_UNIX_FCNTL_CAP)
|
if (cap & CIFS_UNIX_FCNTL_CAP)
|
||||||
|
@ -1686,6 +1744,10 @@ void reset_cifs_unix_caps(int xid, struct cifsTconInfo * tcon,
|
||||||
cFYI(1, ("XATTR cap"));
|
cFYI(1, ("XATTR cap"));
|
||||||
if (cap & CIFS_UNIX_POSIX_ACL_CAP)
|
if (cap & CIFS_UNIX_POSIX_ACL_CAP)
|
||||||
cFYI(1, ("POSIX ACL cap"));
|
cFYI(1, ("POSIX ACL cap"));
|
||||||
|
if (cap & CIFS_UNIX_LARGE_READ_CAP)
|
||||||
|
cFYI(1, ("very large read cap"));
|
||||||
|
if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
|
||||||
|
cFYI(1, ("very large write cap"));
|
||||||
#endif /* CIFS_DEBUG2 */
|
#endif /* CIFS_DEBUG2 */
|
||||||
if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
|
if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
|
||||||
cFYI(1, ("setting capabilities failed"));
|
cFYI(1, ("setting capabilities failed"));
|
||||||
|
@ -1740,11 +1802,13 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (volume_info.UNCip && volume_info.UNC) {
|
if (volume_info.UNCip && volume_info.UNC) {
|
||||||
rc = cifs_inet_pton(AF_INET, volume_info.UNCip,&sin_server.sin_addr.s_addr);
|
rc = cifs_inet_pton(AF_INET, volume_info.UNCip,
|
||||||
|
&sin_server.sin_addr.s_addr);
|
||||||
|
|
||||||
if (rc <= 0) {
|
if (rc <= 0) {
|
||||||
/* not ipv4 address, try ipv6 */
|
/* not ipv4 address, try ipv6 */
|
||||||
rc = cifs_inet_pton(AF_INET6,volume_info.UNCip,&sin_server6.sin6_addr.in6_u);
|
rc = cifs_inet_pton(AF_INET6, volume_info.UNCip,
|
||||||
|
&sin_server6.sin6_addr.in6_u);
|
||||||
if (rc > 0)
|
if (rc > 0)
|
||||||
address_type = AF_INET6;
|
address_type = AF_INET6;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1764,7 +1828,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||||
/* success */
|
/* success */
|
||||||
rc = 0;
|
rc = 0;
|
||||||
} else if (volume_info.UNCip) {
|
} else if (volume_info.UNCip) {
|
||||||
/* BB using ip addr as server name connect to the DFS root below */
|
/* BB using ip addr as server name to connect to the
|
||||||
|
DFS root below */
|
||||||
cERROR(1, ("Connecting to DFS root not implemented yet"));
|
cERROR(1, ("Connecting to DFS root not implemented yet"));
|
||||||
kfree(volume_info.UNC);
|
kfree(volume_info.UNC);
|
||||||
kfree(volume_info.password);
|
kfree(volume_info.password);
|
||||||
|
@ -1773,7 +1838,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
} else /* which servers DFS root would we conect to */ {
|
} else /* which servers DFS root would we conect to */ {
|
||||||
cERROR(1,
|
cERROR(1,
|
||||||
("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified"));
|
("CIFS mount error: No UNC path (e.g. -o "
|
||||||
|
"unc=//192.168.1.100/public) specified"));
|
||||||
kfree(volume_info.UNC);
|
kfree(volume_info.UNC);
|
||||||
kfree(volume_info.password);
|
kfree(volume_info.password);
|
||||||
kfree(volume_info.prepath);
|
kfree(volume_info.prepath);
|
||||||
|
@ -1788,7 +1854,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||||
} else {
|
} else {
|
||||||
cifs_sb->local_nls = load_nls(volume_info.iocharset);
|
cifs_sb->local_nls = load_nls(volume_info.iocharset);
|
||||||
if (cifs_sb->local_nls == NULL) {
|
if (cifs_sb->local_nls == NULL) {
|
||||||
cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset));
|
cERROR(1, ("CIFS mount error: iocharset %s not found",
|
||||||
|
volume_info.iocharset));
|
||||||
kfree(volume_info.UNC);
|
kfree(volume_info.UNC);
|
||||||
kfree(volume_info.password);
|
kfree(volume_info.password);
|
||||||
kfree(volume_info.prepath);
|
kfree(volume_info.prepath);
|
||||||
|
@ -1814,7 +1881,6 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (srvTcp) {
|
if (srvTcp) {
|
||||||
cFYI(1, ("Existing tcp session with server found"));
|
cFYI(1, ("Existing tcp session with server found"));
|
||||||
} else { /* create socket */
|
} else { /* create socket */
|
||||||
|
@ -1832,8 +1898,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||||
volume_info.source_rfc1001_name,
|
volume_info.source_rfc1001_name,
|
||||||
volume_info.target_rfc1001_name);
|
volume_info.target_rfc1001_name);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
cERROR(1,
|
cERROR(1, ("Error connecting to IPv4 socket. "
|
||||||
("Error connecting to IPv4 socket. Aborting operation"));
|
"Aborting operation"));
|
||||||
if (csocket != NULL)
|
if (csocket != NULL)
|
||||||
sock_release(csocket);
|
sock_release(csocket);
|
||||||
kfree(volume_info.UNC);
|
kfree(volume_info.UNC);
|
||||||
|
@ -1854,7 +1920,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||||
return rc;
|
return rc;
|
||||||
} else {
|
} else {
|
||||||
memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
|
memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
|
||||||
memcpy(&srvTcp->addr.sockAddr, &sin_server, sizeof (struct sockaddr_in));
|
memcpy(&srvTcp->addr.sockAddr, &sin_server,
|
||||||
|
sizeof (struct sockaddr_in));
|
||||||
atomic_set(&srvTcp->inFlight, 0);
|
atomic_set(&srvTcp->inFlight, 0);
|
||||||
/* BB Add code for ipv6 case too */
|
/* BB Add code for ipv6 case too */
|
||||||
srvTcp->ssocket = csocket;
|
srvTcp->ssocket = csocket;
|
||||||
|
@ -1881,8 +1948,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||||
}
|
}
|
||||||
wait_for_completion(&cifsd_complete);
|
wait_for_completion(&cifsd_complete);
|
||||||
rc = 0;
|
rc = 0;
|
||||||
memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
|
memcpy(srvTcp->workstation_RFC1001_name,
|
||||||
memcpy(srvTcp->server_RFC1001_name, volume_info.target_rfc1001_name,16);
|
volume_info.source_rfc1001_name, 16);
|
||||||
|
memcpy(srvTcp->server_RFC1001_name,
|
||||||
|
volume_info.target_rfc1001_name, 16);
|
||||||
srvTcp->sequence_number = 0;
|
srvTcp->sequence_number = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1909,7 +1978,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||||
pSesInfo->password = volume_info.password;
|
pSesInfo->password = volume_info.password;
|
||||||
if (volume_info.username)
|
if (volume_info.username)
|
||||||
strncpy(pSesInfo->userName,
|
strncpy(pSesInfo->userName,
|
||||||
volume_info.username,MAX_USERNAME_SIZE);
|
volume_info.username,
|
||||||
|
MAX_USERNAME_SIZE);
|
||||||
if (volume_info.domainname) {
|
if (volume_info.domainname) {
|
||||||
int len = strlen(volume_info.domainname);
|
int len = strlen(volume_info.domainname);
|
||||||
pSesInfo->domainName =
|
pSesInfo->domainName =
|
||||||
|
@ -1922,7 +1992,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||||
pSesInfo->overrideSecFlg = volume_info.secFlg;
|
pSesInfo->overrideSecFlg = volume_info.secFlg;
|
||||||
down(&pSesInfo->sesSem);
|
down(&pSesInfo->sesSem);
|
||||||
/* BB FIXME need to pass vol->secFlgs BB */
|
/* BB FIXME need to pass vol->secFlgs BB */
|
||||||
rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
|
rc = cifs_setup_session(xid, pSesInfo,
|
||||||
|
cifs_sb->local_nls);
|
||||||
up(&pSesInfo->sesSem);
|
up(&pSesInfo->sesSem);
|
||||||
if (!rc)
|
if (!rc)
|
||||||
atomic_inc(&srvTcp->socketUseCount);
|
atomic_inc(&srvTcp->socketUseCount);
|
||||||
|
@ -1936,13 +2007,14 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||||
cERROR(1, ("rsize %d too large, using MaxBufSize",
|
cERROR(1, ("rsize %d too large, using MaxBufSize",
|
||||||
volume_info.rsize));
|
volume_info.rsize));
|
||||||
cifs_sb->rsize = CIFSMaxBufSize;
|
cifs_sb->rsize = CIFSMaxBufSize;
|
||||||
} else if((volume_info.rsize) && (volume_info.rsize <= CIFSMaxBufSize))
|
} else if ((volume_info.rsize) &&
|
||||||
|
(volume_info.rsize <= CIFSMaxBufSize))
|
||||||
cifs_sb->rsize = volume_info.rsize;
|
cifs_sb->rsize = volume_info.rsize;
|
||||||
else /* default */
|
else /* default */
|
||||||
cifs_sb->rsize = CIFSMaxBufSize;
|
cifs_sb->rsize = CIFSMaxBufSize;
|
||||||
|
|
||||||
if (volume_info.wsize > PAGEVEC_SIZE * PAGE_CACHE_SIZE) {
|
if (volume_info.wsize > PAGEVEC_SIZE * PAGE_CACHE_SIZE) {
|
||||||
cERROR(1,("wsize %d too large using 4096 instead",
|
cERROR(1, ("wsize %d too large, using 4096 instead",
|
||||||
volume_info.wsize));
|
volume_info.wsize));
|
||||||
cifs_sb->wsize = 4096;
|
cifs_sb->wsize = 4096;
|
||||||
} else if (volume_info.wsize)
|
} else if (volume_info.wsize)
|
||||||
|
@ -1961,7 +2033,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||||
if (cifs_sb->rsize < 2048) {
|
if (cifs_sb->rsize < 2048) {
|
||||||
cifs_sb->rsize = 2048;
|
cifs_sb->rsize = 2048;
|
||||||
/* Windows ME may prefer this */
|
/* Windows ME may prefer this */
|
||||||
cFYI(1,("readsize set to minimum 2048"));
|
cFYI(1, ("readsize set to minimum: 2048"));
|
||||||
}
|
}
|
||||||
/* calculate prepath */
|
/* calculate prepath */
|
||||||
cifs_sb->prepath = volume_info.prepath;
|
cifs_sb->prepath = volume_info.prepath;
|
||||||
|
@ -2075,7 +2147,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||||
always wake up processes blocked in
|
always wake up processes blocked in
|
||||||
tcp in recv_mesg then we could remove the
|
tcp in recv_mesg then we could remove the
|
||||||
send_sig call */
|
send_sig call */
|
||||||
send_sig(SIGKILL,srvTcp->tsk,1);
|
force_sig(SIGKILL, srvTcp->tsk);
|
||||||
tsk = srvTcp->tsk;
|
tsk = srvTcp->tsk;
|
||||||
if (tsk)
|
if (tsk)
|
||||||
kthread_stop(tsk);
|
kthread_stop(tsk);
|
||||||
|
@ -2092,9 +2164,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||||
temp_rc = CIFSSMBLogoff(xid, pSesInfo);
|
temp_rc = CIFSSMBLogoff(xid, pSesInfo);
|
||||||
/* if the socketUseCount is now zero */
|
/* if the socketUseCount is now zero */
|
||||||
if ((temp_rc == -ESHUTDOWN) &&
|
if ((temp_rc == -ESHUTDOWN) &&
|
||||||
(pSesInfo->server) && (pSesInfo->server->tsk)) {
|
(pSesInfo->server) &&
|
||||||
|
(pSesInfo->server->tsk)) {
|
||||||
struct task_struct *tsk;
|
struct task_struct *tsk;
|
||||||
send_sig(SIGKILL,pSesInfo->server->tsk,1);
|
force_sig(SIGKILL,
|
||||||
|
pSesInfo->server->tsk);
|
||||||
tsk = pSesInfo->server->tsk;
|
tsk = pSesInfo->server->tsk;
|
||||||
if (tsk)
|
if (tsk)
|
||||||
kthread_stop(tsk);
|
kthread_stop(tsk);
|
||||||
|
@ -2116,8 +2190,18 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||||
|
|
||||||
/* tell server which Unix caps we support */
|
/* tell server which Unix caps we support */
|
||||||
if (tcon->ses->capabilities & CAP_UNIX)
|
if (tcon->ses->capabilities & CAP_UNIX)
|
||||||
|
/* reset of caps checks mount to see if unix extensions
|
||||||
|
disabled for just this mount */
|
||||||
reset_cifs_unix_caps(xid, tcon, sb, &volume_info);
|
reset_cifs_unix_caps(xid, tcon, sb, &volume_info);
|
||||||
|
else
|
||||||
|
tcon->unix_ext = 0; /* server does not support them */
|
||||||
|
|
||||||
|
if ((tcon->unix_ext == 0) && (cifs_sb->rsize > (1024 * 127))) {
|
||||||
|
cifs_sb->rsize = 1024 * 127;
|
||||||
|
#ifdef CONFIG_CIFS_DEBUG2
|
||||||
|
cFYI(1, ("no very large read support, rsize now 127K"));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X))
|
if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X))
|
||||||
cifs_sb->wsize = min(cifs_sb->wsize,
|
cifs_sb->wsize = min(cifs_sb->wsize,
|
||||||
(tcon->ses->server->maxBuf -
|
(tcon->ses->server->maxBuf -
|
||||||
|
@ -2178,7 +2262,8 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
||||||
pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
|
pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
|
||||||
pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
|
pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
|
||||||
|
|
||||||
if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
|
if (ses->server->secMode &
|
||||||
|
(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
|
||||||
smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
|
smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
|
||||||
|
|
||||||
capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
|
capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
|
||||||
|
@ -2282,8 +2367,9 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
||||||
__u16 action = le16_to_cpu(pSMBr->resp.Action);
|
__u16 action = le16_to_cpu(pSMBr->resp.Action);
|
||||||
__u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
|
__u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
|
||||||
if (action & GUEST_LOGIN)
|
if (action & GUEST_LOGIN)
|
||||||
cFYI(1, (" Guest login")); /* do we want to mark SesInfo struct ? */
|
cFYI(1, (" Guest login")); /* BB mark SesInfo struct? */
|
||||||
ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
|
ses->Suid = smb_buffer_response->Uid; /* UID left in wire format
|
||||||
|
(little endian) */
|
||||||
cFYI(1, ("UID = %d ", ses->Suid));
|
cFYI(1, ("UID = %d ", ses->Suid));
|
||||||
/* response can have either 3 or 4 word count - Samba sends 3 */
|
/* response can have either 3 or 4 word count - Samba sends 3 */
|
||||||
bcc_ptr = pByteArea(smb_buffer_response);
|
bcc_ptr = pByteArea(smb_buffer_response);
|
||||||
|
@ -2297,7 +2383,9 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
||||||
if ((long) (bcc_ptr) % 2) {
|
if ((long) (bcc_ptr) % 2) {
|
||||||
remaining_words =
|
remaining_words =
|
||||||
(BCC(smb_buffer_response) - 1) / 2;
|
(BCC(smb_buffer_response) - 1) / 2;
|
||||||
bcc_ptr++; /* Unicode strings must be word aligned */
|
/* Unicode strings must be word
|
||||||
|
aligned */
|
||||||
|
bcc_ptr++;
|
||||||
} else {
|
} else {
|
||||||
remaining_words =
|
remaining_words =
|
||||||
BCC(smb_buffer_response) / 2;
|
BCC(smb_buffer_response) / 2;
|
||||||
|
@ -2310,11 +2398,13 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
||||||
terminating last Unicode string in response */
|
terminating last Unicode string in response */
|
||||||
if (ses->serverOS)
|
if (ses->serverOS)
|
||||||
kfree(ses->serverOS);
|
kfree(ses->serverOS);
|
||||||
ses->serverOS = kzalloc(2 * (len + 1), GFP_KERNEL);
|
ses->serverOS = kzalloc(2 * (len + 1),
|
||||||
|
GFP_KERNEL);
|
||||||
if (ses->serverOS == NULL)
|
if (ses->serverOS == NULL)
|
||||||
goto sesssetup_nomem;
|
goto sesssetup_nomem;
|
||||||
cifs_strfromUCS_le(ses->serverOS,
|
cifs_strfromUCS_le(ses->serverOS,
|
||||||
(__le16 *)bcc_ptr, len,nls_codepage);
|
(__le16 *)bcc_ptr,
|
||||||
|
len, nls_codepage);
|
||||||
bcc_ptr += 2 * (len + 1);
|
bcc_ptr += 2 * (len + 1);
|
||||||
remaining_words -= len + 1;
|
remaining_words -= len + 1;
|
||||||
ses->serverOS[2 * len] = 0;
|
ses->serverOS[2 * len] = 0;
|
||||||
|
@ -2323,11 +2413,13 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
||||||
len = UniStrnlen((wchar_t *)bcc_ptr,
|
len = UniStrnlen((wchar_t *)bcc_ptr,
|
||||||
remaining_words-1);
|
remaining_words-1);
|
||||||
kfree(ses->serverNOS);
|
kfree(ses->serverNOS);
|
||||||
ses->serverNOS = kzalloc(2 * (len + 1),GFP_KERNEL);
|
ses->serverNOS = kzalloc(2 * (len + 1),
|
||||||
|
GFP_KERNEL);
|
||||||
if (ses->serverNOS == NULL)
|
if (ses->serverNOS == NULL)
|
||||||
goto sesssetup_nomem;
|
goto sesssetup_nomem;
|
||||||
cifs_strfromUCS_le(ses->serverNOS,
|
cifs_strfromUCS_le(ses->serverNOS,
|
||||||
(__le16 *)bcc_ptr,len,nls_codepage);
|
(__le16 *)bcc_ptr,
|
||||||
|
len, nls_codepage);
|
||||||
bcc_ptr += 2 * (len + 1);
|
bcc_ptr += 2 * (len + 1);
|
||||||
ses->serverNOS[2 * len] = 0;
|
ses->serverNOS[2 * len] = 0;
|
||||||
ses->serverNOS[1 + (2 * len)] = 0;
|
ses->serverNOS[1 + (2 * len)] = 0;
|
||||||
|
@ -2339,26 +2431,31 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
||||||
remaining_words -= len + 1;
|
remaining_words -= len + 1;
|
||||||
if (remaining_words > 0) {
|
if (remaining_words > 0) {
|
||||||
len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
|
len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
|
||||||
/* last string is not always null terminated (for e.g. for Windows XP & 2000) */
|
/* last string is not always null terminated
|
||||||
|
(for e.g. for Windows XP & 2000) */
|
||||||
if (ses->serverDomain)
|
if (ses->serverDomain)
|
||||||
kfree(ses->serverDomain);
|
kfree(ses->serverDomain);
|
||||||
ses->serverDomain =
|
ses->serverDomain =
|
||||||
kzalloc(2*(len+1),GFP_KERNEL);
|
kzalloc(2*(len+1),
|
||||||
|
GFP_KERNEL);
|
||||||
if (ses->serverDomain == NULL)
|
if (ses->serverDomain == NULL)
|
||||||
goto sesssetup_nomem;
|
goto sesssetup_nomem;
|
||||||
cifs_strfromUCS_le(ses->serverDomain,
|
cifs_strfromUCS_le(ses->serverDomain,
|
||||||
(__le16 *)bcc_ptr,len,nls_codepage);
|
(__le16 *)bcc_ptr,
|
||||||
|
len, nls_codepage);
|
||||||
bcc_ptr += 2 * (len + 1);
|
bcc_ptr += 2 * (len + 1);
|
||||||
ses->serverDomain[2*len] = 0;
|
ses->serverDomain[2*len] = 0;
|
||||||
ses->serverDomain[1+(2*len)] = 0;
|
ses->serverDomain[1+(2*len)] = 0;
|
||||||
} /* else no more room so create dummy domain string */
|
} else { /* else no more room so create
|
||||||
else {
|
dummy domain string */
|
||||||
if (ses->serverDomain)
|
if (ses->serverDomain)
|
||||||
kfree(ses->serverDomain);
|
kfree(ses->serverDomain);
|
||||||
ses->serverDomain =
|
ses->serverDomain =
|
||||||
kzalloc(2, GFP_KERNEL);
|
kzalloc(2, GFP_KERNEL);
|
||||||
}
|
}
|
||||||
} else { /* no room so create dummy domain and NOS string */
|
} else { /* no room so create dummy domain
|
||||||
|
and NOS string */
|
||||||
|
|
||||||
/* if these kcallocs fail not much we
|
/* if these kcallocs fail not much we
|
||||||
can do, but better to not fail the
|
can do, but better to not fail the
|
||||||
sesssetup itself */
|
sesssetup itself */
|
||||||
|
@ -2375,18 +2472,21 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
||||||
pByteArea(smb_buffer_response)
|
pByteArea(smb_buffer_response)
|
||||||
<= BCC(smb_buffer_response)) {
|
<= BCC(smb_buffer_response)) {
|
||||||
kfree(ses->serverOS);
|
kfree(ses->serverOS);
|
||||||
ses->serverOS = kzalloc(len + 1,GFP_KERNEL);
|
ses->serverOS = kzalloc(len + 1,
|
||||||
|
GFP_KERNEL);
|
||||||
if (ses->serverOS == NULL)
|
if (ses->serverOS == NULL)
|
||||||
goto sesssetup_nomem;
|
goto sesssetup_nomem;
|
||||||
strncpy(ses->serverOS, bcc_ptr, len);
|
strncpy(ses->serverOS, bcc_ptr, len);
|
||||||
|
|
||||||
bcc_ptr += len;
|
bcc_ptr += len;
|
||||||
bcc_ptr[0] = 0; /* null terminate the string */
|
/* null terminate the string */
|
||||||
|
bcc_ptr[0] = 0;
|
||||||
bcc_ptr++;
|
bcc_ptr++;
|
||||||
|
|
||||||
len = strnlen(bcc_ptr, 1024);
|
len = strnlen(bcc_ptr, 1024);
|
||||||
kfree(ses->serverNOS);
|
kfree(ses->serverNOS);
|
||||||
ses->serverNOS = kzalloc(len + 1,GFP_KERNEL);
|
ses->serverNOS = kzalloc(len + 1,
|
||||||
|
GFP_KERNEL);
|
||||||
if (ses->serverNOS == NULL)
|
if (ses->serverNOS == NULL)
|
||||||
goto sesssetup_nomem;
|
goto sesssetup_nomem;
|
||||||
strncpy(ses->serverNOS, bcc_ptr, len);
|
strncpy(ses->serverNOS, bcc_ptr, len);
|
||||||
|
@ -2397,21 +2497,25 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
||||||
len = strnlen(bcc_ptr, 1024);
|
len = strnlen(bcc_ptr, 1024);
|
||||||
if (ses->serverDomain)
|
if (ses->serverDomain)
|
||||||
kfree(ses->serverDomain);
|
kfree(ses->serverDomain);
|
||||||
ses->serverDomain = kzalloc(len + 1,GFP_KERNEL);
|
ses->serverDomain = kzalloc(len + 1,
|
||||||
|
GFP_KERNEL);
|
||||||
if (ses->serverDomain == NULL)
|
if (ses->serverDomain == NULL)
|
||||||
goto sesssetup_nomem;
|
goto sesssetup_nomem;
|
||||||
strncpy(ses->serverDomain, bcc_ptr, len);
|
strncpy(ses->serverDomain, bcc_ptr,
|
||||||
|
len);
|
||||||
bcc_ptr += len;
|
bcc_ptr += len;
|
||||||
bcc_ptr[0] = 0;
|
bcc_ptr[0] = 0;
|
||||||
bcc_ptr++;
|
bcc_ptr++;
|
||||||
} else
|
} else
|
||||||
cFYI(1,
|
cFYI(1,
|
||||||
("Variable field of length %d extends beyond end of smb ",
|
("Variable field of length %d "
|
||||||
|
"extends beyond end of smb ",
|
||||||
len));
|
len));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
cERROR(1,
|
cERROR(1,
|
||||||
(" Security Blob Length extends beyond end of SMB"));
|
(" Security Blob Length extends beyond "
|
||||||
|
"end of SMB"));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
cERROR(1,
|
cERROR(1,
|
||||||
|
@ -2623,7 +2727,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
|
||||||
remaining_words =
|
remaining_words =
|
||||||
(BCC(smb_buffer_response)
|
(BCC(smb_buffer_response)
|
||||||
- 1) / 2;
|
- 1) / 2;
|
||||||
bcc_ptr++; /* Unicode strings must be word aligned */
|
/* Must word align unicode strings */
|
||||||
|
bcc_ptr++;
|
||||||
} else {
|
} else {
|
||||||
remaining_words =
|
remaining_words =
|
||||||
BCC
|
BCC
|
||||||
|
@ -2669,7 +2774,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
|
||||||
remaining_words -= len + 1;
|
remaining_words -= len + 1;
|
||||||
if (remaining_words > 0) {
|
if (remaining_words > 0) {
|
||||||
len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
|
len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
|
||||||
/* last string is not always null terminated (for e.g. for Windows XP & 2000) */
|
/* last string not always null terminated
|
||||||
|
(for e.g. for Windows XP & 2000) */
|
||||||
kfree(ses->serverDomain);
|
kfree(ses->serverDomain);
|
||||||
ses->serverDomain =
|
ses->serverDomain =
|
||||||
kzalloc(2 *
|
kzalloc(2 *
|
||||||
|
@ -2734,18 +2840,20 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
|
||||||
ses->serverDomain =
|
ses->serverDomain =
|
||||||
kzalloc(len + 1,
|
kzalloc(len + 1,
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
strncpy(ses->serverDomain, bcc_ptr, len);
|
strncpy(ses->serverDomain,
|
||||||
|
bcc_ptr, len);
|
||||||
bcc_ptr += len;
|
bcc_ptr += len;
|
||||||
bcc_ptr[0] = 0;
|
bcc_ptr[0] = 0;
|
||||||
bcc_ptr++;
|
bcc_ptr++;
|
||||||
} else
|
} else
|
||||||
cFYI(1,
|
cFYI(1,
|
||||||
("Variable field of length %d extends beyond end of smb",
|
("field of length %d "
|
||||||
|
"extends beyond end of smb",
|
||||||
len));
|
len));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
cERROR(1,
|
cERROR(1, ("Security Blob Length extends beyond"
|
||||||
(" Security Blob Length extends beyond end of SMB"));
|
" end of SMB"));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
cERROR(1, ("No session structure passed in."));
|
cERROR(1, ("No session structure passed in."));
|
||||||
|
@ -2903,13 +3011,17 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
||||||
cpu_to_le16(len);
|
cpu_to_le16(len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((__le16 *) bcc_ptr, "AMACHINE",64, nls_codepage);
|
/* SecurityBlob->WorkstationName.Length =
|
||||||
|
cifs_strtoUCS((__le16 *) bcc_ptr, "AMACHINE",64, nls_codepage);
|
||||||
SecurityBlob->WorkstationName.Length *= 2;
|
SecurityBlob->WorkstationName.Length *= 2;
|
||||||
SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length);
|
SecurityBlob->WorkstationName.MaximumLength =
|
||||||
SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength);
|
cpu_to_le16(SecurityBlob->WorkstationName.Length);
|
||||||
|
SecurityBlob->WorkstationName.Buffer =
|
||||||
|
cpu_to_le32(SecurityBlobLength);
|
||||||
bcc_ptr += SecurityBlob->WorkstationName.Length;
|
bcc_ptr += SecurityBlob->WorkstationName.Length;
|
||||||
SecurityBlobLength += SecurityBlob->WorkstationName.Length;
|
SecurityBlobLength += SecurityBlob->WorkstationName.Length;
|
||||||
SecurityBlob->WorkstationName.Length = cpu_to_le16(SecurityBlob->WorkstationName.Length); */
|
SecurityBlob->WorkstationName.Length =
|
||||||
|
cpu_to_le16(SecurityBlob->WorkstationName.Length); */
|
||||||
|
|
||||||
if ((long) bcc_ptr % 2) {
|
if ((long) bcc_ptr % 2) {
|
||||||
*bcc_ptr = 0;
|
*bcc_ptr = 0;
|
||||||
|
@ -2995,15 +3107,18 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
||||||
__u16 blob_len =
|
__u16 blob_len =
|
||||||
le16_to_cpu(pSMBr->resp.SecurityBlobLength);
|
le16_to_cpu(pSMBr->resp.SecurityBlobLength);
|
||||||
if (action & GUEST_LOGIN)
|
if (action & GUEST_LOGIN)
|
||||||
cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
|
cFYI(1, (" Guest login")); /* BB Should we set anything
|
||||||
|
in SesInfo struct ? */
|
||||||
/* if (SecurityBlob2->MessageType != NtLm??) {
|
/* if (SecurityBlob2->MessageType != NtLm??) {
|
||||||
cFYI("Unexpected message type on auth response is %d"));
|
cFYI("Unexpected message type on auth response is %d"));
|
||||||
} */
|
} */
|
||||||
|
|
||||||
if (ses) {
|
if (ses) {
|
||||||
cFYI(1,
|
cFYI(1,
|
||||||
("Does UID on challenge %d match auth response UID %d ",
|
("Check challenge UID %d vs auth response UID %d",
|
||||||
ses->Suid, smb_buffer_response->Uid));
|
ses->Suid, smb_buffer_response->Uid));
|
||||||
ses->Suid = smb_buffer_response->Uid; /* UID left in wire format */
|
/* UID left in wire format */
|
||||||
|
ses->Suid = smb_buffer_response->Uid;
|
||||||
bcc_ptr = pByteArea(smb_buffer_response);
|
bcc_ptr = pByteArea(smb_buffer_response);
|
||||||
/* response can have either 3 or 4 word count - Samba sends 3 */
|
/* response can have either 3 or 4 word count - Samba sends 3 */
|
||||||
if ((pSMBr->resp.hdr.WordCount == 3)
|
if ((pSMBr->resp.hdr.WordCount == 3)
|
||||||
|
@ -3124,8 +3239,10 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
||||||
|
|
||||||
len = strnlen(bcc_ptr, 1024);
|
len = strnlen(bcc_ptr, 1024);
|
||||||
kfree(ses->serverNOS);
|
kfree(ses->serverNOS);
|
||||||
ses->serverNOS = kzalloc(len+1,GFP_KERNEL);
|
ses->serverNOS = kzalloc(len+1,
|
||||||
strncpy(ses->serverNOS, bcc_ptr, len);
|
GFP_KERNEL);
|
||||||
|
strncpy(ses->serverNOS,
|
||||||
|
bcc_ptr, len);
|
||||||
bcc_ptr += len;
|
bcc_ptr += len;
|
||||||
bcc_ptr[0] = 0;
|
bcc_ptr[0] = 0;
|
||||||
bcc_ptr++;
|
bcc_ptr++;
|
||||||
|
@ -3133,19 +3250,24 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
||||||
len = strnlen(bcc_ptr, 1024);
|
len = strnlen(bcc_ptr, 1024);
|
||||||
if (ses->serverDomain)
|
if (ses->serverDomain)
|
||||||
kfree(ses->serverDomain);
|
kfree(ses->serverDomain);
|
||||||
ses->serverDomain = kzalloc(len+1,GFP_KERNEL);
|
ses->serverDomain =
|
||||||
strncpy(ses->serverDomain, bcc_ptr, len);
|
kzalloc(len+1,
|
||||||
|
GFP_KERNEL);
|
||||||
|
strncpy(ses->serverDomain,
|
||||||
|
bcc_ptr, len);
|
||||||
bcc_ptr += len;
|
bcc_ptr += len;
|
||||||
bcc_ptr[0] = 0;
|
bcc_ptr[0] = 0;
|
||||||
bcc_ptr++;
|
bcc_ptr++;
|
||||||
} else
|
} else
|
||||||
cFYI(1,
|
cFYI(1,
|
||||||
("Variable field of length %d extends beyond end of smb ",
|
("field of length %d "
|
||||||
|
"extends beyond end of smb ",
|
||||||
len));
|
len));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
cERROR(1,
|
cERROR(1,
|
||||||
(" Security Blob Length extends beyond end of SMB"));
|
(" Security Blob extends beyond end "
|
||||||
|
"of SMB"));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
cERROR(1, ("No session structure passed in."));
|
cERROR(1, ("No session structure passed in."));
|
||||||
|
@ -3285,7 +3407,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
|
||||||
bcc_ptr[1] = 0;
|
bcc_ptr[1] = 0;
|
||||||
bcc_ptr += 2;
|
bcc_ptr += 2;
|
||||||
}
|
}
|
||||||
/* else do not bother copying these informational fields */
|
/* else do not bother copying these information fields*/
|
||||||
} else {
|
} else {
|
||||||
length = strnlen(bcc_ptr, 1024);
|
length = strnlen(bcc_ptr, 1024);
|
||||||
if ((bcc_ptr + length) -
|
if ((bcc_ptr + length) -
|
||||||
|
@ -3297,7 +3419,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
|
||||||
strncpy(tcon->nativeFileSystem, bcc_ptr,
|
strncpy(tcon->nativeFileSystem, bcc_ptr,
|
||||||
length);
|
length);
|
||||||
}
|
}
|
||||||
/* else do not bother copying these informational fields */
|
/* else do not bother copying these information fields*/
|
||||||
}
|
}
|
||||||
if ((smb_buffer_response->WordCount == 3) ||
|
if ((smb_buffer_response->WordCount == 3) ||
|
||||||
(smb_buffer_response->WordCount == 7))
|
(smb_buffer_response->WordCount == 7))
|
||||||
|
@ -3344,9 +3466,9 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
|
||||||
FreeXid(xid);
|
FreeXid(xid);
|
||||||
return 0;
|
return 0;
|
||||||
} else if (rc == -ESHUTDOWN) {
|
} else if (rc == -ESHUTDOWN) {
|
||||||
cFYI(1,("Waking up socket by sending it signal"));
|
cFYI(1, ("Waking up socket by sending signal"));
|
||||||
if (cifsd_task) {
|
if (cifsd_task) {
|
||||||
send_sig(SIGKILL,cifsd_task,1);
|
force_sig(SIGKILL, cifsd_task);
|
||||||
kthread_stop(cifsd_task);
|
kthread_stop(cifsd_task);
|
||||||
}
|
}
|
||||||
rc = 0;
|
rc = 0;
|
||||||
|
@ -3403,7 +3525,8 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
|
||||||
if (linuxExtEnabled == 0)
|
if (linuxExtEnabled == 0)
|
||||||
pSesInfo->capabilities &= (~CAP_UNIX);
|
pSesInfo->capabilities &= (~CAP_UNIX);
|
||||||
/* pSesInfo->sequence_number = 0;*/
|
/* pSesInfo->sequence_number = 0;*/
|
||||||
cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d",
|
cFYI(1,
|
||||||
|
("Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d",
|
||||||
pSesInfo->server->secMode,
|
pSesInfo->server->secMode,
|
||||||
pSesInfo->server->capabilities,
|
pSesInfo->server->capabilities,
|
||||||
pSesInfo->server->timeAdj));
|
pSesInfo->server->timeAdj));
|
||||||
|
@ -3434,7 +3557,8 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
|
||||||
} else
|
} else
|
||||||
v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
|
v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
|
||||||
if (v2_response) {
|
if (v2_response) {
|
||||||
CalcNTLMv2_response(pSesInfo,v2_response);
|
CalcNTLMv2_response(pSesInfo,
|
||||||
|
v2_response);
|
||||||
/* if (first_time)
|
/* if (first_time)
|
||||||
cifs_calculate_ntlmv2_mac_key(
|
cifs_calculate_ntlmv2_mac_key(
|
||||||
pSesInfo->server->mac_signing_key,
|
pSesInfo->server->mac_signing_key,
|
||||||
|
@ -3453,7 +3577,7 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
|
||||||
|
|
||||||
if (first_time)
|
if (first_time)
|
||||||
cifs_calculate_mac_key(
|
cifs_calculate_mac_key(
|
||||||
pSesInfo->server->mac_signing_key,
|
&pSesInfo->server->mac_signing_key,
|
||||||
ntlm_session_key,
|
ntlm_session_key,
|
||||||
pSesInfo->password);
|
pSesInfo->password);
|
||||||
}
|
}
|
||||||
|
@ -3473,7 +3597,7 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
|
||||||
|
|
||||||
if (first_time)
|
if (first_time)
|
||||||
cifs_calculate_mac_key(
|
cifs_calculate_mac_key(
|
||||||
pSesInfo->server->mac_signing_key,
|
&pSesInfo->server->mac_signing_key,
|
||||||
ntlm_session_key, pSesInfo->password);
|
ntlm_session_key, pSesInfo->password);
|
||||||
|
|
||||||
rc = CIFSSessSetup(xid, pSesInfo,
|
rc = CIFSSessSetup(xid, pSesInfo,
|
||||||
|
|
|
@ -207,8 +207,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
|
||||||
} else {
|
} else {
|
||||||
/* If Open reported that we actually created a file
|
/* If Open reported that we actually created a file
|
||||||
then we now have to set the mode if possible */
|
then we now have to set the mode if possible */
|
||||||
if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
|
if ((pTcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) {
|
||||||
(oplock & CIFS_CREATE_ACTION)) {
|
|
||||||
mode &= ~current->fs->umask;
|
mode &= ~current->fs->umask;
|
||||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
|
||||||
CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
|
CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
|
||||||
|
@ -235,8 +234,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
|
||||||
/* Could set r/o dos attribute if mode & 0222 == 0 */
|
/* Could set r/o dos attribute if mode & 0222 == 0 */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* BB server might mask mode so we have to query for Unix case*/
|
/* server might mask mode so we have to query for it */
|
||||||
if (pTcon->ses->capabilities & CAP_UNIX)
|
if (pTcon->unix_ext)
|
||||||
rc = cifs_get_inode_info_unix(&newinode, full_path,
|
rc = cifs_get_inode_info_unix(&newinode, full_path,
|
||||||
inode->i_sb, xid);
|
inode->i_sb, xid);
|
||||||
else {
|
else {
|
||||||
|
@ -264,7 +263,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
|
||||||
direntry->d_op = &cifs_dentry_ops;
|
direntry->d_op = &cifs_dentry_ops;
|
||||||
d_instantiate(direntry, newinode);
|
d_instantiate(direntry, newinode);
|
||||||
}
|
}
|
||||||
if ((nd->flags & LOOKUP_OPEN) == FALSE) {
|
if ((nd == NULL /* nfsd case - nfs srv does not set nd */) ||
|
||||||
|
((nd->flags & LOOKUP_OPEN) == FALSE)) {
|
||||||
/* mknod case - do not leave file open */
|
/* mknod case - do not leave file open */
|
||||||
CIFSSMBClose(xid, pTcon, fileHandle);
|
CIFSSMBClose(xid, pTcon, fileHandle);
|
||||||
} else if (newinode) {
|
} else if (newinode) {
|
||||||
|
@ -336,7 +336,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
|
||||||
full_path = build_path_from_dentry(direntry);
|
full_path = build_path_from_dentry(direntry);
|
||||||
if (full_path == NULL)
|
if (full_path == NULL)
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
else if (pTcon->ses->capabilities & CAP_UNIX) {
|
else if (pTcon->unix_ext) {
|
||||||
mode &= ~current->fs->umask;
|
mode &= ~current->fs->umask;
|
||||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
|
||||||
rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path,
|
rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path,
|
||||||
|
@ -490,7 +490,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
|
||||||
cFYI(1,
|
cFYI(1,
|
||||||
(" Full path: %s inode = 0x%p", full_path, direntry->d_inode));
|
(" Full path: %s inode = 0x%p", full_path, direntry->d_inode));
|
||||||
|
|
||||||
if (pTcon->ses->capabilities & CAP_UNIX)
|
if (pTcon->unix_ext)
|
||||||
rc = cifs_get_inode_info_unix(&newInode, full_path,
|
rc = cifs_get_inode_info_unix(&newInode, full_path,
|
||||||
parent_dir_inode->i_sb, xid);
|
parent_dir_inode->i_sb, xid);
|
||||||
else
|
else
|
||||||
|
|
|
@ -26,23 +26,36 @@
|
||||||
/*
|
/*
|
||||||
* See Documentation/filesystems/Exporting
|
* See Documentation/filesystems/Exporting
|
||||||
* and examples in fs/exportfs
|
* and examples in fs/exportfs
|
||||||
|
*
|
||||||
|
* Since cifs is a network file system, an "fsid" must be included for
|
||||||
|
* any nfs exports file entries which refer to cifs paths. In addition
|
||||||
|
* the cifs mount must be mounted with the "serverino" option (ie use stable
|
||||||
|
* server inode numbers instead of locally generated temporary ones).
|
||||||
|
* Although cifs inodes do not use generation numbers (have generation number
|
||||||
|
* of zero) - the inode number alone should be good enough for simple cases
|
||||||
|
* in which users want to export cifs shares with NFS. The decode and encode
|
||||||
|
* could be improved by using a new routine which expects 64 bit inode numbers
|
||||||
|
* instead of the default 32 bit routines in fs/exportfs
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/exportfs.h>
|
#include <linux/exportfs.h>
|
||||||
|
#include "cifsglob.h"
|
||||||
|
#include "cifs_debug.h"
|
||||||
|
|
||||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
||||||
|
|
||||||
static struct dentry *cifs_get_parent(struct dentry *dentry)
|
static struct dentry *cifs_get_parent(struct dentry *dentry)
|
||||||
{
|
{
|
||||||
/* BB need to add code here eventually to enable export via NFSD */
|
/* BB need to add code here eventually to enable export via NFSD */
|
||||||
|
cFYI(1, ("get parent for %p", dentry));
|
||||||
return ERR_PTR(-EACCES);
|
return ERR_PTR(-EACCES);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct export_operations cifs_export_ops = {
|
struct export_operations cifs_export_ops = {
|
||||||
.get_parent = cifs_get_parent,
|
.get_parent = cifs_get_parent,
|
||||||
/* Following five export operations are unneeded so far and can default */
|
/* Following five export operations are unneeded so far and can default:
|
||||||
/* .get_dentry =
|
.get_dentry =
|
||||||
.get_name =
|
.get_name =
|
||||||
.find_exported_dentry =
|
.find_exported_dentry =
|
||||||
.decode_fh =
|
.decode_fh =
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
*
|
*
|
||||||
* vfs operations that deal with files
|
* vfs operations that deal with files
|
||||||
*
|
*
|
||||||
* Copyright (C) International Business Machines Corp., 2002,2003
|
* Copyright (C) International Business Machines Corp., 2002,2007
|
||||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||||
* Jeremy Allison (jra@samba.org)
|
* Jeremy Allison (jra@samba.org)
|
||||||
*
|
*
|
||||||
|
@ -138,7 +138,7 @@ static inline int cifs_open_inode_helper(struct inode *inode, struct file *file,
|
||||||
}
|
}
|
||||||
|
|
||||||
client_can_cache:
|
client_can_cache:
|
||||||
if (pTcon->ses->capabilities & CAP_UNIX)
|
if (pTcon->unix_ext)
|
||||||
rc = cifs_get_inode_info_unix(&file->f_path.dentry->d_inode,
|
rc = cifs_get_inode_info_unix(&file->f_path.dentry->d_inode,
|
||||||
full_path, inode->i_sb, xid);
|
full_path, inode->i_sb, xid);
|
||||||
else
|
else
|
||||||
|
@ -303,7 +303,7 @@ int cifs_open(struct inode *inode, struct file *file)
|
||||||
if (oplock & CIFS_CREATE_ACTION) {
|
if (oplock & CIFS_CREATE_ACTION) {
|
||||||
/* time to set mode which we can not set earlier due to
|
/* time to set mode which we can not set earlier due to
|
||||||
problems creating new read-only files */
|
problems creating new read-only files */
|
||||||
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) {
|
if (pTcon->unix_ext) {
|
||||||
CIFSSMBUnixSetPerms(xid, pTcon, full_path,
|
CIFSSMBUnixSetPerms(xid, pTcon, full_path,
|
||||||
inode->i_mode,
|
inode->i_mode,
|
||||||
(__u64)-1, (__u64)-1, 0 /* dev */,
|
(__u64)-1, (__u64)-1, 0 /* dev */,
|
||||||
|
@ -430,7 +430,7 @@ reopen_error_exit:
|
||||||
go to server to get inode info */
|
go to server to get inode info */
|
||||||
pCifsInode->clientCanCacheAll = FALSE;
|
pCifsInode->clientCanCacheAll = FALSE;
|
||||||
pCifsInode->clientCanCacheRead = FALSE;
|
pCifsInode->clientCanCacheRead = FALSE;
|
||||||
if (pTcon->ses->capabilities & CAP_UNIX)
|
if (pTcon->unix_ext)
|
||||||
rc = cifs_get_inode_info_unix(&inode,
|
rc = cifs_get_inode_info_unix(&inode,
|
||||||
full_path, inode->i_sb, xid);
|
full_path, inode->i_sb, xid);
|
||||||
else
|
else
|
||||||
|
@ -502,7 +502,8 @@ int cifs_close(struct inode *inode, struct file *file)
|
||||||
timeout *= 4;
|
timeout *= 4;
|
||||||
}
|
}
|
||||||
if (atomic_read(&pSMBFile->wrtPending))
|
if (atomic_read(&pSMBFile->wrtPending))
|
||||||
cERROR(1,("close with pending writes"));
|
cERROR(1,
|
||||||
|
("close with pending writes"));
|
||||||
rc = CIFSSMBClose(xid, pTcon,
|
rc = CIFSSMBClose(xid, pTcon,
|
||||||
pSMBFile->netfid);
|
pSMBFile->netfid);
|
||||||
}
|
}
|
||||||
|
@ -554,7 +555,8 @@ int cifs_closedir(struct inode *inode, struct file *file)
|
||||||
|
|
||||||
if (pCFileStruct) {
|
if (pCFileStruct) {
|
||||||
struct cifsTconInfo *pTcon;
|
struct cifsTconInfo *pTcon;
|
||||||
struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
|
struct cifs_sb_info *cifs_sb =
|
||||||
|
CIFS_SB(file->f_path.dentry->d_sb);
|
||||||
|
|
||||||
pTcon = cifs_sb->tcon;
|
pTcon = cifs_sb->tcon;
|
||||||
|
|
||||||
|
@ -594,7 +596,8 @@ int cifs_closedir(struct inode *inode, struct file *file)
|
||||||
static int store_file_lock(struct cifsFileInfo *fid, __u64 len,
|
static int store_file_lock(struct cifsFileInfo *fid, __u64 len,
|
||||||
__u64 offset, __u8 lockType)
|
__u64 offset, __u8 lockType)
|
||||||
{
|
{
|
||||||
struct cifsLockInfo *li = kmalloc(sizeof(struct cifsLockInfo), GFP_KERNEL);
|
struct cifsLockInfo *li =
|
||||||
|
kmalloc(sizeof(struct cifsLockInfo), GFP_KERNEL);
|
||||||
if (li == NULL)
|
if (li == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
li->offset = offset;
|
li->offset = offset;
|
||||||
|
@ -741,10 +744,12 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
|
||||||
length, pfLock,
|
length, pfLock,
|
||||||
posix_lock_type, wait_flag);
|
posix_lock_type, wait_flag);
|
||||||
} else {
|
} else {
|
||||||
struct cifsFileInfo *fid = (struct cifsFileInfo *)file->private_data;
|
struct cifsFileInfo *fid =
|
||||||
|
(struct cifsFileInfo *)file->private_data;
|
||||||
|
|
||||||
if (numLock) {
|
if (numLock) {
|
||||||
rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start,
|
rc = CIFSSMBLock(xid, pTcon, netfid, length,
|
||||||
|
pfLock->fl_start,
|
||||||
0, numLock, lockType, wait_flag);
|
0, numLock, lockType, wait_flag);
|
||||||
|
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
|
@ -763,7 +768,8 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
|
||||||
list_for_each_entry_safe(li, tmp, &fid->llist, llist) {
|
list_for_each_entry_safe(li, tmp, &fid->llist, llist) {
|
||||||
if (pfLock->fl_start <= li->offset &&
|
if (pfLock->fl_start <= li->offset &&
|
||||||
length >= li->length) {
|
length >= li->length) {
|
||||||
stored_rc = CIFSSMBLock(xid, pTcon, netfid,
|
stored_rc = CIFSSMBLock(xid, pTcon,
|
||||||
|
netfid,
|
||||||
li->length, li->offset,
|
li->length, li->offset,
|
||||||
1, 0, li->type, FALSE);
|
1, 0, li->type, FALSE);
|
||||||
if (stored_rc)
|
if (stored_rc)
|
||||||
|
@ -1030,7 +1036,8 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
|
||||||
/* if it fails, try another handle - might be */
|
/* if it fails, try another handle - might be */
|
||||||
/* dangerous to hold up writepages with retry */
|
/* dangerous to hold up writepages with retry */
|
||||||
if (rc) {
|
if (rc) {
|
||||||
cFYI(1,("failed on reopen file in wp"));
|
cFYI(1,
|
||||||
|
("failed on reopen file in wp"));
|
||||||
read_lock(&GlobalSMBSeslock);
|
read_lock(&GlobalSMBSeslock);
|
||||||
/* can not use this handle, no write
|
/* can not use this handle, no write
|
||||||
pending on this one after all */
|
pending on this one after all */
|
||||||
|
@ -1279,7 +1286,7 @@ retry:
|
||||||
1);
|
1);
|
||||||
atomic_dec(&open_file->wrtPending);
|
atomic_dec(&open_file->wrtPending);
|
||||||
if (rc || bytes_written < bytes_to_write) {
|
if (rc || bytes_written < bytes_to_write) {
|
||||||
cERROR(1,("Write2 ret %d, written = %d",
|
cERROR(1, ("Write2 ret %d, wrote %d",
|
||||||
rc, bytes_written));
|
rc, bytes_written));
|
||||||
/* BB what if continued retry is
|
/* BB what if continued retry is
|
||||||
requested via mount flags? */
|
requested via mount flags? */
|
||||||
|
@ -1720,7 +1727,9 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
|
||||||
pTcon = cifs_sb->tcon;
|
pTcon = cifs_sb->tcon;
|
||||||
|
|
||||||
pagevec_init(&lru_pvec, 0);
|
pagevec_init(&lru_pvec, 0);
|
||||||
|
#ifdef CONFIG_CIFS_DEBUG2
|
||||||
|
cFYI(1, ("rpages: num pages %d", num_pages));
|
||||||
|
#endif
|
||||||
for (i = 0; i < num_pages; ) {
|
for (i = 0; i < num_pages; ) {
|
||||||
unsigned contig_pages;
|
unsigned contig_pages;
|
||||||
struct page *tmp_page;
|
struct page *tmp_page;
|
||||||
|
@ -1753,7 +1762,10 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
|
||||||
/* Read size needs to be in multiples of one page */
|
/* Read size needs to be in multiples of one page */
|
||||||
read_size = min_t(const unsigned int, read_size,
|
read_size = min_t(const unsigned int, read_size,
|
||||||
cifs_sb->rsize & PAGE_CACHE_MASK);
|
cifs_sb->rsize & PAGE_CACHE_MASK);
|
||||||
|
#ifdef CONFIG_CIFS_DEBUG2
|
||||||
|
cFYI(1, ("rpages: read size 0x%x contiguous pages %d",
|
||||||
|
read_size, contig_pages));
|
||||||
|
#endif
|
||||||
rc = -EAGAIN;
|
rc = -EAGAIN;
|
||||||
while (rc == -EAGAIN) {
|
while (rc == -EAGAIN) {
|
||||||
if ((open_file->invalidHandle) &&
|
if ((open_file->invalidHandle) &&
|
||||||
|
@ -1955,14 +1967,7 @@ static int cifs_prepare_write(struct file *file, struct page *page,
|
||||||
* We don't need to read data beyond the end of the file.
|
* We don't need to read data beyond the end of the file.
|
||||||
* zero it, and set the page uptodate
|
* zero it, and set the page uptodate
|
||||||
*/
|
*/
|
||||||
void *kaddr = kmap_atomic(page, KM_USER0);
|
simple_prepare_write(file, page, from, to);
|
||||||
|
|
||||||
if (from)
|
|
||||||
memset(kaddr, 0, from);
|
|
||||||
if (to < PAGE_CACHE_SIZE)
|
|
||||||
memset(kaddr + to, 0, PAGE_CACHE_SIZE - to);
|
|
||||||
flush_dcache_page(page);
|
|
||||||
kunmap_atomic(kaddr, KM_USER0);
|
|
||||||
SetPageUptodate(page);
|
SetPageUptodate(page);
|
||||||
} else if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
|
} else if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
|
||||||
/* might as well read a page, it is fast enough */
|
/* might as well read a page, it is fast enough */
|
||||||
|
|
|
@ -285,7 +285,6 @@ static int decode_sfu_inode(struct inode * inode, __u64 size,
|
||||||
CIFSSMBClose(xid, pTcon, netfid);
|
CIFSSMBClose(xid, pTcon, netfid);
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */
|
#define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */
|
||||||
|
@ -317,8 +316,6 @@ static int get_sfu_uid_mode(struct inode * inode,
|
||||||
#else
|
#else
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int cifs_get_inode_info(struct inode **pinode,
|
int cifs_get_inode_info(struct inode **pinode,
|
||||||
|
@ -364,7 +361,6 @@ int cifs_get_inode_info(struct inode **pinode,
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
adjustTZ = TRUE;
|
adjustTZ = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
/* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */
|
/* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */
|
||||||
if (rc) {
|
if (rc) {
|
||||||
|
@ -471,7 +467,8 @@ int cifs_get_inode_info(struct inode **pinode,
|
||||||
/* new inode, can safely set these fields */
|
/* new inode, can safely set these fields */
|
||||||
inode->i_mode = cifs_sb->mnt_file_mode;
|
inode->i_mode = cifs_sb->mnt_file_mode;
|
||||||
else /* since we set the inode type below we need to mask off
|
else /* since we set the inode type below we need to mask off
|
||||||
to avoid strange results if type changes and both get orred in */
|
to avoid strange results if type changes and both
|
||||||
|
get orred in */
|
||||||
inode->i_mode &= ~S_IFMT;
|
inode->i_mode &= ~S_IFMT;
|
||||||
/* if (attr & ATTR_REPARSE) */
|
/* if (attr & ATTR_REPARSE) */
|
||||||
/* We no longer handle these as symlinks because we could not
|
/* We no longer handle these as symlinks because we could not
|
||||||
|
@ -586,7 +583,8 @@ void cifs_read_inode(struct inode *inode)
|
||||||
|
|
||||||
cifs_sb = CIFS_SB(inode->i_sb);
|
cifs_sb = CIFS_SB(inode->i_sb);
|
||||||
xid = GetXid();
|
xid = GetXid();
|
||||||
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
|
|
||||||
|
if (cifs_sb->tcon->unix_ext)
|
||||||
cifs_get_inode_info_unix(&inode, "", inode->i_sb, xid);
|
cifs_get_inode_info_unix(&inode, "", inode->i_sb, xid);
|
||||||
else
|
else
|
||||||
cifs_get_inode_info(&inode, "", NULL, inode->i_sb, xid);
|
cifs_get_inode_info(&inode, "", NULL, inode->i_sb, xid);
|
||||||
|
@ -623,9 +621,21 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
|
||||||
FreeXid(xid);
|
FreeXid(xid);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((pTcon->ses->capabilities & CAP_UNIX) &&
|
||||||
|
(CIFS_UNIX_POSIX_PATH_OPS_CAP &
|
||||||
|
le64_to_cpu(pTcon->fsUnixInfo.Capability))) {
|
||||||
|
rc = CIFSPOSIXDelFile(xid, pTcon, full_path,
|
||||||
|
SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
|
||||||
|
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
|
cFYI(1, ("posix del rc %d", rc));
|
||||||
|
if ((rc == 0) || (rc == -ENOENT))
|
||||||
|
goto psx_del_no_retry;
|
||||||
|
}
|
||||||
|
|
||||||
rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls,
|
rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls,
|
||||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
|
psx_del_no_retry:
|
||||||
if (!rc) {
|
if (!rc) {
|
||||||
if (direntry->d_inode)
|
if (direntry->d_inode)
|
||||||
drop_nlink(direntry->d_inode);
|
drop_nlink(direntry->d_inode);
|
||||||
|
@ -849,8 +859,9 @@ static void posix_fill_in_inode(struct inode *tmp_inode,
|
||||||
tmp_inode->i_data.a_ops = &cifs_addr_ops;
|
tmp_inode->i_data.a_ops = &cifs_addr_ops;
|
||||||
|
|
||||||
if (isNewInode)
|
if (isNewInode)
|
||||||
return; /* No sense invalidating pages for new inode since we
|
return; /* No sense invalidating pages for new inode
|
||||||
have not started caching readahead file data yet */
|
since we we have not started caching
|
||||||
|
readahead file data yet */
|
||||||
|
|
||||||
if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
|
if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
|
||||||
(local_size == tmp_inode->i_size)) {
|
(local_size == tmp_inode->i_size)) {
|
||||||
|
@ -920,7 +931,8 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
|
||||||
int obj_type;
|
int obj_type;
|
||||||
if (pInfo->Type == -1) /* no return info - go query */
|
if (pInfo->Type == -1) /* no return info - go query */
|
||||||
goto mkdir_get_info;
|
goto mkdir_get_info;
|
||||||
/*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need to set uid/gid */
|
/*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need
|
||||||
|
to set uid/gid */
|
||||||
inc_nlink(inode);
|
inc_nlink(inode);
|
||||||
if (pTcon->nocase)
|
if (pTcon->nocase)
|
||||||
direntry->d_op = &cifs_ci_dentry_ops;
|
direntry->d_op = &cifs_ci_dentry_ops;
|
||||||
|
@ -970,7 +982,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
|
||||||
} else {
|
} else {
|
||||||
mkdir_get_info:
|
mkdir_get_info:
|
||||||
inc_nlink(inode);
|
inc_nlink(inode);
|
||||||
if (pTcon->ses->capabilities & CAP_UNIX)
|
if (pTcon->unix_ext)
|
||||||
rc = cifs_get_inode_info_unix(&newinode, full_path,
|
rc = cifs_get_inode_info_unix(&newinode, full_path,
|
||||||
inode->i_sb, xid);
|
inode->i_sb, xid);
|
||||||
else
|
else
|
||||||
|
@ -986,7 +998,7 @@ mkdir_get_info:
|
||||||
* failed to get it from the server or was set bogus */
|
* failed to get it from the server or was set bogus */
|
||||||
if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2))
|
if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2))
|
||||||
direntry->d_inode->i_nlink = 2;
|
direntry->d_inode->i_nlink = 2;
|
||||||
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) {
|
if (pTcon->unix_ext) {
|
||||||
mode &= ~current->fs->umask;
|
mode &= ~current->fs->umask;
|
||||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
|
||||||
CIFSSMBUnixSetPerms(xid, pTcon, full_path,
|
CIFSSMBUnixSetPerms(xid, pTcon, full_path,
|
||||||
|
@ -1119,7 +1131,7 @@ int cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
|
||||||
kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
|
kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
|
||||||
if (info_buf_source != NULL) {
|
if (info_buf_source != NULL) {
|
||||||
info_buf_target = info_buf_source + 1;
|
info_buf_target = info_buf_source + 1;
|
||||||
if (pTcon->ses->capabilities & CAP_UNIX)
|
if (pTcon->unix_ext)
|
||||||
rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName,
|
rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName,
|
||||||
info_buf_source,
|
info_buf_source,
|
||||||
cifs_sb_source->local_nls,
|
cifs_sb_source->local_nls,
|
||||||
|
@ -1247,7 +1259,7 @@ int cifs_revalidate(struct dentry *direntry)
|
||||||
local_mtime = direntry->d_inode->i_mtime;
|
local_mtime = direntry->d_inode->i_mtime;
|
||||||
local_size = direntry->d_inode->i_size;
|
local_size = direntry->d_inode->i_size;
|
||||||
|
|
||||||
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) {
|
if (cifs_sb->tcon->unix_ext) {
|
||||||
rc = cifs_get_inode_info_unix(&direntry->d_inode, full_path,
|
rc = cifs_get_inode_info_unix(&direntry->d_inode, full_path,
|
||||||
direntry->d_sb, xid);
|
direntry->d_sb, xid);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
|
@ -1335,17 +1347,13 @@ static int cifs_truncate_page(struct address_space *mapping, loff_t from)
|
||||||
pgoff_t index = from >> PAGE_CACHE_SHIFT;
|
pgoff_t index = from >> PAGE_CACHE_SHIFT;
|
||||||
unsigned offset = from & (PAGE_CACHE_SIZE - 1);
|
unsigned offset = from & (PAGE_CACHE_SIZE - 1);
|
||||||
struct page *page;
|
struct page *page;
|
||||||
char *kaddr;
|
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
page = grab_cache_page(mapping, index);
|
page = grab_cache_page(mapping, index);
|
||||||
if (!page)
|
if (!page)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
kaddr = kmap_atomic(page, KM_USER0);
|
zero_user_page(page, offset, PAGE_CACHE_SIZE - offset, KM_USER0);
|
||||||
memset(kaddr + offset, 0, PAGE_CACHE_SIZE - offset);
|
|
||||||
flush_dcache_page(page);
|
|
||||||
kunmap_atomic(kaddr, KM_USER0);
|
|
||||||
unlock_page(page);
|
unlock_page(page);
|
||||||
page_cache_release(page);
|
page_cache_release(page);
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -1535,7 +1543,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
|
||||||
mode = attrs->ia_mode;
|
mode = attrs->ia_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX)
|
if ((pTcon->unix_ext)
|
||||||
&& (attrs->ia_valid & (ATTR_MODE | ATTR_GID | ATTR_UID)))
|
&& (attrs->ia_valid & (ATTR_MODE | ATTR_GID | ATTR_UID)))
|
||||||
rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, uid, gid,
|
rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, uid, gid,
|
||||||
0 /* dev_t */, cifs_sb->local_nls,
|
0 /* dev_t */, cifs_sb->local_nls,
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
*
|
*
|
||||||
* vfs operations that deal with io control
|
* vfs operations that deal with io control
|
||||||
*
|
*
|
||||||
* Copyright (C) International Business Machines Corp., 2005
|
* Copyright (C) International Business Machines Corp., 2005,2007
|
||||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or modify
|
* This library is free software; you can redistribute it and/or modify
|
||||||
|
|
|
@ -55,7 +55,8 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
|
||||||
goto cifs_hl_exit;
|
goto cifs_hl_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cifs_sb_target->tcon->ses->capabilities & CAP_UNIX)
|
/* if (cifs_sb_target->tcon->ses->capabilities & CAP_UNIX)*/
|
||||||
|
if (pTcon->unix_ext)
|
||||||
rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName,
|
rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName,
|
||||||
cifs_sb_target->local_nls,
|
cifs_sb_target->local_nls,
|
||||||
cifs_sb_target->mnt_cifs_flags &
|
cifs_sb_target->mnt_cifs_flags &
|
||||||
|
@ -129,13 +130,19 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* BB add read reparse point symlink code and Unix extensions symlink code here BB */
|
/* We could change this to:
|
||||||
|
if (pTcon->unix_ext)
|
||||||
|
but there does not seem any point in refusing to
|
||||||
|
get symlink info if we can, even if unix extensions
|
||||||
|
turned off for this mount */
|
||||||
|
|
||||||
if (pTcon->ses->capabilities & CAP_UNIX)
|
if (pTcon->ses->capabilities & CAP_UNIX)
|
||||||
rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
|
rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
|
||||||
target_path,
|
target_path,
|
||||||
PATH_MAX-1,
|
PATH_MAX-1,
|
||||||
cifs_sb->local_nls);
|
cifs_sb->local_nls);
|
||||||
else {
|
else {
|
||||||
|
/* BB add read reparse point symlink code here */
|
||||||
/* rc = CIFSSMBQueryReparseLinkInfo */
|
/* rc = CIFSSMBQueryReparseLinkInfo */
|
||||||
/* BB Add code to Query ReparsePoint info */
|
/* BB Add code to Query ReparsePoint info */
|
||||||
/* BB Add MAC style xsymlink check here if enabled */
|
/* BB Add MAC style xsymlink check here if enabled */
|
||||||
|
@ -185,14 +192,15 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
|
||||||
cFYI(1, ("symname is %s", symname));
|
cFYI(1, ("symname is %s", symname));
|
||||||
|
|
||||||
/* BB what if DFS and this volume is on different share? BB */
|
/* BB what if DFS and this volume is on different share? BB */
|
||||||
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
|
if (pTcon->unix_ext)
|
||||||
rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname,
|
rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname,
|
||||||
cifs_sb->local_nls);
|
cifs_sb->local_nls);
|
||||||
/* else
|
/* else
|
||||||
rc = CIFSCreateReparseSymLink(xid, pTcon, fromName, toName,cifs_sb_target->local_nls); */
|
rc = CIFSCreateReparseSymLink(xid, pTcon, fromName, toName,
|
||||||
|
cifs_sb_target->local_nls); */
|
||||||
|
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
if (pTcon->ses->capabilities & CAP_UNIX)
|
if (pTcon->unix_ext)
|
||||||
rc = cifs_get_inode_info_unix(&newinode, full_path,
|
rc = cifs_get_inode_info_unix(&newinode, full_path,
|
||||||
inode->i_sb, xid);
|
inode->i_sb, xid);
|
||||||
else
|
else
|
||||||
|
@ -262,7 +270,9 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* BB add read reparse point symlink code and Unix extensions symlink code here BB */
|
/* BB add read reparse point symlink code and
|
||||||
|
Unix extensions symlink code here BB */
|
||||||
|
/* We could disable this based on pTcon->unix_ext flag instead ... but why? */
|
||||||
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
|
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
|
||||||
rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
|
rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
|
||||||
tmpbuffer,
|
tmpbuffer,
|
||||||
|
@ -271,7 +281,6 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
|
||||||
else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
|
else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
|
||||||
cERROR(1, ("SFU style symlinks not implemented yet"));
|
cERROR(1, ("SFU style symlinks not implemented yet"));
|
||||||
/* add open and read as in fs/cifs/inode.c */
|
/* add open and read as in fs/cifs/inode.c */
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ,
|
rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ,
|
||||||
OPEN_REPARSE_POINT, &fid, &oplock, NULL,
|
OPEN_REPARSE_POINT, &fid, &oplock, NULL,
|
||||||
|
@ -285,7 +294,8 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
|
||||||
fid,
|
fid,
|
||||||
cifs_sb->local_nls);
|
cifs_sb->local_nls);
|
||||||
if (CIFSSMBClose(xid, pTcon, fid)) {
|
if (CIFSSMBClose(xid, pTcon, fid)) {
|
||||||
cFYI(1,("Error closing junction point (open for ioctl)"));
|
cFYI(1, ("Error closing junction point "
|
||||||
|
"(open for ioctl)"));
|
||||||
}
|
}
|
||||||
if (rc == -EIO) {
|
if (rc == -EIO) {
|
||||||
/* Query if DFS Junction */
|
/* Query if DFS Junction */
|
||||||
|
@ -293,28 +303,36 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
|
||||||
kmalloc(MAX_TREE_SIZE + MAX_PATHCONF + 1,
|
kmalloc(MAX_TREE_SIZE + MAX_PATHCONF + 1,
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (tmp_path) {
|
if (tmp_path) {
|
||||||
strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
|
strncpy(tmp_path, pTcon->treeName,
|
||||||
strncat(tmp_path, full_path, MAX_PATHCONF);
|
MAX_TREE_SIZE);
|
||||||
rc = get_dfs_path(xid, pTcon->ses, tmp_path,
|
strncat(tmp_path, full_path,
|
||||||
|
MAX_PATHCONF);
|
||||||
|
rc = get_dfs_path(xid, pTcon->ses,
|
||||||
|
tmp_path,
|
||||||
cifs_sb->local_nls,
|
cifs_sb->local_nls,
|
||||||
&num_referrals, &referrals,
|
&num_referrals, &referrals,
|
||||||
cifs_sb->mnt_cifs_flags &
|
cifs_sb->mnt_cifs_flags &
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
cFYI(1,("Get DFS for %s rc = %d ",tmp_path, rc));
|
cFYI(1, ("Get DFS for %s rc = %d ",
|
||||||
|
tmp_path, rc));
|
||||||
if ((num_referrals == 0) && (rc == 0))
|
if ((num_referrals == 0) && (rc == 0))
|
||||||
rc = -EACCES;
|
rc = -EACCES;
|
||||||
else {
|
else {
|
||||||
cFYI(1,("num referral: %d",num_referrals));
|
cFYI(1, ("num referral: %d",
|
||||||
|
num_referrals));
|
||||||
if (referrals) {
|
if (referrals) {
|
||||||
cFYI(1,("referral string: %s", referrals));
|
cFYI(1,("referral string: %s", referrals));
|
||||||
strncpy(tmpbuffer, referrals, len-1);
|
strncpy(tmpbuffer,
|
||||||
|
referrals,
|
||||||
|
len-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
kfree(referrals);
|
kfree(referrals);
|
||||||
kfree(tmp_path);
|
kfree(tmp_path);
|
||||||
}
|
}
|
||||||
/* BB add code like else decode referrals then memcpy to
|
/* BB add code like else decode referrals
|
||||||
tmpbuffer and free referrals string array BB */
|
then memcpy to tmpbuffer and free referrals
|
||||||
|
string array BB */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* fs/cifs/misc.c
|
* fs/cifs/misc.c
|
||||||
*
|
*
|
||||||
* Copyright (C) International Business Machines Corp., 2002,2005
|
* Copyright (C) International Business Machines Corp., 2002,2007
|
||||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or modify
|
* This library is free software; you can redistribute it and/or modify
|
||||||
|
@ -47,8 +47,10 @@ _GetXid(void)
|
||||||
|
|
||||||
spin_lock(&GlobalMid_Lock);
|
spin_lock(&GlobalMid_Lock);
|
||||||
GlobalTotalActiveXid++;
|
GlobalTotalActiveXid++;
|
||||||
|
|
||||||
|
/* keep high water mark for number of simultaneous ops in filesystem */
|
||||||
if (GlobalTotalActiveXid > GlobalMaxActiveXid)
|
if (GlobalTotalActiveXid > GlobalMaxActiveXid)
|
||||||
GlobalMaxActiveXid = GlobalTotalActiveXid; /* keep high water mark for number of simultaneous vfs ops in our filesystem */
|
GlobalMaxActiveXid = GlobalTotalActiveXid;
|
||||||
if (GlobalTotalActiveXid > 65000)
|
if (GlobalTotalActiveXid > 65000)
|
||||||
cFYI(1, ("warning: more than 65000 requests active"));
|
cFYI(1, ("warning: more than 65000 requests active"));
|
||||||
xid = GlobalCurrentXid++;
|
xid = GlobalCurrentXid++;
|
||||||
|
@ -148,8 +150,8 @@ cifs_buf_get(void)
|
||||||
but it may be more efficient to always alloc same size
|
but it may be more efficient to always alloc same size
|
||||||
albeit slightly larger than necessary and maxbuffersize
|
albeit slightly larger than necessary and maxbuffersize
|
||||||
defaults to this and can not be bigger */
|
defaults to this and can not be bigger */
|
||||||
ret_buf =
|
ret_buf = (struct smb_hdr *) mempool_alloc(cifs_req_poolp,
|
||||||
(struct smb_hdr *) mempool_alloc(cifs_req_poolp, GFP_KERNEL | GFP_NOFS);
|
GFP_KERNEL | GFP_NOFS);
|
||||||
|
|
||||||
/* clear the first few header bytes */
|
/* clear the first few header bytes */
|
||||||
/* for most paths, more is cleared in header_assemble */
|
/* for most paths, more is cleared in header_assemble */
|
||||||
|
@ -187,8 +189,8 @@ cifs_small_buf_get(void)
|
||||||
but it may be more efficient to always alloc same size
|
but it may be more efficient to always alloc same size
|
||||||
albeit slightly larger than necessary and maxbuffersize
|
albeit slightly larger than necessary and maxbuffersize
|
||||||
defaults to this and can not be bigger */
|
defaults to this and can not be bigger */
|
||||||
ret_buf =
|
ret_buf = (struct smb_hdr *) mempool_alloc(cifs_sm_req_poolp,
|
||||||
(struct smb_hdr *) mempool_alloc(cifs_sm_req_poolp, GFP_KERNEL | GFP_NOFS);
|
GFP_KERNEL | GFP_NOFS);
|
||||||
if (ret_buf) {
|
if (ret_buf) {
|
||||||
/* No need to clear memory here, cleared in header assemble */
|
/* No need to clear memory here, cleared in header assemble */
|
||||||
/* memset(ret_buf, 0, sizeof(struct smb_hdr) + 27);*/
|
/* memset(ret_buf, 0, sizeof(struct smb_hdr) + 27);*/
|
||||||
|
@ -351,7 +353,8 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
|
||||||
/* with userid/password pairs found on the smb session */
|
/* with userid/password pairs found on the smb session */
|
||||||
/* for other target tcp/ip addresses BB */
|
/* for other target tcp/ip addresses BB */
|
||||||
if (current->fsuid != treeCon->ses->linux_uid) {
|
if (current->fsuid != treeCon->ses->linux_uid) {
|
||||||
cFYI(1,("Multiuser mode and UID did not match tcon uid"));
|
cFYI(1, ("Multiuser mode and UID "
|
||||||
|
"did not match tcon uid"));
|
||||||
read_lock(&GlobalSMBSeslock);
|
read_lock(&GlobalSMBSeslock);
|
||||||
list_for_each(temp_item, &GlobalSMBSessionList) {
|
list_for_each(temp_item, &GlobalSMBSessionList) {
|
||||||
ses = list_entry(temp_item, struct cifsSesInfo, cifsSessionList);
|
ses = list_entry(temp_item, struct cifsSesInfo, cifsSessionList);
|
||||||
|
@ -362,7 +365,7 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
/* BB eventually call cifs_setup_session here */
|
/* BB eventually call cifs_setup_session here */
|
||||||
cFYI(1,("local UID found but smb sess with this server does not exist"));
|
cFYI(1, ("local UID found but no smb sess with this server exists"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -399,7 +402,7 @@ checkSMBhdr(struct smb_hdr *smb, __u16 mid)
|
||||||
if (smb->Command == SMB_COM_LOCKING_ANDX)
|
if (smb->Command == SMB_COM_LOCKING_ANDX)
|
||||||
return 0;
|
return 0;
|
||||||
else
|
else
|
||||||
cERROR(1, ("Rcvd Request not response"));
|
cERROR(1, ("Received Request not response"));
|
||||||
}
|
}
|
||||||
} else { /* bad signature or mid */
|
} else { /* bad signature or mid */
|
||||||
if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff))
|
if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff))
|
||||||
|
@ -459,7 +462,8 @@ checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length)
|
||||||
clc_len = smbCalcSize_LE(smb);
|
clc_len = smbCalcSize_LE(smb);
|
||||||
|
|
||||||
if (4 + len != length) {
|
if (4 + len != length) {
|
||||||
cERROR(1, ("Length read does not match RFC1001 length %d",len));
|
cERROR(1, ("Length read does not match RFC1001 length %d",
|
||||||
|
len));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -514,14 +518,16 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
|
||||||
|
|
||||||
pnotify = (struct file_notify_information *)
|
pnotify = (struct file_notify_information *)
|
||||||
((char *)&pSMBr->hdr.Protocol + data_offset);
|
((char *)&pSMBr->hdr.Protocol + data_offset);
|
||||||
cFYI(1,("dnotify on %s Action: 0x%x",pnotify->FileName,
|
cFYI(1, ("dnotify on %s Action: 0x%x",
|
||||||
|
pnotify->FileName,
|
||||||
pnotify->Action)); /* BB removeme BB */
|
pnotify->Action)); /* BB removeme BB */
|
||||||
/* cifs_dump_mem("Rcvd notify Data: ",buf,
|
/* cifs_dump_mem("Rcvd notify Data: ",buf,
|
||||||
sizeof(struct smb_hdr)+60); */
|
sizeof(struct smb_hdr)+60); */
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
if (pSMBr->hdr.Status.CifsError) {
|
if (pSMBr->hdr.Status.CifsError) {
|
||||||
cFYI(1,("notify err 0x%d",pSMBr->hdr.Status.CifsError));
|
cFYI(1, ("notify err 0x%d",
|
||||||
|
pSMBr->hdr.Status.CifsError));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -547,7 +553,8 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
|
||||||
if (pSMB->hdr.WordCount != 8)
|
if (pSMB->hdr.WordCount != 8)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
cFYI(1,(" oplock type 0x%d level 0x%d",pSMB->LockType,pSMB->OplockLevel));
|
cFYI(1, ("oplock type 0x%d level 0x%d",
|
||||||
|
pSMB->LockType, pSMB->OplockLevel));
|
||||||
if (!(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE))
|
if (!(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
@ -563,7 +570,8 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
|
||||||
if (pSMB->Fid == netfile->netfid) {
|
if (pSMB->Fid == netfile->netfid) {
|
||||||
struct cifsInodeInfo *pCifsInode;
|
struct cifsInodeInfo *pCifsInode;
|
||||||
read_unlock(&GlobalSMBSeslock);
|
read_unlock(&GlobalSMBSeslock);
|
||||||
cFYI(1,("file id match, oplock break"));
|
cFYI(1,
|
||||||
|
("file id match, oplock break"));
|
||||||
pCifsInode =
|
pCifsInode =
|
||||||
CIFS_I(netfile->pInode);
|
CIFS_I(netfile->pInode);
|
||||||
pCifsInode->clientCanCacheAll = FALSE;
|
pCifsInode->clientCanCacheAll = FALSE;
|
||||||
|
@ -574,7 +582,8 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
|
||||||
AllocOplockQEntry(netfile->pInode,
|
AllocOplockQEntry(netfile->pInode,
|
||||||
netfile->netfid,
|
netfile->netfid,
|
||||||
tcon);
|
tcon);
|
||||||
cFYI(1,("about to wake up oplock thd"));
|
cFYI(1,
|
||||||
|
("about to wake up oplock thread"));
|
||||||
if (oplockThread)
|
if (oplockThread)
|
||||||
wake_up_process(oplockThread);
|
wake_up_process(oplockThread);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
* Error mapping routines from Samba libsmb/errormap.c
|
* Error mapping routines from Samba libsmb/errormap.c
|
||||||
* Copyright (C) Andrew Tridgell 2001
|
* Copyright (C) Andrew Tridgell 2001
|
||||||
*
|
*
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
@ -30,9 +29,7 @@
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <asm/div64.h>
|
#include <asm/div64.h>
|
||||||
#include <asm/byteorder.h>
|
#include <asm/byteorder.h>
|
||||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
|
||||||
#include <linux/inet.h>
|
#include <linux/inet.h>
|
||||||
#endif
|
|
||||||
#include "cifsfs.h"
|
#include "cifsfs.h"
|
||||||
#include "cifspdu.h"
|
#include "cifspdu.h"
|
||||||
#include "cifsglob.h"
|
#include "cifsglob.h"
|
||||||
|
@ -135,12 +132,11 @@ static const struct smb_to_posix_error mapping_table_ERRHRD[] = {
|
||||||
int
|
int
|
||||||
cifs_inet_pton(int address_family, char *cp, void *dst)
|
cifs_inet_pton(int address_family, char *cp, void *dst)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
/* calculate length by finding first slash or NULL */
|
/* calculate length by finding first slash or NULL */
|
||||||
/* BB Should we convert '/' slash to '\' here since it seems already done
|
/* BB Should we convert '/' slash to '\' here since it seems already
|
||||||
before this */
|
* done before this */
|
||||||
if ( address_family == AF_INET ) {
|
if ( address_family == AF_INET ) {
|
||||||
ret = in4_pton(cp, -1 /* len */, dst , '\\', NULL);
|
ret = in4_pton(cp, -1 /* len */, dst , '\\', NULL);
|
||||||
} else if ( address_family == AF_INET6 ) {
|
} else if ( address_family == AF_INET6 ) {
|
||||||
|
@ -152,66 +148,6 @@ cifs_inet_pton(int address_family, char *cp,void *dst)
|
||||||
if (ret > 0)
|
if (ret > 0)
|
||||||
ret = 1;
|
ret = 1;
|
||||||
return ret;
|
return ret;
|
||||||
#else
|
|
||||||
int value;
|
|
||||||
int digit;
|
|
||||||
int i;
|
|
||||||
char temp;
|
|
||||||
char bytes[4];
|
|
||||||
char *end = bytes;
|
|
||||||
static const int addr_class_max[4] =
|
|
||||||
{ 0xffffffff, 0xffffff, 0xffff, 0xff };
|
|
||||||
|
|
||||||
if(address_family != AF_INET)
|
|
||||||
return -EAFNOSUPPORT;
|
|
||||||
|
|
||||||
for (i = 0; i < 4; i++) {
|
|
||||||
bytes[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
temp = *cp;
|
|
||||||
|
|
||||||
while (TRUE) {
|
|
||||||
if (!isdigit(temp))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
value = 0;
|
|
||||||
digit = 0;
|
|
||||||
for (;;) {
|
|
||||||
if (isascii(temp) && isdigit(temp)) {
|
|
||||||
value = (value * 10) + temp - '0';
|
|
||||||
temp = *++cp;
|
|
||||||
digit = 1;
|
|
||||||
} else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (temp == '.') {
|
|
||||||
if ((end > bytes + 2) || (value > 255))
|
|
||||||
return 0;
|
|
||||||
*end++ = value;
|
|
||||||
temp = *++cp;
|
|
||||||
} else if (temp == ':') {
|
|
||||||
cFYI(1,("IPv6 addresses not supported for CIFS mounts yet"));
|
|
||||||
return -1;
|
|
||||||
} else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check for last characters */
|
|
||||||
if (temp != '\0' && (!isascii(temp) || !isspace(temp)))
|
|
||||||
if (temp != '\\') {
|
|
||||||
if (temp != '/')
|
|
||||||
return 0;
|
|
||||||
else
|
|
||||||
(*cp = '\\'); /* switch the slash the expected way */
|
|
||||||
}
|
|
||||||
if (value > addr_class_max[end - bytes])
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
*((__be32 *)dst) = *((__be32 *) bytes) | htonl(value);
|
|
||||||
return 1; /* success */
|
|
||||||
#endif /* EXPERIMENTAL */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
@ -393,8 +329,8 @@ static const struct {
|
||||||
ERRHRD, ERRgeneral, NT_STATUS_FILE_INVALID}, {
|
ERRHRD, ERRgeneral, NT_STATUS_FILE_INVALID}, {
|
||||||
ERRHRD, ERRgeneral, NT_STATUS_ALLOTTED_SPACE_EXCEEDED},
|
ERRHRD, ERRgeneral, NT_STATUS_ALLOTTED_SPACE_EXCEEDED},
|
||||||
/* { This NT error code was 'sqashed'
|
/* { This NT error code was 'sqashed'
|
||||||
from NT_STATUS_INSUFFICIENT_RESOURCES to NT_STATUS_INSUFF_SERVER_RESOURCES
|
from NT_STATUS_INSUFFICIENT_RESOURCES to
|
||||||
during the session setup } */
|
NT_STATUS_INSUFF_SERVER_RESOURCES during the session setup } */
|
||||||
{
|
{
|
||||||
ERRDOS, ERRnomem, NT_STATUS_INSUFFICIENT_RESOURCES}, {
|
ERRDOS, ERRnomem, NT_STATUS_INSUFFICIENT_RESOURCES}, {
|
||||||
ERRDOS, ERRbadpath, NT_STATUS_DFS_EXIT_PATH_FOUND}, {
|
ERRDOS, ERRbadpath, NT_STATUS_DFS_EXIT_PATH_FOUND}, {
|
||||||
|
@ -638,8 +574,8 @@ static const struct {
|
||||||
ERRDOS, 19, NT_STATUS_TOO_LATE}, {
|
ERRDOS, 19, NT_STATUS_TOO_LATE}, {
|
||||||
ERRDOS, ERRnoaccess, NT_STATUS_NO_TRUST_LSA_SECRET},
|
ERRDOS, ERRnoaccess, NT_STATUS_NO_TRUST_LSA_SECRET},
|
||||||
/* { This NT error code was 'sqashed'
|
/* { This NT error code was 'sqashed'
|
||||||
from NT_STATUS_NO_TRUST_SAM_ACCOUNT to NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE
|
from NT_STATUS_NO_TRUST_SAM_ACCOUNT to
|
||||||
during the session setup } */
|
NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE during the session setup } */
|
||||||
{
|
{
|
||||||
ERRDOS, ERRnoaccess, NT_STATUS_NO_TRUST_SAM_ACCOUNT}, {
|
ERRDOS, ERRnoaccess, NT_STATUS_NO_TRUST_SAM_ACCOUNT}, {
|
||||||
ERRDOS, ERRnoaccess, NT_STATUS_TRUSTED_DOMAIN_FAILURE}, {
|
ERRDOS, ERRnoaccess, NT_STATUS_TRUSTED_DOMAIN_FAILURE}, {
|
||||||
|
@ -832,7 +768,8 @@ map_smb_to_linux_error(struct smb_hdr *smb)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (smb->Flags2 & SMBFLG2_ERR_STATUS) {
|
if (smb->Flags2 & SMBFLG2_ERR_STATUS) {
|
||||||
/* translate the newer STATUS codes to old style errors and then to POSIX errors */
|
/* translate the newer STATUS codes to old style SMB errors
|
||||||
|
* and then to POSIX errors */
|
||||||
__u32 err = le32_to_cpu(smb->Status.CifsError);
|
__u32 err = le32_to_cpu(smb->Status.CifsError);
|
||||||
if (cifsFYI & CIFS_RC)
|
if (cifsFYI & CIFS_RC)
|
||||||
cifs_print_status(err);
|
cifs_print_status(err);
|
||||||
|
@ -845,18 +782,19 @@ map_smb_to_linux_error(struct smb_hdr *smb)
|
||||||
/* old style errors */
|
/* old style errors */
|
||||||
|
|
||||||
/* DOS class smb error codes - map DOS */
|
/* DOS class smb error codes - map DOS */
|
||||||
if (smberrclass == ERRDOS) { /* one byte field no need to byte reverse */
|
if (smberrclass == ERRDOS) { /* 1 byte field no need to byte reverse */
|
||||||
for (i = 0;
|
for (i = 0;
|
||||||
i <
|
i <
|
||||||
sizeof (mapping_table_ERRDOS) /
|
sizeof (mapping_table_ERRDOS) /
|
||||||
sizeof (struct smb_to_posix_error); i++) {
|
sizeof (struct smb_to_posix_error); i++) {
|
||||||
if (mapping_table_ERRDOS[i].smb_err == 0)
|
if (mapping_table_ERRDOS[i].smb_err == 0)
|
||||||
break;
|
break;
|
||||||
else if (mapping_table_ERRDOS[i].smb_err == smberrcode) {
|
else if (mapping_table_ERRDOS[i].smb_err ==
|
||||||
|
smberrcode) {
|
||||||
rc = mapping_table_ERRDOS[i].posix_code;
|
rc = mapping_table_ERRDOS[i].posix_code;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* else try the next error mapping one to see if it will match */
|
/* else try next error mapping one to see if match */
|
||||||
}
|
}
|
||||||
} else if (smberrclass == ERRSRV) { /* server class of error codes */
|
} else if (smberrclass == ERRSRV) { /* server class of error codes */
|
||||||
for (i = 0;
|
for (i = 0;
|
||||||
|
@ -865,18 +803,21 @@ map_smb_to_linux_error(struct smb_hdr *smb)
|
||||||
sizeof (struct smb_to_posix_error); i++) {
|
sizeof (struct smb_to_posix_error); i++) {
|
||||||
if (mapping_table_ERRSRV[i].smb_err == 0)
|
if (mapping_table_ERRSRV[i].smb_err == 0)
|
||||||
break;
|
break;
|
||||||
else if (mapping_table_ERRSRV[i].smb_err == smberrcode) {
|
else if (mapping_table_ERRSRV[i].smb_err ==
|
||||||
|
smberrcode) {
|
||||||
rc = mapping_table_ERRSRV[i].posix_code;
|
rc = mapping_table_ERRSRV[i].posix_code;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* else try the next error mapping one to see if it will match */
|
/* else try next error mapping to see if match */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* else ERRHRD class errors or junk - return EIO */
|
/* else ERRHRD class errors or junk - return EIO */
|
||||||
|
|
||||||
cFYI(1, (" !!Mapping smb error code %d to POSIX err %d !!", smberrcode,rc));
|
cFYI(1, (" !!Mapping smb error code %d to POSIX err %d !!",
|
||||||
|
smberrcode, rc));
|
||||||
|
|
||||||
/* generic corrective action e.g. reconnect SMB session on ERRbaduid could be added */
|
/* generic corrective action e.g. reconnect SMB session on
|
||||||
|
* ERRbaduid could be added */
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* fs/cifs/ntlmssp.h
|
* fs/cifs/ntlmssp.h
|
||||||
*
|
*
|
||||||
* Copyright (c) International Business Machines Corp., 2002,2006
|
* Copyright (c) International Business Machines Corp., 2002,2007
|
||||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or modify
|
* This library is free software; you can redistribute it and/or modify
|
||||||
|
@ -27,18 +27,18 @@
|
||||||
#define UnknownMessage cpu_to_le32(8)
|
#define UnknownMessage cpu_to_le32(8)
|
||||||
|
|
||||||
/* Negotiate Flags */
|
/* Negotiate Flags */
|
||||||
#define NTLMSSP_NEGOTIATE_UNICODE 0x01 // Text strings are in unicode
|
#define NTLMSSP_NEGOTIATE_UNICODE 0x01 /* Text strings are in unicode */
|
||||||
#define NTLMSSP_NEGOTIATE_OEM 0x02 // Text strings are in OEM
|
#define NTLMSSP_NEGOTIATE_OEM 0x02 /* Text strings are in OEM */
|
||||||
#define NTLMSSP_REQUEST_TARGET 0x04 // Server return its auth realm
|
#define NTLMSSP_REQUEST_TARGET 0x04 /* Server return its auth realm */
|
||||||
#define NTLMSSP_NEGOTIATE_SIGN 0x0010 // Request signature capability
|
#define NTLMSSP_NEGOTIATE_SIGN 0x0010 /* Request signature capability */
|
||||||
#define NTLMSSP_NEGOTIATE_SEAL 0x0020 // Request confidentiality
|
#define NTLMSSP_NEGOTIATE_SEAL 0x0020 /* Request confidentiality */
|
||||||
#define NTLMSSP_NEGOTIATE_DGRAM 0x0040
|
#define NTLMSSP_NEGOTIATE_DGRAM 0x0040
|
||||||
#define NTLMSSP_NEGOTIATE_LM_KEY 0x0080 // Use LM session key for sign/seal
|
#define NTLMSSP_NEGOTIATE_LM_KEY 0x0080 /* Sign/seal use LM session key */
|
||||||
#define NTLMSSP_NEGOTIATE_NTLM 0x0200 // NTLM authentication
|
#define NTLMSSP_NEGOTIATE_NTLM 0x0200 /* NTLM authentication */
|
||||||
#define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x1000
|
#define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x1000
|
||||||
#define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x2000
|
#define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x2000
|
||||||
#define NTLMSSP_NEGOTIATE_LOCAL_CALL 0x4000 // client/server on same machine
|
#define NTLMSSP_NEGOTIATE_LOCAL_CALL 0x4000 /* client/server on same machine */
|
||||||
#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x8000 // Sign for all security levels
|
#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x8000 /* Sign for all security levels */
|
||||||
#define NTLMSSP_TARGET_TYPE_DOMAIN 0x10000
|
#define NTLMSSP_TARGET_TYPE_DOMAIN 0x10000
|
||||||
#define NTLMSSP_TARGET_TYPE_SERVER 0x20000
|
#define NTLMSSP_TARGET_TYPE_SERVER 0x20000
|
||||||
#define NTLMSSP_TARGET_TYPE_SHARE 0x40000
|
#define NTLMSSP_TARGET_TYPE_SHARE 0x40000
|
||||||
|
|
|
@ -51,7 +51,6 @@ static void dump_cifs_file_struct(struct file *file, char *label)
|
||||||
if (cf->srch_inf.emptyDir) {
|
if (cf->srch_inf.emptyDir) {
|
||||||
cFYI(1, ("empty dir"));
|
cFYI(1, ("empty dir"));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* DEBUG2 */
|
#endif /* DEBUG2 */
|
||||||
|
@ -73,7 +72,8 @@ static int construct_dentry(struct qstr *qstring, struct file *file,
|
||||||
qstring->hash = full_name_hash(qstring->name, qstring->len);
|
qstring->hash = full_name_hash(qstring->name, qstring->len);
|
||||||
tmp_dentry = d_lookup(file->f_path.dentry, qstring);
|
tmp_dentry = d_lookup(file->f_path.dentry, qstring);
|
||||||
if (tmp_dentry) {
|
if (tmp_dentry) {
|
||||||
cFYI(0, ("existing dentry with inode 0x%p", tmp_dentry->d_inode));
|
cFYI(0, ("existing dentry with inode 0x%p",
|
||||||
|
tmp_dentry->d_inode));
|
||||||
*ptmp_inode = tmp_dentry->d_inode;
|
*ptmp_inode = tmp_dentry->d_inode;
|
||||||
/* BB overwrite old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len??*/
|
/* BB overwrite old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len??*/
|
||||||
if (*ptmp_inode == NULL) {
|
if (*ptmp_inode == NULL) {
|
||||||
|
@ -254,7 +254,6 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
|
||||||
tmp_inode->i_fop = &cifs_file_direct_nobrl_ops;
|
tmp_inode->i_fop = &cifs_file_direct_nobrl_ops;
|
||||||
else
|
else
|
||||||
tmp_inode->i_fop = &cifs_file_direct_ops;
|
tmp_inode->i_fop = &cifs_file_direct_ops;
|
||||||
|
|
||||||
} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
||||||
tmp_inode->i_fop = &cifs_file_nobrl_ops;
|
tmp_inode->i_fop = &cifs_file_nobrl_ops;
|
||||||
else
|
else
|
||||||
|
@ -400,8 +399,9 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
|
||||||
tmp_inode->i_data.a_ops = &cifs_addr_ops;
|
tmp_inode->i_data.a_ops = &cifs_addr_ops;
|
||||||
|
|
||||||
if (isNewInode)
|
if (isNewInode)
|
||||||
return; /* No sense invalidating pages for new inode since we
|
return; /* No sense invalidating pages for new inode
|
||||||
have not started caching readahead file data yet */
|
since we have not started caching readahead
|
||||||
|
file data for it yet */
|
||||||
|
|
||||||
if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
|
if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
|
||||||
(local_size == tmp_inode->i_size)) {
|
(local_size == tmp_inode->i_size)) {
|
||||||
|
@ -463,7 +463,9 @@ static int initiate_cifs_search(const int xid, struct file *file)
|
||||||
|
|
||||||
ffirst_retry:
|
ffirst_retry:
|
||||||
/* test for Unix extensions */
|
/* test for Unix extensions */
|
||||||
if (pTcon->ses->capabilities & CAP_UNIX) {
|
/* but now check for them on the share/mount not on the SMB session */
|
||||||
|
/* if (pTcon->ses->capabilities & CAP_UNIX) { */
|
||||||
|
if (pTcon->unix_ext) {
|
||||||
cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX;
|
cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX;
|
||||||
} else if ((pTcon->ses->capabilities &
|
} else if ((pTcon->ses->capabilities &
|
||||||
(CAP_NT_SMBS | CAP_NT_FIND)) == 0) {
|
(CAP_NT_SMBS | CAP_NT_FIND)) == 0) {
|
||||||
|
@ -524,8 +526,8 @@ static char *nxt_dir_entry(char *old_entry, char *end_of_smb, int level)
|
||||||
new_entry, end_of_smb, old_entry));
|
new_entry, end_of_smb, old_entry));
|
||||||
return NULL;
|
return NULL;
|
||||||
} else if (((level == SMB_FIND_FILE_INFO_STANDARD) &&
|
} else if (((level == SMB_FIND_FILE_INFO_STANDARD) &&
|
||||||
(new_entry + sizeof(FIND_FILE_STANDARD_INFO) > end_of_smb)) ||
|
(new_entry + sizeof(FIND_FILE_STANDARD_INFO) > end_of_smb))
|
||||||
((level != SMB_FIND_FILE_INFO_STANDARD) &&
|
|| ((level != SMB_FIND_FILE_INFO_STANDARD) &&
|
||||||
(new_entry + sizeof(FILE_DIRECTORY_INFO) > end_of_smb))) {
|
(new_entry + sizeof(FILE_DIRECTORY_INFO) > end_of_smb))) {
|
||||||
cERROR(1, ("search entry %p extends after end of SMB %p",
|
cERROR(1, ("search entry %p extends after end of SMB %p",
|
||||||
new_entry, end_of_smb));
|
new_entry, end_of_smb));
|
||||||
|
@ -582,7 +584,8 @@ static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile)
|
||||||
filename = &pFindData->FileName[0];
|
filename = &pFindData->FileName[0];
|
||||||
len = pFindData->FileNameLength;
|
len = pFindData->FileNameLength;
|
||||||
} else {
|
} else {
|
||||||
cFYI(1,("Unknown findfirst level %d",cfile->srch_inf.info_level));
|
cFYI(1, ("Unknown findfirst level %d",
|
||||||
|
cfile->srch_inf.info_level));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filename) {
|
if (filename) {
|
||||||
|
@ -680,7 +683,8 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
|
||||||
}
|
}
|
||||||
rc = initiate_cifs_search(xid, file);
|
rc = initiate_cifs_search(xid, file);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
cFYI(1,("error %d reinitiating a search on rewind",rc));
|
cFYI(1, ("error %d reinitiating a search on rewind",
|
||||||
|
rc));
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -727,7 +731,7 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pos_in_buf >= cifsFile->srch_inf.entries_in_buffer) {
|
if (pos_in_buf >= cifsFile->srch_inf.entries_in_buffer) {
|
||||||
cFYI(1,("can not return entries pos_in_buf beyond last entry"));
|
cFYI(1, ("can not return entries pos_in_buf beyond last"));
|
||||||
*num_to_ret = 0;
|
*num_to_ret = 0;
|
||||||
} else
|
} else
|
||||||
*num_to_ret = cifsFile->srch_inf.entries_in_buffer - pos_in_buf;
|
*num_to_ret = cifsFile->srch_inf.entries_in_buffer - pos_in_buf;
|
||||||
|
@ -758,7 +762,7 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst,
|
||||||
len = strnlen(filename, PATH_MAX);
|
len = strnlen(filename, PATH_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* BB fixme - hash low and high 32 bits if not 64 bit arch BB fixme */
|
/* BB fixme - hash low and high 32 bits if not 64 bit arch BB */
|
||||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
|
||||||
*pinum = pFindData->UniqueId;
|
*pinum = pFindData->UniqueId;
|
||||||
} else if (level == SMB_FIND_FILE_DIRECTORY_INFO) {
|
} else if (level == SMB_FIND_FILE_DIRECTORY_INFO) {
|
||||||
|
@ -863,7 +867,8 @@ static int cifs_filldir(char *pfindEntry, struct file *file,
|
||||||
if (rc) {
|
if (rc) {
|
||||||
/* inode created, we need to hash it with right inode number */
|
/* inode created, we need to hash it with right inode number */
|
||||||
if (inum != 0) {
|
if (inum != 0) {
|
||||||
/* BB fixme - hash the 2 32 quantities bits together if necessary BB */
|
/* BB fixme - hash the 2 32 quantities bits together if
|
||||||
|
* necessary BB */
|
||||||
tmp_inode->i_ino = inum;
|
tmp_inode->i_ino = inum;
|
||||||
}
|
}
|
||||||
insert_inode_hash(tmp_inode);
|
insert_inode_hash(tmp_inode);
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
*
|
*
|
||||||
* SMB/CIFS session setup handling routines
|
* SMB/CIFS session setup handling routines
|
||||||
*
|
*
|
||||||
* Copyright (c) International Business Machines Corp., 2006
|
* Copyright (c) International Business Machines Corp., 2006, 2007
|
||||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or modify
|
* This library is free software; you can redistribute it and/or modify
|
||||||
|
@ -51,7 +51,8 @@ static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB)
|
||||||
capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
|
capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
|
||||||
CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
|
CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
|
||||||
|
|
||||||
if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
|
if (ses->server->secMode &
|
||||||
|
(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
|
||||||
pSMB->req.hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
|
pSMB->req.hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
|
||||||
|
|
||||||
if (ses->capabilities & CAP_UNICODE) {
|
if (ses->capabilities & CAP_UNICODE) {
|
||||||
|
@ -170,7 +171,8 @@ static void ascii_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
|
||||||
*pbcc_area = bcc_ptr;
|
*pbcc_area = bcc_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int decode_unicode_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses,
|
static int decode_unicode_ssetup(char **pbcc_area, int bleft,
|
||||||
|
struct cifsSesInfo *ses,
|
||||||
const struct nls_table *nls_cp)
|
const struct nls_table *nls_cp)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
@ -255,7 +257,8 @@ static int decode_unicode_ssetup(char ** pbcc_area, int bleft, struct cifsSesInf
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int decode_ascii_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses,
|
static int decode_ascii_ssetup(char **pbcc_area, int bleft,
|
||||||
|
struct cifsSesInfo *ses,
|
||||||
const struct nls_table *nls_cp)
|
const struct nls_table *nls_cp)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
@ -347,7 +350,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
|
||||||
} else if ((type == NTLM) || (type == NTLMv2)) {
|
} else if ((type == NTLM) || (type == NTLMv2)) {
|
||||||
/* For NTLMv2 failures eventually may need to retry NTLM */
|
/* For NTLMv2 failures eventually may need to retry NTLM */
|
||||||
wct = 13; /* old style NTLM sessionsetup */
|
wct = 13; /* old style NTLM sessionsetup */
|
||||||
} else /* same size for negotiate or auth, NTLMSSP or extended security */
|
} else /* same size: negotiate or auth, NTLMSSP or extended security */
|
||||||
wct = 12;
|
wct = 12;
|
||||||
|
|
||||||
rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses,
|
rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses,
|
||||||
|
@ -416,7 +419,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
|
||||||
|
|
||||||
if (first_time) /* should this be moved into common code
|
if (first_time) /* should this be moved into common code
|
||||||
with similar ntlmv2 path? */
|
with similar ntlmv2 path? */
|
||||||
cifs_calculate_mac_key(ses->server->mac_signing_key,
|
cifs_calculate_mac_key(&ses->server->mac_signing_key,
|
||||||
ntlm_session_key, ses->password);
|
ntlm_session_key, ses->password);
|
||||||
/* copy session key */
|
/* copy session key */
|
||||||
|
|
||||||
|
@ -465,7 +468,8 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
|
||||||
|
|
||||||
/* memcpy(bcc_ptr, (char *)ntlm_session_key,LM2_SESS_KEY_SIZE);
|
/* memcpy(bcc_ptr, (char *)ntlm_session_key,LM2_SESS_KEY_SIZE);
|
||||||
bcc_ptr += LM2_SESS_KEY_SIZE; */
|
bcc_ptr += LM2_SESS_KEY_SIZE; */
|
||||||
memcpy(bcc_ptr, (char *)v2_sess_key, sizeof(struct ntlmv2_resp));
|
memcpy(bcc_ptr, (char *)v2_sess_key,
|
||||||
|
sizeof(struct ntlmv2_resp));
|
||||||
bcc_ptr += sizeof(struct ntlmv2_resp);
|
bcc_ptr += sizeof(struct ntlmv2_resp);
|
||||||
kfree(v2_sess_key);
|
kfree(v2_sess_key);
|
||||||
if (ses->capabilities & CAP_UNICODE) {
|
if (ses->capabilities & CAP_UNICODE) {
|
||||||
|
@ -531,7 +535,8 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
|
||||||
rc = decode_unicode_ssetup(&bcc_ptr, bytes_remaining,
|
rc = decode_unicode_ssetup(&bcc_ptr, bytes_remaining,
|
||||||
ses, nls_cp);
|
ses, nls_cp);
|
||||||
else
|
else
|
||||||
rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,nls_cp);
|
rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining,
|
||||||
|
ses, nls_cp);
|
||||||
|
|
||||||
ssetup_exit:
|
ssetup_exit:
|
||||||
kfree(str_area);
|
kfree(str_area);
|
||||||
|
|
|
@ -97,7 +97,7 @@ _my_wcslen(__u16 * str)
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_my_mbstowcs(__u16 * dst, const unsigned char *src, int len)
|
_my_mbstowcs(__u16 * dst, const unsigned char *src, int len)
|
||||||
{ /* not a very good conversion routine - change/fix */
|
{ /* BB not a very good conversion routine - change/fix */
|
||||||
int i;
|
int i;
|
||||||
__u16 val;
|
__u16 val;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* fs/cifs/transport.c
|
* fs/cifs/transport.c
|
||||||
*
|
*
|
||||||
* Copyright (C) International Business Machines Corp., 2002,2005
|
* Copyright (C) International Business Machines Corp., 2002,2007
|
||||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||||
* Jeremy Allison (jra@samba.org) 2006.
|
* Jeremy Allison (jra@samba.org) 2006.
|
||||||
*
|
*
|
||||||
|
@ -333,8 +333,8 @@ static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* can not count locking commands against total since
|
/* can not count locking commands against total
|
||||||
they are allowed to block on server */
|
as they are allowed to block on server */
|
||||||
|
|
||||||
/* update # of requests on the wire to server */
|
/* update # of requests on the wire to server */
|
||||||
if (long_op < 3)
|
if (long_op < 3)
|
||||||
|
@ -559,7 +559,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
|
||||||
(ses->server->secMode & (SECMODE_SIGN_REQUIRED |
|
(ses->server->secMode & (SECMODE_SIGN_REQUIRED |
|
||||||
SECMODE_SIGN_ENABLED))) {
|
SECMODE_SIGN_ENABLED))) {
|
||||||
rc = cifs_verify_signature(midQ->resp_buf,
|
rc = cifs_verify_signature(midQ->resp_buf,
|
||||||
ses->server->mac_signing_key,
|
&ses->server->mac_signing_key,
|
||||||
midQ->sequence_number+1);
|
midQ->sequence_number+1);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
cERROR(1, ("Unexpected SMB signature"));
|
cERROR(1, ("Unexpected SMB signature"));
|
||||||
|
@ -738,7 +738,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
|
||||||
(ses->server->secMode & (SECMODE_SIGN_REQUIRED |
|
(ses->server->secMode & (SECMODE_SIGN_REQUIRED |
|
||||||
SECMODE_SIGN_ENABLED))) {
|
SECMODE_SIGN_ENABLED))) {
|
||||||
rc = cifs_verify_signature(out_buf,
|
rc = cifs_verify_signature(out_buf,
|
||||||
ses->server->mac_signing_key,
|
&ses->server->mac_signing_key,
|
||||||
midQ->sequence_number+1);
|
midQ->sequence_number+1);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
cERROR(1, ("Unexpected SMB signature"));
|
cERROR(1, ("Unexpected SMB signature"));
|
||||||
|
@ -982,7 +982,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
|
||||||
(ses->server->secMode & (SECMODE_SIGN_REQUIRED |
|
(ses->server->secMode & (SECMODE_SIGN_REQUIRED |
|
||||||
SECMODE_SIGN_ENABLED))) {
|
SECMODE_SIGN_ENABLED))) {
|
||||||
rc = cifs_verify_signature(out_buf,
|
rc = cifs_verify_signature(out_buf,
|
||||||
ses->server->mac_signing_key,
|
&ses->server->mac_signing_key,
|
||||||
midQ->sequence_number+1);
|
midQ->sequence_number+1);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
cERROR(1, ("Unexpected SMB signature"));
|
cERROR(1, ("Unexpected SMB signature"));
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* fs/cifs/xattr.c
|
* fs/cifs/xattr.c
|
||||||
*
|
*
|
||||||
* Copyright (c) International Business Machines Corp., 2003
|
* Copyright (c) International Business Machines Corp., 2003, 2007
|
||||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or modify
|
* This library is free software; you can redistribute it and/or modify
|
||||||
|
@ -71,7 +71,9 @@ int cifs_removexattr(struct dentry * direntry, const char * ea_name)
|
||||||
cFYI(1, ("Null xattr names not supported"));
|
cFYI(1, ("Null xattr names not supported"));
|
||||||
} else if (strncmp(ea_name, CIFS_XATTR_USER_PREFIX, 5)
|
} else if (strncmp(ea_name, CIFS_XATTR_USER_PREFIX, 5)
|
||||||
&& (strncmp(ea_name, CIFS_XATTR_OS2_PREFIX, 4))) {
|
&& (strncmp(ea_name, CIFS_XATTR_OS2_PREFIX, 4))) {
|
||||||
cFYI(1,("illegal xattr namespace %s (only user namespace supported)",ea_name));
|
cFYI(1,
|
||||||
|
("illegal xattr request %s (only user namespace supported)",
|
||||||
|
ea_name));
|
||||||
/* BB what if no namespace prefix? */
|
/* BB what if no namespace prefix? */
|
||||||
/* Should we just pass them to server, except for
|
/* Should we just pass them to server, except for
|
||||||
system and perhaps security prefixes? */
|
system and perhaps security prefixes? */
|
||||||
|
@ -168,7 +170,8 @@ int cifs_setxattr(struct dentry * direntry, const char * ea_name,
|
||||||
#else
|
#else
|
||||||
cFYI(1, ("set POSIX ACL not supported"));
|
cFYI(1, ("set POSIX ACL not supported"));
|
||||||
#endif
|
#endif
|
||||||
} else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
|
} else if (strncmp(ea_name, POSIX_ACL_XATTR_DEFAULT,
|
||||||
|
strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
|
||||||
#ifdef CONFIG_CIFS_POSIX
|
#ifdef CONFIG_CIFS_POSIX
|
||||||
if (sb->s_flags & MS_POSIXACL)
|
if (sb->s_flags & MS_POSIXACL)
|
||||||
rc = CIFSSMBSetPosixACL(xid, pTcon, full_path,
|
rc = CIFSSMBSetPosixACL(xid, pTcon, full_path,
|
||||||
|
@ -181,7 +184,8 @@ int cifs_setxattr(struct dentry * direntry, const char * ea_name,
|
||||||
cFYI(1, ("set default POSIX ACL not supported"));
|
cFYI(1, ("set default POSIX ACL not supported"));
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
cFYI(1,("illegal xattr request %s (only user namespace supported)",ea_name));
|
cFYI(1, ("illegal xattr request %s (only user namespace"
|
||||||
|
" supported)", ea_name));
|
||||||
/* BB what if no namespace prefix? */
|
/* BB what if no namespace prefix? */
|
||||||
/* Should we just pass them to server, except for
|
/* Should we just pass them to server, except for
|
||||||
system and perhaps security prefixes? */
|
system and perhaps security prefixes? */
|
||||||
|
@ -272,7 +276,6 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name,
|
||||||
CIFSSMBClose(xid, pTcon, fid);
|
CIFSSMBClose(xid, pTcon, fid);
|
||||||
}
|
}
|
||||||
} */ /* BB enable after fixing up return data */
|
} */ /* BB enable after fixing up return data */
|
||||||
|
|
||||||
#else
|
#else
|
||||||
cFYI(1, ("query POSIX ACL not supported yet"));
|
cFYI(1, ("query POSIX ACL not supported yet"));
|
||||||
#endif /* CONFIG_CIFS_POSIX */
|
#endif /* CONFIG_CIFS_POSIX */
|
||||||
|
@ -295,7 +298,9 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name,
|
||||||
CIFS_XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) == 0) {
|
CIFS_XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) == 0) {
|
||||||
cFYI(1, ("Security xattr namespace not supported yet"));
|
cFYI(1, ("Security xattr namespace not supported yet"));
|
||||||
} else {
|
} else {
|
||||||
cFYI(1,("illegal xattr name request %s (only user namespace supported)",ea_name));
|
cFYI(1,
|
||||||
|
("illegal xattr request %s (only user namespace supported)",
|
||||||
|
ea_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We could add an additional check for streams ie
|
/* We could add an additional check for streams ie
|
||||||
|
|
Loading…
Add table
Reference in a new issue