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