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