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