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