[CIFS] Remove sparse endian warnings
[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 #endif /* CIFS_EXPERIMENTAL */
2568
2569 int
2570 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2571                         const unsigned char *searchName,
2572                         char *symlinkinfo, const int buflen, __u16 fid,
2573                         const struct nls_table *nls_codepage)
2574 {
2575         int rc = 0;
2576         int bytes_returned;
2577         int name_len;
2578         struct smb_com_transaction_ioctl_req *pSMB;
2579         struct smb_com_transaction_ioctl_rsp *pSMBr;
2580
2581         cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2582         rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2583                       (void **) &pSMBr);
2584         if (rc)
2585                 return rc;
2586
2587         pSMB->TotalParameterCount = 0 ;
2588         pSMB->TotalDataCount = 0;
2589         pSMB->MaxParameterCount = cpu_to_le32(2);
2590         /* BB find exact data count max from sess structure BB */
2591         pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2592                                           MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2593         pSMB->MaxSetupCount = 4;
2594         pSMB->Reserved = 0;
2595         pSMB->ParameterOffset = 0;
2596         pSMB->DataCount = 0;
2597         pSMB->DataOffset = 0;
2598         pSMB->SetupCount = 4;
2599         pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2600         pSMB->ParameterCount = pSMB->TotalParameterCount;
2601         pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2602         pSMB->IsFsctl = 1; /* FSCTL */
2603         pSMB->IsRootFlag = 0;
2604         pSMB->Fid = fid; /* file handle always le */
2605         pSMB->ByteCount = 0;
2606
2607         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2608                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2609         if (rc) {
2610                 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2611         } else {                /* decode response */
2612                 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2613                 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2614                 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
2615                 /* BB also check enough total bytes returned */
2616                         rc = -EIO;      /* bad smb */
2617                 else {
2618                         if (data_count && (data_count < 2048)) {
2619                                 char *end_of_smb = 2 /* sizeof byte count */ +
2620                                                 pSMBr->ByteCount +
2621                                                 (char *)&pSMBr->ByteCount;
2622
2623                                 struct reparse_data *reparse_buf =
2624                                                 (struct reparse_data *)
2625                                                 ((char *)&pSMBr->hdr.Protocol
2626                                                                  + data_offset);
2627                                 if ((char *)reparse_buf >= end_of_smb) {
2628                                         rc = -EIO;
2629                                         goto qreparse_out;
2630                                 }
2631                                 if ((reparse_buf->LinkNamesBuf +
2632                                         reparse_buf->TargetNameOffset +
2633                                         reparse_buf->TargetNameLen) >
2634                                                 end_of_smb) {
2635                                         cFYI(1, ("reparse buf beyond SMB"));
2636                                         rc = -EIO;
2637                                         goto qreparse_out;
2638                                 }
2639
2640                                 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2641                                         name_len = UniStrnlen((wchar_t *)
2642                                                 (reparse_buf->LinkNamesBuf +
2643                                                 reparse_buf->TargetNameOffset),
2644                                                 min(buflen/2,
2645                                                 reparse_buf->TargetNameLen / 2));
2646                                         cifs_strfromUCS_le(symlinkinfo,
2647                                                 (__le16 *) (reparse_buf->LinkNamesBuf +
2648                                                 reparse_buf->TargetNameOffset),
2649                                                 name_len, nls_codepage);
2650                                 } else { /* ASCII names */
2651                                         strncpy(symlinkinfo,
2652                                                 reparse_buf->LinkNamesBuf +
2653                                                 reparse_buf->TargetNameOffset,
2654                                                 min_t(const int, buflen,
2655                                                    reparse_buf->TargetNameLen));
2656                                 }
2657                         } else {
2658                                 rc = -EIO;
2659                                 cFYI(1, ("Invalid return data count on "
2660                                          "get reparse info ioctl"));
2661                         }
2662                         symlinkinfo[buflen] = 0; /* just in case so the caller
2663                                         does not go off the end of the buffer */
2664                         cFYI(1, ("readlink result - %s", symlinkinfo));
2665                 }
2666         }
2667 qreparse_out:
2668         cifs_buf_release(pSMB);
2669
2670         /* Note: On -EAGAIN error only caller can retry on handle based calls
2671                 since file handle passed in no longer valid */
2672
2673         return rc;
2674 }
2675
2676 #ifdef CONFIG_CIFS_POSIX
2677
2678 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2679 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2680                              struct cifs_posix_ace *cifs_ace)
2681 {
2682         /* u8 cifs fields do not need le conversion */
2683         ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2684         ace->e_tag  = cpu_to_le16(cifs_ace->cifs_e_tag);
2685         ace->e_id   = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2686         /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2687
2688         return;
2689 }
2690
2691 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2692 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2693                                const int acl_type, const int size_of_data_area)
2694 {
2695         int size =  0;
2696         int i;
2697         __u16 count;
2698         struct cifs_posix_ace *pACE;
2699         struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2700         posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2701
2702         if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2703                 return -EOPNOTSUPP;
2704
2705         if (acl_type & ACL_TYPE_ACCESS) {
2706                 count = le16_to_cpu(cifs_acl->access_entry_count);
2707                 pACE = &cifs_acl->ace_array[0];
2708                 size = sizeof(struct cifs_posix_acl);
2709                 size += sizeof(struct cifs_posix_ace) * count;
2710                 /* check if we would go beyond end of SMB */
2711                 if (size_of_data_area < size) {
2712                         cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
2713                                 size_of_data_area, size));
2714                         return -EINVAL;
2715                 }
2716         } else if (acl_type & ACL_TYPE_DEFAULT) {
2717                 count = le16_to_cpu(cifs_acl->access_entry_count);
2718                 size = sizeof(struct cifs_posix_acl);
2719                 size += sizeof(struct cifs_posix_ace) * count;
2720 /* skip past access ACEs to get to default ACEs */
2721                 pACE = &cifs_acl->ace_array[count];
2722                 count = le16_to_cpu(cifs_acl->default_entry_count);
2723                 size += sizeof(struct cifs_posix_ace) * count;
2724                 /* check if we would go beyond end of SMB */
2725                 if (size_of_data_area < size)
2726                         return -EINVAL;
2727         } else {
2728                 /* illegal type */
2729                 return -EINVAL;
2730         }
2731
2732         size = posix_acl_xattr_size(count);
2733         if ((buflen == 0) || (local_acl == NULL)) {
2734                 /* used to query ACL EA size */
2735         } else if (size > buflen) {
2736                 return -ERANGE;
2737         } else /* buffer big enough */ {
2738                 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2739                 for (i = 0; i < count ; i++) {
2740                         cifs_convert_ace(&local_acl->a_entries[i], pACE);
2741                         pACE++;
2742                 }
2743         }
2744         return size;
2745 }
2746
2747 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2748                                      const posix_acl_xattr_entry *local_ace)
2749 {
2750         __u16 rc = 0; /* 0 = ACL converted ok */
2751
2752         cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2753         cifs_ace->cifs_e_tag =  le16_to_cpu(local_ace->e_tag);
2754         /* BB is there a better way to handle the large uid? */
2755         if (local_ace->e_id == cpu_to_le32(-1)) {
2756         /* Probably no need to le convert -1 on any arch but can not hurt */
2757                 cifs_ace->cifs_uid = cpu_to_le64(-1);
2758         } else
2759                 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2760         /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2761         return rc;
2762 }
2763
2764 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2765 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2766                                const int buflen, const int acl_type)
2767 {
2768         __u16 rc = 0;
2769         struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2770         posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2771         int count;
2772         int i;
2773
2774         if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2775                 return 0;
2776
2777         count = posix_acl_xattr_count((size_t)buflen);
2778         cFYI(1, ("setting acl with %d entries from buf of length %d and "
2779                 "version of %d",
2780                 count, buflen, le32_to_cpu(local_acl->a_version)));
2781         if (le32_to_cpu(local_acl->a_version) != 2) {
2782                 cFYI(1, ("unknown POSIX ACL version %d",
2783                      le32_to_cpu(local_acl->a_version)));
2784                 return 0;
2785         }
2786         cifs_acl->version = cpu_to_le16(1);
2787         if (acl_type == ACL_TYPE_ACCESS)
2788                 cifs_acl->access_entry_count = cpu_to_le16(count);
2789         else if (acl_type == ACL_TYPE_DEFAULT)
2790                 cifs_acl->default_entry_count = cpu_to_le16(count);
2791         else {
2792                 cFYI(1, ("unknown ACL type %d", acl_type));
2793                 return 0;
2794         }
2795         for (i = 0; i < count; i++) {
2796                 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2797                                         &local_acl->a_entries[i]);
2798                 if (rc != 0) {
2799                         /* ACE not converted */
2800                         break;
2801                 }
2802         }
2803         if (rc == 0) {
2804                 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2805                 rc += sizeof(struct cifs_posix_acl);
2806                 /* BB add check to make sure ACL does not overflow SMB */
2807         }
2808         return rc;
2809 }
2810
2811 int
2812 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2813                    const unsigned char *searchName,
2814                    char *acl_inf, const int buflen, const int acl_type,
2815                    const struct nls_table *nls_codepage, int remap)
2816 {
2817 /* SMB_QUERY_POSIX_ACL */
2818         TRANSACTION2_QPI_REQ *pSMB = NULL;
2819         TRANSACTION2_QPI_RSP *pSMBr = NULL;
2820         int rc = 0;
2821         int bytes_returned;
2822         int name_len;
2823         __u16 params, byte_count;
2824
2825         cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2826
2827 queryAclRetry:
2828         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2829                 (void **) &pSMBr);
2830         if (rc)
2831                 return rc;
2832
2833         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2834                 name_len =
2835                         cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2836                                          PATH_MAX, nls_codepage, remap);
2837                 name_len++;     /* trailing null */
2838                 name_len *= 2;
2839                 pSMB->FileName[name_len] = 0;
2840                 pSMB->FileName[name_len+1] = 0;
2841         } else {        /* BB improve the check for buffer overruns BB */
2842                 name_len = strnlen(searchName, PATH_MAX);
2843                 name_len++;     /* trailing null */
2844                 strncpy(pSMB->FileName, searchName, name_len);
2845         }
2846
2847         params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
2848         pSMB->TotalDataCount = 0;
2849         pSMB->MaxParameterCount = cpu_to_le16(2);
2850         /* BB find exact max data count below from sess structure BB */
2851         pSMB->MaxDataCount = cpu_to_le16(4000);
2852         pSMB->MaxSetupCount = 0;
2853         pSMB->Reserved = 0;
2854         pSMB->Flags = 0;
2855         pSMB->Timeout = 0;
2856         pSMB->Reserved2 = 0;
2857         pSMB->ParameterOffset = cpu_to_le16(
2858                 offsetof(struct smb_com_transaction2_qpi_req,
2859                          InformationLevel) - 4);
2860         pSMB->DataCount = 0;
2861         pSMB->DataOffset = 0;
2862         pSMB->SetupCount = 1;
2863         pSMB->Reserved3 = 0;
2864         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2865         byte_count = params + 1 /* pad */ ;
2866         pSMB->TotalParameterCount = cpu_to_le16(params);
2867         pSMB->ParameterCount = pSMB->TotalParameterCount;
2868         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2869         pSMB->Reserved4 = 0;
2870         pSMB->hdr.smb_buf_length += byte_count;
2871         pSMB->ByteCount = cpu_to_le16(byte_count);
2872
2873         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2874                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2875         cifs_stats_inc(&tcon->num_acl_get);
2876         if (rc) {
2877                 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2878         } else {
2879                 /* decode response */
2880
2881                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2882                 if (rc || (pSMBr->ByteCount < 2))
2883                 /* BB also check enough total bytes returned */
2884                         rc = -EIO;      /* bad smb */
2885                 else {
2886                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2887                         __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2888                         rc = cifs_copy_posix_acl(acl_inf,
2889                                 (char *)&pSMBr->hdr.Protocol+data_offset,
2890                                 buflen, acl_type, count);
2891                 }
2892         }
2893         cifs_buf_release(pSMB);
2894         if (rc == -EAGAIN)
2895                 goto queryAclRetry;
2896         return rc;
2897 }
2898
2899 int
2900 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2901                    const unsigned char *fileName,
2902                    const char *local_acl, const int buflen,
2903                    const int acl_type,
2904                    const struct nls_table *nls_codepage, int remap)
2905 {
2906         struct smb_com_transaction2_spi_req *pSMB = NULL;
2907         struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2908         char *parm_data;
2909         int name_len;
2910         int rc = 0;
2911         int bytes_returned = 0;
2912         __u16 params, byte_count, data_count, param_offset, offset;
2913
2914         cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2915 setAclRetry:
2916         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2917                       (void **) &pSMBr);
2918         if (rc)
2919                 return rc;
2920         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2921                 name_len =
2922                         cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2923                                       PATH_MAX, nls_codepage, remap);
2924                 name_len++;     /* trailing null */
2925                 name_len *= 2;
2926         } else {        /* BB improve the check for buffer overruns BB */
2927                 name_len = strnlen(fileName, PATH_MAX);
2928                 name_len++;     /* trailing null */
2929                 strncpy(pSMB->FileName, fileName, name_len);
2930         }
2931         params = 6 + name_len;
2932         pSMB->MaxParameterCount = cpu_to_le16(2);
2933         /* BB find max SMB size from sess */
2934         pSMB->MaxDataCount = cpu_to_le16(1000);
2935         pSMB->MaxSetupCount = 0;
2936         pSMB->Reserved = 0;
2937         pSMB->Flags = 0;
2938         pSMB->Timeout = 0;
2939         pSMB->Reserved2 = 0;
2940         param_offset = offsetof(struct smb_com_transaction2_spi_req,
2941                                 InformationLevel) - 4;
2942         offset = param_offset + params;
2943         parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2944         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2945
2946         /* convert to on the wire format for POSIX ACL */
2947         data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
2948
2949         if (data_count == 0) {
2950                 rc = -EOPNOTSUPP;
2951                 goto setACLerrorExit;
2952         }
2953         pSMB->DataOffset = cpu_to_le16(offset);
2954         pSMB->SetupCount = 1;
2955         pSMB->Reserved3 = 0;
2956         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2957         pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2958         byte_count = 3 /* pad */  + params + data_count;
2959         pSMB->DataCount = cpu_to_le16(data_count);
2960         pSMB->TotalDataCount = pSMB->DataCount;
2961         pSMB->ParameterCount = cpu_to_le16(params);
2962         pSMB->TotalParameterCount = pSMB->ParameterCount;
2963         pSMB->Reserved4 = 0;
2964         pSMB->hdr.smb_buf_length += byte_count;
2965         pSMB->ByteCount = cpu_to_le16(byte_count);
2966         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2967                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2968         if (rc)
2969                 cFYI(1, ("Set POSIX ACL returned %d", rc));
2970
2971 setACLerrorExit:
2972         cifs_buf_release(pSMB);
2973         if (rc == -EAGAIN)
2974                 goto setAclRetry;
2975         return rc;
2976 }
2977
2978 /* BB fix tabs in this function FIXME BB */
2979 int
2980 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2981                const int netfid, __u64 *pExtAttrBits, __u64 *pMask)
2982 {
2983         int rc = 0;
2984         struct smb_t2_qfi_req *pSMB = NULL;
2985         struct smb_t2_qfi_rsp *pSMBr = NULL;
2986         int bytes_returned;
2987         __u16 params, byte_count;
2988
2989         cFYI(1, ("In GetExtAttr"));
2990         if (tcon == NULL)
2991                 return -ENODEV;
2992
2993 GetExtAttrRetry:
2994         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2995                         (void **) &pSMBr);
2996         if (rc)
2997                 return rc;
2998
2999         params = 2 /* level */ + 2 /* fid */;
3000         pSMB->t2.TotalDataCount = 0;
3001         pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3002         /* BB find exact max data count below from sess structure BB */
3003         pSMB->t2.MaxDataCount = cpu_to_le16(4000);
3004         pSMB->t2.MaxSetupCount = 0;
3005         pSMB->t2.Reserved = 0;
3006         pSMB->t2.Flags = 0;
3007         pSMB->t2.Timeout = 0;
3008         pSMB->t2.Reserved2 = 0;
3009         pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3010                                                Fid) - 4);
3011         pSMB->t2.DataCount = 0;
3012         pSMB->t2.DataOffset = 0;
3013         pSMB->t2.SetupCount = 1;
3014         pSMB->t2.Reserved3 = 0;
3015         pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3016         byte_count = params + 1 /* pad */ ;
3017         pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3018         pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3019         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
3020         pSMB->Pad = 0;
3021         pSMB->Fid = netfid;
3022         pSMB->hdr.smb_buf_length += byte_count;
3023         pSMB->t2.ByteCount = cpu_to_le16(byte_count);
3024
3025         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3026                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3027         if (rc) {
3028                 cFYI(1, ("error %d in GetExtAttr", rc));
3029         } else {
3030                 /* decode response */
3031                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3032                 if (rc || (pSMBr->ByteCount < 2))
3033                 /* BB also check enough total bytes returned */
3034                         /* If rc should we check for EOPNOSUPP and
3035                            disable the srvino flag? or in caller? */
3036                         rc = -EIO;      /* bad smb */
3037                 else {
3038                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3039                         __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3040                         struct file_chattr_info *pfinfo;
3041                         /* BB Do we need a cast or hash here ? */
3042                         if (count != 16) {
3043                                 cFYI(1, ("Illegal size ret in GetExtAttr"));
3044                                 rc = -EIO;
3045                                 goto GetExtAttrOut;
3046                         }
3047                         pfinfo = (struct file_chattr_info *)
3048                                  (data_offset + (char *) &pSMBr->hdr.Protocol);
3049                         *pExtAttrBits = le64_to_cpu(pfinfo->mode);
3050                         *pMask = le64_to_cpu(pfinfo->mask);
3051                 }
3052         }
3053 GetExtAttrOut:
3054         cifs_buf_release(pSMB);
3055         if (rc == -EAGAIN)
3056                 goto GetExtAttrRetry;
3057         return rc;
3058 }
3059
3060 #endif /* CONFIG_POSIX */
3061
3062 #ifdef CONFIG_CIFS_EXPERIMENTAL
3063 /* Get Security Descriptor (by handle) from remote server for a file or dir */
3064 int
3065 CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3066                   struct cifs_ntsd **acl_inf, __u32 *pbuflen)
3067 {
3068         int rc = 0;
3069         int buf_type = 0;
3070         QUERY_SEC_DESC_REQ *pSMB;
3071         struct kvec iov[1];
3072
3073         cFYI(1, ("GetCifsACL"));
3074
3075         *pbuflen = 0;
3076         *acl_inf = NULL;
3077
3078         rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
3079                         8 /* parm len */, tcon, (void **) &pSMB);
3080         if (rc)
3081                 return rc;
3082
3083         pSMB->MaxParameterCount = cpu_to_le32(4);
3084         /* BB TEST with big acls that might need to be e.g. larger than 16K */
3085         pSMB->MaxSetupCount = 0;
3086         pSMB->Fid = fid; /* file handle always le */
3087         pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
3088                                      CIFS_ACL_DACL);
3089         pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
3090         pSMB->hdr.smb_buf_length += 11;
3091         iov[0].iov_base = (char *)pSMB;
3092         iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
3093
3094         rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3095                          CIFS_STD_OP);
3096         cifs_stats_inc(&tcon->num_acl_get);
3097         if (rc) {
3098                 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
3099         } else {                /* decode response */
3100                 __le32 *parm;
3101                 __u32 parm_len;
3102                 __u32 acl_len;
3103                 struct smb_com_ntransact_rsp *pSMBr;
3104                 char *pdata;
3105
3106 /* validate_nttransact */
3107                 rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
3108                                         &pdata, &parm_len, pbuflen);
3109                 if (rc)
3110                         goto qsec_out;
3111                 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3112
3113                 cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, *acl_inf));
3114
3115                 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3116                         rc = -EIO;      /* bad smb */
3117                         *pbuflen = 0;
3118                         goto qsec_out;
3119                 }
3120
3121 /* BB check that data area is minimum length and as big as acl_len */
3122
3123                 acl_len = le32_to_cpu(*parm);
3124                 if (acl_len != *pbuflen) {
3125                         cERROR(1, ("acl length %d does not match %d",
3126                                    acl_len, *pbuflen));
3127                         if (*pbuflen > acl_len)
3128                                 *pbuflen = acl_len;
3129                 }
3130
3131                 /* check if buffer is big enough for the acl
3132                    header followed by the smallest SID */
3133                 if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
3134                     (*pbuflen >= 64 * 1024)) {
3135                         cERROR(1, ("bad acl length %d", *pbuflen));
3136                         rc = -EINVAL;
3137                         *pbuflen = 0;
3138                 } else {
3139                         *acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
3140                         if (*acl_inf == NULL) {
3141                                 *pbuflen = 0;
3142                                 rc = -ENOMEM;
3143                         }
3144                         memcpy(*acl_inf, pdata, *pbuflen);
3145                 }
3146         }
3147 qsec_out:
3148         if (buf_type == CIFS_SMALL_BUFFER)
3149                 cifs_small_buf_release(iov[0].iov_base);
3150         else if (buf_type == CIFS_LARGE_BUFFER)
3151                 cifs_buf_release(iov[0].iov_base);
3152 /*      cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3153         return rc;
3154 }
3155
3156 int
3157 CIFSSMBSetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3158                         struct cifs_ntsd *pntsd, __u32 acllen)
3159 {
3160         __u16 byte_count, param_count, data_count, param_offset, data_offset;
3161         int rc = 0;
3162         int bytes_returned = 0;
3163         SET_SEC_DESC_REQ *pSMB = NULL;
3164         NTRANSACT_RSP *pSMBr = NULL;
3165
3166 setCifsAclRetry:
3167         rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB,
3168                         (void **) &pSMBr);
3169         if (rc)
3170                         return (rc);
3171
3172         pSMB->MaxSetupCount = 0;
3173         pSMB->Reserved = 0;
3174
3175         param_count = 8;
3176         param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4;
3177         data_count = acllen;
3178         data_offset = param_offset + param_count;
3179         byte_count = 3 /* pad */  + param_count;
3180
3181         pSMB->DataCount = cpu_to_le32(data_count);
3182         pSMB->TotalDataCount = pSMB->DataCount;
3183         pSMB->MaxParameterCount = cpu_to_le32(4);
3184         pSMB->MaxDataCount = cpu_to_le32(16384);
3185         pSMB->ParameterCount = cpu_to_le32(param_count);
3186         pSMB->ParameterOffset = cpu_to_le32(param_offset);
3187         pSMB->TotalParameterCount = pSMB->ParameterCount;
3188         pSMB->DataOffset = cpu_to_le32(data_offset);
3189         pSMB->SetupCount = 0;
3190         pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC);
3191         pSMB->ByteCount = cpu_to_le16(byte_count+data_count);
3192
3193         pSMB->Fid = fid; /* file handle always le */
3194         pSMB->Reserved2 = 0;
3195         pSMB->AclFlags = cpu_to_le32(CIFS_ACL_DACL);
3196
3197         if (pntsd && acllen) {
3198                 memcpy((char *) &pSMBr->hdr.Protocol + data_offset,
3199                         (char *) pntsd,
3200                         acllen);
3201                 pSMB->hdr.smb_buf_length += (byte_count + data_count);
3202
3203         } else
3204                 pSMB->hdr.smb_buf_length += byte_count;
3205
3206         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3207                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3208
3209         cFYI(1, ("SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc));
3210         if (rc)
3211                 cFYI(1, ("Set CIFS ACL returned %d", rc));
3212         cifs_buf_release(pSMB);
3213
3214         if (rc == -EAGAIN)
3215                 goto setCifsAclRetry;
3216
3217         return (rc);
3218 }
3219
3220 #endif /* CONFIG_CIFS_EXPERIMENTAL */
3221
3222 /* Legacy Query Path Information call for lookup to old servers such
3223    as Win9x/WinME */
3224 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
3225                         const unsigned char *searchName,
3226                         FILE_ALL_INFO *pFinfo,
3227                         const struct nls_table *nls_codepage, int remap)
3228 {
3229         QUERY_INFORMATION_REQ *pSMB;
3230         QUERY_INFORMATION_RSP *pSMBr;
3231         int rc = 0;
3232         int bytes_returned;
3233         int name_len;
3234
3235         cFYI(1, ("In SMBQPath path %s", searchName));
3236 QInfRetry:
3237         rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
3238                       (void **) &pSMBr);
3239         if (rc)
3240                 return rc;
3241
3242         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3243                 name_len =
3244                         cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3245                                         PATH_MAX, nls_codepage, remap);
3246                 name_len++;     /* trailing null */
3247                 name_len *= 2;
3248         } else {
3249                 name_len = strnlen(searchName, PATH_MAX);
3250                 name_len++;     /* trailing null */
3251                 strncpy(pSMB->FileName, searchName, name_len);
3252         }
3253         pSMB->BufferFormat = 0x04;
3254         name_len++; /* account for buffer type byte */
3255         pSMB->hdr.smb_buf_length += (__u16) name_len;
3256         pSMB->ByteCount = cpu_to_le16(name_len);
3257
3258         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3259                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3260         if (rc) {
3261                 cFYI(1, ("Send error in QueryInfo = %d", rc));
3262         } else if (pFinfo) {
3263                 struct timespec ts;
3264                 __u32 time = le32_to_cpu(pSMBr->last_write_time);
3265
3266                 /* decode response */
3267                 /* BB FIXME - add time zone adjustment BB */
3268                 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
3269                 ts.tv_nsec = 0;
3270                 ts.tv_sec = time;
3271                 /* decode time fields */
3272                 pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
3273                 pFinfo->LastWriteTime = pFinfo->ChangeTime;
3274                 pFinfo->LastAccessTime = 0;
3275                 pFinfo->AllocationSize =
3276                         cpu_to_le64(le32_to_cpu(pSMBr->size));
3277                 pFinfo->EndOfFile = pFinfo->AllocationSize;
3278                 pFinfo->Attributes =
3279                         cpu_to_le32(le16_to_cpu(pSMBr->attr));
3280         } else
3281                 rc = -EIO; /* bad buffer passed in */
3282
3283         cifs_buf_release(pSMB);
3284
3285         if (rc == -EAGAIN)
3286                 goto QInfRetry;
3287
3288         return rc;
3289 }
3290
3291
3292
3293
3294 int
3295 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
3296                  const unsigned char *searchName,
3297                  FILE_ALL_INFO *pFindData,
3298                  int legacy /* old style infolevel */,
3299                  const struct nls_table *nls_codepage, int remap)
3300 {
3301 /* level 263 SMB_QUERY_FILE_ALL_INFO */
3302         TRANSACTION2_QPI_REQ *pSMB = NULL;
3303         TRANSACTION2_QPI_RSP *pSMBr = NULL;
3304         int rc = 0;
3305         int bytes_returned;
3306         int name_len;
3307         __u16 params, byte_count;
3308
3309 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
3310 QPathInfoRetry:
3311         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3312                       (void **) &pSMBr);
3313         if (rc)
3314                 return rc;
3315
3316         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3317                 name_len =
3318                     cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3319                                      PATH_MAX, nls_codepage, remap);
3320                 name_len++;     /* trailing null */
3321                 name_len *= 2;
3322         } else {        /* BB improve the check for buffer overruns BB */
3323                 name_len = strnlen(searchName, PATH_MAX);
3324                 name_len++;     /* trailing null */
3325                 strncpy(pSMB->FileName, searchName, name_len);
3326         }
3327
3328         params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3329         pSMB->TotalDataCount = 0;
3330         pSMB->MaxParameterCount = cpu_to_le16(2);
3331         /* BB find exact max SMB PDU from sess structure BB */
3332         pSMB->MaxDataCount = cpu_to_le16(4000);
3333         pSMB->MaxSetupCount = 0;
3334         pSMB->Reserved = 0;
3335         pSMB->Flags = 0;
3336         pSMB->Timeout = 0;
3337         pSMB->Reserved2 = 0;
3338         pSMB->ParameterOffset = cpu_to_le16(offsetof(
3339         struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3340         pSMB->DataCount = 0;
3341         pSMB->DataOffset = 0;
3342         pSMB->SetupCount = 1;
3343         pSMB->Reserved3 = 0;
3344         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3345         byte_count = params + 1 /* pad */ ;
3346         pSMB->TotalParameterCount = cpu_to_le16(params);
3347         pSMB->ParameterCount = pSMB->TotalParameterCount;
3348         if (legacy)
3349                 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
3350         else
3351                 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3352         pSMB->Reserved4 = 0;
3353         pSMB->hdr.smb_buf_length += byte_count;
3354         pSMB->ByteCount = cpu_to_le16(byte_count);
3355
3356         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3357                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3358         if (rc) {
3359                 cFYI(1, ("Send error in QPathInfo = %d", rc));
3360         } else {                /* decode response */
3361                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3362
3363                 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3364                         rc = -EIO;
3365                 else if (!legacy && (pSMBr->ByteCount < 40))
3366                         rc = -EIO;      /* bad smb */
3367                 else if (legacy && (pSMBr->ByteCount < 24))
3368                         rc = -EIO;  /* 24 or 26 expected but we do not read
3369                                         last field */
3370                 else if (pFindData) {
3371                         int size;
3372                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3373
3374                         /* On legacy responses we do not read the last field,
3375                         EAsize, fortunately since it varies by subdialect and
3376                         also note it differs on Set vs. Get, ie two bytes or 4
3377                         bytes depending but we don't care here */
3378                         if (legacy)
3379                                 size = sizeof(FILE_INFO_STANDARD);
3380                         else
3381                                 size = sizeof(FILE_ALL_INFO);
3382                         memcpy((char *) pFindData,
3383                                (char *) &pSMBr->hdr.Protocol +
3384                                data_offset, size);
3385                 } else
3386                     rc = -ENOMEM;
3387         }
3388         cifs_buf_release(pSMB);
3389         if (rc == -EAGAIN)
3390                 goto QPathInfoRetry;
3391
3392         return rc;
3393 }
3394
3395 int
3396 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3397                      const unsigned char *searchName,
3398                      FILE_UNIX_BASIC_INFO *pFindData,
3399                      const struct nls_table *nls_codepage, int remap)
3400 {
3401 /* SMB_QUERY_FILE_UNIX_BASIC */
3402         TRANSACTION2_QPI_REQ *pSMB = NULL;
3403         TRANSACTION2_QPI_RSP *pSMBr = NULL;
3404         int rc = 0;
3405         int bytes_returned = 0;
3406         int name_len;
3407         __u16 params, byte_count;
3408
3409         cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
3410 UnixQPathInfoRetry:
3411         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3412                       (void **) &pSMBr);
3413         if (rc)
3414                 return rc;
3415
3416         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3417                 name_len =
3418                     cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3419                                   PATH_MAX, nls_codepage, remap);
3420                 name_len++;     /* trailing null */
3421                 name_len *= 2;
3422         } else {        /* BB improve the check for buffer overruns BB */
3423                 name_len = strnlen(searchName, PATH_MAX);
3424                 name_len++;     /* trailing null */
3425                 strncpy(pSMB->FileName, searchName, name_len);
3426         }
3427
3428         params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
3429         pSMB->TotalDataCount = 0;
3430         pSMB->MaxParameterCount = cpu_to_le16(2);
3431         /* BB find exact max SMB PDU from sess structure BB */
3432         pSMB->MaxDataCount = cpu_to_le16(4000);
3433         pSMB->MaxSetupCount = 0;
3434         pSMB->Reserved = 0;
3435         pSMB->Flags = 0;
3436         pSMB->Timeout = 0;
3437         pSMB->Reserved2 = 0;
3438         pSMB->ParameterOffset = cpu_to_le16(offsetof(
3439         struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3440         pSMB->DataCount = 0;
3441         pSMB->DataOffset = 0;
3442         pSMB->SetupCount = 1;
3443         pSMB->Reserved3 = 0;
3444         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3445         byte_count = params + 1 /* pad */ ;
3446         pSMB->TotalParameterCount = cpu_to_le16(params);
3447         pSMB->ParameterCount = pSMB->TotalParameterCount;
3448         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3449         pSMB->Reserved4 = 0;
3450         pSMB->hdr.smb_buf_length += byte_count;
3451         pSMB->ByteCount = cpu_to_le16(byte_count);
3452
3453         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3454                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3455         if (rc) {
3456                 cFYI(1, ("Send error in QPathInfo = %d", rc));
3457         } else {                /* decode response */
3458                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3459
3460                 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3461                         cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3462                                    "Unix Extensions can be disabled on mount "
3463                                    "by specifying the nosfu mount option."));
3464                         rc = -EIO;      /* bad smb */
3465                 } else {
3466                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3467                         memcpy((char *) pFindData,
3468                                (char *) &pSMBr->hdr.Protocol +
3469                                data_offset,
3470                                sizeof(FILE_UNIX_BASIC_INFO));
3471                 }
3472         }
3473         cifs_buf_release(pSMB);
3474         if (rc == -EAGAIN)
3475                 goto UnixQPathInfoRetry;
3476
3477         return rc;
3478 }
3479
3480 /* xid, tcon, searchName and codepage are input parms, rest are returned */
3481 int
3482 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
3483               const char *searchName,
3484               const struct nls_table *nls_codepage,
3485               __u16 *pnetfid,
3486               struct cifs_search_info *psrch_inf, int remap, const char dirsep)
3487 {
3488 /* level 257 SMB_ */
3489         TRANSACTION2_FFIRST_REQ *pSMB = NULL;
3490         TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
3491         T2_FFIRST_RSP_PARMS *parms;
3492         int rc = 0;
3493         int bytes_returned = 0;
3494         int name_len;
3495         __u16 params, byte_count;
3496
3497         cFYI(1, ("In FindFirst for %s", searchName));
3498
3499 findFirstRetry:
3500         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3501                       (void **) &pSMBr);
3502         if (rc)
3503                 return rc;
3504
3505         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3506                 name_len =
3507                     cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3508                                  PATH_MAX, nls_codepage, remap);
3509                 /* We can not add the asterik earlier in case
3510                 it got remapped to 0xF03A as if it were part of the
3511                 directory name instead of a wildcard */
3512                 name_len *= 2;
3513                 pSMB->FileName[name_len] = dirsep;
3514                 pSMB->FileName[name_len+1] = 0;
3515                 pSMB->FileName[name_len+2] = '*';
3516                 pSMB->FileName[name_len+3] = 0;
3517                 name_len += 4; /* now the trailing null */
3518                 pSMB->FileName[name_len] = 0; /* null terminate just in case */
3519                 pSMB->FileName[name_len+1] = 0;
3520                 name_len += 2;
3521         } else {        /* BB add check for overrun of SMB buf BB */
3522                 name_len = strnlen(searchName, PATH_MAX);
3523 /* BB fix here and in unicode clause above ie
3524                 if (name_len > buffersize-header)
3525                         free buffer exit; BB */
3526                 strncpy(pSMB->FileName, searchName, name_len);
3527                 pSMB->FileName[name_len] = dirsep;
3528                 pSMB->FileName[name_len+1] = '*';
3529                 pSMB->FileName[name_len+2] = 0;
3530                 name_len += 3;
3531         }
3532
3533         params = 12 + name_len /* includes null */ ;
3534         pSMB->TotalDataCount = 0;       /* no EAs */
3535         pSMB->MaxParameterCount = cpu_to_le16(10);
3536         pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
3537                                           MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
3538         pSMB->MaxSetupCount = 0;
3539         pSMB->Reserved = 0;
3540         pSMB->Flags = 0;
3541         pSMB->Timeout = 0;
3542         pSMB->Reserved2 = 0;
3543         byte_count = params + 1 /* pad */ ;
3544         pSMB->TotalParameterCount = cpu_to_le16(params);
3545         pSMB->ParameterCount = pSMB->TotalParameterCount;
3546         pSMB->ParameterOffset = cpu_to_le16(
3547               offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
3548                 - 4);
3549         pSMB->DataCount = 0;
3550         pSMB->DataOffset = 0;
3551         pSMB->SetupCount = 1;   /* one byte, no need to make endian neutral */
3552         pSMB->Reserved3 = 0;
3553         pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
3554         pSMB->SearchAttributes =
3555             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
3556                         ATTR_DIRECTORY);
3557         pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
3558         pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
3559                 CIFS_SEARCH_RETURN_RESUME);
3560         pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3561
3562         /* BB what should we set StorageType to? Does it matter? BB */
3563         pSMB->SearchStorageType = 0;
3564         pSMB->hdr.smb_buf_length += byte_count;
3565         pSMB->ByteCount = cpu_to_le16(byte_count);
3566
3567         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3568                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3569         cifs_stats_inc(&tcon->num_ffirst);
3570
3571         if (rc) {/* BB add logic to retry regular search if Unix search
3572                         rejected unexpectedly by server */
3573                 /* BB Add code to handle unsupported level rc */
3574                 cFYI(1, ("Error in FindFirst = %d", rc));
3575
3576                 cifs_buf_release(pSMB);
3577
3578                 /* BB eventually could optimize out free and realloc of buf */
3579                 /*    for this case */
3580                 if (rc == -EAGAIN)
3581                         goto findFirstRetry;
3582         } else { /* decode response */
3583                 /* BB remember to free buffer if error BB */
3584                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3585                 if (rc == 0) {
3586                         unsigned int lnoff;
3587
3588                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3589                                 psrch_inf->unicode = true;
3590                         else
3591                                 psrch_inf->unicode = false;
3592
3593                         psrch_inf->ntwrk_buf_start = (char *)pSMBr;
3594                         psrch_inf->smallBuf = 0;
3595                         psrch_inf->srch_entries_start =
3596                                 (char *) &pSMBr->hdr.Protocol +
3597                                         le16_to_cpu(pSMBr->t2.DataOffset);
3598                         parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
3599                                le16_to_cpu(pSMBr->t2.ParameterOffset));
3600
3601                         if (parms->EndofSearch)
3602                                 psrch_inf->endOfSearch = true;
3603                         else
3604                                 psrch_inf->endOfSearch = false;
3605
3606                         psrch_inf->entries_in_buffer =
3607                                         le16_to_cpu(parms->SearchCount);
3608                         psrch_inf->index_of_last_entry = 2 /* skip . and .. */ +
3609                                 psrch_inf->entries_in_buffer;
3610                         lnoff = le16_to_cpu(parms->LastNameOffset);
3611                         if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3612                               lnoff) {
3613                                 cERROR(1, ("ignoring corrupt resume name"));
3614                                 psrch_inf->last_entry = NULL;
3615                                 return rc;
3616                         }
3617
3618                         psrch_inf->last_entry = psrch_inf->srch_entries_start +
3619                                                         lnoff;
3620
3621                         *pnetfid = parms->SearchHandle;
3622                 } else {
3623                         cifs_buf_release(pSMB);
3624                 }
3625         }
3626
3627         return rc;
3628 }
3629
3630 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
3631                  __u16 searchHandle, struct cifs_search_info *psrch_inf)
3632 {
3633         TRANSACTION2_FNEXT_REQ *pSMB = NULL;
3634         TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
3635         T2_FNEXT_RSP_PARMS *parms;
3636         char *response_data;
3637         int rc = 0;
3638         int bytes_returned, name_len;
3639         __u16 params, byte_count;
3640
3641         cFYI(1, ("In FindNext"));
3642
3643         if (psrch_inf->endOfSearch)
3644                 return -ENOENT;
3645
3646         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3647                 (void **) &pSMBr);
3648         if (rc)
3649                 return rc;
3650
3651         params = 14; /* includes 2 bytes of null string, converted to LE below*/
3652         byte_count = 0;
3653         pSMB->TotalDataCount = 0;       /* no EAs */
3654         pSMB->MaxParameterCount = cpu_to_le16(8);
3655         pSMB->MaxDataCount =
3656                 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) &
3657                                 0xFFFFFF00);
3658         pSMB->MaxSetupCount = 0;
3659         pSMB->Reserved = 0;
3660         pSMB->Flags = 0;
3661         pSMB->Timeout = 0;
3662         pSMB->Reserved2 = 0;
3663         pSMB->ParameterOffset =  cpu_to_le16(
3664               offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
3665         pSMB->DataCount = 0;
3666         pSMB->DataOffset = 0;
3667         pSMB->SetupCount = 1;
3668         pSMB->Reserved3 = 0;
3669         pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
3670         pSMB->SearchHandle = searchHandle;      /* always kept as le */
3671         pSMB->SearchCount =
3672                 cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
3673         pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
3674         pSMB->ResumeKey = psrch_inf->resume_key;
3675         pSMB->SearchFlags =
3676               cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
3677
3678         name_len = psrch_inf->resume_name_len;
3679         params += name_len;
3680         if (name_len < PATH_MAX) {
3681                 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
3682                 byte_count += name_len;
3683                 /* 14 byte parm len above enough for 2 byte null terminator */
3684                 pSMB->ResumeFileName[name_len] = 0;
3685                 pSMB->ResumeFileName[name_len+1] = 0;
3686         } else {
3687                 rc = -EINVAL;
3688                 goto FNext2_err_exit;
3689         }
3690         byte_count = params + 1 /* pad */ ;
3691         pSMB->TotalParameterCount = cpu_to_le16(params);
3692         pSMB->ParameterCount = pSMB->TotalParameterCount;
3693         pSMB->hdr.smb_buf_length += byte_count;
3694         pSMB->ByteCount = cpu_to_le16(byte_count);
3695
3696         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3697                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3698         cifs_stats_inc(&tcon->num_fnext);
3699         if (rc) {
3700                 if (rc == -EBADF) {
3701                         psrch_inf->endOfSearch = true;
3702                         cifs_buf_release(pSMB);
3703                         rc = 0; /* search probably was closed at end of search*/
3704                 } else
3705                         cFYI(1, ("FindNext returned = %d", rc));
3706         } else {                /* decode response */
3707                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3708
3709                 if (rc == 0) {
3710                         unsigned int lnoff;
3711
3712                         /* BB fixme add lock for file (srch_info) struct here */
3713                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3714                                 psrch_inf->unicode = true;
3715                         else
3716                                 psrch_inf->unicode = false;
3717                         response_data = (char *) &pSMBr->hdr.Protocol +
3718                                le16_to_cpu(pSMBr->t2.ParameterOffset);
3719                         parms = (T2_FNEXT_RSP_PARMS *)response_data;
3720                         response_data = (char *)&pSMBr->hdr.Protocol +
3721                                 le16_to_cpu(pSMBr->t2.DataOffset);
3722                         if (psrch_inf->smallBuf)
3723                                 cifs_small_buf_release(
3724                                         psrch_inf->ntwrk_buf_start);
3725                         else
3726                                 cifs_buf_release(psrch_inf->ntwrk_buf_start);
3727                         psrch_inf->srch_entries_start = response_data;
3728                         psrch_inf->ntwrk_buf_start = (char *)pSMB;
3729                         psrch_inf->smallBuf = 0;
3730                         if (parms->EndofSearch)
3731                                 psrch_inf->endOfSearch = true;
3732                         else
3733                                 psrch_inf->endOfSearch = false;
3734                         psrch_inf->entries_in_buffer =
3735                                                 le16_to_cpu(parms->SearchCount);
3736                         psrch_inf->index_of_last_entry +=
3737                                 psrch_inf->entries_in_buffer;
3738                         lnoff = le16_to_cpu(parms->LastNameOffset);
3739                         if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
3740                               lnoff) {
3741                                 cERROR(1, ("ignoring corrupt resume name"));
3742                                 psrch_inf->last_entry = NULL;
3743                                 return rc;
3744                         } else
3745                                 psrch_inf->last_entry =
3746                                         psrch_inf->srch_entries_start + lnoff;
3747
3748 /*  cFYI(1,("fnxt2 entries in buf %d index_of_last %d",
3749             psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */
3750
3751                         /* BB fixme add unlock here */
3752                 }
3753
3754         }
3755
3756         /* BB On error, should we leave previous search buf (and count and
3757         last entry fields) intact or free the previous one? */
3758
3759         /* Note: On -EAGAIN error only caller can retry on handle based calls
3760         since file handle passed in no longer valid */
3761 FNext2_err_exit:
3762         if (rc != 0)
3763                 cifs_buf_release(pSMB);
3764         return rc;
3765 }
3766
3767 int
3768 CIFSFindClose(const int xid, struct cifsTconInfo *tcon,
3769               const __u16 searchHandle)
3770 {
3771         int rc = 0;
3772         FINDCLOSE_REQ *pSMB = NULL;
3773
3774         cFYI(1, ("In CIFSSMBFindClose"));
3775         rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
3776
3777         /* no sense returning error if session restarted
3778                 as file handle has been closed */
3779         if (rc == -EAGAIN)
3780                 return 0;
3781         if (rc)
3782                 return rc;
3783
3784         pSMB->FileID = searchHandle;
3785         pSMB->ByteCount = 0;
3786         rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
3787         if (rc)
3788                 cERROR(1, ("Send error in FindClose = %d", rc));
3789
3790         cifs_stats_inc(&tcon->num_fclose);
3791
3792         /* Since session is dead, search handle closed on server already */
3793         if (rc == -EAGAIN)
3794                 rc = 0;
3795
3796         return rc;
3797 }
3798
3799 int
3800 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
3801                       const unsigned char *searchName,
3802                       __u64 *inode_number,
3803                       const struct nls_table *nls_codepage, int remap)
3804 {
3805         int rc = 0;
3806         TRANSACTION2_QPI_REQ *pSMB = NULL;
3807         TRANSACTION2_QPI_RSP *pSMBr = NULL;
3808         int name_len, bytes_returned;
3809         __u16 params, byte_count;
3810
3811         cFYI(1, ("In GetSrvInodeNum for %s", searchName));
3812         if (tcon == NULL)
3813                 return -ENODEV;
3814
3815 GetInodeNumberRetry:
3816         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3817                       (void **) &pSMBr);
3818         if (rc)
3819                 return rc;
3820
3821         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3822                 name_len =
3823                         cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
3824                                          PATH_MAX, nls_codepage, remap);
3825                 name_len++;     /* trailing null */
3826                 name_len *= 2;
3827         } else {        /* BB improve the check for buffer overruns BB */
3828                 name_len = strnlen(searchName, PATH_MAX);
3829                 name_len++;     /* trailing null */
3830                 strncpy(pSMB->FileName, searchName, name_len);
3831         }
3832
3833         params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
3834         pSMB->TotalDataCount = 0;
3835         pSMB->MaxParameterCount = cpu_to_le16(2);
3836         /* BB find exact max data count below from sess structure BB */
3837         pSMB->MaxDataCount = cpu_to_le16(4000);
3838         pSMB->MaxSetupCount = 0;
3839         pSMB->Reserved = 0;
3840         pSMB->Flags = 0;
3841         pSMB->Timeout = 0;
3842         pSMB->Reserved2 = 0;
3843         pSMB->ParameterOffset = cpu_to_le16(offsetof(
3844                 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
3845         pSMB->DataCount = 0;
3846         pSMB->DataOffset = 0;
3847         pSMB->SetupCount = 1;
3848         pSMB->Reserved3 = 0;
3849         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3850         byte_count = params + 1 /* pad */ ;
3851         pSMB->TotalParameterCount = cpu_to_le16(params);
3852         pSMB->ParameterCount = pSMB->TotalParameterCount;
3853         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3854         pSMB->Reserved4 = 0;
3855         pSMB->hdr.smb_buf_length += byte_count;
3856         pSMB->ByteCount = cpu_to_le16(byte_count);
3857
3858         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3859                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3860         if (rc) {
3861                 cFYI(1, ("error %d in QueryInternalInfo", rc));
3862         } else {
3863                 /* decode response */
3864                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3865                 if (rc || (pSMBr->ByteCount < 2))
3866                 /* BB also check enough total bytes returned */
3867                         /* If rc should we check for EOPNOSUPP and
3868                         disable the srvino flag? or in caller? */
3869                         rc = -EIO;      /* bad smb */
3870                 else {
3871                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3872                         __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3873                         struct file_internal_info *pfinfo;
3874                         /* BB Do we need a cast or hash here ? */
3875                         if (count < 8) {
3876                                 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3877                                 rc = -EIO;
3878                                 goto GetInodeNumOut;
3879                         }
3880                         pfinfo = (struct file_internal_info *)
3881                                 (data_offset + (char *) &pSMBr->hdr.Protocol);
3882                         *inode_number = le64_to_cpu(pfinfo->UniqueId);
3883                 }
3884         }
3885 GetInodeNumOut:
3886         cifs_buf_release(pSMB);
3887         if (rc == -EAGAIN)
3888                 goto GetInodeNumberRetry;
3889         return rc;
3890 }
3891
3892 /* parses DFS refferal V3 structure
3893  * caller is responsible for freeing target_nodes
3894  * returns:
3895  *      on success - 0
3896  *      on failure - errno
3897  */
3898 static int
3899 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
3900                 unsigned int *num_of_nodes,
3901                 struct dfs_info3_param **target_nodes,
3902                 const struct nls_table *nls_codepage, int remap,
3903                 const char *searchName)
3904 {
3905         int i, rc = 0;
3906         char *data_end;
3907         bool is_unicode;
3908         struct dfs_referral_level_3 *ref;
3909
3910         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3911                 is_unicode = true;
3912         else
3913                 is_unicode = false;
3914         *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
3915
3916         if (*num_of_nodes < 1) {
3917                 cERROR(1, ("num_referrals: must be at least > 0,"
3918                         "but we get num_referrals = %d\n", *num_of_nodes));
3919                 rc = -EINVAL;
3920                 goto parse_DFS_referrals_exit;
3921         }
3922
3923         ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
3924         if (ref->VersionNumber != cpu_to_le16(3)) {
3925                 cERROR(1, ("Referrals of V%d version are not supported,"
3926                         "should be V3", le16_to_cpu(ref->VersionNumber)));
3927                 rc = -EINVAL;
3928                 goto parse_DFS_referrals_exit;
3929         }
3930
3931         /* get the upper boundary of the resp buffer */
3932         data_end = (char *)(&(pSMBr->PathConsumed)) +
3933                                 le16_to_cpu(pSMBr->t2.DataCount);
3934
3935         cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n",
3936                         *num_of_nodes,
3937                         le32_to_cpu(pSMBr->DFSFlags)));
3938
3939         *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
3940                         *num_of_nodes, GFP_KERNEL);
3941         if (*target_nodes == NULL) {
3942                 cERROR(1, ("Failed to allocate buffer for target_nodes\n"));
3943                 rc = -ENOMEM;
3944                 goto parse_DFS_referrals_exit;
3945         }
3946
3947         /* collect neccessary data from referrals */
3948         for (i = 0; i < *num_of_nodes; i++) {
3949                 char *temp;
3950                 int max_len;
3951                 struct dfs_info3_param *node = (*target_nodes)+i;
3952
3953                 node->flags = le32_to_cpu(pSMBr->DFSFlags);
3954                 if (is_unicode) {
3955                         __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
3956                                                 GFP_KERNEL);
3957                         cifsConvertToUCS((__le16 *) tmp, searchName,
3958                                         PATH_MAX, nls_codepage, remap);
3959                         node->path_consumed = cifs_ucs2_bytes(tmp,
3960                                         le16_to_cpu(pSMBr->PathConsumed),
3961                                         nls_codepage);
3962                         kfree(tmp);
3963                 } else
3964                         node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
3965
3966                 node->server_type = le16_to_cpu(ref->ServerType);
3967                 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
3968
3969                 /* copy DfsPath */
3970                 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
3971                 max_len = data_end - temp;
3972                 node->path_name = cifs_strndup_from_ucs(temp, max_len,
3973                                                       is_unicode, nls_codepage);
3974                 if (IS_ERR(node->path_name)) {
3975                         rc = PTR_ERR(node->path_name);
3976                         node->path_name = NULL;
3977                         goto parse_DFS_referrals_exit;
3978                 }
3979
3980                 /* copy link target UNC */
3981                 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
3982                 max_len = data_end - temp;
3983                 node->node_name = cifs_strndup_from_ucs(temp, max_len,
3984                                                       is_unicode, nls_codepage);
3985                 if (IS_ERR(node->node_name)) {
3986                         rc = PTR_ERR(node->node_name);
3987                         node->node_name = NULL;
3988                         goto parse_DFS_referrals_exit;
3989                 }
3990         }
3991
3992 parse_DFS_referrals_exit:
3993         if (rc) {
3994                 free_dfs_info_array(*target_nodes, *num_of_nodes);
3995                 *target_nodes = NULL;
3996                 *num_of_nodes = 0;
3997         }
3998         return rc;
3999 }
4000
4001 int
4002 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
4003                 const unsigned char *searchName,
4004                 struct dfs_info3_param **target_nodes,
4005                 unsigned int *num_of_nodes,
4006                 const struct nls_table *nls_codepage, int remap)
4007 {
4008 /* TRANS2_GET_DFS_REFERRAL */
4009         TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4010         TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4011         int rc = 0;
4012         int bytes_returned;
4013         int name_len;
4014         __u16 params, byte_count;
4015         *num_of_nodes = 0;
4016         *target_nodes = NULL;
4017
4018         cFYI(1, ("In GetDFSRefer the path %s", searchName));
4019         if (ses == NULL)
4020                 return -ENODEV;
4021 getDFSRetry:
4022         rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4023                       (void **) &pSMBr);
4024         if (rc)
4025                 return rc;
4026
4027         /* server pointer checked in called function,
4028         but should never be null here anyway */
4029         pSMB->hdr.Mid = GetNextMid(ses->server);
4030         pSMB->hdr.Tid = ses->ipc_tid;
4031         pSMB->hdr.Uid = ses->Suid;
4032         if (ses->capabilities & CAP_STATUS32)
4033                 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4034         if (ses->capabilities & CAP_DFS)
4035                 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4036
4037         if (ses->capabilities & CAP_UNICODE) {
4038                 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4039                 name_len =
4040                     cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
4041                                      searchName, PATH_MAX, nls_codepage, remap);
4042                 name_len++;     /* trailing null */
4043                 name_len *= 2;
4044         } else {        /* BB improve the check for buffer overruns BB */
4045                 name_len = strnlen(searchName, PATH_MAX);
4046                 name_len++;     /* trailing null */
4047                 strncpy(pSMB->RequestFileName, searchName, name_len);
4048         }
4049
4050         if (ses->server) {
4051                 if (ses->server->secMode &
4052                    (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4053                         pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4054         }
4055
4056         pSMB->hdr.Uid = ses->Suid;
4057
4058         params = 2 /* level */  + name_len /*includes null */ ;
4059         pSMB->TotalDataCount = 0;
4060         pSMB->DataCount = 0;
4061         pSMB->DataOffset = 0;
4062         pSMB->MaxParameterCount = 0;
4063         /* BB find exact max SMB PDU from sess structure BB */
4064         pSMB->MaxDataCount = cpu_to_le16(4000);
4065         pSMB->MaxSetupCount = 0;
4066         pSMB->Reserved = 0;
4067         pSMB->Flags = 0;
4068         pSMB->Timeout = 0;
4069         pSMB->Reserved2 = 0;
4070         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4071           struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4072         pSMB->SetupCount = 1;
4073         pSMB->Reserved3 = 0;
4074         pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4075         byte_count = params + 3 /* pad */ ;
4076         pSMB->ParameterCount = cpu_to_le16(params);
4077         pSMB->TotalParameterCount = pSMB->ParameterCount;
4078         pSMB->MaxReferralLevel = cpu_to_le16(3);
4079         pSMB->hdr.smb_buf_length += byte_count;
4080         pSMB->ByteCount = cpu_to_le16(byte_count);
4081
4082         rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4083                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4084         if (rc) {
4085                 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
4086                 goto GetDFSRefExit;
4087         }
4088         rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4089
4090         /* BB Also check if enough total bytes returned? */
4091         if (rc || (pSMBr->ByteCount < 17)) {
4092                 rc = -EIO;      /* bad smb */
4093                 goto GetDFSRefExit;
4094         }
4095
4096         cFYI(1, ("Decoding GetDFSRefer response BCC: %d  Offset %d",
4097                                 pSMBr->ByteCount,
4098                                 le16_to_cpu(pSMBr->t2.DataOffset)));
4099
4100         /* parse returned result into more usable form */
4101         rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4102                                  target_nodes, nls_codepage, remap,
4103                                  searchName);
4104
4105 GetDFSRefExit:
4106         cifs_buf_release(pSMB);
4107
4108         if (rc == -EAGAIN)
4109                 goto getDFSRetry;
4110
4111         return rc;
4112 }
4113
4114 /* Query File System Info such as free space to old servers such as Win 9x */
4115 int
4116 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4117 {
4118 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4119         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4120         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4121         FILE_SYSTEM_ALLOC_INFO *response_data;
4122         int rc = 0;
4123         int bytes_returned = 0;
4124         __u16 params, byte_count;
4125
4126         cFYI(1, ("OldQFSInfo"));
4127 oldQFSInfoRetry:
4128         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4129                 (void **) &pSMBr);
4130         if (rc)
4131                 return rc;
4132
4133         params = 2;     /* level */
4134         pSMB->TotalDataCount = 0;
4135         pSMB->MaxParameterCount = cpu_to_le16(2);
4136         pSMB->MaxDataCount = cpu_to_le16(1000);
4137         pSMB->MaxSetupCount = 0;
4138         pSMB->Reserved = 0;
4139         pSMB->Flags = 0;
4140         pSMB->Timeout = 0;
4141         pSMB->Reserved2 = 0;
4142         byte_count = params + 1 /* pad */ ;
4143         pSMB->TotalParameterCount = cpu_to_le16(params);
4144         pSMB->ParameterCount = pSMB->TotalParameterCount;
4145         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4146         struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4147         pSMB->DataCount = 0;
4148         pSMB->DataOffset = 0;
4149         pSMB->SetupCount = 1;
4150         pSMB->Reserved3 = 0;
4151         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4152         pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4153         pSMB->hdr.smb_buf_length += byte_count;
4154         pSMB->ByteCount = cpu_to_le16(byte_count);
4155
4156         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4157                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4158         if (rc) {
4159                 cFYI(1, ("Send error in QFSInfo = %d", rc));
4160         } else {                /* decode response */
4161                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4162
4163                 if (rc || (pSMBr->ByteCount < 18))
4164                         rc = -EIO;      /* bad smb */
4165                 else {
4166                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4167                         cFYI(1, ("qfsinf resp BCC: %d  Offset %d",
4168                                  pSMBr->ByteCount, data_offset));
4169
4170                         response_data = (FILE_SYSTEM_ALLOC_INFO *)
4171                                 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4172                         FSData->f_bsize =
4173                                 le16_to_cpu(response_data->BytesPerSector) *
4174                                 le32_to_cpu(response_data->
4175                                         SectorsPerAllocationUnit);
4176                         FSData->f_blocks =
4177                                le32_to_cpu(response_data->TotalAllocationUnits);
4178                         FSData->f_bfree = FSData->f_bavail =
4179                                 le32_to_cpu(response_data->FreeAllocationUnits);
4180                         cFYI(1,
4181                              ("Blocks: %lld  Free: %lld Block size %ld",
4182                               (unsigned long long)FSData->f_blocks,
4183                               (unsigned long long)FSData->f_bfree,
4184                               FSData->f_bsize));
4185                 }
4186         }
4187         cifs_buf_release(pSMB);
4188
4189         if (rc == -EAGAIN)
4190                 goto oldQFSInfoRetry;
4191
4192         return rc;
4193 }
4194
4195 int
4196 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4197 {
4198 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4199         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4200         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4201         FILE_SYSTEM_INFO *response_data;
4202         int rc = 0;
4203         int bytes_returned = 0;
4204         __u16 params, byte_count;
4205
4206         cFYI(1, ("In QFSInfo"));
4207 QFSInfoRetry:
4208         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4209                       (void **) &pSMBr);
4210         if (rc)
4211                 return rc;
4212
4213         params = 2;     /* level */
4214         pSMB->TotalDataCount = 0;
4215         pSMB->MaxParameterCount = cpu_to_le16(2);
4216         pSMB->MaxDataCount = cpu_to_le16(1000);
4217         pSMB->MaxSetupCount = 0;
4218         pSMB->Reserved = 0;
4219         pSMB->Flags = 0;
4220         pSMB->Timeout = 0;
4221         pSMB->Reserved2 = 0;
4222         byte_count = params + 1 /* pad */ ;
4223         pSMB->TotalParameterCount = cpu_to_le16(params);
4224         pSMB->ParameterCount = pSMB->TotalParameterCount;
4225         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4226                 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4227         pSMB->DataCount = 0;
4228         pSMB->DataOffset = 0;
4229         pSMB->SetupCount = 1;
4230         pSMB->Reserved3 = 0;
4231         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4232         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4233         pSMB->hdr.smb_buf_length += byte_count;
4234         pSMB->ByteCount = cpu_to_le16(byte_count);
4235
4236         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4237                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4238         if (rc) {
4239                 cFYI(1, ("Send error in QFSInfo = %d", rc));
4240         } else {                /* decode response */
4241                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4242
4243                 if (rc || (pSMBr->ByteCount < 24))
4244                         rc = -EIO;      /* bad smb */
4245                 else {
4246                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4247
4248                         response_data =
4249                             (FILE_SYSTEM_INFO
4250                              *) (((char *) &pSMBr->hdr.Protocol) +
4251                                  data_offset);
4252                         FSData->f_bsize =
4253                             le32_to_cpu(response_data->BytesPerSector) *
4254                             le32_to_cpu(response_data->
4255                                         SectorsPerAllocationUnit);
4256                         FSData->f_blocks =
4257                             le64_to_cpu(response_data->TotalAllocationUnits);
4258                         FSData->f_bfree = FSData->f_bavail =
4259                             le64_to_cpu(response_data->FreeAllocationUnits);
4260                         cFYI(1,
4261                              ("Blocks: %lld  Free: %lld Block size %ld",
4262                               (unsigned long long)FSData->f_blocks,
4263                               (unsigned long long)FSData->f_bfree,
4264                               FSData->f_bsize));
4265                 }
4266         }
4267         cifs_buf_release(pSMB);
4268
4269         if (rc == -EAGAIN)
4270                 goto QFSInfoRetry;
4271
4272         return rc;
4273 }
4274
4275 int
4276 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4277 {
4278 /* level 0x105  SMB_QUERY_FILE_SYSTEM_INFO */
4279         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4280         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4281         FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4282         int rc = 0;
4283         int bytes_returned = 0;
4284         __u16 params, byte_count;
4285
4286         cFYI(1, ("In QFSAttributeInfo"));
4287 QFSAttributeRetry:
4288         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4289                       (void **) &pSMBr);
4290         if (rc)
4291                 return rc;
4292
4293         params = 2;     /* level */
4294         pSMB->TotalDataCount = 0;
4295         pSMB->MaxParameterCount = cpu_to_le16(2);
4296         /* BB find exact max SMB PDU from sess structure BB */
4297         pSMB->MaxDataCount = cpu_to_le16(1000);
4298         pSMB->MaxSetupCount = 0;
4299         pSMB->Reserved = 0;
4300         pSMB->Flags = 0;
4301         pSMB->Timeout = 0;
4302         pSMB->Reserved2 = 0;
4303         byte_count = params + 1 /* pad */ ;
4304         pSMB->TotalParameterCount = cpu_to_le16(params);
4305         pSMB->ParameterCount = pSMB->TotalParameterCount;
4306         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4307                 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4308         pSMB->DataCount = 0;
4309         pSMB->DataOffset = 0;
4310         pSMB->SetupCount = 1;
4311         pSMB->Reserved3 = 0;
4312         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4313         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4314         pSMB->hdr.smb_buf_length += byte_count;
4315         pSMB->ByteCount = cpu_to_le16(byte_count);
4316
4317         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4318                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4319         if (rc) {
4320                 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
4321         } else {                /* decode response */
4322                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4323
4324                 if (rc || (pSMBr->ByteCount < 13)) {
4325                         /* BB also check if enough bytes returned */
4326                         rc = -EIO;      /* bad smb */
4327                 } else {
4328                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4329                         response_data =
4330                             (FILE_SYSTEM_ATTRIBUTE_INFO
4331                              *) (((char *) &pSMBr->hdr.Protocol) +
4332                                  data_offset);
4333                         memcpy(&tcon->fsAttrInfo, response_data,
4334                                sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4335                 }
4336         }
4337         cifs_buf_release(pSMB);
4338
4339         if (rc == -EAGAIN)
4340                 goto QFSAttributeRetry;
4341
4342         return rc;
4343 }
4344
4345 int
4346 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4347 {
4348 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4349         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4350         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4351         FILE_SYSTEM_DEVICE_INFO *response_data;
4352         int rc = 0;
4353         int bytes_returned = 0;
4354         __u16 params, byte_count;
4355
4356         cFYI(1, ("In QFSDeviceInfo"));
4357 QFSDeviceRetry:
4358         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4359                       (void **) &pSMBr);
4360         if (rc)
4361                 return rc;
4362
4363         params = 2;     /* level */
4364         pSMB->TotalDataCount = 0;
4365         pSMB->MaxParameterCount = cpu_to_le16(2);
4366         /* BB find exact max SMB PDU from sess structure BB */
4367         pSMB->MaxDataCount = cpu_to_le16(1000);
4368         pSMB->MaxSetupCount = 0;
4369         pSMB->Reserved = 0;
4370         pSMB->Flags = 0;
4371         pSMB->Timeout = 0;
4372         pSMB->Reserved2 = 0;
4373         byte_count = params + 1 /* pad */ ;
4374         pSMB->TotalParameterCount = cpu_to_le16(params);
4375         pSMB->ParameterCount = pSMB->TotalParameterCount;
4376         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4377                 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4378
4379         pSMB->DataCount = 0;
4380         pSMB->DataOffset = 0;
4381         pSMB->SetupCount = 1;
4382         pSMB->Reserved3 = 0;
4383         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4384         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4385         pSMB->hdr.smb_buf_length += byte_count;
4386         pSMB->ByteCount = cpu_to_le16(byte_count);
4387
4388         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4389                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4390         if (rc) {
4391                 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
4392         } else {                /* decode response */
4393                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4394
4395                 if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO)))
4396                         rc = -EIO;      /* bad smb */
4397                 else {
4398                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4399                         response_data =
4400                             (FILE_SYSTEM_DEVICE_INFO *)
4401                                 (((char *) &pSMBr->hdr.Protocol) +
4402                                  data_offset);
4403                         memcpy(&tcon->fsDevInfo, response_data,
4404                                sizeof(FILE_SYSTEM_DEVICE_INFO));
4405                 }
4406         }
4407         cifs_buf_release(pSMB);
4408
4409         if (rc == -EAGAIN)
4410                 goto QFSDeviceRetry;
4411
4412         return rc;
4413 }
4414
4415 int
4416 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4417 {
4418 /* level 0x200  SMB_QUERY_CIFS_UNIX_INFO */
4419         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4420         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4421         FILE_SYSTEM_UNIX_INFO *response_data;
4422         int rc = 0;
4423         int bytes_returned = 0;
4424         __u16 params, byte_count;
4425
4426         cFYI(1, ("In QFSUnixInfo"));
4427 QFSUnixRetry:
4428         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4429                       (void **) &pSMBr);
4430         if (rc)
4431                 return rc;
4432
4433         params = 2;     /* level */
4434         pSMB->TotalDataCount = 0;
4435         pSMB->DataCount = 0;
4436         pSMB->DataOffset = 0;
4437         pSMB->MaxParameterCount = cpu_to_le16(2);
4438         /* BB find exact max SMB PDU from sess structure BB */
4439         pSMB->MaxDataCount = cpu_to_le16(100);
4440         pSMB->MaxSetupCount = 0;
4441         pSMB->Reserved = 0;
4442         pSMB->Flags = 0;
4443         pSMB->Timeout = 0;
4444         pSMB->Reserved2 = 0;
4445         byte_count = params + 1 /* pad */ ;
4446         pSMB->ParameterCount = cpu_to_le16(params);
4447         pSMB->TotalParameterCount = pSMB->ParameterCount;
4448         pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4449                         smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4450         pSMB->SetupCount = 1;
4451         pSMB->Reserved3 = 0;
4452         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4453         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4454         pSMB->hdr.smb_buf_length += byte_count;
4455         pSMB->ByteCount = cpu_to_le16(byte_count);
4456
4457         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4458                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4459         if (rc) {
4460                 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
4461         } else {                /* decode response */
4462                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4463
4464                 if (rc || (pSMBr->ByteCount < 13)) {
4465                         rc = -EIO;      /* bad smb */
4466                 } else {
4467                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4468                         response_data =
4469                             (FILE_SYSTEM_UNIX_INFO
4470                              *) (((char *) &pSMBr->hdr.Protocol) +
4471                                  data_offset);
4472                         memcpy(&tcon->fsUnixInfo, response_data,
4473                                sizeof(FILE_SYSTEM_UNIX_INFO));
4474                 }
4475         }
4476         cifs_buf_release(pSMB);
4477
4478         if (rc == -EAGAIN)
4479                 goto QFSUnixRetry;
4480
4481
4482         return rc;
4483 }
4484
4485 int
4486 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4487 {
4488 /* level 0x200  SMB_SET_CIFS_UNIX_INFO */
4489         TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4490         TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4491         int rc = 0;
4492         int bytes_returned = 0;
4493         __u16 params, param_offset, offset, byte_count;
4494
4495         cFYI(1, ("In SETFSUnixInfo"));
4496 SETFSUnixRetry:
4497         /* BB switch to small buf init to save memory */
4498         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4499                       (void **) &pSMBr);
4500         if (rc)
4501                 return rc;
4502
4503         params = 4;     /* 2 bytes zero followed by info level. */
4504         pSMB->MaxSetupCount = 0;
4505         pSMB->Reserved = 0;
4506         pSMB->Flags = 0;
4507         pSMB->Timeout = 0;
4508         pSMB->Reserved2 = 0;
4509         param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4510                                 - 4;
4511         offset = param_offset + params;
4512
4513         pSMB->MaxParameterCount = cpu_to_le16(4);
4514         /* BB find exact max SMB PDU from sess structure BB */
4515         pSMB->MaxDataCount = cpu_to_le16(100);
4516         pSMB->SetupCount = 1;
4517         pSMB->Reserved3 = 0;
4518         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4519         byte_count = 1 /* pad */ + params + 12;
4520
4521         pSMB->DataCount = cpu_to_le16(12);
4522         pSMB->ParameterCount = cpu_to_le16(params);
4523         pSMB->TotalDataCount = pSMB->DataCount;
4524         pSMB->TotalParameterCount = pSMB->ParameterCount;
4525         pSMB->ParameterOffset = cpu_to_le16(param_offset);
4526         pSMB->DataOffset = cpu_to_le16(offset);
4527
4528         /* Params. */
4529         pSMB->FileNum = 0;
4530         pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4531
4532         /* Data. */
4533         pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4534         pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4535         pSMB->ClientUnixCap = cpu_to_le64(cap);
4536
4537         pSMB->hdr.smb_buf_length += byte_count;
4538         pSMB->ByteCount = cpu_to_le16(byte_count);
4539
4540         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4541                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4542         if (rc) {
4543                 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4544         } else {                /* decode response */
4545                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4546                 if (rc)
4547                         rc = -EIO;      /* bad smb */
4548         }
4549         cifs_buf_release(pSMB);
4550
4551         if (rc == -EAGAIN)
4552                 goto SETFSUnixRetry;
4553
4554         return rc;
4555 }
4556
4557
4558
4559 int
4560 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4561                    struct kstatfs *FSData)
4562 {
4563 /* level 0x201  SMB_QUERY_CIFS_POSIX_INFO */
4564         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4565         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4566         FILE_SYSTEM_POSIX_INFO *response_data;
4567         int rc = 0;
4568         int bytes_returned = 0;
4569         __u16 params, byte_count;
4570
4571         cFYI(1, ("In QFSPosixInfo"));
4572 QFSPosixRetry:
4573         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4574                       (void **) &pSMBr);
4575         if (rc)
4576                 return rc;
4577
4578         params = 2;     /* level */
4579         pSMB->TotalDataCount = 0;
4580         pSMB->DataCount = 0;
4581         pSMB->DataOffset = 0;
4582         pSMB->MaxParameterCount = cpu_to_le16(2);
4583         /* BB find exact max SMB PDU from sess structure BB */
4584         pSMB->MaxDataCount = cpu_to_le16(100);
4585         pSMB->MaxSetupCount = 0;
4586         pSMB->Reserved = 0;
4587         pSMB->Flags = 0;
4588         pSMB->Timeout = 0;
4589         pSMB->Reserved2 = 0;
4590         byte_count = params + 1 /* pad */ ;
4591         pSMB->ParameterCount = cpu_to_le16(params);
4592         pSMB->TotalParameterCount = pSMB->ParameterCount;
4593         pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4594                         smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4595         pSMB->SetupCount = 1;
4596         pSMB->Reserved3 = 0;
4597         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4598         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4599         pSMB->hdr.smb_buf_length += byte_count;
4600         pSMB->ByteCount = cpu_to_le16(byte_count);
4601
4602         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4603                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4604         if (rc) {
4605                 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4606         } else {                /* decode response */
4607                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4608
4609                 if (rc || (pSMBr->ByteCount < 13)) {
4610                         rc = -EIO;      /* bad smb */
4611                 } else {
4612                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4613                         response_data =
4614                             (FILE_SYSTEM_POSIX_INFO
4615                              *) (((char *) &pSMBr->hdr.Protocol) +
4616                                  data_offset);
4617                         FSData->f_bsize =
4618                                         le32_to_cpu(response_data->BlockSize);
4619                         FSData->f_blocks =
4620                                         le64_to_cpu(response_data->TotalBlocks);
4621                         FSData->f_bfree =
4622                             le64_to_cpu(response_data->BlocksAvail);
4623                         if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4624                                 FSData->f_bavail = FSData->f_bfree;
4625                         } else {
4626                                 FSData->f_bavail =
4627                                     le64_to_cpu(response_data->UserBlocksAvail);
4628                         }
4629                         if (response_data->TotalFileNodes != cpu_to_le64(-1))
4630                                 FSData->f_files =
4631                                      le64_to_cpu(response_data->TotalFileNodes);
4632                         if (response_data->FreeFileNodes != cpu_to_le64(-1))
4633                                 FSData->f_ffree =
4634                                       le64_to_cpu(response_data->FreeFileNodes);
4635                 }
4636         }
4637         cifs_buf_release(pSMB);
4638
4639         if (rc == -EAGAIN)
4640                 goto QFSPosixRetry;
4641
4642         return rc;
4643 }
4644
4645
4646 /* We can not use write of zero bytes trick to
4647    set file size due to need for large file support.  Also note that
4648    this SetPathInfo is preferred to SetFileInfo based method in next
4649    routine which is only needed to work around a sharing violation bug
4650    in Samba which this routine can run into */
4651
4652 int
4653 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4654               __u64 size, bool SetAllocation,
4655               const struct nls_table *nls_codepage, int remap)
4656 {
4657         struct smb_com_transaction2_spi_req *pSMB = NULL;
4658         struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4659         struct file_end_of_file_info *parm_data;
4660         int name_len;
4661         int rc = 0;
4662         int bytes_returned = 0;
4663         __u16 params, byte_count, data_count, param_offset, offset;
4664
4665         cFYI(1, ("In SetEOF"));
4666 SetEOFRetry:
4667         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4668                       (void **) &pSMBr);
4669         if (rc)
4670                 return rc;
4671
4672         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4673                 name_len =
4674                     cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4675                                      PATH_MAX, nls_codepage, remap);
4676                 name_len++;     /* trailing null */
4677                 name_len *= 2;
4678         } else {        /* BB improve the check for buffer overruns BB */
4679                 name_len = strnlen(fileName, PATH_MAX);
4680                 name_len++;     /* trailing null */
4681                 strncpy(pSMB->FileName, fileName, name_len);
4682         }
4683         params = 6 + name_len;
4684         data_count = sizeof(struct file_end_of_file_info);
4685         pSMB->MaxParameterCount = cpu_to_le16(2);
4686         pSMB->MaxDataCount = cpu_to_le16(4100);
4687         pSMB->MaxSetupCount = 0;
4688         pSMB->Reserved = 0;
4689         pSMB->Flags = 0;
4690         pSMB->Timeout = 0;
4691         pSMB->Reserved2 = 0;
4692         param_offset = offsetof(struct smb_com_transaction2_spi_req,
4693                                 InformationLevel) - 4;
4694         offset = param_offset + params;
4695         if (SetAllocation) {
4696                 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4697                         pSMB->InformationLevel =
4698                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4699                 else
4700                         pSMB->InformationLevel =
4701                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4702         } else /* Set File Size */  {
4703             if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4704                     pSMB->InformationLevel =
4705                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4706             else
4707                     pSMB->InformationLevel =
4708                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4709         }
4710
4711         parm_data =
4712             (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4713                                        offset);
4714         pSMB->ParameterOffset = cpu_to_le16(param_offset);
4715         pSMB->DataOffset = cpu_to_le16(offset);
4716         pSMB->SetupCount = 1;
4717         pSMB->Reserved3 = 0;
4718         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4719         byte_count = 3 /* pad */  + params + data_count;
4720         pSMB->DataCount = cpu_to_le16(data_count);
4721         pSMB->TotalDataCount = pSMB->DataCount;
4722         pSMB->ParameterCount = cpu_to_le16(params);
4723         pSMB->TotalParameterCount = pSMB->ParameterCount;
4724         pSMB->Reserved4 = 0;
4725         pSMB->hdr.smb_buf_length += byte_count;
4726         parm_data->FileSize = cpu_to_le64(size);
4727         pSMB->ByteCount = cpu_to_le16(byte_count);
4728         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4729                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4730         if (rc)
4731                 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4732
4733         cifs_buf_release(pSMB);
4734
4735         if (rc == -EAGAIN)
4736                 goto SetEOFRetry;
4737
4738         return rc;
4739 }
4740
4741 int
4742 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4743                    __u16 fid, __u32 pid_of_opener, bool SetAllocation)
4744 {
4745         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
4746         char *data_offset;
4747         struct file_end_of_file_info *parm_data;
4748         int rc = 0;
4749         __u16 params, param_offset, offset, byte_count, count;
4750
4751         cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4752                         (long long)size));
4753         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4754
4755         if (rc)
4756                 return rc;
4757
4758         pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4759         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4760
4761         params = 6;
4762         pSMB->MaxSetupCount = 0;
4763         pSMB->Reserved = 0;
4764         pSMB->Flags = 0;
4765         pSMB->Timeout = 0;
4766         pSMB->Reserved2 = 0;
4767         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4768         offset = param_offset + params;
4769
4770         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4771
4772         count = sizeof(struct file_end_of_file_info);
4773         pSMB->MaxParameterCount = cpu_to_le16(2);
4774         /* BB find exact max SMB PDU from sess structure BB */
4775         pSMB->MaxDataCount = cpu_to_le16(1000);
4776         pSMB->SetupCount = 1;
4777         pSMB->Reserved3 = 0;
4778         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4779         byte_count = 3 /* pad */  + params + count;
4780         pSMB->DataCount = cpu_to_le16(count);
4781         pSMB->ParameterCount = cpu_to_le16(params);
4782         pSMB->TotalDataCount = pSMB->DataCount;
4783         pSMB->TotalParameterCount = pSMB->ParameterCount;
4784         pSMB->ParameterOffset = cpu_to_le16(param_offset);
4785         parm_data =
4786                 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
4787                                 + offset);
4788         pSMB->DataOffset = cpu_to_le16(offset);
4789         parm_data->FileSize = cpu_to_le64(size);
4790         pSMB->Fid = fid;
4791         if (SetAllocation) {
4792                 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4793                         pSMB->InformationLevel =
4794                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4795                 else
4796                         pSMB->InformationLevel =
4797                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4798         } else /* Set File Size */  {
4799             if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4800                     pSMB->InformationLevel =
4801                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4802             else
4803                     pSMB->InformationLevel =
4804                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4805         }
4806         pSMB->Reserved4 = 0;
4807         pSMB->hdr.smb_buf_length += byte_count;
4808         pSMB->ByteCount = cpu_to_le16(byte_count);
4809         rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4810         if (rc) {
4811                 cFYI(1,
4812                      ("Send error in SetFileInfo (SetFileSize) = %d",
4813                       rc));
4814         }
4815
4816         /* Note: On -EAGAIN error only caller can retry on handle based calls
4817                 since file handle passed in no longer valid */
4818
4819         return rc;
4820 }
4821
4822 /* Some legacy servers such as NT4 require that the file times be set on
4823    an open handle, rather than by pathname - this is awkward due to
4824    potential access conflicts on the open, but it is unavoidable for these
4825    old servers since the only other choice is to go from 100 nanosecond DCE
4826    time and resort to the original setpathinfo level which takes the ancient
4827    DOS time format with 2 second granularity */
4828 int
4829 CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon,
4830                     const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
4831 {
4832         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
4833         char *data_offset;
4834         int rc = 0;
4835         __u16 params, param_offset, offset, byte_count, count;
4836
4837         cFYI(1, ("Set Times (via SetFileInfo)"));
4838         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4839
4840         if (rc)
4841                 return rc;
4842
4843         pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4844         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4845
4846         params = 6;
4847         pSMB->MaxSetupCount = 0;
4848         pSMB->Reserved = 0;
4849         pSMB->Flags = 0;
4850         pSMB->Timeout = 0;
4851         pSMB->Reserved2 = 0;
4852         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4853         offset = param_offset + params;
4854
4855         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4856
4857         count = sizeof(FILE_BASIC_INFO);
4858         pSMB->MaxParameterCount = cpu_to_le16(2);
4859         /* BB find max SMB PDU from sess */
4860         pSMB->MaxDataCount = cpu_to_le16(1000);
4861         pSMB->SetupCount = 1;
4862         pSMB->Reserved3 = 0;
4863         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4864         byte_count = 3 /* pad */  + params + count;
4865         pSMB->DataCount = cpu_to_le16(count);
4866         pSMB->ParameterCount = cpu_to_le16(params);
4867         pSMB->TotalDataCount = pSMB->DataCount;
4868         pSMB->TotalParameterCount = pSMB->ParameterCount;
4869         pSMB->ParameterOffset = cpu_to_le16(param_offset);
4870         pSMB->DataOffset = cpu_to_le16(offset);
4871         pSMB->Fid = fid;
4872         if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4873                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4874         else
4875                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4876         pSMB->Reserved4 = 0;
4877         pSMB->hdr.smb_buf_length += byte_count;
4878         pSMB->ByteCount = cpu_to_le16(byte_count);
4879         memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4880         rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4881         if (rc)
4882                 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc));
4883
4884         /* Note: On -EAGAIN error only caller can retry on handle based calls
4885                 since file handle passed in no longer valid */
4886
4887         return rc;
4888 }
4889
4890 int
4891 CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon,
4892                           bool delete_file, __u16 fid, __u32 pid_of_opener)
4893 {
4894         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
4895         char *data_offset;
4896         int rc = 0;
4897         __u16 params, param_offset, offset, byte_count, count;
4898
4899         cFYI(1, ("Set File Disposition (via SetFileInfo)"));
4900         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4901
4902         if (rc)
4903                 return rc;
4904
4905         pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4906         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4907
4908         params = 6;
4909         pSMB->MaxSetupCount = 0;
4910         pSMB->Reserved = 0;
4911         pSMB->Flags = 0;
4912         pSMB->Timeout = 0;
4913         pSMB->Reserved2 = 0;
4914         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4915         offset = param_offset + params;
4916
4917         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4918
4919         count = 1;
4920         pSMB->MaxParameterCount = cpu_to_le16(2);
4921         /* BB find max SMB PDU from sess */
4922         pSMB->MaxDataCount = cpu_to_le16(1000);
4923         pSMB->SetupCount = 1;
4924         pSMB->Reserved3 = 0;
4925         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4926         byte_count = 3 /* pad */  + params + count;
4927         pSMB->DataCount = cpu_to_le16(count);
4928         pSMB->ParameterCount = cpu_to_le16(params);
4929         pSMB->TotalDataCount = pSMB->DataCount;
4930         pSMB->TotalParameterCount = pSMB->ParameterCount;
4931         pSMB->ParameterOffset = cpu_to_le16(param_offset);
4932         pSMB->DataOffset = cpu_to_le16(offset);
4933         pSMB->Fid = fid;
4934         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
4935         pSMB->Reserved4 = 0;
4936         pSMB->hdr.smb_buf_length += byte_count;
4937         pSMB->ByteCount = cpu_to_le16(byte_count);
4938         *data_offset = delete_file ? 1 : 0;
4939         rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4940         if (rc)
4941                 cFYI(1, ("Send error in SetFileDisposition = %d", rc));
4942
4943         return rc;
4944 }
4945
4946 int
4947 CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon,
4948                    const char *fileName, const FILE_BASIC_INFO *data,
4949                    const struct nls_table *nls_codepage, int remap)
4950 {
4951         TRANSACTION2_SPI_REQ *pSMB = NULL;
4952         TRANSACTION2_SPI_RSP *pSMBr = NULL;
4953         int name_len;
4954         int rc = 0;
4955         int bytes_returned = 0;
4956         char *data_offset;
4957         __u16 params, param_offset, offset, byte_count, count;
4958
4959         cFYI(1, ("In SetTimes"));
4960
4961 SetTimesRetry:
4962         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4963                       (void **) &pSMBr);
4964         if (rc)
4965                 return rc;
4966
4967         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4968                 name_len =
4969                     cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4970                                      PATH_MAX, nls_codepage, remap);
4971                 name_len++;     /* trailing null */
4972                 name_len *= 2;
4973         } else {        /* BB improve the check for buffer overruns BB */
4974                 name_len = strnlen(fileName, PATH_MAX);
4975                 name_len++;     /* trailing null */
4976                 strncpy(pSMB->FileName, fileName, name_len);
4977         }
4978
4979         params = 6 + name_len;
4980         count = sizeof(FILE_BASIC_INFO);
4981         pSMB->MaxParameterCount = cpu_to_le16(2);
4982         /* BB find max SMB PDU from sess structure BB */
4983         pSMB->MaxDataCount = cpu_to_le16(1000);
4984         pSMB->MaxSetupCount = 0;
4985         pSMB->Reserved = 0;
4986         pSMB->Flags = 0;
4987         pSMB->Timeout = 0;
4988         pSMB->Reserved2 = 0;
4989         param_offset = offsetof(struct smb_com_transaction2_spi_req,
4990                                 InformationLevel) - 4;
4991         offset = param_offset + params;
4992         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4993         pSMB->ParameterOffset = cpu_to_le16(param_offset);
4994         pSMB->DataOffset = cpu_to_le16(offset);
4995         pSMB->SetupCount = 1;
4996         pSMB->Reserved3 = 0;
4997         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4998         byte_count = 3 /* pad */  + params + count;
4999
5000         pSMB->DataCount = cpu_to_le16(count);
5001         pSMB->ParameterCount = cpu_to_le16(params);
5002         pSMB->TotalDataCount = pSMB->DataCount;
5003         pSMB->TotalParameterCount = pSMB->ParameterCount;
5004         if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5005                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5006         else
5007                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5008         pSMB->Reserved4 = 0;
5009         pSMB->hdr.smb_buf_length += byte_count;
5010         memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5011         pSMB->ByteCount = cpu_to_le16(byte_count);
5012         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5013                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5014         if (rc)
5015                 cFYI(1, ("SetPathInfo (times) returned %d", rc));
5016
5017         cifs_buf_release(pSMB);
5018
5019         if (rc == -EAGAIN)
5020                 goto SetTimesRetry;
5021
5022         return rc;
5023 }
5024
5025 /* Can not be used to set time stamps yet (due to old DOS time format) */
5026 /* Can be used to set attributes */
5027 #if 0  /* Possibly not needed - since it turns out that strangely NT4 has a bug
5028           handling it anyway and NT4 was what we thought it would be needed for
5029           Do not delete it until we prove whether needed for Win9x though */
5030 int
5031 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
5032                 __u16 dos_attrs, const struct nls_table *nls_codepage)
5033 {
5034         SETATTR_REQ *pSMB = NULL;
5035         SETATTR_RSP *pSMBr = NULL;
5036         int rc = 0;
5037         int bytes_returned;
5038         int name_len;
5039
5040         cFYI(1, ("In SetAttrLegacy"));
5041
5042 SetAttrLgcyRetry:
5043         rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5044                       (void **) &pSMBr);
5045         if (rc)
5046                 return rc;
5047
5048         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5049                 name_len =
5050                         ConvertToUCS((__le16 *) pSMB->fileName, fileName,
5051                                 PATH_MAX, nls_codepage);
5052                 name_len++;     /* trailing null */
5053                 name_len *= 2;
5054         } else {        /* BB improve the check for buffer overruns BB */
5055                 name_len = strnlen(fileName, PATH_MAX);
5056                 name_len++;     /* trailing null */
5057                 strncpy(pSMB->fileName, fileName, name_len);
5058         }
5059         pSMB->attr = cpu_to_le16(dos_attrs);
5060         pSMB->BufferFormat = 0x04;
5061         pSMB->hdr.smb_buf_length += name_len + 1;
5062         pSMB->ByteCount = cpu_to_le16(name_len + 1);
5063         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5064                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5065         if (rc)
5066                 cFYI(1, ("Error in LegacySetAttr = %d", rc));
5067
5068         cifs_buf_release(pSMB);
5069
5070         if (rc == -EAGAIN)
5071                 goto SetAttrLgcyRetry;
5072
5073         return rc;
5074 }
5075 #endif /* temporarily unneeded SetAttr legacy function */
5076
5077 int
5078 CIFSSMBUnixSetInfo(const int xid, struct cifsTconInfo *tcon, char *fileName,
5079                    const struct cifs_unix_set_info_args *args,
5080                    const struct nls_table *nls_codepage, int remap)
5081 {
5082         TRANSACTION2_SPI_REQ *pSMB = NULL;
5083         TRANSACTION2_SPI_RSP *pSMBr = NULL;
5084         int name_len;
5085         int rc = 0;
5086         int bytes_returned = 0;
5087         FILE_UNIX_BASIC_INFO *data_offset;
5088         __u16 params, param_offset, offset, count, byte_count;
5089         __u64 mode = args->mode;
5090
5091         cFYI(1, ("In SetUID/GID/Mode"));
5092 setPermsRetry:
5093         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5094                       (void **) &pSMBr);
5095         if (rc)
5096                 return rc;
5097
5098         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5099                 name_len =
5100                     cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5101                                      PATH_MAX, nls_codepage, remap);
5102                 name_len++;     /* trailing null */
5103                 name_len *= 2;
5104         } else {        /* BB improve the check for buffer overruns BB */
5105                 name_len = strnlen(fileName, PATH_MAX);
5106                 name_len++;     /* trailing null */
5107                 strncpy(pSMB->FileName, fileName, name_len);
5108         }
5109
5110         params = 6 + name_len;
5111         count = sizeof(FILE_UNIX_BASIC_INFO);
5112         pSMB->MaxParameterCount = cpu_to_le16(2);
5113         /* BB find max SMB PDU from sess structure BB */
5114         pSMB->MaxDataCount = cpu_to_le16(1000);
5115         pSMB->MaxSetupCount = 0;
5116         pSMB->Reserved = 0;
5117         pSMB->Flags = 0;
5118         pSMB->Timeout = 0;
5119         pSMB->Reserved2 = 0;
5120         param_offset = offsetof(struct smb_com_transaction2_spi_req,
5121                                 InformationLevel) - 4;
5122         offset = param_offset + params;
5123         data_offset =
5124             (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5125                                       offset);
5126         memset(data_offset, 0, count);
5127         pSMB->DataOffset = cpu_to_le16(offset);
5128         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5129         pSMB->SetupCount = 1;
5130         pSMB->Reserved3 = 0;
5131         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5132         byte_count = 3 /* pad */  + params + count;
5133         pSMB->ParameterCount = cpu_to_le16(params);
5134         pSMB->DataCount = cpu_to_le16(count);
5135         pSMB->TotalParameterCount = pSMB->ParameterCount;
5136         pSMB->TotalDataCount = pSMB->DataCount;
5137         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5138         pSMB->Reserved4 = 0;
5139         pSMB->hdr.smb_buf_length += byte_count;
5140         /* Samba server ignores set of file size to zero due to bugs in some
5141         older clients, but we should be precise - we use SetFileSize to
5142         set file size and do not want to truncate file size to zero
5143         accidently as happened on one Samba server beta by putting
5144         zero instead of -1 here */
5145         data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5146         data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5147         data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5148         data_offset->LastAccessTime = cpu_to_le64(args->atime);
5149         data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5150         data_offset->Uid = cpu_to_le64(args->uid);
5151         data_offset->Gid = cpu_to_le64(args->gid);
5152         /* better to leave device as zero when it is  */
5153         data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5154         data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5155         data_offset->Permissions = cpu_to_le64(mode);
5156
5157         if (S_ISREG(mode))
5158                 data_offset->Type = cpu_to_le32(UNIX_FILE);
5159         else if (S_ISDIR(mode))
5160                 data_offset->Type = cpu_to_le32(UNIX_DIR);
5161         else if (S_ISLNK(mode))
5162                 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5163         else if (S_ISCHR(mode))
5164                 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5165         else if (S_ISBLK(mode))
5166                 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5167         else if (S_ISFIFO(mode))
5168                 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5169         else if (S_ISSOCK(mode))
5170                 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5171
5172
5173         pSMB->ByteCount = cpu_to_le16(byte_count);
5174         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5175                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5176         if (rc)
5177                 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
5178
5179         cifs_buf_release(pSMB);
5180         if (rc == -EAGAIN)
5181                 goto setPermsRetry;
5182         return rc;
5183 }
5184
5185 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5186                   const int notify_subdirs, const __u16 netfid,
5187                   __u32 filter, struct file *pfile, int multishot,
5188                   const struct nls_table *nls_codepage)
5189 {
5190         int rc = 0;
5191         struct smb_com_transaction_change_notify_req *pSMB = NULL;
5192         struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
5193         struct dir_notify_req *dnotify_req;
5194         int bytes_returned;
5195
5196         cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid));
5197         rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
5198                       (void **) &pSMBr);
5199         if (rc)
5200                 return rc;
5201
5202         pSMB->TotalParameterCount = 0 ;
5203         pSMB->TotalDataCount = 0;
5204         pSMB->MaxParameterCount = cpu_to_le32(2);
5205         /* BB find exact data count max from sess structure BB */
5206         pSMB->MaxDataCount = 0; /* same in little endian or be */
5207 /* BB VERIFY verify which is correct for above BB */
5208         pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
5209                                              MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
5210
5211         pSMB->MaxSetupCount = 4;
5212         pSMB->Reserved = 0;
5213         pSMB->ParameterOffset = 0;
5214         pSMB->DataCount = 0;
5215         pSMB->DataOffset = 0;
5216         pSMB->SetupCount = 4; /* single byte does not need le conversion */
5217         pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
5218         pSMB->ParameterCount = pSMB->TotalParameterCount;
5219         if (notify_subdirs)
5220                 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
5221         pSMB->Reserved2 = 0;
5222         pSMB->CompletionFilter = cpu_to_le32(filter);
5223         pSMB->Fid = netfid; /* file handle always le */
5224         pSMB->ByteCount = 0;
5225
5226         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5227                          (struct smb_hdr *)pSMBr, &bytes_returned,
5228                          CIFS_ASYNC_OP);
5229         if (rc) {
5230                 cFYI(1, ("Error in Notify = %d", rc));
5231         } else {
5232                 /* Add file to outstanding requests */
5233                 /* BB change to kmem cache alloc */
5234                 dnotify_req = kmalloc(
5235                                                 sizeof(struct dir_notify_req),
5236                                                  GFP_KERNEL);
5237                 if (dnotify_req) {
5238                         dnotify_req->Pid = pSMB->hdr.Pid;
5239                         dnotify_req->PidHigh = pSMB->hdr.PidHigh;
5240                         dnotify_req->Mid = pSMB->hdr.Mid;
5241                         dnotify_req->Tid = pSMB->hdr.Tid;
5242                         dnotify_req->Uid = pSMB->hdr.Uid;
5243                         dnotify_req->netfid = netfid;
5244                         dnotify_req->pfile = pfile;
5245                         dnotify_req->filter = filter;
5246                         dnotify_req->multishot = multishot;
5247                         spin_lock(&GlobalMid_Lock);
5248                         list_add_tail(&dnotify_req->lhead,
5249                                         &GlobalDnotifyReqList);
5250                         spin_unlock(&GlobalMid_Lock);
5251                 } else
5252                         rc = -ENOMEM;
5253         }
5254         cifs_buf_release(pSMB);
5255         return rc;
5256 }
5257 #ifdef CONFIG_CIFS_XATTR
5258 ssize_t
5259 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5260                  const unsigned char *searchName,
5261                  char *EAData, size_t buf_size,
5262                  const struct nls_table *nls_codepage, int remap)
5263 {
5264                 /* BB assumes one setup word */
5265         TRANSACTION2_QPI_REQ *pSMB = NULL;
5266         TRANSACTION2_QPI_RSP *pSMBr = NULL;
5267         int rc = 0;
5268         int bytes_returned;
5269         int name_len;
5270         struct fea *temp_fea;
5271         char *temp_ptr;
5272         __u16 params, byte_count;
5273
5274         cFYI(1, ("In Query All EAs path %s", searchName));
5275 QAllEAsRetry:
5276         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5277                       (void **) &pSMBr);
5278         if (rc)
5279                 return rc;
5280
5281         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5282                 name_len =
5283                     cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5284                                      PATH_MAX, nls_codepage, remap);
5285                 name_len++;     /* trailing null */
5286                 name_len *= 2;
5287         } else {        /* BB improve the check for buffer overruns BB */
5288                 name_len = strnlen(searchName, PATH_MAX);
5289                 name_len++;     /* trailing null */
5290                 strncpy(pSMB->FileName, searchName, name_len);
5291         }
5292
5293         params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5294         pSMB->TotalDataCount = 0;
5295         pSMB->MaxParameterCount = cpu_to_le16(2);
5296         /* BB find exact max SMB PDU from sess structure BB */
5297         pSMB->MaxDataCount = cpu_to_le16(4000);
5298         pSMB->MaxSetupCount = 0;
5299         pSMB->Reserved = 0;
5300         pSMB->Flags = 0;
5301         pSMB->Timeout = 0;
5302         pSMB->Reserved2 = 0;
5303         pSMB->ParameterOffset = cpu_to_le16(offsetof(
5304         struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5305         pSMB->DataCount = 0;
5306         pSMB->DataOffset = 0;
5307         pSMB->SetupCount = 1;
5308         pSMB->Reserved3 = 0;
5309         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5310         byte_count = params + 1 /* pad */ ;
5311         pSMB->TotalParameterCount = cpu_to_le16(params);
5312         pSMB->ParameterCount = pSMB->TotalParameterCount;
5313         pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5314         pSMB->Reserved4 = 0;
5315         pSMB->hdr.smb_buf_length += byte_count;
5316         pSMB->ByteCount = cpu_to_le16(byte_count);
5317
5318         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5319                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5320         if (rc) {
5321                 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
5322         } else {                /* decode response */
5323                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5324
5325                 /* BB also check enough total bytes returned */
5326                 /* BB we need to improve the validity checking
5327                 of these trans2 responses */
5328                 if (rc || (pSMBr->ByteCount < 4))
5329                         rc = -EIO;      /* bad smb */
5330            /* else if (pFindData){
5331                         memcpy((char *) pFindData,
5332                                (char *) &pSMBr->hdr.Protocol +
5333                                data_offset, kl);
5334                 }*/ else {
5335                         /* check that length of list is not more than bcc */
5336                         /* check that each entry does not go beyond length
5337                            of list */
5338                         /* check that each element of each entry does not
5339                            go beyond end of list */
5340                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5341                         struct fealist *ea_response_data;
5342                         rc = 0;
5343                         /* validate_trans2_offsets() */
5344                         /* BB check if start of smb + data_offset > &bcc+ bcc */
5345                         ea_response_data = (struct fealist *)
5346                                 (((char *) &pSMBr->hdr.Protocol) +
5347                                 data_offset);
5348                         name_len = le32_to_cpu(ea_response_data->list_len);
5349                         cFYI(1, ("ea length %d", name_len));
5350                         if (name_len <= 8) {
5351                         /* returned EA size zeroed at top of function */
5352                                 cFYI(1, ("empty EA list returned from server"));
5353                         } else {
5354                                 /* account for ea list len */
5355                                 name_len -= 4;
5356                                 temp_fea = ea_response_data->list;
5357                                 temp_ptr = (char *)temp_fea;
5358                                 while (name_len > 0) {
5359                                         __u16 value_len;
5360                                         name_len -= 4;
5361                                         temp_ptr += 4;
5362                                         rc += temp_fea->name_len;
5363                                 /* account for prefix user. and trailing null */
5364                                         rc = rc + 5 + 1;
5365                                         if (rc < (int)buf_size) {
5366                                                 memcpy(EAData, "user.", 5);
5367                                                 EAData += 5;
5368                                                 memcpy(EAData, temp_ptr,
5369                                                        temp_fea->name_len);
5370                                                 EAData += temp_fea->name_len;
5371                                                 /* null terminate name */
5372                                                 *EAData = 0;
5373                                                 EAData = EAData + 1;
5374                                         } else if (buf_size == 0) {
5375                                                 /* skip copy - calc size only */
5376                                         } else {
5377                                                 /* stop before overrun buffer */
5378                                                 rc = -ERANGE;
5379                                                 break;
5380                                         }
5381                                         name_len -= temp_fea->name_len;
5382                                         temp_ptr += temp_fea->name_len;
5383                                         /* account for trailing null */
5384                                         name_len--;
5385                                         temp_ptr++;
5386                                         value_len =
5387                                               le16_to_cpu(temp_fea->value_len);
5388                                         name_len -= value_len;
5389                                         temp_ptr += value_len;
5390                                         /* BB check that temp_ptr is still
5391                                               within the SMB BB*/
5392
5393                                         /* no trailing null to account for
5394                                            in value len */
5395                                         /* go on to next EA */
5396                                         temp_fea = (struct fea *)temp_ptr;
5397                                 }
5398                         }
5399                 }
5400         }
5401         cifs_buf_release(pSMB);
5402         if (rc == -EAGAIN)
5403                 goto QAllEAsRetry;
5404
5405         return (ssize_t)rc;
5406 }
5407
5408 ssize_t CIFSSMBQueryEA(const int xid, struct cifsTconInfo *tcon,
5409                 const unsigned char *searchName, const unsigned char *ea_name,
5410                 unsigned char *ea_value, size_t buf_size,
5411                 const struct nls_table *nls_codepage, int remap)
5412 {
5413         TRANSACTION2_QPI_REQ *pSMB = NULL;
5414         TRANSACTION2_QPI_RSP *pSMBr = NULL;
5415         int rc = 0;
5416         int bytes_returned;
5417         int name_len;
5418         struct fea *temp_fea;
5419         char *temp_ptr;
5420         __u16 params, byte_count;
5421
5422         cFYI(1, ("In Query EA path %s", searchName));
5423 QEARetry:
5424         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5425                       (void **) &pSMBr);
5426         if (rc)
5427                 return rc;
5428
5429         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5430                 name_len =
5431                     cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5432                                      PATH_MAX, nls_codepage, remap);
5433                 name_len++;     /* trailing null */
5434                 name_len *= 2;
5435         } else {        /* BB improve the check for buffer overruns BB */
5436                 name_len = strnlen(searchName, PATH_MAX);
5437                 name_len++;     /* trailing null */
5438                 strncpy(pSMB->FileName, searchName, name_len);
5439         }
5440
5441         params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5442         pSMB->TotalDataCount = 0;
5443         pSMB->MaxParameterCount = cpu_to_le16(2);
5444         /* BB find exact max SMB PDU from sess structure BB */
5445         pSMB->MaxDataCount = cpu_to_le16(4000);
5446         pSMB->MaxSetupCount = 0;
5447         pSMB->Reserved = 0;
5448         pSMB->Flags = 0;
5449         pSMB->Timeout = 0;
5450         pSMB->Reserved2 = 0;
5451         pSMB->ParameterOffset = cpu_to_le16(offsetof(
5452                 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5453         pSMB->DataCount = 0;
5454         pSMB->DataOffset = 0;
5455         pSMB->SetupCount = 1;
5456         pSMB->Reserved3 = 0;
5457         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5458         byte_count = params + 1 /* pad */ ;
5459         pSMB->TotalParameterCount = cpu_to_le16(params);
5460         pSMB->ParameterCount = pSMB->TotalParameterCount;
5461         pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5462         pSMB->Reserved4 = 0;
5463         pSMB->hdr.smb_buf_length += byte_count;
5464         pSMB->ByteCount = cpu_to_le16(byte_count);
5465
5466         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5467                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5468         if (rc) {
5469                 cFYI(1, ("Send error in Query EA = %d", rc));
5470         } else {                /* decode response */
5471                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5472
5473                 /* BB also check enough total bytes returned */
5474                 /* BB we need to improve the validity checking
5475                 of these trans2 responses */
5476                 if (rc || (pSMBr->ByteCount < 4))
5477                         rc = -EIO;      /* bad smb */
5478            /* else if (pFindData){
5479                         memcpy((char *) pFindData,
5480                                (char *) &pSMBr->hdr.Protocol +
5481                                data_offset, kl);
5482                 }*/ else {
5483                         /* check that length of list is not more than bcc */
5484                         /* check that each entry does not go beyond length
5485                            of list */
5486                         /* check that each element of each entry does not
5487                            go beyond end of list */
5488                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5489                         struct fealist *ea_response_data;
5490                         rc = -ENODATA;
5491                         /* validate_trans2_offsets() */
5492                         /* BB check if start of smb + data_offset > &bcc+ bcc*/
5493                         ea_response_data = (struct fealist *)
5494                                 (((char *) &pSMBr->hdr.Protocol) +
5495                                 data_offset);
5496                         name_len = le32_to_cpu(ea_response_data->list_len);
5497                         cFYI(1, ("ea length %d", name_len));
5498                         if (name_len <= 8) {
5499                         /* returned EA size zeroed at top of function */
5500                                 cFYI(1, ("empty EA list returned from server"));
5501                         } else {
5502                                 /* account for ea list len */
5503                                 name_len -= 4;
5504                                 temp_fea = ea_response_data->list;
5505                                 temp_ptr = (char *)temp_fea;
5506                                 /* loop through checking if we have a matching
5507                                 name and then return the associated value */
5508                                 while (name_len > 0) {
5509                                         __u16 value_len;
5510                                         name_len -= 4;
5511                                         temp_ptr += 4;
5512                                         value_len =
5513                                               le16_to_cpu(temp_fea->value_len);
5514                                 /* BB validate that value_len falls within SMB,
5515                                 even though maximum for name_len is 255 */
5516                                         if (memcmp(temp_fea->name, ea_name,
5517                                                   temp_fea->name_len) == 0) {
5518                                                 /* found a match */
5519                                                 rc = value_len;
5520                                 /* account for prefix user. and trailing null */
5521                                                 if (rc <= (int)buf_size) {
5522                                                         memcpy(ea_value,
5523                                                                 temp_fea->name+temp_fea->name_len+1,
5524                                                                 rc);
5525                                                         /* ea values, unlike ea
5526                                                            names, are not null
5527                                                            terminated */
5528                                                 } else if (buf_size == 0) {
5529                                                 /* skip copy - calc size only */
5530                                                 } else {
5531                                                 /* stop before overrun buffer */
5532                                                         rc = -ERANGE;
5533                                                 }
5534                                                 break;
5535                                         }
5536                                         name_len -= temp_fea->name_len;
5537                                         temp_ptr += temp_fea->name_len;
5538                                         /* account for trailing null */
5539                                         name_len--;
5540                                         temp_ptr++;
5541                                         name_len -= value_len;
5542                                         temp_ptr += value_len;
5543                                         /* No trailing null to account for in
5544                                            value_len.  Go on to next EA */
5545                                         temp_fea = (struct fea *)temp_ptr;
5546                                 }
5547                         }
5548                 }
5549         }
5550         cifs_buf_release(pSMB);
5551         if (rc == -EAGAIN)
5552                 goto QEARetry;
5553
5554         return (ssize_t)rc;
5555 }
5556
5557 int
5558 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5559              const char *ea_name, const void *ea_value,
5560              const __u16 ea_value_len, const struct nls_table *nls_codepage,
5561              int remap)
5562 {
5563         struct smb_com_transaction2_spi_req *pSMB = NULL;
5564         struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5565         struct fealist *parm_data;
5566         int name_len;
5567         int rc = 0;
5568         int bytes_returned = 0;
5569         __u16 params, param_offset, byte_count, offset, count;
5570
5571         cFYI(1, ("In SetEA"));
5572 SetEARetry:
5573         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5574                       (void **) &pSMBr);
5575         if (rc)
5576                 return rc;
5577
5578         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5579                 name_len =
5580                     cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5581                                      PATH_MAX, nls_codepage, remap);
5582                 name_len++;     /* trailing null */
5583                 name_len *= 2;
5584         } else {        /* BB improve the check for buffer overruns BB */
5585                 name_len = strnlen(fileName, PATH_MAX);
5586                 name_len++;     /* trailing null */
5587                 strncpy(pSMB->FileName, fileName, name_len);
5588         }
5589
5590         params = 6 + name_len;
5591
5592         /* done calculating parms using name_len of file name,
5593         now use name_len to calculate length of ea name
5594         we are going to create in the inode xattrs */
5595         if (ea_name == NULL)
5596                 name_len = 0;
5597         else
5598                 name_len = strnlen(ea_name, 255);
5599
5600         count = sizeof(*parm_data) + ea_value_len + name_len;
5601         pSMB->MaxParameterCount = cpu_to_le16(2);
5602         /* BB find max SMB PDU from sess */
5603         pSMB->MaxDataCount = cpu_to_le16(1000);
5604         pSMB->MaxSetupCount = 0;
5605         pSMB->Reserved = 0;
5606         pSMB->Flags = 0;
5607         pSMB->Timeout = 0;
5608         pSMB->Reserved2 = 0;
5609         param_offset = offsetof(struct smb_com_transaction2_spi_req,
5610                                 InformationLevel) - 4;
5611         offset = param_offset + params;
5612         pSMB->InformationLevel =
5613                 cpu_to_le16(SMB_SET_FILE_EA);
5614
5615         parm_data =
5616                 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5617                                        offset);
5618         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5619         pSMB->DataOffset = cpu_to_le16(offset);
5620         pSMB->SetupCount = 1;
5621         pSMB->Reserved3 = 0;
5622         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5623         byte_count = 3 /* pad */  + params + count;
5624         pSMB->DataCount = cpu_to_le16(count);
5625         parm_data->list_len = cpu_to_le32(count);
5626         parm_data->list[0].EA_flags = 0;
5627         /* we checked above that name len is less than 255 */
5628         parm_data->list[0].name_len = (__u8)name_len;
5629         /* EA names are always ASCII */
5630         if (ea_name)
5631                 strncpy(parm_data->list[0].name, ea_name, name_len);
5632         parm_data->list[0].name[name_len] = 0;
5633         parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5634         /* caller ensures that ea_value_len is less than 64K but
5635         we need to ensure that it fits within the smb */
5636
5637         /*BB add length check to see if it would fit in
5638              negotiated SMB buffer size BB */
5639         /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5640         if (ea_value_len)
5641                 memcpy(parm_data->list[0].name+name_len+1,
5642                        ea_value, ea_value_len);
5643
5644         pSMB->TotalDataCount = pSMB->DataCount;
5645         pSMB->ParameterCount = cpu_to_le16(params);
5646         pSMB->TotalParameterCount = pSMB->ParameterCount;
5647         pSMB->Reserved4 = 0;
5648         pSMB->hdr.smb_buf_length += byte_count;
5649         pSMB->ByteCount = cpu_to_le16(byte_count);
5650         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5651                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5652         if (rc)
5653                 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
5654
5655         cifs_buf_release(pSMB);
5656
5657         if (rc == -EAGAIN)
5658                 goto SetEARetry;
5659
5660         return rc;
5661 }
5662
5663 #endif