~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/cifs/cifssmb.c

Version: ~ [ linux-5.13-rc7 ] ~ [ linux-5.12.12 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.45 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.127 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.195 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.237 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.273 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.273 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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