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