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