diff options
Diffstat (limited to 'fs/cifs/cifssmb.c')
-rw-r--r-- | fs/cifs/cifssmb.c | 1171 |
1 files changed, 753 insertions, 418 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 7e83b356cc9e..1a9fe7f816d1 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/vfs.h> | 32 | #include <linux/vfs.h> |
33 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
34 | #include <linux/posix_acl_xattr.h> | 34 | #include <linux/posix_acl_xattr.h> |
35 | #include <linux/pagemap.h> | ||
35 | #include <asm/uaccess.h> | 36 | #include <asm/uaccess.h> |
36 | #include "cifspdu.h" | 37 | #include "cifspdu.h" |
37 | #include "cifsglob.h" | 38 | #include "cifsglob.h" |
@@ -84,30 +85,30 @@ static struct { | |||
84 | 85 | ||
85 | /* Mark as invalid, all open files on tree connections since they | 86 | /* Mark as invalid, all open files on tree connections since they |
86 | were closed when session to server was lost */ | 87 | were closed when session to server was lost */ |
87 | static void mark_open_files_invalid(struct cifsTconInfo *pTcon) | 88 | static void mark_open_files_invalid(struct cifs_tcon *pTcon) |
88 | { | 89 | { |
89 | struct cifsFileInfo *open_file = NULL; | 90 | struct cifsFileInfo *open_file = NULL; |
90 | struct list_head *tmp; | 91 | struct list_head *tmp; |
91 | struct list_head *tmp1; | 92 | struct list_head *tmp1; |
92 | 93 | ||
93 | /* list all files open on tree connection and mark them invalid */ | 94 | /* list all files open on tree connection and mark them invalid */ |
94 | write_lock(&GlobalSMBSeslock); | 95 | spin_lock(&cifs_file_list_lock); |
95 | list_for_each_safe(tmp, tmp1, &pTcon->openFileList) { | 96 | list_for_each_safe(tmp, tmp1, &pTcon->openFileList) { |
96 | open_file = list_entry(tmp, struct cifsFileInfo, tlist); | 97 | open_file = list_entry(tmp, struct cifsFileInfo, tlist); |
97 | open_file->invalidHandle = true; | 98 | open_file->invalidHandle = true; |
98 | open_file->oplock_break_cancelled = true; | 99 | open_file->oplock_break_cancelled = true; |
99 | } | 100 | } |
100 | write_unlock(&GlobalSMBSeslock); | 101 | spin_unlock(&cifs_file_list_lock); |
101 | /* BB Add call to invalidate_inodes(sb) for all superblocks mounted | 102 | /* BB Add call to invalidate_inodes(sb) for all superblocks mounted |
102 | to this tcon */ | 103 | to this tcon */ |
103 | } | 104 | } |
104 | 105 | ||
105 | /* reconnect the socket, tcon, and smb session if needed */ | 106 | /* reconnect the socket, tcon, and smb session if needed */ |
106 | static int | 107 | static int |
107 | cifs_reconnect_tcon(struct cifsTconInfo *tcon, int smb_command) | 108 | cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command) |
108 | { | 109 | { |
109 | int rc = 0; | 110 | int rc = 0; |
110 | struct cifsSesInfo *ses; | 111 | struct cifs_ses *ses; |
111 | struct TCP_Server_Info *server; | 112 | struct TCP_Server_Info *server; |
112 | struct nls_table *nls_codepage; | 113 | struct nls_table *nls_codepage; |
113 | 114 | ||
@@ -136,18 +137,15 @@ cifs_reconnect_tcon(struct cifsTconInfo *tcon, int smb_command) | |||
136 | } | 137 | } |
137 | } | 138 | } |
138 | 139 | ||
139 | if (ses->status == CifsExiting) | ||
140 | return -EIO; | ||
141 | |||
142 | /* | 140 | /* |
143 | * Give demultiplex thread up to 10 seconds to reconnect, should be | 141 | * Give demultiplex thread up to 10 seconds to reconnect, should be |
144 | * greater than cifs socket timeout which is 7 seconds | 142 | * greater than cifs socket timeout which is 7 seconds |
145 | */ | 143 | */ |
146 | while (server->tcpStatus == CifsNeedReconnect) { | 144 | while (server->tcpStatus == CifsNeedReconnect) { |
147 | wait_event_interruptible_timeout(server->response_q, | 145 | wait_event_interruptible_timeout(server->response_q, |
148 | (server->tcpStatus == CifsGood), 10 * HZ); | 146 | (server->tcpStatus != CifsNeedReconnect), 10 * HZ); |
149 | 147 | ||
150 | /* is TCP session is reestablished now ?*/ | 148 | /* are we still trying to reconnect? */ |
151 | if (server->tcpStatus != CifsNeedReconnect) | 149 | if (server->tcpStatus != CifsNeedReconnect) |
152 | break; | 150 | break; |
153 | 151 | ||
@@ -156,7 +154,7 @@ cifs_reconnect_tcon(struct cifsTconInfo *tcon, int smb_command) | |||
156 | * retrying until process is killed or server comes | 154 | * retrying until process is killed or server comes |
157 | * back on-line | 155 | * back on-line |
158 | */ | 156 | */ |
159 | if (!tcon->retry || ses->status == CifsExiting) { | 157 | if (!tcon->retry) { |
160 | cFYI(1, "gave up waiting on reconnect in smb_init"); | 158 | cFYI(1, "gave up waiting on reconnect in smb_init"); |
161 | return -EHOSTDOWN; | 159 | return -EHOSTDOWN; |
162 | } | 160 | } |
@@ -229,7 +227,7 @@ out: | |||
229 | SMB information in the SMB header. If the return code is zero, this | 227 | SMB information in the SMB header. If the return code is zero, this |
230 | function must have filled in request_buf pointer */ | 228 | function must have filled in request_buf pointer */ |
231 | static int | 229 | static int |
232 | small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, | 230 | small_smb_init(int smb_command, int wct, struct cifs_tcon *tcon, |
233 | void **request_buf) | 231 | void **request_buf) |
234 | { | 232 | { |
235 | int rc; | 233 | int rc; |
@@ -255,7 +253,7 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, | |||
255 | 253 | ||
256 | int | 254 | int |
257 | small_smb_init_no_tc(const int smb_command, const int wct, | 255 | small_smb_init_no_tc(const int smb_command, const int wct, |
258 | struct cifsSesInfo *ses, void **request_buf) | 256 | struct cifs_ses *ses, void **request_buf) |
259 | { | 257 | { |
260 | int rc; | 258 | int rc; |
261 | struct smb_hdr *buffer; | 259 | struct smb_hdr *buffer; |
@@ -281,7 +279,7 @@ small_smb_init_no_tc(const int smb_command, const int wct, | |||
281 | 279 | ||
282 | /* If the return code is zero, this function must fill in request_buf pointer */ | 280 | /* If the return code is zero, this function must fill in request_buf pointer */ |
283 | static int | 281 | static int |
284 | __smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, | 282 | __smb_init(int smb_command, int wct, struct cifs_tcon *tcon, |
285 | void **request_buf, void **response_buf) | 283 | void **request_buf, void **response_buf) |
286 | { | 284 | { |
287 | *request_buf = cifs_buf_get(); | 285 | *request_buf = cifs_buf_get(); |
@@ -307,7 +305,7 @@ __smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, | |||
307 | 305 | ||
308 | /* If the return code is zero, this function must fill in request_buf pointer */ | 306 | /* If the return code is zero, this function must fill in request_buf pointer */ |
309 | static int | 307 | static int |
310 | smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, | 308 | smb_init(int smb_command, int wct, struct cifs_tcon *tcon, |
311 | void **request_buf, void **response_buf) | 309 | void **request_buf, void **response_buf) |
312 | { | 310 | { |
313 | int rc; | 311 | int rc; |
@@ -320,7 +318,7 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, | |||
320 | } | 318 | } |
321 | 319 | ||
322 | static int | 320 | static int |
323 | smb_init_no_reconnect(int smb_command, int wct, struct cifsTconInfo *tcon, | 321 | smb_init_no_reconnect(int smb_command, int wct, struct cifs_tcon *tcon, |
324 | void **request_buf, void **response_buf) | 322 | void **request_buf, void **response_buf) |
325 | { | 323 | { |
326 | if (tcon->ses->need_reconnect || tcon->need_reconnect) | 324 | if (tcon->ses->need_reconnect || tcon->need_reconnect) |
@@ -331,39 +329,45 @@ smb_init_no_reconnect(int smb_command, int wct, struct cifsTconInfo *tcon, | |||
331 | 329 | ||
332 | static int validate_t2(struct smb_t2_rsp *pSMB) | 330 | static int validate_t2(struct smb_t2_rsp *pSMB) |
333 | { | 331 | { |
334 | int rc = -EINVAL; | 332 | unsigned int total_size; |
335 | int total_size; | 333 | |
336 | char *pBCC; | 334 | /* check for plausible wct */ |
335 | if (pSMB->hdr.WordCount < 10) | ||
336 | goto vt2_err; | ||
337 | 337 | ||
338 | /* check for plausible wct, bcc and t2 data and parm sizes */ | ||
339 | /* check for parm and data offset going beyond end of smb */ | 338 | /* check for parm and data offset going beyond end of smb */ |
340 | if (pSMB->hdr.WordCount >= 10) { | 339 | if (get_unaligned_le16(&pSMB->t2_rsp.ParameterOffset) > 1024 || |
341 | if ((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) && | 340 | get_unaligned_le16(&pSMB->t2_rsp.DataOffset) > 1024) |
342 | (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) { | 341 | goto vt2_err; |
343 | /* check that bcc is at least as big as parms + data */ | 342 | |
344 | /* check that bcc is less than negotiated smb buffer */ | 343 | total_size = get_unaligned_le16(&pSMB->t2_rsp.ParameterCount); |
345 | total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount); | 344 | if (total_size >= 512) |
346 | if (total_size < 512) { | 345 | goto vt2_err; |
347 | total_size += | 346 | |
348 | le16_to_cpu(pSMB->t2_rsp.DataCount); | 347 | /* check that bcc is at least as big as parms + data, and that it is |
349 | /* BCC le converted in SendReceive */ | 348 | * less than negotiated smb buffer |
350 | pBCC = (pSMB->hdr.WordCount * 2) + | 349 | */ |
351 | sizeof(struct smb_hdr) + | 350 | total_size += get_unaligned_le16(&pSMB->t2_rsp.DataCount); |
352 | (char *)pSMB; | 351 | if (total_size > get_bcc(&pSMB->hdr) || |
353 | if ((total_size <= (*(u16 *)pBCC)) && | 352 | total_size >= CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) |
354 | (total_size < | 353 | goto vt2_err; |
355 | CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) { | 354 | |
356 | return 0; | 355 | return 0; |
357 | } | 356 | vt2_err: |
358 | } | ||
359 | } | ||
360 | } | ||
361 | cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB, | 357 | cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB, |
362 | sizeof(struct smb_t2_rsp) + 16); | 358 | sizeof(struct smb_t2_rsp) + 16); |
363 | return rc; | 359 | return -EINVAL; |
364 | } | 360 | } |
361 | |||
362 | static inline void inc_rfc1001_len(void *pSMB, int count) | ||
363 | { | ||
364 | struct smb_hdr *hdr = (struct smb_hdr *)pSMB; | ||
365 | |||
366 | be32_add_cpu(&hdr->smb_buf_length, count); | ||
367 | } | ||
368 | |||
365 | int | 369 | int |
366 | CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | 370 | CIFSSMBNegotiate(unsigned int xid, struct cifs_ses *ses) |
367 | { | 371 | { |
368 | NEGOTIATE_REQ *pSMB; | 372 | NEGOTIATE_REQ *pSMB; |
369 | NEGOTIATE_RSP *pSMBr; | 373 | NEGOTIATE_RSP *pSMBr; |
@@ -401,15 +405,12 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
401 | else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) { | 405 | else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) { |
402 | cFYI(1, "Kerberos only mechanism, enable extended security"); | 406 | cFYI(1, "Kerberos only mechanism, enable extended security"); |
403 | pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; | 407 | pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; |
404 | } | 408 | } else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP) |
405 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
406 | else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP) | ||
407 | pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; | 409 | pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; |
408 | else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) { | 410 | else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) { |
409 | cFYI(1, "NTLMSSP only mechanism, enable extended security"); | 411 | cFYI(1, "NTLMSSP only mechanism, enable extended security"); |
410 | pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; | 412 | pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; |
411 | } | 413 | } |
412 | #endif | ||
413 | 414 | ||
414 | count = 0; | 415 | count = 0; |
415 | for (i = 0; i < CIFS_NUM_PROT; i++) { | 416 | for (i = 0; i < CIFS_NUM_PROT; i++) { |
@@ -417,7 +418,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
417 | count += strlen(protocols[i].name) + 1; | 418 | count += strlen(protocols[i].name) + 1; |
418 | /* null at end of source and target buffers anyway */ | 419 | /* null at end of source and target buffers anyway */ |
419 | } | 420 | } |
420 | pSMB->hdr.smb_buf_length += count; | 421 | inc_rfc1001_len(pSMB, count); |
421 | pSMB->ByteCount = cpu_to_le16(count); | 422 | pSMB->ByteCount = cpu_to_le16(count); |
422 | 423 | ||
423 | rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB, | 424 | rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB, |
@@ -450,12 +451,11 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
450 | rc = -EOPNOTSUPP; | 451 | rc = -EOPNOTSUPP; |
451 | goto neg_err_exit; | 452 | goto neg_err_exit; |
452 | } | 453 | } |
453 | server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode); | 454 | server->sec_mode = (__u8)le16_to_cpu(rsp->SecurityMode); |
454 | server->maxReq = le16_to_cpu(rsp->MaxMpxCount); | 455 | server->maxReq = le16_to_cpu(rsp->MaxMpxCount); |
455 | server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize), | 456 | server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize), |
456 | (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); | 457 | (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); |
457 | server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs); | 458 | server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs); |
458 | GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey); | ||
459 | /* even though we do not use raw we might as well set this | 459 | /* even though we do not use raw we might as well set this |
460 | accurately, in case we ever find a need for it */ | 460 | accurately, in case we ever find a need for it */ |
461 | if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) { | 461 | if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) { |
@@ -503,9 +503,9 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
503 | 503 | ||
504 | if (rsp->EncryptionKeyLength == | 504 | if (rsp->EncryptionKeyLength == |
505 | cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) { | 505 | cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) { |
506 | memcpy(server->cryptKey, rsp->EncryptionKey, | 506 | memcpy(ses->server->cryptkey, rsp->EncryptionKey, |
507 | CIFS_CRYPTO_KEY_SIZE); | 507 | CIFS_CRYPTO_KEY_SIZE); |
508 | } else if (server->secMode & SECMODE_PW_ENCRYPT) { | 508 | } else if (server->sec_mode & SECMODE_PW_ENCRYPT) { |
509 | rc = -EIO; /* need cryptkey unless plain text */ | 509 | rc = -EIO; /* need cryptkey unless plain text */ |
510 | goto neg_err_exit; | 510 | goto neg_err_exit; |
511 | } | 511 | } |
@@ -527,11 +527,11 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
527 | goto neg_err_exit; | 527 | goto neg_err_exit; |
528 | } | 528 | } |
529 | /* else wct == 17 NTLM */ | 529 | /* else wct == 17 NTLM */ |
530 | server->secMode = pSMBr->SecurityMode; | 530 | server->sec_mode = pSMBr->SecurityMode; |
531 | if ((server->secMode & SECMODE_USER) == 0) | 531 | if ((server->sec_mode & SECMODE_USER) == 0) |
532 | cFYI(1, "share mode security"); | 532 | cFYI(1, "share mode security"); |
533 | 533 | ||
534 | if ((server->secMode & SECMODE_PW_ENCRYPT) == 0) | 534 | if ((server->sec_mode & SECMODE_PW_ENCRYPT) == 0) |
535 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | 535 | #ifdef CONFIG_CIFS_WEAK_PW_HASH |
536 | if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0) | 536 | if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0) |
537 | #endif /* CIFS_WEAK_PW_HASH */ | 537 | #endif /* CIFS_WEAK_PW_HASH */ |
@@ -550,10 +550,6 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
550 | server->secType = RawNTLMSSP; | 550 | server->secType = RawNTLMSSP; |
551 | else if (secFlags & CIFSSEC_MAY_LANMAN) | 551 | else if (secFlags & CIFSSEC_MAY_LANMAN) |
552 | server->secType = LANMAN; | 552 | server->secType = LANMAN; |
553 | /* #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
554 | else if (secFlags & CIFSSEC_MAY_PLNTXT) | ||
555 | server->secType = ?? | ||
556 | #endif */ | ||
557 | else { | 553 | else { |
558 | rc = -EOPNOTSUPP; | 554 | rc = -EOPNOTSUPP; |
559 | cERROR(1, "Invalid security type"); | 555 | cERROR(1, "Invalid security type"); |
@@ -569,33 +565,24 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
569 | (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); | 565 | (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); |
570 | server->max_rw = le32_to_cpu(pSMBr->MaxRawSize); | 566 | server->max_rw = le32_to_cpu(pSMBr->MaxRawSize); |
571 | cFYI(DBG2, "Max buf = %d", ses->server->maxBuf); | 567 | cFYI(DBG2, "Max buf = %d", ses->server->maxBuf); |
572 | GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey); | ||
573 | server->capabilities = le32_to_cpu(pSMBr->Capabilities); | 568 | server->capabilities = le32_to_cpu(pSMBr->Capabilities); |
574 | server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone); | 569 | server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone); |
575 | server->timeAdj *= 60; | 570 | server->timeAdj *= 60; |
576 | if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) { | 571 | if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) { |
577 | memcpy(server->cryptKey, pSMBr->u.EncryptionKey, | 572 | memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey, |
578 | CIFS_CRYPTO_KEY_SIZE); | 573 | CIFS_CRYPTO_KEY_SIZE); |
579 | } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) | 574 | } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC || |
580 | && (pSMBr->EncryptionKeyLength == 0)) { | 575 | server->capabilities & CAP_EXTENDED_SECURITY) && |
576 | (pSMBr->EncryptionKeyLength == 0)) { | ||
581 | /* decode security blob */ | 577 | /* decode security blob */ |
582 | } else if (server->secMode & SECMODE_PW_ENCRYPT) { | 578 | count = get_bcc(&pSMBr->hdr); |
583 | rc = -EIO; /* no crypt key only if plain text pwd */ | ||
584 | goto neg_err_exit; | ||
585 | } | ||
586 | |||
587 | /* BB might be helpful to save off the domain of server here */ | ||
588 | |||
589 | if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) && | ||
590 | (server->capabilities & CAP_EXTENDED_SECURITY)) { | ||
591 | count = pSMBr->ByteCount; | ||
592 | if (count < 16) { | 579 | if (count < 16) { |
593 | rc = -EIO; | 580 | rc = -EIO; |
594 | goto neg_err_exit; | 581 | goto neg_err_exit; |
595 | } | 582 | } |
596 | read_lock(&cifs_tcp_ses_lock); | 583 | spin_lock(&cifs_tcp_ses_lock); |
597 | if (server->srv_count > 1) { | 584 | if (server->srv_count > 1) { |
598 | read_unlock(&cifs_tcp_ses_lock); | 585 | spin_unlock(&cifs_tcp_ses_lock); |
599 | if (memcmp(server->server_GUID, | 586 | if (memcmp(server->server_GUID, |
600 | pSMBr->u.extended_response. | 587 | pSMBr->u.extended_response. |
601 | GUID, 16) != 0) { | 588 | GUID, 16) != 0) { |
@@ -605,7 +592,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
605 | 16); | 592 | 16); |
606 | } | 593 | } |
607 | } else { | 594 | } else { |
608 | read_unlock(&cifs_tcp_ses_lock); | 595 | spin_unlock(&cifs_tcp_ses_lock); |
609 | memcpy(server->server_GUID, | 596 | memcpy(server->server_GUID, |
610 | pSMBr->u.extended_response.GUID, 16); | 597 | pSMBr->u.extended_response.GUID, 16); |
611 | } | 598 | } |
@@ -620,14 +607,19 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
620 | rc = 0; | 607 | rc = 0; |
621 | else | 608 | else |
622 | rc = -EINVAL; | 609 | rc = -EINVAL; |
623 | 610 | if (server->secType == Kerberos) { | |
624 | if (server->sec_kerberos || server->sec_mskerberos) | 611 | if (!server->sec_kerberos && |
625 | server->secType = Kerberos; | 612 | !server->sec_mskerberos) |
626 | else if (server->sec_ntlmssp) | 613 | rc = -EOPNOTSUPP; |
627 | server->secType = RawNTLMSSP; | 614 | } else if (server->secType == RawNTLMSSP) { |
628 | else | 615 | if (!server->sec_ntlmssp) |
629 | rc = -EOPNOTSUPP; | 616 | rc = -EOPNOTSUPP; |
617 | } else | ||
618 | rc = -EOPNOTSUPP; | ||
630 | } | 619 | } |
620 | } else if (server->sec_mode & SECMODE_PW_ENCRYPT) { | ||
621 | rc = -EIO; /* no crypt key only if plain text pwd */ | ||
622 | goto neg_err_exit; | ||
631 | } else | 623 | } else |
632 | server->capabilities &= ~CAP_EXTENDED_SECURITY; | 624 | server->capabilities &= ~CAP_EXTENDED_SECURITY; |
633 | 625 | ||
@@ -638,27 +630,27 @@ signing_check: | |||
638 | /* MUST_SIGN already includes the MAY_SIGN FLAG | 630 | /* MUST_SIGN already includes the MAY_SIGN FLAG |
639 | so if this is zero it means that signing is disabled */ | 631 | so if this is zero it means that signing is disabled */ |
640 | cFYI(1, "Signing disabled"); | 632 | cFYI(1, "Signing disabled"); |
641 | if (server->secMode & SECMODE_SIGN_REQUIRED) { | 633 | if (server->sec_mode & SECMODE_SIGN_REQUIRED) { |
642 | cERROR(1, "Server requires " | 634 | cERROR(1, "Server requires " |
643 | "packet signing to be enabled in " | 635 | "packet signing to be enabled in " |
644 | "/proc/fs/cifs/SecurityFlags."); | 636 | "/proc/fs/cifs/SecurityFlags."); |
645 | rc = -EOPNOTSUPP; | 637 | rc = -EOPNOTSUPP; |
646 | } | 638 | } |
647 | server->secMode &= | 639 | server->sec_mode &= |
648 | ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED); | 640 | ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED); |
649 | } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) { | 641 | } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) { |
650 | /* signing required */ | 642 | /* signing required */ |
651 | cFYI(1, "Must sign - secFlags 0x%x", secFlags); | 643 | cFYI(1, "Must sign - secFlags 0x%x", secFlags); |
652 | if ((server->secMode & | 644 | if ((server->sec_mode & |
653 | (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) { | 645 | (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) { |
654 | cERROR(1, "signing required but server lacks support"); | 646 | cERROR(1, "signing required but server lacks support"); |
655 | rc = -EOPNOTSUPP; | 647 | rc = -EOPNOTSUPP; |
656 | } else | 648 | } else |
657 | server->secMode |= SECMODE_SIGN_REQUIRED; | 649 | server->sec_mode |= SECMODE_SIGN_REQUIRED; |
658 | } else { | 650 | } else { |
659 | /* signing optional ie CIFSSEC_MAY_SIGN */ | 651 | /* signing optional ie CIFSSEC_MAY_SIGN */ |
660 | if ((server->secMode & SECMODE_SIGN_REQUIRED) == 0) | 652 | if ((server->sec_mode & SECMODE_SIGN_REQUIRED) == 0) |
661 | server->secMode &= | 653 | server->sec_mode &= |
662 | ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED); | 654 | ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED); |
663 | } | 655 | } |
664 | 656 | ||
@@ -670,7 +662,7 @@ neg_err_exit: | |||
670 | } | 662 | } |
671 | 663 | ||
672 | int | 664 | int |
673 | CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon) | 665 | CIFSSMBTDis(const int xid, struct cifs_tcon *tcon) |
674 | { | 666 | { |
675 | struct smb_hdr *smb_buffer; | 667 | struct smb_hdr *smb_buffer; |
676 | int rc = 0; | 668 | int rc = 0; |
@@ -707,8 +699,57 @@ CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon) | |||
707 | return rc; | 699 | return rc; |
708 | } | 700 | } |
709 | 701 | ||
702 | /* | ||
703 | * This is a no-op for now. We're not really interested in the reply, but | ||
704 | * rather in the fact that the server sent one and that server->lstrp | ||
705 | * gets updated. | ||
706 | * | ||
707 | * FIXME: maybe we should consider checking that the reply matches request? | ||
708 | */ | ||
709 | static void | ||
710 | cifs_echo_callback(struct mid_q_entry *mid) | ||
711 | { | ||
712 | struct TCP_Server_Info *server = mid->callback_data; | ||
713 | |||
714 | DeleteMidQEntry(mid); | ||
715 | atomic_dec(&server->inFlight); | ||
716 | wake_up(&server->request_q); | ||
717 | } | ||
718 | |||
719 | int | ||
720 | CIFSSMBEcho(struct TCP_Server_Info *server) | ||
721 | { | ||
722 | ECHO_REQ *smb; | ||
723 | int rc = 0; | ||
724 | struct kvec iov; | ||
725 | |||
726 | cFYI(1, "In echo request"); | ||
727 | |||
728 | rc = small_smb_init(SMB_COM_ECHO, 0, NULL, (void **)&smb); | ||
729 | if (rc) | ||
730 | return rc; | ||
731 | |||
732 | /* set up echo request */ | ||
733 | smb->hdr.Tid = 0xffff; | ||
734 | smb->hdr.WordCount = 1; | ||
735 | put_unaligned_le16(1, &smb->EchoCount); | ||
736 | put_bcc(1, &smb->hdr); | ||
737 | smb->Data[0] = 'a'; | ||
738 | inc_rfc1001_len(smb, 3); | ||
739 | iov.iov_base = smb; | ||
740 | iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4; | ||
741 | |||
742 | rc = cifs_call_async(server, &iov, 1, cifs_echo_callback, server, true); | ||
743 | if (rc) | ||
744 | cFYI(1, "Echo request failed: %d", rc); | ||
745 | |||
746 | cifs_small_buf_release(smb); | ||
747 | |||
748 | return rc; | ||
749 | } | ||
750 | |||
710 | int | 751 | int |
711 | CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses) | 752 | CIFSSMBLogoff(const int xid, struct cifs_ses *ses) |
712 | { | 753 | { |
713 | LOGOFF_ANDX_REQ *pSMB; | 754 | LOGOFF_ANDX_REQ *pSMB; |
714 | int rc = 0; | 755 | int rc = 0; |
@@ -735,7 +776,7 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses) | |||
735 | 776 | ||
736 | pSMB->hdr.Mid = GetNextMid(ses->server); | 777 | pSMB->hdr.Mid = GetNextMid(ses->server); |
737 | 778 | ||
738 | if (ses->server->secMode & | 779 | if (ses->server->sec_mode & |
739 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) | 780 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) |
740 | pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE; | 781 | pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE; |
741 | 782 | ||
@@ -755,7 +796,7 @@ session_already_dead: | |||
755 | } | 796 | } |
756 | 797 | ||
757 | int | 798 | int |
758 | CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName, | 799 | CIFSPOSIXDelFile(const int xid, struct cifs_tcon *tcon, const char *fileName, |
759 | __u16 type, const struct nls_table *nls_codepage, int remap) | 800 | __u16 type, const struct nls_table *nls_codepage, int remap) |
760 | { | 801 | { |
761 | TRANSACTION2_SPI_REQ *pSMB = NULL; | 802 | TRANSACTION2_SPI_REQ *pSMB = NULL; |
@@ -813,7 +854,7 @@ PsxDelete: | |||
813 | pSMB->TotalParameterCount = pSMB->ParameterCount; | 854 | pSMB->TotalParameterCount = pSMB->ParameterCount; |
814 | pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK); | 855 | pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK); |
815 | pSMB->Reserved4 = 0; | 856 | pSMB->Reserved4 = 0; |
816 | pSMB->hdr.smb_buf_length += byte_count; | 857 | inc_rfc1001_len(pSMB, byte_count); |
817 | pSMB->ByteCount = cpu_to_le16(byte_count); | 858 | pSMB->ByteCount = cpu_to_le16(byte_count); |
818 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 859 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
819 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 860 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -830,7 +871,7 @@ PsxDelete: | |||
830 | } | 871 | } |
831 | 872 | ||
832 | int | 873 | int |
833 | CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName, | 874 | CIFSSMBDelFile(const int xid, struct cifs_tcon *tcon, const char *fileName, |
834 | const struct nls_table *nls_codepage, int remap) | 875 | const struct nls_table *nls_codepage, int remap) |
835 | { | 876 | { |
836 | DELETE_FILE_REQ *pSMB = NULL; | 877 | DELETE_FILE_REQ *pSMB = NULL; |
@@ -859,7 +900,7 @@ DelFileRetry: | |||
859 | pSMB->SearchAttributes = | 900 | pSMB->SearchAttributes = |
860 | cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM); | 901 | cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM); |
861 | pSMB->BufferFormat = 0x04; | 902 | pSMB->BufferFormat = 0x04; |
862 | pSMB->hdr.smb_buf_length += name_len + 1; | 903 | inc_rfc1001_len(pSMB, name_len + 1); |
863 | pSMB->ByteCount = cpu_to_le16(name_len + 1); | 904 | pSMB->ByteCount = cpu_to_le16(name_len + 1); |
864 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 905 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
865 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 906 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -875,7 +916,7 @@ DelFileRetry: | |||
875 | } | 916 | } |
876 | 917 | ||
877 | int | 918 | int |
878 | CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName, | 919 | CIFSSMBRmDir(const int xid, struct cifs_tcon *tcon, const char *dirName, |
879 | const struct nls_table *nls_codepage, int remap) | 920 | const struct nls_table *nls_codepage, int remap) |
880 | { | 921 | { |
881 | DELETE_DIRECTORY_REQ *pSMB = NULL; | 922 | DELETE_DIRECTORY_REQ *pSMB = NULL; |
@@ -903,7 +944,7 @@ RmDirRetry: | |||
903 | } | 944 | } |
904 | 945 | ||
905 | pSMB->BufferFormat = 0x04; | 946 | pSMB->BufferFormat = 0x04; |
906 | pSMB->hdr.smb_buf_length += name_len + 1; | 947 | inc_rfc1001_len(pSMB, name_len + 1); |
907 | pSMB->ByteCount = cpu_to_le16(name_len + 1); | 948 | pSMB->ByteCount = cpu_to_le16(name_len + 1); |
908 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 949 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
909 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 950 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -918,7 +959,7 @@ RmDirRetry: | |||
918 | } | 959 | } |
919 | 960 | ||
920 | int | 961 | int |
921 | CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon, | 962 | CIFSSMBMkDir(const int xid, struct cifs_tcon *tcon, |
922 | const char *name, const struct nls_table *nls_codepage, int remap) | 963 | const char *name, const struct nls_table *nls_codepage, int remap) |
923 | { | 964 | { |
924 | int rc = 0; | 965 | int rc = 0; |
@@ -946,7 +987,7 @@ MkDirRetry: | |||
946 | } | 987 | } |
947 | 988 | ||
948 | pSMB->BufferFormat = 0x04; | 989 | pSMB->BufferFormat = 0x04; |
949 | pSMB->hdr.smb_buf_length += name_len + 1; | 990 | inc_rfc1001_len(pSMB, name_len + 1); |
950 | pSMB->ByteCount = cpu_to_le16(name_len + 1); | 991 | pSMB->ByteCount = cpu_to_le16(name_len + 1); |
951 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 992 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
952 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 993 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -961,7 +1002,7 @@ MkDirRetry: | |||
961 | } | 1002 | } |
962 | 1003 | ||
963 | int | 1004 | int |
964 | CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags, | 1005 | CIFSPOSIXCreate(const int xid, struct cifs_tcon *tcon, __u32 posix_flags, |
965 | __u64 mode, __u16 *netfid, FILE_UNIX_BASIC_INFO *pRetData, | 1006 | __u64 mode, __u16 *netfid, FILE_UNIX_BASIC_INFO *pRetData, |
966 | __u32 *pOplock, const char *name, | 1007 | __u32 *pOplock, const char *name, |
967 | const struct nls_table *nls_codepage, int remap) | 1008 | const struct nls_table *nls_codepage, int remap) |
@@ -1024,7 +1065,7 @@ PsxCreat: | |||
1024 | pSMB->TotalParameterCount = pSMB->ParameterCount; | 1065 | pSMB->TotalParameterCount = pSMB->ParameterCount; |
1025 | pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN); | 1066 | pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN); |
1026 | pSMB->Reserved4 = 0; | 1067 | pSMB->Reserved4 = 0; |
1027 | pSMB->hdr.smb_buf_length += byte_count; | 1068 | inc_rfc1001_len(pSMB, byte_count); |
1028 | pSMB->ByteCount = cpu_to_le16(byte_count); | 1069 | pSMB->ByteCount = cpu_to_le16(byte_count); |
1029 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1070 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
1030 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 1071 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -1036,7 +1077,7 @@ PsxCreat: | |||
1036 | cFYI(1, "copying inode info"); | 1077 | cFYI(1, "copying inode info"); |
1037 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 1078 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
1038 | 1079 | ||
1039 | if (rc || (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP))) { | 1080 | if (rc || get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)) { |
1040 | rc = -EIO; /* bad smb */ | 1081 | rc = -EIO; /* bad smb */ |
1041 | goto psx_create_err; | 1082 | goto psx_create_err; |
1042 | } | 1083 | } |
@@ -1057,7 +1098,7 @@ PsxCreat: | |||
1057 | pRetData->Type = cpu_to_le32(-1); /* unknown */ | 1098 | pRetData->Type = cpu_to_le32(-1); /* unknown */ |
1058 | cFYI(DBG2, "unknown type"); | 1099 | cFYI(DBG2, "unknown type"); |
1059 | } else { | 1100 | } else { |
1060 | if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP) | 1101 | if (get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP) |
1061 | + sizeof(FILE_UNIX_BASIC_INFO)) { | 1102 | + sizeof(FILE_UNIX_BASIC_INFO)) { |
1062 | cERROR(1, "Open response data too small"); | 1103 | cERROR(1, "Open response data too small"); |
1063 | pRetData->Type = cpu_to_le32(-1); | 1104 | pRetData->Type = cpu_to_le32(-1); |
@@ -1127,7 +1168,7 @@ access_flags_to_smbopen_mode(const int access_flags) | |||
1127 | } | 1168 | } |
1128 | 1169 | ||
1129 | int | 1170 | int |
1130 | SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon, | 1171 | SMBLegacyOpen(const int xid, struct cifs_tcon *tcon, |
1131 | const char *fileName, const int openDisposition, | 1172 | const char *fileName, const int openDisposition, |
1132 | const int access_flags, const int create_options, __u16 *netfid, | 1173 | const int access_flags, const int create_options, __u16 *netfid, |
1133 | int *pOplock, FILE_ALL_INFO *pfile_info, | 1174 | int *pOplock, FILE_ALL_INFO *pfile_info, |
@@ -1189,12 +1230,12 @@ OldOpenRetry: | |||
1189 | pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY); | 1230 | pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY); |
1190 | pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition)); | 1231 | pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition)); |
1191 | count += name_len; | 1232 | count += name_len; |
1192 | pSMB->hdr.smb_buf_length += count; | 1233 | inc_rfc1001_len(pSMB, count); |
1193 | 1234 | ||
1194 | pSMB->ByteCount = cpu_to_le16(count); | 1235 | pSMB->ByteCount = cpu_to_le16(count); |
1195 | /* long_op set to 1 to allow for oplock break timeouts */ | 1236 | /* long_op set to 1 to allow for oplock break timeouts */ |
1196 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1237 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
1197 | (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP); | 1238 | (struct smb_hdr *)pSMBr, &bytes_returned, 0); |
1198 | cifs_stats_inc(&tcon->num_opens); | 1239 | cifs_stats_inc(&tcon->num_opens); |
1199 | if (rc) { | 1240 | if (rc) { |
1200 | cFYI(1, "Error in Open = %d", rc); | 1241 | cFYI(1, "Error in Open = %d", rc); |
@@ -1234,7 +1275,7 @@ OldOpenRetry: | |||
1234 | } | 1275 | } |
1235 | 1276 | ||
1236 | int | 1277 | int |
1237 | CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon, | 1278 | CIFSSMBOpen(const int xid, struct cifs_tcon *tcon, |
1238 | const char *fileName, const int openDisposition, | 1279 | const char *fileName, const int openDisposition, |
1239 | const int access_flags, const int create_options, __u16 *netfid, | 1280 | const int access_flags, const int create_options, __u16 *netfid, |
1240 | int *pOplock, FILE_ALL_INFO *pfile_info, | 1281 | int *pOplock, FILE_ALL_INFO *pfile_info, |
@@ -1302,12 +1343,12 @@ openRetry: | |||
1302 | SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY; | 1343 | SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY; |
1303 | 1344 | ||
1304 | count += name_len; | 1345 | count += name_len; |
1305 | pSMB->hdr.smb_buf_length += count; | 1346 | inc_rfc1001_len(pSMB, count); |
1306 | 1347 | ||
1307 | pSMB->ByteCount = cpu_to_le16(count); | 1348 | pSMB->ByteCount = cpu_to_le16(count); |
1308 | /* long_op set to 1 to allow for oplock break timeouts */ | 1349 | /* long_op set to 1 to allow for oplock break timeouts */ |
1309 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1350 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
1310 | (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP); | 1351 | (struct smb_hdr *)pSMBr, &bytes_returned, 0); |
1311 | cifs_stats_inc(&tcon->num_opens); | 1352 | cifs_stats_inc(&tcon->num_opens); |
1312 | if (rc) { | 1353 | if (rc) { |
1313 | cFYI(1, "Error in Open = %d", rc); | 1354 | cFYI(1, "Error in Open = %d", rc); |
@@ -1336,8 +1377,7 @@ openRetry: | |||
1336 | } | 1377 | } |
1337 | 1378 | ||
1338 | int | 1379 | int |
1339 | CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid, | 1380 | CIFSSMBRead(const int xid, struct cifs_io_parms *io_parms, unsigned int *nbytes, |
1340 | const unsigned int count, const __u64 lseek, unsigned int *nbytes, | ||
1341 | char **buf, int *pbuf_type) | 1381 | char **buf, int *pbuf_type) |
1342 | { | 1382 | { |
1343 | int rc = -EACCES; | 1383 | int rc = -EACCES; |
@@ -1347,13 +1387,18 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid, | |||
1347 | int wct; | 1387 | int wct; |
1348 | int resp_buf_type = 0; | 1388 | int resp_buf_type = 0; |
1349 | struct kvec iov[1]; | 1389 | struct kvec iov[1]; |
1390 | __u32 pid = io_parms->pid; | ||
1391 | __u16 netfid = io_parms->netfid; | ||
1392 | __u64 offset = io_parms->offset; | ||
1393 | struct cifs_tcon *tcon = io_parms->tcon; | ||
1394 | unsigned int count = io_parms->length; | ||
1350 | 1395 | ||
1351 | cFYI(1, "Reading %d bytes on fid %d", count, netfid); | 1396 | cFYI(1, "Reading %d bytes on fid %d", count, netfid); |
1352 | if (tcon->ses->capabilities & CAP_LARGE_FILES) | 1397 | if (tcon->ses->capabilities & CAP_LARGE_FILES) |
1353 | wct = 12; | 1398 | wct = 12; |
1354 | else { | 1399 | else { |
1355 | wct = 10; /* old style read */ | 1400 | wct = 10; /* old style read */ |
1356 | if ((lseek >> 32) > 0) { | 1401 | if ((offset >> 32) > 0) { |
1357 | /* can not handle this big offset for old */ | 1402 | /* can not handle this big offset for old */ |
1358 | return -EIO; | 1403 | return -EIO; |
1359 | } | 1404 | } |
@@ -1364,15 +1409,18 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid, | |||
1364 | if (rc) | 1409 | if (rc) |
1365 | return rc; | 1410 | return rc; |
1366 | 1411 | ||
1412 | pSMB->hdr.Pid = cpu_to_le16((__u16)pid); | ||
1413 | pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16)); | ||
1414 | |||
1367 | /* tcon and ses pointer are checked in smb_init */ | 1415 | /* tcon and ses pointer are checked in smb_init */ |
1368 | if (tcon->ses->server == NULL) | 1416 | if (tcon->ses->server == NULL) |
1369 | return -ECONNABORTED; | 1417 | return -ECONNABORTED; |
1370 | 1418 | ||
1371 | pSMB->AndXCommand = 0xFF; /* none */ | 1419 | pSMB->AndXCommand = 0xFF; /* none */ |
1372 | pSMB->Fid = netfid; | 1420 | pSMB->Fid = netfid; |
1373 | pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF); | 1421 | pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF); |
1374 | if (wct == 12) | 1422 | if (wct == 12) |
1375 | pSMB->OffsetHigh = cpu_to_le32(lseek >> 32); | 1423 | pSMB->OffsetHigh = cpu_to_le32(offset >> 32); |
1376 | 1424 | ||
1377 | pSMB->Remaining = 0; | 1425 | pSMB->Remaining = 0; |
1378 | pSMB->MaxCount = cpu_to_le16(count & 0xFFFF); | 1426 | pSMB->MaxCount = cpu_to_le16(count & 0xFFFF); |
@@ -1387,9 +1435,9 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid, | |||
1387 | } | 1435 | } |
1388 | 1436 | ||
1389 | iov[0].iov_base = (char *)pSMB; | 1437 | iov[0].iov_base = (char *)pSMB; |
1390 | iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; | 1438 | iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4; |
1391 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */, | 1439 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */, |
1392 | &resp_buf_type, CIFS_STD_OP | CIFS_LOG_ERROR); | 1440 | &resp_buf_type, CIFS_LOG_ERROR); |
1393 | cifs_stats_inc(&tcon->num_reads); | 1441 | cifs_stats_inc(&tcon->num_reads); |
1394 | pSMBr = (READ_RSP *)iov[0].iov_base; | 1442 | pSMBr = (READ_RSP *)iov[0].iov_base; |
1395 | if (rc) { | 1443 | if (rc) { |
@@ -1441,9 +1489,8 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid, | |||
1441 | 1489 | ||
1442 | 1490 | ||
1443 | int | 1491 | int |
1444 | CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, | 1492 | CIFSSMBWrite(const int xid, struct cifs_io_parms *io_parms, |
1445 | const int netfid, const unsigned int count, | 1493 | unsigned int *nbytes, const char *buf, |
1446 | const __u64 offset, unsigned int *nbytes, const char *buf, | ||
1447 | const char __user *ubuf, const int long_op) | 1494 | const char __user *ubuf, const int long_op) |
1448 | { | 1495 | { |
1449 | int rc = -EACCES; | 1496 | int rc = -EACCES; |
@@ -1452,6 +1499,11 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, | |||
1452 | int bytes_returned, wct; | 1499 | int bytes_returned, wct; |
1453 | __u32 bytes_sent; | 1500 | __u32 bytes_sent; |
1454 | __u16 byte_count; | 1501 | __u16 byte_count; |
1502 | __u32 pid = io_parms->pid; | ||
1503 | __u16 netfid = io_parms->netfid; | ||
1504 | __u64 offset = io_parms->offset; | ||
1505 | struct cifs_tcon *tcon = io_parms->tcon; | ||
1506 | unsigned int count = io_parms->length; | ||
1455 | 1507 | ||
1456 | *nbytes = 0; | 1508 | *nbytes = 0; |
1457 | 1509 | ||
@@ -1473,6 +1525,10 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, | |||
1473 | (void **) &pSMBr); | 1525 | (void **) &pSMBr); |
1474 | if (rc) | 1526 | if (rc) |
1475 | return rc; | 1527 | return rc; |
1528 | |||
1529 | pSMB->hdr.Pid = cpu_to_le16((__u16)pid); | ||
1530 | pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16)); | ||
1531 | |||
1476 | /* tcon and ses pointer are checked in smb_init */ | 1532 | /* tcon and ses pointer are checked in smb_init */ |
1477 | if (tcon->ses->server == NULL) | 1533 | if (tcon->ses->server == NULL) |
1478 | return -ECONNABORTED; | 1534 | return -ECONNABORTED; |
@@ -1521,7 +1577,7 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, | |||
1521 | 1577 | ||
1522 | pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF); | 1578 | pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF); |
1523 | pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16); | 1579 | pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16); |
1524 | pSMB->hdr.smb_buf_length += byte_count; | 1580 | inc_rfc1001_len(pSMB, byte_count); |
1525 | 1581 | ||
1526 | if (wct == 14) | 1582 | if (wct == 14) |
1527 | pSMB->ByteCount = cpu_to_le16(byte_count); | 1583 | pSMB->ByteCount = cpu_to_le16(byte_count); |
@@ -1559,17 +1615,259 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, | |||
1559 | return rc; | 1615 | return rc; |
1560 | } | 1616 | } |
1561 | 1617 | ||
1618 | void | ||
1619 | cifs_writedata_release(struct kref *refcount) | ||
1620 | { | ||
1621 | struct cifs_writedata *wdata = container_of(refcount, | ||
1622 | struct cifs_writedata, refcount); | ||
1623 | |||
1624 | if (wdata->cfile) | ||
1625 | cifsFileInfo_put(wdata->cfile); | ||
1626 | |||
1627 | kfree(wdata); | ||
1628 | } | ||
1629 | |||
1630 | /* | ||
1631 | * Write failed with a retryable error. Resend the write request. It's also | ||
1632 | * possible that the page was redirtied so re-clean the page. | ||
1633 | */ | ||
1634 | static void | ||
1635 | cifs_writev_requeue(struct cifs_writedata *wdata) | ||
1636 | { | ||
1637 | int i, rc; | ||
1638 | struct inode *inode = wdata->cfile->dentry->d_inode; | ||
1639 | |||
1640 | for (i = 0; i < wdata->nr_pages; i++) { | ||
1641 | lock_page(wdata->pages[i]); | ||
1642 | clear_page_dirty_for_io(wdata->pages[i]); | ||
1643 | } | ||
1644 | |||
1645 | do { | ||
1646 | rc = cifs_async_writev(wdata); | ||
1647 | } while (rc == -EAGAIN); | ||
1648 | |||
1649 | for (i = 0; i < wdata->nr_pages; i++) { | ||
1650 | if (rc != 0) | ||
1651 | SetPageError(wdata->pages[i]); | ||
1652 | unlock_page(wdata->pages[i]); | ||
1653 | } | ||
1654 | |||
1655 | mapping_set_error(inode->i_mapping, rc); | ||
1656 | kref_put(&wdata->refcount, cifs_writedata_release); | ||
1657 | } | ||
1658 | |||
1659 | static void | ||
1660 | cifs_writev_complete(struct work_struct *work) | ||
1661 | { | ||
1662 | struct cifs_writedata *wdata = container_of(work, | ||
1663 | struct cifs_writedata, work); | ||
1664 | struct inode *inode = wdata->cfile->dentry->d_inode; | ||
1665 | int i = 0; | ||
1666 | |||
1667 | if (wdata->result == 0) { | ||
1668 | cifs_update_eof(CIFS_I(inode), wdata->offset, wdata->bytes); | ||
1669 | cifs_stats_bytes_written(tlink_tcon(wdata->cfile->tlink), | ||
1670 | wdata->bytes); | ||
1671 | } else if (wdata->sync_mode == WB_SYNC_ALL && wdata->result == -EAGAIN) | ||
1672 | return cifs_writev_requeue(wdata); | ||
1673 | |||
1674 | for (i = 0; i < wdata->nr_pages; i++) { | ||
1675 | struct page *page = wdata->pages[i]; | ||
1676 | if (wdata->result == -EAGAIN) | ||
1677 | __set_page_dirty_nobuffers(page); | ||
1678 | else if (wdata->result < 0) | ||
1679 | SetPageError(page); | ||
1680 | end_page_writeback(page); | ||
1681 | page_cache_release(page); | ||
1682 | } | ||
1683 | if (wdata->result != -EAGAIN) | ||
1684 | mapping_set_error(inode->i_mapping, wdata->result); | ||
1685 | kref_put(&wdata->refcount, cifs_writedata_release); | ||
1686 | } | ||
1687 | |||
1688 | struct cifs_writedata * | ||
1689 | cifs_writedata_alloc(unsigned int nr_pages) | ||
1690 | { | ||
1691 | struct cifs_writedata *wdata; | ||
1692 | |||
1693 | /* this would overflow */ | ||
1694 | if (nr_pages == 0) { | ||
1695 | cERROR(1, "%s: called with nr_pages == 0!", __func__); | ||
1696 | return NULL; | ||
1697 | } | ||
1698 | |||
1699 | /* writedata + number of page pointers */ | ||
1700 | wdata = kzalloc(sizeof(*wdata) + | ||
1701 | sizeof(struct page *) * (nr_pages - 1), GFP_NOFS); | ||
1702 | if (wdata != NULL) { | ||
1703 | INIT_WORK(&wdata->work, cifs_writev_complete); | ||
1704 | kref_init(&wdata->refcount); | ||
1705 | } | ||
1706 | return wdata; | ||
1707 | } | ||
1708 | |||
1709 | /* | ||
1710 | * Check the midState and signature on received buffer (if any), and queue the | ||
1711 | * workqueue completion task. | ||
1712 | */ | ||
1713 | static void | ||
1714 | cifs_writev_callback(struct mid_q_entry *mid) | ||
1715 | { | ||
1716 | struct cifs_writedata *wdata = mid->callback_data; | ||
1717 | struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink); | ||
1718 | unsigned int written; | ||
1719 | WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf; | ||
1720 | |||
1721 | switch (mid->midState) { | ||
1722 | case MID_RESPONSE_RECEIVED: | ||
1723 | wdata->result = cifs_check_receive(mid, tcon->ses->server, 0); | ||
1724 | if (wdata->result != 0) | ||
1725 | break; | ||
1726 | |||
1727 | written = le16_to_cpu(smb->CountHigh); | ||
1728 | written <<= 16; | ||
1729 | written += le16_to_cpu(smb->Count); | ||
1730 | /* | ||
1731 | * Mask off high 16 bits when bytes written as returned | ||
1732 | * by the server is greater than bytes requested by the | ||
1733 | * client. OS/2 servers are known to set incorrect | ||
1734 | * CountHigh values. | ||
1735 | */ | ||
1736 | if (written > wdata->bytes) | ||
1737 | written &= 0xFFFF; | ||
1738 | |||
1739 | if (written < wdata->bytes) | ||
1740 | wdata->result = -ENOSPC; | ||
1741 | else | ||
1742 | wdata->bytes = written; | ||
1743 | break; | ||
1744 | case MID_REQUEST_SUBMITTED: | ||
1745 | case MID_RETRY_NEEDED: | ||
1746 | wdata->result = -EAGAIN; | ||
1747 | break; | ||
1748 | default: | ||
1749 | wdata->result = -EIO; | ||
1750 | break; | ||
1751 | } | ||
1752 | |||
1753 | queue_work(system_nrt_wq, &wdata->work); | ||
1754 | DeleteMidQEntry(mid); | ||
1755 | atomic_dec(&tcon->ses->server->inFlight); | ||
1756 | wake_up(&tcon->ses->server->request_q); | ||
1757 | } | ||
1758 | |||
1759 | /* cifs_async_writev - send an async write, and set up mid to handle result */ | ||
1760 | int | ||
1761 | cifs_async_writev(struct cifs_writedata *wdata) | ||
1762 | { | ||
1763 | int i, rc = -EACCES; | ||
1764 | WRITE_REQ *smb = NULL; | ||
1765 | int wct; | ||
1766 | struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink); | ||
1767 | struct inode *inode = wdata->cfile->dentry->d_inode; | ||
1768 | struct kvec *iov = NULL; | ||
1769 | |||
1770 | if (tcon->ses->capabilities & CAP_LARGE_FILES) { | ||
1771 | wct = 14; | ||
1772 | } else { | ||
1773 | wct = 12; | ||
1774 | if (wdata->offset >> 32 > 0) { | ||
1775 | /* can not handle big offset for old srv */ | ||
1776 | return -EIO; | ||
1777 | } | ||
1778 | } | ||
1779 | |||
1780 | rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **)&smb); | ||
1781 | if (rc) | ||
1782 | goto async_writev_out; | ||
1783 | |||
1784 | /* 1 iov per page + 1 for header */ | ||
1785 | iov = kzalloc((wdata->nr_pages + 1) * sizeof(*iov), GFP_NOFS); | ||
1786 | if (iov == NULL) { | ||
1787 | rc = -ENOMEM; | ||
1788 | goto async_writev_out; | ||
1789 | } | ||
1790 | |||
1791 | smb->hdr.Pid = cpu_to_le16((__u16)wdata->cfile->pid); | ||
1792 | smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->cfile->pid >> 16)); | ||
1793 | |||
1794 | smb->AndXCommand = 0xFF; /* none */ | ||
1795 | smb->Fid = wdata->cfile->netfid; | ||
1796 | smb->OffsetLow = cpu_to_le32(wdata->offset & 0xFFFFFFFF); | ||
1797 | if (wct == 14) | ||
1798 | smb->OffsetHigh = cpu_to_le32(wdata->offset >> 32); | ||
1799 | smb->Reserved = 0xFFFFFFFF; | ||
1800 | smb->WriteMode = 0; | ||
1801 | smb->Remaining = 0; | ||
1802 | |||
1803 | smb->DataOffset = | ||
1804 | cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4); | ||
1805 | |||
1806 | /* 4 for RFC1001 length + 1 for BCC */ | ||
1807 | iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1; | ||
1808 | iov[0].iov_base = smb; | ||
1809 | |||
1810 | /* marshal up the pages into iov array */ | ||
1811 | wdata->bytes = 0; | ||
1812 | for (i = 0; i < wdata->nr_pages; i++) { | ||
1813 | iov[i + 1].iov_len = min(inode->i_size - | ||
1814 | page_offset(wdata->pages[i]), | ||
1815 | (loff_t)PAGE_CACHE_SIZE); | ||
1816 | iov[i + 1].iov_base = kmap(wdata->pages[i]); | ||
1817 | wdata->bytes += iov[i + 1].iov_len; | ||
1818 | } | ||
1819 | |||
1820 | cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes); | ||
1821 | |||
1822 | smb->DataLengthLow = cpu_to_le16(wdata->bytes & 0xFFFF); | ||
1823 | smb->DataLengthHigh = cpu_to_le16(wdata->bytes >> 16); | ||
1824 | |||
1825 | if (wct == 14) { | ||
1826 | inc_rfc1001_len(&smb->hdr, wdata->bytes + 1); | ||
1827 | put_bcc(wdata->bytes + 1, &smb->hdr); | ||
1828 | } else { | ||
1829 | /* wct == 12 */ | ||
1830 | struct smb_com_writex_req *smbw = | ||
1831 | (struct smb_com_writex_req *)smb; | ||
1832 | inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5); | ||
1833 | put_bcc(wdata->bytes + 5, &smbw->hdr); | ||
1834 | iov[0].iov_len += 4; /* pad bigger by four bytes */ | ||
1835 | } | ||
1836 | |||
1837 | kref_get(&wdata->refcount); | ||
1838 | rc = cifs_call_async(tcon->ses->server, iov, wdata->nr_pages + 1, | ||
1839 | cifs_writev_callback, wdata, false); | ||
1840 | |||
1841 | if (rc == 0) | ||
1842 | cifs_stats_inc(&tcon->num_writes); | ||
1843 | else | ||
1844 | kref_put(&wdata->refcount, cifs_writedata_release); | ||
1845 | |||
1846 | /* send is done, unmap pages */ | ||
1847 | for (i = 0; i < wdata->nr_pages; i++) | ||
1848 | kunmap(wdata->pages[i]); | ||
1849 | |||
1850 | async_writev_out: | ||
1851 | cifs_small_buf_release(smb); | ||
1852 | kfree(iov); | ||
1853 | return rc; | ||
1854 | } | ||
1855 | |||
1562 | int | 1856 | int |
1563 | CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, | 1857 | CIFSSMBWrite2(const int xid, struct cifs_io_parms *io_parms, |
1564 | const int netfid, const unsigned int count, | 1858 | unsigned int *nbytes, struct kvec *iov, int n_vec, |
1565 | const __u64 offset, unsigned int *nbytes, struct kvec *iov, | 1859 | const int long_op) |
1566 | int n_vec, const int long_op) | ||
1567 | { | 1860 | { |
1568 | int rc = -EACCES; | 1861 | int rc = -EACCES; |
1569 | WRITE_REQ *pSMB = NULL; | 1862 | WRITE_REQ *pSMB = NULL; |
1570 | int wct; | 1863 | int wct; |
1571 | int smb_hdr_len; | 1864 | int smb_hdr_len; |
1572 | int resp_buf_type = 0; | 1865 | int resp_buf_type = 0; |
1866 | __u32 pid = io_parms->pid; | ||
1867 | __u16 netfid = io_parms->netfid; | ||
1868 | __u64 offset = io_parms->offset; | ||
1869 | struct cifs_tcon *tcon = io_parms->tcon; | ||
1870 | unsigned int count = io_parms->length; | ||
1573 | 1871 | ||
1574 | *nbytes = 0; | 1872 | *nbytes = 0; |
1575 | 1873 | ||
@@ -1587,6 +1885,10 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, | |||
1587 | rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB); | 1885 | rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB); |
1588 | if (rc) | 1886 | if (rc) |
1589 | return rc; | 1887 | return rc; |
1888 | |||
1889 | pSMB->hdr.Pid = cpu_to_le16((__u16)pid); | ||
1890 | pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16)); | ||
1891 | |||
1590 | /* tcon and ses pointer are checked in smb_init */ | 1892 | /* tcon and ses pointer are checked in smb_init */ |
1591 | if (tcon->ses->server == NULL) | 1893 | if (tcon->ses->server == NULL) |
1592 | return -ECONNABORTED; | 1894 | return -ECONNABORTED; |
@@ -1605,11 +1907,12 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, | |||
1605 | 1907 | ||
1606 | pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF); | 1908 | pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF); |
1607 | pSMB->DataLengthHigh = cpu_to_le16(count >> 16); | 1909 | pSMB->DataLengthHigh = cpu_to_le16(count >> 16); |
1608 | smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */ | 1910 | /* header + 1 byte pad */ |
1911 | smb_hdr_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 1; | ||
1609 | if (wct == 14) | 1912 | if (wct == 14) |
1610 | pSMB->hdr.smb_buf_length += count+1; | 1913 | inc_rfc1001_len(pSMB, count + 1); |
1611 | else /* wct == 12 */ | 1914 | else /* wct == 12 */ |
1612 | pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */ | 1915 | inc_rfc1001_len(pSMB, count + 5); /* smb data starts later */ |
1613 | if (wct == 14) | 1916 | if (wct == 14) |
1614 | pSMB->ByteCount = cpu_to_le16(count + 1); | 1917 | pSMB->ByteCount = cpu_to_le16(count + 1); |
1615 | else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ { | 1918 | else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ { |
@@ -1661,10 +1964,11 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, | |||
1661 | 1964 | ||
1662 | 1965 | ||
1663 | int | 1966 | int |
1664 | CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, | 1967 | CIFSSMBLock(const int xid, struct cifs_tcon *tcon, |
1665 | const __u16 smb_file_id, const __u64 len, | 1968 | const __u16 smb_file_id, const __u64 len, |
1666 | const __u64 offset, const __u32 numUnlock, | 1969 | const __u64 offset, const __u32 numUnlock, |
1667 | const __u32 numLock, const __u8 lockType, const bool waitFlag) | 1970 | const __u32 numLock, const __u8 lockType, |
1971 | const bool waitFlag, const __u8 oplock_level) | ||
1668 | { | 1972 | { |
1669 | int rc = 0; | 1973 | int rc = 0; |
1670 | LOCK_REQ *pSMB = NULL; | 1974 | LOCK_REQ *pSMB = NULL; |
@@ -1692,6 +1996,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, | |||
1692 | pSMB->NumberOfLocks = cpu_to_le16(numLock); | 1996 | pSMB->NumberOfLocks = cpu_to_le16(numLock); |
1693 | pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock); | 1997 | pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock); |
1694 | pSMB->LockType = lockType; | 1998 | pSMB->LockType = lockType; |
1999 | pSMB->OplockLevel = oplock_level; | ||
1695 | pSMB->AndXCommand = 0xFF; /* none */ | 2000 | pSMB->AndXCommand = 0xFF; /* none */ |
1696 | pSMB->Fid = smb_file_id; /* netfid stays le */ | 2001 | pSMB->Fid = smb_file_id; /* netfid stays le */ |
1697 | 2002 | ||
@@ -1707,7 +2012,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, | |||
1707 | /* oplock break */ | 2012 | /* oplock break */ |
1708 | count = 0; | 2013 | count = 0; |
1709 | } | 2014 | } |
1710 | pSMB->hdr.smb_buf_length += count; | 2015 | inc_rfc1001_len(pSMB, count); |
1711 | pSMB->ByteCount = cpu_to_le16(count); | 2016 | pSMB->ByteCount = cpu_to_le16(count); |
1712 | 2017 | ||
1713 | if (waitFlag) { | 2018 | if (waitFlag) { |
@@ -1729,7 +2034,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, | |||
1729 | } | 2034 | } |
1730 | 2035 | ||
1731 | int | 2036 | int |
1732 | CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, | 2037 | CIFSSMBPosixLock(const int xid, struct cifs_tcon *tcon, |
1733 | const __u16 smb_file_id, const int get_flag, const __u64 len, | 2038 | const __u16 smb_file_id, const int get_flag, const __u64 len, |
1734 | struct file_lock *pLockData, const __u16 lock_type, | 2039 | struct file_lock *pLockData, const __u16 lock_type, |
1735 | const bool waitFlag) | 2040 | const bool waitFlag) |
@@ -1798,14 +2103,14 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, | |||
1798 | pSMB->Fid = smb_file_id; | 2103 | pSMB->Fid = smb_file_id; |
1799 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK); | 2104 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK); |
1800 | pSMB->Reserved4 = 0; | 2105 | pSMB->Reserved4 = 0; |
1801 | pSMB->hdr.smb_buf_length += byte_count; | 2106 | inc_rfc1001_len(pSMB, byte_count); |
1802 | pSMB->ByteCount = cpu_to_le16(byte_count); | 2107 | pSMB->ByteCount = cpu_to_le16(byte_count); |
1803 | if (waitFlag) { | 2108 | if (waitFlag) { |
1804 | rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB, | 2109 | rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB, |
1805 | (struct smb_hdr *) pSMBr, &bytes_returned); | 2110 | (struct smb_hdr *) pSMBr, &bytes_returned); |
1806 | } else { | 2111 | } else { |
1807 | iov[0].iov_base = (char *)pSMB; | 2112 | iov[0].iov_base = (char *)pSMB; |
1808 | iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; | 2113 | iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4; |
1809 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */, | 2114 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */, |
1810 | &resp_buf_type, timeout); | 2115 | &resp_buf_type, timeout); |
1811 | pSMB = NULL; /* request buf already freed by SendReceive2. Do | 2116 | pSMB = NULL; /* request buf already freed by SendReceive2. Do |
@@ -1821,7 +2126,7 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, | |||
1821 | __u16 data_count; | 2126 | __u16 data_count; |
1822 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 2127 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
1823 | 2128 | ||
1824 | if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) { | 2129 | if (rc || get_bcc(&pSMBr->hdr) < sizeof(*parm_data)) { |
1825 | rc = -EIO; /* bad smb */ | 2130 | rc = -EIO; /* bad smb */ |
1826 | goto plk_err_exit; | 2131 | goto plk_err_exit; |
1827 | } | 2132 | } |
@@ -1843,10 +2148,10 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, | |||
1843 | __constant_cpu_to_le16(CIFS_WRLCK)) | 2148 | __constant_cpu_to_le16(CIFS_WRLCK)) |
1844 | pLockData->fl_type = F_WRLCK; | 2149 | pLockData->fl_type = F_WRLCK; |
1845 | 2150 | ||
1846 | pLockData->fl_start = parm_data->start; | 2151 | pLockData->fl_start = le64_to_cpu(parm_data->start); |
1847 | pLockData->fl_end = parm_data->start + | 2152 | pLockData->fl_end = pLockData->fl_start + |
1848 | parm_data->length - 1; | 2153 | le64_to_cpu(parm_data->length) - 1; |
1849 | pLockData->fl_pid = parm_data->pid; | 2154 | pLockData->fl_pid = le32_to_cpu(parm_data->pid); |
1850 | } | 2155 | } |
1851 | } | 2156 | } |
1852 | 2157 | ||
@@ -1867,7 +2172,7 @@ plk_err_exit: | |||
1867 | 2172 | ||
1868 | 2173 | ||
1869 | int | 2174 | int |
1870 | CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id) | 2175 | CIFSSMBClose(const int xid, struct cifs_tcon *tcon, int smb_file_id) |
1871 | { | 2176 | { |
1872 | int rc = 0; | 2177 | int rc = 0; |
1873 | CLOSE_REQ *pSMB = NULL; | 2178 | CLOSE_REQ *pSMB = NULL; |
@@ -1900,7 +2205,7 @@ CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id) | |||
1900 | } | 2205 | } |
1901 | 2206 | ||
1902 | int | 2207 | int |
1903 | CIFSSMBFlush(const int xid, struct cifsTconInfo *tcon, int smb_file_id) | 2208 | CIFSSMBFlush(const int xid, struct cifs_tcon *tcon, int smb_file_id) |
1904 | { | 2209 | { |
1905 | int rc = 0; | 2210 | int rc = 0; |
1906 | FLUSH_REQ *pSMB = NULL; | 2211 | FLUSH_REQ *pSMB = NULL; |
@@ -1921,7 +2226,7 @@ CIFSSMBFlush(const int xid, struct cifsTconInfo *tcon, int smb_file_id) | |||
1921 | } | 2226 | } |
1922 | 2227 | ||
1923 | int | 2228 | int |
1924 | CIFSSMBRename(const int xid, struct cifsTconInfo *tcon, | 2229 | CIFSSMBRename(const int xid, struct cifs_tcon *tcon, |
1925 | const char *fromName, const char *toName, | 2230 | const char *fromName, const char *toName, |
1926 | const struct nls_table *nls_codepage, int remap) | 2231 | const struct nls_table *nls_codepage, int remap) |
1927 | { | 2232 | { |
@@ -1971,7 +2276,7 @@ renameRetry: | |||
1971 | } | 2276 | } |
1972 | 2277 | ||
1973 | count = 1 /* 1st signature byte */ + name_len + name_len2; | 2278 | count = 1 /* 1st signature byte */ + name_len + name_len2; |
1974 | pSMB->hdr.smb_buf_length += count; | 2279 | inc_rfc1001_len(pSMB, count); |
1975 | pSMB->ByteCount = cpu_to_le16(count); | 2280 | pSMB->ByteCount = cpu_to_le16(count); |
1976 | 2281 | ||
1977 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 2282 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -1988,7 +2293,7 @@ renameRetry: | |||
1988 | return rc; | 2293 | return rc; |
1989 | } | 2294 | } |
1990 | 2295 | ||
1991 | int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon, | 2296 | int CIFSSMBRenameOpenFile(const int xid, struct cifs_tcon *pTcon, |
1992 | int netfid, const char *target_name, | 2297 | int netfid, const char *target_name, |
1993 | const struct nls_table *nls_codepage, int remap) | 2298 | const struct nls_table *nls_codepage, int remap) |
1994 | { | 2299 | { |
@@ -2051,7 +2356,7 @@ int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon, | |||
2051 | pSMB->InformationLevel = | 2356 | pSMB->InformationLevel = |
2052 | cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION); | 2357 | cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION); |
2053 | pSMB->Reserved4 = 0; | 2358 | pSMB->Reserved4 = 0; |
2054 | pSMB->hdr.smb_buf_length += byte_count; | 2359 | inc_rfc1001_len(pSMB, byte_count); |
2055 | pSMB->ByteCount = cpu_to_le16(byte_count); | 2360 | pSMB->ByteCount = cpu_to_le16(byte_count); |
2056 | rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB, | 2361 | rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB, |
2057 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 2362 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -2068,7 +2373,7 @@ int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon, | |||
2068 | } | 2373 | } |
2069 | 2374 | ||
2070 | int | 2375 | int |
2071 | CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char *fromName, | 2376 | CIFSSMBCopy(const int xid, struct cifs_tcon *tcon, const char *fromName, |
2072 | const __u16 target_tid, const char *toName, const int flags, | 2377 | const __u16 target_tid, const char *toName, const int flags, |
2073 | const struct nls_table *nls_codepage, int remap) | 2378 | const struct nls_table *nls_codepage, int remap) |
2074 | { | 2379 | { |
@@ -2118,7 +2423,7 @@ copyRetry: | |||
2118 | } | 2423 | } |
2119 | 2424 | ||
2120 | count = 1 /* 1st signature byte */ + name_len + name_len2; | 2425 | count = 1 /* 1st signature byte */ + name_len + name_len2; |
2121 | pSMB->hdr.smb_buf_length += count; | 2426 | inc_rfc1001_len(pSMB, count); |
2122 | pSMB->ByteCount = cpu_to_le16(count); | 2427 | pSMB->ByteCount = cpu_to_le16(count); |
2123 | 2428 | ||
2124 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 2429 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -2136,7 +2441,7 @@ copyRetry: | |||
2136 | } | 2441 | } |
2137 | 2442 | ||
2138 | int | 2443 | int |
2139 | CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon, | 2444 | CIFSUnixCreateSymLink(const int xid, struct cifs_tcon *tcon, |
2140 | const char *fromName, const char *toName, | 2445 | const char *fromName, const char *toName, |
2141 | const struct nls_table *nls_codepage) | 2446 | const struct nls_table *nls_codepage) |
2142 | { | 2447 | { |
@@ -2208,7 +2513,7 @@ createSymLinkRetry: | |||
2208 | pSMB->DataOffset = cpu_to_le16(offset); | 2513 | pSMB->DataOffset = cpu_to_le16(offset); |
2209 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK); | 2514 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK); |
2210 | pSMB->Reserved4 = 0; | 2515 | pSMB->Reserved4 = 0; |
2211 | pSMB->hdr.smb_buf_length += byte_count; | 2516 | inc_rfc1001_len(pSMB, byte_count); |
2212 | pSMB->ByteCount = cpu_to_le16(byte_count); | 2517 | pSMB->ByteCount = cpu_to_le16(byte_count); |
2213 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 2518 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
2214 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 2519 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -2225,7 +2530,7 @@ createSymLinkRetry: | |||
2225 | } | 2530 | } |
2226 | 2531 | ||
2227 | int | 2532 | int |
2228 | CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon, | 2533 | CIFSUnixCreateHardLink(const int xid, struct cifs_tcon *tcon, |
2229 | const char *fromName, const char *toName, | 2534 | const char *fromName, const char *toName, |
2230 | const struct nls_table *nls_codepage, int remap) | 2535 | const struct nls_table *nls_codepage, int remap) |
2231 | { | 2536 | { |
@@ -2294,7 +2599,7 @@ createHardLinkRetry: | |||
2294 | pSMB->DataOffset = cpu_to_le16(offset); | 2599 | pSMB->DataOffset = cpu_to_le16(offset); |
2295 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK); | 2600 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK); |
2296 | pSMB->Reserved4 = 0; | 2601 | pSMB->Reserved4 = 0; |
2297 | pSMB->hdr.smb_buf_length += byte_count; | 2602 | inc_rfc1001_len(pSMB, byte_count); |
2298 | pSMB->ByteCount = cpu_to_le16(byte_count); | 2603 | pSMB->ByteCount = cpu_to_le16(byte_count); |
2299 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 2604 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
2300 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 2605 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -2310,7 +2615,7 @@ createHardLinkRetry: | |||
2310 | } | 2615 | } |
2311 | 2616 | ||
2312 | int | 2617 | int |
2313 | CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon, | 2618 | CIFSCreateHardLink(const int xid, struct cifs_tcon *tcon, |
2314 | const char *fromName, const char *toName, | 2619 | const char *fromName, const char *toName, |
2315 | const struct nls_table *nls_codepage, int remap) | 2620 | const struct nls_table *nls_codepage, int remap) |
2316 | { | 2621 | { |
@@ -2365,7 +2670,7 @@ winCreateHardLinkRetry: | |||
2365 | } | 2670 | } |
2366 | 2671 | ||
2367 | count = 1 /* string type byte */ + name_len + name_len2; | 2672 | count = 1 /* string type byte */ + name_len + name_len2; |
2368 | pSMB->hdr.smb_buf_length += count; | 2673 | inc_rfc1001_len(pSMB, count); |
2369 | pSMB->ByteCount = cpu_to_le16(count); | 2674 | pSMB->ByteCount = cpu_to_le16(count); |
2370 | 2675 | ||
2371 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 2676 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -2382,7 +2687,7 @@ winCreateHardLinkRetry: | |||
2382 | } | 2687 | } |
2383 | 2688 | ||
2384 | int | 2689 | int |
2385 | CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon, | 2690 | CIFSSMBUnixQuerySymLink(const int xid, struct cifs_tcon *tcon, |
2386 | const unsigned char *searchName, char **symlinkinfo, | 2691 | const unsigned char *searchName, char **symlinkinfo, |
2387 | const struct nls_table *nls_codepage) | 2692 | const struct nls_table *nls_codepage) |
2388 | { | 2693 | { |
@@ -2436,7 +2741,7 @@ querySymLinkRetry: | |||
2436 | pSMB->ParameterCount = pSMB->TotalParameterCount; | 2741 | pSMB->ParameterCount = pSMB->TotalParameterCount; |
2437 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK); | 2742 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK); |
2438 | pSMB->Reserved4 = 0; | 2743 | pSMB->Reserved4 = 0; |
2439 | pSMB->hdr.smb_buf_length += byte_count; | 2744 | inc_rfc1001_len(pSMB, byte_count); |
2440 | pSMB->ByteCount = cpu_to_le16(byte_count); | 2745 | pSMB->ByteCount = cpu_to_le16(byte_count); |
2441 | 2746 | ||
2442 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 2747 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -2448,7 +2753,7 @@ querySymLinkRetry: | |||
2448 | 2753 | ||
2449 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 2754 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
2450 | /* BB also check enough total bytes returned */ | 2755 | /* BB also check enough total bytes returned */ |
2451 | if (rc || (pSMBr->ByteCount < 2)) | 2756 | if (rc || get_bcc(&pSMBr->hdr) < 2) |
2452 | rc = -EIO; | 2757 | rc = -EIO; |
2453 | else { | 2758 | else { |
2454 | bool is_unicode; | 2759 | bool is_unicode; |
@@ -2475,98 +2780,19 @@ querySymLinkRetry: | |||
2475 | return rc; | 2780 | return rc; |
2476 | } | 2781 | } |
2477 | 2782 | ||
2478 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 2783 | #ifdef CONFIG_CIFS_SYMLINK_EXPERIMENTAL |
2479 | /* Initialize NT TRANSACT SMB into small smb request buffer. | 2784 | /* |
2480 | This assumes that all NT TRANSACTS that we init here have | 2785 | * Recent Windows versions now create symlinks more frequently |
2481 | total parm and data under about 400 bytes (to fit in small cifs | 2786 | * and they use the "reparse point" mechanism below. We can of course |
2482 | buffer size), which is the case so far, it easily fits. NB: | 2787 | * do symlinks nicely to Samba and other servers which support the |
2483 | Setup words themselves and ByteCount | 2788 | * CIFS Unix Extensions and we can also do SFU symlinks and "client only" |
2484 | MaxSetupCount (size of returned setup area) and | 2789 | * "MF" symlinks optionally, but for recent Windows we really need to |
2485 | MaxParameterCount (returned parms size) must be set by caller */ | 2790 | * reenable the code below and fix the cifs_symlink callers to handle this. |
2486 | static int | 2791 | * In the interim this code has been moved to its own config option so |
2487 | smb_init_nttransact(const __u16 sub_command, const int setup_count, | 2792 | * it is not compiled in by default until callers fixed up and more tested. |
2488 | const int parm_len, struct cifsTconInfo *tcon, | 2793 | */ |
2489 | void **ret_buf) | ||
2490 | { | ||
2491 | int rc; | ||
2492 | __u32 temp_offset; | ||
2493 | struct smb_com_ntransact_req *pSMB; | ||
2494 | |||
2495 | rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon, | ||
2496 | (void **)&pSMB); | ||
2497 | if (rc) | ||
2498 | return rc; | ||
2499 | *ret_buf = (void *)pSMB; | ||
2500 | pSMB->Reserved = 0; | ||
2501 | pSMB->TotalParameterCount = cpu_to_le32(parm_len); | ||
2502 | pSMB->TotalDataCount = 0; | ||
2503 | pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf - | ||
2504 | MAX_CIFS_HDR_SIZE) & 0xFFFFFF00); | ||
2505 | pSMB->ParameterCount = pSMB->TotalParameterCount; | ||
2506 | pSMB->DataCount = pSMB->TotalDataCount; | ||
2507 | temp_offset = offsetof(struct smb_com_ntransact_req, Parms) + | ||
2508 | (setup_count * 2) - 4 /* for rfc1001 length itself */; | ||
2509 | pSMB->ParameterOffset = cpu_to_le32(temp_offset); | ||
2510 | pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len); | ||
2511 | pSMB->SetupCount = setup_count; /* no need to le convert byte fields */ | ||
2512 | pSMB->SubCommand = cpu_to_le16(sub_command); | ||
2513 | return 0; | ||
2514 | } | ||
2515 | |||
2516 | static int | ||
2517 | validate_ntransact(char *buf, char **ppparm, char **ppdata, | ||
2518 | __u32 *pparmlen, __u32 *pdatalen) | ||
2519 | { | ||
2520 | char *end_of_smb; | ||
2521 | __u32 data_count, data_offset, parm_count, parm_offset; | ||
2522 | struct smb_com_ntransact_rsp *pSMBr; | ||
2523 | |||
2524 | *pdatalen = 0; | ||
2525 | *pparmlen = 0; | ||
2526 | |||
2527 | if (buf == NULL) | ||
2528 | return -EINVAL; | ||
2529 | |||
2530 | pSMBr = (struct smb_com_ntransact_rsp *)buf; | ||
2531 | |||
2532 | /* ByteCount was converted from little endian in SendReceive */ | ||
2533 | end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount + | ||
2534 | (char *)&pSMBr->ByteCount; | ||
2535 | |||
2536 | data_offset = le32_to_cpu(pSMBr->DataOffset); | ||
2537 | data_count = le32_to_cpu(pSMBr->DataCount); | ||
2538 | parm_offset = le32_to_cpu(pSMBr->ParameterOffset); | ||
2539 | parm_count = le32_to_cpu(pSMBr->ParameterCount); | ||
2540 | |||
2541 | *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset; | ||
2542 | *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset; | ||
2543 | |||
2544 | /* should we also check that parm and data areas do not overlap? */ | ||
2545 | if (*ppparm > end_of_smb) { | ||
2546 | cFYI(1, "parms start after end of smb"); | ||
2547 | return -EINVAL; | ||
2548 | } else if (parm_count + *ppparm > end_of_smb) { | ||
2549 | cFYI(1, "parm end after end of smb"); | ||
2550 | return -EINVAL; | ||
2551 | } else if (*ppdata > end_of_smb) { | ||
2552 | cFYI(1, "data starts after end of smb"); | ||
2553 | return -EINVAL; | ||
2554 | } else if (data_count + *ppdata > end_of_smb) { | ||
2555 | cFYI(1, "data %p + count %d (%p) past smb end %p start %p", | ||
2556 | *ppdata, data_count, (data_count + *ppdata), | ||
2557 | end_of_smb, pSMBr); | ||
2558 | return -EINVAL; | ||
2559 | } else if (parm_count + data_count > pSMBr->ByteCount) { | ||
2560 | cFYI(1, "parm count and data count larger than SMB"); | ||
2561 | return -EINVAL; | ||
2562 | } | ||
2563 | *pdatalen = data_count; | ||
2564 | *pparmlen = parm_count; | ||
2565 | return 0; | ||
2566 | } | ||
2567 | |||
2568 | int | 2794 | int |
2569 | CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, | 2795 | CIFSSMBQueryReparseLinkInfo(const int xid, struct cifs_tcon *tcon, |
2570 | const unsigned char *searchName, | 2796 | const unsigned char *searchName, |
2571 | char *symlinkinfo, const int buflen, __u16 fid, | 2797 | char *symlinkinfo, const int buflen, __u16 fid, |
2572 | const struct nls_table *nls_codepage) | 2798 | const struct nls_table *nls_codepage) |
@@ -2609,14 +2835,14 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, | |||
2609 | } else { /* decode response */ | 2835 | } else { /* decode response */ |
2610 | __u32 data_offset = le32_to_cpu(pSMBr->DataOffset); | 2836 | __u32 data_offset = le32_to_cpu(pSMBr->DataOffset); |
2611 | __u32 data_count = le32_to_cpu(pSMBr->DataCount); | 2837 | __u32 data_count = le32_to_cpu(pSMBr->DataCount); |
2612 | if ((pSMBr->ByteCount < 2) || (data_offset > 512)) { | 2838 | if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) { |
2613 | /* BB also check enough total bytes returned */ | 2839 | /* BB also check enough total bytes returned */ |
2614 | rc = -EIO; /* bad smb */ | 2840 | rc = -EIO; /* bad smb */ |
2615 | goto qreparse_out; | 2841 | goto qreparse_out; |
2616 | } | 2842 | } |
2617 | if (data_count && (data_count < 2048)) { | 2843 | if (data_count && (data_count < 2048)) { |
2618 | char *end_of_smb = 2 /* sizeof byte count */ + | 2844 | char *end_of_smb = 2 /* sizeof byte count */ + |
2619 | pSMBr->ByteCount + (char *)&pSMBr->ByteCount; | 2845 | get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount; |
2620 | 2846 | ||
2621 | struct reparse_data *reparse_buf = | 2847 | struct reparse_data *reparse_buf = |
2622 | (struct reparse_data *) | 2848 | (struct reparse_data *) |
@@ -2666,7 +2892,7 @@ qreparse_out: | |||
2666 | 2892 | ||
2667 | return rc; | 2893 | return rc; |
2668 | } | 2894 | } |
2669 | #endif /* CIFS_EXPERIMENTAL */ | 2895 | #endif /* CIFS_SYMLINK_EXPERIMENTAL */ /* BB temporarily unused */ |
2670 | 2896 | ||
2671 | #ifdef CONFIG_CIFS_POSIX | 2897 | #ifdef CONFIG_CIFS_POSIX |
2672 | 2898 | ||
@@ -2804,7 +3030,7 @@ static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL, | |||
2804 | } | 3030 | } |
2805 | 3031 | ||
2806 | int | 3032 | int |
2807 | CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon, | 3033 | CIFSSMBGetPosixACL(const int xid, struct cifs_tcon *tcon, |
2808 | const unsigned char *searchName, | 3034 | const unsigned char *searchName, |
2809 | char *acl_inf, const int buflen, const int acl_type, | 3035 | char *acl_inf, const int buflen, const int acl_type, |
2810 | const struct nls_table *nls_codepage, int remap) | 3036 | const struct nls_table *nls_codepage, int remap) |
@@ -2862,7 +3088,7 @@ queryAclRetry: | |||
2862 | pSMB->ParameterCount = pSMB->TotalParameterCount; | 3088 | pSMB->ParameterCount = pSMB->TotalParameterCount; |
2863 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL); | 3089 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL); |
2864 | pSMB->Reserved4 = 0; | 3090 | pSMB->Reserved4 = 0; |
2865 | pSMB->hdr.smb_buf_length += byte_count; | 3091 | inc_rfc1001_len(pSMB, byte_count); |
2866 | pSMB->ByteCount = cpu_to_le16(byte_count); | 3092 | pSMB->ByteCount = cpu_to_le16(byte_count); |
2867 | 3093 | ||
2868 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 3094 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -2874,8 +3100,8 @@ queryAclRetry: | |||
2874 | /* decode response */ | 3100 | /* decode response */ |
2875 | 3101 | ||
2876 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 3102 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
2877 | if (rc || (pSMBr->ByteCount < 2)) | ||
2878 | /* BB also check enough total bytes returned */ | 3103 | /* BB also check enough total bytes returned */ |
3104 | if (rc || get_bcc(&pSMBr->hdr) < 2) | ||
2879 | rc = -EIO; /* bad smb */ | 3105 | rc = -EIO; /* bad smb */ |
2880 | else { | 3106 | else { |
2881 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); | 3107 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); |
@@ -2892,7 +3118,7 @@ queryAclRetry: | |||
2892 | } | 3118 | } |
2893 | 3119 | ||
2894 | int | 3120 | int |
2895 | CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon, | 3121 | CIFSSMBSetPosixACL(const int xid, struct cifs_tcon *tcon, |
2896 | const unsigned char *fileName, | 3122 | const unsigned char *fileName, |
2897 | const char *local_acl, const int buflen, | 3123 | const char *local_acl, const int buflen, |
2898 | const int acl_type, | 3124 | const int acl_type, |
@@ -2956,7 +3182,7 @@ setAclRetry: | |||
2956 | pSMB->ParameterCount = cpu_to_le16(params); | 3182 | pSMB->ParameterCount = cpu_to_le16(params); |
2957 | pSMB->TotalParameterCount = pSMB->ParameterCount; | 3183 | pSMB->TotalParameterCount = pSMB->ParameterCount; |
2958 | pSMB->Reserved4 = 0; | 3184 | pSMB->Reserved4 = 0; |
2959 | pSMB->hdr.smb_buf_length += byte_count; | 3185 | inc_rfc1001_len(pSMB, byte_count); |
2960 | pSMB->ByteCount = cpu_to_le16(byte_count); | 3186 | pSMB->ByteCount = cpu_to_le16(byte_count); |
2961 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 3187 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
2962 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 3188 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -2972,7 +3198,7 @@ setACLerrorExit: | |||
2972 | 3198 | ||
2973 | /* BB fix tabs in this function FIXME BB */ | 3199 | /* BB fix tabs in this function FIXME BB */ |
2974 | int | 3200 | int |
2975 | CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon, | 3201 | CIFSGetExtAttr(const int xid, struct cifs_tcon *tcon, |
2976 | const int netfid, __u64 *pExtAttrBits, __u64 *pMask) | 3202 | const int netfid, __u64 *pExtAttrBits, __u64 *pMask) |
2977 | { | 3203 | { |
2978 | int rc = 0; | 3204 | int rc = 0; |
@@ -3014,7 +3240,7 @@ GetExtAttrRetry: | |||
3014 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS); | 3240 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS); |
3015 | pSMB->Pad = 0; | 3241 | pSMB->Pad = 0; |
3016 | pSMB->Fid = netfid; | 3242 | pSMB->Fid = netfid; |
3017 | pSMB->hdr.smb_buf_length += byte_count; | 3243 | inc_rfc1001_len(pSMB, byte_count); |
3018 | pSMB->t2.ByteCount = cpu_to_le16(byte_count); | 3244 | pSMB->t2.ByteCount = cpu_to_le16(byte_count); |
3019 | 3245 | ||
3020 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 3246 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -3024,8 +3250,8 @@ GetExtAttrRetry: | |||
3024 | } else { | 3250 | } else { |
3025 | /* decode response */ | 3251 | /* decode response */ |
3026 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 3252 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
3027 | if (rc || (pSMBr->ByteCount < 2)) | ||
3028 | /* BB also check enough total bytes returned */ | 3253 | /* BB also check enough total bytes returned */ |
3254 | if (rc || get_bcc(&pSMBr->hdr) < 2) | ||
3029 | /* If rc should we check for EOPNOSUPP and | 3255 | /* If rc should we check for EOPNOSUPP and |
3030 | disable the srvino flag? or in caller? */ | 3256 | disable the srvino flag? or in caller? */ |
3031 | rc = -EIO; /* bad smb */ | 3257 | rc = -EIO; /* bad smb */ |
@@ -3054,10 +3280,101 @@ GetExtAttrOut: | |||
3054 | 3280 | ||
3055 | #endif /* CONFIG_POSIX */ | 3281 | #endif /* CONFIG_POSIX */ |
3056 | 3282 | ||
3057 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 3283 | #ifdef CONFIG_CIFS_ACL |
3284 | /* | ||
3285 | * Initialize NT TRANSACT SMB into small smb request buffer. This assumes that | ||
3286 | * all NT TRANSACTS that we init here have total parm and data under about 400 | ||
3287 | * bytes (to fit in small cifs buffer size), which is the case so far, it | ||
3288 | * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of | ||
3289 | * returned setup area) and MaxParameterCount (returned parms size) must be set | ||
3290 | * by caller | ||
3291 | */ | ||
3292 | static int | ||
3293 | smb_init_nttransact(const __u16 sub_command, const int setup_count, | ||
3294 | const int parm_len, struct cifs_tcon *tcon, | ||
3295 | void **ret_buf) | ||
3296 | { | ||
3297 | int rc; | ||
3298 | __u32 temp_offset; | ||
3299 | struct smb_com_ntransact_req *pSMB; | ||
3300 | |||
3301 | rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon, | ||
3302 | (void **)&pSMB); | ||
3303 | if (rc) | ||
3304 | return rc; | ||
3305 | *ret_buf = (void *)pSMB; | ||
3306 | pSMB->Reserved = 0; | ||
3307 | pSMB->TotalParameterCount = cpu_to_le32(parm_len); | ||
3308 | pSMB->TotalDataCount = 0; | ||
3309 | pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf - | ||
3310 | MAX_CIFS_HDR_SIZE) & 0xFFFFFF00); | ||
3311 | pSMB->ParameterCount = pSMB->TotalParameterCount; | ||
3312 | pSMB->DataCount = pSMB->TotalDataCount; | ||
3313 | temp_offset = offsetof(struct smb_com_ntransact_req, Parms) + | ||
3314 | (setup_count * 2) - 4 /* for rfc1001 length itself */; | ||
3315 | pSMB->ParameterOffset = cpu_to_le32(temp_offset); | ||
3316 | pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len); | ||
3317 | pSMB->SetupCount = setup_count; /* no need to le convert byte fields */ | ||
3318 | pSMB->SubCommand = cpu_to_le16(sub_command); | ||
3319 | return 0; | ||
3320 | } | ||
3321 | |||
3322 | static int | ||
3323 | validate_ntransact(char *buf, char **ppparm, char **ppdata, | ||
3324 | __u32 *pparmlen, __u32 *pdatalen) | ||
3325 | { | ||
3326 | char *end_of_smb; | ||
3327 | __u32 data_count, data_offset, parm_count, parm_offset; | ||
3328 | struct smb_com_ntransact_rsp *pSMBr; | ||
3329 | u16 bcc; | ||
3330 | |||
3331 | *pdatalen = 0; | ||
3332 | *pparmlen = 0; | ||
3333 | |||
3334 | if (buf == NULL) | ||
3335 | return -EINVAL; | ||
3336 | |||
3337 | pSMBr = (struct smb_com_ntransact_rsp *)buf; | ||
3338 | |||
3339 | bcc = get_bcc(&pSMBr->hdr); | ||
3340 | end_of_smb = 2 /* sizeof byte count */ + bcc + | ||
3341 | (char *)&pSMBr->ByteCount; | ||
3342 | |||
3343 | data_offset = le32_to_cpu(pSMBr->DataOffset); | ||
3344 | data_count = le32_to_cpu(pSMBr->DataCount); | ||
3345 | parm_offset = le32_to_cpu(pSMBr->ParameterOffset); | ||
3346 | parm_count = le32_to_cpu(pSMBr->ParameterCount); | ||
3347 | |||
3348 | *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset; | ||
3349 | *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset; | ||
3350 | |||
3351 | /* should we also check that parm and data areas do not overlap? */ | ||
3352 | if (*ppparm > end_of_smb) { | ||
3353 | cFYI(1, "parms start after end of smb"); | ||
3354 | return -EINVAL; | ||
3355 | } else if (parm_count + *ppparm > end_of_smb) { | ||
3356 | cFYI(1, "parm end after end of smb"); | ||
3357 | return -EINVAL; | ||
3358 | } else if (*ppdata > end_of_smb) { | ||
3359 | cFYI(1, "data starts after end of smb"); | ||
3360 | return -EINVAL; | ||
3361 | } else if (data_count + *ppdata > end_of_smb) { | ||
3362 | cFYI(1, "data %p + count %d (%p) past smb end %p start %p", | ||
3363 | *ppdata, data_count, (data_count + *ppdata), | ||
3364 | end_of_smb, pSMBr); | ||
3365 | return -EINVAL; | ||
3366 | } else if (parm_count + data_count > bcc) { | ||
3367 | cFYI(1, "parm count and data count larger than SMB"); | ||
3368 | return -EINVAL; | ||
3369 | } | ||
3370 | *pdatalen = data_count; | ||
3371 | *pparmlen = parm_count; | ||
3372 | return 0; | ||
3373 | } | ||
3374 | |||
3058 | /* Get Security Descriptor (by handle) from remote server for a file or dir */ | 3375 | /* Get Security Descriptor (by handle) from remote server for a file or dir */ |
3059 | int | 3376 | int |
3060 | CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, | 3377 | CIFSSMBGetCIFSACL(const int xid, struct cifs_tcon *tcon, __u16 fid, |
3061 | struct cifs_ntsd **acl_inf, __u32 *pbuflen) | 3378 | struct cifs_ntsd **acl_inf, __u32 *pbuflen) |
3062 | { | 3379 | { |
3063 | int rc = 0; | 3380 | int rc = 0; |
@@ -3082,12 +3399,12 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, | |||
3082 | pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP | | 3399 | pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP | |
3083 | CIFS_ACL_DACL); | 3400 | CIFS_ACL_DACL); |
3084 | pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */ | 3401 | pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */ |
3085 | pSMB->hdr.smb_buf_length += 11; | 3402 | inc_rfc1001_len(pSMB, 11); |
3086 | iov[0].iov_base = (char *)pSMB; | 3403 | iov[0].iov_base = (char *)pSMB; |
3087 | iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; | 3404 | iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4; |
3088 | 3405 | ||
3089 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, | 3406 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, |
3090 | CIFS_STD_OP); | 3407 | 0); |
3091 | cifs_stats_inc(&tcon->num_acl_get); | 3408 | cifs_stats_inc(&tcon->num_acl_get); |
3092 | if (rc) { | 3409 | if (rc) { |
3093 | cFYI(1, "Send error in QuerySecDesc = %d", rc); | 3410 | cFYI(1, "Send error in QuerySecDesc = %d", rc); |
@@ -3149,7 +3466,7 @@ qsec_out: | |||
3149 | } | 3466 | } |
3150 | 3467 | ||
3151 | int | 3468 | int |
3152 | CIFSSMBSetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, | 3469 | CIFSSMBSetCIFSACL(const int xid, struct cifs_tcon *tcon, __u16 fid, |
3153 | struct cifs_ntsd *pntsd, __u32 acllen) | 3470 | struct cifs_ntsd *pntsd, __u32 acllen) |
3154 | { | 3471 | { |
3155 | __u16 byte_count, param_count, data_count, param_offset, data_offset; | 3472 | __u16 byte_count, param_count, data_count, param_offset, data_offset; |
@@ -3193,10 +3510,9 @@ setCifsAclRetry: | |||
3193 | memcpy((char *) &pSMBr->hdr.Protocol + data_offset, | 3510 | memcpy((char *) &pSMBr->hdr.Protocol + data_offset, |
3194 | (char *) pntsd, | 3511 | (char *) pntsd, |
3195 | acllen); | 3512 | acllen); |
3196 | pSMB->hdr.smb_buf_length += (byte_count + data_count); | 3513 | inc_rfc1001_len(pSMB, byte_count + data_count); |
3197 | |||
3198 | } else | 3514 | } else |
3199 | pSMB->hdr.smb_buf_length += byte_count; | 3515 | inc_rfc1001_len(pSMB, byte_count); |
3200 | 3516 | ||
3201 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 3517 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
3202 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 3518 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -3212,11 +3528,11 @@ setCifsAclRetry: | |||
3212 | return (rc); | 3528 | return (rc); |
3213 | } | 3529 | } |
3214 | 3530 | ||
3215 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | 3531 | #endif /* CONFIG_CIFS_ACL */ |
3216 | 3532 | ||
3217 | /* Legacy Query Path Information call for lookup to old servers such | 3533 | /* Legacy Query Path Information call for lookup to old servers such |
3218 | as Win9x/WinME */ | 3534 | as Win9x/WinME */ |
3219 | int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon, | 3535 | int SMBQueryInformation(const int xid, struct cifs_tcon *tcon, |
3220 | const unsigned char *searchName, | 3536 | const unsigned char *searchName, |
3221 | FILE_ALL_INFO *pFinfo, | 3537 | FILE_ALL_INFO *pFinfo, |
3222 | const struct nls_table *nls_codepage, int remap) | 3538 | const struct nls_table *nls_codepage, int remap) |
@@ -3247,7 +3563,7 @@ QInfRetry: | |||
3247 | } | 3563 | } |
3248 | pSMB->BufferFormat = 0x04; | 3564 | pSMB->BufferFormat = 0x04; |
3249 | name_len++; /* account for buffer type byte */ | 3565 | name_len++; /* account for buffer type byte */ |
3250 | pSMB->hdr.smb_buf_length += (__u16) name_len; | 3566 | inc_rfc1001_len(pSMB, (__u16)name_len); |
3251 | pSMB->ByteCount = cpu_to_le16(name_len); | 3567 | pSMB->ByteCount = cpu_to_le16(name_len); |
3252 | 3568 | ||
3253 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 3569 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -3284,7 +3600,7 @@ QInfRetry: | |||
3284 | } | 3600 | } |
3285 | 3601 | ||
3286 | int | 3602 | int |
3287 | CIFSSMBQFileInfo(const int xid, struct cifsTconInfo *tcon, | 3603 | CIFSSMBQFileInfo(const int xid, struct cifs_tcon *tcon, |
3288 | u16 netfid, FILE_ALL_INFO *pFindData) | 3604 | u16 netfid, FILE_ALL_INFO *pFindData) |
3289 | { | 3605 | { |
3290 | struct smb_t2_qfi_req *pSMB = NULL; | 3606 | struct smb_t2_qfi_req *pSMB = NULL; |
@@ -3322,7 +3638,7 @@ QFileInfoRetry: | |||
3322 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO); | 3638 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO); |
3323 | pSMB->Pad = 0; | 3639 | pSMB->Pad = 0; |
3324 | pSMB->Fid = netfid; | 3640 | pSMB->Fid = netfid; |
3325 | pSMB->hdr.smb_buf_length += byte_count; | 3641 | inc_rfc1001_len(pSMB, byte_count); |
3326 | 3642 | ||
3327 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 3643 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
3328 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 3644 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -3333,7 +3649,7 @@ QFileInfoRetry: | |||
3333 | 3649 | ||
3334 | if (rc) /* BB add auto retry on EOPNOTSUPP? */ | 3650 | if (rc) /* BB add auto retry on EOPNOTSUPP? */ |
3335 | rc = -EIO; | 3651 | rc = -EIO; |
3336 | else if (pSMBr->ByteCount < 40) | 3652 | else if (get_bcc(&pSMBr->hdr) < 40) |
3337 | rc = -EIO; /* bad smb */ | 3653 | rc = -EIO; /* bad smb */ |
3338 | else if (pFindData) { | 3654 | else if (pFindData) { |
3339 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); | 3655 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); |
@@ -3351,7 +3667,7 @@ QFileInfoRetry: | |||
3351 | } | 3667 | } |
3352 | 3668 | ||
3353 | int | 3669 | int |
3354 | CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, | 3670 | CIFSSMBQPathInfo(const int xid, struct cifs_tcon *tcon, |
3355 | const unsigned char *searchName, | 3671 | const unsigned char *searchName, |
3356 | FILE_ALL_INFO *pFindData, | 3672 | FILE_ALL_INFO *pFindData, |
3357 | int legacy /* old style infolevel */, | 3673 | int legacy /* old style infolevel */, |
@@ -3409,7 +3725,7 @@ QPathInfoRetry: | |||
3409 | else | 3725 | else |
3410 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO); | 3726 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO); |
3411 | pSMB->Reserved4 = 0; | 3727 | pSMB->Reserved4 = 0; |
3412 | pSMB->hdr.smb_buf_length += byte_count; | 3728 | inc_rfc1001_len(pSMB, byte_count); |
3413 | pSMB->ByteCount = cpu_to_le16(byte_count); | 3729 | pSMB->ByteCount = cpu_to_le16(byte_count); |
3414 | 3730 | ||
3415 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 3731 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -3421,9 +3737,9 @@ QPathInfoRetry: | |||
3421 | 3737 | ||
3422 | if (rc) /* BB add auto retry on EOPNOTSUPP? */ | 3738 | if (rc) /* BB add auto retry on EOPNOTSUPP? */ |
3423 | rc = -EIO; | 3739 | rc = -EIO; |
3424 | else if (!legacy && (pSMBr->ByteCount < 40)) | 3740 | else if (!legacy && get_bcc(&pSMBr->hdr) < 40) |
3425 | rc = -EIO; /* bad smb */ | 3741 | rc = -EIO; /* bad smb */ |
3426 | else if (legacy && (pSMBr->ByteCount < 24)) | 3742 | else if (legacy && get_bcc(&pSMBr->hdr) < 24) |
3427 | rc = -EIO; /* 24 or 26 expected but we do not read | 3743 | rc = -EIO; /* 24 or 26 expected but we do not read |
3428 | last field */ | 3744 | last field */ |
3429 | else if (pFindData) { | 3745 | else if (pFindData) { |
@@ -3452,7 +3768,7 @@ QPathInfoRetry: | |||
3452 | } | 3768 | } |
3453 | 3769 | ||
3454 | int | 3770 | int |
3455 | CIFSSMBUnixQFileInfo(const int xid, struct cifsTconInfo *tcon, | 3771 | CIFSSMBUnixQFileInfo(const int xid, struct cifs_tcon *tcon, |
3456 | u16 netfid, FILE_UNIX_BASIC_INFO *pFindData) | 3772 | u16 netfid, FILE_UNIX_BASIC_INFO *pFindData) |
3457 | { | 3773 | { |
3458 | struct smb_t2_qfi_req *pSMB = NULL; | 3774 | struct smb_t2_qfi_req *pSMB = NULL; |
@@ -3490,7 +3806,7 @@ UnixQFileInfoRetry: | |||
3490 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC); | 3806 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC); |
3491 | pSMB->Pad = 0; | 3807 | pSMB->Pad = 0; |
3492 | pSMB->Fid = netfid; | 3808 | pSMB->Fid = netfid; |
3493 | pSMB->hdr.smb_buf_length += byte_count; | 3809 | inc_rfc1001_len(pSMB, byte_count); |
3494 | 3810 | ||
3495 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 3811 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
3496 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 3812 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -3499,7 +3815,7 @@ UnixQFileInfoRetry: | |||
3499 | } else { /* decode response */ | 3815 | } else { /* decode response */ |
3500 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 3816 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
3501 | 3817 | ||
3502 | if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) { | 3818 | if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) { |
3503 | cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n" | 3819 | cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n" |
3504 | "Unix Extensions can be disabled on mount " | 3820 | "Unix Extensions can be disabled on mount " |
3505 | "by specifying the nosfu mount option."); | 3821 | "by specifying the nosfu mount option."); |
@@ -3521,7 +3837,7 @@ UnixQFileInfoRetry: | |||
3521 | } | 3837 | } |
3522 | 3838 | ||
3523 | int | 3839 | int |
3524 | CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon, | 3840 | CIFSSMBUnixQPathInfo(const int xid, struct cifs_tcon *tcon, |
3525 | const unsigned char *searchName, | 3841 | const unsigned char *searchName, |
3526 | FILE_UNIX_BASIC_INFO *pFindData, | 3842 | FILE_UNIX_BASIC_INFO *pFindData, |
3527 | const struct nls_table *nls_codepage, int remap) | 3843 | const struct nls_table *nls_codepage, int remap) |
@@ -3575,7 +3891,7 @@ UnixQPathInfoRetry: | |||
3575 | pSMB->ParameterCount = pSMB->TotalParameterCount; | 3891 | pSMB->ParameterCount = pSMB->TotalParameterCount; |
3576 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC); | 3892 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC); |
3577 | pSMB->Reserved4 = 0; | 3893 | pSMB->Reserved4 = 0; |
3578 | pSMB->hdr.smb_buf_length += byte_count; | 3894 | inc_rfc1001_len(pSMB, byte_count); |
3579 | pSMB->ByteCount = cpu_to_le16(byte_count); | 3895 | pSMB->ByteCount = cpu_to_le16(byte_count); |
3580 | 3896 | ||
3581 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 3897 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -3585,7 +3901,7 @@ UnixQPathInfoRetry: | |||
3585 | } else { /* decode response */ | 3901 | } else { /* decode response */ |
3586 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 3902 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
3587 | 3903 | ||
3588 | if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) { | 3904 | if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) { |
3589 | cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n" | 3905 | cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n" |
3590 | "Unix Extensions can be disabled on mount " | 3906 | "Unix Extensions can be disabled on mount " |
3591 | "by specifying the nosfu mount option."); | 3907 | "by specifying the nosfu mount option."); |
@@ -3607,7 +3923,7 @@ UnixQPathInfoRetry: | |||
3607 | 3923 | ||
3608 | /* xid, tcon, searchName and codepage are input parms, rest are returned */ | 3924 | /* xid, tcon, searchName and codepage are input parms, rest are returned */ |
3609 | int | 3925 | int |
3610 | CIFSFindFirst(const int xid, struct cifsTconInfo *tcon, | 3926 | CIFSFindFirst(const int xid, struct cifs_tcon *tcon, |
3611 | const char *searchName, | 3927 | const char *searchName, |
3612 | const struct nls_table *nls_codepage, | 3928 | const struct nls_table *nls_codepage, |
3613 | __u16 *pnetfid, | 3929 | __u16 *pnetfid, |
@@ -3689,7 +4005,7 @@ findFirstRetry: | |||
3689 | 4005 | ||
3690 | /* BB what should we set StorageType to? Does it matter? BB */ | 4006 | /* BB what should we set StorageType to? Does it matter? BB */ |
3691 | pSMB->SearchStorageType = 0; | 4007 | pSMB->SearchStorageType = 0; |
3692 | pSMB->hdr.smb_buf_length += byte_count; | 4008 | inc_rfc1001_len(pSMB, byte_count); |
3693 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4009 | pSMB->ByteCount = cpu_to_le16(byte_count); |
3694 | 4010 | ||
3695 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4011 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -3755,7 +4071,7 @@ findFirstRetry: | |||
3755 | return rc; | 4071 | return rc; |
3756 | } | 4072 | } |
3757 | 4073 | ||
3758 | int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, | 4074 | int CIFSFindNext(const int xid, struct cifs_tcon *tcon, |
3759 | __u16 searchHandle, struct cifs_search_info *psrch_inf) | 4075 | __u16 searchHandle, struct cifs_search_info *psrch_inf) |
3760 | { | 4076 | { |
3761 | TRANSACTION2_FNEXT_REQ *pSMB = NULL; | 4077 | TRANSACTION2_FNEXT_REQ *pSMB = NULL; |
@@ -3818,7 +4134,7 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, | |||
3818 | byte_count = params + 1 /* pad */ ; | 4134 | byte_count = params + 1 /* pad */ ; |
3819 | pSMB->TotalParameterCount = cpu_to_le16(params); | 4135 | pSMB->TotalParameterCount = cpu_to_le16(params); |
3820 | pSMB->ParameterCount = pSMB->TotalParameterCount; | 4136 | pSMB->ParameterCount = pSMB->TotalParameterCount; |
3821 | pSMB->hdr.smb_buf_length += byte_count; | 4137 | inc_rfc1001_len(pSMB, byte_count); |
3822 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4138 | pSMB->ByteCount = cpu_to_le16(byte_count); |
3823 | 4139 | ||
3824 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4140 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -3893,7 +4209,7 @@ FNext2_err_exit: | |||
3893 | } | 4209 | } |
3894 | 4210 | ||
3895 | int | 4211 | int |
3896 | CIFSFindClose(const int xid, struct cifsTconInfo *tcon, | 4212 | CIFSFindClose(const int xid, struct cifs_tcon *tcon, |
3897 | const __u16 searchHandle) | 4213 | const __u16 searchHandle) |
3898 | { | 4214 | { |
3899 | int rc = 0; | 4215 | int rc = 0; |
@@ -3925,7 +4241,7 @@ CIFSFindClose(const int xid, struct cifsTconInfo *tcon, | |||
3925 | } | 4241 | } |
3926 | 4242 | ||
3927 | int | 4243 | int |
3928 | CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, | 4244 | CIFSGetSrvInodeNumber(const int xid, struct cifs_tcon *tcon, |
3929 | const unsigned char *searchName, | 4245 | const unsigned char *searchName, |
3930 | __u64 *inode_number, | 4246 | __u64 *inode_number, |
3931 | const struct nls_table *nls_codepage, int remap) | 4247 | const struct nls_table *nls_codepage, int remap) |
@@ -3980,7 +4296,7 @@ GetInodeNumberRetry: | |||
3980 | pSMB->ParameterCount = pSMB->TotalParameterCount; | 4296 | pSMB->ParameterCount = pSMB->TotalParameterCount; |
3981 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO); | 4297 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO); |
3982 | pSMB->Reserved4 = 0; | 4298 | pSMB->Reserved4 = 0; |
3983 | pSMB->hdr.smb_buf_length += byte_count; | 4299 | inc_rfc1001_len(pSMB, byte_count); |
3984 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4300 | pSMB->ByteCount = cpu_to_le16(byte_count); |
3985 | 4301 | ||
3986 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4302 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -3990,8 +4306,8 @@ GetInodeNumberRetry: | |||
3990 | } else { | 4306 | } else { |
3991 | /* decode response */ | 4307 | /* decode response */ |
3992 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 4308 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
3993 | if (rc || (pSMBr->ByteCount < 2)) | ||
3994 | /* BB also check enough total bytes returned */ | 4309 | /* BB also check enough total bytes returned */ |
4310 | if (rc || get_bcc(&pSMBr->hdr) < 2) | ||
3995 | /* If rc should we check for EOPNOSUPP and | 4311 | /* If rc should we check for EOPNOSUPP and |
3996 | disable the srvino flag? or in caller? */ | 4312 | disable the srvino flag? or in caller? */ |
3997 | rc = -EIO; /* bad smb */ | 4313 | rc = -EIO; /* bad smb */ |
@@ -4127,7 +4443,7 @@ parse_DFS_referrals_exit: | |||
4127 | } | 4443 | } |
4128 | 4444 | ||
4129 | int | 4445 | int |
4130 | CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses, | 4446 | CIFSGetDFSRefer(const int xid, struct cifs_ses *ses, |
4131 | const unsigned char *searchName, | 4447 | const unsigned char *searchName, |
4132 | struct dfs_info3_param **target_nodes, | 4448 | struct dfs_info3_param **target_nodes, |
4133 | unsigned int *num_of_nodes, | 4449 | unsigned int *num_of_nodes, |
@@ -4176,7 +4492,7 @@ getDFSRetry: | |||
4176 | } | 4492 | } |
4177 | 4493 | ||
4178 | if (ses->server) { | 4494 | if (ses->server) { |
4179 | if (ses->server->secMode & | 4495 | if (ses->server->sec_mode & |
4180 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) | 4496 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) |
4181 | pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE; | 4497 | pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE; |
4182 | } | 4498 | } |
@@ -4204,7 +4520,7 @@ getDFSRetry: | |||
4204 | pSMB->ParameterCount = cpu_to_le16(params); | 4520 | pSMB->ParameterCount = cpu_to_le16(params); |
4205 | pSMB->TotalParameterCount = pSMB->ParameterCount; | 4521 | pSMB->TotalParameterCount = pSMB->ParameterCount; |
4206 | pSMB->MaxReferralLevel = cpu_to_le16(3); | 4522 | pSMB->MaxReferralLevel = cpu_to_le16(3); |
4207 | pSMB->hdr.smb_buf_length += byte_count; | 4523 | inc_rfc1001_len(pSMB, byte_count); |
4208 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4524 | pSMB->ByteCount = cpu_to_le16(byte_count); |
4209 | 4525 | ||
4210 | rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB, | 4526 | rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB, |
@@ -4216,13 +4532,13 @@ getDFSRetry: | |||
4216 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 4532 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
4217 | 4533 | ||
4218 | /* BB Also check if enough total bytes returned? */ | 4534 | /* BB Also check if enough total bytes returned? */ |
4219 | if (rc || (pSMBr->ByteCount < 17)) { | 4535 | if (rc || get_bcc(&pSMBr->hdr) < 17) { |
4220 | rc = -EIO; /* bad smb */ | 4536 | rc = -EIO; /* bad smb */ |
4221 | goto GetDFSRefExit; | 4537 | goto GetDFSRefExit; |
4222 | } | 4538 | } |
4223 | 4539 | ||
4224 | cFYI(1, "Decoding GetDFSRefer response BCC: %d Offset %d", | 4540 | cFYI(1, "Decoding GetDFSRefer response BCC: %d Offset %d", |
4225 | pSMBr->ByteCount, | 4541 | get_bcc(&pSMBr->hdr), |
4226 | le16_to_cpu(pSMBr->t2.DataOffset)); | 4542 | le16_to_cpu(pSMBr->t2.DataOffset)); |
4227 | 4543 | ||
4228 | /* parse returned result into more usable form */ | 4544 | /* parse returned result into more usable form */ |
@@ -4241,7 +4557,7 @@ GetDFSRefExit: | |||
4241 | 4557 | ||
4242 | /* Query File System Info such as free space to old servers such as Win 9x */ | 4558 | /* Query File System Info such as free space to old servers such as Win 9x */ |
4243 | int | 4559 | int |
4244 | SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData) | 4560 | SMBOldQFSInfo(const int xid, struct cifs_tcon *tcon, struct kstatfs *FSData) |
4245 | { | 4561 | { |
4246 | /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */ | 4562 | /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */ |
4247 | TRANSACTION2_QFSI_REQ *pSMB = NULL; | 4563 | TRANSACTION2_QFSI_REQ *pSMB = NULL; |
@@ -4278,7 +4594,7 @@ oldQFSInfoRetry: | |||
4278 | pSMB->Reserved3 = 0; | 4594 | pSMB->Reserved3 = 0; |
4279 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); | 4595 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); |
4280 | pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION); | 4596 | pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION); |
4281 | pSMB->hdr.smb_buf_length += byte_count; | 4597 | inc_rfc1001_len(pSMB, byte_count); |
4282 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4598 | pSMB->ByteCount = cpu_to_le16(byte_count); |
4283 | 4599 | ||
4284 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4600 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -4288,12 +4604,12 @@ oldQFSInfoRetry: | |||
4288 | } else { /* decode response */ | 4604 | } else { /* decode response */ |
4289 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 4605 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
4290 | 4606 | ||
4291 | if (rc || (pSMBr->ByteCount < 18)) | 4607 | if (rc || get_bcc(&pSMBr->hdr) < 18) |
4292 | rc = -EIO; /* bad smb */ | 4608 | rc = -EIO; /* bad smb */ |
4293 | else { | 4609 | else { |
4294 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); | 4610 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); |
4295 | cFYI(1, "qfsinf resp BCC: %d Offset %d", | 4611 | cFYI(1, "qfsinf resp BCC: %d Offset %d", |
4296 | pSMBr->ByteCount, data_offset); | 4612 | get_bcc(&pSMBr->hdr), data_offset); |
4297 | 4613 | ||
4298 | response_data = (FILE_SYSTEM_ALLOC_INFO *) | 4614 | response_data = (FILE_SYSTEM_ALLOC_INFO *) |
4299 | (((char *) &pSMBr->hdr.Protocol) + data_offset); | 4615 | (((char *) &pSMBr->hdr.Protocol) + data_offset); |
@@ -4320,7 +4636,7 @@ oldQFSInfoRetry: | |||
4320 | } | 4636 | } |
4321 | 4637 | ||
4322 | int | 4638 | int |
4323 | CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData) | 4639 | CIFSSMBQFSInfo(const int xid, struct cifs_tcon *tcon, struct kstatfs *FSData) |
4324 | { | 4640 | { |
4325 | /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */ | 4641 | /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */ |
4326 | TRANSACTION2_QFSI_REQ *pSMB = NULL; | 4642 | TRANSACTION2_QFSI_REQ *pSMB = NULL; |
@@ -4357,7 +4673,7 @@ QFSInfoRetry: | |||
4357 | pSMB->Reserved3 = 0; | 4673 | pSMB->Reserved3 = 0; |
4358 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); | 4674 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); |
4359 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO); | 4675 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO); |
4360 | pSMB->hdr.smb_buf_length += byte_count; | 4676 | inc_rfc1001_len(pSMB, byte_count); |
4361 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4677 | pSMB->ByteCount = cpu_to_le16(byte_count); |
4362 | 4678 | ||
4363 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4679 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -4367,7 +4683,7 @@ QFSInfoRetry: | |||
4367 | } else { /* decode response */ | 4683 | } else { /* decode response */ |
4368 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 4684 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
4369 | 4685 | ||
4370 | if (rc || (pSMBr->ByteCount < 24)) | 4686 | if (rc || get_bcc(&pSMBr->hdr) < 24) |
4371 | rc = -EIO; /* bad smb */ | 4687 | rc = -EIO; /* bad smb */ |
4372 | else { | 4688 | else { |
4373 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); | 4689 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); |
@@ -4399,7 +4715,7 @@ QFSInfoRetry: | |||
4399 | } | 4715 | } |
4400 | 4716 | ||
4401 | int | 4717 | int |
4402 | CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon) | 4718 | CIFSSMBQFSAttributeInfo(const int xid, struct cifs_tcon *tcon) |
4403 | { | 4719 | { |
4404 | /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */ | 4720 | /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */ |
4405 | TRANSACTION2_QFSI_REQ *pSMB = NULL; | 4721 | TRANSACTION2_QFSI_REQ *pSMB = NULL; |
@@ -4437,7 +4753,7 @@ QFSAttributeRetry: | |||
4437 | pSMB->Reserved3 = 0; | 4753 | pSMB->Reserved3 = 0; |
4438 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); | 4754 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); |
4439 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO); | 4755 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO); |
4440 | pSMB->hdr.smb_buf_length += byte_count; | 4756 | inc_rfc1001_len(pSMB, byte_count); |
4441 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4757 | pSMB->ByteCount = cpu_to_le16(byte_count); |
4442 | 4758 | ||
4443 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4759 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -4447,7 +4763,7 @@ QFSAttributeRetry: | |||
4447 | } else { /* decode response */ | 4763 | } else { /* decode response */ |
4448 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 4764 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
4449 | 4765 | ||
4450 | if (rc || (pSMBr->ByteCount < 13)) { | 4766 | if (rc || get_bcc(&pSMBr->hdr) < 13) { |
4451 | /* BB also check if enough bytes returned */ | 4767 | /* BB also check if enough bytes returned */ |
4452 | rc = -EIO; /* bad smb */ | 4768 | rc = -EIO; /* bad smb */ |
4453 | } else { | 4769 | } else { |
@@ -4469,7 +4785,7 @@ QFSAttributeRetry: | |||
4469 | } | 4785 | } |
4470 | 4786 | ||
4471 | int | 4787 | int |
4472 | CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon) | 4788 | CIFSSMBQFSDeviceInfo(const int xid, struct cifs_tcon *tcon) |
4473 | { | 4789 | { |
4474 | /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */ | 4790 | /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */ |
4475 | TRANSACTION2_QFSI_REQ *pSMB = NULL; | 4791 | TRANSACTION2_QFSI_REQ *pSMB = NULL; |
@@ -4508,7 +4824,7 @@ QFSDeviceRetry: | |||
4508 | pSMB->Reserved3 = 0; | 4824 | pSMB->Reserved3 = 0; |
4509 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); | 4825 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); |
4510 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO); | 4826 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO); |
4511 | pSMB->hdr.smb_buf_length += byte_count; | 4827 | inc_rfc1001_len(pSMB, byte_count); |
4512 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4828 | pSMB->ByteCount = cpu_to_le16(byte_count); |
4513 | 4829 | ||
4514 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4830 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -4518,7 +4834,8 @@ QFSDeviceRetry: | |||
4518 | } else { /* decode response */ | 4834 | } else { /* decode response */ |
4519 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 4835 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
4520 | 4836 | ||
4521 | if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO))) | 4837 | if (rc || get_bcc(&pSMBr->hdr) < |
4838 | sizeof(FILE_SYSTEM_DEVICE_INFO)) | ||
4522 | rc = -EIO; /* bad smb */ | 4839 | rc = -EIO; /* bad smb */ |
4523 | else { | 4840 | else { |
4524 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); | 4841 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); |
@@ -4539,7 +4856,7 @@ QFSDeviceRetry: | |||
4539 | } | 4856 | } |
4540 | 4857 | ||
4541 | int | 4858 | int |
4542 | CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon) | 4859 | CIFSSMBQFSUnixInfo(const int xid, struct cifs_tcon *tcon) |
4543 | { | 4860 | { |
4544 | /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */ | 4861 | /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */ |
4545 | TRANSACTION2_QFSI_REQ *pSMB = NULL; | 4862 | TRANSACTION2_QFSI_REQ *pSMB = NULL; |
@@ -4577,7 +4894,7 @@ QFSUnixRetry: | |||
4577 | pSMB->Reserved3 = 0; | 4894 | pSMB->Reserved3 = 0; |
4578 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); | 4895 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); |
4579 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO); | 4896 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO); |
4580 | pSMB->hdr.smb_buf_length += byte_count; | 4897 | inc_rfc1001_len(pSMB, byte_count); |
4581 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4898 | pSMB->ByteCount = cpu_to_le16(byte_count); |
4582 | 4899 | ||
4583 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4900 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -4587,7 +4904,7 @@ QFSUnixRetry: | |||
4587 | } else { /* decode response */ | 4904 | } else { /* decode response */ |
4588 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 4905 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
4589 | 4906 | ||
4590 | if (rc || (pSMBr->ByteCount < 13)) { | 4907 | if (rc || get_bcc(&pSMBr->hdr) < 13) { |
4591 | rc = -EIO; /* bad smb */ | 4908 | rc = -EIO; /* bad smb */ |
4592 | } else { | 4909 | } else { |
4593 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); | 4910 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); |
@@ -4609,7 +4926,7 @@ QFSUnixRetry: | |||
4609 | } | 4926 | } |
4610 | 4927 | ||
4611 | int | 4928 | int |
4612 | CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap) | 4929 | CIFSSMBSetFSUnixInfo(const int xid, struct cifs_tcon *tcon, __u64 cap) |
4613 | { | 4930 | { |
4614 | /* level 0x200 SMB_SET_CIFS_UNIX_INFO */ | 4931 | /* level 0x200 SMB_SET_CIFS_UNIX_INFO */ |
4615 | TRANSACTION2_SETFSI_REQ *pSMB = NULL; | 4932 | TRANSACTION2_SETFSI_REQ *pSMB = NULL; |
@@ -4660,7 +4977,7 @@ SETFSUnixRetry: | |||
4660 | pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION); | 4977 | pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION); |
4661 | pSMB->ClientUnixCap = cpu_to_le64(cap); | 4978 | pSMB->ClientUnixCap = cpu_to_le64(cap); |
4662 | 4979 | ||
4663 | pSMB->hdr.smb_buf_length += byte_count; | 4980 | inc_rfc1001_len(pSMB, byte_count); |
4664 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4981 | pSMB->ByteCount = cpu_to_le16(byte_count); |
4665 | 4982 | ||
4666 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4983 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -4683,7 +5000,7 @@ SETFSUnixRetry: | |||
4683 | 5000 | ||
4684 | 5001 | ||
4685 | int | 5002 | int |
4686 | CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon, | 5003 | CIFSSMBQFSPosixInfo(const int xid, struct cifs_tcon *tcon, |
4687 | struct kstatfs *FSData) | 5004 | struct kstatfs *FSData) |
4688 | { | 5005 | { |
4689 | /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */ | 5006 | /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */ |
@@ -4722,7 +5039,7 @@ QFSPosixRetry: | |||
4722 | pSMB->Reserved3 = 0; | 5039 | pSMB->Reserved3 = 0; |
4723 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); | 5040 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); |
4724 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO); | 5041 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO); |
4725 | pSMB->hdr.smb_buf_length += byte_count; | 5042 | inc_rfc1001_len(pSMB, byte_count); |
4726 | pSMB->ByteCount = cpu_to_le16(byte_count); | 5043 | pSMB->ByteCount = cpu_to_le16(byte_count); |
4727 | 5044 | ||
4728 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 5045 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -4732,7 +5049,7 @@ QFSPosixRetry: | |||
4732 | } else { /* decode response */ | 5049 | } else { /* decode response */ |
4733 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 5050 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
4734 | 5051 | ||
4735 | if (rc || (pSMBr->ByteCount < 13)) { | 5052 | if (rc || get_bcc(&pSMBr->hdr) < 13) { |
4736 | rc = -EIO; /* bad smb */ | 5053 | rc = -EIO; /* bad smb */ |
4737 | } else { | 5054 | } else { |
4738 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); | 5055 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); |
@@ -4776,7 +5093,7 @@ QFSPosixRetry: | |||
4776 | in Samba which this routine can run into */ | 5093 | in Samba which this routine can run into */ |
4777 | 5094 | ||
4778 | int | 5095 | int |
4779 | CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName, | 5096 | CIFSSMBSetEOF(const int xid, struct cifs_tcon *tcon, const char *fileName, |
4780 | __u64 size, bool SetAllocation, | 5097 | __u64 size, bool SetAllocation, |
4781 | const struct nls_table *nls_codepage, int remap) | 5098 | const struct nls_table *nls_codepage, int remap) |
4782 | { | 5099 | { |
@@ -4848,7 +5165,7 @@ SetEOFRetry: | |||
4848 | pSMB->ParameterCount = cpu_to_le16(params); | 5165 | pSMB->ParameterCount = cpu_to_le16(params); |
4849 | pSMB->TotalParameterCount = pSMB->ParameterCount; | 5166 | pSMB->TotalParameterCount = pSMB->ParameterCount; |
4850 | pSMB->Reserved4 = 0; | 5167 | pSMB->Reserved4 = 0; |
4851 | pSMB->hdr.smb_buf_length += byte_count; | 5168 | inc_rfc1001_len(pSMB, byte_count); |
4852 | parm_data->FileSize = cpu_to_le64(size); | 5169 | parm_data->FileSize = cpu_to_le64(size); |
4853 | pSMB->ByteCount = cpu_to_le16(byte_count); | 5170 | pSMB->ByteCount = cpu_to_le16(byte_count); |
4854 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 5171 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -4865,11 +5182,10 @@ SetEOFRetry: | |||
4865 | } | 5182 | } |
4866 | 5183 | ||
4867 | int | 5184 | int |
4868 | CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size, | 5185 | CIFSSMBSetFileSize(const int xid, struct cifs_tcon *tcon, __u64 size, |
4869 | __u16 fid, __u32 pid_of_opener, bool SetAllocation) | 5186 | __u16 fid, __u32 pid_of_opener, bool SetAllocation) |
4870 | { | 5187 | { |
4871 | struct smb_com_transaction2_sfi_req *pSMB = NULL; | 5188 | struct smb_com_transaction2_sfi_req *pSMB = NULL; |
4872 | char *data_offset; | ||
4873 | struct file_end_of_file_info *parm_data; | 5189 | struct file_end_of_file_info *parm_data; |
4874 | int rc = 0; | 5190 | int rc = 0; |
4875 | __u16 params, param_offset, offset, byte_count, count; | 5191 | __u16 params, param_offset, offset, byte_count, count; |
@@ -4893,8 +5209,6 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size, | |||
4893 | param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4; | 5209 | param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4; |
4894 | offset = param_offset + params; | 5210 | offset = param_offset + params; |
4895 | 5211 | ||
4896 | data_offset = (char *) (&pSMB->hdr.Protocol) + offset; | ||
4897 | |||
4898 | count = sizeof(struct file_end_of_file_info); | 5212 | count = sizeof(struct file_end_of_file_info); |
4899 | pSMB->MaxParameterCount = cpu_to_le16(2); | 5213 | pSMB->MaxParameterCount = cpu_to_le16(2); |
4900 | /* BB find exact max SMB PDU from sess structure BB */ | 5214 | /* BB find exact max SMB PDU from sess structure BB */ |
@@ -4930,7 +5244,7 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size, | |||
4930 | cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO); | 5244 | cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO); |
4931 | } | 5245 | } |
4932 | pSMB->Reserved4 = 0; | 5246 | pSMB->Reserved4 = 0; |
4933 | pSMB->hdr.smb_buf_length += byte_count; | 5247 | inc_rfc1001_len(pSMB, byte_count); |
4934 | pSMB->ByteCount = cpu_to_le16(byte_count); | 5248 | pSMB->ByteCount = cpu_to_le16(byte_count); |
4935 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); | 5249 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); |
4936 | if (rc) { | 5250 | if (rc) { |
@@ -4950,7 +5264,7 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size, | |||
4950 | time and resort to the original setpathinfo level which takes the ancient | 5264 | time and resort to the original setpathinfo level which takes the ancient |
4951 | DOS time format with 2 second granularity */ | 5265 | DOS time format with 2 second granularity */ |
4952 | int | 5266 | int |
4953 | CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon, | 5267 | CIFSSMBSetFileInfo(const int xid, struct cifs_tcon *tcon, |
4954 | const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener) | 5268 | const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener) |
4955 | { | 5269 | { |
4956 | struct smb_com_transaction2_sfi_req *pSMB = NULL; | 5270 | struct smb_com_transaction2_sfi_req *pSMB = NULL; |
@@ -4998,7 +5312,7 @@ CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon, | |||
4998 | else | 5312 | else |
4999 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO); | 5313 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO); |
5000 | pSMB->Reserved4 = 0; | 5314 | pSMB->Reserved4 = 0; |
5001 | pSMB->hdr.smb_buf_length += byte_count; | 5315 | inc_rfc1001_len(pSMB, byte_count); |
5002 | pSMB->ByteCount = cpu_to_le16(byte_count); | 5316 | pSMB->ByteCount = cpu_to_le16(byte_count); |
5003 | memcpy(data_offset, data, sizeof(FILE_BASIC_INFO)); | 5317 | memcpy(data_offset, data, sizeof(FILE_BASIC_INFO)); |
5004 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); | 5318 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); |
@@ -5012,7 +5326,7 @@ CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon, | |||
5012 | } | 5326 | } |
5013 | 5327 | ||
5014 | int | 5328 | int |
5015 | CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon, | 5329 | CIFSSMBSetFileDisposition(const int xid, struct cifs_tcon *tcon, |
5016 | bool delete_file, __u16 fid, __u32 pid_of_opener) | 5330 | bool delete_file, __u16 fid, __u32 pid_of_opener) |
5017 | { | 5331 | { |
5018 | struct smb_com_transaction2_sfi_req *pSMB = NULL; | 5332 | struct smb_com_transaction2_sfi_req *pSMB = NULL; |
@@ -5057,7 +5371,7 @@ CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon, | |||
5057 | pSMB->Fid = fid; | 5371 | pSMB->Fid = fid; |
5058 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO); | 5372 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO); |
5059 | pSMB->Reserved4 = 0; | 5373 | pSMB->Reserved4 = 0; |
5060 | pSMB->hdr.smb_buf_length += byte_count; | 5374 | inc_rfc1001_len(pSMB, byte_count); |
5061 | pSMB->ByteCount = cpu_to_le16(byte_count); | 5375 | pSMB->ByteCount = cpu_to_le16(byte_count); |
5062 | *data_offset = delete_file ? 1 : 0; | 5376 | *data_offset = delete_file ? 1 : 0; |
5063 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); | 5377 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); |
@@ -5068,7 +5382,7 @@ CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon, | |||
5068 | } | 5382 | } |
5069 | 5383 | ||
5070 | int | 5384 | int |
5071 | CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon, | 5385 | CIFSSMBSetPathInfo(const int xid, struct cifs_tcon *tcon, |
5072 | const char *fileName, const FILE_BASIC_INFO *data, | 5386 | const char *fileName, const FILE_BASIC_INFO *data, |
5073 | const struct nls_table *nls_codepage, int remap) | 5387 | const struct nls_table *nls_codepage, int remap) |
5074 | { | 5388 | { |
@@ -5130,7 +5444,7 @@ SetTimesRetry: | |||
5130 | else | 5444 | else |
5131 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO); | 5445 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO); |
5132 | pSMB->Reserved4 = 0; | 5446 | pSMB->Reserved4 = 0; |
5133 | pSMB->hdr.smb_buf_length += byte_count; | 5447 | inc_rfc1001_len(pSMB, byte_count); |
5134 | memcpy(data_offset, data, sizeof(FILE_BASIC_INFO)); | 5448 | memcpy(data_offset, data, sizeof(FILE_BASIC_INFO)); |
5135 | pSMB->ByteCount = cpu_to_le16(byte_count); | 5449 | pSMB->ByteCount = cpu_to_le16(byte_count); |
5136 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 5450 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -5152,7 +5466,7 @@ SetTimesRetry: | |||
5152 | handling it anyway and NT4 was what we thought it would be needed for | 5466 | handling it anyway and NT4 was what we thought it would be needed for |
5153 | Do not delete it until we prove whether needed for Win9x though */ | 5467 | Do not delete it until we prove whether needed for Win9x though */ |
5154 | int | 5468 | int |
5155 | CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName, | 5469 | CIFSSMBSetAttrLegacy(int xid, struct cifs_tcon *tcon, char *fileName, |
5156 | __u16 dos_attrs, const struct nls_table *nls_codepage) | 5470 | __u16 dos_attrs, const struct nls_table *nls_codepage) |
5157 | { | 5471 | { |
5158 | SETATTR_REQ *pSMB = NULL; | 5472 | SETATTR_REQ *pSMB = NULL; |
@@ -5182,7 +5496,7 @@ SetAttrLgcyRetry: | |||
5182 | } | 5496 | } |
5183 | pSMB->attr = cpu_to_le16(dos_attrs); | 5497 | pSMB->attr = cpu_to_le16(dos_attrs); |
5184 | pSMB->BufferFormat = 0x04; | 5498 | pSMB->BufferFormat = 0x04; |
5185 | pSMB->hdr.smb_buf_length += name_len + 1; | 5499 | inc_rfc1001_len(pSMB, name_len + 1); |
5186 | pSMB->ByteCount = cpu_to_le16(name_len + 1); | 5500 | pSMB->ByteCount = cpu_to_le16(name_len + 1); |
5187 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 5501 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
5188 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 5502 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -5208,7 +5522,7 @@ cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset, | |||
5208 | * Samba server ignores set of file size to zero due to bugs in some | 5522 | * Samba server ignores set of file size to zero due to bugs in some |
5209 | * older clients, but we should be precise - we use SetFileSize to | 5523 | * older clients, but we should be precise - we use SetFileSize to |
5210 | * set file size and do not want to truncate file size to zero | 5524 | * set file size and do not want to truncate file size to zero |
5211 | * accidently as happened on one Samba server beta by putting | 5525 | * accidentally as happened on one Samba server beta by putting |
5212 | * zero instead of -1 here | 5526 | * zero instead of -1 here |
5213 | */ | 5527 | */ |
5214 | data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64); | 5528 | data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64); |
@@ -5240,7 +5554,7 @@ cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset, | |||
5240 | } | 5554 | } |
5241 | 5555 | ||
5242 | int | 5556 | int |
5243 | CIFSSMBUnixSetFileInfo(const int xid, struct cifsTconInfo *tcon, | 5557 | CIFSSMBUnixSetFileInfo(const int xid, struct cifs_tcon *tcon, |
5244 | const struct cifs_unix_set_info_args *args, | 5558 | const struct cifs_unix_set_info_args *args, |
5245 | u16 fid, u32 pid_of_opener) | 5559 | u16 fid, u32 pid_of_opener) |
5246 | { | 5560 | { |
@@ -5287,7 +5601,7 @@ CIFSSMBUnixSetFileInfo(const int xid, struct cifsTconInfo *tcon, | |||
5287 | pSMB->Fid = fid; | 5601 | pSMB->Fid = fid; |
5288 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC); | 5602 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC); |
5289 | pSMB->Reserved4 = 0; | 5603 | pSMB->Reserved4 = 0; |
5290 | pSMB->hdr.smb_buf_length += byte_count; | 5604 | inc_rfc1001_len(pSMB, byte_count); |
5291 | pSMB->ByteCount = cpu_to_le16(byte_count); | 5605 | pSMB->ByteCount = cpu_to_le16(byte_count); |
5292 | 5606 | ||
5293 | cifs_fill_unix_set_info(data_offset, args); | 5607 | cifs_fill_unix_set_info(data_offset, args); |
@@ -5303,7 +5617,7 @@ CIFSSMBUnixSetFileInfo(const int xid, struct cifsTconInfo *tcon, | |||
5303 | } | 5617 | } |
5304 | 5618 | ||
5305 | int | 5619 | int |
5306 | CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *tcon, char *fileName, | 5620 | CIFSSMBUnixSetPathInfo(const int xid, struct cifs_tcon *tcon, char *fileName, |
5307 | const struct cifs_unix_set_info_args *args, | 5621 | const struct cifs_unix_set_info_args *args, |
5308 | const struct nls_table *nls_codepage, int remap) | 5622 | const struct nls_table *nls_codepage, int remap) |
5309 | { | 5623 | { |
@@ -5363,7 +5677,7 @@ setPermsRetry: | |||
5363 | pSMB->TotalDataCount = pSMB->DataCount; | 5677 | pSMB->TotalDataCount = pSMB->DataCount; |
5364 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC); | 5678 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC); |
5365 | pSMB->Reserved4 = 0; | 5679 | pSMB->Reserved4 = 0; |
5366 | pSMB->hdr.smb_buf_length += byte_count; | 5680 | inc_rfc1001_len(pSMB, byte_count); |
5367 | 5681 | ||
5368 | cifs_fill_unix_set_info(data_offset, args); | 5682 | cifs_fill_unix_set_info(data_offset, args); |
5369 | 5683 | ||
@@ -5379,79 +5693,6 @@ setPermsRetry: | |||
5379 | return rc; | 5693 | return rc; |
5380 | } | 5694 | } |
5381 | 5695 | ||
5382 | int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, | ||
5383 | const int notify_subdirs, const __u16 netfid, | ||
5384 | __u32 filter, struct file *pfile, int multishot, | ||
5385 | const struct nls_table *nls_codepage) | ||
5386 | { | ||
5387 | int rc = 0; | ||
5388 | struct smb_com_transaction_change_notify_req *pSMB = NULL; | ||
5389 | struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL; | ||
5390 | struct dir_notify_req *dnotify_req; | ||
5391 | int bytes_returned; | ||
5392 | |||
5393 | cFYI(1, "In CIFSSMBNotify for file handle %d", (int)netfid); | ||
5394 | rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB, | ||
5395 | (void **) &pSMBr); | ||
5396 | if (rc) | ||
5397 | return rc; | ||
5398 | |||
5399 | pSMB->TotalParameterCount = 0 ; | ||
5400 | pSMB->TotalDataCount = 0; | ||
5401 | pSMB->MaxParameterCount = cpu_to_le32(2); | ||
5402 | /* BB find exact data count max from sess structure BB */ | ||
5403 | pSMB->MaxDataCount = 0; /* same in little endian or be */ | ||
5404 | /* BB VERIFY verify which is correct for above BB */ | ||
5405 | pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf - | ||
5406 | MAX_CIFS_HDR_SIZE) & 0xFFFFFF00); | ||
5407 | |||
5408 | pSMB->MaxSetupCount = 4; | ||
5409 | pSMB->Reserved = 0; | ||
5410 | pSMB->ParameterOffset = 0; | ||
5411 | pSMB->DataCount = 0; | ||
5412 | pSMB->DataOffset = 0; | ||
5413 | pSMB->SetupCount = 4; /* single byte does not need le conversion */ | ||
5414 | pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE); | ||
5415 | pSMB->ParameterCount = pSMB->TotalParameterCount; | ||
5416 | if (notify_subdirs) | ||
5417 | pSMB->WatchTree = 1; /* one byte - no le conversion needed */ | ||
5418 | pSMB->Reserved2 = 0; | ||
5419 | pSMB->CompletionFilter = cpu_to_le32(filter); | ||
5420 | pSMB->Fid = netfid; /* file handle always le */ | ||
5421 | pSMB->ByteCount = 0; | ||
5422 | |||
5423 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | ||
5424 | (struct smb_hdr *)pSMBr, &bytes_returned, | ||
5425 | CIFS_ASYNC_OP); | ||
5426 | if (rc) { | ||
5427 | cFYI(1, "Error in Notify = %d", rc); | ||
5428 | } else { | ||
5429 | /* Add file to outstanding requests */ | ||
5430 | /* BB change to kmem cache alloc */ | ||
5431 | dnotify_req = kmalloc( | ||
5432 | sizeof(struct dir_notify_req), | ||
5433 | GFP_KERNEL); | ||
5434 | if (dnotify_req) { | ||
5435 | dnotify_req->Pid = pSMB->hdr.Pid; | ||
5436 | dnotify_req->PidHigh = pSMB->hdr.PidHigh; | ||
5437 | dnotify_req->Mid = pSMB->hdr.Mid; | ||
5438 | dnotify_req->Tid = pSMB->hdr.Tid; | ||
5439 | dnotify_req->Uid = pSMB->hdr.Uid; | ||
5440 | dnotify_req->netfid = netfid; | ||
5441 | dnotify_req->pfile = pfile; | ||
5442 | dnotify_req->filter = filter; | ||
5443 | dnotify_req->multishot = multishot; | ||
5444 | spin_lock(&GlobalMid_Lock); | ||
5445 | list_add_tail(&dnotify_req->lhead, | ||
5446 | &GlobalDnotifyReqList); | ||
5447 | spin_unlock(&GlobalMid_Lock); | ||
5448 | } else | ||
5449 | rc = -ENOMEM; | ||
5450 | } | ||
5451 | cifs_buf_release(pSMB); | ||
5452 | return rc; | ||
5453 | } | ||
5454 | |||
5455 | #ifdef CONFIG_CIFS_XATTR | 5696 | #ifdef CONFIG_CIFS_XATTR |
5456 | /* | 5697 | /* |
5457 | * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common | 5698 | * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common |
@@ -5463,7 +5704,7 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, | |||
5463 | * the data isn't copied to it, but the length is returned. | 5704 | * the data isn't copied to it, but the length is returned. |
5464 | */ | 5705 | */ |
5465 | ssize_t | 5706 | ssize_t |
5466 | CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon, | 5707 | CIFSSMBQAllEAs(const int xid, struct cifs_tcon *tcon, |
5467 | const unsigned char *searchName, const unsigned char *ea_name, | 5708 | const unsigned char *searchName, const unsigned char *ea_name, |
5468 | char *EAData, size_t buf_size, | 5709 | char *EAData, size_t buf_size, |
5469 | const struct nls_table *nls_codepage, int remap) | 5710 | const struct nls_table *nls_codepage, int remap) |
@@ -5521,7 +5762,7 @@ QAllEAsRetry: | |||
5521 | pSMB->ParameterCount = pSMB->TotalParameterCount; | 5762 | pSMB->ParameterCount = pSMB->TotalParameterCount; |
5522 | pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS); | 5763 | pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS); |
5523 | pSMB->Reserved4 = 0; | 5764 | pSMB->Reserved4 = 0; |
5524 | pSMB->hdr.smb_buf_length += byte_count; | 5765 | inc_rfc1001_len(pSMB, byte_count); |
5525 | pSMB->ByteCount = cpu_to_le16(byte_count); | 5766 | pSMB->ByteCount = cpu_to_le16(byte_count); |
5526 | 5767 | ||
5527 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 5768 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -5537,7 +5778,7 @@ QAllEAsRetry: | |||
5537 | of these trans2 responses */ | 5778 | of these trans2 responses */ |
5538 | 5779 | ||
5539 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 5780 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
5540 | if (rc || (pSMBr->ByteCount < 4)) { | 5781 | if (rc || get_bcc(&pSMBr->hdr) < 4) { |
5541 | rc = -EIO; /* bad smb */ | 5782 | rc = -EIO; /* bad smb */ |
5542 | goto QAllEAsOut; | 5783 | goto QAllEAsOut; |
5543 | } | 5784 | } |
@@ -5562,7 +5803,7 @@ QAllEAsRetry: | |||
5562 | } | 5803 | } |
5563 | 5804 | ||
5564 | /* make sure list_len doesn't go past end of SMB */ | 5805 | /* make sure list_len doesn't go past end of SMB */ |
5565 | end_of_smb = (char *)pByteArea(&pSMBr->hdr) + BCC(&pSMBr->hdr); | 5806 | end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr); |
5566 | if ((char *)ea_response_data + list_len > end_of_smb) { | 5807 | if ((char *)ea_response_data + list_len > end_of_smb) { |
5567 | cFYI(1, "EA list appears to go beyond SMB"); | 5808 | cFYI(1, "EA list appears to go beyond SMB"); |
5568 | rc = -EIO; | 5809 | rc = -EIO; |
@@ -5644,7 +5885,7 @@ QAllEAsOut: | |||
5644 | } | 5885 | } |
5645 | 5886 | ||
5646 | int | 5887 | int |
5647 | CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName, | 5888 | CIFSSMBSetEA(const int xid, struct cifs_tcon *tcon, const char *fileName, |
5648 | const char *ea_name, const void *ea_value, | 5889 | const char *ea_name, const void *ea_value, |
5649 | const __u16 ea_value_len, const struct nls_table *nls_codepage, | 5890 | const __u16 ea_value_len, const struct nls_table *nls_codepage, |
5650 | int remap) | 5891 | int remap) |
@@ -5734,7 +5975,7 @@ SetEARetry: | |||
5734 | pSMB->ParameterCount = cpu_to_le16(params); | 5975 | pSMB->ParameterCount = cpu_to_le16(params); |
5735 | pSMB->TotalParameterCount = pSMB->ParameterCount; | 5976 | pSMB->TotalParameterCount = pSMB->ParameterCount; |
5736 | pSMB->Reserved4 = 0; | 5977 | pSMB->Reserved4 = 0; |
5737 | pSMB->hdr.smb_buf_length += byte_count; | 5978 | inc_rfc1001_len(pSMB, byte_count); |
5738 | pSMB->ByteCount = cpu_to_le16(byte_count); | 5979 | pSMB->ByteCount = cpu_to_le16(byte_count); |
5739 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 5980 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
5740 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 5981 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -5748,5 +5989,99 @@ SetEARetry: | |||
5748 | 5989 | ||
5749 | return rc; | 5990 | return rc; |
5750 | } | 5991 | } |
5751 | |||
5752 | #endif | 5992 | #endif |
5993 | |||
5994 | #ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* BB unused temporarily */ | ||
5995 | /* | ||
5996 | * Years ago the kernel added a "dnotify" function for Samba server, | ||
5997 | * to allow network clients (such as Windows) to display updated | ||
5998 | * lists of files in directory listings automatically when | ||
5999 | * files are added by one user when another user has the | ||
6000 | * same directory open on their desktop. The Linux cifs kernel | ||
6001 | * client hooked into the kernel side of this interface for | ||
6002 | * the same reason, but ironically when the VFS moved from | ||
6003 | * "dnotify" to "inotify" it became harder to plug in Linux | ||
6004 | * network file system clients (the most obvious use case | ||
6005 | * for notify interfaces is when multiple users can update | ||
6006 | * the contents of the same directory - exactly what network | ||
6007 | * file systems can do) although the server (Samba) could | ||
6008 | * still use it. For the short term we leave the worker | ||
6009 | * function ifdeffed out (below) until inotify is fixed | ||
6010 | * in the VFS to make it easier to plug in network file | ||
6011 | * system clients. If inotify turns out to be permanently | ||
6012 | * incompatible for network fs clients, we could instead simply | ||
6013 | * expose this config flag by adding a future cifs (and smb2) notify ioctl. | ||
6014 | */ | ||
6015 | int CIFSSMBNotify(const int xid, struct cifs_tcon *tcon, | ||
6016 | const int notify_subdirs, const __u16 netfid, | ||
6017 | __u32 filter, struct file *pfile, int multishot, | ||
6018 | const struct nls_table *nls_codepage) | ||
6019 | { | ||
6020 | int rc = 0; | ||
6021 | struct smb_com_transaction_change_notify_req *pSMB = NULL; | ||
6022 | struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL; | ||
6023 | struct dir_notify_req *dnotify_req; | ||
6024 | int bytes_returned; | ||
6025 | |||
6026 | cFYI(1, "In CIFSSMBNotify for file handle %d", (int)netfid); | ||
6027 | rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB, | ||
6028 | (void **) &pSMBr); | ||
6029 | if (rc) | ||
6030 | return rc; | ||
6031 | |||
6032 | pSMB->TotalParameterCount = 0 ; | ||
6033 | pSMB->TotalDataCount = 0; | ||
6034 | pSMB->MaxParameterCount = cpu_to_le32(2); | ||
6035 | /* BB find exact data count max from sess structure BB */ | ||
6036 | pSMB->MaxDataCount = 0; /* same in little endian or be */ | ||
6037 | /* BB VERIFY verify which is correct for above BB */ | ||
6038 | pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf - | ||
6039 | MAX_CIFS_HDR_SIZE) & 0xFFFFFF00); | ||
6040 | |||
6041 | pSMB->MaxSetupCount = 4; | ||
6042 | pSMB->Reserved = 0; | ||
6043 | pSMB->ParameterOffset = 0; | ||
6044 | pSMB->DataCount = 0; | ||
6045 | pSMB->DataOffset = 0; | ||
6046 | pSMB->SetupCount = 4; /* single byte does not need le conversion */ | ||
6047 | pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE); | ||
6048 | pSMB->ParameterCount = pSMB->TotalParameterCount; | ||
6049 | if (notify_subdirs) | ||
6050 | pSMB->WatchTree = 1; /* one byte - no le conversion needed */ | ||
6051 | pSMB->Reserved2 = 0; | ||
6052 | pSMB->CompletionFilter = cpu_to_le32(filter); | ||
6053 | pSMB->Fid = netfid; /* file handle always le */ | ||
6054 | pSMB->ByteCount = 0; | ||
6055 | |||
6056 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | ||
6057 | (struct smb_hdr *)pSMBr, &bytes_returned, | ||
6058 | CIFS_ASYNC_OP); | ||
6059 | if (rc) { | ||
6060 | cFYI(1, "Error in Notify = %d", rc); | ||
6061 | } else { | ||
6062 | /* Add file to outstanding requests */ | ||
6063 | /* BB change to kmem cache alloc */ | ||
6064 | dnotify_req = kmalloc( | ||
6065 | sizeof(struct dir_notify_req), | ||
6066 | GFP_KERNEL); | ||
6067 | if (dnotify_req) { | ||
6068 | dnotify_req->Pid = pSMB->hdr.Pid; | ||
6069 | dnotify_req->PidHigh = pSMB->hdr.PidHigh; | ||
6070 | dnotify_req->Mid = pSMB->hdr.Mid; | ||
6071 | dnotify_req->Tid = pSMB->hdr.Tid; | ||
6072 | dnotify_req->Uid = pSMB->hdr.Uid; | ||
6073 | dnotify_req->netfid = netfid; | ||
6074 | dnotify_req->pfile = pfile; | ||
6075 | dnotify_req->filter = filter; | ||
6076 | dnotify_req->multishot = multishot; | ||
6077 | spin_lock(&GlobalMid_Lock); | ||
6078 | list_add_tail(&dnotify_req->lhead, | ||
6079 | &GlobalDnotifyReqList); | ||
6080 | spin_unlock(&GlobalMid_Lock); | ||
6081 | } else | ||
6082 | rc = -ENOMEM; | ||
6083 | } | ||
6084 | cifs_buf_release(pSMB); | ||
6085 | return rc; | ||
6086 | } | ||
6087 | #endif /* was needed for dnotify, and will be needed for inotify when VFS fix */ | ||