bk://cifs.bkbits.net/linux-2.5cifs
stevef@smfhome.smfsambadom|ChangeSet|20040426034320|53426 stevef

# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2004/04/25 22:43:20-05:00 stevef@smfhome.smfsambadom 
#   Remove unneeded debug statement
# 
# fs/cifs/connect.c
#   2004/04/25 22:42:58-05:00 stevef@smfhome.smfsambadom +0 -1
#   Remove unneeded debug statement
# 
# ChangeSet
#   2004/04/25 22:41:35-05:00 stevef@smfhome.smfsambadom 
#   Fix port 139 connections to Windows 2K adding missing RFC1002 session_init
# 
# fs/cifs/rfc1002pdu.h
#   2004/04/25 22:41:28-05:00 stevef@smfhome.smfsambadom +6 -2
#   Fix port 139 connections to Windows 2K adding missing RFC1002 session_init
# 
# fs/cifs/file.c
#   2004/04/25 22:41:28-05:00 stevef@smfhome.smfsambadom +1 -1
#   fix typo in comment
# 
# fs/cifs/connect.c
#   2004/04/25 22:41:28-05:00 stevef@smfhome.smfsambadom +74 -11
#   Fix port 139 connections to Windows 2K adding missing RFC1002 session_init
# 
# fs/cifs/cifsglob.h
#   2004/04/25 22:41:28-05:00 stevef@smfhome.smfsambadom +1 -0
#   Fix port 139 connections to Windows 2K adding missing RFC1002 session_init
# 
# ChangeSet
#   2004/04/23 12:36:52-07:00 akpm@bix.(none) 
#   Merge bk://cifs.bkbits.net/linux-2.5cifs
#   into bix.(none):/usr/src/bk-cifs
# 
# fs/cifs/cifsfs.c
#   2004/04/23 12:36:49-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/04/19 19:23:58-07:00 akpm@bix.(none) 
#   Merge bk://cifs.bkbits.net/linux-2.5cifs
#   into bix.(none):/usr/src/bk-cifs
# 
# fs/cifs/cifsfs.c
#   2004/04/19 19:23:56-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/04/16 20:19:53-07:00 akpm@bix.(none) 
#   Merge bk://cifs.bkbits.net/linux-2.5cifs
#   into bix.(none):/usr/src/bk-cifs
# 
# fs/cifs/cifsfs.c
#   2004/04/16 20:19:51-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/04/16 20:18:59-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-cifs
# 
# fs/cifs/cifsfs.c
#   2004/04/16 20:18:56-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
diff -Nru a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
--- a/fs/cifs/cifsglob.h	Sun Apr 25 22:46:16 2004
+++ b/fs/cifs/cifsglob.h	Sun Apr 25 22:46:16 2004
@@ -174,6 +174,7 @@
 	uid_t linux_uid;        /* local Linux uid */
 	int capabilities;
 	char serverName[SERVER_NAME_LEN_WITH_NULL * 2];	/* BB make bigger for tcp names - will ipv6 and sctp addresses fit here?? */
+	char workstation_RFC1001_name[15]; /* 16th byte is always zero */
 	char userName[MAX_USERNAME_SIZE + 1];
 	char domainName[MAX_USERNAME_SIZE + 1];
 	char * password;
diff -Nru a/fs/cifs/connect.c b/fs/cifs/connect.c
--- a/fs/cifs/connect.c	Sun Apr 25 22:46:16 2004
+++ b/fs/cifs/connect.c	Sun Apr 25 22:46:16 2004
@@ -54,7 +54,7 @@
 	char *UNC;
 	char *UNCip;
 	char *iocharset;  /* local code page for mapping to and from Unicode */
-	char *source_rfc1001_name; /* netbios name of client */
+	char source_rfc1001_name[16]; /* netbios name of client */
 	uid_t linux_uid;
 	gid_t linux_gid;
 	mode_t file_mode;
@@ -67,8 +67,8 @@
 	unsigned short int port;
 };
 
-int ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket);
-int ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket);
+static int ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket);
+static int ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket);
 
 
 	/* 
@@ -590,6 +590,8 @@
 				printk(KERN_WARNING "CIFS: invalid domain name\n");
 				return 1;	/* needs_arg; */
 			}
+			/* BB are there cases in which a comma can be valid in
+			a domain name and need special handling? */
 			if (strnlen(value, 65) < 65) {
 				vol->domainname = value;
 				cFYI(1, ("Domain name set"));
@@ -653,9 +655,12 @@
 			}
 		} else if (strnicmp(data, "netbiosname", 4) == 0) {
 			if (!value || !*value) {
-				vol->source_rfc1001_name = NULL;
-			} else if (strnlen(value, 17) < 17) {
-				vol->source_rfc1001_name = value;
+				cFYI(1,("invalid (empty) netbiosname specified"));
+			} else if (strnlen(value, 16) < 16) {
+				/* BB are there cases in which a comma can be 
+				valid in the workstation name (and need special
+				case handling)? */
+				strncpy(vol->source_rfc1001_name,value,16);
 			} else {
 				printk(KERN_WARNING "CIFS: netbiosname too long (more than 15)\n");
 			}
@@ -845,7 +850,22 @@
 	return rc;
 }
 
