[CIFS] Send SMB flush in cifs_fsync
[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_strncpy_to_host(char **dst, const char *src, const int maxlen,
92                  const bool is_unicode, const struct nls_table *nls_codepage)
93 {
94         int plen;
95
96         if (is_unicode) {
97                 plen = UniStrnlen((wchar_t *)src, maxlen);
98                 *dst = kmalloc(plen + 2, GFP_KERNEL);
99                 if (!*dst)
100                         goto cifs_strncpy_to_host_ErrExit;
101                 cifs_strfromUCS_le(*dst, (__le16 *)src, plen, nls_codepage);
102         } else {
103                 plen = strnlen(src, maxlen);
104                 *dst = kmalloc(plen + 2, GFP_KERNEL);
105                 if (!*dst)
106                         goto cifs_strncpy_to_host_ErrExit;
107                 strncpy(*dst, src, plen);
108         }
109         (*dst)[plen] = 0;
110         (*dst)[plen+1] = 0; /* harmless for ASCII case, needed for Unicode */
111         return 0;
112
113 cifs_strncpy_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         cFYI(1, ("write2 at %lld %d bytes", (long long)offset, count));
1630
1631         if (tcon->ses->capabilities & CAP_LARGE_FILES) {
1632                 wct = 14;
1633         } else {
1634                 wct = 12;
1635                 if ((offset >> 32) > 0) {
1636                         /* can not handle big offset for old srv */
1637                         return -EIO;
1638                 }
1639         }
1640         rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1641         if (rc)
1642                 return rc;
1643         /* tcon and ses pointer are checked in smb_init */
1644         if (tcon->ses->server == NULL)
1645                 return -ECONNABORTED;
1646
1647         pSMB->AndXCommand = 0xFF;       /* none */
1648         pSMB->Fid = netfid;
1649         pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1650         if (wct == 14)
1651                 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1652         pSMB->Reserved = 0xFFFFFFFF;
1653         pSMB->WriteMode = 0;
1654         pSMB->Remaining = 0;
1655
1656         pSMB->DataOffset =
1657             cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1658
1659         pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1660         pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1661         smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1662         if (wct == 14)
1663                 pSMB->hdr.smb_buf_length += count+1;
1664         else /* wct == 12 */
1665                 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1666         if (wct == 14)
1667                 pSMB->ByteCount = cpu_to_le16(count + 1);
1668         else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1669                 struct smb_com_writex_req *pSMBW =
1670                                 (struct smb_com_writex_req *)pSMB;
1671                 pSMBW->ByteCount = cpu_to_le16(count + 5);
1672         }
1673         iov[0].iov_base = pSMB;
1674         if (wct == 14)
1675                 iov[0].iov_len = smb_hdr_len + 4;
1676         else /* wct == 12 pad bigger by four bytes */
1677                 iov[0].iov_len = smb_hdr_len + 8;
1678
1679
1680         rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1681                           long_op);
1682         cifs_stats_inc(&tcon->num_writes);
1683         if (rc) {
1684                 cFYI(1, ("Send error Write2 = %d", rc));
1685                 *nbytes = 0;
1686         } else if (resp_buf_type == 0) {
1687                 /* presumably this can not happen, but best to be safe */
1688                 rc = -EIO;
1689                 *nbytes = 0;
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                 pSMB->OldFileName[name_len] = 0;        /* pad */
2381                 pSMB->OldFileName[name_len + 1] = 0x04;
2382                 name_len2 =
2383                     cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2384                                      toName, PATH_MAX, nls_codepage, remap);
2385                 name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2386                 name_len2 *= 2; /* convert to bytes */
2387         } else {        /* BB improve the check for buffer overruns BB */
2388                 name_len = strnlen(fromName, PATH_MAX);
2389                 name_len++;     /* trailing null */
2390                 strncpy(pSMB->OldFileName, fromName, name_len);
2391                 name_len2 = strnlen(toName, PATH_MAX);
2392                 name_len2++;    /* trailing null */
2393                 pSMB->OldFileName[name_len] = 0x04;     /* 2nd buffer format */
2394                 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2395                 name_len2++;    /* trailing null */
2396                 name_len2++;    /* signature byte */
2397         }
2398
2399         count = 1 /* string type byte */  + name_len + name_len2;
2400         pSMB->hdr.smb_buf_length += count;
2401         pSMB->ByteCount = cpu_to_le16(count);
2402
2403         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2404                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2405         cifs_stats_inc(&tcon->num_hardlinks);
2406         if (rc)
2407                 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
2408
2409         cifs_buf_release(pSMB);
2410         if (rc == -EAGAIN)
2411                 goto winCreateHardLinkRetry;
2412
2413         return rc;
2414 }
2415
2416 int
2417 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2418                         const unsigned char *searchName,
2419                         char *symlinkinfo, const int buflen,
2420                         const struct nls_table *nls_codepage)
2421 {
2422 /* SMB_QUERY_FILE_UNIX_LINK */
2423         TRANSACTION2_QPI_REQ *pSMB = NULL;
2424         TRANSACTION2_QPI_RSP *pSMBr = NULL;
2425         int rc = 0;
2426         int bytes_returned;
2427         int name_len;
2428         __u16 params, byte_count;
2429
2430         cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
2431
2432 querySymLinkRetry:
2433         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2434                       (void **) &pSMBr);
2435         if (rc)
2436                 return rc;
2437
2438         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2439                 name_len =
2440                     cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
2441                                   PATH_MAX, nls_codepage);
2442                 name_len++;     /* trailing null */
2443                 name_len *= 2;
2444         } else {        /* BB improve the check for buffer overruns BB */
2445                 name_len = strnlen(searchName, PATH_MAX);
2446                 name_len++;     /* trailing null */
2447                 strncpy(pSMB->FileName, searchName, name_len);
2448         }
2449
2450         params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
2451         pSMB->TotalDataCount = 0;
2452         pSMB->MaxParameterCount = cpu_to_le16(2);
2453         /* BB find exact max data count below from sess structure BB */
2454         pSMB->MaxDataCount = cpu_to_le16(4000);
2455         pSMB->MaxSetupCount = 0;
2456         pSMB->Reserved = 0;
2457         pSMB->Flags = 0;
2458         pSMB->Timeout = 0;
2459         pSMB->Reserved2 = 0;
2460         pSMB->ParameterOffset = cpu_to_le16(offsetof(
2461         struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2462         pSMB->DataCount = 0;
2463         pSMB->DataOffset = 0;
2464         pSMB->SetupCount = 1;
2465         pSMB->Reserved3 = 0;
2466         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2467         byte_count = params + 1 /* pad */ ;
2468         pSMB->TotalParameterCount = cpu_to_le16(params);
2469         pSMB->ParameterCount = pSMB->TotalParameterCount;
2470         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2471         pSMB->Reserved4 = 0;
2472         pSMB->hdr.smb_buf_length += byte_count;
2473         pSMB->ByteCount = cpu_to_le16(byte_count);
2474
2475         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2476                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2477         if (rc) {
2478                 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
2479         } else {
2480                 /* decode response */
2481
2482                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2483                 if (rc || (pSMBr->ByteCount < 2))
2484                 /* BB also check enough total bytes returned */
2485                         rc = -EIO;      /* bad smb */
2486                 else {
2487                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2488                         __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2489
2490                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2491                                 name_len = UniStrnlen((wchar_t *) ((char *)
2492                                         &pSMBr->hdr.Protocol + data_offset),
2493                                         min_t(const int, buflen, count) / 2);
2494                         /* BB FIXME investigate remapping reserved chars here */
2495                                 cifs_strfromUCS_le(symlinkinfo,
2496                                         (__le16 *) ((char *)&pSMBr->hdr.Protocol
2497                                                         + data_offset),
2498                                         name_len, nls_codepage);
2499                         } else {
2500                                 strncpy(symlinkinfo,
2501                                         (char *) &pSMBr->hdr.Protocol +
2502                                                 data_offset,
2503                                         min_t(const int, buflen, count));
2504                         }
2505                         symlinkinfo[buflen] = 0;
2506         /* just in case so calling code does not go off the end of buffer */
2507                 }
2508         }
2509         cifs_buf_release(pSMB);
2510         if (rc == -EAGAIN)
2511                 goto querySymLinkRetry;
2512         return rc;
2513 }
2514
2515 #ifdef CONFIG_CIFS_EXPERIMENTAL
2516 /* Initialize NT TRANSACT SMB into small smb request buffer.
2517    This assumes that all NT TRANSACTS that we init here have
2518    total parm and data under about 400 bytes (to fit in small cifs
2519    buffer size), which is the case so far, it easily fits. NB:
2520         Setup words themselves and ByteCount
2521         MaxSetupCount (size of returned setup area) and
2522         MaxParameterCount (returned parms size) must be set by caller */
2523 static int
2524 smb_init_nttransact(const __u16 sub_command, const int setup_count,
2525                    const int parm_len, struct cifsTconInfo *tcon,
2526                    void **ret_buf)
2527 {
2528         int rc;
2529         __u32 temp_offset;
2530         struct smb_com_ntransact_req *pSMB;
2531
2532         rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2533                                 (void **)&pSMB);
2534         if (rc)
2535                 return rc;
2536         *ret_buf = (void *)pSMB;
2537         pSMB->Reserved = 0;
2538         pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2539         pSMB->TotalDataCount  = 0;
2540         pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2541                                           MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2542         pSMB->ParameterCount = pSMB->TotalParameterCount;
2543         pSMB->DataCount  = pSMB->TotalDataCount;
2544         temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2545                         (setup_count * 2) - 4 /* for rfc1001 length itself */;
2546         pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2547         pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2548         pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
2549         pSMB->SubCommand = cpu_to_le16(sub_command);
2550         return 0;
2551 }
2552
2553 static int
2554 validate_ntransact(char *buf, char **ppparm, char **ppdata,
2555                    __u32 *pparmlen, __u32 *pdatalen)
2556 {
2557         char *end_of_smb;
2558         __u32 data_count, data_offset, parm_count, parm_offset;
2559         struct smb_com_ntransact_rsp *pSMBr;
2560
2561         *pdatalen = 0;
2562         *pparmlen = 0;
2563
2564         if (buf == NULL)
2565                 return -EINVAL;
2566
2567         pSMBr = (struct smb_com_ntransact_rsp *)buf;
2568
2569         /* ByteCount was converted from little endian in SendReceive */
2570         end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
2571                         (char *)&pSMBr->ByteCount;
2572
2573         data_offset = le32_to_cpu(pSMBr->DataOffset);
2574         data_count = le32_to_cpu(pSMBr->DataCount);
2575         parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2576         parm_count = le32_to_cpu(pSMBr->ParameterCount);
2577
2578         *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2579         *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2580
2581         /* should we also check that parm and data areas do not overlap? */
2582         if (*ppparm > end_of_smb) {
2583                 cFYI(1, ("parms start after end of smb"));
2584                 return -EINVAL;
2585         } else if (parm_count + *ppparm > end_of_smb) {
2586                 cFYI(1, ("parm end after end of smb"));
2587                 return -EINVAL;
2588         } else if (*ppdata > end_of_smb) {
2589                 cFYI(1, ("data starts after end of smb"));
2590                 return -EINVAL;
2591         } else if (data_count + *ppdata > end_of_smb) {
2592                 cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
2593                         *ppdata, data_count, (data_count + *ppdata),
2594                         end_of_smb, pSMBr));
2595                 return -EINVAL;
2596         } else if (parm_count + data_count > pSMBr->ByteCount) {
2597                 cFYI(1, ("parm count and data count larger than SMB"));
2598                 return -EINVAL;
2599         }
2600         *pdatalen = data_count;
2601         *pparmlen = parm_count;
2602         return 0;
2603 }
2604 #endif /* CIFS_EXPERIMENTAL */
2605
2606 int
2607 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2608                         const unsigned char *searchName,
2609                         char *symlinkinfo, const int buflen, __u16 fid,
2610                         const struct nls_table *nls_codepage)
2611 {
2612         int rc = 0;
2613         int bytes_returned;
2614         int name_len;
2615         struct smb_com_transaction_ioctl_req *pSMB;
2616         struct smb_com_transaction_ioctl_rsp *pSMBr;
2617
2618         cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2619         rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2620                       (void **) &pSMBr);
2621         if (rc)
2622                 return rc;
2623
2624         pSMB->TotalParameterCount = 0 ;
2625         pSMB->TotalDataCount = 0;
2626         pSMB->MaxParameterCount = cpu_to_le32(2);
2627         /* BB find exact data count max from sess structure BB */
2628         pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2629                                           MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2630         pSMB->MaxSetupCount = 4;
2631         pSMB->Reserved = 0;
2632         pSMB->ParameterOffset = 0;
2633         pSMB->DataCount = 0;
2634         pSMB->DataOffset = 0;
2635         pSMB->SetupCount = 4;
2636         pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2637         pSMB->ParameterCount = pSMB->TotalParameterCount;
2638         pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2639         pSMB->IsFsctl = 1; /* FSCTL */
2640         pSMB->IsRootFlag = 0;
2641         pSMB->Fid = fid; /* file handle always le */
2642         pSMB->ByteCount = 0;
2643
2644         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2645                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2646         if (rc) {
2647                 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2648         } else {                /* decode response */
2649                 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2650                 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2651                 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
2652                 /* BB also check enough total bytes returned */
2653                         rc = -EIO;      /* bad smb */
2654                 else {
2655                         if (data_count && (data_count < 2048)) {
2656                                 char *end_of_smb = 2 /* sizeof byte count */ +
2657                                                 pSMBr->ByteCount +
2658                                                 (char *)&pSMBr->ByteCount;
2659
2660                                 struct reparse_data *reparse_buf =
2661                                                 (struct reparse_data *)
2662                                                 ((char *)&pSMBr->hdr.Protocol
2663                                                                  + data_offset);
2664                                 if ((char *)reparse_buf >= end_of_smb) {
2665                                         rc = -EIO;
2666                                         goto qreparse_out;
2667                                 }
2668                                 if ((reparse_buf->LinkNamesBuf +
2669                                         reparse_buf->TargetNameOffset +
2670                                         reparse_buf->TargetNameLen) >
2671                                                 end_of_smb) {
2672                                         cFYI(1, ("reparse buf beyond SMB"));
2673                                         rc = -EIO;
2674                                         goto qreparse_out;
2675                                 }
2676
2677                                 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2678                                         name_len = UniStrnlen((wchar_t *)
2679                                                 (reparse_buf->LinkNamesBuf +
2680                                                 reparse_buf->TargetNameOffset),
2681                                                 min(buflen/2,
2682                                                 reparse_buf->TargetNameLen / 2));
2683                                         cifs_strfromUCS_le(symlinkinfo,
2684                                                 (__le16 *) (reparse_buf->LinkNamesBuf +
2685                                                 reparse_buf->TargetNameOffset),
2686                                                 name_len, nls_codepage);
2687                                 } else { /* ASCII names */
2688                                         strncpy(symlinkinfo,
2689                                                 reparse_buf->LinkNamesBuf +
2690                                                 reparse_buf->TargetNameOffset,
2691                                                 min_t(const int, buflen,
2692                                                    reparse_buf->TargetNameLen));
2693                                 }
2694                         } else {
2695                                 rc = -EIO;
2696                                 cFYI(1, ("Invalid return data count on "
2697                                          "get reparse info ioctl"));
2698                         }
2699                         symlinkinfo[buflen] = 0; /* just in case so the caller
2700                                         does not go off the end of the buffer */
2701                         cFYI(1, ("readlink result - %s", symlinkinfo));
2702                 }
2703         }
2704 qreparse_out:
2705         cifs_buf_release(pSMB);
2706
2707         /* Note: On -EAGAIN error only caller can retry on handle based calls
2708                 since file handle passed in no longer valid */
2709
2710         return rc;
2711 }
2712
2713 #ifdef CONFIG_CIFS_POSIX
2714
2715 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2716 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2717                              struct cifs_posix_ace *cifs_ace)
2718 {
2719         /* u8 cifs fields do not need le conversion */
2720         ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2721         ace->e_tag  = cpu_to_le16(cifs_ace->cifs_e_tag);
2722         ace->e_id   = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2723         /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2724
2725         return;
2726 }
2727
2728 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2729 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2730                                const int acl_type, const int size_of_data_area)
2731 {
2732         int size =  0;
2733         int i;
2734         __u16 count;
2735         struct cifs_posix_ace *pACE;
2736         struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2737         posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2738
2739         if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2740                 return -EOPNOTSUPP;
2741
2742         if (acl_type & ACL_TYPE_ACCESS) {
2743                 count = le16_to_cpu(cifs_acl->access_entry_count);
2744                 pACE = &cifs_acl->ace_array[0];
2745                 size = sizeof(struct cifs_posix_acl);
2746                 size += sizeof(struct cifs_posix_ace) * count;
2747                 /* check if we would go beyond end of SMB */
2748                 if (size_of_data_area < size) {
2749                         cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
2750                                 size_of_data_area, size));
2751                         return -EINVAL;
2752                 }
2753         } else if (acl_type & ACL_TYPE_DEFAULT) {
2754                 count = le16_to_cpu(cifs_acl->access_entry_count);
2755                 size = sizeof(struct cifs_posix_acl);
2756                 size += sizeof(struct cifs_posix_ace) * count;
2757 /* skip past access ACEs to get to default ACEs */
2758                 pACE = &cifs_acl->ace_array[count];
2759                 count = le16_to_cpu(cifs_acl->default_entry_count);
2760                 size += sizeof(struct cifs_posix_ace) * count;
2761                 /* check if we would go beyond end of SMB */
2762                 if (size_of_data_area < size)
2763                         return -EINVAL;
2764         } else {
2765                 /* illegal type */
2766                 return -EINVAL;
2767         }
2768
2769         size = posix_acl_xattr_size(count);
2770         if ((buflen == 0) || (local_acl == NULL)) {
2771                 /* used to query ACL EA size */
2772         } else if (size > buflen) {
2773                 return -ERANGE;
2774         } else /* buffer big enough */ {
2775                 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2776                 for (i = 0; i < count ; i++) {
2777                         cifs_convert_ace(&local_acl->a_entries[i], pACE);
2778                         pACE++;
2779                 }
2780         }
2781         return size;
2782 }
2783
2784 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2785                                      const posix_acl_xattr_entry *local_ace)
2786 {
2787         __u16 rc = 0; /* 0 = ACL converted ok */
2788
2789         cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2790         cifs_ace->cifs_e_tag =  le16_to_cpu(local_ace->e_tag);
2791         /* BB is there a better way to handle the large uid? */
2792         if (local_ace->e_id == cpu_to_le32(-1)) {
2793         /* Probably no need to le convert -1 on any arch but can not hurt */
2794                 cifs_ace->cifs_uid = cpu_to_le64(-1);
2795         } else
2796                 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2797         /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2798         return rc;
2799 }
2800
2801 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2802 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2803                                const int buflen, const int acl_type)
2804 {
2805         __u16 rc = 0;
2806         struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2807         posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2808         int count;
2809         int i;
2810
2811         if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2812                 return 0;
2813
2814         count = posix_acl_xattr_count((size_t)buflen);
2815         cFYI(1, ("setting acl with %d entries from buf of length %d and "
2816                 "version of %d",
2817                 count, buflen, le32_to_cpu(local_acl->a_version)));
2818         if (le32_to_cpu(local_acl->a_version) != 2) {
2819                 cFYI(1, ("unknown POSIX ACL version %d",
2820                      le32_to_cpu(local_acl->a_version)));
2821                 return 0;
2822         }
2823         cifs_acl->version = cpu_to_le16(1);
2824         if (acl_type == ACL_TYPE_ACCESS)
2825                 cifs_acl->access_entry_count = cpu_to_le16(count);
2826         else if (acl_type == ACL_TYPE_DEFAULT)
2827                 cifs_acl->default_entry_count = cpu_to_le16(count);
2828         else {
2829                 cFYI(1, ("unknown ACL type %d", acl_type));
2830                 return 0;
2831         }
2832         for (i = 0; i < count; i++) {
2833                 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2834                                         &local_acl->a_entries[i]);
2835                 if (rc != 0) {
2836                         /* ACE not converted */
2837                         break;
2838                 }
2839         }
2840         if (rc == 0) {
2841                 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2842                 rc += sizeof(struct cifs_posix_acl);
2843                 /* BB add check to make sure ACL does not overflow SMB */
2844         }
2845         return rc;
2846 }
2847
2848 int
2849 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2850                    const unsigned char *searchName,
2851                    char *acl_inf, const int buflen, const int acl_type,
2852                    const struct nls_table *nls_codepage, int remap)
2853 {
2854 /* SMB_QUERY_POSIX_ACL */
2855         TRANSACTION2_QPI_REQ *pSMB = NULL;
2856         TRANSACTION2_QPI_RSP *pSMBr = NULL;
2857         int rc = 0;
2858         int bytes_returned;
2859         int name_len;
2860         __u16 params, byte_count;
2861
2862         cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2863
2864 queryAclRetry:
2865         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2866                 (void **) &pSMBr);
2867         if (rc)
2868                 return rc;
2869
2870         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2871                 name_len =
2872                         cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2873                                          PATH_MAX, nls_codepage, remap);
2874                 name_len++;     /* trailing null */
2875                 name_len *= 2;
2876                 pSMB->FileName[name_len] = 0;
2877                 pSMB->FileName[name_len+1] = 0;
2878         } else {        /* BB improve the check for buffer overruns BB */
2879                 name_len = strnlen(searchName, PATH_MAX);
2880                 name_len++;     /* trailing null */
2881                 strncpy(pSMB->FileName, searchName, name_len);
2882         }
2883
2884         params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
2885         pSMB->TotalDataCount = 0;
2886         pSMB->MaxParameterCount = cpu_to_le16(2);
2887         /* BB find exact max data count below from sess structure BB */
2888         pSMB->MaxDataCount = cpu_to_le16(4000);
2889         pSMB->MaxSetupCount = 0;
2890         pSMB->Reserved = 0;
2891         pSMB->Flags = 0;
2892         pSMB->Timeout = 0;
2893         pSMB->Reserved2 = 0;
2894         pSMB->ParameterOffset = cpu_to_le16(
2895                 offsetof(struct smb_com_transaction2_qpi_req,
2896                          InformationLevel) - 4);
2897         pSMB->DataCount = 0;
2898         pSMB->DataOffset = 0;
2899         pSMB->SetupCount = 1;
2900         pSMB->Reserved3 = 0;
2901         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2902         byte_count = params + 1 /* pad */ ;
2903         pSMB->TotalParameterCount = cpu_to_le16(params);
2904         pSMB->ParameterCount = pSMB->TotalParameterCount;
2905         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2906         pSMB->Reserved4 = 0;
2907         pSMB->hdr.smb_buf_length += byte_count;
2908         pSMB->ByteCount = cpu_to_le16(byte_count);
2909
2910         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2911                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2912         cifs_stats_inc(&tcon->num_acl_get);
2913         if (rc) {
2914                 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2915         } else {
2916                 /* decode response */
2917
2918                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2919                 if (rc || (pSMBr->ByteCount < 2))
2920                 /* BB also check enough total bytes returned */
2921                         rc = -EIO;      /* bad smb */
2922                 else {
2923                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2924                         __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2925                         rc = cifs_copy_posix_acl(acl_inf,
2926                                 (char *)&pSMBr->hdr.Protocol+data_offset,
2927                                 buflen, acl_type, count);
2928                 }
2929         }
2930         cifs_buf_release(pSMB);
2931         if (rc == -EAGAIN)
2932                 goto queryAclRetry;
2933         return rc;
2934 }
2935
2936 int
2937 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2938                    const unsigned char *fileName,
2939                    const char *local_acl, const int buflen,
2940                    const int acl_type,
2941                    const struct nls_table *nls_codepage, int remap)
2942 {
2943         struct smb_com_transaction2_spi_req *pSMB = NULL;
2944         struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2945         char *parm_data;
2946         int name_len;
2947         int rc = 0;
2948         int bytes_returned = 0;
2949         __u16 params, byte_count, data_count, param_offset, offset;
2950
2951         cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2952 setAclRetry:
2953         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2954                       (void **) &pSMBr);
2955         if (rc)
2956                 return rc;
2957         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2958                 name_len =
2959                         cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2960                                       PATH_MAX, nls_codepage, remap);
2961                 name_len++;     /* trailing null */
2962                 name_len *= 2;
2963         } else {        /* BB improve the check for buffer overruns BB */
2964                 name_len = strnlen(fileName, PATH_MAX);
2965                 name_len++;     /* trailing null */
2966                 strncpy(pSMB->FileName, fileName, name_len);
2967         }
2968         params = 6 + name_len;
2969         pSMB->MaxParameterCount = cpu_to_le16(2);
2970         /* BB find max SMB size from sess */
2971         pSMB->MaxDataCount = cpu_to_le16(1000);
2972         pSMB->MaxSetupCount = 0;
2973         pSMB->Reserved = 0;
2974         pSMB->Flags = 0;
2975         pSMB->Timeout = 0;
2976         pSMB->Reserved2 = 0;
2977         param_offset = offsetof(struct smb_com_transaction2_spi_req,
2978                                 InformationLevel) - 4;
2979         offset = param_offset + params;
2980         parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2981         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2982
2983         /* convert to on the wire format for POSIX ACL */
2984         data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
2985
2986         if (data_count == 0) {
2987                 rc = -EOPNOTSUPP;
2988                 goto setACLerrorExit;
2989         }
2990         pSMB->DataOffset = cpu_to_le16(offset);
2991         pSMB->SetupCount = 1;
2992         pSMB->Reserved3 = 0;
2993         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2994         pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2995         byte_count = 3 /* pad */  + params + data_count;
2996         pSMB->DataCount = cpu_to_le16(data_count);
2997         pSMB->TotalDataCount = pSMB->DataCount;
2998         pSMB->ParameterCount = cpu_to_le16(params);
2999         pSMB->TotalParameterCount = pSMB->ParameterCount;
3000         pSMB->Reserved4 = 0;
3001         pSMB->hdr.smb_buf_length += byte_count;
3002         pSMB->ByteCount = cpu_to_le16(byte_count);
3003         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3004                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3005         if (rc)
3006                 cFYI(1, ("Set POSIX ACL returned %d", rc));
3007
3008 setACLerrorExit:
3009         cifs_buf_release(pSMB);
3010         if (rc == -EAGAIN)
3011                 goto setAclRetry;
3012         return rc;
3013 }
3014
3015 /* BB fix tabs in this function FIXME BB */
3016 int
3017 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
3018                const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
3019 {
3020         int rc = 0;
3021         struct smb_t2_qfi_req *pSMB = NULL;
3022         struct smb_t2_qfi_rsp *pSMBr = NULL;
3023         int bytes_returned;
3024         __u16 params, byte_count;
3025
3026         cFYI(1, ("In GetExtAttr"));
3027         if (tcon == NULL)
3028                 return -ENODEV;
3029
3030 GetExtAttrRetry:
3031         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3032                         (void **) &pSMBr);
3033         if (rc)
3034                 return rc;
3035
3036         params = 2 /* level */ + 2 /* fid */;
3037         pSMB->t2.TotalDataCount = 0;
3038         pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3039         /* BB find exact max data count below from sess structure BB */
3040         pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3041         pSMB->t2.MaxSetupCount = 0;
3042         pSMB->t2.Reserved = 0;
3043         pSMB->t2.Flags = 0;
3044         pSMB->t2.Timeout = 0;
3045         pSMB->t2.Reserved2 = 0;
3046         pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3047                                                Fid) - 4);
3048         pSMB->t2.DataCount = 0;
3049         pSMB->t2.DataOffset = 0;
3050         pSMB->t2.SetupCount = 1;
3051         pSMB->t2.Reserved3 = 0;
3052         pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3053         byte_count = params + 1 /* pad */ ;
3054         pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3055         pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3056         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3057         pSMB->Pad = 0;
3058         pSMB->Fid = netfid;
3059         pSMB->hdr.smb_buf_length += byte_count;
3060         pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3061
3062         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3063                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3064         if (rc) {
3065                 cFYI(1, ("error %d in GetExtAttr", rc));
3066         } else {
3067                 /* decode response */
3068                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3069                 if (rc || (pSMBr->ByteCount < 2))
3070                 /* BB also check enough total bytes returned */
3071                         /* If rc should we check for EOPNOSUPP and
3072                            disable the srvino flag? or in caller? */
3073                         rc = -EIO;      /* bad smb */
3074                 else {
3075                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3076                         __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3077                         struct file_chattr_info *pfinfo;
3078                         /* BB Do we need a cast or hash here ? */
3079                         if (count != 16) {
3080                                 cFYI(1, ("Illegal size ret in GetExtAttr"));
3081                                 rc = -EIO;
3082                                 goto GetExtAttrOut;
3083                         }
3084                         pfinfo = (struct file_chattr_info *)
3085                                  (data_offset + (char *) &pSMBr->hdr.Protocol);
3086                         *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3087                         *pMask = le64_to_cpu(pfinfo->mask);
3088                 }
3089         }
3090 GetExtAttrOut:
3091         cifs_buf_release(pSMB);
3092         if (rc == -EAGAIN)
3093                 goto GetExtAttrRetry;
3094         return rc;
3095 }
3096
3097 #endif /* CONFIG_POSIX */
3098
3099 #ifdef CONFIG_CIFS_EXPERIMENTAL
3100 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3101 int
3102 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3103                   struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3104 {
3105         int rc = 0;
3106         int buf_type = 0;
3107         QUERY_SEC_DESC_REQ *pSMB;
3108         struct kvec iov[1];
3109
3110         cFYI(1, ("GetCifsACL"));
3111
3112         *pbuflen = 0;
3113         *acl_inf = NULL;
3114
3115         rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3116                         8 /* parm len */, tcon, (void **) &pSMB);
3117         if (rc)
3118                 return rc;
3119
3120         pSMB->MaxParameterCount = cpu_to_le32(4);
3121         /* BB TEST with big acls that might need to be e.g. larger than 16K */
3122         pSMB->MaxSetupCount = 0;
3123         pSMB->Fid = fid; /* file handle always le */
3124         pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3125                                      CIFS_ACL_DACL);
3126         pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3127         pSMB->hdr.smb_buf_length += 11;
3128         iov[0].iov_base = (char *)pSMB;
3129         iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
3130
3131         rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3132                          CIFS_STD_OP);
3133         cifs_stats_inc(&tcon->num_acl_get);
3134         if (rc) {
3135                 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
3136         } else {                /* decode response */
3137                 __le32 *parm;
3138                 __u32 parm_len;
3139                 __u32 acl_len;
3140                 struct smb_com_ntransact_rsp *pSMBr;
3141                 char *pdata;
3142
3143 /* validate_nttransact */
3144                 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3145                                         &pdata, &parm_len, pbuflen);
3146                 if (rc)
3147                         goto qsec_out;
3148                 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3149
3150                 cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, *acl_inf));
3151
3152                 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3153                         rc = -EIO;      /* bad smb */
3154                         *pbuflen = 0;
3155                         goto qsec_out;
3156                 }
3157
3158 /* BB check that data area is minimum length and as big as acl_len */
3159
3160                 acl_len = le32_to_cpu(*parm);
3161                 if (acl_len != *pbuflen) {
3162                         cERROR(1, ("acl length %d does not match %d",
3163                                    acl_len, *pbuflen));
3164                         if (*pbuflen > acl_len)
3165                                 *pbuflen = acl_len;
3166                 }
3167
3168                 /* check if buffer is big enough for the acl
3169                    header followed by the smallest SID */
3170                 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3171                     (*pbuflen >= 64 * 1024)) {
3172                         cERROR(1, ("bad acl length %d", *pbuflen));
3173                         rc = -EINVAL;
3174                         *pbuflen = 0;
3175                 } else {
3176                         *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3177                         if (*acl_inf == NULL) {
3178                                 *pbuflen = 0;
3179                                 rc = -ENOMEM;
3180                         }
3181                         memcpy(*acl_inf, pdata, *pbuflen);
3182                 }
3183         }
3184 qsec_out:
3185         if (buf_type == CIFS_SMALL_BUFFER)
3186                 cifs_small_buf_release(iov[0].iov_base);
3187         else if (buf_type == CIFS_LARGE_BUFFER)
3188                 cifs_buf_release(iov[0].iov_base);
3189 /*      cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3190         return rc;
3191 }
3192
3193 int
3194 CIFSSMBSetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3195                         struct cifs_ntsd *pntsd, __u32 acllen)
3196 {
3197         __u16 byte_count, param_count, data_count, param_offset, data_offset;
3198         int rc = 0;
3199         int bytes_returned = 0;
3200         SET_SEC_DESC_REQ *pSMB = NULL;
3201         NTRANSACT_RSP *pSMBr = NULL;
3202
3203 setCifsAclRetry:
3204         rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB,
3205                         (void **) &pSMBr);
3206         if (rc)
3207                         return (rc);
3208
3209         pSMB->MaxSetupCount = 0;
3210         pSMB->Reserved = 0;
3211
3212         param_count = 8;
3213         param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3214         data_count = acllen;
3215         data_offset = param_offset + param_count;
3216         byte_count = 3 /* pad */  + param_count;
3217
3218         pSMB->DataCount = cpu_to_le32(data_count);
3219         pSMB->TotalDataCount = pSMB->DataCount;
3220         pSMB->MaxParameterCount = cpu_to_le32(4);
3221         pSMB->MaxDataCount = cpu_to_le32(16384);
3222         pSMB->ParameterCount = cpu_to_le32(param_count);
3223         pSMB->ParameterOffset = cpu_to_le32(param_offset);
3224         pSMB->TotalParameterCount = pSMB->ParameterCount;
3225         pSMB->DataOffset = cpu_to_le32(data_offset);
3226         pSMB->SetupCount = 0;
3227         pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3228         pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3229
3230         pSMB->Fid = fid; /* file handle always le */
3231         pSMB->Reserved2 = 0;
3232         pSMB->AclFlags = cpu_to_le32(CIFS_ACL_DACL);
3233
3234         if (pntsd && acllen) {
3235                 memcpy((char *) &pSMBr->hdr.Protocol + data_offset,
3236                         (char *) pntsd,
3237                         acllen);
3238                 pSMB->hdr.smb_buf_length += (byte_count + data_count);
3239
3240         } else
3241                 pSMB->hdr.smb_buf_length += byte_count;
3242
3243         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3244                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3245
3246         cFYI(1, ("SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc));
3247         if (rc)
3248                 cFYI(1, ("Set CIFS ACL returned %d", rc));
3249         cifs_buf_release(pSMB);
3250
3251         if (rc == -EAGAIN)
3252                 goto setCifsAclRetry;
3253
3254         return (rc);
3255 }
3256
3257 #endif /* CONFIG_CIFS_EXPERIMENTAL */
3258
3259 /* Legacy Query Path Information call for lookup to old servers such
3260    as Win9x/WinME */
3261 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
3262                         const unsigned char *searchName,
3263                         FILE_ALL_INFO *pFinfo,
3264                         const struct nls_table *nls_codepage, int remap)
3265 {
3266         QUERY_INFORMATION_REQ *pSMB;
3267         QUERY_INFORMATION_RSP *pSMBr;
3268         int rc = 0;
3269         int bytes_returned;
3270         int name_len;
3271
3272         cFYI(1, ("In SMBQPath path %s", searchName));
3273 QInfRetry:
3274         rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3275                       (void **) &pSMBr);
3276         if (rc)
3277                 return rc;
3278
3279         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3280                 name_len =
3281                         cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3282                                         PATH_MAX, nls_codepage, remap);
3283                 name_len++;     /* trailing null */
3284                 name_len *= 2;
3285         } else {
3286                 name_len = strnlen(searchName, PATH_MAX);
3287                 name_len++;     /* trailing null */
3288                 strncpy(pSMB->FileName, searchName, name_len);
3289         }
3290         pSMB->BufferFormat = 0x04;
3291         name_len++; /* account for buffer type byte */
3292         pSMB->hdr.smb_buf_length += (__u16) name_len;
3293         pSMB->ByteCount = cpu_to_le16(name_len);
3294
3295         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3296                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3297         if (rc) {
3298                 cFYI(1, ("Send error in QueryInfo = %d", rc));
3299         } else if (pFinfo) {
3300                 struct timespec ts;
3301                 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3302
3303                 /* decode response */
3304                 /* BB FIXME - add time zone adjustment BB */
3305                 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3306                 ts.tv_nsec = 0;
3307                 ts.tv_sec = time;
3308                 /* decode time fields */
3309                 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3310                 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3311                 pFinfo->LastAccessTime = 0;
3312                 pFinfo->AllocationSize =
3313                         cpu_to_le64(le32_to_cpu(pSMBr->size));
3314                 pFinfo->EndOfFile = pFinfo->AllocationSize;
3315                 pFinfo->Attributes =
3316                         cpu_to_le32(le16_to_cpu(pSMBr->attr));
3317         } else
3318                 rc = -EIO; /* bad buffer passed in */
3319
3320         cifs_buf_release(pSMB);
3321
3322         if (rc == -EAGAIN)
3323                 goto QInfRetry;
3324
3325         return rc;
3326 }
3327
3328
3329
3330
3331 int
3332 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
3333                  const unsigned char *searchName,
3334                  FILE_ALL_INFO *pFindData,
3335                  int legacy /* old style infolevel */,
3336                  const struct nls_table *nls_codepage, int remap)
3337 {
3338 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3339         TRANSACTION2_QPI_REQ *pSMB = NULL;
3340         TRANSACTION2_QPI_RSP *pSMBr = NULL;
3341         int rc = 0;
3342         int bytes_returned;
3343         int name_len;
3344         __u16 params, byte_count;
3345
3346 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
3347 QPathInfoRetry:
3348         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3349                       (void **) &pSMBr);
3350         if (rc)
3351                 return rc;
3352
3353         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3354                 name_len =
3355                     cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3356                                      PATH_MAX, nls_codepage, remap);
3357                 name_len++;     /* trailing null */
3358                 name_len *= 2;
3359         } else {        /* BB improve the check for buffer overruns BB */
3360                 name_len = strnlen(searchName, PATH_MAX);
3361                 name_len++;     /* trailing null */
3362                 strncpy(pSMB->FileName, searchName, name_len);
3363         }
3364
3365         params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3366         pSMB->TotalDataCount = 0;
3367         pSMB->MaxParameterCount = cpu_to_le16(2);
3368         /* BB find exact max SMB PDU from sess structure BB */
3369         pSMB->MaxDataCount = cpu_to_le16(4000);
3370         pSMB->MaxSetupCount = 0;
3371         pSMB->Reserved = 0;
3372         pSMB->Flags = 0;
3373         pSMB->Timeout = 0;
3374         pSMB->Reserved2 = 0;
3375         pSMB->ParameterOffset = cpu_to_le16(offsetof(
3376         struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3377         pSMB->DataCount = 0;
3378         pSMB->DataOffset = 0;
3379         pSMB->SetupCount = 1;
3380         pSMB->Reserved3 = 0;
3381         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3382         byte_count = params + 1 /* pad */ ;
3383         pSMB->TotalParameterCount = cpu_to_le16(params);
3384         pSMB->ParameterCount = pSMB->TotalParameterCount;
3385         if (legacy)
3386                 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3387         else
3388                 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3389         pSMB->Reserved4 = 0;
3390         pSMB->hdr.smb_buf_length += byte_count;
3391         pSMB->ByteCount = cpu_to_le16(byte_count);
3392
3393         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3394                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3395         if (rc) {
3396                 cFYI(1, ("Send error in QPathInfo = %d", rc));
3397         } else {                /* decode response */
3398                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3399
3400                 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3401                         rc = -EIO;
3402                 else if (!legacy && (pSMBr->ByteCount < 40))
3403                         rc = -EIO;      /* bad smb */
3404                 else if (legacy && (pSMBr->ByteCount < 24))
3405                         rc = -EIO;  /* 24 or 26 expected but we do not read
3406                                         last field */
3407                 else if (pFindData) {
3408                         int size;
3409                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3410
3411                         /* On legacy responses we do not read the last field,
3412                         EAsize, fortunately since it varies by subdialect and
3413                         also note it differs on Set vs. Get, ie two bytes or 4
3414                         bytes depending but we don't care here */
3415                         if (legacy)
3416                                 size = sizeof(FILE_INFO_STANDARD);
3417                         else
3418                                 size = sizeof(FILE_ALL_INFO);
3419                         memcpy((char *) pFindData,
3420                                (char *) &pSMBr->hdr.Protocol +
3421                                data_offset, size);
3422                 } else
3423                     rc = -ENOMEM;
3424         }
3425         cifs_buf_release(pSMB);
3426         if (rc == -EAGAIN)
3427                 goto QPathInfoRetry;
3428
3429         return rc;
3430 }
3431
3432 int
3433 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3434                      const unsigned char *searchName,
3435                      FILE_UNIX_BASIC_INFO *pFindData,
3436                      const struct nls_table *nls_codepage, int remap)
3437 {
3438 /* SMB_QUERY_FILE_UNIX_BASIC */
3439         TRANSACTION2_QPI_REQ *pSMB = NULL;
3440         TRANSACTION2_QPI_RSP *pSMBr = NULL;
3441         int rc = 0;
3442         int bytes_returned = 0;
3443         int name_len;
3444         __u16 params, byte_count;
3445
3446         cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
3447 UnixQPathInfoRetry:
3448         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3449                       (void **) &pSMBr);
3450         if (rc)
3451                 return rc;
3452
3453         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3454                 name_len =
3455                     cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3456                                   PATH_MAX, nls_codepage, remap);
3457                 name_len++;     /* trailing null */
3458                 name_len *= 2;
3459         } else {        /* BB improve the check for buffer overruns BB */
3460                 name_len = strnlen(searchName, PATH_MAX);
3461                 name_len++;     /* trailing null */
3462                 strncpy(pSMB->FileName, searchName, name_len);
3463         }
3464
3465         params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3466         pSMB->TotalDataCount = 0;
3467         pSMB->MaxParameterCount = cpu_to_le16(2);
3468         /* BB find exact max SMB PDU from sess structure BB */
3469         pSMB->MaxDataCount = cpu_to_le16(4000);
3470         pSMB->MaxSetupCount = 0;
3471         pSMB->Reserved = 0;
3472         pSMB->Flags = 0;
3473         pSMB->Timeout = 0;
3474         pSMB->Reserved2 = 0;
3475         pSMB->ParameterOffset = cpu_to_le16(offsetof(
3476         struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3477         pSMB->DataCount = 0;
3478         pSMB->DataOffset = 0;
3479         pSMB->SetupCount = 1;
3480         pSMB->Reserved3 = 0;
3481         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3482         byte_count = params + 1 /* pad */ ;
3483         pSMB->TotalParameterCount = cpu_to_le16(params);
3484         pSMB->ParameterCount = pSMB->TotalParameterCount;
3485         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3486         pSMB->Reserved4 = 0;
3487         pSMB->hdr.smb_buf_length += byte_count;
3488         pSMB->ByteCount = cpu_to_le16(byte_count);
3489
3490         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3491                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3492         if (rc) {
3493                 cFYI(1, ("Send error in QPathInfo = %d", rc));
3494         } else {                /* decode response */
3495                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3496
3497                 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3498                         cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3499                                    "Unix Extensions can be disabled on mount "
3500                                    "by specifying the nosfu mount option."));
3501                         rc = -EIO;      /* bad smb */
3502                 } else {
3503                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3504                         memcpy((char *) pFindData,
3505                                (char *) &pSMBr->hdr.Protocol +
3506                                data_offset,
3507                                sizeof(FILE_UNIX_BASIC_INFO));
3508                 }
3509         }
3510         cifs_buf_release(pSMB);
3511         if (rc == -EAGAIN)
3512                 goto UnixQPathInfoRetry;
3513
3514         return rc;
3515 }
3516
3517 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3518 int
3519 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3520               const char *searchName,
3521               const struct nls_table *nls_codepage,
3522               __u16 *pnetfid,
3523               struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3524 {
3525 /* level 257 SMB_ */
3526         TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3527         TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3528         T2_FFIRST_RSP_PARMS *parms;
3529         int rc = 0;
3530         int bytes_returned = 0;
3531         int name_len;
3532         __u16 params, byte_count;
3533
3534         cFYI(1, ("In FindFirst for %s", searchName));
3535
3536 findFirstRetry:
3537         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3538                       (void **) &pSMBr);
3539         if (rc)
3540                 return rc;
3541
3542         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3543                 name_len =
3544                     cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3545                                  PATH_MAX, nls_codepage, remap);
3546                 /* We can not add the asterik earlier in case
3547                 it got remapped to 0xF03A as if it were part of the
3548                 directory name instead of a wildcard */
3549                 name_len *= 2;
3550                 pSMB->FileName[name_len] = dirsep;
3551                 pSMB->FileName[name_len+1] = 0;
3552                 pSMB->FileName[name_len+2] = '*';
3553                 pSMB->FileName[name_len+3] = 0;
3554                 name_len += 4; /* now the trailing null */
3555                 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3556                 pSMB->FileName[name_len+1] = 0;
3557                 name_len += 2;
3558         } else {        /* BB add check for overrun of SMB buf BB */
3559                 name_len = strnlen(searchName, PATH_MAX);
3560 /* BB fix here and in unicode clause above ie
3561                 if (name_len > buffersize-header)
3562                         free buffer exit; BB */
3563                 strncpy(pSMB->FileName, searchName, name_len);
3564                 pSMB->FileName[name_len] = dirsep;
3565                 pSMB->FileName[name_len+1] = '*';
3566                 pSMB->FileName[name_len+2] = 0;
3567                 name_len += 3;
3568         }
3569
3570         params = 12 + name_len /* includes null */ ;
3571         pSMB->TotalDataCount = 0;       /* no EAs */
3572         pSMB->MaxParameterCount = cpu_to_le16(10);
3573         pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3574                                           MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3575         pSMB->MaxSetupCount = 0;
3576         pSMB->Reserved = 0;
3577         pSMB->Flags = 0;
3578         pSMB->Timeout = 0;
3579         pSMB->Reserved2 = 0;
3580         byte_count = params + 1 /* pad */ ;
3581         pSMB->TotalParameterCount = cpu_to_le16(params);
3582         pSMB->ParameterCount = pSMB->TotalParameterCount;
3583         pSMB->ParameterOffset = cpu_to_le16(
3584               offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3585                 - 4);
3586         pSMB->DataCount = 0;
3587         pSMB->DataOffset = 0;
3588         pSMB->SetupCount = 1;   /* one byte, no need to make endian neutral */
3589         pSMB->Reserved3 = 0;
3590         pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3591         pSMB->SearchAttributes =
3592             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3593                         ATTR_DIRECTORY);
3594         pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3595         pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3596                 CIFS_SEARCH_RETURN_RESUME);
3597         pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3598
3599         /* BB what should we set StorageType to? Does it matter? BB */
3600         pSMB->SearchStorageType = 0;
3601         pSMB->hdr.smb_buf_length += byte_count;
3602         pSMB->ByteCount = cpu_to_le16(byte_count);
3603
3604         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3605                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3606         cifs_stats_inc(&tcon->num_ffirst);
3607
3608         if (rc) {/* BB add logic to retry regular search if Unix search
3609                         rejected unexpectedly by server */
3610                 /* BB Add code to handle unsupported level rc */
3611                 cFYI(1, ("Error in FindFirst = %d", rc));
3612
3613                 cifs_buf_release(pSMB);
3614
3615                 /* BB eventually could optimize out free and realloc of buf */
3616                 /*    for this case */
3617                 if (rc == -EAGAIN)
3618                         goto findFirstRetry;
3619         } else { /* decode response */
3620                 /* BB remember to free buffer if error BB */
3621                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3622                 if (rc == 0) {
3623                         unsigned int lnoff;
3624
3625                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3626                                 psrch_inf->unicode = true;
3627                         else
3628                                 psrch_inf->unicode = false;
3629
3630                         psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3631                         psrch_inf->smallBuf = 0;
3632                         psrch_inf->srch_entries_start =
3633                                 (char *) &pSMBr->hdr.Protocol +
3634                                         le16_to_cpu(pSMBr->t2.DataOffset);
3635                         parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3636                                le16_to_cpu(pSMBr->t2.ParameterOffset));
3637
3638                         if (parms->EndofSearch)
3639                                 psrch_inf->endOfSearch = true;
3640                         else
3641                                 psrch_inf->endOfSearch = false;
3642
3643                         psrch_inf->entries_in_buffer =
3644                                         le16_to_cpu(parms->SearchCount);
3645                         psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3646                                 psrch_inf->entries_in_buffer;
3647                         lnoff = le16_to_cpu(parms->LastNameOffset);
3648                         if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3649                               lnoff) {
3650                                 cERROR(1, ("ignoring corrupt resume name"));
3651                                 psrch_inf->last_entry = NULL;
3652                                 return rc;
3653                         }
3654
3655                         psrch_inf->last_entry = psrch_inf->srch_entries_start +
3656                                                         lnoff;
3657
3658                         *pnetfid = parms->SearchHandle;
3659                 } else {
3660                         cifs_buf_release(pSMB);
3661                 }
3662         }
3663
3664         return rc;
3665 }
3666
3667 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3668                  __u16 searchHandle, struct cifs_search_info *psrch_inf)
3669 {
3670         TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3671         TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3672         T2_FNEXT_RSP_PARMS *parms;
3673         char *response_data;
3674         int rc = 0;
3675         int bytes_returned, name_len;
3676         __u16 params, byte_count;
3677
3678         cFYI(1, ("In FindNext"));
3679
3680         if (psrch_inf->endOfSearch)
3681                 return -ENOENT;
3682
3683         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3684                 (void **) &pSMBr);
3685         if (rc)
3686                 return rc;
3687
3688         params = 14; /* includes 2 bytes of null string, converted to LE below*/
3689         byte_count = 0;
3690         pSMB->TotalDataCount = 0;       /* no EAs */
3691         pSMB->MaxParameterCount = cpu_to_le16(8);
3692         pSMB->MaxDataCount =
3693                 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
3694                                 0xFFFFFF00);
3695         pSMB->MaxSetupCount = 0;
3696         pSMB->Reserved = 0;
3697         pSMB->Flags = 0;
3698         pSMB->Timeout = 0;
3699         pSMB->Reserved2 = 0;
3700         pSMB->ParameterOffset =  cpu_to_le16(
3701               offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3702         pSMB->DataCount = 0;
3703         pSMB->DataOffset = 0;
3704         pSMB->SetupCount = 1;
3705         pSMB->Reserved3 = 0;
3706         pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3707         pSMB->SearchHandle = searchHandle;      /* always kept as le */
3708         pSMB->SearchCount =
3709                 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
3710         pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3711         pSMB->ResumeKey = psrch_inf->resume_key;
3712         pSMB->SearchFlags =
3713               cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3714
3715         name_len = psrch_inf->resume_name_len;
3716         params += name_len;
3717         if (name_len < PATH_MAX) {
3718                 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3719                 byte_count += name_len;
3720                 /* 14 byte parm len above enough for 2 byte null terminator */
3721                 pSMB->ResumeFileName[name_len] = 0;
3722                 pSMB->ResumeFileName[name_len+1] = 0;
3723         } else {
3724                 rc = -EINVAL;
3725                 goto FNext2_err_exit;
3726         }
3727         byte_count = params + 1 /* pad */ ;
3728         pSMB->TotalParameterCount = cpu_to_le16(params);
3729         pSMB->ParameterCount = pSMB->TotalParameterCount;
3730         pSMB->hdr.smb_buf_length += byte_count;
3731         pSMB->ByteCount = cpu_to_le16(byte_count);
3732
3733         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3734                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3735         cifs_stats_inc(&tcon->num_fnext);
3736         if (rc) {
3737                 if (rc == -EBADF) {
3738                         psrch_inf->endOfSearch = true;
3739                         cifs_buf_release(pSMB);
3740                         rc = 0; /* search probably was closed at end of search*/
3741                 } else
3742                         cFYI(1, ("FindNext returned = %d", rc));
3743         } else {                /* decode response */
3744                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3745
3746                 if (rc == 0) {
3747                         unsigned int lnoff;
3748
3749                         /* BB fixme add lock for file (srch_info) struct here */
3750                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3751                                 psrch_inf->unicode = true;
3752                         else
3753                                 psrch_inf->unicode = false;
3754                         response_data = (char *) &pSMBr->hdr.Protocol +
3755                                le16_to_cpu(pSMBr->t2.ParameterOffset);
3756                         parms = (T2_FNEXT_RSP_PARMS *)response_data;
3757                         response_data = (char *)&pSMBr->hdr.Protocol +
3758                                 le16_to_cpu(pSMBr->t2.DataOffset);
3759                         if (psrch_inf->smallBuf)
3760                                 cifs_small_buf_release(
3761                                         psrch_inf->ntwrk_buf_start);
3762                         else
3763                                 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3764                         psrch_inf->srch_entries_start = response_data;
3765                         psrch_inf->ntwrk_buf_start = (char *)pSMB;
3766                         psrch_inf->smallBuf = 0;
3767                         if (parms->EndofSearch)
3768                                 psrch_inf->endOfSearch = true;
3769                         else
3770                                 psrch_inf->endOfSearch = false;
3771                         psrch_inf->entries_in_buffer =
3772                                                 le16_to_cpu(parms->SearchCount);
3773                         psrch_inf->index_of_last_entry +=
3774                                 psrch_inf->entries_in_buffer;
3775                         lnoff = le16_to_cpu(parms->LastNameOffset);
3776                         if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3777                               lnoff) {
3778                                 cERROR(1, ("ignoring corrupt resume name"));
3779                                 psrch_inf->last_entry = NULL;
3780                                 return rc;
3781                         } else
3782                                 psrch_inf->last_entry =
3783                                         psrch_inf->srch_entries_start + lnoff;
3784
3785 /*  cFYI(1,("fnxt2 entries in buf %d index_of_last %d",
3786             psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */
3787
3788                         /* BB fixme add unlock here */
3789                 }
3790
3791         }
3792
3793         /* BB On error, should we leave previous search buf (and count and
3794         last entry fields) intact or free the previous one? */
3795
3796         /* Note: On -EAGAIN error only caller can retry on handle based calls
3797         since file handle passed in no longer valid */
3798 FNext2_err_exit:
3799         if (rc != 0)
3800                 cifs_buf_release(pSMB);
3801         return rc;
3802 }
3803
3804 int
3805 CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
3806               const __u16 searchHandle)
3807 {
3808         int rc = 0;
3809         FINDCLOSE_REQ *pSMB = NULL;
3810
3811         cFYI(1, ("In CIFSSMBFindClose"));
3812         rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3813
3814         /* no sense returning error if session restarted
3815                 as file handle has been closed */
3816         if (rc == -EAGAIN)
3817                 return 0;
3818         if (rc)
3819                 return rc;
3820
3821         pSMB->FileID = searchHandle;
3822         pSMB->ByteCount = 0;
3823         rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
3824         if (rc)
3825                 cERROR(1, ("Send error in FindClose = %d", rc));
3826
3827         cifs_stats_inc(&tcon->num_fclose);
3828
3829         /* Since session is dead, search handle closed on server already */
3830         if (rc == -EAGAIN)
3831                 rc = 0;
3832
3833         return rc;
3834 }
3835
3836 int
3837 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3838                       const unsigned char *searchName,
3839                       __u64 *inode_number,
3840                       const struct nls_table *nls_codepage, int remap)
3841 {
3842         int rc = 0;
3843         TRANSACTION2_QPI_REQ *pSMB = NULL;
3844         TRANSACTION2_QPI_RSP *pSMBr = NULL;
3845         int name_len, bytes_returned;
3846         __u16 params, byte_count;
3847
3848         cFYI(1, ("In GetSrvInodeNum for %s", searchName));
3849         if (tcon == NULL)
3850                 return -ENODEV;
3851
3852 GetInodeNumberRetry:
3853         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3854                       (void **) &pSMBr);
3855         if (rc)
3856                 return rc;
3857
3858         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3859                 name_len =
3860                         cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3861                                          PATH_MAX, nls_codepage, remap);
3862                 name_len++;     /* trailing null */
3863                 name_len *= 2;
3864         } else {        /* BB improve the check for buffer overruns BB */
3865                 name_len = strnlen(searchName, PATH_MAX);
3866                 name_len++;     /* trailing null */
3867                 strncpy(pSMB->FileName, searchName, name_len);
3868         }
3869
3870         params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
3871         pSMB->TotalDataCount = 0;
3872         pSMB->MaxParameterCount = cpu_to_le16(2);
3873         /* BB find exact max data count below from sess structure BB */
3874         pSMB->MaxDataCount = cpu_to_le16(4000);
3875         pSMB->MaxSetupCount = 0;
3876         pSMB->Reserved = 0;
3877         pSMB->Flags = 0;
3878         pSMB->Timeout = 0;
3879         pSMB->Reserved2 = 0;
3880         pSMB->ParameterOffset = cpu_to_le16(offsetof(
3881                 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3882         pSMB->DataCount = 0;
3883         pSMB->DataOffset = 0;
3884         pSMB->SetupCount = 1;
3885         pSMB->Reserved3 = 0;
3886         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3887         byte_count = params + 1 /* pad */ ;
3888         pSMB->TotalParameterCount = cpu_to_le16(params);
3889         pSMB->ParameterCount = pSMB->TotalParameterCount;
3890         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3891         pSMB->Reserved4 = 0;
3892         pSMB->hdr.smb_buf_length += byte_count;
3893         pSMB->ByteCount = cpu_to_le16(byte_count);
3894
3895         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3896                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3897         if (rc) {
3898                 cFYI(1, ("error %d in QueryInternalInfo", rc));
3899         } else {
3900                 /* decode response */
3901                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3902                 if (rc || (pSMBr->ByteCount < 2))
3903                 /* BB also check enough total bytes returned */
3904                         /* If rc should we check for EOPNOSUPP and
3905                         disable the srvino flag? or in caller? */
3906                         rc = -EIO;      /* bad smb */
3907                 else {
3908                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3909                         __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3910                         struct file_internal_info *pfinfo;
3911                         /* BB Do we need a cast or hash here ? */
3912                         if (count < 8) {
3913                                 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3914                                 rc = -EIO;
3915                                 goto GetInodeNumOut;
3916                         }
3917                         pfinfo = (struct file_internal_info *)
3918                                 (data_offset + (char *) &pSMBr->hdr.Protocol);
3919                         *inode_number = pfinfo->UniqueId;
3920                 }
3921         }
3922 GetInodeNumOut:
3923         cifs_buf_release(pSMB);
3924         if (rc == -EAGAIN)
3925                 goto GetInodeNumberRetry;
3926         return rc;
3927 }
3928
3929 /* computes length of UCS string converted to host codepage
3930  * @src:        UCS string
3931  * @maxlen:     length of the input string in UCS characters
3932  *              (not in bytes)
3933  *
3934  * return:      size of input string in host codepage
3935  */
3936 static int hostlen_fromUCS(const __le16 *src, const int maxlen,
3937                 const struct nls_table *nls_codepage) {
3938         int i;
3939         int hostlen = 0;
3940         char to[4];
3941         int charlen;
3942         for (i = 0; (i < maxlen) && src[i]; ++i) {
3943                 charlen = nls_codepage->uni2char(le16_to_cpu(src[i]),
3944                                 to, NLS_MAX_CHARSET_SIZE);
3945                 hostlen += charlen > 0 ? charlen : 1;
3946         }
3947         return hostlen;
3948 }
3949
3950 /* parses DFS refferal V3 structure
3951  * caller is responsible for freeing target_nodes
3952  * returns:
3953  *      on success - 0
3954  *      on failure - errno
3955  */
3956 static int
3957 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
3958                 unsigned int *num_of_nodes,
3959                 struct dfs_info3_param **target_nodes,
3960                 const struct nls_table *nls_codepage, int remap,
3961                 const char *searchName)
3962 {
3963         int i, rc = 0;
3964         char *data_end;
3965         bool is_unicode;
3966         struct dfs_referral_level_3 *ref;
3967
3968         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3969                 is_unicode = true;
3970         else
3971                 is_unicode = false;
3972         *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
3973
3974         if (*num_of_nodes < 1) {
3975                 cERROR(1, ("num_referrals: must be at least > 0,"
3976                         "but we get num_referrals = %d\n", *num_of_nodes));
3977                 rc = -EINVAL;
3978                 goto parse_DFS_referrals_exit;
3979         }
3980
3981         ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
3982         if (ref->VersionNumber != cpu_to_le16(3)) {
3983                 cERROR(1, ("Referrals of V%d version are not supported,"
3984                         "should be V3", le16_to_cpu(ref->VersionNumber)));
3985                 rc = -EINVAL;
3986                 goto parse_DFS_referrals_exit;
3987         }
3988
3989         /* get the upper boundary of the resp buffer */
3990         data_end = (char *)(&(pSMBr->PathConsumed)) +
3991                                 le16_to_cpu(pSMBr->t2.DataCount);
3992
3993         cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n",
3994                         *num_of_nodes,
3995                         le16_to_cpu(pSMBr->DFSFlags)));
3996
3997         *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
3998                         *num_of_nodes, GFP_KERNEL);
3999         if (*target_nodes == NULL) {
4000                 cERROR(1, ("Failed to allocate buffer for target_nodes\n"));
4001                 rc = -ENOMEM;
4002                 goto parse_DFS_referrals_exit;
4003         }
4004
4005         /* collect neccessary data from referrals */
4006         for (i = 0; i < *num_of_nodes; i++) {
4007                 char *temp;
4008                 int max_len;
4009                 struct dfs_info3_param *node = (*target_nodes)+i;
4010
4011                 node->flags = le16_to_cpu(pSMBr->DFSFlags);
4012                 if (is_unicode) {
4013                         __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
4014                                                 GFP_KERNEL);
4015                         cifsConvertToUCS((__le16 *) tmp, searchName,
4016                                         PATH_MAX, nls_codepage, remap);
4017                         node->path_consumed = hostlen_fromUCS(tmp,
4018                                         le16_to_cpu(pSMBr->PathConsumed)/2,
4019                                         nls_codepage);
4020                         kfree(tmp);
4021                 } else
4022                         node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
4023
4024                 node->server_type = le16_to_cpu(ref->ServerType);
4025                 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
4026
4027                 /* copy DfsPath */
4028                 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
4029                 max_len = data_end - temp;
4030                 rc = cifs_strncpy_to_host(&(node->path_name), temp,
4031                                         max_len, is_unicode, nls_codepage);
4032                 if (rc)
4033                         goto parse_DFS_referrals_exit;
4034
4035                 /* copy link target UNC */
4036                 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
4037                 max_len = data_end - temp;
4038                 rc = cifs_strncpy_to_host(&(node->node_name), temp,
4039                                         max_len, is_unicode, nls_codepage);
4040                 if (rc)
4041                         goto parse_DFS_referrals_exit;
4042
4043                 ref += le16_to_cpu(ref->Size);
4044         }
4045
4046 parse_DFS_referrals_exit:
4047         if (rc) {
4048                 free_dfs_info_array(*target_nodes, *num_of_nodes);
4049                 *target_nodes = NULL;
4050                 *num_of_nodes = 0;
4051         }
4052         return rc;
4053 }
4054
4055 int
4056 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
4057                 const unsigned char *searchName,
4058                 struct dfs_info3_param **target_nodes,
4059                 unsigned int *num_of_nodes,
4060                 const struct nls_table *nls_codepage, int remap)
4061 {
4062 /* TRANS2_GET_DFS_REFERRAL */
4063         TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4064         TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4065         int rc = 0;
4066         int bytes_returned;
4067         int name_len;
4068         __u16 params, byte_count;
4069         *num_of_nodes = 0;
4070         *target_nodes = NULL;
4071
4072         cFYI(1, ("In GetDFSRefer the path %s", searchName));
4073         if (ses == NULL)
4074                 return -ENODEV;
4075 getDFSRetry:
4076         rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4077                       (void **) &pSMBr);
4078         if (rc)
4079                 return rc;
4080
4081         /* server pointer checked in called function,
4082         but should never be null here anyway */
4083         pSMB->hdr.Mid = GetNextMid(ses->server);
4084         pSMB->hdr.Tid = ses->ipc_tid;
4085         pSMB->hdr.Uid = ses->Suid;
4086         if (ses->capabilities & CAP_STATUS32)
4087                 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4088         if (ses->capabilities & CAP_DFS)
4089                 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4090
4091         if (ses->capabilities & CAP_UNICODE) {
4092                 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4093                 name_len =
4094                     cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
4095                                      searchName, PATH_MAX, nls_codepage, remap);
4096                 name_len++;     /* trailing null */
4097                 name_len *= 2;
4098         } else {        /* BB improve the check for buffer overruns BB */
4099                 name_len = strnlen(searchName, PATH_MAX);
4100                 name_len++;     /* trailing null */
4101                 strncpy(pSMB->RequestFileName, searchName, name_len);
4102         }
4103
4104         if (ses->server) {
4105                 if (ses->server->secMode &
4106                    (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4107                         pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4108         }
4109
4110         pSMB->hdr.Uid = ses->Suid;
4111
4112         params = 2 /* level */  + name_len /*includes null */ ;
4113         pSMB->TotalDataCount = 0;
4114         pSMB->DataCount = 0;
4115         pSMB->DataOffset = 0;
4116         pSMB->MaxParameterCount = 0;
4117         /* BB find exact max SMB PDU from sess structure BB */
4118         pSMB->MaxDataCount = cpu_to_le16(4000);
4119         pSMB->MaxSetupCount = 0;
4120         pSMB->Reserved = 0;
4121         pSMB->Flags = 0;
4122         pSMB->Timeout = 0;
4123         pSMB->Reserved2 = 0;
4124         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4125           struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4126         pSMB->SetupCount = 1;
4127         pSMB->Reserved3 = 0;
4128         pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4129         byte_count = params + 3 /* pad */ ;
4130         pSMB->ParameterCount = cpu_to_le16(params);
4131         pSMB->TotalParameterCount = pSMB->ParameterCount;
4132         pSMB->MaxReferralLevel = cpu_to_le16(3);
4133         pSMB->hdr.smb_buf_length += byte_count;
4134         pSMB->ByteCount = cpu_to_le16(byte_count);
4135
4136         rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4137                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4138         if (rc) {
4139                 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
4140                 goto GetDFSRefExit;
4141         }
4142         rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4143
4144         /* BB Also check if enough total bytes returned? */
4145         if (rc || (pSMBr->ByteCount < 17)) {
4146                 rc = -EIO;      /* bad smb */
4147                 goto GetDFSRefExit;
4148         }
4149
4150         cFYI(1, ("Decoding GetDFSRefer response BCC: %d  Offset %d",
4151                                 pSMBr->ByteCount,
4152                                 le16_to_cpu(pSMBr->t2.DataOffset)));
4153
4154         /* parse returned result into more usable form */
4155         rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4156                                  target_nodes, nls_codepage, remap,
4157                                  searchName);
4158
4159 GetDFSRefExit:
4160         cifs_buf_release(pSMB);
4161
4162         if (rc == -EAGAIN)
4163                 goto getDFSRetry;
4164
4165         return rc;
4166 }
4167
4168 /* Query File System Info such as free space to old servers such as Win 9x */
4169 int
4170 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4171 {
4172 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4173         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4174         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4175         FILE_SYSTEM_ALLOC_INFO *response_data;
4176         int rc = 0;
4177         int bytes_returned = 0;
4178         __u16 params, byte_count;
4179
4180         cFYI(1, ("OldQFSInfo"));
4181 oldQFSInfoRetry:
4182         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4183                 (void **) &pSMBr);
4184         if (rc)
4185                 return rc;
4186
4187         params = 2;     /* level */
4188         pSMB->TotalDataCount = 0;
4189         pSMB->MaxParameterCount = cpu_to_le16(2);
4190         pSMB->MaxDataCount = cpu_to_le16(1000);
4191         pSMB->MaxSetupCount = 0;
4192         pSMB->Reserved = 0;
4193         pSMB->Flags = 0;
4194         pSMB->Timeout = 0;
4195         pSMB->Reserved2 = 0;
4196         byte_count = params + 1 /* pad */ ;
4197         pSMB->TotalParameterCount = cpu_to_le16(params);
4198         pSMB->ParameterCount = pSMB->TotalParameterCount;
4199         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4200         struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4201         pSMB->DataCount = 0;
4202         pSMB->DataOffset = 0;
4203         pSMB->SetupCount = 1;
4204         pSMB->Reserved3 = 0;
4205         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4206         pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4207         pSMB->hdr.smb_buf_length += byte_count;
4208         pSMB->ByteCount = cpu_to_le16(byte_count);
4209
4210         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4211                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4212         if (rc) {
4213                 cFYI(1, ("Send error in QFSInfo = %d", rc));
4214         } else {                /* decode response */
4215                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4216
4217                 if (rc || (pSMBr->ByteCount < 18))
4218                         rc = -EIO;      /* bad smb */
4219                 else {
4220                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4221                         cFYI(1, ("qfsinf resp BCC: %d  Offset %d",
4222                                  pSMBr->ByteCount, data_offset));
4223
4224                         response_data = (FILE_SYSTEM_ALLOC_INFO *)
4225                                 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4226                         FSData->f_bsize =
4227                                 le16_to_cpu(response_data->BytesPerSector) *
4228                                 le32_to_cpu(response_data->
4229                                         SectorsPerAllocationUnit);
4230                         FSData->f_blocks =
4231                                le32_to_cpu(response_data->TotalAllocationUnits);
4232                         FSData->f_bfree = FSData->f_bavail =
4233                                 le32_to_cpu(response_data->FreeAllocationUnits);
4234                         cFYI(1,
4235                              ("Blocks: %lld  Free: %lld Block size %ld",
4236                               (unsigned long long)FSData->f_blocks,
4237                               (unsigned long long)FSData->f_bfree,
4238                               FSData->f_bsize));
4239                 }
4240         }
4241         cifs_buf_release(pSMB);
4242
4243         if (rc == -EAGAIN)
4244                 goto oldQFSInfoRetry;
4245
4246         return rc;
4247 }
4248
4249 int
4250 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4251 {
4252 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4253         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4254         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4255         FILE_SYSTEM_INFO *response_data;
4256         int rc = 0;
4257         int bytes_returned = 0;
4258         __u16 params, byte_count;
4259
4260         cFYI(1, ("In QFSInfo"));
4261 QFSInfoRetry:
4262         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4263                       (void **) &pSMBr);
4264         if (rc)
4265                 return rc;
4266
4267         params = 2;     /* level */
4268         pSMB->TotalDataCount = 0;
4269         pSMB->MaxParameterCount = cpu_to_le16(2);
4270         pSMB->MaxDataCount = cpu_to_le16(1000);
4271         pSMB->MaxSetupCount = 0;
4272         pSMB->Reserved = 0;
4273         pSMB->Flags = 0;
4274         pSMB->Timeout = 0;
4275         pSMB->Reserved2 = 0;
4276         byte_count = params + 1 /* pad */ ;
4277         pSMB->TotalParameterCount = cpu_to_le16(params);
4278         pSMB->ParameterCount = pSMB->TotalParameterCount;
4279         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4280                 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4281         pSMB->DataCount = 0;
4282         pSMB->DataOffset = 0;
4283         pSMB->SetupCount = 1;
4284         pSMB->Reserved3 = 0;
4285         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4286         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4287         pSMB->hdr.smb_buf_length += byte_count;
4288         pSMB->ByteCount = cpu_to_le16(byte_count);
4289
4290         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4291                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4292         if (rc) {
4293                 cFYI(1, ("Send error in QFSInfo = %d", rc));
4294         } else {                /* decode response */
4295                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4296
4297                 if (rc || (pSMBr->ByteCount < 24))
4298                         rc = -EIO;      /* bad smb */
4299                 else {
4300                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4301
4302                         response_data =
4303                             (FILE_SYSTEM_INFO
4304                              *) (((char *) &pSMBr->hdr.Protocol) +
4305                                  data_offset);
4306                         FSData->f_bsize =
4307                             le32_to_cpu(response_data->BytesPerSector) *
4308                             le32_to_cpu(response_data->
4309                                         SectorsPerAllocationUnit);
4310                         FSData->f_blocks =
4311                             le64_to_cpu(response_data->TotalAllocationUnits);
4312                         FSData->f_bfree = FSData->f_bavail =
4313                             le64_to_cpu(response_data->FreeAllocationUnits);
4314                         cFYI(1,
4315                              ("Blocks: %lld  Free: %lld Block size %ld",
4316                               (unsigned long long)FSData->f_blocks,
4317                               (unsigned long long)FSData->f_bfree,
4318                               FSData->f_bsize));
4319                 }
4320         }
4321         cifs_buf_release(pSMB);
4322
4323         if (rc == -EAGAIN)
4324                 goto QFSInfoRetry;
4325
4326         return rc;
4327 }
4328
4329 int
4330 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4331 {
4332 /* level 0x105  SMB_QUERY_FILE_SYSTEM_INFO */
4333         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4334         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4335         FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4336         int rc = 0;
4337         int bytes_returned = 0;
4338         __u16 params, byte_count;
4339
4340         cFYI(1, ("In QFSAttributeInfo"));
4341 QFSAttributeRetry:
4342         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4343                       (void **) &pSMBr);
4344         if (rc)
4345                 return rc;
4346
4347         params = 2;     /* level */
4348         pSMB->TotalDataCount = 0;
4349         pSMB->MaxParameterCount = cpu_to_le16(2);
4350         /* BB find exact max SMB PDU from sess structure BB */
4351         pSMB->MaxDataCount = cpu_to_le16(1000);
4352         pSMB->MaxSetupCount = 0;
4353         pSMB->Reserved = 0;
4354         pSMB->Flags = 0;
4355         pSMB->Timeout = 0;
4356         pSMB->Reserved2 = 0;
4357         byte_count = params + 1 /* pad */ ;
4358         pSMB->TotalParameterCount = cpu_to_le16(params);
4359         pSMB->ParameterCount = pSMB->TotalParameterCount;
4360         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4361                 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4362         pSMB->DataCount = 0;
4363         pSMB->DataOffset = 0;
4364         pSMB->SetupCount = 1;
4365         pSMB->Reserved3 = 0;
4366         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4367         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4368         pSMB->hdr.smb_buf_length += byte_count;
4369         pSMB->ByteCount = cpu_to_le16(byte_count);
4370
4371         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4372                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4373         if (rc) {
4374                 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
4375         } else {                /* decode response */
4376                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4377
4378                 if (rc || (pSMBr->ByteCount < 13)) {
4379                         /* BB also check if enough bytes returned */
4380                         rc = -EIO;      /* bad smb */
4381                 } else {
4382                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4383                         response_data =
4384                             (FILE_SYSTEM_ATTRIBUTE_INFO
4385                              *) (((char *) &pSMBr->hdr.Protocol) +
4386                                  data_offset);
4387                         memcpy(&tcon->fsAttrInfo, response_data,
4388                                sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4389                 }
4390         }
4391         cifs_buf_release(pSMB);
4392
4393         if (rc == -EAGAIN)
4394                 goto QFSAttributeRetry;
4395
4396         return rc;
4397 }
4398
4399 int
4400 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4401 {
4402 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4403         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4404         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4405         FILE_SYSTEM_DEVICE_INFO *response_data;
4406         int rc = 0;
4407         int bytes_returned = 0;
4408         __u16 params, byte_count;
4409
4410         cFYI(1, ("In QFSDeviceInfo"));
4411 QFSDeviceRetry:
4412         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4413                       (void **) &pSMBr);
4414         if (rc)
4415                 return rc;
4416
4417         params = 2;     /* level */
4418         pSMB->TotalDataCount = 0;
4419         pSMB->MaxParameterCount = cpu_to_le16(2);
4420         /* BB find exact max SMB PDU from sess structure BB */
4421         pSMB->MaxDataCount = cpu_to_le16(1000);
4422         pSMB->MaxSetupCount = 0;
4423         pSMB->Reserved = 0;
4424         pSMB->Flags = 0;
4425         pSMB->Timeout = 0;
4426         pSMB->Reserved2 = 0;
4427         byte_count = params + 1 /* pad */ ;
4428         pSMB->TotalParameterCount = cpu_to_le16(params);
4429         pSMB->ParameterCount = pSMB->TotalParameterCount;
4430         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4431                 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4432
4433         pSMB->DataCount = 0;
4434         pSMB->DataOffset = 0;
4435         pSMB->SetupCount = 1;
4436         pSMB->Reserved3 = 0;
4437         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4438         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4439         pSMB->hdr.smb_buf_length += byte_count;
4440         pSMB->ByteCount = cpu_to_le16(byte_count);
4441
4442         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4443                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4444         if (rc) {
4445                 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
4446         } else {                /* decode response */
4447                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4448
4449                 if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO)))
4450                         rc = -EIO;      /* bad smb */
4451                 else {
4452                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4453                         response_data =
4454                             (FILE_SYSTEM_DEVICE_INFO *)
4455                                 (((char *) &pSMBr->hdr.Protocol) +
4456                                  data_offset);
4457                         memcpy(&tcon->fsDevInfo, response_data,
4458                                sizeof(FILE_SYSTEM_DEVICE_INFO));
4459                 }
4460         }
4461         cifs_buf_release(pSMB);
4462
4463         if (rc == -EAGAIN)
4464                 goto QFSDeviceRetry;
4465
4466         return rc;
4467 }
4468
4469 int
4470 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4471 {
4472 /* level 0x200  SMB_QUERY_CIFS_UNIX_INFO */
4473         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4474         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4475         FILE_SYSTEM_UNIX_INFO *response_data;
4476         int rc = 0;
4477         int bytes_returned = 0;
4478         __u16 params, byte_count;
4479
4480         cFYI(1, ("In QFSUnixInfo"));
4481 QFSUnixRetry:
4482         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4483                       (void **) &pSMBr);
4484         if (rc)
4485                 return rc;
4486
4487         params = 2;     /* level */
4488         pSMB->TotalDataCount = 0;
4489         pSMB->DataCount = 0;
4490         pSMB->DataOffset = 0;
4491         pSMB->MaxParameterCount = cpu_to_le16(2);
4492         /* BB find exact max SMB PDU from sess structure BB */
4493         pSMB->MaxDataCount = cpu_to_le16(100);
4494         pSMB->MaxSetupCount = 0;
4495         pSMB->Reserved = 0;
4496         pSMB->Flags = 0;
4497         pSMB->Timeout = 0;
4498         pSMB->Reserved2 = 0;
4499         byte_count = params + 1 /* pad */ ;
4500         pSMB->ParameterCount = cpu_to_le16(params);
4501         pSMB->TotalParameterCount = pSMB->ParameterCount;
4502         pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4503                         smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4504         pSMB->SetupCount = 1;
4505         pSMB->Reserved3 = 0;
4506         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4507         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4508         pSMB->hdr.smb_buf_length += byte_count;
4509         pSMB->ByteCount = cpu_to_le16(byte_count);
4510
4511         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4512                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4513         if (rc) {
4514                 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
4515         } else {                /* decode response */
4516                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4517
4518                 if (rc || (pSMBr->ByteCount < 13)) {
4519                         rc = -EIO;      /* bad smb */
4520                 } else {
4521                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4522                         response_data =
4523                             (FILE_SYSTEM_UNIX_INFO
4524                              *) (((char *) &pSMBr->hdr.Protocol) +
4525                                  data_offset);
4526                         memcpy(&tcon->fsUnixInfo, response_data,
4527                                sizeof(FILE_SYSTEM_UNIX_INFO));
4528                 }
4529         }
4530         cifs_buf_release(pSMB);
4531
4532         if (rc == -EAGAIN)
4533                 goto QFSUnixRetry;
4534
4535
4536         return rc;
4537 }
4538
4539 int
4540 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4541 {
4542 /* level 0x200  SMB_SET_CIFS_UNIX_INFO */
4543         TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4544         TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4545         int rc = 0;
4546         int bytes_returned = 0;
4547         __u16 params, param_offset, offset, byte_count;
4548
4549         cFYI(1, ("In SETFSUnixInfo"));
4550 SETFSUnixRetry:
4551         /* BB switch to small buf init to save memory */
4552         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4553                       (void **) &pSMBr);
4554         if (rc)
4555                 return rc;
4556
4557         params = 4;     /* 2 bytes zero followed by info level. */
4558         pSMB->MaxSetupCount = 0;
4559         pSMB->Reserved = 0;
4560         pSMB->Flags = 0;
4561         pSMB->Timeout = 0;
4562         pSMB->Reserved2 = 0;
4563         param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4564                                 - 4;
4565         offset = param_offset + params;
4566
4567         pSMB->MaxParameterCount = cpu_to_le16(4);
4568         /* BB find exact max SMB PDU from sess structure BB */
4569         pSMB->MaxDataCount = cpu_to_le16(100);
4570         pSMB->SetupCount = 1;
4571         pSMB->Reserved3 = 0;
4572         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4573         byte_count = 1 /* pad */ + params + 12;
4574
4575         pSMB->DataCount = cpu_to_le16(12);
4576         pSMB->ParameterCount = cpu_to_le16(params);
4577         pSMB->TotalDataCount = pSMB->DataCount;
4578         pSMB->TotalParameterCount = pSMB->ParameterCount;
4579         pSMB->ParameterOffset = cpu_to_le16(param_offset);
4580         pSMB->DataOffset = cpu_to_le16(offset);
4581
4582         /* Params. */
4583         pSMB->FileNum = 0;
4584         pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4585
4586         /* Data. */
4587         pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4588         pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4589         pSMB->ClientUnixCap = cpu_to_le64(cap);
4590
4591         pSMB->hdr.smb_buf_length += byte_count;
4592         pSMB->ByteCount = cpu_to_le16(byte_count);
4593
4594         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4595                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4596         if (rc) {
4597                 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4598         } else {                /* decode response */
4599                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4600                 if (rc)
4601                         rc = -EIO;      /* bad smb */
4602         }
4603         cifs_buf_release(pSMB);
4604
4605         if (rc == -EAGAIN)
4606                 goto SETFSUnixRetry;
4607
4608         return rc;
4609 }
4610
4611
4612
4613 int
4614 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4615                    struct kstatfs *FSData)
4616 {
4617 /* level 0x201  SMB_QUERY_CIFS_POSIX_INFO */
4618         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4619         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4620         FILE_SYSTEM_POSIX_INFO *response_data;
4621         int rc = 0;
4622         int bytes_returned = 0;
4623         __u16 params, byte_count;
4624
4625         cFYI(1, ("In QFSPosixInfo"));
4626 QFSPosixRetry:
4627         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4628                       (void **) &pSMBr);
4629         if (rc)
4630                 return rc;
4631
4632         params = 2;     /* level */
4633         pSMB->TotalDataCount = 0;
4634         pSMB->DataCount = 0;
4635         pSMB->DataOffset = 0;
4636         pSMB->MaxParameterCount = cpu_to_le16(2);
4637         /* BB find exact max SMB PDU from sess structure BB */
4638         pSMB->MaxDataCount = cpu_to_le16(100);
4639         pSMB->MaxSetupCount = 0;
4640         pSMB->Reserved = 0;
4641         pSMB->Flags = 0;
4642         pSMB->Timeout = 0;
4643         pSMB->Reserved2 = 0;
4644         byte_count = params + 1 /* pad */ ;
4645         pSMB->ParameterCount = cpu_to_le16(params);
4646         pSMB->TotalParameterCount = pSMB->ParameterCount;
4647         pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4648                         smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4649         pSMB->SetupCount = 1;
4650         pSMB->Reserved3 = 0;
4651         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4652         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4653         pSMB->hdr.smb_buf_length += byte_count;
4654         pSMB->ByteCount = cpu_to_le16(byte_count);
4655
4656         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4657                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4658         if (rc) {
4659                 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4660         } else {                /* decode response */
4661                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4662
4663                 if (rc || (pSMBr->ByteCount < 13)) {
4664                         rc = -EIO;      /* bad smb */
4665                 } else {
4666                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4667                         response_data =
4668                             (FILE_SYSTEM_POSIX_INFO
4669                              *) (((char *) &pSMBr->hdr.Protocol) +
4670                                  data_offset);
4671                         FSData->f_bsize =
4672                                         le32_to_cpu(response_data->BlockSize);
4673                         FSData->f_blocks =
4674                                         le64_to_cpu(response_data->TotalBlocks);
4675                         FSData->f_bfree =
4676                             le64_to_cpu(response_data->BlocksAvail);
4677                         if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4678                                 FSData->f_bavail = FSData->f_bfree;
4679                         } else {
4680                                 FSData->f_bavail =
4681                                     le64_to_cpu(response_data->UserBlocksAvail);
4682                         }
4683                         if (response_data->TotalFileNodes != cpu_to_le64(-1))
4684                                 FSData->f_files =
4685                                      le64_to_cpu(response_data->TotalFileNodes);
4686                         if (response_data->FreeFileNodes != cpu_to_le64(-1))
4687                                 FSData->f_ffree =
4688                                       le64_to_cpu(response_data->FreeFileNodes);
4689                 }
4690         }
4691         cifs_buf_release(pSMB);
4692
4693         if (rc == -EAGAIN)
4694                 goto QFSPosixRetry;
4695
4696         return rc;
4697 }
4698
4699
4700 /* We can not use write of zero bytes trick to
4701    set file size due to need for large file support.  Also note that
4702    this SetPathInfo is preferred to SetFileInfo based method in next
4703    routine which is only needed to work around a sharing violation bug
4704    in Samba which this routine can run into */
4705
4706 int
4707 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4708               __u64 size, bool SetAllocation,
4709               const struct nls_table *nls_codepage, int remap)
4710 {
4711         struct smb_com_transaction2_spi_req *pSMB = NULL;
4712         struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4713         struct file_end_of_file_info *parm_data;
4714         int name_len;
4715         int rc = 0;
4716         int bytes_returned = 0;
4717         __u16 params, byte_count, data_count, param_offset, offset;
4718
4719         cFYI(1, ("In SetEOF"));
4720 SetEOFRetry:
4721         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4722                       (void **) &pSMBr);
4723         if (rc)
4724                 return rc;
4725
4726         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4727                 name_len =
4728                     cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4729                                      PATH_MAX, nls_codepage, remap);
4730                 name_len++;     /* trailing null */
4731                 name_len *= 2;
4732         } else {        /* BB improve the check for buffer overruns BB */
4733                 name_len = strnlen(fileName, PATH_MAX);
4734                 name_len++;     /* trailing null */
4735                 strncpy(pSMB->FileName, fileName, name_len);
4736         }
4737         params = 6 + name_len;
4738         data_count = sizeof(struct file_end_of_file_info);
4739         pSMB->MaxParameterCount = cpu_to_le16(2);
4740         pSMB->MaxDataCount = cpu_to_le16(4100);
4741         pSMB->MaxSetupCount = 0;
4742         pSMB->Reserved = 0;
4743         pSMB->Flags = 0;
4744         pSMB->Timeout = 0;
4745         pSMB->Reserved2 = 0;
4746         param_offset = offsetof(struct smb_com_transaction2_spi_req,
4747                                 InformationLevel) - 4;
4748         offset = param_offset + params;
4749         if (SetAllocation) {
4750                 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4751                         pSMB->InformationLevel =
4752                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4753                 else
4754                         pSMB->InformationLevel =
4755                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4756         } else /* Set File Size */  {
4757             if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4758                     pSMB->InformationLevel =
4759                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4760             else
4761                     pSMB->InformationLevel =
4762                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4763         }
4764
4765         parm_data =
4766             (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4767                                        offset);
4768         pSMB->ParameterOffset = cpu_to_le16(param_offset);
4769         pSMB->DataOffset = cpu_to_le16(offset);
4770         pSMB->SetupCount = 1;
4771         pSMB->Reserved3 = 0;
4772         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4773         byte_count = 3 /* pad */  + params + data_count;
4774         pSMB->DataCount = cpu_to_le16(data_count);
4775         pSMB->TotalDataCount = pSMB->DataCount;
4776         pSMB->ParameterCount = cpu_to_le16(params);
4777         pSMB->TotalParameterCount = pSMB->ParameterCount;
4778         pSMB->Reserved4 = 0;
4779         pSMB->hdr.smb_buf_length += byte_count;
4780         parm_data->FileSize = cpu_to_le64(size);
4781         pSMB->ByteCount = cpu_to_le16(byte_count);
4782         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4783                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4784         if (rc)
4785                 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4786
4787         cifs_buf_release(pSMB);
4788
4789         if (rc == -EAGAIN)
4790                 goto SetEOFRetry;
4791
4792         return rc;
4793 }
4794
4795 int
4796 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4797                    __u16 fid, __u32 pid_of_opener, bool SetAllocation)
4798 {
4799         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
4800         char *data_offset;
4801         struct file_end_of_file_info *parm_data;
4802         int rc = 0;
4803         __u16 params, param_offset, offset, byte_count, count;
4804
4805         cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4806                         (long long)size));
4807         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4808
4809         if (rc)
4810                 return rc;
4811
4812         pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4813         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4814
4815         params = 6;
4816         pSMB->MaxSetupCount = 0;
4817         pSMB->Reserved = 0;
4818         pSMB->Flags = 0;
4819         pSMB->Timeout = 0;
4820         pSMB->Reserved2 = 0;
4821         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4822         offset = param_offset + params;
4823
4824         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4825
4826         count = sizeof(struct file_end_of_file_info);
4827         pSMB->MaxParameterCount = cpu_to_le16(2);
4828         /* BB find exact max SMB PDU from sess structure BB */
4829         pSMB->MaxDataCount = cpu_to_le16(1000);
4830         pSMB->SetupCount = 1;
4831         pSMB->Reserved3 = 0;
4832         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4833         byte_count = 3 /* pad */  + params + count;
4834         pSMB->DataCount = cpu_to_le16(count);
4835         pSMB->ParameterCount = cpu_to_le16(params);
4836         pSMB->TotalDataCount = pSMB->DataCount;
4837         pSMB->TotalParameterCount = pSMB->ParameterCount;
4838         pSMB->ParameterOffset = cpu_to_le16(param_offset);
4839         parm_data =
4840                 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
4841                                 + offset);
4842         pSMB->DataOffset = cpu_to_le16(offset);
4843         parm_data->FileSize = cpu_to_le64(size);
4844         pSMB->Fid = fid;
4845         if (SetAllocation) {
4846                 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4847                         pSMB->InformationLevel =
4848                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4849                 else
4850                         pSMB->InformationLevel =
4851                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4852         } else /* Set File Size */  {
4853             if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4854                     pSMB->InformationLevel =
4855                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4856             else
4857                     pSMB->InformationLevel =
4858                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4859         }
4860         pSMB->Reserved4 = 0;
4861         pSMB->hdr.smb_buf_length += byte_count;
4862         pSMB->ByteCount = cpu_to_le16(byte_count);
4863         rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4864         if (rc) {
4865                 cFYI(1,
4866                      ("Send error in SetFileInfo (SetFileSize) = %d",
4867                       rc));
4868         }
4869
4870         /* Note: On -EAGAIN error only caller can retry on handle based calls
4871                 since file handle passed in no longer valid */
4872
4873         return rc;
4874 }
4875
4876 /* Some legacy servers such as NT4 require that the file times be set on
4877    an open handle, rather than by pathname - this is awkward due to
4878    potential access conflicts on the open, but it is unavoidable for these
4879    old servers since the only other choice is to go from 100 nanosecond DCE
4880    time and resort to the original setpathinfo level which takes the ancient
4881    DOS time format with 2 second granularity */
4882 int
4883 CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon,
4884                     const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
4885 {
4886         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
4887         char *data_offset;
4888         int rc = 0;
4889         __u16 params, param_offset, offset, byte_count, count;
4890
4891         cFYI(1, ("Set Times (via SetFileInfo)"));
4892         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4893
4894         if (rc)
4895                 return rc;
4896
4897         pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4898         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4899
4900         params = 6;
4901         pSMB->MaxSetupCount = 0;
4902         pSMB->Reserved = 0;
4903         pSMB->Flags = 0;
4904         pSMB->Timeout = 0;
4905         pSMB->Reserved2 = 0;
4906         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4907         offset = param_offset + params;
4908
4909         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4910
4911         count = sizeof(FILE_BASIC_INFO);
4912         pSMB->MaxParameterCount = cpu_to_le16(2);
4913         /* BB find max SMB PDU from sess */
4914         pSMB->MaxDataCount = cpu_to_le16(1000);
4915         pSMB->SetupCount = 1;
4916         pSMB->Reserved3 = 0;
4917         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4918         byte_count = 3 /* pad */  + params + count;
4919         pSMB->DataCount = cpu_to_le16(count);
4920         pSMB->ParameterCount = cpu_to_le16(params);
4921         pSMB->TotalDataCount = pSMB->DataCount;
4922         pSMB->TotalParameterCount = pSMB->ParameterCount;
4923         pSMB->ParameterOffset = cpu_to_le16(param_offset);
4924         pSMB->DataOffset = cpu_to_le16(offset);
4925         pSMB->Fid = fid;
4926         if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4927                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4928         else
4929                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4930         pSMB->Reserved4 = 0;
4931         pSMB->hdr.smb_buf_length += byte_count;
4932         pSMB->ByteCount = cpu_to_le16(byte_count);
4933         memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4934         rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4935         if (rc)
4936                 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc));
4937
4938         /* Note: On -EAGAIN error only caller can retry on handle based calls
4939                 since file handle passed in no longer valid */
4940
4941         return rc;
4942 }
4943
4944 int
4945 CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon,
4946                           bool delete_file, __u16 fid, __u32 pid_of_opener)
4947 {
4948         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
4949         char *data_offset;
4950         int rc = 0;
4951         __u16 params, param_offset, offset, byte_count, count;
4952
4953         cFYI(1, ("Set File Disposition (via SetFileInfo)"));
4954         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4955
4956         if (rc)
4957                 return rc;
4958
4959         pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4960         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4961
4962         params = 6;
4963         pSMB->MaxSetupCount = 0;
4964         pSMB->Reserved = 0;
4965         pSMB->Flags = 0;
4966         pSMB->Timeout = 0;
4967         pSMB->Reserved2 = 0;
4968         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4969         offset = param_offset + params;
4970
4971         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4972
4973         count = 1;
4974         pSMB->MaxParameterCount = cpu_to_le16(2);
4975         /* BB find max SMB PDU from sess */
4976         pSMB->MaxDataCount = cpu_to_le16(1000);
4977         pSMB->SetupCount = 1;
4978         pSMB->Reserved3 = 0;
4979         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4980         byte_count = 3 /* pad */  + params + count;
4981         pSMB->DataCount = cpu_to_le16(count);
4982         pSMB->ParameterCount = cpu_to_le16(params);
4983         pSMB->TotalDataCount = pSMB->DataCount;
4984         pSMB->TotalParameterCount = pSMB->ParameterCount;
4985         pSMB->ParameterOffset = cpu_to_le16(param_offset);
4986         pSMB->DataOffset = cpu_to_le16(offset);
4987         pSMB->Fid = fid;
4988         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
4989         pSMB->Reserved4 = 0;
4990         pSMB->hdr.smb_buf_length += byte_count;
4991         pSMB->ByteCount = cpu_to_le16(byte_count);
4992         *data_offset = delete_file ? 1 : 0;
4993         rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4994         if (rc)
4995                 cFYI(1, ("Send error in SetFileDisposition = %d", rc));
4996
4997         return rc;
4998 }
4999
5000 int
5001 CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon,
5002                    const char *fileName, const FILE_BASIC_INFO *data,
5003                    const struct nls_table *nls_codepage, int remap)
5004 {
5005         TRANSACTION2_SPI_REQ *pSMB = NULL;
5006         TRANSACTION2_SPI_RSP *pSMBr = NULL;
5007         int name_len;
5008         int rc = 0;
5009         int bytes_returned = 0;
5010         char *data_offset;
5011         __u16 params, param_offset, offset, byte_count, count;
5012
5013         cFYI(1, ("In SetTimes"));
5014
5015 SetTimesRetry:
5016         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5017                       (void **) &pSMBr);
5018         if (rc)
5019                 return rc;
5020
5021         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5022                 name_len =
5023                     cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5024                                      PATH_MAX, nls_codepage, remap);
5025                 name_len++;     /* trailing null */
5026                 name_len *= 2;
5027         } else {        /* BB improve the check for buffer overruns BB */
5028                 name_len = strnlen(fileName, PATH_MAX);
5029                 name_len++;     /* trailing null */
5030                 strncpy(pSMB->FileName, fileName, name_len);
5031         }
5032
5033         params = 6 + name_len;
5034         count = sizeof(FILE_BASIC_INFO);
5035         pSMB->MaxParameterCount = cpu_to_le16(2);
5036         /* BB find max SMB PDU from sess structure BB */
5037         pSMB->MaxDataCount = cpu_to_le16(1000);
5038         pSMB->MaxSetupCount = 0;
5039         pSMB->Reserved = 0;
5040         pSMB->Flags = 0;
5041         pSMB->Timeout = 0;
5042         pSMB->Reserved2 = 0;
5043         param_offset = offsetof(struct smb_com_transaction2_spi_req,
5044                                 InformationLevel) - 4;
5045         offset = param_offset + params;
5046         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5047         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5048         pSMB->DataOffset = cpu_to_le16(offset);
5049         pSMB->SetupCount = 1;
5050         pSMB->Reserved3 = 0;
5051         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5052         byte_count = 3 /* pad */  + params + count;
5053
5054         pSMB->DataCount = cpu_to_le16(count);
5055         pSMB->ParameterCount = cpu_to_le16(params);
5056         pSMB->TotalDataCount = pSMB->DataCount;
5057         pSMB->TotalParameterCount = pSMB->ParameterCount;
5058         if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5059                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5060         else
5061                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5062         pSMB->Reserved4 = 0;
5063         pSMB->hdr.smb_buf_length += byte_count;
5064         memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5065         pSMB->ByteCount = cpu_to_le16(byte_count);
5066         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5067                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5068         if (rc)
5069                 cFYI(1, ("SetPathInfo (times) returned %d", rc));
5070
5071         cifs_buf_release(pSMB);
5072
5073         if (rc == -EAGAIN)
5074                 goto SetTimesRetry;
5075
5076         return rc;
5077 }
5078
5079 /* Can not be used to set time stamps yet (due to old DOS time format) */
5080 /* Can be used to set attributes */
5081 #if 0  /* Possibly not needed - since it turns out that strangely NT4 has a bug
5082           handling it anyway and NT4 was what we thought it would be needed for
5083           Do not delete it until we prove whether needed for Win9x though */
5084 int
5085 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
5086                 __u16 dos_attrs, const struct nls_table *nls_codepage)
5087 {
5088         SETATTR_REQ *pSMB = NULL;
5089         SETATTR_RSP *pSMBr = NULL;
5090         int rc = 0;
5091         int bytes_returned;
5092         int name_len;
5093
5094         cFYI(1, ("In SetAttrLegacy"));
5095
5096 SetAttrLgcyRetry:
5097         rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5098                       (void **) &pSMBr);
5099         if (rc)
5100                 return rc;
5101
5102         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5103                 name_len =
5104                         ConvertToUCS((__le16 *) pSMB->fileName, fileName,
5105                                 PATH_MAX, nls_codepage);
5106                 name_len++;     /* trailing null */
5107                 name_len *= 2;
5108         } else {        /* BB improve the check for buffer overruns BB */
5109                 name_len = strnlen(fileName, PATH_MAX);
5110                 name_len++;     /* trailing null */
5111                 strncpy(pSMB->fileName, fileName, name_len);
5112         }
5113         pSMB->attr = cpu_to_le16(dos_attrs);
5114         pSMB->BufferFormat = 0x04;
5115         pSMB->hdr.smb_buf_length += name_len + 1;
5116         pSMB->ByteCount = cpu_to_le16(name_len + 1);
5117         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5118                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5119         if (rc)
5120                 cFYI(1, ("Error in LegacySetAttr = %d", rc));
5121
5122         cifs_buf_release(pSMB);
5123
5124         if (rc == -EAGAIN)
5125                 goto SetAttrLgcyRetry;
5126
5127         return rc;
5128 }
5129 #endif /* temporarily unneeded SetAttr legacy function */
5130
5131 int
5132 CIFSSMBUnixSetInfo(const int xid, struct cifsTconInfo *tcon, char *fileName,
5133                    const struct cifs_unix_set_info_args *args,
5134                    const struct nls_table *nls_codepage, int remap)
5135 {
5136         TRANSACTION2_SPI_REQ *pSMB = NULL;
5137         TRANSACTION2_SPI_RSP *pSMBr = NULL;
5138         int name_len;
5139         int rc = 0;
5140         int bytes_returned = 0;
5141         FILE_UNIX_BASIC_INFO *data_offset;
5142         __u16 params, param_offset, offset, count, byte_count;
5143         __u64 mode = args->mode;
5144
5145         cFYI(1, ("In SetUID/GID/Mode"));
5146 setPermsRetry:
5147         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5148                       (void **) &pSMBr);
5149         if (rc)
5150                 return rc;
5151
5152         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5153                 name_len =
5154                     cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5155                                      PATH_MAX, nls_codepage, remap);
5156                 name_len++;     /* trailing null */
5157                 name_len *= 2;
5158         } else {        /* BB improve the check for buffer overruns BB */
5159                 name_len = strnlen(fileName, PATH_MAX);
5160                 name_len++;     /* trailing null */
5161                 strncpy(pSMB->FileName, fileName, name_len);
5162         }
5163
5164         params = 6 + name_len;
5165         count = sizeof(FILE_UNIX_BASIC_INFO);
5166         pSMB->MaxParameterCount = cpu_to_le16(2);
5167         /* BB find max SMB PDU from sess structure BB */
5168         pSMB->MaxDataCount = cpu_to_le16(1000);
5169         pSMB->MaxSetupCount = 0;
5170         pSMB->Reserved = 0;
5171         pSMB->Flags = 0;
5172         pSMB->Timeout = 0;
5173         pSMB->Reserved2 = 0;
5174         param_offset = offsetof(struct smb_com_transaction2_spi_req,
5175                                 InformationLevel) - 4;
5176         offset = param_offset + params;
5177         data_offset =
5178             (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5179                                       offset);
5180         memset(data_offset, 0, count);
5181         pSMB->DataOffset = cpu_to_le16(offset);
5182         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5183         pSMB->SetupCount = 1;
5184         pSMB->Reserved3 = 0;
5185         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5186         byte_count = 3 /* pad */  + params + count;
5187         pSMB->ParameterCount = cpu_to_le16(params);
5188         pSMB->DataCount = cpu_to_le16(count);
5189         pSMB->TotalParameterCount = pSMB->ParameterCount;
5190         pSMB->TotalDataCount = pSMB->DataCount;
5191         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5192         pSMB->Reserved4 = 0;
5193         pSMB->hdr.smb_buf_length += byte_count;
5194         /* Samba server ignores set of file size to zero due to bugs in some
5195         older clients, but we should be precise - we use SetFileSize to
5196         set file size and do not want to truncate file size to zero
5197         accidently as happened on one Samba server beta by putting
5198         zero instead of -1 here */
5199         data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5200         data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5201         data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5202         data_offset->LastAccessTime = cpu_to_le64(args->atime);
5203         data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5204         data_offset->Uid = cpu_to_le64(args->uid);
5205         data_offset->Gid = cpu_to_le64(args->gid);
5206         /* better to leave device as zero when it is  */
5207         data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5208         data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5209         data_offset->Permissions = cpu_to_le64(mode);
5210
5211         if (S_ISREG(mode))
5212                 data_offset->Type = cpu_to_le32(UNIX_FILE);
5213         else if (S_ISDIR(mode))
5214                 data_offset->Type = cpu_to_le32(UNIX_DIR);
5215         else if (S_ISLNK(mode))
5216                 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5217         else if (S_ISCHR(mode))
5218                 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5219         else if (S_ISBLK(mode))
5220                 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5221         else if (S_ISFIFO(mode))
5222                 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5223         else if (S_ISSOCK(mode))
5224                 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5225
5226
5227         pSMB->ByteCount = cpu_to_le16(byte_count);
5228         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5229                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5230         if (rc)
5231                 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
5232
5233         cifs_buf_release(pSMB);
5234         if (rc == -EAGAIN)
5235                 goto setPermsRetry;
5236         return rc;
5237 }
5238
5239 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5240                   const int notify_subdirs, const __u16 netfid,
5241                   __u32 filter, struct file *pfile, int multishot,
5242                   const struct nls_table *nls_codepage)
5243 {
5244         int rc = 0;
5245         struct smb_com_transaction_change_notify_req *pSMB = NULL;
5246         struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
5247         struct dir_notify_req *dnotify_req;
5248         int bytes_returned;
5249
5250         cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid));
5251         rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
5252                       (void **) &pSMBr);
5253         if (rc)
5254                 return rc;
5255
5256         pSMB->TotalParameterCount = 0 ;
5257         pSMB->TotalDataCount = 0;
5258         pSMB->MaxParameterCount = cpu_to_le32(2);
5259         /* BB find exact data count max from sess structure BB */
5260         pSMB->MaxDataCount = 0; /* same in little endian or be */
5261 /* BB VERIFY verify which is correct for above BB */
5262         pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
5263                                              MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
5264
5265         pSMB->MaxSetupCount = 4;
5266         pSMB->Reserved = 0;
5267         pSMB->ParameterOffset = 0;
5268         pSMB->DataCount = 0;
5269         pSMB->DataOffset = 0;
5270         pSMB->SetupCount = 4; /* single byte does not need le conversion */
5271         pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
5272         pSMB->ParameterCount = pSMB->TotalParameterCount;
5273         if (notify_subdirs)
5274                 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
5275         pSMB->Reserved2 = 0;
5276         pSMB->CompletionFilter = cpu_to_le32(filter);
5277         pSMB->Fid = netfid; /* file handle always le */
5278         pSMB->ByteCount = 0;
5279
5280         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5281                          (struct smb_hdr *)pSMBr, &bytes_returned,
5282                          CIFS_ASYNC_OP);
5283         if (rc) {
5284                 cFYI(1, ("Error in Notify = %d", rc));
5285         } else {
5286                 /* Add file to outstanding requests */
5287                 /* BB change to kmem cache alloc */
5288                 dnotify_req = kmalloc(
5289                                                 sizeof(struct dir_notify_req),
5290                                                  GFP_KERNEL);
5291                 if (dnotify_req) {
5292                         dnotify_req->Pid = pSMB->hdr.Pid;
5293                         dnotify_req->PidHigh = pSMB->hdr.PidHigh;
5294                         dnotify_req->Mid = pSMB->hdr.Mid;
5295                         dnotify_req->Tid = pSMB->hdr.Tid;
5296                         dnotify_req->Uid = pSMB->hdr.Uid;
5297                         dnotify_req->netfid = netfid;
5298                         dnotify_req->pfile = pfile;
5299                         dnotify_req->filter = filter;
5300                         dnotify_req->multishot = multishot;
5301                         spin_lock(&GlobalMid_Lock);
5302                         list_add_tail(&dnotify_req->lhead,
5303                                         &GlobalDnotifyReqList);
5304                         spin_unlock(&GlobalMid_Lock);
5305                 } else
5306                         rc = -ENOMEM;
5307         }
5308         cifs_buf_release(pSMB);
5309         return rc;
5310 }
5311 #ifdef CONFIG_CIFS_XATTR
5312 ssize_t
5313 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5314                  const unsigned char *searchName,
5315                  char *EAData, size_t buf_size,
5316                  const struct nls_table *nls_codepage, int remap)
5317 {
5318                 /* BB assumes one setup word */
5319         TRANSACTION2_QPI_REQ *pSMB = NULL;
5320         TRANSACTION2_QPI_RSP *pSMBr = NULL;
5321         int rc = 0;
5322         int bytes_returned;
5323         int name_len;
5324         struct fea *temp_fea;
5325         char *temp_ptr;
5326         __u16 params, byte_count;
5327
5328         cFYI(1, ("In Query All EAs path %s", searchName));
5329 QAllEAsRetry:
5330         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5331                       (void **) &pSMBr);
5332         if (rc)
5333                 return rc;
5334
5335         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5336                 name_len =
5337                     cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5338                                      PATH_MAX, nls_codepage, remap);
5339                 name_len++;     /* trailing null */
5340                 name_len *= 2;
5341         } else {        /* BB improve the check for buffer overruns BB */
5342                 name_len = strnlen(searchName, PATH_MAX);
5343                 name_len++;     /* trailing null */
5344                 strncpy(pSMB->FileName, searchName, name_len);
5345         }
5346
5347         params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5348         pSMB->TotalDataCount = 0;
5349         pSMB->MaxParameterCount = cpu_to_le16(2);
5350         /* BB find exact max SMB PDU from sess structure BB */
5351         pSMB->MaxDataCount = cpu_to_le16(4000);
5352         pSMB->MaxSetupCount = 0;
5353         pSMB->Reserved = 0;
5354         pSMB->Flags = 0;
5355         pSMB->Timeout = 0;
5356         pSMB->Reserved2 = 0;
5357         pSMB->ParameterOffset = cpu_to_le16(offsetof(
5358         struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5359         pSMB->DataCount = 0;
5360         pSMB->DataOffset = 0;
5361         pSMB->SetupCount = 1;
5362         pSMB->Reserved3 = 0;
5363         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5364         byte_count = params + 1 /* pad */ ;
5365         pSMB->TotalParameterCount = cpu_to_le16(params);
5366         pSMB->ParameterCount = pSMB->TotalParameterCount;
5367         pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5368         pSMB->Reserved4 = 0;
5369         pSMB->hdr.smb_buf_length += byte_count;
5370         pSMB->ByteCount = cpu_to_le16(byte_count);
5371
5372         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5373                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5374         if (rc) {
5375                 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
5376         } else {                /* decode response */
5377                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5378
5379                 /* BB also check enough total bytes returned */
5380                 /* BB we need to improve the validity checking
5381                 of these trans2 responses */
5382                 if (rc || (pSMBr->ByteCount < 4))
5383                         rc = -EIO;      /* bad smb */
5384            /* else if (pFindData){
5385                         memcpy((char *) pFindData,
5386                                (char *) &pSMBr->hdr.Protocol +
5387                                data_offset, kl);
5388                 }*/ else {
5389                         /* check that length of list is not more than bcc */
5390                         /* check that each entry does not go beyond length
5391                            of list */
5392                         /* check that each element of each entry does not
5393                            go beyond end of list */
5394                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5395                         struct fealist *ea_response_data;
5396                         rc = 0;
5397                         /* validate_trans2_offsets() */
5398                         /* BB check if start of smb + data_offset > &bcc+ bcc */
5399                         ea_response_data = (struct fealist *)
5400                                 (((char *) &pSMBr->hdr.Protocol) +
5401                                 data_offset);
5402                         name_len = le32_to_cpu(ea_response_data->list_len);
5403                         cFYI(1, ("ea length %d", name_len));
5404                         if (name_len <= 8) {
5405                         /* returned EA size zeroed at top of function */
5406                                 cFYI(1, ("empty EA list returned from server"));
5407                         } else {
5408                                 /* account for ea list len */
5409                                 name_len -= 4;
5410                                 temp_fea = ea_response_data->list;
5411                                 temp_ptr = (char *)temp_fea;
5412                                 while (name_len > 0) {
5413                                         __u16 value_len;
5414                                         name_len -= 4;
5415                                         temp_ptr += 4;
5416                                         rc += temp_fea->name_len;
5417                                 /* account for prefix user. and trailing null */
5418                                         rc = rc + 5 + 1;
5419                                         if (rc < (int)buf_size) {
5420                                                 memcpy(EAData, "user.", 5);
5421                                                 EAData += 5;
5422                                                 memcpy(EAData, temp_ptr,
5423                                                        temp_fea->name_len);
5424                                                 EAData += temp_fea->name_len;
5425                                                 /* null terminate name */
5426                                                 *EAData = 0;
5427                                                 EAData = EAData + 1;
5428                                         } else if (buf_size == 0) {
5429                                                 /* skip copy - calc size only */
5430                                         } else {
5431                                                 /* stop before overrun buffer */
5432                                                 rc = -ERANGE;
5433                                                 break;
5434                                         }
5435                                         name_len -= temp_fea->name_len;
5436                                         temp_ptr += temp_fea->name_len;
5437                                         /* account for trailing null */
5438                                         name_len--;
5439                                         temp_ptr++;
5440                                         value_len =
5441                                               le16_to_cpu(temp_fea->value_len);
5442                                         name_len -= value_len;
5443                                         temp_ptr += value_len;
5444                                         /* BB check that temp_ptr is still
5445                                               within the SMB BB*/
5446
5447                                         /* no trailing null to account for
5448                                            in value len */
5449                                         /* go on to next EA */
5450                                         temp_fea = (struct fea *)temp_ptr;
5451                                 }
5452                         }
5453                 }
5454         }
5455         cifs_buf_release(pSMB);
5456         if (rc == -EAGAIN)
5457                 goto QAllEAsRetry;
5458
5459         return (ssize_t)rc;
5460 }
5461
5462 ssize_t CIFSSMBQueryEA(const int xid, struct cifsTconInfo *tcon,
5463                 const unsigned char *searchName, const unsigned char *ea_name,
5464                 unsigned char *ea_value, size_t buf_size,
5465                 const struct nls_table *nls_codepage, int remap)
5466 {
5467         TRANSACTION2_QPI_REQ *pSMB = NULL;
5468         TRANSACTION2_QPI_RSP *pSMBr = NULL;
5469         int rc = 0;
5470         int bytes_returned;
5471         int name_len;
5472         struct fea *temp_fea;
5473         char *temp_ptr;
5474         __u16 params, byte_count;
5475
5476         cFYI(1, ("In Query EA path %s", searchName));
5477 QEARetry:
5478         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5479                       (void **) &pSMBr);
5480         if (rc)
5481                 return rc;
5482
5483         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5484                 name_len =
5485                     cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5486                                      PATH_MAX, nls_codepage, remap);
5487                 name_len++;     /* trailing null */
5488                 name_len *= 2;
5489         } else {        /* BB improve the check for buffer overruns BB */
5490                 name_len = strnlen(searchName, PATH_MAX);
5491                 name_len++;     /* trailing null */
5492                 strncpy(pSMB->FileName, searchName, name_len);
5493         }
5494
5495         params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5496         pSMB->TotalDataCount = 0;
5497         pSMB->MaxParameterCount = cpu_to_le16(2);
5498         /* BB find exact max SMB PDU from sess structure BB */
5499         pSMB->MaxDataCount = cpu_to_le16(4000);
5500         pSMB->MaxSetupCount = 0;
5501         pSMB->Reserved = 0;
5502         pSMB->Flags = 0;
5503         pSMB->Timeout = 0;
5504         pSMB->Reserved2 = 0;
5505         pSMB->ParameterOffset = cpu_to_le16(offsetof(
5506                 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5507         pSMB->DataCount = 0;
5508         pSMB->DataOffset = 0;
5509         pSMB->SetupCount = 1;
5510         pSMB->Reserved3 = 0;
5511         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5512         byte_count = params + 1 /* pad */ ;
5513         pSMB->TotalParameterCount = cpu_to_le16(params);
5514         pSMB->ParameterCount = pSMB->TotalParameterCount;
5515         pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5516         pSMB->Reserved4 = 0;
5517         pSMB->hdr.smb_buf_length += byte_count;
5518         pSMB->ByteCount = cpu_to_le16(byte_count);
5519
5520         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5521                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5522         if (rc) {
5523                 cFYI(1, ("Send error in Query EA = %d", rc));
5524         } else {                /* decode response */
5525                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5526
5527                 /* BB also check enough total bytes returned */
5528                 /* BB we need to improve the validity checking
5529                 of these trans2 responses */
5530                 if (rc || (pSMBr->ByteCount < 4))
5531                         rc = -EIO;      /* bad smb */
5532            /* else if (pFindData){
5533                         memcpy((char *) pFindData,
5534                                (char *) &pSMBr->hdr.Protocol +
5535                                data_offset, kl);
5536                 }*/ else {
5537                         /* check that length of list is not more than bcc */
5538                         /* check that each entry does not go beyond length
5539                            of list */
5540                         /* check that each element of each entry does not
5541                            go beyond end of list */
5542                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5543                         struct fealist *ea_response_data;
5544                         rc = -ENODATA;
5545                         /* validate_trans2_offsets() */
5546                         /* BB check if start of smb + data_offset > &bcc+ bcc*/
5547                         ea_response_data = (struct fealist *)
5548                                 (((char *) &pSMBr->hdr.Protocol) +
5549                                 data_offset);
5550                         name_len = le32_to_cpu(ea_response_data->list_len);
5551                         cFYI(1, ("ea length %d", name_len));
5552                         if (name_len <= 8) {
5553                         /* returned EA size zeroed at top of function */
5554                                 cFYI(1, ("empty EA list returned from server"));
5555                         } else {
5556                                 /* account for ea list len */
5557                                 name_len -= 4;
5558                                 temp_fea = ea_response_data->list;
5559                                 temp_ptr = (char *)temp_fea;
5560                                 /* loop through checking if we have a matching
5561                                 name and then return the associated value */
5562                                 while (name_len > 0) {
5563                                         __u16 value_len;
5564                                         name_len -= 4;
5565                                         temp_ptr += 4;
5566                                         value_len =
5567                                               le16_to_cpu(temp_fea->value_len);
5568                                 /* BB validate that value_len falls within SMB,
5569                                 even though maximum for name_len is 255 */
5570                                         if (memcmp(temp_fea->name, ea_name,
5571                                                   temp_fea->name_len) == 0) {
5572                                                 /* found a match */
5573                                                 rc = value_len;
5574                                 /* account for prefix user. and trailing null */
5575                                                 if (rc <= (int)buf_size) {
5576                                                         memcpy(ea_value,
5577                                                                 temp_fea->name+temp_fea->name_len+1,
5578                                                                 rc);
5579                                                         /* ea values, unlike ea
5580                                                            names, are not null
5581                                                            terminated */
5582                                                 } else if (buf_size == 0) {
5583                                                 /* skip copy - calc size only */
5584                                                 } else {
5585                                                 /* stop before overrun buffer */
5586                                                         rc = -ERANGE;
5587                                                 }
5588                                                 break;
5589                                         }
5590                                         name_len -= temp_fea->name_len;
5591                                         temp_ptr += temp_fea->name_len;
5592                                         /* account for trailing null */
5593                                         name_len--;
5594                                         temp_ptr++;
5595                                         name_len -= value_len;
5596                                         temp_ptr += value_len;
5597                                         /* No trailing null to account for in
5598                                            value_len.  Go on to next EA */
5599                                         temp_fea = (struct fea *)temp_ptr;
5600                                 }
5601                         }
5602                 }
5603         }
5604         cifs_buf_release(pSMB);
5605         if (rc == -EAGAIN)
5606                 goto QEARetry;
5607
5608         return (ssize_t)rc;
5609 }
5610
5611 int
5612 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5613              const char *ea_name, const void *ea_value,
5614              const __u16 ea_value_len, const struct nls_table *nls_codepage,
5615              int remap)
5616 {
5617         struct smb_com_transaction2_spi_req *pSMB = NULL;
5618         struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5619         struct fealist *parm_data;
5620         int name_len;
5621         int rc = 0;
5622         int bytes_returned = 0;
5623         __u16 params, param_offset, byte_count, offset, count;
5624
5625         cFYI(1, ("In SetEA"));
5626 SetEARetry:
5627         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5628                       (void **) &pSMBr);
5629         if (rc)
5630                 return rc;
5631
5632         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5633                 name_len =
5634                     cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5635                                      PATH_MAX, nls_codepage, remap);
5636                 name_len++;     /* trailing null */
5637                 name_len *= 2;
5638         } else {        /* BB improve the check for buffer overruns BB */
5639                 name_len = strnlen(fileName, PATH_MAX);
5640                 name_len++;     /* trailing null */
5641                 strncpy(pSMB->FileName, fileName, name_len);
5642         }
5643
5644         params = 6 + name_len;
5645
5646         /* done calculating parms using name_len of file name,
5647         now use name_len to calculate length of ea name
5648         we are going to create in the inode xattrs */
5649         if (ea_name == NULL)
5650                 name_len = 0;
5651         else
5652                 name_len = strnlen(ea_name, 255);
5653
5654         count = sizeof(*parm_data) + ea_value_len + name_len;
5655         pSMB->MaxParameterCount = cpu_to_le16(2);
5656         /* BB find max SMB PDU from sess */
5657         pSMB->MaxDataCount = cpu_to_le16(1000);
5658         pSMB->MaxSetupCount = 0;
5659         pSMB->Reserved = 0;
5660         pSMB->Flags = 0;
5661         pSMB->Timeout = 0;
5662         pSMB->Reserved2 = 0;
5663         param_offset = offsetof(struct smb_com_transaction2_spi_req,
5664                                 InformationLevel) - 4;
5665         offset = param_offset + params;
5666         pSMB->InformationLevel =
5667                 cpu_to_le16(SMB_SET_FILE_EA);
5668
5669         parm_data =
5670                 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5671                                        offset);
5672         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5673         pSMB->DataOffset = cpu_to_le16(offset);
5674         pSMB->SetupCount = 1;
5675         pSMB->Reserved3 = 0;
5676         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5677         byte_count = 3 /* pad */  + params + count;
5678         pSMB->DataCount = cpu_to_le16(count);
5679         parm_data->list_len = cpu_to_le32(count);
5680         parm_data->list[0].EA_flags = 0;
5681         /* we checked above that name len is less than 255 */
5682         parm_data->list[0].name_len = (__u8)name_len;
5683         /* EA names are always ASCII */
5684         if (ea_name)
5685                 strncpy(parm_data->list[0].name, ea_name, name_len);
5686         parm_data->list[0].name[name_len] = 0;
5687         parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5688         /* caller ensures that ea_value_len is less than 64K but
5689         we need to ensure that it fits within the smb */
5690
5691         /*BB add length check to see if it would fit in
5692              negotiated SMB buffer size BB */
5693         /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5694         if (ea_value_len)
5695                 memcpy(parm_data->list[0].name+name_len+1,
5696                        ea_value, ea_value_len);
5697
5698         pSMB->TotalDataCount = pSMB->DataCount;
5699         pSMB->ParameterCount = cpu_to_le16(params);
5700         pSMB->TotalParameterCount = pSMB->ParameterCount;
5701         pSMB->Reserved4 = 0;
5702         pSMB->hdr.smb_buf_length += byte_count;
5703         pSMB->ByteCount = cpu_to_le16(byte_count);
5704         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5705                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5706         if (rc)
5707                 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
5708
5709         cifs_buf_release(pSMB);
5710
5711         if (rc == -EAGAIN)
5712                 goto SetEARetry;
5713
5714         return rc;
5715 }
5716
5717 #endif