diff options
-rw-r--r-- | fs/cifs/CHANGES | 7 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 6 | ||||
-rw-r--r-- | fs/cifs/connect.c | 57 |
3 files changed, 58 insertions, 12 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index b0429ea524fb..2137002aecc4 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES | |||
@@ -1,5 +1,6 @@ | |||
1 | Version 1.36 | 1 | Version 1.36 |
2 | ------------ | 2 | ------------ |
3 | Add support for moounting to older pre-CIFS servers such as Windows9x and ME. | ||
3 | Add mount option for disabling the default behavior of sending byte range lock | 4 | Add mount option for disabling the default behavior of sending byte range lock |
4 | requests to the server (necessary for certain applications which break with | 5 | requests to the server (necessary for certain applications which break with |
5 | mandatory lock behavior such as Evolution), and also mount option for | 6 | mandatory lock behavior such as Evolution), and also mount option for |
@@ -10,7 +11,11 @@ Version 1.35 | |||
10 | ------------ | 11 | ------------ |
11 | Add writepage performance improvements. Fix path name conversions | 12 | Add writepage performance improvements. Fix path name conversions |
12 | for long filenames on mounts which were done with "mapchars" mount option | 13 | for long filenames on mounts which were done with "mapchars" mount option |
13 | specified. | 14 | specified. Ensure multiplex ids do not collide. Fix case in which |
15 | rmmod can oops if done soon after last unmount. Fix truncated | ||
16 | search (readdir) output when resume filename was a long filename. | ||
17 | Fix filename conversion when mapchars mount option was specified and | ||
18 | filename was a long filename. | ||
14 | 19 | ||
15 | Version 1.34 | 20 | Version 1.34 |
16 | ------------ | 21 | ------------ |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 6a8c7d1bee8c..f143975627e0 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -110,7 +110,8 @@ enum protocolEnum { | |||
110 | */ | 110 | */ |
111 | 111 | ||
112 | struct TCP_Server_Info { | 112 | struct TCP_Server_Info { |
113 | char server_Name[SERVER_NAME_LEN_WITH_NULL]; /* 15 chars + X'20' 16th */ | 113 | /* 15 character server name + 0x20 16th byte indicating type = srv */ |
114 | char server_RFC1001_name[SERVER_NAME_LEN_WITH_NULL]; | ||
114 | char unicode_server_Name[SERVER_NAME_LEN_WITH_NULL * 2]; | 115 | char unicode_server_Name[SERVER_NAME_LEN_WITH_NULL * 2]; |
115 | struct socket *ssocket; | 116 | struct socket *ssocket; |
116 | union { | 117 | union { |
@@ -149,7 +150,8 @@ struct TCP_Server_Info { | |||
149 | __u16 timeZone; | 150 | __u16 timeZone; |
150 | __u16 CurrentMid; /* multiplex id - rotating counter */ | 151 | __u16 CurrentMid; /* multiplex id - rotating counter */ |
151 | char cryptKey[CIFS_CRYPTO_KEY_SIZE]; | 152 | char cryptKey[CIFS_CRYPTO_KEY_SIZE]; |
152 | char workstation_RFC1001_name[16]; /* 16th byte is always zero */ | 153 | /* 16th byte of RFC1001 workstation name is always null */ |
154 | char workstation_RFC1001_name[SERVER_NAME_LEN_WITH_NULL]; | ||
153 | __u32 sequence_number; /* needed for CIFS PDU signature */ | 155 | __u32 sequence_number; /* needed for CIFS PDU signature */ |
154 | char mac_signing_key[CIFS_SESSION_KEY_SIZE + 16]; | 156 | char mac_signing_key[CIFS_SESSION_KEY_SIZE + 16]; |
155 | }; | 157 | }; |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index ac2c8bdc8e55..9d61844e89b6 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -63,6 +63,7 @@ struct smb_vol { | |||
63 | char *in6_addr; /* ipv6 address as human readable form of in6_addr */ | 63 | char *in6_addr; /* ipv6 address as human readable form of in6_addr */ |
64 | char *iocharset; /* local code page for mapping to and from Unicode */ | 64 | char *iocharset; /* local code page for mapping to and from Unicode */ |
65 | char source_rfc1001_name[16]; /* netbios name of client */ | 65 | char source_rfc1001_name[16]; /* netbios name of client */ |
66 | char target_rfc1001_name[16]; /* netbios name of server for Win9x/ME */ | ||
66 | uid_t linux_uid; | 67 | uid_t linux_uid; |
67 | gid_t linux_gid; | 68 | gid_t linux_gid; |
68 | mode_t file_mode; | 69 | mode_t file_mode; |
@@ -89,7 +90,8 @@ struct smb_vol { | |||
89 | 90 | ||
90 | static int ipv4_connect(struct sockaddr_in *psin_server, | 91 | static int ipv4_connect(struct sockaddr_in *psin_server, |
91 | struct socket **csocket, | 92 | struct socket **csocket, |
92 | char * netb_name); | 93 | char * netb_name, |
94 | char * server_netb_name); | ||
93 | static int ipv6_connect(struct sockaddr_in6 *psin_server, | 95 | static int ipv6_connect(struct sockaddr_in6 *psin_server, |
94 | struct socket **csocket); | 96 | struct socket **csocket); |
95 | 97 | ||
@@ -182,7 +184,8 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
182 | } else { | 184 | } else { |
183 | rc = ipv4_connect(&server->addr.sockAddr, | 185 | rc = ipv4_connect(&server->addr.sockAddr, |
184 | &server->ssocket, | 186 | &server->ssocket, |
185 | server->workstation_RFC1001_name); | 187 | server->workstation_RFC1001_name, |
188 | server->server_RFC1001_name); | ||
186 | } | 189 | } |
187 | if(rc) { | 190 | if(rc) { |
188 | msleep(3000); | 191 | msleep(3000); |
@@ -743,7 +746,9 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) | |||
743 | toupper(system_utsname.nodename[i]); | 746 | toupper(system_utsname.nodename[i]); |
744 | } | 747 | } |
745 | vol->source_rfc1001_name[15] = 0; | 748 | vol->source_rfc1001_name[15] = 0; |
746 | 749 | /* null target name indicates to use *SMBSERVR default called name | |
750 | if we end up sending RFC1001 session initialize */ | ||
751 | vol->target_rfc1001_name[0] = 0; | ||
747 | vol->linux_uid = current->uid; /* current->euid instead? */ | 752 | vol->linux_uid = current->uid; /* current->euid instead? */ |
748 | vol->linux_gid = current->gid; | 753 | vol->linux_gid = current->gid; |
749 | vol->dir_mode = S_IRWXUGO; | 754 | vol->dir_mode = S_IRWXUGO; |
@@ -996,7 +1001,31 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) | |||
996 | /* The string has 16th byte zero still from | 1001 | /* The string has 16th byte zero still from |
997 | set at top of the function */ | 1002 | set at top of the function */ |
998 | if((i==15) && (value[i] != 0)) | 1003 | if((i==15) && (value[i] != 0)) |
999 | printk(KERN_WARNING "CIFS: netbiosname longer than 15 and was truncated.\n"); | 1004 | printk(KERN_WARNING "CIFS: netbiosname longer than 15 truncated.\n"); |
1005 | } | ||
1006 | } else if (strnicmp(data, "servern", 7) == 0) { | ||
1007 | /* servernetbiosname specified override *SMBSERVER */ | ||
1008 | if (!value || !*value || (*value == ' ')) { | ||
1009 | cFYI(1,("empty server netbiosname specified")); | ||
1010 | } else { | ||
1011 | /* last byte, type, is 0x20 for servr type */ | ||
1012 | memset(vol->target_rfc1001_name,0x20,16); | ||
1013 | |||
1014 | for(i=0;i<15;i++) { | ||
1015 | /* BB are there cases in which a comma can be | ||
1016 | valid in this workstation netbios name (and need | ||
1017 | special handling)? */ | ||
1018 | |||
1019 | /* user or mount helper must uppercase netbiosname */ | ||
1020 | if (value[i]==0) | ||
1021 | break; | ||
1022 | else | ||
1023 | vol->target_rfc1001_name[i] = value[i]; | ||
1024 | } | ||
1025 | /* The string has 16th byte zero still from | ||
1026 | set at top of the function */ | ||
1027 | if((i==15) && (value[i] != 0)) | ||
1028 | printk(KERN_WARNING "CIFS: server netbiosname longer than 15 truncated.\n"); | ||
1000 | } | 1029 | } |
1001 | } else if (strnicmp(data, "credentials", 4) == 0) { | 1030 | } else if (strnicmp(data, "credentials", 4) == 0) { |
1002 | /* ignore */ | 1031 | /* ignore */ |
@@ -1042,7 +1071,8 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) | |||
1042 | vol->posix_paths = 1; | 1071 | vol->posix_paths = 1; |
1043 | } else if (strnicmp(data, "noposixpaths", 12) == 0) { | 1072 | } else if (strnicmp(data, "noposixpaths", 12) == 0) { |
1044 | vol->posix_paths = 0; | 1073 | vol->posix_paths = 0; |
1045 | } else if (strnicmp(data, "nocase", 6) == 0) { | 1074 | } else if ((strnicmp(data, "nocase", 6) == 0) || |
1075 | (strnicmp(data, "ignorecase", 10) == 0)) { | ||
1046 | vol->nocase = 1; | 1076 | vol->nocase = 1; |
1047 | } else if (strnicmp(data, "brl", 3) == 0) { | 1077 | } else if (strnicmp(data, "brl", 3) == 0) { |
1048 | vol->nobrl = 0; | 1078 | vol->nobrl = 0; |
@@ -1272,7 +1302,7 @@ static void rfc1002mangle(char * target,char * source, unsigned int length) | |||
1272 | 1302 | ||
1273 | static int | 1303 | static int |
1274 | ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, | 1304 | ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, |
1275 | char * netbios_name) | 1305 | char * netbios_name, char * target_name) |
1276 | { | 1306 | { |
1277 | int rc = 0; | 1307 | int rc = 0; |
1278 | int connected = 0; | 1308 | int connected = 0; |
@@ -1350,8 +1380,14 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, | |||
1350 | ses_init_buf = kcalloc(1, sizeof(struct rfc1002_session_packet), GFP_KERNEL); | 1380 | ses_init_buf = kcalloc(1, sizeof(struct rfc1002_session_packet), GFP_KERNEL); |
1351 | if(ses_init_buf) { | 1381 | if(ses_init_buf) { |
1352 | ses_init_buf->trailer.session_req.called_len = 32; | 1382 | ses_init_buf->trailer.session_req.called_len = 32; |
1353 | rfc1002mangle(ses_init_buf->trailer.session_req.called_name, | 1383 | if(target_name && (target_name[0] != 0)) { |
1354 | DEFAULT_CIFS_CALLED_NAME,16); | 1384 | rfc1002mangle(ses_init_buf->trailer.session_req.called_name, |
1385 | target_name, 16); | ||
1386 | } else { | ||
1387 | rfc1002mangle(ses_init_buf->trailer.session_req.called_name, | ||
1388 | DEFAULT_CIFS_CALLED_NAME,16); | ||
1389 | } | ||
1390 | |||
1355 | ses_init_buf->trailer.session_req.calling_len = 32; | 1391 | ses_init_buf->trailer.session_req.calling_len = 32; |
1356 | /* calling name ends in null (byte 16) from old smb | 1392 | /* calling name ends in null (byte 16) from old smb |
1357 | convention. */ | 1393 | convention. */ |
@@ -1584,7 +1620,9 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1584 | sin_server.sin_port = htons(volume_info.port); | 1620 | sin_server.sin_port = htons(volume_info.port); |
1585 | else | 1621 | else |
1586 | sin_server.sin_port = 0; | 1622 | sin_server.sin_port = 0; |
1587 | rc = ipv4_connect(&sin_server,&csocket,volume_info.source_rfc1001_name); | 1623 | rc = ipv4_connect(&sin_server,&csocket, |
1624 | volume_info.source_rfc1001_name, | ||
1625 | volume_info.target_rfc1001_name); | ||
1588 | if (rc < 0) { | 1626 | if (rc < 0) { |
1589 | cERROR(1, | 1627 | cERROR(1, |
1590 | ("Error connecting to IPv4 socket. Aborting operation")); | 1628 | ("Error connecting to IPv4 socket. Aborting operation")); |
@@ -1638,6 +1676,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1638 | wait_for_completion(&cifsd_complete); | 1676 | wait_for_completion(&cifsd_complete); |
1639 | rc = 0; | 1677 | rc = 0; |
1640 | memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16); | 1678 | memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16); |
1679 | memcpy(srvTcp->server_RFC1001_name, volume_info.target_rfc1001_name,16); | ||
1641 | srvTcp->sequence_number = 0; | 1680 | srvTcp->sequence_number = 0; |
1642 | } | 1681 | } |
1643 | } | 1682 | } |