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