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