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

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

Version: ~ [ linux-5.6-rc7 ] ~ [ linux-5.5.11 ] ~ [ linux-5.4.27 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.112 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.174 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.217 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.217 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.82 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

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