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

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

Version: ~ [ linux-5.13-rc1 ] ~ [ linux-5.12.2 ] ~ [ linux-5.11.19 ] ~ [ linux-5.10.35 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.117 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.190 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.232 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.268 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.268 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

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