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