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