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

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

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