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