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