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