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