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