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