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