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