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