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