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