0580da1cf34c549b2f34a9e43a657471097d3fe9
[linux-2.6.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 = 0;
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, name_len;
4083         __u16 params, byte_count;
4084
4085         cFYI(1, "In FindNext");
4086
4087         if (psrch_inf->endOfSearch)
4088                 return -ENOENT;
4089
4090         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4091                 (void **) &pSMBr);
4092         if (rc)
4093                 return rc;
4094
4095         params = 14; /* includes 2 bytes of null string, converted to LE below*/
4096         byte_count = 0;
4097         pSMB->TotalDataCount = 0;       /* no EAs */
4098         pSMB->MaxParameterCount = cpu_to_le16(8);
4099         pSMB->MaxDataCount =
4100                 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
4101                                 0xFFFFFF00);
4102         pSMB->MaxSetupCount = 0;
4103         pSMB->Reserved = 0;
4104         pSMB->Flags = 0;
4105         pSMB->Timeout = 0;
4106         pSMB->Reserved2 = 0;
4107         pSMB->ParameterOffset =  cpu_to_le16(
4108               offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
4109         pSMB->DataCount = 0;
4110         pSMB->DataOffset = 0;
4111         pSMB->SetupCount = 1;
4112         pSMB->Reserved3 = 0;
4113         pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
4114         pSMB->SearchHandle = searchHandle;      /* always kept as le */
4115         pSMB->SearchCount =
4116                 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
4117         pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
4118         pSMB->ResumeKey = psrch_inf->resume_key;
4119         pSMB->SearchFlags =
4120               cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
4121
4122         name_len = psrch_inf->resume_name_len;
4123         params += name_len;
4124         if (name_len < PATH_MAX) {
4125                 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
4126                 byte_count += name_len;
4127                 /* 14 byte parm len above enough for 2 byte null terminator */
4128                 pSMB->ResumeFileName[name_len] = 0;
4129                 pSMB->ResumeFileName[name_len+1] = 0;
4130         } else {
4131                 rc = -EINVAL;
4132                 goto FNext2_err_exit;
4133         }
4134         byte_count = params + 1 /* pad */ ;
4135         pSMB->TotalParameterCount = cpu_to_le16(params);
4136         pSMB->ParameterCount = pSMB->TotalParameterCount;
4137         inc_rfc1001_len(pSMB, byte_count);
4138         pSMB->ByteCount = cpu_to_le16(byte_count);
4139
4140         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4141                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4142         cifs_stats_inc(&tcon->num_fnext);
4143         if (rc) {
4144                 if (rc == -EBADF) {
4145                         psrch_inf->endOfSearch = true;
4146                         cifs_buf_release(pSMB);
4147                         rc = 0; /* search probably was closed at end of search*/
4148                 } else
4149                         cFYI(1, "FindNext returned = %d", rc);
4150         } else {                /* decode response */
4151                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4152
4153                 if (rc == 0) {
4154                         unsigned int lnoff;
4155
4156                         /* BB fixme add lock for file (srch_info) struct here */
4157                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4158                                 psrch_inf->unicode = true;
4159                         else
4160                                 psrch_inf->unicode = false;
4161                         response_data = (char *) &pSMBr->hdr.Protocol +
4162                                le16_to_cpu(pSMBr->t2.ParameterOffset);
4163                         parms = (T2_FNEXT_RSP_PARMS *)response_data;
4164                         response_data = (char *)&pSMBr->hdr.Protocol +
4165                                 le16_to_cpu(pSMBr->t2.DataOffset);
4166                         if (psrch_inf->smallBuf)
4167                                 cifs_small_buf_release(
4168                                         psrch_inf->ntwrk_buf_start);
4169                         else
4170                                 cifs_buf_release(psrch_inf->ntwrk_buf_start);
4171                         psrch_inf->srch_entries_start = response_data;
4172                         psrch_inf->ntwrk_buf_start = (char *)pSMB;
4173                         psrch_inf->smallBuf = 0;
4174                         if (parms->EndofSearch)
4175                                 psrch_inf->endOfSearch = true;
4176                         else
4177                                 psrch_inf->endOfSearch = false;
4178                         psrch_inf->entries_in_buffer =
4179                                                 le16_to_cpu(parms->SearchCount);
4180                         psrch_inf->index_of_last_entry +=
4181                                 psrch_inf->entries_in_buffer;
4182                         lnoff = le16_to_cpu(parms->LastNameOffset);
4183                         if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
4184                               lnoff) {
4185                                 cERROR(1, "ignoring corrupt resume name");
4186                                 psrch_inf->last_entry = NULL;
4187                                 return rc;
4188                         } else
4189                                 psrch_inf->last_entry =
4190                                         psrch_inf->srch_entries_start + lnoff;
4191
4192 /*  cFYI(1, "fnxt2 entries in buf %d index_of_last %d",
4193             psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
4194
4195                         /* BB fixme add unlock here */
4196                 }
4197
4198         }
4199
4200         /* BB On error, should we leave previous search buf (and count and
4201         last entry fields) intact or free the previous one? */
4202
4203         /* Note: On -EAGAIN error only caller can retry on handle based calls
4204         since file handle passed in no longer valid */
4205 FNext2_err_exit:
4206         if (rc != 0)
4207                 cifs_buf_release(pSMB);
4208         return rc;
4209 }
4210
4211 int
4212 CIFSFindClose(const int xid, struct cifs_tcon *tcon,
4213               const __u16 searchHandle)
4214 {
4215         int rc = 0;
4216         FINDCLOSE_REQ *pSMB = NULL;
4217
4218         cFYI(1, "In CIFSSMBFindClose");
4219         rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
4220
4221         /* no sense returning error if session restarted
4222                 as file handle has been closed */
4223         if (rc == -EAGAIN)
4224                 return 0;
4225         if (rc)
4226                 return rc;
4227
4228         pSMB->FileID = searchHandle;
4229         pSMB->ByteCount = 0;
4230         rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4231         if (rc)
4232                 cERROR(1, "Send error in FindClose = %d", rc);
4233
4234         cifs_stats_inc(&tcon->num_fclose);
4235
4236         /* Since session is dead, search handle closed on server already */
4237         if (rc == -EAGAIN)
4238                 rc = 0;
4239
4240         return rc;
4241 }
4242
4243 int
4244 CIFSGetSrvInodeNumber(const int xid, struct cifs_tcon *tcon,
4245                       const unsigned char *searchName,
4246                       __u64 *inode_number,
4247                       const struct nls_table *nls_codepage, int remap)
4248 {
4249         int rc = 0;
4250         TRANSACTION2_QPI_REQ *pSMB = NULL;
4251         TRANSACTION2_QPI_RSP *pSMBr = NULL;
4252         int name_len, bytes_returned;
4253         __u16 params, byte_count;
4254
4255         cFYI(1, "In GetSrvInodeNum for %s", searchName);
4256         if (tcon == NULL)
4257                 return -ENODEV;
4258
4259 GetInodeNumberRetry:
4260         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4261                       (void **) &pSMBr);
4262         if (rc)
4263                 return rc;
4264
4265         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4266                 name_len =
4267                         cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4268                                          PATH_MAX, nls_codepage, remap);
4269                 name_len++;     /* trailing null */
4270                 name_len *= 2;
4271         } else {        /* BB improve the check for buffer overruns BB */
4272                 name_len = strnlen(searchName, PATH_MAX);
4273                 name_len++;     /* trailing null */
4274                 strncpy(pSMB->FileName, searchName, name_len);
4275         }
4276
4277         params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
4278         pSMB->TotalDataCount = 0;
4279         pSMB->MaxParameterCount = cpu_to_le16(2);
4280         /* BB find exact max data count below from sess structure BB */
4281         pSMB->MaxDataCount = cpu_to_le16(4000);
4282         pSMB->MaxSetupCount = 0;
4283         pSMB->Reserved = 0;
4284         pSMB->Flags = 0;
4285         pSMB->Timeout = 0;
4286         pSMB->Reserved2 = 0;
4287         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4288                 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
4289         pSMB->DataCount = 0;
4290         pSMB->DataOffset = 0;
4291         pSMB->SetupCount = 1;
4292         pSMB->Reserved3 = 0;
4293         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4294         byte_count = params + 1 /* pad */ ;
4295         pSMB->TotalParameterCount = cpu_to_le16(params);
4296         pSMB->ParameterCount = pSMB->TotalParameterCount;
4297         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
4298         pSMB->Reserved4 = 0;
4299         inc_rfc1001_len(pSMB, byte_count);
4300         pSMB->ByteCount = cpu_to_le16(byte_count);
4301
4302         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4303                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4304         if (rc) {
4305                 cFYI(1, "error %d in QueryInternalInfo", rc);
4306         } else {
4307                 /* decode response */
4308                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4309                 /* BB also check enough total bytes returned */
4310                 if (rc || get_bcc(&pSMBr->hdr) < 2)
4311                         /* If rc should we check for EOPNOSUPP and
4312                         disable the srvino flag? or in caller? */
4313                         rc = -EIO;      /* bad smb */
4314                 else {
4315                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4316                         __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
4317                         struct file_internal_info *pfinfo;
4318                         /* BB Do we need a cast or hash here ? */
4319                         if (count < 8) {
4320                                 cFYI(1, "Illegal size ret in QryIntrnlInf");
4321                                 rc = -EIO;
4322                                 goto GetInodeNumOut;
4323                         }
4324                         pfinfo = (struct file_internal_info *)
4325                                 (data_offset + (char *) &pSMBr->hdr.Protocol);
4326                         *inode_number = le64_to_cpu(pfinfo->UniqueId);
4327                 }
4328         }
4329 GetInodeNumOut:
4330         cifs_buf_release(pSMB);
4331         if (rc == -EAGAIN)
4332                 goto GetInodeNumberRetry;
4333         return rc;
4334 }
4335
4336 /* parses DFS refferal V3 structure
4337  * caller is responsible for freeing target_nodes
4338  * returns:
4339  *      on success - 0
4340  *      on failure - errno
4341  */
4342 static int
4343 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
4344                 unsigned int *num_of_nodes,
4345                 struct dfs_info3_param **target_nodes,
4346                 const struct nls_table *nls_codepage, int remap,
4347                 const char *searchName)
4348 {
4349         int i, rc = 0;
4350         char *data_end;
4351         bool is_unicode;
4352         struct dfs_referral_level_3 *ref;
4353
4354         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
4355                 is_unicode = true;
4356         else
4357                 is_unicode = false;
4358         *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
4359
4360         if (*num_of_nodes < 1) {
4361                 cERROR(1, "num_referrals: must be at least > 0,"
4362                         "but we get num_referrals = %d\n", *num_of_nodes);
4363                 rc = -EINVAL;
4364                 goto parse_DFS_referrals_exit;
4365         }
4366
4367         ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
4368         if (ref->VersionNumber != cpu_to_le16(3)) {
4369                 cERROR(1, "Referrals of V%d version are not supported,"
4370                         "should be V3", le16_to_cpu(ref->VersionNumber));
4371                 rc = -EINVAL;
4372                 goto parse_DFS_referrals_exit;
4373         }
4374
4375         /* get the upper boundary of the resp buffer */
4376         data_end = (char *)(&(pSMBr->PathConsumed)) +
4377                                 le16_to_cpu(pSMBr->t2.DataCount);
4378
4379         cFYI(1, "num_referrals: %d dfs flags: 0x%x ...\n",
4380                         *num_of_nodes,
4381                         le32_to_cpu(pSMBr->DFSFlags));
4382
4383         *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
4384                         *num_of_nodes, GFP_KERNEL);
4385         if (*target_nodes == NULL) {
4386                 cERROR(1, "Failed to allocate buffer for target_nodes\n");
4387                 rc = -ENOMEM;
4388                 goto parse_DFS_referrals_exit;
4389         }
4390
4391         /* collect necessary data from referrals */
4392         for (i = 0; i < *num_of_nodes; i++) {
4393                 char *temp;
4394                 int max_len;
4395                 struct dfs_info3_param *node = (*target_nodes)+i;
4396
4397                 node->flags = le32_to_cpu(pSMBr->DFSFlags);
4398                 if (is_unicode) {
4399                         __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
4400                                                 GFP_KERNEL);
4401                         if (tmp == NULL) {
4402                                 rc = -ENOMEM;
4403                                 goto parse_DFS_referrals_exit;
4404                         }
4405                         cifsConvertToUCS((__le16 *) tmp, searchName,
4406                                         PATH_MAX, nls_codepage, remap);
4407                         node->path_consumed = cifs_ucs2_bytes(tmp,
4408                                         le16_to_cpu(pSMBr->PathConsumed),
4409                                         nls_codepage);
4410                         kfree(tmp);
4411                 } else
4412                         node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
4413
4414                 node->server_type = le16_to_cpu(ref->ServerType);
4415                 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
4416
4417                 /* copy DfsPath */
4418                 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
4419                 max_len = data_end - temp;
4420                 node->path_name = cifs_strndup_from_ucs(temp, max_len,
4421                                                       is_unicode, nls_codepage);
4422                 if (!node->path_name) {
4423                         rc = -ENOMEM;
4424                         goto parse_DFS_referrals_exit;
4425                 }
4426
4427                 /* copy link target UNC */
4428                 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
4429                 max_len = data_end - temp;
4430                 node->node_name = cifs_strndup_from_ucs(temp, max_len,
4431                                                       is_unicode, nls_codepage);
4432                 if (!node->node_name)
4433                         rc = -ENOMEM;
4434         }
4435
4436 parse_DFS_referrals_exit:
4437         if (rc) {
4438                 free_dfs_info_array(*target_nodes, *num_of_nodes);
4439                 *target_nodes = NULL;
4440                 *num_of_nodes = 0;
4441         }
4442         return rc;
4443 }
4444
4445 int
4446 CIFSGetDFSRefer(const int xid, struct cifs_ses *ses,
4447                 const unsigned char *searchName,
4448                 struct dfs_info3_param **target_nodes,
4449                 unsigned int *num_of_nodes,
4450                 const struct nls_table *nls_codepage, int remap)
4451 {
4452 /* TRANS2_GET_DFS_REFERRAL */
4453         TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4454         TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4455         int rc = 0;
4456         int bytes_returned;
4457         int name_len;
4458         __u16 params, byte_count;
4459         *num_of_nodes = 0;
4460         *target_nodes = NULL;
4461
4462         cFYI(1, "In GetDFSRefer the path %s", searchName);
4463         if (ses == NULL)
4464                 return -ENODEV;
4465 getDFSRetry:
4466         rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4467                       (void **) &pSMBr);
4468         if (rc)
4469                 return rc;
4470
4471         /* server pointer checked in called function,
4472         but should never be null here anyway */
4473         pSMB->hdr.Mid = GetNextMid(ses->server);
4474         pSMB->hdr.Tid = ses->ipc_tid;
4475         pSMB->hdr.Uid = ses->Suid;
4476         if (ses->capabilities & CAP_STATUS32)
4477                 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4478         if (ses->capabilities & CAP_DFS)
4479                 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4480
4481         if (ses->capabilities & CAP_UNICODE) {
4482                 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4483                 name_len =
4484                     cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
4485                                      searchName, PATH_MAX, nls_codepage, remap);
4486                 name_len++;     /* trailing null */
4487                 name_len *= 2;
4488         } else {        /* BB improve the check for buffer overruns BB */
4489                 name_len = strnlen(searchName, PATH_MAX);
4490                 name_len++;     /* trailing null */
4491                 strncpy(pSMB->RequestFileName, searchName, name_len);
4492         }
4493
4494         if (ses->server) {
4495                 if (ses->server->sec_mode &
4496                    (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4497                         pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4498         }
4499
4500         pSMB->hdr.Uid = ses->Suid;
4501
4502         params = 2 /* level */  + name_len /*includes null */ ;
4503         pSMB->TotalDataCount = 0;
4504         pSMB->DataCount = 0;
4505         pSMB->DataOffset = 0;
4506         pSMB->MaxParameterCount = 0;
4507         /* BB find exact max SMB PDU from sess structure BB */
4508         pSMB->MaxDataCount = cpu_to_le16(4000);
4509         pSMB->MaxSetupCount = 0;
4510         pSMB->Reserved = 0;
4511         pSMB->Flags = 0;
4512         pSMB->Timeout = 0;
4513         pSMB->Reserved2 = 0;
4514         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4515           struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4516         pSMB->SetupCount = 1;
4517         pSMB->Reserved3 = 0;
4518         pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4519         byte_count = params + 3 /* pad */ ;
4520         pSMB->ParameterCount = cpu_to_le16(params);
4521         pSMB->TotalParameterCount = pSMB->ParameterCount;
4522         pSMB->MaxReferralLevel = cpu_to_le16(3);
4523         inc_rfc1001_len(pSMB, byte_count);
4524         pSMB->ByteCount = cpu_to_le16(byte_count);
4525
4526         rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4527                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4528         if (rc) {
4529                 cFYI(1, "Send error in GetDFSRefer = %d", rc);
4530                 goto GetDFSRefExit;
4531         }
4532         rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4533
4534         /* BB Also check if enough total bytes returned? */
4535         if (rc || get_bcc(&pSMBr->hdr) < 17) {
4536                 rc = -EIO;      /* bad smb */
4537                 goto GetDFSRefExit;
4538         }
4539
4540         cFYI(1, "Decoding GetDFSRefer response BCC: %d  Offset %d",
4541                                 get_bcc(&pSMBr->hdr),
4542                                 le16_to_cpu(pSMBr->t2.DataOffset));
4543
4544         /* parse returned result into more usable form */
4545         rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4546                                  target_nodes, nls_codepage, remap,
4547                                  searchName);
4548
4549 GetDFSRefExit:
4550         cifs_buf_release(pSMB);
4551
4552         if (rc == -EAGAIN)
4553                 goto getDFSRetry;
4554
4555         return rc;
4556 }
4557
4558 /* Query File System Info such as free space to old servers such as Win 9x */
4559 int
4560 SMBOldQFSInfo(const int xid, struct cifs_tcon *tcon, struct kstatfs *FSData)
4561 {
4562 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4563         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4564         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4565         FILE_SYSTEM_ALLOC_INFO *response_data;
4566         int rc = 0;
4567         int bytes_returned = 0;
4568         __u16 params, byte_count;
4569
4570         cFYI(1, "OldQFSInfo");
4571 oldQFSInfoRetry:
4572         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4573                 (void **) &pSMBr);
4574         if (rc)
4575                 return rc;
4576
4577         params = 2;     /* level */
4578         pSMB->TotalDataCount = 0;
4579         pSMB->MaxParameterCount = cpu_to_le16(2);
4580         pSMB->MaxDataCount = cpu_to_le16(1000);
4581         pSMB->MaxSetupCount = 0;
4582         pSMB->Reserved = 0;
4583         pSMB->Flags = 0;
4584         pSMB->Timeout = 0;
4585         pSMB->Reserved2 = 0;
4586         byte_count = params + 1 /* pad */ ;
4587         pSMB->TotalParameterCount = cpu_to_le16(params);
4588         pSMB->ParameterCount = pSMB->TotalParameterCount;
4589         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4590         struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4591         pSMB->DataCount = 0;
4592         pSMB->DataOffset = 0;
4593         pSMB->SetupCount = 1;
4594         pSMB->Reserved3 = 0;
4595         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4596         pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4597         inc_rfc1001_len(pSMB, byte_count);
4598         pSMB->ByteCount = cpu_to_le16(byte_count);
4599
4600         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4601                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4602         if (rc) {
4603                 cFYI(1, "Send error in QFSInfo = %d", rc);
4604         } else {                /* decode response */
4605                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4606
4607                 if (rc || get_bcc(&pSMBr->hdr) < 18)
4608                         rc = -EIO;      /* bad smb */
4609                 else {
4610                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4611                         cFYI(1, "qfsinf resp BCC: %d  Offset %d",
4612                                  get_bcc(&pSMBr->hdr), data_offset);
4613
4614                         response_data = (FILE_SYSTEM_ALLOC_INFO *)
4615                                 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4616                         FSData->f_bsize =
4617                                 le16_to_cpu(response_data->BytesPerSector) *
4618                                 le32_to_cpu(response_data->
4619                                         SectorsPerAllocationUnit);
4620                         FSData->f_blocks =
4621                                le32_to_cpu(response_data->TotalAllocationUnits);
4622                         FSData->f_bfree = FSData->f_bavail =
4623                                 le32_to_cpu(response_data->FreeAllocationUnits);
4624                         cFYI(1, "Blocks: %lld  Free: %lld Block size %ld",
4625                              (unsigned long long)FSData->f_blocks,
4626                              (unsigned long long)FSData->f_bfree,
4627                              FSData->f_bsize);
4628                 }
4629         }
4630         cifs_buf_release(pSMB);
4631
4632         if (rc == -EAGAIN)
4633                 goto oldQFSInfoRetry;
4634
4635         return rc;
4636 }
4637
4638 int
4639 CIFSSMBQFSInfo(const int xid, struct cifs_tcon *tcon, struct kstatfs *FSData)
4640 {
4641 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4642         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4643         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4644         FILE_SYSTEM_INFO *response_data;
4645         int rc = 0;
4646         int bytes_returned = 0;
4647         __u16 params, byte_count;
4648
4649         cFYI(1, "In QFSInfo");
4650 QFSInfoRetry:
4651         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4652                       (void **) &pSMBr);
4653         if (rc)
4654                 return rc;
4655
4656         params = 2;     /* level */
4657         pSMB->TotalDataCount = 0;
4658         pSMB->MaxParameterCount = cpu_to_le16(2);
4659         pSMB->MaxDataCount = cpu_to_le16(1000);
4660         pSMB->MaxSetupCount = 0;
4661         pSMB->Reserved = 0;
4662         pSMB->Flags = 0;
4663         pSMB->Timeout = 0;
4664         pSMB->Reserved2 = 0;
4665         byte_count = params + 1 /* pad */ ;
4666         pSMB->TotalParameterCount = cpu_to_le16(params);
4667         pSMB->ParameterCount = pSMB->TotalParameterCount;
4668         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4669                 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4670         pSMB->DataCount = 0;
4671         pSMB->DataOffset = 0;
4672         pSMB->SetupCount = 1;
4673         pSMB->Reserved3 = 0;
4674         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4675         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4676         inc_rfc1001_len(pSMB, byte_count);
4677         pSMB->ByteCount = cpu_to_le16(byte_count);
4678
4679         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4680                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4681         if (rc) {
4682                 cFYI(1, "Send error in QFSInfo = %d", rc);
4683         } else {                /* decode response */
4684                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4685
4686                 if (rc || get_bcc(&pSMBr->hdr) < 24)
4687                         rc = -EIO;      /* bad smb */
4688                 else {
4689                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4690
4691                         response_data =
4692                             (FILE_SYSTEM_INFO
4693                              *) (((char *) &pSMBr->hdr.Protocol) +
4694                                  data_offset);
4695                         FSData->f_bsize =
4696                             le32_to_cpu(response_data->BytesPerSector) *
4697                             le32_to_cpu(response_data->
4698                                         SectorsPerAllocationUnit);
4699                         FSData->f_blocks =
4700                             le64_to_cpu(response_data->TotalAllocationUnits);
4701                         FSData->f_bfree = FSData->f_bavail =
4702                             le64_to_cpu(response_data->FreeAllocationUnits);
4703                         cFYI(1, "Blocks: %lld  Free: %lld Block size %ld",
4704                              (unsigned long long)FSData->f_blocks,
4705                              (unsigned long long)FSData->f_bfree,
4706                              FSData->f_bsize);
4707                 }
4708         }
4709         cifs_buf_release(pSMB);
4710
4711         if (rc == -EAGAIN)
4712                 goto QFSInfoRetry;
4713
4714         return rc;
4715 }
4716
4717 int
4718 CIFSSMBQFSAttributeInfo(const int xid, struct cifs_tcon *tcon)
4719 {
4720 /* level 0x105  SMB_QUERY_FILE_SYSTEM_INFO */
4721         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4722         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4723         FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4724         int rc = 0;
4725         int bytes_returned = 0;
4726         __u16 params, byte_count;
4727
4728         cFYI(1, "In QFSAttributeInfo");
4729 QFSAttributeRetry:
4730         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4731                       (void **) &pSMBr);
4732         if (rc)
4733                 return rc;
4734
4735         params = 2;     /* level */
4736         pSMB->TotalDataCount = 0;
4737         pSMB->MaxParameterCount = cpu_to_le16(2);
4738         /* BB find exact max SMB PDU from sess structure BB */
4739         pSMB->MaxDataCount = cpu_to_le16(1000);
4740         pSMB->MaxSetupCount = 0;
4741         pSMB->Reserved = 0;
4742         pSMB->Flags = 0;
4743         pSMB->Timeout = 0;
4744         pSMB->Reserved2 = 0;
4745         byte_count = params + 1 /* pad */ ;
4746         pSMB->TotalParameterCount = cpu_to_le16(params);
4747         pSMB->ParameterCount = pSMB->TotalParameterCount;
4748         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4749                 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4750         pSMB->DataCount = 0;
4751         pSMB->DataOffset = 0;
4752         pSMB->SetupCount = 1;
4753         pSMB->Reserved3 = 0;
4754         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4755         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4756         inc_rfc1001_len(pSMB, byte_count);
4757         pSMB->ByteCount = cpu_to_le16(byte_count);
4758
4759         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4760                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4761         if (rc) {
4762                 cERROR(1, "Send error in QFSAttributeInfo = %d", rc);
4763         } else {                /* decode response */
4764                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4765
4766                 if (rc || get_bcc(&pSMBr->hdr) < 13) {
4767                         /* BB also check if enough bytes returned */
4768                         rc = -EIO;      /* bad smb */
4769                 } else {
4770                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4771                         response_data =
4772                             (FILE_SYSTEM_ATTRIBUTE_INFO
4773                              *) (((char *) &pSMBr->hdr.Protocol) +
4774                                  data_offset);
4775                         memcpy(&tcon->fsAttrInfo, response_data,
4776                                sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4777                 }
4778         }
4779         cifs_buf_release(pSMB);
4780
4781         if (rc == -EAGAIN)
4782                 goto QFSAttributeRetry;
4783
4784         return rc;
4785 }
4786
4787 int
4788 CIFSSMBQFSDeviceInfo(const int xid, struct cifs_tcon *tcon)
4789 {
4790 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4791         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4792         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4793         FILE_SYSTEM_DEVICE_INFO *response_data;
4794         int rc = 0;
4795         int bytes_returned = 0;
4796         __u16 params, byte_count;
4797
4798         cFYI(1, "In QFSDeviceInfo");
4799 QFSDeviceRetry:
4800         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4801                       (void **) &pSMBr);
4802         if (rc)
4803                 return rc;
4804
4805         params = 2;     /* level */
4806         pSMB->TotalDataCount = 0;
4807         pSMB->MaxParameterCount = cpu_to_le16(2);
4808         /* BB find exact max SMB PDU from sess structure BB */
4809         pSMB->MaxDataCount = cpu_to_le16(1000);
4810         pSMB->MaxSetupCount = 0;
4811         pSMB->Reserved = 0;
4812         pSMB->Flags = 0;
4813         pSMB->Timeout = 0;
4814         pSMB->Reserved2 = 0;
4815         byte_count = params + 1 /* pad */ ;
4816         pSMB->TotalParameterCount = cpu_to_le16(params);
4817         pSMB->ParameterCount = pSMB->TotalParameterCount;
4818         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4819                 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4820
4821         pSMB->DataCount = 0;
4822         pSMB->DataOffset = 0;
4823         pSMB->SetupCount = 1;
4824         pSMB->Reserved3 = 0;
4825         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4826         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4827         inc_rfc1001_len(pSMB, byte_count);
4828         pSMB->ByteCount = cpu_to_le16(byte_count);
4829
4830         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4831                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4832         if (rc) {
4833                 cFYI(1, "Send error in QFSDeviceInfo = %d", rc);
4834         } else {                /* decode response */
4835                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4836
4837                 if (rc || get_bcc(&pSMBr->hdr) <
4838                           sizeof(FILE_SYSTEM_DEVICE_INFO))
4839                         rc = -EIO;      /* bad smb */
4840                 else {
4841                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4842                         response_data =
4843                             (FILE_SYSTEM_DEVICE_INFO *)
4844                                 (((char *) &pSMBr->hdr.Protocol) +
4845                                  data_offset);
4846                         memcpy(&tcon->fsDevInfo, response_data,
4847                                sizeof(FILE_SYSTEM_DEVICE_INFO));
4848                 }
4849         }
4850         cifs_buf_release(pSMB);
4851
4852         if (rc == -EAGAIN)
4853                 goto QFSDeviceRetry;
4854
4855         return rc;
4856 }
4857
4858 int
4859 CIFSSMBQFSUnixInfo(const int xid, struct cifs_tcon *tcon)
4860 {
4861 /* level 0x200  SMB_QUERY_CIFS_UNIX_INFO */
4862         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4863         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4864         FILE_SYSTEM_UNIX_INFO *response_data;
4865         int rc = 0;
4866         int bytes_returned = 0;
4867         __u16 params, byte_count;
4868
4869         cFYI(1, "In QFSUnixInfo");
4870 QFSUnixRetry:
4871         rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
4872                                    (void **) &pSMB, (void **) &pSMBr);
4873         if (rc)
4874                 return rc;
4875
4876         params = 2;     /* level */
4877         pSMB->TotalDataCount = 0;
4878         pSMB->DataCount = 0;
4879         pSMB->DataOffset = 0;
4880         pSMB->MaxParameterCount = cpu_to_le16(2);
4881         /* BB find exact max SMB PDU from sess structure BB */
4882         pSMB->MaxDataCount = cpu_to_le16(100);
4883         pSMB->MaxSetupCount = 0;
4884         pSMB->Reserved = 0;
4885         pSMB->Flags = 0;
4886         pSMB->Timeout = 0;
4887         pSMB->Reserved2 = 0;
4888         byte_count = params + 1 /* pad */ ;
4889         pSMB->ParameterCount = cpu_to_le16(params);
4890         pSMB->TotalParameterCount = pSMB->ParameterCount;
4891         pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4892                         smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4893         pSMB->SetupCount = 1;
4894         pSMB->Reserved3 = 0;
4895         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4896         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4897         inc_rfc1001_len(pSMB, byte_count);
4898         pSMB->ByteCount = cpu_to_le16(byte_count);
4899
4900         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4901                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4902         if (rc) {
4903                 cERROR(1, "Send error in QFSUnixInfo = %d", rc);
4904         } else {                /* decode response */
4905                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4906
4907                 if (rc || get_bcc(&pSMBr->hdr) < 13) {
4908                         rc = -EIO;      /* bad smb */
4909                 } else {
4910                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4911                         response_data =
4912                             (FILE_SYSTEM_UNIX_INFO
4913                              *) (((char *) &pSMBr->hdr.Protocol) +
4914                                  data_offset);
4915                         memcpy(&tcon->fsUnixInfo, response_data,
4916                                sizeof(FILE_SYSTEM_UNIX_INFO));
4917                 }
4918         }
4919         cifs_buf_release(pSMB);
4920
4921         if (rc == -EAGAIN)
4922                 goto QFSUnixRetry;
4923
4924
4925         return rc;
4926 }
4927
4928 int
4929 CIFSSMBSetFSUnixInfo(const int xid, struct cifs_tcon *tcon, __u64 cap)
4930 {
4931 /* level 0x200  SMB_SET_CIFS_UNIX_INFO */
4932         TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4933         TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4934         int rc = 0;
4935         int bytes_returned = 0;
4936         __u16 params, param_offset, offset, byte_count;
4937
4938         cFYI(1, "In SETFSUnixInfo");
4939 SETFSUnixRetry:
4940         /* BB switch to small buf init to save memory */
4941         rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, tcon,
4942                                         (void **) &pSMB, (void **) &pSMBr);
4943         if (rc)
4944                 return rc;
4945
4946         params = 4;     /* 2 bytes zero followed by info level. */
4947         pSMB->MaxSetupCount = 0;
4948         pSMB->Reserved = 0;
4949         pSMB->Flags = 0;
4950         pSMB->Timeout = 0;
4951         pSMB->Reserved2 = 0;
4952         param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4953                                 - 4;
4954         offset = param_offset + params;
4955
4956         pSMB->MaxParameterCount = cpu_to_le16(4);
4957         /* BB find exact max SMB PDU from sess structure BB */
4958         pSMB->MaxDataCount = cpu_to_le16(100);
4959         pSMB->SetupCount = 1;
4960         pSMB->Reserved3 = 0;
4961         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4962         byte_count = 1 /* pad */ + params + 12;
4963
4964         pSMB->DataCount = cpu_to_le16(12);
4965         pSMB->ParameterCount = cpu_to_le16(params);
4966         pSMB->TotalDataCount = pSMB->DataCount;
4967         pSMB->TotalParameterCount = pSMB->ParameterCount;
4968         pSMB->ParameterOffset = cpu_to_le16(param_offset);
4969         pSMB->DataOffset = cpu_to_le16(offset);
4970
4971         /* Params. */
4972         pSMB->FileNum = 0;
4973         pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4974
4975         /* Data. */
4976         pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4977         pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4978         pSMB->ClientUnixCap = cpu_to_le64(cap);
4979
4980         inc_rfc1001_len(pSMB, byte_count);
4981         pSMB->ByteCount = cpu_to_le16(byte_count);
4982
4983         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4984                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4985         if (rc) {
4986                 cERROR(1, "Send error in SETFSUnixInfo = %d", rc);
4987         } else {                /* decode response */
4988                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4989                 if (rc)
4990                         rc = -EIO;      /* bad smb */
4991         }
4992         cifs_buf_release(pSMB);
4993
4994         if (rc == -EAGAIN)
4995                 goto SETFSUnixRetry;
4996
4997         return rc;
4998 }
4999
5000
5001
5002 int
5003 CIFSSMBQFSPosixInfo(const int xid, struct cifs_tcon *tcon,
5004                    struct kstatfs *FSData)
5005 {
5006 /* level 0x201  SMB_QUERY_CIFS_POSIX_INFO */
5007         TRANSACTION2_QFSI_REQ *pSMB = NULL;
5008         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
5009         FILE_SYSTEM_POSIX_INFO *response_data;
5010         int rc = 0;
5011         int bytes_returned = 0;
5012         __u16 params, byte_count;
5013
5014         cFYI(1, "In QFSPosixInfo");
5015 QFSPosixRetry:
5016         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5017                       (void **) &pSMBr);
5018         if (rc)
5019                 return rc;
5020
5021         params = 2;     /* level */
5022         pSMB->TotalDataCount = 0;
5023         pSMB->DataCount = 0;
5024         pSMB->DataOffset = 0;
5025         pSMB->MaxParameterCount = cpu_to_le16(2);
5026         /* BB find exact max SMB PDU from sess structure BB */
5027         pSMB->MaxDataCount = cpu_to_le16(100);
5028         pSMB->MaxSetupCount = 0;
5029         pSMB->Reserved = 0;
5030         pSMB->Flags = 0;
5031         pSMB->Timeout = 0;
5032         pSMB->Reserved2 = 0;
5033         byte_count = params + 1 /* pad */ ;
5034         pSMB->ParameterCount = cpu_to_le16(params);
5035         pSMB->TotalParameterCount = pSMB->ParameterCount;
5036         pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
5037                         smb_com_transaction2_qfsi_req, InformationLevel) - 4);
5038         pSMB->SetupCount = 1;
5039         pSMB->Reserved3 = 0;
5040         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
5041         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
5042         inc_rfc1001_len(pSMB, byte_count);
5043         pSMB->ByteCount = cpu_to_le16(byte_count);
5044
5045         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5046                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5047         if (rc) {
5048                 cFYI(1, "Send error in QFSUnixInfo = %d", rc);
5049         } else {                /* decode response */
5050                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5051
5052                 if (rc || get_bcc(&pSMBr->hdr) < 13) {
5053                         rc = -EIO;      /* bad smb */
5054                 } else {
5055                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5056                         response_data =
5057                             (FILE_SYSTEM_POSIX_INFO
5058                              *) (((char *) &pSMBr->hdr.Protocol) +
5059                                  data_offset);
5060                         FSData->f_bsize =
5061                                         le32_to_cpu(response_data->BlockSize);
5062                         FSData->f_blocks =
5063                                         le64_to_cpu(response_data->TotalBlocks);
5064                         FSData->f_bfree =
5065                             le64_to_cpu(response_data->BlocksAvail);
5066                         if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
5067                                 FSData->f_bavail = FSData->f_bfree;
5068                         } else {
5069                                 FSData->f_bavail =
5070                                     le64_to_cpu(response_data->UserBlocksAvail);
5071                         }
5072                         if (response_data->TotalFileNodes != cpu_to_le64(-1))
5073                                 FSData->f_files =
5074                                      le64_to_cpu(response_data->TotalFileNodes);
5075                         if (response_data->FreeFileNodes != cpu_to_le64(-1))
5076                                 FSData->f_ffree =
5077                                       le64_to_cpu(response_data->FreeFileNodes);
5078                 }
5079         }
5080         cifs_buf_release(pSMB);
5081
5082         if (rc == -EAGAIN)
5083                 goto QFSPosixRetry;
5084
5085         return rc;
5086 }
5087
5088
5089 /* We can not use write of zero bytes trick to
5090    set file size due to need for large file support.  Also note that
5091    this SetPathInfo is preferred to SetFileInfo based method in next
5092    routine which is only needed to work around a sharing violation bug
5093    in Samba which this routine can run into */
5094
5095 int
5096 CIFSSMBSetEOF(const int xid, struct cifs_tcon *tcon, const char *fileName,
5097               __u64 size, bool SetAllocation,
5098               const struct nls_table *nls_codepage, int remap)
5099 {
5100         struct smb_com_transaction2_spi_req *pSMB = NULL;
5101         struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5102         struct file_end_of_file_info *parm_data;
5103         int name_len;
5104         int rc = 0;
5105         int bytes_returned = 0;
5106         __u16 params, byte_count, data_count, param_offset, offset;
5107
5108         cFYI(1, "In SetEOF");
5109 SetEOFRetry:
5110         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5111                       (void **) &pSMBr);
5112         if (rc)
5113                 return rc;
5114
5115         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5116                 name_len =
5117                     cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5118                                      PATH_MAX, nls_codepage, remap);
5119                 name_len++;     /* trailing null */
5120                 name_len *= 2;
5121         } else {        /* BB improve the check for buffer overruns BB */
5122                 name_len = strnlen(fileName, PATH_MAX);
5123                 name_len++;     /* trailing null */
5124                 strncpy(pSMB->FileName, fileName, name_len);
5125         }
5126         params = 6 + name_len;
5127         data_count = sizeof(struct file_end_of_file_info);
5128         pSMB->MaxParameterCount = cpu_to_le16(2);
5129         pSMB->MaxDataCount = cpu_to_le16(4100);
5130         pSMB->MaxSetupCount = 0;
5131         pSMB->Reserved = 0;
5132         pSMB->Flags = 0;
5133         pSMB->Timeout = 0;
5134         pSMB->Reserved2 = 0;
5135         param_offset = offsetof(struct smb_com_transaction2_spi_req,
5136                                 InformationLevel) - 4;
5137         offset = param_offset + params;
5138         if (SetAllocation) {
5139                 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5140                         pSMB->InformationLevel =
5141                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5142                 else
5143                         pSMB->InformationLevel =
5144                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5145         } else /* Set File Size */  {
5146             if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5147                     pSMB->InformationLevel =
5148                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5149             else
5150                     pSMB->InformationLevel =
5151                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5152         }
5153
5154         parm_data =
5155             (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
5156                                        offset);
5157         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5158         pSMB->DataOffset = cpu_to_le16(offset);
5159         pSMB->SetupCount = 1;
5160         pSMB->Reserved3 = 0;
5161         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5162         byte_count = 3 /* pad */  + params + data_count;
5163         pSMB->DataCount = cpu_to_le16(data_count);
5164         pSMB->TotalDataCount = pSMB->DataCount;
5165         pSMB->ParameterCount = cpu_to_le16(params);
5166         pSMB->TotalParameterCount = pSMB->ParameterCount;
5167         pSMB->Reserved4 = 0;
5168         inc_rfc1001_len(pSMB, byte_count);
5169         parm_data->FileSize = cpu_to_le64(size);
5170         pSMB->ByteCount = cpu_to_le16(byte_count);
5171         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5172                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5173         if (rc)
5174                 cFYI(1, "SetPathInfo (file size) returned %d", rc);
5175
5176         cifs_buf_release(pSMB);
5177
5178         if (rc == -EAGAIN)
5179                 goto SetEOFRetry;
5180
5181         return rc;
5182 }
5183
5184 int
5185 CIFSSMBSetFileSize(const int xid, struct cifs_tcon *tcon, __u64 size,
5186                    __u16 fid, __u32 pid_of_opener, bool SetAllocation)
5187 {
5188         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5189         struct file_end_of_file_info *parm_data;
5190         int rc = 0;
5191         __u16 params, param_offset, offset, byte_count, count;
5192
5193         cFYI(1, "SetFileSize (via SetFileInfo) %lld",
5194                         (long long)size);
5195         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5196
5197         if (rc)
5198                 return rc;
5199
5200         pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5201         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5202
5203         params = 6;
5204         pSMB->MaxSetupCount = 0;
5205         pSMB->Reserved = 0;
5206         pSMB->Flags = 0;
5207         pSMB->Timeout = 0;
5208         pSMB->Reserved2 = 0;
5209         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5210         offset = param_offset + params;
5211
5212         count = sizeof(struct file_end_of_file_info);
5213         pSMB->MaxParameterCount = cpu_to_le16(2);
5214         /* BB find exact max SMB PDU from sess structure BB */
5215         pSMB->MaxDataCount = cpu_to_le16(1000);
5216         pSMB->SetupCount = 1;
5217         pSMB->Reserved3 = 0;
5218         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5219         byte_count = 3 /* pad */  + params + count;
5220         pSMB->DataCount = cpu_to_le16(count);
5221         pSMB->ParameterCount = cpu_to_le16(params);
5222         pSMB->TotalDataCount = pSMB->DataCount;
5223         pSMB->TotalParameterCount = pSMB->ParameterCount;
5224         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5225         parm_data =
5226                 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
5227                                 + offset);
5228         pSMB->DataOffset = cpu_to_le16(offset);
5229         parm_data->FileSize = cpu_to_le64(size);
5230         pSMB->Fid = fid;
5231         if (SetAllocation) {
5232                 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5233                         pSMB->InformationLevel =
5234                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
5235                 else
5236                         pSMB->InformationLevel =
5237                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
5238         } else /* Set File Size */  {
5239             if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5240                     pSMB->InformationLevel =
5241                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
5242             else
5243                     pSMB->InformationLevel =
5244                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
5245         }
5246         pSMB->Reserved4 = 0;
5247         inc_rfc1001_len(pSMB, byte_count);
5248         pSMB->ByteCount = cpu_to_le16(byte_count);
5249         rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5250         if (rc) {
5251                 cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc);
5252         }
5253
5254         /* Note: On -EAGAIN error only caller can retry on handle based calls
5255                 since file handle passed in no longer valid */
5256
5257         return rc;
5258 }
5259
5260 /* Some legacy servers such as NT4 require that the file times be set on
5261    an open handle, rather than by pathname - this is awkward due to
5262    potential access conflicts on the open, but it is unavoidable for these
5263    old servers since the only other choice is to go from 100 nanosecond DCE
5264    time and resort to the original setpathinfo level which takes the ancient
5265    DOS time format with 2 second granularity */
5266 int
5267 CIFSSMBSetFileInfo(const int xid, struct cifs_tcon *tcon,
5268                     const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
5269 {
5270         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5271         char *data_offset;
5272         int rc = 0;
5273         __u16 params, param_offset, offset, byte_count, count;
5274
5275         cFYI(1, "Set Times (via SetFileInfo)");
5276         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5277
5278         if (rc)
5279                 return rc;
5280
5281         pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5282         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5283
5284         params = 6;
5285         pSMB->MaxSetupCount = 0;
5286         pSMB->Reserved = 0;
5287         pSMB->Flags = 0;
5288         pSMB->Timeout = 0;
5289         pSMB->Reserved2 = 0;
5290         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5291         offset = param_offset + params;
5292
5293         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5294
5295         count = sizeof(FILE_BASIC_INFO);
5296         pSMB->MaxParameterCount = cpu_to_le16(2);
5297         /* BB find max SMB PDU from sess */
5298         pSMB->MaxDataCount = cpu_to_le16(1000);
5299         pSMB->SetupCount = 1;
5300         pSMB->Reserved3 = 0;
5301         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5302         byte_count = 3 /* pad */  + params + count;
5303         pSMB->DataCount = cpu_to_le16(count);
5304         pSMB->ParameterCount = cpu_to_le16(params);
5305         pSMB->TotalDataCount = pSMB->DataCount;
5306         pSMB->TotalParameterCount = pSMB->ParameterCount;
5307         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5308         pSMB->DataOffset = cpu_to_le16(offset);
5309         pSMB->Fid = fid;
5310         if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5311                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5312         else
5313                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5314         pSMB->Reserved4 = 0;
5315         inc_rfc1001_len(pSMB, byte_count);
5316         pSMB->ByteCount = cpu_to_le16(byte_count);
5317         memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5318         rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5319         if (rc)
5320                 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
5321
5322         /* Note: On -EAGAIN error only caller can retry on handle based calls
5323                 since file handle passed in no longer valid */
5324
5325         return rc;
5326 }
5327
5328 int
5329 CIFSSMBSetFileDisposition(const int xid, struct cifs_tcon *tcon,
5330                           bool delete_file, __u16 fid, __u32 pid_of_opener)
5331 {
5332         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5333         char *data_offset;
5334         int rc = 0;
5335         __u16 params, param_offset, offset, byte_count, count;
5336
5337         cFYI(1, "Set File Disposition (via SetFileInfo)");
5338         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5339
5340         if (rc)
5341                 return rc;
5342
5343         pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5344         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5345
5346         params = 6;
5347         pSMB->MaxSetupCount = 0;
5348         pSMB->Reserved = 0;
5349         pSMB->Flags = 0;
5350         pSMB->Timeout = 0;
5351         pSMB->Reserved2 = 0;
5352         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5353         offset = param_offset + params;
5354
5355         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5356
5357         count = 1;
5358         pSMB->MaxParameterCount = cpu_to_le16(2);
5359         /* BB find max SMB PDU from sess */
5360         pSMB->MaxDataCount = cpu_to_le16(1000);
5361         pSMB->SetupCount = 1;
5362         pSMB->Reserved3 = 0;
5363         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5364         byte_count = 3 /* pad */  + params + count;
5365         pSMB->DataCount = cpu_to_le16(count);
5366         pSMB->ParameterCount = cpu_to_le16(params);
5367         pSMB->TotalDataCount = pSMB->DataCount;
5368         pSMB->TotalParameterCount = pSMB->ParameterCount;
5369         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5370         pSMB->DataOffset = cpu_to_le16(offset);
5371         pSMB->Fid = fid;
5372         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
5373         pSMB->Reserved4 = 0;
5374         inc_rfc1001_len(pSMB, byte_count);
5375         pSMB->ByteCount = cpu_to_le16(byte_count);
5376         *data_offset = delete_file ? 1 : 0;
5377         rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5378         if (rc)
5379                 cFYI(1, "Send error in SetFileDisposition = %d", rc);
5380
5381         return rc;
5382 }
5383
5384 int
5385 CIFSSMBSetPathInfo(const int xid, struct cifs_tcon *tcon,
5386                    const char *fileName, const FILE_BASIC_INFO *data,
5387                    const struct nls_table *nls_codepage, int remap)
5388 {
5389         TRANSACTION2_SPI_REQ *pSMB = NULL;
5390         TRANSACTION2_SPI_RSP *pSMBr = NULL;
5391         int name_len;
5392         int rc = 0;
5393         int bytes_returned = 0;
5394         char *data_offset;
5395         __u16 params, param_offset, offset, byte_count, count;
5396
5397         cFYI(1, "In SetTimes");
5398
5399 SetTimesRetry:
5400         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5401                       (void **) &pSMBr);
5402         if (rc)
5403                 return rc;
5404
5405         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5406                 name_len =
5407                     cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5408                                      PATH_MAX, nls_codepage, remap);
5409                 name_len++;     /* trailing null */
5410                 name_len *= 2;
5411         } else {        /* BB improve the check for buffer overruns BB */
5412                 name_len = strnlen(fileName, PATH_MAX);
5413                 name_len++;     /* trailing null */
5414                 strncpy(pSMB->FileName, fileName, name_len);
5415         }
5416
5417         params = 6 + name_len;
5418         count = sizeof(FILE_BASIC_INFO);
5419         pSMB->MaxParameterCount = cpu_to_le16(2);
5420         /* BB find max SMB PDU from sess structure BB */
5421         pSMB->MaxDataCount = cpu_to_le16(1000);
5422         pSMB->MaxSetupCount = 0;
5423         pSMB->Reserved = 0;
5424         pSMB->Flags = 0;
5425         pSMB->Timeout = 0;
5426         pSMB->Reserved2 = 0;
5427         param_offset = offsetof(struct smb_com_transaction2_spi_req,
5428                                 InformationLevel) - 4;
5429         offset = param_offset + params;
5430         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5431         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5432         pSMB->DataOffset = cpu_to_le16(offset);
5433         pSMB->SetupCount = 1;
5434         pSMB->Reserved3 = 0;
5435         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5436         byte_count = 3 /* pad */  + params + count;
5437
5438         pSMB->DataCount = cpu_to_le16(count);
5439         pSMB->ParameterCount = cpu_to_le16(params);
5440         pSMB->TotalDataCount = pSMB->DataCount;
5441         pSMB->TotalParameterCount = pSMB->ParameterCount;
5442         if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5443                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5444         else
5445                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5446         pSMB->Reserved4 = 0;
5447         inc_rfc1001_len(pSMB, byte_count);
5448         memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5449         pSMB->ByteCount = cpu_to_le16(byte_count);
5450         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5451                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5452         if (rc)
5453                 cFYI(1, "SetPathInfo (times) returned %d", rc);
5454
5455         cifs_buf_release(pSMB);
5456
5457         if (rc == -EAGAIN)
5458                 goto SetTimesRetry;
5459
5460         return rc;
5461 }
5462
5463 /* Can not be used to set time stamps yet (due to old DOS time format) */
5464 /* Can be used to set attributes */
5465 #if 0  /* Possibly not needed - since it turns out that strangely NT4 has a bug
5466           handling it anyway and NT4 was what we thought it would be needed for
5467           Do not delete it until we prove whether needed for Win9x though */
5468 int
5469 CIFSSMBSetAttrLegacy(int xid, struct cifs_tcon *tcon, char *fileName,
5470                 __u16 dos_attrs, const struct nls_table *nls_codepage)
5471 {
5472         SETATTR_REQ *pSMB = NULL;
5473         SETATTR_RSP *pSMBr = NULL;
5474         int rc = 0;
5475         int bytes_returned;
5476         int name_len;
5477
5478         cFYI(1, "In SetAttrLegacy");
5479
5480 SetAttrLgcyRetry:
5481         rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5482                       (void **) &pSMBr);
5483         if (rc)
5484                 return rc;
5485
5486         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5487                 name_len =
5488                         ConvertToUCS((__le16 *) pSMB->fileName, fileName,
5489                                 PATH_MAX, nls_codepage);
5490                 name_len++;     /* trailing null */
5491                 name_len *= 2;
5492         } else {        /* BB improve the check for buffer overruns BB */
5493                 name_len = strnlen(fileName, PATH_MAX);
5494                 name_len++;     /* trailing null */
5495                 strncpy(pSMB->fileName, fileName, name_len);
5496         }
5497         pSMB->attr = cpu_to_le16(dos_attrs);
5498         pSMB->BufferFormat = 0x04;
5499         inc_rfc1001_len(pSMB, name_len + 1);
5500         pSMB->ByteCount = cpu_to_le16(name_len + 1);
5501         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5502                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5503         if (rc)
5504                 cFYI(1, "Error in LegacySetAttr = %d", rc);
5505
5506         cifs_buf_release(pSMB);
5507
5508         if (rc == -EAGAIN)
5509                 goto SetAttrLgcyRetry;
5510
5511         return rc;
5512 }
5513 #endif /* temporarily unneeded SetAttr legacy function */
5514
5515 static void
5516 cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
5517                         const struct cifs_unix_set_info_args *args)
5518 {
5519         u64 mode = args->mode;
5520
5521         /*
5522          * Samba server ignores set of file size to zero due to bugs in some
5523          * older clients, but we should be precise - we use SetFileSize to
5524          * set file size and do not want to truncate file size to zero
5525          * accidentally as happened on one Samba server beta by putting
5526          * zero instead of -1 here
5527          */
5528         data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5529         data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5530         data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5531         data_offset->LastAccessTime = cpu_to_le64(args->atime);
5532         data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5533         data_offset->Uid = cpu_to_le64(args->uid);
5534         data_offset->Gid = cpu_to_le64(args->gid);
5535         /* better to leave device as zero when it is  */
5536         data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5537         data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5538         data_offset->Permissions = cpu_to_le64(mode);
5539
5540         if (S_ISREG(mode))
5541                 data_offset->Type = cpu_to_le32(UNIX_FILE);
5542         else if (S_ISDIR(mode))
5543                 data_offset->Type = cpu_to_le32(UNIX_DIR);
5544         else if (S_ISLNK(mode))
5545                 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5546         else if (S_ISCHR(mode))
5547                 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5548         else if (S_ISBLK(mode))
5549                 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5550         else if (S_ISFIFO(mode))
5551                 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5552         else if (S_ISSOCK(mode))
5553                 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5554 }
5555
5556 int
5557 CIFSSMBUnixSetFileInfo(const int xid, struct cifs_tcon *tcon,
5558                        const struct cifs_unix_set_info_args *args,
5559                        u16 fid, u32 pid_of_opener)
5560 {
5561         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
5562         FILE_UNIX_BASIC_INFO *data_offset;
5563         int rc = 0;
5564         u16 params, param_offset, offset, byte_count, count;
5565
5566         cFYI(1, "Set Unix Info (via SetFileInfo)");
5567         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5568
5569         if (rc)
5570                 return rc;
5571
5572         pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5573         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5574
5575         params = 6;
5576         pSMB->MaxSetupCount = 0;
5577         pSMB->Reserved = 0;
5578         pSMB->Flags = 0;
5579         pSMB->Timeout = 0;
5580         pSMB->Reserved2 = 0;
5581         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5582         offset = param_offset + params;
5583
5584         data_offset = (FILE_UNIX_BASIC_INFO *)
5585                                 ((char *)(&pSMB->hdr.Protocol) + offset);
5586         count = sizeof(FILE_UNIX_BASIC_INFO);
5587
5588         pSMB->MaxParameterCount = cpu_to_le16(2);
5589         /* BB find max SMB PDU from sess */
5590         pSMB->MaxDataCount = cpu_to_le16(1000);
5591         pSMB->SetupCount = 1;
5592         pSMB->Reserved3 = 0;
5593         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5594         byte_count = 3 /* pad */  + params + count;
5595         pSMB->DataCount = cpu_to_le16(count);
5596         pSMB->ParameterCount = cpu_to_le16(params);
5597         pSMB->TotalDataCount = pSMB->DataCount;
5598         pSMB->TotalParameterCount = pSMB->ParameterCount;
5599         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5600         pSMB->DataOffset = cpu_to_le16(offset);
5601         pSMB->Fid = fid;
5602         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5603         pSMB->Reserved4 = 0;
5604         inc_rfc1001_len(pSMB, byte_count);
5605         pSMB->ByteCount = cpu_to_le16(byte_count);
5606
5607         cifs_fill_unix_set_info(data_offset, args);
5608
5609         rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5610         if (rc)
5611                 cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
5612
5613         /* Note: On -EAGAIN error only caller can retry on handle based calls
5614                 since file handle passed in no longer valid */
5615
5616         return rc;
5617 }
5618
5619 int
5620 CIFSSMBUnixSetPathInfo(const int xid, struct cifs_tcon *tcon, char *fileName,
5621                        const struct cifs_unix_set_info_args *args,
5622                        const struct nls_table *nls_codepage, int remap)
5623 {
5624         TRANSACTION2_SPI_REQ *pSMB = NULL;
5625         TRANSACTION2_SPI_RSP *pSMBr = NULL;
5626         int name_len;
5627         int rc = 0;
5628         int bytes_returned = 0;
5629         FILE_UNIX_BASIC_INFO *data_offset;
5630         __u16 params, param_offset, offset, count, byte_count;
5631
5632         cFYI(1, "In SetUID/GID/Mode");
5633 setPermsRetry:
5634         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5635                       (void **) &pSMBr);
5636         if (rc)
5637                 return rc;
5638
5639         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5640                 name_len =
5641                     cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5642                                      PATH_MAX, nls_codepage, remap);
5643                 name_len++;     /* trailing null */
5644                 name_len *= 2;
5645         } else {        /* BB improve the check for buffer overruns BB */
5646                 name_len = strnlen(fileName, PATH_MAX);
5647                 name_len++;     /* trailing null */
5648                 strncpy(pSMB->FileName, fileName, name_len);
5649         }
5650
5651         params = 6 + name_len;
5652         count = sizeof(FILE_UNIX_BASIC_INFO);
5653         pSMB->MaxParameterCount = cpu_to_le16(2);
5654         /* BB find max SMB PDU from sess structure BB */
5655         pSMB->MaxDataCount = cpu_to_le16(1000);
5656         pSMB->MaxSetupCount = 0;
5657         pSMB->Reserved = 0;
5658         pSMB->Flags = 0;
5659         pSMB->Timeout = 0;
5660         pSMB->Reserved2 = 0;
5661         param_offset = offsetof(struct smb_com_transaction2_spi_req,
5662                                 InformationLevel) - 4;
5663         offset = param_offset + params;
5664         data_offset =
5665             (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5666                                       offset);
5667         memset(data_offset, 0, count);
5668         pSMB->DataOffset = cpu_to_le16(offset);
5669         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5670         pSMB->SetupCount = 1;
5671         pSMB->Reserved3 = 0;
5672         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5673         byte_count = 3 /* pad */  + params + count;
5674         pSMB->ParameterCount = cpu_to_le16(params);
5675         pSMB->DataCount = cpu_to_le16(count);
5676         pSMB->TotalParameterCount = pSMB->ParameterCount;
5677         pSMB->TotalDataCount = pSMB->DataCount;
5678         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5679         pSMB->Reserved4 = 0;
5680         inc_rfc1001_len(pSMB, byte_count);
5681
5682         cifs_fill_unix_set_info(data_offset, args);
5683
5684         pSMB->ByteCount = cpu_to_le16(byte_count);
5685         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5686                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5687         if (rc)
5688                 cFYI(1, "SetPathInfo (perms) returned %d", rc);
5689
5690         cifs_buf_release(pSMB);
5691         if (rc == -EAGAIN)
5692                 goto setPermsRetry;
5693         r