diff options
author | Steve French <sfrench@us.ibm.com> | 2005-08-23 00:38:31 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2005-08-23 00:38:31 -0400 |
commit | a10faeb2a3e266385cc334fe9af76e08e5e4330f (patch) | |
tree | 1649766060aeb1bd56fc51af769646ac9ec84539 /fs/cifs/connect.c | |
parent | b92327fe6b25d60004b79df9e3c19091c03118ba (diff) |
[CIFS] Support for mounting to older, pre-CIFS servers added. This
allows specifying an RFC1001 target "called" name (netbios name of the
server, which can now be pecified as mount option "servernetbiosname"
but will eventually be passed in automatically on retry of host down
error messages caused when server refuses to handle default server
name and can not handle port 445). This is an important step, but
additional testing and fixup is needed to add remaining function needed
for these.
Signed-off-by: Steve French (sfrench@us.ibm.com)
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r-- | fs/cifs/connect.c | 57 |
1 files changed, 48 insertions, 9 deletions
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 | } |