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: cifs: use CreationTime like an i_generation field cifs: switch cifs_open and cifs_create to use CIFSSMBUnixSetFileInfo cifs: show "acl" in DebugData Features when it's compiled in cifs: move "ntlmssp" and "local_leases" options out of experimental code cifs: replace some hardcoded values with preprocessor constants cifs: remove unnecessary locking around sequence_number [CIFS] Fix minor merge conflict in fs/cifs/dir.c CIFS: Simplify cifs_open code CIFS: Simplify non-posix open stuff (try #2) CIFS: Add match_port check during looking for an existing connection (try #4) CIFS: Simplify ipv*_connect functions into one (try #4) cifs: Support NTLM2 session security during NTLMSSP authentication [try #5] cifs: don't overwrite dentry name in d_revalidate
This commit is contained in:
commit
f3ea597251
|
@ -64,7 +64,9 @@ static uint16_t cifs_server_get_key(const void *cookie_netfs_data,
|
||||||
void *buffer, uint16_t maxbuf)
|
void *buffer, uint16_t maxbuf)
|
||||||
{
|
{
|
||||||
const struct TCP_Server_Info *server = cookie_netfs_data;
|
const struct TCP_Server_Info *server = cookie_netfs_data;
|
||||||
const struct sockaddr *sa = (struct sockaddr *) &server->addr.sockAddr;
|
const struct sockaddr *sa = (struct sockaddr *) &server->dstaddr;
|
||||||
|
const struct sockaddr_in *addr = (struct sockaddr_in *) sa;
|
||||||
|
const struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) sa;
|
||||||
struct cifs_server_key *key = buffer;
|
struct cifs_server_key *key = buffer;
|
||||||
uint16_t key_len = sizeof(struct cifs_server_key);
|
uint16_t key_len = sizeof(struct cifs_server_key);
|
||||||
|
|
||||||
|
@ -76,16 +78,16 @@ static uint16_t cifs_server_get_key(const void *cookie_netfs_data,
|
||||||
*/
|
*/
|
||||||
switch (sa->sa_family) {
|
switch (sa->sa_family) {
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
key->family = server->addr.sockAddr.sin_family;
|
key->family = sa->sa_family;
|
||||||
key->port = server->addr.sockAddr.sin_port;
|
key->port = addr->sin_port;
|
||||||
key->addr[0].ipv4_addr = server->addr.sockAddr.sin_addr;
|
key->addr[0].ipv4_addr = addr->sin_addr;
|
||||||
key_len += sizeof(key->addr[0].ipv4_addr);
|
key_len += sizeof(key->addr[0].ipv4_addr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
key->family = server->addr.sockAddr6.sin6_family;
|
key->family = sa->sa_family;
|
||||||
key->port = server->addr.sockAddr6.sin6_port;
|
key->port = addr6->sin6_port;
|
||||||
key->addr[0].ipv6_addr = server->addr.sockAddr6.sin6_addr;
|
key->addr[0].ipv6_addr = addr6->sin6_addr;
|
||||||
key_len += sizeof(key->addr[0].ipv6_addr);
|
key_len += sizeof(key->addr[0].ipv6_addr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -119,29 +119,27 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
|
||||||
"Display Internal CIFS Data Structures for Debugging\n"
|
"Display Internal CIFS Data Structures for Debugging\n"
|
||||||
"---------------------------------------------------\n");
|
"---------------------------------------------------\n");
|
||||||
seq_printf(m, "CIFS Version %s\n", CIFS_VERSION);
|
seq_printf(m, "CIFS Version %s\n", CIFS_VERSION);
|
||||||
seq_printf(m, "Features: ");
|
seq_printf(m, "Features:");
|
||||||
#ifdef CONFIG_CIFS_DFS_UPCALL
|
#ifdef CONFIG_CIFS_DFS_UPCALL
|
||||||
seq_printf(m, "dfs");
|
seq_printf(m, " dfs");
|
||||||
seq_putc(m, ' ');
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_CIFS_FSCACHE
|
#ifdef CONFIG_CIFS_FSCACHE
|
||||||
seq_printf(m, "fscache");
|
seq_printf(m, " fscache");
|
||||||
seq_putc(m, ' ');
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
#ifdef CONFIG_CIFS_WEAK_PW_HASH
|
||||||
seq_printf(m, "lanman");
|
seq_printf(m, " lanman");
|
||||||
seq_putc(m, ' ');
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_CIFS_POSIX
|
#ifdef CONFIG_CIFS_POSIX
|
||||||
seq_printf(m, "posix");
|
seq_printf(m, " posix");
|
||||||
seq_putc(m, ' ');
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_CIFS_UPCALL
|
#ifdef CONFIG_CIFS_UPCALL
|
||||||
seq_printf(m, "spnego");
|
seq_printf(m, " spnego");
|
||||||
seq_putc(m, ' ');
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_CIFS_XATTR
|
#ifdef CONFIG_CIFS_XATTR
|
||||||
seq_printf(m, "xattr");
|
seq_printf(m, " xattr");
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_CIFS_ACL
|
||||||
|
seq_printf(m, " acl");
|
||||||
#endif
|
#endif
|
||||||
seq_putc(m, '\n');
|
seq_putc(m, '\n');
|
||||||
seq_printf(m, "Active VFS Requests: %d\n", GlobalTotalActiveXid);
|
seq_printf(m, "Active VFS Requests: %d\n", GlobalTotalActiveXid);
|
||||||
|
|
|
@ -98,6 +98,8 @@ struct key *
|
||||||
cifs_get_spnego_key(struct cifsSesInfo *sesInfo)
|
cifs_get_spnego_key(struct cifsSesInfo *sesInfo)
|
||||||
{
|
{
|
||||||
struct TCP_Server_Info *server = sesInfo->server;
|
struct TCP_Server_Info *server = sesInfo->server;
|
||||||
|
struct sockaddr_in *sa = (struct sockaddr_in *) &server->dstaddr;
|
||||||
|
struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) &server->dstaddr;
|
||||||
char *description, *dp;
|
char *description, *dp;
|
||||||
size_t desc_len;
|
size_t desc_len;
|
||||||
struct key *spnego_key;
|
struct key *spnego_key;
|
||||||
|
@ -127,10 +129,10 @@ cifs_get_spnego_key(struct cifsSesInfo *sesInfo)
|
||||||
dp = description + strlen(description);
|
dp = description + strlen(description);
|
||||||
|
|
||||||
/* add the server address */
|
/* add the server address */
|
||||||
if (server->addr.sockAddr.sin_family == AF_INET)
|
if (server->dstaddr.ss_family == AF_INET)
|
||||||
sprintf(dp, "ip4=%pI4", &server->addr.sockAddr.sin_addr);
|
sprintf(dp, "ip4=%pI4", &sa->sin_addr);
|
||||||
else if (server->addr.sockAddr.sin_family == AF_INET6)
|
else if (server->dstaddr.ss_family == AF_INET6)
|
||||||
sprintf(dp, "ip6=%pI6", &server->addr.sockAddr6.sin6_addr);
|
sprintf(dp, "ip6=%pI6", &sa6->sin6_addr);
|
||||||
else
|
else
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,7 @@ static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* must be called with server->srv_mutex held */
|
||||||
int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
|
int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
|
||||||
__u32 *pexpected_response_sequence_number)
|
__u32 *pexpected_response_sequence_number)
|
||||||
{
|
{
|
||||||
|
@ -84,14 +85,12 @@ int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
|
||||||
if ((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0)
|
if ((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
spin_lock(&GlobalMid_Lock);
|
|
||||||
cifs_pdu->Signature.Sequence.SequenceNumber =
|
cifs_pdu->Signature.Sequence.SequenceNumber =
|
||||||
cpu_to_le32(server->sequence_number);
|
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);
|
|
||||||
|
|
||||||
rc = cifs_calculate_signature(cifs_pdu, server, smb_signature);
|
rc = cifs_calculate_signature(cifs_pdu, server, smb_signature);
|
||||||
if (rc)
|
if (rc)
|
||||||
|
@ -149,6 +148,7 @@ static int cifs_calc_signature2(const struct kvec *iov, int n_vec,
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* must be called with server->srv_mutex held */
|
||||||
int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
|
int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
|
||||||
__u32 *pexpected_response_sequence_number)
|
__u32 *pexpected_response_sequence_number)
|
||||||
{
|
{
|
||||||
|
@ -162,14 +162,12 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
|
||||||
if ((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0)
|
if ((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
spin_lock(&GlobalMid_Lock);
|
|
||||||
cifs_pdu->Signature.Sequence.SequenceNumber =
|
cifs_pdu->Signature.Sequence.SequenceNumber =
|
||||||
cpu_to_le32(server->sequence_number);
|
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);
|
|
||||||
|
|
||||||
rc = cifs_calc_signature2(iov, n_vec, server, smb_signature);
|
rc = cifs_calc_signature2(iov, n_vec, server, smb_signature);
|
||||||
if (rc)
|
if (rc)
|
||||||
|
|
|
@ -329,6 +329,8 @@ cifs_alloc_inode(struct super_block *sb)
|
||||||
cifs_inode->invalid_mapping = false;
|
cifs_inode->invalid_mapping = false;
|
||||||
cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
|
cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
|
||||||
cifs_inode->server_eof = 0;
|
cifs_inode->server_eof = 0;
|
||||||
|
cifs_inode->uniqueid = 0;
|
||||||
|
cifs_inode->createtime = 0;
|
||||||
|
|
||||||
/* Can not set i_flags here - they get immediately overwritten
|
/* Can not set i_flags here - they get immediately overwritten
|
||||||
to zero by the VFS */
|
to zero by the VFS */
|
||||||
|
@ -361,18 +363,19 @@ cifs_evict_inode(struct inode *inode)
|
||||||
static void
|
static void
|
||||||
cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server)
|
cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server)
|
||||||
{
|
{
|
||||||
|
struct sockaddr_in *sa = (struct sockaddr_in *) &server->dstaddr;
|
||||||
|
struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) &server->dstaddr;
|
||||||
|
|
||||||
seq_printf(s, ",addr=");
|
seq_printf(s, ",addr=");
|
||||||
|
|
||||||
switch (server->addr.sockAddr.sin_family) {
|
switch (server->dstaddr.ss_family) {
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
seq_printf(s, "%pI4", &server->addr.sockAddr.sin_addr.s_addr);
|
seq_printf(s, "%pI4", &sa->sin_addr.s_addr);
|
||||||
break;
|
break;
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
seq_printf(s, "%pI6",
|
seq_printf(s, "%pI6", &sa6->sin6_addr.s6_addr);
|
||||||
&server->addr.sockAddr6.sin6_addr.s6_addr);
|
if (sa6->sin6_scope_id)
|
||||||
if (server->addr.sockAddr6.sin6_scope_id)
|
seq_printf(s, "%%%u", sa6->sin6_scope_id);
|
||||||
seq_printf(s, "%%%u",
|
|
||||||
server->addr.sockAddr6.sin6_scope_id);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
seq_printf(s, "(unknown)");
|
seq_printf(s, "(unknown)");
|
||||||
|
|
|
@ -163,10 +163,7 @@ struct TCP_Server_Info {
|
||||||
char server_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL];
|
char server_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL];
|
||||||
char *hostname; /* hostname portion of UNC string */
|
char *hostname; /* hostname portion of UNC string */
|
||||||
struct socket *ssocket;
|
struct socket *ssocket;
|
||||||
union {
|
struct sockaddr_storage dstaddr;
|
||||||
struct sockaddr_in sockAddr;
|
|
||||||
struct sockaddr_in6 sockAddr6;
|
|
||||||
} addr;
|
|
||||||
struct sockaddr_storage srcaddr; /* locally bind to this IP */
|
struct sockaddr_storage srcaddr; /* locally bind to this IP */
|
||||||
wait_queue_head_t response_q;
|
wait_queue_head_t response_q;
|
||||||
wait_queue_head_t request_q; /* if more than maxmpx to srvr must block*/
|
wait_queue_head_t request_q; /* if more than maxmpx to srvr must block*/
|
||||||
|
@ -210,7 +207,7 @@ struct TCP_Server_Info {
|
||||||
char cryptkey[CIFS_CRYPTO_KEY_SIZE]; /* used by ntlm, ntlmv2 etc */
|
char cryptkey[CIFS_CRYPTO_KEY_SIZE]; /* used by ntlm, ntlmv2 etc */
|
||||||
/* 16th byte of RFC1001 workstation name is always null */
|
/* 16th byte of RFC1001 workstation name is always null */
|
||||||
char workstation_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL];
|
char workstation_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL];
|
||||||
__u32 sequence_number; /* needed for CIFS PDU signature */
|
__u32 sequence_number; /* for signing, protected by srv_mutex */
|
||||||
struct session_key session_key;
|
struct session_key session_key;
|
||||||
unsigned long lstrp; /* when we got last response from this server */
|
unsigned long lstrp; /* when we got last response from this server */
|
||||||
u16 dialect; /* dialect index that server chose */
|
u16 dialect; /* dialect index that server chose */
|
||||||
|
@ -456,6 +453,7 @@ struct cifsInodeInfo {
|
||||||
bool invalid_mapping:1; /* pagecache is invalid */
|
bool invalid_mapping:1; /* pagecache is invalid */
|
||||||
u64 server_eof; /* current file size on server */
|
u64 server_eof; /* current file size on server */
|
||||||
u64 uniqueid; /* server inode number */
|
u64 uniqueid; /* server inode number */
|
||||||
|
u64 createtime; /* creation time on server */
|
||||||
#ifdef CONFIG_CIFS_FSCACHE
|
#ifdef CONFIG_CIFS_FSCACHE
|
||||||
struct fscache_cookie *fscache;
|
struct fscache_cookie *fscache;
|
||||||
#endif
|
#endif
|
||||||
|
@ -576,6 +574,7 @@ struct cifs_fattr {
|
||||||
u64 cf_uniqueid;
|
u64 cf_uniqueid;
|
||||||
u64 cf_eof;
|
u64 cf_eof;
|
||||||
u64 cf_bytes;
|
u64 cf_bytes;
|
||||||
|
u64 cf_createtime;
|
||||||
uid_t cf_uid;
|
uid_t cf_uid;
|
||||||
gid_t cf_gid;
|
gid_t cf_gid;
|
||||||
umode_t cf_mode;
|
umode_t cf_mode;
|
||||||
|
|
|
@ -401,15 +401,12 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
|
||||||
else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
|
else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
|
||||||
cFYI(1, "Kerberos only mechanism, enable extended security");
|
cFYI(1, "Kerberos only mechanism, enable extended security");
|
||||||
pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
|
pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
|
||||||
}
|
} else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
|
||||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
|
||||||
else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
|
|
||||||
pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
|
pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
|
||||||
else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) {
|
else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) {
|
||||||
cFYI(1, "NTLMSSP only mechanism, enable extended security");
|
cFYI(1, "NTLMSSP only mechanism, enable extended security");
|
||||||
pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
|
pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
count = 0;
|
count = 0;
|
||||||
for (i = 0; i < CIFS_NUM_PROT; i++) {
|
for (i = 0; i < CIFS_NUM_PROT; i++) {
|
||||||
|
|
|
@ -64,8 +64,8 @@ struct smb_vol {
|
||||||
char *UNC;
|
char *UNC;
|
||||||
char *UNCip;
|
char *UNCip;
|
||||||
char *iocharset; /* local code page for mapping to and from Unicode */
|
char *iocharset; /* local code page for mapping to and from Unicode */
|
||||||
char source_rfc1001_name[16]; /* netbios name of client */
|
char source_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* clnt nb name */
|
||||||
char target_rfc1001_name[16]; /* netbios name of server for Win9x/ME */
|
char target_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* srvr nb name */
|
||||||
uid_t cred_uid;
|
uid_t cred_uid;
|
||||||
uid_t linux_uid;
|
uid_t linux_uid;
|
||||||
gid_t linux_gid;
|
gid_t linux_gid;
|
||||||
|
@ -115,8 +115,8 @@ struct smb_vol {
|
||||||
#define TLINK_ERROR_EXPIRE (1 * HZ)
|
#define TLINK_ERROR_EXPIRE (1 * HZ)
|
||||||
#define TLINK_IDLE_EXPIRE (600 * HZ)
|
#define TLINK_IDLE_EXPIRE (600 * HZ)
|
||||||
|
|
||||||
static int ipv4_connect(struct TCP_Server_Info *server);
|
static int ip_connect(struct TCP_Server_Info *server);
|
||||||
static int ipv6_connect(struct TCP_Server_Info *server);
|
static int generic_ip_connect(struct TCP_Server_Info *server);
|
||||||
static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
|
static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
|
||||||
static void cifs_prune_tlinks(struct work_struct *work);
|
static void cifs_prune_tlinks(struct work_struct *work);
|
||||||
|
|
||||||
|
@ -200,10 +200,9 @@ cifs_reconnect(struct TCP_Server_Info *server)
|
||||||
while ((server->tcpStatus != CifsExiting) &&
|
while ((server->tcpStatus != CifsExiting) &&
|
||||||
(server->tcpStatus != CifsGood)) {
|
(server->tcpStatus != CifsGood)) {
|
||||||
try_to_freeze();
|
try_to_freeze();
|
||||||
if (server->addr.sockAddr6.sin6_family == AF_INET6)
|
|
||||||
rc = ipv6_connect(server);
|
/* we should try only the port we connected to before */
|
||||||
else
|
rc = generic_ip_connect(server);
|
||||||
rc = ipv4_connect(server);
|
|
||||||
if (rc) {
|
if (rc) {
|
||||||
cFYI(1, "reconnect error %d", rc);
|
cFYI(1, "reconnect error %d", rc);
|
||||||
msleep(3000);
|
msleep(3000);
|
||||||
|
@ -477,7 +476,7 @@ incomplete_rcv:
|
||||||
* initialize frame)
|
* initialize frame)
|
||||||
*/
|
*/
|
||||||
cifs_set_port((struct sockaddr *)
|
cifs_set_port((struct sockaddr *)
|
||||||
&server->addr.sockAddr, CIFS_PORT);
|
&server->dstaddr, CIFS_PORT);
|
||||||
cifs_reconnect(server);
|
cifs_reconnect(server);
|
||||||
csocket = server->ssocket;
|
csocket = server->ssocket;
|
||||||
wake_up(&server->response_q);
|
wake_up(&server->response_q);
|
||||||
|
@ -817,11 +816,11 @@ cifs_parse_mount_options(char *options, const char *devname,
|
||||||
* informational, only used for servers that do not support
|
* informational, only used for servers that do not support
|
||||||
* port 445 and it can be overridden at mount time
|
* port 445 and it can be overridden at mount time
|
||||||
*/
|
*/
|
||||||
memset(vol->source_rfc1001_name, 0x20, 15);
|
memset(vol->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
|
||||||
for (i = 0; i < strnlen(nodename, 15); i++)
|
for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
|
||||||
vol->source_rfc1001_name[i] = toupper(nodename[i]);
|
vol->source_rfc1001_name[i] = toupper(nodename[i]);
|
||||||
|
|
||||||
vol->source_rfc1001_name[15] = 0;
|
vol->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
|
||||||
/* null target name indicates to use *SMBSERVR default called name
|
/* null target name indicates to use *SMBSERVR default called name
|
||||||
if we end up sending RFC1001 session initialize */
|
if we end up sending RFC1001 session initialize */
|
||||||
vol->target_rfc1001_name[0] = 0;
|
vol->target_rfc1001_name[0] = 0;
|
||||||
|
@ -985,13 +984,11 @@ cifs_parse_mount_options(char *options, const char *devname,
|
||||||
return 1;
|
return 1;
|
||||||
} else if (strnicmp(value, "krb5", 4) == 0) {
|
} else if (strnicmp(value, "krb5", 4) == 0) {
|
||||||
vol->secFlg |= CIFSSEC_MAY_KRB5;
|
vol->secFlg |= CIFSSEC_MAY_KRB5;
|
||||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
|
||||||
} else if (strnicmp(value, "ntlmsspi", 8) == 0) {
|
} else if (strnicmp(value, "ntlmsspi", 8) == 0) {
|
||||||
vol->secFlg |= CIFSSEC_MAY_NTLMSSP |
|
vol->secFlg |= CIFSSEC_MAY_NTLMSSP |
|
||||||
CIFSSEC_MUST_SIGN;
|
CIFSSEC_MUST_SIGN;
|
||||||
} else if (strnicmp(value, "ntlmssp", 7) == 0) {
|
} else if (strnicmp(value, "ntlmssp", 7) == 0) {
|
||||||
vol->secFlg |= CIFSSEC_MAY_NTLMSSP;
|
vol->secFlg |= CIFSSEC_MAY_NTLMSSP;
|
||||||
#endif
|
|
||||||
} else if (strnicmp(value, "ntlmv2i", 7) == 0) {
|
} else if (strnicmp(value, "ntlmv2i", 7) == 0) {
|
||||||
vol->secFlg |= CIFSSEC_MAY_NTLMV2 |
|
vol->secFlg |= CIFSSEC_MAY_NTLMV2 |
|
||||||
CIFSSEC_MUST_SIGN;
|
CIFSSEC_MUST_SIGN;
|
||||||
|
@ -1168,22 +1165,22 @@ cifs_parse_mount_options(char *options, const char *devname,
|
||||||
if (!value || !*value || (*value == ' ')) {
|
if (!value || !*value || (*value == ' ')) {
|
||||||
cFYI(1, "invalid (empty) netbiosname");
|
cFYI(1, "invalid (empty) netbiosname");
|
||||||
} else {
|
} else {
|
||||||
memset(vol->source_rfc1001_name, 0x20, 15);
|
memset(vol->source_rfc1001_name, 0x20,
|
||||||
for (i = 0; i < 15; i++) {
|
RFC1001_NAME_LEN);
|
||||||
/* BB are there cases in which a comma can be
|
/*
|
||||||
valid in this workstation netbios name (and need
|
* FIXME: are there cases in which a comma can
|
||||||
special handling)? */
|
* be valid in workstation netbios name (and
|
||||||
|
* need special handling)?
|
||||||
/* We do not uppercase netbiosname for user */
|
*/
|
||||||
|
for (i = 0; i < RFC1001_NAME_LEN; i++) {
|
||||||
|
/* don't ucase netbiosname for user */
|
||||||
if (value[i] == 0)
|
if (value[i] == 0)
|
||||||
break;
|
break;
|
||||||
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 == RFC1001_NAME_LEN && value[i] != 0)
|
||||||
printk(KERN_WARNING "CIFS: netbiosname"
|
printk(KERN_WARNING "CIFS: netbiosname"
|
||||||
" longer than 15 truncated.\n");
|
" longer than 15 truncated.\n");
|
||||||
}
|
}
|
||||||
|
@ -1193,7 +1190,8 @@ cifs_parse_mount_options(char *options, const char *devname,
|
||||||
cFYI(1, "empty server netbiosname specified");
|
cFYI(1, "empty server netbiosname specified");
|
||||||
} else {
|
} else {
|
||||||
/* last byte, type, is 0x20 for servr type */
|
/* last byte, type, is 0x20 for servr type */
|
||||||
memset(vol->target_rfc1001_name, 0x20, 16);
|
memset(vol->target_rfc1001_name, 0x20,
|
||||||
|
RFC1001_NAME_LEN_WITH_NULL);
|
||||||
|
|
||||||
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
|
||||||
|
@ -1210,7 +1208,7 @@ cifs_parse_mount_options(char *options, const char *devname,
|
||||||
}
|
}
|
||||||
/* 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 == RFC1001_NAME_LEN && value[i] != 0)
|
||||||
printk(KERN_WARNING "CIFS: server net"
|
printk(KERN_WARNING "CIFS: server net"
|
||||||
"biosname longer than 15 truncated.\n");
|
"biosname longer than 15 truncated.\n");
|
||||||
}
|
}
|
||||||
|
@ -1341,10 +1339,8 @@ cifs_parse_mount_options(char *options, const char *devname,
|
||||||
vol->no_psx_acl = 0;
|
vol->no_psx_acl = 0;
|
||||||
} else if (strnicmp(data, "noacl", 5) == 0) {
|
} else if (strnicmp(data, "noacl", 5) == 0) {
|
||||||
vol->no_psx_acl = 1;
|
vol->no_psx_acl = 1;
|
||||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
|
||||||
} else if (strnicmp(data, "locallease", 6) == 0) {
|
} else if (strnicmp(data, "locallease", 6) == 0) {
|
||||||
vol->local_lease = 1;
|
vol->local_lease = 1;
|
||||||
#endif
|
|
||||||
} else if (strnicmp(data, "sign", 4) == 0) {
|
} else if (strnicmp(data, "sign", 4) == 0) {
|
||||||
vol->secFlg |= CIFSSEC_MUST_SIGN;
|
vol->secFlg |= CIFSSEC_MUST_SIGN;
|
||||||
} else if (strnicmp(data, "seal", 4) == 0) {
|
} else if (strnicmp(data, "seal", 4) == 0) {
|
||||||
|
@ -1454,35 +1450,71 @@ srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If no port is specified in addr structure, we try to match with 445 port
|
||||||
|
* and if it fails - with 139 ports. It should be called only if address
|
||||||
|
* families of server and addr are equal.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
match_port(struct TCP_Server_Info *server, struct sockaddr *addr)
|
||||||
|
{
|
||||||
|
unsigned short int port, *sport;
|
||||||
|
|
||||||
|
switch (addr->sa_family) {
|
||||||
|
case AF_INET:
|
||||||
|
sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port;
|
||||||
|
port = ((struct sockaddr_in *) addr)->sin_port;
|
||||||
|
break;
|
||||||
|
case AF_INET6:
|
||||||
|
sport = &((struct sockaddr_in6 *) &server->dstaddr)->sin6_port;
|
||||||
|
port = ((struct sockaddr_in6 *) addr)->sin6_port;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
WARN_ON(1);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!port) {
|
||||||
|
port = htons(CIFS_PORT);
|
||||||
|
if (port == *sport)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
port = htons(RFC1001_PORT);
|
||||||
|
}
|
||||||
|
|
||||||
|
return port == *sport;
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
|
match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
|
||||||
struct sockaddr *srcaddr)
|
struct sockaddr *srcaddr)
|
||||||
{
|
{
|
||||||
struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
|
|
||||||
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
|
|
||||||
|
|
||||||
switch (addr->sa_family) {
|
switch (addr->sa_family) {
|
||||||
case AF_INET:
|
case AF_INET: {
|
||||||
if (addr4->sin_addr.s_addr !=
|
struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
|
||||||
server->addr.sockAddr.sin_addr.s_addr)
|
struct sockaddr_in *srv_addr4 =
|
||||||
return false;
|
(struct sockaddr_in *)&server->dstaddr;
|
||||||
if (addr4->sin_port &&
|
|
||||||
addr4->sin_port != server->addr.sockAddr.sin_port)
|
if (addr4->sin_addr.s_addr != srv_addr4->sin_addr.s_addr)
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
case AF_INET6:
|
}
|
||||||
|
case AF_INET6: {
|
||||||
|
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
|
||||||
|
struct sockaddr_in6 *srv_addr6 =
|
||||||
|
(struct sockaddr_in6 *)&server->dstaddr;
|
||||||
|
|
||||||
if (!ipv6_addr_equal(&addr6->sin6_addr,
|
if (!ipv6_addr_equal(&addr6->sin6_addr,
|
||||||
&server->addr.sockAddr6.sin6_addr))
|
&srv_addr6->sin6_addr))
|
||||||
return false;
|
return false;
|
||||||
if (addr6->sin6_scope_id !=
|
if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id)
|
||||||
server->addr.sockAddr6.sin6_scope_id)
|
|
||||||
return false;
|
|
||||||
if (addr6->sin6_port &&
|
|
||||||
addr6->sin6_port != server->addr.sockAddr6.sin6_port)
|
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
WARN_ON(1);
|
||||||
|
return false; /* don't expect to be here */
|
||||||
|
}
|
||||||
|
|
||||||
if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr))
|
if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr))
|
||||||
return false;
|
return false;
|
||||||
|
@ -1549,6 +1581,9 @@ cifs_find_tcp_session(struct sockaddr *addr, struct smb_vol *vol)
|
||||||
(struct sockaddr *)&vol->srcaddr))
|
(struct sockaddr *)&vol->srcaddr))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (!match_port(server, addr))
|
||||||
|
continue;
|
||||||
|
|
||||||
if (!match_security(server, vol))
|
if (!match_security(server, vol))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -1681,14 +1716,13 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
|
||||||
cFYI(1, "attempting ipv6 connect");
|
cFYI(1, "attempting ipv6 connect");
|
||||||
/* BB should we allow ipv6 on port 139? */
|
/* BB should we allow ipv6 on port 139? */
|
||||||
/* other OS never observed in Wild doing 139 with v6 */
|
/* other OS never observed in Wild doing 139 with v6 */
|
||||||
memcpy(&tcp_ses->addr.sockAddr6, sin_server6,
|
memcpy(&tcp_ses->dstaddr, sin_server6,
|
||||||
sizeof(struct sockaddr_in6));
|
sizeof(struct sockaddr_in6));
|
||||||
rc = ipv6_connect(tcp_ses);
|
} else
|
||||||
} else {
|
memcpy(&tcp_ses->dstaddr, sin_server,
|
||||||
memcpy(&tcp_ses->addr.sockAddr, sin_server,
|
sizeof(struct sockaddr_in));
|
||||||
sizeof(struct sockaddr_in));
|
|
||||||
rc = ipv4_connect(tcp_ses);
|
rc = ip_connect(tcp_ses);
|
||||||
}
|
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
cERROR(1, "Error connecting to socket. Aborting operation");
|
cERROR(1, "Error connecting to socket. Aborting operation");
|
||||||
goto out_err_crypto_release;
|
goto out_err_crypto_release;
|
||||||
|
@ -1793,6 +1827,8 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
|
||||||
{
|
{
|
||||||
int rc = -ENOMEM, xid;
|
int rc = -ENOMEM, xid;
|
||||||
struct cifsSesInfo *ses;
|
struct cifsSesInfo *ses;
|
||||||
|
struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
|
||||||
|
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
|
||||||
|
|
||||||
xid = GetXid();
|
xid = GetXid();
|
||||||
|
|
||||||
|
@ -1836,12 +1872,10 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
|
||||||
|
|
||||||
/* new SMB session uses our server ref */
|
/* new SMB session uses our server ref */
|
||||||
ses->server = server;
|
ses->server = server;
|
||||||
if (server->addr.sockAddr6.sin6_family == AF_INET6)
|
if (server->dstaddr.ss_family == AF_INET6)
|
||||||
sprintf(ses->serverName, "%pI6",
|
sprintf(ses->serverName, "%pI6", &addr6->sin6_addr);
|
||||||
&server->addr.sockAddr6.sin6_addr);
|
|
||||||
else
|
else
|
||||||
sprintf(ses->serverName, "%pI4",
|
sprintf(ses->serverName, "%pI4", &addr->sin_addr);
|
||||||
&server->addr.sockAddr.sin_addr.s_addr);
|
|
||||||
|
|
||||||
if (volume_info->username)
|
if (volume_info->username)
|
||||||
strncpy(ses->userName, volume_info->username,
|
strncpy(ses->userName, volume_info->username,
|
||||||
|
@ -2136,19 +2170,106 @@ bind_socket(struct TCP_Server_Info *server)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ipv4_connect(struct TCP_Server_Info *server)
|
ip_rfc1001_connect(struct TCP_Server_Info *server)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
int val;
|
/*
|
||||||
bool connected = false;
|
* some servers require RFC1001 sessinit before sending
|
||||||
__be16 orig_port = 0;
|
* negprot - BB check reconnection in case where second
|
||||||
|
* sessinit is sent but no second negprot
|
||||||
|
*/
|
||||||
|
struct rfc1002_session_packet *ses_init_buf;
|
||||||
|
struct smb_hdr *smb_buf;
|
||||||
|
ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (ses_init_buf) {
|
||||||
|
ses_init_buf->trailer.session_req.called_len = 32;
|
||||||
|
|
||||||
|
if (server->server_RFC1001_name &&
|
||||||
|
server->server_RFC1001_name[0] != 0)
|
||||||
|
rfc1002mangle(ses_init_buf->trailer.
|
||||||
|
session_req.called_name,
|
||||||
|
server->server_RFC1001_name,
|
||||||
|
RFC1001_NAME_LEN_WITH_NULL);
|
||||||
|
else
|
||||||
|
rfc1002mangle(ses_init_buf->trailer.
|
||||||
|
session_req.called_name,
|
||||||
|
DEFAULT_CIFS_CALLED_NAME,
|
||||||
|
RFC1001_NAME_LEN_WITH_NULL);
|
||||||
|
|
||||||
|
ses_init_buf->trailer.session_req.calling_len = 32;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* calling name ends in null (byte 16) from old smb
|
||||||
|
* convention.
|
||||||
|
*/
|
||||||
|
if (server->workstation_RFC1001_name &&
|
||||||
|
server->workstation_RFC1001_name[0] != 0)
|
||||||
|
rfc1002mangle(ses_init_buf->trailer.
|
||||||
|
session_req.calling_name,
|
||||||
|
server->workstation_RFC1001_name,
|
||||||
|
RFC1001_NAME_LEN_WITH_NULL);
|
||||||
|
else
|
||||||
|
rfc1002mangle(ses_init_buf->trailer.
|
||||||
|
session_req.calling_name,
|
||||||
|
"LINUX_CIFS_CLNT",
|
||||||
|
RFC1001_NAME_LEN_WITH_NULL);
|
||||||
|
|
||||||
|
ses_init_buf->trailer.session_req.scope1 = 0;
|
||||||
|
ses_init_buf->trailer.session_req.scope2 = 0;
|
||||||
|
smb_buf = (struct smb_hdr *)ses_init_buf;
|
||||||
|
|
||||||
|
/* sizeof RFC1002_SESSION_REQUEST with no scope */
|
||||||
|
smb_buf->smb_buf_length = 0x81000044;
|
||||||
|
rc = smb_send(server, smb_buf, 0x44);
|
||||||
|
kfree(ses_init_buf);
|
||||||
|
/*
|
||||||
|
* RFC1001 layer in at least one server
|
||||||
|
* requires very short break before negprot
|
||||||
|
* presumably because not expecting negprot
|
||||||
|
* to follow so fast. This is a simple
|
||||||
|
* solution that works without
|
||||||
|
* complicating the code and causes no
|
||||||
|
* significant slowing down on mount
|
||||||
|
* for everyone else
|
||||||
|
*/
|
||||||
|
usleep_range(1000, 2000);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* else the negprot may still work without this
|
||||||
|
* even though malloc failed
|
||||||
|
*/
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
generic_ip_connect(struct TCP_Server_Info *server)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
unsigned short int sport;
|
||||||
|
int slen, sfamily;
|
||||||
struct socket *socket = server->ssocket;
|
struct socket *socket = server->ssocket;
|
||||||
|
struct sockaddr *saddr;
|
||||||
|
|
||||||
|
saddr = (struct sockaddr *) &server->dstaddr;
|
||||||
|
|
||||||
|
if (server->dstaddr.ss_family == AF_INET6) {
|
||||||
|
sport = ((struct sockaddr_in6 *) saddr)->sin6_port;
|
||||||
|
slen = sizeof(struct sockaddr_in6);
|
||||||
|
sfamily = AF_INET6;
|
||||||
|
} else {
|
||||||
|
sport = ((struct sockaddr_in *) saddr)->sin_port;
|
||||||
|
slen = sizeof(struct sockaddr_in);
|
||||||
|
sfamily = AF_INET;
|
||||||
|
}
|
||||||
|
|
||||||
if (socket == NULL) {
|
if (socket == NULL) {
|
||||||
rc = sock_create_kern(PF_INET, SOCK_STREAM,
|
rc = sock_create_kern(sfamily, SOCK_STREAM,
|
||||||
IPPROTO_TCP, &socket);
|
IPPROTO_TCP, &socket);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
cERROR(1, "Error %d creating socket", rc);
|
cERROR(1, "Error %d creating socket", rc);
|
||||||
|
server->ssocket = NULL;
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2156,218 +2277,19 @@ ipv4_connect(struct TCP_Server_Info *server)
|
||||||
cFYI(1, "Socket created");
|
cFYI(1, "Socket created");
|
||||||
server->ssocket = socket;
|
server->ssocket = socket;
|
||||||
socket->sk->sk_allocation = GFP_NOFS;
|
socket->sk->sk_allocation = GFP_NOFS;
|
||||||
cifs_reclassify_socket4(socket);
|
if (sfamily == AF_INET6)
|
||||||
|
cifs_reclassify_socket6(socket);
|
||||||
|
else
|
||||||
|
cifs_reclassify_socket4(socket);
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = bind_socket(server);
|
rc = bind_socket(server);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
/* user overrode default port */
|
rc = socket->ops->connect(socket, saddr, slen, 0);
|
||||||
if (server->addr.sockAddr.sin_port) {
|
if (rc < 0) {
|
||||||
rc = socket->ops->connect(socket, (struct sockaddr *)
|
cFYI(1, "Error %d connecting to server", rc);
|
||||||
&server->addr.sockAddr,
|
|
||||||
sizeof(struct sockaddr_in), 0);
|
|
||||||
if (rc >= 0)
|
|
||||||
connected = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!connected) {
|
|
||||||
/* save original port so we can retry user specified port
|
|
||||||
later if fall back ports fail this time */
|
|
||||||
orig_port = server->addr.sockAddr.sin_port;
|
|
||||||
|
|
||||||
/* do not retry on the same port we just failed on */
|
|
||||||
if (server->addr.sockAddr.sin_port != htons(CIFS_PORT)) {
|
|
||||||
server->addr.sockAddr.sin_port = htons(CIFS_PORT);
|
|
||||||
rc = socket->ops->connect(socket,
|
|
||||||
(struct sockaddr *)
|
|
||||||
&server->addr.sockAddr,
|
|
||||||
sizeof(struct sockaddr_in), 0);
|
|
||||||
if (rc >= 0)
|
|
||||||
connected = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!connected) {
|
|
||||||
server->addr.sockAddr.sin_port = htons(RFC1001_PORT);
|
|
||||||
rc = socket->ops->connect(socket, (struct sockaddr *)
|
|
||||||
&server->addr.sockAddr,
|
|
||||||
sizeof(struct sockaddr_in), 0);
|
|
||||||
if (rc >= 0)
|
|
||||||
connected = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* give up here - unless we want to retry on different
|
|
||||||
protocol families some day */
|
|
||||||
if (!connected) {
|
|
||||||
if (orig_port)
|
|
||||||
server->addr.sockAddr.sin_port = orig_port;
|
|
||||||
cFYI(1, "Error %d connecting to server via ipv4", rc);
|
|
||||||
sock_release(socket);
|
|
||||||
server->ssocket = NULL;
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Eventually check for other socket options to change from
|
|
||||||
* the default. sock_setsockopt not used because it expects
|
|
||||||
* user space buffer
|
|
||||||
*/
|
|
||||||
socket->sk->sk_rcvtimeo = 7 * HZ;
|
|
||||||
socket->sk->sk_sndtimeo = 5 * HZ;
|
|
||||||
|
|
||||||
/* make the bufsizes depend on wsize/rsize and max requests */
|
|
||||||
if (server->noautotune) {
|
|
||||||
if (socket->sk->sk_sndbuf < (200 * 1024))
|
|
||||||
socket->sk->sk_sndbuf = 200 * 1024;
|
|
||||||
if (socket->sk->sk_rcvbuf < (140 * 1024))
|
|
||||||
socket->sk->sk_rcvbuf = 140 * 1024;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (server->tcp_nodelay) {
|
|
||||||
val = 1;
|
|
||||||
rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
|
|
||||||
(char *)&val, sizeof(val));
|
|
||||||
if (rc)
|
|
||||||
cFYI(1, "set TCP_NODELAY socket option error %d", rc);
|
|
||||||
}
|
|
||||||
|
|
||||||
cFYI(1, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx",
|
|
||||||
socket->sk->sk_sndbuf,
|
|
||||||
socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
|
|
||||||
|
|
||||||
/* send RFC1001 sessinit */
|
|
||||||
if (server->addr.sockAddr.sin_port == htons(RFC1001_PORT)) {
|
|
||||||
/* some servers require RFC1001 sessinit before sending
|
|
||||||
negprot - BB check reconnection in case where second
|
|
||||||
sessinit is sent but no second negprot */
|
|
||||||
struct rfc1002_session_packet *ses_init_buf;
|
|
||||||
struct smb_hdr *smb_buf;
|
|
||||||
ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
|
|
||||||
GFP_KERNEL);
|
|
||||||
if (ses_init_buf) {
|
|
||||||
ses_init_buf->trailer.session_req.called_len = 32;
|
|
||||||
if (server->server_RFC1001_name &&
|
|
||||||
server->server_RFC1001_name[0] != 0)
|
|
||||||
rfc1002mangle(ses_init_buf->trailer.
|
|
||||||
session_req.called_name,
|
|
||||||
server->server_RFC1001_name,
|
|
||||||
RFC1001_NAME_LEN_WITH_NULL);
|
|
||||||
else
|
|
||||||
rfc1002mangle(ses_init_buf->trailer.
|
|
||||||
session_req.called_name,
|
|
||||||
DEFAULT_CIFS_CALLED_NAME,
|
|
||||||
RFC1001_NAME_LEN_WITH_NULL);
|
|
||||||
|
|
||||||
ses_init_buf->trailer.session_req.calling_len = 32;
|
|
||||||
|
|
||||||
/* calling name ends in null (byte 16) from old smb
|
|
||||||
convention. */
|
|
||||||
if (server->workstation_RFC1001_name &&
|
|
||||||
server->workstation_RFC1001_name[0] != 0)
|
|
||||||
rfc1002mangle(ses_init_buf->trailer.
|
|
||||||
session_req.calling_name,
|
|
||||||
server->workstation_RFC1001_name,
|
|
||||||
RFC1001_NAME_LEN_WITH_NULL);
|
|
||||||
else
|
|
||||||
rfc1002mangle(ses_init_buf->trailer.
|
|
||||||
session_req.calling_name,
|
|
||||||
"LINUX_CIFS_CLNT",
|
|
||||||
RFC1001_NAME_LEN_WITH_NULL);
|
|
||||||
|
|
||||||
ses_init_buf->trailer.session_req.scope1 = 0;
|
|
||||||
ses_init_buf->trailer.session_req.scope2 = 0;
|
|
||||||
smb_buf = (struct smb_hdr *)ses_init_buf;
|
|
||||||
/* sizeof RFC1002_SESSION_REQUEST with no scope */
|
|
||||||
smb_buf->smb_buf_length = 0x81000044;
|
|
||||||
rc = smb_send(server, smb_buf, 0x44);
|
|
||||||
kfree(ses_init_buf);
|
|
||||||
msleep(1); /* RFC1001 layer in at least one server
|
|
||||||
requires very short break before negprot
|
|
||||||
presumably because not expecting negprot
|
|
||||||
to follow so fast. This is a simple
|
|
||||||
solution that works without
|
|
||||||
complicating the code and causes no
|
|
||||||
significant slowing down on mount
|
|
||||||
for everyone else */
|
|
||||||
}
|
|
||||||
/* else the negprot may still work without this
|
|
||||||
even though malloc failed */
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
ipv6_connect(struct TCP_Server_Info *server)
|
|
||||||
{
|
|
||||||
int rc = 0;
|
|
||||||
int val;
|
|
||||||
bool connected = false;
|
|
||||||
__be16 orig_port = 0;
|
|
||||||
struct socket *socket = server->ssocket;
|
|
||||||
|
|
||||||
if (socket == NULL) {
|
|
||||||
rc = sock_create_kern(PF_INET6, SOCK_STREAM,
|
|
||||||
IPPROTO_TCP, &socket);
|
|
||||||
if (rc < 0) {
|
|
||||||
cERROR(1, "Error %d creating ipv6 socket", rc);
|
|
||||||
socket = NULL;
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* BB other socket options to set KEEPALIVE, NODELAY? */
|
|
||||||
cFYI(1, "ipv6 Socket created");
|
|
||||||
server->ssocket = socket;
|
|
||||||
socket->sk->sk_allocation = GFP_NOFS;
|
|
||||||
cifs_reclassify_socket6(socket);
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = bind_socket(server);
|
|
||||||
if (rc < 0)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
/* user overrode default port */
|
|
||||||
if (server->addr.sockAddr6.sin6_port) {
|
|
||||||
rc = socket->ops->connect(socket,
|
|
||||||
(struct sockaddr *) &server->addr.sockAddr6,
|
|
||||||
sizeof(struct sockaddr_in6), 0);
|
|
||||||
if (rc >= 0)
|
|
||||||
connected = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!connected) {
|
|
||||||
/* save original port so we can retry user specified port
|
|
||||||
later if fall back ports fail this time */
|
|
||||||
|
|
||||||
orig_port = server->addr.sockAddr6.sin6_port;
|
|
||||||
/* do not retry on the same port we just failed on */
|
|
||||||
if (server->addr.sockAddr6.sin6_port != htons(CIFS_PORT)) {
|
|
||||||
server->addr.sockAddr6.sin6_port = htons(CIFS_PORT);
|
|
||||||
rc = socket->ops->connect(socket, (struct sockaddr *)
|
|
||||||
&server->addr.sockAddr6,
|
|
||||||
sizeof(struct sockaddr_in6), 0);
|
|
||||||
if (rc >= 0)
|
|
||||||
connected = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!connected) {
|
|
||||||
server->addr.sockAddr6.sin6_port = htons(RFC1001_PORT);
|
|
||||||
rc = socket->ops->connect(socket, (struct sockaddr *)
|
|
||||||
&server->addr.sockAddr6,
|
|
||||||
sizeof(struct sockaddr_in6), 0);
|
|
||||||
if (rc >= 0)
|
|
||||||
connected = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* give up here - unless we want to retry on different
|
|
||||||
protocol families some day */
|
|
||||||
if (!connected) {
|
|
||||||
if (orig_port)
|
|
||||||
server->addr.sockAddr6.sin6_port = orig_port;
|
|
||||||
cFYI(1, "Error %d connecting to server via ipv6", rc);
|
|
||||||
sock_release(socket);
|
sock_release(socket);
|
||||||
server->ssocket = NULL;
|
server->ssocket = NULL;
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -2381,19 +2303,61 @@ ipv6_connect(struct TCP_Server_Info *server)
|
||||||
socket->sk->sk_rcvtimeo = 7 * HZ;
|
socket->sk->sk_rcvtimeo = 7 * HZ;
|
||||||
socket->sk->sk_sndtimeo = 5 * HZ;
|
socket->sk->sk_sndtimeo = 5 * HZ;
|
||||||
|
|
||||||
|
/* make the bufsizes depend on wsize/rsize and max requests */
|
||||||
|
if (server->noautotune) {
|
||||||
|
if (socket->sk->sk_sndbuf < (200 * 1024))
|
||||||
|
socket->sk->sk_sndbuf = 200 * 1024;
|
||||||
|
if (socket->sk->sk_rcvbuf < (140 * 1024))
|
||||||
|
socket->sk->sk_rcvbuf = 140 * 1024;
|
||||||
|
}
|
||||||
|
|
||||||
if (server->tcp_nodelay) {
|
if (server->tcp_nodelay) {
|
||||||
val = 1;
|
int val = 1;
|
||||||
rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
|
rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
|
||||||
(char *)&val, sizeof(val));
|
(char *)&val, sizeof(val));
|
||||||
if (rc)
|
if (rc)
|
||||||
cFYI(1, "set TCP_NODELAY socket option error %d", rc);
|
cFYI(1, "set TCP_NODELAY socket option error %d", rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
server->ssocket = socket;
|
cFYI(1, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx",
|
||||||
|
socket->sk->sk_sndbuf,
|
||||||
|
socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
|
||||||
|
|
||||||
|
if (sport == htons(RFC1001_PORT))
|
||||||
|
rc = ip_rfc1001_connect(server);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ip_connect(struct TCP_Server_Info *server)
|
||||||
|
{
|
||||||
|
unsigned short int *sport;
|
||||||
|
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
|
||||||
|
struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
|
||||||
|
|
||||||
|
if (server->dstaddr.ss_family == AF_INET6)
|
||||||
|
sport = &addr6->sin6_port;
|
||||||
|
else
|
||||||
|
sport = &addr->sin_port;
|
||||||
|
|
||||||
|
if (*sport == 0) {
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* try with 445 port at first */
|
||||||
|
*sport = htons(CIFS_PORT);
|
||||||
|
|
||||||
|
rc = generic_ip_connect(server);
|
||||||
|
if (rc >= 0)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
/* if it failed, try with 139 port */
|
||||||
|
*sport = htons(RFC1001_PORT);
|
||||||
|
}
|
||||||
|
|
||||||
|
return generic_ip_connect(server);
|
||||||
|
}
|
||||||
|
|
||||||
void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon,
|
void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon,
|
||||||
struct super_block *sb, struct smb_vol *vol_info)
|
struct super_block *sb, struct smb_vol *vol_info)
|
||||||
{
|
{
|
||||||
|
|
|
@ -293,10 +293,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
|
||||||
args.uid = NO_CHANGE_64;
|
args.uid = NO_CHANGE_64;
|
||||||
args.gid = NO_CHANGE_64;
|
args.gid = NO_CHANGE_64;
|
||||||
}
|
}
|
||||||
CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
|
CIFSSMBUnixSetFileInfo(xid, tcon, &args, fileHandle,
|
||||||
cifs_sb->local_nls,
|
current->tgid);
|
||||||
cifs_sb->mnt_cifs_flags &
|
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
|
||||||
} else {
|
} else {
|
||||||
/* BB implement mode setting via Windows security
|
/* BB implement mode setting via Windows security
|
||||||
descriptors e.g. */
|
descriptors e.g. */
|
||||||
|
|
233
fs/cifs/file.c
233
fs/cifs/file.c
|
@ -104,53 +104,6 @@ static inline int cifs_get_disposition(unsigned int flags)
|
||||||
return FILE_OPEN;
|
return FILE_OPEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int cifs_open_inode_helper(struct inode *inode,
|
|
||||||
struct cifsTconInfo *pTcon, __u32 oplock, FILE_ALL_INFO *buf,
|
|
||||||
char *full_path, int xid)
|
|
||||||
{
|
|
||||||
struct cifsInodeInfo *pCifsInode = CIFS_I(inode);
|
|
||||||
struct timespec temp;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
if (pCifsInode->clientCanCacheRead) {
|
|
||||||
/* we have the inode open somewhere else
|
|
||||||
no need to discard cache data */
|
|
||||||
goto client_can_cache;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* BB need same check in cifs_create too? */
|
|
||||||
/* if not oplocked, invalidate inode pages if mtime or file
|
|
||||||
size changed */
|
|
||||||
temp = cifs_NTtimeToUnix(buf->LastWriteTime);
|
|
||||||
if (timespec_equal(&inode->i_mtime, &temp) &&
|
|
||||||
(inode->i_size ==
|
|
||||||
(loff_t)le64_to_cpu(buf->EndOfFile))) {
|
|
||||||
cFYI(1, "inode unchanged on server");
|
|
||||||
} else {
|
|
||||||
if (inode->i_mapping) {
|
|
||||||
/* BB no need to lock inode until after invalidate
|
|
||||||
since namei code should already have it locked? */
|
|
||||||
rc = filemap_write_and_wait(inode->i_mapping);
|
|
||||||
mapping_set_error(inode->i_mapping, rc);
|
|
||||||
}
|
|
||||||
cFYI(1, "invalidating remote inode since open detected it "
|
|
||||||
"changed");
|
|
||||||
invalidate_remote_inode(inode);
|
|
||||||
}
|
|
||||||
|
|
||||||
client_can_cache:
|
|
||||||
if (pTcon->unix_ext)
|
|
||||||
rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb,
|
|
||||||
xid);
|
|
||||||
else
|
|
||||||
rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb,
|
|
||||||
xid, NULL);
|
|
||||||
|
|
||||||
cifs_set_oplock_level(pCifsInode, oplock);
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
int cifs_posix_open(char *full_path, struct inode **pinode,
|
int cifs_posix_open(char *full_path, struct inode **pinode,
|
||||||
struct super_block *sb, int mode, unsigned int f_flags,
|
struct super_block *sb, int mode, unsigned int f_flags,
|
||||||
__u32 *poplock, __u16 *pnetfid, int xid)
|
__u32 *poplock, __u16 *pnetfid, int xid)
|
||||||
|
@ -213,6 +166,76 @@ posix_open_ret:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb,
|
||||||
|
struct cifsTconInfo *tcon, unsigned int f_flags, __u32 *poplock,
|
||||||
|
__u16 *pnetfid, int xid)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
int desiredAccess;
|
||||||
|
int disposition;
|
||||||
|
FILE_ALL_INFO *buf;
|
||||||
|
|
||||||
|
desiredAccess = cifs_convert_flags(f_flags);
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
* open flag mapping table:
|
||||||
|
*
|
||||||
|
* POSIX Flag CIFS Disposition
|
||||||
|
* ---------- ----------------
|
||||||
|
* O_CREAT FILE_OPEN_IF
|
||||||
|
* O_CREAT | O_EXCL FILE_CREATE
|
||||||
|
* O_CREAT | O_TRUNC FILE_OVERWRITE_IF
|
||||||
|
* O_TRUNC FILE_OVERWRITE
|
||||||
|
* none of the above FILE_OPEN
|
||||||
|
*
|
||||||
|
* Note that there is not a direct match between disposition
|
||||||
|
* FILE_SUPERSEDE (ie create whether or not file exists although
|
||||||
|
* O_CREAT | O_TRUNC is similar but truncates the existing
|
||||||
|
* file rather than creating a new file as FILE_SUPERSEDE does
|
||||||
|
* (which uses the attributes / metadata passed in on open call)
|
||||||
|
*?
|
||||||
|
*? O_SYNC is a reasonable match to CIFS writethrough flag
|
||||||
|
*? and the read write flags match reasonably. O_LARGEFILE
|
||||||
|
*? is irrelevant because largefile support is always used
|
||||||
|
*? by this client. Flags O_APPEND, O_DIRECT, O_DIRECTORY,
|
||||||
|
* O_FASYNC, O_NOFOLLOW, O_NONBLOCK need further investigation
|
||||||
|
*********************************************************************/
|
||||||
|
|
||||||
|
disposition = cifs_get_disposition(f_flags);
|
||||||
|
|
||||||
|
/* BB pass O_SYNC flag through on file attributes .. BB */
|
||||||
|
|
||||||
|
buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
|
||||||
|
if (!buf)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
if (tcon->ses->capabilities & CAP_NT_SMBS)
|
||||||
|
rc = CIFSSMBOpen(xid, tcon, full_path, disposition,
|
||||||
|
desiredAccess, CREATE_NOT_DIR, pnetfid, poplock, buf,
|
||||||
|
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
|
||||||
|
& CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
|
else
|
||||||
|
rc = SMBLegacyOpen(xid, tcon, full_path, disposition,
|
||||||
|
desiredAccess, CREATE_NOT_DIR, pnetfid, poplock, buf,
|
||||||
|
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
|
||||||
|
& CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
|
|
||||||
|
if (rc)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (tcon->unix_ext)
|
||||||
|
rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb,
|
||||||
|
xid);
|
||||||
|
else
|
||||||
|
rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb,
|
||||||
|
xid, pnetfid);
|
||||||
|
|
||||||
|
out:
|
||||||
|
kfree(buf);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
struct cifsFileInfo *
|
struct cifsFileInfo *
|
||||||
cifs_new_fileinfo(__u16 fileHandle, struct file *file,
|
cifs_new_fileinfo(__u16 fileHandle, struct file *file,
|
||||||
struct tcon_link *tlink, __u32 oplock)
|
struct tcon_link *tlink, __u32 oplock)
|
||||||
|
@ -317,10 +340,8 @@ int cifs_open(struct inode *inode, struct file *file)
|
||||||
struct cifsFileInfo *pCifsFile = NULL;
|
struct cifsFileInfo *pCifsFile = NULL;
|
||||||
struct cifsInodeInfo *pCifsInode;
|
struct cifsInodeInfo *pCifsInode;
|
||||||
char *full_path = NULL;
|
char *full_path = NULL;
|
||||||
int desiredAccess;
|
bool posix_open_ok = false;
|
||||||
int disposition;
|
|
||||||
__u16 netfid;
|
__u16 netfid;
|
||||||
FILE_ALL_INFO *buf = NULL;
|
|
||||||
|
|
||||||
xid = GetXid();
|
xid = GetXid();
|
||||||
|
|
||||||
|
@ -358,17 +379,7 @@ int cifs_open(struct inode *inode, struct file *file)
|
||||||
file->f_flags, &oplock, &netfid, xid);
|
file->f_flags, &oplock, &netfid, xid);
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
cFYI(1, "posix open succeeded");
|
cFYI(1, "posix open succeeded");
|
||||||
|
posix_open_ok = true;
|
||||||
pCifsFile = cifs_new_fileinfo(netfid, file, tlink,
|
|
||||||
oplock);
|
|
||||||
if (pCifsFile == NULL) {
|
|
||||||
CIFSSMBClose(xid, tcon, netfid);
|
|
||||||
rc = -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
cifs_fscache_set_inode_cookie(inode, file);
|
|
||||||
|
|
||||||
goto out;
|
|
||||||
} else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
|
} else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
|
||||||
if (tcon->ses->serverNOS)
|
if (tcon->ses->serverNOS)
|
||||||
cERROR(1, "server %s of type %s returned"
|
cERROR(1, "server %s of type %s returned"
|
||||||
|
@ -385,103 +396,39 @@ int cifs_open(struct inode *inode, struct file *file)
|
||||||
or DFS errors */
|
or DFS errors */
|
||||||
}
|
}
|
||||||
|
|
||||||
desiredAccess = cifs_convert_flags(file->f_flags);
|
if (!posix_open_ok) {
|
||||||
|
rc = cifs_nt_open(full_path, inode, cifs_sb, tcon,
|
||||||
/*********************************************************************
|
file->f_flags, &oplock, &netfid, xid);
|
||||||
* open flag mapping table:
|
if (rc)
|
||||||
*
|
goto out;
|
||||||
* POSIX Flag CIFS Disposition
|
|
||||||
* ---------- ----------------
|
|
||||||
* O_CREAT FILE_OPEN_IF
|
|
||||||
* O_CREAT | O_EXCL FILE_CREATE
|
|
||||||
* O_CREAT | O_TRUNC FILE_OVERWRITE_IF
|
|
||||||
* O_TRUNC FILE_OVERWRITE
|
|
||||||
* none of the above FILE_OPEN
|
|
||||||
*
|
|
||||||
* Note that there is not a direct match between disposition
|
|
||||||
* FILE_SUPERSEDE (ie create whether or not file exists although
|
|
||||||
* O_CREAT | O_TRUNC is similar but truncates the existing
|
|
||||||
* file rather than creating a new file as FILE_SUPERSEDE does
|
|
||||||
* (which uses the attributes / metadata passed in on open call)
|
|
||||||
*?
|
|
||||||
*? O_SYNC is a reasonable match to CIFS writethrough flag
|
|
||||||
*? and the read write flags match reasonably. O_LARGEFILE
|
|
||||||
*? is irrelevant because largefile support is always used
|
|
||||||
*? by this client. Flags O_APPEND, O_DIRECT, O_DIRECTORY,
|
|
||||||
* O_FASYNC, O_NOFOLLOW, O_NONBLOCK need further investigation
|
|
||||||
*********************************************************************/
|
|
||||||
|
|
||||||
disposition = cifs_get_disposition(file->f_flags);
|
|
||||||
|
|
||||||
/* BB pass O_SYNC flag through on file attributes .. BB */
|
|
||||||
|
|
||||||
/* Also refresh inode by passing in file_info buf returned by SMBOpen
|
|
||||||
and calling get_inode_info with returned buf (at least helps
|
|
||||||
non-Unix server case) */
|
|
||||||
|
|
||||||
/* BB we can not do this if this is the second open of a file
|
|
||||||
and the first handle has writebehind data, we might be
|
|
||||||
able to simply do a filemap_fdatawrite/filemap_fdatawait first */
|
|
||||||
buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
|
|
||||||
if (!buf) {
|
|
||||||
rc = -ENOMEM;
|
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tcon->ses->capabilities & CAP_NT_SMBS)
|
|
||||||
rc = CIFSSMBOpen(xid, tcon, full_path, disposition,
|
|
||||||
desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf,
|
|
||||||
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
|
|
||||||
& CIFS_MOUNT_MAP_SPECIAL_CHR);
|
|
||||||
else
|
|
||||||
rc = -EIO; /* no NT SMB support fall into legacy open below */
|
|
||||||
|
|
||||||
if (rc == -EIO) {
|
|
||||||
/* Old server, try legacy style OpenX */
|
|
||||||
rc = SMBLegacyOpen(xid, tcon, full_path, disposition,
|
|
||||||
desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf,
|
|
||||||
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
|
|
||||||
& CIFS_MOUNT_MAP_SPECIAL_CHR);
|
|
||||||
}
|
|
||||||
if (rc) {
|
|
||||||
cFYI(1, "cifs_open returned 0x%x", rc);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = cifs_open_inode_helper(inode, tcon, oplock, buf, full_path, xid);
|
|
||||||
if (rc != 0)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
pCifsFile = cifs_new_fileinfo(netfid, file, tlink, oplock);
|
pCifsFile = cifs_new_fileinfo(netfid, file, tlink, oplock);
|
||||||
if (pCifsFile == NULL) {
|
if (pCifsFile == NULL) {
|
||||||
|
CIFSSMBClose(xid, tcon, netfid);
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
cifs_fscache_set_inode_cookie(inode, file);
|
cifs_fscache_set_inode_cookie(inode, file);
|
||||||
|
|
||||||
if (oplock & CIFS_CREATE_ACTION) {
|
if ((oplock & CIFS_CREATE_ACTION) && !posix_open_ok && tcon->unix_ext) {
|
||||||
/* 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 (tcon->unix_ext) {
|
struct cifs_unix_set_info_args args = {
|
||||||
struct cifs_unix_set_info_args args = {
|
.mode = inode->i_mode,
|
||||||
.mode = inode->i_mode,
|
.uid = NO_CHANGE_64,
|
||||||
.uid = NO_CHANGE_64,
|
.gid = NO_CHANGE_64,
|
||||||
.gid = NO_CHANGE_64,
|
.ctime = NO_CHANGE_64,
|
||||||
.ctime = NO_CHANGE_64,
|
.atime = NO_CHANGE_64,
|
||||||
.atime = NO_CHANGE_64,
|
.mtime = NO_CHANGE_64,
|
||||||
.mtime = NO_CHANGE_64,
|
.device = 0,
|
||||||
.device = 0,
|
};
|
||||||
};
|
CIFSSMBUnixSetFileInfo(xid, tcon, &args, netfid,
|
||||||
CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
|
pCifsFile->pid);
|
||||||
cifs_sb->local_nls,
|
|
||||||
cifs_sb->mnt_cifs_flags &
|
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
kfree(buf);
|
|
||||||
kfree(full_path);
|
kfree(full_path);
|
||||||
FreeXid(xid);
|
FreeXid(xid);
|
||||||
cifs_put_tlink(tlink);
|
cifs_put_tlink(tlink);
|
||||||
|
|
|
@ -518,6 +518,7 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
|
||||||
|
|
||||||
fattr->cf_eof = le64_to_cpu(info->EndOfFile);
|
fattr->cf_eof = le64_to_cpu(info->EndOfFile);
|
||||||
fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
|
fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
|
||||||
|
fattr->cf_createtime = le64_to_cpu(info->CreationTime);
|
||||||
|
|
||||||
if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
|
if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
|
||||||
fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode;
|
fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode;
|
||||||
|
@ -779,6 +780,10 @@ cifs_find_inode(struct inode *inode, void *opaque)
|
||||||
if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid)
|
if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
/* use createtime like an i_generation field */
|
||||||
|
if (CIFS_I(inode)->createtime != fattr->cf_createtime)
|
||||||
|
return 0;
|
||||||
|
|
||||||
/* don't match inode of different type */
|
/* don't match inode of different type */
|
||||||
if ((inode->i_mode & S_IFMT) != (fattr->cf_mode & S_IFMT))
|
if ((inode->i_mode & S_IFMT) != (fattr->cf_mode & S_IFMT))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -796,6 +801,7 @@ cifs_init_inode(struct inode *inode, void *opaque)
|
||||||
struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
|
struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
|
||||||
|
|
||||||
CIFS_I(inode)->uniqueid = fattr->cf_uniqueid;
|
CIFS_I(inode)->uniqueid = fattr->cf_uniqueid;
|
||||||
|
CIFS_I(inode)->createtime = fattr->cf_createtime;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -160,6 +160,7 @@ cifs_dir_info_to_fattr(struct cifs_fattr *fattr, FILE_DIRECTORY_INFO *info,
|
||||||
fattr->cf_cifsattrs = le32_to_cpu(info->ExtFileAttributes);
|
fattr->cf_cifsattrs = le32_to_cpu(info->ExtFileAttributes);
|
||||||
fattr->cf_eof = le64_to_cpu(info->EndOfFile);
|
fattr->cf_eof = le64_to_cpu(info->EndOfFile);
|
||||||
fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
|
fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
|
||||||
|
fattr->cf_createtime = le64_to_cpu(info->CreationTime);
|
||||||
fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
|
fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
|
||||||
fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
|
fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
|
||||||
fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
|
fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
|
||||||
|
|
143
fs/cifs/sess.c
143
fs/cifs/sess.c
|
@ -420,7 +420,6 @@ static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
|
||||||
/* BB Move to ntlmssp.c eventually */
|
/* BB Move to ntlmssp.c eventually */
|
||||||
|
|
||||||
/* We do not malloc the blob, it is passed in pbuffer, because
|
/* We do not malloc the blob, it is passed in pbuffer, because
|
||||||
|
@ -431,13 +430,14 @@ static void build_ntlmssp_negotiate_blob(unsigned char *pbuffer,
|
||||||
NEGOTIATE_MESSAGE *sec_blob = (NEGOTIATE_MESSAGE *)pbuffer;
|
NEGOTIATE_MESSAGE *sec_blob = (NEGOTIATE_MESSAGE *)pbuffer;
|
||||||
__u32 flags;
|
__u32 flags;
|
||||||
|
|
||||||
|
memset(pbuffer, 0, sizeof(NEGOTIATE_MESSAGE));
|
||||||
memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
|
memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
|
||||||
sec_blob->MessageType = NtLmNegotiate;
|
sec_blob->MessageType = NtLmNegotiate;
|
||||||
|
|
||||||
/* BB is NTLMV2 session security format easier to use here? */
|
/* BB is NTLMV2 session security format easier to use here? */
|
||||||
flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET |
|
flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET |
|
||||||
NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE |
|
NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE |
|
||||||
NTLMSSP_NEGOTIATE_NTLM;
|
NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC;
|
||||||
if (ses->server->secMode &
|
if (ses->server->secMode &
|
||||||
(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
|
(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
|
||||||
flags |= NTLMSSP_NEGOTIATE_SIGN;
|
flags |= NTLMSSP_NEGOTIATE_SIGN;
|
||||||
|
@ -446,7 +446,7 @@ static void build_ntlmssp_negotiate_blob(unsigned char *pbuffer,
|
||||||
NTLMSSP_NEGOTIATE_EXTENDED_SEC;
|
NTLMSSP_NEGOTIATE_EXTENDED_SEC;
|
||||||
}
|
}
|
||||||
|
|
||||||
sec_blob->NegotiateFlags |= cpu_to_le32(flags);
|
sec_blob->NegotiateFlags = cpu_to_le32(flags);
|
||||||
|
|
||||||
sec_blob->WorkstationName.BufferOffset = 0;
|
sec_blob->WorkstationName.BufferOffset = 0;
|
||||||
sec_blob->WorkstationName.Length = 0;
|
sec_blob->WorkstationName.Length = 0;
|
||||||
|
@ -477,7 +477,7 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
|
||||||
flags = NTLMSSP_NEGOTIATE_56 |
|
flags = NTLMSSP_NEGOTIATE_56 |
|
||||||
NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_TARGET_INFO |
|
NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_TARGET_INFO |
|
||||||
NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE |
|
NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE |
|
||||||
NTLMSSP_NEGOTIATE_NTLM;
|
NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC;
|
||||||
if (ses->server->secMode &
|
if (ses->server->secMode &
|
||||||
(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
|
(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
|
||||||
flags |= NTLMSSP_NEGOTIATE_SIGN;
|
flags |= NTLMSSP_NEGOTIATE_SIGN;
|
||||||
|
@ -485,7 +485,7 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
|
||||||
flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
|
flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
|
||||||
|
|
||||||
tmp = pbuffer + sizeof(AUTHENTICATE_MESSAGE);
|
tmp = pbuffer + sizeof(AUTHENTICATE_MESSAGE);
|
||||||
sec_blob->NegotiateFlags |= cpu_to_le32(flags);
|
sec_blob->NegotiateFlags = cpu_to_le32(flags);
|
||||||
|
|
||||||
sec_blob->LmChallengeResponse.BufferOffset =
|
sec_blob->LmChallengeResponse.BufferOffset =
|
||||||
cpu_to_le32(sizeof(AUTHENTICATE_MESSAGE));
|
cpu_to_le32(sizeof(AUTHENTICATE_MESSAGE));
|
||||||
|
@ -544,8 +544,9 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
|
||||||
sec_blob->WorkstationName.MaximumLength = 0;
|
sec_blob->WorkstationName.MaximumLength = 0;
|
||||||
tmp += 2;
|
tmp += 2;
|
||||||
|
|
||||||
if ((ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_KEY_XCH) &&
|
if (((ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_KEY_XCH) ||
|
||||||
!calc_seckey(ses)) {
|
(ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_EXTENDED_SEC))
|
||||||
|
&& !calc_seckey(ses)) {
|
||||||
memcpy(tmp, ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE);
|
memcpy(tmp, ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE);
|
||||||
sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer);
|
sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer);
|
||||||
sec_blob->SessionKey.Length = cpu_to_le16(CIFS_CPHTXT_SIZE);
|
sec_blob->SessionKey.Length = cpu_to_le16(CIFS_CPHTXT_SIZE);
|
||||||
|
@ -563,17 +564,6 @@ setup_ntlmv2_ret:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void setup_ntlmssp_neg_req(SESSION_SETUP_ANDX *pSMB,
|
|
||||||
struct cifsSesInfo *ses)
|
|
||||||
{
|
|
||||||
build_ntlmssp_negotiate_blob(&pSMB->req.SecurityBlob[0], ses);
|
|
||||||
pSMB->req.SecurityBlobLength = cpu_to_le16(sizeof(NEGOTIATE_MESSAGE));
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int
|
int
|
||||||
CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
||||||
const struct nls_table *nls_cp)
|
const struct nls_table *nls_cp)
|
||||||
|
@ -814,71 +804,70 @@ ssetup_ntlmssp_authenticate:
|
||||||
rc = -ENOSYS;
|
rc = -ENOSYS;
|
||||||
goto ssetup_exit;
|
goto ssetup_exit;
|
||||||
#endif /* CONFIG_CIFS_UPCALL */
|
#endif /* CONFIG_CIFS_UPCALL */
|
||||||
} else {
|
} else if (type == RawNTLMSSP) {
|
||||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
if ((pSMB->req.hdr.Flags2 & SMBFLG2_UNICODE) == 0) {
|
||||||
if (type == RawNTLMSSP) {
|
cERROR(1, "NTLMSSP requires Unicode support");
|
||||||
if ((pSMB->req.hdr.Flags2 & SMBFLG2_UNICODE) == 0) {
|
|
||||||
cERROR(1, "NTLMSSP requires Unicode support");
|
|
||||||
rc = -ENOSYS;
|
|
||||||
goto ssetup_exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
cFYI(1, "ntlmssp session setup phase %d", phase);
|
|
||||||
pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
|
|
||||||
capabilities |= CAP_EXTENDED_SECURITY;
|
|
||||||
pSMB->req.Capabilities |= cpu_to_le32(capabilities);
|
|
||||||
if (phase == NtLmNegotiate) {
|
|
||||||
setup_ntlmssp_neg_req(pSMB, ses);
|
|
||||||
iov[1].iov_len = sizeof(NEGOTIATE_MESSAGE);
|
|
||||||
iov[1].iov_base = &pSMB->req.SecurityBlob[0];
|
|
||||||
} else if (phase == NtLmAuthenticate) {
|
|
||||||
/* 5 is an empirical value, large enought to
|
|
||||||
* hold authenticate message, max 10 of
|
|
||||||
* av paris, doamin,user,workstation mames,
|
|
||||||
* flags etc..
|
|
||||||
*/
|
|
||||||
ntlmsspblob = kmalloc(
|
|
||||||
5*sizeof(struct _AUTHENTICATE_MESSAGE),
|
|
||||||
GFP_KERNEL);
|
|
||||||
if (!ntlmsspblob) {
|
|
||||||
cERROR(1, "Can't allocate NTLMSSP");
|
|
||||||
rc = -ENOMEM;
|
|
||||||
goto ssetup_exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = build_ntlmssp_auth_blob(ntlmsspblob,
|
|
||||||
&blob_len, ses, nls_cp);
|
|
||||||
if (rc)
|
|
||||||
goto ssetup_exit;
|
|
||||||
iov[1].iov_len = blob_len;
|
|
||||||
iov[1].iov_base = ntlmsspblob;
|
|
||||||
pSMB->req.SecurityBlobLength =
|
|
||||||
cpu_to_le16(blob_len);
|
|
||||||
/* Make sure that we tell the server that we
|
|
||||||
are using the uid that it just gave us back
|
|
||||||
on the response (challenge) */
|
|
||||||
smb_buf->Uid = ses->Suid;
|
|
||||||
} else {
|
|
||||||
cERROR(1, "invalid phase %d", phase);
|
|
||||||
rc = -ENOSYS;
|
|
||||||
goto ssetup_exit;
|
|
||||||
}
|
|
||||||
/* unicode strings must be word aligned */
|
|
||||||
if ((iov[0].iov_len + iov[1].iov_len) % 2) {
|
|
||||||
*bcc_ptr = 0;
|
|
||||||
bcc_ptr++;
|
|
||||||
}
|
|
||||||
unicode_oslm_strings(&bcc_ptr, nls_cp);
|
|
||||||
} else {
|
|
||||||
cERROR(1, "secType %d not supported!", type);
|
|
||||||
rc = -ENOSYS;
|
rc = -ENOSYS;
|
||||||
goto ssetup_exit;
|
goto ssetup_exit;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
|
cFYI(1, "ntlmssp session setup phase %d", phase);
|
||||||
|
pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
|
||||||
|
capabilities |= CAP_EXTENDED_SECURITY;
|
||||||
|
pSMB->req.Capabilities |= cpu_to_le32(capabilities);
|
||||||
|
switch(phase) {
|
||||||
|
case NtLmNegotiate:
|
||||||
|
build_ntlmssp_negotiate_blob(
|
||||||
|
pSMB->req.SecurityBlob, ses);
|
||||||
|
iov[1].iov_len = sizeof(NEGOTIATE_MESSAGE);
|
||||||
|
iov[1].iov_base = pSMB->req.SecurityBlob;
|
||||||
|
pSMB->req.SecurityBlobLength =
|
||||||
|
cpu_to_le16(sizeof(NEGOTIATE_MESSAGE));
|
||||||
|
break;
|
||||||
|
case NtLmAuthenticate:
|
||||||
|
/*
|
||||||
|
* 5 is an empirical value, large enough to hold
|
||||||
|
* authenticate message plus max 10 of av paris,
|
||||||
|
* domain, user, workstation names, flags, etc.
|
||||||
|
*/
|
||||||
|
ntlmsspblob = kzalloc(
|
||||||
|
5*sizeof(struct _AUTHENTICATE_MESSAGE),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!ntlmsspblob) {
|
||||||
|
cERROR(1, "Can't allocate NTLMSSP blob");
|
||||||
|
rc = -ENOMEM;
|
||||||
|
goto ssetup_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = build_ntlmssp_auth_blob(ntlmsspblob,
|
||||||
|
&blob_len, ses, nls_cp);
|
||||||
|
if (rc)
|
||||||
|
goto ssetup_exit;
|
||||||
|
iov[1].iov_len = blob_len;
|
||||||
|
iov[1].iov_base = ntlmsspblob;
|
||||||
|
pSMB->req.SecurityBlobLength = cpu_to_le16(blob_len);
|
||||||
|
/*
|
||||||
|
* Make sure that we tell the server that we are using
|
||||||
|
* the uid that it just gave us back on the response
|
||||||
|
* (challenge)
|
||||||
|
*/
|
||||||
|
smb_buf->Uid = ses->Suid;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
cERROR(1, "invalid phase %d", phase);
|
||||||
|
rc = -ENOSYS;
|
||||||
|
goto ssetup_exit;
|
||||||
|
}
|
||||||
|
/* unicode strings must be word aligned */
|
||||||
|
if ((iov[0].iov_len + iov[1].iov_len) % 2) {
|
||||||
|
*bcc_ptr = 0;
|
||||||
|
bcc_ptr++;
|
||||||
|
}
|
||||||
|
unicode_oslm_strings(&bcc_ptr, nls_cp);
|
||||||
|
} else {
|
||||||
cERROR(1, "secType %d not supported!", type);
|
cERROR(1, "secType %d not supported!", type);
|
||||||
rc = -ENOSYS;
|
rc = -ENOSYS;
|
||||||
goto ssetup_exit;
|
goto ssetup_exit;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
iov[2].iov_base = str_area;
|
iov[2].iov_base = str_area;
|
||||||
|
|
|
@ -119,7 +119,7 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
|
||||||
if (ssocket == NULL)
|
if (ssocket == NULL)
|
||||||
return -ENOTSOCK; /* BB eventually add reconnect code here */
|
return -ENOTSOCK; /* BB eventually add reconnect code here */
|
||||||
|
|
||||||
smb_msg.msg_name = (struct sockaddr *) &server->addr.sockAddr;
|
smb_msg.msg_name = (struct sockaddr *) &server->dstaddr;
|
||||||
smb_msg.msg_namelen = sizeof(struct sockaddr);
|
smb_msg.msg_namelen = sizeof(struct sockaddr);
|
||||||
smb_msg.msg_control = NULL;
|
smb_msg.msg_control = NULL;
|
||||||
smb_msg.msg_controllen = 0;
|
smb_msg.msg_controllen = 0;
|
||||||
|
|
Loading…
Reference in New Issue