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