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

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

Version: ~ [ linux-5.16 ] ~ [ linux-5.15.13 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.90 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.170 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.224 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.261 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.296 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.298 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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