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