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

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

Version: ~ [ linux-5.3-rc5 ] ~ [ linux-5.2.9 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.67 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.139 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.189 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.189 ] ~ [ 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.72 ] ~ [ 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-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ 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