Loading...
1/*
2 * fs/cifs/cifssmb.c
3 *
4 * Copyright (C) International Business Machines Corp., 2002,2010
5 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * Contains the routines for constructing the SMB PDUs themselves
8 *
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24 /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c */
25 /* These are mostly routines that operate on a pathname, or on a tree id */
26 /* (mounted volume), but there are eight handle based routines which must be */
27 /* treated slightly differently for reconnection purposes since we never */
28 /* want to reuse a stale file handle and only the caller knows the file info */
29
30#include <linux/fs.h>
31#include <linux/kernel.h>
32#include <linux/vfs.h>
33#include <linux/slab.h>
34#include <linux/posix_acl_xattr.h>
35#include <linux/pagemap.h>
36#include <asm/uaccess.h>
37#include "cifspdu.h"
38#include "cifsglob.h"
39#include "cifsacl.h"
40#include "cifsproto.h"
41#include "cifs_unicode.h"
42#include "cifs_debug.h"
43
44#ifdef CONFIG_CIFS_POSIX
45static struct {
46 int index;
47 char *name;
48} protocols[] = {
49#ifdef CONFIG_CIFS_WEAK_PW_HASH
50 {LANMAN_PROT, "\2LM1.2X002"},
51 {LANMAN2_PROT, "\2LANMAN2.1"},
52#endif /* weak password hashing for legacy clients */
53 {CIFS_PROT, "\2NT LM 0.12"},
54 {POSIX_PROT, "\2POSIX 2"},
55 {BAD_PROT, "\2"}
56};
57#else
58static struct {
59 int index;
60 char *name;
61} protocols[] = {
62#ifdef CONFIG_CIFS_WEAK_PW_HASH
63 {LANMAN_PROT, "\2LM1.2X002"},
64 {LANMAN2_PROT, "\2LANMAN2.1"},
65#endif /* weak password hashing for legacy clients */
66 {CIFS_PROT, "\2NT LM 0.12"},
67 {BAD_PROT, "\2"}
68};
69#endif
70
71/* define the number of elements in the cifs dialect array */
72#ifdef CONFIG_CIFS_POSIX
73#ifdef CONFIG_CIFS_WEAK_PW_HASH
74#define CIFS_NUM_PROT 4
75#else
76#define CIFS_NUM_PROT 2
77#endif /* CIFS_WEAK_PW_HASH */
78#else /* not posix */
79#ifdef CONFIG_CIFS_WEAK_PW_HASH
80#define CIFS_NUM_PROT 3
81#else
82#define CIFS_NUM_PROT 1
83#endif /* CONFIG_CIFS_WEAK_PW_HASH */
84#endif /* CIFS_POSIX */
85
86/* Mark as invalid, all open files on tree connections since they
87 were closed when session to server was lost */
88static void mark_open_files_invalid(struct cifs_tcon *pTcon)
89{
90 struct cifsFileInfo *open_file = NULL;
91 struct list_head *tmp;
92 struct list_head *tmp1;
93
94/* list all files open on tree connection and mark them invalid */
95 spin_lock(&cifs_file_list_lock);
96 list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
97 open_file = list_entry(tmp, struct cifsFileInfo, tlist);
98 open_file->invalidHandle = true;
99 open_file->oplock_break_cancelled = true;
100 }
101 spin_unlock(&cifs_file_list_lock);
102 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
103 to this tcon */
104}
105
106/* reconnect the socket, tcon, and smb session if needed */
107static int
108cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
109{
110 int rc;
111 struct cifs_ses *ses;
112 struct TCP_Server_Info *server;
113 struct nls_table *nls_codepage;
114
115 /*
116 * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for
117 * tcp and smb session status done differently for those three - in the
118 * calling routine
119 */
120 if (!tcon)
121 return 0;
122
123 ses = tcon->ses;
124 server = ses->server;
125
126 /*
127 * only tree disconnect, open, and write, (and ulogoff which does not
128 * have tcon) are allowed as we start force umount
129 */
130 if (tcon->tidStatus == CifsExiting) {
131 if (smb_command != SMB_COM_WRITE_ANDX &&
132 smb_command != SMB_COM_OPEN_ANDX &&
133 smb_command != SMB_COM_TREE_DISCONNECT) {
134 cFYI(1, "can not send cmd %d while umounting",
135 smb_command);
136 return -ENODEV;
137 }
138 }
139
140 /*
141 * Give demultiplex thread up to 10 seconds to reconnect, should be
142 * greater than cifs socket timeout which is 7 seconds
143 */
144 while (server->tcpStatus == CifsNeedReconnect) {
145 wait_event_interruptible_timeout(server->response_q,
146 (server->tcpStatus != CifsNeedReconnect), 10 * HZ);
147
148 /* are we still trying to reconnect? */
149 if (server->tcpStatus != CifsNeedReconnect)
150 break;
151
152 /*
153 * on "soft" mounts we wait once. Hard mounts keep
154 * retrying until process is killed or server comes
155 * back on-line
156 */
157 if (!tcon->retry) {
158 cFYI(1, "gave up waiting on reconnect in smb_init");
159 return -EHOSTDOWN;
160 }
161 }
162
163 if (!ses->need_reconnect && !tcon->need_reconnect)
164 return 0;
165
166 nls_codepage = load_nls_default();
167
168 /*
169 * need to prevent multiple threads trying to simultaneously
170 * reconnect the same SMB session
171 */
172 mutex_lock(&ses->session_mutex);
173 rc = cifs_negotiate_protocol(0, ses);
174 if (rc == 0 && ses->need_reconnect)
175 rc = cifs_setup_session(0, ses, nls_codepage);
176
177 /* do we need to reconnect tcon? */
178 if (rc || !tcon->need_reconnect) {
179 mutex_unlock(&ses->session_mutex);
180 goto out;
181 }
182
183 mark_open_files_invalid(tcon);
184 rc = CIFSTCon(0, ses, tcon->treeName, tcon, nls_codepage);
185 mutex_unlock(&ses->session_mutex);
186 cFYI(1, "reconnect tcon rc = %d", rc);
187
188 if (rc)
189 goto out;
190
191 /*
192 * FIXME: check if wsize needs updated due to negotiated smb buffer
193 * size shrinking
194 */
195 atomic_inc(&tconInfoReconnectCount);
196
197 /* tell server Unix caps we support */
198 if (ses->capabilities & CAP_UNIX)
199 reset_cifs_unix_caps(0, tcon, NULL, NULL);
200
201 /*
202 * Removed call to reopen open files here. It is safer (and faster) to
203 * reopen files one at a time as needed in read and write.
204 *
205 * FIXME: what about file locks? don't we need to reclaim them ASAP?
206 */
207
208out:
209 /*
210 * Check if handle based operation so we know whether we can continue
211 * or not without returning to caller to reset file handle
212 */
213 switch (smb_command) {
214 case SMB_COM_READ_ANDX:
215 case SMB_COM_WRITE_ANDX:
216 case SMB_COM_CLOSE:
217 case SMB_COM_FIND_CLOSE2:
218 case SMB_COM_LOCKING_ANDX:
219 rc = -EAGAIN;
220 }
221
222 unload_nls(nls_codepage);
223 return rc;
224}
225
226/* Allocate and return pointer to an SMB request buffer, and set basic
227 SMB information in the SMB header. If the return code is zero, this
228 function must have filled in request_buf pointer */
229static int
230small_smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
231 void **request_buf)
232{
233 int rc;
234
235 rc = cifs_reconnect_tcon(tcon, smb_command);
236 if (rc)
237 return rc;
238
239 *request_buf = cifs_small_buf_get();
240 if (*request_buf == NULL) {
241 /* BB should we add a retry in here if not a writepage? */
242 return -ENOMEM;
243 }
244
245 header_assemble((struct smb_hdr *) *request_buf, smb_command,
246 tcon, wct);
247
248 if (tcon != NULL)
249 cifs_stats_inc(&tcon->num_smbs_sent);
250
251 return 0;
252}
253
254int
255small_smb_init_no_tc(const int smb_command, const int wct,
256 struct cifs_ses *ses, void **request_buf)
257{
258 int rc;
259 struct smb_hdr *buffer;
260
261 rc = small_smb_init(smb_command, wct, NULL, request_buf);
262 if (rc)
263 return rc;
264
265 buffer = (struct smb_hdr *)*request_buf;
266 buffer->Mid = GetNextMid(ses->server);
267 if (ses->capabilities & CAP_UNICODE)
268 buffer->Flags2 |= SMBFLG2_UNICODE;
269 if (ses->capabilities & CAP_STATUS32)
270 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
271
272 /* uid, tid can stay at zero as set in header assemble */
273
274 /* BB add support for turning on the signing when
275 this function is used after 1st of session setup requests */
276
277 return rc;
278}
279
280/* If the return code is zero, this function must fill in request_buf pointer */
281static int
282__smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
283 void **request_buf, void **response_buf)
284{
285 *request_buf = cifs_buf_get();
286 if (*request_buf == NULL) {
287 /* BB should we add a retry in here if not a writepage? */
288 return -ENOMEM;
289 }
290 /* Although the original thought was we needed the response buf for */
291 /* potential retries of smb operations it turns out we can determine */
292 /* from the mid flags when the request buffer can be resent without */
293 /* having to use a second distinct buffer for the response */
294 if (response_buf)
295 *response_buf = *request_buf;
296
297 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
298 wct);
299
300 if (tcon != NULL)
301 cifs_stats_inc(&tcon->num_smbs_sent);
302
303 return 0;
304}
305
306/* If the return code is zero, this function must fill in request_buf pointer */
307static int
308smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
309 void **request_buf, void **response_buf)
310{
311 int rc;
312
313 rc = cifs_reconnect_tcon(tcon, smb_command);
314 if (rc)
315 return rc;
316
317 return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
318}
319
320static int
321smb_init_no_reconnect(int smb_command, int wct, struct cifs_tcon *tcon,
322 void **request_buf, void **response_buf)
323{
324 if (tcon->ses->need_reconnect || tcon->need_reconnect)
325 return -EHOSTDOWN;
326
327 return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
328}
329
330static int validate_t2(struct smb_t2_rsp *pSMB)
331{
332 unsigned int total_size;
333
334 /* check for plausible wct */
335 if (pSMB->hdr.WordCount < 10)
336 goto vt2_err;
337
338 /* check for parm and data offset going beyond end of smb */
339 if (get_unaligned_le16(&pSMB->t2_rsp.ParameterOffset) > 1024 ||
340 get_unaligned_le16(&pSMB->t2_rsp.DataOffset) > 1024)
341 goto vt2_err;
342
343 total_size = get_unaligned_le16(&pSMB->t2_rsp.ParameterCount);
344 if (total_size >= 512)
345 goto vt2_err;
346
347 /* check that bcc is at least as big as parms + data, and that it is
348 * less than negotiated smb buffer
349 */
350 total_size += get_unaligned_le16(&pSMB->t2_rsp.DataCount);
351 if (total_size > get_bcc(&pSMB->hdr) ||
352 total_size >= CIFSMaxBufSize + MAX_CIFS_HDR_SIZE)
353 goto vt2_err;
354
355 return 0;
356vt2_err:
357 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
358 sizeof(struct smb_t2_rsp) + 16);
359 return -EINVAL;
360}
361
362static 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
369int
370CIFSSMBNegotiate(unsigned int xid, struct cifs_ses *ses)
371{
372 NEGOTIATE_REQ *pSMB;
373 NEGOTIATE_RSP *pSMBr;
374 int rc = 0;
375 int bytes_returned;
376 int i;
377 struct TCP_Server_Info *server;
378 u16 count;
379 unsigned int secFlags;
380
381 if (ses->server)
382 server = ses->server;
383 else {
384 rc = -EIO;
385 return rc;
386 }
387 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
388 (void **) &pSMB, (void **) &pSMBr);
389 if (rc)
390 return rc;
391
392 /* if any of auth flags (ie not sign or seal) are overriden use them */
393 if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
394 secFlags = ses->overrideSecFlg; /* BB FIXME fix sign flags? */
395 else /* if override flags set only sign/seal OR them with global auth */
396 secFlags = global_secflags | ses->overrideSecFlg;
397
398 cFYI(1, "secFlags 0x%x", secFlags);
399
400 pSMB->hdr.Mid = GetNextMid(server);
401 pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
402
403 if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
404 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
405 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
406 cFYI(1, "Kerberos only mechanism, enable extended security");
407 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
408 } else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
409 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
410 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) {
411 cFYI(1, "NTLMSSP only mechanism, enable extended security");
412 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
413 }
414
415 count = 0;
416 for (i = 0; i < CIFS_NUM_PROT; i++) {
417 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
418 count += strlen(protocols[i].name) + 1;
419 /* null at end of source and target buffers anyway */
420 }
421 inc_rfc1001_len(pSMB, count);
422 pSMB->ByteCount = cpu_to_le16(count);
423
424 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
425 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
426 if (rc != 0)
427 goto neg_err_exit;
428
429 server->dialect = le16_to_cpu(pSMBr->DialectIndex);
430 cFYI(1, "Dialect: %d", server->dialect);
431 /* Check wct = 1 error case */
432 if ((pSMBr->hdr.WordCount < 13) || (server->dialect == BAD_PROT)) {
433 /* core returns wct = 1, but we do not ask for core - otherwise
434 small wct just comes when dialect index is -1 indicating we
435 could not negotiate a common dialect */
436 rc = -EOPNOTSUPP;
437 goto neg_err_exit;
438#ifdef CONFIG_CIFS_WEAK_PW_HASH
439 } else if ((pSMBr->hdr.WordCount == 13)
440 && ((server->dialect == LANMAN_PROT)
441 || (server->dialect == LANMAN2_PROT))) {
442 __s16 tmp;
443 struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
444
445 if ((secFlags & CIFSSEC_MAY_LANMAN) ||
446 (secFlags & CIFSSEC_MAY_PLNTXT))
447 server->secType = LANMAN;
448 else {
449 cERROR(1, "mount failed weak security disabled"
450 " in /proc/fs/cifs/SecurityFlags");
451 rc = -EOPNOTSUPP;
452 goto neg_err_exit;
453 }
454 server->sec_mode = (__u8)le16_to_cpu(rsp->SecurityMode);
455 server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
456 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
457 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
458 server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs);
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 */
461 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
462 server->max_rw = 0xFF00;
463 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
464 } else {
465 server->max_rw = 0;/* do not need to use raw anyway */
466 server->capabilities = CAP_MPX_MODE;
467 }
468 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
469 if (tmp == -1) {
470 /* OS/2 often does not set timezone therefore
471 * we must use server time to calc time zone.
472 * Could deviate slightly from the right zone.
473 * Smallest defined timezone difference is 15 minutes
474 * (i.e. Nepal). Rounding up/down is done to match
475 * this requirement.
476 */
477 int val, seconds, remain, result;
478 struct timespec ts, utc;
479 utc = CURRENT_TIME;
480 ts = cnvrtDosUnixTm(rsp->SrvTime.Date,
481 rsp->SrvTime.Time, 0);
482 cFYI(1, "SrvTime %d sec since 1970 (utc: %d) diff: %d",
483 (int)ts.tv_sec, (int)utc.tv_sec,
484 (int)(utc.tv_sec - ts.tv_sec));
485 val = (int)(utc.tv_sec - ts.tv_sec);
486 seconds = abs(val);
487 result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
488 remain = seconds % MIN_TZ_ADJ;
489 if (remain >= (MIN_TZ_ADJ / 2))
490 result += MIN_TZ_ADJ;
491 if (val < 0)
492 result = -result;
493 server->timeAdj = result;
494 } else {
495 server->timeAdj = (int)tmp;
496 server->timeAdj *= 60; /* also in seconds */
497 }
498 cFYI(1, "server->timeAdj: %d seconds", server->timeAdj);
499
500
501 /* BB get server time for time conversions and add
502 code to use it and timezone since this is not UTC */
503
504 if (rsp->EncryptionKeyLength ==
505 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
506 memcpy(ses->server->cryptkey, rsp->EncryptionKey,
507 CIFS_CRYPTO_KEY_SIZE);
508 } else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
509 rc = -EIO; /* need cryptkey unless plain text */
510 goto neg_err_exit;
511 }
512
513 cFYI(1, "LANMAN negotiated");
514 /* we will not end up setting signing flags - as no signing
515 was in LANMAN and server did not return the flags on */
516 goto signing_check;
517#else /* weak security disabled */
518 } else if (pSMBr->hdr.WordCount == 13) {
519 cERROR(1, "mount failed, cifs module not built "
520 "with CIFS_WEAK_PW_HASH support");
521 rc = -EOPNOTSUPP;
522#endif /* WEAK_PW_HASH */
523 goto neg_err_exit;
524 } else if (pSMBr->hdr.WordCount != 17) {
525 /* unknown wct */
526 rc = -EOPNOTSUPP;
527 goto neg_err_exit;
528 }
529 /* else wct == 17 NTLM */
530 server->sec_mode = pSMBr->SecurityMode;
531 if ((server->sec_mode & SECMODE_USER) == 0)
532 cFYI(1, "share mode security");
533
534 if ((server->sec_mode & SECMODE_PW_ENCRYPT) == 0)
535#ifdef CONFIG_CIFS_WEAK_PW_HASH
536 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
537#endif /* CIFS_WEAK_PW_HASH */
538 cERROR(1, "Server requests plain text password"
539 " but client support disabled");
540
541 if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
542 server->secType = NTLMv2;
543 else if (secFlags & CIFSSEC_MAY_NTLM)
544 server->secType = NTLM;
545 else if (secFlags & CIFSSEC_MAY_NTLMV2)
546 server->secType = NTLMv2;
547 else if (secFlags & CIFSSEC_MAY_KRB5)
548 server->secType = Kerberos;
549 else if (secFlags & CIFSSEC_MAY_NTLMSSP)
550 server->secType = RawNTLMSSP;
551 else if (secFlags & CIFSSEC_MAY_LANMAN)
552 server->secType = LANMAN;
553 else {
554 rc = -EOPNOTSUPP;
555 cERROR(1, "Invalid security type");
556 goto neg_err_exit;
557 }
558 /* else ... any others ...? */
559
560 /* one byte, so no need to convert this or EncryptionKeyLen from
561 little endian */
562 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
563 /* probably no need to store and check maxvcs */
564 server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
565 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
566 server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
567 cFYI(DBG2, "Max buf = %d", ses->server->maxBuf);
568 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
569 server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
570 server->timeAdj *= 60;
571 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
572 memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey,
573 CIFS_CRYPTO_KEY_SIZE);
574 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC ||
575 server->capabilities & CAP_EXTENDED_SECURITY) &&
576 (pSMBr->EncryptionKeyLength == 0)) {
577 /* decode security blob */
578 count = get_bcc(&pSMBr->hdr);
579 if (count < 16) {
580 rc = -EIO;
581 goto neg_err_exit;
582 }
583 spin_lock(&cifs_tcp_ses_lock);
584 if (server->srv_count > 1) {
585 spin_unlock(&cifs_tcp_ses_lock);
586 if (memcmp(server->server_GUID,
587 pSMBr->u.extended_response.
588 GUID, 16) != 0) {
589 cFYI(1, "server UID changed");
590 memcpy(server->server_GUID,
591 pSMBr->u.extended_response.GUID,
592 16);
593 }
594 } else {
595 spin_unlock(&cifs_tcp_ses_lock);
596 memcpy(server->server_GUID,
597 pSMBr->u.extended_response.GUID, 16);
598 }
599
600 if (count == 16) {
601 server->secType = RawNTLMSSP;
602 } else {
603 rc = decode_negTokenInit(pSMBr->u.extended_response.
604 SecurityBlob, count - 16,
605 server);
606 if (rc == 1)
607 rc = 0;
608 else
609 rc = -EINVAL;
610 if (server->secType == Kerberos) {
611 if (!server->sec_kerberos &&
612 !server->sec_mskerberos)
613 rc = -EOPNOTSUPP;
614 } else if (server->secType == RawNTLMSSP) {
615 if (!server->sec_ntlmssp)
616 rc = -EOPNOTSUPP;
617 } else
618 rc = -EOPNOTSUPP;
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;
623 } else
624 server->capabilities &= ~CAP_EXTENDED_SECURITY;
625
626#ifdef CONFIG_CIFS_WEAK_PW_HASH
627signing_check:
628#endif
629 if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
630 /* MUST_SIGN already includes the MAY_SIGN FLAG
631 so if this is zero it means that signing is disabled */
632 cFYI(1, "Signing disabled");
633 if (server->sec_mode & SECMODE_SIGN_REQUIRED) {
634 cERROR(1, "Server requires "
635 "packet signing to be enabled in "
636 "/proc/fs/cifs/SecurityFlags.");
637 rc = -EOPNOTSUPP;
638 }
639 server->sec_mode &=
640 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
641 } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
642 /* signing required */
643 cFYI(1, "Must sign - secFlags 0x%x", secFlags);
644 if ((server->sec_mode &
645 (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
646 cERROR(1, "signing required but server lacks support");
647 rc = -EOPNOTSUPP;
648 } else
649 server->sec_mode |= SECMODE_SIGN_REQUIRED;
650 } else {
651 /* signing optional ie CIFSSEC_MAY_SIGN */
652 if ((server->sec_mode & SECMODE_SIGN_REQUIRED) == 0)
653 server->sec_mode &=
654 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
655 }
656
657neg_err_exit:
658 cifs_buf_release(pSMB);
659
660 cFYI(1, "negprot rc %d", rc);
661 return rc;
662}
663
664int
665CIFSSMBTDis(const int xid, struct cifs_tcon *tcon)
666{
667 struct smb_hdr *smb_buffer;
668 int rc = 0;
669
670 cFYI(1, "In tree disconnect");
671
672 /* BB: do we need to check this? These should never be NULL. */
673 if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
674 return -EIO;
675
676 /*
677 * No need to return error on this operation if tid invalidated and
678 * closed on server already e.g. due to tcp session crashing. Also,
679 * the tcon is no longer on the list, so no need to take lock before
680 * checking this.
681 */
682 if ((tcon->need_reconnect) || (tcon->ses->need_reconnect))
683 return 0;
684
685 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
686 (void **)&smb_buffer);
687 if (rc)
688 return rc;
689
690 rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0);
691 if (rc)
692 cFYI(1, "Tree disconnect failed %d", rc);
693
694 /* No need to return error on this operation if tid invalidated and
695 closed on server already e.g. due to tcp session crashing */
696 if (rc == -EAGAIN)
697 rc = 0;
698
699 return rc;
700}
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 */
709static void
710cifs_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
719int
720CIFSSMBEcho(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
751int
752CIFSSMBLogoff(const int xid, struct cifs_ses *ses)
753{
754 LOGOFF_ANDX_REQ *pSMB;
755 int rc = 0;
756
757 cFYI(1, "In SMBLogoff for session disconnect");
758
759 /*
760 * BB: do we need to check validity of ses and server? They should
761 * always be valid since we have an active reference. If not, that
762 * should probably be a BUG()
763 */
764 if (!ses || !ses->server)
765 return -EIO;
766
767 mutex_lock(&ses->session_mutex);
768 if (ses->need_reconnect)
769 goto session_already_dead; /* no need to send SMBlogoff if uid
770 already closed due to reconnect */
771 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
772 if (rc) {
773 mutex_unlock(&ses->session_mutex);
774 return rc;
775 }
776
777 pSMB->hdr.Mid = GetNextMid(ses->server);
778
779 if (ses->server->sec_mode &
780 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
781 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
782
783 pSMB->hdr.Uid = ses->Suid;
784
785 pSMB->AndXCommand = 0xFF;
786 rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0);
787session_already_dead:
788 mutex_unlock(&ses->session_mutex);
789
790 /* if session dead then we do not need to do ulogoff,
791 since server closed smb session, no sense reporting
792 error */
793 if (rc == -EAGAIN)
794 rc = 0;
795 return rc;
796}
797
798int
799CIFSPOSIXDelFile(const int xid, struct cifs_tcon *tcon, const char *fileName,
800 __u16 type, const struct nls_table *nls_codepage, int remap)
801{
802 TRANSACTION2_SPI_REQ *pSMB = NULL;
803 TRANSACTION2_SPI_RSP *pSMBr = NULL;
804 struct unlink_psx_rq *pRqD;
805 int name_len;
806 int rc = 0;
807 int bytes_returned = 0;
808 __u16 params, param_offset, offset, byte_count;
809
810 cFYI(1, "In POSIX delete");
811PsxDelete:
812 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
813 (void **) &pSMBr);
814 if (rc)
815 return rc;
816
817 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
818 name_len =
819 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
820 PATH_MAX, nls_codepage, remap);
821 name_len++; /* trailing null */
822 name_len *= 2;
823 } else { /* BB add path length overrun check */
824 name_len = strnlen(fileName, PATH_MAX);
825 name_len++; /* trailing null */
826 strncpy(pSMB->FileName, fileName, name_len);
827 }
828
829 params = 6 + name_len;
830 pSMB->MaxParameterCount = cpu_to_le16(2);
831 pSMB->MaxDataCount = 0; /* BB double check this with jra */
832 pSMB->MaxSetupCount = 0;
833 pSMB->Reserved = 0;
834 pSMB->Flags = 0;
835 pSMB->Timeout = 0;
836 pSMB->Reserved2 = 0;
837 param_offset = offsetof(struct smb_com_transaction2_spi_req,
838 InformationLevel) - 4;
839 offset = param_offset + params;
840
841 /* Setup pointer to Request Data (inode type) */
842 pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
843 pRqD->type = cpu_to_le16(type);
844 pSMB->ParameterOffset = cpu_to_le16(param_offset);
845 pSMB->DataOffset = cpu_to_le16(offset);
846 pSMB->SetupCount = 1;
847 pSMB->Reserved3 = 0;
848 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
849 byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
850
851 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
852 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
853 pSMB->ParameterCount = cpu_to_le16(params);
854 pSMB->TotalParameterCount = pSMB->ParameterCount;
855 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
856 pSMB->Reserved4 = 0;
857 inc_rfc1001_len(pSMB, byte_count);
858 pSMB->ByteCount = cpu_to_le16(byte_count);
859 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
860 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
861 if (rc)
862 cFYI(1, "Posix delete returned %d", rc);
863 cifs_buf_release(pSMB);
864
865 cifs_stats_inc(&tcon->num_deletes);
866
867 if (rc == -EAGAIN)
868 goto PsxDelete;
869
870 return rc;
871}
872
873int
874CIFSSMBDelFile(const int xid, struct cifs_tcon *tcon, const char *fileName,
875 const struct nls_table *nls_codepage, int remap)
876{
877 DELETE_FILE_REQ *pSMB = NULL;
878 DELETE_FILE_RSP *pSMBr = NULL;
879 int rc = 0;
880 int bytes_returned;
881 int name_len;
882
883DelFileRetry:
884 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
885 (void **) &pSMBr);
886 if (rc)
887 return rc;
888
889 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
890 name_len =
891 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
892 PATH_MAX, nls_codepage, remap);
893 name_len++; /* trailing null */
894 name_len *= 2;
895 } else { /* BB improve check for buffer overruns BB */
896 name_len = strnlen(fileName, PATH_MAX);
897 name_len++; /* trailing null */
898 strncpy(pSMB->fileName, fileName, name_len);
899 }
900 pSMB->SearchAttributes =
901 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
902 pSMB->BufferFormat = 0x04;
903 inc_rfc1001_len(pSMB, name_len + 1);
904 pSMB->ByteCount = cpu_to_le16(name_len + 1);
905 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
906 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
907 cifs_stats_inc(&tcon->num_deletes);
908 if (rc)
909 cFYI(1, "Error in RMFile = %d", rc);
910
911 cifs_buf_release(pSMB);
912 if (rc == -EAGAIN)
913 goto DelFileRetry;
914
915 return rc;
916}
917
918int
919CIFSSMBRmDir(const int xid, struct cifs_tcon *tcon, const char *dirName,
920 const struct nls_table *nls_codepage, int remap)
921{
922 DELETE_DIRECTORY_REQ *pSMB = NULL;
923 DELETE_DIRECTORY_RSP *pSMBr = NULL;
924 int rc = 0;
925 int bytes_returned;
926 int name_len;
927
928 cFYI(1, "In CIFSSMBRmDir");
929RmDirRetry:
930 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
931 (void **) &pSMBr);
932 if (rc)
933 return rc;
934
935 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
936 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
937 PATH_MAX, nls_codepage, remap);
938 name_len++; /* trailing null */
939 name_len *= 2;
940 } else { /* BB improve check for buffer overruns BB */
941 name_len = strnlen(dirName, PATH_MAX);
942 name_len++; /* trailing null */
943 strncpy(pSMB->DirName, dirName, name_len);
944 }
945
946 pSMB->BufferFormat = 0x04;
947 inc_rfc1001_len(pSMB, name_len + 1);
948 pSMB->ByteCount = cpu_to_le16(name_len + 1);
949 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
950 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
951 cifs_stats_inc(&tcon->num_rmdirs);
952 if (rc)
953 cFYI(1, "Error in RMDir = %d", rc);
954
955 cifs_buf_release(pSMB);
956 if (rc == -EAGAIN)
957 goto RmDirRetry;
958 return rc;
959}
960
961int
962CIFSSMBMkDir(const int xid, struct cifs_tcon *tcon,
963 const char *name, const struct nls_table *nls_codepage, int remap)
964{
965 int rc = 0;
966 CREATE_DIRECTORY_REQ *pSMB = NULL;
967 CREATE_DIRECTORY_RSP *pSMBr = NULL;
968 int bytes_returned;
969 int name_len;
970
971 cFYI(1, "In CIFSSMBMkDir");
972MkDirRetry:
973 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
974 (void **) &pSMBr);
975 if (rc)
976 return rc;
977
978 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
979 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
980 PATH_MAX, nls_codepage, remap);
981 name_len++; /* trailing null */
982 name_len *= 2;
983 } else { /* BB improve check for buffer overruns BB */
984 name_len = strnlen(name, PATH_MAX);
985 name_len++; /* trailing null */
986 strncpy(pSMB->DirName, name, name_len);
987 }
988
989 pSMB->BufferFormat = 0x04;
990 inc_rfc1001_len(pSMB, name_len + 1);
991 pSMB->ByteCount = cpu_to_le16(name_len + 1);
992 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
993 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
994 cifs_stats_inc(&tcon->num_mkdirs);
995 if (rc)
996 cFYI(1, "Error in Mkdir = %d", rc);
997
998 cifs_buf_release(pSMB);
999 if (rc == -EAGAIN)
1000 goto MkDirRetry;
1001 return rc;
1002}
1003
1004int
1005CIFSPOSIXCreate(const int xid, struct cifs_tcon *tcon, __u32 posix_flags,
1006 __u64 mode, __u16 *netfid, FILE_UNIX_BASIC_INFO *pRetData,
1007 __u32 *pOplock, const char *name,
1008 const struct nls_table *nls_codepage, int remap)
1009{
1010 TRANSACTION2_SPI_REQ *pSMB = NULL;
1011 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1012 int name_len;
1013 int rc = 0;
1014 int bytes_returned = 0;
1015 __u16 params, param_offset, offset, byte_count, count;
1016 OPEN_PSX_REQ *pdata;
1017 OPEN_PSX_RSP *psx_rsp;
1018
1019 cFYI(1, "In POSIX Create");
1020PsxCreat:
1021 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1022 (void **) &pSMBr);
1023 if (rc)
1024 return rc;
1025
1026 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1027 name_len =
1028 cifsConvertToUCS((__le16 *) pSMB->FileName, name,
1029 PATH_MAX, nls_codepage, remap);
1030 name_len++; /* trailing null */
1031 name_len *= 2;
1032 } else { /* BB improve the check for buffer overruns BB */
1033 name_len = strnlen(name, PATH_MAX);
1034 name_len++; /* trailing null */
1035 strncpy(pSMB->FileName, name, name_len);
1036 }
1037
1038 params = 6 + name_len;
1039 count = sizeof(OPEN_PSX_REQ);
1040 pSMB->MaxParameterCount = cpu_to_le16(2);
1041 pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1042 pSMB->MaxSetupCount = 0;
1043 pSMB->Reserved = 0;
1044 pSMB->Flags = 0;
1045 pSMB->Timeout = 0;
1046 pSMB->Reserved2 = 0;
1047 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1048 InformationLevel) - 4;
1049 offset = param_offset + params;
1050 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1051 pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1052 pdata->Permissions = cpu_to_le64(mode);
1053 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1054 pdata->OpenFlags = cpu_to_le32(*pOplock);
1055 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1056 pSMB->DataOffset = cpu_to_le16(offset);
1057 pSMB->SetupCount = 1;
1058 pSMB->Reserved3 = 0;
1059 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1060 byte_count = 3 /* pad */ + params + count;
1061
1062 pSMB->DataCount = cpu_to_le16(count);
1063 pSMB->ParameterCount = cpu_to_le16(params);
1064 pSMB->TotalDataCount = pSMB->DataCount;
1065 pSMB->TotalParameterCount = pSMB->ParameterCount;
1066 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1067 pSMB->Reserved4 = 0;
1068 inc_rfc1001_len(pSMB, byte_count);
1069 pSMB->ByteCount = cpu_to_le16(byte_count);
1070 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1071 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1072 if (rc) {
1073 cFYI(1, "Posix create returned %d", rc);
1074 goto psx_create_err;
1075 }
1076
1077 cFYI(1, "copying inode info");
1078 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1079
1080 if (rc || get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)) {
1081 rc = -EIO; /* bad smb */
1082 goto psx_create_err;
1083 }
1084
1085 /* copy return information to pRetData */
1086 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1087 + le16_to_cpu(pSMBr->t2.DataOffset));
1088
1089 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1090 if (netfid)
1091 *netfid = psx_rsp->Fid; /* cifs fid stays in le */
1092 /* Let caller know file was created so we can set the mode. */
1093 /* Do we care about the CreateAction in any other cases? */
1094 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1095 *pOplock |= CIFS_CREATE_ACTION;
1096 /* check to make sure response data is there */
1097 if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1098 pRetData->Type = cpu_to_le32(-1); /* unknown */
1099 cFYI(DBG2, "unknown type");
1100 } else {
1101 if (get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)
1102 + sizeof(FILE_UNIX_BASIC_INFO)) {
1103 cERROR(1, "Open response data too small");
1104 pRetData->Type = cpu_to_le32(-1);
1105 goto psx_create_err;
1106 }
1107 memcpy((char *) pRetData,
1108 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1109 sizeof(FILE_UNIX_BASIC_INFO));
1110 }
1111
1112psx_create_err:
1113 cifs_buf_release(pSMB);
1114
1115 if (posix_flags & SMB_O_DIRECTORY)
1116 cifs_stats_inc(&tcon->num_posixmkdirs);
1117 else
1118 cifs_stats_inc(&tcon->num_posixopens);
1119
1120 if (rc == -EAGAIN)
1121 goto PsxCreat;
1122
1123 return rc;
1124}
1125
1126static __u16 convert_disposition(int disposition)
1127{
1128 __u16 ofun = 0;
1129
1130 switch (disposition) {
1131 case FILE_SUPERSEDE:
1132 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1133 break;
1134 case FILE_OPEN:
1135 ofun = SMBOPEN_OAPPEND;
1136 break;
1137 case FILE_CREATE:
1138 ofun = SMBOPEN_OCREATE;
1139 break;
1140 case FILE_OPEN_IF:
1141 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1142 break;
1143 case FILE_OVERWRITE:
1144 ofun = SMBOPEN_OTRUNC;
1145 break;
1146 case FILE_OVERWRITE_IF:
1147 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1148 break;
1149 default:
1150 cFYI(1, "unknown disposition %d", disposition);
1151 ofun = SMBOPEN_OAPPEND; /* regular open */
1152 }
1153 return ofun;
1154}
1155
1156static int
1157access_flags_to_smbopen_mode(const int access_flags)
1158{
1159 int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1160
1161 if (masked_flags == GENERIC_READ)
1162 return SMBOPEN_READ;
1163 else if (masked_flags == GENERIC_WRITE)
1164 return SMBOPEN_WRITE;
1165
1166 /* just go for read/write */
1167 return SMBOPEN_READWRITE;
1168}
1169
1170int
1171SMBLegacyOpen(const int xid, struct cifs_tcon *tcon,
1172 const char *fileName, const int openDisposition,
1173 const int access_flags, const int create_options, __u16 *netfid,
1174 int *pOplock, FILE_ALL_INFO *pfile_info,
1175 const struct nls_table *nls_codepage, int remap)
1176{
1177 int rc = -EACCES;
1178 OPENX_REQ *pSMB = NULL;
1179 OPENX_RSP *pSMBr = NULL;
1180 int bytes_returned;
1181 int name_len;
1182 __u16 count;
1183
1184OldOpenRetry:
1185 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1186 (void **) &pSMBr);
1187 if (rc)
1188 return rc;
1189
1190 pSMB->AndXCommand = 0xFF; /* none */
1191
1192 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1193 count = 1; /* account for one byte pad to word boundary */
1194 name_len =
1195 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1196 fileName, PATH_MAX, nls_codepage, remap);
1197 name_len++; /* trailing null */
1198 name_len *= 2;
1199 } else { /* BB improve check for buffer overruns BB */
1200 count = 0; /* no pad */
1201 name_len = strnlen(fileName, PATH_MAX);
1202 name_len++; /* trailing null */
1203 strncpy(pSMB->fileName, fileName, name_len);
1204 }
1205 if (*pOplock & REQ_OPLOCK)
1206 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1207 else if (*pOplock & REQ_BATCHOPLOCK)
1208 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1209
1210 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1211 pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1212 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1213 /* set file as system file if special file such
1214 as fifo and server expecting SFU style and
1215 no Unix extensions */
1216
1217 if (create_options & CREATE_OPTION_SPECIAL)
1218 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1219 else /* BB FIXME BB */
1220 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1221
1222 if (create_options & CREATE_OPTION_READONLY)
1223 pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1224
1225 /* BB FIXME BB */
1226/* pSMB->CreateOptions = cpu_to_le32(create_options &
1227 CREATE_OPTIONS_MASK); */
1228 /* BB FIXME END BB */
1229
1230 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1231 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1232 count += name_len;
1233 inc_rfc1001_len(pSMB, count);
1234
1235 pSMB->ByteCount = cpu_to_le16(count);
1236 /* long_op set to 1 to allow for oplock break timeouts */
1237 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1238 (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1239 cifs_stats_inc(&tcon->num_opens);
1240 if (rc) {
1241 cFYI(1, "Error in Open = %d", rc);
1242 } else {
1243 /* BB verify if wct == 15 */
1244
1245/* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1246
1247 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1248 /* Let caller know file was created so we can set the mode. */
1249 /* Do we care about the CreateAction in any other cases? */
1250 /* BB FIXME BB */
1251/* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1252 *pOplock |= CIFS_CREATE_ACTION; */
1253 /* BB FIXME END */
1254
1255 if (pfile_info) {
1256 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1257 pfile_info->LastAccessTime = 0; /* BB fixme */
1258 pfile_info->LastWriteTime = 0; /* BB fixme */
1259 pfile_info->ChangeTime = 0; /* BB fixme */
1260 pfile_info->Attributes =
1261 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1262 /* the file_info buf is endian converted by caller */
1263 pfile_info->AllocationSize =
1264 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1265 pfile_info->EndOfFile = pfile_info->AllocationSize;
1266 pfile_info->NumberOfLinks = cpu_to_le32(1);
1267 pfile_info->DeletePending = 0;
1268 }
1269 }
1270
1271 cifs_buf_release(pSMB);
1272 if (rc == -EAGAIN)
1273 goto OldOpenRetry;
1274 return rc;
1275}
1276
1277int
1278CIFSSMBOpen(const int xid, struct cifs_tcon *tcon,
1279 const char *fileName, const int openDisposition,
1280 const int access_flags, const int create_options, __u16 *netfid,
1281 int *pOplock, FILE_ALL_INFO *pfile_info,
1282 const struct nls_table *nls_codepage, int remap)
1283{
1284 int rc = -EACCES;
1285 OPEN_REQ *pSMB = NULL;
1286 OPEN_RSP *pSMBr = NULL;
1287 int bytes_returned;
1288 int name_len;
1289 __u16 count;
1290
1291openRetry:
1292 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1293 (void **) &pSMBr);
1294 if (rc)
1295 return rc;
1296
1297 pSMB->AndXCommand = 0xFF; /* none */
1298
1299 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1300 count = 1; /* account for one byte pad to word boundary */
1301 name_len =
1302 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1303 fileName, PATH_MAX, nls_codepage, remap);
1304 name_len++; /* trailing null */
1305 name_len *= 2;
1306 pSMB->NameLength = cpu_to_le16(name_len);
1307 } else { /* BB improve check for buffer overruns BB */
1308 count = 0; /* no pad */
1309 name_len = strnlen(fileName, PATH_MAX);
1310 name_len++; /* trailing null */
1311 pSMB->NameLength = cpu_to_le16(name_len);
1312 strncpy(pSMB->fileName, fileName, name_len);
1313 }
1314 if (*pOplock & REQ_OPLOCK)
1315 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1316 else if (*pOplock & REQ_BATCHOPLOCK)
1317 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1318 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1319 pSMB->AllocationSize = 0;
1320 /* set file as system file if special file such
1321 as fifo and server expecting SFU style and
1322 no Unix extensions */
1323 if (create_options & CREATE_OPTION_SPECIAL)
1324 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1325 else
1326 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1327
1328 /* XP does not handle ATTR_POSIX_SEMANTICS */
1329 /* but it helps speed up case sensitive checks for other
1330 servers such as Samba */
1331 if (tcon->ses->capabilities & CAP_UNIX)
1332 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1333
1334 if (create_options & CREATE_OPTION_READONLY)
1335 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1336
1337 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1338 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1339 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1340 /* BB Expirement with various impersonation levels and verify */
1341 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1342 pSMB->SecurityFlags =
1343 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1344
1345 count += name_len;
1346 inc_rfc1001_len(pSMB, count);
1347
1348 pSMB->ByteCount = cpu_to_le16(count);
1349 /* long_op set to 1 to allow for oplock break timeouts */
1350 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1351 (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1352 cifs_stats_inc(&tcon->num_opens);
1353 if (rc) {
1354 cFYI(1, "Error in Open = %d", rc);
1355 } else {
1356 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1357 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1358 /* Let caller know file was created so we can set the mode. */
1359 /* Do we care about the CreateAction in any other cases? */
1360 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1361 *pOplock |= CIFS_CREATE_ACTION;
1362 if (pfile_info) {
1363 memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1364 36 /* CreationTime to Attributes */);
1365 /* the file_info buf is endian converted by caller */
1366 pfile_info->AllocationSize = pSMBr->AllocationSize;
1367 pfile_info->EndOfFile = pSMBr->EndOfFile;
1368 pfile_info->NumberOfLinks = cpu_to_le32(1);
1369 pfile_info->DeletePending = 0;
1370 }
1371 }
1372
1373 cifs_buf_release(pSMB);
1374 if (rc == -EAGAIN)
1375 goto openRetry;
1376 return rc;
1377}
1378
1379int
1380CIFSSMBRead(const int xid, struct cifs_io_parms *io_parms, unsigned int *nbytes,
1381 char **buf, int *pbuf_type)
1382{
1383 int rc = -EACCES;
1384 READ_REQ *pSMB = NULL;
1385 READ_RSP *pSMBr = NULL;
1386 char *pReadData = NULL;
1387 int wct;
1388 int resp_buf_type = 0;
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;
1395
1396 cFYI(1, "Reading %d bytes on fid %d", count, netfid);
1397 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1398 wct = 12;
1399 else {
1400 wct = 10; /* old style read */
1401 if ((offset >> 32) > 0) {
1402 /* can not handle this big offset for old */
1403 return -EIO;
1404 }
1405 }
1406
1407 *nbytes = 0;
1408 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1409 if (rc)
1410 return rc;
1411
1412 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1413 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1414
1415 /* tcon and ses pointer are checked in smb_init */
1416 if (tcon->ses->server == NULL)
1417 return -ECONNABORTED;
1418
1419 pSMB->AndXCommand = 0xFF; /* none */
1420 pSMB->Fid = netfid;
1421 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1422 if (wct == 12)
1423 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1424
1425 pSMB->Remaining = 0;
1426 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1427 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1428 if (wct == 12)
1429 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1430 else {
1431 /* old style read */
1432 struct smb_com_readx_req *pSMBW =
1433 (struct smb_com_readx_req *)pSMB;
1434 pSMBW->ByteCount = 0;
1435 }
1436
1437 iov[0].iov_base = (char *)pSMB;
1438 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
1439 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1440 &resp_buf_type, CIFS_LOG_ERROR);
1441 cifs_stats_inc(&tcon->num_reads);
1442 pSMBr = (READ_RSP *)iov[0].iov_base;
1443 if (rc) {
1444 cERROR(1, "Send error in read = %d", rc);
1445 } else {
1446 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1447 data_length = data_length << 16;
1448 data_length += le16_to_cpu(pSMBr->DataLength);
1449 *nbytes = data_length;
1450
1451 /*check that DataLength would not go beyond end of SMB */
1452 if ((data_length > CIFSMaxBufSize)
1453 || (data_length > count)) {
1454 cFYI(1, "bad length %d for count %d",
1455 data_length, count);
1456 rc = -EIO;
1457 *nbytes = 0;
1458 } else {
1459 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1460 le16_to_cpu(pSMBr->DataOffset);
1461/* if (rc = copy_to_user(buf, pReadData, data_length)) {
1462 cERROR(1, "Faulting on read rc = %d",rc);
1463 rc = -EFAULT;
1464 }*/ /* can not use copy_to_user when using page cache*/
1465 if (*buf)
1466 memcpy(*buf, pReadData, data_length);
1467 }
1468 }
1469
1470/* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1471 if (*buf) {
1472 if (resp_buf_type == CIFS_SMALL_BUFFER)
1473 cifs_small_buf_release(iov[0].iov_base);
1474 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1475 cifs_buf_release(iov[0].iov_base);
1476 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1477 /* return buffer to caller to free */
1478 *buf = iov[0].iov_base;
1479 if (resp_buf_type == CIFS_SMALL_BUFFER)
1480 *pbuf_type = CIFS_SMALL_BUFFER;
1481 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1482 *pbuf_type = CIFS_LARGE_BUFFER;
1483 } /* else no valid buffer on return - leave as null */
1484
1485 /* Note: On -EAGAIN error only caller can retry on handle based calls
1486 since file handle passed in no longer valid */
1487 return rc;
1488}
1489
1490
1491int
1492CIFSSMBWrite(const int xid, struct cifs_io_parms *io_parms,
1493 unsigned int *nbytes, const char *buf,
1494 const char __user *ubuf, const int long_op)
1495{
1496 int rc = -EACCES;
1497 WRITE_REQ *pSMB = NULL;
1498 WRITE_RSP *pSMBr = NULL;
1499 int bytes_returned, wct;
1500 __u32 bytes_sent;
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;
1507
1508 *nbytes = 0;
1509
1510 /* cFYI(1, "write at %lld %d bytes", offset, count);*/
1511 if (tcon->ses == NULL)
1512 return -ECONNABORTED;
1513
1514 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1515 wct = 14;
1516 else {
1517 wct = 12;
1518 if ((offset >> 32) > 0) {
1519 /* can not handle big offset for old srv */
1520 return -EIO;
1521 }
1522 }
1523
1524 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1525 (void **) &pSMBr);
1526 if (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
1532 /* tcon and ses pointer are checked in smb_init */
1533 if (tcon->ses->server == NULL)
1534 return -ECONNABORTED;
1535
1536 pSMB->AndXCommand = 0xFF; /* none */
1537 pSMB->Fid = netfid;
1538 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1539 if (wct == 14)
1540 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1541
1542 pSMB->Reserved = 0xFFFFFFFF;
1543 pSMB->WriteMode = 0;
1544 pSMB->Remaining = 0;
1545
1546 /* Can increase buffer size if buffer is big enough in some cases ie we
1547 can send more if LARGE_WRITE_X capability returned by the server and if
1548 our buffer is big enough or if we convert to iovecs on socket writes
1549 and eliminate the copy to the CIFS buffer */
1550 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1551 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1552 } else {
1553 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1554 & ~0xFF;
1555 }
1556
1557 if (bytes_sent > count)
1558 bytes_sent = count;
1559 pSMB->DataOffset =
1560 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1561 if (buf)
1562 memcpy(pSMB->Data, buf, bytes_sent);
1563 else if (ubuf) {
1564 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1565 cifs_buf_release(pSMB);
1566 return -EFAULT;
1567 }
1568 } else if (count != 0) {
1569 /* No buffer */
1570 cifs_buf_release(pSMB);
1571 return -EINVAL;
1572 } /* else setting file size with write of zero bytes */
1573 if (wct == 14)
1574 byte_count = bytes_sent + 1; /* pad */
1575 else /* wct == 12 */
1576 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1577
1578 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1579 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1580 inc_rfc1001_len(pSMB, byte_count);
1581
1582 if (wct == 14)
1583 pSMB->ByteCount = cpu_to_le16(byte_count);
1584 else { /* old style write has byte count 4 bytes earlier
1585 so 4 bytes pad */
1586 struct smb_com_writex_req *pSMBW =
1587 (struct smb_com_writex_req *)pSMB;
1588 pSMBW->ByteCount = cpu_to_le16(byte_count);
1589 }
1590
1591 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1592 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1593 cifs_stats_inc(&tcon->num_writes);
1594 if (rc) {
1595 cFYI(1, "Send error in write = %d", rc);
1596 } else {
1597 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1598 *nbytes = (*nbytes) << 16;
1599 *nbytes += le16_to_cpu(pSMBr->Count);
1600
1601 /*
1602 * Mask off high 16 bits when bytes written as returned by the
1603 * server is greater than bytes requested by the client. Some
1604 * OS/2 servers are known to set incorrect CountHigh values.
1605 */
1606 if (*nbytes > count)
1607 *nbytes &= 0xFFFF;
1608 }
1609
1610 cifs_buf_release(pSMB);
1611
1612 /* Note: On -EAGAIN error only caller can retry on handle based calls
1613 since file handle passed in no longer valid */
1614
1615 return rc;
1616}
1617
1618void
1619cifs_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 */
1634static void
1635cifs_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
1659static void
1660cifs_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
1688struct cifs_writedata *
1689cifs_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 */
1713static void
1714cifs_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 */
1760int
1761cifs_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
1850async_writev_out:
1851 cifs_small_buf_release(smb);
1852 kfree(iov);
1853 return rc;
1854}
1855
1856int
1857CIFSSMBWrite2(const int xid, struct cifs_io_parms *io_parms,
1858 unsigned int *nbytes, struct kvec *iov, int n_vec,
1859 const int long_op)
1860{
1861 int rc = -EACCES;
1862 WRITE_REQ *pSMB = NULL;
1863 int wct;
1864 int smb_hdr_len;
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;
1871
1872 *nbytes = 0;
1873
1874 cFYI(1, "write2 at %lld %d bytes", (long long)offset, count);
1875
1876 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
1877 wct = 14;
1878 } else {
1879 wct = 12;
1880 if ((offset >> 32) > 0) {
1881 /* can not handle big offset for old srv */
1882 return -EIO;
1883 }
1884 }
1885 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1886 if (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
1892 /* tcon and ses pointer are checked in smb_init */
1893 if (tcon->ses->server == NULL)
1894 return -ECONNABORTED;
1895
1896 pSMB->AndXCommand = 0xFF; /* none */
1897 pSMB->Fid = netfid;
1898 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1899 if (wct == 14)
1900 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1901 pSMB->Reserved = 0xFFFFFFFF;
1902 pSMB->WriteMode = 0;
1903 pSMB->Remaining = 0;
1904
1905 pSMB->DataOffset =
1906 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1907
1908 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1909 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1910 /* header + 1 byte pad */
1911 smb_hdr_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 1;
1912 if (wct == 14)
1913 inc_rfc1001_len(pSMB, count + 1);
1914 else /* wct == 12 */
1915 inc_rfc1001_len(pSMB, count + 5); /* smb data starts later */
1916 if (wct == 14)
1917 pSMB->ByteCount = cpu_to_le16(count + 1);
1918 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1919 struct smb_com_writex_req *pSMBW =
1920 (struct smb_com_writex_req *)pSMB;
1921 pSMBW->ByteCount = cpu_to_le16(count + 5);
1922 }
1923 iov[0].iov_base = pSMB;
1924 if (wct == 14)
1925 iov[0].iov_len = smb_hdr_len + 4;
1926 else /* wct == 12 pad bigger by four bytes */
1927 iov[0].iov_len = smb_hdr_len + 8;
1928
1929
1930 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1931 long_op);
1932 cifs_stats_inc(&tcon->num_writes);
1933 if (rc) {
1934 cFYI(1, "Send error Write2 = %d", rc);
1935 } else if (resp_buf_type == 0) {
1936 /* presumably this can not happen, but best to be safe */
1937 rc = -EIO;
1938 } else {
1939 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
1940 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1941 *nbytes = (*nbytes) << 16;
1942 *nbytes += le16_to_cpu(pSMBr->Count);
1943
1944 /*
1945 * Mask off high 16 bits when bytes written as returned by the
1946 * server is greater than bytes requested by the client. OS/2
1947 * servers are known to set incorrect CountHigh values.
1948 */
1949 if (*nbytes > count)
1950 *nbytes &= 0xFFFF;
1951 }
1952
1953/* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1954 if (resp_buf_type == CIFS_SMALL_BUFFER)
1955 cifs_small_buf_release(iov[0].iov_base);
1956 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1957 cifs_buf_release(iov[0].iov_base);
1958
1959 /* Note: On -EAGAIN error only caller can retry on handle based calls
1960 since file handle passed in no longer valid */
1961
1962 return rc;
1963}
1964
1965
1966int
1967CIFSSMBLock(const int xid, struct cifs_tcon *tcon,
1968 const __u16 smb_file_id, const __u64 len,
1969 const __u64 offset, const __u32 numUnlock,
1970 const __u32 numLock, const __u8 lockType,
1971 const bool waitFlag, const __u8 oplock_level)
1972{
1973 int rc = 0;
1974 LOCK_REQ *pSMB = NULL;
1975/* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
1976 int bytes_returned;
1977 int timeout = 0;
1978 __u16 count;
1979
1980 cFYI(1, "CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock);
1981 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1982
1983 if (rc)
1984 return rc;
1985
1986 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1987 timeout = CIFS_ASYNC_OP; /* no response expected */
1988 pSMB->Timeout = 0;
1989 } else if (waitFlag) {
1990 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1991 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1992 } else {
1993 pSMB->Timeout = 0;
1994 }
1995
1996 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1997 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1998 pSMB->LockType = lockType;
1999 pSMB->OplockLevel = oplock_level;
2000 pSMB->AndXCommand = 0xFF; /* none */
2001 pSMB->Fid = smb_file_id; /* netfid stays le */
2002
2003 if ((numLock != 0) || (numUnlock != 0)) {
2004 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
2005 /* BB where to store pid high? */
2006 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
2007 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
2008 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
2009 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
2010 count = sizeof(LOCKING_ANDX_RANGE);
2011 } else {
2012 /* oplock break */
2013 count = 0;
2014 }
2015 inc_rfc1001_len(pSMB, count);
2016 pSMB->ByteCount = cpu_to_le16(count);
2017
2018 if (waitFlag) {
2019 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2020 (struct smb_hdr *) pSMB, &bytes_returned);
2021 cifs_small_buf_release(pSMB);
2022 } else {
2023 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB,
2024 timeout);
2025 /* SMB buffer freed by function above */
2026 }
2027 cifs_stats_inc(&tcon->num_locks);
2028 if (rc)
2029 cFYI(1, "Send error in Lock = %d", rc);
2030
2031 /* Note: On -EAGAIN error only caller can retry on handle based calls
2032 since file handle passed in no longer valid */
2033 return rc;
2034}
2035
2036int
2037CIFSSMBPosixLock(const int xid, struct cifs_tcon *tcon,
2038 const __u16 smb_file_id, const int get_flag, const __u64 len,
2039 struct file_lock *pLockData, const __u16 lock_type,
2040 const bool waitFlag)
2041{
2042 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2043 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2044 struct cifs_posix_lock *parm_data;
2045 int rc = 0;
2046 int timeout = 0;
2047 int bytes_returned = 0;
2048 int resp_buf_type = 0;
2049 __u16 params, param_offset, offset, byte_count, count;
2050 struct kvec iov[1];
2051
2052 cFYI(1, "Posix Lock");
2053
2054 if (pLockData == NULL)
2055 return -EINVAL;
2056
2057 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
2058
2059 if (rc)
2060 return rc;
2061
2062 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
2063
2064 params = 6;
2065 pSMB->MaxSetupCount = 0;
2066 pSMB->Reserved = 0;
2067 pSMB->Flags = 0;
2068 pSMB->Reserved2 = 0;
2069 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2070 offset = param_offset + params;
2071
2072 count = sizeof(struct cifs_posix_lock);
2073 pSMB->MaxParameterCount = cpu_to_le16(2);
2074 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2075 pSMB->SetupCount = 1;
2076 pSMB->Reserved3 = 0;
2077 if (get_flag)
2078 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2079 else
2080 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2081 byte_count = 3 /* pad */ + params + count;
2082 pSMB->DataCount = cpu_to_le16(count);
2083 pSMB->ParameterCount = cpu_to_le16(params);
2084 pSMB->TotalDataCount = pSMB->DataCount;
2085 pSMB->TotalParameterCount = pSMB->ParameterCount;
2086 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2087 parm_data = (struct cifs_posix_lock *)
2088 (((char *) &pSMB->hdr.Protocol) + offset);
2089
2090 parm_data->lock_type = cpu_to_le16(lock_type);
2091 if (waitFlag) {
2092 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2093 parm_data->lock_flags = cpu_to_le16(1);
2094 pSMB->Timeout = cpu_to_le32(-1);
2095 } else
2096 pSMB->Timeout = 0;
2097
2098 parm_data->pid = cpu_to_le32(current->tgid);
2099 parm_data->start = cpu_to_le64(pLockData->fl_start);
2100 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
2101
2102 pSMB->DataOffset = cpu_to_le16(offset);
2103 pSMB->Fid = smb_file_id;
2104 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
2105 pSMB->Reserved4 = 0;
2106 inc_rfc1001_len(pSMB, byte_count);
2107 pSMB->ByteCount = cpu_to_le16(byte_count);
2108 if (waitFlag) {
2109 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2110 (struct smb_hdr *) pSMBr, &bytes_returned);
2111 } else {
2112 iov[0].iov_base = (char *)pSMB;
2113 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
2114 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
2115 &resp_buf_type, timeout);
2116 pSMB = NULL; /* request buf already freed by SendReceive2. Do
2117 not try to free it twice below on exit */
2118 pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
2119 }
2120
2121 if (rc) {
2122 cFYI(1, "Send error in Posix Lock = %d", rc);
2123 } else if (get_flag) {
2124 /* lock structure can be returned on get */
2125 __u16 data_offset;
2126 __u16 data_count;
2127 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2128
2129 if (rc || get_bcc(&pSMBr->hdr) < sizeof(*parm_data)) {
2130 rc = -EIO; /* bad smb */
2131 goto plk_err_exit;
2132 }
2133 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2134 data_count = le16_to_cpu(pSMBr->t2.DataCount);
2135 if (data_count < sizeof(struct cifs_posix_lock)) {
2136 rc = -EIO;
2137 goto plk_err_exit;
2138 }
2139 parm_data = (struct cifs_posix_lock *)
2140 ((char *)&pSMBr->hdr.Protocol + data_offset);
2141 if (parm_data->lock_type == __constant_cpu_to_le16(CIFS_UNLCK))
2142 pLockData->fl_type = F_UNLCK;
2143 else {
2144 if (parm_data->lock_type ==
2145 __constant_cpu_to_le16(CIFS_RDLCK))
2146 pLockData->fl_type = F_RDLCK;
2147 else if (parm_data->lock_type ==
2148 __constant_cpu_to_le16(CIFS_WRLCK))
2149 pLockData->fl_type = F_WRLCK;
2150
2151 pLockData->fl_start = le64_to_cpu(parm_data->start);
2152 pLockData->fl_end = pLockData->fl_start +
2153 le64_to_cpu(parm_data->length) - 1;
2154 pLockData->fl_pid = le32_to_cpu(parm_data->pid);
2155 }
2156 }
2157
2158plk_err_exit:
2159 if (pSMB)
2160 cifs_small_buf_release(pSMB);
2161
2162 if (resp_buf_type == CIFS_SMALL_BUFFER)
2163 cifs_small_buf_release(iov[0].iov_base);
2164 else if (resp_buf_type == CIFS_LARGE_BUFFER)
2165 cifs_buf_release(iov[0].iov_base);
2166
2167 /* Note: On -EAGAIN error only caller can retry on handle based calls
2168 since file handle passed in no longer valid */
2169
2170 return rc;
2171}
2172
2173
2174int
2175CIFSSMBClose(const int xid, struct cifs_tcon *tcon, int smb_file_id)
2176{
2177 int rc = 0;
2178 CLOSE_REQ *pSMB = NULL;
2179 cFYI(1, "In CIFSSMBClose");
2180
2181/* do not retry on dead session on close */
2182 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
2183 if (rc == -EAGAIN)
2184 return 0;
2185 if (rc)
2186 return rc;
2187
2188 pSMB->FileID = (__u16) smb_file_id;
2189 pSMB->LastWriteTime = 0xFFFFFFFF;
2190 pSMB->ByteCount = 0;
2191 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
2192 cifs_stats_inc(&tcon->num_closes);
2193 if (rc) {
2194 if (rc != -EINTR) {
2195 /* EINTR is expected when user ctl-c to kill app */
2196 cERROR(1, "Send error in Close = %d", rc);
2197 }
2198 }
2199
2200 /* Since session is dead, file will be closed on server already */
2201 if (rc == -EAGAIN)
2202 rc = 0;
2203
2204 return rc;
2205}
2206
2207int
2208CIFSSMBFlush(const int xid, struct cifs_tcon *tcon, int smb_file_id)
2209{
2210 int rc = 0;
2211 FLUSH_REQ *pSMB = NULL;
2212 cFYI(1, "In CIFSSMBFlush");
2213
2214 rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
2215 if (rc)
2216 return rc;
2217
2218 pSMB->FileID = (__u16) smb_file_id;
2219 pSMB->ByteCount = 0;
2220 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
2221 cifs_stats_inc(&tcon->num_flushes);
2222 if (rc)
2223 cERROR(1, "Send error in Flush = %d", rc);
2224
2225 return rc;
2226}
2227
2228int
2229CIFSSMBRename(const int xid, struct cifs_tcon *tcon,
2230 const char *fromName, const char *toName,
2231 const struct nls_table *nls_codepage, int remap)
2232{
2233 int rc = 0;
2234 RENAME_REQ *pSMB = NULL;
2235 RENAME_RSP *pSMBr = NULL;
2236 int bytes_returned;
2237 int name_len, name_len2;
2238 __u16 count;
2239
2240 cFYI(1, "In CIFSSMBRename");
2241renameRetry:
2242 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
2243 (void **) &pSMBr);
2244 if (rc)
2245 return rc;
2246
2247 pSMB->BufferFormat = 0x04;
2248 pSMB->SearchAttributes =
2249 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2250 ATTR_DIRECTORY);
2251
2252 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2253 name_len =
2254 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2255 PATH_MAX, nls_codepage, remap);
2256 name_len++; /* trailing null */
2257 name_len *= 2;
2258 pSMB->OldFileName[name_len] = 0x04; /* pad */
2259 /* protocol requires ASCII signature byte on Unicode string */
2260 pSMB->OldFileName[name_len + 1] = 0x00;
2261 name_len2 =
2262 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2263 toName, PATH_MAX, nls_codepage, remap);
2264 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2265 name_len2 *= 2; /* convert to bytes */
2266 } else { /* BB improve the check for buffer overruns BB */
2267 name_len = strnlen(fromName, PATH_MAX);
2268 name_len++; /* trailing null */
2269 strncpy(pSMB->OldFileName, fromName, name_len);
2270 name_len2 = strnlen(toName, PATH_MAX);
2271 name_len2++; /* trailing null */
2272 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2273 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2274 name_len2++; /* trailing null */
2275 name_len2++; /* signature byte */
2276 }
2277
2278 count = 1 /* 1st signature byte */ + name_len + name_len2;
2279 inc_rfc1001_len(pSMB, count);
2280 pSMB->ByteCount = cpu_to_le16(count);
2281
2282 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2283 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2284 cifs_stats_inc(&tcon->num_renames);
2285 if (rc)
2286 cFYI(1, "Send error in rename = %d", rc);
2287
2288 cifs_buf_release(pSMB);
2289
2290 if (rc == -EAGAIN)
2291 goto renameRetry;
2292
2293 return rc;
2294}
2295
2296int CIFSSMBRenameOpenFile(const int xid, struct cifs_tcon *pTcon,
2297 int netfid, const char *target_name,
2298 const struct nls_table *nls_codepage, int remap)
2299{
2300 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2301 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2302 struct set_file_rename *rename_info;
2303 char *data_offset;
2304 char dummy_string[30];
2305 int rc = 0;
2306 int bytes_returned = 0;
2307 int len_of_str;
2308 __u16 params, param_offset, offset, count, byte_count;
2309
2310 cFYI(1, "Rename to File by handle");
2311 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2312 (void **) &pSMBr);
2313 if (rc)
2314 return rc;
2315
2316 params = 6;
2317 pSMB->MaxSetupCount = 0;
2318 pSMB->Reserved = 0;
2319 pSMB->Flags = 0;
2320 pSMB->Timeout = 0;
2321 pSMB->Reserved2 = 0;
2322 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2323 offset = param_offset + params;
2324
2325 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2326 rename_info = (struct set_file_rename *) data_offset;
2327 pSMB->MaxParameterCount = cpu_to_le16(2);
2328 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2329 pSMB->SetupCount = 1;
2330 pSMB->Reserved3 = 0;
2331 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2332 byte_count = 3 /* pad */ + params;
2333 pSMB->ParameterCount = cpu_to_le16(params);
2334 pSMB->TotalParameterCount = pSMB->ParameterCount;
2335 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2336 pSMB->DataOffset = cpu_to_le16(offset);
2337 /* construct random name ".cifs_tmp<inodenum><mid>" */
2338 rename_info->overwrite = cpu_to_le32(1);
2339 rename_info->root_fid = 0;
2340 /* unicode only call */
2341 if (target_name == NULL) {
2342 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2343 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2344 dummy_string, 24, nls_codepage, remap);
2345 } else {
2346 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2347 target_name, PATH_MAX, nls_codepage,
2348 remap);
2349 }
2350 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2351 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2352 byte_count += count;
2353 pSMB->DataCount = cpu_to_le16(count);
2354 pSMB->TotalDataCount = pSMB->DataCount;
2355 pSMB->Fid = netfid;
2356 pSMB->InformationLevel =
2357 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2358 pSMB->Reserved4 = 0;
2359 inc_rfc1001_len(pSMB, byte_count);
2360 pSMB->ByteCount = cpu_to_le16(byte_count);
2361 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2362 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2363 cifs_stats_inc(&pTcon->num_t2renames);
2364 if (rc)
2365 cFYI(1, "Send error in Rename (by file handle) = %d", rc);
2366
2367 cifs_buf_release(pSMB);
2368
2369 /* Note: On -EAGAIN error only caller can retry on handle based calls
2370 since file handle passed in no longer valid */
2371
2372 return rc;
2373}
2374
2375int
2376CIFSSMBCopy(const int xid, struct cifs_tcon *tcon, const char *fromName,
2377 const __u16 target_tid, const char *toName, const int flags,
2378 const struct nls_table *nls_codepage, int remap)
2379{
2380 int rc = 0;
2381 COPY_REQ *pSMB = NULL;
2382 COPY_RSP *pSMBr = NULL;
2383 int bytes_returned;
2384 int name_len, name_len2;
2385 __u16 count;
2386
2387 cFYI(1, "In CIFSSMBCopy");
2388copyRetry:
2389 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2390 (void **) &pSMBr);
2391 if (rc)
2392 return rc;
2393
2394 pSMB->BufferFormat = 0x04;
2395 pSMB->Tid2 = target_tid;
2396
2397 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2398
2399 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2400 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
2401 fromName, PATH_MAX, nls_codepage,
2402 remap);
2403 name_len++; /* trailing null */
2404 name_len *= 2;
2405 pSMB->OldFileName[name_len] = 0x04; /* pad */
2406 /* protocol requires ASCII signature byte on Unicode string */
2407 pSMB->OldFileName[name_len + 1] = 0x00;
2408 name_len2 =
2409 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2410 toName, PATH_MAX, nls_codepage, remap);
2411 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2412 name_len2 *= 2; /* convert to bytes */
2413 } else { /* BB improve the check for buffer overruns BB */
2414 name_len = strnlen(fromName, PATH_MAX);
2415 name_len++; /* trailing null */
2416 strncpy(pSMB->OldFileName, fromName, name_len);
2417 name_len2 = strnlen(toName, PATH_MAX);
2418 name_len2++; /* trailing null */
2419 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2420 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2421 name_len2++; /* trailing null */
2422 name_len2++; /* signature byte */
2423 }
2424
2425 count = 1 /* 1st signature byte */ + name_len + name_len2;
2426 inc_rfc1001_len(pSMB, count);
2427 pSMB->ByteCount = cpu_to_le16(count);
2428
2429 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2430 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2431 if (rc) {
2432 cFYI(1, "Send error in copy = %d with %d files copied",
2433 rc, le16_to_cpu(pSMBr->CopyCount));
2434 }
2435 cifs_buf_release(pSMB);
2436
2437 if (rc == -EAGAIN)
2438 goto copyRetry;
2439
2440 return rc;
2441}
2442
2443int
2444CIFSUnixCreateSymLink(const int xid, struct cifs_tcon *tcon,
2445 const char *fromName, const char *toName,
2446 const struct nls_table *nls_codepage)
2447{
2448 TRANSACTION2_SPI_REQ *pSMB = NULL;
2449 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2450 char *data_offset;
2451 int name_len;
2452 int name_len_target;
2453 int rc = 0;
2454 int bytes_returned = 0;
2455 __u16 params, param_offset, offset, byte_count;
2456
2457 cFYI(1, "In Symlink Unix style");
2458createSymLinkRetry:
2459 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2460 (void **) &pSMBr);
2461 if (rc)
2462 return rc;
2463
2464 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2465 name_len =
2466 cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
2467 /* find define for this maxpathcomponent */
2468 , nls_codepage);
2469 name_len++; /* trailing null */
2470 name_len *= 2;
2471
2472 } else { /* BB improve the check for buffer overruns BB */
2473 name_len = strnlen(fromName, PATH_MAX);
2474 name_len++; /* trailing null */
2475 strncpy(pSMB->FileName, fromName, name_len);
2476 }
2477 params = 6 + name_len;
2478 pSMB->MaxSetupCount = 0;
2479 pSMB->Reserved = 0;
2480 pSMB->Flags = 0;
2481 pSMB->Timeout = 0;
2482 pSMB->Reserved2 = 0;
2483 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2484 InformationLevel) - 4;
2485 offset = param_offset + params;
2486
2487 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2488 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2489 name_len_target =
2490 cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
2491 /* find define for this maxpathcomponent */
2492 , nls_codepage);
2493 name_len_target++; /* trailing null */
2494 name_len_target *= 2;
2495 } else { /* BB improve the check for buffer overruns BB */
2496 name_len_target = strnlen(toName, PATH_MAX);
2497 name_len_target++; /* trailing null */
2498 strncpy(data_offset, toName, name_len_target);
2499 }
2500
2501 pSMB->MaxParameterCount = cpu_to_le16(2);
2502 /* BB find exact max on data count below from sess */
2503 pSMB->MaxDataCount = cpu_to_le16(1000);
2504 pSMB->SetupCount = 1;
2505 pSMB->Reserved3 = 0;
2506 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2507 byte_count = 3 /* pad */ + params + name_len_target;
2508 pSMB->DataCount = cpu_to_le16(name_len_target);
2509 pSMB->ParameterCount = cpu_to_le16(params);
2510 pSMB->TotalDataCount = pSMB->DataCount;
2511 pSMB->TotalParameterCount = pSMB->ParameterCount;
2512 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2513 pSMB->DataOffset = cpu_to_le16(offset);
2514 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2515 pSMB->Reserved4 = 0;
2516 inc_rfc1001_len(pSMB, byte_count);
2517 pSMB->ByteCount = cpu_to_le16(byte_count);
2518 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2519 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2520 cifs_stats_inc(&tcon->num_symlinks);
2521 if (rc)
2522 cFYI(1, "Send error in SetPathInfo create symlink = %d", rc);
2523
2524 cifs_buf_release(pSMB);
2525
2526 if (rc == -EAGAIN)
2527 goto createSymLinkRetry;
2528
2529 return rc;
2530}
2531
2532int
2533CIFSUnixCreateHardLink(const int xid, struct cifs_tcon *tcon,
2534 const char *fromName, const char *toName,
2535 const struct nls_table *nls_codepage, int remap)
2536{
2537 TRANSACTION2_SPI_REQ *pSMB = NULL;
2538 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2539 char *data_offset;
2540 int name_len;
2541 int name_len_target;
2542 int rc = 0;
2543 int bytes_returned = 0;
2544 __u16 params, param_offset, offset, byte_count;
2545
2546 cFYI(1, "In Create Hard link Unix style");
2547createHardLinkRetry:
2548 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2549 (void **) &pSMBr);
2550 if (rc)
2551 return rc;
2552
2553 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2554 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2555 PATH_MAX, nls_codepage, remap);
2556 name_len++; /* trailing null */
2557 name_len *= 2;
2558
2559 } else { /* BB improve the check for buffer overruns BB */
2560 name_len = strnlen(toName, PATH_MAX);
2561 name_len++; /* trailing null */
2562 strncpy(pSMB->FileName, toName, name_len);
2563 }
2564 params = 6 + name_len;
2565 pSMB->MaxSetupCount = 0;
2566 pSMB->Reserved = 0;
2567 pSMB->Flags = 0;
2568 pSMB->Timeout = 0;
2569 pSMB->Reserved2 = 0;
2570 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2571 InformationLevel) - 4;
2572 offset = param_offset + params;
2573
2574 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2575 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2576 name_len_target =
2577 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2578 nls_codepage, remap);
2579 name_len_target++; /* trailing null */
2580 name_len_target *= 2;
2581 } else { /* BB improve the check for buffer overruns BB */
2582 name_len_target = strnlen(fromName, PATH_MAX);
2583 name_len_target++; /* trailing null */
2584 strncpy(data_offset, fromName, name_len_target);
2585 }
2586
2587 pSMB->MaxParameterCount = cpu_to_le16(2);
2588 /* BB find exact max on data count below from sess*/
2589 pSMB->MaxDataCount = cpu_to_le16(1000);
2590 pSMB->SetupCount = 1;
2591 pSMB->Reserved3 = 0;
2592 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2593 byte_count = 3 /* pad */ + params + name_len_target;
2594 pSMB->ParameterCount = cpu_to_le16(params);
2595 pSMB->TotalParameterCount = pSMB->ParameterCount;
2596 pSMB->DataCount = cpu_to_le16(name_len_target);
2597 pSMB->TotalDataCount = pSMB->DataCount;
2598 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2599 pSMB->DataOffset = cpu_to_le16(offset);
2600 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2601 pSMB->Reserved4 = 0;
2602 inc_rfc1001_len(pSMB, byte_count);
2603 pSMB->ByteCount = cpu_to_le16(byte_count);
2604 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2605 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2606 cifs_stats_inc(&tcon->num_hardlinks);
2607 if (rc)
2608 cFYI(1, "Send error in SetPathInfo (hard link) = %d", rc);
2609
2610 cifs_buf_release(pSMB);
2611 if (rc == -EAGAIN)
2612 goto createHardLinkRetry;
2613
2614 return rc;
2615}
2616
2617int
2618CIFSCreateHardLink(const int xid, struct cifs_tcon *tcon,
2619 const char *fromName, const char *toName,
2620 const struct nls_table *nls_codepage, int remap)
2621{
2622 int rc = 0;
2623 NT_RENAME_REQ *pSMB = NULL;
2624 RENAME_RSP *pSMBr = NULL;
2625 int bytes_returned;
2626 int name_len, name_len2;
2627 __u16 count;
2628
2629 cFYI(1, "In CIFSCreateHardLink");
2630winCreateHardLinkRetry:
2631
2632 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2633 (void **) &pSMBr);
2634 if (rc)
2635 return rc;
2636
2637 pSMB->SearchAttributes =
2638 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2639 ATTR_DIRECTORY);
2640 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2641 pSMB->ClusterCount = 0;
2642
2643 pSMB->BufferFormat = 0x04;
2644
2645 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2646 name_len =
2647 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2648 PATH_MAX, nls_codepage, remap);
2649 name_len++; /* trailing null */
2650 name_len *= 2;
2651
2652 /* protocol specifies ASCII buffer format (0x04) for unicode */
2653 pSMB->OldFileName[name_len] = 0x04;
2654 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
2655 name_len2 =
2656 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2657 toName, PATH_MAX, nls_codepage, remap);
2658 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2659 name_len2 *= 2; /* convert to bytes */
2660 } else { /* BB improve the check for buffer overruns BB */
2661 name_len = strnlen(fromName, PATH_MAX);
2662 name_len++; /* trailing null */
2663 strncpy(pSMB->OldFileName, fromName, name_len);
2664 name_len2 = strnlen(toName, PATH_MAX);
2665 name_len2++; /* trailing null */
2666 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2667 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2668 name_len2++; /* trailing null */
2669 name_len2++; /* signature byte */
2670 }
2671
2672 count = 1 /* string type byte */ + name_len + name_len2;
2673 inc_rfc1001_len(pSMB, count);
2674 pSMB->ByteCount = cpu_to_le16(count);
2675
2676 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2677 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2678 cifs_stats_inc(&tcon->num_hardlinks);
2679 if (rc)
2680 cFYI(1, "Send error in hard link (NT rename) = %d", rc);
2681
2682 cifs_buf_release(pSMB);
2683 if (rc == -EAGAIN)
2684 goto winCreateHardLinkRetry;
2685
2686 return rc;
2687}
2688
2689int
2690CIFSSMBUnixQuerySymLink(const int xid, struct cifs_tcon *tcon,
2691 const unsigned char *searchName, char **symlinkinfo,
2692 const struct nls_table *nls_codepage)
2693{
2694/* SMB_QUERY_FILE_UNIX_LINK */
2695 TRANSACTION2_QPI_REQ *pSMB = NULL;
2696 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2697 int rc = 0;
2698 int bytes_returned;
2699 int name_len;
2700 __u16 params, byte_count;
2701 char *data_start;
2702
2703 cFYI(1, "In QPathSymLinkInfo (Unix) for path %s", searchName);
2704
2705querySymLinkRetry:
2706 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2707 (void **) &pSMBr);
2708 if (rc)
2709 return rc;
2710
2711 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2712 name_len =
2713 cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
2714 PATH_MAX, nls_codepage);
2715 name_len++; /* trailing null */
2716 name_len *= 2;
2717 } else { /* BB improve the check for buffer overruns BB */
2718 name_len = strnlen(searchName, PATH_MAX);
2719 name_len++; /* trailing null */
2720 strncpy(pSMB->FileName, searchName, name_len);
2721 }
2722
2723 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2724 pSMB->TotalDataCount = 0;
2725 pSMB->MaxParameterCount = cpu_to_le16(2);
2726 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
2727 pSMB->MaxSetupCount = 0;
2728 pSMB->Reserved = 0;
2729 pSMB->Flags = 0;
2730 pSMB->Timeout = 0;
2731 pSMB->Reserved2 = 0;
2732 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2733 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2734 pSMB->DataCount = 0;
2735 pSMB->DataOffset = 0;
2736 pSMB->SetupCount = 1;
2737 pSMB->Reserved3 = 0;
2738 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2739 byte_count = params + 1 /* pad */ ;
2740 pSMB->TotalParameterCount = cpu_to_le16(params);
2741 pSMB->ParameterCount = pSMB->TotalParameterCount;
2742 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2743 pSMB->Reserved4 = 0;
2744 inc_rfc1001_len(pSMB, byte_count);
2745 pSMB->ByteCount = cpu_to_le16(byte_count);
2746
2747 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2748 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2749 if (rc) {
2750 cFYI(1, "Send error in QuerySymLinkInfo = %d", rc);
2751 } else {
2752 /* decode response */
2753
2754 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2755 /* BB also check enough total bytes returned */
2756 if (rc || get_bcc(&pSMBr->hdr) < 2)
2757 rc = -EIO;
2758 else {
2759 bool is_unicode;
2760 u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2761
2762 data_start = ((char *) &pSMBr->hdr.Protocol) +
2763 le16_to_cpu(pSMBr->t2.DataOffset);
2764
2765 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2766 is_unicode = true;
2767 else
2768 is_unicode = false;
2769
2770 /* BB FIXME investigate remapping reserved chars here */
2771 *symlinkinfo = cifs_strndup_from_ucs(data_start, count,
2772 is_unicode, nls_codepage);
2773 if (!*symlinkinfo)
2774 rc = -ENOMEM;
2775 }
2776 }
2777 cifs_buf_release(pSMB);
2778 if (rc == -EAGAIN)
2779 goto querySymLinkRetry;
2780 return rc;
2781}
2782
2783#ifdef CONFIG_CIFS_SYMLINK_EXPERIMENTAL
2784/*
2785 * Recent Windows versions now create symlinks more frequently
2786 * and they use the "reparse point" mechanism below. We can of course
2787 * do symlinks nicely to Samba and other servers which support the
2788 * CIFS Unix Extensions and we can also do SFU symlinks and "client only"
2789 * "MF" symlinks optionally, but for recent Windows we really need to
2790 * reenable the code below and fix the cifs_symlink callers to handle this.
2791 * In the interim this code has been moved to its own config option so
2792 * it is not compiled in by default until callers fixed up and more tested.
2793 */
2794int
2795CIFSSMBQueryReparseLinkInfo(const int xid, struct cifs_tcon *tcon,
2796 const unsigned char *searchName,
2797 char *symlinkinfo, const int buflen, __u16 fid,
2798 const struct nls_table *nls_codepage)
2799{
2800 int rc = 0;
2801 int bytes_returned;
2802 struct smb_com_transaction_ioctl_req *pSMB;
2803 struct smb_com_transaction_ioctl_rsp *pSMBr;
2804
2805 cFYI(1, "In Windows reparse style QueryLink for path %s", searchName);
2806 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2807 (void **) &pSMBr);
2808 if (rc)
2809 return rc;
2810
2811 pSMB->TotalParameterCount = 0 ;
2812 pSMB->TotalDataCount = 0;
2813 pSMB->MaxParameterCount = cpu_to_le32(2);
2814 /* BB find exact data count max from sess structure BB */
2815 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2816 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2817 pSMB->MaxSetupCount = 4;
2818 pSMB->Reserved = 0;
2819 pSMB->ParameterOffset = 0;
2820 pSMB->DataCount = 0;
2821 pSMB->DataOffset = 0;
2822 pSMB->SetupCount = 4;
2823 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2824 pSMB->ParameterCount = pSMB->TotalParameterCount;
2825 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2826 pSMB->IsFsctl = 1; /* FSCTL */
2827 pSMB->IsRootFlag = 0;
2828 pSMB->Fid = fid; /* file handle always le */
2829 pSMB->ByteCount = 0;
2830
2831 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2832 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2833 if (rc) {
2834 cFYI(1, "Send error in QueryReparseLinkInfo = %d", rc);
2835 } else { /* decode response */
2836 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2837 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2838 if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) {
2839 /* BB also check enough total bytes returned */
2840 rc = -EIO; /* bad smb */
2841 goto qreparse_out;
2842 }
2843 if (data_count && (data_count < 2048)) {
2844 char *end_of_smb = 2 /* sizeof byte count */ +
2845 get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
2846
2847 struct reparse_data *reparse_buf =
2848 (struct reparse_data *)
2849 ((char *)&pSMBr->hdr.Protocol
2850 + data_offset);
2851 if ((char *)reparse_buf >= end_of_smb) {
2852 rc = -EIO;
2853 goto qreparse_out;
2854 }
2855 if ((reparse_buf->LinkNamesBuf +
2856 reparse_buf->TargetNameOffset +
2857 reparse_buf->TargetNameLen) > end_of_smb) {
2858 cFYI(1, "reparse buf beyond SMB");
2859 rc = -EIO;
2860 goto qreparse_out;
2861 }
2862
2863 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2864 cifs_from_ucs2(symlinkinfo, (__le16 *)
2865 (reparse_buf->LinkNamesBuf +
2866 reparse_buf->TargetNameOffset),
2867 buflen,
2868 reparse_buf->TargetNameLen,
2869 nls_codepage, 0);
2870 } else { /* ASCII names */
2871 strncpy(symlinkinfo,
2872 reparse_buf->LinkNamesBuf +
2873 reparse_buf->TargetNameOffset,
2874 min_t(const int, buflen,
2875 reparse_buf->TargetNameLen));
2876 }
2877 } else {
2878 rc = -EIO;
2879 cFYI(1, "Invalid return data count on "
2880 "get reparse info ioctl");
2881 }
2882 symlinkinfo[buflen] = 0; /* just in case so the caller
2883 does not go off the end of the buffer */
2884 cFYI(1, "readlink result - %s", symlinkinfo);
2885 }
2886
2887qreparse_out:
2888 cifs_buf_release(pSMB);
2889
2890 /* Note: On -EAGAIN error only caller can retry on handle based calls
2891 since file handle passed in no longer valid */
2892
2893 return rc;
2894}
2895#endif /* CIFS_SYMLINK_EXPERIMENTAL */ /* BB temporarily unused */
2896
2897#ifdef CONFIG_CIFS_POSIX
2898
2899/*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2900static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2901 struct cifs_posix_ace *cifs_ace)
2902{
2903 /* u8 cifs fields do not need le conversion */
2904 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2905 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
2906 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2907 /* cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id); */
2908
2909 return;
2910}
2911
2912/* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2913static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2914 const int acl_type, const int size_of_data_area)
2915{
2916 int size = 0;
2917 int i;
2918 __u16 count;
2919 struct cifs_posix_ace *pACE;
2920 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2921 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2922
2923 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2924 return -EOPNOTSUPP;
2925
2926 if (acl_type & ACL_TYPE_ACCESS) {
2927 count = le16_to_cpu(cifs_acl->access_entry_count);
2928 pACE = &cifs_acl->ace_array[0];
2929 size = sizeof(struct cifs_posix_acl);
2930 size += sizeof(struct cifs_posix_ace) * count;
2931 /* check if we would go beyond end of SMB */
2932 if (size_of_data_area < size) {
2933 cFYI(1, "bad CIFS POSIX ACL size %d vs. %d",
2934 size_of_data_area, size);
2935 return -EINVAL;
2936 }
2937 } else if (acl_type & ACL_TYPE_DEFAULT) {
2938 count = le16_to_cpu(cifs_acl->access_entry_count);
2939 size = sizeof(struct cifs_posix_acl);
2940 size += sizeof(struct cifs_posix_ace) * count;
2941/* skip past access ACEs to get to default ACEs */
2942 pACE = &cifs_acl->ace_array[count];
2943 count = le16_to_cpu(cifs_acl->default_entry_count);
2944 size += sizeof(struct cifs_posix_ace) * count;
2945 /* check if we would go beyond end of SMB */
2946 if (size_of_data_area < size)
2947 return -EINVAL;
2948 } else {
2949 /* illegal type */
2950 return -EINVAL;
2951 }
2952
2953 size = posix_acl_xattr_size(count);
2954 if ((buflen == 0) || (local_acl == NULL)) {
2955 /* used to query ACL EA size */
2956 } else if (size > buflen) {
2957 return -ERANGE;
2958 } else /* buffer big enough */ {
2959 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2960 for (i = 0; i < count ; i++) {
2961 cifs_convert_ace(&local_acl->a_entries[i], pACE);
2962 pACE++;
2963 }
2964 }
2965 return size;
2966}
2967
2968static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2969 const posix_acl_xattr_entry *local_ace)
2970{
2971 __u16 rc = 0; /* 0 = ACL converted ok */
2972
2973 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2974 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
2975 /* BB is there a better way to handle the large uid? */
2976 if (local_ace->e_id == cpu_to_le32(-1)) {
2977 /* Probably no need to le convert -1 on any arch but can not hurt */
2978 cifs_ace->cifs_uid = cpu_to_le64(-1);
2979 } else
2980 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2981 /*cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id);*/
2982 return rc;
2983}
2984
2985/* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2986static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2987 const int buflen, const int acl_type)
2988{
2989 __u16 rc = 0;
2990 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2991 posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2992 int count;
2993 int i;
2994
2995 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2996 return 0;
2997
2998 count = posix_acl_xattr_count((size_t)buflen);
2999 cFYI(1, "setting acl with %d entries from buf of length %d and "
3000 "version of %d",
3001 count, buflen, le32_to_cpu(local_acl->a_version));
3002 if (le32_to_cpu(local_acl->a_version) != 2) {
3003 cFYI(1, "unknown POSIX ACL version %d",
3004 le32_to_cpu(local_acl->a_version));
3005 return 0;
3006 }
3007 cifs_acl->version = cpu_to_le16(1);
3008 if (acl_type == ACL_TYPE_ACCESS)
3009 cifs_acl->access_entry_count = cpu_to_le16(count);
3010 else if (acl_type == ACL_TYPE_DEFAULT)
3011 cifs_acl->default_entry_count = cpu_to_le16(count);
3012 else {
3013 cFYI(1, "unknown ACL type %d", acl_type);
3014 return 0;
3015 }
3016 for (i = 0; i < count; i++) {
3017 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
3018 &local_acl->a_entries[i]);
3019 if (rc != 0) {
3020 /* ACE not converted */
3021 break;
3022 }
3023 }
3024 if (rc == 0) {
3025 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
3026 rc += sizeof(struct cifs_posix_acl);
3027 /* BB add check to make sure ACL does not overflow SMB */
3028 }
3029 return rc;
3030}
3031
3032int
3033CIFSSMBGetPosixACL(const int xid, struct cifs_tcon *tcon,
3034 const unsigned char *searchName,
3035 char *acl_inf, const int buflen, const int acl_type,
3036 const struct nls_table *nls_codepage, int remap)
3037{
3038/* SMB_QUERY_POSIX_ACL */
3039 TRANSACTION2_QPI_REQ *pSMB = NULL;
3040 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3041 int rc = 0;
3042 int bytes_returned;
3043 int name_len;
3044 __u16 params, byte_count;
3045
3046 cFYI(1, "In GetPosixACL (Unix) for path %s", searchName);
3047
3048queryAclRetry:
3049 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3050 (void **) &pSMBr);
3051 if (rc)
3052 return rc;
3053
3054 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3055 name_len =
3056 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3057 PATH_MAX, nls_codepage, remap);
3058 name_len++; /* trailing null */
3059 name_len *= 2;
3060 pSMB->FileName[name_len] = 0;
3061 pSMB->FileName[name_len+1] = 0;
3062 } else { /* BB improve the check for buffer overruns BB */
3063 name_len = strnlen(searchName, PATH_MAX);
3064 name_len++; /* trailing null */
3065 strncpy(pSMB->FileName, searchName, name_len);
3066 }
3067
3068 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3069 pSMB->TotalDataCount = 0;
3070 pSMB->MaxParameterCount = cpu_to_le16(2);
3071 /* BB find exact max data count below from sess structure BB */
3072 pSMB->MaxDataCount = cpu_to_le16(4000);
3073 pSMB->MaxSetupCount = 0;
3074 pSMB->Reserved = 0;
3075 pSMB->Flags = 0;
3076 pSMB->Timeout = 0;
3077 pSMB->Reserved2 = 0;
3078 pSMB->ParameterOffset = cpu_to_le16(
3079 offsetof(struct smb_com_transaction2_qpi_req,
3080 InformationLevel) - 4);
3081 pSMB->DataCount = 0;
3082 pSMB->DataOffset = 0;
3083 pSMB->SetupCount = 1;
3084 pSMB->Reserved3 = 0;
3085 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3086 byte_count = params + 1 /* pad */ ;
3087 pSMB->TotalParameterCount = cpu_to_le16(params);
3088 pSMB->ParameterCount = pSMB->TotalParameterCount;
3089 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
3090 pSMB->Reserved4 = 0;
3091 inc_rfc1001_len(pSMB, byte_count);
3092 pSMB->ByteCount = cpu_to_le16(byte_count);
3093
3094 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3095 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3096 cifs_stats_inc(&tcon->num_acl_get);
3097 if (rc) {
3098 cFYI(1, "Send error in Query POSIX ACL = %d", rc);
3099 } else {
3100 /* decode response */
3101
3102 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3103 /* BB also check enough total bytes returned */
3104 if (rc || get_bcc(&pSMBr->hdr) < 2)
3105 rc = -EIO; /* bad smb */
3106 else {
3107 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3108 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3109 rc = cifs_copy_posix_acl(acl_inf,
3110 (char *)&pSMBr->hdr.Protocol+data_offset,
3111 buflen, acl_type, count);
3112 }
3113 }
3114 cifs_buf_release(pSMB);
3115 if (rc == -EAGAIN)
3116 goto queryAclRetry;
3117 return rc;
3118}
3119
3120int
3121CIFSSMBSetPosixACL(const int xid, struct cifs_tcon *tcon,
3122 const unsigned char *fileName,
3123 const char *local_acl, const int buflen,
3124 const int acl_type,
3125 const struct nls_table *nls_codepage, int remap)
3126{
3127 struct smb_com_transaction2_spi_req *pSMB = NULL;
3128 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3129 char *parm_data;
3130 int name_len;
3131 int rc = 0;
3132 int bytes_returned = 0;
3133 __u16 params, byte_count, data_count, param_offset, offset;
3134
3135 cFYI(1, "In SetPosixACL (Unix) for path %s", fileName);
3136setAclRetry:
3137 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3138 (void **) &pSMBr);
3139 if (rc)
3140 return rc;
3141 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3142 name_len =
3143 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
3144 PATH_MAX, nls_codepage, remap);
3145 name_len++; /* trailing null */
3146 name_len *= 2;
3147 } else { /* BB improve the check for buffer overruns BB */
3148 name_len = strnlen(fileName, PATH_MAX);
3149 name_len++; /* trailing null */
3150 strncpy(pSMB->FileName, fileName, name_len);
3151 }
3152 params = 6 + name_len;
3153 pSMB->MaxParameterCount = cpu_to_le16(2);
3154 /* BB find max SMB size from sess */
3155 pSMB->MaxDataCount = cpu_to_le16(1000);
3156 pSMB->MaxSetupCount = 0;
3157 pSMB->Reserved = 0;
3158 pSMB->Flags = 0;
3159 pSMB->Timeout = 0;
3160 pSMB->Reserved2 = 0;
3161 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3162 InformationLevel) - 4;
3163 offset = param_offset + params;
3164 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
3165 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3166
3167 /* convert to on the wire format for POSIX ACL */
3168 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
3169
3170 if (data_count == 0) {
3171 rc = -EOPNOTSUPP;
3172 goto setACLerrorExit;
3173 }
3174 pSMB->DataOffset = cpu_to_le16(offset);
3175 pSMB->SetupCount = 1;
3176 pSMB->Reserved3 = 0;
3177 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3178 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
3179 byte_count = 3 /* pad */ + params + data_count;
3180 pSMB->DataCount = cpu_to_le16(data_count);
3181 pSMB->TotalDataCount = pSMB->DataCount;
3182 pSMB->ParameterCount = cpu_to_le16(params);
3183 pSMB->TotalParameterCount = pSMB->ParameterCount;
3184 pSMB->Reserved4 = 0;
3185 inc_rfc1001_len(pSMB, byte_count);
3186 pSMB->ByteCount = cpu_to_le16(byte_count);
3187 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3188 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3189 if (rc)
3190 cFYI(1, "Set POSIX ACL returned %d", rc);
3191
3192setACLerrorExit:
3193 cifs_buf_release(pSMB);
3194 if (rc == -EAGAIN)
3195 goto setAclRetry;
3196 return rc;
3197}
3198
3199/* BB fix tabs in this function FIXME BB */
3200int
3201CIFSGetExtAttr(const int xid, struct cifs_tcon *tcon,
3202 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
3203{
3204 int rc = 0;
3205 struct smb_t2_qfi_req *pSMB = NULL;
3206 struct smb_t2_qfi_rsp *pSMBr = NULL;
3207 int bytes_returned;
3208 __u16 params, byte_count;
3209
3210 cFYI(1, "In GetExtAttr");
3211 if (tcon == NULL)
3212 return -ENODEV;
3213
3214GetExtAttrRetry:
3215 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3216 (void **) &pSMBr);
3217 if (rc)
3218 return rc;
3219
3220 params = 2 /* level */ + 2 /* fid */;
3221 pSMB->t2.TotalDataCount = 0;
3222 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3223 /* BB find exact max data count below from sess structure BB */
3224 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3225 pSMB->t2.MaxSetupCount = 0;
3226 pSMB->t2.Reserved = 0;
3227 pSMB->t2.Flags = 0;
3228 pSMB->t2.Timeout = 0;
3229 pSMB->t2.Reserved2 = 0;
3230 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3231 Fid) - 4);
3232 pSMB->t2.DataCount = 0;
3233 pSMB->t2.DataOffset = 0;
3234 pSMB->t2.SetupCount = 1;
3235 pSMB->t2.Reserved3 = 0;
3236 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3237 byte_count = params + 1 /* pad */ ;
3238 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3239 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3240 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3241 pSMB->Pad = 0;
3242 pSMB->Fid = netfid;
3243 inc_rfc1001_len(pSMB, byte_count);
3244 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3245
3246 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3247 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3248 if (rc) {
3249 cFYI(1, "error %d in GetExtAttr", rc);
3250 } else {
3251 /* decode response */
3252 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3253 /* BB also check enough total bytes returned */
3254 if (rc || get_bcc(&pSMBr->hdr) < 2)
3255 /* If rc should we check for EOPNOSUPP and
3256 disable the srvino flag? or in caller? */
3257 rc = -EIO; /* bad smb */
3258 else {
3259 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3260 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3261 struct file_chattr_info *pfinfo;
3262 /* BB Do we need a cast or hash here ? */
3263 if (count != 16) {
3264 cFYI(1, "Illegal size ret in GetExtAttr");
3265 rc = -EIO;
3266 goto GetExtAttrOut;
3267 }
3268 pfinfo = (struct file_chattr_info *)
3269 (data_offset + (char *) &pSMBr->hdr.Protocol);
3270 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3271 *pMask = le64_to_cpu(pfinfo->mask);
3272 }
3273 }
3274GetExtAttrOut:
3275 cifs_buf_release(pSMB);
3276 if (rc == -EAGAIN)
3277 goto GetExtAttrRetry;
3278 return rc;
3279}
3280
3281#endif /* CONFIG_POSIX */
3282
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 */
3292static int
3293smb_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
3322static int
3323validate_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
3375/* Get Security Descriptor (by handle) from remote server for a file or dir */
3376int
3377CIFSSMBGetCIFSACL(const int xid, struct cifs_tcon *tcon, __u16 fid,
3378 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3379{
3380 int rc = 0;
3381 int buf_type = 0;
3382 QUERY_SEC_DESC_REQ *pSMB;
3383 struct kvec iov[1];
3384
3385 cFYI(1, "GetCifsACL");
3386
3387 *pbuflen = 0;
3388 *acl_inf = NULL;
3389
3390 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3391 8 /* parm len */, tcon, (void **) &pSMB);
3392 if (rc)
3393 return rc;
3394
3395 pSMB->MaxParameterCount = cpu_to_le32(4);
3396 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3397 pSMB->MaxSetupCount = 0;
3398 pSMB->Fid = fid; /* file handle always le */
3399 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3400 CIFS_ACL_DACL);
3401 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3402 inc_rfc1001_len(pSMB, 11);
3403 iov[0].iov_base = (char *)pSMB;
3404 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
3405
3406 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3407 0);
3408 cifs_stats_inc(&tcon->num_acl_get);
3409 if (rc) {
3410 cFYI(1, "Send error in QuerySecDesc = %d", rc);
3411 } else { /* decode response */
3412 __le32 *parm;
3413 __u32 parm_len;
3414 __u32 acl_len;
3415 struct smb_com_ntransact_rsp *pSMBr;
3416 char *pdata;
3417
3418/* validate_nttransact */
3419 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3420 &pdata, &parm_len, pbuflen);
3421 if (rc)
3422 goto qsec_out;
3423 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3424
3425 cFYI(1, "smb %p parm %p data %p", pSMBr, parm, *acl_inf);
3426
3427 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3428 rc = -EIO; /* bad smb */
3429 *pbuflen = 0;
3430 goto qsec_out;
3431 }
3432
3433/* BB check that data area is minimum length and as big as acl_len */
3434
3435 acl_len = le32_to_cpu(*parm);
3436 if (acl_len != *pbuflen) {
3437 cERROR(1, "acl length %d does not match %d",
3438 acl_len, *pbuflen);
3439 if (*pbuflen > acl_len)
3440 *pbuflen = acl_len;
3441 }
3442
3443 /* check if buffer is big enough for the acl
3444 header followed by the smallest SID */
3445 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3446 (*pbuflen >= 64 * 1024)) {
3447 cERROR(1, "bad acl length %d", *pbuflen);
3448 rc = -EINVAL;
3449 *pbuflen = 0;
3450 } else {
3451 *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3452 if (*acl_inf == NULL) {
3453 *pbuflen = 0;
3454 rc = -ENOMEM;
3455 }
3456 memcpy(*acl_inf, pdata, *pbuflen);
3457 }
3458 }
3459qsec_out:
3460 if (buf_type == CIFS_SMALL_BUFFER)
3461 cifs_small_buf_release(iov[0].iov_base);
3462 else if (buf_type == CIFS_LARGE_BUFFER)
3463 cifs_buf_release(iov[0].iov_base);
3464/* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3465 return rc;
3466}
3467
3468int
3469CIFSSMBSetCIFSACL(const int xid, struct cifs_tcon *tcon, __u16 fid,
3470 struct cifs_ntsd *pntsd, __u32 acllen)
3471{
3472 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3473 int rc = 0;
3474 int bytes_returned = 0;
3475 SET_SEC_DESC_REQ *pSMB = NULL;
3476 NTRANSACT_RSP *pSMBr = NULL;
3477
3478setCifsAclRetry:
3479 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB,
3480 (void **) &pSMBr);
3481 if (rc)
3482 return (rc);
3483
3484 pSMB->MaxSetupCount = 0;
3485 pSMB->Reserved = 0;
3486
3487 param_count = 8;
3488 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3489 data_count = acllen;
3490 data_offset = param_offset + param_count;
3491 byte_count = 3 /* pad */ + param_count;
3492
3493 pSMB->DataCount = cpu_to_le32(data_count);
3494 pSMB->TotalDataCount = pSMB->DataCount;
3495 pSMB->MaxParameterCount = cpu_to_le32(4);
3496 pSMB->MaxDataCount = cpu_to_le32(16384);
3497 pSMB->ParameterCount = cpu_to_le32(param_count);
3498 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3499 pSMB->TotalParameterCount = pSMB->ParameterCount;
3500 pSMB->DataOffset = cpu_to_le32(data_offset);
3501 pSMB->SetupCount = 0;
3502 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3503 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3504
3505 pSMB->Fid = fid; /* file handle always le */
3506 pSMB->Reserved2 = 0;
3507 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_DACL);
3508
3509 if (pntsd && acllen) {
3510 memcpy((char *) &pSMBr->hdr.Protocol + data_offset,
3511 (char *) pntsd,
3512 acllen);
3513 inc_rfc1001_len(pSMB, byte_count + data_count);
3514 } else
3515 inc_rfc1001_len(pSMB, byte_count);
3516
3517 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3518 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3519
3520 cFYI(1, "SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc);
3521 if (rc)
3522 cFYI(1, "Set CIFS ACL returned %d", rc);
3523 cifs_buf_release(pSMB);
3524
3525 if (rc == -EAGAIN)
3526 goto setCifsAclRetry;
3527
3528 return (rc);
3529}
3530
3531#endif /* CONFIG_CIFS_ACL */
3532
3533/* Legacy Query Path Information call for lookup to old servers such
3534 as Win9x/WinME */
3535int SMBQueryInformation(const int xid, struct cifs_tcon *tcon,
3536 const unsigned char *searchName,
3537 FILE_ALL_INFO *pFinfo,
3538 const struct nls_table *nls_codepage, int remap)
3539{
3540 QUERY_INFORMATION_REQ *pSMB;
3541 QUERY_INFORMATION_RSP *pSMBr;
3542 int rc = 0;
3543 int bytes_returned;
3544 int name_len;
3545
3546 cFYI(1, "In SMBQPath path %s", searchName);
3547QInfRetry:
3548 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3549 (void **) &pSMBr);
3550 if (rc)
3551 return rc;
3552
3553 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3554 name_len =
3555 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3556 PATH_MAX, nls_codepage, remap);
3557 name_len++; /* trailing null */
3558 name_len *= 2;
3559 } else {
3560 name_len = strnlen(searchName, PATH_MAX);
3561 name_len++; /* trailing null */
3562 strncpy(pSMB->FileName, searchName, name_len);
3563 }
3564 pSMB->BufferFormat = 0x04;
3565 name_len++; /* account for buffer type byte */
3566 inc_rfc1001_len(pSMB, (__u16)name_len);
3567 pSMB->ByteCount = cpu_to_le16(name_len);
3568
3569 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3570 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3571 if (rc) {
3572 cFYI(1, "Send error in QueryInfo = %d", rc);
3573 } else if (pFinfo) {
3574 struct timespec ts;
3575 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3576
3577 /* decode response */
3578 /* BB FIXME - add time zone adjustment BB */
3579 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3580 ts.tv_nsec = 0;
3581 ts.tv_sec = time;
3582 /* decode time fields */
3583 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3584 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3585 pFinfo->LastAccessTime = 0;
3586 pFinfo->AllocationSize =
3587 cpu_to_le64(le32_to_cpu(pSMBr->size));
3588 pFinfo->EndOfFile = pFinfo->AllocationSize;
3589 pFinfo->Attributes =
3590 cpu_to_le32(le16_to_cpu(pSMBr->attr));
3591 } else
3592 rc = -EIO; /* bad buffer passed in */
3593
3594 cifs_buf_release(pSMB);
3595
3596 if (rc == -EAGAIN)
3597 goto QInfRetry;
3598
3599 return rc;
3600}
3601
3602int
3603CIFSSMBQFileInfo(const int xid, struct cifs_tcon *tcon,
3604 u16 netfid, FILE_ALL_INFO *pFindData)
3605{
3606 struct smb_t2_qfi_req *pSMB = NULL;
3607 struct smb_t2_qfi_rsp *pSMBr = NULL;
3608 int rc = 0;
3609 int bytes_returned;
3610 __u16 params, byte_count;
3611
3612QFileInfoRetry:
3613 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3614 (void **) &pSMBr);
3615 if (rc)
3616 return rc;
3617
3618 params = 2 /* level */ + 2 /* fid */;
3619 pSMB->t2.TotalDataCount = 0;
3620 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3621 /* BB find exact max data count below from sess structure BB */
3622 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3623 pSMB->t2.MaxSetupCount = 0;
3624 pSMB->t2.Reserved = 0;
3625 pSMB->t2.Flags = 0;
3626 pSMB->t2.Timeout = 0;
3627 pSMB->t2.Reserved2 = 0;
3628 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3629 Fid) - 4);
3630 pSMB->t2.DataCount = 0;
3631 pSMB->t2.DataOffset = 0;
3632 pSMB->t2.SetupCount = 1;
3633 pSMB->t2.Reserved3 = 0;
3634 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3635 byte_count = params + 1 /* pad */ ;
3636 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3637 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3638 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3639 pSMB->Pad = 0;
3640 pSMB->Fid = netfid;
3641 inc_rfc1001_len(pSMB, byte_count);
3642
3643 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3644 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3645 if (rc) {
3646 cFYI(1, "Send error in QPathInfo = %d", rc);
3647 } else { /* decode response */
3648 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3649
3650 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3651 rc = -EIO;
3652 else if (get_bcc(&pSMBr->hdr) < 40)
3653 rc = -EIO; /* bad smb */
3654 else if (pFindData) {
3655 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3656 memcpy((char *) pFindData,
3657 (char *) &pSMBr->hdr.Protocol +
3658 data_offset, sizeof(FILE_ALL_INFO));
3659 } else
3660 rc = -ENOMEM;
3661 }
3662 cifs_buf_release(pSMB);
3663 if (rc == -EAGAIN)
3664 goto QFileInfoRetry;
3665
3666 return rc;
3667}
3668
3669int
3670CIFSSMBQPathInfo(const int xid, struct cifs_tcon *tcon,
3671 const unsigned char *searchName,
3672 FILE_ALL_INFO *pFindData,
3673 int legacy /* old style infolevel */,
3674 const struct nls_table *nls_codepage, int remap)
3675{
3676/* level 263 SMB_QUERY_FILE_ALL_INFO */
3677 TRANSACTION2_QPI_REQ *pSMB = NULL;
3678 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3679 int rc = 0;
3680 int bytes_returned;
3681 int name_len;
3682 __u16 params, byte_count;
3683
3684/* cFYI(1, "In QPathInfo path %s", searchName); */
3685QPathInfoRetry:
3686 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3687 (void **) &pSMBr);
3688 if (rc)
3689 return rc;
3690
3691 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3692 name_len =
3693 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3694 PATH_MAX, nls_codepage, remap);
3695 name_len++; /* trailing null */
3696 name_len *= 2;
3697 } else { /* BB improve the check for buffer overruns BB */
3698 name_len = strnlen(searchName, PATH_MAX);
3699 name_len++; /* trailing null */
3700 strncpy(pSMB->FileName, searchName, name_len);
3701 }
3702
3703 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3704 pSMB->TotalDataCount = 0;
3705 pSMB->MaxParameterCount = cpu_to_le16(2);
3706 /* BB find exact max SMB PDU from sess structure BB */
3707 pSMB->MaxDataCount = cpu_to_le16(4000);
3708 pSMB->MaxSetupCount = 0;
3709 pSMB->Reserved = 0;
3710 pSMB->Flags = 0;
3711 pSMB->Timeout = 0;
3712 pSMB->Reserved2 = 0;
3713 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3714 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3715 pSMB->DataCount = 0;
3716 pSMB->DataOffset = 0;
3717 pSMB->SetupCount = 1;
3718 pSMB->Reserved3 = 0;
3719 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3720 byte_count = params + 1 /* pad */ ;
3721 pSMB->TotalParameterCount = cpu_to_le16(params);
3722 pSMB->ParameterCount = pSMB->TotalParameterCount;
3723 if (legacy)
3724 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3725 else
3726 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3727 pSMB->Reserved4 = 0;
3728 inc_rfc1001_len(pSMB, byte_count);
3729 pSMB->ByteCount = cpu_to_le16(byte_count);
3730
3731 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3732 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3733 if (rc) {
3734 cFYI(1, "Send error in QPathInfo = %d", rc);
3735 } else { /* decode response */
3736 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3737
3738 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3739 rc = -EIO;
3740 else if (!legacy && get_bcc(&pSMBr->hdr) < 40)
3741 rc = -EIO; /* bad smb */
3742 else if (legacy && get_bcc(&pSMBr->hdr) < 24)
3743 rc = -EIO; /* 24 or 26 expected but we do not read
3744 last field */
3745 else if (pFindData) {
3746 int size;
3747 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3748
3749 /* On legacy responses we do not read the last field,
3750 EAsize, fortunately since it varies by subdialect and
3751 also note it differs on Set vs. Get, ie two bytes or 4
3752 bytes depending but we don't care here */
3753 if (legacy)
3754 size = sizeof(FILE_INFO_STANDARD);
3755 else
3756 size = sizeof(FILE_ALL_INFO);
3757 memcpy((char *) pFindData,
3758 (char *) &pSMBr->hdr.Protocol +
3759 data_offset, size);
3760 } else
3761 rc = -ENOMEM;
3762 }
3763 cifs_buf_release(pSMB);
3764 if (rc == -EAGAIN)
3765 goto QPathInfoRetry;
3766
3767 return rc;
3768}
3769
3770int
3771CIFSSMBUnixQFileInfo(const int xid, struct cifs_tcon *tcon,
3772 u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
3773{
3774 struct smb_t2_qfi_req *pSMB = NULL;
3775 struct smb_t2_qfi_rsp *pSMBr = NULL;
3776 int rc = 0;
3777 int bytes_returned;
3778 __u16 params, byte_count;
3779
3780UnixQFileInfoRetry:
3781 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3782 (void **) &pSMBr);
3783 if (rc)
3784 return rc;
3785
3786 params = 2 /* level */ + 2 /* fid */;
3787 pSMB->t2.TotalDataCount = 0;
3788 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3789 /* BB find exact max data count below from sess structure BB */
3790 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3791 pSMB->t2.MaxSetupCount = 0;
3792 pSMB->t2.Reserved = 0;
3793 pSMB->t2.Flags = 0;
3794 pSMB->t2.Timeout = 0;
3795 pSMB->t2.Reserved2 = 0;
3796 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3797 Fid) - 4);
3798 pSMB->t2.DataCount = 0;
3799 pSMB->t2.DataOffset = 0;
3800 pSMB->t2.SetupCount = 1;
3801 pSMB->t2.Reserved3 = 0;
3802 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3803 byte_count = params + 1 /* pad */ ;
3804 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3805 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3806 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3807 pSMB->Pad = 0;
3808 pSMB->Fid = netfid;
3809 inc_rfc1001_len(pSMB, byte_count);
3810
3811 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3812 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3813 if (rc) {
3814 cFYI(1, "Send error in QPathInfo = %d", rc);
3815 } else { /* decode response */
3816 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3817
3818 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
3819 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
3820 "Unix Extensions can be disabled on mount "
3821 "by specifying the nosfu mount option.");
3822 rc = -EIO; /* bad smb */
3823 } else {
3824 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3825 memcpy((char *) pFindData,
3826 (char *) &pSMBr->hdr.Protocol +
3827 data_offset,
3828 sizeof(FILE_UNIX_BASIC_INFO));
3829 }
3830 }
3831
3832 cifs_buf_release(pSMB);
3833 if (rc == -EAGAIN)
3834 goto UnixQFileInfoRetry;
3835
3836 return rc;
3837}
3838
3839int
3840CIFSSMBUnixQPathInfo(const int xid, struct cifs_tcon *tcon,
3841 const unsigned char *searchName,
3842 FILE_UNIX_BASIC_INFO *pFindData,
3843 const struct nls_table *nls_codepage, int remap)
3844{
3845/* SMB_QUERY_FILE_UNIX_BASIC */
3846 TRANSACTION2_QPI_REQ *pSMB = NULL;
3847 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3848 int rc = 0;
3849 int bytes_returned = 0;
3850 int name_len;
3851 __u16 params, byte_count;
3852
3853 cFYI(1, "In QPathInfo (Unix) the path %s", searchName);
3854UnixQPathInfoRetry:
3855 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3856 (void **) &pSMBr);
3857 if (rc)
3858 return rc;
3859
3860 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3861 name_len =
3862 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3863 PATH_MAX, nls_codepage, remap);
3864 name_len++; /* trailing null */
3865 name_len *= 2;
3866 } else { /* BB improve the check for buffer overruns BB */
3867 name_len = strnlen(searchName, PATH_MAX);
3868 name_len++; /* trailing null */
3869 strncpy(pSMB->FileName, searchName, name_len);
3870 }
3871
3872 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3873 pSMB->TotalDataCount = 0;
3874 pSMB->MaxParameterCount = cpu_to_le16(2);
3875 /* BB find exact max SMB PDU from sess structure BB */
3876 pSMB->MaxDataCount = cpu_to_le16(4000);
3877 pSMB->MaxSetupCount = 0;
3878 pSMB->Reserved = 0;
3879 pSMB->Flags = 0;
3880 pSMB->Timeout = 0;
3881 pSMB->Reserved2 = 0;
3882 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3883 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3884 pSMB->DataCount = 0;
3885 pSMB->DataOffset = 0;
3886 pSMB->SetupCount = 1;
3887 pSMB->Reserved3 = 0;
3888 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3889 byte_count = params + 1 /* pad */ ;
3890 pSMB->TotalParameterCount = cpu_to_le16(params);
3891 pSMB->ParameterCount = pSMB->TotalParameterCount;
3892 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3893 pSMB->Reserved4 = 0;
3894 inc_rfc1001_len(pSMB, byte_count);
3895 pSMB->ByteCount = cpu_to_le16(byte_count);
3896
3897 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3898 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3899 if (rc) {
3900 cFYI(1, "Send error in QPathInfo = %d", rc);
3901 } else { /* decode response */
3902 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3903
3904 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
3905 cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
3906 "Unix Extensions can be disabled on mount "
3907 "by specifying the nosfu mount option.");
3908 rc = -EIO; /* bad smb */
3909 } else {
3910 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3911 memcpy((char *) pFindData,
3912 (char *) &pSMBr->hdr.Protocol +
3913 data_offset,
3914 sizeof(FILE_UNIX_BASIC_INFO));
3915 }
3916 }
3917 cifs_buf_release(pSMB);
3918 if (rc == -EAGAIN)
3919 goto UnixQPathInfoRetry;
3920
3921 return rc;
3922}
3923
3924/* xid, tcon, searchName and codepage are input parms, rest are returned */
3925int
3926CIFSFindFirst(const int xid, struct cifs_tcon *tcon,
3927 const char *searchName,
3928 const struct nls_table *nls_codepage,
3929 __u16 *pnetfid,
3930 struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3931{
3932/* level 257 SMB_ */
3933 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3934 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3935 T2_FFIRST_RSP_PARMS *parms;
3936 int rc = 0;
3937 int bytes_returned = 0;
3938 int name_len;
3939 __u16 params, byte_count;
3940
3941 cFYI(1, "In FindFirst for %s", searchName);
3942
3943findFirstRetry:
3944 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3945 (void **) &pSMBr);
3946 if (rc)
3947 return rc;
3948
3949 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3950 name_len =
3951 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3952 PATH_MAX, nls_codepage, remap);
3953 /* We can not add the asterik earlier in case
3954 it got remapped to 0xF03A as if it were part of the
3955 directory name instead of a wildcard */
3956 name_len *= 2;
3957 pSMB->FileName[name_len] = dirsep;
3958 pSMB->FileName[name_len+1] = 0;
3959 pSMB->FileName[name_len+2] = '*';
3960 pSMB->FileName[name_len+3] = 0;
3961 name_len += 4; /* now the trailing null */
3962 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3963 pSMB->FileName[name_len+1] = 0;
3964 name_len += 2;
3965 } else { /* BB add check for overrun of SMB buf BB */
3966 name_len = strnlen(searchName, PATH_MAX);
3967/* BB fix here and in unicode clause above ie
3968 if (name_len > buffersize-header)
3969 free buffer exit; BB */
3970 strncpy(pSMB->FileName, searchName, name_len);
3971 pSMB->FileName[name_len] = dirsep;
3972 pSMB->FileName[name_len+1] = '*';
3973 pSMB->FileName[name_len+2] = 0;
3974 name_len += 3;
3975 }
3976
3977 params = 12 + name_len /* includes null */ ;
3978 pSMB->TotalDataCount = 0; /* no EAs */
3979 pSMB->MaxParameterCount = cpu_to_le16(10);
3980 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3981 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3982 pSMB->MaxSetupCount = 0;
3983 pSMB->Reserved = 0;
3984 pSMB->Flags = 0;
3985 pSMB->Timeout = 0;
3986 pSMB->Reserved2 = 0;
3987 byte_count = params + 1 /* pad */ ;
3988 pSMB->TotalParameterCount = cpu_to_le16(params);
3989 pSMB->ParameterCount = pSMB->TotalParameterCount;
3990 pSMB->ParameterOffset = cpu_to_le16(
3991 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3992 - 4);
3993 pSMB->DataCount = 0;
3994 pSMB->DataOffset = 0;
3995 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
3996 pSMB->Reserved3 = 0;
3997 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3998 pSMB->SearchAttributes =
3999 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
4000 ATTR_DIRECTORY);
4001 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
4002 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
4003 CIFS_SEARCH_RETURN_RESUME);
4004 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4005
4006 /* BB what should we set StorageType to? Does it matter? BB */
4007 pSMB->SearchStorageType = 0;
4008 inc_rfc1001_len(pSMB, byte_count);
4009 pSMB->ByteCount = cpu_to_le16(byte_count);
4010
4011 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4012 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4013 cifs_stats_inc(&tcon->num_ffirst);
4014
4015 if (rc) {/* BB add logic to retry regular search if Unix search
4016 rejected unexpectedly by server */
4017 /* BB Add code to handle unsupported level rc */
4018 cFYI(1, "Error in FindFirst = %d", rc);
4019
4020 cifs_buf_release(pSMB);
4021
4022 /* BB eventually could optimize out free and realloc of buf */
4023 /* for this case */
4024 if (rc == -EAGAIN)
4025 goto findFirstRetry;
4026 } else { /* decode response */
4027 /* BB remember to free buffer if error BB */
4028 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4029 if (rc == 0) {
4030 unsigned int lnoff;
4031
4032 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4033 psrch_inf->unicode = true;
4034 else
4035 psrch_inf->unicode = false;
4036
4037 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
4038 psrch_inf->smallBuf = 0;
4039 psrch_inf->srch_entries_start =
4040 (char *) &pSMBr->hdr.Protocol +
4041 le16_to_cpu(pSMBr->t2.DataOffset);
4042 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
4043 le16_to_cpu(pSMBr->t2.ParameterOffset));
4044
4045 if (parms->EndofSearch)
4046 psrch_inf->endOfSearch = true;
4047 else
4048 psrch_inf->endOfSearch = false;
4049
4050 psrch_inf->entries_in_buffer =
4051 le16_to_cpu(parms->SearchCount);
4052 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
4053 psrch_inf->entries_in_buffer;
4054 lnoff = le16_to_cpu(parms->LastNameOffset);
4055 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
4056 lnoff) {
4057 cERROR(1, "ignoring corrupt resume name");
4058 psrch_inf->last_entry = NULL;
4059 return rc;
4060 }
4061
4062 psrch_inf->last_entry = psrch_inf->srch_entries_start +
4063 lnoff;
4064
4065 *pnetfid = parms->SearchHandle;
4066 } else {
4067 cifs_buf_release(pSMB);
4068 }
4069 }
4070
4071 return rc;
4072}
4073
4074int CIFSFindNext(const int xid, struct cifs_tcon *tcon,
4075 __u16 searchHandle, struct cifs_search_info *psrch_inf)
4076{
4077 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
4078 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
4079 T2_FNEXT_RSP_PARMS *parms;
4080 char *response_data;
4081 int rc = 0;
4082 int bytes_returned;
4083 unsigned int name_len;
4084 __u16 params, byte_count;
4085
4086 cFYI(1, "In FindNext");
4087
4088 if (psrch_inf->endOfSearch)
4089 return -ENOENT;
4090
4091 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4092 (void **) &pSMBr);
4093 if (rc)
4094 return rc;
4095
4096 params = 14; /* includes 2 bytes of null string, converted to LE below*/
4097 byte_count = 0;
4098 pSMB->TotalDataCount = 0; /* no EAs */
4099 pSMB->MaxParameterCount = cpu_to_le16(8);
4100 pSMB->MaxDataCount =
4101 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
4102 0xFFFFFF00);
4103 pSMB->MaxSetupCount = 0;
4104 pSMB->Reserved = 0;
4105 pSMB->Flags = 0;
4106 pSMB->Timeout = 0;
4107 pSMB->Reserved2 = 0;
4108 pSMB->ParameterOffset = cpu_to_le16(
4109 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
4110 pSMB->DataCount = 0;
4111 pSMB->DataOffset = 0;
4112 pSMB->SetupCount = 1;
4113 pSMB->Reserved3 = 0;
4114 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
4115 pSMB->SearchHandle = searchHandle; /* always kept as le */
4116 pSMB->SearchCount =
4117 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
4118 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4119 pSMB->ResumeKey = psrch_inf->resume_key;
4120 pSMB->SearchFlags =
4121 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
4122
4123 name_len = psrch_inf->resume_name_len;
4124 params += name_len;
4125 if (name_len < PATH_MAX) {
4126 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
4127 byte_count += name_len;
4128 /* 14 byte parm len above enough for 2 byte null terminator */
4129 pSMB->ResumeFileName[name_len] = 0;
4130 pSMB->ResumeFileName[name_len+1] = 0;
4131 } else {
4132 rc = -EINVAL;
4133 goto FNext2_err_exit;
4134 }
4135 byte_count = params + 1 /* pad */ ;
4136 pSMB->TotalParameterCount = cpu_to_le16(params);
4137 pSMB->ParameterCount = pSMB->TotalParameterCount;
4138 inc_rfc1001_len(pSMB, byte_count);
4139 pSMB->ByteCount = cpu_to_le16(byte_count);
4140
4141 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4142 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4143 cifs_stats_inc(&tcon->num_fnext);
4144 if (rc) {
4145 if (rc == -EBADF) {
4146 psrch_inf->endOfSearch = true;
4147 cifs_buf_release(pSMB);
4148 rc = 0; /* search probably was closed at end of search*/
4149 } else
4150 cFYI(1, "FindNext returned = %d", rc);
4151 } else { /* decode response */
4152 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4153
4154 if (rc == 0) {
4155 unsigned int lnoff;
4156
4157 /* BB fixme add lock for file (srch_info) struct here */
4158 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4159 psrch_inf->unicode = true;
4160 else
4161 psrch_inf->unicode = false;
4162 response_data = (char *) &pSMBr->hdr.Protocol +
4163 le16_to_cpu(pSMBr->t2.ParameterOffset);
4164 parms = (T2_FNEXT_RSP_PARMS *)response_data;
4165 response_data = (char *)&pSMBr->hdr.Protocol +
4166 le16_to_cpu(pSMBr->t2.DataOffset);
4167 if (psrch_inf->smallBuf)
4168 cifs_small_buf_release(
4169 psrch_inf->ntwrk_buf_start);
4170 else
4171 cifs_buf_release(psrch_inf->ntwrk_buf_start);
4172 psrch_inf->srch_entries_start = response_data;
4173 psrch_inf->ntwrk_buf_start = (char *)pSMB;
4174 psrch_inf->smallBuf = 0;
4175 if (parms->EndofSearch)
4176 psrch_inf->endOfSearch = true;
4177 else
4178 psrch_inf->endOfSearch = false;
4179 psrch_inf->entries_in_buffer =
4180 le16_to_cpu(parms->SearchCount);
4181 psrch_inf->index_of_last_entry +=
4182 psrch_inf->entries_in_buffer;
4183 lnoff = le16_to_cpu(parms->LastNameOffset);
4184 if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
4185 lnoff) {
4186 cERROR(1, "ignoring corrupt resume name");
4187 psrch_inf->last_entry = NULL;
4188 return rc;
4189 } else
4190 psrch_inf->last_entry =
4191 psrch_inf->srch_entries_start + lnoff;
4192
4193/* cFYI(1, "fnxt2 entries in buf %d index_of_last %d",
4194 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
4195
4196 /* BB fixme add unlock here */
4197 }
4198
4199 }
4200
4201 /* BB On error, should we leave previous search buf (and count and
4202 last entry fields) intact or free the previous one? */
4203
4204 /* Note: On -EAGAIN error only caller can retry on handle based calls
4205 since file handle passed in no longer valid */
4206FNext2_err_exit:
4207 if (rc != 0)
4208 cifs_buf_release(pSMB);
4209 return rc;
4210}
4211
4212int
4213CIFSFindClose(const int xid, struct cifs_tcon *tcon,
4214 const __u16 searchHandle)
4215{
4216 int rc = 0;
4217 FINDCLOSE_REQ *pSMB = NULL;
4218
4219 cFYI(1, "In CIFSSMBFindClose");
4220 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
4221
4222 /* no sense returning error if session restarted
4223 as file handle has been closed */
4224 if (rc == -EAGAIN)
4225 return 0;
4226 if (rc)
4227 return rc;
4228
4229 pSMB->FileID = searchHandle;
4230 pSMB->ByteCount = 0;
4231 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4232 if (rc)
4233 cERROR(1, "Send error in FindClose = %d", rc);
4234
4235 cifs_stats_inc(&tcon->num_fclose);
4236
4237 /* Since session is dead, search handle closed on server already */
4238 if (rc == -EAGAIN)
4239 rc = 0;
4240
4241 return rc;
4242}
4243
4244int
4245CIFSGetSrvInodeNumber(const int xid, struct cifs_tcon *tcon,
4246 const unsigned char *searchName,
4247 __u64 *inode_number,
4248 const struct nls_table *nls_codepage, int remap)
4249{
4250 int rc = 0;
4251 TRANSACTION2_QPI_REQ *pSMB = NULL;
4252 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4253 int name_len, bytes_returned;
4254 __u16 params, byte_count;
4255
4256 cFYI(1, "In GetSrvInodeNum for %s", searchName);
4257 if (tcon == NULL)
4258 return -ENODEV;
4259
4260GetInodeNumberRetry:
4261 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4262 (void **) &pSMBr);
4263 if (rc)
4264 return rc;
4265
4266 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4267 name_len =
4268 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4269 PATH_MAX, nls_codepage, remap);
4270 name_len++; /* trailing null */
4271 name_len *= 2;
4272 } else { /* BB improve the check for buffer overruns BB */
4273 name_len = strnlen(searchName, PATH_MAX);
4274 name_len++; /* trailing null */
4275 strncpy(pSMB->FileName, searchName, name_len);
4276 }
4277
4278 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
4279 pSMB->TotalDataCount = 0;
4280 pSMB->MaxParameterCount = cpu_to_le16(2);
4281 /* BB find exact max data count below from sess structure BB */
4282 pSMB->MaxDataCount = cpu_to_le16(4000);
4283 pSMB->MaxSetupCount = 0;
4284 pSMB->Reserved = 0;
4285 pSMB->Flags = 0;
4286 pSMB->Timeout = 0;
4287 pSMB->Reserved2 = 0;
4288 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4289 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4290 pSMB->DataCount = 0;
4291 pSMB->DataOffset = 0;
4292 pSMB->SetupCount = 1;
4293 pSMB->Reserved3 = 0;
4294 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4295 byte_count = params + 1 /* pad */ ;
4296 pSMB->TotalParameterCount = cpu_to_le16(params);
4297 pSMB->ParameterCount = pSMB->TotalParameterCount;
4298 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
4299 pSMB->Reserved4 = 0;
4300 inc_rfc1001_len(pSMB, byte_count);
4301 pSMB->ByteCount = cpu_to_le16(byte_count);
4302
4303 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4304 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4305 if (rc) {
4306 cFYI(1, "error %d in QueryInternalInfo", rc);
4307 } else {
4308 /* decode response */
4309 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4310 /* BB also check enough total bytes returned */
4311 if (rc || get_bcc(&pSMBr->hdr) < 2)
4312 /* If rc should we check for EOPNOSUPP and
4313 disable the srvino flag? or in caller? */
4314 rc = -EIO; /* bad smb */
4315 else {
4316 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4317 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
4318 struct file_internal_info *pfinfo;
4319 /* BB Do we need a cast or hash here ? */
4320 if (count < 8) {
4321 cFYI(1, "Illegal size ret in QryIntrnlInf");
4322 rc = -EIO;
4323 goto GetInodeNumOut;
4324 }
4325 pfinfo = (struct file_internal_info *)
4326 (data_offset + (char *) &pSMBr->hdr.Protocol);
4327 *inode_number = le64_to_cpu(pfinfo->UniqueId);
4328 }
4329 }
4330GetInodeNumOut:
4331 cifs_buf_release(pSMB);
4332 if (rc == -EAGAIN)
4333 goto GetInodeNumberRetry;
4334 return rc;
4335}
4336
4337/* parses DFS refferal V3 structure
4338 * caller is responsible for freeing target_nodes
4339 * returns:
4340 * on success - 0
4341 * on failure - errno
4342 */
4343static int
4344parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
4345 unsigned int *num_of_nodes,
4346 struct dfs_info3_param **target_nodes,
4347 const struct nls_table *nls_codepage, int remap,
4348 const char *searchName)
4349{
4350 int i, rc = 0;
4351 char *data_end;
4352 bool is_unicode;
4353 struct dfs_referral_level_3 *ref;
4354
4355 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4356 is_unicode = true;
4357 else
4358 is_unicode = false;
4359 *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
4360
4361 if (*num_of_nodes < 1) {
4362 cERROR(1, "num_referrals: must be at least > 0,"
4363 "but we get num_referrals = %d\n", *num_of_nodes);
4364 rc = -EINVAL;
4365 goto parse_DFS_referrals_exit;
4366 }
4367
4368 ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
4369 if (ref->VersionNumber != cpu_to_le16(3)) {
4370 cERROR(1, "Referrals of V%d version are not supported,"
4371 "should be V3", le16_to_cpu(ref->VersionNumber));
4372 rc = -EINVAL;
4373 goto parse_DFS_referrals_exit;
4374 }
4375
4376 /* get the upper boundary of the resp buffer */
4377 data_end = (char *)(&(pSMBr->PathConsumed)) +
4378 le16_to_cpu(pSMBr->t2.DataCount);
4379
4380 cFYI(1, "num_referrals: %d dfs flags: 0x%x ...\n",
4381 *num_of_nodes,
4382 le32_to_cpu(pSMBr->DFSFlags));
4383
4384 *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
4385 *num_of_nodes, GFP_KERNEL);
4386 if (*target_nodes == NULL) {
4387 cERROR(1, "Failed to allocate buffer for target_nodes\n");
4388 rc = -ENOMEM;
4389 goto parse_DFS_referrals_exit;
4390 }
4391
4392 /* collect necessary data from referrals */
4393 for (i = 0; i < *num_of_nodes; i++) {
4394 char *temp;
4395 int max_len;
4396 struct dfs_info3_param *node = (*target_nodes)+i;
4397
4398 node->flags = le32_to_cpu(pSMBr->DFSFlags);
4399 if (is_unicode) {
4400 __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
4401 GFP_KERNEL);
4402 if (tmp == NULL) {
4403 rc = -ENOMEM;
4404 goto parse_DFS_referrals_exit;
4405 }
4406 cifsConvertToUCS((__le16 *) tmp, searchName,
4407 PATH_MAX, nls_codepage, remap);
4408 node->path_consumed = cifs_ucs2_bytes(tmp,
4409 le16_to_cpu(pSMBr->PathConsumed),
4410 nls_codepage);
4411 kfree(tmp);
4412 } else
4413 node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
4414
4415 node->server_type = le16_to_cpu(ref->ServerType);
4416 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
4417
4418 /* copy DfsPath */
4419 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
4420 max_len = data_end - temp;
4421 node->path_name = cifs_strndup_from_ucs(temp, max_len,
4422 is_unicode, nls_codepage);
4423 if (!node->path_name) {
4424 rc = -ENOMEM;
4425 goto parse_DFS_referrals_exit;
4426 }
4427
4428 /* copy link target UNC */
4429 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
4430 max_len = data_end - temp;
4431 node->node_name = cifs_strndup_from_ucs(temp, max_len,
4432 is_unicode, nls_codepage);
4433 if (!node->node_name)
4434 rc = -ENOMEM;
4435 }
4436
4437parse_DFS_referrals_exit:
4438 if (rc) {
4439 free_dfs_info_array(*target_nodes, *num_of_nodes);
4440 *target_nodes = NULL;
4441 *num_of_nodes = 0;
4442 }
4443 return rc;
4444}
4445
4446int
4447CIFSGetDFSRefer(const int xid, struct cifs_ses *ses,
4448 const unsigned char *searchName,
4449 struct dfs_info3_param **target_nodes,
4450 unsigned int *num_of_nodes,
4451 const struct nls_table *nls_codepage, int remap)
4452{
4453/* TRANS2_GET_DFS_REFERRAL */
4454 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4455 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4456 int rc = 0;
4457 int bytes_returned;
4458 int name_len;
4459 __u16 params, byte_count;
4460 *num_of_nodes = 0;
4461 *target_nodes = NULL;
4462
4463 cFYI(1, "In GetDFSRefer the path %s", searchName);
4464 if (ses == NULL)
4465 return -ENODEV;
4466getDFSRetry:
4467 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4468 (void **) &pSMBr);
4469 if (rc)
4470 return rc;
4471
4472 /* server pointer checked in called function,
4473 but should never be null here anyway */
4474 pSMB->hdr.Mid = GetNextMid(ses->server);
4475 pSMB->hdr.Tid = ses->ipc_tid;
4476 pSMB->hdr.Uid = ses->Suid;
4477 if (ses->capabilities & CAP_STATUS32)
4478 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4479 if (ses->capabilities & CAP_DFS)
4480 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4481
4482 if (ses->capabilities & CAP_UNICODE) {
4483 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4484 name_len =
4485 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
4486 searchName, PATH_MAX, nls_codepage, remap);
4487 name_len++; /* trailing null */
4488 name_len *= 2;
4489 } else { /* BB improve the check for buffer overruns BB */
4490 name_len = strnlen(searchName, PATH_MAX);
4491 name_len++; /* trailing null */
4492 strncpy(pSMB->RequestFileName, searchName, name_len);
4493 }
4494
4495 if (ses->server) {
4496 if (ses->server->sec_mode &
4497 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4498 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4499 }
4500
4501 pSMB->hdr.Uid = ses->Suid;
4502
4503 params = 2 /* level */ + name_len /*includes null */ ;
4504 pSMB->TotalDataCount = 0;
4505 pSMB->DataCount = 0;
4506 pSMB->DataOffset = 0;
4507 pSMB->MaxParameterCount = 0;
4508 /* BB find exact max SMB PDU from sess structure BB */
4509 pSMB->MaxDataCount = cpu_to_le16(4000);
4510 pSMB->MaxSetupCount = 0;
4511 pSMB->Reserved = 0;
4512 pSMB->Flags = 0;
4513 pSMB->Timeout = 0;
4514 pSMB->Reserved2 = 0;
4515 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4516 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4517 pSMB->SetupCount = 1;
4518 pSMB->Reserved3 = 0;
4519 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4520 byte_count = params + 3 /* pad */ ;
4521 pSMB->ParameterCount = cpu_to_le16(params);
4522 pSMB->TotalParameterCount = pSMB->ParameterCount;
4523 pSMB->MaxReferralLevel = cpu_to_le16(3);
4524 inc_rfc1001_len(pSMB, byte_count);
4525 pSMB->ByteCount = cpu_to_le16(byte_count);
4526
4527 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4528 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4529 if (rc) {
4530 cFYI(1, "Send error in GetDFSRefer = %d", rc);
4531 goto GetDFSRefExit;
4532 }
4533 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4534
4535 /* BB Also check if enough total bytes returned? */
4536 if (rc || get_bcc(&pSMBr->hdr) < 17) {
4537 rc = -EIO; /* bad smb */
4538 goto GetDFSRefExit;
4539 }
4540
4541 cFYI(1, "Decoding GetDFSRefer response BCC: %d Offset %d",
4542 get_bcc(&pSMBr->hdr),
4543 le16_to_cpu(pSMBr->t2.DataOffset));
4544
4545 /* parse returned result into more usable form */
4546 rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4547 target_nodes, nls_codepage, remap,
4548 searchName);
4549
4550GetDFSRefExit:
4551 cifs_buf_release(pSMB);
4552
4553 if (rc == -EAGAIN)
4554 goto getDFSRetry;
4555
4556 return rc;
4557}
4558
4559/* Query File System Info such as free space to old servers such as Win 9x */
4560int
4561SMBOldQFSInfo(const int xid, struct cifs_tcon *tcon, struct kstatfs *FSData)
4562{
4563/* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4564 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4565 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4566 FILE_SYSTEM_ALLOC_INFO *response_data;
4567 int rc = 0;
4568 int bytes_returned = 0;
4569 __u16 params, byte_count;
4570
4571 cFYI(1, "OldQFSInfo");
4572oldQFSInfoRetry:
4573 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4574 (void **) &pSMBr);
4575 if (rc)
4576 return rc;
4577
4578 params = 2; /* level */
4579 pSMB->TotalDataCount = 0;
4580 pSMB->MaxParameterCount = cpu_to_le16(2);
4581 pSMB->MaxDataCount = cpu_to_le16(1000);
4582 pSMB->MaxSetupCount = 0;
4583 pSMB->Reserved = 0;
4584 pSMB->Flags = 0;
4585 pSMB->Timeout = 0;
4586 pSMB->Reserved2 = 0;
4587 byte_count = params + 1 /* pad */ ;
4588 pSMB->TotalParameterCount = cpu_to_le16(params);
4589 pSMB->ParameterCount = pSMB->TotalParameterCount;
4590 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4591 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4592 pSMB->DataCount = 0;
4593 pSMB->DataOffset = 0;
4594 pSMB->SetupCount = 1;
4595 pSMB->Reserved3 = 0;
4596 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4597 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4598 inc_rfc1001_len(pSMB, byte_count);
4599 pSMB->ByteCount = cpu_to_le16(byte_count);
4600
4601 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4602 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4603 if (rc) {
4604 cFYI(1, "Send error in QFSInfo = %d", rc);
4605 } else { /* decode response */
4606 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4607
4608 if (rc || get_bcc(&pSMBr->hdr) < 18)
4609 rc = -EIO; /* bad smb */
4610 else {
4611 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4612 cFYI(1, "qfsinf resp BCC: %d Offset %d",
4613 get_bcc(&pSMBr->hdr), data_offset);
4614
4615 response_data = (FILE_SYSTEM_ALLOC_INFO *)
4616 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4617 FSData->f_bsize =
4618 le16_to_cpu(response_data->BytesPerSector) *
4619 le32_to_cpu(response_data->
4620 SectorsPerAllocationUnit);
4621 FSData->f_blocks =
4622 le32_to_cpu(response_data->TotalAllocationUnits);
4623 FSData->f_bfree = FSData->f_bavail =
4624 le32_to_cpu(response_data->FreeAllocationUnits);
4625 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
4626 (unsigned long long)FSData->f_blocks,
4627 (unsigned long long)FSData->f_bfree,
4628 FSData->f_bsize);
4629 }
4630 }
4631 cifs_buf_release(pSMB);
4632
4633 if (rc == -EAGAIN)
4634 goto oldQFSInfoRetry;
4635
4636 return rc;
4637}
4638
4639int
4640CIFSSMBQFSInfo(const int xid, struct cifs_tcon *tcon, struct kstatfs *FSData)
4641{
4642/* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4643 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4644 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4645 FILE_SYSTEM_INFO *response_data;
4646 int rc = 0;
4647 int bytes_returned = 0;
4648 __u16 params, byte_count;
4649
4650 cFYI(1, "In QFSInfo");
4651QFSInfoRetry:
4652 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4653 (void **) &pSMBr);
4654 if (rc)
4655 return rc;
4656
4657 params = 2; /* level */
4658 pSMB->TotalDataCount = 0;
4659 pSMB->MaxParameterCount = cpu_to_le16(2);
4660 pSMB->MaxDataCount = cpu_to_le16(1000);
4661 pSMB->MaxSetupCount = 0;
4662 pSMB->Reserved = 0;
4663 pSMB->Flags = 0;
4664 pSMB->Timeout = 0;
4665 pSMB->Reserved2 = 0;
4666 byte_count = params + 1 /* pad */ ;
4667 pSMB->TotalParameterCount = cpu_to_le16(params);
4668 pSMB->ParameterCount = pSMB->TotalParameterCount;
4669 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4670 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4671 pSMB->DataCount = 0;
4672 pSMB->DataOffset = 0;
4673 pSMB->SetupCount = 1;
4674 pSMB->Reserved3 = 0;
4675 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4676 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4677 inc_rfc1001_len(pSMB, byte_count);
4678 pSMB->ByteCount = cpu_to_le16(byte_count);
4679
4680 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4681 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4682 if (rc) {
4683 cFYI(1, "Send error in QFSInfo = %d", rc);
4684 } else { /* decode response */
4685 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4686
4687 if (rc || get_bcc(&pSMBr->hdr) < 24)
4688 rc = -EIO; /* bad smb */
4689 else {
4690 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4691
4692 response_data =
4693 (FILE_SYSTEM_INFO
4694 *) (((char *) &pSMBr->hdr.Protocol) +
4695 data_offset);
4696 FSData->f_bsize =
4697 le32_to_cpu(response_data->BytesPerSector) *
4698 le32_to_cpu(response_data->
4699 SectorsPerAllocationUnit);
4700 FSData->f_blocks =
4701 le64_to_cpu(response_data->TotalAllocationUnits);
4702 FSData->f_bfree = FSData->f_bavail =
4703 le64_to_cpu(response_data->FreeAllocationUnits);
4704 cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
4705 (unsigned long long)FSData->f_blocks,
4706 (unsigned long long)FSData->f_bfree,
4707 FSData->f_bsize);
4708 }
4709 }
4710 cifs_buf_release(pSMB);
4711
4712 if (rc == -EAGAIN)
4713 goto QFSInfoRetry;
4714
4715 return rc;
4716}
4717
4718int
4719CIFSSMBQFSAttributeInfo(const int xid, struct cifs_tcon *tcon)
4720{
4721/* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
4722 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4723 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4724 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4725 int rc = 0;
4726 int bytes_returned = 0;
4727 __u16 params, byte_count;
4728
4729 cFYI(1, "In QFSAttributeInfo");
4730QFSAttributeRetry:
4731 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4732 (void **) &pSMBr);
4733 if (rc)
4734 return rc;
4735
4736 params = 2; /* level */
4737 pSMB->TotalDataCount = 0;
4738 pSMB->MaxParameterCount = cpu_to_le16(2);
4739 /* BB find exact max SMB PDU from sess structure BB */
4740 pSMB->MaxDataCount = cpu_to_le16(1000);
4741 pSMB->MaxSetupCount = 0;
4742 pSMB->Reserved = 0;
4743 pSMB->Flags = 0;
4744 pSMB->Timeout = 0;
4745 pSMB->Reserved2 = 0;
4746 byte_count = params + 1 /* pad */ ;
4747 pSMB->TotalParameterCount = cpu_to_le16(params);
4748 pSMB->ParameterCount = pSMB->TotalParameterCount;
4749 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4750 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4751 pSMB->DataCount = 0;
4752 pSMB->DataOffset = 0;
4753 pSMB->SetupCount = 1;
4754 pSMB->Reserved3 = 0;
4755 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4756 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4757 inc_rfc1001_len(pSMB, byte_count);
4758 pSMB->ByteCount = cpu_to_le16(byte_count);
4759
4760 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4761 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4762 if (rc) {
4763 cERROR(1, "Send error in QFSAttributeInfo = %d", rc);
4764 } else { /* decode response */
4765 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4766
4767 if (rc || get_bcc(&pSMBr->hdr) < 13) {
4768 /* BB also check if enough bytes returned */
4769 rc = -EIO; /* bad smb */
4770 } else {
4771 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4772 response_data =
4773 (FILE_SYSTEM_ATTRIBUTE_INFO
4774 *) (((char *) &pSMBr->hdr.Protocol) +
4775 data_offset);
4776 memcpy(&tcon->fsAttrInfo, response_data,
4777 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4778 }
4779 }
4780 cifs_buf_release(pSMB);
4781
4782 if (rc == -EAGAIN)
4783 goto QFSAttributeRetry;
4784
4785 return rc;
4786}
4787
4788int
4789CIFSSMBQFSDeviceInfo(const int xid, struct cifs_tcon *tcon)
4790{
4791/* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4792 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4793 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4794 FILE_SYSTEM_DEVICE_INFO *response_data;
4795 int rc = 0;
4796 int bytes_returned = 0;
4797 __u16 params, byte_count;
4798
4799 cFYI(1, "In QFSDeviceInfo");
4800QFSDeviceRetry:
4801 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4802 (void **) &pSMBr);
4803 if (rc)
4804 return rc;
4805
4806 params = 2; /* level */
4807 pSMB->TotalDataCount = 0;
4808 pSMB->MaxParameterCount = cpu_to_le16(2);
4809 /* BB find exact max SMB PDU from sess structure BB */
4810 pSMB->MaxDataCount = cpu_to_le16(1000);
4811 pSMB->MaxSetupCount = 0;
4812 pSMB->Reserved = 0;
4813 pSMB->Flags = 0;
4814 pSMB->Timeout = 0;
4815 pSMB->Reserved2 = 0;
4816 byte_count = params + 1 /* pad */ ;
4817 pSMB->TotalParameterCount = cpu_to_le16(params);
4818 pSMB->ParameterCount = pSMB->TotalParameterCount;
4819 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4820 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4821
4822 pSMB->DataCount = 0;
4823 pSMB->DataOffset = 0;
4824 pSMB->SetupCount = 1;
4825 pSMB->Reserved3 = 0;
4826 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4827 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4828 inc_rfc1001_len(pSMB, byte_count);
4829 pSMB->ByteCount = cpu_to_le16(byte_count);
4830
4831 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4832 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4833 if (rc) {
4834 cFYI(1, "Send error in QFSDeviceInfo = %d", rc);
4835 } else { /* decode response */
4836 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4837
4838 if (rc || get_bcc(&pSMBr->hdr) <
4839 sizeof(FILE_SYSTEM_DEVICE_INFO))
4840 rc = -EIO; /* bad smb */
4841 else {
4842 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4843 response_data =
4844 (FILE_SYSTEM_DEVICE_INFO *)
4845 (((char *) &pSMBr->hdr.Protocol) +
4846 data_offset);
4847 memcpy(&tcon->fsDevInfo, response_data,
4848 sizeof(FILE_SYSTEM_DEVICE_INFO));
4849 }
4850 }
4851 cifs_buf_release(pSMB);
4852
4853 if (rc == -EAGAIN)
4854 goto QFSDeviceRetry;
4855
4856 return rc;
4857}
4858
4859int
4860CIFSSMBQFSUnixInfo(const int xid, struct cifs_tcon *tcon)
4861{
4862/* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
4863 TRANSACTION2_QFSI_REQ *pSMB = NULL;
4864 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4865 FILE_SYSTEM_UNIX_INFO *response_data;
4866 int rc = 0;
4867 int bytes_returned = 0;
4868 __u16 params, byte_count;
4869
4870 cFYI(1, "In QFSUnixInfo");
4871QFSUnixRetry:
4872 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
4873 (void **) &pSMB, (void **) &pSMBr);
4874 if (rc)
4875 return rc;
4876
4877 params = 2; /* level */
4878 pSMB->TotalDataCount = 0;
4879 pSMB->DataCount = 0;
4880 pSMB->DataOffset = 0;
4881 pSMB->MaxParameterCount = cpu_to_le16(2);
4882 /* BB find exact max SMB PDU from sess structure BB */
4883 pSMB->MaxDataCount = cpu_to_le16(100);
4884 pSMB->MaxSetupCount = 0;
4885 pSMB->Reserved = 0;
4886 pSMB->Flags = 0;
4887 pSMB->Timeout = 0;
4888 pSMB->Reserved2 = 0;
4889 byte_count = params + 1 /* pad */ ;
4890 pSMB->ParameterCount = cpu_to_le16(params);
4891 pSMB->TotalParameterCount = pSMB->ParameterCount;
4892 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4893 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4894 pSMB->SetupCount = 1;
4895 pSMB->Reserved3 = 0;
4896 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4897 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4898 inc_rfc1001_len(pSMB, byte_count);
4899 pSMB->ByteCount = cpu_to_le16(byte_count);
4900
4901 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4902 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4903 if (rc) {
4904 cERROR(1, "Send error in QFSUnixInfo = %d", rc);
4905 } else { /* decode response */
4906 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4907
4908 if (rc || get_bcc(&pSMBr->hdr) < 13) {
4909 rc = -EIO; /* bad smb */
4910 } else {
4911 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4912 response_data =
4913 (FILE_SYSTEM_UNIX_INFO
4914 *) (((char *) &pSMBr->hdr.Protocol) +
4915 data_offset);
4916 memcpy(&tcon->fsUnixInfo, response_data,
4917 sizeof(FILE_SYSTEM_UNIX_INFO));
4918 }
4919 }
4920 cifs_buf_release(pSMB);
4921
4922 if (rc == -EAGAIN)
4923 goto QFSUnixRetry;
4924
4925
4926 return rc;
4927}
4928
4929int
4930CIFSSMBSetFSUnixInfo(const int xid, struct cifs_tcon *tcon, __u64 cap)
4931{
4932/* level 0x200 SMB_SET_CIFS_UNIX_INFO */
4933 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4934 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4935 int rc = 0;
4936 int bytes_returned = 0;
4937 __u16 params, param_offset, offset, byte_count;
4938
4939 cFYI(1, "In SETFSUnixInfo");
4940SETFSUnixRetry:
4941 /* BB switch to small buf init to save memory */
4942 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
4943 (void **) &pSMB, (void **) &pSMBr);
4944 if (rc)
4945 return rc;
4946
4947 params = 4; /* 2 bytes zero followed by info level. */
4948 pSMB->MaxSetupCount = 0;
4949 pSMB->Reserved = 0;
4950 pSMB->Flags = 0;
4951 pSMB->Timeout = 0;
4952 pSMB->Reserved2 = 0;
4953 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4954 - 4;
4955 offset = param_offset + params;
4956
4957 pSMB->MaxParameterCount = cpu_to_le16(4);
4958 /* BB find exact max SMB PDU from sess structure BB */
4959 pSMB->MaxDataCount = cpu_to_le16(100);
4960 pSMB->SetupCount = 1;
4961 pSMB->Reserved3 = 0;
4962 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4963 byte_count = 1 /* pad */ + params + 12;
4964
4965 pSMB->DataCount = cpu_to_le16(12);
4966 pSMB->ParameterCount = cpu_to_le16(params);
4967 pSMB->TotalDataCount = pSMB->DataCount;
4968 pSMB->TotalParameterCount = pSMB->ParameterCount;
4969 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4970 pSMB->DataOffset = cpu_to_le16(offset);
4971
4972 /* Params. */
4973 pSMB->FileNum = 0;
4974 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4975
4976 /* Data. */
4977 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4978 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4979 pSMB->ClientUnixCap = cpu_to_le64(cap);
4980
4981 inc_rfc1001_len(pSMB, byte_count);
4982 pSMB->ByteCount = cpu_to_le16(byte_count);
4983
4984 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4985 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4986 if (rc) {
4987 cERROR(1, "Send error in SETFSUnixInfo = %d", rc);
4988 } else { /* decode response */
4989 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4990 if (rc)
4991 rc = -EIO; /* bad smb */
4992 }
4993 cifs_buf_release(pSMB);
4994
4995 if (rc == -EAGAIN)
4996 goto SETFSUnixRetry;
4997
4998 return rc;
4999}
5000
5001
5002
5003int
5004CIFSSMBQFSPosixInfo(const int xid, struct cifs_tcon *tcon,
5005 struct kstatfs *FSData)
5006{
5007/* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
5008 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5009 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5010 FILE_SYSTEM_POSIX_INFO *response_data;
5011 int rc = 0;
5012 int bytes_returned = 0;
5013 __u16 params, byte_count;
5014
5015 cFYI(1, "In QFSPosixInfo");
5016QFSPosixRetry:
5017 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5018 (void **) &pSMBr);
5019 if (rc)
5020 return rc;
5021
5022 params = 2; /* level */
5023 pSMB->TotalDataCount = 0;
5024 pSMB->DataCount = 0;
5025 pSMB->DataOffset = 0;
5026 pSMB->MaxParameterCount = cpu_to_le16(2);
5027 /* BB find exact max SMB PDU from sess structure BB */
5028 pSMB->MaxDataCount = cpu_to_le16(100);
5029 pSMB->MaxSetupCount = 0;
5030 pSMB->Reserved = 0;
5031 pSMB->Flags = 0;
5032 pSMB->Timeout = 0;
5033 pSMB->Reserved2 = 0;
5034 byte_count = params + 1 /* pad */ ;
5035 pSMB->ParameterCount = cpu_to_le16(params);
5036 pSMB->TotalParameterCount = pSMB->ParameterCount;
5037 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5038 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5039 pSMB->SetupCount = 1;
5040 pSMB->Reserved3 = 0;
5041 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5042 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
5043 inc_rfc1001_len(pSMB, byte_count);
5044 pSMB->ByteCount = cpu_to_le16(byte_count);
5045
5046 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5047 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5048 if (rc) {
5049 cFYI(1, "Send error in QFSUnixInfo = %d", rc);
5050 } else { /* decode response */
5051 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5052
5053 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5054 rc = -EIO; /* bad smb */
5055 } else {
5056 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5057 response_data =
5058 (FILE_SYSTEM_POSIX_INFO
5059 *) (((char *) &pSMBr->hdr.Protocol) +
5060 data_offset);
5061 FSData->f_bsize =
5062 le32_to_cpu(response_data->BlockSize);
5063 FSData->f_blocks =
5064 le64_to_cpu(response_data->TotalBlocks);
5065 FSData->f_bfree =
5066 le64_to_cpu(response_data->BlocksAvail);
5067 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
5068 FSData->f_bavail = FSData->f_bfree;
5069 } else {
5070 FSData->f_bavail =
5071 le64_to_cpu(response_data->UserBlocksAvail);
5072 }
5073 if (response_data->TotalFileNodes != cpu_to_le64(-1))
5074 FSData->f_files =
5075 le64_to_cpu(response_data->TotalFileNodes);
5076 if (response_data->FreeFileNodes != cpu_to_le64(-1))
5077 FSData->f_ffree =
5078 le64_to_cpu(response_data->FreeFileNodes);
5079 }
5080 }
5081 cifs_buf_release(pSMB);
5082
5083 if (rc == -EAGAIN)
5084 goto QFSPosixRetry;
5085
5086 return rc;
5087}
5088
5089
5090/* We can not use write of zero bytes trick to
5091 set file size due to need for large file support. Also note that
5092 this SetPathInfo is preferred to SetFileInfo based method in next
5093 routine which is only needed to work around a sharing violation bug
5094 in Samba which this routine can run into */
5095
5096int
5097CIFSSMBSetEOF(const int xid, struct cifs_tcon *tcon, const char *fileName,
5098 __u64 size, bool SetAllocation,
5099 const struct nls_table *nls_codepage, int remap)
5100{
5101 struct smb_com_transaction2_spi_req *pSMB = NULL;
5102 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5103 struct file_end_of_file_info *parm_data;
5104 int name_len;
5105 int rc = 0;
5106 int bytes_returned = 0;
5107 __u16 params, byte_count, data_count, param_offset, offset;
5108
5109 cFYI(1, "In SetEOF");
5110SetEOFRetry:
5111 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5112 (void **) &pSMBr);
5113 if (rc)
5114 return rc;
5115
5116 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5117 name_len =
5118 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5119 PATH_MAX, nls_codepage, remap);
5120 name_len++; /* trailing null */
5121 name_len *= 2;
5122 } else { /* BB improve the check for buffer overruns BB */
5123 name_len = strnlen(fileName, PATH_MAX);
5124 name_len++; /* trailing null */
5125 strncpy(pSMB->FileName, fileName, name_len);
5126 }
5127 params = 6 + name_len;
5128 data_count = sizeof(struct file_end_of_file_info);
5129 pSMB->MaxParameterCount = cpu_to_le16(2);
5130 pSMB->MaxDataCount = cpu_to_le16(4100);
5131 pSMB->MaxSetupCount = 0;
5132 pSMB->Reserved = 0;
5133 pSMB->Flags = 0;
5134 pSMB->Timeout = 0;
5135 pSMB->Reserved2 = 0;
5136 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5137 InformationLevel) - 4;
5138 offset = param_offset + params;
5139 if (SetAllocation) {
5140 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5141 pSMB->InformationLevel =
5142 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5143 else
5144 pSMB->InformationLevel =
5145 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5146 } else /* Set File Size */ {
5147 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5148 pSMB->InformationLevel =
5149 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5150 else
5151 pSMB->InformationLevel =
5152 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5153 }
5154
5155 parm_data =
5156 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
5157 offset);
5158 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5159 pSMB->DataOffset = cpu_to_le16(offset);
5160 pSMB->SetupCount = 1;
5161 pSMB->Reserved3 = 0;
5162 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5163 byte_count = 3 /* pad */ + params + data_count;
5164 pSMB->DataCount = cpu_to_le16(data_count);
5165 pSMB->TotalDataCount = pSMB->DataCount;
5166 pSMB->ParameterCount = cpu_to_le16(params);
5167 pSMB->TotalParameterCount = pSMB->ParameterCount;
5168 pSMB->Reserved4 = 0;
5169 inc_rfc1001_len(pSMB, byte_count);
5170 parm_data->FileSize = cpu_to_le64(size);
5171 pSMB->ByteCount = cpu_to_le16(byte_count);
5172 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5173 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5174 if (rc)
5175 cFYI(1, "SetPathInfo (file size) returned %d", rc);
5176
5177 cifs_buf_release(pSMB);
5178
5179 if (rc == -EAGAIN)
5180 goto SetEOFRetry;
5181
5182 return rc;
5183}
5184
5185int
5186CIFSSMBSetFileSize(const int xid, struct cifs_tcon *tcon, __u64 size,
5187 __u16 fid, __u32 pid_of_opener, bool SetAllocation)
5188{
5189 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5190 struct file_end_of_file_info *parm_data;
5191 int rc = 0;
5192 __u16 params, param_offset, offset, byte_count, count;
5193
5194 cFYI(1, "SetFileSize (via SetFileInfo) %lld",
5195 (long long)size);
5196 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5197
5198 if (rc)
5199 return rc;
5200
5201 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5202 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5203
5204 params = 6;
5205 pSMB->MaxSetupCount = 0;
5206 pSMB->Reserved = 0;
5207 pSMB->Flags = 0;
5208 pSMB->Timeout = 0;
5209 pSMB->Reserved2 = 0;
5210 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5211 offset = param_offset + params;
5212
5213 count = sizeof(struct file_end_of_file_info);
5214 pSMB->MaxParameterCount = cpu_to_le16(2);
5215 /* BB find exact max SMB PDU from sess structure BB */
5216 pSMB->MaxDataCount = cpu_to_le16(1000);
5217 pSMB->SetupCount = 1;
5218 pSMB->Reserved3 = 0;
5219 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5220 byte_count = 3 /* pad */ + params + count;
5221 pSMB->DataCount = cpu_to_le16(count);
5222 pSMB->ParameterCount = cpu_to_le16(params);
5223 pSMB->TotalDataCount = pSMB->DataCount;
5224 pSMB->TotalParameterCount = pSMB->ParameterCount;
5225 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5226 parm_data =
5227 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
5228 + offset);
5229 pSMB->DataOffset = cpu_to_le16(offset);
5230 parm_data->FileSize = cpu_to_le64(size);
5231 pSMB->Fid = fid;
5232 if (SetAllocation) {
5233 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5234 pSMB->InformationLevel =
5235 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5236 else
5237 pSMB->InformationLevel =
5238 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5239 } else /* Set File Size */ {
5240 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5241 pSMB->InformationLevel =
5242 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5243 else
5244 pSMB->InformationLevel =
5245 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5246 }
5247 pSMB->Reserved4 = 0;
5248 inc_rfc1001_len(pSMB, byte_count);
5249 pSMB->ByteCount = cpu_to_le16(byte_count);
5250 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5251 if (rc) {
5252 cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc);
5253 }
5254
5255 /* Note: On -EAGAIN error only caller can retry on handle based calls
5256 since file handle passed in no longer valid */
5257
5258 return rc;
5259}
5260
5261/* Some legacy servers such as NT4 require that the file times be set on
5262 an open handle, rather than by pathname - this is awkward due to
5263 potential access conflicts on the open, but it is unavoidable for these
5264 old servers since the only other choice is to go from 100 nanosecond DCE
5265 time and resort to the original setpathinfo level which takes the ancient
5266 DOS time format with 2 second granularity */
5267int
5268CIFSSMBSetFileInfo(const int xid, struct cifs_tcon *tcon,
5269 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
5270{
5271 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5272 char *data_offset;
5273 int rc = 0;
5274 __u16 params, param_offset, offset, byte_count, count;
5275
5276 cFYI(1, "Set Times (via SetFileInfo)");
5277 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5278
5279 if (rc)
5280 return rc;
5281
5282 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5283 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5284
5285 params = 6;
5286 pSMB->MaxSetupCount = 0;
5287 pSMB->Reserved = 0;
5288 pSMB->Flags = 0;
5289 pSMB->Timeout = 0;
5290 pSMB->Reserved2 = 0;
5291 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5292 offset = param_offset + params;
5293
5294 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5295
5296 count = sizeof(FILE_BASIC_INFO);
5297 pSMB->MaxParameterCount = cpu_to_le16(2);
5298 /* BB find max SMB PDU from sess */
5299 pSMB->MaxDataCount = cpu_to_le16(1000);
5300 pSMB->SetupCount = 1;
5301 pSMB->Reserved3 = 0;
5302 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5303 byte_count = 3 /* pad */ + params + count;
5304 pSMB->DataCount = cpu_to_le16(count);
5305 pSMB->ParameterCount = cpu_to_le16(params);
5306 pSMB->TotalDataCount = pSMB->DataCount;
5307 pSMB->TotalParameterCount = pSMB->ParameterCount;
5308 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5309 pSMB->DataOffset = cpu_to_le16(offset);
5310 pSMB->Fid = fid;
5311 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5312 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5313 else
5314 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5315 pSMB->Reserved4 = 0;
5316 inc_rfc1001_len(pSMB, byte_count);
5317 pSMB->ByteCount = cpu_to_le16(byte_count);
5318 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5319 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5320 if (rc)
5321 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
5322
5323 /* Note: On -EAGAIN error only caller can retry on handle based calls
5324 since file handle passed in no longer valid */
5325
5326 return rc;
5327}
5328
5329int
5330CIFSSMBSetFileDisposition(const int xid, struct cifs_tcon *tcon,
5331 bool delete_file, __u16 fid, __u32 pid_of_opener)
5332{
5333 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5334 char *data_offset;
5335 int rc = 0;
5336 __u16 params, param_offset, offset, byte_count, count;
5337
5338 cFYI(1, "Set File Disposition (via SetFileInfo)");
5339 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5340
5341 if (rc)
5342 return rc;
5343
5344 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5345 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5346
5347 params = 6;
5348 pSMB->MaxSetupCount = 0;
5349 pSMB->Reserved = 0;
5350 pSMB->Flags = 0;
5351 pSMB->Timeout = 0;
5352 pSMB->Reserved2 = 0;
5353 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5354 offset = param_offset + params;
5355
5356 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5357
5358 count = 1;
5359 pSMB->MaxParameterCount = cpu_to_le16(2);
5360 /* BB find max SMB PDU from sess */
5361 pSMB->MaxDataCount = cpu_to_le16(1000);
5362 pSMB->SetupCount = 1;
5363 pSMB->Reserved3 = 0;
5364 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5365 byte_count = 3 /* pad */ + params + count;
5366 pSMB->DataCount = cpu_to_le16(count);
5367 pSMB->ParameterCount = cpu_to_le16(params);
5368 pSMB->TotalDataCount = pSMB->DataCount;
5369 pSMB->TotalParameterCount = pSMB->ParameterCount;
5370 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5371 pSMB->DataOffset = cpu_to_le16(offset);
5372 pSMB->Fid = fid;
5373 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
5374 pSMB->Reserved4 = 0;
5375 inc_rfc1001_len(pSMB, byte_count);
5376 pSMB->ByteCount = cpu_to_le16(byte_count);
5377 *data_offset = delete_file ? 1 : 0;
5378 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5379 if (rc)
5380 cFYI(1, "Send error in SetFileDisposition = %d", rc);
5381
5382 return rc;
5383}
5384
5385int
5386CIFSSMBSetPathInfo(const int xid, struct cifs_tcon *tcon,
5387 const char *fileName, const FILE_BASIC_INFO *data,
5388 const struct nls_table *nls_codepage, int remap)
5389{
5390 TRANSACTION2_SPI_REQ *pSMB = NULL;
5391 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5392 int name_len;
5393 int rc = 0;
5394 int bytes_returned = 0;
5395 char *data_offset;
5396 __u16 params, param_offset, offset, byte_count, count;
5397
5398 cFYI(1, "In SetTimes");
5399
5400SetTimesRetry:
5401 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5402 (void **) &pSMBr);
5403 if (rc)
5404 return rc;
5405
5406 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5407 name_len =
5408 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5409 PATH_MAX, nls_codepage, remap);
5410 name_len++; /* trailing null */
5411 name_len *= 2;
5412 } else { /* BB improve the check for buffer overruns BB */
5413 name_len = strnlen(fileName, PATH_MAX);
5414 name_len++; /* trailing null */
5415 strncpy(pSMB->FileName, fileName, name_len);
5416 }
5417
5418 params = 6 + name_len;
5419 count = sizeof(FILE_BASIC_INFO);
5420 pSMB->MaxParameterCount = cpu_to_le16(2);
5421 /* BB find max SMB PDU from sess structure BB */
5422 pSMB->MaxDataCount = cpu_to_le16(1000);
5423 pSMB->MaxSetupCount = 0;
5424 pSMB->Reserved = 0;
5425 pSMB->Flags = 0;
5426 pSMB->Timeout = 0;
5427 pSMB->Reserved2 = 0;
5428 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5429 InformationLevel) - 4;
5430 offset = param_offset + params;
5431 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5432 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5433 pSMB->DataOffset = cpu_to_le16(offset);
5434 pSMB->SetupCount = 1;
5435 pSMB->Reserved3 = 0;
5436 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5437 byte_count = 3 /* pad */ + params + count;
5438
5439 pSMB->DataCount = cpu_to_le16(count);
5440 pSMB->ParameterCount = cpu_to_le16(params);
5441 pSMB->TotalDataCount = pSMB->DataCount;
5442 pSMB->TotalParameterCount = pSMB->ParameterCount;
5443 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5444 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5445 else
5446 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5447 pSMB->Reserved4 = 0;
5448 inc_rfc1001_len(pSMB, byte_count);
5449 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5450 pSMB->ByteCount = cpu_to_le16(byte_count);
5451 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5452 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5453 if (rc)
5454 cFYI(1, "SetPathInfo (times) returned %d", rc);
5455
5456 cifs_buf_release(pSMB);
5457
5458 if (rc == -EAGAIN)
5459 goto SetTimesRetry;
5460
5461 return rc;
5462}
5463
5464/* Can not be used to set time stamps yet (due to old DOS time format) */
5465/* Can be used to set attributes */
5466#if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5467 handling it anyway and NT4 was what we thought it would be needed for
5468 Do not delete it until we prove whether needed for Win9x though */
5469int
5470CIFSSMBSetAttrLegacy(int xid, struct cifs_tcon *tcon, char *fileName,
5471 __u16 dos_attrs, const struct nls_table *nls_codepage)
5472{
5473 SETATTR_REQ *pSMB = NULL;
5474 SETATTR_RSP *pSMBr = NULL;
5475 int rc = 0;
5476 int bytes_returned;
5477 int name_len;
5478
5479 cFYI(1, "In SetAttrLegacy");
5480
5481SetAttrLgcyRetry:
5482 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5483 (void **) &pSMBr);
5484 if (rc)
5485 return rc;
5486
5487 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5488 name_len =
5489 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
5490 PATH_MAX, nls_codepage);
5491 name_len++; /* trailing null */
5492 name_len *= 2;
5493 } else { /* BB improve the check for buffer overruns BB */
5494 name_len = strnlen(fileName, PATH_MAX);
5495 name_len++; /* trailing null */
5496 strncpy(pSMB->fileName, fileName, name_len);
5497 }
5498 pSMB->attr = cpu_to_le16(dos_attrs);
5499 pSMB->BufferFormat = 0x04;
5500 inc_rfc1001_len(pSMB, name_len + 1);
5501 pSMB->ByteCount = cpu_to_le16(name_len + 1);
5502 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5503 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5504 if (rc)
5505 cFYI(1, "Error in LegacySetAttr = %d", rc);
5506
5507 cifs_buf_release(pSMB);
5508
5509 if (rc == -EAGAIN)
5510 goto SetAttrLgcyRetry;
5511
5512 return rc;
5513}
5514#endif /* temporarily unneeded SetAttr legacy function */
5515
5516static void
5517cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
5518 const struct cifs_unix_set_info_args *args)
5519{
5520 u64 mode = args->mode;
5521
5522 /*
5523 * Samba server ignores set of file size to zero due to bugs in some
5524 * older clients, but we should be precise - we use SetFileSize to
5525 * set file size and do not want to truncate file size to zero
5526 * accidentally as happened on one Samba server beta by putting
5527 * zero instead of -1 here
5528 */
5529 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5530 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5531 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5532 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5533 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5534 data_offset->Uid = cpu_to_le64(args->uid);
5535 data_offset->Gid = cpu_to_le64(args->gid);
5536 /* better to leave device as zero when it is */
5537 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5538 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5539 data_offset->Permissions = cpu_to_le64(mode);
5540
5541 if (S_ISREG(mode))
5542 data_offset->Type = cpu_to_le32(UNIX_FILE);
5543 else if (S_ISDIR(mode))
5544 data_offset->Type = cpu_to_le32(UNIX_DIR);
5545 else if (S_ISLNK(mode))
5546 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5547 else if (S_ISCHR(mode))
5548 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5549 else if (S_ISBLK(mode))
5550 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5551 else if (S_ISFIFO(mode))
5552 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5553 else if (S_ISSOCK(mode))
5554 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5555}
5556
5557int
5558CIFSSMBUnixSetFileInfo(const int xid, struct cifs_tcon *tcon,
5559 const struct cifs_unix_set_info_args *args,
5560 u16 fid, u32 pid_of_opener)
5561{
5562 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5563 FILE_UNIX_BASIC_INFO *data_offset;
5564 int rc = 0;
5565 u16 params, param_offset, offset, byte_count, count;
5566
5567 cFYI(1, "Set Unix Info (via SetFileInfo)");
5568 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5569
5570 if (rc)
5571 return rc;
5572
5573 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5574 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5575
5576 params = 6;
5577 pSMB->MaxSetupCount = 0;
5578 pSMB->Reserved = 0;
5579 pSMB->Flags = 0;
5580 pSMB->Timeout = 0;
5581 pSMB->Reserved2 = 0;
5582 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5583 offset = param_offset + params;
5584
5585 data_offset = (FILE_UNIX_BASIC_INFO *)
5586 ((char *)(&pSMB->hdr.Protocol) + offset);
5587 count = sizeof(FILE_UNIX_BASIC_INFO);
5588
5589 pSMB->MaxParameterCount = cpu_to_le16(2);
5590 /* BB find max SMB PDU from sess */
5591 pSMB->MaxDataCount = cpu_to_le16(1000);
5592 pSMB->SetupCount = 1;
5593 pSMB->Reserved3 = 0;
5594 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5595 byte_count = 3 /* pad */ + params + count;
5596 pSMB->DataCount = cpu_to_le16(count);
5597 pSMB->ParameterCount = cpu_to_le16(params);
5598 pSMB->TotalDataCount = pSMB->DataCount;
5599 pSMB->TotalParameterCount = pSMB->ParameterCount;
5600 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5601 pSMB->DataOffset = cpu_to_le16(offset);
5602 pSMB->Fid = fid;
5603 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5604 pSMB->Reserved4 = 0;
5605 inc_rfc1001_len(pSMB, byte_count);
5606 pSMB->ByteCount = cpu_to_le16(byte_count);
5607
5608 cifs_fill_unix_set_info(data_offset, args);
5609
5610 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5611 if (rc)
5612 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
5613
5614 /* Note: On -EAGAIN error only caller can retry on handle based calls
5615 since file handle passed in no longer valid */
5616
5617 return rc;
5618}
5619
5620int
5621CIFSSMBUnixSetPathInfo(const int xid, struct cifs_tcon *tcon, char *fileName,
5622 const struct cifs_unix_set_info_args *args,
5623 const struct nls_table *nls_codepage, int remap)
5624{
5625 TRANSACTION2_SPI_REQ *pSMB = NULL;
5626 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5627 int name_len;
5628 int rc = 0;
5629 int bytes_returned = 0;
5630 FILE_UNIX_BASIC_INFO *data_offset;
5631 __u16 params, param_offset, offset, count, byte_count;
5632
5633 cFYI(1, "In SetUID/GID/Mode");
5634setPermsRetry:
5635 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5636 (void **) &pSMBr);
5637 if (rc)
5638 return rc;
5639
5640 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5641 name_len =
5642 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5643 PATH_MAX, nls_codepage, remap);
5644 name_len++; /* trailing null */
5645 name_len *= 2;
5646 } else { /* BB improve the check for buffer overruns BB */
5647 name_len = strnlen(fileName, PATH_MAX);
5648 name_len++; /* trailing null */
5649 strncpy(pSMB->FileName, fileName, name_len);
5650 }
5651
5652 params = 6 + name_len;
5653 count = sizeof(FILE_UNIX_BASIC_INFO);
5654 pSMB->MaxParameterCount = cpu_to_le16(2);
5655 /* BB find max SMB PDU from sess structure BB */
5656 pSMB->MaxDataCount = cpu_to_le16(1000);
5657 pSMB->MaxSetupCount = 0;
5658 pSMB->Reserved = 0;
5659 pSMB->Flags = 0;
5660 pSMB->Timeout = 0;
5661 pSMB->Reserved2 = 0;
5662 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5663 InformationLevel) - 4;
5664 offset = param_offset + params;
5665 data_offset =
5666 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5667 offset);
5668 memset(data_offset, 0, count);
5669 pSMB->DataOffset = cpu_to_le16(offset);
5670 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5671 pSMB->SetupCount = 1;
5672 pSMB->Reserved3 = 0;
5673 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5674 byte_count = 3 /* pad */ + params + count;
5675 pSMB->ParameterCount = cpu_to_le16(params);
5676 pSMB->DataCount = cpu_to_le16(count);
5677 pSMB->TotalParameterCount = pSMB->ParameterCount;
5678 pSMB->TotalDataCount = pSMB->DataCount;
5679 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5680 pSMB->Reserved4 = 0;
5681 inc_rfc1001_len(pSMB, byte_count);
5682
5683 cifs_fill_unix_set_info(data_offset, args);
5684
5685 pSMB->ByteCount = cpu_to_le16(byte_count);
5686 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5687 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5688 if (rc)
5689 cFYI(1, "SetPathInfo (perms) returned %d", rc);
5690
5691 cifs_buf_release(pSMB);
5692 if (rc == -EAGAIN)
5693 goto setPermsRetry;
5694 return rc;
5695}
5696
5697#ifdef CONFIG_CIFS_XATTR
5698/*
5699 * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
5700 * function used by listxattr and getxattr type calls. When ea_name is set,
5701 * it looks for that attribute name and stuffs that value into the EAData
5702 * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
5703 * buffer. In both cases, the return value is either the length of the
5704 * resulting data or a negative error code. If EAData is a NULL pointer then
5705 * the data isn't copied to it, but the length is returned.
5706 */
5707ssize_t
5708CIFSSMBQAllEAs(const int xid, struct cifs_tcon *tcon,
5709 const unsigned char *searchName, const unsigned char *ea_name,
5710 char *EAData, size_t buf_size,
5711 const struct nls_table *nls_codepage, int remap)
5712{
5713 /* BB assumes one setup word */
5714 TRANSACTION2_QPI_REQ *pSMB = NULL;
5715 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5716 int rc = 0;
5717 int bytes_returned;
5718 int list_len;
5719 struct fealist *ea_response_data;
5720 struct fea *temp_fea;
5721 char *temp_ptr;
5722 char *end_of_smb;
5723 __u16 params, byte_count, data_offset;
5724 unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0;
5725
5726 cFYI(1, "In Query All EAs path %s", searchName);
5727QAllEAsRetry:
5728 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5729 (void **) &pSMBr);
5730 if (rc)
5731 return rc;
5732
5733 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5734 list_len =
5735 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5736 PATH_MAX, nls_codepage, remap);
5737 list_len++; /* trailing null */
5738 list_len *= 2;
5739 } else { /* BB improve the check for buffer overruns BB */
5740 list_len = strnlen(searchName, PATH_MAX);
5741 list_len++; /* trailing null */
5742 strncpy(pSMB->FileName, searchName, list_len);
5743 }
5744
5745 params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
5746 pSMB->TotalDataCount = 0;
5747 pSMB->MaxParameterCount = cpu_to_le16(2);
5748 /* BB find exact max SMB PDU from sess structure BB */
5749 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
5750 pSMB->MaxSetupCount = 0;
5751 pSMB->Reserved = 0;
5752 pSMB->Flags = 0;
5753 pSMB->Timeout = 0;
5754 pSMB->Reserved2 = 0;
5755 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5756 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5757 pSMB->DataCount = 0;
5758 pSMB->DataOffset = 0;
5759 pSMB->SetupCount = 1;
5760 pSMB->Reserved3 = 0;
5761 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5762 byte_count = params + 1 /* pad */ ;
5763 pSMB->TotalParameterCount = cpu_to_le16(params);
5764 pSMB->ParameterCount = pSMB->TotalParameterCount;
5765 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5766 pSMB->Reserved4 = 0;
5767 inc_rfc1001_len(pSMB, byte_count);
5768 pSMB->ByteCount = cpu_to_le16(byte_count);
5769
5770 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5771 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5772 if (rc) {
5773 cFYI(1, "Send error in QueryAllEAs = %d", rc);
5774 goto QAllEAsOut;
5775 }
5776
5777
5778 /* BB also check enough total bytes returned */
5779 /* BB we need to improve the validity checking
5780 of these trans2 responses */
5781
5782 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5783 if (rc || get_bcc(&pSMBr->hdr) < 4) {
5784 rc = -EIO; /* bad smb */
5785 goto QAllEAsOut;
5786 }
5787
5788 /* check that length of list is not more than bcc */
5789 /* check that each entry does not go beyond length
5790 of list */
5791 /* check that each element of each entry does not
5792 go beyond end of list */
5793 /* validate_trans2_offsets() */
5794 /* BB check if start of smb + data_offset > &bcc+ bcc */
5795
5796 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5797 ea_response_data = (struct fealist *)
5798 (((char *) &pSMBr->hdr.Protocol) + data_offset);
5799
5800 list_len = le32_to_cpu(ea_response_data->list_len);
5801 cFYI(1, "ea length %d", list_len);
5802 if (list_len <= 8) {
5803 cFYI(1, "empty EA list returned from server");
5804 goto QAllEAsOut;
5805 }
5806
5807 /* make sure list_len doesn't go past end of SMB */
5808 end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr);
5809 if ((char *)ea_response_data + list_len > end_of_smb) {
5810 cFYI(1, "EA list appears to go beyond SMB");
5811 rc = -EIO;
5812 goto QAllEAsOut;
5813 }
5814
5815 /* account for ea list len */
5816 list_len -= 4;
5817 temp_fea = ea_response_data->list;
5818 temp_ptr = (char *)temp_fea;
5819 while (list_len > 0) {
5820 unsigned int name_len;
5821 __u16 value_len;
5822
5823 list_len -= 4;
5824 temp_ptr += 4;
5825 /* make sure we can read name_len and value_len */
5826 if (list_len < 0) {
5827 cFYI(1, "EA entry goes beyond length of list");
5828 rc = -EIO;
5829 goto QAllEAsOut;
5830 }
5831
5832 name_len = temp_fea->name_len;
5833 value_len = le16_to_cpu(temp_fea->value_len);
5834 list_len -= name_len + 1 + value_len;
5835 if (list_len < 0) {
5836 cFYI(1, "EA entry goes beyond length of list");
5837 rc = -EIO;
5838 goto QAllEAsOut;
5839 }
5840
5841 if (ea_name) {
5842 if (ea_name_len == name_len &&
5843 strncmp(ea_name, temp_ptr, name_len) == 0) {
5844 temp_ptr += name_len + 1;
5845 rc = value_len;
5846 if (buf_size == 0)
5847 goto QAllEAsOut;
5848 if ((size_t)value_len > buf_size) {
5849 rc = -ERANGE;
5850 goto QAllEAsOut;
5851 }
5852 memcpy(EAData, temp_ptr, value_len);
5853 goto QAllEAsOut;
5854 }
5855 } else {
5856 /* account for prefix user. and trailing null */
5857 rc += (5 + 1 + name_len);
5858 if (rc < (int) buf_size) {
5859 memcpy(EAData, "user.", 5);
5860 EAData += 5;
5861 memcpy(EAData, temp_ptr, name_len);
5862 EAData += name_len;
5863 /* null terminate name */
5864 *EAData = 0;
5865 ++EAData;
5866 } else if (buf_size == 0) {
5867 /* skip copy - calc size only */
5868 } else {
5869 /* stop before overrun buffer */
5870 rc = -ERANGE;
5871 break;
5872 }
5873 }
5874 temp_ptr += name_len + 1 + value_len;
5875 temp_fea = (struct fea *)temp_ptr;
5876 }
5877
5878 /* didn't find the named attribute */
5879 if (ea_name)
5880 rc = -ENODATA;
5881
5882QAllEAsOut:
5883 cifs_buf_release(pSMB);
5884 if (rc == -EAGAIN)
5885 goto QAllEAsRetry;
5886
5887 return (ssize_t)rc;
5888}
5889
5890int
5891CIFSSMBSetEA(const int xid, struct cifs_tcon *tcon, const char *fileName,
5892 const char *ea_name, const void *ea_value,
5893 const __u16 ea_value_len, const struct nls_table *nls_codepage,
5894 int remap)
5895{
5896 struct smb_com_transaction2_spi_req *pSMB = NULL;
5897 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5898 struct fealist *parm_data;
5899 int name_len;
5900 int rc = 0;
5901 int bytes_returned = 0;
5902 __u16 params, param_offset, byte_count, offset, count;
5903
5904 cFYI(1, "In SetEA");
5905SetEARetry:
5906 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5907 (void **) &pSMBr);
5908 if (rc)
5909 return rc;
5910
5911 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5912 name_len =
5913 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5914 PATH_MAX, nls_codepage, remap);
5915 name_len++; /* trailing null */
5916 name_len *= 2;
5917 } else { /* BB improve the check for buffer overruns BB */
5918 name_len = strnlen(fileName, PATH_MAX);
5919 name_len++; /* trailing null */
5920 strncpy(pSMB->FileName, fileName, name_len);
5921 }
5922
5923 params = 6 + name_len;
5924
5925 /* done calculating parms using name_len of file name,
5926 now use name_len to calculate length of ea name
5927 we are going to create in the inode xattrs */
5928 if (ea_name == NULL)
5929 name_len = 0;
5930 else
5931 name_len = strnlen(ea_name, 255);
5932
5933 count = sizeof(*parm_data) + ea_value_len + name_len;
5934 pSMB->MaxParameterCount = cpu_to_le16(2);
5935 /* BB find max SMB PDU from sess */
5936 pSMB->MaxDataCount = cpu_to_le16(1000);
5937 pSMB->MaxSetupCount = 0;
5938 pSMB->Reserved = 0;
5939 pSMB->Flags = 0;
5940 pSMB->Timeout = 0;
5941 pSMB->Reserved2 = 0;
5942 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5943 InformationLevel) - 4;
5944 offset = param_offset + params;
5945 pSMB->InformationLevel =
5946 cpu_to_le16(SMB_SET_FILE_EA);
5947
5948 parm_data =
5949 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5950 offset);
5951 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5952 pSMB->DataOffset = cpu_to_le16(offset);
5953 pSMB->SetupCount = 1;
5954 pSMB->Reserved3 = 0;
5955 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5956 byte_count = 3 /* pad */ + params + count;
5957 pSMB->DataCount = cpu_to_le16(count);
5958 parm_data->list_len = cpu_to_le32(count);
5959 parm_data->list[0].EA_flags = 0;
5960 /* we checked above that name len is less than 255 */
5961 parm_data->list[0].name_len = (__u8)name_len;
5962 /* EA names are always ASCII */
5963 if (ea_name)
5964 strncpy(parm_data->list[0].name, ea_name, name_len);
5965 parm_data->list[0].name[name_len] = 0;
5966 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5967 /* caller ensures that ea_value_len is less than 64K but
5968 we need to ensure that it fits within the smb */
5969
5970 /*BB add length check to see if it would fit in
5971 negotiated SMB buffer size BB */
5972 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5973 if (ea_value_len)
5974 memcpy(parm_data->list[0].name+name_len+1,
5975 ea_value, ea_value_len);
5976
5977 pSMB->TotalDataCount = pSMB->DataCount;
5978 pSMB->ParameterCount = cpu_to_le16(params);
5979 pSMB->TotalParameterCount = pSMB->ParameterCount;
5980 pSMB->Reserved4 = 0;
5981 inc_rfc1001_len(pSMB, byte_count);
5982 pSMB->ByteCount = cpu_to_le16(byte_count);
5983 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5984 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5985 if (rc)
5986 cFYI(1, "SetPathInfo (EA) returned %d", rc);
5987
5988 cifs_buf_release(pSMB);
5989
5990 if (rc == -EAGAIN)
5991 goto SetEARetry;
5992
5993 return rc;
5994}
5995#endif
5996
5997#ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* BB unused temporarily */
5998/*
5999 * Years ago the kernel added a "dnotify" function for Samba server,
6000 * to allow network clients (such as Windows) to display updated
6001 * lists of files in directory listings automatically when
6002 * files are added by one user when another user has the
6003 * same directory open on their desktop. The Linux cifs kernel
6004 * client hooked into the kernel side of this interface for
6005 * the same reason, but ironically when the VFS moved from
6006 * "dnotify" to "inotify" it became harder to plug in Linux
6007 * network file system clients (the most obvious use case
6008 * for notify interfaces is when multiple users can update
6009 * the contents of the same directory - exactly what network
6010 * file systems can do) although the server (Samba) could
6011 * still use it. For the short term we leave the worker
6012 * function ifdeffed out (below) until inotify is fixed
6013 * in the VFS to make it easier to plug in network file
6014 * system clients. If inotify turns out to be permanently
6015 * incompatible for network fs clients, we could instead simply
6016 * expose this config flag by adding a future cifs (and smb2) notify ioctl.
6017 */
6018int CIFSSMBNotify(const int xid, struct cifs_tcon *tcon,
6019 const int notify_subdirs, const __u16 netfid,
6020 __u32 filter, struct file *pfile, int multishot,
6021 const struct nls_table *nls_codepage)
6022{
6023 int rc = 0;
6024 struct smb_com_transaction_change_notify_req *pSMB = NULL;
6025 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
6026 struct dir_notify_req *dnotify_req;
6027 int bytes_returned;
6028
6029 cFYI(1, "In CIFSSMBNotify for file handle %d", (int)netfid);
6030 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
6031 (void **) &pSMBr);
6032 if (rc)
6033 return rc;
6034
6035 pSMB->TotalParameterCount = 0 ;
6036 pSMB->TotalDataCount = 0;
6037 pSMB->MaxParameterCount = cpu_to_le32(2);
6038 /* BB find exact data count max from sess structure BB */
6039 pSMB->MaxDataCount = 0; /* same in little endian or be */
6040/* BB VERIFY verify which is correct for above BB */
6041 pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
6042 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
6043
6044 pSMB->MaxSetupCount = 4;
6045 pSMB->Reserved = 0;
6046 pSMB->ParameterOffset = 0;
6047 pSMB->DataCount = 0;
6048 pSMB->DataOffset = 0;
6049 pSMB->SetupCount = 4; /* single byte does not need le conversion */
6050 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
6051 pSMB->ParameterCount = pSMB->TotalParameterCount;
6052 if (notify_subdirs)
6053 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
6054 pSMB->Reserved2 = 0;
6055 pSMB->CompletionFilter = cpu_to_le32(filter);
6056 pSMB->Fid = netfid; /* file handle always le */
6057 pSMB->ByteCount = 0;
6058
6059 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6060 (struct smb_hdr *)pSMBr, &bytes_returned,
6061 CIFS_ASYNC_OP);
6062 if (rc) {
6063 cFYI(1, "Error in Notify = %d", rc);
6064 } else {
6065 /* Add file to outstanding requests */
6066 /* BB change to kmem cache alloc */
6067 dnotify_req = kmalloc(
6068 sizeof(struct dir_notify_req),
6069 GFP_KERNEL);
6070 if (dnotify_req) {
6071 dnotify_req->Pid = pSMB->hdr.Pid;
6072 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
6073 dnotify_req->Mid = pSMB->hdr.Mid;
6074 dnotify_req->Tid = pSMB->hdr.Tid;
6075 dnotify_req->Uid = pSMB->hdr.Uid;
6076 dnotify_req->netfid = netfid;
6077 dnotify_req->pfile = pfile;
6078 dnotify_req->filter = filter;
6079 dnotify_req->multishot = multishot;
6080 spin_lock(&GlobalMid_Lock);
6081 list_add_tail(&dnotify_req->lhead,
6082 &GlobalDnotifyReqList);
6083 spin_unlock(&GlobalMid_Lock);
6084 } else
6085 rc = -ENOMEM;
6086 }
6087 cifs_buf_release(pSMB);
6088 return rc;
6089}
6090#endif /* was needed for dnotify, and will be needed for inotify when VFS fix */
1/*
2 * fs/cifs/cifssmb.c
3 *
4 * Copyright (C) International Business Machines Corp., 2002,2010
5 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * Contains the routines for constructing the SMB PDUs themselves
8 *
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24 /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c */
25 /* These are mostly routines that operate on a pathname, or on a tree id */
26 /* (mounted volume), but there are eight handle based routines which must be */
27 /* treated slightly differently for reconnection purposes since we never */
28 /* want to reuse a stale file handle and only the caller knows the file info */
29
30#include <linux/fs.h>
31#include <linux/kernel.h>
32#include <linux/vfs.h>
33#include <linux/slab.h>
34#include <linux/posix_acl_xattr.h>
35#include <linux/pagemap.h>
36#include <linux/swap.h>
37#include <linux/task_io_accounting_ops.h>
38#include <linux/uaccess.h>
39#include "cifspdu.h"
40#include "cifsglob.h"
41#include "cifsacl.h"
42#include "cifsproto.h"
43#include "cifs_unicode.h"
44#include "cifs_debug.h"
45#include "fscache.h"
46
47#ifdef CONFIG_CIFS_POSIX
48static struct {
49 int index;
50 char *name;
51} protocols[] = {
52#ifdef CONFIG_CIFS_WEAK_PW_HASH
53 {LANMAN_PROT, "\2LM1.2X002"},
54 {LANMAN2_PROT, "\2LANMAN2.1"},
55#endif /* weak password hashing for legacy clients */
56 {CIFS_PROT, "\2NT LM 0.12"},
57 {POSIX_PROT, "\2POSIX 2"},
58 {BAD_PROT, "\2"}
59};
60#else
61static struct {
62 int index;
63 char *name;
64} protocols[] = {
65#ifdef CONFIG_CIFS_WEAK_PW_HASH
66 {LANMAN_PROT, "\2LM1.2X002"},
67 {LANMAN2_PROT, "\2LANMAN2.1"},
68#endif /* weak password hashing for legacy clients */
69 {CIFS_PROT, "\2NT LM 0.12"},
70 {BAD_PROT, "\2"}
71};
72#endif
73
74/* define the number of elements in the cifs dialect array */
75#ifdef CONFIG_CIFS_POSIX
76#ifdef CONFIG_CIFS_WEAK_PW_HASH
77#define CIFS_NUM_PROT 4
78#else
79#define CIFS_NUM_PROT 2
80#endif /* CIFS_WEAK_PW_HASH */
81#else /* not posix */
82#ifdef CONFIG_CIFS_WEAK_PW_HASH
83#define CIFS_NUM_PROT 3
84#else
85#define CIFS_NUM_PROT 1
86#endif /* CONFIG_CIFS_WEAK_PW_HASH */
87#endif /* CIFS_POSIX */
88
89/*
90 * Mark as invalid, all open files on tree connections since they
91 * were closed when session to server was lost.
92 */
93void
94cifs_mark_open_files_invalid(struct cifs_tcon *tcon)
95{
96 struct cifsFileInfo *open_file = NULL;
97 struct list_head *tmp;
98 struct list_head *tmp1;
99
100 /* list all files open on tree connection and mark them invalid */
101 spin_lock(&tcon->open_file_lock);
102 list_for_each_safe(tmp, tmp1, &tcon->openFileList) {
103 open_file = list_entry(tmp, struct cifsFileInfo, tlist);
104 open_file->invalidHandle = true;
105 open_file->oplock_break_cancelled = true;
106 }
107 spin_unlock(&tcon->open_file_lock);
108 /*
109 * BB Add call to invalidate_inodes(sb) for all superblocks mounted
110 * to this tcon.
111 */
112}
113
114/* reconnect the socket, tcon, and smb session if needed */
115static int
116cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
117{
118 int rc;
119 struct cifs_ses *ses;
120 struct TCP_Server_Info *server;
121 struct nls_table *nls_codepage;
122
123 /*
124 * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for
125 * tcp and smb session status done differently for those three - in the
126 * calling routine
127 */
128 if (!tcon)
129 return 0;
130
131 ses = tcon->ses;
132 server = ses->server;
133
134 /*
135 * only tree disconnect, open, and write, (and ulogoff which does not
136 * have tcon) are allowed as we start force umount
137 */
138 if (tcon->tidStatus == CifsExiting) {
139 if (smb_command != SMB_COM_WRITE_ANDX &&
140 smb_command != SMB_COM_OPEN_ANDX &&
141 smb_command != SMB_COM_TREE_DISCONNECT) {
142 cifs_dbg(FYI, "can not send cmd %d while umounting\n",
143 smb_command);
144 return -ENODEV;
145 }
146 }
147
148 /*
149 * Give demultiplex thread up to 10 seconds to reconnect, should be
150 * greater than cifs socket timeout which is 7 seconds
151 */
152 while (server->tcpStatus == CifsNeedReconnect) {
153 wait_event_interruptible_timeout(server->response_q,
154 (server->tcpStatus != CifsNeedReconnect), 10 * HZ);
155
156 /* are we still trying to reconnect? */
157 if (server->tcpStatus != CifsNeedReconnect)
158 break;
159
160 /*
161 * on "soft" mounts we wait once. Hard mounts keep
162 * retrying until process is killed or server comes
163 * back on-line
164 */
165 if (!tcon->retry) {
166 cifs_dbg(FYI, "gave up waiting on reconnect in smb_init\n");
167 return -EHOSTDOWN;
168 }
169 }
170
171 if (!ses->need_reconnect && !tcon->need_reconnect)
172 return 0;
173
174 nls_codepage = load_nls_default();
175
176 /*
177 * need to prevent multiple threads trying to simultaneously
178 * reconnect the same SMB session
179 */
180 mutex_lock(&ses->session_mutex);
181 rc = cifs_negotiate_protocol(0, ses);
182 if (rc == 0 && ses->need_reconnect)
183 rc = cifs_setup_session(0, ses, nls_codepage);
184
185 /* do we need to reconnect tcon? */
186 if (rc || !tcon->need_reconnect) {
187 mutex_unlock(&ses->session_mutex);
188 goto out;
189 }
190
191 cifs_mark_open_files_invalid(tcon);
192 rc = CIFSTCon(0, ses, tcon->treeName, tcon, nls_codepage);
193 mutex_unlock(&ses->session_mutex);
194 cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc);
195
196 if (rc)
197 goto out;
198
199 atomic_inc(&tconInfoReconnectCount);
200
201 /* tell server Unix caps we support */
202 if (ses->capabilities & CAP_UNIX)
203 reset_cifs_unix_caps(0, tcon, NULL, NULL);
204
205 /*
206 * Removed call to reopen open files here. It is safer (and faster) to
207 * reopen files one at a time as needed in read and write.
208 *
209 * FIXME: what about file locks? don't we need to reclaim them ASAP?
210 */
211
212out:
213 /*
214 * Check if handle based operation so we know whether we can continue
215 * or not without returning to caller to reset file handle
216 */
217 switch (smb_command) {
218 case SMB_COM_READ_ANDX:
219 case SMB_COM_WRITE_ANDX:
220 case SMB_COM_CLOSE:
221 case SMB_COM_FIND_CLOSE2:
222 case SMB_COM_LOCKING_ANDX:
223 rc = -EAGAIN;
224 }
225
226 unload_nls(nls_codepage);
227 return rc;
228}
229
230/* Allocate and return pointer to an SMB request buffer, and set basic
231 SMB information in the SMB header. If the return code is zero, this
232 function must have filled in request_buf pointer */
233static int
234small_smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
235 void **request_buf)
236{
237 int rc;
238
239 rc = cifs_reconnect_tcon(tcon, smb_command);
240 if (rc)
241 return rc;
242
243 *request_buf = cifs_small_buf_get();
244 if (*request_buf == NULL) {
245 /* BB should we add a retry in here if not a writepage? */
246 return -ENOMEM;
247 }
248
249 header_assemble((struct smb_hdr *) *request_buf, smb_command,
250 tcon, wct);
251
252 if (tcon != NULL)
253 cifs_stats_inc(&tcon->num_smbs_sent);
254
255 return 0;
256}
257
258int
259small_smb_init_no_tc(const int smb_command, const int wct,
260 struct cifs_ses *ses, void **request_buf)
261{
262 int rc;
263 struct smb_hdr *buffer;
264
265 rc = small_smb_init(smb_command, wct, NULL, request_buf);
266 if (rc)
267 return rc;
268
269 buffer = (struct smb_hdr *)*request_buf;
270 buffer->Mid = get_next_mid(ses->server);
271 if (ses->capabilities & CAP_UNICODE)
272 buffer->Flags2 |= SMBFLG2_UNICODE;
273 if (ses->capabilities & CAP_STATUS32)
274 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
275
276 /* uid, tid can stay at zero as set in header assemble */
277
278 /* BB add support for turning on the signing when
279 this function is used after 1st of session setup requests */
280
281 return rc;
282}
283
284/* If the return code is zero, this function must fill in request_buf pointer */
285static int
286__smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
287 void **request_buf, void **response_buf)
288{
289 *request_buf = cifs_buf_get();
290 if (*request_buf == NULL) {
291 /* BB should we add a retry in here if not a writepage? */
292 return -ENOMEM;
293 }
294 /* Although the original thought was we needed the response buf for */
295 /* potential retries of smb operations it turns out we can determine */
296 /* from the mid flags when the request buffer can be resent without */
297 /* having to use a second distinct buffer for the response */
298 if (response_buf)
299 *response_buf = *request_buf;
300
301 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
302 wct);
303
304 if (tcon != NULL)
305 cifs_stats_inc(&tcon->num_smbs_sent);
306
307 return 0;
308}
309
310/* If the return code is zero, this function must fill in request_buf pointer */
311static int
312smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
313 void **request_buf, void **response_buf)
314{
315 int rc;
316
317 rc = cifs_reconnect_tcon(tcon, smb_command);
318 if (rc)
319 return rc;
320
321 return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
322}
323
324static int
325smb_init_no_reconnect(int smb_command, int wct, struct cifs_tcon *tcon,
326 void **request_buf, void **response_buf)
327{
328 if (tcon->ses->need_reconnect || tcon->need_reconnect)
329 return -EHOSTDOWN;
330
331 return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
332}
333
334static int validate_t2(struct smb_t2_rsp *pSMB)
335{
336 unsigned int total_size;
337
338 /* check for plausible wct */
339 if (pSMB->hdr.WordCount < 10)
340 goto vt2_err;
341
342 /* check for parm and data offset going beyond end of smb */
343 if (get_unaligned_le16(&pSMB->t2_rsp.ParameterOffset) > 1024 ||
344 get_unaligned_le16(&pSMB->t2_rsp.DataOffset) > 1024)
345 goto vt2_err;
346
347 total_size = get_unaligned_le16(&pSMB->t2_rsp.ParameterCount);
348 if (total_size >= 512)
349 goto vt2_err;
350
351 /* check that bcc is at least as big as parms + data, and that it is
352 * less than negotiated smb buffer
353 */
354 total_size += get_unaligned_le16(&pSMB->t2_rsp.DataCount);
355 if (total_size > get_bcc(&pSMB->hdr) ||
356 total_size >= CIFSMaxBufSize + MAX_CIFS_HDR_SIZE)
357 goto vt2_err;
358
359 return 0;
360vt2_err:
361 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
362 sizeof(struct smb_t2_rsp) + 16);
363 return -EINVAL;
364}
365
366static int
367decode_ext_sec_blob(struct cifs_ses *ses, NEGOTIATE_RSP *pSMBr)
368{
369 int rc = 0;
370 u16 count;
371 char *guid = pSMBr->u.extended_response.GUID;
372 struct TCP_Server_Info *server = ses->server;
373
374 count = get_bcc(&pSMBr->hdr);
375 if (count < SMB1_CLIENT_GUID_SIZE)
376 return -EIO;
377
378 spin_lock(&cifs_tcp_ses_lock);
379 if (server->srv_count > 1) {
380 spin_unlock(&cifs_tcp_ses_lock);
381 if (memcmp(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE) != 0) {
382 cifs_dbg(FYI, "server UID changed\n");
383 memcpy(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE);
384 }
385 } else {
386 spin_unlock(&cifs_tcp_ses_lock);
387 memcpy(server->server_GUID, guid, SMB1_CLIENT_GUID_SIZE);
388 }
389
390 if (count == SMB1_CLIENT_GUID_SIZE) {
391 server->sec_ntlmssp = true;
392 } else {
393 count -= SMB1_CLIENT_GUID_SIZE;
394 rc = decode_negTokenInit(
395 pSMBr->u.extended_response.SecurityBlob, count, server);
396 if (rc != 1)
397 return -EINVAL;
398 }
399
400 return 0;
401}
402
403int
404cifs_enable_signing(struct TCP_Server_Info *server, bool mnt_sign_required)
405{
406 bool srv_sign_required = server->sec_mode & server->vals->signing_required;
407 bool srv_sign_enabled = server->sec_mode & server->vals->signing_enabled;
408 bool mnt_sign_enabled = global_secflags & CIFSSEC_MAY_SIGN;
409
410 /*
411 * Is signing required by mnt options? If not then check
412 * global_secflags to see if it is there.
413 */
414 if (!mnt_sign_required)
415 mnt_sign_required = ((global_secflags & CIFSSEC_MUST_SIGN) ==
416 CIFSSEC_MUST_SIGN);
417
418 /*
419 * If signing is required then it's automatically enabled too,
420 * otherwise, check to see if the secflags allow it.
421 */
422 mnt_sign_enabled = mnt_sign_required ? mnt_sign_required :
423 (global_secflags & CIFSSEC_MAY_SIGN);
424
425 /* If server requires signing, does client allow it? */
426 if (srv_sign_required) {
427 if (!mnt_sign_enabled) {
428 cifs_dbg(VFS, "Server requires signing, but it's disabled in SecurityFlags!");
429 return -ENOTSUPP;
430 }
431 server->sign = true;
432 }
433
434 /* If client requires signing, does server allow it? */
435 if (mnt_sign_required) {
436 if (!srv_sign_enabled) {
437 cifs_dbg(VFS, "Server does not support signing!");
438 return -ENOTSUPP;
439 }
440 server->sign = true;
441 }
442
443 return 0;
444}
445
446#ifdef CONFIG_CIFS_WEAK_PW_HASH
447static int
448decode_lanman_negprot_rsp(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr)
449{
450 __s16 tmp;
451 struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
452
453 if (server->dialect != LANMAN_PROT && server->dialect != LANMAN2_PROT)
454 return -EOPNOTSUPP;
455
456 server->sec_mode = le16_to_cpu(rsp->SecurityMode);
457 server->maxReq = min_t(unsigned int,
458 le16_to_cpu(rsp->MaxMpxCount),
459 cifs_max_pending);
460 set_credits(server, server->maxReq);
461 server->maxBuf = le16_to_cpu(rsp->MaxBufSize);
462 /* even though we do not use raw we might as well set this
463 accurately, in case we ever find a need for it */
464 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
465 server->max_rw = 0xFF00;
466 server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
467 } else {
468 server->max_rw = 0;/* do not need to use raw anyway */
469 server->capabilities = CAP_MPX_MODE;
470 }
471 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
472 if (tmp == -1) {
473 /* OS/2 often does not set timezone therefore
474 * we must use server time to calc time zone.
475 * Could deviate slightly from the right zone.
476 * Smallest defined timezone difference is 15 minutes
477 * (i.e. Nepal). Rounding up/down is done to match
478 * this requirement.
479 */
480 int val, seconds, remain, result;
481 struct timespec ts, utc;
482 utc = CURRENT_TIME;
483 ts = cnvrtDosUnixTm(rsp->SrvTime.Date,
484 rsp->SrvTime.Time, 0);
485 cifs_dbg(FYI, "SrvTime %d sec since 1970 (utc: %d) diff: %d\n",
486 (int)ts.tv_sec, (int)utc.tv_sec,
487 (int)(utc.tv_sec - ts.tv_sec));
488 val = (int)(utc.tv_sec - ts.tv_sec);
489 seconds = abs(val);
490 result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
491 remain = seconds % MIN_TZ_ADJ;
492 if (remain >= (MIN_TZ_ADJ / 2))
493 result += MIN_TZ_ADJ;
494 if (val < 0)
495 result = -result;
496 server->timeAdj = result;
497 } else {
498 server->timeAdj = (int)tmp;
499 server->timeAdj *= 60; /* also in seconds */
500 }
501 cifs_dbg(FYI, "server->timeAdj: %d seconds\n", server->timeAdj);
502
503
504 /* BB get server time for time conversions and add
505 code to use it and timezone since this is not UTC */
506
507 if (rsp->EncryptionKeyLength ==
508 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
509 memcpy(server->cryptkey, rsp->EncryptionKey,
510 CIFS_CRYPTO_KEY_SIZE);
511 } else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
512 return -EIO; /* need cryptkey unless plain text */
513 }
514
515 cifs_dbg(FYI, "LANMAN negotiated\n");
516 return 0;
517}
518#else
519static inline int
520decode_lanman_negprot_rsp(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr)
521{
522 cifs_dbg(VFS, "mount failed, cifs module not built with CIFS_WEAK_PW_HASH support\n");
523 return -EOPNOTSUPP;
524}
525#endif
526
527static bool
528should_set_ext_sec_flag(enum securityEnum sectype)
529{
530 switch (sectype) {
531 case RawNTLMSSP:
532 case Kerberos:
533 return true;
534 case Unspecified:
535 if (global_secflags &
536 (CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_NTLMSSP))
537 return true;
538 /* Fallthrough */
539 default:
540 return false;
541 }
542}
543
544int
545CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses)
546{
547 NEGOTIATE_REQ *pSMB;
548 NEGOTIATE_RSP *pSMBr;
549 int rc = 0;
550 int bytes_returned;
551 int i;
552 struct TCP_Server_Info *server = ses->server;
553 u16 count;
554
555 if (!server) {
556 WARN(1, "%s: server is NULL!\n", __func__);
557 return -EIO;
558 }
559
560 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
561 (void **) &pSMB, (void **) &pSMBr);
562 if (rc)
563 return rc;
564
565 pSMB->hdr.Mid = get_next_mid(server);
566 pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
567
568 if (should_set_ext_sec_flag(ses->sectype)) {
569 cifs_dbg(FYI, "Requesting extended security.");
570 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
571 }
572
573 count = 0;
574 for (i = 0; i < CIFS_NUM_PROT; i++) {
575 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
576 count += strlen(protocols[i].name) + 1;
577 /* null at end of source and target buffers anyway */
578 }
579 inc_rfc1001_len(pSMB, count);
580 pSMB->ByteCount = cpu_to_le16(count);
581
582 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
583 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
584 if (rc != 0)
585 goto neg_err_exit;
586
587 server->dialect = le16_to_cpu(pSMBr->DialectIndex);
588 cifs_dbg(FYI, "Dialect: %d\n", server->dialect);
589 /* Check wct = 1 error case */
590 if ((pSMBr->hdr.WordCount < 13) || (server->dialect == BAD_PROT)) {
591 /* core returns wct = 1, but we do not ask for core - otherwise
592 small wct just comes when dialect index is -1 indicating we
593 could not negotiate a common dialect */
594 rc = -EOPNOTSUPP;
595 goto neg_err_exit;
596 } else if (pSMBr->hdr.WordCount == 13) {
597 server->negflavor = CIFS_NEGFLAVOR_LANMAN;
598 rc = decode_lanman_negprot_rsp(server, pSMBr);
599 goto signing_check;
600 } else if (pSMBr->hdr.WordCount != 17) {
601 /* unknown wct */
602 rc = -EOPNOTSUPP;
603 goto neg_err_exit;
604 }
605 /* else wct == 17, NTLM or better */
606
607 server->sec_mode = pSMBr->SecurityMode;
608 if ((server->sec_mode & SECMODE_USER) == 0)
609 cifs_dbg(FYI, "share mode security\n");
610
611 /* one byte, so no need to convert this or EncryptionKeyLen from
612 little endian */
613 server->maxReq = min_t(unsigned int, le16_to_cpu(pSMBr->MaxMpxCount),
614 cifs_max_pending);
615 set_credits(server, server->maxReq);
616 /* probably no need to store and check maxvcs */
617 server->maxBuf = le32_to_cpu(pSMBr->MaxBufferSize);
618 server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
619 cifs_dbg(NOISY, "Max buf = %d\n", ses->server->maxBuf);
620 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
621 server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
622 server->timeAdj *= 60;
623
624 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
625 server->negflavor = CIFS_NEGFLAVOR_UNENCAP;
626 memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey,
627 CIFS_CRYPTO_KEY_SIZE);
628 } else if (pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC ||
629 server->capabilities & CAP_EXTENDED_SECURITY) {
630 server->negflavor = CIFS_NEGFLAVOR_EXTENDED;
631 rc = decode_ext_sec_blob(ses, pSMBr);
632 } else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
633 rc = -EIO; /* no crypt key only if plain text pwd */
634 } else {
635 server->negflavor = CIFS_NEGFLAVOR_UNENCAP;
636 server->capabilities &= ~CAP_EXTENDED_SECURITY;
637 }
638
639signing_check:
640 if (!rc)
641 rc = cifs_enable_signing(server, ses->sign);
642neg_err_exit:
643 cifs_buf_release(pSMB);
644
645 cifs_dbg(FYI, "negprot rc %d\n", rc);
646 return rc;
647}
648
649int
650CIFSSMBTDis(const unsigned int xid, struct cifs_tcon *tcon)
651{
652 struct smb_hdr *smb_buffer;
653 int rc = 0;
654
655 cifs_dbg(FYI, "In tree disconnect\n");
656
657 /* BB: do we need to check this? These should never be NULL. */
658 if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
659 return -EIO;
660
661 /*
662 * No need to return error on this operation if tid invalidated and
663 * closed on server already e.g. due to tcp session crashing. Also,
664 * the tcon is no longer on the list, so no need to take lock before
665 * checking this.
666 */
667 if ((tcon->need_reconnect) || (tcon->ses->need_reconnect))
668 return 0;
669
670 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
671 (void **)&smb_buffer);
672 if (rc)
673 return rc;
674
675 rc = SendReceiveNoRsp(xid, tcon->ses, (char *)smb_buffer, 0);
676 if (rc)
677 cifs_dbg(FYI, "Tree disconnect failed %d\n", rc);
678
679 /* No need to return error on this operation if tid invalidated and
680 closed on server already e.g. due to tcp session crashing */
681 if (rc == -EAGAIN)
682 rc = 0;
683
684 return rc;
685}
686
687/*
688 * This is a no-op for now. We're not really interested in the reply, but
689 * rather in the fact that the server sent one and that server->lstrp
690 * gets updated.
691 *
692 * FIXME: maybe we should consider checking that the reply matches request?
693 */
694static void
695cifs_echo_callback(struct mid_q_entry *mid)
696{
697 struct TCP_Server_Info *server = mid->callback_data;
698
699 mutex_lock(&server->srv_mutex);
700 DeleteMidQEntry(mid);
701 mutex_unlock(&server->srv_mutex);
702 add_credits(server, 1, CIFS_ECHO_OP);
703}
704
705int
706CIFSSMBEcho(struct TCP_Server_Info *server)
707{
708 ECHO_REQ *smb;
709 int rc = 0;
710 struct kvec iov;
711 struct smb_rqst rqst = { .rq_iov = &iov,
712 .rq_nvec = 1 };
713
714 cifs_dbg(FYI, "In echo request\n");
715
716 rc = small_smb_init(SMB_COM_ECHO, 0, NULL, (void **)&smb);
717 if (rc)
718 return rc;
719
720 /* set up echo request */
721 smb->hdr.Tid = 0xffff;
722 smb->hdr.WordCount = 1;
723 put_unaligned_le16(1, &smb->EchoCount);
724 put_bcc(1, &smb->hdr);
725 smb->Data[0] = 'a';
726 inc_rfc1001_len(smb, 3);
727 iov.iov_base = smb;
728 iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;
729
730 rc = cifs_call_async(server, &rqst, NULL, cifs_echo_callback,
731 server, CIFS_ASYNC_OP | CIFS_ECHO_OP);
732 if (rc)
733 cifs_dbg(FYI, "Echo request failed: %d\n", rc);
734
735 cifs_small_buf_release(smb);
736
737 return rc;
738}
739
740int
741CIFSSMBLogoff(const unsigned int xid, struct cifs_ses *ses)
742{
743 LOGOFF_ANDX_REQ *pSMB;
744 int rc = 0;
745
746 cifs_dbg(FYI, "In SMBLogoff for session disconnect\n");
747
748 /*
749 * BB: do we need to check validity of ses and server? They should
750 * always be valid since we have an active reference. If not, that
751 * should probably be a BUG()
752 */
753 if (!ses || !ses->server)
754 return -EIO;
755
756 mutex_lock(&ses->session_mutex);
757 if (ses->need_reconnect)
758 goto session_already_dead; /* no need to send SMBlogoff if uid
759 already closed due to reconnect */
760 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
761 if (rc) {
762 mutex_unlock(&ses->session_mutex);
763 return rc;
764 }
765
766 pSMB->hdr.Mid = get_next_mid(ses->server);
767
768 if (ses->server->sign)
769 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
770
771 pSMB->hdr.Uid = ses->Suid;
772
773 pSMB->AndXCommand = 0xFF;
774 rc = SendReceiveNoRsp(xid, ses, (char *) pSMB, 0);
775session_already_dead:
776 mutex_unlock(&ses->session_mutex);
777
778 /* if session dead then we do not need to do ulogoff,
779 since server closed smb session, no sense reporting
780 error */
781 if (rc == -EAGAIN)
782 rc = 0;
783 return rc;
784}
785
786int
787CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon,
788 const char *fileName, __u16 type,
789 const struct nls_table *nls_codepage, int remap)
790{
791 TRANSACTION2_SPI_REQ *pSMB = NULL;
792 TRANSACTION2_SPI_RSP *pSMBr = NULL;
793 struct unlink_psx_rq *pRqD;
794 int name_len;
795 int rc = 0;
796 int bytes_returned = 0;
797 __u16 params, param_offset, offset, byte_count;
798
799 cifs_dbg(FYI, "In POSIX delete\n");
800PsxDelete:
801 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
802 (void **) &pSMBr);
803 if (rc)
804 return rc;
805
806 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
807 name_len =
808 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
809 PATH_MAX, nls_codepage, remap);
810 name_len++; /* trailing null */
811 name_len *= 2;
812 } else { /* BB add path length overrun check */
813 name_len = strnlen(fileName, PATH_MAX);
814 name_len++; /* trailing null */
815 strncpy(pSMB->FileName, fileName, name_len);
816 }
817
818 params = 6 + name_len;
819 pSMB->MaxParameterCount = cpu_to_le16(2);
820 pSMB->MaxDataCount = 0; /* BB double check this with jra */
821 pSMB->MaxSetupCount = 0;
822 pSMB->Reserved = 0;
823 pSMB->Flags = 0;
824 pSMB->Timeout = 0;
825 pSMB->Reserved2 = 0;
826 param_offset = offsetof(struct smb_com_transaction2_spi_req,
827 InformationLevel) - 4;
828 offset = param_offset + params;
829
830 /* Setup pointer to Request Data (inode type) */
831 pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
832 pRqD->type = cpu_to_le16(type);
833 pSMB->ParameterOffset = cpu_to_le16(param_offset);
834 pSMB->DataOffset = cpu_to_le16(offset);
835 pSMB->SetupCount = 1;
836 pSMB->Reserved3 = 0;
837 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
838 byte_count = 3 /* pad */ + params + sizeof(struct unlink_psx_rq);
839
840 pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
841 pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
842 pSMB->ParameterCount = cpu_to_le16(params);
843 pSMB->TotalParameterCount = pSMB->ParameterCount;
844 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
845 pSMB->Reserved4 = 0;
846 inc_rfc1001_len(pSMB, byte_count);
847 pSMB->ByteCount = cpu_to_le16(byte_count);
848 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
849 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
850 if (rc)
851 cifs_dbg(FYI, "Posix delete returned %d\n", rc);
852 cifs_buf_release(pSMB);
853
854 cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
855
856 if (rc == -EAGAIN)
857 goto PsxDelete;
858
859 return rc;
860}
861
862int
863CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
864 struct cifs_sb_info *cifs_sb)
865{
866 DELETE_FILE_REQ *pSMB = NULL;
867 DELETE_FILE_RSP *pSMBr = NULL;
868 int rc = 0;
869 int bytes_returned;
870 int name_len;
871 int remap = cifs_remap(cifs_sb);
872
873DelFileRetry:
874 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
875 (void **) &pSMBr);
876 if (rc)
877 return rc;
878
879 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
880 name_len = cifsConvertToUTF16((__le16 *) pSMB->fileName, name,
881 PATH_MAX, cifs_sb->local_nls,
882 remap);
883 name_len++; /* trailing null */
884 name_len *= 2;
885 } else { /* BB improve check for buffer overruns BB */
886 name_len = strnlen(name, PATH_MAX);
887 name_len++; /* trailing null */
888 strncpy(pSMB->fileName, name, name_len);
889 }
890 pSMB->SearchAttributes =
891 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
892 pSMB->BufferFormat = 0x04;
893 inc_rfc1001_len(pSMB, name_len + 1);
894 pSMB->ByteCount = cpu_to_le16(name_len + 1);
895 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
896 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
897 cifs_stats_inc(&tcon->stats.cifs_stats.num_deletes);
898 if (rc)
899 cifs_dbg(FYI, "Error in RMFile = %d\n", rc);
900
901 cifs_buf_release(pSMB);
902 if (rc == -EAGAIN)
903 goto DelFileRetry;
904
905 return rc;
906}
907
908int
909CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
910 struct cifs_sb_info *cifs_sb)
911{
912 DELETE_DIRECTORY_REQ *pSMB = NULL;
913 DELETE_DIRECTORY_RSP *pSMBr = NULL;
914 int rc = 0;
915 int bytes_returned;
916 int name_len;
917 int remap = cifs_remap(cifs_sb);
918
919 cifs_dbg(FYI, "In CIFSSMBRmDir\n");
920RmDirRetry:
921 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
922 (void **) &pSMBr);
923 if (rc)
924 return rc;
925
926 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
927 name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
928 PATH_MAX, cifs_sb->local_nls,
929 remap);
930 name_len++; /* trailing null */
931 name_len *= 2;
932 } else { /* BB improve check for buffer overruns BB */
933 name_len = strnlen(name, PATH_MAX);
934 name_len++; /* trailing null */
935 strncpy(pSMB->DirName, name, name_len);
936 }
937
938 pSMB->BufferFormat = 0x04;
939 inc_rfc1001_len(pSMB, name_len + 1);
940 pSMB->ByteCount = cpu_to_le16(name_len + 1);
941 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
942 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
943 cifs_stats_inc(&tcon->stats.cifs_stats.num_rmdirs);
944 if (rc)
945 cifs_dbg(FYI, "Error in RMDir = %d\n", rc);
946
947 cifs_buf_release(pSMB);
948 if (rc == -EAGAIN)
949 goto RmDirRetry;
950 return rc;
951}
952
953int
954CIFSSMBMkDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
955 struct cifs_sb_info *cifs_sb)
956{
957 int rc = 0;
958 CREATE_DIRECTORY_REQ *pSMB = NULL;
959 CREATE_DIRECTORY_RSP *pSMBr = NULL;
960 int bytes_returned;
961 int name_len;
962 int remap = cifs_remap(cifs_sb);
963
964 cifs_dbg(FYI, "In CIFSSMBMkDir\n");
965MkDirRetry:
966 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
967 (void **) &pSMBr);
968 if (rc)
969 return rc;
970
971 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
972 name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
973 PATH_MAX, cifs_sb->local_nls,
974 remap);
975 name_len++; /* trailing null */
976 name_len *= 2;
977 } else { /* BB improve check for buffer overruns BB */
978 name_len = strnlen(name, PATH_MAX);
979 name_len++; /* trailing null */
980 strncpy(pSMB->DirName, name, name_len);
981 }
982
983 pSMB->BufferFormat = 0x04;
984 inc_rfc1001_len(pSMB, name_len + 1);
985 pSMB->ByteCount = cpu_to_le16(name_len + 1);
986 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
987 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
988 cifs_stats_inc(&tcon->stats.cifs_stats.num_mkdirs);
989 if (rc)
990 cifs_dbg(FYI, "Error in Mkdir = %d\n", rc);
991
992 cifs_buf_release(pSMB);
993 if (rc == -EAGAIN)
994 goto MkDirRetry;
995 return rc;
996}
997
998int
999CIFSPOSIXCreate(const unsigned int xid, struct cifs_tcon *tcon,
1000 __u32 posix_flags, __u64 mode, __u16 *netfid,
1001 FILE_UNIX_BASIC_INFO *pRetData, __u32 *pOplock,
1002 const char *name, const struct nls_table *nls_codepage,
1003 int remap)
1004{
1005 TRANSACTION2_SPI_REQ *pSMB = NULL;
1006 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1007 int name_len;
1008 int rc = 0;
1009 int bytes_returned = 0;
1010 __u16 params, param_offset, offset, byte_count, count;
1011 OPEN_PSX_REQ *pdata;
1012 OPEN_PSX_RSP *psx_rsp;
1013
1014 cifs_dbg(FYI, "In POSIX Create\n");
1015PsxCreat:
1016 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1017 (void **) &pSMBr);
1018 if (rc)
1019 return rc;
1020
1021 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1022 name_len =
1023 cifsConvertToUTF16((__le16 *) pSMB->FileName, name,
1024 PATH_MAX, nls_codepage, remap);
1025 name_len++; /* trailing null */
1026 name_len *= 2;
1027 } else { /* BB improve the check for buffer overruns BB */
1028 name_len = strnlen(name, PATH_MAX);
1029 name_len++; /* trailing null */
1030 strncpy(pSMB->FileName, name, name_len);
1031 }
1032
1033 params = 6 + name_len;
1034 count = sizeof(OPEN_PSX_REQ);
1035 pSMB->MaxParameterCount = cpu_to_le16(2);
1036 pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1037 pSMB->MaxSetupCount = 0;
1038 pSMB->Reserved = 0;
1039 pSMB->Flags = 0;
1040 pSMB->Timeout = 0;
1041 pSMB->Reserved2 = 0;
1042 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1043 InformationLevel) - 4;
1044 offset = param_offset + params;
1045 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1046 pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1047 pdata->Permissions = cpu_to_le64(mode);
1048 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1049 pdata->OpenFlags = cpu_to_le32(*pOplock);
1050 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1051 pSMB->DataOffset = cpu_to_le16(offset);
1052 pSMB->SetupCount = 1;
1053 pSMB->Reserved3 = 0;
1054 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1055 byte_count = 3 /* pad */ + params + count;
1056
1057 pSMB->DataCount = cpu_to_le16(count);
1058 pSMB->ParameterCount = cpu_to_le16(params);
1059 pSMB->TotalDataCount = pSMB->DataCount;
1060 pSMB->TotalParameterCount = pSMB->ParameterCount;
1061 pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1062 pSMB->Reserved4 = 0;
1063 inc_rfc1001_len(pSMB, byte_count);
1064 pSMB->ByteCount = cpu_to_le16(byte_count);
1065 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1066 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1067 if (rc) {
1068 cifs_dbg(FYI, "Posix create returned %d\n", rc);
1069 goto psx_create_err;
1070 }
1071
1072 cifs_dbg(FYI, "copying inode info\n");
1073 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1074
1075 if (rc || get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)) {
1076 rc = -EIO; /* bad smb */
1077 goto psx_create_err;
1078 }
1079
1080 /* copy return information to pRetData */
1081 psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1082 + le16_to_cpu(pSMBr->t2.DataOffset));
1083
1084 *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1085 if (netfid)
1086 *netfid = psx_rsp->Fid; /* cifs fid stays in le */
1087 /* Let caller know file was created so we can set the mode. */
1088 /* Do we care about the CreateAction in any other cases? */
1089 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1090 *pOplock |= CIFS_CREATE_ACTION;
1091 /* check to make sure response data is there */
1092 if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1093 pRetData->Type = cpu_to_le32(-1); /* unknown */
1094 cifs_dbg(NOISY, "unknown type\n");
1095 } else {
1096 if (get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)
1097 + sizeof(FILE_UNIX_BASIC_INFO)) {
1098 cifs_dbg(VFS, "Open response data too small\n");
1099 pRetData->Type = cpu_to_le32(-1);
1100 goto psx_create_err;
1101 }
1102 memcpy((char *) pRetData,
1103 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1104 sizeof(FILE_UNIX_BASIC_INFO));
1105 }
1106
1107psx_create_err:
1108 cifs_buf_release(pSMB);
1109
1110 if (posix_flags & SMB_O_DIRECTORY)
1111 cifs_stats_inc(&tcon->stats.cifs_stats.num_posixmkdirs);
1112 else
1113 cifs_stats_inc(&tcon->stats.cifs_stats.num_posixopens);
1114
1115 if (rc == -EAGAIN)
1116 goto PsxCreat;
1117
1118 return rc;
1119}
1120
1121static __u16 convert_disposition(int disposition)
1122{
1123 __u16 ofun = 0;
1124
1125 switch (disposition) {
1126 case FILE_SUPERSEDE:
1127 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1128 break;
1129 case FILE_OPEN:
1130 ofun = SMBOPEN_OAPPEND;
1131 break;
1132 case FILE_CREATE:
1133 ofun = SMBOPEN_OCREATE;
1134 break;
1135 case FILE_OPEN_IF:
1136 ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1137 break;
1138 case FILE_OVERWRITE:
1139 ofun = SMBOPEN_OTRUNC;
1140 break;
1141 case FILE_OVERWRITE_IF:
1142 ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1143 break;
1144 default:
1145 cifs_dbg(FYI, "unknown disposition %d\n", disposition);
1146 ofun = SMBOPEN_OAPPEND; /* regular open */
1147 }
1148 return ofun;
1149}
1150
1151static int
1152access_flags_to_smbopen_mode(const int access_flags)
1153{
1154 int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1155
1156 if (masked_flags == GENERIC_READ)
1157 return SMBOPEN_READ;
1158 else if (masked_flags == GENERIC_WRITE)
1159 return SMBOPEN_WRITE;
1160
1161 /* just go for read/write */
1162 return SMBOPEN_READWRITE;
1163}
1164
1165int
1166SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon,
1167 const char *fileName, const int openDisposition,
1168 const int access_flags, const int create_options, __u16 *netfid,
1169 int *pOplock, FILE_ALL_INFO *pfile_info,
1170 const struct nls_table *nls_codepage, int remap)
1171{
1172 int rc = -EACCES;
1173 OPENX_REQ *pSMB = NULL;
1174 OPENX_RSP *pSMBr = NULL;
1175 int bytes_returned;
1176 int name_len;
1177 __u16 count;
1178
1179OldOpenRetry:
1180 rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1181 (void **) &pSMBr);
1182 if (rc)
1183 return rc;
1184
1185 pSMB->AndXCommand = 0xFF; /* none */
1186
1187 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1188 count = 1; /* account for one byte pad to word boundary */
1189 name_len =
1190 cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
1191 fileName, PATH_MAX, nls_codepage, remap);
1192 name_len++; /* trailing null */
1193 name_len *= 2;
1194 } else { /* BB improve check for buffer overruns BB */
1195 count = 0; /* no pad */
1196 name_len = strnlen(fileName, PATH_MAX);
1197 name_len++; /* trailing null */
1198 strncpy(pSMB->fileName, fileName, name_len);
1199 }
1200 if (*pOplock & REQ_OPLOCK)
1201 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1202 else if (*pOplock & REQ_BATCHOPLOCK)
1203 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1204
1205 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1206 pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1207 pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1208 /* set file as system file if special file such
1209 as fifo and server expecting SFU style and
1210 no Unix extensions */
1211
1212 if (create_options & CREATE_OPTION_SPECIAL)
1213 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1214 else /* BB FIXME BB */
1215 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1216
1217 if (create_options & CREATE_OPTION_READONLY)
1218 pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1219
1220 /* BB FIXME BB */
1221/* pSMB->CreateOptions = cpu_to_le32(create_options &
1222 CREATE_OPTIONS_MASK); */
1223 /* BB FIXME END BB */
1224
1225 pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1226 pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1227 count += name_len;
1228 inc_rfc1001_len(pSMB, count);
1229
1230 pSMB->ByteCount = cpu_to_le16(count);
1231 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1232 (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1233 cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
1234 if (rc) {
1235 cifs_dbg(FYI, "Error in Open = %d\n", rc);
1236 } else {
1237 /* BB verify if wct == 15 */
1238
1239/* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1240
1241 *netfid = pSMBr->Fid; /* cifs fid stays in le */
1242 /* Let caller know file was created so we can set the mode. */
1243 /* Do we care about the CreateAction in any other cases? */
1244 /* BB FIXME BB */
1245/* if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1246 *pOplock |= CIFS_CREATE_ACTION; */
1247 /* BB FIXME END */
1248
1249 if (pfile_info) {
1250 pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1251 pfile_info->LastAccessTime = 0; /* BB fixme */
1252 pfile_info->LastWriteTime = 0; /* BB fixme */
1253 pfile_info->ChangeTime = 0; /* BB fixme */
1254 pfile_info->Attributes =
1255 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1256 /* the file_info buf is endian converted by caller */
1257 pfile_info->AllocationSize =
1258 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1259 pfile_info->EndOfFile = pfile_info->AllocationSize;
1260 pfile_info->NumberOfLinks = cpu_to_le32(1);
1261 pfile_info->DeletePending = 0;
1262 }
1263 }
1264
1265 cifs_buf_release(pSMB);
1266 if (rc == -EAGAIN)
1267 goto OldOpenRetry;
1268 return rc;
1269}
1270
1271int
1272CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock,
1273 FILE_ALL_INFO *buf)
1274{
1275 int rc = -EACCES;
1276 OPEN_REQ *req = NULL;
1277 OPEN_RSP *rsp = NULL;
1278 int bytes_returned;
1279 int name_len;
1280 __u16 count;
1281 struct cifs_sb_info *cifs_sb = oparms->cifs_sb;
1282 struct cifs_tcon *tcon = oparms->tcon;
1283 int remap = cifs_remap(cifs_sb);
1284 const struct nls_table *nls = cifs_sb->local_nls;
1285 int create_options = oparms->create_options;
1286 int desired_access = oparms->desired_access;
1287 int disposition = oparms->disposition;
1288 const char *path = oparms->path;
1289
1290openRetry:
1291 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **)&req,
1292 (void **)&rsp);
1293 if (rc)
1294 return rc;
1295
1296 /* no commands go after this */
1297 req->AndXCommand = 0xFF;
1298
1299 if (req->hdr.Flags2 & SMBFLG2_UNICODE) {
1300 /* account for one byte pad to word boundary */
1301 count = 1;
1302 name_len = cifsConvertToUTF16((__le16 *)(req->fileName + 1),
1303 path, PATH_MAX, nls, remap);
1304 /* trailing null */
1305 name_len++;
1306 name_len *= 2;
1307 req->NameLength = cpu_to_le16(name_len);
1308 } else {
1309 /* BB improve check for buffer overruns BB */
1310 /* no pad */
1311 count = 0;
1312 name_len = strnlen(path, PATH_MAX);
1313 /* trailing null */
1314 name_len++;
1315 req->NameLength = cpu_to_le16(name_len);
1316 strncpy(req->fileName, path, name_len);
1317 }
1318
1319 if (*oplock & REQ_OPLOCK)
1320 req->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1321 else if (*oplock & REQ_BATCHOPLOCK)
1322 req->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1323
1324 req->DesiredAccess = cpu_to_le32(desired_access);
1325 req->AllocationSize = 0;
1326
1327 /*
1328 * Set file as system file if special file such as fifo and server
1329 * expecting SFU style and no Unix extensions.
1330 */
1331 if (create_options & CREATE_OPTION_SPECIAL)
1332 req->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1333 else
1334 req->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1335
1336 /*
1337 * XP does not handle ATTR_POSIX_SEMANTICS but it helps speed up case
1338 * sensitive checks for other servers such as Samba.
1339 */
1340 if (tcon->ses->capabilities & CAP_UNIX)
1341 req->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1342
1343 if (create_options & CREATE_OPTION_READONLY)
1344 req->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1345
1346 req->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1347 req->CreateDisposition = cpu_to_le32(disposition);
1348 req->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1349
1350 /* BB Expirement with various impersonation levels and verify */
1351 req->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1352 req->SecurityFlags = SECURITY_CONTEXT_TRACKING|SECURITY_EFFECTIVE_ONLY;
1353
1354 count += name_len;
1355 inc_rfc1001_len(req, count);
1356
1357 req->ByteCount = cpu_to_le16(count);
1358 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *)req,
1359 (struct smb_hdr *)rsp, &bytes_returned, 0);
1360 cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
1361 if (rc) {
1362 cifs_dbg(FYI, "Error in Open = %d\n", rc);
1363 cifs_buf_release(req);
1364 if (rc == -EAGAIN)
1365 goto openRetry;
1366 return rc;
1367 }
1368
1369 /* 1 byte no need to le_to_cpu */
1370 *oplock = rsp->OplockLevel;
1371 /* cifs fid stays in le */
1372 oparms->fid->netfid = rsp->Fid;
1373
1374 /* Let caller know file was created so we can set the mode. */
1375 /* Do we care about the CreateAction in any other cases? */
1376 if (cpu_to_le32(FILE_CREATE) == rsp->CreateAction)
1377 *oplock |= CIFS_CREATE_ACTION;
1378
1379 if (buf) {
1380 /* copy from CreationTime to Attributes */
1381 memcpy((char *)buf, (char *)&rsp->CreationTime, 36);
1382 /* the file_info buf is endian converted by caller */
1383 buf->AllocationSize = rsp->AllocationSize;
1384 buf->EndOfFile = rsp->EndOfFile;
1385 buf->NumberOfLinks = cpu_to_le32(1);
1386 buf->DeletePending = 0;
1387 }
1388
1389 cifs_buf_release(req);
1390 return rc;
1391}
1392
1393/*
1394 * Discard any remaining data in the current SMB. To do this, we borrow the
1395 * current bigbuf.
1396 */
1397static int
1398discard_remaining_data(struct TCP_Server_Info *server)
1399{
1400 unsigned int rfclen = get_rfc1002_length(server->smallbuf);
1401 int remaining = rfclen + 4 - server->total_read;
1402
1403 while (remaining > 0) {
1404 int length;
1405
1406 length = cifs_read_from_socket(server, server->bigbuf,
1407 min_t(unsigned int, remaining,
1408 CIFSMaxBufSize + MAX_HEADER_SIZE(server)));
1409 if (length < 0)
1410 return length;
1411 server->total_read += length;
1412 remaining -= length;
1413 }
1414
1415 return 0;
1416}
1417
1418static int
1419cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1420{
1421 int length;
1422 struct cifs_readdata *rdata = mid->callback_data;
1423
1424 length = discard_remaining_data(server);
1425 dequeue_mid(mid, rdata->result);
1426 return length;
1427}
1428
1429int
1430cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1431{
1432 int length, len;
1433 unsigned int data_offset, data_len;
1434 struct cifs_readdata *rdata = mid->callback_data;
1435 char *buf = server->smallbuf;
1436 unsigned int buflen = get_rfc1002_length(buf) + 4;
1437
1438 cifs_dbg(FYI, "%s: mid=%llu offset=%llu bytes=%u\n",
1439 __func__, mid->mid, rdata->offset, rdata->bytes);
1440
1441 /*
1442 * read the rest of READ_RSP header (sans Data array), or whatever we
1443 * can if there's not enough data. At this point, we've read down to
1444 * the Mid.
1445 */
1446 len = min_t(unsigned int, buflen, server->vals->read_rsp_size) -
1447 HEADER_SIZE(server) + 1;
1448
1449 length = cifs_read_from_socket(server,
1450 buf + HEADER_SIZE(server) - 1, len);
1451 if (length < 0)
1452 return length;
1453 server->total_read += length;
1454
1455 if (server->ops->is_status_pending &&
1456 server->ops->is_status_pending(buf, server, 0)) {
1457 discard_remaining_data(server);
1458 return -1;
1459 }
1460
1461 /* Was the SMB read successful? */
1462 rdata->result = server->ops->map_error(buf, false);
1463 if (rdata->result != 0) {
1464 cifs_dbg(FYI, "%s: server returned error %d\n",
1465 __func__, rdata->result);
1466 return cifs_readv_discard(server, mid);
1467 }
1468
1469 /* Is there enough to get to the rest of the READ_RSP header? */
1470 if (server->total_read < server->vals->read_rsp_size) {
1471 cifs_dbg(FYI, "%s: server returned short header. got=%u expected=%zu\n",
1472 __func__, server->total_read,
1473 server->vals->read_rsp_size);
1474 rdata->result = -EIO;
1475 return cifs_readv_discard(server, mid);
1476 }
1477
1478 data_offset = server->ops->read_data_offset(buf) + 4;
1479 if (data_offset < server->total_read) {
1480 /*
1481 * win2k8 sometimes sends an offset of 0 when the read
1482 * is beyond the EOF. Treat it as if the data starts just after
1483 * the header.
1484 */
1485 cifs_dbg(FYI, "%s: data offset (%u) inside read response header\n",
1486 __func__, data_offset);
1487 data_offset = server->total_read;
1488 } else if (data_offset > MAX_CIFS_SMALL_BUFFER_SIZE) {
1489 /* data_offset is beyond the end of smallbuf */
1490 cifs_dbg(FYI, "%s: data offset (%u) beyond end of smallbuf\n",
1491 __func__, data_offset);
1492 rdata->result = -EIO;
1493 return cifs_readv_discard(server, mid);
1494 }
1495
1496 cifs_dbg(FYI, "%s: total_read=%u data_offset=%u\n",
1497 __func__, server->total_read, data_offset);
1498
1499 len = data_offset - server->total_read;
1500 if (len > 0) {
1501 /* read any junk before data into the rest of smallbuf */
1502 length = cifs_read_from_socket(server,
1503 buf + server->total_read, len);
1504 if (length < 0)
1505 return length;
1506 server->total_read += length;
1507 }
1508
1509 /* set up first iov for signature check */
1510 rdata->iov.iov_base = buf;
1511 rdata->iov.iov_len = server->total_read;
1512 cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n",
1513 rdata->iov.iov_base, rdata->iov.iov_len);
1514
1515 /* how much data is in the response? */
1516 data_len = server->ops->read_data_length(buf);
1517 if (data_offset + data_len > buflen) {
1518 /* data_len is corrupt -- discard frame */
1519 rdata->result = -EIO;
1520 return cifs_readv_discard(server, mid);
1521 }
1522
1523 length = rdata->read_into_pages(server, rdata, data_len);
1524 if (length < 0)
1525 return length;
1526
1527 server->total_read += length;
1528
1529 cifs_dbg(FYI, "total_read=%u buflen=%u remaining=%u\n",
1530 server->total_read, buflen, data_len);
1531
1532 /* discard anything left over */
1533 if (server->total_read < buflen)
1534 return cifs_readv_discard(server, mid);
1535
1536 dequeue_mid(mid, false);
1537 return length;
1538}
1539
1540static void
1541cifs_readv_callback(struct mid_q_entry *mid)
1542{
1543 struct cifs_readdata *rdata = mid->callback_data;
1544 struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1545 struct TCP_Server_Info *server = tcon->ses->server;
1546 struct smb_rqst rqst = { .rq_iov = &rdata->iov,
1547 .rq_nvec = 1,
1548 .rq_pages = rdata->pages,
1549 .rq_npages = rdata->nr_pages,
1550 .rq_pagesz = rdata->pagesz,
1551 .rq_tailsz = rdata->tailsz };
1552
1553 cifs_dbg(FYI, "%s: mid=%llu state=%d result=%d bytes=%u\n",
1554 __func__, mid->mid, mid->mid_state, rdata->result,
1555 rdata->bytes);
1556
1557 switch (mid->mid_state) {
1558 case MID_RESPONSE_RECEIVED:
1559 /* result already set, check signature */
1560 if (server->sign) {
1561 int rc = 0;
1562
1563 rc = cifs_verify_signature(&rqst, server,
1564 mid->sequence_number);
1565 if (rc)
1566 cifs_dbg(VFS, "SMB signature verification returned error = %d\n",
1567 rc);
1568 }
1569 /* FIXME: should this be counted toward the initiating task? */
1570 task_io_account_read(rdata->got_bytes);
1571 cifs_stats_bytes_read(tcon, rdata->got_bytes);
1572 break;
1573 case MID_REQUEST_SUBMITTED:
1574 case MID_RETRY_NEEDED:
1575 rdata->result = -EAGAIN;
1576 if (server->sign && rdata->got_bytes)
1577 /* reset bytes number since we can not check a sign */
1578 rdata->got_bytes = 0;
1579 /* FIXME: should this be counted toward the initiating task? */
1580 task_io_account_read(rdata->got_bytes);
1581 cifs_stats_bytes_read(tcon, rdata->got_bytes);
1582 break;
1583 default:
1584 rdata->result = -EIO;
1585 }
1586
1587 queue_work(cifsiod_wq, &rdata->work);
1588 mutex_lock(&server->srv_mutex);
1589 DeleteMidQEntry(mid);
1590 mutex_unlock(&server->srv_mutex);
1591 add_credits(server, 1, 0);
1592}
1593
1594/* cifs_async_readv - send an async write, and set up mid to handle result */
1595int
1596cifs_async_readv(struct cifs_readdata *rdata)
1597{
1598 int rc;
1599 READ_REQ *smb = NULL;
1600 int wct;
1601 struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1602 struct smb_rqst rqst = { .rq_iov = &rdata->iov,
1603 .rq_nvec = 1 };
1604
1605 cifs_dbg(FYI, "%s: offset=%llu bytes=%u\n",
1606 __func__, rdata->offset, rdata->bytes);
1607
1608 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1609 wct = 12;
1610 else {
1611 wct = 10; /* old style read */
1612 if ((rdata->offset >> 32) > 0) {
1613 /* can not handle this big offset for old */
1614 return -EIO;
1615 }
1616 }
1617
1618 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **)&smb);
1619 if (rc)
1620 return rc;
1621
1622 smb->hdr.Pid = cpu_to_le16((__u16)rdata->pid);
1623 smb->hdr.PidHigh = cpu_to_le16((__u16)(rdata->pid >> 16));
1624
1625 smb->AndXCommand = 0xFF; /* none */
1626 smb->Fid = rdata->cfile->fid.netfid;
1627 smb->OffsetLow = cpu_to_le32(rdata->offset & 0xFFFFFFFF);
1628 if (wct == 12)
1629 smb->OffsetHigh = cpu_to_le32(rdata->offset >> 32);
1630 smb->Remaining = 0;
1631 smb->MaxCount = cpu_to_le16(rdata->bytes & 0xFFFF);
1632 smb->MaxCountHigh = cpu_to_le32(rdata->bytes >> 16);
1633 if (wct == 12)
1634 smb->ByteCount = 0;
1635 else {
1636 /* old style read */
1637 struct smb_com_readx_req *smbr =
1638 (struct smb_com_readx_req *)smb;
1639 smbr->ByteCount = 0;
1640 }
1641
1642 /* 4 for RFC1001 length + 1 for BCC */
1643 rdata->iov.iov_base = smb;
1644 rdata->iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;
1645
1646 kref_get(&rdata->refcount);
1647 rc = cifs_call_async(tcon->ses->server, &rqst, cifs_readv_receive,
1648 cifs_readv_callback, rdata, 0);
1649
1650 if (rc == 0)
1651 cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1652 else
1653 kref_put(&rdata->refcount, cifs_readdata_release);
1654
1655 cifs_small_buf_release(smb);
1656 return rc;
1657}
1658
1659int
1660CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms,
1661 unsigned int *nbytes, char **buf, int *pbuf_type)
1662{
1663 int rc = -EACCES;
1664 READ_REQ *pSMB = NULL;
1665 READ_RSP *pSMBr = NULL;
1666 char *pReadData = NULL;
1667 int wct;
1668 int resp_buf_type = 0;
1669 struct kvec iov[1];
1670 __u32 pid = io_parms->pid;
1671 __u16 netfid = io_parms->netfid;
1672 __u64 offset = io_parms->offset;
1673 struct cifs_tcon *tcon = io_parms->tcon;
1674 unsigned int count = io_parms->length;
1675
1676 cifs_dbg(FYI, "Reading %d bytes on fid %d\n", count, netfid);
1677 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1678 wct = 12;
1679 else {
1680 wct = 10; /* old style read */
1681 if ((offset >> 32) > 0) {
1682 /* can not handle this big offset for old */
1683 return -EIO;
1684 }
1685 }
1686
1687 *nbytes = 0;
1688 rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1689 if (rc)
1690 return rc;
1691
1692 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1693 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1694
1695 /* tcon and ses pointer are checked in smb_init */
1696 if (tcon->ses->server == NULL)
1697 return -ECONNABORTED;
1698
1699 pSMB->AndXCommand = 0xFF; /* none */
1700 pSMB->Fid = netfid;
1701 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1702 if (wct == 12)
1703 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1704
1705 pSMB->Remaining = 0;
1706 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1707 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1708 if (wct == 12)
1709 pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
1710 else {
1711 /* old style read */
1712 struct smb_com_readx_req *pSMBW =
1713 (struct smb_com_readx_req *)pSMB;
1714 pSMBW->ByteCount = 0;
1715 }
1716
1717 iov[0].iov_base = (char *)pSMB;
1718 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
1719 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1720 &resp_buf_type, CIFS_LOG_ERROR);
1721 cifs_stats_inc(&tcon->stats.cifs_stats.num_reads);
1722 pSMBr = (READ_RSP *)iov[0].iov_base;
1723 if (rc) {
1724 cifs_dbg(VFS, "Send error in read = %d\n", rc);
1725 } else {
1726 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1727 data_length = data_length << 16;
1728 data_length += le16_to_cpu(pSMBr->DataLength);
1729 *nbytes = data_length;
1730
1731 /*check that DataLength would not go beyond end of SMB */
1732 if ((data_length > CIFSMaxBufSize)
1733 || (data_length > count)) {
1734 cifs_dbg(FYI, "bad length %d for count %d\n",
1735 data_length, count);
1736 rc = -EIO;
1737 *nbytes = 0;
1738 } else {
1739 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1740 le16_to_cpu(pSMBr->DataOffset);
1741/* if (rc = copy_to_user(buf, pReadData, data_length)) {
1742 cifs_dbg(VFS, "Faulting on read rc = %d\n",rc);
1743 rc = -EFAULT;
1744 }*/ /* can not use copy_to_user when using page cache*/
1745 if (*buf)
1746 memcpy(*buf, pReadData, data_length);
1747 }
1748 }
1749
1750/* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1751 if (*buf) {
1752 free_rsp_buf(resp_buf_type, iov[0].iov_base);
1753 } else if (resp_buf_type != CIFS_NO_BUFFER) {
1754 /* return buffer to caller to free */
1755 *buf = iov[0].iov_base;
1756 if (resp_buf_type == CIFS_SMALL_BUFFER)
1757 *pbuf_type = CIFS_SMALL_BUFFER;
1758 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1759 *pbuf_type = CIFS_LARGE_BUFFER;
1760 } /* else no valid buffer on return - leave as null */
1761
1762 /* Note: On -EAGAIN error only caller can retry on handle based calls
1763 since file handle passed in no longer valid */
1764 return rc;
1765}
1766
1767
1768int
1769CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms,
1770 unsigned int *nbytes, const char *buf)
1771{
1772 int rc = -EACCES;
1773 WRITE_REQ *pSMB = NULL;
1774 WRITE_RSP *pSMBr = NULL;
1775 int bytes_returned, wct;
1776 __u32 bytes_sent;
1777 __u16 byte_count;
1778 __u32 pid = io_parms->pid;
1779 __u16 netfid = io_parms->netfid;
1780 __u64 offset = io_parms->offset;
1781 struct cifs_tcon *tcon = io_parms->tcon;
1782 unsigned int count = io_parms->length;
1783
1784 *nbytes = 0;
1785
1786 /* cifs_dbg(FYI, "write at %lld %d bytes\n", offset, count);*/
1787 if (tcon->ses == NULL)
1788 return -ECONNABORTED;
1789
1790 if (tcon->ses->capabilities & CAP_LARGE_FILES)
1791 wct = 14;
1792 else {
1793 wct = 12;
1794 if ((offset >> 32) > 0) {
1795 /* can not handle big offset for old srv */
1796 return -EIO;
1797 }
1798 }
1799
1800 rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1801 (void **) &pSMBr);
1802 if (rc)
1803 return rc;
1804
1805 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1806 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1807
1808 /* tcon and ses pointer are checked in smb_init */
1809 if (tcon->ses->server == NULL)
1810 return -ECONNABORTED;
1811
1812 pSMB->AndXCommand = 0xFF; /* none */
1813 pSMB->Fid = netfid;
1814 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1815 if (wct == 14)
1816 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1817
1818 pSMB->Reserved = 0xFFFFFFFF;
1819 pSMB->WriteMode = 0;
1820 pSMB->Remaining = 0;
1821
1822 /* Can increase buffer size if buffer is big enough in some cases ie we
1823 can send more if LARGE_WRITE_X capability returned by the server and if
1824 our buffer is big enough or if we convert to iovecs on socket writes
1825 and eliminate the copy to the CIFS buffer */
1826 if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1827 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1828 } else {
1829 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1830 & ~0xFF;
1831 }
1832
1833 if (bytes_sent > count)
1834 bytes_sent = count;
1835 pSMB->DataOffset =
1836 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1837 if (buf)
1838 memcpy(pSMB->Data, buf, bytes_sent);
1839 else if (count != 0) {
1840 /* No buffer */
1841 cifs_buf_release(pSMB);
1842 return -EINVAL;
1843 } /* else setting file size with write of zero bytes */
1844 if (wct == 14)
1845 byte_count = bytes_sent + 1; /* pad */
1846 else /* wct == 12 */
1847 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1848
1849 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1850 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1851 inc_rfc1001_len(pSMB, byte_count);
1852
1853 if (wct == 14)
1854 pSMB->ByteCount = cpu_to_le16(byte_count);
1855 else { /* old style write has byte count 4 bytes earlier
1856 so 4 bytes pad */
1857 struct smb_com_writex_req *pSMBW =
1858 (struct smb_com_writex_req *)pSMB;
1859 pSMBW->ByteCount = cpu_to_le16(byte_count);
1860 }
1861
1862 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1863 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1864 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
1865 if (rc) {
1866 cifs_dbg(FYI, "Send error in write = %d\n", rc);
1867 } else {
1868 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1869 *nbytes = (*nbytes) << 16;
1870 *nbytes += le16_to_cpu(pSMBr->Count);
1871
1872 /*
1873 * Mask off high 16 bits when bytes written as returned by the
1874 * server is greater than bytes requested by the client. Some
1875 * OS/2 servers are known to set incorrect CountHigh values.
1876 */
1877 if (*nbytes > count)
1878 *nbytes &= 0xFFFF;
1879 }
1880
1881 cifs_buf_release(pSMB);
1882
1883 /* Note: On -EAGAIN error only caller can retry on handle based calls
1884 since file handle passed in no longer valid */
1885
1886 return rc;
1887}
1888
1889void
1890cifs_writedata_release(struct kref *refcount)
1891{
1892 struct cifs_writedata *wdata = container_of(refcount,
1893 struct cifs_writedata, refcount);
1894
1895 if (wdata->cfile)
1896 cifsFileInfo_put(wdata->cfile);
1897
1898 kfree(wdata);
1899}
1900
1901/*
1902 * Write failed with a retryable error. Resend the write request. It's also
1903 * possible that the page was redirtied so re-clean the page.
1904 */
1905static void
1906cifs_writev_requeue(struct cifs_writedata *wdata)
1907{
1908 int i, rc = 0;
1909 struct inode *inode = d_inode(wdata->cfile->dentry);
1910 struct TCP_Server_Info *server;
1911 unsigned int rest_len;
1912
1913 server = tlink_tcon(wdata->cfile->tlink)->ses->server;
1914 i = 0;
1915 rest_len = wdata->bytes;
1916 do {
1917 struct cifs_writedata *wdata2;
1918 unsigned int j, nr_pages, wsize, tailsz, cur_len;
1919
1920 wsize = server->ops->wp_retry_size(inode);
1921 if (wsize < rest_len) {
1922 nr_pages = wsize / PAGE_SIZE;
1923 if (!nr_pages) {
1924 rc = -ENOTSUPP;
1925 break;
1926 }
1927 cur_len = nr_pages * PAGE_SIZE;
1928 tailsz = PAGE_SIZE;
1929 } else {
1930 nr_pages = DIV_ROUND_UP(rest_len, PAGE_SIZE);
1931 cur_len = rest_len;
1932 tailsz = rest_len - (nr_pages - 1) * PAGE_SIZE;
1933 }
1934
1935 wdata2 = cifs_writedata_alloc(nr_pages, cifs_writev_complete);
1936 if (!wdata2) {
1937 rc = -ENOMEM;
1938 break;
1939 }
1940
1941 for (j = 0; j < nr_pages; j++) {
1942 wdata2->pages[j] = wdata->pages[i + j];
1943 lock_page(wdata2->pages[j]);
1944 clear_page_dirty_for_io(wdata2->pages[j]);
1945 }
1946
1947 wdata2->sync_mode = wdata->sync_mode;
1948 wdata2->nr_pages = nr_pages;
1949 wdata2->offset = page_offset(wdata2->pages[0]);
1950 wdata2->pagesz = PAGE_SIZE;
1951 wdata2->tailsz = tailsz;
1952 wdata2->bytes = cur_len;
1953
1954 wdata2->cfile = find_writable_file(CIFS_I(inode), false);
1955 if (!wdata2->cfile) {
1956 cifs_dbg(VFS, "No writable handles for inode\n");
1957 rc = -EBADF;
1958 break;
1959 }
1960 wdata2->pid = wdata2->cfile->pid;
1961 rc = server->ops->async_writev(wdata2, cifs_writedata_release);
1962
1963 for (j = 0; j < nr_pages; j++) {
1964 unlock_page(wdata2->pages[j]);
1965 if (rc != 0 && rc != -EAGAIN) {
1966 SetPageError(wdata2->pages[j]);
1967 end_page_writeback(wdata2->pages[j]);
1968 put_page(wdata2->pages[j]);
1969 }
1970 }
1971
1972 if (rc) {
1973 kref_put(&wdata2->refcount, cifs_writedata_release);
1974 if (rc == -EAGAIN)
1975 continue;
1976 break;
1977 }
1978
1979 rest_len -= cur_len;
1980 i += nr_pages;
1981 } while (i < wdata->nr_pages);
1982
1983 mapping_set_error(inode->i_mapping, rc);
1984 kref_put(&wdata->refcount, cifs_writedata_release);
1985}
1986
1987void
1988cifs_writev_complete(struct work_struct *work)
1989{
1990 struct cifs_writedata *wdata = container_of(work,
1991 struct cifs_writedata, work);
1992 struct inode *inode = d_inode(wdata->cfile->dentry);
1993 int i = 0;
1994
1995 if (wdata->result == 0) {
1996 spin_lock(&inode->i_lock);
1997 cifs_update_eof(CIFS_I(inode), wdata->offset, wdata->bytes);
1998 spin_unlock(&inode->i_lock);
1999 cifs_stats_bytes_written(tlink_tcon(wdata->cfile->tlink),
2000 wdata->bytes);
2001 } else if (wdata->sync_mode == WB_SYNC_ALL && wdata->result == -EAGAIN)
2002 return cifs_writev_requeue(wdata);
2003
2004 for (i = 0; i < wdata->nr_pages; i++) {
2005 struct page *page = wdata->pages[i];
2006 if (wdata->result == -EAGAIN)
2007 __set_page_dirty_nobuffers(page);
2008 else if (wdata->result < 0)
2009 SetPageError(page);
2010 end_page_writeback(page);
2011 put_page(page);
2012 }
2013 if (wdata->result != -EAGAIN)
2014 mapping_set_error(inode->i_mapping, wdata->result);
2015 kref_put(&wdata->refcount, cifs_writedata_release);
2016}
2017
2018struct cifs_writedata *
2019cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete)
2020{
2021 struct cifs_writedata *wdata;
2022
2023 /* writedata + number of page pointers */
2024 wdata = kzalloc(sizeof(*wdata) +
2025 sizeof(struct page *) * nr_pages, GFP_NOFS);
2026 if (wdata != NULL) {
2027 kref_init(&wdata->refcount);
2028 INIT_LIST_HEAD(&wdata->list);
2029 init_completion(&wdata->done);
2030 INIT_WORK(&wdata->work, complete);
2031 }
2032 return wdata;
2033}
2034
2035/*
2036 * Check the mid_state and signature on received buffer (if any), and queue the
2037 * workqueue completion task.
2038 */
2039static void
2040cifs_writev_callback(struct mid_q_entry *mid)
2041{
2042 struct cifs_writedata *wdata = mid->callback_data;
2043 struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2044 struct TCP_Server_Info *server = tcon->ses->server;
2045 unsigned int written;
2046 WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
2047
2048 switch (mid->mid_state) {
2049 case MID_RESPONSE_RECEIVED:
2050 wdata->result = cifs_check_receive(mid, tcon->ses->server, 0);
2051 if (wdata->result != 0)
2052 break;
2053
2054 written = le16_to_cpu(smb->CountHigh);
2055 written <<= 16;
2056 written += le16_to_cpu(smb->Count);
2057 /*
2058 * Mask off high 16 bits when bytes written as returned
2059 * by the server is greater than bytes requested by the
2060 * client. OS/2 servers are known to set incorrect
2061 * CountHigh values.
2062 */
2063 if (written > wdata->bytes)
2064 written &= 0xFFFF;
2065
2066 if (written < wdata->bytes)
2067 wdata->result = -ENOSPC;
2068 else
2069 wdata->bytes = written;
2070 break;
2071 case MID_REQUEST_SUBMITTED:
2072 case MID_RETRY_NEEDED:
2073 wdata->result = -EAGAIN;
2074 break;
2075 default:
2076 wdata->result = -EIO;
2077 break;
2078 }
2079
2080 queue_work(cifsiod_wq, &wdata->work);
2081 mutex_lock(&server->srv_mutex);
2082 DeleteMidQEntry(mid);
2083 mutex_unlock(&server->srv_mutex);
2084 add_credits(tcon->ses->server, 1, 0);
2085}
2086
2087/* cifs_async_writev - send an async write, and set up mid to handle result */
2088int
2089cifs_async_writev(struct cifs_writedata *wdata,
2090 void (*release)(struct kref *kref))
2091{
2092 int rc = -EACCES;
2093 WRITE_REQ *smb = NULL;
2094 int wct;
2095 struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2096 struct kvec iov;
2097 struct smb_rqst rqst = { };
2098
2099 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2100 wct = 14;
2101 } else {
2102 wct = 12;
2103 if (wdata->offset >> 32 > 0) {
2104 /* can not handle big offset for old srv */
2105 return -EIO;
2106 }
2107 }
2108
2109 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **)&smb);
2110 if (rc)
2111 goto async_writev_out;
2112
2113 smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid);
2114 smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16));
2115
2116 smb->AndXCommand = 0xFF; /* none */
2117 smb->Fid = wdata->cfile->fid.netfid;
2118 smb->OffsetLow = cpu_to_le32(wdata->offset & 0xFFFFFFFF);
2119 if (wct == 14)
2120 smb->OffsetHigh = cpu_to_le32(wdata->offset >> 32);
2121 smb->Reserved = 0xFFFFFFFF;
2122 smb->WriteMode = 0;
2123 smb->Remaining = 0;
2124
2125 smb->DataOffset =
2126 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2127
2128 /* 4 for RFC1001 length + 1 for BCC */
2129 iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1;
2130 iov.iov_base = smb;
2131
2132 rqst.rq_iov = &iov;
2133 rqst.rq_nvec = 1;
2134 rqst.rq_pages = wdata->pages;
2135 rqst.rq_npages = wdata->nr_pages;
2136 rqst.rq_pagesz = wdata->pagesz;
2137 rqst.rq_tailsz = wdata->tailsz;
2138
2139 cifs_dbg(FYI, "async write at %llu %u bytes\n",
2140 wdata->offset, wdata->bytes);
2141
2142 smb->DataLengthLow = cpu_to_le16(wdata->bytes & 0xFFFF);
2143 smb->DataLengthHigh = cpu_to_le16(wdata->bytes >> 16);
2144
2145 if (wct == 14) {
2146 inc_rfc1001_len(&smb->hdr, wdata->bytes + 1);
2147 put_bcc(wdata->bytes + 1, &smb->hdr);
2148 } else {
2149 /* wct == 12 */
2150 struct smb_com_writex_req *smbw =
2151 (struct smb_com_writex_req *)smb;
2152 inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5);
2153 put_bcc(wdata->bytes + 5, &smbw->hdr);
2154 iov.iov_len += 4; /* pad bigger by four bytes */
2155 }
2156
2157 kref_get(&wdata->refcount);
2158 rc = cifs_call_async(tcon->ses->server, &rqst, NULL,
2159 cifs_writev_callback, wdata, 0);
2160
2161 if (rc == 0)
2162 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
2163 else
2164 kref_put(&wdata->refcount, release);
2165
2166async_writev_out:
2167 cifs_small_buf_release(smb);
2168 return rc;
2169}
2170
2171int
2172CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms,
2173 unsigned int *nbytes, struct kvec *iov, int n_vec)
2174{
2175 int rc = -EACCES;
2176 WRITE_REQ *pSMB = NULL;
2177 int wct;
2178 int smb_hdr_len;
2179 int resp_buf_type = 0;
2180 __u32 pid = io_parms->pid;
2181 __u16 netfid = io_parms->netfid;
2182 __u64 offset = io_parms->offset;
2183 struct cifs_tcon *tcon = io_parms->tcon;
2184 unsigned int count = io_parms->length;
2185
2186 *nbytes = 0;
2187
2188 cifs_dbg(FYI, "write2 at %lld %d bytes\n", (long long)offset, count);
2189
2190 if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2191 wct = 14;
2192 } else {
2193 wct = 12;
2194 if ((offset >> 32) > 0) {
2195 /* can not handle big offset for old srv */
2196 return -EIO;
2197 }
2198 }
2199 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
2200 if (rc)
2201 return rc;
2202
2203 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
2204 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
2205
2206 /* tcon and ses pointer are checked in smb_init */
2207 if (tcon->ses->server == NULL)
2208 return -ECONNABORTED;
2209
2210 pSMB->AndXCommand = 0xFF; /* none */
2211 pSMB->Fid = netfid;
2212 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
2213 if (wct == 14)
2214 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
2215 pSMB->Reserved = 0xFFFFFFFF;
2216 pSMB->WriteMode = 0;
2217 pSMB->Remaining = 0;
2218
2219 pSMB->DataOffset =
2220 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2221
2222 pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
2223 pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
2224 /* header + 1 byte pad */
2225 smb_hdr_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 1;
2226 if (wct == 14)
2227 inc_rfc1001_len(pSMB, count + 1);
2228 else /* wct == 12 */
2229 inc_rfc1001_len(pSMB, count + 5); /* smb data starts later */
2230 if (wct == 14)
2231 pSMB->ByteCount = cpu_to_le16(count + 1);
2232 else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
2233 struct smb_com_writex_req *pSMBW =
2234 (struct smb_com_writex_req *)pSMB;
2235 pSMBW->ByteCount = cpu_to_le16(count + 5);
2236 }
2237 iov[0].iov_base = pSMB;
2238 if (wct == 14)
2239 iov[0].iov_len = smb_hdr_len + 4;
2240 else /* wct == 12 pad bigger by four bytes */
2241 iov[0].iov_len = smb_hdr_len + 8;
2242
2243
2244 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type, 0);
2245 cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
2246 if (rc) {
2247 cifs_dbg(FYI, "Send error Write2 = %d\n", rc);
2248 } else if (resp_buf_type == 0) {
2249 /* presumably this can not happen, but best to be safe */
2250 rc = -EIO;
2251 } else {
2252 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
2253 *nbytes = le16_to_cpu(pSMBr->CountHigh);
2254 *nbytes = (*nbytes) << 16;
2255 *nbytes += le16_to_cpu(pSMBr->Count);
2256
2257 /*
2258 * Mask off high 16 bits when bytes written as returned by the
2259 * server is greater than bytes requested by the client. OS/2
2260 * servers are known to set incorrect CountHigh values.
2261 */
2262 if (*nbytes > count)
2263 *nbytes &= 0xFFFF;
2264 }
2265
2266/* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
2267 free_rsp_buf(resp_buf_type, iov[0].iov_base);
2268
2269 /* Note: On -EAGAIN error only caller can retry on handle based calls
2270 since file handle passed in no longer valid */
2271
2272 return rc;
2273}
2274
2275int cifs_lockv(const unsigned int xid, struct cifs_tcon *tcon,
2276 const __u16 netfid, const __u8 lock_type, const __u32 num_unlock,
2277 const __u32 num_lock, LOCKING_ANDX_RANGE *buf)
2278{
2279 int rc = 0;
2280 LOCK_REQ *pSMB = NULL;
2281 struct kvec iov[2];
2282 int resp_buf_type;
2283 __u16 count;
2284
2285 cifs_dbg(FYI, "cifs_lockv num lock %d num unlock %d\n",
2286 num_lock, num_unlock);
2287
2288 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2289 if (rc)
2290 return rc;
2291
2292 pSMB->Timeout = 0;
2293 pSMB->NumberOfLocks = cpu_to_le16(num_lock);
2294 pSMB->NumberOfUnlocks = cpu_to_le16(num_unlock);
2295 pSMB->LockType = lock_type;
2296 pSMB->AndXCommand = 0xFF; /* none */
2297 pSMB->Fid = netfid; /* netfid stays le */
2298
2299 count = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2300 inc_rfc1001_len(pSMB, count);
2301 pSMB->ByteCount = cpu_to_le16(count);
2302
2303 iov[0].iov_base = (char *)pSMB;
2304 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4 -
2305 (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2306 iov[1].iov_base = (char *)buf;
2307 iov[1].iov_len = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2308
2309 cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
2310 rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type, CIFS_NO_RESP);
2311 if (rc)
2312 cifs_dbg(FYI, "Send error in cifs_lockv = %d\n", rc);
2313
2314 return rc;
2315}
2316
2317int
2318CIFSSMBLock(const unsigned int xid, struct cifs_tcon *tcon,
2319 const __u16 smb_file_id, const __u32 netpid, const __u64 len,
2320 const __u64 offset, const __u32 numUnlock,
2321 const __u32 numLock, const __u8 lockType,
2322 const bool waitFlag, const __u8 oplock_level)
2323{
2324 int rc = 0;
2325 LOCK_REQ *pSMB = NULL;
2326/* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
2327 int bytes_returned;
2328 int flags = 0;
2329 __u16 count;
2330
2331 cifs_dbg(FYI, "CIFSSMBLock timeout %d numLock %d\n",
2332 (int)waitFlag, numLock);
2333 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2334
2335 if (rc)
2336 return rc;
2337
2338 if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
2339 /* no response expected */
2340 flags = CIFS_ASYNC_OP | CIFS_OBREAK_OP;
2341 pSMB->Timeout = 0;
2342 } else if (waitFlag) {
2343 flags = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2344 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
2345 } else {
2346 pSMB->Timeout = 0;
2347 }
2348
2349 pSMB->NumberOfLocks = cpu_to_le16(numLock);
2350 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
2351 pSMB->LockType = lockType;
2352 pSMB->OplockLevel = oplock_level;
2353 pSMB->AndXCommand = 0xFF; /* none */
2354 pSMB->Fid = smb_file_id; /* netfid stays le */
2355
2356 if ((numLock != 0) || (numUnlock != 0)) {
2357 pSMB->Locks[0].Pid = cpu_to_le16(netpid);
2358 /* BB where to store pid high? */
2359 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
2360 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
2361 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
2362 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
2363 count = sizeof(LOCKING_ANDX_RANGE);
2364 } else {
2365 /* oplock break */
2366 count = 0;
2367 }
2368 inc_rfc1001_len(pSMB, count);
2369 pSMB->ByteCount = cpu_to_le16(count);
2370
2371 if (waitFlag) {
2372 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2373 (struct smb_hdr *) pSMB, &bytes_returned);
2374 cifs_small_buf_release(pSMB);
2375 } else {
2376 rc = SendReceiveNoRsp(xid, tcon->ses, (char *)pSMB, flags);
2377 /* SMB buffer freed by function above */
2378 }
2379 cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
2380 if (rc)
2381 cifs_dbg(FYI, "Send error in Lock = %d\n", rc);
2382
2383 /* Note: On -EAGAIN error only caller can retry on handle based calls
2384 since file handle passed in no longer valid */
2385 return rc;
2386}
2387
2388int
2389CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon,
2390 const __u16 smb_file_id, const __u32 netpid,
2391 const loff_t start_offset, const __u64 len,
2392 struct file_lock *pLockData, const __u16 lock_type,
2393 const bool waitFlag)
2394{
2395 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2396 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2397 struct cifs_posix_lock *parm_data;
2398 int rc = 0;
2399 int timeout = 0;
2400 int bytes_returned = 0;
2401 int resp_buf_type = 0;
2402 __u16 params, param_offset, offset, byte_count, count;
2403 struct kvec iov[1];
2404
2405 cifs_dbg(FYI, "Posix Lock\n");
2406
2407 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
2408
2409 if (rc)
2410 return rc;
2411
2412 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
2413
2414 params = 6;
2415 pSMB->MaxSetupCount = 0;
2416 pSMB->Reserved = 0;
2417 pSMB->Flags = 0;
2418 pSMB->Reserved2 = 0;
2419 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2420 offset = param_offset + params;
2421
2422 count = sizeof(struct cifs_posix_lock);
2423 pSMB->MaxParameterCount = cpu_to_le16(2);
2424 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2425 pSMB->SetupCount = 1;
2426 pSMB->Reserved3 = 0;
2427 if (pLockData)
2428 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2429 else
2430 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2431 byte_count = 3 /* pad */ + params + count;
2432 pSMB->DataCount = cpu_to_le16(count);
2433 pSMB->ParameterCount = cpu_to_le16(params);
2434 pSMB->TotalDataCount = pSMB->DataCount;
2435 pSMB->TotalParameterCount = pSMB->ParameterCount;
2436 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2437 parm_data = (struct cifs_posix_lock *)
2438 (((char *) &pSMB->hdr.Protocol) + offset);
2439
2440 parm_data->lock_type = cpu_to_le16(lock_type);
2441 if (waitFlag) {
2442 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2443 parm_data->lock_flags = cpu_to_le16(1);
2444 pSMB->Timeout = cpu_to_le32(-1);
2445 } else
2446 pSMB->Timeout = 0;
2447
2448 parm_data->pid = cpu_to_le32(netpid);
2449 parm_data->start = cpu_to_le64(start_offset);
2450 parm_data->length = cpu_to_le64(len); /* normalize negative numbers */
2451
2452 pSMB->DataOffset = cpu_to_le16(offset);
2453 pSMB->Fid = smb_file_id;
2454 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
2455 pSMB->Reserved4 = 0;
2456 inc_rfc1001_len(pSMB, byte_count);
2457 pSMB->ByteCount = cpu_to_le16(byte_count);
2458 if (waitFlag) {
2459 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2460 (struct smb_hdr *) pSMBr, &bytes_returned);
2461 } else {
2462 iov[0].iov_base = (char *)pSMB;
2463 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
2464 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
2465 &resp_buf_type, timeout);
2466 pSMB = NULL; /* request buf already freed by SendReceive2. Do
2467 not try to free it twice below on exit */
2468 pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
2469 }
2470
2471 if (rc) {
2472 cifs_dbg(FYI, "Send error in Posix Lock = %d\n", rc);
2473 } else if (pLockData) {
2474 /* lock structure can be returned on get */
2475 __u16 data_offset;
2476 __u16 data_count;
2477 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2478
2479 if (rc || get_bcc(&pSMBr->hdr) < sizeof(*parm_data)) {
2480 rc = -EIO; /* bad smb */
2481 goto plk_err_exit;
2482 }
2483 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2484 data_count = le16_to_cpu(pSMBr->t2.DataCount);
2485 if (data_count < sizeof(struct cifs_posix_lock)) {
2486 rc = -EIO;
2487 goto plk_err_exit;
2488 }
2489 parm_data = (struct cifs_posix_lock *)
2490 ((char *)&pSMBr->hdr.Protocol + data_offset);
2491 if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
2492 pLockData->fl_type = F_UNLCK;
2493 else {
2494 if (parm_data->lock_type ==
2495 cpu_to_le16(CIFS_RDLCK))
2496 pLockData->fl_type = F_RDLCK;
2497 else if (parm_data->lock_type ==
2498 cpu_to_le16(CIFS_WRLCK))
2499 pLockData->fl_type = F_WRLCK;
2500
2501 pLockData->fl_start = le64_to_cpu(parm_data->start);
2502 pLockData->fl_end = pLockData->fl_start +
2503 le64_to_cpu(parm_data->length) - 1;
2504 pLockData->fl_pid = le32_to_cpu(parm_data->pid);
2505 }
2506 }
2507
2508plk_err_exit:
2509 if (pSMB)
2510 cifs_small_buf_release(pSMB);
2511
2512 free_rsp_buf(resp_buf_type, iov[0].iov_base);
2513
2514 /* Note: On -EAGAIN error only caller can retry on handle based calls
2515 since file handle passed in no longer valid */
2516
2517 return rc;
2518}
2519
2520
2521int
2522CIFSSMBClose(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2523{
2524 int rc = 0;
2525 CLOSE_REQ *pSMB = NULL;
2526 cifs_dbg(FYI, "In CIFSSMBClose\n");
2527
2528/* do not retry on dead session on close */
2529 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
2530 if (rc == -EAGAIN)
2531 return 0;
2532 if (rc)
2533 return rc;
2534
2535 pSMB->FileID = (__u16) smb_file_id;
2536 pSMB->LastWriteTime = 0xFFFFFFFF;
2537 pSMB->ByteCount = 0;
2538 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2539 cifs_stats_inc(&tcon->stats.cifs_stats.num_closes);
2540 if (rc) {
2541 if (rc != -EINTR) {
2542 /* EINTR is expected when user ctl-c to kill app */
2543 cifs_dbg(VFS, "Send error in Close = %d\n", rc);
2544 }
2545 }
2546
2547 /* Since session is dead, file will be closed on server already */
2548 if (rc == -EAGAIN)
2549 rc = 0;
2550
2551 return rc;
2552}
2553
2554int
2555CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
2556{
2557 int rc = 0;
2558 FLUSH_REQ *pSMB = NULL;
2559 cifs_dbg(FYI, "In CIFSSMBFlush\n");
2560
2561 rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
2562 if (rc)
2563 return rc;
2564
2565 pSMB->FileID = (__u16) smb_file_id;
2566 pSMB->ByteCount = 0;
2567 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2568 cifs_stats_inc(&tcon->stats.cifs_stats.num_flushes);
2569 if (rc)
2570 cifs_dbg(VFS, "Send error in Flush = %d\n", rc);
2571
2572 return rc;
2573}
2574
2575int
2576CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
2577 const char *from_name, const char *to_name,
2578 struct cifs_sb_info *cifs_sb)
2579{
2580 int rc = 0;
2581 RENAME_REQ *pSMB = NULL;
2582 RENAME_RSP *pSMBr = NULL;
2583 int bytes_returned;
2584 int name_len, name_len2;
2585 __u16 count;
2586 int remap = cifs_remap(cifs_sb);
2587
2588 cifs_dbg(FYI, "In CIFSSMBRename\n");
2589renameRetry:
2590 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
2591 (void **) &pSMBr);
2592 if (rc)
2593 return rc;
2594
2595 pSMB->BufferFormat = 0x04;
2596 pSMB->SearchAttributes =
2597 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2598 ATTR_DIRECTORY);
2599
2600 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2601 name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2602 from_name, PATH_MAX,
2603 cifs_sb->local_nls, remap);
2604 name_len++; /* trailing null */
2605 name_len *= 2;
2606 pSMB->OldFileName[name_len] = 0x04; /* pad */
2607 /* protocol requires ASCII signature byte on Unicode string */
2608 pSMB->OldFileName[name_len + 1] = 0x00;
2609 name_len2 =
2610 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2611 to_name, PATH_MAX, cifs_sb->local_nls,
2612 remap);
2613 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2614 name_len2 *= 2; /* convert to bytes */
2615 } else { /* BB improve the check for buffer overruns BB */
2616 name_len = strnlen(from_name, PATH_MAX);
2617 name_len++; /* trailing null */
2618 strncpy(pSMB->OldFileName, from_name, name_len);
2619 name_len2 = strnlen(to_name, PATH_MAX);
2620 name_len2++; /* trailing null */
2621 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2622 strncpy(&pSMB->OldFileName[name_len + 1], to_name, name_len2);
2623 name_len2++; /* trailing null */
2624 name_len2++; /* signature byte */
2625 }
2626
2627 count = 1 /* 1st signature byte */ + name_len + name_len2;
2628 inc_rfc1001_len(pSMB, count);
2629 pSMB->ByteCount = cpu_to_le16(count);
2630
2631 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2632 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2633 cifs_stats_inc(&tcon->stats.cifs_stats.num_renames);
2634 if (rc)
2635 cifs_dbg(FYI, "Send error in rename = %d\n", rc);
2636
2637 cifs_buf_release(pSMB);
2638
2639 if (rc == -EAGAIN)
2640 goto renameRetry;
2641
2642 return rc;
2643}
2644
2645int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *pTcon,
2646 int netfid, const char *target_name,
2647 const struct nls_table *nls_codepage, int remap)
2648{
2649 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2650 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2651 struct set_file_rename *rename_info;
2652 char *data_offset;
2653 char dummy_string[30];
2654 int rc = 0;
2655 int bytes_returned = 0;
2656 int len_of_str;
2657 __u16 params, param_offset, offset, count, byte_count;
2658
2659 cifs_dbg(FYI, "Rename to File by handle\n");
2660 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2661 (void **) &pSMBr);
2662 if (rc)
2663 return rc;
2664
2665 params = 6;
2666 pSMB->MaxSetupCount = 0;
2667 pSMB->Reserved = 0;
2668 pSMB->Flags = 0;
2669 pSMB->Timeout = 0;
2670 pSMB->Reserved2 = 0;
2671 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2672 offset = param_offset + params;
2673
2674 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2675 rename_info = (struct set_file_rename *) data_offset;
2676 pSMB->MaxParameterCount = cpu_to_le16(2);
2677 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2678 pSMB->SetupCount = 1;
2679 pSMB->Reserved3 = 0;
2680 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2681 byte_count = 3 /* pad */ + params;
2682 pSMB->ParameterCount = cpu_to_le16(params);
2683 pSMB->TotalParameterCount = pSMB->ParameterCount;
2684 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2685 pSMB->DataOffset = cpu_to_le16(offset);
2686 /* construct random name ".cifs_tmp<inodenum><mid>" */
2687 rename_info->overwrite = cpu_to_le32(1);
2688 rename_info->root_fid = 0;
2689 /* unicode only call */
2690 if (target_name == NULL) {
2691 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2692 len_of_str =
2693 cifsConvertToUTF16((__le16 *)rename_info->target_name,
2694 dummy_string, 24, nls_codepage, remap);
2695 } else {
2696 len_of_str =
2697 cifsConvertToUTF16((__le16 *)rename_info->target_name,
2698 target_name, PATH_MAX, nls_codepage,
2699 remap);
2700 }
2701 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2702 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2703 byte_count += count;
2704 pSMB->DataCount = cpu_to_le16(count);
2705 pSMB->TotalDataCount = pSMB->DataCount;
2706 pSMB->Fid = netfid;
2707 pSMB->InformationLevel =
2708 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2709 pSMB->Reserved4 = 0;
2710 inc_rfc1001_len(pSMB, byte_count);
2711 pSMB->ByteCount = cpu_to_le16(byte_count);
2712 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2713 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2714 cifs_stats_inc(&pTcon->stats.cifs_stats.num_t2renames);
2715 if (rc)
2716 cifs_dbg(FYI, "Send error in Rename (by file handle) = %d\n",
2717 rc);
2718
2719 cifs_buf_release(pSMB);
2720
2721 /* Note: On -EAGAIN error only caller can retry on handle based calls
2722 since file handle passed in no longer valid */
2723
2724 return rc;
2725}
2726
2727int
2728CIFSSMBCopy(const unsigned int xid, struct cifs_tcon *tcon,
2729 const char *fromName, const __u16 target_tid, const char *toName,
2730 const int flags, const struct nls_table *nls_codepage, int remap)
2731{
2732 int rc = 0;
2733 COPY_REQ *pSMB = NULL;
2734 COPY_RSP *pSMBr = NULL;
2735 int bytes_returned;
2736 int name_len, name_len2;
2737 __u16 count;
2738
2739 cifs_dbg(FYI, "In CIFSSMBCopy\n");
2740copyRetry:
2741 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2742 (void **) &pSMBr);
2743 if (rc)
2744 return rc;
2745
2746 pSMB->BufferFormat = 0x04;
2747 pSMB->Tid2 = target_tid;
2748
2749 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2750
2751 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2752 name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2753 fromName, PATH_MAX, nls_codepage,
2754 remap);
2755 name_len++; /* trailing null */
2756 name_len *= 2;
2757 pSMB->OldFileName[name_len] = 0x04; /* pad */
2758 /* protocol requires ASCII signature byte on Unicode string */
2759 pSMB->OldFileName[name_len + 1] = 0x00;
2760 name_len2 =
2761 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2762 toName, PATH_MAX, nls_codepage, remap);
2763 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2764 name_len2 *= 2; /* convert to bytes */
2765 } else { /* BB improve the check for buffer overruns BB */
2766 name_len = strnlen(fromName, PATH_MAX);
2767 name_len++; /* trailing null */
2768 strncpy(pSMB->OldFileName, fromName, name_len);
2769 name_len2 = strnlen(toName, PATH_MAX);
2770 name_len2++; /* trailing null */
2771 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2772 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2773 name_len2++; /* trailing null */
2774 name_len2++; /* signature byte */
2775 }
2776
2777 count = 1 /* 1st signature byte */ + name_len + name_len2;
2778 inc_rfc1001_len(pSMB, count);
2779 pSMB->ByteCount = cpu_to_le16(count);
2780
2781 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2782 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2783 if (rc) {
2784 cifs_dbg(FYI, "Send error in copy = %d with %d files copied\n",
2785 rc, le16_to_cpu(pSMBr->CopyCount));
2786 }
2787 cifs_buf_release(pSMB);
2788
2789 if (rc == -EAGAIN)
2790 goto copyRetry;
2791
2792 return rc;
2793}
2794
2795int
2796CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon,
2797 const char *fromName, const char *toName,
2798 const struct nls_table *nls_codepage, int remap)
2799{
2800 TRANSACTION2_SPI_REQ *pSMB = NULL;
2801 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2802 char *data_offset;
2803 int name_len;
2804 int name_len_target;
2805 int rc = 0;
2806 int bytes_returned = 0;
2807 __u16 params, param_offset, offset, byte_count;
2808
2809 cifs_dbg(FYI, "In Symlink Unix style\n");
2810createSymLinkRetry:
2811 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2812 (void **) &pSMBr);
2813 if (rc)
2814 return rc;
2815
2816 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2817 name_len =
2818 cifsConvertToUTF16((__le16 *) pSMB->FileName, fromName,
2819 /* find define for this maxpathcomponent */
2820 PATH_MAX, nls_codepage, remap);
2821 name_len++; /* trailing null */
2822 name_len *= 2;
2823
2824 } else { /* BB improve the check for buffer overruns BB */
2825 name_len = strnlen(fromName, PATH_MAX);
2826 name_len++; /* trailing null */
2827 strncpy(pSMB->FileName, fromName, name_len);
2828 }
2829 params = 6 + name_len;
2830 pSMB->MaxSetupCount = 0;
2831 pSMB->Reserved = 0;
2832 pSMB->Flags = 0;
2833 pSMB->Timeout = 0;
2834 pSMB->Reserved2 = 0;
2835 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2836 InformationLevel) - 4;
2837 offset = param_offset + params;
2838
2839 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2840 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2841 name_len_target =
2842 cifsConvertToUTF16((__le16 *) data_offset, toName,
2843 /* find define for this maxpathcomponent */
2844 PATH_MAX, nls_codepage, remap);
2845 name_len_target++; /* trailing null */
2846 name_len_target *= 2;
2847 } else { /* BB improve the check for buffer overruns BB */
2848 name_len_target = strnlen(toName, PATH_MAX);
2849 name_len_target++; /* trailing null */
2850 strncpy(data_offset, toName, name_len_target);
2851 }
2852
2853 pSMB->MaxParameterCount = cpu_to_le16(2);
2854 /* BB find exact max on data count below from sess */
2855 pSMB->MaxDataCount = cpu_to_le16(1000);
2856 pSMB->SetupCount = 1;
2857 pSMB->Reserved3 = 0;
2858 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2859 byte_count = 3 /* pad */ + params + name_len_target;
2860 pSMB->DataCount = cpu_to_le16(name_len_target);
2861 pSMB->ParameterCount = cpu_to_le16(params);
2862 pSMB->TotalDataCount = pSMB->DataCount;
2863 pSMB->TotalParameterCount = pSMB->ParameterCount;
2864 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2865 pSMB->DataOffset = cpu_to_le16(offset);
2866 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2867 pSMB->Reserved4 = 0;
2868 inc_rfc1001_len(pSMB, byte_count);
2869 pSMB->ByteCount = cpu_to_le16(byte_count);
2870 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2871 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2872 cifs_stats_inc(&tcon->stats.cifs_stats.num_symlinks);
2873 if (rc)
2874 cifs_dbg(FYI, "Send error in SetPathInfo create symlink = %d\n",
2875 rc);
2876
2877 cifs_buf_release(pSMB);
2878
2879 if (rc == -EAGAIN)
2880 goto createSymLinkRetry;
2881
2882 return rc;
2883}
2884
2885int
2886CIFSUnixCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2887 const char *fromName, const char *toName,
2888 const struct nls_table *nls_codepage, int remap)
2889{
2890 TRANSACTION2_SPI_REQ *pSMB = NULL;
2891 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2892 char *data_offset;
2893 int name_len;
2894 int name_len_target;
2895 int rc = 0;
2896 int bytes_returned = 0;
2897 __u16 params, param_offset, offset, byte_count;
2898
2899 cifs_dbg(FYI, "In Create Hard link Unix style\n");
2900createHardLinkRetry:
2901 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2902 (void **) &pSMBr);
2903 if (rc)
2904 return rc;
2905
2906 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2907 name_len = cifsConvertToUTF16((__le16 *) pSMB->FileName, toName,
2908 PATH_MAX, nls_codepage, remap);
2909 name_len++; /* trailing null */
2910 name_len *= 2;
2911
2912 } else { /* BB improve the check for buffer overruns BB */
2913 name_len = strnlen(toName, PATH_MAX);
2914 name_len++; /* trailing null */
2915 strncpy(pSMB->FileName, toName, name_len);
2916 }
2917 params = 6 + name_len;
2918 pSMB->MaxSetupCount = 0;
2919 pSMB->Reserved = 0;
2920 pSMB->Flags = 0;
2921 pSMB->Timeout = 0;
2922 pSMB->Reserved2 = 0;
2923 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2924 InformationLevel) - 4;
2925 offset = param_offset + params;
2926
2927 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2928 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2929 name_len_target =
2930 cifsConvertToUTF16((__le16 *) data_offset, fromName,
2931 PATH_MAX, nls_codepage, remap);
2932 name_len_target++; /* trailing null */
2933 name_len_target *= 2;
2934 } else { /* BB improve the check for buffer overruns BB */
2935 name_len_target = strnlen(fromName, PATH_MAX);
2936 name_len_target++; /* trailing null */
2937 strncpy(data_offset, fromName, name_len_target);
2938 }
2939
2940 pSMB->MaxParameterCount = cpu_to_le16(2);
2941 /* BB find exact max on data count below from sess*/
2942 pSMB->MaxDataCount = cpu_to_le16(1000);
2943 pSMB->SetupCount = 1;
2944 pSMB->Reserved3 = 0;
2945 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2946 byte_count = 3 /* pad */ + params + name_len_target;
2947 pSMB->ParameterCount = cpu_to_le16(params);
2948 pSMB->TotalParameterCount = pSMB->ParameterCount;
2949 pSMB->DataCount = cpu_to_le16(name_len_target);
2950 pSMB->TotalDataCount = pSMB->DataCount;
2951 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2952 pSMB->DataOffset = cpu_to_le16(offset);
2953 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2954 pSMB->Reserved4 = 0;
2955 inc_rfc1001_len(pSMB, byte_count);
2956 pSMB->ByteCount = cpu_to_le16(byte_count);
2957 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2958 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2959 cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
2960 if (rc)
2961 cifs_dbg(FYI, "Send error in SetPathInfo (hard link) = %d\n",
2962 rc);
2963
2964 cifs_buf_release(pSMB);
2965 if (rc == -EAGAIN)
2966 goto createHardLinkRetry;
2967
2968 return rc;
2969}
2970
2971int
2972CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2973 const char *from_name, const char *to_name,
2974 struct cifs_sb_info *cifs_sb)
2975{
2976 int rc = 0;
2977 NT_RENAME_REQ *pSMB = NULL;
2978 RENAME_RSP *pSMBr = NULL;
2979 int bytes_returned;
2980 int name_len, name_len2;
2981 __u16 count;
2982 int remap = cifs_remap(cifs_sb);
2983
2984 cifs_dbg(FYI, "In CIFSCreateHardLink\n");
2985winCreateHardLinkRetry:
2986
2987 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2988 (void **) &pSMBr);
2989 if (rc)
2990 return rc;
2991
2992 pSMB->SearchAttributes =
2993 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2994 ATTR_DIRECTORY);
2995 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2996 pSMB->ClusterCount = 0;
2997
2998 pSMB->BufferFormat = 0x04;
2999
3000 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3001 name_len =
3002 cifsConvertToUTF16((__le16 *) pSMB->OldFileName, from_name,
3003 PATH_MAX, cifs_sb->local_nls, remap);
3004 name_len++; /* trailing null */
3005 name_len *= 2;
3006
3007 /* protocol specifies ASCII buffer format (0x04) for unicode */
3008 pSMB->OldFileName[name_len] = 0x04;
3009 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
3010 name_len2 =
3011 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
3012 to_name, PATH_MAX, cifs_sb->local_nls,
3013 remap);
3014 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
3015 name_len2 *= 2; /* convert to bytes */
3016 } else { /* BB improve the check for buffer overruns BB */
3017 name_len = strnlen(from_name, PATH_MAX);
3018 name_len++; /* trailing null */
3019 strncpy(pSMB->OldFileName, from_name, name_len);
3020 name_len2 = strnlen(to_name, PATH_MAX);
3021 name_len2++; /* trailing null */
3022 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
3023 strncpy(&pSMB->OldFileName[name_len + 1], to_name, name_len2);
3024 name_len2++; /* trailing null */
3025 name_len2++; /* signature byte */
3026 }
3027
3028 count = 1 /* string type byte */ + name_len + name_len2;
3029 inc_rfc1001_len(pSMB, count);
3030 pSMB->ByteCount = cpu_to_le16(count);
3031
3032 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3033 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3034 cifs_stats_inc(&tcon->stats.cifs_stats.num_hardlinks);
3035 if (rc)
3036 cifs_dbg(FYI, "Send error in hard link (NT rename) = %d\n", rc);
3037
3038 cifs_buf_release(pSMB);
3039 if (rc == -EAGAIN)
3040 goto winCreateHardLinkRetry;
3041
3042 return rc;
3043}
3044
3045int
3046CIFSSMBUnixQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
3047 const unsigned char *searchName, char **symlinkinfo,
3048 const struct nls_table *nls_codepage, int remap)
3049{
3050/* SMB_QUERY_FILE_UNIX_LINK */
3051 TRANSACTION2_QPI_REQ *pSMB = NULL;
3052 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3053 int rc = 0;
3054 int bytes_returned;
3055 int name_len;
3056 __u16 params, byte_count;
3057 char *data_start;
3058
3059 cifs_dbg(FYI, "In QPathSymLinkInfo (Unix) for path %s\n", searchName);
3060
3061querySymLinkRetry:
3062 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3063 (void **) &pSMBr);
3064 if (rc)
3065 return rc;
3066
3067 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3068 name_len =
3069 cifsConvertToUTF16((__le16 *) pSMB->FileName,
3070 searchName, PATH_MAX, nls_codepage,
3071 remap);
3072 name_len++; /* trailing null */
3073 name_len *= 2;
3074 } else { /* BB improve the check for buffer overruns BB */
3075 name_len = strnlen(searchName, PATH_MAX);
3076 name_len++; /* trailing null */
3077 strncpy(pSMB->FileName, searchName, name_len);
3078 }
3079
3080 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3081 pSMB->TotalDataCount = 0;
3082 pSMB->MaxParameterCount = cpu_to_le16(2);
3083 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3084 pSMB->MaxSetupCount = 0;
3085 pSMB->Reserved = 0;
3086 pSMB->Flags = 0;
3087 pSMB->Timeout = 0;
3088 pSMB->Reserved2 = 0;
3089 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3090 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3091 pSMB->DataCount = 0;
3092 pSMB->DataOffset = 0;
3093 pSMB->SetupCount = 1;
3094 pSMB->Reserved3 = 0;
3095 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3096 byte_count = params + 1 /* pad */ ;
3097 pSMB->TotalParameterCount = cpu_to_le16(params);
3098 pSMB->ParameterCount = pSMB->TotalParameterCount;
3099 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
3100 pSMB->Reserved4 = 0;
3101 inc_rfc1001_len(pSMB, byte_count);
3102 pSMB->ByteCount = cpu_to_le16(byte_count);
3103
3104 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3105 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3106 if (rc) {
3107 cifs_dbg(FYI, "Send error in QuerySymLinkInfo = %d\n", rc);
3108 } else {
3109 /* decode response */
3110
3111 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3112 /* BB also check enough total bytes returned */
3113 if (rc || get_bcc(&pSMBr->hdr) < 2)
3114 rc = -EIO;
3115 else {
3116 bool is_unicode;
3117 u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3118
3119 data_start = ((char *) &pSMBr->hdr.Protocol) +
3120 le16_to_cpu(pSMBr->t2.DataOffset);
3121
3122 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3123 is_unicode = true;
3124 else
3125 is_unicode = false;
3126
3127 /* BB FIXME investigate remapping reserved chars here */
3128 *symlinkinfo = cifs_strndup_from_utf16(data_start,
3129 count, is_unicode, nls_codepage);
3130 if (!*symlinkinfo)
3131 rc = -ENOMEM;
3132 }
3133 }
3134 cifs_buf_release(pSMB);
3135 if (rc == -EAGAIN)
3136 goto querySymLinkRetry;
3137 return rc;
3138}
3139
3140/*
3141 * Recent Windows versions now create symlinks more frequently
3142 * and they use the "reparse point" mechanism below. We can of course
3143 * do symlinks nicely to Samba and other servers which support the
3144 * CIFS Unix Extensions and we can also do SFU symlinks and "client only"
3145 * "MF" symlinks optionally, but for recent Windows we really need to
3146 * reenable the code below and fix the cifs_symlink callers to handle this.
3147 * In the interim this code has been moved to its own config option so
3148 * it is not compiled in by default until callers fixed up and more tested.
3149 */
3150int
3151CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
3152 __u16 fid, char **symlinkinfo,
3153 const struct nls_table *nls_codepage)
3154{
3155 int rc = 0;
3156 int bytes_returned;
3157 struct smb_com_transaction_ioctl_req *pSMB;
3158 struct smb_com_transaction_ioctl_rsp *pSMBr;
3159 bool is_unicode;
3160 unsigned int sub_len;
3161 char *sub_start;
3162 struct reparse_symlink_data *reparse_buf;
3163 struct reparse_posix_data *posix_buf;
3164 __u32 data_offset, data_count;
3165 char *end_of_smb;
3166
3167 cifs_dbg(FYI, "In Windows reparse style QueryLink for fid %u\n", fid);
3168 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3169 (void **) &pSMBr);
3170 if (rc)
3171 return rc;
3172
3173 pSMB->TotalParameterCount = 0 ;
3174 pSMB->TotalDataCount = 0;
3175 pSMB->MaxParameterCount = cpu_to_le32(2);
3176 /* BB find exact data count max from sess structure BB */
3177 pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3178 pSMB->MaxSetupCount = 4;
3179 pSMB->Reserved = 0;
3180 pSMB->ParameterOffset = 0;
3181 pSMB->DataCount = 0;
3182 pSMB->DataOffset = 0;
3183 pSMB->SetupCount = 4;
3184 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
3185 pSMB->ParameterCount = pSMB->TotalParameterCount;
3186 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
3187 pSMB->IsFsctl = 1; /* FSCTL */
3188 pSMB->IsRootFlag = 0;
3189 pSMB->Fid = fid; /* file handle always le */
3190 pSMB->ByteCount = 0;
3191
3192 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3193 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3194 if (rc) {
3195 cifs_dbg(FYI, "Send error in QueryReparseLinkInfo = %d\n", rc);
3196 goto qreparse_out;
3197 }
3198
3199 data_offset = le32_to_cpu(pSMBr->DataOffset);
3200 data_count = le32_to_cpu(pSMBr->DataCount);
3201 if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) {
3202 /* BB also check enough total bytes returned */
3203 rc = -EIO; /* bad smb */
3204 goto qreparse_out;
3205 }
3206 if (!data_count || (data_count > 2048)) {
3207 rc = -EIO;
3208 cifs_dbg(FYI, "Invalid return data count on get reparse info ioctl\n");
3209 goto qreparse_out;
3210 }
3211 end_of_smb = 2 + get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
3212 reparse_buf = (struct reparse_symlink_data *)
3213 ((char *)&pSMBr->hdr.Protocol + data_offset);
3214 if ((char *)reparse_buf >= end_of_smb) {
3215 rc = -EIO;
3216 goto qreparse_out;
3217 }
3218 if (reparse_buf->ReparseTag == cpu_to_le32(IO_REPARSE_TAG_NFS)) {
3219 cifs_dbg(FYI, "NFS style reparse tag\n");
3220 posix_buf = (struct reparse_posix_data *)reparse_buf;
3221
3222 if (posix_buf->InodeType != cpu_to_le64(NFS_SPECFILE_LNK)) {
3223 cifs_dbg(FYI, "unsupported file type 0x%llx\n",
3224 le64_to_cpu(posix_buf->InodeType));
3225 rc = -EOPNOTSUPP;
3226 goto qreparse_out;
3227 }
3228 is_unicode = true;
3229 sub_len = le16_to_cpu(reparse_buf->ReparseDataLength);
3230 if (posix_buf->PathBuffer + sub_len > end_of_smb) {
3231 cifs_dbg(FYI, "reparse buf beyond SMB\n");
3232 rc = -EIO;
3233 goto qreparse_out;
3234 }
3235 *symlinkinfo = cifs_strndup_from_utf16(posix_buf->PathBuffer,
3236 sub_len, is_unicode, nls_codepage);
3237 goto qreparse_out;
3238 } else if (reparse_buf->ReparseTag !=
3239 cpu_to_le32(IO_REPARSE_TAG_SYMLINK)) {
3240 rc = -EOPNOTSUPP;
3241 goto qreparse_out;
3242 }
3243
3244 /* Reparse tag is NTFS symlink */
3245 sub_start = le16_to_cpu(reparse_buf->SubstituteNameOffset) +
3246 reparse_buf->PathBuffer;
3247 sub_len = le16_to_cpu(reparse_buf->SubstituteNameLength);
3248 if (sub_start + sub_len > end_of_smb) {
3249 cifs_dbg(FYI, "reparse buf beyond SMB\n");
3250 rc = -EIO;
3251 goto qreparse_out;
3252 }
3253 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3254 is_unicode = true;
3255 else
3256 is_unicode = false;
3257
3258 /* BB FIXME investigate remapping reserved chars here */
3259 *symlinkinfo = cifs_strndup_from_utf16(sub_start, sub_len, is_unicode,
3260 nls_codepage);
3261 if (!*symlinkinfo)
3262 rc = -ENOMEM;
3263qreparse_out:
3264 cifs_buf_release(pSMB);
3265
3266 /*
3267 * Note: On -EAGAIN error only caller can retry on handle based calls
3268 * since file handle passed in no longer valid.
3269 */
3270 return rc;
3271}
3272
3273int
3274CIFSSMB_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
3275 __u16 fid)
3276{
3277 int rc = 0;
3278 int bytes_returned;
3279 struct smb_com_transaction_compr_ioctl_req *pSMB;
3280 struct smb_com_transaction_ioctl_rsp *pSMBr;
3281
3282 cifs_dbg(FYI, "Set compression for %u\n", fid);
3283 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3284 (void **) &pSMBr);
3285 if (rc)
3286 return rc;
3287
3288 pSMB->compression_state = cpu_to_le16(COMPRESSION_FORMAT_DEFAULT);
3289
3290 pSMB->TotalParameterCount = 0;
3291 pSMB->TotalDataCount = cpu_to_le32(2);
3292 pSMB->MaxParameterCount = 0;
3293 pSMB->MaxDataCount = 0;
3294 pSMB->MaxSetupCount = 4;
3295 pSMB->Reserved = 0;
3296 pSMB->ParameterOffset = 0;
3297 pSMB->DataCount = cpu_to_le32(2);
3298 pSMB->DataOffset =
3299 cpu_to_le32(offsetof(struct smb_com_transaction_compr_ioctl_req,
3300 compression_state) - 4); /* 84 */
3301 pSMB->SetupCount = 4;
3302 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
3303 pSMB->ParameterCount = 0;
3304 pSMB->FunctionCode = cpu_to_le32(FSCTL_SET_COMPRESSION);
3305 pSMB->IsFsctl = 1; /* FSCTL */
3306 pSMB->IsRootFlag = 0;
3307 pSMB->Fid = fid; /* file handle always le */
3308 /* 3 byte pad, followed by 2 byte compress state */
3309 pSMB->ByteCount = cpu_to_le16(5);
3310 inc_rfc1001_len(pSMB, 5);
3311
3312 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3313 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3314 if (rc)
3315 cifs_dbg(FYI, "Send error in SetCompression = %d\n", rc);
3316
3317 cifs_buf_release(pSMB);
3318
3319 /*
3320 * Note: On -EAGAIN error only caller can retry on handle based calls
3321 * since file handle passed in no longer valid.
3322 */
3323 return rc;
3324}
3325
3326
3327#ifdef CONFIG_CIFS_POSIX
3328
3329/*Convert an Access Control Entry from wire format to local POSIX xattr format*/
3330static void cifs_convert_ace(struct posix_acl_xattr_entry *ace,
3331 struct cifs_posix_ace *cifs_ace)
3332{
3333 /* u8 cifs fields do not need le conversion */
3334 ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
3335 ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
3336 ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
3337/*
3338 cifs_dbg(FYI, "perm %d tag %d id %d\n",
3339 ace->e_perm, ace->e_tag, ace->e_id);
3340*/
3341
3342 return;
3343}
3344
3345/* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
3346static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
3347 const int acl_type, const int size_of_data_area)
3348{
3349 int size = 0;
3350 int i;
3351 __u16 count;
3352 struct cifs_posix_ace *pACE;
3353 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
3354 struct posix_acl_xattr_header *local_acl = (void *)trgt;
3355
3356 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
3357 return -EOPNOTSUPP;
3358
3359 if (acl_type == ACL_TYPE_ACCESS) {
3360 count = le16_to_cpu(cifs_acl->access_entry_count);
3361 pACE = &cifs_acl->ace_array[0];
3362 size = sizeof(struct cifs_posix_acl);
3363 size += sizeof(struct cifs_posix_ace) * count;
3364 /* check if we would go beyond end of SMB */
3365 if (size_of_data_area < size) {
3366 cifs_dbg(FYI, "bad CIFS POSIX ACL size %d vs. %d\n",
3367 size_of_data_area, size);
3368 return -EINVAL;
3369 }
3370 } else if (acl_type == ACL_TYPE_DEFAULT) {
3371 count = le16_to_cpu(cifs_acl->access_entry_count);
3372 size = sizeof(struct cifs_posix_acl);
3373 size += sizeof(struct cifs_posix_ace) * count;
3374/* skip past access ACEs to get to default ACEs */
3375 pACE = &cifs_acl->ace_array[count];
3376 count = le16_to_cpu(cifs_acl->default_entry_count);
3377 size += sizeof(struct cifs_posix_ace) * count;
3378 /* check if we would go beyond end of SMB */
3379 if (size_of_data_area < size)
3380 return -EINVAL;
3381 } else {
3382 /* illegal type */
3383 return -EINVAL;
3384 }
3385
3386 size = posix_acl_xattr_size(count);
3387 if ((buflen == 0) || (local_acl == NULL)) {
3388 /* used to query ACL EA size */
3389 } else if (size > buflen) {
3390 return -ERANGE;
3391 } else /* buffer big enough */ {
3392 struct posix_acl_xattr_entry *ace = (void *)(local_acl + 1);
3393
3394 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
3395 for (i = 0; i < count ; i++) {
3396 cifs_convert_ace(&ace[i], pACE);
3397 pACE++;
3398 }
3399 }
3400 return size;
3401}
3402
3403static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
3404 const struct posix_acl_xattr_entry *local_ace)
3405{
3406 __u16 rc = 0; /* 0 = ACL converted ok */
3407
3408 cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
3409 cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
3410 /* BB is there a better way to handle the large uid? */
3411 if (local_ace->e_id == cpu_to_le32(-1)) {
3412 /* Probably no need to le convert -1 on any arch but can not hurt */
3413 cifs_ace->cifs_uid = cpu_to_le64(-1);
3414 } else
3415 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
3416/*
3417 cifs_dbg(FYI, "perm %d tag %d id %d\n",
3418 ace->e_perm, ace->e_tag, ace->e_id);
3419*/
3420 return rc;
3421}
3422
3423/* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
3424static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
3425 const int buflen, const int acl_type)
3426{
3427 __u16 rc = 0;
3428 struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
3429 struct posix_acl_xattr_header *local_acl = (void *)pACL;
3430 struct posix_acl_xattr_entry *ace = (void *)(local_acl + 1);
3431 int count;
3432 int i;
3433
3434 if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
3435 return 0;
3436
3437 count = posix_acl_xattr_count((size_t)buflen);
3438 cifs_dbg(FYI, "setting acl with %d entries from buf of length %d and version of %d\n",
3439 count, buflen, le32_to_cpu(local_acl->a_version));
3440 if (le32_to_cpu(local_acl->a_version) != 2) {
3441 cifs_dbg(FYI, "unknown POSIX ACL version %d\n",
3442 le32_to_cpu(local_acl->a_version));
3443 return 0;
3444 }
3445 cifs_acl->version = cpu_to_le16(1);
3446 if (acl_type == ACL_TYPE_ACCESS) {
3447 cifs_acl->access_entry_count = cpu_to_le16(count);
3448 cifs_acl->default_entry_count = cpu_to_le16(0xFFFF);
3449 } else if (acl_type == ACL_TYPE_DEFAULT) {
3450 cifs_acl->default_entry_count = cpu_to_le16(count);
3451 cifs_acl->access_entry_count = cpu_to_le16(0xFFFF);
3452 } else {
3453 cifs_dbg(FYI, "unknown ACL type %d\n", acl_type);
3454 return 0;
3455 }
3456 for (i = 0; i < count; i++) {
3457 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i], &ace[i]);
3458 if (rc != 0) {
3459 /* ACE not converted */
3460 break;
3461 }
3462 }
3463 if (rc == 0) {
3464 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
3465 rc += sizeof(struct cifs_posix_acl);
3466 /* BB add check to make sure ACL does not overflow SMB */
3467 }
3468 return rc;
3469}
3470
3471int
3472CIFSSMBGetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
3473 const unsigned char *searchName,
3474 char *acl_inf, const int buflen, const int acl_type,
3475 const struct nls_table *nls_codepage, int remap)
3476{
3477/* SMB_QUERY_POSIX_ACL */
3478 TRANSACTION2_QPI_REQ *pSMB = NULL;
3479 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3480 int rc = 0;
3481 int bytes_returned;
3482 int name_len;
3483 __u16 params, byte_count;
3484
3485 cifs_dbg(FYI, "In GetPosixACL (Unix) for path %s\n", searchName);
3486
3487queryAclRetry:
3488 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3489 (void **) &pSMBr);
3490 if (rc)
3491 return rc;
3492
3493 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3494 name_len =
3495 cifsConvertToUTF16((__le16 *) pSMB->FileName,
3496 searchName, PATH_MAX, nls_codepage,
3497 remap);
3498 name_len++; /* trailing null */
3499 name_len *= 2;
3500 pSMB->FileName[name_len] = 0;
3501 pSMB->FileName[name_len+1] = 0;
3502 } else { /* BB improve the check for buffer overruns BB */
3503 name_len = strnlen(searchName, PATH_MAX);
3504 name_len++; /* trailing null */
3505 strncpy(pSMB->FileName, searchName, name_len);
3506 }
3507
3508 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
3509 pSMB->TotalDataCount = 0;
3510 pSMB->MaxParameterCount = cpu_to_le16(2);
3511 /* BB find exact max data count below from sess structure BB */
3512 pSMB->MaxDataCount = cpu_to_le16(4000);
3513 pSMB->MaxSetupCount = 0;
3514 pSMB->Reserved = 0;
3515 pSMB->Flags = 0;
3516 pSMB->Timeout = 0;
3517 pSMB->Reserved2 = 0;
3518 pSMB->ParameterOffset = cpu_to_le16(
3519 offsetof(struct smb_com_transaction2_qpi_req,
3520 InformationLevel) - 4);
3521 pSMB->DataCount = 0;
3522 pSMB->DataOffset = 0;
3523 pSMB->SetupCount = 1;
3524 pSMB->Reserved3 = 0;
3525 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3526 byte_count = params + 1 /* pad */ ;
3527 pSMB->TotalParameterCount = cpu_to_le16(params);
3528 pSMB->ParameterCount = pSMB->TotalParameterCount;
3529 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
3530 pSMB->Reserved4 = 0;
3531 inc_rfc1001_len(pSMB, byte_count);
3532 pSMB->ByteCount = cpu_to_le16(byte_count);
3533
3534 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3535 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3536 cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3537 if (rc) {
3538 cifs_dbg(FYI, "Send error in Query POSIX ACL = %d\n", rc);
3539 } else {
3540 /* decode response */
3541
3542 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3543 /* BB also check enough total bytes returned */
3544 if (rc || get_bcc(&pSMBr->hdr) < 2)
3545 rc = -EIO; /* bad smb */
3546 else {
3547 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3548 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3549 rc = cifs_copy_posix_acl(acl_inf,
3550 (char *)&pSMBr->hdr.Protocol+data_offset,
3551 buflen, acl_type, count);
3552 }
3553 }
3554 cifs_buf_release(pSMB);
3555 if (rc == -EAGAIN)
3556 goto queryAclRetry;
3557 return rc;
3558}
3559
3560int
3561CIFSSMBSetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
3562 const unsigned char *fileName,
3563 const char *local_acl, const int buflen,
3564 const int acl_type,
3565 const struct nls_table *nls_codepage, int remap)
3566{
3567 struct smb_com_transaction2_spi_req *pSMB = NULL;
3568 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3569 char *parm_data;
3570 int name_len;
3571 int rc = 0;
3572 int bytes_returned = 0;
3573 __u16 params, byte_count, data_count, param_offset, offset;
3574
3575 cifs_dbg(FYI, "In SetPosixACL (Unix) for path %s\n", fileName);
3576setAclRetry:
3577 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3578 (void **) &pSMBr);
3579 if (rc)
3580 return rc;
3581 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3582 name_len =
3583 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
3584 PATH_MAX, nls_codepage, remap);
3585 name_len++; /* trailing null */
3586 name_len *= 2;
3587 } else { /* BB improve the check for buffer overruns BB */
3588 name_len = strnlen(fileName, PATH_MAX);
3589 name_len++; /* trailing null */
3590 strncpy(pSMB->FileName, fileName, name_len);
3591 }
3592 params = 6 + name_len;
3593 pSMB->MaxParameterCount = cpu_to_le16(2);
3594 /* BB find max SMB size from sess */
3595 pSMB->MaxDataCount = cpu_to_le16(1000);
3596 pSMB->MaxSetupCount = 0;
3597 pSMB->Reserved = 0;
3598 pSMB->Flags = 0;
3599 pSMB->Timeout = 0;
3600 pSMB->Reserved2 = 0;
3601 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3602 InformationLevel) - 4;
3603 offset = param_offset + params;
3604 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
3605 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3606
3607 /* convert to on the wire format for POSIX ACL */
3608 data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
3609
3610 if (data_count == 0) {
3611 rc = -EOPNOTSUPP;
3612 goto setACLerrorExit;
3613 }
3614 pSMB->DataOffset = cpu_to_le16(offset);
3615 pSMB->SetupCount = 1;
3616 pSMB->Reserved3 = 0;
3617 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3618 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
3619 byte_count = 3 /* pad */ + params + data_count;
3620 pSMB->DataCount = cpu_to_le16(data_count);
3621 pSMB->TotalDataCount = pSMB->DataCount;
3622 pSMB->ParameterCount = cpu_to_le16(params);
3623 pSMB->TotalParameterCount = pSMB->ParameterCount;
3624 pSMB->Reserved4 = 0;
3625 inc_rfc1001_len(pSMB, byte_count);
3626 pSMB->ByteCount = cpu_to_le16(byte_count);
3627 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3628 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3629 if (rc)
3630 cifs_dbg(FYI, "Set POSIX ACL returned %d\n", rc);
3631
3632setACLerrorExit:
3633 cifs_buf_release(pSMB);
3634 if (rc == -EAGAIN)
3635 goto setAclRetry;
3636 return rc;
3637}
3638
3639/* BB fix tabs in this function FIXME BB */
3640int
3641CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
3642 const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
3643{
3644 int rc = 0;
3645 struct smb_t2_qfi_req *pSMB = NULL;
3646 struct smb_t2_qfi_rsp *pSMBr = NULL;
3647 int bytes_returned;
3648 __u16 params, byte_count;
3649
3650 cifs_dbg(FYI, "In GetExtAttr\n");
3651 if (tcon == NULL)
3652 return -ENODEV;
3653
3654GetExtAttrRetry:
3655 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3656 (void **) &pSMBr);
3657 if (rc)
3658 return rc;
3659
3660 params = 2 /* level */ + 2 /* fid */;
3661 pSMB->t2.TotalDataCount = 0;
3662 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3663 /* BB find exact max data count below from sess structure BB */
3664 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3665 pSMB->t2.MaxSetupCount = 0;
3666 pSMB->t2.Reserved = 0;
3667 pSMB->t2.Flags = 0;
3668 pSMB->t2.Timeout = 0;
3669 pSMB->t2.Reserved2 = 0;
3670 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3671 Fid) - 4);
3672 pSMB->t2.DataCount = 0;
3673 pSMB->t2.DataOffset = 0;
3674 pSMB->t2.SetupCount = 1;
3675 pSMB->t2.Reserved3 = 0;
3676 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3677 byte_count = params + 1 /* pad */ ;
3678 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3679 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3680 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3681 pSMB->Pad = 0;
3682 pSMB->Fid = netfid;
3683 inc_rfc1001_len(pSMB, byte_count);
3684 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3685
3686 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3687 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3688 if (rc) {
3689 cifs_dbg(FYI, "error %d in GetExtAttr\n", rc);
3690 } else {
3691 /* decode response */
3692 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3693 /* BB also check enough total bytes returned */
3694 if (rc || get_bcc(&pSMBr->hdr) < 2)
3695 /* If rc should we check for EOPNOSUPP and
3696 disable the srvino flag? or in caller? */
3697 rc = -EIO; /* bad smb */
3698 else {
3699 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3700 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3701 struct file_chattr_info *pfinfo;
3702 /* BB Do we need a cast or hash here ? */
3703 if (count != 16) {
3704 cifs_dbg(FYI, "Illegal size ret in GetExtAttr\n");
3705 rc = -EIO;
3706 goto GetExtAttrOut;
3707 }
3708 pfinfo = (struct file_chattr_info *)
3709 (data_offset + (char *) &pSMBr->hdr.Protocol);
3710 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3711 *pMask = le64_to_cpu(pfinfo->mask);
3712 }
3713 }
3714GetExtAttrOut:
3715 cifs_buf_release(pSMB);
3716 if (rc == -EAGAIN)
3717 goto GetExtAttrRetry;
3718 return rc;
3719}
3720
3721#endif /* CONFIG_POSIX */
3722
3723#ifdef CONFIG_CIFS_ACL
3724/*
3725 * Initialize NT TRANSACT SMB into small smb request buffer. This assumes that
3726 * all NT TRANSACTS that we init here have total parm and data under about 400
3727 * bytes (to fit in small cifs buffer size), which is the case so far, it
3728 * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
3729 * returned setup area) and MaxParameterCount (returned parms size) must be set
3730 * by caller
3731 */
3732static int
3733smb_init_nttransact(const __u16 sub_command, const int setup_count,
3734 const int parm_len, struct cifs_tcon *tcon,
3735 void **ret_buf)
3736{
3737 int rc;
3738 __u32 temp_offset;
3739 struct smb_com_ntransact_req *pSMB;
3740
3741 rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
3742 (void **)&pSMB);
3743 if (rc)
3744 return rc;
3745 *ret_buf = (void *)pSMB;
3746 pSMB->Reserved = 0;
3747 pSMB->TotalParameterCount = cpu_to_le32(parm_len);
3748 pSMB->TotalDataCount = 0;
3749 pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3750 pSMB->ParameterCount = pSMB->TotalParameterCount;
3751 pSMB->DataCount = pSMB->TotalDataCount;
3752 temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
3753 (setup_count * 2) - 4 /* for rfc1001 length itself */;
3754 pSMB->ParameterOffset = cpu_to_le32(temp_offset);
3755 pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
3756 pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
3757 pSMB->SubCommand = cpu_to_le16(sub_command);
3758 return 0;
3759}
3760
3761static int
3762validate_ntransact(char *buf, char **ppparm, char **ppdata,
3763 __u32 *pparmlen, __u32 *pdatalen)
3764{
3765 char *end_of_smb;
3766 __u32 data_count, data_offset, parm_count, parm_offset;
3767 struct smb_com_ntransact_rsp *pSMBr;
3768 u16 bcc;
3769
3770 *pdatalen = 0;
3771 *pparmlen = 0;
3772
3773 if (buf == NULL)
3774 return -EINVAL;
3775
3776 pSMBr = (struct smb_com_ntransact_rsp *)buf;
3777
3778 bcc = get_bcc(&pSMBr->hdr);
3779 end_of_smb = 2 /* sizeof byte count */ + bcc +
3780 (char *)&pSMBr->ByteCount;
3781
3782 data_offset = le32_to_cpu(pSMBr->DataOffset);
3783 data_count = le32_to_cpu(pSMBr->DataCount);
3784 parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
3785 parm_count = le32_to_cpu(pSMBr->ParameterCount);
3786
3787 *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
3788 *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
3789
3790 /* should we also check that parm and data areas do not overlap? */
3791 if (*ppparm > end_of_smb) {
3792 cifs_dbg(FYI, "parms start after end of smb\n");
3793 return -EINVAL;
3794 } else if (parm_count + *ppparm > end_of_smb) {
3795 cifs_dbg(FYI, "parm end after end of smb\n");
3796 return -EINVAL;
3797 } else if (*ppdata > end_of_smb) {
3798 cifs_dbg(FYI, "data starts after end of smb\n");
3799 return -EINVAL;
3800 } else if (data_count + *ppdata > end_of_smb) {
3801 cifs_dbg(FYI, "data %p + count %d (%p) past smb end %p start %p\n",
3802 *ppdata, data_count, (data_count + *ppdata),
3803 end_of_smb, pSMBr);
3804 return -EINVAL;
3805 } else if (parm_count + data_count > bcc) {
3806 cifs_dbg(FYI, "parm count and data count larger than SMB\n");
3807 return -EINVAL;
3808 }
3809 *pdatalen = data_count;
3810 *pparmlen = parm_count;
3811 return 0;
3812}
3813
3814/* Get Security Descriptor (by handle) from remote server for a file or dir */
3815int
3816CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3817 struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3818{
3819 int rc = 0;
3820 int buf_type = 0;
3821 QUERY_SEC_DESC_REQ *pSMB;
3822 struct kvec iov[1];
3823
3824 cifs_dbg(FYI, "GetCifsACL\n");
3825
3826 *pbuflen = 0;
3827 *acl_inf = NULL;
3828
3829 rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3830 8 /* parm len */, tcon, (void **) &pSMB);
3831 if (rc)
3832 return rc;
3833
3834 pSMB->MaxParameterCount = cpu_to_le32(4);
3835 /* BB TEST with big acls that might need to be e.g. larger than 16K */
3836 pSMB->MaxSetupCount = 0;
3837 pSMB->Fid = fid; /* file handle always le */
3838 pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3839 CIFS_ACL_DACL);
3840 pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3841 inc_rfc1001_len(pSMB, 11);
3842 iov[0].iov_base = (char *)pSMB;
3843 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
3844
3845 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3846 0);
3847 cifs_stats_inc(&tcon->stats.cifs_stats.num_acl_get);
3848 if (rc) {
3849 cifs_dbg(FYI, "Send error in QuerySecDesc = %d\n", rc);
3850 } else { /* decode response */
3851 __le32 *parm;
3852 __u32 parm_len;
3853 __u32 acl_len;
3854 struct smb_com_ntransact_rsp *pSMBr;
3855 char *pdata;
3856
3857/* validate_nttransact */
3858 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3859 &pdata, &parm_len, pbuflen);
3860 if (rc)
3861 goto qsec_out;
3862 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3863
3864 cifs_dbg(FYI, "smb %p parm %p data %p\n",
3865 pSMBr, parm, *acl_inf);
3866
3867 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3868 rc = -EIO; /* bad smb */
3869 *pbuflen = 0;
3870 goto qsec_out;
3871 }
3872
3873/* BB check that data area is minimum length and as big as acl_len */
3874
3875 acl_len = le32_to_cpu(*parm);
3876 if (acl_len != *pbuflen) {
3877 cifs_dbg(VFS, "acl length %d does not match %d\n",
3878 acl_len, *pbuflen);
3879 if (*pbuflen > acl_len)
3880 *pbuflen = acl_len;
3881 }
3882
3883 /* check if buffer is big enough for the acl
3884 header followed by the smallest SID */
3885 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3886 (*pbuflen >= 64 * 1024)) {
3887 cifs_dbg(VFS, "bad acl length %d\n", *pbuflen);
3888 rc = -EINVAL;
3889 *pbuflen = 0;
3890 } else {
3891 *acl_inf = kmemdup(pdata, *pbuflen, GFP_KERNEL);
3892 if (*acl_inf == NULL) {
3893 *pbuflen = 0;
3894 rc = -ENOMEM;
3895 }
3896 }
3897 }
3898qsec_out:
3899 free_rsp_buf(buf_type, iov[0].iov_base);
3900/* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3901 return rc;
3902}
3903
3904int
3905CIFSSMBSetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
3906 struct cifs_ntsd *pntsd, __u32 acllen, int aclflag)
3907{
3908 __u16 byte_count, param_count, data_count, param_offset, data_offset;
3909 int rc = 0;
3910 int bytes_returned = 0;
3911 SET_SEC_DESC_REQ *pSMB = NULL;
3912 void *pSMBr;
3913
3914setCifsAclRetry:
3915 rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, &pSMBr);
3916 if (rc)
3917 return rc;
3918
3919 pSMB->MaxSetupCount = 0;
3920 pSMB->Reserved = 0;
3921
3922 param_count = 8;
3923 param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3924 data_count = acllen;
3925 data_offset = param_offset + param_count;
3926 byte_count = 3 /* pad */ + param_count;
3927
3928 pSMB->DataCount = cpu_to_le32(data_count);
3929 pSMB->TotalDataCount = pSMB->DataCount;
3930 pSMB->MaxParameterCount = cpu_to_le32(4);
3931 pSMB->MaxDataCount = cpu_to_le32(16384);
3932 pSMB->ParameterCount = cpu_to_le32(param_count);
3933 pSMB->ParameterOffset = cpu_to_le32(param_offset);
3934 pSMB->TotalParameterCount = pSMB->ParameterCount;
3935 pSMB->DataOffset = cpu_to_le32(data_offset);
3936 pSMB->SetupCount = 0;
3937 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3938 pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3939
3940 pSMB->Fid = fid; /* file handle always le */
3941 pSMB->Reserved2 = 0;
3942 pSMB->AclFlags = cpu_to_le32(aclflag);
3943
3944 if (pntsd && acllen) {
3945 memcpy((char *)pSMBr + offsetof(struct smb_hdr, Protocol) +
3946 data_offset, pntsd, acllen);
3947 inc_rfc1001_len(pSMB, byte_count + data_count);
3948 } else
3949 inc_rfc1001_len(pSMB, byte_count);
3950
3951 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3952 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3953
3954 cifs_dbg(FYI, "SetCIFSACL bytes_returned: %d, rc: %d\n",
3955 bytes_returned, rc);
3956 if (rc)
3957 cifs_dbg(FYI, "Set CIFS ACL returned %d\n", rc);
3958 cifs_buf_release(pSMB);
3959
3960 if (rc == -EAGAIN)
3961 goto setCifsAclRetry;
3962
3963 return (rc);
3964}
3965
3966#endif /* CONFIG_CIFS_ACL */
3967
3968/* Legacy Query Path Information call for lookup to old servers such
3969 as Win9x/WinME */
3970int
3971SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon,
3972 const char *search_name, FILE_ALL_INFO *data,
3973 const struct nls_table *nls_codepage, int remap)
3974{
3975 QUERY_INFORMATION_REQ *pSMB;
3976 QUERY_INFORMATION_RSP *pSMBr;
3977 int rc = 0;
3978 int bytes_returned;
3979 int name_len;
3980
3981 cifs_dbg(FYI, "In SMBQPath path %s\n", search_name);
3982QInfRetry:
3983 rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3984 (void **) &pSMBr);
3985 if (rc)
3986 return rc;
3987
3988 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3989 name_len =
3990 cifsConvertToUTF16((__le16 *) pSMB->FileName,
3991 search_name, PATH_MAX, nls_codepage,
3992 remap);
3993 name_len++; /* trailing null */
3994 name_len *= 2;
3995 } else {
3996 name_len = strnlen(search_name, PATH_MAX);
3997 name_len++; /* trailing null */
3998 strncpy(pSMB->FileName, search_name, name_len);
3999 }
4000 pSMB->BufferFormat = 0x04;
4001 name_len++; /* account for buffer type byte */
4002 inc_rfc1001_len(pSMB, (__u16)name_len);
4003 pSMB->ByteCount = cpu_to_le16(name_len);
4004
4005 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4006 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4007 if (rc) {
4008 cifs_dbg(FYI, "Send error in QueryInfo = %d\n", rc);
4009 } else if (data) {
4010 struct timespec ts;
4011 __u32 time = le32_to_cpu(pSMBr->last_write_time);
4012
4013 /* decode response */
4014 /* BB FIXME - add time zone adjustment BB */
4015 memset(data, 0, sizeof(FILE_ALL_INFO));
4016 ts.tv_nsec = 0;
4017 ts.tv_sec = time;
4018 /* decode time fields */
4019 data->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
4020 data->LastWriteTime = data->ChangeTime;
4021 data->LastAccessTime = 0;
4022 data->AllocationSize =
4023 cpu_to_le64(le32_to_cpu(pSMBr->size));
4024 data->EndOfFile = data->AllocationSize;
4025 data->Attributes =
4026 cpu_to_le32(le16_to_cpu(pSMBr->attr));
4027 } else
4028 rc = -EIO; /* bad buffer passed in */
4029
4030 cifs_buf_release(pSMB);
4031
4032 if (rc == -EAGAIN)
4033 goto QInfRetry;
4034
4035 return rc;
4036}
4037
4038int
4039CIFSSMBQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
4040 u16 netfid, FILE_ALL_INFO *pFindData)
4041{
4042 struct smb_t2_qfi_req *pSMB = NULL;
4043 struct smb_t2_qfi_rsp *pSMBr = NULL;
4044 int rc = 0;
4045 int bytes_returned;
4046 __u16 params, byte_count;
4047
4048QFileInfoRetry:
4049 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4050 (void **) &pSMBr);
4051 if (rc)
4052 return rc;
4053
4054 params = 2 /* level */ + 2 /* fid */;
4055 pSMB->t2.TotalDataCount = 0;
4056 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
4057 /* BB find exact max data count below from sess structure BB */
4058 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
4059 pSMB->t2.MaxSetupCount = 0;
4060 pSMB->t2.Reserved = 0;
4061 pSMB->t2.Flags = 0;
4062 pSMB->t2.Timeout = 0;
4063 pSMB->t2.Reserved2 = 0;
4064 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
4065 Fid) - 4);
4066 pSMB->t2.DataCount = 0;
4067 pSMB->t2.DataOffset = 0;
4068 pSMB->t2.SetupCount = 1;
4069 pSMB->t2.Reserved3 = 0;
4070 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
4071 byte_count = params + 1 /* pad */ ;
4072 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
4073 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
4074 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
4075 pSMB->Pad = 0;
4076 pSMB->Fid = netfid;
4077 inc_rfc1001_len(pSMB, byte_count);
4078 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
4079
4080 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4081 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4082 if (rc) {
4083 cifs_dbg(FYI, "Send error in QFileInfo = %d", rc);
4084 } else { /* decode response */
4085 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4086
4087 if (rc) /* BB add auto retry on EOPNOTSUPP? */
4088 rc = -EIO;
4089 else if (get_bcc(&pSMBr->hdr) < 40)
4090 rc = -EIO; /* bad smb */
4091 else if (pFindData) {
4092 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4093 memcpy((char *) pFindData,
4094 (char *) &pSMBr->hdr.Protocol +
4095 data_offset, sizeof(FILE_ALL_INFO));
4096 } else
4097 rc = -ENOMEM;
4098 }
4099 cifs_buf_release(pSMB);
4100 if (rc == -EAGAIN)
4101 goto QFileInfoRetry;
4102
4103 return rc;
4104}
4105
4106int
4107CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
4108 const char *search_name, FILE_ALL_INFO *data,
4109 int legacy /* old style infolevel */,
4110 const struct nls_table *nls_codepage, int remap)
4111{
4112 /* level 263 SMB_QUERY_FILE_ALL_INFO */
4113 TRANSACTION2_QPI_REQ *pSMB = NULL;
4114 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4115 int rc = 0;
4116 int bytes_returned;
4117 int name_len;
4118 __u16 params, byte_count;
4119
4120 /* cifs_dbg(FYI, "In QPathInfo path %s\n", search_name); */
4121QPathInfoRetry:
4122 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4123 (void **) &pSMBr);
4124 if (rc)
4125 return rc;
4126
4127 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4128 name_len =
4129 cifsConvertToUTF16((__le16 *) pSMB->FileName, search_name,
4130 PATH_MAX, nls_codepage, remap);
4131 name_len++; /* trailing null */
4132 name_len *= 2;
4133 } else { /* BB improve the check for buffer overruns BB */
4134 name_len = strnlen(search_name, PATH_MAX);
4135 name_len++; /* trailing null */
4136 strncpy(pSMB->FileName, search_name, name_len);
4137 }
4138
4139 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4140 pSMB->TotalDataCount = 0;
4141 pSMB->MaxParameterCount = cpu_to_le16(2);
4142 /* BB find exact max SMB PDU from sess structure BB */
4143 pSMB->MaxDataCount = cpu_to_le16(4000);
4144 pSMB->MaxSetupCount = 0;
4145 pSMB->Reserved = 0;
4146 pSMB->Flags = 0;
4147 pSMB->Timeout = 0;
4148 pSMB->Reserved2 = 0;
4149 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4150 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4151 pSMB->DataCount = 0;
4152 pSMB->DataOffset = 0;
4153 pSMB->SetupCount = 1;
4154 pSMB->Reserved3 = 0;
4155 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4156 byte_count = params + 1 /* pad */ ;
4157 pSMB->TotalParameterCount = cpu_to_le16(params);
4158 pSMB->ParameterCount = pSMB->TotalParameterCount;
4159 if (legacy)
4160 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
4161 else
4162 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
4163 pSMB->Reserved4 = 0;
4164 inc_rfc1001_len(pSMB, byte_count);
4165 pSMB->ByteCount = cpu_to_le16(byte_count);
4166
4167 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4168 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4169 if (rc) {
4170 cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc);
4171 } else { /* decode response */
4172 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4173
4174 if (rc) /* BB add auto retry on EOPNOTSUPP? */
4175 rc = -EIO;
4176 else if (!legacy && get_bcc(&pSMBr->hdr) < 40)
4177 rc = -EIO; /* bad smb */
4178 else if (legacy && get_bcc(&pSMBr->hdr) < 24)
4179 rc = -EIO; /* 24 or 26 expected but we do not read
4180 last field */
4181 else if (data) {
4182 int size;
4183 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4184
4185 /*
4186 * On legacy responses we do not read the last field,
4187 * EAsize, fortunately since it varies by subdialect and
4188 * also note it differs on Set vs Get, ie two bytes or 4
4189 * bytes depending but we don't care here.
4190 */
4191 if (legacy)
4192 size = sizeof(FILE_INFO_STANDARD);
4193 else
4194 size = sizeof(FILE_ALL_INFO);
4195 memcpy((char *) data, (char *) &pSMBr->hdr.Protocol +
4196 data_offset, size);
4197 } else
4198 rc = -ENOMEM;
4199 }
4200 cifs_buf_release(pSMB);
4201 if (rc == -EAGAIN)
4202 goto QPathInfoRetry;
4203
4204 return rc;
4205}
4206
4207int
4208CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
4209 u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
4210{
4211 struct smb_t2_qfi_req *pSMB = NULL;
4212 struct smb_t2_qfi_rsp *pSMBr = NULL;
4213 int rc = 0;
4214 int bytes_returned;
4215 __u16 params, byte_count;
4216
4217UnixQFileInfoRetry:
4218 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4219 (void **) &pSMBr);
4220 if (rc)
4221 return rc;
4222
4223 params = 2 /* level */ + 2 /* fid */;
4224 pSMB->t2.TotalDataCount = 0;
4225 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
4226 /* BB find exact max data count below from sess structure BB */
4227 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
4228 pSMB->t2.MaxSetupCount = 0;
4229 pSMB->t2.Reserved = 0;
4230 pSMB->t2.Flags = 0;
4231 pSMB->t2.Timeout = 0;
4232 pSMB->t2.Reserved2 = 0;
4233 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
4234 Fid) - 4);
4235 pSMB->t2.DataCount = 0;
4236 pSMB->t2.DataOffset = 0;
4237 pSMB->t2.SetupCount = 1;
4238 pSMB->t2.Reserved3 = 0;
4239 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
4240 byte_count = params + 1 /* pad */ ;
4241 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
4242 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
4243 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4244 pSMB->Pad = 0;
4245 pSMB->Fid = netfid;
4246 inc_rfc1001_len(pSMB, byte_count);
4247 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
4248
4249 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4250 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4251 if (rc) {
4252 cifs_dbg(FYI, "Send error in UnixQFileInfo = %d", rc);
4253 } else { /* decode response */
4254 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4255
4256 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4257 cifs_dbg(VFS, "Malformed FILE_UNIX_BASIC_INFO response. Unix Extensions can be disabled on mount by specifying the nosfu mount option.\n");
4258 rc = -EIO; /* bad smb */
4259 } else {
4260 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4261 memcpy((char *) pFindData,
4262 (char *) &pSMBr->hdr.Protocol +
4263 data_offset,
4264 sizeof(FILE_UNIX_BASIC_INFO));
4265 }
4266 }
4267
4268 cifs_buf_release(pSMB);
4269 if (rc == -EAGAIN)
4270 goto UnixQFileInfoRetry;
4271
4272 return rc;
4273}
4274
4275int
4276CIFSSMBUnixQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
4277 const unsigned char *searchName,
4278 FILE_UNIX_BASIC_INFO *pFindData,
4279 const struct nls_table *nls_codepage, int remap)
4280{
4281/* SMB_QUERY_FILE_UNIX_BASIC */
4282 TRANSACTION2_QPI_REQ *pSMB = NULL;
4283 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4284 int rc = 0;
4285 int bytes_returned = 0;
4286 int name_len;
4287 __u16 params, byte_count;
4288
4289 cifs_dbg(FYI, "In QPathInfo (Unix) the path %s\n", searchName);
4290UnixQPathInfoRetry:
4291 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4292 (void **) &pSMBr);
4293 if (rc)
4294 return rc;
4295
4296 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4297 name_len =
4298 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4299 PATH_MAX, nls_codepage, remap);
4300 name_len++; /* trailing null */
4301 name_len *= 2;
4302 } else { /* BB improve the check for buffer overruns BB */
4303 name_len = strnlen(searchName, PATH_MAX);
4304 name_len++; /* trailing null */
4305 strncpy(pSMB->FileName, searchName, name_len);
4306 }
4307
4308 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4309 pSMB->TotalDataCount = 0;
4310 pSMB->MaxParameterCount = cpu_to_le16(2);
4311 /* BB find exact max SMB PDU from sess structure BB */
4312 pSMB->MaxDataCount = cpu_to_le16(4000);
4313 pSMB->MaxSetupCount = 0;
4314 pSMB->Reserved = 0;
4315 pSMB->Flags = 0;
4316 pSMB->Timeout = 0;
4317 pSMB->Reserved2 = 0;
4318 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4319 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4320 pSMB->DataCount = 0;
4321 pSMB->DataOffset = 0;
4322 pSMB->SetupCount = 1;
4323 pSMB->Reserved3 = 0;
4324 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4325 byte_count = params + 1 /* pad */ ;
4326 pSMB->TotalParameterCount = cpu_to_le16(params);
4327 pSMB->ParameterCount = pSMB->TotalParameterCount;
4328 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4329 pSMB->Reserved4 = 0;
4330 inc_rfc1001_len(pSMB, byte_count);
4331 pSMB->ByteCount = cpu_to_le16(byte_count);
4332
4333 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4334 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4335 if (rc) {
4336 cifs_dbg(FYI, "Send error in UnixQPathInfo = %d", rc);
4337 } else { /* decode response */
4338 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4339
4340 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4341 cifs_dbg(VFS, "Malformed FILE_UNIX_BASIC_INFO response. Unix Extensions can be disabled on mount by specifying the nosfu mount option.\n");
4342 rc = -EIO; /* bad smb */
4343 } else {
4344 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4345 memcpy((char *) pFindData,
4346 (char *) &pSMBr->hdr.Protocol +
4347 data_offset,
4348 sizeof(FILE_UNIX_BASIC_INFO));
4349 }
4350 }
4351 cifs_buf_release(pSMB);
4352 if (rc == -EAGAIN)
4353 goto UnixQPathInfoRetry;
4354
4355 return rc;
4356}
4357
4358/* xid, tcon, searchName and codepage are input parms, rest are returned */
4359int
4360CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon,
4361 const char *searchName, struct cifs_sb_info *cifs_sb,
4362 __u16 *pnetfid, __u16 search_flags,
4363 struct cifs_search_info *psrch_inf, bool msearch)
4364{
4365/* level 257 SMB_ */
4366 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
4367 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
4368 T2_FFIRST_RSP_PARMS *parms;
4369 int rc = 0;
4370 int bytes_returned = 0;
4371 int name_len, remap;
4372 __u16 params, byte_count;
4373 struct nls_table *nls_codepage;
4374
4375 cifs_dbg(FYI, "In FindFirst for %s\n", searchName);
4376
4377findFirstRetry:
4378 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4379 (void **) &pSMBr);
4380 if (rc)
4381 return rc;
4382
4383 nls_codepage = cifs_sb->local_nls;
4384 remap = cifs_remap(cifs_sb);
4385
4386 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4387 name_len =
4388 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4389 PATH_MAX, nls_codepage, remap);
4390 /* We can not add the asterik earlier in case
4391 it got remapped to 0xF03A as if it were part of the
4392 directory name instead of a wildcard */
4393 name_len *= 2;
4394 if (msearch) {
4395 pSMB->FileName[name_len] = CIFS_DIR_SEP(cifs_sb);
4396 pSMB->FileName[name_len+1] = 0;
4397 pSMB->FileName[name_len+2] = '*';
4398 pSMB->FileName[name_len+3] = 0;
4399 name_len += 4; /* now the trailing null */
4400 /* null terminate just in case */
4401 pSMB->FileName[name_len] = 0;
4402 pSMB->FileName[name_len+1] = 0;
4403 name_len += 2;
4404 }
4405 } else { /* BB add check for overrun of SMB buf BB */
4406 name_len = strnlen(searchName, PATH_MAX);
4407/* BB fix here and in unicode clause above ie
4408 if (name_len > buffersize-header)
4409 free buffer exit; BB */
4410 strncpy(pSMB->FileName, searchName, name_len);
4411 if (msearch) {
4412 pSMB->FileName[name_len] = CIFS_DIR_SEP(cifs_sb);
4413 pSMB->FileName[name_len+1] = '*';
4414 pSMB->FileName[name_len+2] = 0;
4415 name_len += 3;
4416 }
4417 }
4418
4419 params = 12 + name_len /* includes null */ ;
4420 pSMB->TotalDataCount = 0; /* no EAs */
4421 pSMB->MaxParameterCount = cpu_to_le16(10);
4422 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4423 pSMB->MaxSetupCount = 0;
4424 pSMB->Reserved = 0;
4425 pSMB->Flags = 0;
4426 pSMB->Timeout = 0;
4427 pSMB->Reserved2 = 0;
4428 byte_count = params + 1 /* pad */ ;
4429 pSMB->TotalParameterCount = cpu_to_le16(params);
4430 pSMB->ParameterCount = pSMB->TotalParameterCount;
4431 pSMB->ParameterOffset = cpu_to_le16(
4432 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
4433 - 4);
4434 pSMB->DataCount = 0;
4435 pSMB->DataOffset = 0;
4436 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
4437 pSMB->Reserved3 = 0;
4438 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
4439 pSMB->SearchAttributes =
4440 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
4441 ATTR_DIRECTORY);
4442 pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
4443 pSMB->SearchFlags = cpu_to_le16(search_flags);
4444 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4445
4446 /* BB what should we set StorageType to? Does it matter? BB */
4447 pSMB->SearchStorageType = 0;
4448 inc_rfc1001_len(pSMB, byte_count);
4449 pSMB->ByteCount = cpu_to_le16(byte_count);
4450
4451 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4452 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4453 cifs_stats_inc(&tcon->stats.cifs_stats.num_ffirst);
4454
4455 if (rc) {/* BB add logic to retry regular search if Unix search
4456 rejected unexpectedly by server */
4457 /* BB Add code to handle unsupported level rc */
4458 cifs_dbg(FYI, "Error in FindFirst = %d\n", rc);
4459
4460 cifs_buf_release(pSMB);
4461
4462 /* BB eventually could optimize out free and realloc of buf */
4463 /* for this case */
4464 if (rc == -EAGAIN)
4465 goto findFirstRetry;
4466 } else { /* decode response */
4467 /* BB remember to free buffer if error BB */
4468 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4469 if (rc == 0) {
4470 unsigned int lnoff;
4471
4472 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4473 psrch_inf->unicode = true;
4474 else
4475 psrch_inf->unicode = false;
4476
4477 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
4478 psrch_inf->smallBuf = 0;
4479 psrch_inf->srch_entries_start =
4480 (char *) &pSMBr->hdr.Protocol +
4481 le16_to_cpu(pSMBr->t2.DataOffset);
4482 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
4483 le16_to_cpu(pSMBr->t2.ParameterOffset));
4484
4485 if (parms->EndofSearch)
4486 psrch_inf->endOfSearch = true;
4487 else
4488 psrch_inf->endOfSearch = false;
4489
4490 psrch_inf->entries_in_buffer =
4491 le16_to_cpu(parms->SearchCount);
4492 psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
4493 psrch_inf->entries_in_buffer;
4494 lnoff = le16_to_cpu(parms->LastNameOffset);
4495 if (CIFSMaxBufSize < lnoff) {
4496 cifs_dbg(VFS, "ignoring corrupt resume name\n");
4497 psrch_inf->last_entry = NULL;
4498 return rc;
4499 }
4500
4501 psrch_inf->last_entry = psrch_inf->srch_entries_start +
4502 lnoff;
4503
4504 if (pnetfid)
4505 *pnetfid = parms->SearchHandle;
4506 } else {
4507 cifs_buf_release(pSMB);
4508 }
4509 }
4510
4511 return rc;
4512}
4513
4514int CIFSFindNext(const unsigned int xid, struct cifs_tcon *tcon,
4515 __u16 searchHandle, __u16 search_flags,
4516 struct cifs_search_info *psrch_inf)
4517{
4518 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
4519 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
4520 T2_FNEXT_RSP_PARMS *parms;
4521 char *response_data;
4522 int rc = 0;
4523 int bytes_returned;
4524 unsigned int name_len;
4525 __u16 params, byte_count;
4526
4527 cifs_dbg(FYI, "In FindNext\n");
4528
4529 if (psrch_inf->endOfSearch)
4530 return -ENOENT;
4531
4532 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4533 (void **) &pSMBr);
4534 if (rc)
4535 return rc;
4536
4537 params = 14; /* includes 2 bytes of null string, converted to LE below*/
4538 byte_count = 0;
4539 pSMB->TotalDataCount = 0; /* no EAs */
4540 pSMB->MaxParameterCount = cpu_to_le16(8);
4541 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4542 pSMB->MaxSetupCount = 0;
4543 pSMB->Reserved = 0;
4544 pSMB->Flags = 0;
4545 pSMB->Timeout = 0;
4546 pSMB->Reserved2 = 0;
4547 pSMB->ParameterOffset = cpu_to_le16(
4548 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
4549 pSMB->DataCount = 0;
4550 pSMB->DataOffset = 0;
4551 pSMB->SetupCount = 1;
4552 pSMB->Reserved3 = 0;
4553 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
4554 pSMB->SearchHandle = searchHandle; /* always kept as le */
4555 pSMB->SearchCount =
4556 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
4557 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4558 pSMB->ResumeKey = psrch_inf->resume_key;
4559 pSMB->SearchFlags = cpu_to_le16(search_flags);
4560
4561 name_len = psrch_inf->resume_name_len;
4562 params += name_len;
4563 if (name_len < PATH_MAX) {
4564 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
4565 byte_count += name_len;
4566 /* 14 byte parm len above enough for 2 byte null terminator */
4567 pSMB->ResumeFileName[name_len] = 0;
4568 pSMB->ResumeFileName[name_len+1] = 0;
4569 } else {
4570 rc = -EINVAL;
4571 goto FNext2_err_exit;
4572 }
4573 byte_count = params + 1 /* pad */ ;
4574 pSMB->TotalParameterCount = cpu_to_le16(params);
4575 pSMB->ParameterCount = pSMB->TotalParameterCount;
4576 inc_rfc1001_len(pSMB, byte_count);
4577 pSMB->ByteCount = cpu_to_le16(byte_count);
4578
4579 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4580 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4581 cifs_stats_inc(&tcon->stats.cifs_stats.num_fnext);
4582 if (rc) {
4583 if (rc == -EBADF) {
4584 psrch_inf->endOfSearch = true;
4585 cifs_buf_release(pSMB);
4586 rc = 0; /* search probably was closed at end of search*/
4587 } else
4588 cifs_dbg(FYI, "FindNext returned = %d\n", rc);
4589 } else { /* decode response */
4590 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4591
4592 if (rc == 0) {
4593 unsigned int lnoff;
4594
4595 /* BB fixme add lock for file (srch_info) struct here */
4596 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4597 psrch_inf->unicode = true;
4598 else
4599 psrch_inf->unicode = false;
4600 response_data = (char *) &pSMBr->hdr.Protocol +
4601 le16_to_cpu(pSMBr->t2.ParameterOffset);
4602 parms = (T2_FNEXT_RSP_PARMS *)response_data;
4603 response_data = (char *)&pSMBr->hdr.Protocol +
4604 le16_to_cpu(pSMBr->t2.DataOffset);
4605 if (psrch_inf->smallBuf)
4606 cifs_small_buf_release(
4607 psrch_inf->ntwrk_buf_start);
4608 else
4609 cifs_buf_release(psrch_inf->ntwrk_buf_start);
4610 psrch_inf->srch_entries_start = response_data;
4611 psrch_inf->ntwrk_buf_start = (char *)pSMB;
4612 psrch_inf->smallBuf = 0;
4613 if (parms->EndofSearch)
4614 psrch_inf->endOfSearch = true;
4615 else
4616 psrch_inf->endOfSearch = false;
4617 psrch_inf->entries_in_buffer =
4618 le16_to_cpu(parms->SearchCount);
4619 psrch_inf->index_of_last_entry +=
4620 psrch_inf->entries_in_buffer;
4621 lnoff = le16_to_cpu(parms->LastNameOffset);
4622 if (CIFSMaxBufSize < lnoff) {
4623 cifs_dbg(VFS, "ignoring corrupt resume name\n");
4624 psrch_inf->last_entry = NULL;
4625 return rc;
4626 } else
4627 psrch_inf->last_entry =
4628 psrch_inf->srch_entries_start + lnoff;
4629
4630/* cifs_dbg(FYI, "fnxt2 entries in buf %d index_of_last %d\n",
4631 psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
4632
4633 /* BB fixme add unlock here */
4634 }
4635
4636 }
4637
4638 /* BB On error, should we leave previous search buf (and count and
4639 last entry fields) intact or free the previous one? */
4640
4641 /* Note: On -EAGAIN error only caller can retry on handle based calls
4642 since file handle passed in no longer valid */
4643FNext2_err_exit:
4644 if (rc != 0)
4645 cifs_buf_release(pSMB);
4646 return rc;
4647}
4648
4649int
4650CIFSFindClose(const unsigned int xid, struct cifs_tcon *tcon,
4651 const __u16 searchHandle)
4652{
4653 int rc = 0;
4654 FINDCLOSE_REQ *pSMB = NULL;
4655
4656 cifs_dbg(FYI, "In CIFSSMBFindClose\n");
4657 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
4658
4659 /* no sense returning error if session restarted
4660 as file handle has been closed */
4661 if (rc == -EAGAIN)
4662 return 0;
4663 if (rc)
4664 return rc;
4665
4666 pSMB->FileID = searchHandle;
4667 pSMB->ByteCount = 0;
4668 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
4669 if (rc)
4670 cifs_dbg(VFS, "Send error in FindClose = %d\n", rc);
4671
4672 cifs_stats_inc(&tcon->stats.cifs_stats.num_fclose);
4673
4674 /* Since session is dead, search handle closed on server already */
4675 if (rc == -EAGAIN)
4676 rc = 0;
4677
4678 return rc;
4679}
4680
4681int
4682CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon,
4683 const char *search_name, __u64 *inode_number,
4684 const struct nls_table *nls_codepage, int remap)
4685{
4686 int rc = 0;
4687 TRANSACTION2_QPI_REQ *pSMB = NULL;
4688 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4689 int name_len, bytes_returned;
4690 __u16 params, byte_count;
4691
4692 cifs_dbg(FYI, "In GetSrvInodeNum for %s\n", search_name);
4693 if (tcon == NULL)
4694 return -ENODEV;
4695
4696GetInodeNumberRetry:
4697 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4698 (void **) &pSMBr);
4699 if (rc)
4700 return rc;
4701
4702 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4703 name_len =
4704 cifsConvertToUTF16((__le16 *) pSMB->FileName,
4705 search_name, PATH_MAX, nls_codepage,
4706 remap);
4707 name_len++; /* trailing null */
4708 name_len *= 2;
4709 } else { /* BB improve the check for buffer overruns BB */
4710 name_len = strnlen(search_name, PATH_MAX);
4711 name_len++; /* trailing null */
4712 strncpy(pSMB->FileName, search_name, name_len);
4713 }
4714
4715 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
4716 pSMB->TotalDataCount = 0;
4717 pSMB->MaxParameterCount = cpu_to_le16(2);
4718 /* BB find exact max data count below from sess structure BB */
4719 pSMB->MaxDataCount = cpu_to_le16(4000);
4720 pSMB->MaxSetupCount = 0;
4721 pSMB->Reserved = 0;
4722 pSMB->Flags = 0;
4723 pSMB->Timeout = 0;
4724 pSMB->Reserved2 = 0;
4725 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4726 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4727 pSMB->DataCount = 0;
4728 pSMB->DataOffset = 0;
4729 pSMB->SetupCount = 1;
4730 pSMB->Reserved3 = 0;
4731 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4732 byte_count = params + 1 /* pad */ ;
4733 pSMB->TotalParameterCount = cpu_to_le16(params);
4734 pSMB->ParameterCount = pSMB->TotalParameterCount;
4735 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
4736 pSMB->Reserved4 = 0;
4737 inc_rfc1001_len(pSMB, byte_count);
4738 pSMB->ByteCount = cpu_to_le16(byte_count);
4739
4740 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4741 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4742 if (rc) {
4743 cifs_dbg(FYI, "error %d in QueryInternalInfo\n", rc);
4744 } else {
4745 /* decode response */
4746 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4747 /* BB also check enough total bytes returned */
4748 if (rc || get_bcc(&pSMBr->hdr) < 2)
4749 /* If rc should we check for EOPNOSUPP and
4750 disable the srvino flag? or in caller? */
4751 rc = -EIO; /* bad smb */
4752 else {
4753 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4754 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
4755 struct file_internal_info *pfinfo;
4756 /* BB Do we need a cast or hash here ? */
4757 if (count < 8) {
4758 cifs_dbg(FYI, "Illegal size ret in QryIntrnlInf\n");
4759 rc = -EIO;
4760 goto GetInodeNumOut;
4761 }
4762 pfinfo = (struct file_internal_info *)
4763 (data_offset + (char *) &pSMBr->hdr.Protocol);
4764 *inode_number = le64_to_cpu(pfinfo->UniqueId);
4765 }
4766 }
4767GetInodeNumOut:
4768 cifs_buf_release(pSMB);
4769 if (rc == -EAGAIN)
4770 goto GetInodeNumberRetry;
4771 return rc;
4772}
4773
4774/* parses DFS refferal V3 structure
4775 * caller is responsible for freeing target_nodes
4776 * returns:
4777 * on success - 0
4778 * on failure - errno
4779 */
4780static int
4781parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
4782 unsigned int *num_of_nodes,
4783 struct dfs_info3_param **target_nodes,
4784 const struct nls_table *nls_codepage, int remap,
4785 const char *searchName)
4786{
4787 int i, rc = 0;
4788 char *data_end;
4789 bool is_unicode;
4790 struct dfs_referral_level_3 *ref;
4791
4792 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4793 is_unicode = true;
4794 else
4795 is_unicode = false;
4796 *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
4797
4798 if (*num_of_nodes < 1) {
4799 cifs_dbg(VFS, "num_referrals: must be at least > 0, but we get num_referrals = %d\n",
4800 *num_of_nodes);
4801 rc = -EINVAL;
4802 goto parse_DFS_referrals_exit;
4803 }
4804
4805 ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
4806 if (ref->VersionNumber != cpu_to_le16(3)) {
4807 cifs_dbg(VFS, "Referrals of V%d version are not supported, should be V3\n",
4808 le16_to_cpu(ref->VersionNumber));
4809 rc = -EINVAL;
4810 goto parse_DFS_referrals_exit;
4811 }
4812
4813 /* get the upper boundary of the resp buffer */
4814 data_end = (char *)(&(pSMBr->PathConsumed)) +
4815 le16_to_cpu(pSMBr->t2.DataCount);
4816
4817 cifs_dbg(FYI, "num_referrals: %d dfs flags: 0x%x ...\n",
4818 *num_of_nodes, le32_to_cpu(pSMBr->DFSFlags));
4819
4820 *target_nodes = kcalloc(*num_of_nodes, sizeof(struct dfs_info3_param),
4821 GFP_KERNEL);
4822 if (*target_nodes == NULL) {
4823 rc = -ENOMEM;
4824 goto parse_DFS_referrals_exit;
4825 }
4826
4827 /* collect necessary data from referrals */
4828 for (i = 0; i < *num_of_nodes; i++) {
4829 char *temp;
4830 int max_len;
4831 struct dfs_info3_param *node = (*target_nodes)+i;
4832
4833 node->flags = le32_to_cpu(pSMBr->DFSFlags);
4834 if (is_unicode) {
4835 __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
4836 GFP_KERNEL);
4837 if (tmp == NULL) {
4838 rc = -ENOMEM;
4839 goto parse_DFS_referrals_exit;
4840 }
4841 cifsConvertToUTF16((__le16 *) tmp, searchName,
4842 PATH_MAX, nls_codepage, remap);
4843 node->path_consumed = cifs_utf16_bytes(tmp,
4844 le16_to_cpu(pSMBr->PathConsumed),
4845 nls_codepage);
4846 kfree(tmp);
4847 } else
4848 node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
4849
4850 node->server_type = le16_to_cpu(ref->ServerType);
4851 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
4852
4853 /* copy DfsPath */
4854 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
4855 max_len = data_end - temp;
4856 node->path_name = cifs_strndup_from_utf16(temp, max_len,
4857 is_unicode, nls_codepage);
4858 if (!node->path_name) {
4859 rc = -ENOMEM;
4860 goto parse_DFS_referrals_exit;
4861 }
4862
4863 /* copy link target UNC */
4864 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
4865 max_len = data_end - temp;
4866 node->node_name = cifs_strndup_from_utf16(temp, max_len,
4867 is_unicode, nls_codepage);
4868 if (!node->node_name) {
4869 rc = -ENOMEM;
4870 goto parse_DFS_referrals_exit;
4871 }
4872
4873 ref++;
4874 }
4875
4876parse_DFS_referrals_exit:
4877 if (rc) {
4878 free_dfs_info_array(*target_nodes, *num_of_nodes);
4879 *target_nodes = NULL;
4880 *num_of_nodes = 0;
4881 }
4882 return rc;
4883}
4884
4885int
4886CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses,
4887 const char *search_name, struct dfs_info3_param **target_nodes,
4888 unsigned int *num_of_nodes,
4889 const struct nls_table *nls_codepage, int remap)
4890{
4891/* TRANS2_GET_DFS_REFERRAL */
4892 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4893 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4894 int rc = 0;
4895 int bytes_returned;
4896 int name_len;
4897 __u16 params, byte_count;
4898 *num_of_nodes = 0;
4899 *target_nodes = NULL;
4900
4901 cifs_dbg(FYI, "In GetDFSRefer the path %s\n", search_name);
4902 if (ses == NULL)
4903 return -ENODEV;
4904getDFSRetry:
4905 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4906 (void **) &pSMBr);
4907 if (rc)
4908 return rc;
4909
4910 /* server pointer checked in called function,
4911 but should never be null here anyway */
4912 pSMB->hdr.Mid = get_next_mid(ses->server);
4913 pSMB->hdr.Tid = ses->ipc_tid;
4914 pSMB->hdr.Uid = ses->Suid;
4915 if (ses->capabilities & CAP_STATUS32)
4916 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4917 if (ses->capabilities & CAP_DFS)
4918 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4919
4920 if (ses->capabilities & CAP_UNICODE) {
4921 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4922 name_len =
4923 cifsConvertToUTF16((__le16 *) pSMB->RequestFileName,
4924 search_name, PATH_MAX, nls_codepage,
4925 remap);
4926 name_len++; /* trailing null */
4927 name_len *= 2;
4928 } else { /* BB improve the check for buffer overruns BB */
4929 name_len = strnlen(search_name, PATH_MAX);
4930 name_len++; /* trailing null */
4931 strncpy(pSMB->RequestFileName, search_name, name_len);
4932 }
4933
4934 if (ses->server->sign)
4935 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4936
4937 pSMB->hdr.Uid = ses->Suid;
4938
4939 params = 2 /* level */ + name_len /*includes null */ ;
4940 pSMB->TotalDataCount = 0;
4941 pSMB->DataCount = 0;
4942 pSMB->DataOffset = 0;
4943 pSMB->MaxParameterCount = 0;
4944 /* BB find exact max SMB PDU from sess structure BB */
4945 pSMB->MaxDataCount = cpu_to_le16(4000);
4946 pSMB->MaxSetupCount = 0;
4947 pSMB->Reserved = 0;
4948 pSMB->Flags = 0;
4949 pSMB->Timeout = 0;
4950 pSMB->Reserved2 = 0;
4951 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4952 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4953 pSMB->SetupCount = 1;
4954 pSMB->Reserved3 = 0;
4955 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4956 byte_count = params + 3 /* pad */ ;
4957 pSMB->ParameterCount = cpu_to_le16(params);
4958 pSMB->TotalParameterCount = pSMB->ParameterCount;
4959 pSMB->MaxReferralLevel = cpu_to_le16(3);
4960 inc_rfc1001_len(pSMB, byte_count);
4961 pSMB->ByteCount = cpu_to_le16(byte_count);
4962
4963 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4964 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4965 if (rc) {
4966 cifs_dbg(FYI, "Send error in GetDFSRefer = %d\n", rc);
4967 goto GetDFSRefExit;
4968 }
4969 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4970
4971 /* BB Also check if enough total bytes returned? */
4972 if (rc || get_bcc(&pSMBr->hdr) < 17) {
4973 rc = -EIO; /* bad smb */
4974 goto GetDFSRefExit;
4975 }
4976
4977 cifs_dbg(FYI, "Decoding GetDFSRefer response BCC: %d Offset %d\n",
4978 get_bcc(&pSMBr->hdr), le16_to_cpu(pSMBr->t2.DataOffset));
4979
4980 /* parse returned result into more usable form */
4981 rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4982 target_nodes, nls_codepage, remap,
4983 search_name);
4984
4985GetDFSRefExit:
4986 cifs_buf_release(pSMB);
4987
4988 if (rc == -EAGAIN)
4989 goto getDFSRetry;
4990
4991 return rc;
4992}
4993
4994/* Query File System Info such as free space to old servers such as Win 9x */
4995int
4996SMBOldQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
4997 struct kstatfs *FSData)
4998{
4999/* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
5000 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5001 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5002 FILE_SYSTEM_ALLOC_INFO *response_data;
5003 int rc = 0;
5004 int bytes_returned = 0;
5005 __u16 params, byte_count;
5006
5007 cifs_dbg(FYI, "OldQFSInfo\n");
5008oldQFSInfoRetry:
5009 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5010 (void **) &pSMBr);
5011 if (rc)
5012 return rc;
5013
5014 params = 2; /* level */
5015 pSMB->TotalDataCount = 0;
5016 pSMB->MaxParameterCount = cpu_to_le16(2);
5017 pSMB->MaxDataCount = cpu_to_le16(1000);
5018 pSMB->MaxSetupCount = 0;
5019 pSMB->Reserved = 0;
5020 pSMB->Flags = 0;
5021 pSMB->Timeout = 0;
5022 pSMB->Reserved2 = 0;
5023 byte_count = params + 1 /* pad */ ;
5024 pSMB->TotalParameterCount = cpu_to_le16(params);
5025 pSMB->ParameterCount = pSMB->TotalParameterCount;
5026 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5027 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5028 pSMB->DataCount = 0;
5029 pSMB->DataOffset = 0;
5030 pSMB->SetupCount = 1;
5031 pSMB->Reserved3 = 0;
5032 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5033 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
5034 inc_rfc1001_len(pSMB, byte_count);
5035 pSMB->ByteCount = cpu_to_le16(byte_count);
5036
5037 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5038 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5039 if (rc) {
5040 cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);
5041 } else { /* decode response */
5042 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5043
5044 if (rc || get_bcc(&pSMBr->hdr) < 18)
5045 rc = -EIO; /* bad smb */
5046 else {
5047 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5048 cifs_dbg(FYI, "qfsinf resp BCC: %d Offset %d\n",
5049 get_bcc(&pSMBr->hdr), data_offset);
5050
5051 response_data = (FILE_SYSTEM_ALLOC_INFO *)
5052 (((char *) &pSMBr->hdr.Protocol) + data_offset);
5053 FSData->f_bsize =
5054 le16_to_cpu(response_data->BytesPerSector) *
5055 le32_to_cpu(response_data->
5056 SectorsPerAllocationUnit);
5057 FSData->f_blocks =
5058 le32_to_cpu(response_data->TotalAllocationUnits);
5059 FSData->f_bfree = FSData->f_bavail =
5060 le32_to_cpu(response_data->FreeAllocationUnits);
5061 cifs_dbg(FYI, "Blocks: %lld Free: %lld Block size %ld\n",
5062 (unsigned long long)FSData->f_blocks,
5063 (unsigned long long)FSData->f_bfree,
5064 FSData->f_bsize);
5065 }
5066 }
5067 cifs_buf_release(pSMB);
5068
5069 if (rc == -EAGAIN)
5070 goto oldQFSInfoRetry;
5071
5072 return rc;
5073}
5074
5075int
5076CIFSSMBQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
5077 struct kstatfs *FSData)
5078{
5079/* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
5080 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5081 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5082 FILE_SYSTEM_INFO *response_data;
5083 int rc = 0;
5084 int bytes_returned = 0;
5085 __u16 params, byte_count;
5086
5087 cifs_dbg(FYI, "In QFSInfo\n");
5088QFSInfoRetry:
5089 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5090 (void **) &pSMBr);
5091 if (rc)
5092 return rc;
5093
5094 params = 2; /* level */
5095 pSMB->TotalDataCount = 0;
5096 pSMB->MaxParameterCount = cpu_to_le16(2);
5097 pSMB->MaxDataCount = cpu_to_le16(1000);
5098 pSMB->MaxSetupCount = 0;
5099 pSMB->Reserved = 0;
5100 pSMB->Flags = 0;
5101 pSMB->Timeout = 0;
5102 pSMB->Reserved2 = 0;
5103 byte_count = params + 1 /* pad */ ;
5104 pSMB->TotalParameterCount = cpu_to_le16(params);
5105 pSMB->ParameterCount = pSMB->TotalParameterCount;
5106 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5107 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5108 pSMB->DataCount = 0;
5109 pSMB->DataOffset = 0;
5110 pSMB->SetupCount = 1;
5111 pSMB->Reserved3 = 0;
5112 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5113 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
5114 inc_rfc1001_len(pSMB, byte_count);
5115 pSMB->ByteCount = cpu_to_le16(byte_count);
5116
5117 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5118 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5119 if (rc) {
5120 cifs_dbg(FYI, "Send error in QFSInfo = %d\n", rc);
5121 } else { /* decode response */
5122 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5123
5124 if (rc || get_bcc(&pSMBr->hdr) < 24)
5125 rc = -EIO; /* bad smb */
5126 else {
5127 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5128
5129 response_data =
5130 (FILE_SYSTEM_INFO
5131 *) (((char *) &pSMBr->hdr.Protocol) +
5132 data_offset);
5133 FSData->f_bsize =
5134 le32_to_cpu(response_data->BytesPerSector) *
5135 le32_to_cpu(response_data->
5136 SectorsPerAllocationUnit);
5137 FSData->f_blocks =
5138 le64_to_cpu(response_data->TotalAllocationUnits);
5139 FSData->f_bfree = FSData->f_bavail =
5140 le64_to_cpu(response_data->FreeAllocationUnits);
5141 cifs_dbg(FYI, "Blocks: %lld Free: %lld Block size %ld\n",
5142 (unsigned long long)FSData->f_blocks,
5143 (unsigned long long)FSData->f_bfree,
5144 FSData->f_bsize);
5145 }
5146 }
5147 cifs_buf_release(pSMB);
5148
5149 if (rc == -EAGAIN)
5150 goto QFSInfoRetry;
5151
5152 return rc;
5153}
5154
5155int
5156CIFSSMBQFSAttributeInfo(const unsigned int xid, struct cifs_tcon *tcon)
5157{
5158/* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
5159 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5160 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5161 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
5162 int rc = 0;
5163 int bytes_returned = 0;
5164 __u16 params, byte_count;
5165
5166 cifs_dbg(FYI, "In QFSAttributeInfo\n");
5167QFSAttributeRetry:
5168 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5169 (void **) &pSMBr);
5170 if (rc)
5171 return rc;
5172
5173 params = 2; /* level */
5174 pSMB->TotalDataCount = 0;
5175 pSMB->MaxParameterCount = cpu_to_le16(2);
5176 /* BB find exact max SMB PDU from sess structure BB */
5177 pSMB->MaxDataCount = cpu_to_le16(1000);
5178 pSMB->MaxSetupCount = 0;
5179 pSMB->Reserved = 0;
5180 pSMB->Flags = 0;
5181 pSMB->Timeout = 0;
5182 pSMB->Reserved2 = 0;
5183 byte_count = params + 1 /* pad */ ;
5184 pSMB->TotalParameterCount = cpu_to_le16(params);
5185 pSMB->ParameterCount = pSMB->TotalParameterCount;
5186 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5187 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5188 pSMB->DataCount = 0;
5189 pSMB->DataOffset = 0;
5190 pSMB->SetupCount = 1;
5191 pSMB->Reserved3 = 0;
5192 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5193 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
5194 inc_rfc1001_len(pSMB, byte_count);
5195 pSMB->ByteCount = cpu_to_le16(byte_count);
5196
5197 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5198 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5199 if (rc) {
5200 cifs_dbg(VFS, "Send error in QFSAttributeInfo = %d\n", rc);
5201 } else { /* decode response */
5202 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5203
5204 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5205 /* BB also check if enough bytes returned */
5206 rc = -EIO; /* bad smb */
5207 } else {
5208 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5209 response_data =
5210 (FILE_SYSTEM_ATTRIBUTE_INFO
5211 *) (((char *) &pSMBr->hdr.Protocol) +
5212 data_offset);
5213 memcpy(&tcon->fsAttrInfo, response_data,
5214 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
5215 }
5216 }
5217 cifs_buf_release(pSMB);
5218
5219 if (rc == -EAGAIN)
5220 goto QFSAttributeRetry;
5221
5222 return rc;
5223}
5224
5225int
5226CIFSSMBQFSDeviceInfo(const unsigned int xid, struct cifs_tcon *tcon)
5227{
5228/* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
5229 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5230 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5231 FILE_SYSTEM_DEVICE_INFO *response_data;
5232 int rc = 0;
5233 int bytes_returned = 0;
5234 __u16 params, byte_count;
5235
5236 cifs_dbg(FYI, "In QFSDeviceInfo\n");
5237QFSDeviceRetry:
5238 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5239 (void **) &pSMBr);
5240 if (rc)
5241 return rc;
5242
5243 params = 2; /* level */
5244 pSMB->TotalDataCount = 0;
5245 pSMB->MaxParameterCount = cpu_to_le16(2);
5246 /* BB find exact max SMB PDU from sess structure BB */
5247 pSMB->MaxDataCount = cpu_to_le16(1000);
5248 pSMB->MaxSetupCount = 0;
5249 pSMB->Reserved = 0;
5250 pSMB->Flags = 0;
5251 pSMB->Timeout = 0;
5252 pSMB->Reserved2 = 0;
5253 byte_count = params + 1 /* pad */ ;
5254 pSMB->TotalParameterCount = cpu_to_le16(params);
5255 pSMB->ParameterCount = pSMB->TotalParameterCount;
5256 pSMB->ParameterOffset = cpu_to_le16(offsetof(
5257 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5258
5259 pSMB->DataCount = 0;
5260 pSMB->DataOffset = 0;
5261 pSMB->SetupCount = 1;
5262 pSMB->Reserved3 = 0;
5263 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5264 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
5265 inc_rfc1001_len(pSMB, byte_count);
5266 pSMB->ByteCount = cpu_to_le16(byte_count);
5267
5268 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5269 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5270 if (rc) {
5271 cifs_dbg(FYI, "Send error in QFSDeviceInfo = %d\n", rc);
5272 } else { /* decode response */
5273 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5274
5275 if (rc || get_bcc(&pSMBr->hdr) <
5276 sizeof(FILE_SYSTEM_DEVICE_INFO))
5277 rc = -EIO; /* bad smb */
5278 else {
5279 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5280 response_data =
5281 (FILE_SYSTEM_DEVICE_INFO *)
5282 (((char *) &pSMBr->hdr.Protocol) +
5283 data_offset);
5284 memcpy(&tcon->fsDevInfo, response_data,
5285 sizeof(FILE_SYSTEM_DEVICE_INFO));
5286 }
5287 }
5288 cifs_buf_release(pSMB);
5289
5290 if (rc == -EAGAIN)
5291 goto QFSDeviceRetry;
5292
5293 return rc;
5294}
5295
5296int
5297CIFSSMBQFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon)
5298{
5299/* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
5300 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5301 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5302 FILE_SYSTEM_UNIX_INFO *response_data;
5303 int rc = 0;
5304 int bytes_returned = 0;
5305 __u16 params, byte_count;
5306
5307 cifs_dbg(FYI, "In QFSUnixInfo\n");
5308QFSUnixRetry:
5309 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5310 (void **) &pSMB, (void **) &pSMBr);
5311 if (rc)
5312 return rc;
5313
5314 params = 2; /* level */
5315 pSMB->TotalDataCount = 0;
5316 pSMB->DataCount = 0;
5317 pSMB->DataOffset = 0;
5318 pSMB->MaxParameterCount = cpu_to_le16(2);
5319 /* BB find exact max SMB PDU from sess structure BB */
5320 pSMB->MaxDataCount = cpu_to_le16(100);
5321 pSMB->MaxSetupCount = 0;
5322 pSMB->Reserved = 0;
5323 pSMB->Flags = 0;
5324 pSMB->Timeout = 0;
5325 pSMB->Reserved2 = 0;
5326 byte_count = params + 1 /* pad */ ;
5327 pSMB->ParameterCount = cpu_to_le16(params);
5328 pSMB->TotalParameterCount = pSMB->ParameterCount;
5329 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5330 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5331 pSMB->SetupCount = 1;
5332 pSMB->Reserved3 = 0;
5333 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5334 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
5335 inc_rfc1001_len(pSMB, byte_count);
5336 pSMB->ByteCount = cpu_to_le16(byte_count);
5337
5338 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5339 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5340 if (rc) {
5341 cifs_dbg(VFS, "Send error in QFSUnixInfo = %d\n", rc);
5342 } else { /* decode response */
5343 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5344
5345 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5346 rc = -EIO; /* bad smb */
5347 } else {
5348 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5349 response_data =
5350 (FILE_SYSTEM_UNIX_INFO
5351 *) (((char *) &pSMBr->hdr.Protocol) +
5352 data_offset);
5353 memcpy(&tcon->fsUnixInfo, response_data,
5354 sizeof(FILE_SYSTEM_UNIX_INFO));
5355 }
5356 }
5357 cifs_buf_release(pSMB);
5358
5359 if (rc == -EAGAIN)
5360 goto QFSUnixRetry;
5361
5362
5363 return rc;
5364}
5365
5366int
5367CIFSSMBSetFSUnixInfo(const unsigned int xid, struct cifs_tcon *tcon, __u64 cap)
5368{
5369/* level 0x200 SMB_SET_CIFS_UNIX_INFO */
5370 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
5371 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
5372 int rc = 0;
5373 int bytes_returned = 0;
5374 __u16 params, param_offset, offset, byte_count;
5375
5376 cifs_dbg(FYI, "In SETFSUnixInfo\n");
5377SETFSUnixRetry:
5378 /* BB switch to small buf init to save memory */
5379 rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5380 (void **) &pSMB, (void **) &pSMBr);
5381 if (rc)
5382 return rc;
5383
5384 params = 4; /* 2 bytes zero followed by info level. */
5385 pSMB->MaxSetupCount = 0;
5386 pSMB->Reserved = 0;
5387 pSMB->Flags = 0;
5388 pSMB->Timeout = 0;
5389 pSMB->Reserved2 = 0;
5390 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
5391 - 4;
5392 offset = param_offset + params;
5393
5394 pSMB->MaxParameterCount = cpu_to_le16(4);
5395 /* BB find exact max SMB PDU from sess structure BB */
5396 pSMB->MaxDataCount = cpu_to_le16(100);
5397 pSMB->SetupCount = 1;
5398 pSMB->Reserved3 = 0;
5399 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
5400 byte_count = 1 /* pad */ + params + 12;
5401
5402 pSMB->DataCount = cpu_to_le16(12);
5403 pSMB->ParameterCount = cpu_to_le16(params);
5404 pSMB->TotalDataCount = pSMB->DataCount;
5405 pSMB->TotalParameterCount = pSMB->ParameterCount;
5406 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5407 pSMB->DataOffset = cpu_to_le16(offset);
5408
5409 /* Params. */
5410 pSMB->FileNum = 0;
5411 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
5412
5413 /* Data. */
5414 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
5415 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
5416 pSMB->ClientUnixCap = cpu_to_le64(cap);
5417
5418 inc_rfc1001_len(pSMB, byte_count);
5419 pSMB->ByteCount = cpu_to_le16(byte_count);
5420
5421 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5422 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5423 if (rc) {
5424 cifs_dbg(VFS, "Send error in SETFSUnixInfo = %d\n", rc);
5425 } else { /* decode response */
5426 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5427 if (rc)
5428 rc = -EIO; /* bad smb */
5429 }
5430 cifs_buf_release(pSMB);
5431
5432 if (rc == -EAGAIN)
5433 goto SETFSUnixRetry;
5434
5435 return rc;
5436}
5437
5438
5439
5440int
5441CIFSSMBQFSPosixInfo(const unsigned int xid, struct cifs_tcon *tcon,
5442 struct kstatfs *FSData)
5443{
5444/* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
5445 TRANSACTION2_QFSI_REQ *pSMB = NULL;
5446 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5447 FILE_SYSTEM_POSIX_INFO *response_data;
5448 int rc = 0;
5449 int bytes_returned = 0;
5450 __u16 params, byte_count;
5451
5452 cifs_dbg(FYI, "In QFSPosixInfo\n");
5453QFSPosixRetry:
5454 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5455 (void **) &pSMBr);
5456 if (rc)
5457 return rc;
5458
5459 params = 2; /* level */
5460 pSMB->TotalDataCount = 0;
5461 pSMB->DataCount = 0;
5462 pSMB->DataOffset = 0;
5463 pSMB->MaxParameterCount = cpu_to_le16(2);
5464 /* BB find exact max SMB PDU from sess structure BB */
5465 pSMB->MaxDataCount = cpu_to_le16(100);
5466 pSMB->MaxSetupCount = 0;
5467 pSMB->Reserved = 0;
5468 pSMB->Flags = 0;
5469 pSMB->Timeout = 0;
5470 pSMB->Reserved2 = 0;
5471 byte_count = params + 1 /* pad */ ;
5472 pSMB->ParameterCount = cpu_to_le16(params);
5473 pSMB->TotalParameterCount = pSMB->ParameterCount;
5474 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5475 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5476 pSMB->SetupCount = 1;
5477 pSMB->Reserved3 = 0;
5478 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5479 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
5480 inc_rfc1001_len(pSMB, byte_count);
5481 pSMB->ByteCount = cpu_to_le16(byte_count);
5482
5483 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5484 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5485 if (rc) {
5486 cifs_dbg(FYI, "Send error in QFSUnixInfo = %d\n", rc);
5487 } else { /* decode response */
5488 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5489
5490 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5491 rc = -EIO; /* bad smb */
5492 } else {
5493 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5494 response_data =
5495 (FILE_SYSTEM_POSIX_INFO
5496 *) (((char *) &pSMBr->hdr.Protocol) +
5497 data_offset);
5498 FSData->f_bsize =
5499 le32_to_cpu(response_data->BlockSize);
5500 FSData->f_blocks =
5501 le64_to_cpu(response_data->TotalBlocks);
5502 FSData->f_bfree =
5503 le64_to_cpu(response_data->BlocksAvail);
5504 if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
5505 FSData->f_bavail = FSData->f_bfree;
5506 } else {
5507 FSData->f_bavail =
5508 le64_to_cpu(response_data->UserBlocksAvail);
5509 }
5510 if (response_data->TotalFileNodes != cpu_to_le64(-1))
5511 FSData->f_files =
5512 le64_to_cpu(response_data->TotalFileNodes);
5513 if (response_data->FreeFileNodes != cpu_to_le64(-1))
5514 FSData->f_ffree =
5515 le64_to_cpu(response_data->FreeFileNodes);
5516 }
5517 }
5518 cifs_buf_release(pSMB);
5519
5520 if (rc == -EAGAIN)
5521 goto QFSPosixRetry;
5522
5523 return rc;
5524}
5525
5526
5527/*
5528 * We can not use write of zero bytes trick to set file size due to need for
5529 * large file support. Also note that this SetPathInfo is preferred to
5530 * SetFileInfo based method in next routine which is only needed to work around
5531 * a sharing violation bugin Samba which this routine can run into.
5532 */
5533int
5534CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon,
5535 const char *file_name, __u64 size, struct cifs_sb_info *cifs_sb,
5536 bool set_allocation)
5537{
5538 struct smb_com_transaction2_spi_req *pSMB = NULL;
5539 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5540 struct file_end_of_file_info *parm_data;
5541 int name_len;
5542 int rc = 0;
5543 int bytes_returned = 0;
5544 int remap = cifs_remap(cifs_sb);
5545
5546 __u16 params, byte_count, data_count, param_offset, offset;
5547
5548 cifs_dbg(FYI, "In SetEOF\n");
5549SetEOFRetry:
5550 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5551 (void **) &pSMBr);
5552 if (rc)
5553 return rc;
5554
5555 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5556 name_len =
5557 cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
5558 PATH_MAX, cifs_sb->local_nls, remap);
5559 name_len++; /* trailing null */
5560 name_len *= 2;
5561 } else { /* BB improve the check for buffer overruns BB */
5562 name_len = strnlen(file_name, PATH_MAX);
5563 name_len++; /* trailing null */
5564 strncpy(pSMB->FileName, file_name, name_len);
5565 }
5566 params = 6 + name_len;
5567 data_count = sizeof(struct file_end_of_file_info);
5568 pSMB->MaxParameterCount = cpu_to_le16(2);
5569 pSMB->MaxDataCount = cpu_to_le16(4100);
5570 pSMB->MaxSetupCount = 0;
5571 pSMB->Reserved = 0;
5572 pSMB->Flags = 0;
5573 pSMB->Timeout = 0;
5574 pSMB->Reserved2 = 0;
5575 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5576 InformationLevel) - 4;
5577 offset = param_offset + params;
5578 if (set_allocation) {
5579 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5580 pSMB->InformationLevel =
5581 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5582 else
5583 pSMB->InformationLevel =
5584 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5585 } else /* Set File Size */ {
5586 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5587 pSMB->InformationLevel =
5588 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5589 else
5590 pSMB->InformationLevel =
5591 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5592 }
5593
5594 parm_data =
5595 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
5596 offset);
5597 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5598 pSMB->DataOffset = cpu_to_le16(offset);
5599 pSMB->SetupCount = 1;
5600 pSMB->Reserved3 = 0;
5601 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5602 byte_count = 3 /* pad */ + params + data_count;
5603 pSMB->DataCount = cpu_to_le16(data_count);
5604 pSMB->TotalDataCount = pSMB->DataCount;
5605 pSMB->ParameterCount = cpu_to_le16(params);
5606 pSMB->TotalParameterCount = pSMB->ParameterCount;
5607 pSMB->Reserved4 = 0;
5608 inc_rfc1001_len(pSMB, byte_count);
5609 parm_data->FileSize = cpu_to_le64(size);
5610 pSMB->ByteCount = cpu_to_le16(byte_count);
5611 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5612 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5613 if (rc)
5614 cifs_dbg(FYI, "SetPathInfo (file size) returned %d\n", rc);
5615
5616 cifs_buf_release(pSMB);
5617
5618 if (rc == -EAGAIN)
5619 goto SetEOFRetry;
5620
5621 return rc;
5622}
5623
5624int
5625CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon,
5626 struct cifsFileInfo *cfile, __u64 size, bool set_allocation)
5627{
5628 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5629 struct file_end_of_file_info *parm_data;
5630 int rc = 0;
5631 __u16 params, param_offset, offset, byte_count, count;
5632
5633 cifs_dbg(FYI, "SetFileSize (via SetFileInfo) %lld\n",
5634 (long long)size);
5635 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5636
5637 if (rc)
5638 return rc;
5639
5640 pSMB->hdr.Pid = cpu_to_le16((__u16)cfile->pid);
5641 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(cfile->pid >> 16));
5642
5643 params = 6;
5644 pSMB->MaxSetupCount = 0;
5645 pSMB->Reserved = 0;
5646 pSMB->Flags = 0;
5647 pSMB->Timeout = 0;
5648 pSMB->Reserved2 = 0;
5649 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5650 offset = param_offset + params;
5651
5652 count = sizeof(struct file_end_of_file_info);
5653 pSMB->MaxParameterCount = cpu_to_le16(2);
5654 /* BB find exact max SMB PDU from sess structure BB */
5655 pSMB->MaxDataCount = cpu_to_le16(1000);
5656 pSMB->SetupCount = 1;
5657 pSMB->Reserved3 = 0;
5658 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5659 byte_count = 3 /* pad */ + params + count;
5660 pSMB->DataCount = cpu_to_le16(count);
5661 pSMB->ParameterCount = cpu_to_le16(params);
5662 pSMB->TotalDataCount = pSMB->DataCount;
5663 pSMB->TotalParameterCount = pSMB->ParameterCount;
5664 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5665 parm_data =
5666 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
5667 + offset);
5668 pSMB->DataOffset = cpu_to_le16(offset);
5669 parm_data->FileSize = cpu_to_le64(size);
5670 pSMB->Fid = cfile->fid.netfid;
5671 if (set_allocation) {
5672 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5673 pSMB->InformationLevel =
5674 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5675 else
5676 pSMB->InformationLevel =
5677 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5678 } else /* Set File Size */ {
5679 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5680 pSMB->InformationLevel =
5681 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5682 else
5683 pSMB->InformationLevel =
5684 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5685 }
5686 pSMB->Reserved4 = 0;
5687 inc_rfc1001_len(pSMB, byte_count);
5688 pSMB->ByteCount = cpu_to_le16(byte_count);
5689 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5690 if (rc) {
5691 cifs_dbg(FYI, "Send error in SetFileInfo (SetFileSize) = %d\n",
5692 rc);
5693 }
5694
5695 /* Note: On -EAGAIN error only caller can retry on handle based calls
5696 since file handle passed in no longer valid */
5697
5698 return rc;
5699}
5700
5701/* Some legacy servers such as NT4 require that the file times be set on
5702 an open handle, rather than by pathname - this is awkward due to
5703 potential access conflicts on the open, but it is unavoidable for these
5704 old servers since the only other choice is to go from 100 nanosecond DCE
5705 time and resort to the original setpathinfo level which takes the ancient
5706 DOS time format with 2 second granularity */
5707int
5708CIFSSMBSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
5709 const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
5710{
5711 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5712 char *data_offset;
5713 int rc = 0;
5714 __u16 params, param_offset, offset, byte_count, count;
5715
5716 cifs_dbg(FYI, "Set Times (via SetFileInfo)\n");
5717 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5718
5719 if (rc)
5720 return rc;
5721
5722 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5723 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5724
5725 params = 6;
5726 pSMB->MaxSetupCount = 0;
5727 pSMB->Reserved = 0;
5728 pSMB->Flags = 0;
5729 pSMB->Timeout = 0;
5730 pSMB->Reserved2 = 0;
5731 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5732 offset = param_offset + params;
5733
5734 data_offset = (char *)pSMB +
5735 offsetof(struct smb_hdr, Protocol) + offset;
5736
5737 count = sizeof(FILE_BASIC_INFO);
5738 pSMB->MaxParameterCount = cpu_to_le16(2);
5739 /* BB find max SMB PDU from sess */
5740 pSMB->MaxDataCount = cpu_to_le16(1000);
5741 pSMB->SetupCount = 1;
5742 pSMB->Reserved3 = 0;
5743 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5744 byte_count = 3 /* pad */ + params + count;
5745 pSMB->DataCount = cpu_to_le16(count);
5746 pSMB->ParameterCount = cpu_to_le16(params);
5747 pSMB->TotalDataCount = pSMB->DataCount;
5748 pSMB->TotalParameterCount = pSMB->ParameterCount;
5749 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5750 pSMB->DataOffset = cpu_to_le16(offset);
5751 pSMB->Fid = fid;
5752 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5753 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5754 else
5755 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5756 pSMB->Reserved4 = 0;
5757 inc_rfc1001_len(pSMB, byte_count);
5758 pSMB->ByteCount = cpu_to_le16(byte_count);
5759 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5760 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5761 if (rc)
5762 cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n",
5763 rc);
5764
5765 /* Note: On -EAGAIN error only caller can retry on handle based calls
5766 since file handle passed in no longer valid */
5767
5768 return rc;
5769}
5770
5771int
5772CIFSSMBSetFileDisposition(const unsigned int xid, struct cifs_tcon *tcon,
5773 bool delete_file, __u16 fid, __u32 pid_of_opener)
5774{
5775 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5776 char *data_offset;
5777 int rc = 0;
5778 __u16 params, param_offset, offset, byte_count, count;
5779
5780 cifs_dbg(FYI, "Set File Disposition (via SetFileInfo)\n");
5781 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5782
5783 if (rc)
5784 return rc;
5785
5786 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5787 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5788
5789 params = 6;
5790 pSMB->MaxSetupCount = 0;
5791 pSMB->Reserved = 0;
5792 pSMB->Flags = 0;
5793 pSMB->Timeout = 0;
5794 pSMB->Reserved2 = 0;
5795 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5796 offset = param_offset + params;
5797
5798 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5799
5800 count = 1;
5801 pSMB->MaxParameterCount = cpu_to_le16(2);
5802 /* BB find max SMB PDU from sess */
5803 pSMB->MaxDataCount = cpu_to_le16(1000);
5804 pSMB->SetupCount = 1;
5805 pSMB->Reserved3 = 0;
5806 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5807 byte_count = 3 /* pad */ + params + count;
5808 pSMB->DataCount = cpu_to_le16(count);
5809 pSMB->ParameterCount = cpu_to_le16(params);
5810 pSMB->TotalDataCount = pSMB->DataCount;
5811 pSMB->TotalParameterCount = pSMB->ParameterCount;
5812 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5813 pSMB->DataOffset = cpu_to_le16(offset);
5814 pSMB->Fid = fid;
5815 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
5816 pSMB->Reserved4 = 0;
5817 inc_rfc1001_len(pSMB, byte_count);
5818 pSMB->ByteCount = cpu_to_le16(byte_count);
5819 *data_offset = delete_file ? 1 : 0;
5820 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5821 if (rc)
5822 cifs_dbg(FYI, "Send error in SetFileDisposition = %d\n", rc);
5823
5824 return rc;
5825}
5826
5827int
5828CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
5829 const char *fileName, const FILE_BASIC_INFO *data,
5830 const struct nls_table *nls_codepage, int remap)
5831{
5832 TRANSACTION2_SPI_REQ *pSMB = NULL;
5833 TRANSACTION2_SPI_RSP *pSMBr = NULL;
5834 int name_len;
5835 int rc = 0;
5836 int bytes_returned = 0;
5837 char *data_offset;
5838 __u16 params, param_offset, offset, byte_count, count;
5839
5840 cifs_dbg(FYI, "In SetTimes\n");
5841
5842SetTimesRetry:
5843 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5844 (void **) &pSMBr);
5845 if (rc)
5846 return rc;
5847
5848 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5849 name_len =
5850 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
5851 PATH_MAX, nls_codepage, remap);
5852 name_len++; /* trailing null */
5853 name_len *= 2;
5854 } else { /* BB improve the check for buffer overruns BB */
5855 name_len = strnlen(fileName, PATH_MAX);
5856 name_len++; /* trailing null */
5857 strncpy(pSMB->FileName, fileName, name_len);
5858 }
5859
5860 params = 6 + name_len;
5861 count = sizeof(FILE_BASIC_INFO);
5862 pSMB->MaxParameterCount = cpu_to_le16(2);
5863 /* BB find max SMB PDU from sess structure BB */
5864 pSMB->MaxDataCount = cpu_to_le16(1000);
5865 pSMB->MaxSetupCount = 0;
5866 pSMB->Reserved = 0;
5867 pSMB->Flags = 0;
5868 pSMB->Timeout = 0;
5869 pSMB->Reserved2 = 0;
5870 param_offset = offsetof(struct smb_com_transaction2_spi_req,
5871 InformationLevel) - 4;
5872 offset = param_offset + params;
5873 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5874 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5875 pSMB->DataOffset = cpu_to_le16(offset);
5876 pSMB->SetupCount = 1;
5877 pSMB->Reserved3 = 0;
5878 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5879 byte_count = 3 /* pad */ + params + count;
5880
5881 pSMB->DataCount = cpu_to_le16(count);
5882 pSMB->ParameterCount = cpu_to_le16(params);
5883 pSMB->TotalDataCount = pSMB->DataCount;
5884 pSMB->TotalParameterCount = pSMB->ParameterCount;
5885 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5886 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5887 else
5888 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5889 pSMB->Reserved4 = 0;
5890 inc_rfc1001_len(pSMB, byte_count);
5891 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5892 pSMB->ByteCount = cpu_to_le16(byte_count);
5893 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5894 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5895 if (rc)
5896 cifs_dbg(FYI, "SetPathInfo (times) returned %d\n", rc);
5897
5898 cifs_buf_release(pSMB);
5899
5900 if (rc == -EAGAIN)
5901 goto SetTimesRetry;
5902
5903 return rc;
5904}
5905
5906/* Can not be used to set time stamps yet (due to old DOS time format) */
5907/* Can be used to set attributes */
5908#if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
5909 handling it anyway and NT4 was what we thought it would be needed for
5910 Do not delete it until we prove whether needed for Win9x though */
5911int
5912CIFSSMBSetAttrLegacy(unsigned int xid, struct cifs_tcon *tcon, char *fileName,
5913 __u16 dos_attrs, const struct nls_table *nls_codepage)
5914{
5915 SETATTR_REQ *pSMB = NULL;
5916 SETATTR_RSP *pSMBr = NULL;
5917 int rc = 0;
5918 int bytes_returned;
5919 int name_len;
5920
5921 cifs_dbg(FYI, "In SetAttrLegacy\n");
5922
5923SetAttrLgcyRetry:
5924 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5925 (void **) &pSMBr);
5926 if (rc)
5927 return rc;
5928
5929 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5930 name_len =
5931 ConvertToUTF16((__le16 *) pSMB->fileName, fileName,
5932 PATH_MAX, nls_codepage);
5933 name_len++; /* trailing null */
5934 name_len *= 2;
5935 } else { /* BB improve the check for buffer overruns BB */
5936 name_len = strnlen(fileName, PATH_MAX);
5937 name_len++; /* trailing null */
5938 strncpy(pSMB->fileName, fileName, name_len);
5939 }
5940 pSMB->attr = cpu_to_le16(dos_attrs);
5941 pSMB->BufferFormat = 0x04;
5942 inc_rfc1001_len(pSMB, name_len + 1);
5943 pSMB->ByteCount = cpu_to_le16(name_len + 1);
5944 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5945 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5946 if (rc)
5947 cifs_dbg(FYI, "Error in LegacySetAttr = %d\n", rc);
5948
5949 cifs_buf_release(pSMB);
5950
5951 if (rc == -EAGAIN)
5952 goto SetAttrLgcyRetry;
5953
5954 return rc;
5955}
5956#endif /* temporarily unneeded SetAttr legacy function */
5957
5958static void
5959cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
5960 const struct cifs_unix_set_info_args *args)
5961{
5962 u64 uid = NO_CHANGE_64, gid = NO_CHANGE_64;
5963 u64 mode = args->mode;
5964
5965 if (uid_valid(args->uid))
5966 uid = from_kuid(&init_user_ns, args->uid);
5967 if (gid_valid(args->gid))
5968 gid = from_kgid(&init_user_ns, args->gid);
5969
5970 /*
5971 * Samba server ignores set of file size to zero due to bugs in some
5972 * older clients, but we should be precise - we use SetFileSize to
5973 * set file size and do not want to truncate file size to zero
5974 * accidentally as happened on one Samba server beta by putting
5975 * zero instead of -1 here
5976 */
5977 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5978 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5979 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5980 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5981 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5982 data_offset->Uid = cpu_to_le64(uid);
5983 data_offset->Gid = cpu_to_le64(gid);
5984 /* better to leave device as zero when it is */
5985 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5986 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5987 data_offset->Permissions = cpu_to_le64(mode);
5988
5989 if (S_ISREG(mode))
5990 data_offset->Type = cpu_to_le32(UNIX_FILE);
5991 else if (S_ISDIR(mode))
5992 data_offset->Type = cpu_to_le32(UNIX_DIR);
5993 else if (S_ISLNK(mode))
5994 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5995 else if (S_ISCHR(mode))
5996 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5997 else if (S_ISBLK(mode))
5998 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5999 else if (S_ISFIFO(mode))
6000 data_offset->Type = cpu_to_le32(UNIX_FIFO);
6001 else if (S_ISSOCK(mode))
6002 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
6003}
6004
6005int
6006CIFSSMBUnixSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
6007 const struct cifs_unix_set_info_args *args,
6008 u16 fid, u32 pid_of_opener)
6009{
6010 struct smb_com_transaction2_sfi_req *pSMB = NULL;
6011 char *data_offset;
6012 int rc = 0;
6013 u16 params, param_offset, offset, byte_count, count;
6014
6015 cifs_dbg(FYI, "Set Unix Info (via SetFileInfo)\n");
6016 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
6017
6018 if (rc)
6019 return rc;
6020
6021 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
6022 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
6023
6024 params = 6;
6025 pSMB->MaxSetupCount = 0;
6026 pSMB->Reserved = 0;
6027 pSMB->Flags = 0;
6028 pSMB->Timeout = 0;
6029 pSMB->Reserved2 = 0;
6030 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
6031 offset = param_offset + params;
6032
6033 data_offset = (char *)pSMB +
6034 offsetof(struct smb_hdr, Protocol) + offset;
6035
6036 count = sizeof(FILE_UNIX_BASIC_INFO);
6037
6038 pSMB->MaxParameterCount = cpu_to_le16(2);
6039 /* BB find max SMB PDU from sess */
6040 pSMB->MaxDataCount = cpu_to_le16(1000);
6041 pSMB->SetupCount = 1;
6042 pSMB->Reserved3 = 0;
6043 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
6044 byte_count = 3 /* pad */ + params + count;
6045 pSMB->DataCount = cpu_to_le16(count);
6046 pSMB->ParameterCount = cpu_to_le16(params);
6047 pSMB->TotalDataCount = pSMB->DataCount;
6048 pSMB->TotalParameterCount = pSMB->ParameterCount;
6049 pSMB->ParameterOffset = cpu_to_le16(param_offset);
6050 pSMB->DataOffset = cpu_to_le16(offset);
6051 pSMB->Fid = fid;
6052 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
6053 pSMB->Reserved4 = 0;
6054 inc_rfc1001_len(pSMB, byte_count);
6055 pSMB->ByteCount = cpu_to_le16(byte_count);
6056
6057 cifs_fill_unix_set_info((FILE_UNIX_BASIC_INFO *)data_offset, args);
6058
6059 rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
6060 if (rc)
6061 cifs_dbg(FYI, "Send error in Set Time (SetFileInfo) = %d\n",
6062 rc);
6063
6064 /* Note: On -EAGAIN error only caller can retry on handle based calls
6065 since file handle passed in no longer valid */
6066
6067 return rc;
6068}
6069
6070int
6071CIFSSMBUnixSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
6072 const char *file_name,
6073 const struct cifs_unix_set_info_args *args,
6074 const struct nls_table *nls_codepage, int remap)
6075{
6076 TRANSACTION2_SPI_REQ *pSMB = NULL;
6077 TRANSACTION2_SPI_RSP *pSMBr = NULL;
6078 int name_len;
6079 int rc = 0;
6080 int bytes_returned = 0;
6081 FILE_UNIX_BASIC_INFO *data_offset;
6082 __u16 params, param_offset, offset, count, byte_count;
6083
6084 cifs_dbg(FYI, "In SetUID/GID/Mode\n");
6085setPermsRetry:
6086 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6087 (void **) &pSMBr);
6088 if (rc)
6089 return rc;
6090
6091 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6092 name_len =
6093 cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name,
6094 PATH_MAX, nls_codepage, remap);
6095 name_len++; /* trailing null */
6096 name_len *= 2;
6097 } else { /* BB improve the check for buffer overruns BB */
6098 name_len = strnlen(file_name, PATH_MAX);
6099 name_len++; /* trailing null */
6100 strncpy(pSMB->FileName, file_name, name_len);
6101 }
6102
6103 params = 6 + name_len;
6104 count = sizeof(FILE_UNIX_BASIC_INFO);
6105 pSMB->MaxParameterCount = cpu_to_le16(2);
6106 /* BB find max SMB PDU from sess structure BB */
6107 pSMB->MaxDataCount = cpu_to_le16(1000);
6108 pSMB->MaxSetupCount = 0;
6109 pSMB->Reserved = 0;
6110 pSMB->Flags = 0;
6111 pSMB->Timeout = 0;
6112 pSMB->Reserved2 = 0;
6113 param_offset = offsetof(struct smb_com_transaction2_spi_req,
6114 InformationLevel) - 4;
6115 offset = param_offset + params;
6116 data_offset =
6117 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
6118 offset);
6119 memset(data_offset, 0, count);
6120 pSMB->DataOffset = cpu_to_le16(offset);
6121 pSMB->ParameterOffset = cpu_to_le16(param_offset);
6122 pSMB->SetupCount = 1;
6123 pSMB->Reserved3 = 0;
6124 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
6125 byte_count = 3 /* pad */ + params + count;
6126 pSMB->ParameterCount = cpu_to_le16(params);
6127 pSMB->DataCount = cpu_to_le16(count);
6128 pSMB->TotalParameterCount = pSMB->ParameterCount;
6129 pSMB->TotalDataCount = pSMB->DataCount;
6130 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
6131 pSMB->Reserved4 = 0;
6132 inc_rfc1001_len(pSMB, byte_count);
6133
6134 cifs_fill_unix_set_info(data_offset, args);
6135
6136 pSMB->ByteCount = cpu_to_le16(byte_count);
6137 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6138 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6139 if (rc)
6140 cifs_dbg(FYI, "SetPathInfo (perms) returned %d\n", rc);
6141
6142 cifs_buf_release(pSMB);
6143 if (rc == -EAGAIN)
6144 goto setPermsRetry;
6145 return rc;
6146}
6147
6148#ifdef CONFIG_CIFS_XATTR
6149/*
6150 * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
6151 * function used by listxattr and getxattr type calls. When ea_name is set,
6152 * it looks for that attribute name and stuffs that value into the EAData
6153 * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
6154 * buffer. In both cases, the return value is either the length of the
6155 * resulting data or a negative error code. If EAData is a NULL pointer then
6156 * the data isn't copied to it, but the length is returned.
6157 */
6158ssize_t
6159CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon,
6160 const unsigned char *searchName, const unsigned char *ea_name,
6161 char *EAData, size_t buf_size,
6162 const struct nls_table *nls_codepage, int remap)
6163{
6164 /* BB assumes one setup word */
6165 TRANSACTION2_QPI_REQ *pSMB = NULL;
6166 TRANSACTION2_QPI_RSP *pSMBr = NULL;
6167 int rc = 0;
6168 int bytes_returned;
6169 int list_len;
6170 struct fealist *ea_response_data;
6171 struct fea *temp_fea;
6172 char *temp_ptr;
6173 char *end_of_smb;
6174 __u16 params, byte_count, data_offset;
6175 unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0;
6176
6177 cifs_dbg(FYI, "In Query All EAs path %s\n", searchName);
6178QAllEAsRetry:
6179 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6180 (void **) &pSMBr);
6181 if (rc)
6182 return rc;
6183
6184 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6185 list_len =
6186 cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
6187 PATH_MAX, nls_codepage, remap);
6188 list_len++; /* trailing null */
6189 list_len *= 2;
6190 } else { /* BB improve the check for buffer overruns BB */
6191 list_len = strnlen(searchName, PATH_MAX);
6192 list_len++; /* trailing null */
6193 strncpy(pSMB->FileName, searchName, list_len);
6194 }
6195
6196 params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
6197 pSMB->TotalDataCount = 0;
6198 pSMB->MaxParameterCount = cpu_to_le16(2);
6199 /* BB find exact max SMB PDU from sess structure BB */
6200 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
6201 pSMB->MaxSetupCount = 0;
6202 pSMB->Reserved = 0;
6203 pSMB->Flags = 0;
6204 pSMB->Timeout = 0;
6205 pSMB->Reserved2 = 0;
6206 pSMB->ParameterOffset = cpu_to_le16(offsetof(
6207 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
6208 pSMB->DataCount = 0;
6209 pSMB->DataOffset = 0;
6210 pSMB->SetupCount = 1;
6211 pSMB->Reserved3 = 0;
6212 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
6213 byte_count = params + 1 /* pad */ ;
6214 pSMB->TotalParameterCount = cpu_to_le16(params);
6215 pSMB->ParameterCount = pSMB->TotalParameterCount;
6216 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
6217 pSMB->Reserved4 = 0;
6218 inc_rfc1001_len(pSMB, byte_count);
6219 pSMB->ByteCount = cpu_to_le16(byte_count);
6220
6221 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6222 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6223 if (rc) {
6224 cifs_dbg(FYI, "Send error in QueryAllEAs = %d\n", rc);
6225 goto QAllEAsOut;
6226 }
6227
6228
6229 /* BB also check enough total bytes returned */
6230 /* BB we need to improve the validity checking
6231 of these trans2 responses */
6232
6233 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
6234 if (rc || get_bcc(&pSMBr->hdr) < 4) {
6235 rc = -EIO; /* bad smb */
6236 goto QAllEAsOut;
6237 }
6238
6239 /* check that length of list is not more than bcc */
6240 /* check that each entry does not go beyond length
6241 of list */
6242 /* check that each element of each entry does not
6243 go beyond end of list */
6244 /* validate_trans2_offsets() */
6245 /* BB check if start of smb + data_offset > &bcc+ bcc */
6246
6247 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
6248 ea_response_data = (struct fealist *)
6249 (((char *) &pSMBr->hdr.Protocol) + data_offset);
6250
6251 list_len = le32_to_cpu(ea_response_data->list_len);
6252 cifs_dbg(FYI, "ea length %d\n", list_len);
6253 if (list_len <= 8) {
6254 cifs_dbg(FYI, "empty EA list returned from server\n");
6255 /* didn't find the named attribute */
6256 if (ea_name)
6257 rc = -ENODATA;
6258 goto QAllEAsOut;
6259 }
6260
6261 /* make sure list_len doesn't go past end of SMB */
6262 end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr);
6263 if ((char *)ea_response_data + list_len > end_of_smb) {
6264 cifs_dbg(FYI, "EA list appears to go beyond SMB\n");
6265 rc = -EIO;
6266 goto QAllEAsOut;
6267 }
6268
6269 /* account for ea list len */
6270 list_len -= 4;
6271 temp_fea = ea_response_data->list;
6272 temp_ptr = (char *)temp_fea;
6273 while (list_len > 0) {
6274 unsigned int name_len;
6275 __u16 value_len;
6276
6277 list_len -= 4;
6278 temp_ptr += 4;
6279 /* make sure we can read name_len and value_len */
6280 if (list_len < 0) {
6281 cifs_dbg(FYI, "EA entry goes beyond length of list\n");
6282 rc = -EIO;
6283 goto QAllEAsOut;
6284 }
6285
6286 name_len = temp_fea->name_len;
6287 value_len = le16_to_cpu(temp_fea->value_len);
6288 list_len -= name_len + 1 + value_len;
6289 if (list_len < 0) {
6290 cifs_dbg(FYI, "EA entry goes beyond length of list\n");
6291 rc = -EIO;
6292 goto QAllEAsOut;
6293 }
6294
6295 if (ea_name) {
6296 if (ea_name_len == name_len &&
6297 memcmp(ea_name, temp_ptr, name_len) == 0) {
6298 temp_ptr += name_len + 1;
6299 rc = value_len;
6300 if (buf_size == 0)
6301 goto QAllEAsOut;
6302 if ((size_t)value_len > buf_size) {
6303 rc = -ERANGE;
6304 goto QAllEAsOut;
6305 }
6306 memcpy(EAData, temp_ptr, value_len);
6307 goto QAllEAsOut;
6308 }
6309 } else {
6310 /* account for prefix user. and trailing null */
6311 rc += (5 + 1 + name_len);
6312 if (rc < (int) buf_size) {
6313 memcpy(EAData, "user.", 5);
6314 EAData += 5;
6315 memcpy(EAData, temp_ptr, name_len);
6316 EAData += name_len;
6317 /* null terminate name */
6318 *EAData = 0;
6319 ++EAData;
6320 } else if (buf_size == 0) {
6321 /* skip copy - calc size only */
6322 } else {
6323 /* stop before overrun buffer */
6324 rc = -ERANGE;
6325 break;
6326 }
6327 }
6328 temp_ptr += name_len + 1 + value_len;
6329 temp_fea = (struct fea *)temp_ptr;
6330 }
6331
6332 /* didn't find the named attribute */
6333 if (ea_name)
6334 rc = -ENODATA;
6335
6336QAllEAsOut:
6337 cifs_buf_release(pSMB);
6338 if (rc == -EAGAIN)
6339 goto QAllEAsRetry;
6340
6341 return (ssize_t)rc;
6342}
6343
6344int
6345CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,
6346 const char *fileName, const char *ea_name, const void *ea_value,
6347 const __u16 ea_value_len, const struct nls_table *nls_codepage,
6348 int remap)
6349{
6350 struct smb_com_transaction2_spi_req *pSMB = NULL;
6351 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
6352 struct fealist *parm_data;
6353 int name_len;
6354 int rc = 0;
6355 int bytes_returned = 0;
6356 __u16 params, param_offset, byte_count, offset, count;
6357
6358 cifs_dbg(FYI, "In SetEA\n");
6359SetEARetry:
6360 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6361 (void **) &pSMBr);
6362 if (rc)
6363 return rc;
6364
6365 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6366 name_len =
6367 cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
6368 PATH_MAX, nls_codepage, remap);
6369 name_len++; /* trailing null */
6370 name_len *= 2;
6371 } else { /* BB improve the check for buffer overruns BB */
6372 name_len = strnlen(fileName, PATH_MAX);
6373 name_len++; /* trailing null */
6374 strncpy(pSMB->FileName, fileName, name_len);
6375 }
6376
6377 params = 6 + name_len;
6378
6379 /* done calculating parms using name_len of file name,
6380 now use name_len to calculate length of ea name
6381 we are going to create in the inode xattrs */
6382 if (ea_name == NULL)
6383 name_len = 0;
6384 else
6385 name_len = strnlen(ea_name, 255);
6386
6387 count = sizeof(*parm_data) + ea_value_len + name_len;
6388 pSMB->MaxParameterCount = cpu_to_le16(2);
6389 /* BB find max SMB PDU from sess */
6390 pSMB->MaxDataCount = cpu_to_le16(1000);
6391 pSMB->MaxSetupCount = 0;
6392 pSMB->Reserved = 0;
6393 pSMB->Flags = 0;
6394 pSMB->Timeout = 0;
6395 pSMB->Reserved2 = 0;
6396 param_offset = offsetof(struct smb_com_transaction2_spi_req,
6397 InformationLevel) - 4;
6398 offset = param_offset + params;
6399 pSMB->InformationLevel =
6400 cpu_to_le16(SMB_SET_FILE_EA);
6401
6402 parm_data =
6403 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
6404 offset);
6405 pSMB->ParameterOffset = cpu_to_le16(param_offset);
6406 pSMB->DataOffset = cpu_to_le16(offset);
6407 pSMB->SetupCount = 1;
6408 pSMB->Reserved3 = 0;
6409 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
6410 byte_count = 3 /* pad */ + params + count;
6411 pSMB->DataCount = cpu_to_le16(count);
6412 parm_data->list_len = cpu_to_le32(count);
6413 parm_data->list[0].EA_flags = 0;
6414 /* we checked above that name len is less than 255 */
6415 parm_data->list[0].name_len = (__u8)name_len;
6416 /* EA names are always ASCII */
6417 if (ea_name)
6418 strncpy(parm_data->list[0].name, ea_name, name_len);
6419 parm_data->list[0].name[name_len] = 0;
6420 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
6421 /* caller ensures that ea_value_len is less than 64K but
6422 we need to ensure that it fits within the smb */
6423
6424 /*BB add length check to see if it would fit in
6425 negotiated SMB buffer size BB */
6426 /* if (ea_value_len > buffer_size - 512 (enough for header)) */
6427 if (ea_value_len)
6428 memcpy(parm_data->list[0].name+name_len+1,
6429 ea_value, ea_value_len);
6430
6431 pSMB->TotalDataCount = pSMB->DataCount;
6432 pSMB->ParameterCount = cpu_to_le16(params);
6433 pSMB->TotalParameterCount = pSMB->ParameterCount;
6434 pSMB->Reserved4 = 0;
6435 inc_rfc1001_len(pSMB, byte_count);
6436 pSMB->ByteCount = cpu_to_le16(byte_count);
6437 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6438 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6439 if (rc)
6440 cifs_dbg(FYI, "SetPathInfo (EA) returned %d\n", rc);
6441
6442 cifs_buf_release(pSMB);
6443
6444 if (rc == -EAGAIN)
6445 goto SetEARetry;
6446
6447 return rc;
6448}
6449#endif
6450
6451#ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* BB unused temporarily */
6452/*
6453 * Years ago the kernel added a "dnotify" function for Samba server,
6454 * to allow network clients (such as Windows) to display updated
6455 * lists of files in directory listings automatically when
6456 * files are added by one user when another user has the
6457 * same directory open on their desktop. The Linux cifs kernel
6458 * client hooked into the kernel side of this interface for
6459 * the same reason, but ironically when the VFS moved from
6460 * "dnotify" to "inotify" it became harder to plug in Linux
6461 * network file system clients (the most obvious use case
6462 * for notify interfaces is when multiple users can update
6463 * the contents of the same directory - exactly what network
6464 * file systems can do) although the server (Samba) could
6465 * still use it. For the short term we leave the worker
6466 * function ifdeffed out (below) until inotify is fixed
6467 * in the VFS to make it easier to plug in network file
6468 * system clients. If inotify turns out to be permanently
6469 * incompatible for network fs clients, we could instead simply
6470 * expose this config flag by adding a future cifs (and smb2) notify ioctl.
6471 */
6472int CIFSSMBNotify(const unsigned int xid, struct cifs_tcon *tcon,
6473 const int notify_subdirs, const __u16 netfid,
6474 __u32 filter, struct file *pfile, int multishot,
6475 const struct nls_table *nls_codepage)
6476{
6477 int rc = 0;
6478 struct smb_com_transaction_change_notify_req *pSMB = NULL;
6479 struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
6480 struct dir_notify_req *dnotify_req;
6481 int bytes_returned;
6482
6483 cifs_dbg(FYI, "In CIFSSMBNotify for file handle %d\n", (int)netfid);
6484 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
6485 (void **) &pSMBr);
6486 if (rc)
6487 return rc;
6488
6489 pSMB->TotalParameterCount = 0 ;
6490 pSMB->TotalDataCount = 0;
6491 pSMB->MaxParameterCount = cpu_to_le32(2);
6492 pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
6493 pSMB->MaxSetupCount = 4;
6494 pSMB->Reserved = 0;
6495 pSMB->ParameterOffset = 0;
6496 pSMB->DataCount = 0;
6497 pSMB->DataOffset = 0;
6498 pSMB->SetupCount = 4; /* single byte does not need le conversion */
6499 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
6500 pSMB->ParameterCount = pSMB->TotalParameterCount;
6501 if (notify_subdirs)
6502 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
6503 pSMB->Reserved2 = 0;
6504 pSMB->CompletionFilter = cpu_to_le32(filter);
6505 pSMB->Fid = netfid; /* file handle always le */
6506 pSMB->ByteCount = 0;
6507
6508 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6509 (struct smb_hdr *)pSMBr, &bytes_returned,
6510 CIFS_ASYNC_OP);
6511 if (rc) {
6512 cifs_dbg(FYI, "Error in Notify = %d\n", rc);
6513 } else {
6514 /* Add file to outstanding requests */
6515 /* BB change to kmem cache alloc */
6516 dnotify_req = kmalloc(
6517 sizeof(struct dir_notify_req),
6518 GFP_KERNEL);
6519 if (dnotify_req) {
6520 dnotify_req->Pid = pSMB->hdr.Pid;
6521 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
6522 dnotify_req->Mid = pSMB->hdr.Mid;
6523 dnotify_req->Tid = pSMB->hdr.Tid;
6524 dnotify_req->Uid = pSMB->hdr.Uid;
6525 dnotify_req->netfid = netfid;
6526 dnotify_req->pfile = pfile;
6527 dnotify_req->filter = filter;
6528 dnotify_req->multishot = multishot;
6529 spin_lock(&GlobalMid_Lock);
6530 list_add_tail(&dnotify_req->lhead,
6531 &GlobalDnotifyReqList);
6532 spin_unlock(&GlobalMid_Lock);
6533 } else
6534 rc = -ENOMEM;
6535 }
6536 cifs_buf_release(pSMB);
6537 return rc;
6538}
6539#endif /* was needed for dnotify, and will be needed for inotify when VFS fix */