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