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