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