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