diff options
Diffstat (limited to 'fs/cifs/connect.c')
| -rw-r--r-- | fs/cifs/connect.c | 219 |
1 files changed, 182 insertions, 37 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 47360156cc54..d74367a08d51 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
| @@ -29,6 +29,8 @@ | |||
| 29 | #include <linux/utsname.h> | 29 | #include <linux/utsname.h> |
| 30 | #include <linux/mempool.h> | 30 | #include <linux/mempool.h> |
| 31 | #include <linux/delay.h> | 31 | #include <linux/delay.h> |
| 32 | #include <linux/completion.h> | ||
| 33 | #include <linux/pagevec.h> | ||
| 32 | #include <asm/uaccess.h> | 34 | #include <asm/uaccess.h> |
| 33 | #include <asm/processor.h> | 35 | #include <asm/processor.h> |
| 34 | #include "cifspdu.h" | 36 | #include "cifspdu.h" |
| @@ -44,6 +46,8 @@ | |||
| 44 | #define CIFS_PORT 445 | 46 | #define CIFS_PORT 445 |
| 45 | #define RFC1001_PORT 139 | 47 | #define RFC1001_PORT 139 |
| 46 | 48 | ||
| 49 | static DECLARE_COMPLETION(cifsd_complete); | ||
| 50 | |||
| 47 | extern void SMBencrypt(unsigned char *passwd, unsigned char *c8, | 51 | extern void SMBencrypt(unsigned char *passwd, unsigned char *c8, |
| 48 | unsigned char *p24); | 52 | unsigned char *p24); |
| 49 | extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, | 53 | extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, |
| @@ -60,6 +64,7 @@ struct smb_vol { | |||
| 60 | char *in6_addr; /* ipv6 address as human readable form of in6_addr */ | 64 | char *in6_addr; /* ipv6 address as human readable form of in6_addr */ |
| 61 | char *iocharset; /* local code page for mapping to and from Unicode */ | 65 | char *iocharset; /* local code page for mapping to and from Unicode */ |
| 62 | char source_rfc1001_name[16]; /* netbios name of client */ | 66 | char source_rfc1001_name[16]; /* netbios name of client */ |
| 67 | char target_rfc1001_name[16]; /* netbios name of server for Win9x/ME */ | ||
| 63 | uid_t linux_uid; | 68 | uid_t linux_uid; |
| 64 | gid_t linux_gid; | 69 | gid_t linux_gid; |
| 65 | mode_t file_mode; | 70 | mode_t file_mode; |
| @@ -74,6 +79,10 @@ struct smb_vol { | |||
| 74 | unsigned server_ino:1; /* use inode numbers from server ie UniqueId */ | 79 | unsigned server_ino:1; /* use inode numbers from server ie UniqueId */ |
| 75 | unsigned direct_io:1; | 80 | unsigned direct_io:1; |
| 76 | unsigned remap:1; /* set to remap seven reserved chars in filenames */ | 81 | unsigned remap:1; /* set to remap seven reserved chars in filenames */ |
| 82 | unsigned posix_paths:1; /* unset to not ask for posix pathnames. */ | ||
| 83 | unsigned sfu_emul:1; | ||
| 84 | unsigned nocase; /* request case insensitive filenames */ | ||
| 85 | unsigned nobrl; /* disable sending byte range locks to srv */ | ||
| 77 | unsigned int rsize; | 86 | unsigned int rsize; |
| 78 | unsigned int wsize; | 87 | unsigned int wsize; |
| 79 | unsigned int sockopt; | 88 | unsigned int sockopt; |
| @@ -82,7 +91,8 @@ struct smb_vol { | |||
| 82 | 91 | ||
| 83 | static int ipv4_connect(struct sockaddr_in *psin_server, | 92 | static int ipv4_connect(struct sockaddr_in *psin_server, |
| 84 | struct socket **csocket, | 93 | struct socket **csocket, |
| 85 | char * netb_name); | 94 | char * netb_name, |
| 95 | char * server_netb_name); | ||
| 86 | static int ipv6_connect(struct sockaddr_in6 *psin_server, | 96 | static int ipv6_connect(struct sockaddr_in6 *psin_server, |
| 87 | struct socket **csocket); | 97 | struct socket **csocket); |
| 88 | 98 | ||
| @@ -175,9 +185,11 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
| 175 | } else { | 185 | } else { |
| 176 | rc = ipv4_connect(&server->addr.sockAddr, | 186 | rc = ipv4_connect(&server->addr.sockAddr, |
| 177 | &server->ssocket, | 187 | &server->ssocket, |
| 178 | server->workstation_RFC1001_name); | 188 | server->workstation_RFC1001_name, |
| 189 | server->server_RFC1001_name); | ||
| 179 | } | 190 | } |
| 180 | if(rc) { | 191 | if(rc) { |
| 192 | cFYI(1,("reconnect error %d",rc)); | ||
| 181 | msleep(3000); | 193 | msleep(3000); |
| 182 | } else { | 194 | } else { |
| 183 | atomic_inc(&tcpSesReconnectCount); | 195 | atomic_inc(&tcpSesReconnectCount); |
| @@ -293,12 +305,12 @@ static int coalesce_t2(struct smb_hdr * psecond, struct smb_hdr *pTargetSMB) | |||
| 293 | byte_count += total_in_buf2; | 305 | byte_count += total_in_buf2; |
| 294 | BCC_LE(pTargetSMB) = cpu_to_le16(byte_count); | 306 | BCC_LE(pTargetSMB) = cpu_to_le16(byte_count); |
| 295 | 307 | ||
| 296 | byte_count = be32_to_cpu(pTargetSMB->smb_buf_length); | 308 | byte_count = pTargetSMB->smb_buf_length; |
| 297 | byte_count += total_in_buf2; | 309 | byte_count += total_in_buf2; |
| 298 | 310 | ||
| 299 | /* BB also add check that we are not beyond maximum buffer size */ | 311 | /* BB also add check that we are not beyond maximum buffer size */ |
| 300 | 312 | ||
| 301 | pTargetSMB->smb_buf_length = cpu_to_be32(byte_count); | 313 | pTargetSMB->smb_buf_length = byte_count; |
| 302 | 314 | ||
| 303 | if(remaining == total_in_buf2) { | 315 | if(remaining == total_in_buf2) { |
| 304 | cFYI(1,("found the last secondary response")); | 316 | cFYI(1,("found the last secondary response")); |
| @@ -323,7 +335,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
| 323 | struct cifsSesInfo *ses; | 335 | struct cifsSesInfo *ses; |
| 324 | struct task_struct *task_to_wake = NULL; | 336 | struct task_struct *task_to_wake = NULL; |
| 325 | struct mid_q_entry *mid_entry; | 337 | struct mid_q_entry *mid_entry; |
| 326 | char *temp; | 338 | char temp; |
| 327 | int isLargeBuf = FALSE; | 339 | int isLargeBuf = FALSE; |
| 328 | int isMultiRsp; | 340 | int isMultiRsp; |
| 329 | int reconnect; | 341 | int reconnect; |
| @@ -337,6 +349,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
| 337 | atomic_inc(&tcpSesAllocCount); | 349 | atomic_inc(&tcpSesAllocCount); |
| 338 | length = tcpSesAllocCount.counter; | 350 | length = tcpSesAllocCount.counter; |
| 339 | write_unlock(&GlobalSMBSeslock); | 351 | write_unlock(&GlobalSMBSeslock); |
| 352 | complete(&cifsd_complete); | ||
| 340 | if(length > 1) { | 353 | if(length > 1) { |
| 341 | mempool_resize(cifs_req_poolp, | 354 | mempool_resize(cifs_req_poolp, |
| 342 | length + cifs_min_rcv, | 355 | length + cifs_min_rcv, |
| @@ -424,22 +437,32 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
| 424 | continue; | 437 | continue; |
| 425 | } | 438 | } |
| 426 | 439 | ||
| 427 | /* the right amount was read from socket - 4 bytes */ | 440 | /* The right amount was read from socket - 4 bytes */ |
| 441 | /* so we can now interpret the length field */ | ||
| 442 | |||
| 443 | /* the first byte big endian of the length field, | ||
| 444 | is actually not part of the length but the type | ||
| 445 | with the most common, zero, as regular data */ | ||
| 446 | temp = *((char *) smb_buffer); | ||
| 428 | 447 | ||
| 448 | /* Note that FC 1001 length is big endian on the wire, | ||
| 449 | but we convert it here so it is always manipulated | ||
| 450 | as host byte order */ | ||
| 429 | pdu_length = ntohl(smb_buffer->smb_buf_length); | 451 | pdu_length = ntohl(smb_buffer->smb_buf_length); |
| 430 | cFYI(1,("rfc1002 length(big endian)0x%x)", pdu_length+4)); | 452 | smb_buffer->smb_buf_length = pdu_length; |
| 453 | |||
| 454 | cFYI(1,("rfc1002 length 0x%x)", pdu_length+4)); | ||
| 431 | 455 | ||
| 432 | temp = (char *) smb_buffer; | 456 | if (temp == (char) RFC1002_SESSION_KEEP_ALIVE) { |
| 433 | if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) { | ||
| 434 | continue; | 457 | continue; |
| 435 | } else if (temp[0] == (char)RFC1002_POSITIVE_SESSION_RESPONSE) { | 458 | } else if (temp == (char)RFC1002_POSITIVE_SESSION_RESPONSE) { |
| 436 | cFYI(1,("Good RFC 1002 session rsp")); | 459 | cFYI(1,("Good RFC 1002 session rsp")); |
| 437 | continue; | 460 | continue; |
| 438 | } else if (temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) { | 461 | } else if (temp == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) { |
| 439 | /* we get this from Windows 98 instead of | 462 | /* we get this from Windows 98 instead of |
| 440 | an error on SMB negprot response */ | 463 | an error on SMB negprot response */ |
| 441 | cFYI(1,("Negative RFC1002 Session Response Error 0x%x)", | 464 | cFYI(1,("Negative RFC1002 Session Response Error 0x%x)", |
| 442 | temp[4])); | 465 | pdu_length)); |
| 443 | if(server->tcpStatus == CifsNew) { | 466 | if(server->tcpStatus == CifsNew) { |
| 444 | /* if nack on negprot (rather than | 467 | /* if nack on negprot (rather than |
| 445 | ret of smb negprot error) reconnecting | 468 | ret of smb negprot error) reconnecting |
| @@ -461,9 +484,10 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
| 461 | wake_up(&server->response_q); | 484 | wake_up(&server->response_q); |
| 462 | continue; | 485 | continue; |
| 463 | } | 486 | } |
| 464 | } else if (temp[0] != (char) 0) { | 487 | } else if (temp != (char) 0) { |
| 465 | cERROR(1,("Unknown RFC 1002 frame")); | 488 | cERROR(1,("Unknown RFC 1002 frame")); |
| 466 | cifs_dump_mem(" Received Data: ", temp, length); | 489 | cifs_dump_mem(" Received Data: ", (char *)smb_buffer, |
| 490 | length); | ||
| 467 | cifs_reconnect(server); | 491 | cifs_reconnect(server); |
| 468 | csocket = server->ssocket; | 492 | csocket = server->ssocket; |
| 469 | continue; | 493 | continue; |
| @@ -533,7 +557,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
| 533 | 557 | ||
| 534 | dump_smb(smb_buffer, length); | 558 | dump_smb(smb_buffer, length); |
| 535 | if (checkSMB (smb_buffer, smb_buffer->Mid, total_read+4)) { | 559 | if (checkSMB (smb_buffer, smb_buffer->Mid, total_read+4)) { |
| 536 | cERROR(1, ("Bad SMB Received ")); | 560 | cifs_dump_mem("Bad SMB: ", smb_buffer, 48); |
| 537 | continue; | 561 | continue; |
| 538 | } | 562 | } |
| 539 | 563 | ||
| @@ -581,6 +605,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
| 581 | multi_t2_fnd: | 605 | multi_t2_fnd: |
| 582 | task_to_wake = mid_entry->tsk; | 606 | task_to_wake = mid_entry->tsk; |
| 583 | mid_entry->midState = MID_RESPONSE_RECEIVED; | 607 | mid_entry->midState = MID_RESPONSE_RECEIVED; |
| 608 | #ifdef CONFIG_CIFS_STATS2 | ||
| 609 | mid_entry->when_received = jiffies; | ||
| 610 | #endif | ||
| 584 | break; | 611 | break; |
| 585 | } | 612 | } |
| 586 | } | 613 | } |
| @@ -598,7 +625,8 @@ multi_t2_fnd: | |||
| 598 | } else if ((is_valid_oplock_break(smb_buffer) == FALSE) | 625 | } else if ((is_valid_oplock_break(smb_buffer) == FALSE) |
| 599 | && (isMultiRsp == FALSE)) { | 626 | && (isMultiRsp == FALSE)) { |
| 600 | cERROR(1, ("No task to wake, unknown frame rcvd!")); | 627 | cERROR(1, ("No task to wake, unknown frame rcvd!")); |
| 601 | cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr)); | 628 | cifs_dump_mem("Received Data is: ",(char *)smb_buffer, |
| 629 | sizeof(struct smb_hdr)); | ||
| 602 | } | 630 | } |
| 603 | } /* end while !EXITING */ | 631 | } /* end while !EXITING */ |
| 604 | 632 | ||
| @@ -676,7 +704,7 @@ multi_t2_fnd: | |||
| 676 | msleep(125); | 704 | msleep(125); |
| 677 | } | 705 | } |
| 678 | 706 | ||
| 679 | if (list_empty(&server->pending_mid_q)) { | 707 | if (!list_empty(&server->pending_mid_q)) { |
| 680 | /* mpx threads have not exited yet give them | 708 | /* mpx threads have not exited yet give them |
| 681 | at least the smb send timeout time for long ops */ | 709 | at least the smb send timeout time for long ops */ |
| 682 | /* due to delays on oplock break requests, we need | 710 | /* due to delays on oplock break requests, we need |
| @@ -713,7 +741,7 @@ multi_t2_fnd: | |||
| 713 | GFP_KERNEL); | 741 | GFP_KERNEL); |
| 714 | } | 742 | } |
| 715 | 743 | ||
| 716 | msleep(250); | 744 | complete_and_exit(&cifsd_complete, 0); |
| 717 | return 0; | 745 | return 0; |
| 718 | } | 746 | } |
| 719 | 747 | ||
| @@ -737,7 +765,9 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) | |||
| 737 | toupper(system_utsname.nodename[i]); | 765 | toupper(system_utsname.nodename[i]); |
| 738 | } | 766 | } |
| 739 | vol->source_rfc1001_name[15] = 0; | 767 | vol->source_rfc1001_name[15] = 0; |
| 740 | 768 | /* null target name indicates to use *SMBSERVR default called name | |
| 769 | if we end up sending RFC1001 session initialize */ | ||
| 770 | vol->target_rfc1001_name[0] = 0; | ||
| 741 | vol->linux_uid = current->uid; /* current->euid instead? */ | 771 | vol->linux_uid = current->uid; /* current->euid instead? */ |
| 742 | vol->linux_gid = current->gid; | 772 | vol->linux_gid = current->gid; |
| 743 | vol->dir_mode = S_IRWXUGO; | 773 | vol->dir_mode = S_IRWXUGO; |
| @@ -747,6 +777,9 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) | |||
| 747 | /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */ | 777 | /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */ |
| 748 | vol->rw = TRUE; | 778 | vol->rw = TRUE; |
| 749 | 779 | ||
| 780 | /* default is always to request posix paths. */ | ||
| 781 | vol->posix_paths = 1; | ||
| 782 | |||
| 750 | if (!options) | 783 | if (!options) |
| 751 | return 1; | 784 | return 1; |
| 752 | 785 | ||
| @@ -987,7 +1020,31 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) | |||
| 987 | /* The string has 16th byte zero still from | 1020 | /* The string has 16th byte zero still from |
| 988 | set at top of the function */ | 1021 | set at top of the function */ |
| 989 | if((i==15) && (value[i] != 0)) | 1022 | if((i==15) && (value[i] != 0)) |
| 990 | printk(KERN_WARNING "CIFS: netbiosname longer than 15 and was truncated.\n"); | 1023 | printk(KERN_WARNING "CIFS: netbiosname longer than 15 truncated.\n"); |
| 1024 | } | ||
| 1025 | } else if (strnicmp(data, "servern", 7) == 0) { | ||
| 1026 | /* servernetbiosname specified override *SMBSERVER */ | ||
| 1027 | if (!value || !*value || (*value == ' ')) { | ||
| 1028 | cFYI(1,("empty server netbiosname specified")); | ||
| 1029 | } else { | ||
| 1030 | /* last byte, type, is 0x20 for servr type */ | ||
| 1031 | memset(vol->target_rfc1001_name,0x20,16); | ||
| 1032 | |||
| 1033 | for(i=0;i<15;i++) { | ||
| 1034 | /* BB are there cases in which a comma can be | ||
| 1035 | valid in this workstation netbios name (and need | ||
| 1036 | special handling)? */ | ||
| 1037 | |||
| 1038 | /* user or mount helper must uppercase netbiosname */ | ||
| 1039 | if (value[i]==0) | ||
| 1040 | break; | ||
| 1041 | else | ||
| 1042 | vol->target_rfc1001_name[i] = value[i]; | ||
| 1043 | } | ||
| 1044 | /* The string has 16th byte zero still from | ||
| 1045 | set at top of the function */ | ||
| 1046 | if((i==15) && (value[i] != 0)) | ||
| 1047 | printk(KERN_WARNING "CIFS: server netbiosname longer than 15 truncated.\n"); | ||
| 991 | } | 1048 | } |
| 992 | } else if (strnicmp(data, "credentials", 4) == 0) { | 1049 | } else if (strnicmp(data, "credentials", 4) == 0) { |
| 993 | /* ignore */ | 1050 | /* ignore */ |
| @@ -1025,6 +1082,27 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) | |||
| 1025 | vol->remap = 1; | 1082 | vol->remap = 1; |
| 1026 | } else if (strnicmp(data, "nomapchars", 10) == 0) { | 1083 | } else if (strnicmp(data, "nomapchars", 10) == 0) { |
| 1027 | vol->remap = 0; | 1084 | vol->remap = 0; |
| 1085 | } else if (strnicmp(data, "sfu", 3) == 0) { | ||
| 1086 | vol->sfu_emul = 1; | ||
| 1087 | } else if (strnicmp(data, "nosfu", 5) == 0) { | ||
| 1088 | vol->sfu_emul = 0; | ||
| 1089 | } else if (strnicmp(data, "posixpaths", 10) == 0) { | ||
| 1090 | vol->posix_paths = 1; | ||
| 1091 | } else if (strnicmp(data, "noposixpaths", 12) == 0) { | ||
| 1092 | vol->posix_paths = 0; | ||
| 1093 | } else if ((strnicmp(data, "nocase", 6) == 0) || | ||
| 1094 | (strnicmp(data, "ignorecase", 10) == 0)) { | ||
| 1095 | vol->nocase = 1; | ||
| 1096 | } else if (strnicmp(data, "brl", 3) == 0) { | ||
| 1097 | vol->nobrl = 0; | ||
| 1098 | } else if ((strnicmp(data, "nobrl", 5) == 0) || | ||
| 1099 | (strnicmp(data, "nolock", 6) == 0)) { | ||
| 1100 | vol->nobrl = 1; | ||
| 1101 | /* turn off mandatory locking in mode | ||
| 1102 | if remote locking is turned off since the | ||
| 1103 | local vfs will do advisory */ | ||
| 1104 | if(vol->file_mode == (S_IALLUGO & ~(S_ISUID | S_IXGRP))) | ||
| 1105 | vol->file_mode = S_IALLUGO; | ||
| 1028 | } else if (strnicmp(data, "setuids", 7) == 0) { | 1106 | } else if (strnicmp(data, "setuids", 7) == 0) { |
| 1029 | vol->setuids = 1; | 1107 | vol->setuids = 1; |
| 1030 | } else if (strnicmp(data, "nosetuids", 9) == 0) { | 1108 | } else if (strnicmp(data, "nosetuids", 9) == 0) { |
| @@ -1244,7 +1322,7 @@ static void rfc1002mangle(char * target,char * source, unsigned int length) | |||
| 1244 | 1322 | ||
| 1245 | static int | 1323 | static int |
| 1246 | ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, | 1324 | ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, |
| 1247 | char * netbios_name) | 1325 | char * netbios_name, char * target_name) |
| 1248 | { | 1326 | { |
| 1249 | int rc = 0; | 1327 | int rc = 0; |
| 1250 | int connected = 0; | 1328 | int connected = 0; |
| @@ -1309,10 +1387,16 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, | |||
| 1309 | /* Eventually check for other socket options to change from | 1387 | /* Eventually check for other socket options to change from |
| 1310 | the default. sock_setsockopt not used because it expects | 1388 | the default. sock_setsockopt not used because it expects |
| 1311 | user space buffer */ | 1389 | user space buffer */ |
| 1390 | cFYI(1,("sndbuf %d rcvbuf %d rcvtimeo 0x%lx",(*csocket)->sk->sk_sndbuf, | ||
| 1391 | (*csocket)->sk->sk_rcvbuf, (*csocket)->sk->sk_rcvtimeo)); | ||
| 1312 | (*csocket)->sk->sk_rcvtimeo = 7 * HZ; | 1392 | (*csocket)->sk->sk_rcvtimeo = 7 * HZ; |
| 1393 | /* make the bufsizes depend on wsize/rsize and max requests */ | ||
| 1394 | if((*csocket)->sk->sk_sndbuf < (200 * 1024)) | ||
| 1395 | (*csocket)->sk->sk_sndbuf = 200 * 1024; | ||
| 1396 | if((*csocket)->sk->sk_rcvbuf < (140 * 1024)) | ||
| 1397 | (*csocket)->sk->sk_rcvbuf = 140 * 1024; | ||
| 1313 | 1398 | ||
| 1314 | /* send RFC1001 sessinit */ | 1399 | /* send RFC1001 sessinit */ |
| 1315 | |||
| 1316 | if(psin_server->sin_port == htons(RFC1001_PORT)) { | 1400 | if(psin_server->sin_port == htons(RFC1001_PORT)) { |
| 1317 | /* some servers require RFC1001 sessinit before sending | 1401 | /* some servers require RFC1001 sessinit before sending |
| 1318 | negprot - BB check reconnection in case where second | 1402 | negprot - BB check reconnection in case where second |
| @@ -1322,8 +1406,14 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, | |||
| 1322 | ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet), GFP_KERNEL); | 1406 | ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet), GFP_KERNEL); |
| 1323 | if(ses_init_buf) { | 1407 | if(ses_init_buf) { |
| 1324 | ses_init_buf->trailer.session_req.called_len = 32; | 1408 | ses_init_buf->trailer.session_req.called_len = 32; |
| 1325 | rfc1002mangle(ses_init_buf->trailer.session_req.called_name, | 1409 | if(target_name && (target_name[0] != 0)) { |
| 1326 | DEFAULT_CIFS_CALLED_NAME,16); | 1410 | rfc1002mangle(ses_init_buf->trailer.session_req.called_name, |
| 1411 | target_name, 16); | ||
| 1412 | } else { | ||
| 1413 | rfc1002mangle(ses_init_buf->trailer.session_req.called_name, | ||
| 1414 | DEFAULT_CIFS_CALLED_NAME,16); | ||
| 1415 | } | ||
| 1416 | |||
| 1327 | ses_init_buf->trailer.session_req.calling_len = 32; | 1417 | ses_init_buf->trailer.session_req.calling_len = 32; |
| 1328 | /* calling name ends in null (byte 16) from old smb | 1418 | /* calling name ends in null (byte 16) from old smb |
| 1329 | convention. */ | 1419 | convention. */ |
| @@ -1556,7 +1646,9 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
| 1556 | sin_server.sin_port = htons(volume_info.port); | 1646 | sin_server.sin_port = htons(volume_info.port); |
| 1557 | else | 1647 | else |
| 1558 | sin_server.sin_port = 0; | 1648 | sin_server.sin_port = 0; |
| 1559 | rc = ipv4_connect(&sin_server,&csocket,volume_info.source_rfc1001_name); | 1649 | rc = ipv4_connect(&sin_server,&csocket, |
| 1650 | volume_info.source_rfc1001_name, | ||
| 1651 | volume_info.target_rfc1001_name); | ||
| 1560 | if (rc < 0) { | 1652 | if (rc < 0) { |
| 1561 | cERROR(1, | 1653 | cERROR(1, |
| 1562 | ("Error connecting to IPv4 socket. Aborting operation")); | 1654 | ("Error connecting to IPv4 socket. Aborting operation")); |
| @@ -1606,9 +1698,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
| 1606 | kfree(volume_info.password); | 1698 | kfree(volume_info.password); |
| 1607 | FreeXid(xid); | 1699 | FreeXid(xid); |
| 1608 | return rc; | 1700 | return rc; |
| 1609 | } else | 1701 | } |
| 1610 | rc = 0; | 1702 | wait_for_completion(&cifsd_complete); |
| 1703 | rc = 0; | ||
| 1611 | memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16); | 1704 | memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16); |
| 1705 | memcpy(srvTcp->server_RFC1001_name, volume_info.target_rfc1001_name,16); | ||
| 1612 | srvTcp->sequence_number = 0; | 1706 | srvTcp->sequence_number = 0; |
| 1613 | } | 1707 | } |
| 1614 | } | 1708 | } |
| @@ -1653,17 +1747,27 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
| 1653 | 1747 | ||
| 1654 | /* search for existing tcon to this server share */ | 1748 | /* search for existing tcon to this server share */ |
| 1655 | if (!rc) { | 1749 | if (!rc) { |
| 1656 | if((volume_info.rsize) && (volume_info.rsize <= CIFSMaxBufSize)) | 1750 | if(volume_info.rsize > CIFSMaxBufSize) { |
| 1751 | cERROR(1,("rsize %d too large, using MaxBufSize", | ||
| 1752 | volume_info.rsize)); | ||
| 1753 | cifs_sb->rsize = CIFSMaxBufSize; | ||
| 1754 | } else if((volume_info.rsize) && (volume_info.rsize <= CIFSMaxBufSize)) | ||
| 1657 | cifs_sb->rsize = volume_info.rsize; | 1755 | cifs_sb->rsize = volume_info.rsize; |
| 1658 | else | 1756 | else /* default */ |
| 1659 | cifs_sb->rsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */ | 1757 | cifs_sb->rsize = CIFSMaxBufSize; |
| 1660 | if((volume_info.wsize) && (volume_info.wsize <= CIFSMaxBufSize)) | 1758 | |
| 1759 | if(volume_info.wsize > PAGEVEC_SIZE * PAGE_CACHE_SIZE) { | ||
| 1760 | cERROR(1,("wsize %d too large using 4096 instead", | ||
| 1761 | volume_info.wsize)); | ||
| 1762 | cifs_sb->wsize = 4096; | ||
| 1763 | } else if(volume_info.wsize) | ||
| 1661 | cifs_sb->wsize = volume_info.wsize; | 1764 | cifs_sb->wsize = volume_info.wsize; |
| 1662 | else | 1765 | else |
| 1663 | cifs_sb->wsize = CIFSMaxBufSize; /* default */ | 1766 | cifs_sb->wsize = CIFSMaxBufSize; /* default */ |
| 1664 | if(cifs_sb->rsize < PAGE_CACHE_SIZE) { | 1767 | if(cifs_sb->rsize < PAGE_CACHE_SIZE) { |
| 1665 | cifs_sb->rsize = PAGE_CACHE_SIZE; | 1768 | cifs_sb->rsize = PAGE_CACHE_SIZE; |
| 1666 | cERROR(1,("Attempt to set readsize for mount to less than one page (4096)")); | 1769 | /* Windows ME does this */ |
| 1770 | cFYI(1,("Attempt to set readsize for mount to less than one page (4096)")); | ||
| 1667 | } | 1771 | } |
| 1668 | cifs_sb->mnt_uid = volume_info.linux_uid; | 1772 | cifs_sb->mnt_uid = volume_info.linux_uid; |
| 1669 | cifs_sb->mnt_gid = volume_info.linux_gid; | 1773 | cifs_sb->mnt_gid = volume_info.linux_gid; |
| @@ -1681,8 +1785,13 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
| 1681 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR; | 1785 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR; |
| 1682 | if(volume_info.no_xattr) | 1786 | if(volume_info.no_xattr) |
| 1683 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR; | 1787 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR; |
| 1788 | if(volume_info.sfu_emul) | ||
| 1789 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL; | ||
| 1790 | if(volume_info.nobrl) | ||
| 1791 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL; | ||
| 1792 | |||
| 1684 | if(volume_info.direct_io) { | 1793 | if(volume_info.direct_io) { |
| 1685 | cERROR(1,("mounting share using direct i/o")); | 1794 | cFYI(1,("mounting share using direct i/o")); |
| 1686 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; | 1795 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; |
| 1687 | } | 1796 | } |
| 1688 | 1797 | ||
| @@ -1696,6 +1805,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
| 1696 | to the same server share the last value passed in | 1805 | to the same server share the last value passed in |
| 1697 | for the retry flag is used */ | 1806 | for the retry flag is used */ |
| 1698 | tcon->retry = volume_info.retry; | 1807 | tcon->retry = volume_info.retry; |
| 1808 | tcon->nocase = volume_info.nocase; | ||
| 1699 | } else { | 1809 | } else { |
| 1700 | tcon = tconInfoAlloc(); | 1810 | tcon = tconInfoAlloc(); |
| 1701 | if (tcon == NULL) | 1811 | if (tcon == NULL) |
| @@ -1724,6 +1834,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
| 1724 | if (!rc) { | 1834 | if (!rc) { |
| 1725 | atomic_inc(&pSesInfo->inUse); | 1835 | atomic_inc(&pSesInfo->inUse); |
| 1726 | tcon->retry = volume_info.retry; | 1836 | tcon->retry = volume_info.retry; |
| 1837 | tcon->nocase = volume_info.nocase; | ||
| 1727 | } | 1838 | } |
| 1728 | } | 1839 | } |
| 1729 | } | 1840 | } |
| @@ -1745,8 +1856,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
| 1745 | spin_lock(&GlobalMid_Lock); | 1856 | spin_lock(&GlobalMid_Lock); |
| 1746 | srvTcp->tcpStatus = CifsExiting; | 1857 | srvTcp->tcpStatus = CifsExiting; |
| 1747 | spin_unlock(&GlobalMid_Lock); | 1858 | spin_unlock(&GlobalMid_Lock); |
| 1748 | if(srvTcp->tsk) | 1859 | if(srvTcp->tsk) { |
| 1749 | send_sig(SIGKILL,srvTcp->tsk,1); | 1860 | send_sig(SIGKILL,srvTcp->tsk,1); |
| 1861 | wait_for_completion(&cifsd_complete); | ||
| 1862 | } | ||
| 1750 | } | 1863 | } |
| 1751 | /* If find_unc succeeded then rc == 0 so we can not end */ | 1864 | /* If find_unc succeeded then rc == 0 so we can not end */ |
| 1752 | if (tcon) /* up accidently freeing someone elses tcon struct */ | 1865 | if (tcon) /* up accidently freeing someone elses tcon struct */ |
| @@ -1759,8 +1872,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
| 1759 | temp_rc = CIFSSMBLogoff(xid, pSesInfo); | 1872 | temp_rc = CIFSSMBLogoff(xid, pSesInfo); |
| 1760 | /* if the socketUseCount is now zero */ | 1873 | /* if the socketUseCount is now zero */ |
| 1761 | if((temp_rc == -ESHUTDOWN) && | 1874 | if((temp_rc == -ESHUTDOWN) && |
| 1762 | (pSesInfo->server->tsk)) | 1875 | (pSesInfo->server->tsk)) { |
| 1763 | send_sig(SIGKILL,pSesInfo->server->tsk,1); | 1876 | send_sig(SIGKILL,pSesInfo->server->tsk,1); |
| 1877 | wait_for_completion(&cifsd_complete); | ||
| 1878 | } | ||
| 1764 | } else | 1879 | } else |
| 1765 | cFYI(1, ("No session or bad tcon")); | 1880 | cFYI(1, ("No session or bad tcon")); |
| 1766 | sesInfoFree(pSesInfo); | 1881 | sesInfoFree(pSesInfo); |
| @@ -1783,8 +1898,27 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
| 1783 | cFYI(1,("server negotiated posix acl support")); | 1898 | cFYI(1,("server negotiated posix acl support")); |
| 1784 | sb->s_flags |= MS_POSIXACL; | 1899 | sb->s_flags |= MS_POSIXACL; |
| 1785 | } | 1900 | } |
| 1901 | |||
| 1902 | /* Try and negotiate POSIX pathnames if we can. */ | ||
| 1903 | if (volume_info.posix_paths && (CIFS_UNIX_POSIX_PATHNAMES_CAP & | ||
| 1904 | le64_to_cpu(tcon->fsUnixInfo.Capability))) { | ||
| 1905 | if (!CIFSSMBSetFSUnixInfo(xid, tcon, CIFS_UNIX_POSIX_PATHNAMES_CAP)) { | ||
| 1906 | cFYI(1,("negotiated posix pathnames support")); | ||
| 1907 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS; | ||
| 1908 | } else { | ||
| 1909 | cFYI(1,("posix pathnames support requested but not supported")); | ||
| 1910 | } | ||
| 1911 | } | ||
| 1786 | } | 1912 | } |
| 1787 | } | 1913 | } |
| 1914 | if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X)) | ||
| 1915 | cifs_sb->wsize = min(cifs_sb->wsize, | ||
| 1916 | (tcon->ses->server->maxBuf - | ||
| 1917 | MAX_CIFS_HDR_SIZE)); | ||
| 1918 | if (!(tcon->ses->capabilities & CAP_LARGE_READ_X)) | ||
| 1919 | cifs_sb->rsize = min(cifs_sb->rsize, | ||
| 1920 | (tcon->ses->server->maxBuf - | ||
| 1921 | MAX_CIFS_HDR_SIZE)); | ||
| 1788 | } | 1922 | } |
| 1789 | 1923 | ||
| 1790 | /* volume_info.password is freed above when existing session found | 1924 | /* volume_info.password is freed above when existing session found |
| @@ -1832,6 +1966,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
| 1832 | header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, | 1966 | header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, |
| 1833 | NULL /* no tCon exists yet */ , 13 /* wct */ ); | 1967 | NULL /* no tCon exists yet */ , 13 /* wct */ ); |
| 1834 | 1968 | ||
| 1969 | smb_buffer->Mid = GetNextMid(ses->server); | ||
| 1835 | pSMB->req_no_secext.AndXCommand = 0xFF; | 1970 | pSMB->req_no_secext.AndXCommand = 0xFF; |
| 1836 | pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); | 1971 | pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); |
| 1837 | pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq); | 1972 | pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq); |
| @@ -2107,6 +2242,8 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
| 2107 | /* send SMBsessionSetup here */ | 2242 | /* send SMBsessionSetup here */ |
| 2108 | header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, | 2243 | header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, |
| 2109 | NULL /* no tCon exists yet */ , 12 /* wct */ ); | 2244 | NULL /* no tCon exists yet */ , 12 /* wct */ ); |
| 2245 | |||
| 2246 | smb_buffer->Mid = GetNextMid(ses->server); | ||
| 2110 | pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; | 2247 | pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; |
| 2111 | pSMB->req.AndXCommand = 0xFF; | 2248 | pSMB->req.AndXCommand = 0xFF; |
| 2112 | pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); | 2249 | pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); |
| @@ -2373,6 +2510,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, | |||
| 2373 | /* send SMBsessionSetup here */ | 2510 | /* send SMBsessionSetup here */ |
| 2374 | header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, | 2511 | header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, |
| 2375 | NULL /* no tCon exists yet */ , 12 /* wct */ ); | 2512 | NULL /* no tCon exists yet */ , 12 /* wct */ ); |
| 2513 | |||
| 2514 | smb_buffer->Mid = GetNextMid(ses->server); | ||
| 2376 | pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; | 2515 | pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; |
| 2377 | pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT); | 2516 | pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT); |
| 2378 | 2517 | ||
| @@ -2715,6 +2854,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
| 2715 | /* send SMBsessionSetup here */ | 2854 | /* send SMBsessionSetup here */ |
| 2716 | header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, | 2855 | header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, |
| 2717 | NULL /* no tCon exists yet */ , 12 /* wct */ ); | 2856 | NULL /* no tCon exists yet */ , 12 /* wct */ ); |
| 2857 | |||
| 2858 | smb_buffer->Mid = GetNextMid(ses->server); | ||
| 2718 | pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT); | 2859 | pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT); |
| 2719 | pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; | 2860 | pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; |
| 2720 | pSMB->req.AndXCommand = 0xFF; | 2861 | pSMB->req.AndXCommand = 0xFF; |
| @@ -3086,6 +3227,8 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
| 3086 | 3227 | ||
| 3087 | header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX, | 3228 | header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX, |
| 3088 | NULL /*no tid */ , 4 /*wct */ ); | 3229 | NULL /*no tid */ , 4 /*wct */ ); |
| 3230 | |||
| 3231 | smb_buffer->Mid = GetNextMid(ses->server); | ||
| 3089 | smb_buffer->Uid = ses->Suid; | 3232 | smb_buffer->Uid = ses->Suid; |
| 3090 | pSMB = (TCONX_REQ *) smb_buffer; | 3233 | pSMB = (TCONX_REQ *) smb_buffer; |
| 3091 | pSMBr = (TCONX_RSP *) smb_buffer_response; | 3234 | pSMBr = (TCONX_RSP *) smb_buffer_response; |
| @@ -3207,8 +3350,10 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb) | |||
| 3207 | return 0; | 3350 | return 0; |
| 3208 | } else if (rc == -ESHUTDOWN) { | 3351 | } else if (rc == -ESHUTDOWN) { |
| 3209 | cFYI(1,("Waking up socket by sending it signal")); | 3352 | cFYI(1,("Waking up socket by sending it signal")); |
| 3210 | if(cifsd_task) | 3353 | if(cifsd_task) { |
| 3211 | send_sig(SIGKILL,cifsd_task,1); | 3354 | send_sig(SIGKILL,cifsd_task,1); |
| 3355 | wait_for_completion(&cifsd_complete); | ||
| 3356 | } | ||
| 3212 | rc = 0; | 3357 | rc = 0; |
| 3213 | } /* else - we have an smb session | 3358 | } /* else - we have an smb session |
| 3214 | left on this socket do not kill cifsd */ | 3359 | left on this socket do not kill cifsd */ |
