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