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

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

Version: ~ [ linux-5.11-rc3 ] ~ [ linux-5.10.7 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.89 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.167 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.215 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.251 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.251 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

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

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp