cifs: add a CIFSSMBQFileInfo function
[linux-flexiantxendom0-natty.git] / fs / cifs / cifssmb.c
1 /*
2  *   fs/cifs/cifssmb.c
3  *
4  *   Copyright (C) International Business Machines  Corp., 2002,2009
5  *   Author(s): Steve French (sfrench@us.ibm.com)
6  *
7  *   Contains the routines for constructing the SMB PDUs themselves
8  *
9  *   This library is free software; you can redistribute it and/or modify
10  *   it under the terms of the GNU Lesser General Public License as published
11  *   by the Free Software Foundation; either version 2.1 of the License, or
12  *   (at your option) any later version.
13  *
14  *   This library is distributed in the hope that it will be useful,
15  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
17  *   the GNU Lesser General Public License for more details.
18  *
19  *   You should have received a copy of the GNU Lesser General Public License
20  *   along with this library; if not, write to the Free Software
21  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22  */
23
24  /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c   */
25  /* These are mostly routines that operate on a pathname, or on a tree id     */
26  /* (mounted volume), but there are eight handle based routines which must be */
27  /* treated slightly differently for reconnection purposes since we never     */
28  /* want to reuse a stale file handle and only the caller knows the file info */
29
30 #include <linux/fs.h>
31 #include <linux/kernel.h>
32 #include <linux/vfs.h>
33 #include <linux/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 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3403                      const unsigned char *searchName,
3404                      FILE_UNIX_BASIC_INFO *pFindData,
3405                      const struct nls_table *nls_codepage, int remap)
3406 {
3407 /* SMB_QUERY_FILE_UNIX_BASIC */
3408         TRANSACTION2_QPI_REQ *pSMB = NULL;
3409         TRANSACTION2_QPI_RSP *pSMBr = NULL;
3410         int rc = 0;
3411         int bytes_returned = 0;
3412         int name_len;
3413         __u16 params, byte_count;
3414
3415         cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
3416 UnixQPathInfoRetry:
3417         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3418                       (void **) &pSMBr);
3419         if (rc)
3420                 return rc;
3421
3422         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3423                 name_len =
3424                     cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3425                                   PATH_MAX, nls_codepage, remap);
3426                 name_len++;     /* trailing null */
3427                 name_len *= 2;
3428         } else {        /* BB improve the check for buffer overruns BB */
3429                 name_len = strnlen(searchName, PATH_MAX);
3430                 name_len++;     /* trailing null */
3431                 strncpy(pSMB->FileName, searchName, name_len);
3432         }
3433
3434         params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3435         pSMB->TotalDataCount = 0;
3436         pSMB->MaxParameterCount = cpu_to_le16(2);
3437         /* BB find exact max SMB PDU from sess structure BB */
3438         pSMB->MaxDataCount = cpu_to_le16(4000);
3439         pSMB->MaxSetupCount = 0;
3440         pSMB->Reserved = 0;
3441         pSMB->Flags = 0;
3442         pSMB->Timeout = 0;
3443         pSMB->Reserved2 = 0;
3444         pSMB->ParameterOffset = cpu_to_le16(offsetof(
3445         struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3446         pSMB->DataCount = 0;
3447         pSMB->DataOffset = 0;
3448         pSMB->SetupCount = 1;
3449         pSMB->Reserved3 = 0;
3450         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3451         byte_count = params + 1 /* pad */ ;
3452         pSMB->TotalParameterCount = cpu_to_le16(params);
3453         pSMB->ParameterCount = pSMB->TotalParameterCount;
3454         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3455         pSMB->Reserved4 = 0;
3456         pSMB->hdr.smb_buf_length += byte_count;
3457         pSMB->ByteCount = cpu_to_le16(byte_count);
3458
3459         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3460                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3461         if (rc) {
3462                 cFYI(1, ("Send error in QPathInfo = %d", rc));
3463         } else {                /* decode response */
3464                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3465
3466                 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3467                         cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3468                                    "Unix Extensions can be disabled on mount "
3469                                    "by specifying the nosfu mount option."));
3470                         rc = -EIO;      /* bad smb */
3471                 } else {
3472                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3473                         memcpy((char *) pFindData,
3474                                (char *) &pSMBr->hdr.Protocol +
3475                                data_offset,
3476                                sizeof(FILE_UNIX_BASIC_INFO));
3477                 }
3478         }
3479         cifs_buf_release(pSMB);
3480         if (rc == -EAGAIN)
3481                 goto UnixQPathInfoRetry;
3482
3483         return rc;
3484 }
3485
3486 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3487 int
3488 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3489               const char *searchName,
3490               const struct nls_table *nls_codepage,
3491               __u16 *pnetfid,
3492               struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3493 {
3494 /* level 257 SMB_ */
3495         TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3496         TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3497         T2_FFIRST_RSP_PARMS *parms;
3498         int rc = 0;
3499         int bytes_returned = 0;
3500         int name_len;
3501         __u16 params, byte_count;
3502
3503         cFYI(1, ("In FindFirst for %s", searchName));
3504
3505 findFirstRetry:
3506         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3507                       (void **) &pSMBr);
3508         if (rc)
3509                 return rc;
3510
3511         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3512                 name_len =
3513                     cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3514                                  PATH_MAX, nls_codepage, remap);
3515                 /* We can not add the asterik earlier in case
3516                 it got remapped to 0xF03A as if it were part of the
3517                 directory name instead of a wildcard */
3518                 name_len *= 2;
3519                 pSMB->FileName[name_len] = dirsep;
3520                 pSMB->FileName[name_len+1] = 0;
3521                 pSMB->FileName[name_len+2] = '*';
3522                 pSMB->FileName[name_len+3] = 0;
3523                 name_len += 4; /* now the trailing null */
3524                 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3525                 pSMB->FileName[name_len+1] = 0;
3526                 name_len += 2;
3527         } else {        /* BB add check for overrun of SMB buf BB */
3528                 name_len = strnlen(searchName, PATH_MAX);
3529 /* BB fix here and in unicode clause above ie
3530                 if (name_len > buffersize-header)
3531                         free buffer exit; BB */
3532                 strncpy(pSMB->FileName, searchName, name_len);
3533                 pSMB->FileName[name_len] = dirsep;
3534                 pSMB->FileName[name_len+1] = '*';
3535                 pSMB->FileName[name_len+2] = 0;
3536                 name_len += 3;
3537         }
3538
3539         params = 12 + name_len /* includes null */ ;
3540         pSMB->TotalDataCount = 0;       /* no EAs */
3541         pSMB->MaxParameterCount = cpu_to_le16(10);
3542         pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3543                                           MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3544         pSMB->MaxSetupCount = 0;
3545         pSMB->Reserved = 0;
3546         pSMB->Flags = 0;
3547         pSMB->Timeout = 0;
3548         pSMB->Reserved2 = 0;
3549         byte_count = params + 1 /* pad */ ;
3550         pSMB->TotalParameterCount = cpu_to_le16(params);
3551         pSMB->ParameterCount = pSMB->TotalParameterCount;
3552         pSMB->ParameterOffset = cpu_to_le16(
3553               offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3554                 - 4);
3555         pSMB->DataCount = 0;
3556         pSMB->DataOffset = 0;
3557         pSMB->SetupCount = 1;   /* one byte, no need to make endian neutral */
3558         pSMB->Reserved3 = 0;
3559         pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3560         pSMB->SearchAttributes =
3561             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3562                         ATTR_DIRECTORY);
3563         pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3564         pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3565                 CIFS_SEARCH_RETURN_RESUME);
3566         pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3567
3568         /* BB what should we set StorageType to? Does it matter? BB */
3569         pSMB->SearchStorageType = 0;
3570         pSMB->hdr.smb_buf_length += byte_count;
3571         pSMB->ByteCount = cpu_to_le16(byte_count);
3572
3573         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3574                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3575         cifs_stats_inc(&tcon->num_ffirst);
3576
3577         if (rc) {/* BB add logic to retry regular search if Unix search
3578                         rejected unexpectedly by server */
3579                 /* BB Add code to handle unsupported level rc */
3580                 cFYI(1, ("Error in FindFirst = %d", rc));
3581
3582                 cifs_buf_release(pSMB);
3583
3584                 /* BB eventually could optimize out free and realloc of buf */
3585                 /*    for this case */
3586                 if (rc == -EAGAIN)
3587                         goto findFirstRetry;
3588         } else { /* decode response */
3589                 /* BB remember to free buffer if error BB */
3590                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3591                 if (rc == 0) {
3592                         unsigned int lnoff;
3593
3594                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3595                                 psrch_inf->unicode = true;
3596                         else
3597                                 psrch_inf->unicode = false;
3598
3599                         psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3600                         psrch_inf->smallBuf = 0;
3601                         psrch_inf->srch_entries_start =
3602                                 (char *) &pSMBr->hdr.Protocol +
3603                                         le16_to_cpu(pSMBr->t2.DataOffset);
3604                         parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3605                                le16_to_cpu(pSMBr->t2.ParameterOffset));
3606
3607                         if (parms->EndofSearch)
3608                                 psrch_inf->endOfSearch = true;
3609                         else
3610                                 psrch_inf->endOfSearch = false;
3611
3612                         psrch_inf->entries_in_buffer =
3613                                         le16_to_cpu(parms->SearchCount);
3614                         psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3615                                 psrch_inf->entries_in_buffer;
3616                         lnoff = le16_to_cpu(parms->LastNameOffset);
3617                         if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3618                               lnoff) {
3619                                 cERROR(1, ("ignoring corrupt resume name"));
3620                                 psrch_inf->last_entry = NULL;
3621                                 return rc;
3622                         }
3623
3624                         psrch_inf->last_entry = psrch_inf->srch_entries_start +
3625                                                         lnoff;
3626
3627                         *pnetfid = parms->SearchHandle;
3628                 } else {
3629                         cifs_buf_release(pSMB);
3630                 }
3631         }
3632
3633         return rc;
3634 }
3635
3636 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3637                  __u16 searchHandle, struct cifs_search_info *psrch_inf)
3638 {
3639         TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3640         TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3641         T2_FNEXT_RSP_PARMS *parms;
3642         char *response_data;
3643         int rc = 0;
3644         int bytes_returned, name_len;
3645         __u16 params, byte_count;
3646
3647         cFYI(1, ("In FindNext"));
3648
3649         if (psrch_inf->endOfSearch)
3650                 return -ENOENT;
3651
3652         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3653                 (void **) &pSMBr);
3654         if (rc)
3655                 return rc;
3656
3657         params = 14; /* includes 2 bytes of null string, converted to LE below*/
3658         byte_count = 0;
3659         pSMB->TotalDataCount = 0;       /* no EAs */
3660         pSMB->MaxParameterCount = cpu_to_le16(8);
3661         pSMB->MaxDataCount =
3662                 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
3663                                 0xFFFFFF00);
3664         pSMB->MaxSetupCount = 0;
3665         pSMB->Reserved = 0;
3666         pSMB->Flags = 0;
3667         pSMB->Timeout = 0;
3668         pSMB->Reserved2 = 0;
3669         pSMB->ParameterOffset =  cpu_to_le16(
3670               offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3671         pSMB->DataCount = 0;
3672         pSMB->DataOffset = 0;
3673         pSMB->SetupCount = 1;
3674         pSMB->Reserved3 = 0;
3675         pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3676         pSMB->SearchHandle = searchHandle;      /* always kept as le */
3677         pSMB->SearchCount =
3678                 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
3679         pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3680         pSMB->ResumeKey = psrch_inf->resume_key;
3681         pSMB->SearchFlags =
3682               cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3683
3684         name_len = psrch_inf->resume_name_len;
3685         params += name_len;
3686         if (name_len < PATH_MAX) {
3687                 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3688                 byte_count += name_len;
3689                 /* 14 byte parm len above enough for 2 byte null terminator */
3690                 pSMB->ResumeFileName[name_len] = 0;
3691                 pSMB->ResumeFileName[name_len+1] = 0;
3692         } else {
3693                 rc = -EINVAL;
3694                 goto FNext2_err_exit;
3695         }
3696         byte_count = params + 1 /* pad */ ;
3697         pSMB->TotalParameterCount = cpu_to_le16(params);
3698         pSMB->ParameterCount = pSMB->TotalParameterCount;
3699         pSMB->hdr.smb_buf_length += byte_count;
3700         pSMB->ByteCount = cpu_to_le16(byte_count);
3701
3702         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3703                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3704         cifs_stats_inc(&tcon->num_fnext);
3705         if (rc) {
3706                 if (rc == -EBADF) {
3707                         psrch_inf->endOfSearch = true;
3708                         cifs_buf_release(pSMB);
3709                         rc = 0; /* search probably was closed at end of search*/
3710                 } else
3711                         cFYI(1, ("FindNext returned = %d", rc));
3712         } else {                /* decode response */
3713                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3714
3715                 if (rc == 0) {
3716                         unsigned int lnoff;
3717
3718                         /* BB fixme add lock for file (srch_info) struct here */
3719                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3720                                 psrch_inf->unicode = true;
3721                         else
3722                                 psrch_inf->unicode = false;
3723                         response_data = (char *) &pSMBr->hdr.Protocol +
3724                                le16_to_cpu(pSMBr->t2.ParameterOffset);
3725                         parms = (T2_FNEXT_RSP_PARMS *)response_data;
3726                         response_data = (char *)&pSMBr->hdr.Protocol +
3727                                 le16_to_cpu(pSMBr->t2.DataOffset);
3728                         if (psrch_inf->smallBuf)
3729                                 cifs_small_buf_release(
3730                                         psrch_inf->ntwrk_buf_start);
3731                         else
3732                                 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3733                         psrch_inf->srch_entries_start = response_data;
3734                         psrch_inf->ntwrk_buf_start = (char *)pSMB;
3735                         psrch_inf->smallBuf = 0;
3736                         if (parms->EndofSearch)
3737                                 psrch_inf->endOfSearch = true;
3738                         else
3739                                 psrch_inf->endOfSearch = false;
3740                         psrch_inf->entries_in_buffer =
3741                                                 le16_to_cpu(parms->SearchCount);
3742                         psrch_inf->index_of_last_entry +=
3743                                 psrch_inf->entries_in_buffer;
3744                         lnoff = le16_to_cpu(parms->LastNameOffset);
3745                         if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3746                               lnoff) {
3747                                 cERROR(1, ("ignoring corrupt resume name"));
3748                                 psrch_inf->last_entry = NULL;
3749                                 return rc;
3750                         } else
3751                                 psrch_inf->last_entry =
3752                                         psrch_inf->srch_entries_start + lnoff;
3753
3754 /*  cFYI(1,("fnxt2 entries in buf %d index_of_last %d",
3755             psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */
3756
3757                         /* BB fixme add unlock here */
3758                 }
3759
3760         }
3761
3762         /* BB On error, should we leave previous search buf (and count and
3763         last entry fields) intact or free the previous one? */
3764
3765         /* Note: On -EAGAIN error only caller can retry on handle based calls
3766         since file handle passed in no longer valid */
3767 FNext2_err_exit:
3768         if (rc != 0)
3769                 cifs_buf_release(pSMB);
3770         return rc;
3771 }
3772
3773 int
3774 CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
3775               const __u16 searchHandle)
3776 {
3777         int rc = 0;
3778         FINDCLOSE_REQ *pSMB = NULL;
3779
3780         cFYI(1, ("In CIFSSMBFindClose"));
3781         rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3782
3783         /* no sense returning error if session restarted
3784                 as file handle has been closed */
3785         if (rc == -EAGAIN)
3786                 return 0;
3787         if (rc)
3788                 return rc;
3789
3790         pSMB->FileID = searchHandle;
3791         pSMB->ByteCount = 0;
3792         rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
3793         if (rc)
3794                 cERROR(1, ("Send error in FindClose = %d", rc));
3795
3796         cifs_stats_inc(&tcon->num_fclose);
3797
3798         /* Since session is dead, search handle closed on server already */
3799         if (rc == -EAGAIN)
3800                 rc = 0;
3801
3802         return rc;
3803 }
3804
3805 int
3806 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3807                       const unsigned char *searchName,
3808                       __u64 *inode_number,
3809                       const struct nls_table *nls_codepage, int remap)
3810 {
3811         int rc = 0;
3812         TRANSACTION2_QPI_REQ *pSMB = NULL;
3813         TRANSACTION2_QPI_RSP *pSMBr = NULL;
3814         int name_len, bytes_returned;
3815         __u16 params, byte_count;
3816
3817         cFYI(1, ("In GetSrvInodeNum for %s", searchName));
3818         if (tcon == NULL)
3819                 return -ENODEV;
3820
3821 GetInodeNumberRetry:
3822         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3823                       (void **) &pSMBr);
3824         if (rc)
3825                 return rc;
3826
3827         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3828                 name_len =
3829                         cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3830                                          PATH_MAX, nls_codepage, remap);
3831                 name_len++;     /* trailing null */
3832                 name_len *= 2;
3833         } else {        /* BB improve the check for buffer overruns BB */
3834                 name_len = strnlen(searchName, PATH_MAX);
3835                 name_len++;     /* trailing null */
3836                 strncpy(pSMB->FileName, searchName, name_len);
3837         }
3838
3839         params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
3840         pSMB->TotalDataCount = 0;
3841         pSMB->MaxParameterCount = cpu_to_le16(2);
3842         /* BB find exact max data count below from sess structure BB */
3843         pSMB->MaxDataCount = cpu_to_le16(4000);
3844         pSMB->MaxSetupCount = 0;
3845         pSMB->Reserved = 0;
3846         pSMB->Flags = 0;
3847         pSMB->Timeout = 0;
3848         pSMB->Reserved2 = 0;
3849         pSMB->ParameterOffset = cpu_to_le16(offsetof(
3850                 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3851         pSMB->DataCount = 0;
3852         pSMB->DataOffset = 0;
3853         pSMB->SetupCount = 1;
3854         pSMB->Reserved3 = 0;
3855         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3856         byte_count = params + 1 /* pad */ ;
3857         pSMB->TotalParameterCount = cpu_to_le16(params);
3858         pSMB->ParameterCount = pSMB->TotalParameterCount;
3859         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3860         pSMB->Reserved4 = 0;
3861         pSMB->hdr.smb_buf_length += byte_count;
3862         pSMB->ByteCount = cpu_to_le16(byte_count);
3863
3864         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3865                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3866         if (rc) {
3867                 cFYI(1, ("error %d in QueryInternalInfo", rc));
3868         } else {
3869                 /* decode response */
3870                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3871                 if (rc || (pSMBr->ByteCount < 2))
3872                 /* BB also check enough total bytes returned */
3873                         /* If rc should we check for EOPNOSUPP and
3874                         disable the srvino flag? or in caller? */
3875                         rc = -EIO;      /* bad smb */
3876                 else {
3877                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3878                         __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3879                         struct file_internal_info *pfinfo;
3880                         /* BB Do we need a cast or hash here ? */
3881                         if (count < 8) {
3882                                 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3883                                 rc = -EIO;
3884                                 goto GetInodeNumOut;
3885                         }
3886                         pfinfo = (struct file_internal_info *)
3887                                 (data_offset + (char *) &pSMBr->hdr.Protocol);
3888                         *inode_number = le64_to_cpu(pfinfo->UniqueId);
3889                 }
3890         }
3891 GetInodeNumOut:
3892         cifs_buf_release(pSMB);
3893         if (rc == -EAGAIN)
3894                 goto GetInodeNumberRetry;
3895         return rc;
3896 }
3897
3898 /* parses DFS refferal V3 structure
3899  * caller is responsible for freeing target_nodes
3900  * returns:
3901  *      on success - 0
3902  *      on failure - errno
3903  */
3904 static int
3905 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
3906                 unsigned int *num_of_nodes,
3907                 struct dfs_info3_param **target_nodes,
3908                 const struct nls_table *nls_codepage, int remap,
3909                 const char *searchName)
3910 {
3911         int i, rc = 0;
3912         char *data_end;
3913         bool is_unicode;
3914         struct dfs_referral_level_3 *ref;
3915
3916         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3917                 is_unicode = true;
3918         else
3919                 is_unicode = false;
3920         *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
3921
3922         if (*num_of_nodes < 1) {
3923                 cERROR(1, ("num_referrals: must be at least > 0,"
3924                         "but we get num_referrals = %d\n", *num_of_nodes));
3925                 rc = -EINVAL;
3926                 goto parse_DFS_referrals_exit;
3927         }
3928
3929         ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
3930         if (ref->VersionNumber != cpu_to_le16(3)) {
3931                 cERROR(1, ("Referrals of V%d version are not supported,"
3932                         "should be V3", le16_to_cpu(ref->VersionNumber)));
3933                 rc = -EINVAL;
3934                 goto parse_DFS_referrals_exit;
3935         }
3936
3937         /* get the upper boundary of the resp buffer */
3938         data_end = (char *)(&(pSMBr->PathConsumed)) +
3939                                 le16_to_cpu(pSMBr->t2.DataCount);
3940
3941         cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n",
3942                         *num_of_nodes,
3943                         le32_to_cpu(pSMBr->DFSFlags)));
3944
3945         *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
3946                         *num_of_nodes, GFP_KERNEL);
3947         if (*target_nodes == NULL) {
3948                 cERROR(1, ("Failed to allocate buffer for target_nodes\n"));
3949                 rc = -ENOMEM;
3950                 goto parse_DFS_referrals_exit;
3951         }
3952
3953         /* collect neccessary data from referrals */
3954         for (i = 0; i < *num_of_nodes; i++) {
3955                 char *temp;
3956                 int max_len;
3957                 struct dfs_info3_param *node = (*target_nodes)+i;
3958
3959                 node->flags = le32_to_cpu(pSMBr->DFSFlags);
3960                 if (is_unicode) {
3961                         __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
3962                                                 GFP_KERNEL);
3963                         if (tmp == NULL) {
3964                                 rc = -ENOMEM;
3965                                 goto parse_DFS_referrals_exit;
3966                         }
3967                         cifsConvertToUCS((__le16 *) tmp, searchName,
3968                                         PATH_MAX, nls_codepage, remap);
3969                         node->path_consumed = cifs_ucs2_bytes(tmp,
3970                                         le16_to_cpu(pSMBr->PathConsumed),
3971                                         nls_codepage);
3972                         kfree(tmp);
3973                 } else
3974                         node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
3975
3976                 node->server_type = le16_to_cpu(ref->ServerType);
3977                 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
3978
3979                 /* copy DfsPath */
3980                 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
3981                 max_len = data_end - temp;
3982                 node->path_name = cifs_strndup_from_ucs(temp, max_len,
3983                                                       is_unicode, nls_codepage);
3984                 if (!node->path_name) {
3985                         rc = -ENOMEM;
3986                         goto parse_DFS_referrals_exit;
3987                 }
3988
3989                 /* copy link target UNC */
3990                 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
3991                 max_len = data_end - temp;
3992                 node->node_name = cifs_strndup_from_ucs(temp, max_len,
3993                                                       is_unicode, nls_codepage);
3994                 if (!node->node_name)
3995                         rc = -ENOMEM;
3996         }
3997
3998 parse_DFS_referrals_exit:
3999         if (rc) {
4000                 free_dfs_info_array(*target_nodes, *num_of_nodes);
4001                 *target_nodes = NULL;
4002                 *num_of_nodes = 0;
4003         }
4004         return rc;
4005 }
4006
4007 int
4008 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
4009                 const unsigned char *searchName,
4010                 struct dfs_info3_param **target_nodes,
4011                 unsigned int *num_of_nodes,
4012                 const struct nls_table *nls_codepage, int remap)
4013 {
4014 /* TRANS2_GET_DFS_REFERRAL */
4015         TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4016         TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4017         int rc = 0;
4018         int bytes_returned;
4019         int name_len;
4020         __u16 params, byte_count;
4021         *num_of_nodes = 0;
4022         *target_nodes = NULL;
4023
4024         cFYI(1, ("In GetDFSRefer the path %s", searchName));
4025         if (ses == NULL)
4026                 return -ENODEV;
4027 getDFSRetry:
4028         rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4029                       (void **) &pSMBr);
4030         if (rc)
4031                 return rc;
4032
4033         /* server pointer checked in called function,
4034         but should never be null here anyway */
4035         pSMB->hdr.Mid = GetNextMid(ses->server);
4036         pSMB->hdr.Tid = ses->ipc_tid;
4037         pSMB->hdr.Uid = ses->Suid;
4038         if (ses->capabilities & CAP_STATUS32)
4039                 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4040         if (ses->capabilities & CAP_DFS)
4041                 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4042
4043         if (ses->capabilities & CAP_UNICODE) {
4044                 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4045                 name_len =
4046                     cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
4047                                      searchName, PATH_MAX, nls_codepage, remap);
4048                 name_len++;     /* trailing null */
4049                 name_len *= 2;
4050         } else {        /* BB improve the check for buffer overruns BB */
4051                 name_len = strnlen(searchName, PATH_MAX);
4052                 name_len++;     /* trailing null */
4053                 strncpy(pSMB->RequestFileName, searchName, name_len);
4054         }
4055
4056         if (ses->server) {
4057                 if (ses->server->secMode &
4058                    (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4059                         pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4060         }
4061
4062         pSMB->hdr.Uid = ses->Suid;
4063
4064         params = 2 /* level */  + name_len /*includes null */ ;
4065         pSMB->TotalDataCount = 0;
4066         pSMB->DataCount = 0;
4067         pSMB->DataOffset = 0;
4068         pSMB->MaxParameterCount = 0;
4069         /* BB find exact max SMB PDU from sess structure BB */
4070         pSMB->MaxDataCount = cpu_to_le16(4000);
4071         pSMB->MaxSetupCount = 0;
4072         pSMB->Reserved = 0;
4073         pSMB->Flags = 0;
4074         pSMB->Timeout = 0;
4075         pSMB->Reserved2 = 0;
4076         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4077           struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4078         pSMB->SetupCount = 1;
4079         pSMB->Reserved3 = 0;
4080         pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4081         byte_count = params + 3 /* pad */ ;
4082         pSMB->ParameterCount = cpu_to_le16(params);
4083         pSMB->TotalParameterCount = pSMB->ParameterCount;
4084         pSMB->MaxReferralLevel = cpu_to_le16(3);
4085         pSMB->hdr.smb_buf_length += byte_count;
4086         pSMB->ByteCount = cpu_to_le16(byte_count);
4087
4088         rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4089                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4090         if (rc) {
4091                 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
4092                 goto GetDFSRefExit;
4093         }
4094         rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4095
4096         /* BB Also check if enough total bytes returned? */
4097         if (rc || (pSMBr->ByteCount < 17)) {
4098                 rc = -EIO;      /* bad smb */
4099                 goto GetDFSRefExit;
4100         }
4101
4102         cFYI(1, ("Decoding GetDFSRefer response BCC: %d  Offset %d",
4103                                 pSMBr->ByteCount,
4104                                 le16_to_cpu(pSMBr->t2.DataOffset)));
4105
4106         /* parse returned result into more usable form */
4107         rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4108                                  target_nodes, nls_codepage, remap,
4109                                  searchName);
4110
4111 GetDFSRefExit:
4112         cifs_buf_release(pSMB);
4113
4114         if (rc == -EAGAIN)
4115                 goto getDFSRetry;
4116
4117         return rc;
4118 }
4119
4120 /* Query File System Info such as free space to old servers such as Win 9x */
4121 int
4122 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4123 {
4124 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4125         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4126         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4127         FILE_SYSTEM_ALLOC_INFO *response_data;
4128         int rc = 0;
4129         int bytes_returned = 0;
4130         __u16 params, byte_count;
4131
4132         cFYI(1, ("OldQFSInfo"));
4133 oldQFSInfoRetry:
4134         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4135                 (void **) &pSMBr);
4136         if (rc)
4137                 return rc;
4138
4139         params = 2;     /* level */
4140         pSMB->TotalDataCount = 0;
4141         pSMB->MaxParameterCount = cpu_to_le16(2);
4142         pSMB->MaxDataCount = cpu_to_le16(1000);
4143         pSMB->MaxSetupCount = 0;
4144         pSMB->Reserved = 0;
4145         pSMB->Flags = 0;
4146         pSMB->Timeout = 0;
4147         pSMB->Reserved2 = 0;
4148         byte_count = params + 1 /* pad */ ;
4149         pSMB->TotalParameterCount = cpu_to_le16(params);
4150         pSMB->ParameterCount = pSMB->TotalParameterCount;
4151         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4152         struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4153         pSMB->DataCount = 0;
4154         pSMB->DataOffset = 0;
4155         pSMB->SetupCount = 1;
4156         pSMB->Reserved3 = 0;
4157         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4158         pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4159         pSMB->hdr.smb_buf_length += byte_count;
4160         pSMB->ByteCount = cpu_to_le16(byte_count);
4161
4162         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4163                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4164         if (rc) {
4165                 cFYI(1, ("Send error in QFSInfo = %d", rc));
4166         } else {                /* decode response */
4167                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4168
4169                 if (rc || (pSMBr->ByteCount < 18))
4170                         rc = -EIO;      /* bad smb */
4171                 else {
4172                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4173                         cFYI(1, ("qfsinf resp BCC: %d  Offset %d",
4174                                  pSMBr->ByteCount, data_offset));
4175
4176                         response_data = (FILE_SYSTEM_ALLOC_INFO *)
4177                                 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4178                         FSData->f_bsize =
4179                                 le16_to_cpu(response_data->BytesPerSector) *
4180                                 le32_to_cpu(response_data->
4181                                         SectorsPerAllocationUnit);
4182                         FSData->f_blocks =
4183                                le32_to_cpu(response_data->TotalAllocationUnits);
4184                         FSData->f_bfree = FSData->f_bavail =
4185                                 le32_to_cpu(response_data->FreeAllocationUnits);
4186                         cFYI(1,
4187                              ("Blocks: %lld  Free: %lld Block size %ld",
4188                               (unsigned long long)FSData->f_blocks,
4189                               (unsigned long long)FSData->f_bfree,
4190                               FSData->f_bsize));
4191                 }
4192         }
4193         cifs_buf_release(pSMB);
4194
4195         if (rc == -EAGAIN)
4196                 goto oldQFSInfoRetry;
4197
4198         return rc;
4199 }
4200
4201 int
4202 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4203 {
4204 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4205         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4206         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4207         FILE_SYSTEM_INFO *response_data;
4208         int rc = 0;
4209         int bytes_returned = 0;
4210         __u16 params, byte_count;
4211
4212         cFYI(1, ("In QFSInfo"));
4213 QFSInfoRetry:
4214         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4215                       (void **) &pSMBr);
4216         if (rc)
4217                 return rc;
4218
4219         params = 2;     /* level */
4220         pSMB->TotalDataCount = 0;
4221         pSMB->MaxParameterCount = cpu_to_le16(2);
4222         pSMB->MaxDataCount = cpu_to_le16(1000);
4223         pSMB->MaxSetupCount = 0;
4224         pSMB->Reserved = 0;
4225         pSMB->Flags = 0;
4226         pSMB->Timeout = 0;
4227         pSMB->Reserved2 = 0;
4228         byte_count = params + 1 /* pad */ ;
4229         pSMB->TotalParameterCount = cpu_to_le16(params);
4230         pSMB->ParameterCount = pSMB->TotalParameterCount;
4231         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4232                 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4233         pSMB->DataCount = 0;
4234         pSMB->DataOffset = 0;
4235         pSMB->SetupCount = 1;
4236         pSMB->Reserved3 = 0;
4237         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4238         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4239         pSMB->hdr.smb_buf_length += byte_count;
4240         pSMB->ByteCount = cpu_to_le16(byte_count);
4241
4242         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4243                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4244         if (rc) {
4245                 cFYI(1, ("Send error in QFSInfo = %d", rc));
4246         } else {                /* decode response */
4247                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4248
4249                 if (rc || (pSMBr->ByteCount < 24))
4250                         rc = -EIO;      /* bad smb */
4251                 else {
4252                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4253
4254                         response_data =
4255                             (FILE_SYSTEM_INFO
4256                              *) (((char *) &pSMBr->hdr.Protocol) +
4257                                  data_offset);
4258                         FSData->f_bsize =
4259                             le32_to_cpu(response_data->BytesPerSector) *
4260                             le32_to_cpu(response_data->
4261                                         SectorsPerAllocationUnit);
4262                         FSData->f_blocks =
4263                             le64_to_cpu(response_data->TotalAllocationUnits);
4264                         FSData->f_bfree = FSData->f_bavail =
4265                             le64_to_cpu(response_data->FreeAllocationUnits);
4266                         cFYI(1,
4267                              ("Blocks: %lld  Free: %lld Block size %ld",
4268                               (unsigned long long)FSData->f_blocks,
4269                               (unsigned long long)FSData->f_bfree,
4270                               FSData->f_bsize));
4271                 }
4272         }
4273         cifs_buf_release(pSMB);
4274
4275         if (rc == -EAGAIN)
4276                 goto QFSInfoRetry;
4277
4278         return rc;
4279 }
4280
4281 int
4282 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4283 {
4284 /* level 0x105  SMB_QUERY_FILE_SYSTEM_INFO */
4285         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4286         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4287         FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4288         int rc = 0;
4289         int bytes_returned = 0;
4290         __u16 params, byte_count;
4291
4292         cFYI(1, ("In QFSAttributeInfo"));
4293 QFSAttributeRetry:
4294         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4295                       (void **) &pSMBr);
4296         if (rc)
4297                 return rc;
4298
4299         params = 2;     /* level */
4300         pSMB->TotalDataCount = 0;
4301         pSMB->MaxParameterCount = cpu_to_le16(2);
4302         /* BB find exact max SMB PDU from sess structure BB */
4303         pSMB->MaxDataCount = cpu_to_le16(1000);
4304         pSMB->MaxSetupCount = 0;
4305         pSMB->Reserved = 0;
4306         pSMB->Flags = 0;
4307         pSMB->Timeout = 0;
4308         pSMB->Reserved2 = 0;
4309         byte_count = params + 1 /* pad */ ;
4310         pSMB->TotalParameterCount = cpu_to_le16(params);
4311         pSMB->ParameterCount = pSMB->TotalParameterCount;
4312         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4313                 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4314         pSMB->DataCount = 0;
4315         pSMB->DataOffset = 0;
4316         pSMB->SetupCount = 1;
4317         pSMB->Reserved3 = 0;
4318         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4319         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4320         pSMB->hdr.smb_buf_length += byte_count;
4321         pSMB->ByteCount = cpu_to_le16(byte_count);
4322
4323         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4324                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4325         if (rc) {
4326                 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
4327         } else {                /* decode response */
4328                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4329
4330                 if (rc || (pSMBr->ByteCount < 13)) {
4331                         /* BB also check if enough bytes returned */
4332                         rc = -EIO;      /* bad smb */
4333                 } else {
4334                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4335                         response_data =
4336                             (FILE_SYSTEM_ATTRIBUTE_INFO
4337                              *) (((char *) &pSMBr->hdr.Protocol) +
4338                                  data_offset);
4339                         memcpy(&tcon->fsAttrInfo, response_data,
4340                                sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4341                 }
4342         }
4343         cifs_buf_release(pSMB);
4344
4345         if (rc == -EAGAIN)
4346                 goto QFSAttributeRetry;
4347
4348         return rc;
4349 }
4350
4351 int
4352 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4353 {
4354 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4355         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4356         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4357         FILE_SYSTEM_DEVICE_INFO *response_data;
4358         int rc = 0;
4359         int bytes_returned = 0;
4360         __u16 params, byte_count;
4361
4362         cFYI(1, ("In QFSDeviceInfo"));
4363 QFSDeviceRetry:
4364         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4365                       (void **) &pSMBr);
4366         if (rc)
4367                 return rc;
4368
4369         params = 2;     /* level */
4370         pSMB->TotalDataCount = 0;
4371         pSMB->MaxParameterCount = cpu_to_le16(2);
4372         /* BB find exact max SMB PDU from sess structure BB */
4373         pSMB->MaxDataCount = cpu_to_le16(1000);
4374         pSMB->MaxSetupCount = 0;
4375         pSMB->Reserved = 0;
4376         pSMB->Flags = 0;
4377         pSMB->Timeout = 0;
4378         pSMB->Reserved2 = 0;
4379         byte_count = params + 1 /* pad */ ;
4380         pSMB->TotalParameterCount = cpu_to_le16(params);
4381         pSMB->ParameterCount = pSMB->TotalParameterCount;
4382         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4383                 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4384
4385         pSMB->DataCount = 0;
4386         pSMB->DataOffset = 0;
4387         pSMB->SetupCount = 1;
4388         pSMB->Reserved3 = 0;
4389         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4390         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4391         pSMB->hdr.smb_buf_length += byte_count;
4392         pSMB->ByteCount = cpu_to_le16(byte_count);
4393
4394         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4395                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4396         if (rc) {
4397                 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
4398         } else {                /* decode response */
4399                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4400
4401                 if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO)))
4402                         rc = -EIO;      /* bad smb */
4403                 else {
4404                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4405                         response_data =
4406                             (FILE_SYSTEM_DEVICE_INFO *)
4407                                 (((char *) &pSMBr->hdr.Protocol) +
4408                                  data_offset);
4409                         memcpy(&tcon->fsDevInfo, response_data,
4410                                sizeof(FILE_SYSTEM_DEVICE_INFO));
4411                 }
4412         }
4413         cifs_buf_release(pSMB);
4414
4415         if (rc == -EAGAIN)
4416                 goto QFSDeviceRetry;
4417
4418         return rc;
4419 }
4420
4421 int
4422 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4423 {
4424 /* level 0x200  SMB_QUERY_CIFS_UNIX_INFO */
4425         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4426         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4427         FILE_SYSTEM_UNIX_INFO *response_data;
4428         int rc = 0;
4429         int bytes_returned = 0;
4430         __u16 params, byte_count;
4431
4432         cFYI(1, ("In QFSUnixInfo"));
4433 QFSUnixRetry:
4434         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4435                       (void **) &pSMBr);
4436         if (rc)
4437                 return rc;
4438
4439         params = 2;     /* level */
4440         pSMB->TotalDataCount = 0;
4441         pSMB->DataCount = 0;
4442         pSMB->DataOffset = 0;
4443         pSMB->MaxParameterCount = cpu_to_le16(2);
4444         /* BB find exact max SMB PDU from sess structure BB */
4445         pSMB->MaxDataCount = cpu_to_le16(100);
4446         pSMB->MaxSetupCount = 0;
4447         pSMB->Reserved = 0;
4448         pSMB->Flags = 0;
4449         pSMB->Timeout = 0;
4450         pSMB->Reserved2 = 0;
4451         byte_count = params + 1 /* pad */ ;
4452         pSMB->ParameterCount = cpu_to_le16(params);
4453         pSMB->TotalParameterCount = pSMB->ParameterCount;
4454         pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4455                         smb_com_transaction2_qfsi_req, InformationLevel) - 4);
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_CIFS_UNIX_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                 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
4467         } else {                /* decode response */
4468                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4469
4470                 if (rc || (pSMBr->ByteCount < 13)) {
4471                         rc = -EIO;      /* bad smb */
4472                 } else {
4473                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4474                         response_data =
4475                             (FILE_SYSTEM_UNIX_INFO
4476                              *) (((char *) &pSMBr->hdr.Protocol) +
4477                                  data_offset);
4478                         memcpy(&tcon->fsUnixInfo, response_data,
4479                                sizeof(FILE_SYSTEM_UNIX_INFO));
4480                 }
4481         }
4482         cifs_buf_release(pSMB);
4483
4484         if (rc == -EAGAIN)
4485                 goto QFSUnixRetry;
4486
4487
4488         return rc;
4489 }
4490
4491 int
4492 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4493 {
4494 /* level 0x200  SMB_SET_CIFS_UNIX_INFO */
4495         TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4496         TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4497         int rc = 0;
4498         int bytes_returned = 0;
4499         __u16 params, param_offset, offset, byte_count;
4500
4501         cFYI(1, ("In SETFSUnixInfo"));
4502 SETFSUnixRetry:
4503         /* BB switch to small buf init to save memory */
4504         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4505                       (void **) &pSMBr);
4506         if (rc)
4507                 return rc;
4508
4509         params = 4;     /* 2 bytes zero followed by info level. */
4510         pSMB->MaxSetupCount = 0;
4511         pSMB->Reserved = 0;
4512         pSMB->Flags = 0;
4513         pSMB->Timeout = 0;
4514         pSMB->Reserved2 = 0;
4515         param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4516                                 - 4;
4517         offset = param_offset + params;
4518
4519         pSMB->MaxParameterCount = cpu_to_le16(4);
4520         /* BB find exact max SMB PDU from sess structure BB */
4521         pSMB->MaxDataCount = cpu_to_le16(100);
4522         pSMB->SetupCount = 1;
4523         pSMB->Reserved3 = 0;
4524         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4525         byte_count = 1 /* pad */ + params + 12;
4526
4527         pSMB->DataCount = cpu_to_le16(12);
4528         pSMB->ParameterCount = cpu_to_le16(params);
4529         pSMB->TotalDataCount = pSMB->DataCount;
4530         pSMB->TotalParameterCount = pSMB->ParameterCount;
4531         pSMB->ParameterOffset = cpu_to_le16(param_offset);
4532         pSMB->DataOffset = cpu_to_le16(offset);
4533
4534         /* Params. */
4535         pSMB->FileNum = 0;
4536         pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4537
4538         /* Data. */
4539         pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4540         pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4541         pSMB->ClientUnixCap = cpu_to_le64(cap);
4542
4543         pSMB->hdr.smb_buf_length += byte_count;
4544         pSMB->ByteCount = cpu_to_le16(byte_count);
4545
4546         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4547                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4548         if (rc) {
4549                 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4550         } else {                /* decode response */
4551                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4552                 if (rc)
4553                         rc = -EIO;      /* bad smb */
4554         }
4555         cifs_buf_release(pSMB);
4556
4557         if (rc == -EAGAIN)
4558                 goto SETFSUnixRetry;
4559
4560         return rc;
4561 }
4562
4563
4564
4565 int
4566 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4567                    struct kstatfs *FSData)
4568 {
4569 /* level 0x201  SMB_QUERY_CIFS_POSIX_INFO */
4570         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4571         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4572         FILE_SYSTEM_POSIX_INFO *response_data;
4573         int rc = 0;
4574         int bytes_returned = 0;
4575         __u16 params, byte_count;
4576
4577         cFYI(1, ("In QFSPosixInfo"));
4578 QFSPosixRetry:
4579         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4580                       (void **) &pSMBr);
4581         if (rc)
4582                 return rc;
4583
4584         params = 2;     /* level */
4585         pSMB->TotalDataCount = 0;
4586         pSMB->DataCount = 0;
4587         pSMB->DataOffset = 0;
4588         pSMB->MaxParameterCount = cpu_to_le16(2);
4589         /* BB find exact max SMB PDU from sess structure BB */
4590         pSMB->MaxDataCount = cpu_to_le16(100);
4591         pSMB->MaxSetupCount = 0;
4592         pSMB->Reserved = 0;
4593         pSMB->Flags = 0;
4594         pSMB->Timeout = 0;
4595         pSMB->Reserved2 = 0;
4596         byte_count = params + 1 /* pad */ ;
4597         pSMB->ParameterCount = cpu_to_le16(params);
4598         pSMB->TotalParameterCount = pSMB->ParameterCount;
4599         pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4600                         smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4601         pSMB->SetupCount = 1;
4602         pSMB->Reserved3 = 0;
4603         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4604         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4605         pSMB->hdr.smb_buf_length += byte_count;
4606         pSMB->ByteCount = cpu_to_le16(byte_count);
4607
4608         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4609                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4610         if (rc) {
4611                 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4612         } else {                /* decode response */
4613                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4614
4615                 if (rc || (pSMBr->ByteCount < 13)) {
4616                         rc = -EIO;      /* bad smb */
4617                 } else {
4618                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4619                         response_data =
4620                             (FILE_SYSTEM_POSIX_INFO
4621                              *) (((char *) &pSMBr->hdr.Protocol) +
4622                                  data_offset);
4623                         FSData->f_bsize =
4624                                         le32_to_cpu(response_data->BlockSize);
4625                         FSData->f_blocks =
4626                                         le64_to_cpu(response_data->TotalBlocks);
4627                         FSData->f_bfree =
4628                             le64_to_cpu(response_data->BlocksAvail);
4629                         if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4630                                 FSData->f_bavail = FSData->f_bfree;
4631                         } else {
4632                                 FSData->f_bavail =
4633                                     le64_to_cpu(response_data->UserBlocksAvail);
4634                         }
4635                         if (response_data->TotalFileNodes != cpu_to_le64(-1))
4636                                 FSData->f_files =
4637                                      le64_to_cpu(response_data->TotalFileNodes);
4638                         if (response_data->FreeFileNodes != cpu_to_le64(-1))
4639                                 FSData->f_ffree =
4640                                       le64_to_cpu(response_data->FreeFileNodes);
4641                 }
4642         }
4643         cifs_buf_release(pSMB);
4644
4645         if (rc == -EAGAIN)
4646                 goto QFSPosixRetry;
4647
4648         return rc;
4649 }
4650
4651
4652 /* We can not use write of zero bytes trick to
4653    set file size due to need for large file support.  Also note that
4654    this SetPathInfo is preferred to SetFileInfo based method in next
4655    routine which is only needed to work around a sharing violation bug
4656    in Samba which this routine can run into */
4657
4658 int
4659 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4660               __u64 size, bool SetAllocation,
4661               const struct nls_table *nls_codepage, int remap)
4662 {
4663         struct smb_com_transaction2_spi_req *pSMB = NULL;
4664         struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4665         struct file_end_of_file_info *parm_data;
4666         int name_len;
4667         int rc = 0;
4668         int bytes_returned = 0;
4669         __u16 params, byte_count, data_count, param_offset, offset;
4670
4671         cFYI(1, ("In SetEOF"));
4672 SetEOFRetry:
4673         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4674                       (void **) &pSMBr);
4675         if (rc)
4676                 return rc;
4677
4678         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4679                 name_len =
4680                     cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4681                                      PATH_MAX, nls_codepage, remap);
4682                 name_len++;     /* trailing null */
4683                 name_len *= 2;
4684         } else {        /* BB improve the check for buffer overruns BB */
4685                 name_len = strnlen(fileName, PATH_MAX);
4686                 name_len++;     /* trailing null */
4687                 strncpy(pSMB->FileName, fileName, name_len);
4688         }
4689         params = 6 + name_len;
4690         data_count = sizeof(struct file_end_of_file_info);
4691         pSMB->MaxParameterCount = cpu_to_le16(2);
4692         pSMB->MaxDataCount = cpu_to_le16(4100);
4693         pSMB->MaxSetupCount = 0;
4694         pSMB->Reserved = 0;
4695         pSMB->Flags = 0;
4696         pSMB->Timeout = 0;
4697         pSMB->Reserved2 = 0;
4698         param_offset = offsetof(struct smb_com_transaction2_spi_req,
4699                                 InformationLevel) - 4;
4700         offset = param_offset + params;
4701         if (SetAllocation) {
4702                 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4703                         pSMB->InformationLevel =
4704                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4705                 else
4706                         pSMB->InformationLevel =
4707                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4708         } else /* Set File Size */  {
4709             if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4710                     pSMB->InformationLevel =
4711                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4712             else
4713                     pSMB->InformationLevel =
4714                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4715         }
4716
4717         parm_data =
4718             (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4719                                        offset);
4720         pSMB->ParameterOffset = cpu_to_le16(param_offset);
4721         pSMB->DataOffset = cpu_to_le16(offset);
4722         pSMB->SetupCount = 1;
4723         pSMB->Reserved3 = 0;
4724         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4725         byte_count = 3 /* pad */  + params + data_count;
4726         pSMB->DataCount = cpu_to_le16(data_count);
4727         pSMB->TotalDataCount = pSMB->DataCount;
4728         pSMB->ParameterCount = cpu_to_le16(params);
4729         pSMB->TotalParameterCount = pSMB->ParameterCount;
4730         pSMB->Reserved4 = 0;
4731         pSMB->hdr.smb_buf_length += byte_count;
4732         parm_data->FileSize = cpu_to_le64(size);
4733         pSMB->ByteCount = cpu_to_le16(byte_count);
4734         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4735                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4736         if (rc)
4737                 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4738
4739         cifs_buf_release(pSMB);
4740
4741         if (rc == -EAGAIN)
4742                 goto SetEOFRetry;
4743
4744         return rc;
4745 }
4746
4747 int
4748 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4749                    __u16 fid, __u32 pid_of_opener, bool SetAllocation)
4750 {
4751         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
4752         char *data_offset;
4753         struct file_end_of_file_info *parm_data;
4754         int rc = 0;
4755         __u16 params, param_offset, offset, byte_count, count;
4756
4757         cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4758                         (long long)size));
4759         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4760
4761         if (rc)
4762                 return rc;
4763
4764         pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4765         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4766
4767         params = 6;
4768         pSMB->MaxSetupCount = 0;
4769         pSMB->Reserved = 0;
4770         pSMB->Flags = 0;
4771         pSMB->Timeout = 0;
4772         pSMB->Reserved2 = 0;
4773         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4774         offset = param_offset + params;
4775
4776         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4777
4778         count = sizeof(struct file_end_of_file_info);
4779         pSMB->MaxParameterCount = cpu_to_le16(2);
4780         /* BB find exact max SMB PDU from sess structure BB */
4781         pSMB->MaxDataCount = cpu_to_le16(1000);
4782         pSMB->SetupCount = 1;
4783         pSMB->Reserved3 = 0;
4784         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4785         byte_count = 3 /* pad */  + params + count;
4786         pSMB->DataCount = cpu_to_le16(count);
4787         pSMB->ParameterCount = cpu_to_le16(params);
4788         pSMB->TotalDataCount = pSMB->DataCount;
4789         pSMB->TotalParameterCount = pSMB->ParameterCount;
4790         pSMB->ParameterOffset = cpu_to_le16(param_offset);
4791         parm_data =
4792                 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
4793                                 + offset);
4794         pSMB->DataOffset = cpu_to_le16(offset);
4795         parm_data->FileSize = cpu_to_le64(size);
4796         pSMB->Fid = fid;
4797         if (SetAllocation) {
4798                 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4799                         pSMB->InformationLevel =
4800                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4801                 else
4802                         pSMB->InformationLevel =
4803                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4804         } else /* Set File Size */  {
4805             if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4806                     pSMB->InformationLevel =
4807                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4808             else
4809                     pSMB->InformationLevel =
4810                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4811         }
4812         pSMB->Reserved4 = 0;
4813         pSMB->hdr.smb_buf_length += byte_count;
4814         pSMB->ByteCount = cpu_to_le16(byte_count);
4815         rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4816         if (rc) {
4817                 cFYI(1,
4818                      ("Send error in SetFileInfo (SetFileSize) = %d",
4819                       rc));
4820         }
4821
4822         /* Note: On -EAGAIN error only caller can retry on handle based calls
4823                 since file handle passed in no longer valid */
4824
4825         return rc;
4826 }
4827
4828 /* Some legacy servers such as NT4 require that the file times be set on
4829    an open handle, rather than by pathname - this is awkward due to
4830    potential access conflicts on the open, but it is unavoidable for these
4831    old servers since the only other choice is to go from 100 nanosecond DCE
4832    time and resort to the original setpathinfo level which takes the ancient
4833    DOS time format with 2 second granularity */
4834 int
4835 CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon,
4836                     const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
4837 {
4838         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
4839         char *data_offset;
4840         int rc = 0;
4841         __u16 params, param_offset, offset, byte_count, count;
4842
4843         cFYI(1, ("Set Times (via SetFileInfo)"));
4844         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4845
4846         if (rc)
4847                 return rc;
4848
4849         pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4850         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4851
4852         params = 6;
4853         pSMB->MaxSetupCount = 0;
4854         pSMB->Reserved = 0;
4855         pSMB->Flags = 0;
4856         pSMB->Timeout = 0;
4857         pSMB->Reserved2 = 0;
4858         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4859         offset = param_offset + params;
4860
4861         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4862
4863         count = sizeof(FILE_BASIC_INFO);
4864         pSMB->MaxParameterCount = cpu_to_le16(2);
4865         /* BB find max SMB PDU from sess */
4866         pSMB->MaxDataCount = cpu_to_le16(1000);
4867         pSMB->SetupCount = 1;
4868         pSMB->Reserved3 = 0;
4869         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4870         byte_count = 3 /* pad */  + params + count;
4871         pSMB->DataCount = cpu_to_le16(count);
4872         pSMB->ParameterCount = cpu_to_le16(params);
4873         pSMB->TotalDataCount = pSMB->DataCount;
4874         pSMB->TotalParameterCount = pSMB->ParameterCount;
4875         pSMB->ParameterOffset = cpu_to_le16(param_offset);
4876         pSMB->DataOffset = cpu_to_le16(offset);
4877         pSMB->Fid = fid;
4878         if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4879                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4880         else
4881                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4882         pSMB->Reserved4 = 0;
4883         pSMB->hdr.smb_buf_length += byte_count;
4884         pSMB->ByteCount = cpu_to_le16(byte_count);
4885         memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4886         rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4887         if (rc)
4888                 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc));
4889
4890         /* Note: On -EAGAIN error only caller can retry on handle based calls
4891                 since file handle passed in no longer valid */
4892
4893         return rc;
4894 }
4895
4896 int
4897 CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon,
4898                           bool delete_file, __u16 fid, __u32 pid_of_opener)
4899 {
4900         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
4901         char *data_offset;
4902         int rc = 0;
4903         __u16 params, param_offset, offset, byte_count, count;
4904
4905         cFYI(1, ("Set File Disposition (via SetFileInfo)"));
4906         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4907
4908         if (rc)
4909                 return rc;
4910
4911         pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4912         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4913
4914         params = 6;
4915         pSMB->MaxSetupCount = 0;
4916         pSMB->Reserved = 0;
4917         pSMB->Flags = 0;
4918         pSMB->Timeout = 0;
4919         pSMB->Reserved2 = 0;
4920         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4921         offset = param_offset + params;
4922
4923         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4924
4925         count = 1;
4926         pSMB->MaxParameterCount = cpu_to_le16(2);
4927         /* BB find max SMB PDU from sess */
4928         pSMB->MaxDataCount = cpu_to_le16(1000);
4929         pSMB->SetupCount = 1;
4930         pSMB->Reserved3 = 0;
4931         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4932         byte_count = 3 /* pad */  + params + count;
4933         pSMB->DataCount = cpu_to_le16(count);
4934         pSMB->ParameterCount = cpu_to_le16(params);
4935         pSMB->TotalDataCount = pSMB->DataCount;
4936         pSMB->TotalParameterCount = pSMB->ParameterCount;
4937         pSMB->ParameterOffset = cpu_to_le16(param_offset);
4938         pSMB->DataOffset = cpu_to_le16(offset);
4939         pSMB->Fid = fid;
4940         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
4941         pSMB->Reserved4 = 0;
4942         pSMB->hdr.smb_buf_length += byte_count;
4943         pSMB->ByteCount = cpu_to_le16(byte_count);
4944         *data_offset = delete_file ? 1 : 0;
4945         rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4946         if (rc)
4947                 cFYI(1, ("Send error in SetFileDisposition = %d", rc));
4948
4949         return rc;
4950 }
4951
4952 int
4953 CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon,
4954                    const char *fileName, const FILE_BASIC_INFO *data,
4955                    const struct nls_table *nls_codepage, int remap)
4956 {
4957         TRANSACTION2_SPI_REQ *pSMB = NULL;
4958         TRANSACTION2_SPI_RSP *pSMBr = NULL;
4959         int name_len;
4960         int rc = 0;
4961         int bytes_returned = 0;
4962         char *data_offset;
4963         __u16 params, param_offset, offset, byte_count, count;
4964
4965         cFYI(1, ("In SetTimes"));
4966
4967 SetTimesRetry:
4968         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4969                       (void **) &pSMBr);
4970         if (rc)
4971                 return rc;
4972
4973         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4974                 name_len =
4975                     cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4976                                      PATH_MAX, nls_codepage, remap);
4977                 name_len++;     /* trailing null */
4978                 name_len *= 2;
4979         } else {        /* BB improve the check for buffer overruns BB */
4980                 name_len = strnlen(fileName, PATH_MAX);
4981                 name_len++;     /* trailing null */
4982                 strncpy(pSMB->FileName, fileName, name_len);
4983         }
4984
4985         params = 6 + name_len;
4986         count = sizeof(FILE_BASIC_INFO);
4987         pSMB->MaxParameterCount = cpu_to_le16(2);
4988         /* BB find max SMB PDU from sess structure BB */
4989         pSMB->MaxDataCount = cpu_to_le16(1000);
4990         pSMB->MaxSetupCount = 0;
4991         pSMB->Reserved = 0;
4992         pSMB->Flags = 0;
4993         pSMB->Timeout = 0;
4994         pSMB->Reserved2 = 0;
4995         param_offset = offsetof(struct smb_com_transaction2_spi_req,
4996                                 InformationLevel) - 4;
4997         offset = param_offset + params;
4998         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4999         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5000         pSMB->DataOffset = cpu_to_le16(offset);
5001         pSMB->SetupCount = 1;
5002         pSMB->Reserved3 = 0;
5003         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5004         byte_count = 3 /* pad */  + params + count;
5005
5006         pSMB->DataCount = cpu_to_le16(count);
5007         pSMB->ParameterCount = cpu_to_le16(params);
5008         pSMB->TotalDataCount = pSMB->DataCount;
5009         pSMB->TotalParameterCount = pSMB->ParameterCount;
5010         if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5011                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5012         else
5013                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5014         pSMB->Reserved4 = 0;
5015         pSMB->hdr.smb_buf_length += byte_count;
5016         memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5017         pSMB->ByteCount = cpu_to_le16(byte_count);
5018         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5019                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5020         if (rc)
5021                 cFYI(1, ("SetPathInfo (times) returned %d", rc));
5022
5023         cifs_buf_release(pSMB);
5024
5025         if (rc == -EAGAIN)
5026                 goto SetTimesRetry;
5027
5028         return rc;
5029 }
5030
5031 /* Can not be used to set time stamps yet (due to old DOS time format) */
5032 /* Can be used to set attributes */
5033 #if 0  /* Possibly not needed - since it turns out that strangely NT4 has a bug
5034           handling it anyway and NT4 was what we thought it would be needed for
5035           Do not delete it until we prove whether needed for Win9x though */
5036 int
5037 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
5038                 __u16 dos_attrs, const struct nls_table *nls_codepage)
5039 {
5040         SETATTR_REQ *pSMB = NULL;
5041         SETATTR_RSP *pSMBr = NULL;
5042         int rc = 0;
5043         int bytes_returned;
5044         int name_len;
5045
5046         cFYI(1, ("In SetAttrLegacy"));
5047
5048 SetAttrLgcyRetry:
5049         rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5050                       (void **) &pSMBr);
5051         if (rc)
5052                 return rc;
5053
5054         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5055                 name_len =
5056                         ConvertToUCS((__le16 *) pSMB->fileName, fileName,
5057                                 PATH_MAX, nls_codepage);
5058                 name_len++;     /* trailing null */
5059                 name_len *= 2;
5060         } else {        /* BB improve the check for buffer overruns BB */
5061                 name_len = strnlen(fileName, PATH_MAX);
5062                 name_len++;     /* trailing null */
5063                 strncpy(pSMB->fileName, fileName, name_len);
5064         }
5065         pSMB->attr = cpu_to_le16(dos_attrs);
5066         pSMB->BufferFormat = 0x04;
5067         pSMB->hdr.smb_buf_length += name_len + 1;
5068         pSMB->ByteCount = cpu_to_le16(name_len + 1);
5069         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5070                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5071         if (rc)
5072                 cFYI(1, ("Error in LegacySetAttr = %d", rc));
5073
5074         cifs_buf_release(pSMB);
5075
5076         if (rc == -EAGAIN)
5077                 goto SetAttrLgcyRetry;
5078
5079         return rc;
5080 }
5081 #endif /* temporarily unneeded SetAttr legacy function */
5082
5083 static void
5084 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
5085                         const struct cifs_unix_set_info_args *args)
5086 {
5087         u64 mode = args->mode;
5088
5089         /*
5090          * Samba server ignores set of file size to zero due to bugs in some
5091          * older clients, but we should be precise - we use SetFileSize to
5092          * set file size and do not want to truncate file size to zero
5093          * accidently as happened on one Samba server beta by putting
5094          * zero instead of -1 here
5095          */
5096         data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5097         data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5098         data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5099         data_offset->LastAccessTime = cpu_to_le64(args->atime);
5100         data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5101         data_offset->Uid = cpu_to_le64(args->uid);
5102         data_offset->Gid = cpu_to_le64(args->gid);
5103         /* better to leave device as zero when it is  */
5104         data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5105         data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5106         data_offset->Permissions = cpu_to_le64(mode);
5107
5108         if (S_ISREG(mode))
5109                 data_offset->Type = cpu_to_le32(UNIX_FILE);
5110         else if (S_ISDIR(mode))
5111                 data_offset->Type = cpu_to_le32(UNIX_DIR);
5112         else if (S_ISLNK(mode))
5113                 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5114         else if (S_ISCHR(mode))
5115                 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5116         else if (S_ISBLK(mode))
5117                 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5118         else if (S_ISFIFO(mode))
5119                 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5120         else if (S_ISSOCK(mode))
5121                 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5122 }
5123
5124 int
5125 CIFSSMBUnixSetFileInfo(const int xid, struct cifsTconInfo *tcon,
5126                        const struct cifs_unix_set_info_args *args,
5127                        u16 fid, u32 pid_of_opener)
5128 {
5129         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5130         FILE_UNIX_BASIC_INFO *data_offset;
5131         int rc = 0;
5132         u16 params, param_offset, offset, byte_count, count;
5133
5134         cFYI(1, ("Set Unix Info (via SetFileInfo)"));
5135         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5136
5137         if (rc)
5138                 return rc;
5139
5140         pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5141         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5142
5143         params = 6;
5144         pSMB->MaxSetupCount = 0;
5145         pSMB->Reserved = 0;
5146         pSMB->Flags = 0;
5147         pSMB->Timeout = 0;
5148         pSMB->Reserved2 = 0;
5149         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5150         offset = param_offset + params;
5151
5152         data_offset = (FILE_UNIX_BASIC_INFO *)
5153                                 ((char *)(&pSMB->hdr.Protocol) + offset);
5154         count = sizeof(FILE_UNIX_BASIC_INFO);
5155
5156         pSMB->MaxParameterCount = cpu_to_le16(2);
5157         /* BB find max SMB PDU from sess */
5158         pSMB->MaxDataCount = cpu_to_le16(1000);
5159         pSMB->SetupCount = 1;
5160         pSMB->Reserved3 = 0;
5161         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5162         byte_count = 3 /* pad */  + params + count;
5163         pSMB->DataCount = cpu_to_le16(count);
5164         pSMB->ParameterCount = cpu_to_le16(params);
5165         pSMB->TotalDataCount = pSMB->DataCount;
5166         pSMB->TotalParameterCount = pSMB->ParameterCount;
5167         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5168         pSMB->DataOffset = cpu_to_le16(offset);
5169         pSMB->Fid = fid;
5170         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5171         pSMB->Reserved4 = 0;
5172         pSMB->hdr.smb_buf_length += byte_count;
5173         pSMB->ByteCount = cpu_to_le16(byte_count);
5174
5175         cifs_fill_unix_set_info(data_offset, args);
5176
5177         rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5178         if (rc)
5179                 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc));
5180
5181         /* Note: On -EAGAIN error only caller can retry on handle based calls
5182                 since file handle passed in no longer valid */
5183
5184         return rc;
5185 }
5186
5187 int
5188 CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *tcon, char *fileName,
5189                        const struct cifs_unix_set_info_args *args,
5190                        const struct nls_table *nls_codepage, int remap)
5191 {
5192         TRANSACTION2_SPI_REQ *pSMB = NULL;
5193         TRANSACTION2_SPI_RSP *pSMBr = NULL;
5194         int name_len;
5195         int rc = 0;
5196         int bytes_returned = 0;
5197         FILE_UNIX_BASIC_INFO *data_offset;
5198         __u16 params, param_offset, offset, count, byte_count;
5199
5200         cFYI(1, ("In SetUID/GID/Mode"));
5201 setPermsRetry:
5202         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5203                       (void **) &pSMBr);
5204         if (rc)
5205                 return rc;
5206
5207         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5208                 name_len =
5209                     cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5210                                      PATH_MAX, nls_codepage, remap);
5211                 name_len++;     /* trailing null */
5212                 name_len *= 2;
5213         } else {        /* BB improve the check for buffer overruns BB */
5214                 name_len = strnlen(fileName, PATH_MAX);
5215                 name_len++;     /* trailing null */
5216                 strncpy(pSMB->FileName, fileName, name_len);
5217         }
5218
5219         params = 6 + name_len;
5220         count = sizeof(FILE_UNIX_BASIC_INFO);
5221         pSMB->MaxParameterCount = cpu_to_le16(2);
5222         /* BB find max SMB PDU from sess structure BB */
5223         pSMB->MaxDataCount = cpu_to_le16(1000);
5224         pSMB->MaxSetupCount = 0;
5225         pSMB->Reserved = 0;
5226         pSMB->Flags = 0;
5227         pSMB->Timeout = 0;
5228         pSMB->Reserved2 = 0;
5229         param_offset = offsetof(struct smb_com_transaction2_spi_req,
5230                                 InformationLevel) - 4;
5231         offset = param_offset + params;
5232         data_offset =
5233             (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5234                                       offset);
5235         memset(data_offset, 0, count);
5236         pSMB->DataOffset = cpu_to_le16(offset);
5237         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5238         pSMB->SetupCount = 1;
5239         pSMB->Reserved3 = 0;
5240         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5241         byte_count = 3 /* pad */  + params + count;
5242         pSMB->ParameterCount = cpu_to_le16(params);
5243         pSMB->DataCount = cpu_to_le16(count);
5244         pSMB->TotalParameterCount = pSMB->ParameterCount;
5245         pSMB->TotalDataCount = pSMB->DataCount;
5246         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5247         pSMB->Reserved4 = 0;
5248         pSMB->hdr.smb_buf_length += byte_count;
5249
5250         cifs_fill_unix_set_info(data_offset, args);
5251
5252         pSMB->ByteCount = cpu_to_le16(byte_count);
5253         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5254                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5255         if (rc)
5256                 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
5257
5258         cifs_buf_release(pSMB);
5259         if (rc == -EAGAIN)
5260                 goto setPermsRetry;
5261         return rc;
5262 }
5263
5264 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5265                   const int notify_subdirs, const __u16 netfid,
5266                   __u32 filter, struct file *pfile, int multishot,
5267                   const struct nls_table *nls_codepage)
5268 {
5269         int rc = 0;
5270         struct smb_com_transaction_change_notify_req *pSMB = NULL;
5271         struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
5272         struct dir_notify_req *dnotify_req;
5273         int bytes_returned;
5274
5275         cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid));
5276         rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
5277                       (void **) &pSMBr);
5278         if (rc)
5279                 return rc;
5280
5281         pSMB->TotalParameterCount = 0 ;
5282         pSMB->TotalDataCount = 0;
5283         pSMB->MaxParameterCount = cpu_to_le32(2);
5284         /* BB find exact data count max from sess structure BB */
5285         pSMB->MaxDataCount = 0; /* same in little endian or be */
5286 /* BB VERIFY verify which is correct for above BB */
5287         pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
5288                                              MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
5289
5290         pSMB->MaxSetupCount = 4;
5291         pSMB->Reserved = 0;
5292         pSMB->ParameterOffset = 0;
5293         pSMB->DataCount = 0;
5294         pSMB->DataOffset = 0;
5295         pSMB->SetupCount = 4; /* single byte does not need le conversion */
5296         pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
5297         pSMB->ParameterCount = pSMB->TotalParameterCount;
5298         if (notify_subdirs)
5299                 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
5300         pSMB->Reserved2 = 0;
5301         pSMB->CompletionFilter = cpu_to_le32(filter);
5302         pSMB->Fid = netfid; /* file handle always le */
5303         pSMB->ByteCount = 0;
5304
5305         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5306                          (struct smb_hdr *)pSMBr, &bytes_returned,
5307                          CIFS_ASYNC_OP);
5308         if (rc) {
5309                 cFYI(1, ("Error in Notify = %d", rc));
5310         } else {
5311                 /* Add file to outstanding requests */
5312                 /* BB change to kmem cache alloc */
5313                 dnotify_req = kmalloc(
5314                                                 sizeof(struct dir_notify_req),
5315                                                  GFP_KERNEL);
5316                 if (dnotify_req) {
5317                         dnotify_req->Pid = pSMB->hdr.Pid;
5318                         dnotify_req->PidHigh = pSMB->hdr.PidHigh;
5319                         dnotify_req->Mid = pSMB->hdr.Mid;
5320                         dnotify_req->Tid = pSMB->hdr.Tid;
5321                         dnotify_req->Uid = pSMB->hdr.Uid;
5322                         dnotify_req->netfid = netfid;
5323                         dnotify_req->pfile = pfile;
5324                         dnotify_req->filter = filter;
5325                         dnotify_req->multishot = multishot;
5326                         spin_lock(&GlobalMid_Lock);
5327                         list_add_tail(&dnotify_req->lhead,
5328                                         &GlobalDnotifyReqList);
5329                         spin_unlock(&GlobalMid_Lock);
5330                 } else
5331                         rc = -ENOMEM;
5332         }
5333         cifs_buf_release(pSMB);
5334         return rc;
5335 }
5336
5337 #ifdef CONFIG_CIFS_XATTR
5338 /*
5339  * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
5340  * function used by listxattr and getxattr type calls. When ea_name is set,
5341  * it looks for that attribute name and stuffs that value into the EAData
5342  * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
5343  * buffer. In both cases, the return value is either the length of the
5344  * resulting data or a negative error code. If EAData is a NULL pointer then
5345  * the data isn't copied to it, but the length is returned.
5346  */
5347 ssize_t
5348 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5349                 const unsigned char *searchName, const unsigned char *ea_name,
5350                 char *EAData, size_t buf_size,
5351                 const struct nls_table *nls_codepage, int remap)
5352 {
5353                 /* BB assumes one setup word */
5354         TRANSACTION2_QPI_REQ *pSMB = NULL;
5355         TRANSACTION2_QPI_RSP *pSMBr = NULL;
5356         int rc = 0;
5357         int bytes_returned;
5358         int list_len;
5359         struct fealist *ea_response_data;
5360         struct fea *temp_fea;
5361         char *temp_ptr;
5362         char *end_of_smb;
5363         __u16 params, byte_count, data_offset;
5364
5365         cFYI(1, ("In Query All EAs path %s", searchName));
5366 QAllEAsRetry:
5367         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5368                       (void **) &pSMBr);
5369         if (rc)
5370                 return rc;
5371
5372         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5373                 list_len =
5374                     cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5375                                      PATH_MAX, nls_codepage, remap);
5376                 list_len++;     /* trailing null */
5377                 list_len *= 2;
5378         } else {        /* BB improve the check for buffer overruns BB */
5379                 list_len = strnlen(searchName, PATH_MAX);
5380                 list_len++;     /* trailing null */
5381                 strncpy(pSMB->FileName, searchName, list_len);
5382         }
5383
5384         params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
5385         pSMB->TotalDataCount = 0;
5386         pSMB->MaxParameterCount = cpu_to_le16(2);
5387         /* BB find exact max SMB PDU from sess structure BB */
5388         pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
5389         pSMB->MaxSetupCount = 0;
5390         pSMB->Reserved = 0;
5391         pSMB->Flags = 0;
5392         pSMB->Timeout = 0;
5393         pSMB->Reserved2 = 0;
5394         pSMB->ParameterOffset = cpu_to_le16(offsetof(
5395         struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5396         pSMB->DataCount = 0;
5397         pSMB->DataOffset = 0;
5398         pSMB->SetupCount = 1;
5399         pSMB->Reserved3 = 0;
5400         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5401         byte_count = params + 1 /* pad */ ;
5402         pSMB->TotalParameterCount = cpu_to_le16(params);
5403         pSMB->ParameterCount = pSMB->TotalParameterCount;
5404         pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5405         pSMB->Reserved4 = 0;
5406         pSMB->hdr.smb_buf_length += byte_count;
5407         pSMB->ByteCount = cpu_to_le16(byte_count);
5408
5409         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5410                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5411         if (rc) {
5412                 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
5413                 goto QAllEAsOut;
5414         }
5415
5416
5417         /* BB also check enough total bytes returned */
5418         /* BB we need to improve the validity checking
5419         of these trans2 responses */
5420
5421         rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5422         if (rc || (pSMBr->ByteCount < 4)) {
5423                 rc = -EIO;      /* bad smb */
5424                 goto QAllEAsOut;
5425         }
5426
5427         /* check that length of list is not more than bcc */
5428         /* check that each entry does not go beyond length
5429            of list */
5430         /* check that each element of each entry does not
5431            go beyond end of list */
5432         /* validate_trans2_offsets() */
5433         /* BB check if start of smb + data_offset > &bcc+ bcc */
5434
5435         data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5436         ea_response_data = (struct fealist *)
5437                                 (((char *) &pSMBr->hdr.Protocol) + data_offset);
5438
5439         list_len = le32_to_cpu(ea_response_data->list_len);
5440         cFYI(1, ("ea length %d", list_len));
5441         if (list_len <= 8) {
5442                 cFYI(1, ("empty EA list returned from server"));
5443                 goto QAllEAsOut;
5444         }
5445
5446         /* make sure list_len doesn't go past end of SMB */
5447         end_of_smb = (char *)pByteArea(&pSMBr->hdr) + BCC(&pSMBr->hdr);
5448         if ((char *)ea_response_data + list_len > end_of_smb) {
5449                 cFYI(1, ("EA list appears to go beyond SMB"));
5450                 rc = -EIO;
5451                 goto QAllEAsOut;
5452         }
5453
5454         /* account for ea list len */
5455         list_len -= 4;
5456         temp_fea = ea_response_data->list;
5457         temp_ptr = (char *)temp_fea;
5458         while (list_len > 0) {
5459                 unsigned int name_len;
5460                 __u16 value_len;
5461
5462                 list_len -= 4;
5463                 temp_ptr += 4;
5464                 /* make sure we can read name_len and value_len */
5465                 if (list_len < 0) {
5466                         cFYI(1, ("EA entry goes beyond length of list"));
5467                         rc = -EIO;
5468                         goto QAllEAsOut;
5469                 }
5470
5471                 name_len = temp_fea->name_len;
5472                 value_len = le16_to_cpu(temp_fea->value_len);
5473                 list_len -= name_len + 1 + value_len;
5474                 if (list_len < 0) {
5475                         cFYI(1, ("EA entry goes beyond length of list"));
5476                         rc = -EIO;
5477                         goto QAllEAsOut;
5478                 }
5479
5480                 if (ea_name) {
5481                         if (strncmp(ea_name, temp_ptr, name_len) == 0) {
5482                                 temp_ptr += name_len + 1;
5483                                 rc = value_len;
5484                                 if (buf_size == 0)
5485                                         goto QAllEAsOut;
5486                                 if ((size_t)value_len > buf_size) {
5487                                         rc = -ERANGE;
5488                                         goto QAllEAsOut;
5489                                 }
5490                                 memcpy(EAData, temp_ptr, value_len);
5491                                 goto QAllEAsOut;
5492                         }
5493                 } else {
5494                         /* account for prefix user. and trailing null */
5495                         rc += (5 + 1 + name_len);
5496                         if (rc < (int) buf_size) {
5497                                 memcpy(EAData, "user.", 5);
5498                                 EAData += 5;
5499                                 memcpy(EAData, temp_ptr, name_len);
5500                                 EAData += name_len;
5501                                 /* null terminate name */
5502                                 *EAData = 0;
5503                                 ++EAData;
5504                         } else if (buf_size == 0) {
5505                                 /* skip copy - calc size only */
5506                         } else {
5507                                 /* stop before overrun buffer */
5508                                 rc = -ERANGE;
5509                                 break;
5510                         }
5511                 }
5512                 temp_ptr += name_len + 1 + value_len;
5513                 temp_fea = (struct fea *)temp_ptr;
5514         }
5515
5516         /* didn't find the named attribute */
5517         if (ea_name)
5518                 rc = -ENODATA;
5519
5520 QAllEAsOut:
5521         cifs_buf_release(pSMB);
5522         if (rc == -EAGAIN)
5523                 goto QAllEAsRetry;
5524
5525         return (ssize_t)rc;
5526 }
5527
5528 int
5529 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5530              const char *ea_name, const void *ea_value,
5531              const __u16 ea_value_len, const struct nls_table *nls_codepage,
5532              int remap)
5533 {
5534         struct smb_com_transaction2_spi_req *pSMB = NULL;
5535         struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5536         struct fealist *parm_data;
5537         int name_len;
5538         int rc = 0;
5539         int bytes_returned = 0;
5540         __u16 params, param_offset, byte_count, offset, count;
5541
5542         cFYI(1, ("In SetEA"));
5543 SetEARetry:
5544         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5545                       (void **) &pSMBr);
5546         if (rc)
5547                 return rc;
5548
5549         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5550                 name_len =
5551                     cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5552                                      PATH_MAX, nls_codepage, remap);
5553                 name_len++;     /* trailing null */
5554                 name_len *= 2;
5555         } else {        /* BB improve the check for buffer overruns BB */
5556                 name_len = strnlen(fileName, PATH_MAX);
5557                 name_len++;     /* trailing null */
5558                 strncpy(pSMB->FileName, fileName, name_len);
5559         }
5560
5561         params = 6 + name_len;
5562
5563         /* done calculating parms using name_len of file name,
5564         now use name_len to calculate length of ea name
5565         we are going to create in the inode xattrs */
5566         if (ea_name == NULL)
5567                 name_len = 0;
5568         else
5569                 name_len = strnlen(ea_name, 255);
5570
5571         count = sizeof(*parm_data) + ea_value_len + name_len;
5572         pSMB->MaxParameterCount = cpu_to_le16(2);
5573         /* BB find max SMB PDU from sess */
5574         pSMB->MaxDataCount = cpu_to_le16(1000);
5575         pSMB->MaxSetupCount = 0;
5576         pSMB->Reserved = 0;
5577         pSMB->Flags = 0;
5578         pSMB->Timeout = 0;
5579         pSMB->Reserved2 = 0;
5580         param_offset = offsetof(struct smb_com_transaction2_spi_req,
5581                                 InformationLevel) - 4;
5582         offset = param_offset + params;
5583         pSMB->InformationLevel =
5584                 cpu_to_le16(SMB_SET_FILE_EA);
5585
5586         parm_data =
5587                 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5588                                        offset);
5589         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5590         pSMB->DataOffset = cpu_to_le16(offset);
5591         pSMB->SetupCount = 1;
5592         pSMB->Reserved3 = 0;
5593         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5594         byte_count = 3 /* pad */  + params + count;
5595         pSMB->DataCount = cpu_to_le16(count);
5596         parm_data->list_len = cpu_to_le32(count);
5597         parm_data->list[0].EA_flags = 0;
5598         /* we checked above that name len is less than 255 */
5599         parm_data->list[0].name_len = (__u8)name_len;
5600         /* EA names are always ASCII */
5601         if (ea_name)
5602                 strncpy(parm_data->list[0].name, ea_name, name_len);
5603         parm_data->list[0].name[name_len] = 0;
5604         parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5605         /* caller ensures that ea_value_len is less than 64K but
5606         we need to ensure that it fits within the smb */
5607
5608         /*BB add length check to see if it would fit in
5609              negotiated SMB buffer size BB */
5610         /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5611         if (ea_value_len)
5612                 memcpy(parm_data->list[0].name+name_len+1,
5613                        ea_value, ea_value_len);
5614
5615         pSMB->TotalDataCount = pSMB->DataCount;
5616         pSMB->ParameterCount = cpu_to_le16(params);
5617         pSMB->TotalParameterCount = pSMB->ParameterCount;
5618         pSMB->Reserved4 = 0;
5619         pSMB->hdr.smb_buf_length += byte_count;
5620         pSMB->ByteCount = cpu_to_le16(byte_count);
5621         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5622                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5623         if (rc)
5624                 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
5625
5626         cifs_buf_release(pSMB);
5627
5628         if (rc == -EAGAIN)
5629                 goto SetEARetry;
5630
5631         return rc;
5632 }
5633
5634 #endif