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