]> Pileus Git - ~andy/linux/blob - fs/cifs/cifssmb.c
Merge branch 'upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/floppy...
[~andy/linux] / 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                 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         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         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(server)));
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 int
1415 cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1416 {
1417         int length, len;
1418         unsigned int data_offset, data_len;
1419         struct cifs_readdata *rdata = mid->callback_data;
1420         char *buf = server->smallbuf;
1421         unsigned int buflen = get_rfc1002_length(buf) + 4;
1422
1423         cFYI(1, "%s: mid=%llu offset=%llu bytes=%u", __func__,
1424                 mid->mid, rdata->offset, rdata->bytes);
1425
1426         /*
1427          * read the rest of READ_RSP header (sans Data array), or whatever we
1428          * can if there's not enough data. At this point, we've read down to
1429          * the Mid.
1430          */
1431         len = min_t(unsigned int, buflen, server->vals->read_rsp_size) -
1432                                                         HEADER_SIZE(server) + 1;
1433
1434         rdata->iov[0].iov_base = buf + HEADER_SIZE(server) - 1;
1435         rdata->iov[0].iov_len = len;
1436
1437         length = cifs_readv_from_socket(server, rdata->iov, 1, len);
1438         if (length < 0)
1439                 return length;
1440         server->total_read += length;
1441
1442         /* Was the SMB read successful? */
1443         rdata->result = server->ops->map_error(buf, false);
1444         if (rdata->result != 0) {
1445                 cFYI(1, "%s: server returned error %d", __func__,
1446                         rdata->result);
1447                 return cifs_readv_discard(server, mid);
1448         }
1449
1450         /* Is there enough to get to the rest of the READ_RSP header? */
1451         if (server->total_read < server->vals->read_rsp_size) {
1452                 cFYI(1, "%s: server returned short header. got=%u expected=%zu",
1453                         __func__, server->total_read,
1454                         server->vals->read_rsp_size);
1455                 rdata->result = -EIO;
1456                 return cifs_readv_discard(server, mid);
1457         }
1458
1459         data_offset = server->ops->read_data_offset(buf) + 4;
1460         if (data_offset < server->total_read) {
1461                 /*
1462                  * win2k8 sometimes sends an offset of 0 when the read
1463                  * is beyond the EOF. Treat it as if the data starts just after
1464                  * the header.
1465                  */
1466                 cFYI(1, "%s: data offset (%u) inside read response header",
1467                         __func__, data_offset);
1468                 data_offset = server->total_read;
1469         } else if (data_offset > MAX_CIFS_SMALL_BUFFER_SIZE) {
1470                 /* data_offset is beyond the end of smallbuf */
1471                 cFYI(1, "%s: data offset (%u) beyond end of smallbuf",
1472                         __func__, data_offset);
1473                 rdata->result = -EIO;
1474                 return cifs_readv_discard(server, mid);
1475         }
1476
1477         cFYI(1, "%s: total_read=%u data_offset=%u", __func__,
1478                 server->total_read, data_offset);
1479
1480         len = data_offset - server->total_read;
1481         if (len > 0) {
1482                 /* read any junk before data into the rest of smallbuf */
1483                 rdata->iov[0].iov_base = buf + server->total_read;
1484                 rdata->iov[0].iov_len = len;
1485                 length = cifs_readv_from_socket(server, rdata->iov, 1, len);
1486                 if (length < 0)
1487                         return length;
1488                 server->total_read += length;
1489         }
1490
1491         /* set up first iov for signature check */
1492         rdata->iov[0].iov_base = buf;
1493         rdata->iov[0].iov_len = server->total_read;
1494         cFYI(1, "0: iov_base=%p iov_len=%zu",
1495                 rdata->iov[0].iov_base, rdata->iov[0].iov_len);
1496
1497         /* how much data is in the response? */
1498         data_len = server->ops->read_data_length(buf);
1499         if (data_offset + data_len > buflen) {
1500                 /* data_len is corrupt -- discard frame */
1501                 rdata->result = -EIO;
1502                 return cifs_readv_discard(server, mid);
1503         }
1504
1505         /* marshal up the page array */
1506         len = rdata->marshal_iov(rdata, data_len);
1507         data_len -= len;
1508
1509         /* issue the read if we have any iovecs left to fill */
1510         if (rdata->nr_iov > 1) {
1511                 length = cifs_readv_from_socket(server, &rdata->iov[1],
1512                                                 rdata->nr_iov - 1, len);
1513                 if (length < 0)
1514                         return length;
1515                 server->total_read += length;
1516         } else {
1517                 length = 0;
1518         }
1519
1520         rdata->bytes = length;
1521
1522         cFYI(1, "total_read=%u buflen=%u remaining=%u", server->total_read,
1523                 buflen, data_len);
1524
1525         /* discard anything left over */
1526         if (server->total_read < buflen)
1527                 return cifs_readv_discard(server, mid);
1528
1529         dequeue_mid(mid, false);
1530         return length;
1531 }
1532
1533 static void
1534 cifs_readv_callback(struct mid_q_entry *mid)
1535 {
1536         struct cifs_readdata *rdata = mid->callback_data;
1537         struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1538         struct TCP_Server_Info *server = tcon->ses->server;
1539
1540         cFYI(1, "%s: mid=%llu state=%d result=%d bytes=%u", __func__,
1541                 mid->mid, mid->mid_state, rdata->result, rdata->bytes);
1542
1543         switch (mid->mid_state) {
1544         case MID_RESPONSE_RECEIVED:
1545                 /* result already set, check signature */
1546                 if (server->sec_mode &
1547                     (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
1548                         if (cifs_verify_signature(rdata->iov, rdata->nr_iov,
1549                                           server, mid->sequence_number + 1))
1550                                 cERROR(1, "Unexpected SMB signature");
1551                 }
1552                 /* FIXME: should this be counted toward the initiating task? */
1553                 task_io_account_read(rdata->bytes);
1554                 cifs_stats_bytes_read(tcon, rdata->bytes);
1555                 break;
1556         case MID_REQUEST_SUBMITTED:
1557         case MID_RETRY_NEEDED:
1558                 rdata->result = -EAGAIN;
1559                 break;
1560         default:
1561                 rdata->result = -EIO;
1562         }
1563
1564         queue_work(cifsiod_wq, &rdata->work);
1565         DeleteMidQEntry(mid);
1566         add_credits(server, 1);
1567 }
1568
1569 /* cifs_async_readv - send an async write, and set up mid to handle result */
1570 int
1571 cifs_async_readv(struct cifs_readdata *rdata)
1572 {
1573         int rc;
1574         READ_REQ *smb = NULL;
1575         int wct;
1576         struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
1577
1578         cFYI(1, "%s: offset=%llu bytes=%u", __func__,
1579                 rdata->offset, rdata->bytes);
1580
1581         if (tcon->ses->capabilities & CAP_LARGE_FILES)
1582                 wct = 12;
1583         else {
1584                 wct = 10; /* old style read */
1585                 if ((rdata->offset >> 32) > 0)  {
1586                         /* can not handle this big offset for old */
1587                         return -EIO;
1588                 }
1589         }
1590
1591         rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **)&smb);
1592         if (rc)
1593                 return rc;
1594
1595         smb->hdr.Pid = cpu_to_le16((__u16)rdata->pid);
1596         smb->hdr.PidHigh = cpu_to_le16((__u16)(rdata->pid >> 16));
1597
1598         smb->AndXCommand = 0xFF;        /* none */
1599         smb->Fid = rdata->cfile->netfid;
1600         smb->OffsetLow = cpu_to_le32(rdata->offset & 0xFFFFFFFF);
1601         if (wct == 12)
1602                 smb->OffsetHigh = cpu_to_le32(rdata->offset >> 32);
1603         smb->Remaining = 0;
1604         smb->MaxCount = cpu_to_le16(rdata->bytes & 0xFFFF);
1605         smb->MaxCountHigh = cpu_to_le32(rdata->bytes >> 16);
1606         if (wct == 12)
1607                 smb->ByteCount = 0;
1608         else {
1609                 /* old style read */
1610                 struct smb_com_readx_req *smbr =
1611                         (struct smb_com_readx_req *)smb;
1612                 smbr->ByteCount = 0;
1613         }
1614
1615         /* 4 for RFC1001 length + 1 for BCC */
1616         rdata->iov[0].iov_base = smb;
1617         rdata->iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4;
1618
1619         kref_get(&rdata->refcount);
1620         rc = cifs_call_async(tcon->ses->server, rdata->iov, 1,
1621                              cifs_readv_receive, cifs_readv_callback,
1622                              rdata, false);
1623
1624         if (rc == 0)
1625                 cifs_stats_inc(&tcon->num_reads);
1626         else
1627                 kref_put(&rdata->refcount, cifs_readdata_release);
1628
1629         cifs_small_buf_release(smb);
1630         return rc;
1631 }
1632
1633 int
1634 CIFSSMBRead(const int xid, struct cifs_io_parms *io_parms, unsigned int *nbytes,
1635             char **buf, int *pbuf_type)
1636 {
1637         int rc = -EACCES;
1638         READ_REQ *pSMB = NULL;
1639         READ_RSP *pSMBr = NULL;
1640         char *pReadData = NULL;
1641         int wct;
1642         int resp_buf_type = 0;
1643         struct kvec iov[1];
1644         __u32 pid = io_parms->pid;
1645         __u16 netfid = io_parms->netfid;
1646         __u64 offset = io_parms->offset;
1647         struct cifs_tcon *tcon = io_parms->tcon;
1648         unsigned int count = io_parms->length;
1649
1650         cFYI(1, "Reading %d bytes on fid %d", count, netfid);
1651         if (tcon->ses->capabilities & CAP_LARGE_FILES)
1652                 wct = 12;
1653         else {
1654                 wct = 10; /* old style read */
1655                 if ((offset >> 32) > 0)  {
1656                         /* can not handle this big offset for old */
1657                         return -EIO;
1658                 }
1659         }
1660
1661         *nbytes = 0;
1662         rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1663         if (rc)
1664                 return rc;
1665
1666         pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1667         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1668
1669         /* tcon and ses pointer are checked in smb_init */
1670         if (tcon->ses->server == NULL)
1671                 return -ECONNABORTED;
1672
1673         pSMB->AndXCommand = 0xFF;       /* none */
1674         pSMB->Fid = netfid;
1675         pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1676         if (wct == 12)
1677                 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1678
1679         pSMB->Remaining = 0;
1680         pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1681         pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1682         if (wct == 12)
1683                 pSMB->ByteCount = 0;  /* no need to do le conversion since 0 */
1684         else {
1685                 /* old style read */
1686                 struct smb_com_readx_req *pSMBW =
1687                         (struct smb_com_readx_req *)pSMB;
1688                 pSMBW->ByteCount = 0;
1689         }
1690
1691         iov[0].iov_base = (char *)pSMB;
1692         iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
1693         rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1694                          &resp_buf_type, CIFS_LOG_ERROR);
1695         cifs_stats_inc(&tcon->num_reads);
1696         pSMBr = (READ_RSP *)iov[0].iov_base;
1697         if (rc) {
1698                 cERROR(1, "Send error in read = %d", rc);
1699         } else {
1700                 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1701                 data_length = data_length << 16;
1702                 data_length += le16_to_cpu(pSMBr->DataLength);
1703                 *nbytes = data_length;
1704
1705                 /*check that DataLength would not go beyond end of SMB */
1706                 if ((data_length > CIFSMaxBufSize)
1707                                 || (data_length > count)) {
1708                         cFYI(1, "bad length %d for count %d",
1709                                  data_length, count);
1710                         rc = -EIO;
1711                         *nbytes = 0;
1712                 } else {
1713                         pReadData = (char *) (&pSMBr->hdr.Protocol) +
1714                                         le16_to_cpu(pSMBr->DataOffset);
1715 /*                      if (rc = copy_to_user(buf, pReadData, data_length)) {
1716                                 cERROR(1, "Faulting on read rc = %d",rc);
1717                                 rc = -EFAULT;
1718                         }*/ /* can not use copy_to_user when using page cache*/
1719                         if (*buf)
1720                                 memcpy(*buf, pReadData, data_length);
1721                 }
1722         }
1723
1724 /*      cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1725         if (*buf) {
1726                 if (resp_buf_type == CIFS_SMALL_BUFFER)
1727                         cifs_small_buf_release(iov[0].iov_base);
1728                 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1729                         cifs_buf_release(iov[0].iov_base);
1730         } else if (resp_buf_type != CIFS_NO_BUFFER) {
1731                 /* return buffer to caller to free */
1732                 *buf = iov[0].iov_base;
1733                 if (resp_buf_type == CIFS_SMALL_BUFFER)
1734                         *pbuf_type = CIFS_SMALL_BUFFER;
1735                 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1736                         *pbuf_type = CIFS_LARGE_BUFFER;
1737         } /* else no valid buffer on return - leave as null */
1738
1739         /* Note: On -EAGAIN error only caller can retry on handle based calls
1740                 since file handle passed in no longer valid */
1741         return rc;
1742 }
1743
1744
1745 int
1746 CIFSSMBWrite(const int xid, struct cifs_io_parms *io_parms,
1747              unsigned int *nbytes, const char *buf,
1748              const char __user *ubuf, const int long_op)
1749 {
1750         int rc = -EACCES;
1751         WRITE_REQ *pSMB = NULL;
1752         WRITE_RSP *pSMBr = NULL;
1753         int bytes_returned, wct;
1754         __u32 bytes_sent;
1755         __u16 byte_count;
1756         __u32 pid = io_parms->pid;
1757         __u16 netfid = io_parms->netfid;
1758         __u64 offset = io_parms->offset;
1759         struct cifs_tcon *tcon = io_parms->tcon;
1760         unsigned int count = io_parms->length;
1761
1762         *nbytes = 0;
1763
1764         /* cFYI(1, "write at %lld %d bytes", offset, count);*/
1765         if (tcon->ses == NULL)
1766                 return -ECONNABORTED;
1767
1768         if (tcon->ses->capabilities & CAP_LARGE_FILES)
1769                 wct = 14;
1770         else {
1771                 wct = 12;
1772                 if ((offset >> 32) > 0) {
1773                         /* can not handle big offset for old srv */
1774                         return -EIO;
1775                 }
1776         }
1777
1778         rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1779                       (void **) &pSMBr);
1780         if (rc)
1781                 return rc;
1782
1783         pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1784         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1785
1786         /* tcon and ses pointer are checked in smb_init */
1787         if (tcon->ses->server == NULL)
1788                 return -ECONNABORTED;
1789
1790         pSMB->AndXCommand = 0xFF;       /* none */
1791         pSMB->Fid = netfid;
1792         pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1793         if (wct == 14)
1794                 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1795
1796         pSMB->Reserved = 0xFFFFFFFF;
1797         pSMB->WriteMode = 0;
1798         pSMB->Remaining = 0;
1799
1800         /* Can increase buffer size if buffer is big enough in some cases ie we
1801         can send more if LARGE_WRITE_X capability returned by the server and if
1802         our buffer is big enough or if we convert to iovecs on socket writes
1803         and eliminate the copy to the CIFS buffer */
1804         if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1805                 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1806         } else {
1807                 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1808                          & ~0xFF;
1809         }
1810
1811         if (bytes_sent > count)
1812                 bytes_sent = count;
1813         pSMB->DataOffset =
1814                 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1815         if (buf)
1816                 memcpy(pSMB->Data, buf, bytes_sent);
1817         else if (ubuf) {
1818                 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1819                         cifs_buf_release(pSMB);
1820                         return -EFAULT;
1821                 }
1822         } else if (count != 0) {
1823                 /* No buffer */
1824                 cifs_buf_release(pSMB);
1825                 return -EINVAL;
1826         } /* else setting file size with write of zero bytes */
1827         if (wct == 14)
1828                 byte_count = bytes_sent + 1; /* pad */
1829         else /* wct == 12 */
1830                 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1831
1832         pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1833         pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1834         inc_rfc1001_len(pSMB, byte_count);
1835
1836         if (wct == 14)
1837                 pSMB->ByteCount = cpu_to_le16(byte_count);
1838         else { /* old style write has byte count 4 bytes earlier
1839                   so 4 bytes pad  */
1840                 struct smb_com_writex_req *pSMBW =
1841                         (struct smb_com_writex_req *)pSMB;
1842                 pSMBW->ByteCount = cpu_to_le16(byte_count);
1843         }
1844
1845         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1846                          (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1847         cifs_stats_inc(&tcon->num_writes);
1848         if (rc) {
1849                 cFYI(1, "Send error in write = %d", rc);
1850         } else {
1851                 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1852                 *nbytes = (*nbytes) << 16;
1853                 *nbytes += le16_to_cpu(pSMBr->Count);
1854
1855                 /*
1856                  * Mask off high 16 bits when bytes written as returned by the
1857                  * server is greater than bytes requested by the client. Some
1858                  * OS/2 servers are known to set incorrect CountHigh values.
1859                  */
1860                 if (*nbytes > count)
1861                         *nbytes &= 0xFFFF;
1862         }
1863
1864         cifs_buf_release(pSMB);
1865
1866         /* Note: On -EAGAIN error only caller can retry on handle based calls
1867                 since file handle passed in no longer valid */
1868
1869         return rc;
1870 }
1871
1872 void
1873 cifs_writedata_release(struct kref *refcount)
1874 {
1875         struct cifs_writedata *wdata = container_of(refcount,
1876                                         struct cifs_writedata, refcount);
1877
1878         if (wdata->cfile)
1879                 cifsFileInfo_put(wdata->cfile);
1880
1881         kfree(wdata);
1882 }
1883
1884 /*
1885  * Write failed with a retryable error. Resend the write request. It's also
1886  * possible that the page was redirtied so re-clean the page.
1887  */
1888 static void
1889 cifs_writev_requeue(struct cifs_writedata *wdata)
1890 {
1891         int i, rc;
1892         struct inode *inode = wdata->cfile->dentry->d_inode;
1893
1894         for (i = 0; i < wdata->nr_pages; i++) {
1895                 lock_page(wdata->pages[i]);
1896                 clear_page_dirty_for_io(wdata->pages[i]);
1897         }
1898
1899         do {
1900                 rc = cifs_async_writev(wdata);
1901         } while (rc == -EAGAIN);
1902
1903         for (i = 0; i < wdata->nr_pages; i++) {
1904                 if (rc != 0)
1905                         SetPageError(wdata->pages[i]);
1906                 unlock_page(wdata->pages[i]);
1907         }
1908
1909         mapping_set_error(inode->i_mapping, rc);
1910         kref_put(&wdata->refcount, cifs_writedata_release);
1911 }
1912
1913 void
1914 cifs_writev_complete(struct work_struct *work)
1915 {
1916         struct cifs_writedata *wdata = container_of(work,
1917                                                 struct cifs_writedata, work);
1918         struct inode *inode = wdata->cfile->dentry->d_inode;
1919         int i = 0;
1920
1921         if (wdata->result == 0) {
1922                 spin_lock(&inode->i_lock);
1923                 cifs_update_eof(CIFS_I(inode), wdata->offset, wdata->bytes);
1924                 spin_unlock(&inode->i_lock);
1925                 cifs_stats_bytes_written(tlink_tcon(wdata->cfile->tlink),
1926                                          wdata->bytes);
1927         } else if (wdata->sync_mode == WB_SYNC_ALL && wdata->result == -EAGAIN)
1928                 return cifs_writev_requeue(wdata);
1929
1930         for (i = 0; i < wdata->nr_pages; i++) {
1931                 struct page *page = wdata->pages[i];
1932                 if (wdata->result == -EAGAIN)
1933                         __set_page_dirty_nobuffers(page);
1934                 else if (wdata->result < 0)
1935                         SetPageError(page);
1936                 end_page_writeback(page);
1937                 page_cache_release(page);
1938         }
1939         if (wdata->result != -EAGAIN)
1940                 mapping_set_error(inode->i_mapping, wdata->result);
1941         kref_put(&wdata->refcount, cifs_writedata_release);
1942 }
1943
1944 struct cifs_writedata *
1945 cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete)
1946 {
1947         struct cifs_writedata *wdata;
1948
1949         /* this would overflow */
1950         if (nr_pages == 0) {
1951                 cERROR(1, "%s: called with nr_pages == 0!", __func__);
1952                 return NULL;
1953         }
1954
1955         /* writedata + number of page pointers */
1956         wdata = kzalloc(sizeof(*wdata) +
1957                         sizeof(struct page *) * (nr_pages - 1), GFP_NOFS);
1958         if (wdata != NULL) {
1959                 kref_init(&wdata->refcount);
1960                 INIT_LIST_HEAD(&wdata->list);
1961                 init_completion(&wdata->done);
1962                 INIT_WORK(&wdata->work, complete);
1963         }
1964         return wdata;
1965 }
1966
1967 /*
1968  * Check the mid_state and signature on received buffer (if any), and queue the
1969  * workqueue completion task.
1970  */
1971 static void
1972 cifs_writev_callback(struct mid_q_entry *mid)
1973 {
1974         struct cifs_writedata *wdata = mid->callback_data;
1975         struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
1976         unsigned int written;
1977         WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
1978
1979         switch (mid->mid_state) {
1980         case MID_RESPONSE_RECEIVED:
1981                 wdata->result = cifs_check_receive(mid, tcon->ses->server, 0);
1982                 if (wdata->result != 0)
1983                         break;
1984
1985                 written = le16_to_cpu(smb->CountHigh);
1986                 written <<= 16;
1987                 written += le16_to_cpu(smb->Count);
1988                 /*
1989                  * Mask off high 16 bits when bytes written as returned
1990                  * by the server is greater than bytes requested by the
1991                  * client. OS/2 servers are known to set incorrect
1992                  * CountHigh values.
1993                  */
1994                 if (written > wdata->bytes)
1995                         written &= 0xFFFF;
1996
1997                 if (written < wdata->bytes)
1998                         wdata->result = -ENOSPC;
1999                 else
2000                         wdata->bytes = written;
2001                 break;
2002         case MID_REQUEST_SUBMITTED:
2003         case MID_RETRY_NEEDED:
2004                 wdata->result = -EAGAIN;
2005                 break;
2006         default:
2007                 wdata->result = -EIO;
2008                 break;
2009         }
2010
2011         queue_work(cifsiod_wq, &wdata->work);
2012         DeleteMidQEntry(mid);
2013         add_credits(tcon->ses->server, 1);
2014 }
2015
2016 /* cifs_async_writev - send an async write, and set up mid to handle result */
2017 int
2018 cifs_async_writev(struct cifs_writedata *wdata)
2019 {
2020         int i, rc = -EACCES;
2021         WRITE_REQ *smb = NULL;
2022         int wct;
2023         struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
2024         struct kvec *iov = NULL;
2025
2026         if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2027                 wct = 14;
2028         } else {
2029                 wct = 12;
2030                 if (wdata->offset >> 32 > 0) {
2031                         /* can not handle big offset for old srv */
2032                         return -EIO;
2033                 }
2034         }
2035
2036         rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **)&smb);
2037         if (rc)
2038                 goto async_writev_out;
2039
2040         /* 1 iov per page + 1 for header */
2041         iov = kzalloc((wdata->nr_pages + 1) * sizeof(*iov), GFP_NOFS);
2042         if (iov == NULL) {
2043                 rc = -ENOMEM;
2044                 goto async_writev_out;
2045         }
2046
2047         smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid);
2048         smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16));
2049
2050         smb->AndXCommand = 0xFF;        /* none */
2051         smb->Fid = wdata->cfile->netfid;
2052         smb->OffsetLow = cpu_to_le32(wdata->offset & 0xFFFFFFFF);
2053         if (wct == 14)
2054                 smb->OffsetHigh = cpu_to_le32(wdata->offset >> 32);
2055         smb->Reserved = 0xFFFFFFFF;
2056         smb->WriteMode = 0;
2057         smb->Remaining = 0;
2058
2059         smb->DataOffset =
2060             cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2061
2062         /* 4 for RFC1001 length + 1 for BCC */
2063         iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1;
2064         iov[0].iov_base = smb;
2065
2066         /*
2067          * This function should marshal up the page array into the kvec
2068          * array, reserving [0] for the header. It should kmap the pages
2069          * and set the iov_len properly for each one. It may also set
2070          * wdata->bytes too.
2071          */
2072         wdata->marshal_iov(iov, wdata);
2073
2074         cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes);
2075
2076         smb->DataLengthLow = cpu_to_le16(wdata->bytes & 0xFFFF);
2077         smb->DataLengthHigh = cpu_to_le16(wdata->bytes >> 16);
2078
2079         if (wct == 14) {
2080                 inc_rfc1001_len(&smb->hdr, wdata->bytes + 1);
2081                 put_bcc(wdata->bytes + 1, &smb->hdr);
2082         } else {
2083                 /* wct == 12 */
2084                 struct smb_com_writex_req *smbw =
2085                                 (struct smb_com_writex_req *)smb;
2086                 inc_rfc1001_len(&smbw->hdr, wdata->bytes + 5);
2087                 put_bcc(wdata->bytes + 5, &smbw->hdr);
2088                 iov[0].iov_len += 4; /* pad bigger by four bytes */
2089         }
2090
2091         kref_get(&wdata->refcount);
2092         rc = cifs_call_async(tcon->ses->server, iov, wdata->nr_pages + 1,
2093                              NULL, cifs_writev_callback, wdata, false);
2094
2095         if (rc == 0)
2096                 cifs_stats_inc(&tcon->num_writes);
2097         else
2098                 kref_put(&wdata->refcount, cifs_writedata_release);
2099
2100         /* send is done, unmap pages */
2101         for (i = 0; i < wdata->nr_pages; i++)
2102                 kunmap(wdata->pages[i]);
2103
2104 async_writev_out:
2105         cifs_small_buf_release(smb);
2106         kfree(iov);
2107         return rc;
2108 }
2109
2110 int
2111 CIFSSMBWrite2(const int xid, struct cifs_io_parms *io_parms,
2112               unsigned int *nbytes, struct kvec *iov, int n_vec,
2113               const int long_op)
2114 {
2115         int rc = -EACCES;
2116         WRITE_REQ *pSMB = NULL;
2117         int wct;
2118         int smb_hdr_len;
2119         int resp_buf_type = 0;
2120         __u32 pid = io_parms->pid;
2121         __u16 netfid = io_parms->netfid;
2122         __u64 offset = io_parms->offset;
2123         struct cifs_tcon *tcon = io_parms->tcon;
2124         unsigned int count = io_parms->length;
2125
2126         *nbytes = 0;
2127
2128         cFYI(1, "write2 at %lld %d bytes", (long long)offset, count);
2129
2130         if (tcon->ses->capabilities & CAP_LARGE_FILES) {
2131                 wct = 14;
2132         } else {
2133                 wct = 12;
2134                 if ((offset >> 32) > 0) {
2135                         /* can not handle big offset for old srv */
2136                         return -EIO;
2137                 }
2138         }
2139         rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
2140         if (rc)
2141                 return rc;
2142
2143         pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
2144         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
2145
2146         /* tcon and ses pointer are checked in smb_init */
2147         if (tcon->ses->server == NULL)
2148                 return -ECONNABORTED;
2149
2150         pSMB->AndXCommand = 0xFF;       /* none */
2151         pSMB->Fid = netfid;
2152         pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
2153         if (wct == 14)
2154                 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
2155         pSMB->Reserved = 0xFFFFFFFF;
2156         pSMB->WriteMode = 0;
2157         pSMB->Remaining = 0;
2158
2159         pSMB->DataOffset =
2160             cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
2161
2162         pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
2163         pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
2164         /* header + 1 byte pad */
2165         smb_hdr_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 1;
2166         if (wct == 14)
2167                 inc_rfc1001_len(pSMB, count + 1);
2168         else /* wct == 12 */
2169                 inc_rfc1001_len(pSMB, count + 5); /* smb data starts later */
2170         if (wct == 14)
2171                 pSMB->ByteCount = cpu_to_le16(count + 1);
2172         else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
2173                 struct smb_com_writex_req *pSMBW =
2174                                 (struct smb_com_writex_req *)pSMB;
2175                 pSMBW->ByteCount = cpu_to_le16(count + 5);
2176         }
2177         iov[0].iov_base = pSMB;
2178         if (wct == 14)
2179                 iov[0].iov_len = smb_hdr_len + 4;
2180         else /* wct == 12 pad bigger by four bytes */
2181                 iov[0].iov_len = smb_hdr_len + 8;
2182
2183
2184         rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
2185                           long_op);
2186         cifs_stats_inc(&tcon->num_writes);
2187         if (rc) {
2188                 cFYI(1, "Send error Write2 = %d", rc);
2189         } else if (resp_buf_type == 0) {
2190                 /* presumably this can not happen, but best to be safe */
2191                 rc = -EIO;
2192         } else {
2193                 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
2194                 *nbytes = le16_to_cpu(pSMBr->CountHigh);
2195                 *nbytes = (*nbytes) << 16;
2196                 *nbytes += le16_to_cpu(pSMBr->Count);
2197
2198                 /*
2199                  * Mask off high 16 bits when bytes written as returned by the
2200                  * server is greater than bytes requested by the client. OS/2
2201                  * servers are known to set incorrect CountHigh values.
2202                  */
2203                 if (*nbytes > count)
2204                         *nbytes &= 0xFFFF;
2205         }
2206
2207 /*      cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
2208         if (resp_buf_type == CIFS_SMALL_BUFFER)
2209                 cifs_small_buf_release(iov[0].iov_base);
2210         else if (resp_buf_type == CIFS_LARGE_BUFFER)
2211                 cifs_buf_release(iov[0].iov_base);
2212
2213         /* Note: On -EAGAIN error only caller can retry on handle based calls
2214                 since file handle passed in no longer valid */
2215
2216         return rc;
2217 }
2218
2219 int cifs_lockv(const int xid, struct cifs_tcon *tcon, const __u16 netfid,
2220                const __u8 lock_type, const __u32 num_unlock,
2221                const __u32 num_lock, LOCKING_ANDX_RANGE *buf)
2222 {
2223         int rc = 0;
2224         LOCK_REQ *pSMB = NULL;
2225         struct kvec iov[2];
2226         int resp_buf_type;
2227         __u16 count;
2228
2229         cFYI(1, "cifs_lockv num lock %d num unlock %d", num_lock, num_unlock);
2230
2231         rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2232         if (rc)
2233                 return rc;
2234
2235         pSMB->Timeout = 0;
2236         pSMB->NumberOfLocks = cpu_to_le16(num_lock);
2237         pSMB->NumberOfUnlocks = cpu_to_le16(num_unlock);
2238         pSMB->LockType = lock_type;
2239         pSMB->AndXCommand = 0xFF; /* none */
2240         pSMB->Fid = netfid; /* netfid stays le */
2241
2242         count = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2243         inc_rfc1001_len(pSMB, count);
2244         pSMB->ByteCount = cpu_to_le16(count);
2245
2246         iov[0].iov_base = (char *)pSMB;
2247         iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4 -
2248                          (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2249         iov[1].iov_base = (char *)buf;
2250         iov[1].iov_len = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE);
2251
2252         cifs_stats_inc(&tcon->num_locks);
2253         rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type, CIFS_NO_RESP);
2254         if (rc)
2255                 cFYI(1, "Send error in cifs_lockv = %d", rc);
2256
2257         return rc;
2258 }
2259
2260 int
2261 CIFSSMBLock(const int xid, struct cifs_tcon *tcon,
2262             const __u16 smb_file_id, const __u32 netpid, const __u64 len,
2263             const __u64 offset, const __u32 numUnlock,
2264             const __u32 numLock, const __u8 lockType,
2265             const bool waitFlag, const __u8 oplock_level)
2266 {
2267         int rc = 0;
2268         LOCK_REQ *pSMB = NULL;
2269 /*      LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
2270         int bytes_returned;
2271         int timeout = 0;
2272         __u16 count;
2273
2274         cFYI(1, "CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock);
2275         rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
2276
2277         if (rc)
2278                 return rc;
2279
2280         if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
2281                 timeout = CIFS_ASYNC_OP; /* no response expected */
2282                 pSMB->Timeout = 0;
2283         } else if (waitFlag) {
2284                 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2285                 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
2286         } else {
2287                 pSMB->Timeout = 0;
2288         }
2289
2290         pSMB->NumberOfLocks = cpu_to_le16(numLock);
2291         pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
2292         pSMB->LockType = lockType;
2293         pSMB->OplockLevel = oplock_level;
2294         pSMB->AndXCommand = 0xFF;       /* none */
2295         pSMB->Fid = smb_file_id; /* netfid stays le */
2296
2297         if ((numLock != 0) || (numUnlock != 0)) {
2298                 pSMB->Locks[0].Pid = cpu_to_le16(netpid);
2299                 /* BB where to store pid high? */
2300                 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
2301                 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
2302                 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
2303                 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
2304                 count = sizeof(LOCKING_ANDX_RANGE);
2305         } else {
2306                 /* oplock break */
2307                 count = 0;
2308         }
2309         inc_rfc1001_len(pSMB, count);
2310         pSMB->ByteCount = cpu_to_le16(count);
2311
2312         if (waitFlag) {
2313                 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2314                         (struct smb_hdr *) pSMB, &bytes_returned);
2315                 cifs_small_buf_release(pSMB);
2316         } else {
2317                 rc = SendReceiveNoRsp(xid, tcon->ses, (char *)pSMB, timeout);
2318                 /* SMB buffer freed by function above */
2319         }
2320         cifs_stats_inc(&tcon->num_locks);
2321         if (rc)
2322                 cFYI(1, "Send error in Lock = %d", rc);
2323
2324         /* Note: On -EAGAIN error only caller can retry on handle based calls
2325         since file handle passed in no longer valid */
2326         return rc;
2327 }
2328
2329 int
2330 CIFSSMBPosixLock(const int xid, struct cifs_tcon *tcon,
2331                 const __u16 smb_file_id, const __u32 netpid, const int get_flag,
2332                 const __u64 len, struct file_lock *pLockData,
2333                 const __u16 lock_type, const bool waitFlag)
2334 {
2335         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
2336         struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2337         struct cifs_posix_lock *parm_data;
2338         int rc = 0;
2339         int timeout = 0;
2340         int bytes_returned = 0;
2341         int resp_buf_type = 0;
2342         __u16 params, param_offset, offset, byte_count, count;
2343         struct kvec iov[1];
2344
2345         cFYI(1, "Posix Lock");
2346
2347         if (pLockData == NULL)
2348                 return -EINVAL;
2349
2350         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
2351
2352         if (rc)
2353                 return rc;
2354
2355         pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
2356
2357         params = 6;
2358         pSMB->MaxSetupCount = 0;
2359         pSMB->Reserved = 0;
2360         pSMB->Flags = 0;
2361         pSMB->Reserved2 = 0;
2362         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2363         offset = param_offset + params;
2364
2365         count = sizeof(struct cifs_posix_lock);
2366         pSMB->MaxParameterCount = cpu_to_le16(2);
2367         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2368         pSMB->SetupCount = 1;
2369         pSMB->Reserved3 = 0;
2370         if (get_flag)
2371                 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2372         else
2373                 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2374         byte_count = 3 /* pad */  + params + count;
2375         pSMB->DataCount = cpu_to_le16(count);
2376         pSMB->ParameterCount = cpu_to_le16(params);
2377         pSMB->TotalDataCount = pSMB->DataCount;
2378         pSMB->TotalParameterCount = pSMB->ParameterCount;
2379         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2380         parm_data = (struct cifs_posix_lock *)
2381                         (((char *) &pSMB->hdr.Protocol) + offset);
2382
2383         parm_data->lock_type = cpu_to_le16(lock_type);
2384         if (waitFlag) {
2385                 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
2386                 parm_data->lock_flags = cpu_to_le16(1);
2387                 pSMB->Timeout = cpu_to_le32(-1);
2388         } else
2389                 pSMB->Timeout = 0;
2390
2391         parm_data->pid = cpu_to_le32(netpid);
2392         parm_data->start = cpu_to_le64(pLockData->fl_start);
2393         parm_data->length = cpu_to_le64(len);  /* normalize negative numbers */
2394
2395         pSMB->DataOffset = cpu_to_le16(offset);
2396         pSMB->Fid = smb_file_id;
2397         pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
2398         pSMB->Reserved4 = 0;
2399         inc_rfc1001_len(pSMB, byte_count);
2400         pSMB->ByteCount = cpu_to_le16(byte_count);
2401         if (waitFlag) {
2402                 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
2403                         (struct smb_hdr *) pSMBr, &bytes_returned);
2404         } else {
2405                 iov[0].iov_base = (char *)pSMB;
2406                 iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
2407                 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
2408                                 &resp_buf_type, timeout);
2409                 pSMB = NULL; /* request buf already freed by SendReceive2. Do
2410                                 not try to free it twice below on exit */
2411                 pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
2412         }
2413
2414         if (rc) {
2415                 cFYI(1, "Send error in Posix Lock = %d", rc);
2416         } else if (get_flag) {
2417                 /* lock structure can be returned on get */
2418                 __u16 data_offset;
2419                 __u16 data_count;
2420                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2421
2422                 if (rc || get_bcc(&pSMBr->hdr) < sizeof(*parm_data)) {
2423                         rc = -EIO;      /* bad smb */
2424                         goto plk_err_exit;
2425                 }
2426                 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2427                 data_count  = le16_to_cpu(pSMBr->t2.DataCount);
2428                 if (data_count < sizeof(struct cifs_posix_lock)) {
2429                         rc = -EIO;
2430                         goto plk_err_exit;
2431                 }
2432                 parm_data = (struct cifs_posix_lock *)
2433                         ((char *)&pSMBr->hdr.Protocol + data_offset);
2434                 if (parm_data->lock_type == __constant_cpu_to_le16(CIFS_UNLCK))
2435                         pLockData->fl_type = F_UNLCK;
2436                 else {
2437                         if (parm_data->lock_type ==
2438                                         __constant_cpu_to_le16(CIFS_RDLCK))
2439                                 pLockData->fl_type = F_RDLCK;
2440                         else if (parm_data->lock_type ==
2441                                         __constant_cpu_to_le16(CIFS_WRLCK))
2442                                 pLockData->fl_type = F_WRLCK;
2443
2444                         pLockData->fl_start = le64_to_cpu(parm_data->start);
2445                         pLockData->fl_end = pLockData->fl_start +
2446                                         le64_to_cpu(parm_data->length) - 1;
2447                         pLockData->fl_pid = le32_to_cpu(parm_data->pid);
2448                 }
2449         }
2450
2451 plk_err_exit:
2452         if (pSMB)
2453                 cifs_small_buf_release(pSMB);
2454
2455         if (resp_buf_type == CIFS_SMALL_BUFFER)
2456                 cifs_small_buf_release(iov[0].iov_base);
2457         else if (resp_buf_type == CIFS_LARGE_BUFFER)
2458                 cifs_buf_release(iov[0].iov_base);
2459
2460         /* Note: On -EAGAIN error only caller can retry on handle based calls
2461            since file handle passed in no longer valid */
2462
2463         return rc;
2464 }
2465
2466
2467 int
2468 CIFSSMBClose(const int xid, struct cifs_tcon *tcon, int smb_file_id)
2469 {
2470         int rc = 0;
2471         CLOSE_REQ *pSMB = NULL;
2472         cFYI(1, "In CIFSSMBClose");
2473
2474 /* do not retry on dead session on close */
2475         rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
2476         if (rc == -EAGAIN)
2477                 return 0;
2478         if (rc)
2479                 return rc;
2480
2481         pSMB->FileID = (__u16) smb_file_id;
2482         pSMB->LastWriteTime = 0xFFFFFFFF;
2483         pSMB->ByteCount = 0;
2484         rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2485         cifs_stats_inc(&tcon->num_closes);
2486         if (rc) {
2487                 if (rc != -EINTR) {
2488                         /* EINTR is expected when user ctl-c to kill app */
2489                         cERROR(1, "Send error in Close = %d", rc);
2490                 }
2491         }
2492
2493         /* Since session is dead, file will be closed on server already */
2494         if (rc == -EAGAIN)
2495                 rc = 0;
2496
2497         return rc;
2498 }
2499
2500 int
2501 CIFSSMBFlush(const int xid, struct cifs_tcon *tcon, int smb_file_id)
2502 {
2503         int rc = 0;
2504         FLUSH_REQ *pSMB = NULL;
2505         cFYI(1, "In CIFSSMBFlush");
2506
2507         rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
2508         if (rc)
2509                 return rc;
2510
2511         pSMB->FileID = (__u16) smb_file_id;
2512         pSMB->ByteCount = 0;
2513         rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
2514         cifs_stats_inc(&tcon->num_flushes);
2515         if (rc)
2516                 cERROR(1, "Send error in Flush = %d", rc);
2517
2518         return rc;
2519 }
2520
2521 int
2522 CIFSSMBRename(const int xid, struct cifs_tcon *tcon,
2523               const char *fromName, const char *toName,
2524               const struct nls_table *nls_codepage, int remap)
2525 {
2526         int rc = 0;
2527         RENAME_REQ *pSMB = NULL;
2528         RENAME_RSP *pSMBr = NULL;
2529         int bytes_returned;
2530         int name_len, name_len2;
2531         __u16 count;
2532
2533         cFYI(1, "In CIFSSMBRename");
2534 renameRetry:
2535         rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
2536                       (void **) &pSMBr);
2537         if (rc)
2538                 return rc;
2539
2540         pSMB->BufferFormat = 0x04;
2541         pSMB->SearchAttributes =
2542             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2543                         ATTR_DIRECTORY);
2544
2545         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2546                 name_len =
2547                     cifsConvertToUTF16((__le16 *) pSMB->OldFileName, fromName,
2548                                        PATH_MAX, nls_codepage, remap);
2549                 name_len++;     /* trailing null */
2550                 name_len *= 2;
2551                 pSMB->OldFileName[name_len] = 0x04;     /* pad */
2552         /* protocol requires ASCII signature byte on Unicode string */
2553                 pSMB->OldFileName[name_len + 1] = 0x00;
2554                 name_len2 =
2555                     cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2556                                        toName, PATH_MAX, nls_codepage, remap);
2557                 name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2558                 name_len2 *= 2; /* convert to bytes */
2559         } else {        /* BB improve the check for buffer overruns BB */
2560                 name_len = strnlen(fromName, PATH_MAX);
2561                 name_len++;     /* trailing null */
2562                 strncpy(pSMB->OldFileName, fromName, name_len);
2563                 name_len2 = strnlen(toName, PATH_MAX);
2564                 name_len2++;    /* trailing null */
2565                 pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
2566                 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2567                 name_len2++;    /* trailing null */
2568                 name_len2++;    /* signature byte */
2569         }
2570
2571         count = 1 /* 1st signature byte */  + name_len + name_len2;
2572         inc_rfc1001_len(pSMB, count);
2573         pSMB->ByteCount = cpu_to_le16(count);
2574
2575         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2576                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2577         cifs_stats_inc(&tcon->num_renames);
2578         if (rc)
2579                 cFYI(1, "Send error in rename = %d", rc);
2580
2581         cifs_buf_release(pSMB);
2582
2583         if (rc == -EAGAIN)
2584                 goto renameRetry;
2585
2586         return rc;
2587 }
2588
2589 int CIFSSMBRenameOpenFile(const int xid, struct cifs_tcon *pTcon,
2590                 int netfid, const char *target_name,
2591                 const struct nls_table *nls_codepage, int remap)
2592 {
2593         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
2594         struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2595         struct set_file_rename *rename_info;
2596         char *data_offset;
2597         char dummy_string[30];
2598         int rc = 0;
2599         int bytes_returned = 0;
2600         int len_of_str;
2601         __u16 params, param_offset, offset, count, byte_count;
2602
2603         cFYI(1, "Rename to File by handle");
2604         rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2605                         (void **) &pSMBr);
2606         if (rc)
2607                 return rc;
2608
2609         params = 6;
2610         pSMB->MaxSetupCount = 0;
2611         pSMB->Reserved = 0;
2612         pSMB->Flags = 0;
2613         pSMB->Timeout = 0;
2614         pSMB->Reserved2 = 0;
2615         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2616         offset = param_offset + params;
2617
2618         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2619         rename_info = (struct set_file_rename *) data_offset;
2620         pSMB->MaxParameterCount = cpu_to_le16(2);
2621         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2622         pSMB->SetupCount = 1;
2623         pSMB->Reserved3 = 0;
2624         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2625         byte_count = 3 /* pad */  + params;
2626         pSMB->ParameterCount = cpu_to_le16(params);
2627         pSMB->TotalParameterCount = pSMB->ParameterCount;
2628         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2629         pSMB->DataOffset = cpu_to_le16(offset);
2630         /* construct random name ".cifs_tmp<inodenum><mid>" */
2631         rename_info->overwrite = cpu_to_le32(1);
2632         rename_info->root_fid  = 0;
2633         /* unicode only call */
2634         if (target_name == NULL) {
2635                 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2636                 len_of_str =
2637                         cifsConvertToUTF16((__le16 *)rename_info->target_name,
2638                                         dummy_string, 24, nls_codepage, remap);
2639         } else {
2640                 len_of_str =
2641                         cifsConvertToUTF16((__le16 *)rename_info->target_name,
2642                                         target_name, PATH_MAX, nls_codepage,
2643                                         remap);
2644         }
2645         rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2646         count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2647         byte_count += count;
2648         pSMB->DataCount = cpu_to_le16(count);
2649         pSMB->TotalDataCount = pSMB->DataCount;
2650         pSMB->Fid = netfid;
2651         pSMB->InformationLevel =
2652                 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2653         pSMB->Reserved4 = 0;
2654         inc_rfc1001_len(pSMB, byte_count);
2655         pSMB->ByteCount = cpu_to_le16(byte_count);
2656         rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2657                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2658         cifs_stats_inc(&pTcon->num_t2renames);
2659         if (rc)
2660                 cFYI(1, "Send error in Rename (by file handle) = %d", rc);
2661
2662         cifs_buf_release(pSMB);
2663
2664         /* Note: On -EAGAIN error only caller can retry on handle based calls
2665                 since file handle passed in no longer valid */
2666
2667         return rc;
2668 }
2669
2670 int
2671 CIFSSMBCopy(const int xid, struct cifs_tcon *tcon, const char *fromName,
2672             const __u16 target_tid, const char *toName, const int flags,
2673             const struct nls_table *nls_codepage, int remap)
2674 {
2675         int rc = 0;
2676         COPY_REQ *pSMB = NULL;
2677         COPY_RSP *pSMBr = NULL;
2678         int bytes_returned;
2679         int name_len, name_len2;
2680         __u16 count;
2681
2682         cFYI(1, "In CIFSSMBCopy");
2683 copyRetry:
2684         rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2685                         (void **) &pSMBr);
2686         if (rc)
2687                 return rc;
2688
2689         pSMB->BufferFormat = 0x04;
2690         pSMB->Tid2 = target_tid;
2691
2692         pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2693
2694         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2695                 name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
2696                                               fromName, PATH_MAX, nls_codepage,
2697                                               remap);
2698                 name_len++;     /* trailing null */
2699                 name_len *= 2;
2700                 pSMB->OldFileName[name_len] = 0x04;     /* pad */
2701                 /* protocol requires ASCII signature byte on Unicode string */
2702                 pSMB->OldFileName[name_len + 1] = 0x00;
2703                 name_len2 =
2704                     cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2705                                        toName, PATH_MAX, nls_codepage, remap);
2706                 name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2707                 name_len2 *= 2; /* convert to bytes */
2708         } else {        /* BB improve the check for buffer overruns BB */
2709                 name_len = strnlen(fromName, PATH_MAX);
2710                 name_len++;     /* trailing null */
2711                 strncpy(pSMB->OldFileName, fromName, name_len);
2712                 name_len2 = strnlen(toName, PATH_MAX);
2713                 name_len2++;    /* trailing null */
2714                 pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
2715                 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2716                 name_len2++;    /* trailing null */
2717                 name_len2++;    /* signature byte */
2718         }
2719
2720         count = 1 /* 1st signature byte */  + name_len + name_len2;
2721         inc_rfc1001_len(pSMB, count);
2722         pSMB->ByteCount = cpu_to_le16(count);
2723
2724         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2725                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2726         if (rc) {
2727                 cFYI(1, "Send error in copy = %d with %d files copied",
2728                         rc, le16_to_cpu(pSMBr->CopyCount));
2729         }
2730         cifs_buf_release(pSMB);
2731
2732         if (rc == -EAGAIN)
2733                 goto copyRetry;
2734
2735         return rc;
2736 }
2737
2738 int
2739 CIFSUnixCreateSymLink(const int xid, struct cifs_tcon *tcon,
2740                       const char *fromName, const char *toName,
2741                       const struct nls_table *nls_codepage)
2742 {
2743         TRANSACTION2_SPI_REQ *pSMB = NULL;
2744         TRANSACTION2_SPI_RSP *pSMBr = NULL;
2745         char *data_offset;
2746         int name_len;
2747         int name_len_target;
2748         int rc = 0;
2749         int bytes_returned = 0;
2750         __u16 params, param_offset, offset, byte_count;
2751
2752         cFYI(1, "In Symlink Unix style");
2753 createSymLinkRetry:
2754         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2755                       (void **) &pSMBr);
2756         if (rc)
2757                 return rc;
2758
2759         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2760                 name_len =
2761                     cifs_strtoUTF16((__le16 *) pSMB->FileName, fromName,
2762                                     /* find define for this maxpathcomponent */
2763                                     PATH_MAX, nls_codepage);
2764                 name_len++;     /* trailing null */
2765                 name_len *= 2;
2766
2767         } else {        /* BB improve the check for buffer overruns BB */
2768                 name_len = strnlen(fromName, PATH_MAX);
2769                 name_len++;     /* trailing null */
2770                 strncpy(pSMB->FileName, fromName, name_len);
2771         }
2772         params = 6 + name_len;
2773         pSMB->MaxSetupCount = 0;
2774         pSMB->Reserved = 0;
2775         pSMB->Flags = 0;
2776         pSMB->Timeout = 0;
2777         pSMB->Reserved2 = 0;
2778         param_offset = offsetof(struct smb_com_transaction2_spi_req,
2779                                 InformationLevel) - 4;
2780         offset = param_offset + params;
2781
2782         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2783         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2784                 name_len_target =
2785                     cifs_strtoUTF16((__le16 *) data_offset, toName, PATH_MAX
2786                                     /* find define for this maxpathcomponent */
2787                                     , nls_codepage);
2788                 name_len_target++;      /* trailing null */
2789                 name_len_target *= 2;
2790         } else {        /* BB improve the check for buffer overruns BB */
2791                 name_len_target = strnlen(toName, PATH_MAX);
2792                 name_len_target++;      /* trailing null */
2793                 strncpy(data_offset, toName, name_len_target);
2794         }
2795
2796         pSMB->MaxParameterCount = cpu_to_le16(2);
2797         /* BB find exact max on data count below from sess */
2798         pSMB->MaxDataCount = cpu_to_le16(1000);
2799         pSMB->SetupCount = 1;
2800         pSMB->Reserved3 = 0;
2801         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2802         byte_count = 3 /* pad */  + params + name_len_target;
2803         pSMB->DataCount = cpu_to_le16(name_len_target);
2804         pSMB->ParameterCount = cpu_to_le16(params);
2805         pSMB->TotalDataCount = pSMB->DataCount;
2806         pSMB->TotalParameterCount = pSMB->ParameterCount;
2807         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2808         pSMB->DataOffset = cpu_to_le16(offset);
2809         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2810         pSMB->Reserved4 = 0;
2811         inc_rfc1001_len(pSMB, byte_count);
2812         pSMB->ByteCount = cpu_to_le16(byte_count);
2813         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2814                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2815         cifs_stats_inc(&tcon->num_symlinks);
2816         if (rc)
2817                 cFYI(1, "Send error in SetPathInfo create symlink = %d", rc);
2818
2819         cifs_buf_release(pSMB);
2820
2821         if (rc == -EAGAIN)
2822                 goto createSymLinkRetry;
2823
2824         return rc;
2825 }
2826
2827 int
2828 CIFSUnixCreateHardLink(const int xid, struct cifs_tcon *tcon,
2829                        const char *fromName, const char *toName,
2830                        const struct nls_table *nls_codepage, int remap)
2831 {
2832         TRANSACTION2_SPI_REQ *pSMB = NULL;
2833         TRANSACTION2_SPI_RSP *pSMBr = NULL;
2834         char *data_offset;
2835         int name_len;
2836         int name_len_target;
2837         int rc = 0;
2838         int bytes_returned = 0;
2839         __u16 params, param_offset, offset, byte_count;
2840
2841         cFYI(1, "In Create Hard link Unix style");
2842 createHardLinkRetry:
2843         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2844                       (void **) &pSMBr);
2845         if (rc)
2846                 return rc;
2847
2848         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2849                 name_len = cifsConvertToUTF16((__le16 *) pSMB->FileName, toName,
2850                                               PATH_MAX, nls_codepage, remap);
2851                 name_len++;     /* trailing null */
2852                 name_len *= 2;
2853
2854         } else {        /* BB improve the check for buffer overruns BB */
2855                 name_len = strnlen(toName, PATH_MAX);
2856                 name_len++;     /* trailing null */
2857                 strncpy(pSMB->FileName, toName, name_len);
2858         }
2859         params = 6 + name_len;
2860         pSMB->MaxSetupCount = 0;
2861         pSMB->Reserved = 0;
2862         pSMB->Flags = 0;
2863         pSMB->Timeout = 0;
2864         pSMB->Reserved2 = 0;
2865         param_offset = offsetof(struct smb_com_transaction2_spi_req,
2866                                 InformationLevel) - 4;
2867         offset = param_offset + params;
2868
2869         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2870         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2871                 name_len_target =
2872                     cifsConvertToUTF16((__le16 *) data_offset, fromName,
2873                                        PATH_MAX, nls_codepage, remap);
2874                 name_len_target++;      /* trailing null */
2875                 name_len_target *= 2;
2876         } else {        /* BB improve the check for buffer overruns BB */
2877                 name_len_target = strnlen(fromName, PATH_MAX);
2878                 name_len_target++;      /* trailing null */
2879                 strncpy(data_offset, fromName, name_len_target);
2880         }
2881
2882         pSMB->MaxParameterCount = cpu_to_le16(2);
2883         /* BB find exact max on data count below from sess*/
2884         pSMB->MaxDataCount = cpu_to_le16(1000);
2885         pSMB->SetupCount = 1;
2886         pSMB->Reserved3 = 0;
2887         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2888         byte_count = 3 /* pad */  + params + name_len_target;
2889         pSMB->ParameterCount = cpu_to_le16(params);
2890         pSMB->TotalParameterCount = pSMB->ParameterCount;
2891         pSMB->DataCount = cpu_to_le16(name_len_target);
2892         pSMB->TotalDataCount = pSMB->DataCount;
2893         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2894         pSMB->DataOffset = cpu_to_le16(offset);
2895         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2896         pSMB->Reserved4 = 0;
2897         inc_rfc1001_len(pSMB, byte_count);
2898         pSMB->ByteCount = cpu_to_le16(byte_count);
2899         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2900                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2901         cifs_stats_inc(&tcon->num_hardlinks);
2902         if (rc)
2903                 cFYI(1, "Send error in SetPathInfo (hard link) = %d", rc);
2904
2905         cifs_buf_release(pSMB);
2906         if (rc == -EAGAIN)
2907                 goto createHardLinkRetry;
2908
2909         return rc;
2910 }
2911
2912 int
2913 CIFSCreateHardLink(const int xid, struct cifs_tcon *tcon,
2914                    const char *fromName, const char *toName,
2915                    const struct nls_table *nls_codepage, int remap)
2916 {
2917         int rc = 0;
2918         NT_RENAME_REQ *pSMB = NULL;
2919         RENAME_RSP *pSMBr = NULL;
2920         int bytes_returned;
2921         int name_len, name_len2;
2922         __u16 count;
2923
2924         cFYI(1, "In CIFSCreateHardLink");
2925 winCreateHardLinkRetry:
2926
2927         rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2928                       (void **) &pSMBr);
2929         if (rc)
2930                 return rc;
2931
2932         pSMB->SearchAttributes =
2933             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2934                         ATTR_DIRECTORY);
2935         pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2936         pSMB->ClusterCount = 0;
2937
2938         pSMB->BufferFormat = 0x04;
2939
2940         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2941                 name_len =
2942                     cifsConvertToUTF16((__le16 *) pSMB->OldFileName, fromName,
2943                                        PATH_MAX, nls_codepage, remap);
2944                 name_len++;     /* trailing null */
2945                 name_len *= 2;
2946
2947                 /* protocol specifies ASCII buffer format (0x04) for unicode */
2948                 pSMB->OldFileName[name_len] = 0x04;
2949                 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
2950                 name_len2 =
2951                     cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2952                                        toName, PATH_MAX, nls_codepage, remap);
2953                 name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2954                 name_len2 *= 2; /* convert to bytes */
2955         } else {        /* BB improve the check for buffer overruns BB */
2956                 name_len = strnlen(fromName, PATH_MAX);
2957                 name_len++;     /* trailing null */
2958                 strncpy(pSMB->OldFileName, fromName, name_len);
2959                 name_len2 = strnlen(toName, PATH_MAX);
2960                 name_len2++;    /* trailing null */
2961                 pSMB->OldFileName[name_len] = 0x04;     /* 2nd buffer format */
2962                 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2963                 name_len2++;    /* trailing null */
2964                 name_len2++;    /* signature byte */
2965         }
2966
2967         count = 1 /* string type byte */  + name_len + name_len2;
2968         inc_rfc1001_len(pSMB, count);
2969         pSMB->ByteCount = cpu_to_le16(count);
2970
2971         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2972                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2973         cifs_stats_inc(&tcon->num_hardlinks);
2974         if (rc)
2975                 cFYI(1, "Send error in hard link (NT rename) = %d", rc);
2976
2977         cifs_buf_release(pSMB);
2978         if (rc == -EAGAIN)
2979                 goto winCreateHardLinkRetry;
2980
2981         return rc;
2982 }
2983
2984 int
2985 CIFSSMBUnixQuerySymLink(const int xid, struct cifs_tcon *tcon,
2986                         const unsigned char *searchName, char **symlinkinfo,
2987                         const struct nls_table *nls_codepage)
2988 {
2989 /* SMB_QUERY_FILE_UNIX_LINK */
2990         TRANSACTION2_QPI_REQ *pSMB = NULL;
2991         TRANSACTION2_QPI_RSP *pSMBr = NULL;
2992         int rc = 0;
2993         int bytes_returned;
2994         int name_len;
2995         __u16 params, byte_count;
2996         char *data_start;
2997
2998         cFYI(1, "In QPathSymLinkInfo (Unix) for path %s", searchName);
2999
3000 querySymLinkRetry:
3001         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3002                       (void **) &pSMBr);
3003         if (rc)
3004                 return rc;
3005
3006         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3007                 name_len =
3008                         cifs_strtoUTF16((__le16 *) pSMB->FileName, searchName,
3009                                         PATH_MAX, nls_codepage);
3010                 name_len++;     /* trailing null */
3011                 name_len *= 2;
3012         } else {        /* BB improve the check for buffer overruns BB */
3013                 name_len = strnlen(searchName, PATH_MAX);
3014                 name_len++;     /* trailing null */
3015                 strncpy(pSMB->FileName, searchName, name_len);
3016         }
3017
3018         params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
3019         pSMB->TotalDataCount = 0;
3020         pSMB->MaxParameterCount = cpu_to_le16(2);
3021         pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3022         pSMB->MaxSetupCount = 0;
3023         pSMB->Reserved = 0;
3024         pSMB->Flags = 0;
3025         pSMB->Timeout = 0;
3026         pSMB->Reserved2 = 0;
3027         pSMB->ParameterOffset = cpu_to_le16(offsetof(
3028         struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3029         pSMB->DataCount = 0;
3030         pSMB->DataOffset = 0;
3031         pSMB->SetupCount = 1;
3032         pSMB->Reserved3 = 0;
3033         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3034         byte_count = params + 1 /* pad */ ;
3035         pSMB->TotalParameterCount = cpu_to_le16(params);
3036         pSMB->ParameterCount = pSMB->TotalParameterCount;
3037         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
3038         pSMB->Reserved4 = 0;
3039         inc_rfc1001_len(pSMB, byte_count);
3040         pSMB->ByteCount = cpu_to_le16(byte_count);
3041
3042         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3043                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3044         if (rc) {
3045                 cFYI(1, "Send error in QuerySymLinkInfo = %d", rc);
3046         } else {
3047                 /* decode response */
3048
3049                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3050                 /* BB also check enough total bytes returned */
3051                 if (rc || get_bcc(&pSMBr->hdr) < 2)
3052                         rc = -EIO;
3053                 else {
3054                         bool is_unicode;
3055                         u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3056
3057                         data_start = ((char *) &pSMBr->hdr.Protocol) +
3058                                            le16_to_cpu(pSMBr->t2.DataOffset);
3059
3060                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3061                                 is_unicode = true;
3062                         else
3063                                 is_unicode = false;
3064
3065                         /* BB FIXME investigate remapping reserved chars here */
3066                         *symlinkinfo = cifs_strndup_from_utf16(data_start,
3067                                         count, is_unicode, nls_codepage);
3068                         if (!*symlinkinfo)
3069                                 rc = -ENOMEM;
3070                 }
3071         }
3072         cifs_buf_release(pSMB);
3073         if (rc == -EAGAIN)
3074                 goto querySymLinkRetry;
3075         return rc;
3076 }
3077
3078 #ifdef CONFIG_CIFS_SYMLINK_EXPERIMENTAL
3079 /*
3080  *      Recent Windows versions now create symlinks more frequently
3081  *      and they use the "reparse point" mechanism below.  We can of course
3082  *      do symlinks nicely to Samba and other servers which support the
3083  *      CIFS Unix Extensions and we can also do SFU symlinks and "client only"
3084  *      "MF" symlinks optionally, but for recent Windows we really need to
3085  *      reenable the code below and fix the cifs_symlink callers to handle this.
3086  *      In the interim this code has been moved to its own config option so
3087  *      it is not compiled in by default until callers fixed up and more tested.
3088  */
3089 int
3090 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifs_tcon *tcon,
3091                         const unsigned char *searchName,
3092                         char *symlinkinfo, const int buflen, __u16 fid,
3093                         const struct nls_table *nls_codepage)
3094 {
3095         int rc = 0;
3096         int bytes_returned;
3097         struct smb_com_transaction_ioctl_req *pSMB;
3098         struct smb_com_transaction_ioctl_rsp *pSMBr;
3099
3100         cFYI(1, "In Windows reparse style QueryLink for path %s", searchName);
3101         rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3102                       (void **) &pSMBr);
3103         if (rc)
3104                 return rc;
3105
3106         pSMB->TotalParameterCount = 0 ;
3107         pSMB->TotalDataCount = 0;
3108         pSMB->MaxParameterCount = cpu_to_le32(2);
3109         /* BB find exact data count max from sess structure BB */
3110         pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3111         pSMB->MaxSetupCount = 4;
3112         pSMB->Reserved = 0;
3113         pSMB->ParameterOffset = 0;
3114         pSMB->DataCount = 0;
3115         pSMB->DataOffset = 0;
3116         pSMB->SetupCount = 4;
3117         pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
3118         pSMB->ParameterCount = pSMB->TotalParameterCount;
3119         pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
3120         pSMB->IsFsctl = 1; /* FSCTL */
3121         pSMB->IsRootFlag = 0;
3122         pSMB->Fid = fid; /* file handle always le */
3123         pSMB->ByteCount = 0;
3124
3125         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3126                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3127         if (rc) {
3128                 cFYI(1, "Send error in QueryReparseLinkInfo = %d", rc);
3129         } else {                /* decode response */
3130                 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
3131                 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
3132                 if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) {
3133                         /* BB also check enough total bytes returned */
3134                         rc = -EIO;      /* bad smb */
3135                         goto qreparse_out;
3136                 }
3137                 if (data_count && (data_count < 2048)) {
3138                         char *end_of_smb = 2 /* sizeof byte count */ +
3139                                get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
3140
3141                         struct reparse_data *reparse_buf =
3142                                                 (struct reparse_data *)
3143                                                 ((char *)&pSMBr->hdr.Protocol
3144                                                                  + data_offset);
3145                         if ((char *)reparse_buf >= end_of_smb) {
3146                                 rc = -EIO;
3147                                 goto qreparse_out;
3148                         }
3149                         if ((reparse_buf->LinkNamesBuf +
3150                                 reparse_buf->TargetNameOffset +
3151                                 reparse_buf->TargetNameLen) > end_of_smb) {
3152                                 cFYI(1, "reparse buf beyond SMB");
3153                                 rc = -EIO;
3154                                 goto qreparse_out;
3155                         }
3156
3157                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3158                                 cifs_from_ucs2(symlinkinfo, (__le16 *)
3159                                                 (reparse_buf->LinkNamesBuf +
3160                                                 reparse_buf->TargetNameOffset),
3161                                                 buflen,
3162                                                 reparse_buf->TargetNameLen,
3163                                                 nls_codepage, 0);
3164                         } else { /* ASCII names */
3165                                 strncpy(symlinkinfo,
3166                                         reparse_buf->LinkNamesBuf +
3167                                         reparse_buf->TargetNameOffset,
3168                                         min_t(const int, buflen,
3169                                            reparse_buf->TargetNameLen));
3170                         }
3171                 } else {
3172                         rc = -EIO;
3173                         cFYI(1, "Invalid return data count on "
3174                                  "get reparse info ioctl");
3175                 }
3176                 symlinkinfo[buflen] = 0; /* just in case so the caller
3177                                         does not go off the end of the buffer */
3178                 cFYI(1, "readlink result - %s", symlinkinfo);
3179         }
3180
3181 qreparse_out:
3182         cifs_buf_release(pSMB);
3183
3184         /* Note: On -EAGAIN error only caller can retry on handle based calls
3185                 since file handle passed in no longer valid */
3186
3187         return rc;
3188 }
3189 #endif /* CIFS_SYMLINK_EXPERIMENTAL */ /* BB temporarily unused */
3190
3191 #ifdef CONFIG_CIFS_POSIX
3192
3193 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
3194 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
3195                              struct cifs_posix_ace *cifs_ace)
3196 {
3197         /* u8 cifs fields do not need le conversion */
3198         ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
3199         ace->e_tag  = cpu_to_le16(cifs_ace->cifs_e_tag);
3200         ace->e_id   = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
3201         /* cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id); */
3202
3203         return;
3204 }
3205
3206 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
3207 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
3208                                const int acl_type, const int size_of_data_area)
3209 {
3210         int size =  0;
3211         int i;
3212         __u16 count;
3213         struct cifs_posix_ace *pACE;
3214         struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
3215         posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
3216
3217         if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
3218                 return -EOPNOTSUPP;
3219
3220         if (acl_type & ACL_TYPE_ACCESS) {
3221                 count = le16_to_cpu(cifs_acl->access_entry_count);
3222                 pACE = &cifs_acl->ace_array[0];
3223                 size = sizeof(struct cifs_posix_acl);
3224                 size += sizeof(struct cifs_posix_ace) * count;
3225                 /* check if we would go beyond end of SMB */
3226                 if (size_of_data_area < size) {
3227                         cFYI(1, "bad CIFS POSIX ACL size %d vs. %d",
3228                                 size_of_data_area, size);
3229                         return -EINVAL;
3230                 }
3231         } else if (acl_type & ACL_TYPE_DEFAULT) {
3232                 count = le16_to_cpu(cifs_acl->access_entry_count);
3233                 size = sizeof(struct cifs_posix_acl);
3234                 size += sizeof(struct cifs_posix_ace) * count;
3235 /* skip past access ACEs to get to default ACEs */
3236                 pACE = &cifs_acl->ace_array[count];
3237                 count = le16_to_cpu(cifs_acl->default_entry_count);
3238                 size += sizeof(struct cifs_posix_ace) * count;
3239                 /* check if we would go beyond end of SMB */
3240                 if (size_of_data_area < size)
3241                         return -EINVAL;
3242         } else {
3243                 /* illegal type */
3244                 return -EINVAL;
3245         }
3246
3247         size = posix_acl_xattr_size(count);
3248         if ((buflen == 0) || (local_acl == NULL)) {
3249                 /* used to query ACL EA size */
3250         } else if (size > buflen) {
3251                 return -ERANGE;
3252         } else /* buffer big enough */ {
3253                 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
3254                 for (i = 0; i < count ; i++) {
3255                         cifs_convert_ace(&local_acl->a_entries[i], pACE);
3256                         pACE++;
3257                 }
3258         }
3259         return size;
3260 }
3261
3262 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
3263                                      const posix_acl_xattr_entry *local_ace)
3264 {
3265         __u16 rc = 0; /* 0 = ACL converted ok */
3266
3267         cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
3268         cifs_ace->cifs_e_tag =  le16_to_cpu(local_ace->e_tag);
3269         /* BB is there a better way to handle the large uid? */
3270         if (local_ace->e_id == cpu_to_le32(-1)) {
3271         /* Probably no need to le convert -1 on any arch but can not hurt */
3272                 cifs_ace->cifs_uid = cpu_to_le64(-1);
3273         } else
3274                 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
3275         /*cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id);*/
3276         return rc;
3277 }
3278
3279 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
3280 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
3281                                const int buflen, const int acl_type)
3282 {
3283         __u16 rc = 0;
3284         struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
3285         posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
3286         int count;
3287         int i;
3288
3289         if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
3290                 return 0;
3291
3292         count = posix_acl_xattr_count((size_t)buflen);
3293         cFYI(1, "setting acl with %d entries from buf of length %d and "
3294                 "version of %d",
3295                 count, buflen, le32_to_cpu(local_acl->a_version));
3296         if (le32_to_cpu(local_acl->a_version) != 2) {
3297                 cFYI(1, "unknown POSIX ACL version %d",
3298                      le32_to_cpu(local_acl->a_version));
3299                 return 0;
3300         }
3301         cifs_acl->version = cpu_to_le16(1);
3302         if (acl_type == ACL_TYPE_ACCESS)
3303                 cifs_acl->access_entry_count = cpu_to_le16(count);
3304         else if (acl_type == ACL_TYPE_DEFAULT)
3305                 cifs_acl->default_entry_count = cpu_to_le16(count);
3306         else {
3307                 cFYI(1, "unknown ACL type %d", acl_type);
3308                 return 0;
3309         }
3310         for (i = 0; i < count; i++) {
3311                 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
3312                                         &local_acl->a_entries[i]);
3313                 if (rc != 0) {
3314                         /* ACE not converted */
3315                         break;
3316                 }
3317         }
3318         if (rc == 0) {
3319                 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
3320                 rc += sizeof(struct cifs_posix_acl);
3321                 /* BB add check to make sure ACL does not overflow SMB */
3322         }
3323         return rc;
3324 }
3325
3326 int
3327 CIFSSMBGetPosixACL(const int xid, struct cifs_tcon *tcon,
3328                    const unsigned char *searchName,
3329                    char *acl_inf, const int buflen, const int acl_type,
3330                    const struct nls_table *nls_codepage, int remap)
3331 {
3332 /* SMB_QUERY_POSIX_ACL */
3333         TRANSACTION2_QPI_REQ *pSMB = NULL;
3334         TRANSACTION2_QPI_RSP *pSMBr = NULL;
3335         int rc = 0;
3336         int bytes_returned;
3337         int name_len;
3338         __u16 params, byte_count;
3339
3340         cFYI(1, "In GetPosixACL (Unix) for path %s", searchName);
3341
3342 queryAclRetry:
3343         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3344                 (void **) &pSMBr);
3345         if (rc)
3346                 return rc;
3347
3348         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3349                 name_len =
3350                         cifsConvertToUTF16((__le16 *) pSMB->FileName,
3351                                            searchName, PATH_MAX, nls_codepage,
3352                                            remap);
3353                 name_len++;     /* trailing null */
3354                 name_len *= 2;
3355                 pSMB->FileName[name_len] = 0;
3356                 pSMB->FileName[name_len+1] = 0;
3357         } else {        /* BB improve the check for buffer overruns BB */
3358                 name_len = strnlen(searchName, PATH_MAX);
3359                 name_len++;     /* trailing null */
3360                 strncpy(pSMB->FileName, searchName, name_len);
3361         }
3362
3363         params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
3364         pSMB->TotalDataCount = 0;
3365         pSMB->MaxParameterCount = cpu_to_le16(2);
3366         /* BB find exact max data count below from sess structure BB */
3367         pSMB->MaxDataCount = cpu_to_le16(4000);
3368         pSMB->MaxSetupCount = 0;
3369         pSMB->Reserved = 0;
3370         pSMB->Flags = 0;
3371         pSMB->Timeout = 0;
3372         pSMB->Reserved2 = 0;
3373         pSMB->ParameterOffset = cpu_to_le16(
3374                 offsetof(struct smb_com_transaction2_qpi_req,
3375                          InformationLevel) - 4);
3376         pSMB->DataCount = 0;
3377         pSMB->DataOffset = 0;
3378         pSMB->SetupCount = 1;
3379         pSMB->Reserved3 = 0;
3380         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3381         byte_count = params + 1 /* pad */ ;
3382         pSMB->TotalParameterCount = cpu_to_le16(params);
3383         pSMB->ParameterCount = pSMB->TotalParameterCount;
3384         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
3385         pSMB->Reserved4 = 0;
3386         inc_rfc1001_len(pSMB, byte_count);
3387         pSMB->ByteCount = cpu_to_le16(byte_count);
3388
3389         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3390                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3391         cifs_stats_inc(&tcon->num_acl_get);
3392         if (rc) {
3393                 cFYI(1, "Send error in Query POSIX ACL = %d", rc);
3394         } else {
3395                 /* decode response */
3396
3397                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3398                 /* BB also check enough total bytes returned */
3399                 if (rc || get_bcc(&pSMBr->hdr) < 2)
3400                         rc = -EIO;      /* bad smb */
3401                 else {
3402                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3403                         __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3404                         rc = cifs_copy_posix_acl(acl_inf,
3405                                 (char *)&pSMBr->hdr.Protocol+data_offset,
3406                                 buflen, acl_type, count);
3407                 }
3408         }
3409         cifs_buf_release(pSMB);
3410         if (rc == -EAGAIN)
3411                 goto queryAclRetry;
3412         return rc;
3413 }
3414
3415 int
3416 CIFSSMBSetPosixACL(const int xid, struct cifs_tcon *tcon,
3417                    const unsigned char *fileName,
3418                    const char *local_acl, const int buflen,
3419                    const int acl_type,
3420                    const struct nls_table *nls_codepage, int remap)
3421 {
3422         struct smb_com_transaction2_spi_req *pSMB = NULL;
3423         struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3424         char *parm_data;
3425         int name_len;
3426         int rc = 0;
3427         int bytes_returned = 0;
3428         __u16 params, byte_count, data_count, param_offset, offset;
3429
3430         cFYI(1, "In SetPosixACL (Unix) for path %s", fileName);
3431 setAclRetry:
3432         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3433                       (void **) &pSMBr);
3434         if (rc)
3435                 return rc;
3436         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3437                 name_len =
3438                         cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
3439                                            PATH_MAX, nls_codepage, remap);
3440                 name_len++;     /* trailing null */
3441                 name_len *= 2;
3442         } else {        /* BB improve the check for buffer overruns BB */
3443                 name_len = strnlen(fileName, PATH_MAX);
3444                 name_len++;     /* trailing null */
3445                 strncpy(pSMB->FileName, fileName, name_len);
3446         }
3447         params = 6 + name_len;
3448         pSMB->MaxParameterCount = cpu_to_le16(2);
3449         /* BB find max SMB size from sess */
3450         pSMB->MaxDataCount = cpu_to_le16(1000);
3451         pSMB->MaxSetupCount = 0;
3452         pSMB->Reserved = 0;
3453         pSMB->Flags = 0;
3454         pSMB->Timeout = 0;
3455         pSMB->Reserved2 = 0;
3456         param_offset = offsetof(struct smb_com_transaction2_spi_req,
3457                                 InformationLevel) - 4;
3458         offset = param_offset + params;
3459         parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
3460         pSMB->ParameterOffset = cpu_to_le16(param_offset);
3461
3462         /* convert to on the wire format for POSIX ACL */
3463         data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
3464
3465         if (data_count == 0) {
3466                 rc = -EOPNOTSUPP;
3467                 goto setACLerrorExit;
3468         }
3469         pSMB->DataOffset = cpu_to_le16(offset);
3470         pSMB->SetupCount = 1;
3471         pSMB->Reserved3 = 0;
3472         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3473         pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
3474         byte_count = 3 /* pad */  + params + data_count;
3475         pSMB->DataCount = cpu_to_le16(data_count);
3476         pSMB->TotalDataCount = pSMB->DataCount;
3477         pSMB->ParameterCount = cpu_to_le16(params);
3478         pSMB->TotalParameterCount = pSMB->ParameterCount;
3479         pSMB->Reserved4 = 0;
3480         inc_rfc1001_len(pSMB, byte_count);
3481         pSMB->ByteCount = cpu_to_le16(byte_count);
3482         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3483                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3484         if (rc)
3485                 cFYI(1, "Set POSIX ACL returned %d", rc);
3486
3487 setACLerrorExit:
3488         cifs_buf_release(pSMB);
3489         if (rc == -EAGAIN)
3490                 goto setAclRetry;
3491         return rc;
3492 }
3493
3494 /* BB fix tabs in this function FIXME BB */
3495 int
3496 CIFSGetExtAttr(const int xid, struct cifs_tcon *tcon,
3497                const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
3498 {
3499         int rc = 0;
3500         struct smb_t2_qfi_req *pSMB = NULL;
3501         struct smb_t2_qfi_rsp *pSMBr = NULL;
3502         int bytes_returned;
3503         __u16 params, byte_count;
3504
3505         cFYI(1, "In GetExtAttr");
3506         if (tcon == NULL)
3507                 return -ENODEV;
3508
3509 GetExtAttrRetry:
3510         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3511                         (void **) &pSMBr);
3512         if (rc)
3513                 return rc;
3514
3515         params = 2 /* level */ + 2 /* fid */;
3516         pSMB->t2.TotalDataCount = 0;
3517         pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3518         /* BB find exact max data count below from sess structure BB */
3519         pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3520         pSMB->t2.MaxSetupCount = 0;
3521         pSMB->t2.Reserved = 0;
3522         pSMB->t2.Flags = 0;
3523         pSMB->t2.Timeout = 0;
3524         pSMB->t2.Reserved2 = 0;
3525         pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3526                                                Fid) - 4);
3527         pSMB->t2.DataCount = 0;
3528         pSMB->t2.DataOffset = 0;
3529         pSMB->t2.SetupCount = 1;
3530         pSMB->t2.Reserved3 = 0;
3531         pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3532         byte_count = params + 1 /* pad */ ;
3533         pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3534         pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3535         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3536         pSMB->Pad = 0;
3537         pSMB->Fid = netfid;
3538         inc_rfc1001_len(pSMB, byte_count);
3539         pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3540
3541         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3542                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3543         if (rc) {
3544                 cFYI(1, "error %d in GetExtAttr", rc);
3545         } else {
3546                 /* decode response */
3547                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3548                 /* BB also check enough total bytes returned */
3549                 if (rc || get_bcc(&pSMBr->hdr) < 2)
3550                         /* If rc should we check for EOPNOSUPP and
3551                            disable the srvino flag? or in caller? */
3552                         rc = -EIO;      /* bad smb */
3553                 else {
3554                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3555                         __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3556                         struct file_chattr_info *pfinfo;
3557                         /* BB Do we need a cast or hash here ? */
3558                         if (count != 16) {
3559                                 cFYI(1, "Illegal size ret in GetExtAttr");
3560                                 rc = -EIO;
3561                                 goto GetExtAttrOut;
3562                         }
3563                         pfinfo = (struct file_chattr_info *)
3564                                  (data_offset + (char *) &pSMBr->hdr.Protocol);
3565                         *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3566                         *pMask = le64_to_cpu(pfinfo->mask);
3567                 }
3568         }
3569 GetExtAttrOut:
3570         cifs_buf_release(pSMB);
3571         if (rc == -EAGAIN)
3572                 goto GetExtAttrRetry;
3573         return rc;
3574 }
3575
3576 #endif /* CONFIG_POSIX */
3577
3578 #ifdef CONFIG_CIFS_ACL
3579 /*
3580  * Initialize NT TRANSACT SMB into small smb request buffer.  This assumes that
3581  * all NT TRANSACTS that we init here have total parm and data under about 400
3582  * bytes (to fit in small cifs buffer size), which is the case so far, it
3583  * easily fits. NB: Setup words themselves and ByteCount MaxSetupCount (size of
3584  * returned setup area) and MaxParameterCount (returned parms size) must be set
3585  * by caller
3586  */
3587 static int
3588 smb_init_nttransact(const __u16 sub_command, const int setup_count,
3589                    const int parm_len, struct cifs_tcon *tcon,
3590                    void **ret_buf)
3591 {
3592         int rc;
3593         __u32 temp_offset;
3594         struct smb_com_ntransact_req *pSMB;
3595
3596         rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
3597                                 (void **)&pSMB);
3598         if (rc)
3599                 return rc;
3600         *ret_buf = (void *)pSMB;
3601         pSMB->Reserved = 0;
3602         pSMB->TotalParameterCount = cpu_to_le32(parm_len);
3603         pSMB->TotalDataCount  = 0;
3604         pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
3605         pSMB->ParameterCount = pSMB->TotalParameterCount;
3606         pSMB->DataCount  = pSMB->TotalDataCount;
3607         temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
3608                         (setup_count * 2) - 4 /* for rfc1001 length itself */;
3609         pSMB->ParameterOffset = cpu_to_le32(temp_offset);
3610         pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
3611         pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
3612         pSMB->SubCommand = cpu_to_le16(sub_command);
3613         return 0;
3614 }
3615
3616 static int
3617 validate_ntransact(char *buf, char **ppparm, char **ppdata,
3618                    __u32 *pparmlen, __u32 *pdatalen)
3619 {
3620         char *end_of_smb;
3621         __u32 data_count, data_offset, parm_count, parm_offset;
3622         struct smb_com_ntransact_rsp *pSMBr;
3623         u16 bcc;
3624
3625         *pdatalen = 0;
3626         *pparmlen = 0;
3627
3628         if (buf == NULL)
3629                 return -EINVAL;
3630
3631         pSMBr = (struct smb_com_ntransact_rsp *)buf;
3632
3633         bcc = get_bcc(&pSMBr->hdr);
3634         end_of_smb = 2 /* sizeof byte count */ + bcc +
3635                         (char *)&pSMBr->ByteCount;
3636
3637         data_offset = le32_to_cpu(pSMBr->DataOffset);
3638         data_count = le32_to_cpu(pSMBr->DataCount);
3639         parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
3640         parm_count = le32_to_cpu(pSMBr->ParameterCount);
3641
3642         *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
3643         *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
3644
3645         /* should we also check that parm and data areas do not overlap? */
3646         if (*ppparm > end_of_smb) {
3647                 cFYI(1, "parms start after end of smb");
3648                 return -EINVAL;
3649         } else if (parm_count + *ppparm > end_of_smb) {
3650                 cFYI(1, "parm end after end of smb");
3651                 return -EINVAL;
3652         } else if (*ppdata > end_of_smb) {
3653                 cFYI(1, "data starts after end of smb");
3654                 return -EINVAL;
3655         } else if (data_count + *ppdata > end_of_smb) {
3656                 cFYI(1, "data %p + count %d (%p) past smb end %p start %p",
3657                         *ppdata, data_count, (data_count + *ppdata),
3658                         end_of_smb, pSMBr);
3659                 return -EINVAL;
3660         } else if (parm_count + data_count > bcc) {
3661                 cFYI(1, "parm count and data count larger than SMB");
3662                 return -EINVAL;
3663         }
3664         *pdatalen = data_count;
3665         *pparmlen = parm_count;
3666         return 0;
3667 }
3668
3669 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3670 int
3671 CIFSSMBGetCIFSACL(const int xid, struct cifs_tcon *tcon, __u16 fid,
3672                   struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3673 {
3674         int rc = 0;
3675         int buf_type = 0;
3676         QUERY_SEC_DESC_REQ *pSMB;
3677         struct kvec iov[1];
3678
3679         cFYI(1, "GetCifsACL");
3680
3681         *pbuflen = 0;
3682         *acl_inf = NULL;
3683
3684         rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3685                         8 /* parm len */, tcon, (void **) &pSMB);
3686         if (rc)
3687                 return rc;
3688
3689         pSMB->MaxParameterCount = cpu_to_le32(4);
3690         /* BB TEST with big acls that might need to be e.g. larger than 16K */
3691         pSMB->MaxSetupCount = 0;
3692         pSMB->Fid = fid; /* file handle always le */
3693         pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3694                                      CIFS_ACL_DACL);
3695         pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3696         inc_rfc1001_len(pSMB, 11);
3697         iov[0].iov_base = (char *)pSMB;
3698         iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4;
3699
3700         rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3701                          0);
3702         cifs_stats_inc(&tcon->num_acl_get);
3703         if (rc) {
3704                 cFYI(1, "Send error in QuerySecDesc = %d", rc);
3705         } else {                /* decode response */
3706                 __le32 *parm;
3707                 __u32 parm_len;
3708                 __u32 acl_len;
3709                 struct smb_com_ntransact_rsp *pSMBr;
3710                 char *pdata;
3711
3712 /* validate_nttransact */
3713                 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3714                                         &pdata, &parm_len, pbuflen);
3715                 if (rc)
3716                         goto qsec_out;
3717                 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3718
3719                 cFYI(1, "smb %p parm %p data %p", pSMBr, parm, *acl_inf);
3720
3721                 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3722                         rc = -EIO;      /* bad smb */
3723                         *pbuflen = 0;
3724                         goto qsec_out;
3725                 }
3726
3727 /* BB check that data area is minimum length and as big as acl_len */
3728
3729                 acl_len = le32_to_cpu(*parm);
3730                 if (acl_len != *pbuflen) {
3731                         cERROR(1, "acl length %d does not match %d",
3732                                    acl_len, *pbuflen);
3733                         if (*pbuflen > acl_len)
3734                                 *pbuflen = acl_len;
3735                 }
3736
3737                 /* check if buffer is big enough for the acl
3738                    header followed by the smallest SID */
3739                 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3740                     (*pbuflen >= 64 * 1024)) {
3741                         cERROR(1, "bad acl length %d", *pbuflen);
3742                         rc = -EINVAL;
3743                         *pbuflen = 0;
3744                 } else {
3745                         *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3746                         if (*acl_inf == NULL) {
3747                                 *pbuflen = 0;
3748                                 rc = -ENOMEM;
3749                         }
3750                         memcpy(*acl_inf, pdata, *pbuflen);
3751                 }
3752         }
3753 qsec_out:
3754         if (buf_type == CIFS_SMALL_BUFFER)
3755                 cifs_small_buf_release(iov[0].iov_base);
3756         else if (buf_type == CIFS_LARGE_BUFFER)
3757                 cifs_buf_release(iov[0].iov_base);
3758 /*      cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3759         return rc;
3760 }
3761
3762 int
3763 CIFSSMBSetCIFSACL(const int xid, struct cifs_tcon *tcon, __u16 fid,
3764                         struct cifs_ntsd *pntsd, __u32 acllen, int aclflag)
3765 {
3766         __u16 byte_count, param_count, data_count, param_offset, data_offset;
3767         int rc = 0;
3768         int bytes_returned = 0;
3769         SET_SEC_DESC_REQ *pSMB = NULL;
3770         void *pSMBr;
3771
3772 setCifsAclRetry:
3773         rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, &pSMBr);
3774         if (rc)
3775                 return rc;
3776
3777         pSMB->MaxSetupCount = 0;
3778         pSMB->Reserved = 0;
3779
3780         param_count = 8;
3781         param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3782         data_count = acllen;
3783         data_offset = param_offset + param_count;
3784         byte_count = 3 /* pad */  + param_count;
3785
3786         pSMB->DataCount = cpu_to_le32(data_count);
3787         pSMB->TotalDataCount = pSMB->DataCount;
3788         pSMB->MaxParameterCount = cpu_to_le32(4);
3789         pSMB->MaxDataCount = cpu_to_le32(16384);
3790         pSMB->ParameterCount = cpu_to_le32(param_count);
3791         pSMB->ParameterOffset = cpu_to_le32(param_offset);
3792         pSMB->TotalParameterCount = pSMB->ParameterCount;
3793         pSMB->DataOffset = cpu_to_le32(data_offset);
3794         pSMB->SetupCount = 0;
3795         pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3796         pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3797
3798         pSMB->Fid = fid; /* file handle always le */
3799         pSMB->Reserved2 = 0;
3800         pSMB->AclFlags = cpu_to_le32(aclflag);
3801
3802         if (pntsd && acllen) {
3803                 memcpy((char *)pSMBr + offsetof(struct smb_hdr, Protocol) +
3804                                 data_offset, pntsd, acllen);
3805                 inc_rfc1001_len(pSMB, byte_count + data_count);
3806         } else
3807                 inc_rfc1001_len(pSMB, byte_count);
3808
3809         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3810                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3811
3812         cFYI(1, "SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc);
3813         if (rc)
3814                 cFYI(1, "Set CIFS ACL returned %d", rc);
3815         cifs_buf_release(pSMB);
3816
3817         if (rc == -EAGAIN)
3818                 goto setCifsAclRetry;
3819
3820         return (rc);
3821 }
3822
3823 #endif /* CONFIG_CIFS_ACL */
3824
3825 /* Legacy Query Path Information call for lookup to old servers such
3826    as Win9x/WinME */
3827 int SMBQueryInformation(const int xid, struct cifs_tcon *tcon,
3828                         const unsigned char *searchName,
3829                         FILE_ALL_INFO *pFinfo,
3830                         const struct nls_table *nls_codepage, int remap)
3831 {
3832         QUERY_INFORMATION_REQ *pSMB;
3833         QUERY_INFORMATION_RSP *pSMBr;
3834         int rc = 0;
3835         int bytes_returned;
3836         int name_len;
3837
3838         cFYI(1, "In SMBQPath path %s", searchName);
3839 QInfRetry:
3840         rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3841                       (void **) &pSMBr);
3842         if (rc)
3843                 return rc;
3844
3845         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3846                 name_len =
3847                         cifsConvertToUTF16((__le16 *) pSMB->FileName,
3848                                            searchName, PATH_MAX, nls_codepage,
3849                                            remap);
3850                 name_len++;     /* trailing null */
3851                 name_len *= 2;
3852         } else {
3853                 name_len = strnlen(searchName, PATH_MAX);
3854                 name_len++;     /* trailing null */
3855                 strncpy(pSMB->FileName, searchName, name_len);
3856         }
3857         pSMB->BufferFormat = 0x04;
3858         name_len++; /* account for buffer type byte */
3859         inc_rfc1001_len(pSMB, (__u16)name_len);
3860         pSMB->ByteCount = cpu_to_le16(name_len);
3861
3862         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3863                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3864         if (rc) {
3865                 cFYI(1, "Send error in QueryInfo = %d", rc);
3866         } else if (pFinfo) {
3867                 struct timespec ts;
3868                 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3869
3870                 /* decode response */
3871                 /* BB FIXME - add time zone adjustment BB */
3872                 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3873                 ts.tv_nsec = 0;
3874                 ts.tv_sec = time;
3875                 /* decode time fields */
3876                 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3877                 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3878                 pFinfo->LastAccessTime = 0;
3879                 pFinfo->AllocationSize =
3880                         cpu_to_le64(le32_to_cpu(pSMBr->size));
3881                 pFinfo->EndOfFile = pFinfo->AllocationSize;
3882                 pFinfo->Attributes =
3883                         cpu_to_le32(le16_to_cpu(pSMBr->attr));
3884         } else
3885                 rc = -EIO; /* bad buffer passed in */
3886
3887         cifs_buf_release(pSMB);
3888
3889         if (rc == -EAGAIN)
3890                 goto QInfRetry;
3891
3892         return rc;
3893 }
3894
3895 int
3896 CIFSSMBQFileInfo(const int xid, struct cifs_tcon *tcon,
3897                  u16 netfid, FILE_ALL_INFO *pFindData)
3898 {
3899         struct smb_t2_qfi_req *pSMB = NULL;
3900         struct smb_t2_qfi_rsp *pSMBr = NULL;
3901         int rc = 0;
3902         int bytes_returned;
3903         __u16 params, byte_count;
3904
3905 QFileInfoRetry:
3906         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3907                       (void **) &pSMBr);
3908         if (rc)
3909                 return rc;
3910
3911         params = 2 /* level */ + 2 /* fid */;
3912         pSMB->t2.TotalDataCount = 0;
3913         pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3914         /* BB find exact max data count below from sess structure BB */
3915         pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3916         pSMB->t2.MaxSetupCount = 0;
3917         pSMB->t2.Reserved = 0;
3918         pSMB->t2.Flags = 0;
3919         pSMB->t2.Timeout = 0;
3920         pSMB->t2.Reserved2 = 0;
3921         pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3922                                                Fid) - 4);
3923         pSMB->t2.DataCount = 0;
3924         pSMB->t2.DataOffset = 0;
3925         pSMB->t2.SetupCount = 1;
3926         pSMB->t2.Reserved3 = 0;
3927         pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3928         byte_count = params + 1 /* pad */ ;
3929         pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3930         pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3931         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3932         pSMB->Pad = 0;
3933         pSMB->Fid = netfid;
3934         inc_rfc1001_len(pSMB, byte_count);
3935
3936         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3937                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3938         if (rc) {
3939                 cFYI(1, "Send error in QPathInfo = %d", rc);
3940         } else {                /* decode response */
3941                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3942
3943                 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3944                         rc = -EIO;
3945                 else if (get_bcc(&pSMBr->hdr) < 40)
3946                         rc = -EIO;      /* bad smb */
3947                 else if (pFindData) {
3948                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3949                         memcpy((char *) pFindData,
3950                                (char *) &pSMBr->hdr.Protocol +
3951                                data_offset, sizeof(FILE_ALL_INFO));
3952                 } else
3953                     rc = -ENOMEM;
3954         }
3955         cifs_buf_release(pSMB);
3956         if (rc == -EAGAIN)
3957                 goto QFileInfoRetry;
3958
3959         return rc;
3960 }
3961
3962 int
3963 CIFSSMBQPathInfo(const int xid, struct cifs_tcon *tcon,
3964                  const unsigned char *searchName,
3965                  FILE_ALL_INFO *pFindData,
3966                  int legacy /* old style infolevel */,
3967                  const struct nls_table *nls_codepage, int remap)
3968 {
3969 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3970         TRANSACTION2_QPI_REQ *pSMB = NULL;
3971         TRANSACTION2_QPI_RSP *pSMBr = NULL;
3972         int rc = 0;
3973         int bytes_returned;
3974         int name_len;
3975         __u16 params, byte_count;
3976
3977 /* cFYI(1, "In QPathInfo path %s", searchName); */
3978 QPathInfoRetry:
3979         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3980                       (void **) &pSMBr);
3981         if (rc)
3982                 return rc;
3983
3984         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3985                 name_len =
3986                     cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
3987                                        PATH_MAX, nls_codepage, remap);
3988                 name_len++;     /* trailing null */
3989                 name_len *= 2;
3990         } else {        /* BB improve the check for buffer overruns BB */
3991                 name_len = strnlen(searchName, PATH_MAX);
3992                 name_len++;     /* trailing null */
3993                 strncpy(pSMB->FileName, searchName, name_len);
3994         }
3995
3996         params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3997         pSMB->TotalDataCount = 0;
3998         pSMB->MaxParameterCount = cpu_to_le16(2);
3999         /* BB find exact max SMB PDU from sess structure BB */
4000         pSMB->MaxDataCount = cpu_to_le16(4000);
4001         pSMB->MaxSetupCount = 0;
4002         pSMB->Reserved = 0;
4003         pSMB->Flags = 0;
4004         pSMB->Timeout = 0;
4005         pSMB->Reserved2 = 0;
4006         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4007         struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4008         pSMB->DataCount = 0;
4009         pSMB->DataOffset = 0;
4010         pSMB->SetupCount = 1;
4011         pSMB->Reserved3 = 0;
4012         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4013         byte_count = params + 1 /* pad */ ;
4014         pSMB->TotalParameterCount = cpu_to_le16(params);
4015         pSMB->ParameterCount = pSMB->TotalParameterCount;
4016         if (legacy)
4017                 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
4018         else
4019                 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
4020         pSMB->Reserved4 = 0;
4021         inc_rfc1001_len(pSMB, byte_count);
4022         pSMB->ByteCount = cpu_to_le16(byte_count);
4023
4024         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4025                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4026         if (rc) {
4027                 cFYI(1, "Send error in QPathInfo = %d", rc);
4028         } else {                /* decode response */
4029                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4030
4031                 if (rc) /* BB add auto retry on EOPNOTSUPP? */
4032                         rc = -EIO;
4033                 else if (!legacy && get_bcc(&pSMBr->hdr) < 40)
4034                         rc = -EIO;      /* bad smb */
4035                 else if (legacy && get_bcc(&pSMBr->hdr) < 24)
4036                         rc = -EIO;  /* 24 or 26 expected but we do not read
4037                                         last field */
4038                 else if (pFindData) {
4039                         int size;
4040                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4041
4042                         /* On legacy responses we do not read the last field,
4043                         EAsize, fortunately since it varies by subdialect and
4044                         also note it differs on Set vs. Get, ie two bytes or 4
4045                         bytes depending but we don't care here */
4046                         if (legacy)
4047                                 size = sizeof(FILE_INFO_STANDARD);
4048                         else
4049                                 size = sizeof(FILE_ALL_INFO);
4050                         memcpy((char *) pFindData,
4051                                (char *) &pSMBr->hdr.Protocol +
4052                                data_offset, size);
4053                 } else
4054                     rc = -ENOMEM;
4055         }
4056         cifs_buf_release(pSMB);
4057         if (rc == -EAGAIN)
4058                 goto QPathInfoRetry;
4059
4060         return rc;
4061 }
4062
4063 int
4064 CIFSSMBUnixQFileInfo(const int xid, struct cifs_tcon *tcon,
4065                  u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
4066 {
4067         struct smb_t2_qfi_req *pSMB = NULL;
4068         struct smb_t2_qfi_rsp *pSMBr = NULL;
4069         int rc = 0;
4070         int bytes_returned;
4071         __u16 params, byte_count;
4072
4073 UnixQFileInfoRetry:
4074         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4075                       (void **) &pSMBr);
4076         if (rc)
4077                 return rc;
4078
4079         params = 2 /* level */ + 2 /* fid */;
4080         pSMB->t2.TotalDataCount = 0;
4081         pSMB->t2.MaxParameterCount = cpu_to_le16(4);
4082         /* BB find exact max data count below from sess structure BB */
4083         pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
4084         pSMB->t2.MaxSetupCount = 0;
4085         pSMB->t2.Reserved = 0;
4086         pSMB->t2.Flags = 0;
4087         pSMB->t2.Timeout = 0;
4088         pSMB->t2.Reserved2 = 0;
4089         pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
4090                                                Fid) - 4);
4091         pSMB->t2.DataCount = 0;
4092         pSMB->t2.DataOffset = 0;
4093         pSMB->t2.SetupCount = 1;
4094         pSMB->t2.Reserved3 = 0;
4095         pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
4096         byte_count = params + 1 /* pad */ ;
4097         pSMB->t2.TotalParameterCount = cpu_to_le16(params);
4098         pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
4099         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4100         pSMB->Pad = 0;
4101         pSMB->Fid = netfid;
4102         inc_rfc1001_len(pSMB, byte_count);
4103
4104         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4105                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4106         if (rc) {
4107                 cFYI(1, "Send error in QPathInfo = %d", rc);
4108         } else {                /* decode response */
4109                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4110
4111                 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4112                         cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
4113                                    "Unix Extensions can be disabled on mount "
4114                                    "by specifying the nosfu mount option.");
4115                         rc = -EIO;      /* bad smb */
4116                 } else {
4117                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4118                         memcpy((char *) pFindData,
4119                                (char *) &pSMBr->hdr.Protocol +
4120                                data_offset,
4121                                sizeof(FILE_UNIX_BASIC_INFO));
4122                 }
4123         }
4124
4125         cifs_buf_release(pSMB);
4126         if (rc == -EAGAIN)
4127                 goto UnixQFileInfoRetry;
4128
4129         return rc;
4130 }
4131
4132 int
4133 CIFSSMBUnixQPathInfo(const int xid, struct cifs_tcon *tcon,
4134                      const unsigned char *searchName,
4135                      FILE_UNIX_BASIC_INFO *pFindData,
4136                      const struct nls_table *nls_codepage, int remap)
4137 {
4138 /* SMB_QUERY_FILE_UNIX_BASIC */
4139         TRANSACTION2_QPI_REQ *pSMB = NULL;
4140         TRANSACTION2_QPI_RSP *pSMBr = NULL;
4141         int rc = 0;
4142         int bytes_returned = 0;
4143         int name_len;
4144         __u16 params, byte_count;
4145
4146         cFYI(1, "In QPathInfo (Unix) the path %s", searchName);
4147 UnixQPathInfoRetry:
4148         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4149                       (void **) &pSMBr);
4150         if (rc)
4151                 return rc;
4152
4153         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4154                 name_len =
4155                     cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4156                                        PATH_MAX, nls_codepage, remap);
4157                 name_len++;     /* trailing null */
4158                 name_len *= 2;
4159         } else {        /* BB improve the check for buffer overruns BB */
4160                 name_len = strnlen(searchName, PATH_MAX);
4161                 name_len++;     /* trailing null */
4162                 strncpy(pSMB->FileName, searchName, name_len);
4163         }
4164
4165         params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
4166         pSMB->TotalDataCount = 0;
4167         pSMB->MaxParameterCount = cpu_to_le16(2);
4168         /* BB find exact max SMB PDU from sess structure BB */
4169         pSMB->MaxDataCount = cpu_to_le16(4000);
4170         pSMB->MaxSetupCount = 0;
4171         pSMB->Reserved = 0;
4172         pSMB->Flags = 0;
4173         pSMB->Timeout = 0;
4174         pSMB->Reserved2 = 0;
4175         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4176         struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4177         pSMB->DataCount = 0;
4178         pSMB->DataOffset = 0;
4179         pSMB->SetupCount = 1;
4180         pSMB->Reserved3 = 0;
4181         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4182         byte_count = params + 1 /* pad */ ;
4183         pSMB->TotalParameterCount = cpu_to_le16(params);
4184         pSMB->ParameterCount = pSMB->TotalParameterCount;
4185         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
4186         pSMB->Reserved4 = 0;
4187         inc_rfc1001_len(pSMB, byte_count);
4188         pSMB->ByteCount = cpu_to_le16(byte_count);
4189
4190         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4191                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4192         if (rc) {
4193                 cFYI(1, "Send error in QPathInfo = %d", rc);
4194         } else {                /* decode response */
4195                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4196
4197                 if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) {
4198                         cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
4199                                    "Unix Extensions can be disabled on mount "
4200                                    "by specifying the nosfu mount option.");
4201                         rc = -EIO;      /* bad smb */
4202                 } else {
4203                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4204                         memcpy((char *) pFindData,
4205                                (char *) &pSMBr->hdr.Protocol +
4206                                data_offset,
4207                                sizeof(FILE_UNIX_BASIC_INFO));
4208                 }
4209         }
4210         cifs_buf_release(pSMB);
4211         if (rc == -EAGAIN)
4212                 goto UnixQPathInfoRetry;
4213
4214         return rc;
4215 }
4216
4217 /* xid, tcon, searchName and codepage are input parms, rest are returned */
4218 int
4219 CIFSFindFirst(const int xid, struct cifs_tcon *tcon,
4220               const char *searchName,
4221               const struct nls_table *nls_codepage,
4222               __u16 *pnetfid, __u16 search_flags,
4223               struct cifs_search_info *psrch_inf, int remap, const char dirsep)
4224 {
4225 /* level 257 SMB_ */
4226         TRANSACTION2_FFIRST_REQ *pSMB = NULL;
4227         TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
4228         T2_FFIRST_RSP_PARMS *parms;
4229         int rc = 0;
4230         int bytes_returned = 0;
4231         int name_len;
4232         __u16 params, byte_count;
4233
4234         cFYI(1, "In FindFirst for %s", searchName);
4235
4236 findFirstRetry:
4237         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4238                       (void **) &pSMBr);
4239         if (rc)
4240                 return rc;
4241
4242         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4243                 name_len =
4244                     cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
4245                                        PATH_MAX, nls_codepage, remap);
4246                 /* We can not add the asterik earlier in case
4247                 it got remapped to 0xF03A as if it were part of the
4248                 directory name instead of a wildcard */
4249                 name_len *= 2;
4250                 pSMB->FileName[name_len] = dirsep;
4251                 pSMB->FileName[name_len+1] = 0;
4252                 pSMB->FileName[name_len+2] = '*';
4253                 pSMB->FileName[name_len+3] = 0;
4254                 name_len += 4; /* now the trailing null */
4255                 pSMB->FileName[name_len] = 0; /* null terminate just in case */
4256                 pSMB->FileName[name_len+1] = 0;
4257                 name_len += 2;
4258         } else {        /* BB add check for overrun of SMB buf BB */
4259                 name_len = strnlen(searchName, PATH_MAX);
4260 /* BB fix here and in unicode clause above ie
4261                 if (name_len > buffersize-header)
4262                         free buffer exit; BB */
4263                 strncpy(pSMB->FileName, searchName, name_len);
4264                 pSMB->FileName[name_len] = dirsep;
4265                 pSMB->FileName[name_len+1] = '*';
4266                 pSMB->FileName[name_len+2] = 0;
4267                 name_len += 3;
4268         }
4269
4270         params = 12 + name_len /* includes null */ ;
4271         pSMB->TotalDataCount = 0;       /* no EAs */
4272         pSMB->MaxParameterCount = cpu_to_le16(10);
4273         pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4274         pSMB->MaxSetupCount = 0;
4275         pSMB->Reserved = 0;
4276         pSMB->Flags = 0;
4277         pSMB->Timeout = 0;
4278         pSMB->Reserved2 = 0;
4279         byte_count = params + 1 /* pad */ ;
4280         pSMB->TotalParameterCount = cpu_to_le16(params);
4281         pSMB->ParameterCount = pSMB->TotalParameterCount;
4282         pSMB->ParameterOffset = cpu_to_le16(
4283               offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
4284                 - 4);
4285         pSMB->DataCount = 0;
4286         pSMB->DataOffset = 0;
4287         pSMB->SetupCount = 1;   /* one byte, no need to make endian neutral */
4288         pSMB->Reserved3 = 0;
4289         pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
4290         pSMB->SearchAttributes =
4291             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
4292                         ATTR_DIRECTORY);
4293         pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
4294         pSMB->SearchFlags = cpu_to_le16(search_flags);
4295         pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4296
4297         /* BB what should we set StorageType to? Does it matter? BB */
4298         pSMB->SearchStorageType = 0;
4299         inc_rfc1001_len(pSMB, byte_count);
4300         pSMB->ByteCount = cpu_to_le16(byte_count);
4301
4302         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4303                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4304         cifs_stats_inc(&tcon->num_ffirst);
4305
4306         if (rc) {/* BB add logic to retry regular search if Unix search
4307                         rejected unexpectedly by server */
4308                 /* BB Add code to handle unsupported level rc */
4309                 cFYI(1, "Error in FindFirst = %d", rc);
4310
4311                 cifs_buf_release(pSMB);
4312
4313                 /* BB eventually could optimize out free and realloc of buf */
4314                 /*    for this case */
4315                 if (rc == -EAGAIN)
4316                         goto findFirstRetry;
4317         } else { /* decode response */
4318                 /* BB remember to free buffer if error BB */
4319                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4320                 if (rc == 0) {
4321                         unsigned int lnoff;
4322
4323                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4324                                 psrch_inf->unicode = true;
4325                         else
4326                                 psrch_inf->unicode = false;
4327
4328                         psrch_inf->ntwrk_buf_start = (char *)pSMBr;
4329                         psrch_inf->smallBuf = 0;
4330                         psrch_inf->srch_entries_start =
4331                                 (char *) &pSMBr->hdr.Protocol +
4332                                         le16_to_cpu(pSMBr->t2.DataOffset);
4333                         parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
4334                                le16_to_cpu(pSMBr->t2.ParameterOffset));
4335
4336                         if (parms->EndofSearch)
4337                                 psrch_inf->endOfSearch = true;
4338                         else
4339                                 psrch_inf->endOfSearch = false;
4340
4341                         psrch_inf->entries_in_buffer =
4342                                         le16_to_cpu(parms->SearchCount);
4343                         psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
4344                                 psrch_inf->entries_in_buffer;
4345                         lnoff = le16_to_cpu(parms->LastNameOffset);
4346                         if (CIFSMaxBufSize < lnoff) {
4347                                 cERROR(1, "ignoring corrupt resume name");
4348                                 psrch_inf->last_entry = NULL;
4349                                 return rc;
4350                         }
4351
4352                         psrch_inf->last_entry = psrch_inf->srch_entries_start +
4353                                                         lnoff;
4354
4355                         *pnetfid = parms->SearchHandle;
4356                 } else {
4357                         cifs_buf_release(pSMB);
4358                 }
4359         }
4360
4361         return rc;
4362 }
4363
4364 int CIFSFindNext(const int xid, struct cifs_tcon *tcon, __u16 searchHandle,
4365                  __u16 search_flags, struct cifs_search_info *psrch_inf)
4366 {
4367         TRANSACTION2_FNEXT_REQ *pSMB = NULL;
4368         TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
4369         T2_FNEXT_RSP_PARMS *parms;
4370         char *response_data;
4371         int rc = 0;
4372         int bytes_returned;
4373         unsigned int name_len;
4374         __u16 params, byte_count;
4375
4376         cFYI(1, "In FindNext");
4377
4378         if (psrch_inf->endOfSearch)
4379                 return -ENOENT;
4380
4381         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4382                 (void **) &pSMBr);
4383         if (rc)
4384                 return rc;
4385
4386         params = 14; /* includes 2 bytes of null string, converted to LE below*/
4387         byte_count = 0;
4388         pSMB->TotalDataCount = 0;       /* no EAs */
4389         pSMB->MaxParameterCount = cpu_to_le16(8);
4390         pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00);
4391         pSMB->MaxSetupCount = 0;
4392         pSMB->Reserved = 0;
4393         pSMB->Flags = 0;
4394         pSMB->Timeout = 0;
4395         pSMB->Reserved2 = 0;
4396         pSMB->ParameterOffset =  cpu_to_le16(
4397               offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
4398         pSMB->DataCount = 0;
4399         pSMB->DataOffset = 0;
4400         pSMB->SetupCount = 1;
4401         pSMB->Reserved3 = 0;
4402         pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
4403         pSMB->SearchHandle = searchHandle;      /* always kept as le */
4404         pSMB->SearchCount =
4405                 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
4406         pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4407         pSMB->ResumeKey = psrch_inf->resume_key;
4408         pSMB->SearchFlags = cpu_to_le16(search_flags);
4409
4410         name_len = psrch_inf->resume_name_len;
4411         params += name_len;
4412         if (name_len < PATH_MAX) {
4413                 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
4414                 byte_count += name_len;
4415                 /* 14 byte parm len above enough for 2 byte null terminator */
4416                 pSMB->ResumeFileName[name_len] = 0;
4417                 pSMB->ResumeFileName[name_len+1] = 0;
4418         } else {
4419                 rc = -EINVAL;
4420                 goto FNext2_err_exit;
4421         }
4422         byte_count = params + 1 /* pad */ ;
4423         pSMB->TotalParameterCount = cpu_to_le16(params);
4424         pSMB->ParameterCount = pSMB->TotalParameterCount;
4425         inc_rfc1001_len(pSMB, byte_count);
4426         pSMB->ByteCount = cpu_to_le16(byte_count);
4427
4428         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4429                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4430         cifs_stats_inc(&tcon->num_fnext);
4431         if (rc) {
4432                 if (rc == -EBADF) {
4433                         psrch_inf->endOfSearch = true;
4434                         cifs_buf_release(pSMB);
4435                         rc = 0; /* search probably was closed at end of search*/
4436                 } else
4437                         cFYI(1, "FindNext returned = %d", rc);
4438         } else {                /* decode response */
4439                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4440
4441                 if (rc == 0) {
4442                         unsigned int lnoff;
4443
4444                         /* BB fixme add lock for file (srch_info) struct here */
4445                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4446                                 psrch_inf->unicode = true;
4447                         else
4448                                 psrch_inf->unicode = false;
4449                         response_data = (char *) &pSMBr->hdr.Protocol +
4450                                le16_to_cpu(pSMBr->t2.ParameterOffset);
4451                         parms = (T2_FNEXT_RSP_PARMS *)response_data;
4452                         response_data = (char *)&pSMBr->hdr.Protocol +
4453                                 le16_to_cpu(pSMBr->t2.DataOffset);
4454                         if (psrch_inf->smallBuf)
4455                                 cifs_small_buf_release(
4456                                         psrch_inf->ntwrk_buf_start);
4457                         else
4458                                 cifs_buf_release(psrch_inf->ntwrk_buf_start);
4459                         psrch_inf->srch_entries_start = response_data;
4460                         psrch_inf->ntwrk_buf_start = (char *)pSMB;
4461                         psrch_inf->smallBuf = 0;
4462                         if (parms->EndofSearch)
4463                                 psrch_inf->endOfSearch = true;
4464                         else
4465                                 psrch_inf->endOfSearch = false;
4466                         psrch_inf->entries_in_buffer =
4467                                                 le16_to_cpu(parms->SearchCount);
4468                         psrch_inf->index_of_last_entry +=
4469                                 psrch_inf->entries_in_buffer;
4470                         lnoff = le16_to_cpu(parms->LastNameOffset);
4471                         if (CIFSMaxBufSize < lnoff) {
4472                                 cERROR(1, "ignoring corrupt resume name");
4473                                 psrch_inf->last_entry = NULL;
4474                                 return rc;
4475                         } else
4476                                 psrch_inf->last_entry =
4477                                         psrch_inf->srch_entries_start + lnoff;
4478
4479 /*  cFYI(1, "fnxt2 entries in buf %d index_of_last %d",
4480             psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
4481
4482                         /* BB fixme add unlock here */
4483                 }
4484
4485         }
4486
4487         /* BB On error, should we leave previous search buf (and count and
4488         last entry fields) intact or free the previous one? */
4489
4490         /* Note: On -EAGAIN error only caller can retry on handle based calls
4491         since file handle passed in no longer valid */
4492 FNext2_err_exit:
4493         if (rc != 0)
4494                 cifs_buf_release(pSMB);
4495         return rc;
4496 }
4497
4498 int
4499 CIFSFindClose(const int xid, struct cifs_tcon *tcon,
4500               const __u16 searchHandle)
4501 {
4502         int rc = 0;
4503         FINDCLOSE_REQ *pSMB = NULL;
4504
4505         cFYI(1, "In CIFSSMBFindClose");
4506         rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
4507
4508         /* no sense returning error if session restarted
4509                 as file handle has been closed */
4510         if (rc == -EAGAIN)
4511                 return 0;
4512         if (rc)
4513                 return rc;
4514
4515         pSMB->FileID = searchHandle;
4516         pSMB->ByteCount = 0;
4517         rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
4518         if (rc)
4519                 cERROR(1, "Send error in FindClose = %d", rc);
4520
4521         cifs_stats_inc(&tcon->num_fclose);
4522
4523         /* Since session is dead, search handle closed on server already */
4524         if (rc == -EAGAIN)
4525                 rc = 0;
4526
4527         return rc;
4528 }
4529
4530 int
4531 CIFSGetSrvInodeNumber(const int xid, struct cifs_tcon *tcon,
4532                       const unsigned char *searchName,
4533                       __u64 *inode_number,
4534                       const struct nls_table *nls_codepage, int remap)
4535 {
4536         int rc = 0;
4537         TRANSACTION2_QPI_REQ *pSMB = NULL;
4538         TRANSACTION2_QPI_RSP *pSMBr = NULL;
4539         int name_len, bytes_returned;
4540         __u16 params, byte_count;
4541
4542         cFYI(1, "In GetSrvInodeNum for %s", searchName);
4543         if (tcon == NULL)
4544                 return -ENODEV;
4545
4546 GetInodeNumberRetry:
4547         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4548                       (void **) &pSMBr);
4549         if (rc)
4550                 return rc;
4551
4552         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4553                 name_len =
4554                         cifsConvertToUTF16((__le16 *) pSMB->FileName,
4555                                            searchName, PATH_MAX, nls_codepage,
4556                                            remap);
4557                 name_len++;     /* trailing null */
4558                 name_len *= 2;
4559         } else {        /* BB improve the check for buffer overruns BB */
4560                 name_len = strnlen(searchName, PATH_MAX);
4561                 name_len++;     /* trailing null */
4562                 strncpy(pSMB->FileName, searchName, name_len);
4563         }
4564
4565         params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
4566         pSMB->TotalDataCount = 0;
4567         pSMB->MaxParameterCount = cpu_to_le16(2);
4568         /* BB find exact max data count below from sess structure BB */
4569         pSMB->MaxDataCount = cpu_to_le16(4000);
4570         pSMB->MaxSetupCount = 0;
4571         pSMB->Reserved = 0;
4572         pSMB->Flags = 0;
4573         pSMB->Timeout = 0;
4574         pSMB->Reserved2 = 0;
4575         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4576                 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4577         pSMB->DataCount = 0;
4578         pSMB->DataOffset = 0;
4579         pSMB->SetupCount = 1;
4580         pSMB->Reserved3 = 0;
4581         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4582         byte_count = params + 1 /* pad */ ;
4583         pSMB->TotalParameterCount = cpu_to_le16(params);
4584         pSMB->ParameterCount = pSMB->TotalParameterCount;
4585         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
4586         pSMB->Reserved4 = 0;
4587         inc_rfc1001_len(pSMB, byte_count);
4588         pSMB->ByteCount = cpu_to_le16(byte_count);
4589
4590         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4591                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4592         if (rc) {
4593                 cFYI(1, "error %d in QueryInternalInfo", rc);
4594         } else {
4595                 /* decode response */
4596                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4597                 /* BB also check enough total bytes returned */
4598                 if (rc || get_bcc(&pSMBr->hdr) < 2)
4599                         /* If rc should we check for EOPNOSUPP and
4600                         disable the srvino flag? or in caller? */
4601                         rc = -EIO;      /* bad smb */
4602                 else {
4603                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4604                         __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
4605                         struct file_internal_info *pfinfo;
4606                         /* BB Do we need a cast or hash here ? */
4607                         if (count < 8) {
4608                                 cFYI(1, "Illegal size ret in QryIntrnlInf");
4609                                 rc = -EIO;
4610                                 goto GetInodeNumOut;
4611                         }
4612                         pfinfo = (struct file_internal_info *)
4613                                 (data_offset + (char *) &pSMBr->hdr.Protocol);
4614                         *inode_number = le64_to_cpu(pfinfo->UniqueId);
4615                 }
4616         }
4617 GetInodeNumOut:
4618         cifs_buf_release(pSMB);
4619         if (rc == -EAGAIN)
4620                 goto GetInodeNumberRetry;
4621         return rc;
4622 }
4623
4624 /* parses DFS refferal V3 structure
4625  * caller is responsible for freeing target_nodes
4626  * returns:
4627  *      on success - 0
4628  *      on failure - errno
4629  */
4630 static int
4631 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
4632                 unsigned int *num_of_nodes,
4633                 struct dfs_info3_param **target_nodes,
4634                 const struct nls_table *nls_codepage, int remap,
4635                 const char *searchName)
4636 {
4637         int i, rc = 0;
4638         char *data_end;
4639         bool is_unicode;
4640         struct dfs_referral_level_3 *ref;
4641
4642         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4643                 is_unicode = true;
4644         else
4645                 is_unicode = false;
4646         *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
4647
4648         if (*num_of_nodes < 1) {
4649                 cERROR(1, "num_referrals: must be at least > 0,"
4650                         "but we get num_referrals = %d\n", *num_of_nodes);
4651                 rc = -EINVAL;
4652                 goto parse_DFS_referrals_exit;
4653         }
4654
4655         ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
4656         if (ref->VersionNumber != cpu_to_le16(3)) {
4657                 cERROR(1, "Referrals of V%d version are not supported,"
4658                         "should be V3", le16_to_cpu(ref->VersionNumber));
4659                 rc = -EINVAL;
4660                 goto parse_DFS_referrals_exit;
4661         }
4662
4663         /* get the upper boundary of the resp buffer */
4664         data_end = (char *)(&(pSMBr->PathConsumed)) +
4665                                 le16_to_cpu(pSMBr->t2.DataCount);
4666
4667         cFYI(1, "num_referrals: %d dfs flags: 0x%x ...\n",
4668                         *num_of_nodes,
4669                         le32_to_cpu(pSMBr->DFSFlags));
4670
4671         *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
4672                         *num_of_nodes, GFP_KERNEL);
4673         if (*target_nodes == NULL) {
4674                 cERROR(1, "Failed to allocate buffer for target_nodes\n");
4675                 rc = -ENOMEM;
4676                 goto parse_DFS_referrals_exit;
4677         }
4678
4679         /* collect necessary data from referrals */
4680         for (i = 0; i < *num_of_nodes; i++) {
4681                 char *temp;
4682                 int max_len;
4683                 struct dfs_info3_param *node = (*target_nodes)+i;
4684
4685                 node->flags = le32_to_cpu(pSMBr->DFSFlags);
4686                 if (is_unicode) {
4687                         __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
4688                                                 GFP_KERNEL);
4689                         if (tmp == NULL) {
4690                                 rc = -ENOMEM;
4691                                 goto parse_DFS_referrals_exit;
4692                         }
4693                         cifsConvertToUTF16((__le16 *) tmp, searchName,
4694                                            PATH_MAX, nls_codepage, remap);
4695                         node->path_consumed = cifs_utf16_bytes(tmp,
4696                                         le16_to_cpu(pSMBr->PathConsumed),
4697                                         nls_codepage);
4698                         kfree(tmp);
4699                 } else
4700                         node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
4701
4702                 node->server_type = le16_to_cpu(ref->ServerType);
4703                 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
4704
4705                 /* copy DfsPath */
4706                 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
4707                 max_len = data_end - temp;
4708                 node->path_name = cifs_strndup_from_utf16(temp, max_len,
4709                                                 is_unicode, nls_codepage);
4710                 if (!node->path_name) {
4711                         rc = -ENOMEM;
4712                         goto parse_DFS_referrals_exit;
4713                 }
4714
4715                 /* copy link target UNC */
4716                 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
4717                 max_len = data_end - temp;
4718                 node->node_name = cifs_strndup_from_utf16(temp, max_len,
4719                                                 is_unicode, nls_codepage);
4720                 if (!node->node_name) {
4721                         rc = -ENOMEM;
4722                         goto parse_DFS_referrals_exit;
4723                 }
4724
4725                 ref++;
4726         }
4727
4728 parse_DFS_referrals_exit:
4729         if (rc) {
4730                 free_dfs_info_array(*target_nodes, *num_of_nodes);
4731                 *target_nodes = NULL;
4732                 *num_of_nodes = 0;
4733         }
4734         return rc;
4735 }
4736
4737 int
4738 CIFSGetDFSRefer(const int xid, struct cifs_ses *ses,
4739                 const unsigned char *searchName,
4740                 struct dfs_info3_param **target_nodes,
4741                 unsigned int *num_of_nodes,
4742                 const struct nls_table *nls_codepage, int remap)
4743 {
4744 /* TRANS2_GET_DFS_REFERRAL */
4745         TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4746         TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4747         int rc = 0;
4748         int bytes_returned;
4749         int name_len;
4750         __u16 params, byte_count;
4751         *num_of_nodes = 0;
4752         *target_nodes = NULL;
4753
4754         cFYI(1, "In GetDFSRefer the path %s", searchName);
4755         if (ses == NULL)
4756                 return -ENODEV;
4757 getDFSRetry:
4758         rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4759                       (void **) &pSMBr);
4760         if (rc)
4761                 return rc;
4762
4763         /* server pointer checked in called function,
4764         but should never be null here anyway */
4765         pSMB->hdr.Mid = GetNextMid(ses->server);
4766         pSMB->hdr.Tid = ses->ipc_tid;
4767         pSMB->hdr.Uid = ses->Suid;
4768         if (ses->capabilities & CAP_STATUS32)
4769                 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4770         if (ses->capabilities & CAP_DFS)
4771                 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4772
4773         if (ses->capabilities & CAP_UNICODE) {
4774                 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4775                 name_len =
4776                     cifsConvertToUTF16((__le16 *) pSMB->RequestFileName,
4777                                        searchName, PATH_MAX, nls_codepage,
4778                                        remap);
4779                 name_len++;     /* trailing null */
4780                 name_len *= 2;
4781         } else {        /* BB improve the check for buffer overruns BB */
4782                 name_len = strnlen(searchName, PATH_MAX);
4783                 name_len++;     /* trailing null */
4784                 strncpy(pSMB->RequestFileName, searchName, name_len);
4785         }
4786
4787         if (ses->server) {
4788                 if (ses->server->sec_mode &
4789                    (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4790                         pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4791         }
4792
4793         pSMB->hdr.Uid = ses->Suid;
4794
4795         params = 2 /* level */  + name_len /*includes null */ ;
4796         pSMB->TotalDataCount = 0;
4797         pSMB->DataCount = 0;
4798         pSMB->DataOffset = 0;
4799         pSMB->MaxParameterCount = 0;
4800         /* BB find exact max SMB PDU from sess structure BB */
4801         pSMB->MaxDataCount = cpu_to_le16(4000);
4802         pSMB->MaxSetupCount = 0;
4803         pSMB->Reserved = 0;
4804         pSMB->Flags = 0;
4805         pSMB->Timeout = 0;
4806         pSMB->Reserved2 = 0;
4807         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4808           struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4809         pSMB->SetupCount = 1;
4810         pSMB->Reserved3 = 0;
4811         pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4812         byte_count = params + 3 /* pad */ ;
4813         pSMB->ParameterCount = cpu_to_le16(params);
4814         pSMB->TotalParameterCount = pSMB->ParameterCount;
4815         pSMB->MaxReferralLevel = cpu_to_le16(3);
4816         inc_rfc1001_len(pSMB, byte_count);
4817         pSMB->ByteCount = cpu_to_le16(byte_count);
4818
4819         rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4820                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4821         if (rc) {
4822                 cFYI(1, "Send error in GetDFSRefer = %d", rc);
4823                 goto GetDFSRefExit;
4824         }
4825         rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4826
4827         /* BB Also check if enough total bytes returned? */
4828         if (rc || get_bcc(&pSMBr->hdr) < 17) {
4829                 rc = -EIO;      /* bad smb */
4830                 goto GetDFSRefExit;
4831         }
4832
4833         cFYI(1, "Decoding GetDFSRefer response BCC: %d  Offset %d",
4834                                 get_bcc(&pSMBr->hdr),
4835                                 le16_to_cpu(pSMBr->t2.DataOffset));
4836
4837         /* parse returned result into more usable form */
4838         rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4839                                  target_nodes, nls_codepage, remap,
4840                                  searchName);
4841
4842 GetDFSRefExit:
4843         cifs_buf_release(pSMB);
4844
4845         if (rc == -EAGAIN)
4846                 goto getDFSRetry;
4847
4848         return rc;
4849 }
4850
4851 /* Query File System Info such as free space to old servers such as Win 9x */
4852 int
4853 SMBOldQFSInfo(const int xid, struct cifs_tcon *tcon, struct kstatfs *FSData)
4854 {
4855 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4856         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4857         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4858         FILE_SYSTEM_ALLOC_INFO *response_data;
4859         int rc = 0;
4860         int bytes_returned = 0;
4861         __u16 params, byte_count;
4862
4863         cFYI(1, "OldQFSInfo");
4864 oldQFSInfoRetry:
4865         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4866                 (void **) &pSMBr);
4867         if (rc)
4868                 return rc;
4869
4870         params = 2;     /* level */
4871         pSMB->TotalDataCount = 0;
4872         pSMB->MaxParameterCount = cpu_to_le16(2);
4873         pSMB->MaxDataCount = cpu_to_le16(1000);
4874         pSMB->MaxSetupCount = 0;
4875         pSMB->Reserved = 0;
4876         pSMB->Flags = 0;
4877         pSMB->Timeout = 0;
4878         pSMB->Reserved2 = 0;
4879         byte_count = params + 1 /* pad */ ;
4880         pSMB->TotalParameterCount = cpu_to_le16(params);
4881         pSMB->ParameterCount = pSMB->TotalParameterCount;
4882         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4883         struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4884         pSMB->DataCount = 0;
4885         pSMB->DataOffset = 0;
4886         pSMB->SetupCount = 1;
4887         pSMB->Reserved3 = 0;
4888         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4889         pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4890         inc_rfc1001_len(pSMB, byte_count);
4891         pSMB->ByteCount = cpu_to_le16(byte_count);
4892
4893         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4894                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4895         if (rc) {
4896                 cFYI(1, "Send error in QFSInfo = %d", rc);
4897         } else {                /* decode response */
4898                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4899
4900                 if (rc || get_bcc(&pSMBr->hdr) < 18)
4901                         rc = -EIO;      /* bad smb */
4902                 else {
4903                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4904                         cFYI(1, "qfsinf resp BCC: %d  Offset %d",
4905                                  get_bcc(&pSMBr->hdr), data_offset);
4906
4907                         response_data = (FILE_SYSTEM_ALLOC_INFO *)
4908                                 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4909                         FSData->f_bsize =
4910                                 le16_to_cpu(response_data->BytesPerSector) *
4911                                 le32_to_cpu(response_data->
4912                                         SectorsPerAllocationUnit);
4913                         FSData->f_blocks =
4914                                le32_to_cpu(response_data->TotalAllocationUnits);
4915                         FSData->f_bfree = FSData->f_bavail =
4916                                 le32_to_cpu(response_data->FreeAllocationUnits);
4917                         cFYI(1, "Blocks: %lld  Free: %lld Block size %ld",
4918                              (unsigned long long)FSData->f_blocks,
4919                              (unsigned long long)FSData->f_bfree,
4920                              FSData->f_bsize);
4921                 }
4922         }
4923         cifs_buf_release(pSMB);
4924
4925         if (rc == -EAGAIN)
4926                 goto oldQFSInfoRetry;
4927
4928         return rc;
4929 }
4930
4931 int
4932 CIFSSMBQFSInfo(const int xid, struct cifs_tcon *tcon, struct kstatfs *FSData)
4933 {
4934 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4935         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4936         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4937         FILE_SYSTEM_INFO *response_data;
4938         int rc = 0;
4939         int bytes_returned = 0;
4940         __u16 params, byte_count;
4941
4942         cFYI(1, "In QFSInfo");
4943 QFSInfoRetry:
4944         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4945                       (void **) &pSMBr);
4946         if (rc)
4947                 return rc;
4948
4949         params = 2;     /* level */
4950         pSMB->TotalDataCount = 0;
4951         pSMB->MaxParameterCount = cpu_to_le16(2);
4952         pSMB->MaxDataCount = cpu_to_le16(1000);
4953         pSMB->MaxSetupCount = 0;
4954         pSMB->Reserved = 0;
4955         pSMB->Flags = 0;
4956         pSMB->Timeout = 0;
4957         pSMB->Reserved2 = 0;
4958         byte_count = params + 1 /* pad */ ;
4959         pSMB->TotalParameterCount = cpu_to_le16(params);
4960         pSMB->ParameterCount = pSMB->TotalParameterCount;
4961         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4962                 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4963         pSMB->DataCount = 0;
4964         pSMB->DataOffset = 0;
4965         pSMB->SetupCount = 1;
4966         pSMB->Reserved3 = 0;
4967         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4968         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4969         inc_rfc1001_len(pSMB, byte_count);
4970         pSMB->ByteCount = cpu_to_le16(byte_count);
4971
4972         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4973                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4974         if (rc) {
4975                 cFYI(1, "Send error in QFSInfo = %d", rc);
4976         } else {                /* decode response */
4977                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4978
4979                 if (rc || get_bcc(&pSMBr->hdr) < 24)
4980                         rc = -EIO;      /* bad smb */
4981                 else {
4982                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4983
4984                         response_data =
4985                             (FILE_SYSTEM_INFO
4986                              *) (((char *) &pSMBr->hdr.Protocol) +
4987                                  data_offset);
4988                         FSData->f_bsize =
4989                             le32_to_cpu(response_data->BytesPerSector) *
4990                             le32_to_cpu(response_data->
4991                                         SectorsPerAllocationUnit);
4992                         FSData->f_blocks =
4993                             le64_to_cpu(response_data->TotalAllocationUnits);
4994                         FSData->f_bfree = FSData->f_bavail =
4995                             le64_to_cpu(response_data->FreeAllocationUnits);
4996                         cFYI(1, "Blocks: %lld  Free: %lld Block size %ld",
4997                              (unsigned long long)FSData->f_blocks,
4998                              (unsigned long long)FSData->f_bfree,
4999                              FSData->f_bsize);
5000                 }
5001         }
5002         cifs_buf_release(pSMB);
5003
5004         if (rc == -EAGAIN)
5005                 goto QFSInfoRetry;
5006
5007         return rc;
5008 }
5009
5010 int
5011 CIFSSMBQFSAttributeInfo(const int xid, struct cifs_tcon *tcon)
5012 {
5013 /* level 0x105  SMB_QUERY_FILE_SYSTEM_INFO */
5014         TRANSACTION2_QFSI_REQ *pSMB = NULL;
5015         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5016         FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
5017         int rc = 0;
5018         int bytes_returned = 0;
5019         __u16 params, byte_count;
5020
5021         cFYI(1, "In QFSAttributeInfo");
5022 QFSAttributeRetry:
5023         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5024                       (void **) &pSMBr);
5025         if (rc)
5026                 return rc;
5027
5028         params = 2;     /* level */
5029         pSMB->TotalDataCount = 0;
5030         pSMB->MaxParameterCount = cpu_to_le16(2);
5031         /* BB find exact max SMB PDU from sess structure BB */
5032         pSMB->MaxDataCount = cpu_to_le16(1000);
5033         pSMB->MaxSetupCount = 0;
5034         pSMB->Reserved = 0;
5035         pSMB->Flags = 0;
5036         pSMB->Timeout = 0;
5037         pSMB->Reserved2 = 0;
5038         byte_count = params + 1 /* pad */ ;
5039         pSMB->TotalParameterCount = cpu_to_le16(params);
5040         pSMB->ParameterCount = pSMB->TotalParameterCount;
5041         pSMB->ParameterOffset = cpu_to_le16(offsetof(
5042                 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5043         pSMB->DataCount = 0;
5044         pSMB->DataOffset = 0;
5045         pSMB->SetupCount = 1;
5046         pSMB->Reserved3 = 0;
5047         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5048         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
5049         inc_rfc1001_len(pSMB, byte_count);
5050         pSMB->ByteCount = cpu_to_le16(byte_count);
5051
5052         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5053                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5054         if (rc) {
5055                 cERROR(1, "Send error in QFSAttributeInfo = %d", rc);
5056         } else {                /* decode response */
5057                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5058
5059                 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5060                         /* BB also check if enough bytes returned */
5061                         rc = -EIO;      /* bad smb */
5062                 } else {
5063                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5064                         response_data =
5065                             (FILE_SYSTEM_ATTRIBUTE_INFO
5066                              *) (((char *) &pSMBr->hdr.Protocol) +
5067                                  data_offset);
5068                         memcpy(&tcon->fsAttrInfo, response_data,
5069                                sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
5070                 }
5071         }
5072         cifs_buf_release(pSMB);
5073
5074         if (rc == -EAGAIN)
5075                 goto QFSAttributeRetry;
5076
5077         return rc;
5078 }
5079
5080 int
5081 CIFSSMBQFSDeviceInfo(const int xid, struct cifs_tcon *tcon)
5082 {
5083 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
5084         TRANSACTION2_QFSI_REQ *pSMB = NULL;
5085         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5086         FILE_SYSTEM_DEVICE_INFO *response_data;
5087         int rc = 0;
5088         int bytes_returned = 0;
5089         __u16 params, byte_count;
5090
5091         cFYI(1, "In QFSDeviceInfo");
5092 QFSDeviceRetry:
5093         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5094                       (void **) &pSMBr);
5095         if (rc)
5096                 return rc;
5097
5098         params = 2;     /* level */
5099         pSMB->TotalDataCount = 0;
5100         pSMB->MaxParameterCount = cpu_to_le16(2);
5101         /* BB find exact max SMB PDU from sess structure BB */
5102         pSMB->MaxDataCount = cpu_to_le16(1000);
5103         pSMB->MaxSetupCount = 0;
5104         pSMB->Reserved = 0;
5105         pSMB->Flags = 0;
5106         pSMB->Timeout = 0;
5107         pSMB->Reserved2 = 0;
5108         byte_count = params + 1 /* pad */ ;
5109         pSMB->TotalParameterCount = cpu_to_le16(params);
5110         pSMB->ParameterCount = pSMB->TotalParameterCount;
5111         pSMB->ParameterOffset = cpu_to_le16(offsetof(
5112                 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5113
5114         pSMB->DataCount = 0;
5115         pSMB->DataOffset = 0;
5116         pSMB->SetupCount = 1;
5117         pSMB->Reserved3 = 0;
5118         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5119         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
5120         inc_rfc1001_len(pSMB, byte_count);
5121         pSMB->ByteCount = cpu_to_le16(byte_count);
5122
5123         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5124                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5125         if (rc) {
5126                 cFYI(1, "Send error in QFSDeviceInfo = %d", rc);
5127         } else {                /* decode response */
5128                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5129
5130                 if (rc || get_bcc(&pSMBr->hdr) <
5131                           sizeof(FILE_SYSTEM_DEVICE_INFO))
5132                         rc = -EIO;      /* bad smb */
5133                 else {
5134                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5135                         response_data =
5136                             (FILE_SYSTEM_DEVICE_INFO *)
5137                                 (((char *) &pSMBr->hdr.Protocol) +
5138                                  data_offset);
5139                         memcpy(&tcon->fsDevInfo, response_data,
5140                                sizeof(FILE_SYSTEM_DEVICE_INFO));
5141                 }
5142         }
5143         cifs_buf_release(pSMB);
5144
5145         if (rc == -EAGAIN)
5146                 goto QFSDeviceRetry;
5147
5148         return rc;
5149 }
5150
5151 int
5152 CIFSSMBQFSUnixInfo(const int xid, struct cifs_tcon *tcon)
5153 {
5154 /* level 0x200  SMB_QUERY_CIFS_UNIX_INFO */
5155         TRANSACTION2_QFSI_REQ *pSMB = NULL;
5156         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5157         FILE_SYSTEM_UNIX_INFO *response_data;
5158         int rc = 0;
5159         int bytes_returned = 0;
5160         __u16 params, byte_count;
5161
5162         cFYI(1, "In QFSUnixInfo");
5163 QFSUnixRetry:
5164         rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5165                                    (void **) &pSMB, (void **) &pSMBr);
5166         if (rc)
5167                 return rc;
5168
5169         params = 2;     /* level */
5170         pSMB->TotalDataCount = 0;
5171         pSMB->DataCount = 0;
5172         pSMB->DataOffset = 0;
5173         pSMB->MaxParameterCount = cpu_to_le16(2);
5174         /* BB find exact max SMB PDU from sess structure BB */
5175         pSMB->MaxDataCount = cpu_to_le16(100);
5176         pSMB->MaxSetupCount = 0;
5177         pSMB->Reserved = 0;
5178         pSMB->Flags = 0;
5179         pSMB->Timeout = 0;
5180         pSMB->Reserved2 = 0;
5181         byte_count = params + 1 /* pad */ ;
5182         pSMB->ParameterCount = cpu_to_le16(params);
5183         pSMB->TotalParameterCount = pSMB->ParameterCount;
5184         pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5185                         smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5186         pSMB->SetupCount = 1;
5187         pSMB->Reserved3 = 0;
5188         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5189         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
5190         inc_rfc1001_len(pSMB, byte_count);
5191         pSMB->ByteCount = cpu_to_le16(byte_count);
5192
5193         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5194                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5195         if (rc) {
5196                 cERROR(1, "Send error in QFSUnixInfo = %d", rc);
5197         } else {                /* decode response */
5198                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5199
5200                 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5201                         rc = -EIO;      /* bad smb */
5202                 } else {
5203                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5204                         response_data =
5205                             (FILE_SYSTEM_UNIX_INFO
5206                              *) (((char *) &pSMBr->hdr.Protocol) +
5207                                  data_offset);
5208                         memcpy(&tcon->fsUnixInfo, response_data,
5209                                sizeof(FILE_SYSTEM_UNIX_INFO));
5210                 }
5211         }
5212         cifs_buf_release(pSMB);
5213
5214         if (rc == -EAGAIN)
5215                 goto QFSUnixRetry;
5216
5217
5218         return rc;
5219 }
5220
5221 int
5222 CIFSSMBSetFSUnixInfo(const int xid, struct cifs_tcon *tcon, __u64 cap)
5223 {
5224 /* level 0x200  SMB_SET_CIFS_UNIX_INFO */
5225         TRANSACTION2_SETFSI_REQ *pSMB = NULL;
5226         TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
5227         int rc = 0;
5228         int bytes_returned = 0;
5229         __u16 params, param_offset, offset, byte_count;
5230
5231         cFYI(1, "In SETFSUnixInfo");
5232 SETFSUnixRetry:
5233         /* BB switch to small buf init to save memory */
5234         rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
5235                                         (void **) &pSMB, (void **) &pSMBr);
5236         if (rc)
5237                 return rc;
5238
5239         params = 4;     /* 2 bytes zero followed by info level. */
5240         pSMB->MaxSetupCount = 0;
5241         pSMB->Reserved = 0;
5242         pSMB->Flags = 0;
5243         pSMB->Timeout = 0;
5244         pSMB->Reserved2 = 0;
5245         param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
5246                                 - 4;
5247         offset = param_offset + params;
5248
5249         pSMB->MaxParameterCount = cpu_to_le16(4);
5250         /* BB find exact max SMB PDU from sess structure BB */
5251         pSMB->MaxDataCount = cpu_to_le16(100);
5252         pSMB->SetupCount = 1;
5253         pSMB->Reserved3 = 0;
5254         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
5255         byte_count = 1 /* pad */ + params + 12;
5256
5257         pSMB->DataCount = cpu_to_le16(12);
5258         pSMB->ParameterCount = cpu_to_le16(params);
5259         pSMB->TotalDataCount = pSMB->DataCount;
5260         pSMB->TotalParameterCount = pSMB->ParameterCount;
5261         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5262         pSMB->DataOffset = cpu_to_le16(offset);
5263
5264         /* Params. */
5265         pSMB->FileNum = 0;
5266         pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
5267
5268         /* Data. */
5269         pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
5270         pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
5271         pSMB->ClientUnixCap = cpu_to_le64(cap);
5272
5273         inc_rfc1001_len(pSMB, byte_count);
5274         pSMB->ByteCount = cpu_to_le16(byte_count);
5275
5276         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5277                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5278         if (rc) {
5279                 cERROR(1, "Send error in SETFSUnixInfo = %d", rc);
5280         } else {                /* decode response */
5281                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5282                 if (rc)
5283                         rc = -EIO;      /* bad smb */
5284         }
5285         cifs_buf_release(pSMB);
5286
5287         if (rc == -EAGAIN)
5288                 goto SETFSUnixRetry;
5289
5290         return rc;
5291 }
5292
5293
5294
5295 int
5296 CIFSSMBQFSPosixInfo(const int xid, struct cifs_tcon *tcon,
5297                    struct kstatfs *FSData)
5298 {
5299 /* level 0x201  SMB_QUERY_CIFS_POSIX_INFO */
5300         TRANSACTION2_QFSI_REQ *pSMB = NULL;
5301         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5302         FILE_SYSTEM_POSIX_INFO *response_data;
5303         int rc = 0;
5304         int bytes_returned = 0;
5305         __u16 params, byte_count;
5306
5307         cFYI(1, "In QFSPosixInfo");
5308 QFSPosixRetry:
5309         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5310                       (void **) &pSMBr);
5311         if (rc)
5312                 return rc;
5313
5314         params = 2;     /* level */
5315         pSMB->TotalDataCount = 0;
5316         pSMB->DataCount = 0;
5317         pSMB->DataOffset = 0;
5318         pSMB->MaxParameterCount = cpu_to_le16(2);
5319         /* BB find exact max SMB PDU from sess structure BB */
5320         pSMB->MaxDataCount = cpu_to_le16(100);
5321         pSMB->MaxSetupCount = 0;
5322         pSMB->Reserved = 0;
5323         pSMB->Flags = 0;
5324         pSMB->Timeout = 0;
5325         pSMB->Reserved2 = 0;
5326         byte_count = params + 1 /* pad */ ;
5327         pSMB->ParameterCount = cpu_to_le16(params);
5328         pSMB->TotalParameterCount = pSMB->ParameterCount;
5329         pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5330                         smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5331         pSMB->SetupCount = 1;
5332         pSMB->Reserved3 = 0;
5333         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5334         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
5335         inc_rfc1001_len(pSMB, byte_count);
5336         pSMB->ByteCount = cpu_to_le16(byte_count);
5337
5338         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5339                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5340         if (rc) {
5341                 cFYI(1, "Send error in QFSUnixInfo = %d", rc);
5342         } else {                /* decode response */
5343                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5344
5345                 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5346                         rc = -EIO;      /* bad smb */
5347                 } else {
5348                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5349                         response_data =
5350                             (FILE_SYSTEM_POSIX_INFO
5351                              *) (((char *) &pSMBr->hdr.Protocol) +
5352                                  data_offset);
5353                         FSData->f_bsize =
5354                                         le32_to_cpu(response_data->BlockSize);
5355                         FSData->f_blocks =
5356                                         le64_to_cpu(response_data->TotalBlocks);
5357                         FSData->f_bfree =
5358                             le64_to_cpu(response_data->BlocksAvail);
5359                         if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
5360                                 FSData->f_bavail = FSData->f_bfree;
5361                         } else {
5362                                 FSData->f_bavail =
5363                                     le64_to_cpu(response_data->UserBlocksAvail);
5364                         }
5365                         if (response_data->TotalFileNodes != cpu_to_le64(-1))
5366                                 FSData->f_files =
5367                                      le64_to_cpu(response_data->TotalFileNodes);
5368                         if (response_data->FreeFileNodes != cpu_to_le64(-1))
5369                                 FSData->f_ffree =
5370                                       le64_to_cpu(response_data->FreeFileNodes);
5371                 }
5372         }
5373         cifs_buf_release(pSMB);
5374
5375         if (rc == -EAGAIN)
5376                 goto QFSPosixRetry;
5377
5378         return rc;
5379 }
5380
5381
5382 /* We can not use write of zero bytes trick to
5383    set file size due to need for large file support.  Also note that
5384    this SetPathInfo is preferred to SetFileInfo based method in next
5385    routine which is only needed to work around a sharing violation bug
5386    in Samba which this routine can run into */
5387
5388 int
5389 CIFSSMBSetEOF(const int xid, struct cifs_tcon *tcon, const char *fileName,
5390               __u64 size, bool SetAllocation,
5391               const struct nls_table *nls_codepage, int remap)
5392 {
5393         struct smb_com_transaction2_spi_req *pSMB = NULL;
5394         struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5395         struct file_end_of_file_info *parm_data;
5396         int name_len;
5397         int rc = 0;
5398         int bytes_returned = 0;
5399         __u16 params, byte_count, data_count, param_offset, offset;
5400
5401         cFYI(1, "In SetEOF");
5402 SetEOFRetry:
5403         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5404                       (void **) &pSMBr);
5405         if (rc)
5406                 return rc;
5407
5408         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5409                 name_len =
5410                     cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
5411                                        PATH_MAX, nls_codepage, remap);
5412                 name_len++;     /* trailing null */
5413                 name_len *= 2;
5414         } else {        /* BB improve the check for buffer overruns BB */
5415                 name_len = strnlen(fileName, PATH_MAX);
5416                 name_len++;     /* trailing null */
5417                 strncpy(pSMB->FileName, fileName, name_len);
5418         }
5419         params = 6 + name_len;
5420         data_count = sizeof(struct file_end_of_file_info);
5421         pSMB->MaxParameterCount = cpu_to_le16(2);
5422         pSMB->MaxDataCount = cpu_to_le16(4100);
5423         pSMB->MaxSetupCount = 0;
5424         pSMB->Reserved = 0;
5425         pSMB->Flags = 0;
5426         pSMB->Timeout = 0;
5427         pSMB->Reserved2 = 0;
5428         param_offset = offsetof(struct smb_com_transaction2_spi_req,
5429                                 InformationLevel) - 4;
5430         offset = param_offset + params;
5431         if (SetAllocation) {
5432                 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5433                         pSMB->InformationLevel =
5434                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5435                 else
5436                         pSMB->InformationLevel =
5437                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5438         } else /* Set File Size */  {
5439             if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5440                     pSMB->InformationLevel =
5441                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5442             else
5443                     pSMB->InformationLevel =
5444                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5445         }
5446
5447         parm_data =
5448             (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
5449                                        offset);
5450         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5451         pSMB->DataOffset = cpu_to_le16(offset);
5452         pSMB->SetupCount = 1;
5453         pSMB->Reserved3 = 0;
5454         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5455         byte_count = 3 /* pad */  + params + data_count;
5456         pSMB->DataCount = cpu_to_le16(data_count);
5457         pSMB->TotalDataCount = pSMB->DataCount;
5458         pSMB->ParameterCount = cpu_to_le16(params);
5459         pSMB->TotalParameterCount = pSMB->ParameterCount;
5460         pSMB->Reserved4 = 0;
5461         inc_rfc1001_len(pSMB, byte_count);
5462         parm_data->FileSize = cpu_to_le64(size);
5463         pSMB->ByteCount = cpu_to_le16(byte_count);
5464         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5465                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5466         if (rc)
5467                 cFYI(1, "SetPathInfo (file size) returned %d", rc);
5468
5469         cifs_buf_release(pSMB);
5470
5471         if (rc == -EAGAIN)
5472                 goto SetEOFRetry;
5473
5474         return rc;
5475 }
5476
5477 int
5478 CIFSSMBSetFileSize(const int xid, struct cifs_tcon *tcon, __u64 size,
5479                    __u16 fid, __u32 pid_of_opener, bool SetAllocation)
5480 {
5481         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5482         struct file_end_of_file_info *parm_data;
5483         int rc = 0;
5484         __u16 params, param_offset, offset, byte_count, count;
5485
5486         cFYI(1, "SetFileSize (via SetFileInfo) %lld",
5487                         (long long)size);
5488         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5489
5490         if (rc)
5491                 return rc;
5492
5493         pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5494         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5495
5496         params = 6;
5497         pSMB->MaxSetupCount = 0;
5498         pSMB->Reserved = 0;
5499         pSMB->Flags = 0;
5500         pSMB->Timeout = 0;
5501         pSMB->Reserved2 = 0;
5502         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5503         offset = param_offset + params;
5504
5505         count = sizeof(struct file_end_of_file_info);
5506         pSMB->MaxParameterCount = cpu_to_le16(2);
5507         /* BB find exact max SMB PDU from sess structure BB */
5508         pSMB->MaxDataCount = cpu_to_le16(1000);
5509         pSMB->SetupCount = 1;
5510         pSMB->Reserved3 = 0;
5511         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5512         byte_count = 3 /* pad */  + params + count;
5513         pSMB->DataCount = cpu_to_le16(count);
5514         pSMB->ParameterCount = cpu_to_le16(params);
5515         pSMB->TotalDataCount = pSMB->DataCount;
5516         pSMB->TotalParameterCount = pSMB->ParameterCount;
5517         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5518         parm_data =
5519                 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
5520                                 + offset);
5521         pSMB->DataOffset = cpu_to_le16(offset);
5522         parm_data->FileSize = cpu_to_le64(size);
5523         pSMB->Fid = fid;
5524         if (SetAllocation) {
5525                 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5526                         pSMB->InformationLevel =
5527                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5528                 else
5529                         pSMB->InformationLevel =
5530                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5531         } else /* Set File Size */  {
5532             if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5533                     pSMB->InformationLevel =
5534                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5535             else
5536                     pSMB->InformationLevel =
5537                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5538         }
5539         pSMB->Reserved4 = 0;
5540         inc_rfc1001_len(pSMB, byte_count);
5541         pSMB->ByteCount = cpu_to_le16(byte_count);
5542         rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5543         if (rc) {
5544                 cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc);
5545         }
5546
5547         /* Note: On -EAGAIN error only caller can retry on handle based calls
5548                 since file handle passed in no longer valid */
5549
5550         return rc;
5551 }
5552
5553 /* Some legacy servers such as NT4 require that the file times be set on
5554    an open handle, rather than by pathname - this is awkward due to
5555    potential access conflicts on the open, but it is unavoidable for these
5556    old servers since the only other choice is to go from 100 nanosecond DCE
5557    time and resort to the original setpathinfo level which takes the ancient
5558    DOS time format with 2 second granularity */
5559 int
5560 CIFSSMBSetFileInfo(const int xid, struct cifs_tcon *tcon,
5561                     const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
5562 {
5563         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5564         char *data_offset;
5565         int rc = 0;
5566         __u16 params, param_offset, offset, byte_count, count;
5567
5568         cFYI(1, "Set Times (via SetFileInfo)");
5569         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5570
5571         if (rc)
5572                 return rc;
5573
5574         pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5575         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5576
5577         params = 6;
5578         pSMB->MaxSetupCount = 0;
5579         pSMB->Reserved = 0;
5580         pSMB->Flags = 0;
5581         pSMB->Timeout = 0;
5582         pSMB->Reserved2 = 0;
5583         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5584         offset = param_offset + params;
5585
5586         data_offset = (char *)pSMB +
5587                         offsetof(struct smb_hdr, Protocol) + offset;
5588
5589         count = sizeof(FILE_BASIC_INFO);
5590         pSMB->MaxParameterCount = cpu_to_le16(2);
5591         /* BB find max SMB PDU from sess */
5592         pSMB->MaxDataCount = cpu_to_le16(1000);
5593         pSMB->SetupCount = 1;
5594         pSMB->Reserved3 = 0;
5595         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5596         byte_count = 3 /* pad */  + params + count;
5597         pSMB->DataCount = cpu_to_le16(count);
5598         pSMB->ParameterCount = cpu_to_le16(params);
5599         pSMB->TotalDataCount = pSMB->DataCount;
5600         pSMB->TotalParameterCount = pSMB->ParameterCount;
5601         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5602         pSMB->DataOffset = cpu_to_le16(offset);
5603         pSMB->Fid = fid;
5604         if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5605                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5606         else
5607                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5608         pSMB->Reserved4 = 0;
5609         inc_rfc1001_len(pSMB, byte_count);
5610         pSMB->ByteCount = cpu_to_le16(byte_count);
5611         memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5612         rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5613         if (rc)
5614                 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
5615
5616         /* Note: On -EAGAIN error only caller can retry on handle based calls
5617                 since file handle passed in no longer valid */
5618
5619         return rc;
5620 }
5621
5622 int
5623 CIFSSMBSetFileDisposition(const int xid, struct cifs_tcon *tcon,
5624                           bool delete_file, __u16 fid, __u32 pid_of_opener)
5625 {
5626         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5627         char *data_offset;
5628         int rc = 0;
5629         __u16 params, param_offset, offset, byte_count, count;
5630
5631         cFYI(1, "Set File Disposition (via SetFileInfo)");
5632         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5633
5634         if (rc)
5635                 return rc;
5636
5637         pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5638         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5639
5640         params = 6;
5641         pSMB->MaxSetupCount = 0;
5642         pSMB->Reserved = 0;
5643         pSMB->Flags = 0;
5644         pSMB->Timeout = 0;
5645         pSMB->Reserved2 = 0;
5646         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5647         offset = param_offset + params;
5648
5649         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5650
5651         count = 1;
5652         pSMB->MaxParameterCount = cpu_to_le16(2);
5653         /* BB find max SMB PDU from sess */
5654         pSMB->MaxDataCount = cpu_to_le16(1000);
5655         pSMB->SetupCount = 1;
5656         pSMB->Reserved3 = 0;
5657         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5658         byte_count = 3 /* pad */  + params + count;
5659         pSMB->DataCount = cpu_to_le16(count);
5660         pSMB->ParameterCount = cpu_to_le16(params);
5661         pSMB->TotalDataCount = pSMB->DataCount;
5662         pSMB->TotalParameterCount = pSMB->ParameterCount;
5663         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5664         pSMB->DataOffset = cpu_to_le16(offset);
5665         pSMB->Fid = fid;
5666         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
5667         pSMB->Reserved4 = 0;
5668         inc_rfc1001_len(pSMB, byte_count);
5669         pSMB->ByteCount = cpu_to_le16(byte_count);
5670         *data_offset = delete_file ? 1 : 0;
5671         rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5672         if (rc)
5673                 cFYI(1, "Send error in SetFileDisposition = %d", rc);
5674
5675         return rc;
5676 }
5677
5678 int
5679 CIFSSMBSetPathInfo(const int xid, struct cifs_tcon *tcon,
5680                    const char *fileName, const FILE_BASIC_INFO *data,
5681                    const struct nls_table *nls_codepage, int remap)
5682 {
5683         TRANSACTION2_SPI_REQ *pSMB = NULL;
5684         TRANSACTION2_SPI_RSP *pSMBr = NULL;
5685         int name_len;
5686         int rc = 0;
5687         int bytes_returned = 0;
5688         char *data_offset;
5689         __u16 params, param_offset, offset, byte_count, count;
5690
5691         cFYI(1, "In SetTimes");
5692
5693 SetTimesRetry:
5694         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5695                       (void **) &pSMBr);
5696         if (rc)
5697                 return rc;
5698
5699         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5700                 name_len =
5701                     cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
5702                                        PATH_MAX, nls_codepage, remap);
5703                 name_len++;     /* trailing null */
5704                 name_len *= 2;
5705         } else {        /* BB improve the check for buffer overruns BB */
5706                 name_len = strnlen(fileName, PATH_MAX);
5707                 name_len++;     /* trailing null */
5708                 strncpy(pSMB->FileName, fileName, name_len);
5709         }
5710
5711         params = 6 + name_len;
5712         count = sizeof(FILE_BASIC_INFO);
5713         pSMB->MaxParameterCount = cpu_to_le16(2);
5714         /* BB find max SMB PDU from sess structure BB */
5715         pSMB->MaxDataCount = cpu_to_le16(1000);
5716         pSMB->MaxSetupCount = 0;
5717         pSMB->Reserved = 0;
5718         pSMB->Flags = 0;
5719         pSMB->Timeout = 0;
5720         pSMB->Reserved2 = 0;
5721         param_offset = offsetof(struct smb_com_transaction2_spi_req,
5722                                 InformationLevel) - 4;
5723         offset = param_offset + params;
5724         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5725         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5726         pSMB->DataOffset = cpu_to_le16(offset);
5727         pSMB->SetupCount = 1;
5728         pSMB->Reserved3 = 0;
5729         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5730         byte_count = 3 /* pad */  + params + count;
5731
5732         pSMB->DataCount = cpu_to_le16(count);
5733         pSMB->ParameterCount = cpu_to_le16(params);
5734         pSMB->TotalDataCount = pSMB->DataCount;
5735         pSMB->TotalParameterCount = pSMB->ParameterCount;
5736         if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5737                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5738         else
5739                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5740         pSMB->Reserved4 = 0;
5741         inc_rfc1001_len(pSMB, byte_count);
5742         memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5743         pSMB->ByteCount = cpu_to_le16(byte_count);
5744         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5745                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5746         if (rc)
5747                 cFYI(1, "SetPathInfo (times) returned %d", rc);
5748
5749         cifs_buf_release(pSMB);
5750
5751         if (rc == -EAGAIN)
5752                 goto SetTimesRetry;
5753
5754         return rc;
5755 }
5756
5757 /* Can not be used to set time stamps yet (due to old DOS time format) */
5758 /* Can be used to set attributes */
5759 #if 0  /* Possibly not needed - since it turns out that strangely NT4 has a bug
5760           handling it anyway and NT4 was what we thought it would be needed for
5761           Do not delete it until we prove whether needed for Win9x though */
5762 int
5763 CIFSSMBSetAttrLegacy(int xid, struct cifs_tcon *tcon, char *fileName,
5764                 __u16 dos_attrs, const struct nls_table *nls_codepage)
5765 {
5766         SETATTR_REQ *pSMB = NULL;
5767         SETATTR_RSP *pSMBr = NULL;
5768         int rc = 0;
5769         int bytes_returned;
5770         int name_len;
5771
5772         cFYI(1, "In SetAttrLegacy");
5773
5774 SetAttrLgcyRetry:
5775         rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5776                       (void **) &pSMBr);
5777         if (rc)
5778                 return rc;
5779
5780         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5781                 name_len =
5782                         ConvertToUTF16((__le16 *) pSMB->fileName, fileName,
5783                                        PATH_MAX, nls_codepage);
5784                 name_len++;     /* trailing null */
5785                 name_len *= 2;
5786         } else {        /* BB improve the check for buffer overruns BB */
5787                 name_len = strnlen(fileName, PATH_MAX);
5788                 name_len++;     /* trailing null */
5789                 strncpy(pSMB->fileName, fileName, name_len);
5790         }
5791         pSMB->attr = cpu_to_le16(dos_attrs);
5792         pSMB->BufferFormat = 0x04;
5793         inc_rfc1001_len(pSMB, name_len + 1);
5794         pSMB->ByteCount = cpu_to_le16(name_len + 1);
5795         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5796                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5797         if (rc)
5798                 cFYI(1, "Error in LegacySetAttr = %d", rc);
5799
5800         cifs_buf_release(pSMB);
5801
5802         if (rc == -EAGAIN)
5803                 goto SetAttrLgcyRetry;
5804
5805         return rc;
5806 }
5807 #endif /* temporarily unneeded SetAttr legacy function */
5808
5809 static void
5810 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
5811                         const struct cifs_unix_set_info_args *args)
5812 {
5813         u64 mode = args->mode;
5814
5815         /*
5816          * Samba server ignores set of file size to zero due to bugs in some
5817          * older clients, but we should be precise - we use SetFileSize to
5818          * set file size and do not want to truncate file size to zero
5819          * accidentally as happened on one Samba server beta by putting
5820          * zero instead of -1 here
5821          */
5822         data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5823         data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5824         data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5825         data_offset->LastAccessTime = cpu_to_le64(args->atime);
5826         data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5827         data_offset->Uid = cpu_to_le64(args->uid);
5828         data_offset->Gid = cpu_to_le64(args->gid);
5829         /* better to leave device as zero when it is  */
5830         data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5831         data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5832         data_offset->Permissions = cpu_to_le64(mode);
5833
5834         if (S_ISREG(mode))
5835                 data_offset->Type = cpu_to_le32(UNIX_FILE);
5836         else if (S_ISDIR(mode))
5837                 data_offset->Type = cpu_to_le32(UNIX_DIR);
5838         else if (S_ISLNK(mode))
5839                 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5840         else if (S_ISCHR(mode))
5841                 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5842         else if (S_ISBLK(mode))
5843                 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5844         else if (S_ISFIFO(mode))
5845                 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5846         else if (S_ISSOCK(mode))
5847                 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5848 }
5849
5850 int
5851 CIFSSMBUnixSetFileInfo(const int xid, struct cifs_tcon *tcon,
5852                        const struct cifs_unix_set_info_args *args,
5853                        u16 fid, u32 pid_of_opener)
5854 {
5855         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5856         char *data_offset;
5857         int rc = 0;
5858         u16 params, param_offset, offset, byte_count, count;
5859
5860         cFYI(1, "Set Unix Info (via SetFileInfo)");
5861         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5862
5863         if (rc)
5864                 return rc;
5865
5866         pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5867         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5868
5869         params = 6;
5870         pSMB->MaxSetupCount = 0;
5871         pSMB->Reserved = 0;
5872         pSMB->Flags = 0;
5873         pSMB->Timeout = 0;
5874         pSMB->Reserved2 = 0;
5875         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5876         offset = param_offset + params;
5877
5878         data_offset = (char *)pSMB +
5879                         offsetof(struct smb_hdr, Protocol) + offset;
5880
5881         count = sizeof(FILE_UNIX_BASIC_INFO);
5882
5883         pSMB->MaxParameterCount = cpu_to_le16(2);
5884         /* BB find max SMB PDU from sess */
5885         pSMB->MaxDataCount = cpu_to_le16(1000);
5886         pSMB->SetupCount = 1;
5887         pSMB->Reserved3 = 0;
5888         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5889         byte_count = 3 /* pad */  + params + count;
5890         pSMB->DataCount = cpu_to_le16(count);
5891         pSMB->ParameterCount = cpu_to_le16(params);
5892         pSMB->TotalDataCount = pSMB->DataCount;
5893         pSMB->TotalParameterCount = pSMB->ParameterCount;
5894         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5895         pSMB->DataOffset = cpu_to_le16(offset);
5896         pSMB->Fid = fid;
5897         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5898         pSMB->Reserved4 = 0;
5899         inc_rfc1001_len(pSMB, byte_count);
5900         pSMB->ByteCount = cpu_to_le16(byte_count);
5901
5902         cifs_fill_unix_set_info((FILE_UNIX_BASIC_INFO *)data_offset, args);
5903
5904         rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
5905         if (rc)
5906                 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
5907
5908         /* Note: On -EAGAIN error only caller can retry on handle based calls
5909                 since file handle passed in no longer valid */
5910
5911         return rc;
5912 }
5913
5914 int
5915 CIFSSMBUnixSetPathInfo(const int xid, struct cifs_tcon *tcon, char *fileName,
5916                        const struct cifs_unix_set_info_args *args,
5917                        const struct nls_table *nls_codepage, int remap)
5918 {
5919         TRANSACTION2_SPI_REQ *pSMB = NULL;
5920         TRANSACTION2_SPI_RSP *pSMBr = NULL;
5921         int name_len;
5922         int rc = 0;
5923         int bytes_returned = 0;
5924         FILE_UNIX_BASIC_INFO *data_offset;
5925         __u16 params, param_offset, offset, count, byte_count;
5926
5927         cFYI(1, "In SetUID/GID/Mode");
5928 setPermsRetry:
5929         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5930                       (void **) &pSMBr);
5931         if (rc)
5932                 return rc;
5933
5934         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5935                 name_len =
5936                     cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
5937                                        PATH_MAX, nls_codepage, remap);
5938                 name_len++;     /* trailing null */
5939                 name_len *= 2;
5940         } else {        /* BB improve the check for buffer overruns BB */
5941                 name_len = strnlen(fileName, PATH_MAX);
5942                 name_len++;     /* trailing null */
5943                 strncpy(pSMB->FileName, fileName, name_len);
5944         }
5945
5946         params = 6 + name_len;
5947         count = sizeof(FILE_UNIX_BASIC_INFO);
5948         pSMB->MaxParameterCount = cpu_to_le16(2);
5949         /* BB find max SMB PDU from sess structure BB */
5950         pSMB->MaxDataCount = cpu_to_le16(1000);
5951         pSMB->MaxSetupCount = 0;
5952         pSMB->Reserved = 0;
5953         pSMB->Flags = 0;
5954         pSMB->Timeout = 0;
5955         pSMB->Reserved2 = 0;
5956         param_offset = offsetof(struct smb_com_transaction2_spi_req,
5957                                 InformationLevel) - 4;
5958         offset = param_offset + params;
5959         data_offset =
5960             (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5961                                       offset);
5962         memset(data_offset, 0, count);
5963         pSMB->DataOffset = cpu_to_le16(offset);
5964         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5965         pSMB->SetupCount = 1;
5966         pSMB->Reserved3 = 0;
5967         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5968         byte_count = 3 /* pad */  + params + count;
5969         pSMB->ParameterCount = cpu_to_le16(params);
5970         pSMB->DataCount = cpu_to_le16(count);
5971         pSMB->TotalParameterCount = pSMB->ParameterCount;
5972         pSMB->TotalDataCount = pSMB->DataCount;
5973         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5974         pSMB->Reserved4 = 0;
5975         inc_rfc1001_len(pSMB, byte_count);
5976
5977         cifs_fill_unix_set_info(data_offset, args);
5978
5979         pSMB->ByteCount = cpu_to_le16(byte_count);
5980         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5981                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5982         if (rc)
5983                 cFYI(1, "SetPathInfo (perms) returned %d", rc);
5984
5985         cifs_buf_release(pSMB);
5986         if (rc == -EAGAIN)
5987                 goto setPermsRetry;
5988         return rc;
5989 }
5990
5991 #ifdef CONFIG_CIFS_XATTR
5992 /*
5993  * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
5994  * function used by listxattr and getxattr type calls. When ea_name is set,
5995  * it looks for that attribute name and stuffs that value into the EAData
5996  * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
5997  * buffer. In both cases, the return value is either the length of the
5998  * resulting data or a negative error code. If EAData is a NULL pointer then
5999  * the data isn't copied to it, but the length is returned.
6000  */
6001 ssize_t
6002 CIFSSMBQAllEAs(const int xid, struct cifs_tcon *tcon,
6003                 const unsigned char *searchName, const unsigned char *ea_name,
6004                 char *EAData, size_t buf_size,
6005                 const struct nls_table *nls_codepage, int remap)
6006 {
6007                 /* BB assumes one setup word */
6008         TRANSACTION2_QPI_REQ *pSMB = NULL;
6009         TRANSACTION2_QPI_RSP *pSMBr = NULL;
6010         int rc = 0;
6011         int bytes_returned;
6012         int list_len;
6013         struct fealist *ea_response_data;
6014         struct fea *temp_fea;
6015         char *temp_ptr;
6016         char *end_of_smb;
6017         __u16 params, byte_count, data_offset;
6018         unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0;
6019
6020         cFYI(1, "In Query All EAs path %s", searchName);
6021 QAllEAsRetry:
6022         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6023                       (void **) &pSMBr);
6024         if (rc)
6025                 return rc;
6026
6027         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6028                 list_len =
6029                     cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
6030                                        PATH_MAX, nls_codepage, remap);
6031                 list_len++;     /* trailing null */
6032                 list_len *= 2;
6033         } else {        /* BB improve the check for buffer overruns BB */
6034                 list_len = strnlen(searchName, PATH_MAX);
6035                 list_len++;     /* trailing null */
6036                 strncpy(pSMB->FileName, searchName, list_len);
6037         }
6038
6039         params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
6040         pSMB->TotalDataCount = 0;
6041         pSMB->MaxParameterCount = cpu_to_le16(2);
6042         /* BB find exact max SMB PDU from sess structure BB */
6043         pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
6044         pSMB->MaxSetupCount = 0;
6045         pSMB->Reserved = 0;
6046         pSMB->Flags = 0;
6047         pSMB->Timeout = 0;
6048         pSMB->Reserved2 = 0;
6049         pSMB->ParameterOffset = cpu_to_le16(offsetof(
6050         struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
6051         pSMB->DataCount = 0;
6052         pSMB->DataOffset = 0;
6053         pSMB->SetupCount = 1;
6054         pSMB->Reserved3 = 0;
6055         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
6056         byte_count = params + 1 /* pad */ ;
6057         pSMB->TotalParameterCount = cpu_to_le16(params);
6058         pSMB->ParameterCount = pSMB->TotalParameterCount;
6059         pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
6060         pSMB->Reserved4 = 0;
6061         inc_rfc1001_len(pSMB, byte_count);
6062         pSMB->ByteCount = cpu_to_le16(byte_count);
6063
6064         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6065                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6066         if (rc) {
6067                 cFYI(1, "Send error in QueryAllEAs = %d", rc);
6068                 goto QAllEAsOut;
6069         }
6070
6071
6072         /* BB also check enough total bytes returned */
6073         /* BB we need to improve the validity checking
6074         of these trans2 responses */
6075
6076         rc = validate_t2((struct smb_t2_rsp *)pSMBr);
6077         if (rc || get_bcc(&pSMBr->hdr) < 4) {
6078                 rc = -EIO;      /* bad smb */
6079                 goto QAllEAsOut;
6080         }
6081
6082         /* check that length of list is not more than bcc */
6083         /* check that each entry does not go beyond length
6084            of list */
6085         /* check that each element of each entry does not
6086            go beyond end of list */
6087         /* validate_trans2_offsets() */
6088         /* BB check if start of smb + data_offset > &bcc+ bcc */
6089
6090         data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
6091         ea_response_data = (struct fealist *)
6092                                 (((char *) &pSMBr->hdr.Protocol) + data_offset);
6093
6094         list_len = le32_to_cpu(ea_response_data->list_len);
6095         cFYI(1, "ea length %d", list_len);
6096         if (list_len <= 8) {
6097                 cFYI(1, "empty EA list returned from server");
6098                 goto QAllEAsOut;
6099         }
6100
6101         /* make sure list_len doesn't go past end of SMB */
6102         end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr);
6103         if ((char *)ea_response_data + list_len > end_of_smb) {
6104                 cFYI(1, "EA list appears to go beyond SMB");
6105                 rc = -EIO;
6106                 goto QAllEAsOut;
6107         }
6108
6109         /* account for ea list len */
6110         list_len -= 4;
6111         temp_fea = ea_response_data->list;
6112         temp_ptr = (char *)temp_fea;
6113         while (list_len > 0) {
6114                 unsigned int name_len;
6115                 __u16 value_len;
6116
6117                 list_len -= 4;
6118                 temp_ptr += 4;
6119                 /* make sure we can read name_len and value_len */
6120                 if (list_len < 0) {
6121                         cFYI(1, "EA entry goes beyond length of list");
6122                         rc = -EIO;
6123                         goto QAllEAsOut;
6124                 }
6125
6126                 name_len = temp_fea->name_len;
6127                 value_len = le16_to_cpu(temp_fea->value_len);
6128                 list_len -= name_len + 1 + value_len;
6129                 if (list_len < 0) {
6130                         cFYI(1, "EA entry goes beyond length of list");
6131                         rc = -EIO;
6132                         goto QAllEAsOut;
6133                 }
6134
6135                 if (ea_name) {
6136                         if (ea_name_len == name_len &&
6137                             memcmp(ea_name, temp_ptr, name_len) == 0) {
6138                                 temp_ptr += name_len + 1;
6139                                 rc = value_len;
6140                                 if (buf_size == 0)
6141                                         goto QAllEAsOut;
6142                                 if ((size_t)value_len > buf_size) {
6143                                         rc = -ERANGE;
6144                                         goto QAllEAsOut;
6145                                 }
6146                                 memcpy(EAData, temp_ptr, value_len);
6147                                 goto QAllEAsOut;
6148                         }
6149                 } else {
6150                         /* account for prefix user. and trailing null */
6151                         rc += (5 + 1 + name_len);
6152                         if (rc < (int) buf_size) {
6153                                 memcpy(EAData, "user.", 5);
6154                                 EAData += 5;
6155                                 memcpy(EAData, temp_ptr, name_len);
6156                                 EAData += name_len;
6157                                 /* null terminate name */
6158                                 *EAData = 0;
6159                                 ++EAData;
6160                         } else if (buf_size == 0) {
6161                                 /* skip copy - calc size only */
6162                         } else {
6163                                 /* stop before overrun buffer */
6164                                 rc = -ERANGE;
6165                                 break;
6166                         }
6167                 }
6168                 temp_ptr += name_len + 1 + value_len;
6169                 temp_fea = (struct fea *)temp_ptr;
6170         }
6171
6172         /* didn't find the named attribute */
6173         if (ea_name)
6174                 rc = -ENODATA;
6175
6176 QAllEAsOut:
6177         cifs_buf_release(pSMB);
6178         if (rc == -EAGAIN)
6179                 goto QAllEAsRetry;
6180
6181         return (ssize_t)rc;
6182 }
6183
6184 int
6185 CIFSSMBSetEA(const int xid, struct cifs_tcon *tcon, const char *fileName,
6186              const char *ea_name, const void *ea_value,
6187              const __u16 ea_value_len, const struct nls_table *nls_codepage,
6188              int remap)
6189 {
6190         struct smb_com_transaction2_spi_req *pSMB = NULL;
6191         struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
6192         struct fealist *parm_data;
6193         int name_len;
6194         int rc = 0;
6195         int bytes_returned = 0;
6196         __u16 params, param_offset, byte_count, offset, count;
6197
6198         cFYI(1, "In SetEA");
6199 SetEARetry:
6200         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
6201                       (void **) &pSMBr);
6202         if (rc)
6203                 return rc;
6204
6205         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
6206                 name_len =
6207                     cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
6208                                        PATH_MAX, nls_codepage, remap);
6209                 name_len++;     /* trailing null */
6210                 name_len *= 2;
6211         } else {        /* BB improve the check for buffer overruns BB */
6212                 name_len = strnlen(fileName, PATH_MAX);
6213                 name_len++;     /* trailing null */
6214                 strncpy(pSMB->FileName, fileName, name_len);
6215         }
6216
6217         params = 6 + name_len;
6218
6219         /* done calculating parms using name_len of file name,
6220         now use name_len to calculate length of ea name
6221         we are going to create in the inode xattrs */
6222         if (ea_name == NULL)
6223                 name_len = 0;
6224         else
6225                 name_len = strnlen(ea_name, 255);
6226
6227         count = sizeof(*parm_data) + ea_value_len + name_len;
6228         pSMB->MaxParameterCount = cpu_to_le16(2);
6229         /* BB find max SMB PDU from sess */
6230         pSMB->MaxDataCount = cpu_to_le16(1000);
6231         pSMB->MaxSetupCount = 0;
6232         pSMB->Reserved = 0;
6233         pSMB->Flags = 0;
6234         pSMB->Timeout = 0;
6235         pSMB->Reserved2 = 0;
6236         param_offset = offsetof(struct smb_com_transaction2_spi_req,
6237                                 InformationLevel) - 4;
6238         offset = param_offset + params;
6239         pSMB->InformationLevel =
6240                 cpu_to_le16(SMB_SET_FILE_EA);
6241
6242         parm_data =
6243                 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
6244                                        offset);
6245         pSMB->ParameterOffset = cpu_to_le16(param_offset);
6246         pSMB->DataOffset = cpu_to_le16(offset);
6247         pSMB->SetupCount = 1;
6248         pSMB->Reserved3 = 0;
6249         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
6250         byte_count = 3 /* pad */  + params + count;
6251         pSMB->DataCount = cpu_to_le16(count);
6252         parm_data->list_len = cpu_to_le32(count);
6253         parm_data->list[0].EA_flags = 0;
6254         /* we checked above that name len is less than 255 */
6255         parm_data->list[0].name_len = (__u8)name_len;
6256         /* EA names are always ASCII */
6257         if (ea_name)
6258                 strncpy(parm_data->list[0].name, ea_name, name_len);
6259         parm_data->list[0].name[name_len] = 0;
6260         parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
6261         /* caller ensures that ea_value_len is less than 64K but
6262         we need to ensure that it fits within the smb */
6263
6264         /*BB add length check to see if it would fit in
6265              negotiated SMB buffer size BB */
6266         /* if (ea_value_len > buffer_size - 512 (enough for header)) */
6267         if (ea_value_len)
6268                 memcpy(parm_data->list[0].name+name_len+1,
6269                        ea_value, ea_value_len);
6270
6271         pSMB->TotalDataCount = pSMB->DataCount;
6272         pSMB->ParameterCount = cpu_to_le16(params);
6273         pSMB->TotalParameterCount = pSMB->ParameterCount;
6274         pSMB->Reserved4 = 0;
6275         inc_rfc1001_len(pSMB, byte_count);
6276         pSMB->ByteCount = cpu_to_le16(byte_count);
6277         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6278                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
6279         if (rc)
6280                 cFYI(1, "SetPathInfo (EA) returned %d", rc);
6281
6282         cifs_buf_release(pSMB);
6283
6284         if (rc == -EAGAIN)
6285                 goto SetEARetry;
6286
6287         return rc;
6288 }
6289 #endif
6290
6291 #ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* BB unused temporarily */
6292 /*
6293  *      Years ago the kernel added a "dnotify" function for Samba server,
6294  *      to allow network clients (such as Windows) to display updated
6295  *      lists of files in directory listings automatically when
6296  *      files are added by one user when another user has the
6297  *      same directory open on their desktop.  The Linux cifs kernel
6298  *      client hooked into the kernel side of this interface for
6299  *      the same reason, but ironically when the VFS moved from
6300  *      "dnotify" to "inotify" it became harder to plug in Linux
6301  *      network file system clients (the most obvious use case
6302  *      for notify interfaces is when multiple users can update
6303  *      the contents of the same directory - exactly what network
6304  *      file systems can do) although the server (Samba) could
6305  *      still use it.  For the short term we leave the worker
6306  *      function ifdeffed out (below) until inotify is fixed
6307  *      in the VFS to make it easier to plug in network file
6308  *      system clients.  If inotify turns out to be permanently
6309  *      incompatible for network fs clients, we could instead simply
6310  *      expose this config flag by adding a future cifs (and smb2) notify ioctl.
6311  */
6312 int CIFSSMBNotify(const int xid, struct cifs_tcon *tcon,
6313                   const int notify_subdirs, const __u16 netfid,
6314                   __u32 filter, struct file *pfile, int multishot,
6315                   const struct nls_table *nls_codepage)
6316 {
6317         int rc = 0;
6318         struct smb_com_transaction_change_notify_req *pSMB = NULL;
6319         struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
6320         struct dir_notify_req *dnotify_req;
6321         int bytes_returned;
6322
6323         cFYI(1, "In CIFSSMBNotify for file handle %d", (int)netfid);
6324         rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
6325                       (void **) &pSMBr);
6326         if (rc)
6327                 return rc;
6328
6329         pSMB->TotalParameterCount = 0 ;
6330         pSMB->TotalDataCount = 0;
6331         pSMB->MaxParameterCount = cpu_to_le32(2);
6332         pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
6333         pSMB->MaxSetupCount = 4;
6334         pSMB->Reserved = 0;
6335         pSMB->ParameterOffset = 0;
6336         pSMB->DataCount = 0;
6337         pSMB->DataOffset = 0;
6338         pSMB->SetupCount = 4; /* single byte does not need le conversion */
6339         pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
6340         pSMB->ParameterCount = pSMB->TotalParameterCount;
6341         if (notify_subdirs)
6342                 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
6343         pSMB->Reserved2 = 0;
6344         pSMB->CompletionFilter = cpu_to_le32(filter);
6345         pSMB->Fid = netfid; /* file handle always le */
6346         pSMB->ByteCount = 0;
6347
6348         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
6349                          (struct smb_hdr *)pSMBr, &bytes_returned,
6350                          CIFS_ASYNC_OP);
6351         if (rc) {
6352                 cFYI(1, "Error in Notify = %d", rc);
6353         } else {
6354                 /* Add file to outstanding requests */
6355                 /* BB change to kmem cache alloc */
6356                 dnotify_req = kmalloc(
6357                                                 sizeof(struct dir_notify_req),
6358                                                  GFP_KERNEL);
6359                 if (dnotify_req) {
6360                         dnotify_req->Pid = pSMB->hdr.Pid;
6361                         dnotify_req->PidHigh = pSMB->hdr.PidHigh;
6362                         dnotify_req->Mid = pSMB->hdr.Mid;
6363                         dnotify_req->Tid = pSMB->hdr.Tid;
6364                         dnotify_req->Uid = pSMB->hdr.Uid;
6365                         dnotify_req->netfid = netfid;
6366                         dnotify_req->pfile = pfile;
6367                         dnotify_req->filter = filter;
6368                         dnotify_req->multishot = multishot;
6369                         spin_lock(&GlobalMid_Lock);
6370                         list_add_tail(&dnotify_req->lhead,
6371                                         &GlobalDnotifyReqList);
6372                         spin_unlock(&GlobalMid_Lock);
6373                 } else
6374                         rc = -ENOMEM;
6375         }
6376         cifs_buf_release(pSMB);
6377         return rc;
6378 }
6379 #endif /* was needed for dnotify, and will be needed for inotify when VFS fix */