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