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