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