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