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