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