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