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