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