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