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