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