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