cifs: Include backup intent search flags during searches {try #2)
[linux-3.10.git] / fs / cifs / cifssmb.c
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 <asm/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
48 static 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
61 static 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 /* Forward declarations */
90
91 /* Mark as invalid, all open files on tree connections since they
92    were closed when session to server was lost */
93 static void mark_open_files_invalid(struct cifs_tcon *pTcon)
94 {
95         struct cifsFileInfo *open_file = NULL;
96         struct list_head *tmp;
97         struct list_head *tmp1;
98
99 /* list all files open on tree connection and mark them invalid */
100         spin_lock(&cifs_file_list_lock);
101         list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
102                 open_file = list_entry(tmp, struct cifsFileInfo, tlist);
103                 open_file->invalidHandle = true;
104                 open_file->oplock_break_cancelled = true;
105         }
106         spin_unlock(&cifs_file_list_lock);
107         /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
108            to this tcon */
109 }
110
111 /* reconnect the socket, tcon, and smb session if needed */
112 static int
113 cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
114 {
115         int rc;
116         struct cifs_ses *ses;
117         struct TCP_Server_Info *server;
118         struct nls_table *nls_codepage;
119
120         /*
121          * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for
122          * tcp and smb session status done differently for those three - in the
123          * calling routine
124          */
125         if (!tcon)
126                 return 0;
127
128         ses = tcon->ses;
129         server = ses->server;
130
131         /*
132          * only tree disconnect, open, and write, (and ulogoff which does not
133          * have tcon) are allowed as we start force umount
134          */
135         if (tcon->tidStatus == CifsExiting) {
136                 if (smb_command != SMB_COM_WRITE_ANDX &&
137                     smb_command != SMB_COM_OPEN_ANDX &&
138                     smb_command != SMB_COM_TREE_DISCONNECT) {
139                         cFYI(1, "can not send cmd %d while umounting",
140                                 smb_command);
141                         return -ENODEV;
142                 }
143         }
144
145         /*
146          * Give demultiplex thread up to 10 seconds to reconnect, should be
147          * greater than cifs socket timeout which is 7 seconds
148          */
149         while (server->tcpStatus == CifsNeedReconnect) {
150                 wait_event_interruptible_timeout(server->response_q,
151                         (server->tcpStatus != CifsNeedReconnect), 10 * HZ);
152
153                 /* are we still trying to reconnect? */
154                 if (server->tcpStatus != CifsNeedReconnect)
155                         break;
156
157                 /*
158                  * on "soft" mounts we wait once. Hard mounts keep
159                  * retrying until process is killed or server comes
160                  * back on-line
161                  */
162                 if (!tcon->retry) {
163                         cFYI(1, "gave up waiting on reconnect in smb_init");
164                         return -EHOSTDOWN;
165                 }
166         }
167
168         if (!ses->need_reconnect && !tcon->need_reconnect)
169                 return 0;
170
171         nls_codepage = load_nls_default();
172
173         /*
174          * need to prevent multiple threads trying to simultaneously
175          * reconnect the same SMB session
176          */
177         mutex_lock(&ses->session_mutex);
178         rc = cifs_negotiate_protocol(0, ses);
179         if (rc == 0 && ses->need_reconnect)
180                 rc = cifs_setup_session(0, ses, nls_codepage);
181
182         /* do we need to reconnect tcon? */
183         if (rc || !tcon->need_reconnect) {
184                 mutex_unlock(&ses->session_mutex);
185                 goto out;
186         }
187
188         mark_open_files_invalid(tcon);
189         rc = CIFSTCon(0, ses, tcon->treeName, tcon, nls_codepage);
190         mutex_unlock(&ses->session_mutex);
191         cFYI(1, "reconnect tcon rc = %d", rc);
192
193         if (rc)
194                 goto out;
195
196         /*
197          * FIXME: check if wsize needs updated due to negotiated smb buffer
198          *        size shrinking
199          */
200         atomic_inc(&tconInfoReconnectCount);
201
202         /* tell server Unix caps we support */
203         if (ses->capabilities & CAP_UNIX)
204                 reset_cifs_unix_caps(0, tcon, NULL, NULL);
205
206         /*
207          * Removed call to reopen open files here. It is safer (and faster) to
208          * reopen files one at a time as needed in read and write.
209          *
210          * FIXME: what about file locks? don't we need to reclaim them ASAP?
211          */
212
213 out:
214         /*
215          * Check if handle based operation so we know whether we can continue
216          * or not without returning to caller to reset file handle
217          */
218         switch (smb_command) {
219         case SMB_COM_READ_ANDX:
220         case SMB_COM_WRITE_ANDX:
221         case SMB_COM_CLOSE:
222         case SMB_COM_FIND_CLOSE2:
223         case SMB_COM_LOCKING_ANDX:
224                 rc = -EAGAIN;
225         }
226
227         unload_nls(nls_codepage);
228         return rc;
229 }
230
231 /* Allocate and return pointer to an SMB request buffer, and set basic
232    SMB information in the SMB header.  If the return code is zero, this
233    function must have filled in request_buf pointer */
234 static int
235 small_smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
236                 void **request_buf)
237 {
238         int rc;
239
240         rc = cifs_reconnect_tcon(tcon, smb_command);
241         if (rc)
242                 return rc;
243
244         *request_buf = cifs_small_buf_get();
245         if (*request_buf == NULL) {
246                 /* BB should we add a retry in here if not a writepage? */
247                 return -ENOMEM;
248         }
249
250         header_assemble((struct smb_hdr *) *request_buf, smb_command,
251                         tcon, wct);
252
253         if (tcon != NULL)
254                 cifs_stats_inc(&tcon->num_smbs_sent);
255
256         return 0;
257 }
258
259 int
260 small_smb_init_no_tc(const int smb_command, const int wct,
261                      struct cifs_ses *ses, void **request_buf)
262 {
263         int rc;
264         struct smb_hdr *buffer;
265
266         rc = small_smb_init(smb_command, wct, NULL, request_buf);
267         if (rc)
268                 return rc;
269
270         buffer = (struct smb_hdr *)*request_buf;
271         buffer->Mid = GetNextMid(ses->server);
272         if (ses->capabilities & CAP_UNICODE)
273                 buffer->Flags2 |= SMBFLG2_UNICODE;
274         if (ses->capabilities & CAP_STATUS32)
275                 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
276
277         /* uid, tid can stay at zero as set in header assemble */
278
279         /* BB add support for turning on the signing when
280         this function is used after 1st of session setup requests */
281
282         return rc;
283 }
284
285 /* If the return code is zero, this function must fill in request_buf pointer */
286 static int
287 __smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
288                         void **request_buf, void **response_buf)
289 {
290         *request_buf = cifs_buf_get();
291         if (*request_buf == NULL) {
292                 /* BB should we add a retry in here if not a writepage? */
293                 return -ENOMEM;
294         }
295     /* Although the original thought was we needed the response buf for  */
296     /* potential retries of smb operations it turns out we can determine */
297     /* from the mid flags when the request buffer can be resent without  */
298     /* having to use a second distinct buffer for the response */
299         if (response_buf)
300                 *response_buf = *request_buf;
301
302         header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
303                         wct);
304
305         if (tcon != NULL)
306                 cifs_stats_inc(&tcon->num_smbs_sent);
307
308         return 0;
309 }
310
311 /* If the return code is zero, this function must fill in request_buf pointer */
312 static int
313 smb_init(int smb_command, int wct, struct cifs_tcon *tcon,
314          void **request_buf, void **response_buf)
315 {
316         int rc;
317
318         rc = cifs_reconnect_tcon(tcon, smb_command);
319         if (rc)
320                 return rc;
321
322         return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
323 }
324
325 static int
326 smb_init_no_reconnect(int smb_command, int wct, struct cifs_tcon *tcon,
327                         void **request_buf, void **response_buf)
328 {
329         if (tcon->ses->need_reconnect || tcon->need_reconnect)
330                 return -EHOSTDOWN;
331
332         return __smb_init(smb_command, wct, tcon, request_buf, response_buf);
333 }
334
335 static int validate_t2(struct smb_t2_rsp *pSMB)
336 {
337         unsigned int total_size;
338
339         /* check for plausible wct */
340         if (pSMB->hdr.WordCount < 10)
341                 goto vt2_err;
342
343         /* check for parm and data offset going beyond end of smb */
344         if (get_unaligned_le16(&pSMB->t2_rsp.ParameterOffset) > 1024 ||
345             get_unaligned_le16(&pSMB->t2_rsp.DataOffset) > 1024)
346                 goto vt2_err;
347
348         total_size = get_unaligned_le16(&pSMB->t2_rsp.ParameterCount);
349         if (total_size >= 512)
350                 goto vt2_err;
351
352         /* check that bcc is at least as big as parms + data, and that it is
353          * less than negotiated smb buffer
354          */
355         total_size += get_unaligned_le16(&pSMB->t2_rsp.DataCount);
356         if (total_size > get_bcc(&pSMB->hdr) ||
357             total_size >= CIFSMaxBufSize + MAX_CIFS_HDR_SIZE)
358                 goto vt2_err;
359
360         return 0;
361 vt2_err:
362         cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
363                 sizeof(struct smb_t2_rsp) + 16);
364         return -EINVAL;
365 }
366
367 static inline void inc_rfc1001_len(void *pSMB, int count)
368 {
369         struct smb_hdr *hdr = (struct smb_hdr *)pSMB;
370
371         be32_add_cpu(&hdr->smb_buf_length, count);
372 }
373
374 int
375 CIFSSMBNegotiate(unsigned int xid, struct cifs_ses *ses)
376 {
377         NEGOTIATE_REQ *pSMB;
378         NEGOTIATE_RSP *pSMBr;
379         int rc = 0;
380         int bytes_returned;
381         int i;
382         struct TCP_Server_Info *server;
383         u16 count;
384         unsigned int secFlags;
385
386         if (ses->server)
387                 server = ses->server;
388         else {
389                 rc = -EIO;
390                 return rc;
391         }
392         rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
393                       (void **) &pSMB, (void **) &pSMBr);
394         if (rc)
395                 return rc;
396
397         /* if any of auth flags (ie not sign or seal) are overriden use them */
398         if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
399                 secFlags = ses->overrideSecFlg;  /* BB FIXME fix sign flags? */
400         else /* if override flags set only sign/seal OR them with global auth */
401                 secFlags = global_secflags | ses->overrideSecFlg;
402
403         cFYI(1, "secFlags 0x%x", secFlags);
404
405         pSMB->hdr.Mid = GetNextMid(server);
406         pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
407
408         if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
409                 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
410         else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
411                 cFYI(1, "Kerberos only mechanism, enable extended security");
412                 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
413         } else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
414                 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
415         else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) {
416                 cFYI(1, "NTLMSSP only mechanism, enable extended security");
417                 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
418         }
419
420         count = 0;
421         for (i = 0; i < CIFS_NUM_PROT; i++) {
422                 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
423                 count += strlen(protocols[i].name) + 1;
424                 /* null at end of source and target buffers anyway */
425         }
426         inc_rfc1001_len(pSMB, count);
427         pSMB->ByteCount = cpu_to_le16(count);
428
429         rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
430                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
431         if (rc != 0)
432                 goto neg_err_exit;
433
434         server->dialect = le16_to_cpu(pSMBr->DialectIndex);
435         cFYI(1, "Dialect: %d", server->dialect);
436         /* Check wct = 1 error case */
437         if ((pSMBr->hdr.WordCount < 13) || (server->dialect == BAD_PROT)) {
438                 /* core returns wct = 1, but we do not ask for core - otherwise
439                 small wct just comes when dialect index is -1 indicating we
440                 could not negotiate a common dialect */
441                 rc = -EOPNOTSUPP;
442                 goto neg_err_exit;
443 #ifdef CONFIG_CIFS_WEAK_PW_HASH
444         } else if ((pSMBr->hdr.WordCount == 13)
445                         && ((server->dialect == LANMAN_PROT)
446                                 || (server->dialect == LANMAN2_PROT))) {
447                 __s16 tmp;
448                 struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
449
450                 if ((secFlags & CIFSSEC_MAY_LANMAN) ||
451                         (secFlags & CIFSSEC_MAY_PLNTXT))
452                         server->secType = LANMAN;
453                 else {
454                         cERROR(1, "mount failed weak security disabled"
455                                    " in /proc/fs/cifs/SecurityFlags");
456                         rc = -EOPNOTSUPP;
457                         goto neg_err_exit;
458                 }
459                 server->sec_mode = (__u8)le16_to_cpu(rsp->SecurityMode);
460                 server->maxReq = min_t(unsigned int,
461                                        le16_to_cpu(rsp->MaxMpxCount),
462                                        cifs_max_pending);
463                 cifs_set_credits(server, server->maxReq);
464                 server->maxBuf = le16_to_cpu(rsp->MaxBufSize);
465                 server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs);
466                 /* even though we do not use raw we might as well set this
467                 accurately, in case we ever find a need for it */
468                 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
469                         server->max_rw = 0xFF00;
470                         server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
471                 } else {
472                         server->max_rw = 0;/* do not need to use raw anyway */
473                         server->capabilities = CAP_MPX_MODE;
474                 }
475                 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
476                 if (tmp == -1) {
477                         /* OS/2 often does not set timezone therefore
478                          * we must use server time to calc time zone.
479                          * Could deviate slightly from the right zone.
480                          * Smallest defined timezone difference is 15 minutes
481                          * (i.e. Nepal).  Rounding up/down is done to match
482                          * this requirement.
483                          */
484                         int val, seconds, remain, result;
485                         struct timespec ts, utc;
486                         utc = CURRENT_TIME;
487                         ts = cnvrtDosUnixTm(rsp->SrvTime.Date,
488                                             rsp->SrvTime.Time, 0);
489                         cFYI(1, "SrvTime %d sec since 1970 (utc: %d) diff: %d",
490                                 (int)ts.tv_sec, (int)utc.tv_sec,
491                                 (int)(utc.tv_sec - ts.tv_sec));
492                         val = (int)(utc.tv_sec - ts.tv_sec);
493                         seconds = abs(val);
494                         result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
495                         remain = seconds % MIN_TZ_ADJ;
496                         if (remain >= (MIN_TZ_ADJ / 2))
497                                 result += MIN_TZ_ADJ;
498                         if (val < 0)
499                                 result = -result;
500                         server->timeAdj = result;
501                 } else {
502                         server->timeAdj = (int)tmp;
503                         server->timeAdj *= 60; /* also in seconds */
504                 }
505                 cFYI(1, "server->timeAdj: %d seconds", server->timeAdj);
506
507
508                 /* BB get server time for time conversions and add
509                 code to use it and timezone since this is not UTC */
510
511                 if (rsp->EncryptionKeyLength ==
512                                 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
513                         memcpy(ses->server->cryptkey, rsp->EncryptionKey,
514                                 CIFS_CRYPTO_KEY_SIZE);
515                 } else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
516                         rc = -EIO; /* need cryptkey unless plain text */
517                         goto neg_err_exit;
518                 }
519
520                 cFYI(1, "LANMAN negotiated");
521                 /* we will not end up setting signing flags - as no signing
522                 was in LANMAN and server did not return the flags on */
523                 goto signing_check;
524 #else /* weak security disabled */
525         } else if (pSMBr->hdr.WordCount == 13) {
526                 cERROR(1, "mount failed, cifs module not built "
527                           "with CIFS_WEAK_PW_HASH support");
528                 rc = -EOPNOTSUPP;
529 #endif /* WEAK_PW_HASH */
530                 goto neg_err_exit;
531         } else if (pSMBr->hdr.WordCount != 17) {
532                 /* unknown wct */
533                 rc = -EOPNOTSUPP;
534                 goto neg_err_exit;
535         }
536         /* else wct == 17 NTLM */
537         server->sec_mode = pSMBr->SecurityMode;
538         if ((server->sec_mode & SECMODE_USER) == 0)
539                 cFYI(1, "share mode security");
540
541         if ((server->sec_mode & SECMODE_PW_ENCRYPT) == 0)
542 #ifdef CONFIG_CIFS_WEAK_PW_HASH
543                 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
544 #endif /* CIFS_WEAK_PW_HASH */
545                         cERROR(1, "Server requests plain text password"
546                                   " but client support disabled");
547
548         if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
549                 server->secType = NTLMv2;
550         else if (secFlags & CIFSSEC_MAY_NTLM)
551                 server->secType = NTLM;
552         else if (secFlags & CIFSSEC_MAY_NTLMV2)
553                 server->secType = NTLMv2;
554         else if (secFlags & CIFSSEC_MAY_KRB5)
555                 server->secType = Kerberos;
556         else if (secFlags & CIFSSEC_MAY_NTLMSSP)
557                 server->secType = RawNTLMSSP;
558         else if (secFlags & CIFSSEC_MAY_LANMAN)
559                 server->secType = LANMAN;
560         else {
561                 rc = -EOPNOTSUPP;
562                 cERROR(1, "Invalid security type");
563                 goto neg_err_exit;
564         }
565         /* else ... any others ...? */
566
567         /* one byte, so no need to convert this or EncryptionKeyLen from
568            little endian */
569         server->maxReq = min_t(unsigned int, le16_to_cpu(pSMBr->MaxMpxCount),
570                                cifs_max_pending);
571         cifs_set_credits(server, server->maxReq);
572         /* probably no need to store and check maxvcs */
573         server->maxBuf = le32_to_cpu(pSMBr->MaxBufferSize);
574         server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
575         cFYI(DBG2, "Max buf = %d", ses->server->maxBuf);
576         server->capabilities = le32_to_cpu(pSMBr->Capabilities);
577         server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
578         server->timeAdj *= 60;
579         if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
580                 memcpy(ses->server->cryptkey, pSMBr->u.EncryptionKey,
581                        CIFS_CRYPTO_KEY_SIZE);
582         } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC ||
583                         server->capabilities & CAP_EXTENDED_SECURITY) &&
584                                 (pSMBr->EncryptionKeyLength == 0)) {
585                 /* decode security blob */
586                 count = get_bcc(&pSMBr->hdr);
587                 if (count < 16) {
588                         rc = -EIO;
589                         goto neg_err_exit;
590                 }
591                 spin_lock(&cifs_tcp_ses_lock);
592                 if (server->srv_count > 1) {
593                         spin_unlock(&cifs_tcp_ses_lock);
594                         if (memcmp(server->server_GUID,
595                                    pSMBr->u.extended_response.
596                                    GUID, 16) != 0) {
597                                 cFYI(1, "server UID changed");
598                                 memcpy(server->server_GUID,
599                                         pSMBr->u.extended_response.GUID,
600                                         16);
601                         }
602                 } else {
603                         spin_unlock(&cifs_tcp_ses_lock);
604                         memcpy(server->server_GUID,
605                                pSMBr->u.extended_response.GUID, 16);
606                 }
607
608                 if (count == 16) {
609                         server->secType = RawNTLMSSP;
610                 } else {
611                         rc = decode_negTokenInit(pSMBr->u.extended_response.
612                                                  SecurityBlob, count - 16,
613                                                  server);
614                         if (rc == 1)
615                                 rc = 0;
616                         else
617                                 rc = -EINVAL;
618                         if (server->secType == Kerberos) {
619                                 if (!server->sec_kerberos &&
620                                                 !server->sec_mskerberos)
621                                         rc = -EOPNOTSUPP;
622                         } else if (server->secType == RawNTLMSSP) {
623                                 if (!server->sec_ntlmssp)
624                                         rc = -EOPNOTSUPP;
625                         } else
626                                         rc = -EOPNOTSUPP;
627                 }
628         } else if (server->sec_mode & SECMODE_PW_ENCRYPT) {
629                 rc = -EIO; /* no crypt key only if plain text pwd */
630                 goto neg_err_exit;
631         } else
632                 server->capabilities &= ~CAP_EXTENDED_SECURITY;
633
634 #ifdef CONFIG_CIFS_WEAK_PW_HASH
635 signing_check:
636 #endif
637         if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
638                 /* MUST_SIGN already includes the MAY_SIGN FLAG
639                    so if this is zero it means that signing is disabled */
640                 cFYI(1, "Signing disabled");
641                 if (server->sec_mode & SECMODE_SIGN_REQUIRED) {
642                         cERROR(1, "Server requires "
643                                    "packet signing to be enabled in "
644                                    "/proc/fs/cifs/SecurityFlags.");
645                         rc = -EOPNOTSUPP;
646                 }
647                 server->sec_mode &=
648                         ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
649         } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
650                 /* signing required */
651                 cFYI(1, "Must sign - secFlags 0x%x", secFlags);
652                 if ((server->sec_mode &
653                         (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
654                         cERROR(1, "signing required but server lacks support");
655                         rc = -EOPNOTSUPP;
656                 } else
657                         server->sec_mode |= SECMODE_SIGN_REQUIRED;
658         } else {
659                 /* signing optional ie CIFSSEC_MAY_SIGN */
660                 if ((server->sec_mode & SECMODE_SIGN_REQUIRED) == 0)
661                         server->sec_mode &=
662                                 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
663         }
664
665 neg_err_exit:
666         cifs_buf_release(pSMB);
667
668         cFYI(1, "negprot rc %d", rc);
669         return rc;
670 }
671
672 int
673 CIFSSMBTDis(const int xid, struct cifs_tcon *tcon)
674 {
675         struct smb_hdr *smb_buffer;
676         int rc = 0;
677
678         cFYI(1, "In tree disconnect");
679
680         /* BB: do we need to check this? These should never be NULL. */
681         if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
682                 return -EIO;
683
684         /*
685          * No need to return error on this operation if tid invalidated and
686          * closed on server already e.g. due to tcp session crashing. Also,
687          * the tcon is no longer on the list, so no need to take lock before
688          * checking this.
689          */
690         if ((tcon->need_reconnect) || (tcon->ses->need_reconnect))
691                 return 0;
692
693         rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
694                             (void **)&smb_buffer);
695         if (rc)
696                 return rc;
697
698         rc = SendReceiveNoRsp(xid, tcon->ses, (char *)smb_buffer, 0);
699         if (rc)
700                 cFYI(1, "Tree disconnect failed %d", rc);
701
702         /* No need to return error on this operation if tid invalidated and
703            closed on server already e.g. due to tcp session crashing */
704         if (rc == -EAGAIN)
705                 rc = 0;
706
707         return rc;
708 }
709
710 /*
711  * This is a no-op for now. We're not really interested in the reply, but
712  * rather in the fact that the server sent one and that server->lstrp
713  * gets updated.
714  *
715  * FIXME: maybe we should consider checking that the reply matches request?
716  */
717 static void
718 cifs_echo_callback(struct mid_q_entry *mid)
719 {
720         struct TCP_Server_Info *server = mid->callback_data;
721
722         DeleteMidQEntry(mid);
723         cifs_add_credits(server, 1);
724 }
725
726 int
727 CIFSSMBEcho(struct TCP_Server_Info *server)
728 {
729         ECHO_REQ *smb;
730         int rc = 0;
731         struct kvec iov;
732
733         cFYI(1, "In echo request");
734
735         rc = small_smb_init(SMB_COM_ECHO, 0, NULL, (void **)&smb);
736         if (rc)
737                 return rc;
738
739         /* set up echo request */
740         smb->hdr.Tid = 0xffff;
741         smb->hdr.WordCount = 1;
742         put_unaligned_le16(1, &smb->EchoCount);
743         put_bcc(1, &smb->hdr);
744         smb->Data[0] = 'a';
745         inc_rfc1001_len(smb, 3);
746         iov.iov_base = smb;
747         iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;
748
749         rc = cifs_call_async(server, &iov, 1, NULL, cifs_echo_callback,
750                              server, true);
751         if (rc)
752                 cFYI(1, "Echo request failed: %d", rc);
753
754         cifs_small_buf_release(smb);
755
756         return rc;
757 }
758
759 int
760 CIFSSMBLogoff(const int xid, struct cifs_ses *ses)
761 {
762         LOGOFF_ANDX_REQ *pSMB;
763         int rc = 0;
764
765         cFYI(1, "In SMBLogoff for session disconnect");
766
767         /*
768          * BB: do we need to check validity of ses and server? They should
769          * always be valid since we have an active reference. If not, that
770          * should probably be a BUG()
771          */
772         if (!ses || !ses->server)
773                 return -EIO;
774
775         mutex_lock(&ses->session_mutex);
776         if (ses->need_reconnect)
777                 goto session_already_dead; /* no need to send SMBlogoff if uid
778                                               already closed due to reconnect */
779         rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
780         if (rc) {
781                 mutex_unlock(&ses->session_mutex);
782                 return rc;
783         }
784
785         pSMB->hdr.Mid = GetNextMid(ses->server);
786
787         if (ses->server->sec_mode &
788                    (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
789                         pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
790
791         pSMB->hdr.Uid = ses->Suid;
792
793         pSMB->AndXCommand = 0xFF;
794         rc = SendReceiveNoRsp(xid, ses, (char *) pSMB, 0);
795 session_already_dead:
796         mutex_unlock(&ses->session_mutex);
797
798         /* if session dead then we do not need to do ulogoff,
799                 since server closed smb session, no sense reporting
800                 error */
801         if (rc == -EAGAIN)
802                 rc = 0;
803         return rc;
804 }
805
806 int
807 CIFSPOSIXDelFile(const int xid, struct cifs_tcon *tcon, const char *fileName,
808                  __u16 type, const struct nls_table *nls_codepage, int remap)
809 {
810         TRANSACTION2_SPI_REQ *pSMB = NULL;
811         TRANSACTION2_SPI_RSP *pSMBr = NULL;
812         struct unlink_psx_rq *pRqD;
813         int name_len;
814         int rc = 0;
815         int bytes_returned = 0;
816         __u16 params, param_offset, offset, byte_count;
817
818         cFYI(1, "In POSIX delete");
819 PsxDelete:
820         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
821                       (void **) &pSMBr);
822         if (rc)
823                 return rc;
824
825         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
826                 name_len =
827                     cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
828                                        PATH_MAX, nls_codepage, remap);
829                 name_len++;     /* trailing null */
830                 name_len *= 2;
831         } else { /* BB add path length overrun check */
832                 name_len = strnlen(fileName, PATH_MAX);
833                 name_len++;     /* trailing null */
834                 strncpy(pSMB->FileName, fileName, name_len);
835         }
836
837         params = 6 + name_len;
838         pSMB->MaxParameterCount = cpu_to_le16(2);
839         pSMB->MaxDataCount = 0; /* BB double check this with jra */
840         pSMB->MaxSetupCount = 0;
841         pSMB->Reserved = 0;
842         pSMB->Flags = 0;
843         pSMB->Timeout = 0;
844         pSMB->Reserved2 = 0;
845         param_offset = offsetof(struct smb_com_transaction2_spi_req,
846                                 InformationLevel) - 4;
847         offset = param_offset + params;
848
849         /* Setup pointer to Request Data (inode type) */
850         pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
851         pRqD->type = cpu_to_le16(type);
852         pSMB->ParameterOffset = cpu_to_le16(param_offset);
853         pSMB->DataOffset = cpu_to_le16(offset);
854         pSMB->SetupCount = 1;
855         pSMB->Reserved3 = 0;
856         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
857         byte_count = 3 /* pad */  + params + sizeof(struct unlink_psx_rq);
858
859         pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
860         pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
861         pSMB->ParameterCount = cpu_to_le16(params);
862         pSMB->TotalParameterCount = pSMB->ParameterCount;
863         pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
864         pSMB->Reserved4 = 0;
865         inc_rfc1001_len(pSMB, byte_count);
866         pSMB->ByteCount = cpu_to_le16(byte_count);
867         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
868                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
869         if (rc)
870                 cFYI(1, "Posix delete returned %d", rc);
871         cifs_buf_release(pSMB);
872
873         cifs_stats_inc(&tcon->num_deletes);
874
875         if (rc == -EAGAIN)
876                 goto PsxDelete;
877
878         return rc;
879 }
880
881 int
882 CIFSSMBDelFile(const int xid, struct cifs_tcon *tcon, const char *fileName,
883                const struct nls_table *nls_codepage, int remap)
884 {
885         DELETE_FILE_REQ *pSMB = NULL;
886         DELETE_FILE_RSP *pSMBr = NULL;
887         int rc = 0;
888         int bytes_returned;
889         int name_len;
890
891 DelFileRetry:
892         rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
893                       (void **) &pSMBr);
894         if (rc)
895                 return rc;
896
897         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
898                 name_len =
899                     cifsConvertToUTF16((__le16 *) pSMB->fileName, fileName,
900                                        PATH_MAX, nls_codepage, remap);
901                 name_len++;     /* trailing null */
902                 name_len *= 2;
903         } else {                /* BB improve check for buffer overruns BB */
904                 name_len = strnlen(fileName, PATH_MAX);
905                 name_len++;     /* trailing null */
906                 strncpy(pSMB->fileName, fileName, name_len);
907         }
908         pSMB->SearchAttributes =
909             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
910         pSMB->BufferFormat = 0x04;
911         inc_rfc1001_len(pSMB, name_len + 1);
912         pSMB->ByteCount = cpu_to_le16(name_len + 1);
913         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
914                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
915         cifs_stats_inc(&tcon->num_deletes);
916         if (rc)
917                 cFYI(1, "Error in RMFile = %d", rc);
918
919         cifs_buf_release(pSMB);
920         if (rc == -EAGAIN)
921                 goto DelFileRetry;
922
923         return rc;
924 }
925
926 int
927 CIFSSMBRmDir(const int xid, struct cifs_tcon *tcon, const char *dirName,
928              const struct nls_table *nls_codepage, int remap)
929 {
930         DELETE_DIRECTORY_REQ *pSMB = NULL;
931         DELETE_DIRECTORY_RSP *pSMBr = NULL;
932         int rc = 0;
933         int bytes_returned;
934         int name_len;
935
936         cFYI(1, "In CIFSSMBRmDir");
937 RmDirRetry:
938         rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
939                       (void **) &pSMBr);
940         if (rc)
941                 return rc;
942
943         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
944                 name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, dirName,
945                                               PATH_MAX, nls_codepage, remap);
946                 name_len++;     /* trailing null */
947                 name_len *= 2;
948         } else {                /* BB improve check for buffer overruns BB */
949                 name_len = strnlen(dirName, PATH_MAX);
950                 name_len++;     /* trailing null */
951                 strncpy(pSMB->DirName, dirName, name_len);
952         }
953
954         pSMB->BufferFormat = 0x04;
955         inc_rfc1001_len(pSMB, name_len + 1);
956         pSMB->ByteCount = cpu_to_le16(name_len + 1);
957         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
958                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
959         cifs_stats_inc(&tcon->num_rmdirs);
960         if (rc)
961                 cFYI(1, "Error in RMDir = %d", rc);
962
963         cifs_buf_release(pSMB);
964         if (rc == -EAGAIN)
965                 goto RmDirRetry;
966         return rc;
967 }
968
969 int
970 CIFSSMBMkDir(const int xid, struct cifs_tcon *tcon,
971              const char *name, const struct nls_table *nls_codepage, int remap)
972 {
973         int rc = 0;
974         CREATE_DIRECTORY_REQ *pSMB = NULL;
975         CREATE_DIRECTORY_RSP *pSMBr = NULL;
976         int bytes_returned;
977         int name_len;
978
979         cFYI(1, "In CIFSSMBMkDir");
980 MkDirRetry:
981         rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
982                       (void **) &pSMBr);
983         if (rc)
984                 return rc;
985
986         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
987                 name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
988                                               PATH_MAX, nls_codepage, remap);
989                 name_len++;     /* trailing null */
990                 name_len *= 2;
991         } else {                /* BB improve check for buffer overruns BB */
992                 name_len = strnlen(name, PATH_MAX);
993                 name_len++;     /* trailing null */
994                 strncpy(pSMB->DirName, name, name_len);
995         }
996
997         pSMB->BufferFormat = 0x04;
998         inc_rfc1001_len(pSMB, name_len + 1);
999         pSMB->ByteCount = cpu_to_le16(name_len + 1);
1000         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1001                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1002         cifs_stats_inc(&tcon->num_mkdirs);
1003         if (rc)
1004                 cFYI(1, "Error in Mkdir = %d", rc);
1005
1006         cifs_buf_release(pSMB);
1007         if (rc == -EAGAIN)
1008                 goto MkDirRetry;
1009         return rc;
1010 }
1011
1012 int
1013 CIFSPOSIXCreate(const int xid, struct cifs_tcon *tcon, __u32 posix_flags,
1014                 __u64 mode, __u16 *netfid, FILE_UNIX_BASIC_INFO *pRetData,
1015                 __u32 *pOplock, const char *name,
1016                 const struct nls_table *nls_codepage, int remap)
1017 {
1018         TRANSACTION2_SPI_REQ *pSMB = NULL;
1019         TRANSACTION2_SPI_RSP *pSMBr = NULL;
1020         int name_len;
1021         int rc = 0;
1022         int bytes_returned = 0;
1023         __u16 params, param_offset, offset, byte_count, count;
1024         OPEN_PSX_REQ *pdata;
1025         OPEN_PSX_RSP *psx_rsp;
1026
1027         cFYI(1, "In POSIX Create");
1028 PsxCreat:
1029         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1030                       (void **) &pSMBr);
1031         if (rc)
1032                 return rc;
1033
1034         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1035                 name_len =
1036                     cifsConvertToUTF16((__le16 *) pSMB->FileName, name,
1037                                        PATH_MAX, nls_codepage, remap);
1038                 name_len++;     /* trailing null */
1039                 name_len *= 2;
1040         } else {        /* BB improve the check for buffer overruns BB */
1041                 name_len = strnlen(name, PATH_MAX);
1042                 name_len++;     /* trailing null */
1043                 strncpy(pSMB->FileName, name, name_len);
1044         }
1045
1046         params = 6 + name_len;
1047         count = sizeof(OPEN_PSX_REQ);
1048         pSMB->MaxParameterCount = cpu_to_le16(2);
1049         pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1050         pSMB->MaxSetupCount = 0;
1051         pSMB->Reserved = 0;
1052         pSMB->Flags = 0;
1053         pSMB->Timeout = 0;
1054         pSMB->Reserved2 = 0;
1055         param_offset = offsetof(struct smb_com_transaction2_spi_req,
1056                                 InformationLevel) - 4;
1057         offset = param_offset + params;
1058         pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1059         pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1060         pdata->Permissions = cpu_to_le64(mode);
1061         pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1062         pdata->OpenFlags =  cpu_to_le32(*pOplock);
1063         pSMB->ParameterOffset = cpu_to_le16(param_offset);
1064         pSMB->DataOffset = cpu_to_le16(offset);
1065         pSMB->SetupCount = 1;
1066         pSMB->Reserved3 = 0;
1067         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1068         byte_count = 3 /* pad */  + params + count;
1069
1070         pSMB->DataCount = cpu_to_le16(count);
1071         pSMB->ParameterCount = cpu_to_le16(params);
1072         pSMB->TotalDataCount = pSMB->DataCount;
1073         pSMB->TotalParameterCount = pSMB->ParameterCount;
1074         pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1075         pSMB->Reserved4 = 0;
1076         inc_rfc1001_len(pSMB, byte_count);
1077         pSMB->ByteCount = cpu_to_le16(byte_count);
1078         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1079                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1080         if (rc) {
1081                 cFYI(1, "Posix create returned %d", rc);
1082                 goto psx_create_err;
1083         }
1084
1085         cFYI(1, "copying inode info");
1086         rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1087
1088         if (rc || get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)) {
1089                 rc = -EIO;      /* bad smb */
1090                 goto psx_create_err;
1091         }
1092
1093         /* copy return information to pRetData */
1094         psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1095                         + le16_to_cpu(pSMBr->t2.DataOffset));
1096
1097         *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1098         if (netfid)
1099                 *netfid = psx_rsp->Fid;   /* cifs fid stays in le */
1100         /* Let caller know file was created so we can set the mode. */
1101         /* Do we care about the CreateAction in any other cases? */
1102         if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1103                 *pOplock |= CIFS_CREATE_ACTION;
1104         /* check to make sure response data is there */
1105         if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1106                 pRetData->Type = cpu_to_le32(-1); /* unknown */
1107                 cFYI(DBG2, "unknown type");
1108         } else {
1109                 if (get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)
1110                                         + sizeof(FILE_UNIX_BASIC_INFO)) {
1111                         cERROR(1, "Open response data too small");
1112                         pRetData->Type = cpu_to_le32(-1);
1113                         goto psx_create_err;
1114                 }
1115                 memcpy((char *) pRetData,
1116                         (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1117                         sizeof(FILE_UNIX_BASIC_INFO));
1118         }
1119
1120 psx_create_err:
1121         cifs_buf_release(pSMB);
1122
1123         if (posix_flags & SMB_O_DIRECTORY)
1124                 cifs_stats_inc(&tcon->num_posixmkdirs);
1125         else
1126                 cifs_stats_inc(&tcon->num_posixopens);
1127
1128         if (rc == -EAGAIN)
1129                 goto PsxCreat;
1130
1131         return rc;
1132 }
1133
1134 static __u16 convert_disposition(int disposition)
1135 {
1136         __u16 ofun = 0;
1137
1138         switch (disposition) {
1139                 case FILE_SUPERSEDE:
1140                         ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1141                         break;
1142                 case FILE_OPEN:
1143                         ofun = SMBOPEN_OAPPEND;
1144                         break;
1145                 case FILE_CREATE:
1146                         ofun = SMBOPEN_OCREATE;
1147                         break;
1148                 case FILE_OPEN_IF:
1149                         ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1150                         break;
1151                 case FILE_OVERWRITE:
1152                         ofun = SMBOPEN_OTRUNC;
1153                         break;
1154                 case FILE_OVERWRITE_IF:
1155                         ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1156                         break;
1157                 default:
1158                         cFYI(1, "unknown disposition %d", disposition);
1159                         ofun =  SMBOPEN_OAPPEND; /* regular open */
1160         }
1161         return ofun;
1162 }
1163
1164 static int
1165 access_flags_to_smbopen_mode(const int access_flags)
1166 {
1167         int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1168
1169         if (masked_flags == GENERIC_READ)
1170                 return SMBOPEN_READ;
1171         else if (masked_flags == GENERIC_WRITE)
1172                 return SMBOPEN_WRITE;
1173
1174         /* just go for read/write */
1175         return SMBOPEN_READWRITE;
1176 }
1177
1178 int
1179 SMBLegacyOpen(const int xid, struct cifs_tcon *tcon,
1180             const char *fileName, const int openDisposition,
1181             const int access_flags, const int create_options, __u16 *netfid,
1182             int *pOplock, FILE_ALL_INFO *pfile_info,
1183             const struct nls_table *nls_codepage, int remap)
1184 {
1185         int rc = -EACCES;
1186         OPENX_REQ *pSMB = NULL;
1187         OPENX_RSP *pSMBr = NULL;
1188         int bytes_returned;
1189         int name_len;
1190         __u16 count;
1191
1192 OldOpenRetry:
1193         rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1194                       (void **) &pSMBr);
1195         if (rc)
1196                 return rc;
1197
1198         pSMB->AndXCommand = 0xFF;       /* none */
1199
1200         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1201                 count = 1;      /* account for one byte pad to word boundary */
1202                 name_len =
1203                    cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
1204                                       fileName, PATH_MAX, nls_codepage, remap);
1205                 name_len++;     /* trailing null */
1206                 name_len *= 2;
1207         } else {                /* BB improve check for buffer overruns BB */
1208                 count = 0;      /* no pad */
1209                 name_len = strnlen(fileName, PATH_MAX);
1210                 name_len++;     /* trailing null */
1211                 strncpy(pSMB->fileName, fileName, name_len);
1212         }
1213         if (*pOplock & REQ_OPLOCK)
1214                 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1215         else if (*pOplock & REQ_BATCHOPLOCK)
1216                 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1217
1218         pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1219         pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1220         pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1221         /* set file as system file if special file such
1222            as fifo and server expecting SFU style and
1223            no Unix extensions */
1224
1225         if (create_options & CREATE_OPTION_SPECIAL)
1226                 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1227         else /* BB FIXME BB */
1228                 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1229
1230         if (create_options & CREATE_OPTION_READONLY)
1231                 pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1232
1233         /* BB FIXME BB */
1234 /*      pSMB->CreateOptions = cpu_to_le32(create_options &
1235                                                  CREATE_OPTIONS_MASK); */
1236         /* BB FIXME END BB */
1237
1238         pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1239         pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1240         count += name_len;
1241         inc_rfc1001_len(pSMB, count);
1242
1243         pSMB->ByteCount = cpu_to_le16(count);
1244         /* long_op set to 1 to allow for oplock break timeouts */
1245         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1246                         (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1247         cifs_stats_inc(&tcon->num_opens);
1248         if (rc) {
1249                 cFYI(1, "Error in Open = %d", rc);
1250         } else {
1251         /* BB verify if wct == 15 */
1252
1253 /*              *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1254
1255                 *netfid = pSMBr->Fid;   /* cifs fid stays in le */
1256                 /* Let caller know file was created so we can set the mode. */
1257                 /* Do we care about the CreateAction in any other cases? */
1258         /* BB FIXME BB */
1259 /*              if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1260                         *pOplock |= CIFS_CREATE_ACTION; */
1261         /* BB FIXME END */
1262
1263                 if (pfile_info) {
1264                         pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1265                         pfile_info->LastAccessTime = 0; /* BB fixme */
1266                         pfile_info->LastWriteTime = 0; /* BB fixme */
1267                         pfile_info->ChangeTime = 0;  /* BB fixme */
1268                         pfile_info->Attributes =
1269                                 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1270                         /* the file_info buf is endian converted by caller */
1271                         pfile_info->AllocationSize =
1272                                 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1273                         pfile_info->EndOfFile = pfile_info->AllocationSize;
1274                         pfile_info->NumberOfLinks = cpu_to_le32(1);
1275                         pfile_info->DeletePending = 0;
1276                 }
1277         }
1278
1279         cifs_buf_release(pSMB);
1280         if (rc == -EAGAIN)
1281                 goto OldOpenRetry;
1282         return rc;
1283 }
1284
1285 int
1286 CIFSSMBOpen(const int xid, struct cifs_tcon *tcon,
1287             const char *fileName, const int openDisposition,
1288             const int access_flags, const int create_options, __u16 *netfid,
1289             int *pOplock, FILE_ALL_INFO *pfile_info,
1290             const struct nls_table *nls_codepage, int remap)
1291 {
1292         int rc = -EACCES;
1293         OPEN_REQ *pSMB = NULL;
1294         OPEN_RSP *pSMBr = NULL;
1295         int bytes_returned;
1296         int name_len;
1297         __u16 count;
1298
1299 openRetry:
1300         rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1301                       (void **) &pSMBr);
1302         if (rc)
1303                 return rc;
1304
1305         pSMB->AndXCommand = 0xFF;       /* none */
1306
1307         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1308                 count = 1;      /* account for one byte pad to word boundary */
1309                 name_len =
1310                     cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
1311                                        fileName, PATH_MAX, nls_codepage, remap);
1312                 name_len++;     /* trailing null */
1313                 name_len *= 2;
1314                 pSMB->NameLength = cpu_to_le16(name_len);
1315         } else {                /* BB improve check for buffer overruns BB */
1316                 count = 0;      /* no pad */
1317                 name_len = strnlen(fileName, PATH_MAX);
1318                 name_len++;     /* trailing null */
1319                 pSMB->NameLength = cpu_to_le16(name_len);
1320                 strncpy(pSMB->fileName, fileName, name_len);
1321         }
1322         if (*pOplock & REQ_OPLOCK)
1323                 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1324         else if (*pOplock & REQ_BATCHOPLOCK)
1325                 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1326         pSMB->DesiredAccess = cpu_to_le32(access_flags);
1327         pSMB->AllocationSize = 0;
1328         /* set file as system file if special file such
1329            as fifo and server expecting SFU style and
1330            no Unix extensions */
1331         if (create_options & CREATE_OPTION_SPECIAL)
1332                 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1333         else
1334                 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1335
1336         /* XP does not handle ATTR_POSIX_SEMANTICS */
1337         /* but it helps speed up case sensitive checks for other
1338         servers such as Samba */
1339         if (tcon->ses->capabilities & CAP_UNIX)
1340                 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1341
1342         if (create_options & CREATE_OPTION_READONLY)
1343                 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1344
1345         pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1346         pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1347         pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1348         /* BB Expirement with various impersonation levels and verify */
1349         pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1350         pSMB->SecurityFlags =
1351             SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1352
1353         count += name_len;
1354         inc_rfc1001_len(pSMB, count);
1355
1356         pSMB->ByteCount = cpu_to_le16(count);
1357         /* long_op set to 1 to allow for oplock break timeouts */
1358         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1359                         (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1360         cifs_stats_inc(&tcon->num_opens);
1361         if (rc) {
1362                 cFYI(1, "Error in Open = %d", rc);
1363         } else {
1364                 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1365                 *netfid = pSMBr->Fid;   /* cifs fid stays in le */
1366                 /* Let caller know file was created so we can set the mode. */
1367                 /* Do we care about the CreateAction in any other cases? */
1368                 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1369                         *pOplock |= CIFS_CREATE_ACTION;
1370                 if (pfile_info) {
1371                         memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1372                                 36 /* CreationTime to Attributes */);
1373                         /* the file_info buf is endian converted by caller */
1374                         pfile_info->AllocationSize = pSMBr->AllocationSize;
1375                         pfile_info->EndOfFile = pSMBr->EndOfFile;
1376                         pfile_info->NumberOfLinks = cpu_to_le32(1);
1377                         pfile_info->DeletePending = 0;
1378                 }
1379         }
1380
1381         cifs_buf_release(pSMB);
1382         if (rc == -EAGAIN)
1383                 goto openRetry;
1384         return rc;
1385 }
1386
1387 /*
1388  * Discard any remaining data in the current SMB. To do this, we borrow the
1389  * current bigbuf.
1390  */
1391 static int
1392 cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1393 {
1394         unsigned int rfclen = get_rfc1002_length(server->smallbuf);
1395         int remaining = rfclen + 4 - server->total_read;
1396         struct cifs_readdata *rdata = mid->callback_data;
1397
1398         while (remaining > 0) {
1399                 int length;
1400
1401                 length = cifs_read_from_socket(server, server->bigbuf,
1402                                 min_t(unsigned int, remaining,
1403                                         CIFSMaxBufSize + max_header_size()));
1404                 if (length < 0)
1405                         return length;
1406                 server->total_read += length;
1407                 remaining -= length;
1408         }
1409
1410         dequeue_mid(mid, rdata->result);
1411         return 0;
1412 }
1413
1414 static inline size_t
1415 read_rsp_size(void)
1416 {
1417         return sizeof(READ_RSP);
1418 }
1419
1420 static inline unsigned int
1421 read_data_offset(char *buf)
1422 {
1423         READ_RSP *rsp = (READ_RSP *)buf;
1424         return le16_to_cpu(rsp->DataOffset);
1425 }
1426
1427 static inline unsigned int
1428 read_data_length(char *buf)
1429 {
1430         READ_RSP *rsp = (READ_RSP *)buf;
1431         return (le16_to_cpu(rsp->DataLengthHigh) << 16) +
1432                le16_to_cpu(rsp->DataLength);
1433 }
1434
1435 static int
1436 cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1437 {
1438         int length, len;
1439         unsigned int data_offset, data_len;
1440         struct cifs_readdata *rdata = mid->callback_data;
1441         char *buf = server->smallbuf;
1442         unsigned int buflen = get_rfc1002_length(buf) + 4;
1443
1444         cFYI(1, "%s: mid=%llu offset=%llu bytes=%u", __func__,
1445                 mid->mid, rdata->offset, rdata->bytes);
1446
1447         /*
1448          * read the rest of READ_RSP header (sans Data array), or whatever we
1449          * can if there's not enough data. At this point, we've read down to
1450          * the Mid.
1451          */
1452         len = min_t(unsigned int, buflen, read_rsp_size()) - header_size() + 1;
1453
1454         rdata->iov[0].iov_base = buf + header_size() - 1;
1455         rdata->iov[0].iov_len = len;
1456
1457         length = cifs_readv_from_socket(server, rdata->iov, 1, len);
1458         if (length < 0)
1459                 return length;
1460         server->total_read += length;
1461
1462         /* Was the SMB read successful? */
1463         rdata->result = map_smb_to_linux_error(buf, false);
1464         if (rdata->result != 0) {
1465                 cFYI(1, "%s: server returned error %d", __func__,
1466                         rdata->result);
1467                 return cifs_readv_discard(server, mid);
1468         }
1469
1470         /* Is there enough to get to the rest of the READ_RSP header? */
1471         if (server->total_read < read_rsp_size()) {
1472                 cFYI(1, "%s: server returned short header. got=%u expected=%zu",
1473                         __func__, server->total_read, read_rsp_size());
1474                 rdata->result = -EIO;
1475                 return cifs_readv_discard(server, mid);
1476         }
1477
1478         data_offset = 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                 cFYI(1, "%s: data offset (%u) inside read response header",
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                 cFYI(1, "%s: data offset (%u) beyond end of smallbuf",
1491                         __func__, data_offset);
1492                 rdata->result = -EIO;
1493                 return cifs_readv_discard(server, mid);
1494         }
1495
1496         cFYI(1, "%s: total_read=%u data_offset=%u", __func__,
1497                 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                 rdata->iov[0].iov_base = buf + server->total_read;
1503                 rdata->iov[0].iov_len = len;
1504                 length = cifs_readv_from_socket(server, rdata->iov, 1, len);
1505                 if (length < 0)
1506                         return length;
1507                 server->total_read += length;
1508         }
1509
1510         /* set up first iov for signature check */
1511         rdata->iov[0].iov_base = buf;
1512         rdata->iov[0].iov_len = server->total_read;
1513         cFYI(1, "0: iov_base=%p iov_len=%zu",
1514                 rdata->iov[0].iov_base, rdata->iov[0].iov_len);
1515
1516         /* how much data is in the response? */
1517         data_len = read_data_length(buf);
1518         if (data_offset + data_len > buflen) {
1519                 /* data_len is corrupt -- discard frame */
1520                 rdata->result = -EIO;
1521                 return cifs_readv_discard(server, mid);
1522         }
1523
1524         /* marshal up the page array */
1525         len = rdata->marshal_iov(rdata, data_len);
1526         data_len -= len;
1527
1528         /* issue the read if we have any iovecs left to fill */
1529         if (rdata->nr_iov > 1) {
1530                 length = cifs_readv_from_socket(server, &rdata->iov[1],
1531                                                 rdata->nr_iov - 1, len);
1532                 if (length < 0)
1533                         return length;
1534                 server->total_read += length;
1535         } else {
1536                 length = 0;
1537         }
1538
1539         rdata->bytes = length;
1540
1541         cFYI(1, "total_read=%u buflen=%u remaining=%u", server->total_read,
1542                 buflen, data_len);
1543
1544         /* discard anything left over */
1545         if (server->total_read < buflen)
1546                 return cifs_readv_discard(server, mid);
1547
1548         dequeue_mid(mid, false);
1549         return length;
1550 }
1551
1552 static void
1553 cifs_readv_callback(struct mid_q_entry *mid)
1554 {
1555         struct cifs_readdata *rdata = mid->callback_data;
1556         struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1557         struct TCP_Server_Info *server = tcon->ses->server;
1558
1559         cFYI(1, "%s: mid=%llu state=%d result=%d bytes=%u", __func__,
1560                 mid->mid, mid->mid_state, rdata->result, rdata->bytes);
1561
1562         switch (mid->mid_state) {
1563         case MID_RESPONSE_RECEIVED:
1564                 /* result already set, check signature */
1565                 if (server->sec_mode &
1566                     (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
1567                         if (cifs_verify_signature(rdata->iov, rdata->nr_iov,
1568                                           server, mid->sequence_number + 1))
1569                                 cERROR(1, "Unexpected SMB signature");
1570                 }
1571                 /* FIXME: should this be counted toward the initiating task? */
1572                 task_io_account_read(rdata->bytes);
1573                 cifs_stats_bytes_read(tcon, rdata->bytes);
1574                 break;
1575         case MID_REQUEST_SUBMITTED:
1576         case MID_RETRY_NEEDED:
1577                 rdata->result = -EAGAIN;
1578                 break;
1579         default:
1580                 rdata->result = -EIO;
1581         }
1582
1583         queue_work(cifsiod_wq, &rdata->work);
1584         DeleteMidQEntry(mid);
1585         cifs_add_credits(server, 1);
1586 }
1587
1588 /* cifs_async_readv - send an async write, and set up mid to handle result */
1589 int
1590 cifs_async_readv(struct cifs_readdata *rdata)
1591 {
1592         int rc;
1593         READ_REQ *smb = NULL;
1594         int wct;
1595         struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1596
1597         cFYI(1, "%s: offset=%llu bytes=%u", __func__,
1598                 rdata->offset, rdata->bytes);
1599
1600         if (tcon->ses->capabilities & CAP_LARGE_FILES)
1601                 wct = 12;
1602         else {
1603                 wct = 10; /* old style read */
1604                 if ((rdata->offset >> 32) > 0)  {
1605                         /* can not handle this big offset for old */
1606                         return -EIO;
1607                 }
1608         }
1609
1610         rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **)&smb);
1611         if (rc)
1612                 return rc;
1613
1614         smb->hdr.Pid = cpu_to_le16((__u16)rdata->pid);
1615         smb->hdr.PidHigh = cpu_to_le16((__u16)(rdata->pid >> 16));
1616
1617         smb->AndXCommand = 0xFF;        /* none */
1618         smb->Fid = rdata->cfile->netfid;
1619         smb->OffsetLow = cpu_to_le32(rdata->offset & 0xFFFFFFFF);
1620         if (wct == 12)
1621                 smb->OffsetHigh = cpu_to_le32(rdata->offset >> 32);
1622         smb->Remaining = 0;
1623         smb->MaxCount = cpu_to_le16(rdata->bytes & 0xFFFF);
1624         smb->MaxCountHigh = cpu_to_le32(rdata->bytes >> 16);
1625         if (wct == 12)
1626                 smb->ByteCount = 0;
1627         else {
1628                 /* old style read */
1629                 struct smb_com_readx_req *smbr =
1630                         (struct smb_com_readx_req *)smb;
1631                 smbr->ByteCount = 0;
1632         }
1633
1634         /* 4 for RFC1001 length + 1 for BCC */
1635         rdata->iov[0].iov_base = smb;
1636         rdata->iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;
1637
1638         kref_get(&rdata->refcount);
1639         rc = cifs_call_async(tcon->ses->server, rdata->iov, 1,
1640                              cifs_readv_receive, cifs_readv_callback,
1641                              rdata, false);
1642
1643         if (rc == 0)
1644                 cifs_stats_inc(&tcon->num_reads);
1645         else
1646                 kref_put(&rdata->refcount, cifs_readdata_release);
1647
1648         cifs_small_buf_release(smb);
1649         return rc;
1650 }
1651
1652 int
1653 CIFSSMBRead(const int xid, struct cifs_io_parms *io_parms, unsigned int *nbytes,
1654             char **buf, int *pbuf_type)
1655 {
1656         int rc = -EACCES;
1657         READ_REQ *pSMB = NULL;
1658         READ_RSP *pSMBr = NULL;
1659         char *pReadData = NULL;
1660         int wct;
1661         int resp_buf_type = 0;
1662         struct kvec iov[1];
1663         __u32 pid = io_parms->pid;
1664         __u16 netfid = io_parms->netfid;
1665         __u64 offset = io_parms->offset;
1666         struct cifs_tcon *tcon = io_parms->tcon;
1667         unsigned int count = io_parms->length;
1668
1669         cFYI(1, "Reading %d bytes on fid %d", count, netfid);
1670         if (tcon->ses->capabilities & CAP_LARGE_FILES)
1671                 wct = 12;
1672         else {
1673                 wct = 10; /* old style read */
1674                 if ((offset >> 32) > 0)  {
1675                         /* can not handle this big offset for old */
1676                         return -EIO;
1677                 }
1678         }
1679
1680         *nbytes = 0;
1681         rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1682         if (rc)
1683                 return rc;
1684
1685         pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1686         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1687
1688         /* tcon and ses pointer are checked in smb_init */
1689         if (tcon->ses->server == NULL)
1690                 return -ECONNABORTED;
1691
1692         pSMB->AndXCommand = 0xFF;       /* none */
1693         pSMB->Fid = netfid;
1694         pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1695         if (wct == 12)
1696                 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1697
1698         pSMB->Remaining = 0;
1699         pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1700         pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1701         if (wct == 12)
1702                 pSMB->ByteCount = 0;  /* no need to do le conversion since 0 */
1703         else {
1704                 /* old style read */
1705                 struct smb_com_readx_req *pSMBW =
1706                         (struct smb_com_readx_req *)pSMB;
1707                 pSMBW->ByteCount = 0;
1708         }
1709
1710         iov[0].iov_base = (char *)pSMB;
1711         iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
1712         rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1713                          &resp_buf_type, CIFS_LOG_ERROR);
1714         cifs_stats_inc(&tcon->num_reads);
1715         pSMBr = (READ_RSP *)iov[0].iov_base;
1716         if (rc) {
1717                 cERROR(1, "Send error in read = %d", rc);
1718         } else {
1719                 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1720                 data_length = data_length << 16;
1721                 data_length += le16_to_cpu(pSMBr->DataLength);
1722                 *nbytes = data_length;
1723
1724                 /*check that DataLength would not go beyond end of SMB */
1725                 if ((data_length > CIFSMaxBufSize)
1726                                 || (data_length > count)) {
1727                         cFYI(1, "bad length %d for count %d",
1728                                  data_length, count);
1729                         rc = -EIO;
1730                         *nbytes = 0;
1731                 } else {
1732                         pReadData = (char *) (&pSMBr->hdr.Protocol) +
1733                                         le16_to_cpu(pSMBr->DataOffset);
1734 /*                      if (rc = copy_to_user(buf, pReadData, data_length)) {
1735                                 cERROR(1, "Faulting on read rc = %d",rc);
1736                                 rc = -EFAULT;
1737                         }*/ /* can not use copy_to_user when using page cache*/
1738                         if (*buf)
1739                                 memcpy(*buf, pReadData, data_length);
1740                 }
1741         }
1742
1743 /*      cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1744         if (*buf) {
1745                 if (resp_buf_type == CIFS_SMALL_BUFFER)
1746                         cifs_small_buf_release(iov[0].iov_base);
1747                 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1748                         cifs_buf_release(iov[0].iov_base);
1749         } else if (resp_buf_type != CIFS_NO_BUFFER) {
1750                 /* return buffer to caller to free */
1751                 *buf = iov[0].iov_base;
1752                 if (resp_buf_type == CIFS_SMALL_BUFFER)
1753                         *pbuf_type = CIFS_SMALL_BUFFER;
1754                 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1755                         *pbuf_type = CIFS_LARGE_BUFFER;
1756         } /* else no valid buffer on return - leave as null */
1757
1758         /* Note: On -EAGAIN error only caller can retry on handle based calls
1759                 since file handle passed in no longer valid */
1760         return rc;
1761 }
1762
1763
1764 int
1765 CIFSSMBWrite(const int xid, struct cifs_io_parms *io_parms,
1766              unsigned int *nbytes, const char *buf,
1767              const char __user *ubuf, const int long_op)
1768 {
1769         int rc = -EACCES;
1770         WRITE_REQ *pSMB = NULL;
1771         WRITE_RSP *pSMBr = NULL;
1772         int bytes_returned, wct;
1773         __u32 bytes_sent;
1774         __u16 byte_count;
1775         __u32 pid = io_parms->pid;
1776         __u16 netfid = io_parms->netfid;
1777         __u64 offset = io_parms->offset;
1778         struct cifs_tcon *tcon = io_parms->tcon;
1779         unsigned int count = io_parms->length;
1780
1781         *nbytes = 0;
1782
1783         /* cFYI(1, "write at %lld %d bytes", offset, count);*/
1784         if (tcon->ses == NULL)
1785                 return -ECONNABORTED;
1786
1787         if (tcon->ses->capabilities & CAP_LARGE_FILES)
1788                 wct = 14;
1789         else {
1790                 wct = 12;
1791                 if ((offset >> 32) > 0) {
1792                         /* can not handle big offset for old srv */
1793                         return -EIO;
1794                 }
1795         }
1796
1797         rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1798                       (void **) &pSMBr);
1799         if (rc)
1800                 return rc;
1801
1802         pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1803         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1804
1805         /* tcon and ses pointer are checked in smb_init */
1806         if (tcon->ses->server == NULL)
1807                 return -ECONNABORTED;
1808
1809         pSMB->AndXCommand = 0xFF;       /* none */
1810         pSMB->Fid = netfid;
1811         pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1812         if (wct == 14)
1813                 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1814
1815         pSMB->Reserved = 0xFFFFFFFF;
1816         pSMB->WriteMode = 0;
1817         pSMB->Remaining = 0;
1818
1819         /* Can increase buffer size if buffer is big enough in some cases ie we
1820         can send more if LARGE_WRITE_X capability returned by the server and if
1821         our buffer is big enough or if we convert to iovecs on socket writes
1822         and eliminate the copy to the CIFS buffer */
1823         if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1824                 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1825         } else {
1826                 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1827                          & ~0xFF;
1828         }
1829
1830         if (bytes_sent > count)
1831                 bytes_sent = count;
1832         pSMB->DataOffset =
1833                 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1834         if (buf)
1835                 memcpy(pSMB->Data, buf, bytes_sent);
1836         else if (ubuf) {
1837                 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1838                         cifs_buf_release(pSMB);
1839                         return -EFAULT;
1840                 }
1841         } else if (count != 0) {
1842                 /* No buffer */
1843                 cifs_buf_release(pSMB);
1844                 return -EINVAL;
1845         } /* else setting file size with write of zero bytes */
1846         if (wct == 14)
1847                 byte_count = bytes_sent + 1; /* pad */
1848         else /* wct == 12 */
1849                 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1850
1851         pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1852         pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1853         inc_rfc1001_len(pSMB, byte_count);
1854
1855         if (wct == 14)
1856                 pSMB->ByteCount = cpu_to_le16(byte_count);
1857         else { /* old style write has byte count 4 bytes earlier
1858                   so 4 bytes pad  */
1859                 struct smb_com_writex_req *pSMBW =
1860                         (struct smb_com_writex_req *)pSMB;
1861                 pSMBW->ByteCount = cpu_to_le16(byte_count);
1862         }
1863
1864         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1865                          (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1866         cifs_stats_inc(&tcon->num_writes);
1867         if (rc) {
1868                 cFYI(1, "Send error in write = %d", rc);
1869         } else {
1870                 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1871                 *nbytes = (*nbytes) << 16;
1872                 *nbytes += le16_to_cpu(pSMBr->Count);
1873
1874                 /*
1875                  * Mask off high 16 bits when bytes written as returned by the
1876                  * server is greater than bytes requested by the client. Some
1877                  * OS/2 servers are known to set incorrect CountHigh values.
1878                  */
1879                 if (*nbytes > count)
1880                         *nbytes &= 0xFFFF;
1881         }
1882
1883         cifs_buf_release(pSMB);
1884
1885         /* Note: On -EAGAIN error only caller can retry on handle based calls
1886                 since file handle passed in no longer valid */
1887
1888         return rc;
1889 }
1890
1891 void
1892 cifs_writedata_release(struct kref *refcount)
1893 {
1894         struct cifs_writedata *wdata = container_of(refcount,
1895                                         struct cifs_writedata, refcount);
1896
1897         if (wdata->cfile)
1898                 cifsFileInfo_put(wdata->cfile);
1899
1900         kfree(wdata);
1901 }
1902
1903 /*
1904  * Write failed with a retryable error. Resend the write request. It's also
1905  * possible that the page was redirtied so re-clean the page.
1906  */
1907 static void
1908 cifs_writev_requeue(struct cifs_writedata *wdata)
1909 {
1910         int i, rc;
1911         struct inode *inode = wdata->cfile->dentry->d_inode;
1912
1913         for (i = 0; i < wdata->nr_pages; i++) {
1914                 lock_page(wdata->pages[i]);
1915                 clear_page_dirty_for_io(wdata->pages[i]);
1916         }
1917
1918         do {
1919                 rc = cifs_async_writev(wdata);
1920         } while (rc == -EAGAIN);
1921
1922         for (i = 0; i < wdata->nr_pages; i++) {
1923                 if (rc != 0)
1924                         SetPageError(wdata->pages[i]);
1925                 unlock_page(wdata->pages[i]);
1926         }
1927
1928         mapping_set_error(inode->i_mapping, rc);
1929         kref_put(&wdata->refcount, cifs_writedata_release);
1930 }
1931
1932 void
1933 cifs_writev_complete(struct work_struct *work)
1934 {
1935         struct cifs_writedata *wdata = container_of(work,
1936                                                 struct cifs_writedata, work);
1937         struct inode *inode = wdata->cfile->dentry->d_inode;
1938         int i = 0;
1939
1940         if (wdata->result == 0) {
1941                 spin_lock(&inode->i_lock);
1942                 cifs_update_eof(CIFS_I(inode), wdata->offset, wdata->bytes);
1943                 spin_unlock(&inode->i_lock);
1944                 cifs_stats_bytes_written(tlink_tcon(wdata->cfile->tlink),
1945                                          wdata->bytes);
1946         } else if (wdata->sync_mode == WB_SYNC_ALL && wdata->result == -EAGAIN)
1947                 return cifs_writev_requeue(wdata);
1948
1949         for (i = 0; i < wdata->nr_pages; i++) {
1950                 struct page *page = wdata->pages[i];
1951                 if (wdata->result == -EAGAIN)
1952                         __set_page_dirty_nobuffers(page);
1953                 else if (wdata->result < 0)
1954                         SetPageError(page);
1955                 end_page_writeback(page);
1956                 page_cache_release(page);
1957         }
1958         if (wdata->result != -EAGAIN)
1959                 mapping_set_error(inode->i_mapping, wdata->result);
1960         kref_put(&wdata->refcount, cifs_writedata_release);
1961 }
1962
1963 struct cifs_writedata *
1964 cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete)
1965 {
1966         struct cifs_writedata *wdata;
1967
1968         /* this would overflow */
1969         if (nr_pages == 0) {
1970                 cERROR(1, "%s: called with nr_pages == 0!", __func__);
1971                 return NULL;
1972         }
1973
1974         /* writedata + number of page pointers */
1975         wdata = kzalloc(sizeof(*wdata) +
1976                         sizeof(struct page *) * (nr_pages - 1), GFP_NOFS);
1977         if (wdata != NULL) {
1978                 kref_init(&wdata->refcount);
1979                 INIT_LIST_HEAD(&wdata->list);
1980                 init_completion(&wdata->done);
1981                 INIT_WORK(&wdata->work, complete);
1982         }
1983         return wdata;
1984 }
1985
1986 /*
1987  * Check the mid_state and signature on received buffer (if any), and queue the
1988  * workqueue completion task.
1989  */
1990 static void
1991 cifs_writev_callback(struct mid_q_entry *mid)
1992 {
1993         struct cifs_writedata *wdata = mid->callback_data;
1994         struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
1995         unsigned int written;
1996         WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
1997
1998         switch (mid->mid_state) {
1999         case MID_RESPONSE_RECEIVED:
2000                 wdata->result = cifs_check_receive(mid, tcon->ses->server, 0);
2001                 if (wdata->result != 0)
2002                         break;
2003
2004                 written = le16_to_cpu(smb->CountHigh);
2005                 written <<= 16;
2006                 written += le16_to_cpu(smb->Count);
2007                 /*
2008                  * Mask off high 16 bits when bytes written as returned
2009                  * by the server is greater than bytes requested by the
2010                  * client. OS/2 servers are known to set incorrect
2011                  * CountHigh values.
2012                  */
2013                 if (written > wdata->bytes)
2014                         written &= 0xFFFF;
2015
2016                 if (written < wdata->bytes)
2017                         wdata->result = -ENOSPC;
2018                 else
2019                         wdata->bytes = written;
2020                 break;
2021         case MID_REQUEST_SUBMITTED:
2022         case MID_RETRY_NEEDED:
2023                 wdata->result = -EAGAIN;
2024                 break;
2025         default:
2026                 wdata->result = -EIO;
2027                 break;
2028         }
2029
2030         queue_work(cifsiod_wq, &wdata->work);
2031         DeleteMidQEntry(mid);
2032         cifs_add_credits(tcon->ses->server, 1);
2033 }
2034
2035 /* cifs_async_writev - send an async write, and set up mid to handle result */
2036 int
2037 cifs_async_writev(struct cifs_writedata *wdata)
2038 {
2039         int i, rc = -EACCES;
2040         WRITE_REQ *smb = NULL;
2041         int wct;
2042         struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2043         struct kvec *iov = NULL;
2044
2045         if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2046                 wct = 14;
2047         } else {
2048                 wct = 12;
2049                 if (wdata->offset >> 32 > 0) {
2050                         /* can not handle big offset for old srv */
2051                         return -EIO;
2052                 }
2053         }
2054
2055         rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **)&smb);
2056         if (rc)
2057                 goto async_writev_out;
2058
2059         /* 1 iov per page + 1 for header */
2060         iov = kzalloc((wdata->nr_pages + 1) * sizeof(*iov), GFP_NOFS);
2061         if (iov == NULL) {
2062                 rc = -ENOMEM;
2063                 goto async_writev_out;
2064         }
2065
2066         smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid);
2067         smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16));
2068
2069         smb->AndXCommand = 0xFF;        /* none */
2070         smb->Fid = wdata->cfile->netfid;
2071         smb->OffsetLow = cpu_to_le32(wdata->offset & 0xFFFFFFFF);
2072         if (wct == 14)
2073                 smb->OffsetHigh = cpu_to_le32(wdata->offset >> 32);
2074         smb->Reserved = 0xFFFFFFFF;
2075         smb->WriteMode = 0;
2076         smb->Remaining = 0;
2077
2078         smb->DataOffset =
2079             cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2080
2081         /* 4 for RFC1001 length + 1 for BCC */
2082         iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1;
2083         iov[0].iov_base = smb;
2084
2085         /*
2086          * This function should marshal up the page array into the kvec
2087          * array, reserving [0] for the header. It should kmap the pages
2088          * and set the iov_len properly for each one. It may also set
2089          * wdata->bytes too.
2090          */
2091         wdata->marshal_iov(iov, wdata);
2092
2093         cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes);
2094
2095         smb->DataLengthLow = cpu_to_le16(wdata->bytes & 0xFFFF);
2096         smb->DataLengthHigh = cpu_to_le16(wdata->bytes >> 16);
2097
2098         if (wct == 14) {
2099                 inc_rfc1001_len(&smb->hdr, wdata->bytes + 1);
2100                 put_bcc(wdata->bytes + 1, &smb->hdr);
2101         } else {
2102                 /* wct == 12 */
2103                 struct smb_com_writex_req *smbw =
2104                                 (struct smb_com_writex_req *)smb;
2105                 inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5);
2106                 put_bcc(wdata->bytes + 5, &smbw->hdr);
2107                 iov[0].iov_len += 4; /* pad bigger by four bytes */
2108         }
2109
2110         kref_get(&wdata->refcount);
2111         rc = cifs_call_async(tcon->ses->server, iov, wdata->nr_pages + 1,
2112                              NULL, cifs_writev_callback, wdata, false);
2113
2114         if (rc == 0)
2115                 cifs_stats_inc(&tcon->num_writes);
2116         else
2117                 kref_put(&wdata->refcount, cifs_writedata_release);
2118
2119         /* send is done, unmap pages */
2120         for (i = 0; i < wdata->nr_pages; i++)
2121                 kunmap(wdata->pages[i]);
2122
2123 async_writev_out:
2124         cifs_small_buf_release(smb);
2125         kfree(iov);
2126         return rc;
2127 }
2128
2129 int
2130 CIFSSMBWrite2(const int xid, struct cifs_io_parms *io_parms,
2131               unsigned int *nbytes, struct kvec *iov, int n_vec,
2132               const int long_op)
2133 {
2134         int rc = -EACCES;
2135         WRITE_REQ *pSMB = NULL;
2136         int wct;
2137         int smb_hdr_len;
2138         int resp_buf_type = 0;
2139         __u32 pid = io_parms->pid;
2140         __u16 netfid = io_parms->netfid;
2141         __u64 offset = io_parms->offset;
2142         struct cifs_tcon *tcon = io_parms->tcon;
2143         unsigned int count = io_parms->length;
2144
2145         *nbytes = 0;
2146
2147         cFYI(1, "write2 at %lld %d bytes", (long long)offset, count);
2148
2149         if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2150                 wct = 14;
2151         } else {
2152                 wct = 12;
2153                 if ((offset >> 32) > 0) {
2154                         /* can not handle big offset for old srv */
2155                         return -EIO;
2156                 }
2157         }
2158         rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
2159         if (rc)
2160                 return rc;
2161
2162         pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
2163         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
2164
2165         /* tcon and ses pointer are checked in smb_init */
2166         if (tcon->ses->server == NULL)
2167                 return -ECONNABORTED;
2168
2169         pSMB->AndXCommand = 0xFF;       /* none */
2170         pSMB->Fid = netfid;
2171         pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
2172         if (wct == 14)
2173                 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
2174         pSMB->Reserved = 0xFFFFFFFF;
2175         pSMB->WriteMode = 0;
2176         pSMB->Remaining = 0;
2177
2178         pSMB->DataOffset =
2179             cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2180
2181         pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
2182         pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
2183         /* header + 1 byte pad */
2184         smb_hdr_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 1;
2185         if (wct == 14)
2186                 inc_rfc1001_len(pSMB, count + 1);
2187         else /* wct == 12 */
2188                 inc_rfc1001_len(pSMB, count + 5); /* smb data starts later */
2189         if (wct == 14)
2190                 pSMB->ByteCount = cpu_to_le16(count + 1);
2191         else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
2192                 struct smb_com_writex_req *pSMBW =
2193                                 (struct smb_com_writex_req *)pSMB;
2194                 pSMBW->ByteCount = cpu_to_le16(count + 5);
2195         }
2196         iov[0].iov_base = pSMB;
2197         if (wct == 14)
2198                 iov[0].iov_len = smb_hdr_len + 4;
2199         else /* wct == 12 pad bigger by four bytes */
2200                 iov[0].iov_len = smb_hdr_len + 8;
2201
2202
2203         rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
2204                           long_op);
2205         cifs_stats_inc(&tcon->num_writes);
2206         if (rc) {
2207                 cFYI(1, "Send error Write2 = %d", rc);
2208         } else if (resp_buf_type == 0) {
2209                 /* presumably this can not happen, but best to be safe */
2210                 rc = -EIO;
2211         } else {
2212                 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
2213                 *nbytes = le16_to_cpu(pSMBr->CountHigh);
2214                 *nbytes = (*nbytes) << 16;
2215                 *nbytes += le16_to_cpu(pSMBr->Count);
2216
2217                 /*
2218                  * Mask off high 16 bits when bytes written as returned by the
2219                  * server is greater than bytes requested by the client. OS/2
2220                  * servers are known to set incorrect CountHigh values.
2221                  */
2222                 if (*nbytes > count)
2223                         *nbytes &= 0xFFFF;
2224         }
2225
2226 /*      cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
2227         if (resp_buf_type == CIFS_SMALL_BUFFER)
2228                 cifs_small_buf_release(iov[0].iov_base);
2229         else if (resp_buf_type == CIFS_LARGE_BUFFER)
2230                 cifs_buf_release(iov[0].iov_base);
2231
2232         /* Note: On -EAGAIN error only caller can retry on handle based calls
2233                 since file handle passed in no longer valid */
2234
2235         return rc;
2236 }
2237
2238 int cifs_lockv(const int xid, struct cifs_tcon *tcon, const __u16 netfid,
2239                const __u8 lock_type, const __u32 num_unlock,
2240                const __u32 num_lock, LOCKING_ANDX_RANGE *buf)
2241 {
2242         int rc = 0;
2243         LOCK_REQ *pSMB = NULL;
2244         struct kvec iov[2];
2245         int resp_buf_type;
2246         __u16 count;
2247
2248         cFYI(1, "cifs_lockv num lock %d num unlock %d", num_lock, num_unlock);
2249
2250         rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2251         if (rc)
2252                 return rc;
2253
2254         pSMB->Timeout = 0;
2255         pSMB->NumberOfLocks = cpu_to_le16(num_lock);
2256         pSMB->NumberOfUnlocks = cpu_to_le16(num_unlock);
2257         pSMB->LockType = lock_type;
2258         pSMB->AndXCommand = 0xFF; /* none */
2259         pSMB->Fid = netfid; /* netfid stays le */
2260
2261         count = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2262         inc_rfc1001_len(pSMB, count);
2263         pSMB->ByteCount = cpu_to_le16(count);
2264
2265         iov[0].iov_base = (char *)pSMB;
2266         iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4 -
2267                          (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2268         iov[1].iov_base = (char *)buf;
2269         iov[1].iov_len = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2270
2271         cifs_stats_inc(&tcon->num_locks);
2272         rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type, CIFS_NO_RESP);
2273         if (rc)
2274                 cFYI(1, "Send error in cifs_lockv = %d", rc);
2275
2276         return rc;
2277 }
2278
2279 int
2280 CIFSSMBLock(const int xid, struct cifs_tcon *tcon,
2281             const __u16 smb_file_id, const __u32 netpid, const __u64 len,
2282             const __u64 offset, const __u32 numUnlock,
2283             const __u32 numLock, const __u8 lockType,
2284             const bool waitFlag, const __u8 oplock_level)
2285 {
2286         int rc = 0;
2287         LOCK_REQ *pSMB = NULL;
2288 /*      LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
2289         int bytes_returned;
2290         int timeout = 0;
2291         __u16 count;
2292
2293         cFYI(1, "CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock);
2294         rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2295
2296         if (rc)
2297                 return rc;
2298
2299         if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
2300                 timeout = CIFS_ASYNC_OP; /* no response expected */
2301                 pSMB->Timeout = 0;
2302         } else if (waitFlag) {
2303                 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2304                 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
2305         } else {
2306                 pSMB->Timeout = 0;
2307         }
2308
2309         pSMB->NumberOfLocks = cpu_to_le16(numLock);
2310         pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
2311         pSMB->LockType = lockType;
2312         pSMB->OplockLevel = oplock_level;
2313         pSMB->AndXCommand = 0xFF;       /* none */
2314         pSMB->Fid = smb_file_id; /* netfid stays le */
2315
2316         if ((numLock != 0) || (numUnlock != 0)) {
2317                 pSMB->Locks[0].Pid = cpu_to_le16(netpid);
2318                 /* BB where to store pid high? */
2319                 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
2320                 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
2321                 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
2322                 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
2323                 count = sizeof(LOCKING_ANDX_RANGE);
2324         } else {
2325                 /* oplock break */
2326                 count = 0;
2327         }
2328         inc_rfc1001_len(pSMB, count);
2329         pSMB->ByteCount = cpu_to_le16(count);
2330
2331         if (waitFlag) {
2332                 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2333                         (struct smb_hdr *) pSMB, &bytes_returned);
2334                 cifs_small_buf_release(pSMB);
2335         } else {
2336                 rc = SendReceiveNoRsp(xid, tcon->ses, (char *)pSMB, timeout);
2337                 /* SMB buffer freed by function above */
2338         }
2339         cifs_stats_inc(&tcon->num_locks);
2340         if (rc)
2341                 cFYI(1, "Send error in Lock = %d", rc);
2342
2343         /* Note: On -EAGAIN error only caller can retry on handle based calls
2344         since file handle passed in no longer valid */
2345         return rc;
2346 }
2347
2348 int
2349 CIFSSMBPosixLock(const int xid, struct cifs_tcon *tcon,
2350                 const __u16 smb_file_id, const __u32 netpid, const int get_flag,
2351                 const __u64 len, struct file_lock *pLockData,
2352                 const __u16 lock_type, const bool waitFlag)
2353 {
2354         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
2355         struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2356         struct cifs_posix_lock *parm_data;
2357         int rc = 0;
2358         int timeout = 0;
2359         int bytes_returned = 0;
2360         int resp_buf_type = 0;
2361         __u16 params, param_offset, offset, byte_count, count;
2362         struct kvec iov[1];
2363
2364         cFYI(1, "Posix Lock");
2365
2366         if (pLockData == NULL)
2367                 return -EINVAL;
2368
2369         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
2370
2371         if (rc)
2372                 return rc;
2373
2374         pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
2375
2376         params = 6;
2377         pSMB->MaxSetupCount = 0;
2378         pSMB->Reserved = 0;
2379         pSMB->Flags = 0;
2380         pSMB->Reserved2 = 0;
2381         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2382         offset = param_offset + params;
2383
2384         count = sizeof(struct cifs_posix_lock);
2385         pSMB->MaxParameterCount = cpu_to_le16(2);
2386         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2387         pSMB->SetupCount = 1;
2388         pSMB->Reserved3 = 0;
2389         if (get_flag)
2390                 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2391         else
2392                 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2393         byte_count = 3 /* pad */  + params + count;
2394         pSMB->DataCount = cpu_to_le16(count);
2395         pSMB->ParameterCount = cpu_to_le16(params);
2396         pSMB->TotalDataCount = pSMB->DataCount;
2397         pSMB->TotalParameterCount = pSMB->ParameterCount;
2398         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2399         parm_data = (struct cifs_posix_lock *)
2400                         (((char *) &pSMB->hdr.Protocol) + offset);
2401
2402         parm_data->lock_type = cpu_to_le16(lock_type);
2403         if (waitFlag) {
2404                 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2405                 parm_data->lock_flags = cpu_to_le16(1);
2406                 pSMB->Timeout = cpu_to_le32(-1);
2407         } else
2408                 pSMB->Timeout = 0;
2409
2410         parm_data->pid = cpu_to_le32(netpid);
2411         parm_data->start = cpu_to_le64(pLockData->fl_start);
2412         parm_data->length = cpu_to_le64(len);  /* normalize negative numbers */
2413
2414         pSMB->DataOffset = cpu_to_le16(offset);
2415         pSMB->Fid = smb_file_id;
2416         pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
2417         pSMB->Reserved4 = 0;
2418         inc_rfc1001_len(pSMB, byte_count);
2419         pSMB->ByteCount = cpu_to_le16(byte_count);
2420         if (waitFlag) {
2421                 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2422                         (struct smb_hdr *) pSMBr, &bytes_returned);
2423         } else {
2424                 iov[0].iov_base = (char *)pSMB;
2425                 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
2426                 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
2427                                 &resp_buf_type, timeout);
2428                 pSMB = NULL; /* request buf already freed by SendReceive2. Do
2429                                 not try to free it twice below on exit */
2430                 pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
2431         }
2432
2433         if (rc) {
2434                 cFYI(1, "Send error in Posix Lock = %d", rc);
2435         } else if (get_flag) {
2436                 /* lock structure can be returned on get */
2437                 __u16 data_offset;
2438                 __u16 data_count;
2439                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2440
2441                 if (rc || get_bcc(&pSMBr->hdr) < sizeof(*parm_data)) {
2442                         rc = -EIO;      /* bad smb */
2443                         goto plk_err_exit;
2444                 }
2445                 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2446                 data_count  = le16_to_cpu(pSMBr->t2.DataCount);
2447                 if (data_count < sizeof(struct cifs_posix_lock)) {
2448                         rc = -EIO;
2449                         goto plk_err_exit;
2450                 }
2451                 parm_data = (struct cifs_posix_lock *)
2452                         ((char *)&pSMBr->hdr.Protocol + data_offset);
2453                 if (parm_data->lock_type == __constant_cpu_to_le16(CIFS_UNLCK))
2454                         pLockData->fl_type = F_UNLCK;
2455                 else {
2456                         if (parm_data->lock_type ==
2457                                         __constant_cpu_to_le16(CIFS_RDLCK))
2458                                 pLockData->fl_type = F_RDLCK;
2459                         else if (parm_data->lock_type ==
2460                                         __constant_cpu_to_le16(CIFS_WRLCK))
2461                                 pLockData->fl_type = F_WRLCK;
2462
2463                         pLockData->fl_start = le64_to_cpu(parm_data->start);
2464                         pLockData->fl_end = pLockData->fl_start +
2465                                         le64_to_cpu(parm_data->length) - 1;
2466                         pLockData->fl_pid = le32_to_cpu(parm_data->pid);
2467                 }
2468         }
2469
2470 plk_err_exit:
2471         if (pSMB)
2472                 cifs_small_buf_release(pSMB);
2473
2474         if (resp_buf_type == CIFS_SMALL_BUFFER)
2475                 cifs_small_buf_release(iov[0].iov_base);
2476         else if (resp_buf_type == CIFS_LARGE_BUFFER)
2477                 cifs_buf_release(iov[0].iov_base);
2478
2479         /* Note: On -EAGAIN error only caller can retry on handle based calls
2480            since file handle passed in no longer valid */
2481
2482         return rc;
2483 }
2484
2485
2486 int
2487 CIFSSMBClose(const int xid, struct cifs_tcon *tcon, int smb_file_id)
2488 {
2489         int rc = 0;
2490         CLOSE_REQ *pSMB = NULL;
2491         cFYI(1, "In CIFSSMBClose");
2492
2493 /* do not retry on dead session on close */
2494         rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
2495         if (rc == -EAGAIN)
2496                 return 0;
2497         if (rc)
2498                 return rc;
2499
2500         pSMB->FileID = (__u16) smb_file_id;
2501         pSMB->LastWriteTime = 0xFFFFFFFF;
2502         pSMB->ByteCount = 0;
2503         rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2504         cifs_stats_inc(&tcon->num_closes);
2505         if (rc) {
2506                 if (rc != -EINTR) {
2507                         /* EINTR is expected when user ctl-c to kill app */
2508                         cERROR(1, "Send error in Close = %d", rc);
2509                 }
2510         }
2511
2512         /* Since session is dead, file will be closed on server already */
2513         if (rc == -EAGAIN)
2514                 rc = 0;
2515
2516         return rc;
2517 }
2518
2519 int
2520 CIFSSMBFlush(const int xid, struct cifs_tcon *tcon, int smb_file_id)
2521 {
2522         int rc = 0;
2523         FLUSH_REQ *pSMB = NULL;
2524         cFYI(1, "In CIFSSMBFlush");
2525
2526         rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
2527         if (rc)
2528                 return rc;
2529
2530         pSMB->FileID = (__u16) smb_file_id;
2531         pSMB->ByteCount = 0;
2532         rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2533         cifs_stats_inc(&tcon->num_flushes);
2534         if (rc)
2535                 cERROR(1, "Send error in Flush = %d", rc);
2536
2537         return rc;
2538 }
2539
2540 int
2541 CIFSSMBRename(const int xid, struct cifs_tcon *tcon,
2542               const char *fromName, const char *toName,
2543               const struct nls_table *nls_codepage, int remap)
2544 {
2545         int rc = 0;
2546         RENAME_REQ *pSMB = NULL;
2547         RENAME_RSP *pSMBr = NULL;
2548         int bytes_returned;
2549         int name_len, name_len2;
2550         __u16 count;
2551
2552         cFYI(1, "In CIFSSMBRename");
2553 renameRetry:
2554         rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
2555                       (void **) &pSMBr);
2556         if (rc)
2557                 return rc;
2558
2559         pSMB->BufferFormat = 0x04;
2560         pSMB->SearchAttributes =
2561             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2562                         ATTR_DIRECTORY);
2563
2564         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2565                 name_len =
2566                     cifsConvertToUTF16((__le16 *) pSMB->OldFileName, fromName,
2567                                        PATH_MAX, nls_codepage, remap);
2568                 name_len++;     /* trailing null */
2569                 name_len *= 2;
2570                 pSMB->OldFileName[name_len] = 0x04;     /* pad */
2571         /* protocol requires ASCII signature byte on Unicode string */
2572                 pSMB->OldFileName[name_len + 1] = 0x00;
2573                 name_len2 =
2574                     cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2575                                        toName, PATH_MAX, nls_codepage, remap);
2576                 name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2577                 name_len2 *= 2; /* convert to bytes */
2578         } else {        /* BB improve the check for buffer overruns BB */
2579                 name_len = strnlen(fromName, PATH_MAX);
2580                 name_len++;     /* trailing null */
2581                 strncpy(pSMB->OldFileName, fromName, name_len);
2582                 name_len2 = strnlen(toName, PATH_MAX);
2583                 name_len2++;    /* trailing null */
2584                 pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
2585                 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2586                 name_len2++;    /* trailing null */
2587                 name_len2++;    /* signature byte */
2588         }
2589
2590         count = 1 /* 1st signature byte */  + name_len + name_len2;
2591         inc_rfc1001_len(pSMB, count);
2592         pSMB->ByteCount = cpu_to_le16(count);
2593
2594         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2595                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2596         cifs_stats_inc(&tcon->num_renames);
2597         if (rc)
2598                 cFYI(1, "Send error in rename = %d", rc);
2599
2600         cifs_buf_release(pSMB);
2601
2602         if (rc == -EAGAIN)
2603                 goto renameRetry;
2604
2605         return rc;
2606 }
2607
2608 int CIFSSMBRenameOpenFile(const int xid, struct cifs_tcon *pTcon,
2609                 int netfid, const char *target_name,
2610                 const struct nls_table *nls_codepage, int remap)
2611 {
2612         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
2613         struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2614         struct set_file_rename *rename_info;
2615         char *data_offset;
2616         char dummy_string[30];
2617         int rc = 0;
2618         int bytes_returned = 0;
2619         int len_of_str;
2620         __u16 params, param_offset, offset, count, byte_count;
2621
2622         cFYI(1, "Rename to File by handle");
2623         rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2624                         (void **) &pSMBr);
2625         if (rc)
2626                 return rc;
2627
2628         params = 6;
2629         pSMB->MaxSetupCount = 0;
2630         pSMB->Reserved = 0;
2631         pSMB->Flags = 0;
2632         pSMB->Timeout = 0;
2633         pSMB->Reserved2 = 0;
2634         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2635         offset = param_offset + params;
2636
2637         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2638         rename_info = (struct set_file_rename *) data_offset;
2639         pSMB->MaxParameterCount = cpu_to_le16(2);
2640         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2641         pSMB->SetupCount = 1;
2642         pSMB->Reserved3 = 0;
2643         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2644         byte_count = 3 /* pad */  + params;
2645         pSMB->ParameterCount = cpu_to_le16(params);
2646         pSMB->TotalParameterCount = pSMB->ParameterCount;
2647         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2648         pSMB->DataOffset = cpu_to_le16(offset);
2649         /* construct random name ".cifs_tmp<inodenum><mid>" */
2650         rename_info->overwrite = cpu_to_le32(1);
2651         rename_info->root_fid  = 0;
2652         /* unicode only call */
2653         if (target_name == NULL) {
2654                 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2655                 len_of_str =
2656                         cifsConvertToUTF16((__le16 *)rename_info->target_name,
2657                                         dummy_string, 24, nls_codepage, remap);
2658         } else {
2659                 len_of_str =
2660                         cifsConvertToUTF16((__le16 *)rename_info->target_name,
2661                                         target_name, PATH_MAX, nls_codepage,
2662                                         remap);
2663         }
2664         rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2665         count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2666         byte_count += count;
2667         pSMB->DataCount = cpu_to_le16(count);
2668         pSMB->TotalDataCount = pSMB->DataCount;
2669         pSMB->Fid = netfid;
2670         pSMB->InformationLevel =
2671                 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2672         pSMB->Reserved4 = 0;
2673         inc_rfc1001_len(pSMB, byte_count);
2674         pSMB->ByteCount = cpu_to_le16(byte_count);
2675         rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2676                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2677         cifs_stats_inc(&pTcon->num_t2renames);
2678         if (rc)
2679                 cFYI(1, "Send error in Rename (by file handle) = %d", rc);
2680
2681         cifs_buf_release(pSMB);
2682
2683         /* Note: On -EAGAIN error only caller can retry on handle based calls
2684                 since file handle passed in no longer valid */
2685
2686         return rc;
2687 }
2688
2689 int
2690 CIFSSMBCopy(const int xid, struct cifs_tcon *tcon, const char *fromName,
2691             const __u16 target_tid, const char *toName, const int flags,
2692             const struct nls_table *nls_codepage, int remap)
2693 {
2694         int rc = 0;
2695         COPY_REQ *pSMB = NULL;
2696         COPY_RSP *pSMBr = NULL;
2697         int bytes_returned;
2698         int name_len, name_len2;
2699         __u16 count;
2700
2701         cFYI(1, "In CIFSSMBCopy");
2702 copyRetry:
2703         rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2704                         (void **) &pSMBr);
2705         if (rc)
2706                 return rc;
2707
2708         pSMB->BufferFormat = 0x04;
2709         pSMB->Tid2 = target_tid;
2710
2711         pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2712
2713         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2714                 name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2715                                               fromName, PATH_MAX, nls_codepage,
2716                                               remap);
2717                 name_len++;     /* trailing null */
2718                 name_len *= 2;
2719                 pSMB->OldFileName[name_len] = 0x04;     /* pad */
2720                 /* protocol requires ASCII signature byte on Unicode string */
2721                 pSMB->OldFileName[name_len + 1] = 0x00;
2722                 name_len2 =
2723                     cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2724                                        toName, PATH_MAX, nls_codepage, remap);
2725                 name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2726                 name_len2 *= 2; /* convert to bytes */
2727         } else {        /* BB improve the check for buffer overruns BB */
2728                 name_len = strnlen(fromName, PATH_MAX);
2729                 name_len++;     /* trailing null */
2730                 strncpy(pSMB->OldFileName, fromName, name_len);
2731                 name_len2 = strnlen(toName, PATH_MAX);
2732                 name_len2++;    /* trailing null */
2733                 pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
2734                 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2735                 name_len2++;    /* trailing null */
2736                 name_len2++;    /* signature byte */
2737         }
2738
2739         count = 1 /* 1st signature byte */  + name_len + name_len2;
2740         inc_rfc1001_len(pSMB, count);
2741         pSMB->ByteCount = cpu_to_le16(count);
2742
2743         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2744                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2745         if (rc) {
2746                 cFYI(1, "Send error in copy = %d with %d files copied",
2747                         rc, le16_to_cpu(pSMBr->CopyCount));
2748         }
2749         cifs_buf_release(pSMB);
2750
2751         if (rc == -EAGAIN)
2752                 goto copyRetry;
2753
2754         return rc;
2755 }
2756
2757 int
2758 CIFSUnixCreateSymLink(const int xid, struct cifs_tcon *tcon,
2759                       const char *fromName, const char *toName,
2760                       const struct nls_table *nls_codepage)
2761 {
2762         TRANSACTION2_SPI_REQ *pSMB = NULL;
2763         TRANSACTION2_SPI_RSP *pSMBr = NULL;
2764         char *data_offset;
2765         int name_len;
2766         int name_len_target;
2767         int rc = 0;
2768         int bytes_returned = 0;
2769         __u16 params, param_offset, offset, byte_count;
2770
2771         cFYI(1, "In Symlink Unix style");
2772 createSymLinkRetry:
2773         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2774                       (void **) &pSMBr);
2775         if (rc)
2776                 return rc;
2777
2778         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2779                 name_len =
2780                     cifs_strtoUTF16((__le16 *) pSMB->FileName, fromName,
2781                                     /* find define for this maxpathcomponent */
2782                                     PATH_MAX, nls_codepage);
2783                 name_len++;     /* trailing null */
2784                 name_len *= 2;
2785
2786         } else {        /* BB improve the check for buffer overruns BB */
2787                 name_len = strnlen(fromName, PATH_MAX);
2788                 name_len++;     /* trailing null */
2789                 strncpy(pSMB->FileName, fromName, name_len);
2790         }
2791         params = 6 + name_len;
2792         pSMB->MaxSetupCount = 0;
2793         pSMB->Reserved = 0;
2794         pSMB->Flags = 0;
2795         pSMB->Timeout = 0;
2796         pSMB->Reserved2 = 0;
2797         param_offset = offsetof(struct smb_com_transaction2_spi_req,
2798                                 InformationLevel) - 4;
2799         offset = param_offset + params;
2800
2801         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2802         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2803                 name_len_target =
2804                     cifs_strtoUTF16((__le16 *) data_offset, toName, PATH_MAX
2805                                     /* find define for this maxpathcomponent */
2806                                     , nls_codepage);
2807                 name_len_target++;      /* trailing null */
2808                 name_len_target *= 2;
2809         } else {        /* BB improve the check for buffer overruns BB */
2810                 name_len_target = strnlen(toName, PATH_MAX);
2811                 name_len_target++;      /* trailing null */
2812                 strncpy(data_offset, toName, name_len_target);
2813         }
2814
2815         pSMB->MaxParameterCount = cpu_to_le16(2);
2816         /* BB find exact max on data count below from sess */
2817         pSMB->MaxDataCount = cpu_to_le16(1000);
2818         pSMB->SetupCount = 1;
2819         pSMB->Reserved3 = 0;
2820         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2821         byte_count = 3 /* pad */  + params + name_len_target;
2822         pSMB->DataCount = cpu_to_le16(name_len_target);
2823         pSMB->ParameterCount = cpu_to_le16(params);
2824         pSMB->TotalDataCount = pSMB->DataCount;
2825         pSMB->TotalParameterCount = pSMB->ParameterCount;
2826         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2827         pSMB->DataOffset = cpu_to_le16(offset);
2828         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2829         pSMB->Reserved4 = 0;
2830         inc_rfc1001_len(pSMB, byte_count);
2831         pSMB->ByteCount = cpu_to_le16(byte_count);
2832         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2833                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2834         cifs_stats_inc(&tcon->num_symlinks);
2835         if (rc)
2836                 cFYI(1, "Send error in SetPathInfo create symlink = %d", rc);
2837
2838         cifs_buf_release(pSMB);
2839
2840         if (rc == -EAGAIN)
2841                 goto createSymLinkRetry;
2842
2843         return rc;
2844 }
2845
2846 int
2847 CIFSUnixCreateHardLink(const int xid, struct cifs_tcon *tcon,
2848                        const char *fromName, const char *toName,
2849                        const struct nls_table *nls_codepage, int remap)
2850 {
2851         TRANSACTION2_SPI_REQ *pSMB = NULL;
2852         TRANSACTION2_SPI_RSP *pSMBr = NULL;
2853         char *data_offset;
2854         int name_len;
2855         int name_len_target;
2856         int rc = 0;
2857         int bytes_returned = 0;
2858         __u16 params, param_offset, offset, byte_count;
2859
2860         cFYI(1, "In Create Hard link Unix style");
2861 createHardLinkRetry:
2862         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2863                       (void **) &pSMBr);
2864         if (rc)
2865                 return rc;
2866
2867         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2868                 name_len = cifsConvertToUTF16((__le16 *) pSMB->FileName, toName,
2869                                               PATH_MAX, nls_codepage, remap);
2870                 name_len++;     /* trailing null */
2871                 name_len *= 2;
2872
2873         } else {        /* BB improve the check for buffer overruns BB */
2874                 name_len = strnlen(toName, PATH_MAX);
2875                 name_len++;     /* trailing null */
2876                 strncpy(pSMB->FileName, toName, name_len);
2877         }
2878         params = 6 + name_len;
2879         pSMB->MaxSetupCount = 0;
2880         pSMB->Reserved = 0;
2881         pSMB->Flags = 0;
2882         pSMB->Timeout = 0;
2883         pSMB->Reserved2 = 0;
2884         param_offset = offsetof(struct smb_com_transaction2_spi_req,
2885                                 InformationLevel) - 4;
2886         offset = param_offset + params;
2887
2888         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2889         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2890                 name_len_target =
2891                     cifsConvertToUTF16((__le16 *) data_offset, fromName,
2892                                        PATH_MAX, nls_codepage, remap);
2893                 name_len_target++;      /* trailing null */
2894                 name_len_target *= 2;
2895         } else {        /* BB improve the check for buffer overruns BB */
2896                 name_len_target = strnlen(fromName, PATH_MAX);
2897                 name_len_target++;      /* trailing null */
2898                 strncpy(data_offset, fromName, name_len_target);
2899         }
2900
2901         pSMB->MaxParameterCount = cpu_to_le16(2);
2902         /* BB find exact max on data count below from sess*/
2903         pSMB->MaxDataCount = cpu_to_le16(1000);
2904         pSMB->SetupCount = 1;
2905         pSMB->Reserved3 = 0;
2906         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2907         byte_count = 3 /* pad */  + params + name_len_target;
2908         pSMB->ParameterCount = cpu_to_le16(params);
2909         pSMB->TotalParameterCount = pSMB->ParameterCount;
2910         pSMB->DataCount = cpu_to_le16(name_len_target);
2911         pSMB->TotalDataCount = pSMB->DataCount;
2912         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2913         pSMB->DataOffset = cpu_to_le16(offset);
2914         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2915         pSMB->Reserved4 = 0;
2916         inc_rfc1001_len(pSMB, byte_count);
2917         pSMB->ByteCount = cpu_to_le16(byte_count);
2918         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2919                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2920         cifs_stats_inc(&tcon->num_hardlinks);
2921         if (rc)
2922                 cFYI(1, "Send error in SetPathInfo (hard link) = %d", rc);
2923
2924         cifs_buf_release(pSMB);
2925         if (rc == -EAGAIN)
2926                 goto createHardLinkRetry;
2927
2928         return rc;
2929 }
2930
2931 int
2932 CIFSCreateHardLink(const int xid, struct cifs_tcon *tcon,
2933                    const char *fromName, const char *toName,
2934                    const struct nls_table *nls_codepage, int remap)
2935 {
2936         int rc = 0;
2937         NT_RENAME_REQ *pSMB = NULL;
2938         RENAME_RSP *pSMBr = NULL;
2939         int bytes_returned;
2940         int name_len, name_len2;
2941         __u16 count;
2942
2943         cFYI(1, "In CIFSCreateHardLink");
2944 winCreateHardLinkRetry:
2945
2946         rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2947                       (void **) &pSMBr);
2948         if (rc)
2949                 return rc;
2950
2951         pSMB->SearchAttributes =
2952             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2953                         ATTR_DIRECTORY);
2954         pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2955         pSMB->ClusterCount = 0;
2956
2957         pSMB->BufferFormat = 0x04;
2958
2959         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2960                 name_len =
2961                     cifsConvertToUTF16((__le16 *) pSMB->OldFileName, fromName,
2962                                        PATH_MAX, nls_codepage, remap);
2963                 name_len++;     /* trailing null */
2964                 name_len *= 2;
2965
2966                 /* protocol specifies ASCII buffer format (0x04) for unicode */
2967                 pSMB->OldFileName[name_len] = 0x04;
2968                 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
2969                 name_len2 =
2970                     cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2971                                        toName, PATH_MAX, nls_codepage, remap);
2972                 name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2973                 name_len2 *= 2; /* convert to bytes */
2974         } else {        /* BB improve the check for buffer overruns BB */
2975                 name_len = strnlen(fromName, PATH_MAX);
2976                 name_len++;     /* trailing null */
2977                 strncpy(pSMB->OldFileName, fromName, name_len);
2978                 name_len2 = strnlen(toName, PATH_MAX);
2979                 name_len2++;    /* trailing null */
2980                 pSMB->OldFileName[name_len] = 0x04;     /* 2nd buffer format */
2981                 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2982                 name_len2++;    /* trailing null */
2983                 name_len2++;    /* signature byte */
2984         }
2985
2986         count = 1 /* string type byte */  + name_len + name_len2;
2987         inc_rfc1001_len(pSMB, count);
2988         pSMB->ByteCount = cpu_to_le16(count);
2989
2990         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2991                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2992         cifs_stats_inc(&tcon->num_hardlinks);
2993         if (rc)
2994                 cFYI(1, "Send error in hard link (NT rename) = %d", rc);
2995
2996         cifs_buf_release(pSMB);
2997         if (rc == -EAGAIN)
2998                 goto winCreateHardLinkRetry;
2999
3000         return rc;
3001 }
3002
3003 int
3004 CIFSSMBUnixQuerySymLink(const int xid, struct cifs_tcon *tcon,
3005                         const unsigned char *searchName, char **symlinkinfo,
3006                         const struct nls_table *nls_codepage)
3007 {
3008 /* SMB_QUERY_FILE_UNIX_LINK */
3009         TRANSACTION2_QPI_REQ *pSMB = NULL;
3010         TRANSACTION2_QPI_RSP *pSMBr = NULL;
3011         int rc = 0;
3012         int bytes_returned;
3013         int name_len;
3014         __u16 params, byte_count;
3015         char *data_start;
3016
3017         cFYI(1, "In QPathSymLinkInfo (Unix) for path %s", searchName);
3018
3019 querySymLinkRetry:
3020         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3021                       (void **) &pSMBr);
3022         if (rc)
3023                 return rc;
3024
3025         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3026                 name_len =
3027                         cifs_strtoUTF16((__le16 *) pSMB->FileName, searchName,
3028                                         PATH_MAX, nls_codepage);
3029                 name_len++;     /* trailing null */
3030                 name_len *= 2;
3031         } else {        /* BB improve the check for buffer overruns BB */
3032                 name_len = strnlen(searchName, PATH_MAX);
3033                 name_len++;     /* trailing null */
3034                 strncpy(pSMB->FileName, searchName, name_len);
3035         }
3036
3037         params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
3038         pSMB->TotalDataCount = 0;
3039         pSMB->MaxParameterCount = cpu_to_le16(2);
3040         pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3041         pSMB->MaxSetupCount = 0;
3042         pSMB->Reserved = 0;
3043         pSMB->Flags = 0;
3044         pSMB->Timeout = 0;
3045         pSMB->Reserved2 = 0;
3046         pSMB->ParameterOffset = cpu_to_le16(offsetof(
3047         struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3048         pSMB->DataCount = 0;
3049         pSMB->DataOffset = 0;
3050         pSMB->SetupCount = 1;
3051         pSMB->Reserved3 = 0;
3052         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3053         byte_count = params + 1 /* pad */ ;
3054         pSMB->TotalParameterCount = cpu_to_le16(params);
3055         pSMB->ParameterCount = pSMB->TotalParameterCount;
3056         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
3057         pSMB->Reserved4 = 0;
3058         inc_rfc1001_len(pSMB, byte_count);
3059         pSMB->ByteCount = cpu_to_le16(byte_count);
3060
3061         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3062                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3063         if (rc) {
3064                 cFYI(1, "Send error in QuerySymLinkInfo = %d", rc);
3065         } else {
3066                 /* decode response */
3067
3068                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3069                 /* BB also check enough total bytes returned */
3070                 if (rc || get_bcc(&pSMBr->hdr) < 2)
3071                         rc = -EIO;
3072                 else {
3073                         bool is_unicode;
3074                         u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3075
3076                         data_start = ((char *) &pSMBr->hdr.Protocol) +
3077                                            le16_to_cpu(pSMBr->t2.DataOffset);
3078
3079                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3080                                 is_unicode = true;
3081                         else
3082                                 is_unicode = false;
3083
3084                         /* BB FIXME investigate remapping reserved chars here */
3085                         *symlinkinfo = cifs_strndup_from_utf16(data_start,
3086                                         count, is_unicode, nls_codepage);
3087                         if (!*symlinkinfo)
3088                                 rc = -ENOMEM;
3089                 }
3090         }
3091         cifs_buf_release(pSMB);
3092         if (rc == -EAGAIN)
3093                 goto querySymLinkRetry;
3094         return rc;
3095 }
3096
3097 #ifdef CONFIG_CIFS_SYMLINK_EXPERIMENTAL
3098 /*
3099  *      Recent Windows versions now create symlinks more frequently
3100  *      and they use the "reparse point" mechanism below.  We can of course
3101  *      do symlinks nicely to Samba and other servers which support the
3102  *      CIFS Unix Extensions and we can also do SFU symlinks and "client only"
3103  *      "MF" symlinks optionally, but for recent Windows we really need to
3104  *      reenable the code below and fix the cifs_symlink callers to handle this.
3105  *      In the interim this code has been moved to its own config option so
3106  *      it is not compiled in by default until callers fixed up and more tested.
3107  */
3108 int
3109 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifs_tcon *tcon,
3110                         const unsigned char *searchName,
3111                         char *symlinkinfo, const int buflen, __u16 fid,
3112                         const struct nls_table *nls_codepage)
3113 {
3114         int rc = 0;
3115         int bytes_returned;
3116         struct smb_com_transaction_ioctl_req *pSMB;
3117         struct smb_com_transaction_ioctl_rsp *pSMBr;
3118
3119         cFYI(1, "In Windows reparse style QueryLink for path %s", searchName);
3120         rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3121                       (void **) &pSMBr);
3122         if (rc)
3123                 return rc;
3124
3125         pSMB->TotalParameterCount = 0 ;
3126         pSMB->TotalDataCount = 0;
3127         pSMB->MaxParameterCount = cpu_to_le32(2);
3128         /* BB find exact data count max from sess structure BB */
3129         pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3130         pSMB->MaxSetupCount = 4;
3131         pSMB->Reserved = 0;
3132         pSMB->ParameterOffset = 0;
3133         pSMB->DataCount = 0;
3134         pSMB->DataOffset = 0;
3135         pSMB->SetupCount = 4;
3136         pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
3137         pSMB->ParameterCount = pSMB->TotalParameterCount;
3138         pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
3139         pSMB->IsFsctl = 1; /* FSCTL */
3140         pSMB->IsRootFlag = 0;
3141         pSMB->Fid = fid; /* file handle always le */
3142         pSMB->ByteCount = 0;
3143
3144         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3145                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3146         if (rc) {
3147                 cFYI(1, "Send error in QueryReparseLinkInfo = %d", rc);
3148         } else {                /* decode response */
3149                 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
3150                 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
3151                 if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) {
3152                         /* BB also check enough total bytes returned */
3153                         rc = -EIO;      /* bad smb */
3154                         goto qreparse_out;
3155                 }
3156                 if (data_count && (data_count < 2048)) {
3157                         char *end_of_smb = 2 /* sizeof byte count */ +
3158                                get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
3159
3160                         struct reparse_data *reparse_buf =
3161                                                 (struct reparse_data *)
3162                                                 ((char *)&pSMBr->hdr.Protocol
3163                                                                  + data_offset);
3164                         if ((char *)reparse_buf >= end_of_smb) {
3165                                 rc = -EIO;
3166                                 goto qreparse_out;
3167                         }
3168                         if ((reparse_buf->LinkNamesBuf +
3169                                 reparse_buf->TargetNameOffset +
3170                                 reparse_buf->TargetNameLen) > end_of_smb) {
3171                                 cFYI(1, "reparse buf beyond SMB");
3172                                 rc = -EIO;
3173                                 goto qreparse_out;
3174                         }
3175
3176                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3177                                 cifs_from_ucs2(symlinkinfo, (__le16 *)
3178                                                 (reparse_buf->LinkNamesBuf +
3179                                                 reparse_buf->TargetNameOffset),
3180                                                 buflen,
3181                                                 reparse_buf->TargetNameLen,
3182                                                 nls_codepage, 0);
3183                         } else { /* ASCII names */
3184                                 strncpy(symlinkinfo,
3185                                         reparse_buf->LinkNamesBuf +
3186                                         reparse_buf->TargetNameOffset,
3187                                         min_t(const int, buflen,
3188                                            reparse_buf->TargetNameLen));
3189                         }
3190                 } else {
3191                         rc = -EIO;
3192                         cFYI(1, "Invalid return data count on "
3193                                  "get reparse info ioctl");
3194                 }
3195                 symlinkinfo[buflen] = 0; /* just in case so the caller
3196                                         does not go off the end of the buffer */
3197                 cFYI(1, "readlink result - %s", symlinkinfo);
3198         }
3199
3200 qreparse_out:
3201         cifs_buf_release(pSMB);
3202
3203         /* Note: On -EAGAIN error only caller can retry on handle based calls
3204                 since file handle passed in no longer valid */
3205
3206         return rc;
3207 }
3208 #endif /* CIFS_SYMLINK_EXPERIMENTAL */ /* BB temporarily unused */
3209
3210 #ifdef CONFIG_CIFS_POSIX
3211
3212 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
3213 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
3214                              struct cifs_posix_ace *cifs_ace)
3215 {
3216         /* u8 cifs fields do not need le conversion */
3217         ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
3218         ace->e_tag  = cpu_to_le16(cifs_ace->cifs_e_tag);
3219         ace->e_id   = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
3220         /* cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id); */
3221
3222         return;
3223 }
3224
3225 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
3226 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
3227                                const int acl_type, const int size_of_data_area)
3228 {
3229         int size =  0;
3230         int i;
3231         __u16 count;
3232         struct cifs_posix_ace *pACE;
3233         struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
3234         posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
3235
3236         if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
3237                 return -EOPNOTSUPP;
3238
3239         if (acl_type & ACL_TYPE_ACCESS) {
3240                 count = le16_to_cpu(cifs_acl->access_entry_count);
3241                 pACE = &cifs_acl->ace_array[0];
3242                 size = sizeof(struct cifs_posix_acl);
3243                 size += sizeof(struct cifs_posix_ace) * count;
3244                 /* check if we would go beyond end of SMB */
3245                 if (size_of_data_area < size) {
3246                         cFYI(1, "bad CIFS POSIX ACL size %d vs. %d",
3247                                 size_of_data_area, size);
3248                         return -EINVAL;
3249                 }
3250         } else if (acl_type & ACL_TYPE_DEFAULT) {
3251                 count = le16_to_cpu(cifs_acl->access_entry_count);
3252                 size = sizeof(struct cifs_posix_acl);
3253                 size += sizeof(struct cifs_posix_ace) * count;
3254 /* skip past access ACEs to get to default ACEs */
3255                 pACE = &cifs_acl->ace_array[count];
3256                 count = le16_to_cpu(cifs_acl->default_entry_count);
3257                 size += sizeof(struct cifs_posix_ace) * count;
3258                 /* check if we would go beyond end of SMB */
3259                 if (size_of_data_area < size)
3260                         return -EINVAL;
3261         } else {
3262                 /* illegal type */
3263                 return -EINVAL;
3264         }
3265
3266         size = posix_acl_xattr_size(count);
3267         if ((buflen == 0) || (local_acl == NULL)) {
3268                 /* used to query ACL EA size */
3269         } else if (size > buflen) {
3270                 return -ERANGE;
3271         } else /* buffer big enough */ {
3272                 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
3273                 for (i = 0; i < count ; i++) {
3274                         cifs_convert_ace(&local_acl->a_entries[i], pACE);
3275                         pACE++;
3276                 }
3277         }
3278         return size;
3279 }
3280
3281 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
3282                                      const posix_acl_xattr_entry *local_ace)
3283 {
3284         __u16 rc = 0; /* 0 = ACL converted ok */
3285
3286         cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
3287         cifs_ace->cifs_e_tag =  le16_to_cpu(local_ace->e_tag);
3288         /* BB is there a better way to handle the large uid? */
3289         if (local_ace->e_id == cpu_to_le32(-1)) {
3290         /* Probably no need to le convert -1 on any arch but can not hurt */
3291                 cifs_ace->cifs_uid = cpu_to_le64(-1);
3292         } else
3293                 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
3294         /*cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id);*/
3295         return rc;
3296 }
3297
3298 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
3299 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
3300                                const int buflen, const int acl_type)
3301 {
3302         __u16 rc = 0;
3303         struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
3304         posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
3305         int count;
3306         int i;
3307
3308         if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
3309                 return 0;
3310
3311         count = posix_acl_xattr_count((size_t)buflen);
3312         cFYI(1, "setting acl with %d entries from buf of length %d and "
3313                 "version of %d",
3314                 count, buflen, le32_to_cpu(local_acl->a_version));
3315         if (le32_to_cpu(local_acl->a_version) != 2) {
3316                 cFYI(1, "unknown POSIX ACL version %d",
3317                      le32_to_cpu(local_acl->a_version));
3318                 return 0;
3319         }
3320         cifs_acl->version = cpu_to_le16(1);
3321         if (acl_type == ACL_TYPE_ACCESS)
3322                 cifs_acl->access_entry_count = cpu_to_le16(count);
3323         else if (acl_type == ACL_TYPE_DEFAULT)
3324                 cifs_acl->default_entry_count = cpu_to_le16(count);
3325         else {
3326                 cFYI(1, "unknown ACL type %d", acl_type);
3327                 return 0;
3328         }
3329         for (i = 0; i < count; i++) {
3330                 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
3331                                         &local_acl->a_entries[i]);
3332                 if (rc != 0) {
3333                         /* ACE not converted */
3334                         break;
3335                 }
3336         }
3337         if (rc == 0) {
3338                 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
3339                 rc += sizeof(struct cifs_posix_acl);
3340                 /* BB add check to make sure ACL does not overflow SMB */
3341         }
3342         return rc;
3343 }
3344
3345 int
3346 CIFSSMBGetPosixACL(const int xid, struct cifs_tcon *tcon,
3347                    const unsigned char *searchName,
3348                    char *acl_inf, const int buflen, const int acl_type,
3349                    const struct nls_table *nls_codepage, int remap)
3350 {
3351 /* SMB_QUERY_POSIX_ACL */
3352         TRANSACTION2_QPI_REQ *pSMB = NULL;
3353         TRANSACTION2_QPI_RSP *pSMBr = NULL;
3354         int rc = 0;
3355         int bytes_returned;
3356         int name_len;
3357         __u16 params, byte_count;
3358
3359         cFYI(1, "In GetPosixACL (Unix) for path %s", searchName);
3360
3361 queryAclRetry:
3362         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3363                 (void **) &pSMBr);
3364         if (rc)
3365                 return rc;
3366
3367         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3368                 name_len =
3369                         cifsConvertToUTF16((__le16 *) pSMB->FileName,
3370                                            searchName, PATH_MAX, nls_codepage,
3371                                            remap);
3372                 name_len++;     /* trailing null */
3373                 name_len *= 2;
3374                 pSMB->FileName[name_len] = 0;
3375                 pSMB->FileName[name_len+1] = 0;
3376         } else {        /* BB improve the check for buffer overruns BB */
3377                 name_len = strnlen(searchName, PATH_MAX);
3378                 name_len++;     /* trailing null */
3379                 strncpy(pSMB->FileName, searchName, name_len);
3380         }
3381
3382         params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
3383         pSMB->TotalDataCount = 0;
3384         pSMB->MaxParameterCount = cpu_to_le16(2);
3385         /* BB find exact max data count below from sess structure BB */
3386         pSMB->MaxDataCount = cpu_to_le16(4000);
3387         pSMB->MaxSetupCount = 0;
3388         pSMB->Reserved = 0;
3389         pSMB->Flags = 0;
3390         pSMB->Timeout = 0;
3391         pSMB->Reserved2 = 0;
3392         pSMB->ParameterOffset = cpu_to_le16(
3393                 offsetof(struct smb_com_transaction2_qpi_req,
3394                          InformationLevel) - 4);
3395         pSMB->DataCount = 0;
3396         pSMB->DataOffset = 0;
3397         pSMB->SetupCount = 1;
3398         pSMB->Reserved3 = 0;
3399         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3400         byte_count = params + 1 /* pad */ ;
3401         pSMB->TotalParameterCount = cpu_to_le16(params);
3402         pSMB->ParameterCount = pSMB->TotalParameterCount;
3403         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
3404         pSMB->Reserved4 = 0;
3405         inc_rfc1001_len(pSMB, byte_count);
3406         pSMB->ByteCount = cpu_to_le16(byte_count);
3407
3408         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3409                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3410         cifs_stats_inc(&tcon->num_acl_get);
3411         if (rc) {
3412                 cFYI(1, "Send error in Query POSIX ACL = %d", rc);
3413         } else {
3414                 /* decode response */
3415
3416                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3417                 /* BB also check enough total bytes returned */
3418                 if (rc || get_bcc(&pSMBr->hdr) < 2)
3419                         rc = -EIO;      /* bad smb */
3420                 else {
3421                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3422                         __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3423                         rc = cifs_copy_posix_acl(acl_inf,
3424                                 (char *)&pSMBr->hdr.Protocol+data_offset,
3425                                 buflen, acl_type, count);
3426                 }
3427         }
3428         cifs_buf_release(pSMB);
3429         if (rc == -EAGAIN)
3430                 goto queryAclRetry;
3431         return rc;
3432 }
3433
3434 int
3435 CIFSSMBSetPosixACL(const int xid, struct cifs_tcon *tcon,
3436                    const unsigned char *fileName,
3437                    const char *local_acl, const int buflen,
3438                    const int acl_type,
3439                    const struct nls_table *nls_codepage, int remap)
3440 {
3441         struct smb_com_transaction2_spi_req *pSMB = NULL;
3442         struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3443         char *parm_data;
3444         int name_len;
3445         int rc = 0;
3446         int bytes_returned = 0;
3447         __u16 params, byte_count, data_count, param_offset, offset;
3448
3449         cFYI(1, "In SetPosixACL (Unix) for path %s", fileName);
3450 setAclRetry:
3451         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3452                       (void **) &pSMBr);
3453         if (rc)
3454                 return rc;
3455         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3456                 name_len =
3457                         cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
3458                                            PATH_MAX, nls_codepage, remap);
3459                 name_len++;     /* trailing null */
3460                 name_len *= 2;
3461         } else {        /* BB improve the check for buffer overruns BB */
3462                 name_len = strnlen(fileName, PATH_MAX);
3463                 name_len++;     /* trailing null */
3464                 strncpy(pSMB->FileName, fileName, name_len);
3465         }
3466         params = 6 + name_len;
3467         pSMB->MaxParameterCount = cpu_to_le16(2);
3468         /* BB find max SMB size from sess */
3469         pSMB->MaxDataCount = cpu_to_le16(1000);
3470         pSMB->MaxSetupCount = 0;
3471         pSMB->Reserved = 0;
3472         pSMB->Flags = 0;
3473         pSMB->Timeout = 0;
3474         pSMB->Reserved2 = 0;
3475         param_offset = offsetof(struct smb_com_transaction2_spi_req,
3476                                 InformationLevel) - 4;
3477         offset = param_offset + params;
3478         parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
3479         pSMB->ParameterOffset = cpu_to_le16(param_offset);
3480
3481         /* convert to on the wire format for POSIX ACL */
3482         data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
3483
3484         if (data_count == 0) {
3485                 rc = -EOPNOTSUPP;
3486                 goto setACLerrorExit;
3487         }
3488         pSMB->DataOffset = cpu_to_le16(offset);
3489         pSMB->SetupCount = 1;
3490         pSMB->Reserved3 = 0;
3491         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3492         pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
3493         byte_count = 3 /* pad */  + params + data_count;
3494         pSMB->DataCount = cpu_to_le16(data_count);
3495         pSMB->TotalDataCount = pSMB->DataCount;
3496         pSMB->ParameterCount = cpu_to_le16(params);
3497         pSMB->TotalParameterCount = pSMB->ParameterCount;
3498         pSMB->Reserved4 = 0;
3499         inc_rfc1001_len(pSMB, byte_count);
3500         pSMB->ByteCount = cpu_to_le16(byte_count);
3501         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3502                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3503         if (rc)
3504                 cFYI(1, "Set POSIX ACL returned %d", rc);
3505
3506 setACLerrorExit:
3507         cifs_buf_release(pSMB);
3508         if (rc == -EAGAIN)
3509                 goto setAclRetry;
3510         return rc;
3511 }
3512
3513 /* BB fix tabs in this function FIXME BB */
3514 int
3515 CIFSGetExtAttr(const int xid, struct cifs_tcon *tcon,
3516                const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
3517 {
3518         int rc = 0;
3519         struct smb_t2_qfi_req *pSMB = NULL;
3520         struct smb_t2_qfi_rsp *pSMBr = NULL;
3521         int bytes_returned;
3522         __u16 params, byte_count;
3523
3524         cFYI(1, "In GetExtAttr");
3525         if (tcon == NULL)
3526                 return -ENODEV;
3527
3528 GetExtAttrRetry:
3529         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3530                         (void **) &pSMBr);
3531         if (rc)
3532                 return rc;
3533
3534         params = 2 /* level */ + 2 /* fid */;
3535         pSMB->t2.TotalDataCount = 0;
3536         pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3537         /* BB find exact max data count below from sess structure BB */
3538         pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3539         pSMB->t2.MaxSetupCount = 0;
3540         pSMB->t2.Reserved = 0;
3541         pSMB->t2.Flags = 0;
3542         pSMB->t2.Timeout = 0;
3543         pSMB->t2.Reserved2 = 0;
3544         pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3545                                                Fid) - 4);
3546         pSMB->t2.DataCount = 0;
3547         pSMB->t2.DataOffset = 0;
3548         pSMB->t2.SetupCount = 1;
3549         pSMB->t2.Reserved3 = 0;
3550         pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3551         byte_count = params + 1 /* pad */ ;
3552         pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3553         pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3554         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3555         pSMB->Pad = 0;
3556         pSMB->Fid = netfid;
3557         inc_rfc1001_len(pSMB, byte_count);
3558         pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3559
3560         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3561                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3562         if (rc) {
3563                 cFYI(1, "error %d in GetExtAttr", rc);
3564         } else {
3565                 /* decode response */
3566                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3567                 /* BB also check enough total bytes returned */
3568                 if (rc || get_bcc(&pSMBr->hdr) < 2)
3569                         /* If rc should we check for EOPNOSUPP and
3570                            disable the srvino flag? or in caller? */
3571                         rc = -EIO;      /* bad smb */
3572                 else {
3573                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3574                         __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3575                         struct file_chattr_info *pfinfo;
3576                         /* BB Do we need a cast or hash here ? */
3577                         if (count != 16) {
3578                                 cFYI(1, "Illegal size ret in GetExtAttr");
3579                                 rc = -EIO;
3580                                 goto GetExtAttrOut;
3581                         }
3582                         pfinfo = (struct file_chattr_info *)
3583                                  (data_offset + (char *) &pSMBr->hdr.Protocol);
3584                         *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3585                         *pMask = le64_to_cpu(pfinfo->mask);
3586                 }
3587         }
3588 GetExtAttrOut:
3589         cifs_buf_release(pSMB);
3590         if (rc == -EAGAIN)
3591                 goto GetExtAttrRetry;
3592         return rc;
3593 }
3594
3595 #endif /* CONFIG_POSIX */
3596
3597 #ifdef CONFIG_CIFS_ACL
3598 /*
3599  * Initialize NT TRANSACT SMB into small smb request buffer.  This assumes that
3600  * all NT TRANSACTS that we init here have total parm and data under about 400
3601  * bytes (to fit in small cifs buffer size), which is the case so far, it
3602  * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
3603  * returned setup area) and MaxParameterCount (returned parms size) must be set
3604  * by caller
3605  */
3606 static int
3607 smb_init_nttransact(const __u16 sub_command, const int setup_count,
3608                    const int parm_len, struct cifs_tcon *tcon,
3609                    void **ret_buf)
3610 {
3611         int rc;
3612         __u32 temp_offset;
3613         struct smb_com_ntransact_req *pSMB;
3614
3615         rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
3616                                 (void **)&pSMB);
3617         if (rc)
3618                 return rc;
3619         *ret_buf = (void *)pSMB;
3620         pSMB->Reserved = 0;
3621         pSMB->TotalParameterCount = cpu_to_le32(parm_len);
3622         pSMB->TotalDataCount  = 0;
3623         pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3624         pSMB->ParameterCount = pSMB->TotalParameterCount;
3625         pSMB->DataCount  = pSMB->TotalDataCount;
3626         temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
3627                         (setup_count * 2) - 4 /* for rfc1001 length itself */;
3628         pSMB->ParameterOffset = cpu_to_le32(temp_offset);
3629         pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
3630         pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
3631         pSMB->SubCommand = cpu_to_le16(sub_command);
3632         return 0;
3633 }
3634
3635 static int
3636 validate_ntransact(char *buf, char **ppparm, char **ppdata,
3637                    __u32 *pparmlen, __u32 *pdatalen)
3638 {
3639         char *end_of_smb;
3640         __u32 data_count, data_offset, parm_count, parm_offset;
3641         struct smb_com_ntransact_rsp *pSMBr;
3642         u16 bcc;
3643
3644         *pdatalen = 0;
3645         *pparmlen = 0;
3646
3647         if (buf == NULL)
3648                 return -EINVAL;
3649
3650         pSMBr = (struct smb_com_ntransact_rsp *)buf;
3651
3652         bcc = get_bcc(&pSMBr->hdr);
3653         end_of_smb = 2 /* sizeof byte count */ + bcc +
3654                         (char *)&pSMBr->ByteCount;
3655
3656         data_offset = le32_to_cpu(pSMBr->DataOffset);
3657         data_count = le32_to_cpu(pSMBr->DataCount);
3658         parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
3659         parm_count = le32_to_cpu(pSMBr->ParameterCount);
3660
3661         *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
3662         *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
3663
3664         /* should we also check that parm and data areas do not overlap? */
3665         if (*ppparm > end_of_smb) {
3666                 cFYI(1, "parms start after end of smb");
3667                 return -EINVAL;
3668         } else if (parm_count + *ppparm > end_of_smb) {
3669                 cFYI(1, "parm end after end of smb");
3670                 return -EINVAL;
3671         } else if (*ppdata > end_of_smb) {
3672                 cFYI(1, "data starts after end of smb");
3673                 return -EINVAL;
3674         } else if (data_count + *ppdata > end_of_smb) {
3675                 cFYI(1, "data %p + count %d (%p) past smb end %p start %p",
3676                         *ppdata, data_count, (data_count + *ppdata),
3677                         end_of_smb, pSMBr);
3678                 return -EINVAL;
3679         } else if (parm_count + data_count > bcc) {
3680                 cFYI(1, "parm count and data count larger than SMB");
3681                 return -EINVAL;
3682         }
3683         *pdatalen = data_count;
3684         *pparmlen = parm_count;
3685         return 0;
3686 }
3687
3688 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3689 int
3690 CIFSSMBGetCIFSACL(const int xid, struct cifs_tcon *tcon, __u16 fid,
3691                   struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3692 {
3693         int rc = 0;
3694         int buf_type = 0;
3695         QUERY_SEC_DESC_REQ *pSMB;
3696         struct kvec iov[1];
3697
3698         cFYI(1, "GetCifsACL");
3699
3700         *pbuflen = 0;
3701         *acl_inf = NULL;
3702
3703         rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3704                         8 /* parm len */, tcon, (void **) &pSMB);
3705         if (rc)
3706                 return rc;
3707
3708         pSMB->MaxParameterCount = cpu_to_le32(4);
3709         /* BB TEST with big acls that might need to be e.g. larger than 16K */
3710         pSMB->MaxSetupCount = 0;
3711         pSMB->Fid = fid; /* file handle always le */
3712         pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3713                                      CIFS_ACL_DACL);
3714         pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3715         inc_rfc1001_len(pSMB, 11);
3716         iov[0].iov_base = (char *)pSMB;
3717         iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
3718
3719         rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3720                          0);
3721         cifs_stats_inc(&tcon->num_acl_get);
3722         if (rc) {
3723                 cFYI(1, "Send error in QuerySecDesc = %d", rc);
3724         } else {                /* decode response */
3725                 __le32 *parm;
3726                 __u32 parm_len;
3727                 __u32 acl_len;
3728                 struct smb_com_ntransact_rsp *pSMBr;
3729                 char *pdata;
3730
3731 /* validate_nttransact */
3732                 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3733                                         &pdata, &parm_len, pbuflen);
3734                 if (rc)
3735                         goto qsec_out;
3736                 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3737
3738                 cFYI(1, "smb %p parm %p data %p", pSMBr, parm, *acl_inf);
3739
3740                 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3741                         rc = -EIO;      /* bad smb */
3742                         *pbuflen = 0;
3743                         goto qsec_out;
3744                 }
3745
3746 /* BB check that data area is minimum length and as big as acl_len */
3747
3748                 acl_len = le32_to_cpu(*parm);
3749                 if (acl_len != *pbuflen) {
3750                         cERROR(1, "acl length %d does not match %d",
3751                                    acl_len, *pbuflen);
3752                         if (*pbuflen > acl_len)
3753                                 *pbuflen = acl_len;
3754                 }
3755
3756                 /* check if buffer is big enough for the acl
3757                    header followed by the smallest SID */
3758                 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3759                     (*pbuflen >= 64 * 1024)) {
3760                         cERROR(1, "bad acl length %d", *pbuflen);
3761                         rc = -EINVAL;
3762                         *pbuflen = 0;
3763                 } else {
3764                         *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3765                         if (*acl_inf == NULL) {
3766                                 *pbuflen = 0;
3767                                 rc = -ENOMEM;
3768                         }
3769                         memcpy(*acl_inf, pdata, *pbuflen);
3770                 }
3771         }
3772 qsec_out:
3773         if (buf_type == CIFS_SMALL_BUFFER)
3774                 cifs_small_buf_release(iov[0].iov_base);
3775         else if (buf_type == CIFS_LARGE_BUFFER)
3776                 cifs_buf_release(iov[0].iov_base);
3777 /*      cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3778         return rc;
3779 }
3780
3781 int
3782 CIFSSMBSetCIFSACL(const int xid, struct cifs_tcon *tcon, __u16 fid,
3783                         struct cifs_ntsd *pntsd, __u32 acllen, int aclflag)
3784 {
3785         __u16 byte_count, param_count, data_count, param_offset, data_offset;
3786         int rc = 0;
3787         int bytes_returned = 0;
3788         SET_SEC_DESC_REQ *pSMB = NULL;
3789         void *pSMBr;
3790
3791 setCifsAclRetry:
3792         rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, &pSMBr);
3793         if (rc)
3794                 return rc;
3795
3796         pSMB->MaxSetupCount = 0;
3797         pSMB->Reserved = 0;
3798
3799         param_count = 8;
3800         param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3801         data_count = acllen;
3802         data_offset = param_offset + param_count;
3803         byte_count = 3 /* pad */  + param_count;
3804
3805         pSMB->DataCount = cpu_to_le32(data_count);
3806         pSMB->TotalDataCount = pSMB->DataCount;
3807         pSMB->MaxParameterCount = cpu_to_le32(4);
3808         pSMB->MaxDataCount = cpu_to_le32(16384);
3809         pSMB->ParameterCount = cpu_to_le32(param_count);
3810         pSMB->ParameterOffset = cpu_to_le32(param_offset);
3811         pSMB->TotalParameterCount = pSMB->ParameterCount;
3812         pSMB->DataOffset = cpu_to_le32(data_offset);
3813         pSMB->SetupCount = 0;
3814         pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3815         pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3816
3817         pSMB->Fid = fid; /* file handle always le */
3818         pSMB->Reserved2 = 0;
3819         pSMB->AclFlags = cpu_to_le32(aclflag);
3820
3821         if (pntsd && acllen) {
3822                 memcpy((char *)pSMBr + offsetof(struct smb_hdr, Protocol) +
3823                                 data_offset, pntsd, acllen);
3824                 inc_rfc1001_len(pSMB, byte_count + data_count);
3825         } else
3826                 inc_rfc1001_len(pSMB, byte_count);
3827
3828         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3829                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3830
3831         cFYI(1, "SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc);
3832         if (rc)
3833                 cFYI(1, "Set CIFS ACL returned %d", rc);
3834         cifs_buf_release(pSMB);
3835
3836         if (rc == -EAGAIN)
3837                 goto setCifsAclRetry;
3838
3839         return (rc);
3840 }
3841
3842 #endif /* CONFIG_CIFS_ACL */
3843
3844 /* Legacy Query Path Information call for lookup to old servers such
3845    as Win9x/WinME */
3846 int SMBQueryInformation(const int xid, struct cifs_tcon *tcon,
3847                         const unsigned char *searchName,
3848                         FILE_ALL_INFO *pFinfo,
3849                         const struct nls_table *nls_codepage, int remap)
3850 {
3851         QUERY_INFORMATION_REQ *pSMB;
3852         QUERY_INFORMATION_RSP *pSMBr;
3853         int rc = 0;
3854         int bytes_returned;
3855         int name_len;
3856
3857         cFYI(1, "In SMBQPath path %s", searchName);
3858 QInfRetry:
3859         rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3860                       (void **) &pSMBr);
3861         if (rc)
3862                 return rc;
3863
3864         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3865                 name_len =
3866                         cifsConvertToUTF16((__le16 *) pSMB->FileName,
3867                                            searchName, PATH_MAX, nls_codepage,
3868                                            remap);
3869                 name_len++;     /* trailing null */
3870                 name_len *= 2;
3871         } else {
3872                 name_len = strnlen(searchName, PATH_MAX);
3873                 name_len++;     /* trailing null */
3874                 strncpy(pSMB->FileName, searchName, name_len);
3875         }
3876         pSMB->BufferFormat = 0x04;
3877         name_len++; /* account for buffer type byte */
3878         inc_rfc1001_len(pSMB, (__u16)name_len);
3879         pSMB->ByteCount = cpu_to_le16(name_len);
3880
3881         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3882                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3883         if (rc) {
3884                 cFYI(1, "Send error in QueryInfo = %d", rc);
3885         } else if (pFinfo) {
3886                 struct timespec ts;
3887                 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3888
3889                 /* decode response */
3890                 /* BB FIXME - add time zone adjustment BB */
3891                 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3892                 ts.tv_nsec = 0;
3893                 ts.tv_sec = time;
3894                 /* decode time fields */
3895                 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3896                 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3897                 pFinfo->LastAccessTime = 0;
3898                 pFinfo->AllocationSize =
3899                         cpu_to_le64(le32_to_cpu(pSMBr->size));
3900                 pFinfo->EndOfFile = pFinfo->AllocationSize;
3901                 pFinfo->Attributes =
3902                         cpu_to_le32(le16_to_cpu(pSMBr->attr));
3903         } else
3904                 rc = -EIO; /* bad buffer passed in */
3905
3906         cifs_buf_release(pSMB);
3907
3908         if (rc == -EAGAIN)
3909                 goto QInfRetry;
3910
3911         return rc;
3912 }
3913
3914 int
3915 CIFSSMBQFileInfo(const int xid, struct cifs_tcon *tcon,
3916                  u16 netfid, FILE_ALL_INFO *pFindData)
3917 {
3918         struct smb_t2_qfi_req *pSMB = NULL;
3919         struct smb_t2_qfi_rsp *pSMBr = NULL;
3920         int rc = 0;
3921         int bytes_returned;
3922         __u16 params, byte_count;
3923
3924 QFileInfoRetry:
3925         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3926                       (void **) &pSMBr);
3927         if (rc)
3928                 return rc;
3929
3930         params = 2 /* level */ + 2 /* fid */;
3931         pSMB->t2.TotalDataCount = 0;
3932         pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3933         /* BB find exact max data count below from sess structure BB */
3934         pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3935         pSMB->t2.MaxSetupCount = 0;
3936         pSMB->t2.Reserved = 0;
3937         pSMB->t2.Flags = 0;
3938         pSMB->t2.Timeout = 0;
3939         pSMB->t2.Reserved2 = 0;
3940         pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3941                                                Fid) - 4);
3942         pSMB->t2.DataCount = 0;
3943         pSMB->t2.DataOffset = 0;
3944         pSMB->t2.SetupCount = 1;
3945         pSMB->t2.Reserved3 = 0;
3946         pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3947         byte_count = params + 1 /* pad */ ;
3948         pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3949         pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3950         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3951         pSMB->Pad = 0;
3952         pSMB->Fid = netfid;
3953         inc_rfc1001_len(pSMB, byte_count);
3954
3955         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3956                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3957         if (rc) {
3958                 cFYI(1, "Send error in QPathInfo = %d", rc);
3959         } else {                /* decode response */
3960                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3961
3962                 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3963                         rc = -EIO;
3964                 else if (get_bcc(&pSMBr->hdr) < 40)
3965                         rc = -EIO;      /* bad smb */
3966                 else if (pFindData) {
3967                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3968                         memcpy((char *) pFindData,
3969                                (char *) &pSMBr->hdr.Protocol +
3970                                data_offset, sizeof(FILE_ALL_INFO));
3971                 } else
3972                     rc = -ENOMEM;
3973         }
3974         cifs_buf_release(pSMB);
3975         if (rc == -EAGAIN)
3976                 goto QFileInfoRetry;
3977
3978         return rc;
3979 }
3980
3981 int
3982 CIFSSMBQPathInfo(const int xid, struct cifs_tcon *tcon,
3983                  const unsigned char *searchName,
3984                  FILE_ALL_INFO *pFindData,
3985                  int legacy /* old style infolevel */,
3986                  const struct nls_table *nls_codepage, int remap)
3987 {
3988 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3989         TRANSACTION2_QPI_REQ *pSMB = NULL;
3990         TRANSACTION2_QPI_RSP *pSMBr = NULL;
3991         int rc = 0;
3992         int bytes_returned;
3993         int name_len;
3994         __u16 params, byte_count;
3995
3996 /* cFYI(1, "In QPathInfo path %s", searchName); */
3997 QPathInfoRetry:
3998         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3999                       (void **) &pSMBr);
4000         if (rc)
4001                 return rc;
4002
4003         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4004                 name_len =
4005                     cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4006                                        PATH_MAX, nls_codepage, remap);
4007                 name_len++;     /* trailing null */
4008                 name_len *= 2;
4009         } else {        /* BB improve the check for buffer overruns BB */
4010                 name_len = strnlen(searchName, PATH_MAX);
4011                 name_len++;     /* trailing null */
4012                 strncpy(pSMB->FileName, searchName, name_len);
4013         }
4014
4015         params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4016         pSMB->TotalDataCount = 0;
4017         pSMB->MaxParameterCount = cpu_to_le16(2);
4018         /* BB find exact max SMB PDU from sess structure BB */
4019         pSMB->MaxDataCount = cpu_to_le16(4000);
4020         pSMB->MaxSetupCount = 0;
4021         pSMB->Reserved = 0;
4022         pSMB->Flags = 0;
4023         pSMB->Timeout = 0;
4024         pSMB->Reserved2 = 0;
4025         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4026         struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4027         pSMB->DataCount = 0;
4028         pSMB->DataOffset = 0;
4029         pSMB->SetupCount = 1;
4030         pSMB->Reserved3 = 0;
4031         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4032         byte_count = params + 1 /* pad */ ;
4033         pSMB->TotalParameterCount = cpu_to_le16(params);
4034         pSMB->ParameterCount = pSMB->TotalParameterCount;
4035         if (legacy)
4036                 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
4037         else
4038                 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
4039         pSMB->Reserved4 = 0;
4040         inc_rfc1001_len(pSMB, byte_count);
4041         pSMB->ByteCount = cpu_to_le16(byte_count);
4042
4043         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4044                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4045         if (rc) {
4046                 cFYI(1, "Send error in QPathInfo = %d", rc);
4047         } else {                /* decode response */
4048                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4049
4050                 if (rc) /* BB add auto retry on EOPNOTSUPP? */
4051                         rc = -EIO;
4052                 else if (!legacy && get_bcc(&pSMBr->hdr) < 40)
4053                         rc = -EIO;      /* bad smb */
4054                 else if (legacy && get_bcc(&pSMBr->hdr) < 24)
4055                         rc = -EIO;  /* 24 or 26 expected but we do not read
4056                                         last field */
4057                 else if (pFindData) {
4058                         int size;
4059                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4060
4061                         /* On legacy responses we do not read the last field,
4062                         EAsize, fortunately since it varies by subdialect and
4063                         also note it differs on Set vs. Get, ie two bytes or 4
4064                         bytes depending but we don't care here */
4065                         if (legacy)
4066                                 size = sizeof(FILE_INFO_STANDARD);
4067                         else
4068                                 size = sizeof(FILE_ALL_INFO);
4069                         memcpy((char *) pFindData,
4070                                (char *) &pSMBr->hdr.Protocol +
4071                                data_offset, size);
4072                 } else
4073                     rc = -ENOMEM;
4074         }
4075         cifs_buf_release(pSMB);
4076         if (rc == -EAGAIN)
4077                 goto QPathInfoRetry;
4078
4079         return rc;
4080 }
4081
4082 int
4083 CIFSSMBUnixQFileInfo(const int xid, struct cifs_tcon *tcon,
4084                  u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
4085 {
4086         struct smb_t2_qfi_req *pSMB = NULL;
4087         struct smb_t2_qfi_rsp *pSMBr = NULL;
4088         int rc = 0;
4089         int bytes_returned;
4090         __u16 params, byte_count;
4091
4092 UnixQFileInfoRetry:
4093         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4094                       (void **) &pSMBr);
4095         if (rc)
4096                 return rc;
4097
4098         params = 2 /* level */ + 2 /* fid */;
4099         pSMB->t2.TotalDataCount = 0;
4100         pSMB->t2.MaxParameterCount = cpu_to_le16(4);
4101         /* BB find exact max data count below from sess structure BB */
4102         pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
4103         pSMB->t2.MaxSetupCount = 0;
4104         pSMB->t2.Reserved = 0;
4105         pSMB->t2.Flags = 0;
4106         pSMB->t2.Timeout = 0;
4107         pSMB->t2.Reserved2 = 0;
4108         pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
4109                                                Fid) - 4);
4110         pSMB->t2.DataCount = 0;
4111         pSMB->t2.DataOffset = 0;
4112         pSMB->t2.SetupCount = 1;
4113         pSMB->t2.Reserved3 = 0;
4114         pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
4115         byte_count = params + 1 /* pad */ ;
4116         pSMB->t2.TotalParameterCount = cpu_to_le16(params);
4117         pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
4118         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4119         pSMB->Pad = 0;
4120         pSMB->Fid = netfid;
4121         inc_rfc1001_len(pSMB, byte_count);
4122
4123         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4124                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4125         if (rc) {
4126                 cFYI(1, "Send error in QPathInfo = %d", rc);
4127         } else {                /* decode response */
4128                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4129
4130                 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4131                         cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
4132                                    "Unix Extensions can be disabled on mount "
4133                                    "by specifying the nosfu mount option.");
4134                         rc = -EIO;      /* bad smb */
4135                 } else {
4136                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4137                         memcpy((char *) pFindData,
4138                                (char *) &pSMBr->hdr.Protocol +
4139                                data_offset,
4140                                sizeof(FILE_UNIX_BASIC_INFO));
4141                 }
4142         }
4143
4144         cifs_buf_release(pSMB);
4145         if (rc == -EAGAIN)
4146                 goto UnixQFileInfoRetry;
4147
4148         return rc;
4149 }
4150
4151 int
4152 CIFSSMBUnixQPathInfo(const int xid, struct cifs_tcon *tcon,
4153                      const unsigned char *searchName,
4154                      FILE_UNIX_BASIC_INFO *pFindData,
4155                      const struct nls_table *nls_codepage, int remap)
4156 {
4157 /* SMB_QUERY_FILE_UNIX_BASIC */
4158         TRANSACTION2_QPI_REQ *pSMB = NULL;
4159         TRANSACTION2_QPI_RSP *pSMBr = NULL;
4160         int rc = 0;
4161         int bytes_returned = 0;
4162         int name_len;
4163         __u16 params, byte_count;
4164
4165         cFYI(1, "In QPathInfo (Unix) the path %s", searchName);
4166 UnixQPathInfoRetry:
4167         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4168                       (void **) &pSMBr);
4169         if (rc)
4170                 return rc;
4171
4172         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4173                 name_len =
4174                     cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4175                                        PATH_MAX, nls_codepage, remap);
4176                 name_len++;     /* trailing null */
4177                 name_len *= 2;
4178         } else {        /* BB improve the check for buffer overruns BB */
4179                 name_len = strnlen(searchName, PATH_MAX);
4180                 name_len++;     /* trailing null */
4181                 strncpy(pSMB->FileName, searchName, name_len);
4182         }
4183
4184         params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4185         pSMB->TotalDataCount = 0;
4186         pSMB->MaxParameterCount = cpu_to_le16(2);
4187         /* BB find exact max SMB PDU from sess structure BB */
4188         pSMB->MaxDataCount = cpu_to_le16(4000);
4189         pSMB->MaxSetupCount = 0;
4190         pSMB->Reserved = 0;
4191         pSMB->Flags = 0;
4192         pSMB->Timeout = 0;
4193         pSMB->Reserved2 = 0;
4194         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4195         struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4196         pSMB->DataCount = 0;
4197         pSMB->DataOffset = 0;
4198         pSMB->SetupCount = 1;
4199         pSMB->Reserved3 = 0;
4200         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4201         byte_count = params + 1 /* pad */ ;
4202         pSMB->TotalParameterCount = cpu_to_le16(params);
4203         pSMB->ParameterCount = pSMB->TotalParameterCount;
4204         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4205         pSMB->Reserved4 = 0;
4206         inc_rfc1001_len(pSMB, byte_count);
4207         pSMB->ByteCount = cpu_to_le16(byte_count);
4208
4209         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4210                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4211         if (rc) {
4212                 cFYI(1, "Send error in QPathInfo = %d", rc);
4213         } else {                /* decode response */
4214                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4215
4216                 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4217                         cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
4218                                    "Unix Extensions can be disabled on mount "
4219                                    "by specifying the nosfu mount option.");
4220                         rc = -EIO;      /* bad smb */
4221                 } else {
4222                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4223                         memcpy((char *) pFindData,
4224                                (char *) &pSMBr->hdr.Protocol +
4225                                data_offset,
4226                                sizeof(FILE_UNIX_BASIC_INFO));
4227                 }
4228         }
4229         cifs_buf_release(pSMB);
4230         if (rc == -EAGAIN)
4231                 goto UnixQPathInfoRetry;
4232
4233         return rc;
4234 }
4235
4236 /* xid, tcon, searchName and codepage are input parms, rest are returned */
4237 int
4238 CIFSFindFirst(const int xid, struct cifs_tcon *tcon,
4239               const char *searchName,
4240               const struct nls_table *nls_codepage,
4241               __u16 *pnetfid, __u16 search_flags,
4242               struct cifs_search_info *psrch_inf, int remap, const char dirsep)
4243 {
4244 /* level 257 SMB_ */
4245         TRANSACTION2_FFIRST_REQ *pSMB = NULL;
4246         TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
4247         T2_FFIRST_RSP_PARMS *parms;
4248         int rc = 0;
4249         int bytes_returned = 0;
4250         int name_len;
4251         __u16 params, byte_count;
4252
4253         cFYI(1, "In FindFirst for %s", searchName);
4254
4255 findFirstRetry:
4256         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4257                       (void **) &pSMBr);
4258         if (rc)
4259                 return rc;
4260
4261         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4262                 name_len =
4263                     cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4264                                        PATH_MAX, nls_codepage, remap);
4265                 /* We can not add the asterik earlier in case
4266                 it got remapped to 0xF03A as if it were part of the
4267                 directory name instead of a wildcard */
4268                 name_len *= 2;
4269                 pSMB->FileName[name_len] = dirsep;
4270                 pSMB->FileName[name_len+1] = 0;
4271                 pSMB->FileName[name_len+2] = '*';
4272                 pSMB->FileName[name_len+3] = 0;
4273                 name_len += 4; /* now the trailing null */
4274                 pSMB->FileName[name_len] = 0; /* null terminate just in case */
4275                 pSMB->FileName[name_len+1] = 0;
4276                 name_len += 2;
4277         } else {        /* BB add check for overrun of SMB buf BB */
4278                 name_len = strnlen(searchName, PATH_MAX);
4279 /* BB fix here and in unicode clause above ie
4280                 if (name_len > buffersize-header)
4281                         free buffer exit; BB */
4282                 strncpy(pSMB->FileName, searchName, name_len);
4283                 pSMB->FileName[name_len] = dirsep;
4284                 pSMB->FileName[name_len+1] = '*';
4285                 pSMB->FileName[name_len+2] = 0;
4286                 name_len += 3;
4287         }
4288
4289         params = 12 + name_len /* includes null */ ;
4290         pSMB->TotalDataCount = 0;       /* no EAs */
4291         pSMB->MaxParameterCount = cpu_to_le16(10);
4292         pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4293         pSMB->MaxSetupCount = 0;
4294         pSMB->Reserved = 0;
4295         pSMB->Flags = 0;
4296         pSMB->Timeout = 0;
4297         pSMB->Reserved2 = 0;
4298         byte_count = params + 1 /* pad */ ;
4299         pSMB->TotalParameterCount = cpu_to_le16(params);
4300         pSMB->ParameterCount = pSMB->TotalParameterCount;
4301         pSMB->ParameterOffset = cpu_to_le16(
4302               offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
4303                 - 4);
4304         pSMB->DataCount = 0;
4305         pSMB->DataOffset = 0;
4306         pSMB->SetupCount = 1;   /* one byte, no need to make endian neutral */
4307         pSMB->Reserved3 = 0;
4308         pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
4309         pSMB->SearchAttributes =
4310             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
4311                         ATTR_DIRECTORY);
4312         pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
4313         pSMB->SearchFlags = cpu_to_le16(search_flags);
4314         pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4315
4316         /* BB what should we set StorageType to? Does it matter? BB */
4317         pSMB->SearchStorageType = 0;
4318         inc_rfc1001_len(pSMB, byte_count);
4319         pSMB->ByteCount = cpu_to_le16(byte_count);
4320
4321         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4322                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4323         cifs_stats_inc(&tcon->num_ffirst);
4324
4325         if (rc) {/* BB add logic to retry regular search if Unix search
4326                         rejected unexpectedly by server */
4327                 /* BB Add code to handle unsupported level rc */
4328                 cFYI(1, "Error in FindFirst = %d", rc);
4329
4330                 cifs_buf_release(pSMB);
4331
4332                 /* BB eventually could optimize out free and realloc of buf */
4333                 /*    for this case */
4334                 if (rc == -EAGAIN)
4335                         goto findFirstRetry;
4336         } else { /* decode response */
4337                 /* BB remember to free buffer if error BB */
4338                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4339                 if (rc == 0) {
4340                         unsigned int lnoff;
4341
4342                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4343                                 psrch_inf->unicode = true;
4344                         else
4345                                 psrch_inf->unicode = false;
4346
4347                         psrch_inf->ntwrk_buf_start = (char *)pSMBr;
4348                         psrch_inf->smallBuf = 0;
4349                         psrch_inf->srch_entries_start =
4350                                 (char *) &pSMBr->hdr.Protocol +
4351                                         le16_to_cpu(pSMBr->t2.DataOffset);
4352                         parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
4353                                le16_to_cpu(pSMBr->t2.ParameterOffset));
4354
4355                         if (parms->EndofSearch)
4356                                 psrch_inf->endOfSearch = true;
4357                         else
4358                                 psrch_inf->endOfSearch = false;
4359
4360                         psrch_inf->entries_in_buffer =
4361                                         le16_to_cpu(parms->SearchCount);
4362                         psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
4363                                 psrch_inf->entries_in_buffer;
4364                         lnoff = le16_to_cpu(parms->LastNameOffset);
4365                         if (CIFSMaxBufSize < lnoff) {
4366                                 cERROR(1, "ignoring corrupt resume name");
4367                                 psrch_inf->last_entry = NULL;
4368                                 return rc;
4369                         }
4370
4371                         psrch_inf->last_entry = psrch_inf->srch_entries_start +
4372                                                         lnoff;
4373
4374                         *pnetfid = parms->SearchHandle;
4375                 } else {
4376                         cifs_buf_release(pSMB);
4377                 }
4378         }
4379
4380         return rc;
4381 }
4382
4383 int CIFSFindNext(const int xid, struct cifs_tcon *tcon, __u16 searchHandle,
4384                  __u16 search_flags, struct cifs_search_info *psrch_inf)
4385 {
4386         TRANSACTION2_FNEXT_REQ *pSMB = NULL;
4387         TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
4388         T2_FNEXT_RSP_PARMS *parms;
4389         char *response_data;
4390         int rc = 0;
4391         int bytes_returned;
4392         unsigned int name_len;
4393         __u16 params, byte_count;
4394
4395         cFYI(1, "In FindNext");
4396
4397         if (psrch_inf->endOfSearch)
4398                 return -ENOENT;
4399
4400         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4401                 (void **) &pSMBr);
4402         if (rc)
4403                 return rc;
4404
4405         params = 14; /* includes 2 bytes of null string, converted to LE below*/
4406         byte_count = 0;
4407         pSMB->TotalDataCount = 0;       /* no EAs */
4408         pSMB->MaxParameterCount = cpu_to_le16(8);
4409         pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4410         pSMB->MaxSetupCount = 0;
4411         pSMB->Reserved = 0;
4412         pSMB->Flags = 0;
4413         pSMB->Timeout = 0;
4414         pSMB->Reserved2 = 0;
4415         pSMB->ParameterOffset =  cpu_to_le16(
4416               offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
4417         pSMB->DataCount = 0;
4418         pSMB->DataOffset = 0;
4419         pSMB->SetupCount = 1;
4420         pSMB->Reserved3 = 0;
4421         pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
4422         pSMB->SearchHandle = searchHandle;      /* always kept as le */
4423         pSMB->SearchCount =
4424                 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
4425         pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4426         pSMB->ResumeKey = psrch_inf->resume_key;
4427         pSMB->SearchFlags = cpu_to_le16(search_flags);
4428
4429         name_len = psrch_inf->resume_name_len;
4430         params += name_len;
4431         if (name_len < PATH_MAX) {
4432                 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
4433                 byte_count += name_len;
4434                 /* 14 byte parm len above enough for 2 byte null terminator */
4435                 pSMB->ResumeFileName[name_len] = 0;
4436                 pSMB->ResumeFileName[name_len+1] = 0;
4437         } else {
4438                 rc = -EINVAL;
4439                 goto FNext2_err_exit;
4440         }
4441         byte_count = params + 1 /* pad */ ;
4442         pSMB->TotalParameterCount = cpu_to_le16(params);
4443         pSMB->ParameterCount = pSMB->TotalParameterCount;
4444         inc_rfc1001_len(pSMB, byte_count);
4445         pSMB->ByteCount = cpu_to_le16(byte_count);
4446
4447         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4448                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4449         cifs_stats_inc(&tcon->num_fnext);
4450         if (rc) {
4451                 if (rc == -EBADF) {
4452                         psrch_inf->endOfSearch = true;
4453                         cifs_buf_release(pSMB);
4454                         rc = 0; /* search probably was closed at end of search*/
4455                 } else
4456                         cFYI(1, "FindNext returned = %d", rc);
4457         } else {                /* decode response */
4458                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4459
4460                 if (rc == 0) {
4461                         unsigned int lnoff;
4462
4463                         /* BB fixme add lock for file (srch_info) struct here */
4464                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4465                                 psrch_inf->unicode = true;
4466                         else
4467                                 psrch_inf->unicode = false;
4468                         response_data = (char *) &pSMBr->hdr.Protocol +
4469                                le16_to_cpu(pSMBr->t2.ParameterOffset);
4470                         parms = (T2_FNEXT_RSP_PARMS *)response_data;
4471                         response_data = (char *)&pSMBr->hdr.Protocol +
4472                                 le16_to_cpu(pSMBr->t2.DataOffset);
4473                         if (psrch_inf->smallBuf)
4474                                 cifs_small_buf_release(
4475                                         psrch_inf->ntwrk_buf_start);
4476                         else
4477                                 cifs_buf_release(psrch_inf->ntwrk_buf_start);
4478                         psrch_inf->srch_entries_start = response_data;
4479                         psrch_inf->ntwrk_buf_start = (char *)pSMB;
4480                         psrch_inf->smallBuf = 0;
4481                         if (parms->EndofSearch)
4482                                 psrch_inf->endOfSearch = true;
4483                         else
4484                                 psrch_inf->endOfSearch = false;
4485                         psrch_inf->entries_in_buffer =
4486                                                 le16_to_cpu(parms->SearchCount);
4487                         psrch_inf->index_of_last_entry +=
4488                                 psrch_inf->entries_in_buffer;
4489                         lnoff = le16_to_cpu(parms->LastNameOffset);
4490                         if (CIFSMaxBufSize < lnoff) {
4491                                 cERROR(1, "ignoring corrupt resume name");
4492                                 psrch_inf->last_entry = NULL;
4493                                 return rc;
4494                         } else
4495                                 psrch_inf->last_entry =
4496                                         psrch_inf->srch_entries_start + lnoff;
4497
4498 /*  cFYI(1, "fnxt2 entries in buf %d index_of_last %d",
4499             psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
4500
4501                         /* BB fixme add unlock here */
4502                 }
4503
4504         }
4505
4506         /* BB On error, should we leave previous search buf (and count and
4507         last entry fields) intact or free the previous one? */
4508
4509         /* Note: On -EAGAIN error only caller can retry on handle based calls
4510         since file handle passed in no longer valid */
4511 FNext2_err_exit:
4512         if (rc != 0)
4513                 cifs_buf_release(pSMB);
4514         return rc;
4515 }
4516
4517 int
4518 CIFSFindClose(const int xid, struct cifs_tcon *tcon,
4519               const __u16 searchHandle)
4520 {
4521         int rc = 0;
4522         FINDCLOSE_REQ *pSMB = NULL;
4523
4524         cFYI(1, "In CIFSSMBFindClose");
4525         rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
4526
4527         /* no sense returning error if session restarted
4528                 as file handle has been closed */
4529         if (rc == -EAGAIN)
4530                 return 0;
4531         if (rc)
4532                 return rc;
4533
4534         pSMB->FileID = searchHandle;
4535         pSMB->ByteCount = 0;
4536         rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
4537         if (rc)
4538                 cERROR(1, "Send error in FindClose = %d", rc);
4539
4540         cifs_stats_inc(&tcon->num_fclose);
4541
4542         /* Since session is dead, search handle closed on server already */
4543         if (rc == -EAGAIN)
4544                 rc = 0;
4545
4546         return rc;
4547 }
4548
4549 int
4550 CIFSGetSrvInodeNumber(const int xid, struct cifs_tcon *tcon,
4551                       const unsigned char *searchName,
4552                       __u64 *inode_number,
4553                       const struct nls_table *nls_codepage, int remap)
4554 {
4555         int rc = 0;
4556         TRANSACTION2_QPI_REQ *pSMB = NULL;
4557         TRANSACTION2_QPI_RSP *pSMBr = NULL;
4558         int name_len, bytes_returned;
4559         __u16 params, byte_count;
4560
4561         cFYI(1, "In GetSrvInodeNum for %s", searchName);
4562         if (tcon == NULL)
4563                 return -ENODEV;
4564
4565 GetInodeNumberRetry:
4566         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4567                       (void **) &pSMBr);
4568         if (rc)
4569                 return rc;
4570
4571         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4572                 name_len =
4573                         cifsConvertToUTF16((__le16 *) pSMB->FileName,
4574                                            searchName, PATH_MAX, nls_codepage,
4575                                            remap);
4576                 name_len++;     /* trailing null */
4577                 name_len *= 2;
4578         } else {        /* BB improve the check for buffer overruns BB */
4579                 name_len = strnlen(searchName, PATH_MAX);
4580                 name_len++;     /* trailing null */
4581                 strncpy(pSMB->FileName, searchName, name_len);
4582         }
4583
4584         params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
4585         pSMB->TotalDataCount = 0;
4586         pSMB->MaxParameterCount = cpu_to_le16(2);
4587         /* BB find exact max data count below from sess structure BB */
4588         pSMB->MaxDataCount = cpu_to_le16(4000);
4589         pSMB->MaxSetupCount = 0;
4590         pSMB->Reserved = 0;
4591         pSMB->Flags = 0;
4592         pSMB->Timeout = 0;
4593         pSMB->Reserved2 = 0;
4594         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4595                 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4596         pSMB->DataCount = 0;
4597         pSMB->DataOffset = 0;
4598         pSMB->SetupCount = 1;
4599         pSMB->Reserved3 = 0;
4600         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4601         byte_count = params + 1 /* pad */ ;
4602         pSMB->TotalParameterCount = cpu_to_le16(params);
4603         pSMB->ParameterCount = pSMB->TotalParameterCount;
4604         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
4605         pSMB->Reserved4 = 0;
4606         inc_rfc1001_len(pSMB, byte_count);
4607         pSMB->ByteCount = cpu_to_le16(byte_count);
4608
4609         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4610                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4611         if (rc) {
4612                 cFYI(1, "error %d in QueryInternalInfo", rc);
4613         } else {
4614                 /* decode response */
4615                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4616                 /* BB also check enough total bytes returned */
4617                 if (rc || get_bcc(&pSMBr->hdr) < 2)
4618                         /* If rc should we check for EOPNOSUPP and
4619                         disable the srvino flag? or in caller? */
4620                         rc = -EIO;      /* bad smb */
4621                 else {
4622                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4623                         __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
4624                         struct file_internal_info *pfinfo;
4625                         /* BB Do we need a cast or hash here ? */
4626                         if (count < 8) {
4627                                 cFYI(1, "Illegal size ret in QryIntrnlInf");
4628                                 rc = -EIO;
4629                                 goto GetInodeNumOut;
4630                         }
4631                         pfinfo = (struct file_internal_info *)
4632                                 (data_offset + (char *) &pSMBr->hdr.Protocol);
4633                         *inode_number = le64_to_cpu(pfinfo->UniqueId);
4634                 }
4635         }
4636 GetInodeNumOut:
4637         cifs_buf_release(pSMB);
4638         if (rc == -EAGAIN)
4639                 goto GetInodeNumberRetry;
4640         return rc;
4641 }
4642
4643 /* parses DFS refferal V3 structure
4644  * caller is responsible for freeing target_nodes
4645  * returns:
4646  *      on success - 0
4647  *      on failure - errno
4648  */
4649 static int
4650 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
4651                 unsigned int *num_of_nodes,
4652                 struct dfs_info3_param **target_nodes,
4653                 const struct nls_table *nls_codepage, int remap,
4654                 const char *searchName)
4655 {
4656         int i, rc = 0;
4657         char *data_end;
4658         bool is_unicode;
4659         struct dfs_referral_level_3 *ref;
4660
4661         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4662                 is_unicode = true;
4663         else
4664                 is_unicode = false;
4665         *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
4666
4667         if (*num_of_nodes < 1) {
4668                 cERROR(1, "num_referrals: must be at least > 0,"
4669                         "but we get num_referrals = %d\n", *num_of_nodes);
4670                 rc = -EINVAL;
4671                 goto parse_DFS_referrals_exit;
4672         }
4673
4674         ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
4675         if (ref->VersionNumber != cpu_to_le16(3)) {
4676                 cERROR(1, "Referrals of V%d version are not supported,"
4677                         "should be V3", le16_to_cpu(ref->VersionNumber));
4678                 rc = -EINVAL;
4679                 goto parse_DFS_referrals_exit;
4680         }
4681
4682         /* get the upper boundary of the resp buffer */
4683         data_end = (char *)(&(pSMBr->PathConsumed)) +
4684                                 le16_to_cpu(pSMBr->t2.DataCount);
4685
4686         cFYI(1, "num_referrals: %d dfs flags: 0x%x ...\n",
4687                         *num_of_nodes,
4688                         le32_to_cpu(pSMBr->DFSFlags));
4689
4690         *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
4691                         *num_of_nodes, GFP_KERNEL);
4692         if (*target_nodes == NULL) {
4693                 cERROR(1, "Failed to allocate buffer for target_nodes\n");
4694                 rc = -ENOMEM;
4695                 goto parse_DFS_referrals_exit;
4696         }
4697
4698         /* collect necessary data from referrals */
4699         for (i = 0; i < *num_of_nodes; i++) {
4700                 char *temp;
4701                 int max_len;
4702                 struct dfs_info3_param *node = (*target_nodes)+i;
4703
4704                 node->flags = le32_to_cpu(pSMBr->DFSFlags);
4705                 if (is_unicode) {
4706                         __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
4707                                                 GFP_KERNEL);
4708                         if (tmp == NULL) {
4709                                 rc = -ENOMEM;
4710                                 goto parse_DFS_referrals_exit;
4711                         }
4712                         cifsConvertToUTF16((__le16 *) tmp, searchName,
4713                                            PATH_MAX, nls_codepage, remap);
4714                         node->path_consumed = cifs_utf16_bytes(tmp,
4715                                         le16_to_cpu(pSMBr->PathConsumed),
4716                                         nls_codepage);
4717                         kfree(tmp);
4718                 } else
4719                         node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
4720
4721                 node->server_type = le16_to_cpu(ref->ServerType);
4722                 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
4723
4724                 /* copy DfsPath */
4725                 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
4726                 max_len = data_end - temp;
4727                 node->path_name = cifs_strndup_from_utf16(temp, max_len,
4728                                                 is_unicode, nls_codepage);
4729                 if (!node->path_name) {
4730                         rc = -ENOMEM;
4731                         goto parse_DFS_referrals_exit;
4732                 }
4733
4734                 /* copy link target UNC */
4735                 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
4736                 max_len = data_end - temp;
4737                 node->node_name = cifs_strndup_from_utf16(temp, max_len,
4738                                                 is_unicode, nls_codepage);
4739                 if (!node->node_name) {
4740                         rc = -ENOMEM;
4741                         goto parse_DFS_referrals_exit;
4742                 }
4743
4744                 ref++;
4745         }
4746
4747 parse_DFS_referrals_exit:
4748         if (rc) {
4749                 free_dfs_info_array(*target_nodes, *num_of_nodes);
4750                 *target_nodes = NULL;
4751                 *num_of_nodes = 0;
4752         }
4753         return rc;
4754 }
4755
4756 int
4757 CIFSGetDFSRefer(const int xid, struct cifs_ses *ses,
4758                 const unsigned char *searchName,
4759                 struct dfs_info3_param **target_nodes,
4760                 unsigned int *num_of_nodes,
4761                 const struct nls_table *nls_codepage, int remap)
4762 {
4763 /* TRANS2_GET_DFS_REFERRAL */
4764         TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4765         TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4766         int rc = 0;
4767         int bytes_returned;
4768         int name_len;
4769         __u16 params, byte_count;
4770         *num_of_nodes = 0;
4771         *target_nodes = NULL;
4772
4773         cFYI(1, "In GetDFSRefer the path %s", searchName);
4774         if (ses == NULL)
4775                 return -ENODEV;
4776 getDFSRetry:
4777         rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4778                       (void **) &pSMBr);
4779         if (rc)
4780                 return rc;
4781
4782         /* server pointer checked in called function,
4783         but should never be null here anyway */
4784         pSMB->hdr.Mid = GetNextMid(ses->server);
4785         pSMB->hdr.Tid = ses->ipc_tid;
4786         pSMB->hdr.Uid = ses->Suid;
4787         if (ses->capabilities & CAP_STATUS32)
4788                 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4789         if (ses->capabilities & CAP_DFS)
4790                 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4791
4792         if (ses->capabilities & CAP_UNICODE) {
4793                 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4794                 name_len =
4795                     cifsConvertToUTF16((__le16 *) pSMB->RequestFileName,
4796                                        searchName, PATH_MAX, nls_codepage,
4797                                        remap);
4798                 name_len++;     /* trailing null */
4799                 name_len *= 2;
4800         } else {        /* BB improve the check for buffer overruns BB */
4801                 name_len = strnlen(searchName, PATH_MAX);
4802                 name_len++;     /* trailing null */
4803                 strncpy(pSMB->RequestFileName, searchName, name_len);
4804         }
4805
4806         if (ses->server) {
4807                 if (ses->server->sec_mode &
4808                    (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4809                         pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4810         }
4811
4812         pSMB->hdr.Uid = ses->Suid;
4813
4814         params = 2 /* level */  + name_len /*includes null */ ;
4815         pSMB->TotalDataCount = 0;
4816         pSMB->DataCount = 0;
4817         pSMB->DataOffset = 0;
4818         pSMB->MaxParameterCount = 0;
4819         /* BB find exact max SMB PDU from sess structure BB */
4820         pSMB->MaxDataCount = cpu_to_le16(4000);
4821         pSMB->MaxSetupCount = 0;
4822         pSMB->Reserved = 0;
4823         pSMB->Flags = 0;
4824         pSMB->Timeout = 0;
4825         pSMB->Reserved2 = 0;
4826         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4827           struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4828         pSMB->SetupCount = 1;
4829         pSMB->Reserved3 = 0;
4830         pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4831         byte_count = params + 3 /* pad */ ;
4832         pSMB->ParameterCount = cpu_to_le16(params);
4833         pSMB->TotalParameterCount = pSMB->ParameterCount;
4834         pSMB->MaxReferralLevel = cpu_to_le16(3);
4835         inc_rfc1001_len(pSMB, byte_count);
4836         pSMB->ByteCount = cpu_to_le16(byte_count);
4837
4838         rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4839                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4840         if (rc) {
4841                 cFYI(1, "Send error in GetDFSRefer = %d", rc);
4842                 goto GetDFSRefExit;
4843         }
4844         rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4845
4846         /* BB Also check if enough total bytes returned? */
4847         if (rc || get_bcc(&pSMBr->hdr) < 17) {
4848                 rc = -EIO;      /* bad smb */
4849                 goto GetDFSRefExit;
4850         }
4851
4852         cFYI(1, "Decoding GetDFSRefer response BCC: %d  Offset %d",
4853                                 get_bcc(&pSMBr->hdr),
4854                                 le16_to_cpu(pSMBr->t2.DataOffset));
4855
4856         /* parse returned result into more usable form */
4857         rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4858                                  target_nodes, nls_codepage, remap,
4859                                  searchName);
4860
4861 GetDFSRefExit:
4862         cifs_buf_release(pSMB);
4863
4864         if (rc == -EAGAIN)
4865                 goto getDFSRetry;
4866
4867         return rc;
4868 }
4869
4870 /* Query File System Info such as free space to old servers such as Win 9x */
4871 int
4872 SMBOldQFSInfo(const int xid, struct cifs_tcon *tcon, struct kstatfs *FSData)
4873 {
4874 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4875         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4876         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4877         FILE_SYSTEM_ALLOC_INFO *response_data;
4878         int rc = 0;
4879         int bytes_returned = 0;
4880         __u16 params, byte_count;
4881
4882         cFYI(1, "OldQFSInfo");
4883 oldQFSInfoRetry:
4884         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4885                 (void **) &pSMBr);
4886         if (rc)
4887                 return rc;
4888
4889         params = 2;     /* level */
4890         pSMB->TotalDataCount = 0;
4891         pSMB->MaxParameterCount = cpu_to_le16(2);
4892         pSMB->MaxDataCount = cpu_to_le16(1000);
4893         pSMB->MaxSetupCount = 0;
4894         pSMB->Reserved = 0;
4895         pSMB->Flags = 0;
4896         pSMB->Timeout = 0;
4897         pSMB->Reserved2 = 0;
4898         byte_count = params + 1 /* pad */ ;
4899         pSMB->TotalParameterCount = cpu_to_le16(params);
4900         pSMB->ParameterCount = pSMB->TotalParameterCount;
4901         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4902         struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4903         pSMB->DataCount = 0;
4904         pSMB->DataOffset = 0;
4905         pSMB->SetupCount = 1;
4906         pSMB->Reserved3 = 0;
4907         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4908         pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4909         inc_rfc1001_len(pSMB, byte_count);
4910         pSMB->ByteCount = cpu_to_le16(byte_count);
4911
4912         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4913                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4914         if (rc) {
4915                 cFYI(1, "Send error in QFSInfo = %d", rc);
4916         } else {                /* decode response */
4917                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4918
4919                 if (rc || get_bcc(&pSMBr->hdr) < 18)
4920                         rc = -EIO;      /* bad smb */
4921                 else {
4922                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4923                         cFYI(1, "qfsinf resp BCC: %d  Offset %d",
4924                                  get_bcc(&pSMBr->hdr), data_offset);
4925
4926                         response_data = (FILE_SYSTEM_ALLOC_INFO *)
4927                                 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4928                         FSData->f_bsize =
4929                                 le16_to_cpu(response_data->BytesPerSector) *
4930                                 le32_to_cpu(response_data->
4931                                         SectorsPerAllocationUnit);
4932                         FSData->f_blocks =
4933                                le32_to_cpu(response_data->TotalAllocationUnits);
4934                         FSData->f_bfree = FSData->f_bavail =
4935                                 le32_to_cpu(response_data->FreeAllocationUnits);
4936                         cFYI(1, "Blocks: %lld  Free: %lld Block size %ld",
4937                              (unsigned long long)FSData->f_blocks,
4938                              (unsigned long long)FSData->f_bfree,
4939                              FSData->f_bsize);
4940                 }
4941         }
4942         cifs_buf_release(pSMB);
4943
4944         if (rc == -EAGAIN)
4945                 goto oldQFSInfoRetry;
4946
4947         return rc;
4948 }
4949
4950 int
4951 CIFSSMBQFSInfo(const int xid, struct cifs_tcon *tcon, struct kstatfs *FSData)
4952 {
4953 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4954         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4955         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4956         FILE_SYSTEM_INFO *response_data;
4957         int rc = 0;
4958         int bytes_returned = 0;
4959         __u16 params, byte_count;
4960
4961         cFYI(1, "In QFSInfo");
4962 QFSInfoRetry:
4963         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4964                       (void **) &pSMBr);
4965         if (rc)
4966                 return rc;
4967
4968         params = 2;     /* level */
4969         pSMB->TotalDataCount = 0;
4970         pSMB->MaxParameterCount = cpu_to_le16(2);
4971         pSMB->MaxDataCount = cpu_to_le16(1000);
4972         pSMB->MaxSetupCount = 0;
4973         pSMB->Reserved = 0;
4974         pSMB->Flags = 0;
4975         pSMB->Timeout = 0;
4976         pSMB->Reserved2 = 0;
4977         byte_count = params + 1 /* pad */ ;
4978         pSMB->TotalParameterCount = cpu_to_le16(params);
4979         pSMB->ParameterCount = pSMB->TotalParameterCount;
4980         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4981                 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4982         pSMB->DataCount = 0;
4983         pSMB->DataOffset = 0;
4984         pSMB->SetupCount = 1;
4985         pSMB->Reserved3 = 0;
4986         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4987         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4988         inc_rfc1001_len(pSMB, byte_count);
4989         pSMB->ByteCount = cpu_to_le16(byte_count);
4990
4991         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4992                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4993         if (rc) {
4994                 cFYI(1, "Send error in QFSInfo = %d", rc);
4995         } else {                /* decode response */
4996                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4997
4998                 if (rc || get_bcc(&pSMBr->hdr) < 24)
4999                         rc = -EIO;      /* bad smb */
5000                 else {
5001                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5002
5003                         response_data =
5004                             (FILE_SYSTEM_INFO
5005                              *) (((char *) &pSMBr->hdr.Protocol) +
5006                                  data_offset);
5007                         FSData->f_bsize =
5008                             le32_to_cpu(response_data->BytesPerSector) *
5009                             le32_to_cpu(response_data->
5010                                         SectorsPerAllocationUnit);
5011                         FSData->f_blocks =
5012                             le64_to_cpu(response_data->TotalAllocationUnits);
5013                         FSData->f_bfree = FSData->f_bavail =
5014                             le64_to_cpu(response_data->FreeAllocationUnits);
5015                         cFYI(1, "Blocks: %lld  Free: %lld Block size %ld",
5016                              (unsigned long long)FSData->f_blocks,
5017                              (unsigned long long)FSData->f_bfree,
5018                              FSData->f_bsize);
5019                 }
5020         }
5021         cifs_buf_release(pSMB);
5022
5023         if (rc == -EAGAIN)
5024                 goto QFSInfoRetry;
5025
5026         return rc;
5027 }
5028
5029 int
5030 CIFSSMBQFSAttributeInfo(const int xid, struct cifs_tcon *tcon)
5031 {
5032 /* level 0x105  SMB_QUERY_FILE_SYSTEM_INFO */
5033         TRANSACTION2_QFSI_REQ *pSMB = NULL;
5034         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5035         FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
5036         int rc = 0;
5037         int bytes_returned = 0;
5038         __u16 params, byte_count;
5039
5040         cFYI(1, "In QFSAttributeInfo");
5041 QFSAttributeRetry:
5042         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5043                       (void **) &pSMBr);
5044         if (rc)
5045                 return rc;
5046
5047         params = 2;     /* level */
5048         pSMB->TotalDataCount = 0;
5049         pSMB->MaxParameterCount = cpu_to_le16(2);
5050         /* BB find exact max SMB PDU from sess structure BB */
5051         pSMB->MaxDataCount = cpu_to_le16(1000);
5052         pSMB->MaxSetupCount = 0;
5053         pSMB->Reserved = 0;
5054         pSMB->Flags = 0;
5055         pSMB->Timeout = 0;
5056         pSMB->Reserved2 = 0;
5057         byte_count = params + 1 /* pad */ ;
5058         pSMB->TotalParameterCount = cpu_to_le16(params);
5059         pSMB->ParameterCount = pSMB->TotalParameterCount;
5060         pSMB->ParameterOffset = cpu_to_le16(offsetof(
5061                 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5062         pSMB->DataCount = 0;
5063         pSMB->DataOffset = 0;
5064         pSMB->SetupCount = 1;
5065         pSMB->Reserved3 = 0;
5066         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5067         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
5068         inc_rfc1001_len(pSMB, byte_count);
5069         pSMB->ByteCount = cpu_to_le16(byte_count);
5070
5071         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5072                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5073         if (rc) {
5074                 cERROR(1, "Send error in QFSAttributeInfo = %d", rc);
5075         } else {                /* decode response */
5076                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5077
5078                 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5079                         /* BB also check if enough bytes returned */
5080                         rc = -EIO;      /* bad smb */
5081                 } else {
5082                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5083                         response_data =
5084                             (FILE_SYSTEM_ATTRIBUTE_INFO
5085                              *) (((char *) &pSMBr->hdr.Protocol) +
5086                                  data_offset);
5087                         memcpy(&tcon->fsAttrInfo, response_data,
5088                                sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
5089                 }
5090         }
5091         cifs_buf_release(pSMB);
5092
5093         if (rc == -EAGAIN)
5094                 goto QFSAttributeRetry;
5095
5096         return rc;
5097 }
5098
5099 int
5100 CIFSSMBQFSDeviceInfo(const int xid, struct cifs_tcon *tcon)
5101 {
5102 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
5103         TRANSACTION2_QFSI_REQ *pSMB = NULL;
5104         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5105         FILE_SYSTEM_DEVICE_INFO *response_data;
5106         int rc = 0;
5107         int bytes_returned = 0;
5108         __u16 params, byte_count;
5109
5110         cFYI(1, "In QFSDeviceInfo");
5111 QFSDeviceRetry:
5112         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5113                       (void **) &pSMBr);
5114         if (rc)
5115                 return rc;
5116
5117         params = 2;     /* level */
5118         pSMB->TotalDataCount = 0;
5119         pSMB->MaxParameterCount = cpu_to_le16(2);
5120         /* BB find exact max SMB PDU from sess structure BB */
5121         pSMB->MaxDataCount = cpu_to_le16(1000);
5122         pSMB->MaxSetupCount = 0;
5123         pSMB->Reserved = 0;
5124         pSMB->Flags = 0;
5125         pSMB->Timeout = 0;
5126         pSMB->Reserved2 = 0;
5127         byte_count = params + 1 /* pad */ ;
5128         pSMB->TotalParameterCount = cpu_to_le16(params);
5129         pSMB->ParameterCount = pSMB->TotalParameterCount;
5130         pSMB->ParameterOffset = cpu_to_le16(offsetof(
5131                 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5132
5133         pSMB->DataCount = 0;
5134         pSMB->DataOffset = 0;
5135         pSMB->SetupCount = 1;
5136         pSMB->Reserved3 = 0;
5137         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5138         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
5139         inc_rfc1001_len(pSMB, byte_count);
5140         pSMB->ByteCount = cpu_to_le16(byte_count);
5141
5142         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5143                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5144         if (rc) {
5145                 cFYI(1, "Send error in QFSDeviceInfo = %d", rc);
5146         } else {                /* decode response */
5147                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5148
5149                 if (rc || get_bcc(&pSMBr->hdr) <
5150                           sizeof(FILE_SYSTEM_DEVICE_INFO))
5151                         rc = -EIO;      /* bad smb */
5152                 else {
5153                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5154                         response_data =
5155                             (FILE_SYSTEM_DEVICE_INFO *)
5156                                 (((char *) &pSMBr->hdr.Protocol) +
5157                                  data_offset);
5158                         memcpy(&tcon->fsDevInfo, response_data,
5159                                sizeof(FILE_SYSTEM_DEVICE_INFO));
5160                 }
5161         }
5162         cifs_buf_release(pSMB);
5163
5164         if (rc == -EAGAIN)
5165                 goto QFSDeviceRetry;
5166
5167         return rc;
5168 }
5169
5170 int
5171 CIFSSMBQFSUnixInfo(const int xid, struct cifs_tcon *tcon)
5172 {
5173 /* level 0x200  SMB_QUERY_CIFS_UNIX_INFO */
5174         TRANSACTION2_QFSI_REQ *pSMB = NULL;
5175         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5176         FILE_SYSTEM_UNIX_INFO *response_data;
5177         int rc = 0;
5178         int bytes_returned = 0;
5179         __u16 params, byte_count;
5180
5181         cFYI(1, "In QFSUnixInfo");
5182 QFSUnixRetry:
5183         rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5184                                    (void **) &pSMB, (void **) &pSMBr);
5185         if (rc)
5186                 return rc;
5187
5188         params = 2;     /* level */
5189         pSMB->TotalDataCount = 0;
5190         pSMB->DataCount = 0;
5191         pSMB->DataOffset = 0;
5192         pSMB->MaxParameterCount = cpu_to_le16(2);
5193         /* BB find exact max SMB PDU from sess structure BB */
5194         pSMB->MaxDataCount = cpu_to_le16(100);
5195         pSMB->MaxSetupCount = 0;
5196         pSMB->Reserved = 0;
5197         pSMB->Flags = 0;
5198         pSMB->Timeout = 0;
5199         pSMB->Reserved2 = 0;
5200         byte_count = params + 1 /* pad */ ;
5201         pSMB->ParameterCount = cpu_to_le16(params);
5202         pSMB->TotalParameterCount = pSMB->ParameterCount;
5203         pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5204                         smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5205         pSMB->SetupCount = 1;
5206         pSMB->Reserved3 = 0;
5207         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5208         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
5209         inc_rfc1001_len(pSMB, byte_count);
5210         pSMB->ByteCount = cpu_to_le16(byte_count);
5211
5212         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5213                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5214         if (rc) {
5215                 cERROR(1, "Send error in QFSUnixInfo = %d", rc);
5216         } else {                /* decode response */
5217                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5218
5219                 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5220                         rc = -EIO;      /* bad smb */
5221                 } else {
5222                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5223                         response_data =
5224                             (FILE_SYSTEM_UNIX_INFO
5225                              *) (((char *) &pSMBr->hdr.Protocol) +
5226                                  data_offset);
5227                         memcpy(&tcon->fsUnixInfo, response_data,
5228                                sizeof(FILE_SYSTEM_UNIX_INFO));
5229                 }
5230         }
5231         cifs_buf_release(pSMB);
5232
5233         if (rc == -EAGAIN)
5234                 goto QFSUnixRetry;
5235
5236
5237         return rc;
5238 }
5239
5240 int
5241 CIFSSMBSetFSUnixInfo(const int xid, struct cifs_tcon *tcon, __u64 cap)
5242 {
5243 /* level 0x200  SMB_SET_CIFS_UNIX_INFO */
5244         TRANSACTION2_SETFSI_REQ *pSMB = NULL;
5245         TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
5246         int rc = 0;
5247         int bytes_returned = 0;
5248         __u16 params, param_offset, offset, byte_count;
5249
5250         cFYI(1, "In SETFSUnixInfo");
5251 SETFSUnixRetry:
5252         /* BB switch to small buf init to save memory */
5253         rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5254                                         (void **) &pSMB, (void **) &pSMBr);
5255         if (rc)
5256                 return rc;
5257
5258         params = 4;     /* 2 bytes zero followed by info level. */
5259         pSMB->MaxSetupCount = 0;
5260         pSMB->Reserved = 0;
5261         pSMB->Flags = 0;
5262         pSMB->Timeout = 0;
5263         pSMB->Reserved2 = 0;
5264         param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
5265                                 - 4;
5266         offset = param_offset + params;
5267
5268         pSMB->MaxParameterCount = cpu_to_le16(4);
5269         /* BB find exact max SMB PDU from sess structure BB */
5270         pSMB->MaxDataCount = cpu_to_le16(100);
5271         pSMB->SetupCount = 1;
5272         pSMB->Reserved3 = 0;
5273         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
5274         byte_count = 1 /* pad */ + params + 12;
5275
5276         pSMB->DataCount = cpu_to_le16(12);
5277         pSMB->ParameterCount = cpu_to_le16(params);
5278         pSMB->TotalDataCount = pSMB->DataCount;
5279         pSMB->TotalParameterCount = pSMB->ParameterCount;
5280         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5281         pSMB->DataOffset = cpu_to_le16(offset);
5282
5283         /* Params. */
5284         pSMB->FileNum = 0;
5285         pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
5286
5287         /* Data. */
5288         pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
5289         pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
5290         pSMB->ClientUnixCap = cpu_to_le64(cap);
5291
5292         inc_rfc1001_len(pSMB, byte_count);
5293         pSMB->ByteCount = cpu_to_le16(byte_count);
5294
5295         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5296                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5297         if (rc) {
5298                 cERROR(1, "Send error in SETFSUnixInfo = %d", rc);
5299         } else {                /* decode response */
5300                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5301                 if (rc)
5302                         rc = -EIO;      /* bad smb */
5303         }
5304         cifs_buf_release(pSMB);
5305
5306         if (rc == -EAGAIN)
5307                 goto SETFSUnixRetry;
5308
5309         return rc;
5310 }
5311
5312
5313
5314 int
5315 CIFSSMBQFSPosixInfo(const int xid, struct cifs_tcon *tcon,
5316                    struct kstatfs *FSData)
5317 {
5318 /* level 0x201  SMB_QUERY_CIFS_POSIX_INFO */
5319         TRANSACTION2_QFSI_REQ *pSMB = NULL;
5320         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5321         FILE_SYSTEM_POSIX_INFO *response_data;
5322         int rc = 0;
5323         int bytes_returned = 0;
5324         __u16 params, byte_count;
5325
5326         cFYI(1, "In QFSPosixInfo");
5327 QFSPosixRetry:
5328         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5329                       (void **) &pSMBr);
5330         if (rc)
5331                 return rc;
5332
5333         params = 2;     /* level */
5334         pSMB->TotalDataCount = 0;
5335         pSMB->DataCount = 0;
5336         pSMB->DataOffset = 0;
5337         pSMB->MaxParameterCount = cpu_to_le16(2);
5338         /* BB find exact max SMB PDU from sess structure BB */
5339         pSMB->MaxDataCount = cpu_to_le16(100);
5340         pSMB->MaxSetupCount = 0;
5341         pSMB->Reserved = 0;
5342         pSMB->Flags = 0;
5343         pSMB->Timeout = 0;
5344         pSMB->Reserved2 = 0;
5345         byte_count = params + 1 /* pad */ ;
5346         pSMB->ParameterCount = cpu_to_le16(params);
5347         pSMB->TotalParameterCount = pSMB->ParameterCount;
5348         pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5349                         smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5350         pSMB->SetupCount = 1;
5351         pSMB->Reserved3 = 0;
5352         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5353         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
5354         inc_rfc1001_len(pSMB, byte_count);
5355         pSMB->ByteCount = cpu_to_le16(byte_count);
5356
5357         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5358                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5359         if (rc) {
5360                 cFYI(1, "Send error in QFSUnixInfo = %d", rc);
5361         } else {                /* decode response */
5362                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5363
5364                 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5365                         rc = -EIO;      /* bad smb */
5366                 } else {
5367                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5368                         response_data =
5369                             (FILE_SYSTEM_POSIX_INFO
5370                              *) (((char *) &pSMBr->hdr.Protocol) +
5371                                  data_offset);
5372                         FSData->f_bsize =
5373                                         le32_to_cpu(response_data->BlockSize);
5374                         FSData->f_blocks =
5375                                         le64_to_cpu(response_data->TotalBlocks);
5376                         FSData->f_bfree =
5377                             le64_to_cpu(response_data->BlocksAvail);
5378                         if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
5379                                 FSData->f_bavail = FSData->f_bfree;
5380                         } else {
5381                                 FSData->f_bavail =
5382                                     le64_to_cpu(response_data->UserBlocksAvail);
5383                         }
5384                         if (response_data->TotalFileNodes != cpu_to_le64(-1))
5385                                 FSData->f_files =
5386                                      le64_to_cpu(response_data->TotalFileNodes);
5387                         if (response_data->FreeFileNodes != cpu_to_le64(-1))
5388                                 FSData->f_ffree =
5389                                       le64_to_cpu(response_data->FreeFileNodes);
5390                 }
5391         }
5392         cifs_buf_release(pSMB);
5393
5394         if (rc == -EAGAIN)
5395                 goto QFSPosixRetry;
5396
5397         return rc;
5398 }
5399
5400
5401 /* We can not use write of zero bytes trick to
5402    set file size due to need for large file support.  Also note that
5403    this SetPathInfo is preferred to SetFileInfo based method in next
5404    routine which is only needed to work around a sharing violation bug
5405    in Samba which this routine can run into */
5406
5407 int
5408 CIFSSMBSetEOF(const int xid, struct cifs_tcon *tcon, const char *fileName,
5409               __u64 size, bool SetAllocation,
5410               const struct nls_table *nls_codepage, int remap)
5411 {
5412         struct smb_com_transaction2_spi_req *pSMB = NULL;
5413         struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5414         struct file_end_of_file_info *parm_data;
5415         int name_len;
5416         int rc = 0;
5417         int bytes_returned = 0;
5418         __u16 params, byte_count, data_count, param_offset, offset;
5419
5420         cFYI(1, "In SetEOF");
5421 SetEOFRetry:
5422         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5423                       (void **) &pSMBr);
5424         if (rc)
5425                 return rc;
5426
5427         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5428                 name_len =
5429                     cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
5430                                        PATH_MAX, nls_codepage, remap);
5431                 name_len++;     /* trailing null */
5432                 name_len *= 2;
5433         } else {        /* BB improve the check for buffer overruns BB */
5434                 name_len = strnlen(fileName, PATH_MAX);
5435                 name_len++;     /* trailing null */
5436                 strncpy(pSMB->FileName, fileName, name_len);
5437         }
5438         params = 6 + name_len;
5439         data_count = sizeof(struct file_end_of_file_info);
5440         pSMB->MaxParameterCount = cpu_to_le16(2);
5441         pSMB->MaxDataCount = cpu_to_le16(4100);
5442         pSMB->MaxSetupCount = 0;
5443         pSMB->Reserved = 0;
5444         pSMB->Flags = 0;
5445         pSMB->Timeout = 0;
5446         pSMB->Reserved2 = 0;
5447         param_offset = offsetof(struct smb_com_transaction2_spi_req,
5448                                 InformationLevel) - 4;
5449         offset = param_offset + params;
5450         if (SetAllocation) {
5451                 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5452                         pSMB->InformationLevel =
5453                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5454                 else
5455                         pSMB->InformationLevel =
5456                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5457         } else /* Set File Size */  {
5458             if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5459                     pSMB->InformationLevel =
5460                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5461             else
5462                     pSMB->InformationLevel =
5463                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5464         }
5465
5466         parm_data =
5467             (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
5468                                        offset);
5469         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5470         pSMB->DataOffset = cpu_to_le16(offset);
5471         pSMB->SetupCount = 1;
5472         pSMB->Reserved3 = 0;
5473         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5474         byte_count = 3 /* pad */  + params + data_count;
5475         pSMB->DataCount = cpu_to_le16(data_count);
5476         pSMB->TotalDataCount = pSMB->DataCount;
5477         pSMB->ParameterCount = cpu_to_le16(params);
5478         pSMB->TotalParameterCount = pSMB->ParameterCount;
5479         pSMB->Reserved4 = 0;
5480         inc_rfc1001_len(pSMB, byte_count);
5481         parm_data->FileSize = cpu_to_le64(size);
5482         pSMB->ByteCount = cpu_to_le16(byte_count);
5483         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5484                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5485         if (rc)
5486                 cFYI(1, "SetPathInfo (file size) returned %d", rc);
5487
5488         cifs_buf_release(pSMB);
5489
5490         if (rc == -EAGAIN)
5491                 goto SetEOFRetry;
5492
5493         return rc;
5494 }
5495
5496 int
5497 CIFSSMBSetFileSize(const int xid, struct cifs_tcon *tcon, __u64 size,
5498                    __u16 fid, __u32 pid_of_opener, bool SetAllocation)
5499 {
5500         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5501         struct file_end_of_file_info *parm_data;
5502         int rc = 0;
5503         __u16 params, param_offset, offset, byte_count, count;
5504
5505         cFYI(1, "SetFileSize (via SetFileInfo) %lld",
5506                         (long long)size);
5507         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5508
5509         if (rc)
5510                 return rc;
5511
5512         pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5513         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5514
5515         params = 6;
5516         pSMB->MaxSetupCount = 0;
5517         pSMB->Reserved = 0;
5518         pSMB->Flags = 0;
5519         pSMB->Timeout = 0;
5520         pSMB->Reserved2 = 0;
5521         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5522         offset = param_offset + params;
5523
5524         count = sizeof(struct file_end_of_file_info);
5525         pSMB->MaxParameterCount = cpu_to_le16(2);
5526         /* BB find exact max SMB PDU from sess structure BB */
5527         pSMB->MaxDataCount = cpu_to_le16(1000);
5528         pSMB->SetupCount = 1;
5529         pSMB->Reserved3 = 0;
5530         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5531         byte_count = 3 /* pad */  + params + count;
5532         pSMB->DataCount = cpu_to_le16(count);
5533         pSMB->ParameterCount = cpu_to_le16(params);
5534         pSMB->TotalDataCount = pSMB->DataCount;
5535         pSMB->TotalParameterCount = pSMB->ParameterCount;
5536         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5537         parm_data =
5538                 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
5539                                 + offset);
5540         pSMB->DataOffset = cpu_to_le16(offset);
5541         parm_data->FileSize = cpu_to_le64(size);
5542         pSMB->Fid = fid;
5543         if (SetAllocation) {
5544                 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5545                         pSMB->InformationLevel =
5546                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5547                 else
5548                         pSMB->InformationLevel =
5549                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5550         } else /* Set File Size */  {
5551             if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5552                     pSMB->InformationLevel =
5553                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5554             else
5555                     pSMB->InformationLevel =
5556                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5557         }
5558         pSMB->Reserved4 = 0;
5559         inc_rfc1001_len(pSMB, byte_count);
5560         pSMB->ByteCount = cpu_to_le16(byte_count);
5561         rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5562         if (rc) {
5563                 cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc);
5564         }
5565
5566         /* Note: On -EAGAIN error only caller can retry on handle based calls
5567                 since file handle passed in no longer valid */
5568
5569         return rc;
5570 }
5571
5572 /* Some legacy servers such as NT4 require that the file times be set on
5573    an open handle, rather than by pathname - this is awkward due to
5574    potential access conflicts on the open, but it is unavoidable for these
5575    old servers since the only other choice is to go from 100 nanosecond DCE
5576    time and resort to the original setpathinfo level which takes the ancient
5577    DOS time format with 2 second granularity */
5578 int
5579 CIFSSMBSetFileInfo(const int xid, struct cifs_tcon *tcon,
5580                     const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
5581 {
5582         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5583         char *data_offset;
5584         int rc = 0;
5585         __u16 params, param_offset, offset, byte_count, count;
5586
5587         cFYI(1, "Set Times (via SetFileInfo)");
5588         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5589
5590         if (rc)
5591                 return rc;
5592
5593         pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5594         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5595
5596         params = 6;
5597         pSMB->MaxSetupCount = 0;
5598         pSMB->Reserved = 0;
5599         pSMB->Flags = 0;
5600         pSMB->Timeout = 0;
5601         pSMB->Reserved2 = 0;
5602         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5603         offset = param_offset + params;
5604
5605         data_offset = (char *)pSMB +
5606                         offsetof(struct smb_hdr, Protocol) + offset;
5607
5608         count = sizeof(FILE_BASIC_INFO);
5609         pSMB->MaxParameterCount = cpu_to_le16(2);
5610         /* BB find max SMB PDU from sess */
5611         pSMB->MaxDataCount = cpu_to_le16(1000);
5612         pSMB->SetupCount = 1;
5613         pSMB->Reserved3 = 0;
5614         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5615         byte_count = 3 /* pad */  + params + count;
5616         pSMB->DataCount = cpu_to_le16(count);
5617         pSMB->ParameterCount = cpu_to_le16(params);
5618         pSMB->TotalDataCount = pSMB->DataCount;
5619         pSMB->TotalParameterCount = pSMB->ParameterCount;
5620         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5621         pSMB->DataOffset = cpu_to_le16(offset);
5622         pSMB->Fid = fid;
5623         if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5624                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5625         else
5626                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5627         pSMB->Reserved4 = 0;
5628         inc_rfc1001_len(pSMB, byte_count);
5629         pSMB->ByteCount = cpu_to_le16(byte_count);
5630         memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5631         rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5632         if (rc)
5633                 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
5634
5635         /* Note: On -EAGAIN error only caller can retry on handle based calls
5636                 since file handle passed in no longer valid */
5637
5638         return rc;
5639 }
5640
5641 int
5642 CIFSSMBSetFileDisposition(const int xid, struct cifs_tcon *tcon,
5643                           bool delete_file, __u16 fid, __u32 pid_of_opener)
5644 {
5645         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5646         char *data_offset;
5647         int rc = 0;
5648         __u16 params, param_offset, offset, byte_count, count;
5649
5650         cFYI(1, "Set File Disposition (via SetFileInfo)");
5651         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5652
5653         if (rc)
5654                 return rc;
5655
5656         pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5657         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5658
5659         params = 6;
5660         pSMB->MaxSetupCount = 0;
5661         pSMB->Reserved = 0;
5662         pSMB->Flags = 0;
5663         pSMB->Timeout = 0;
5664         pSMB->Reserved2 = 0;
5665         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5666         offset = param_offset + params;
5667
5668         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5669
5670         count = 1;
5671         pSMB->MaxParameterCount = cpu_to_le16(2);
5672         /* BB find max SMB PDU from sess */
5673         pSMB->MaxDataCount = cpu_to_le16(1000);
5674         pSMB->SetupCount = 1;
5675         pSMB->Reserved3 = 0;
5676         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5677         byte_count = 3 /* pad */  + params + count;
5678         pSMB->DataCount = cpu_to_le16(count);
5679         pSMB->ParameterCount = cpu_to_le16(params);
5680         pSMB->TotalDataCount = pSMB->DataCount;
5681         pSMB->TotalParameterCount = pSMB->ParameterCount;
5682         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5683         pSMB->DataOffset = cpu_to_le16(offset);
5684         pSMB->Fid = fid;
5685         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
5686         pSMB->Reserved4 = 0;
5687         inc_rfc1001_len(pSMB, byte_count);
5688         pSMB->ByteCount = cpu_to_le16(byte_count);
5689         *data_offset = delete_file ? 1 : 0;
5690         rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5691         if (rc)
5692                 cFYI(1, "Send error in SetFileDisposition = %d", rc);
5693
5694         return rc;
5695 }
5696