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