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