-int
+/* See RFC1001 section 14 on representation of Netbios names */
+static void rfc1002mangle(char * target,char * source, unsigned int length)
+{
+	int i,j;
+
+	for(i=0,j=0;i<(length);i++) {
+		/* mask a nibble at a time and encode */
+		target[j] = 'A' + (0x0F & (source[i] >> 4));
+		target[j+1] = 'A' + (0x0F & source[i]);
+		j+=2;
+	}
+
+}
+
+
+static int
 ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket)
 {
 	int rc = 0;
@@ -865,7 +885,6 @@
 	}
 
 	psin_server->sin_family = AF_INET;
-	
 	if(psin_server->sin_port) { /* user overrode default port */
 		rc = (*csocket)->ops->connect(*csocket,
 				(struct sockaddr *) psin_server,
@@ -912,11 +931,42 @@
 		the default. sock_setsockopt not used because it expects 
 		user space buffer */
 	(*csocket)->sk->sk_rcvtimeo = 7 * HZ;
+
+	/* send RFC1001 sessinit */
+
+	if(psin_server->sin_port == htons(139)) {
+		/* 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 = cifs_kcalloc(36, GFP_KERNEL);
+		if(ses_init_buf) {
+			ses_init_buf->trailer.session_req.called_len = 32;
+			rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
+				DEFAULT_CIFS_CALLED_NAME,16);
+			ses_init_buf->trailer.session_req.calling_len = 32;
+			rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
+				"LINUX_CIFS_CLNT",16);
+			ses_init_buf->trailer.session_req.scope1 = 0;
+			ses_init_buf->trailer.session_req.scope2 = 0;
+		/* BB fixme ensure calling space padded w/null terminate*/
+			smb_buf = (struct smb_hdr *)ses_init_buf;
+			/* sizeof RFC1002_SESSION_REQUEST with no scope */
+			smb_buf->smb_buf_length = 0x81000044;
+			rc = smb_send(*csocket, smb_buf, 0x44,
+				(struct sockaddr *)psin_server);
+			kfree(ses_init_buf);
+		}
+		/* else the negprot may still work without this 
+		even though malloc failed */
+		
+	}
 		
 	return rc;
 }
 
-int
+static int
 ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
 {
 	int rc = 0;
@@ -1000,7 +1050,6 @@
 /* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */
 	
 	memset(&volume_info,0,sizeof(struct smb_vol));
-
 	if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
 		if(volume_info.UNC)
 			kfree(volume_info.UNC);
@@ -1049,6 +1098,12 @@
 	} else if (volume_info.UNCip){
 		/* BB using ip addr as server name connect to the DFS root below */
 		cERROR(1,("Connecting to DFS root not implemented yet"));
+		if(volume_info.UNC)
+			kfree(volume_info.UNC);
+		if(volume_info.password)
+			kfree(volume_info.password);
+		FreeXid(xid);
+		return -EINVAL;
 	} else /* which servers DFS root would we conect to */ {
 		cERROR(1,
 		       ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified  "));
@@ -1131,6 +1186,7 @@
 		cFYI(1, ("Existing smb sess found "));
 		if(volume_info.password)
 			kfree(volume_info.password);
+		/* volume_info.UNC freed at end of function */
 	} else if (!rc) {
 		cFYI(1, ("Existing smb sess not found "));
 		pSesInfo = sesInfoAlloc();
@@ -1142,7 +1198,8 @@
 				NIPQUAD(sin_server.sin_addr.s_addr));
 		}
 
-		if (!rc){   
+		if (!rc){
+			/* volume_info.password freed at unmount */   
 			if (volume_info.password)
 				pSesInfo->password = volume_info.password;
 			if (volume_info.username)
@@ -1263,6 +1320,11 @@
 		if (tcon->ses->capabilities & CAP_UNIX)
 			CIFSSMBQFSUnixInfo(xid, tcon, cifs_sb->local_nls);
 	}
+
+	/* volume_info.password is freed above when existing session found
+	(in which case it is not needed anymore) but when new sesion is created
+	the password ptr is put in the new session structure (in which case the
+	password will be freed at unmount time) */
 	if(volume_info.UNC)
 		kfree(volume_info.UNC);
 	FreeXid(xid);
diff -Nru a/fs/cifs/file.c b/fs/cifs/file.c
--- a/fs/cifs/file.c	Sun Apr 25 22:46:16 2004
+++ b/fs/cifs/file.c	Sun Apr 25 22:46:16 2004
@@ -1049,7 +1049,7 @@
 		} else if (bytes_read > 0) {
 			pSMBr = (struct smb_com_read_rsp *)smb_read_data;
 			cifs_copy_cache_pages(mapping, page_list, bytes_read,
-				smb_read_data + 4 /* RFC1000 hdr */ +
+				smb_read_data + 4 /* RFC1001 hdr */ +
 				le16_to_cpu(pSMBr->DataOffset), &lru_pvec);
 
 			i +=  bytes_read >> PAGE_CACHE_SHIFT;
diff -Nru a/fs/cifs/rfc1002pdu.h b/fs/cifs/rfc1002pdu.h
--- a/fs/cifs/rfc1002pdu.h	Sun Apr 25 22:46:16 2004
+++ b/fs/cifs/rfc1002pdu.h	Sun Apr 25 22:46:16 2004
@@ -42,8 +42,12 @@
 	__u16	length;
 	union {
 		struct {
-			__u8 called_name[16];
-			__u8 calling_name[16];
+			__u8 called_len;
+			__u8 called_name[32];
+			__u8 scope1; /* null */
+			__u8 calling_len;
+			__u8 calling_name[32];
+			__u8 scope2; /* null */
 		} session_req;
 		struct {
 			__u32 retarget_ip_addr;
