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