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