Merge master.kernel.org:/home/rmk/linux-2.6-arm
[linux-2.6] / fs / cifs / cifssmb.c
1 /*
2  *   fs/cifs/cifssmb.c
3  *
4  *   Copyright (C) International Business Machines  Corp., 2002,2008
5  *   Author(s): Steve French (sfrench@us.ibm.com)
6  *
7  *   Contains the routines for constructing the SMB PDUs themselves
8  *
9  *   This library is free software; you can redistribute it and/or modify
10  *   it under the terms of the GNU Lesser General Public License as published
11  *   by the Free Software Foundation; either version 2.1 of the License, or
12  *   (at your option) any later version.
13  *
14  *   This library is distributed in the hope that it will be useful,
15  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
17  *   the GNU Lesser General Public License for more details.
18  *
19  *   You should have received a copy of the GNU Lesser General Public License
20  *   along with this library; if not, write to the Free Software
21  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22  */
23
24  /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c   */
25  /* These are mostly routines that operate on a pathname, or on a tree id     */
26  /* (mounted volume), but there are eight handle based routines which must be */
27  /* treated slightly differently for reconnection purposes since we never     */
28  /* want to reuse a stale file handle and only the caller knows the file info */
29
30 #include <linux/fs.h>
31 #include <linux/kernel.h>
32 #include <linux/vfs.h>
33 #include <linux/posix_acl_xattr.h>
34 #include <asm/uaccess.h>
35 #include "cifspdu.h"
36 #include "cifsglob.h"
37 #include "cifsacl.h"
38 #include "cifsproto.h"
39 #include "cifs_unicode.h"
40 #include "cifs_debug.h"
41
42 #ifdef CONFIG_CIFS_POSIX
43 static struct {
44         int index;
45         char *name;
46 } protocols[] = {
47 #ifdef CONFIG_CIFS_WEAK_PW_HASH
48         {LANMAN_PROT, "\2LM1.2X002"},
49         {LANMAN2_PROT, "\2LANMAN2.1"},
50 #endif /* weak password hashing for legacy clients */
51         {CIFS_PROT, "\2NT LM 0.12"},
52         {POSIX_PROT, "\2POSIX 2"},
53         {BAD_PROT, "\2"}
54 };
55 #else
56 static struct {
57         int index;
58         char *name;
59 } protocols[] = {
60 #ifdef CONFIG_CIFS_WEAK_PW_HASH
61         {LANMAN_PROT, "\2LM1.2X002"},
62         {LANMAN2_PROT, "\2LANMAN2.1"},
63 #endif /* weak password hashing for legacy clients */
64         {CIFS_PROT, "\2NT LM 0.12"},
65         {BAD_PROT, "\2"}
66 };
67 #endif
68
69 /* define the number of elements in the cifs dialect array */
70 #ifdef CONFIG_CIFS_POSIX
71 #ifdef CONFIG_CIFS_WEAK_PW_HASH
72 #define CIFS_NUM_PROT 4
73 #else
74 #define CIFS_NUM_PROT 2
75 #endif /* CIFS_WEAK_PW_HASH */
76 #else /* not posix */
77 #ifdef CONFIG_CIFS_WEAK_PW_HASH
78 #define CIFS_NUM_PROT 3
79 #else
80 #define CIFS_NUM_PROT 1
81 #endif /* CONFIG_CIFS_WEAK_PW_HASH */
82 #endif /* CIFS_POSIX */
83
84 /* Allocates buffer into dst and copies smb string from src to it.
85  * caller is responsible for freeing dst if function returned 0.
86  * returns:
87  *      on success - 0
88  *      on failure - errno
89  */
90 static int
91 cifs_strncpy_to_host(char **dst, const char *src, const int maxlen,
92                  const bool is_unicode, const struct nls_table *nls_codepage)
93 {
94         int plen;
95
96         if (is_unicode) {
97                 plen = UniStrnlen((wchar_t *)src, maxlen);
98                 *dst = kmalloc(plen + 2, GFP_KERNEL);
99                 if (!*dst)
100                         goto cifs_strncpy_to_host_ErrExit;
101                 cifs_strfromUCS_le(*dst, (__le16 *)src, plen, nls_codepage);
102         } else {
103                 plen = strnlen(src, maxlen);
104                 *dst = kmalloc(plen + 2, GFP_KERNEL);
105                 if (!*dst)
106                         goto cifs_strncpy_to_host_ErrExit;
107                 strncpy(*dst, src, plen);
108         }
109         (*dst)[plen] = 0;
110         (*dst)[plen+1] = 0; /* harmless for ASCII case, needed for Unicode */
111         return 0;
112
113 cifs_strncpy_to_host_ErrExit:
114         cERROR(1, ("Failed to allocate buffer for string\n"));
115         return -ENOMEM;
116 }
117
118
119 /* Mark as invalid, all open files on tree connections since they
120    were closed when session to server was lost */
121 static void mark_open_files_invalid(struct cifsTconInfo *pTcon)
122 {
123         struct cifsFileInfo *open_file = NULL;
124         struct list_head *tmp;
125         struct list_head *tmp1;
126
127 /* list all files open on tree connection and mark them invalid */
128         write_lock(&GlobalSMBSeslock);
129         list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
130                 open_file = list_entry(tmp, struct cifsFileInfo, tlist);
131                 open_file->invalidHandle = true;
132         }
133         write_unlock(&GlobalSMBSeslock);
134         /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
135            to this tcon */
136 }
137
138 /* Allocate and return pointer to an SMB request buffer, and set basic
139    SMB information in the SMB header.  If the return code is zero, this
140    function must have filled in request_buf pointer */
141 static int
142 small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
143                 void **request_buf)
144 {
145         int rc = 0;
146
147         /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
148            check for tcp and smb session status done differently
149            for those three - in the calling routine */
150         if (tcon) {
151                 if (tcon->tidStatus == CifsExiting) {
152                         /* only tree disconnect, open, and write,
153                         (and ulogoff which does not have tcon)
154                         are allowed as we start force umount */
155                         if ((smb_command != SMB_COM_WRITE_ANDX) &&
156                            (smb_command != SMB_COM_OPEN_ANDX) &&
157                            (smb_command != SMB_COM_TREE_DISCONNECT)) {
158                                 cFYI(1, ("can not send cmd %d while umounting",
159                                         smb_command));
160                                 return -ENODEV;
161                         }
162                 }
163                 if ((tcon->ses) && (tcon->ses->status != CifsExiting) &&
164                                   (tcon->ses->server)) {
165                         struct nls_table *nls_codepage;
166                                 /* Give Demultiplex thread up to 10 seconds to
167                                    reconnect, should be greater than cifs socket
168                                    timeout which is 7 seconds */
169                         while (tcon->ses->server->tcpStatus ==
170                                                          CifsNeedReconnect) {
171                                 wait_event_interruptible_timeout(tcon->ses->server->response_q,
172                                         (tcon->ses->server->tcpStatus ==
173                                                         CifsGood), 10 * HZ);
174                                 if (tcon->ses->server->tcpStatus ==
175                                                         CifsNeedReconnect) {
176                                         /* on "soft" mounts we wait once */
177                                         if (!tcon->retry ||
178                                            (tcon->ses->status == CifsExiting)) {
179                                                 cFYI(1, ("gave up waiting on "
180                                                       "reconnect in smb_init"));
181                                                 return -EHOSTDOWN;
182                                         } /* else "hard" mount - keep retrying
183                                              until process is killed or server
184                                              comes back on-line */
185                                 } else /* TCP session is reestablished now */
186                                         break;
187                         }
188
189                         nls_codepage = load_nls_default();
190                 /* need to prevent multiple threads trying to
191                 simultaneously reconnect the same SMB session */
192                         down(&tcon->ses->sesSem);
193                         if (tcon->ses->need_reconnect)
194                                 rc = cifs_setup_session(0, tcon->ses,
195                                                         nls_codepage);
196                         if (!rc && (tcon->need_reconnect)) {
197                                 mark_open_files_invalid(tcon);
198                                 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
199                                               tcon, nls_codepage);
200                                 up(&tcon->ses->sesSem);
201                                 /* BB FIXME add code to check if wsize needs
202                                    update due to negotiated smb buffer size
203                                    shrinking */
204                                 if (rc == 0) {
205                                         atomic_inc(&tconInfoReconnectCount);
206                                         /* tell server Unix caps we support */
207                                         if (tcon->ses->capabilities & CAP_UNIX)
208                                                 reset_cifs_unix_caps(
209                                                 0 /* no xid */,
210                                                 tcon,
211                                                 NULL /* we do not know sb */,
212                                                 NULL /* no vol info */);
213                                 }
214
215                                 cFYI(1, ("reconnect tcon rc = %d", rc));
216                                 /* Removed call to reopen open files here.
217                                    It is safer (and faster) to reopen files
218                                    one at a time as needed in read and write */
219
220                                 /* Check if handle based operation so we
221                                    know whether we can continue or not without
222                                    returning to caller to reset file handle */
223                                 switch (smb_command) {
224                                         case SMB_COM_READ_ANDX:
225                                         case SMB_COM_WRITE_ANDX:
226                                         case SMB_COM_CLOSE:
227                                         case SMB_COM_FIND_CLOSE2:
228                                         case SMB_COM_LOCKING_ANDX: {
229                                                 unload_nls(nls_codepage);
230                                                 return -EAGAIN;
231                                         }
232                                 }
233                         } else {
234                                 up(&tcon->ses->sesSem);
235                         }
236                         unload_nls(nls_codepage);
237
238                 } else {
239                         return -EIO;
240                 }
241         }
242         if (rc)
243                 return rc;
244
245         *request_buf = cifs_small_buf_get();
246         if (*request_buf == NULL) {
247                 /* BB should we add a retry in here if not a writepage? */
248                 return -ENOMEM;
249         }
250
251         header_assemble((struct smb_hdr *) *request_buf, smb_command,
252                         tcon, wct);
253
254         if (tcon != NULL)
255                 cifs_stats_inc(&tcon->num_smbs_sent);
256
257         return rc;
258 }
259
260 int
261 small_smb_init_no_tc(const int smb_command, const int wct,
262                      struct cifsSesInfo *ses, void **request_buf)
263 {
264         int rc;
265         struct smb_hdr *buffer;
266
267         rc = small_smb_init(smb_command, wct, NULL, request_buf);
268         if (rc)
269                 return rc;
270
271         buffer = (struct smb_hdr *)*request_buf;
272         buffer->Mid = GetNextMid(ses->server);
273         if (ses->capabilities & CAP_UNICODE)
274                 buffer->Flags2 |= SMBFLG2_UNICODE;
275         if (ses->capabilities & CAP_STATUS32)
276                 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
277
278         /* uid, tid can stay at zero as set in header assemble */
279
280         /* BB add support for turning on the signing when
281         this function is used after 1st of session setup requests */
282
283         return rc;
284 }
285
286 /* If the return code is zero, this function must fill in request_buf pointer */
287 static int
288 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
289          void **request_buf /* returned */ ,
290          void **response_buf /* returned */ )
291 {
292         int rc = 0;
293
294         /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
295            check for tcp and smb session status done differently
296            for those three - in the calling routine */
297         if (tcon) {
298                 if (tcon->tidStatus == CifsExiting) {
299                         /* only tree disconnect, open, and write,
300                           (and ulogoff which does not have tcon)
301                           are allowed as we start force umount */
302                         if ((smb_command != SMB_COM_WRITE_ANDX) &&
303                            (smb_command != SMB_COM_OPEN_ANDX) &&
304                            (smb_command != SMB_COM_TREE_DISCONNECT)) {
305                                 cFYI(1, ("can not send cmd %d while umounting",
306                                         smb_command));
307                                 return -ENODEV;
308                         }
309                 }
310
311                 if ((tcon->ses) && (tcon->ses->status != CifsExiting) &&
312                                   (tcon->ses->server)) {
313                         struct nls_table *nls_codepage;
314                                 /* Give Demultiplex thread up to 10 seconds to
315                                    reconnect, should be greater than cifs socket
316                                    timeout which is 7 seconds */
317                         while (tcon->ses->server->tcpStatus ==
318                                                         CifsNeedReconnect) {
319                                 wait_event_interruptible_timeout(tcon->ses->server->response_q,
320                                         (tcon->ses->server->tcpStatus ==
321                                                         CifsGood), 10 * HZ);
322                                 if (tcon->ses->server->tcpStatus ==
323                                                 CifsNeedReconnect) {
324                                         /* on "soft" mounts we wait once */
325                                         if (!tcon->retry ||
326                                            (tcon->ses->status == CifsExiting)) {
327                                                 cFYI(1, ("gave up waiting on "
328                                                       "reconnect in smb_init"));
329                                                 return -EHOSTDOWN;
330                                         } /* else "hard" mount - keep retrying
331                                              until process is killed or server
332                                              comes on-line */
333                                 } else /* TCP session is reestablished now */
334                                         break;
335                         }
336                         nls_codepage = load_nls_default();
337                 /* need to prevent multiple threads trying to
338                 simultaneously reconnect the same SMB session */
339                         down(&tcon->ses->sesSem);
340                         if (tcon->ses->need_reconnect)
341                                 rc = cifs_setup_session(0, tcon->ses,
342                                                         nls_codepage);
343                         if (!rc && (tcon->need_reconnect)) {
344                                 mark_open_files_invalid(tcon);
345                                 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
346                                               tcon, nls_codepage);
347                                 up(&tcon->ses->sesSem);
348                                 /* BB FIXME add code to check if wsize needs
349                                 update due to negotiated smb buffer size
350                                 shrinking */
351                                 if (rc == 0) {
352                                         atomic_inc(&tconInfoReconnectCount);
353                                         /* tell server Unix caps we support */
354                                         if (tcon->ses->capabilities & CAP_UNIX)
355                                                 reset_cifs_unix_caps(
356                                                 0 /* no xid */,
357                                                 tcon,
358                                                 NULL /* do not know sb */,
359                                                 NULL /* no vol info */);
360                                 }
361
362                                 cFYI(1, ("reconnect tcon rc = %d", rc));
363                                 /* Removed call to reopen open files here.
364                                    It is safer (and faster) to reopen files
365                                    one at a time as needed in read and write */
366
367                                 /* Check if handle based operation so we
368                                    know whether we can continue or not without
369                                    returning to caller to reset file handle */
370                                 switch (smb_command) {
371                                         case SMB_COM_READ_ANDX:
372                                         case SMB_COM_WRITE_ANDX:
373                                         case SMB_COM_CLOSE:
374                                         case SMB_COM_FIND_CLOSE2:
375                                         case SMB_COM_LOCKING_ANDX: {
376                                                 unload_nls(nls_codepage);
377                                                 return -EAGAIN;
378                                         }
379                                 }
380                         } else {
381                                 up(&tcon->ses->sesSem);
382                         }
383                         unload_nls(nls_codepage);
384
385                 } else {
386                         return -EIO;
387                 }
388         }
389         if (rc)
390                 return rc;
391
392         *request_buf = cifs_buf_get();
393         if (*request_buf == NULL) {
394                 /* BB should we add a retry in here if not a writepage? */
395                 return -ENOMEM;
396         }
397     /* Although the original thought was we needed the response buf for  */
398     /* potential retries of smb operations it turns out we can determine */
399     /* from the mid flags when the request buffer can be resent without  */
400     /* having to use a second distinct buffer for the response */
401         if (response_buf)
402                 *response_buf = *request_buf;
403
404         header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
405                         wct);
406
407         if (tcon != NULL)
408                 cifs_stats_inc(&tcon->num_smbs_sent);
409
410         return rc;
411 }
412
413 static int validate_t2(struct smb_t2_rsp *pSMB)
414 {
415         int rc = -EINVAL;
416         int total_size;
417         char *pBCC;
418
419         /* check for plausible wct, bcc and t2 data and parm sizes */
420         /* check for parm and data offset going beyond end of smb */
421         if (pSMB->hdr.WordCount >= 10) {
422                 if ((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
423                    (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
424                         /* check that bcc is at least as big as parms + data */
425                         /* check that bcc is less than negotiated smb buffer */
426                         total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
427                         if (total_size < 512) {
428                                 total_size +=
429                                         le16_to_cpu(pSMB->t2_rsp.DataCount);
430                                 /* BCC le converted in SendReceive */
431                                 pBCC = (pSMB->hdr.WordCount * 2) +
432                                         sizeof(struct smb_hdr) +
433                                         (char *)pSMB;
434                                 if ((total_size <= (*(u16 *)pBCC)) &&
435                                    (total_size <
436                                         CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
437                                         return 0;
438                                 }
439                         }
440                 }
441         }
442         cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
443                 sizeof(struct smb_t2_rsp) + 16);
444         return rc;
445 }
446 int
447 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
448 {
449         NEGOTIATE_REQ *pSMB;
450         NEGOTIATE_RSP *pSMBr;
451         int rc = 0;
452         int bytes_returned;
453         int i;
454         struct TCP_Server_Info *server;
455         u16 count;
456         unsigned int secFlags;
457         u16 dialect;
458
459         if (ses->server)
460                 server = ses->server;
461         else {
462                 rc = -EIO;
463                 return rc;
464         }
465         rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
466                       (void **) &pSMB, (void **) &pSMBr);
467         if (rc)
468                 return rc;
469
470         /* if any of auth flags (ie not sign or seal) are overriden use them */
471         if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
472                 secFlags = ses->overrideSecFlg;  /* BB FIXME fix sign flags? */
473         else /* if override flags set only sign/seal OR them with global auth */
474                 secFlags = extended_security | ses->overrideSecFlg;
475
476         cFYI(1, ("secFlags 0x%x", secFlags));
477
478         pSMB->hdr.Mid = GetNextMid(server);
479         pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
480
481         if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
482                 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
483         else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
484                 cFYI(1, ("Kerberos only mechanism, enable extended security"));
485                 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
486         }
487
488         count = 0;
489         for (i = 0; i < CIFS_NUM_PROT; i++) {
490                 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
491                 count += strlen(protocols[i].name) + 1;
492                 /* null at end of source and target buffers anyway */
493         }
494         pSMB->hdr.smb_buf_length += count;
495         pSMB->ByteCount = cpu_to_le16(count);
496
497         rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
498                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
499         if (rc != 0)
500                 goto neg_err_exit;
501
502         dialect = le16_to_cpu(pSMBr->DialectIndex);
503         cFYI(1, ("Dialect: %d", dialect));
504         /* Check wct = 1 error case */
505         if ((pSMBr->hdr.WordCount < 13) || (dialect == BAD_PROT)) {
506                 /* core returns wct = 1, but we do not ask for core - otherwise
507                 small wct just comes when dialect index is -1 indicating we
508                 could not negotiate a common dialect */
509                 rc = -EOPNOTSUPP;
510                 goto neg_err_exit;
511 #ifdef CONFIG_CIFS_WEAK_PW_HASH
512         } else if ((pSMBr->hdr.WordCount == 13)
513                         && ((dialect == LANMAN_PROT)
514                                 || (dialect == LANMAN2_PROT))) {
515                 __s16 tmp;
516                 struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
517
518                 if ((secFlags & CIFSSEC_MAY_LANMAN) ||
519                         (secFlags & CIFSSEC_MAY_PLNTXT))
520                         server->secType = LANMAN;
521                 else {
522                         cERROR(1, ("mount failed weak security disabled"
523                                    " in /proc/fs/cifs/SecurityFlags"));
524                         rc = -EOPNOTSUPP;
525                         goto neg_err_exit;
526                 }
527                 server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
528                 server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
529                 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
530                                 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
531                 GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey);
532                 /* even though we do not use raw we might as well set this
533                 accurately, in case we ever find a need for it */
534                 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
535                         server->maxRw = 0xFF00;
536                         server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
537                 } else {
538                         server->maxRw = 0;/* we do not need to use raw anyway */
539                         server->capabilities = CAP_MPX_MODE;
540                 }
541                 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
542                 if (tmp == -1) {
543                         /* OS/2 often does not set timezone therefore
544                          * we must use server time to calc time zone.
545                          * Could deviate slightly from the right zone.
546                          * Smallest defined timezone difference is 15 minutes
547                          * (i.e. Nepal).  Rounding up/down is done to match
548                          * this requirement.
549                          */
550                         int val, seconds, remain, result;
551                         struct timespec ts, utc;
552                         utc = CURRENT_TIME;
553                         ts = cnvrtDosUnixTm(le16_to_cpu(rsp->SrvTime.Date),
554                                                 le16_to_cpu(rsp->SrvTime.Time));
555                         cFYI(1, ("SrvTime %d sec since 1970 (utc: %d) diff: %d",
556                                 (int)ts.tv_sec, (int)utc.tv_sec,
557                                 (int)(utc.tv_sec - ts.tv_sec)));
558                         val = (int)(utc.tv_sec - ts.tv_sec);
559                         seconds = abs(val);
560                         result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
561                         remain = seconds % MIN_TZ_ADJ;
562                         if (remain >= (MIN_TZ_ADJ / 2))
563                                 result += MIN_TZ_ADJ;
564                         if (val < 0)
565                                 result = -result;
566                         server->timeAdj = result;
567                 } else {
568                         server->timeAdj = (int)tmp;
569                         server->timeAdj *= 60; /* also in seconds */
570                 }
571                 cFYI(1, ("server->timeAdj: %d seconds", server->timeAdj));
572
573
574                 /* BB get server time for time conversions and add
575                 code to use it and timezone since this is not UTC */
576
577                 if (rsp->EncryptionKeyLength ==
578                                 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
579                         memcpy(server->cryptKey, rsp->EncryptionKey,
580                                 CIFS_CRYPTO_KEY_SIZE);
581                 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
582                         rc = -EIO; /* need cryptkey unless plain text */
583                         goto neg_err_exit;
584                 }
585
586                 cFYI(1, ("LANMAN negotiated"));
587                 /* we will not end up setting signing flags - as no signing
588                 was in LANMAN and server did not return the flags on */
589                 goto signing_check;
590 #else /* weak security disabled */
591         } else if (pSMBr->hdr.WordCount == 13) {
592                 cERROR(1, ("mount failed, cifs module not built "
593                           "with CIFS_WEAK_PW_HASH support"));
594                         rc = -EOPNOTSUPP;
595 #endif /* WEAK_PW_HASH */
596                 goto neg_err_exit;
597         } else if (pSMBr->hdr.WordCount != 17) {
598                 /* unknown wct */
599                 rc = -EOPNOTSUPP;
600                 goto neg_err_exit;
601         }
602         /* else wct == 17 NTLM */
603         server->secMode = pSMBr->SecurityMode;
604         if ((server->secMode & SECMODE_USER) == 0)
605                 cFYI(1, ("share mode security"));
606
607         if ((server->secMode & SECMODE_PW_ENCRYPT) == 0)
608 #ifdef CONFIG_CIFS_WEAK_PW_HASH
609                 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
610 #endif /* CIFS_WEAK_PW_HASH */
611                         cERROR(1, ("Server requests plain text password"
612                                   " but client support disabled"));
613
614         if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
615                 server->secType = NTLMv2;
616         else if (secFlags & CIFSSEC_MAY_NTLM)
617                 server->secType = NTLM;
618         else if (secFlags & CIFSSEC_MAY_NTLMV2)
619                 server->secType = NTLMv2;
620         else if (secFlags & CIFSSEC_MAY_KRB5)
621                 server->secType = Kerberos;
622         else if (secFlags & CIFSSEC_MAY_LANMAN)
623                 server->secType = LANMAN;
624 /* #ifdef CONFIG_CIFS_EXPERIMENTAL
625         else if (secFlags & CIFSSEC_MAY_PLNTXT)
626                 server->secType = ??
627 #endif */
628         else {
629                 rc = -EOPNOTSUPP;
630                 cERROR(1, ("Invalid security type"));
631                 goto neg_err_exit;
632         }
633         /* else ... any others ...? */
634
635         /* one byte, so no need to convert this or EncryptionKeyLen from
636            little endian */
637         server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
638         /* probably no need to store and check maxvcs */
639         server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
640                         (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
641         server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
642         cFYI(DBG2, ("Max buf = %d", ses->server->maxBuf));
643         GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
644         server->capabilities = le32_to_cpu(pSMBr->Capabilities);
645         server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
646         server->timeAdj *= 60;
647         if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
648                 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
649                        CIFS_CRYPTO_KEY_SIZE);
650         } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
651                         && (pSMBr->EncryptionKeyLength == 0)) {
652                 /* decode security blob */
653         } else if (server->secMode & SECMODE_PW_ENCRYPT) {
654                 rc = -EIO; /* no crypt key only if plain text pwd */
655                 goto neg_err_exit;
656         }
657
658         /* BB might be helpful to save off the domain of server here */
659
660         if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
661                 (server->capabilities & CAP_EXTENDED_SECURITY)) {
662                 count = pSMBr->ByteCount;
663                 if (count < 16) {
664                         rc = -EIO;
665                         goto neg_err_exit;
666                 }
667                 read_lock(&cifs_tcp_ses_lock);
668                 if (server->srv_count > 1) {
669                         read_unlock(&cifs_tcp_ses_lock);
670                         if (memcmp(server->server_GUID,
671                                    pSMBr->u.extended_response.
672                                    GUID, 16) != 0) {
673                                 cFYI(1, ("server UID changed"));
674                                 memcpy(server->server_GUID,
675                                         pSMBr->u.extended_response.GUID,
676                                         16);
677                         }
678                 } else {
679                         read_unlock(&cifs_tcp_ses_lock);
680                         memcpy(server->server_GUID,
681                                pSMBr->u.extended_response.GUID, 16);
682                 }
683
684                 if (count == 16) {
685                         server->secType = RawNTLMSSP;
686                 } else {
687                         rc = decode_negTokenInit(pSMBr->u.extended_response.
688                                                  SecurityBlob,
689                                                  count - 16,
690                                                  &server->secType);
691                         if (rc == 1)
692                                 rc = 0;
693                         else
694                                 rc = -EINVAL;
695                 }
696         } else
697                 server->capabilities &= ~CAP_EXTENDED_SECURITY;
698
699 #ifdef CONFIG_CIFS_WEAK_PW_HASH
700 signing_check:
701 #endif
702         if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
703                 /* MUST_SIGN already includes the MAY_SIGN FLAG
704                    so if this is zero it means that signing is disabled */
705                 cFYI(1, ("Signing disabled"));
706                 if (server->secMode & SECMODE_SIGN_REQUIRED) {
707                         cERROR(1, ("Server requires "
708                                    "packet signing to be enabled in "
709                                    "/proc/fs/cifs/SecurityFlags."));
710                         rc = -EOPNOTSUPP;
711                 }
712                 server->secMode &=
713                         ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
714         } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
715                 /* signing required */
716                 cFYI(1, ("Must sign - secFlags 0x%x", secFlags));
717                 if ((server->secMode &
718                         (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
719                         cERROR(1,
720                                 ("signing required but server lacks support"));
721                         rc = -EOPNOTSUPP;
722                 } else
723                         server->secMode |= SECMODE_SIGN_REQUIRED;
724         } else {
725                 /* signing optional ie CIFSSEC_MAY_SIGN */
726                 if ((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
727                         server->secMode &=
728                                 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
729         }
730
731 neg_err_exit:
732         cifs_buf_release(pSMB);
733
734         cFYI(1, ("negprot rc %d", rc));
735         return rc;
736 }
737
738 int
739 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
740 {
741         struct smb_hdr *smb_buffer;
742         int rc = 0;
743
744         cFYI(1, ("In tree disconnect"));
745
746         /* BB: do we need to check this? These should never be NULL. */
747         if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
748                 return -EIO;
749
750         /*
751          * No need to return error on this operation if tid invalidated and
752          * closed on server already e.g. due to tcp session crashing. Also,
753          * the tcon is no longer on the list, so no need to take lock before
754          * checking this.
755          */
756         if (tcon->need_reconnect)
757                 return 0;
758
759         rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
760                             (void **)&smb_buffer);
761         if (rc)
762                 return rc;
763
764         rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0);
765         if (rc)
766                 cFYI(1, ("Tree disconnect failed %d", rc));
767
768         /* No need to return error on this operation if tid invalidated and
769            closed on server already e.g. due to tcp session crashing */
770         if (rc == -EAGAIN)
771                 rc = 0;
772
773         return rc;
774 }
775
776 int
777 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
778 {
779         LOGOFF_ANDX_REQ *pSMB;
780         int rc = 0;
781
782         cFYI(1, ("In SMBLogoff for session disconnect"));
783
784         /*
785          * BB: do we need to check validity of ses and server? They should
786          * always be valid since we have an active reference. If not, that
787          * should probably be a BUG()
788          */
789         if (!ses || !ses->server)
790                 return -EIO;
791
792         down(&ses->sesSem);
793         if (ses->need_reconnect)
794                 goto session_already_dead; /* no need to send SMBlogoff if uid
795                                               already closed due to reconnect */
796         rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
797         if (rc) {
798                 up(&ses->sesSem);
799                 return rc;
800         }
801
802         pSMB->hdr.Mid = GetNextMid(ses->server);
803
804         if (ses->server->secMode &
805                    (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
806                         pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
807
808         pSMB->hdr.Uid = ses->Suid;
809
810         pSMB->AndXCommand = 0xFF;
811         rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0);
812 session_already_dead:
813         up(&ses->sesSem);
814
815         /* if session dead then we do not need to do ulogoff,
816                 since server closed smb session, no sense reporting
817                 error */
818         if (rc == -EAGAIN)
819                 rc = 0;
820         return rc;
821 }
822
823 int
824 CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
825                  __u16 type, const struct nls_table *nls_codepage, int remap)
826 {
827         TRANSACTION2_SPI_REQ *pSMB = NULL;
828         TRANSACTION2_SPI_RSP *pSMBr = NULL;
829         struct unlink_psx_rq *pRqD;
830         int name_len;
831         int rc = 0;
832         int bytes_returned = 0;
833         __u16 params, param_offset, offset, byte_count;
834
835         cFYI(1, ("In POSIX delete"));
836 PsxDelete:
837         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
838                       (void **) &pSMBr);
839         if (rc)
840                 return rc;
841
842         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
843                 name_len =
844                     cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
845                                      PATH_MAX, nls_codepage, remap);
846                 name_len++;     /* trailing null */
847                 name_len *= 2;
848         } else { /* BB add path length overrun check */
849                 name_len = strnlen(fileName, PATH_MAX);
850                 name_len++;     /* trailing null */
851                 strncpy(pSMB->FileName, fileName, name_len);
852         }
853
854         params = 6 + name_len;
855         pSMB->MaxParameterCount = cpu_to_le16(2);
856         pSMB->MaxDataCount = 0; /* BB double check this with jra */
857         pSMB->MaxSetupCount = 0;
858         pSMB->Reserved = 0;
859         pSMB->Flags = 0;
860         pSMB->Timeout = 0;
861         pSMB->Reserved2 = 0;
862         param_offset = offsetof(struct smb_com_transaction2_spi_req,
863                                 InformationLevel) - 4;
864         offset = param_offset + params;
865
866         /* Setup pointer to Request Data (inode type) */
867         pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
868         pRqD->type = cpu_to_le16(type);
869         pSMB->ParameterOffset = cpu_to_le16(param_offset);
870         pSMB->DataOffset = cpu_to_le16(offset);
871         pSMB->SetupCount = 1;
872         pSMB->Reserved3 = 0;
873         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
874         byte_count = 3 /* pad */  + params + sizeof(struct unlink_psx_rq);
875
876         pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
877         pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
878         pSMB->ParameterCount = cpu_to_le16(params);
879         pSMB->TotalParameterCount = pSMB->ParameterCount;
880         pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
881         pSMB->Reserved4 = 0;
882         pSMB->hdr.smb_buf_length += byte_count;
883         pSMB->ByteCount = cpu_to_le16(byte_count);
884         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
885                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
886         if (rc)
887                 cFYI(1, ("Posix delete returned %d", rc));
888         cifs_buf_release(pSMB);
889
890         cifs_stats_inc(&tcon->num_deletes);
891
892         if (rc == -EAGAIN)
893                 goto PsxDelete;
894
895         return rc;
896 }
897
898 int
899 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
900                const struct nls_table *nls_codepage, int remap)
901 {
902         DELETE_FILE_REQ *pSMB = NULL;
903         DELETE_FILE_RSP *pSMBr = NULL;
904         int rc = 0;
905         int bytes_returned;
906         int name_len;
907
908 DelFileRetry:
909         rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
910                       (void **) &pSMBr);
911         if (rc)
912                 return rc;
913
914         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
915                 name_len =
916                     cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
917                                      PATH_MAX, nls_codepage, remap);
918                 name_len++;     /* trailing null */
919                 name_len *= 2;
920         } else {                /* BB improve check for buffer overruns BB */
921                 name_len = strnlen(fileName, PATH_MAX);
922                 name_len++;     /* trailing null */
923                 strncpy(pSMB->fileName, fileName, name_len);
924         }
925         pSMB->SearchAttributes =
926             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
927         pSMB->BufferFormat = 0x04;
928         pSMB->hdr.smb_buf_length += name_len + 1;
929         pSMB->ByteCount = cpu_to_le16(name_len + 1);
930         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
931                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
932         cifs_stats_inc(&tcon->num_deletes);
933         if (rc)
934                 cFYI(1, ("Error in RMFile = %d", rc));
935
936         cifs_buf_release(pSMB);
937         if (rc == -EAGAIN)
938                 goto DelFileRetry;
939
940         return rc;
941 }
942
943 int
944 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
945              const struct nls_table *nls_codepage, int remap)
946 {
947         DELETE_DIRECTORY_REQ *pSMB = NULL;
948         DELETE_DIRECTORY_RSP *pSMBr = NULL;
949         int rc = 0;
950         int bytes_returned;
951         int name_len;
952
953         cFYI(1, ("In CIFSSMBRmDir"));
954 RmDirRetry:
955         rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
956                       (void **) &pSMBr);
957         if (rc)
958                 return rc;
959
960         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
961                 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
962                                          PATH_MAX, nls_codepage, remap);
963                 name_len++;     /* trailing null */
964                 name_len *= 2;
965         } else {                /* BB improve check for buffer overruns BB */
966                 name_len = strnlen(dirName, PATH_MAX);
967                 name_len++;     /* trailing null */
968                 strncpy(pSMB->DirName, dirName, name_len);
969         }
970
971         pSMB->BufferFormat = 0x04;
972         pSMB->hdr.smb_buf_length += name_len + 1;
973         pSMB->ByteCount = cpu_to_le16(name_len + 1);
974         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
975                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
976         cifs_stats_inc(&tcon->num_rmdirs);
977         if (rc)
978                 cFYI(1, ("Error in RMDir = %d", rc));
979
980         cifs_buf_release(pSMB);
981         if (rc == -EAGAIN)
982                 goto RmDirRetry;
983         return rc;
984 }
985
986 int
987 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
988              const char *name, const struct nls_table *nls_codepage, int remap)
989 {
990         int rc = 0;
991         CREATE_DIRECTORY_REQ *pSMB = NULL;
992         CREATE_DIRECTORY_RSP *pSMBr = NULL;
993         int bytes_returned;
994         int name_len;
995
996         cFYI(1, ("In CIFSSMBMkDir"));
997 MkDirRetry:
998         rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
999                       (void **) &pSMBr);
1000         if (rc)
1001                 return rc;
1002
1003         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1004                 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
1005                                             PATH_MAX, nls_codepage, remap);
1006                 name_len++;     /* trailing null */
1007                 name_len *= 2;
1008         } else {                /* BB improve check for buffer overruns BB */
1009                 name_len = strnlen(name, PATH_MAX);
1010                 name_len++;     /* trailing null */
1011                 strncpy(pSMB->DirName, name, name_len);
1012         }
1013
1014         pSMB->BufferFormat = 0x04;
1015         pSMB->hdr.smb_buf_length += name_len + 1;
1016         pSMB->ByteCount = cpu_to_le16(name_len + 1);
1017         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1018                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1019         cifs_stats_inc(&tcon->num_mkdirs);
1020         if (rc)
1021                 cFYI(1, ("Error in Mkdir = %d", rc));
1022
1023         cifs_buf_release(pSMB);
1024         if (rc == -EAGAIN)
1025                 goto MkDirRetry;
1026         return rc;
1027 }
1028
1029 int
1030 CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
1031                 __u64 mode, __u16 *netfid, FILE_UNIX_BASIC_INFO *pRetData,
1032                 __u32 *pOplock, const char *name,
1033                 const struct nls_table *nls_codepage, int remap)
1034 {
1035         TRANSACTION2_SPI_REQ *pSMB = NULL;
1036         TRANSACTION2_SPI_RSP *pSMBr = NULL;
1037         int name_len;
1038         int rc = 0;
1039         int bytes_returned = 0;
1040         __u16 params, param_offset, offset, byte_count, count;
1041         OPEN_PSX_REQ *pdata;
1042         OPEN_PSX_RSP *psx_rsp;
1043
1044         cFYI(1, ("In POSIX Create"));
1045 PsxCreat:
1046         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1047                       (void **) &pSMBr);
1048         if (rc)
1049                 return rc;
1050
1051         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1052                 name_len =
1053                     cifsConvertToUCS((__le16 *) pSMB->FileName, name,
1054                                      PATH_MAX, nls_codepage, remap);
1055                 name_len++;     /* trailing null */
1056                 name_len *= 2;
1057         } else {        /* BB improve the check for buffer overruns BB */
1058                 name_len = strnlen(name, PATH_MAX);
1059                 name_len++;     /* trailing null */
1060                 strncpy(pSMB->FileName, name, name_len);
1061         }
1062
1063         params = 6 + name_len;
1064         count = sizeof(OPEN_PSX_REQ);
1065         pSMB->MaxParameterCount = cpu_to_le16(2);
1066         pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1067         pSMB->MaxSetupCount = 0;
1068         pSMB->Reserved = 0;
1069         pSMB->Flags = 0;
1070         pSMB->Timeout = 0;
1071         pSMB->Reserved2 = 0;
1072         param_offset = offsetof(struct smb_com_transaction2_spi_req,
1073                                 InformationLevel) - 4;
1074         offset = param_offset + params;
1075         pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1076         pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1077         pdata->Permissions = cpu_to_le64(mode);
1078         pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1079         pdata->OpenFlags =  cpu_to_le32(*pOplock);
1080         pSMB->ParameterOffset = cpu_to_le16(param_offset);
1081         pSMB->DataOffset = cpu_to_le16(offset);
1082         pSMB->SetupCount = 1;
1083         pSMB->Reserved3 = 0;
1084         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1085         byte_count = 3 /* pad */  + params + count;
1086
1087         pSMB->DataCount = cpu_to_le16(count);
1088         pSMB->ParameterCount = cpu_to_le16(params);
1089         pSMB->TotalDataCount = pSMB->DataCount;
1090         pSMB->TotalParameterCount = pSMB->ParameterCount;
1091         pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1092         pSMB->Reserved4 = 0;
1093         pSMB->hdr.smb_buf_length += byte_count;
1094         pSMB->ByteCount = cpu_to_le16(byte_count);
1095         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1096                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1097         if (rc) {
1098                 cFYI(1, ("Posix create returned %d", rc));
1099                 goto psx_create_err;
1100         }
1101
1102         cFYI(1, ("copying inode info"));
1103         rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1104
1105         if (rc || (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP))) {
1106                 rc = -EIO;      /* bad smb */
1107                 goto psx_create_err;
1108         }
1109
1110         /* copy return information to pRetData */
1111         psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1112                         + le16_to_cpu(pSMBr->t2.DataOffset));
1113
1114         *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1115         if (netfid)
1116                 *netfid = psx_rsp->Fid;   /* cifs fid stays in le */
1117         /* Let caller know file was created so we can set the mode. */
1118         /* Do we care about the CreateAction in any other cases? */
1119         if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1120                 *pOplock |= CIFS_CREATE_ACTION;
1121         /* check to make sure response data is there */
1122         if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1123                 pRetData->Type = cpu_to_le32(-1); /* unknown */
1124                 cFYI(DBG2, ("unknown type"));
1125         } else {
1126                 if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP)
1127                                         + sizeof(FILE_UNIX_BASIC_INFO)) {
1128                         cERROR(1, ("Open response data too small"));
1129                         pRetData->Type = cpu_to_le32(-1);
1130                         goto psx_create_err;
1131                 }
1132                 memcpy((char *) pRetData,
1133                         (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1134                         sizeof(FILE_UNIX_BASIC_INFO));
1135         }
1136
1137 psx_create_err:
1138         cifs_buf_release(pSMB);
1139
1140         cifs_stats_inc(&tcon->num_mkdirs);
1141
1142         if (rc == -EAGAIN)
1143                 goto PsxCreat;
1144
1145         return rc;
1146 }
1147
1148 static __u16 convert_disposition(int disposition)
1149 {
1150         __u16 ofun = 0;
1151
1152         switch (disposition) {
1153                 case FILE_SUPERSEDE:
1154                         ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1155                         break;
1156                 case FILE_OPEN:
1157                         ofun = SMBOPEN_OAPPEND;
1158                         break;
1159                 case FILE_CREATE:
1160                         ofun = SMBOPEN_OCREATE;
1161                         break;
1162                 case FILE_OPEN_IF:
1163                         ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1164                         break;
1165                 case FILE_OVERWRITE:
1166                         ofun = SMBOPEN_OTRUNC;
1167                         break;
1168                 case FILE_OVERWRITE_IF:
1169                         ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1170                         break;
1171                 default:
1172                         cFYI(1, ("unknown disposition %d", disposition));
1173                         ofun =  SMBOPEN_OAPPEND; /* regular open */
1174         }
1175         return ofun;
1176 }
1177
1178 static int
1179 access_flags_to_smbopen_mode(const int access_flags)
1180 {
1181         int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1182
1183         if (masked_flags == GENERIC_READ)
1184                 return SMBOPEN_READ;
1185         else if (masked_flags == GENERIC_WRITE)
1186                 return SMBOPEN_WRITE;
1187
1188         /* just go for read/write */
1189         return SMBOPEN_READWRITE;
1190 }
1191
1192 int
1193 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
1194             const char *fileName, const int openDisposition,
1195             const int access_flags, const int create_options, __u16 *netfid,
1196             int *pOplock, FILE_ALL_INFO *pfile_info,
1197             const struct nls_table *nls_codepage, int remap)
1198 {
1199         int rc = -EACCES;
1200         OPENX_REQ *pSMB = NULL;
1201         OPENX_RSP *pSMBr = NULL;
1202         int bytes_returned;
1203         int name_len;
1204         __u16 count;
1205
1206 OldOpenRetry:
1207         rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1208                       (void **) &pSMBr);
1209         if (rc)
1210                 return rc;
1211
1212         pSMB->AndXCommand = 0xFF;       /* none */
1213
1214         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1215                 count = 1;      /* account for one byte pad to word boundary */
1216                 name_len =
1217                    cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1218                                     fileName, PATH_MAX, nls_codepage, remap);
1219                 name_len++;     /* trailing null */
1220                 name_len *= 2;
1221         } else {                /* BB improve check for buffer overruns BB */
1222                 count = 0;      /* no pad */
1223                 name_len = strnlen(fileName, PATH_MAX);
1224                 name_len++;     /* trailing null */
1225                 strncpy(pSMB->fileName, fileName, name_len);
1226         }
1227         if (*pOplock & REQ_OPLOCK)
1228                 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1229         else if (*pOplock & REQ_BATCHOPLOCK)
1230                 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1231
1232         pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1233         pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1234         pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1235         /* set file as system file if special file such
1236            as fifo and server expecting SFU style and
1237            no Unix extensions */
1238
1239         if (create_options & CREATE_OPTION_SPECIAL)
1240                 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1241         else /* BB FIXME BB */
1242                 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1243
1244         if (create_options & CREATE_OPTION_READONLY)
1245                 pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1246
1247         /* BB FIXME BB */
1248 /*      pSMB->CreateOptions = cpu_to_le32(create_options &
1249                                                  CREATE_OPTIONS_MASK); */
1250         /* BB FIXME END BB */
1251
1252         pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1253         pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1254         count += name_len;
1255         pSMB->hdr.smb_buf_length += count;
1256
1257         pSMB->ByteCount = cpu_to_le16(count);
1258         /* long_op set to 1 to allow for oplock break timeouts */
1259         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1260                         (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1261         cifs_stats_inc(&tcon->num_opens);
1262         if (rc) {
1263                 cFYI(1, ("Error in Open = %d", rc));
1264         } else {
1265         /* BB verify if wct == 15 */
1266
1267 /*              *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1268
1269                 *netfid = pSMBr->Fid;   /* cifs fid stays in le */
1270                 /* Let caller know file was created so we can set the mode. */
1271                 /* Do we care about the CreateAction in any other cases? */
1272         /* BB FIXME BB */
1273 /*              if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1274                         *pOplock |= CIFS_CREATE_ACTION; */
1275         /* BB FIXME END */
1276
1277                 if (pfile_info) {
1278                         pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1279                         pfile_info->LastAccessTime = 0; /* BB fixme */
1280                         pfile_info->LastWriteTime = 0; /* BB fixme */
1281                         pfile_info->ChangeTime = 0;  /* BB fixme */
1282                         pfile_info->Attributes =
1283                                 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1284                         /* the file_info buf is endian converted by caller */
1285                         pfile_info->AllocationSize =
1286                                 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1287                         pfile_info->EndOfFile = pfile_info->AllocationSize;
1288                         pfile_info->NumberOfLinks = cpu_to_le32(1);
1289                         pfile_info->DeletePending = 0;
1290                 }
1291         }
1292
1293         cifs_buf_release(pSMB);
1294         if (rc == -EAGAIN)
1295                 goto OldOpenRetry;
1296         return rc;
1297 }
1298
1299 int
1300 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1301             const char *fileName, const int openDisposition,
1302             const int access_flags, const int create_options, __u16 *netfid,
1303             int *pOplock, FILE_ALL_INFO *pfile_info,
1304             const struct nls_table *nls_codepage, int remap)
1305 {
1306         int rc = -EACCES;
1307         OPEN_REQ *pSMB = NULL;
1308         OPEN_RSP *pSMBr = NULL;
1309         int bytes_returned;
1310         int name_len;
1311         __u16 count;
1312
1313 openRetry:
1314         rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1315                       (void **) &pSMBr);
1316         if (rc)
1317                 return rc;
1318
1319         pSMB->AndXCommand = 0xFF;       /* none */
1320
1321         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1322                 count = 1;      /* account for one byte pad to word boundary */
1323                 name_len =
1324                     cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1325                                      fileName, PATH_MAX, nls_codepage, remap);
1326                 name_len++;     /* trailing null */
1327                 name_len *= 2;
1328                 pSMB->NameLength = cpu_to_le16(name_len);
1329         } else {                /* BB improve check for buffer overruns BB */
1330                 count = 0;      /* no pad */
1331                 name_len = strnlen(fileName, PATH_MAX);
1332                 name_len++;     /* trailing null */
1333                 pSMB->NameLength = cpu_to_le16(name_len);
1334                 strncpy(pSMB->fileName, fileName, name_len);
1335         }
1336         if (*pOplock & REQ_OPLOCK)
1337                 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1338         else if (*pOplock & REQ_BATCHOPLOCK)
1339                 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1340         pSMB->DesiredAccess = cpu_to_le32(access_flags);
1341         pSMB->AllocationSize = 0;
1342         /* set file as system file if special file such
1343            as fifo and server expecting SFU style and
1344            no Unix extensions */
1345         if (create_options & CREATE_OPTION_SPECIAL)
1346                 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1347         else
1348                 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1349
1350         /* XP does not handle ATTR_POSIX_SEMANTICS */
1351         /* but it helps speed up case sensitive checks for other
1352         servers such as Samba */
1353         if (tcon->ses->capabilities & CAP_UNIX)
1354                 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1355
1356         if (create_options & CREATE_OPTION_READONLY)
1357                 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1358
1359         pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1360         pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1361         pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1362         /* BB Expirement with various impersonation levels and verify */
1363         pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1364         pSMB->SecurityFlags =
1365             SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1366
1367         count += name_len;
1368         pSMB->hdr.smb_buf_length += count;
1369
1370         pSMB->ByteCount = cpu_to_le16(count);
1371         /* long_op set to 1 to allow for oplock break timeouts */
1372         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1373                         (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1374         cifs_stats_inc(&tcon->num_opens);
1375         if (rc) {
1376                 cFYI(1, ("Error in Open = %d", rc));
1377         } else {
1378                 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1379                 *netfid = pSMBr->Fid;   /* cifs fid stays in le */
1380                 /* Let caller know file was created so we can set the mode. */
1381                 /* Do we care about the CreateAction in any other cases? */
1382                 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1383                         *pOplock |= CIFS_CREATE_ACTION;
1384                 if (pfile_info) {
1385                     memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1386                         36 /* CreationTime to Attributes */);
1387                     /* the file_info buf is endian converted by caller */
1388                     pfile_info->AllocationSize = pSMBr->AllocationSize;
1389                     pfile_info->EndOfFile = pSMBr->EndOfFile;
1390                     pfile_info->NumberOfLinks = cpu_to_le32(1);
1391                     pfile_info->DeletePending = 0;
1392                 }
1393         }
1394
1395         cifs_buf_release(pSMB);
1396         if (rc == -EAGAIN)
1397                 goto openRetry;
1398         return rc;
1399 }
1400
1401 int
1402 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1403             const unsigned int count, const __u64 lseek, unsigned int *nbytes,
1404             char **buf, int *pbuf_type)
1405 {
1406         int rc = -EACCES;
1407         READ_REQ *pSMB = NULL;
1408         READ_RSP *pSMBr = NULL;
1409         char *pReadData = NULL;
1410         int wct;
1411         int resp_buf_type = 0;
1412         struct kvec iov[1];
1413
1414         cFYI(1, ("Reading %d bytes on fid %d", count, netfid));
1415         if (tcon->ses->capabilities & CAP_LARGE_FILES)
1416                 wct = 12;
1417         else
1418                 wct = 10; /* old style read */
1419
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 /* computes length of UCS string converted to host codepage
3903  * @src:        UCS string
3904  * @maxlen:     length of the input string in UCS characters
3905  *              (not in bytes)
3906  *
3907  * return:      size of input string in host codepage
3908  */
3909 static int hostlen_fromUCS(const __le16 *src, const int maxlen,
3910                 const struct nls_table *nls_codepage) {
3911         int i;
3912         int hostlen = 0;
3913         char to[4];
3914         int charlen;
3915         for (i = 0; (i < maxlen) && src[i]; ++i) {
3916                 charlen = nls_codepage->uni2char(le16_to_cpu(src[i]),
3917                                 to, NLS_MAX_CHARSET_SIZE);
3918                 hostlen += charlen > 0 ? charlen : 1;
3919         }
3920         return hostlen;
3921 }
3922
3923 /* parses DFS refferal V3 structure
3924  * caller is responsible for freeing target_nodes
3925  * returns:
3926  *      on success - 0
3927  *      on failure - errno
3928  */
3929 static int
3930 parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
3931                 unsigned int *num_of_nodes,
3932                 struct dfs_info3_param **target_nodes,
3933                 const struct nls_table *nls_codepage, int remap,
3934                 const char *searchName)
3935 {
3936         int i, rc = 0;
3937         char *data_end;
3938         bool is_unicode;
3939         struct dfs_referral_level_3 *ref;
3940
3941         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
3942                 is_unicode = true;
3943         else
3944                 is_unicode = false;
3945         *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
3946
3947         if (*num_of_nodes < 1) {
3948                 cERROR(1, ("num_referrals: must be at least > 0,"
3949                         "but we get num_referrals = %d\n", *num_of_nodes));
3950                 rc = -EINVAL;
3951                 goto parse_DFS_referrals_exit;
3952         }
3953
3954         ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
3955         if (ref->VersionNumber != cpu_to_le16(3)) {
3956                 cERROR(1, ("Referrals of V%d version are not supported,"
3957                         "should be V3", le16_to_cpu(ref->VersionNumber)));
3958                 rc = -EINVAL;
3959                 goto parse_DFS_referrals_exit;
3960         }
3961
3962         /* get the upper boundary of the resp buffer */
3963         data_end = (char *)(&(pSMBr->PathConsumed)) +
3964                                 le16_to_cpu(pSMBr->t2.DataCount);
3965
3966         cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n",
3967                         *num_of_nodes,
3968                         le16_to_cpu(pSMBr->DFSFlags)));
3969
3970         *target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
3971                         *num_of_nodes, GFP_KERNEL);
3972         if (*target_nodes == NULL) {
3973                 cERROR(1, ("Failed to allocate buffer for target_nodes\n"));
3974                 rc = -ENOMEM;
3975                 goto parse_DFS_referrals_exit;
3976         }
3977
3978         /* collect neccessary data from referrals */
3979         for (i = 0; i < *num_of_nodes; i++) {
3980                 char *temp;
3981                 int max_len;
3982                 struct dfs_info3_param *node = (*target_nodes)+i;
3983
3984                 node->flags = le16_to_cpu(pSMBr->DFSFlags);
3985                 if (is_unicode) {
3986                         __le16 *tmp = kmalloc(strlen(searchName)*2, GFP_KERNEL);
3987                         cifsConvertToUCS((__le16 *) tmp, searchName,
3988                                         PATH_MAX, nls_codepage, remap);
3989                         node->path_consumed = hostlen_fromUCS(tmp,
3990                                         le16_to_cpu(pSMBr->PathConsumed)/2,
3991                                         nls_codepage);
3992                         kfree(tmp);
3993                 } else
3994                         node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
3995
3996                 node->server_type = le16_to_cpu(ref->ServerType);
3997                 node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
3998
3999                 /* copy DfsPath */
4000                 temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
4001                 max_len = data_end - temp;
4002                 rc = cifs_strncpy_to_host(&(node->path_name), temp,
4003                                         max_len, is_unicode, nls_codepage);
4004                 if (rc)
4005                         goto parse_DFS_referrals_exit;
4006
4007                 /* copy link target UNC */
4008                 temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
4009                 max_len = data_end - temp;
4010                 rc = cifs_strncpy_to_host(&(node->node_name), temp,
4011                                         max_len, is_unicode, nls_codepage);
4012                 if (rc)
4013                         goto parse_DFS_referrals_exit;
4014
4015                 ref += le16_to_cpu(ref->Size);
4016         }
4017
4018 parse_DFS_referrals_exit:
4019         if (rc) {
4020                 free_dfs_info_array(*target_nodes, *num_of_nodes);
4021                 *target_nodes = NULL;
4022                 *num_of_nodes = 0;
4023         }
4024         return rc;
4025 }
4026
4027 int
4028 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
4029                 const unsigned char *searchName,
4030                 struct dfs_info3_param **target_nodes,
4031                 unsigned int *num_of_nodes,
4032                 const struct nls_table *nls_codepage, int remap)
4033 {
4034 /* TRANS2_GET_DFS_REFERRAL */
4035         TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
4036         TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
4037         int rc = 0;
4038         int bytes_returned;
4039         int name_len;
4040         __u16 params, byte_count;
4041         *num_of_nodes = 0;
4042         *target_nodes = NULL;
4043
4044         cFYI(1, ("In GetDFSRefer the path %s", searchName));
4045         if (ses == NULL)
4046                 return -ENODEV;
4047 getDFSRetry:
4048         rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
4049                       (void **) &pSMBr);
4050         if (rc)
4051                 return rc;
4052
4053         /* server pointer checked in called function,
4054         but should never be null here anyway */
4055         pSMB->hdr.Mid = GetNextMid(ses->server);
4056         pSMB->hdr.Tid = ses->ipc_tid;
4057         pSMB->hdr.Uid = ses->Suid;
4058         if (ses->capabilities & CAP_STATUS32)
4059                 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
4060         if (ses->capabilities & CAP_DFS)
4061                 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
4062
4063         if (ses->capabilities & CAP_UNICODE) {
4064                 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
4065                 name_len =
4066                     cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
4067                                      searchName, PATH_MAX, nls_codepage, remap);
4068                 name_len++;     /* trailing null */
4069                 name_len *= 2;
4070         } else {        /* BB improve the check for buffer overruns BB */
4071                 name_len = strnlen(searchName, PATH_MAX);
4072                 name_len++;     /* trailing null */
4073                 strncpy(pSMB->RequestFileName, searchName, name_len);
4074         }
4075
4076         if (ses->server) {
4077                 if (ses->server->secMode &
4078                    (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
4079                         pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4080         }
4081
4082         pSMB->hdr.Uid = ses->Suid;
4083
4084         params = 2 /* level */  + name_len /*includes null */ ;
4085         pSMB->TotalDataCount = 0;
4086         pSMB->DataCount = 0;
4087         pSMB->DataOffset = 0;
4088         pSMB->MaxParameterCount = 0;
4089         /* BB find exact max SMB PDU from sess structure BB */
4090         pSMB->MaxDataCount = cpu_to_le16(4000);
4091         pSMB->MaxSetupCount = 0;
4092         pSMB->Reserved = 0;
4093         pSMB->Flags = 0;
4094         pSMB->Timeout = 0;
4095         pSMB->Reserved2 = 0;
4096         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4097           struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
4098         pSMB->SetupCount = 1;
4099         pSMB->Reserved3 = 0;
4100         pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
4101         byte_count = params + 3 /* pad */ ;
4102         pSMB->ParameterCount = cpu_to_le16(params);
4103         pSMB->TotalParameterCount = pSMB->ParameterCount;
4104         pSMB->MaxReferralLevel = cpu_to_le16(3);
4105         pSMB->hdr.smb_buf_length += byte_count;
4106         pSMB->ByteCount = cpu_to_le16(byte_count);
4107
4108         rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
4109                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4110         if (rc) {
4111                 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
4112                 goto GetDFSRefExit;
4113         }
4114         rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4115
4116         /* BB Also check if enough total bytes returned? */
4117         if (rc || (pSMBr->ByteCount < 17)) {
4118                 rc = -EIO;      /* bad smb */
4119                 goto GetDFSRefExit;
4120         }
4121
4122         cFYI(1, ("Decoding GetDFSRefer response BCC: %d  Offset %d",
4123                                 pSMBr->ByteCount,
4124                                 le16_to_cpu(pSMBr->t2.DataOffset)));
4125
4126         /* parse returned result into more usable form */
4127         rc = parse_DFS_referrals(pSMBr, num_of_nodes,
4128                                  target_nodes, nls_codepage, remap,
4129                                  searchName);
4130
4131 GetDFSRefExit:
4132         cifs_buf_release(pSMB);
4133
4134         if (rc == -EAGAIN)
4135                 goto getDFSRetry;
4136
4137         return rc;
4138 }
4139
4140 /* Query File System Info such as free space to old servers such as Win 9x */
4141 int
4142 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4143 {
4144 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
4145         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4146         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4147         FILE_SYSTEM_ALLOC_INFO *response_data;
4148         int rc = 0;
4149         int bytes_returned = 0;
4150         __u16 params, byte_count;
4151
4152         cFYI(1, ("OldQFSInfo"));
4153 oldQFSInfoRetry:
4154         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4155                 (void **) &pSMBr);
4156         if (rc)
4157                 return rc;
4158
4159         params = 2;     /* level */
4160         pSMB->TotalDataCount = 0;
4161         pSMB->MaxParameterCount = cpu_to_le16(2);
4162         pSMB->MaxDataCount = cpu_to_le16(1000);
4163         pSMB->MaxSetupCount = 0;
4164         pSMB->Reserved = 0;
4165         pSMB->Flags = 0;
4166         pSMB->Timeout = 0;
4167         pSMB->Reserved2 = 0;
4168         byte_count = params + 1 /* pad */ ;
4169         pSMB->TotalParameterCount = cpu_to_le16(params);
4170         pSMB->ParameterCount = pSMB->TotalParameterCount;
4171         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4172         struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4173         pSMB->DataCount = 0;
4174         pSMB->DataOffset = 0;
4175         pSMB->SetupCount = 1;
4176         pSMB->Reserved3 = 0;
4177         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4178         pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
4179         pSMB->hdr.smb_buf_length += byte_count;
4180         pSMB->ByteCount = cpu_to_le16(byte_count);
4181
4182         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4183                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4184         if (rc) {
4185                 cFYI(1, ("Send error in QFSInfo = %d", rc));
4186         } else {                /* decode response */
4187                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4188
4189                 if (rc || (pSMBr->ByteCount < 18))
4190                         rc = -EIO;      /* bad smb */
4191                 else {
4192                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4193                         cFYI(1, ("qfsinf resp BCC: %d  Offset %d",
4194                                  pSMBr->ByteCount, data_offset));
4195
4196                         response_data = (FILE_SYSTEM_ALLOC_INFO *)
4197                                 (((char *) &pSMBr->hdr.Protocol) + data_offset);
4198                         FSData->f_bsize =
4199                                 le16_to_cpu(response_data->BytesPerSector) *
4200                                 le32_to_cpu(response_data->
4201                                         SectorsPerAllocationUnit);
4202                         FSData->f_blocks =
4203                                le32_to_cpu(response_data->TotalAllocationUnits);
4204                         FSData->f_bfree = FSData->f_bavail =
4205                                 le32_to_cpu(response_data->FreeAllocationUnits);
4206                         cFYI(1,
4207                              ("Blocks: %lld  Free: %lld Block size %ld",
4208                               (unsigned long long)FSData->f_blocks,
4209                               (unsigned long long)FSData->f_bfree,
4210                               FSData->f_bsize));
4211                 }
4212         }
4213         cifs_buf_release(pSMB);
4214
4215         if (rc == -EAGAIN)
4216                 goto oldQFSInfoRetry;
4217
4218         return rc;
4219 }
4220
4221 int
4222 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
4223 {
4224 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
4225         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4226         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4227         FILE_SYSTEM_INFO *response_data;
4228         int rc = 0;
4229         int bytes_returned = 0;
4230         __u16 params, byte_count;
4231
4232         cFYI(1, ("In QFSInfo"));
4233 QFSInfoRetry:
4234         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4235                       (void **) &pSMBr);
4236         if (rc)
4237                 return rc;
4238
4239         params = 2;     /* level */
4240         pSMB->TotalDataCount = 0;
4241         pSMB->MaxParameterCount = cpu_to_le16(2);
4242         pSMB->MaxDataCount = cpu_to_le16(1000);
4243         pSMB->MaxSetupCount = 0;
4244         pSMB->Reserved = 0;
4245         pSMB->Flags = 0;
4246         pSMB->Timeout = 0;
4247         pSMB->Reserved2 = 0;
4248         byte_count = params + 1 /* pad */ ;
4249         pSMB->TotalParameterCount = cpu_to_le16(params);
4250         pSMB->ParameterCount = pSMB->TotalParameterCount;
4251         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4252                 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4253         pSMB->DataCount = 0;
4254         pSMB->DataOffset = 0;
4255         pSMB->SetupCount = 1;
4256         pSMB->Reserved3 = 0;
4257         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4258         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
4259         pSMB->hdr.smb_buf_length += byte_count;
4260         pSMB->ByteCount = cpu_to_le16(byte_count);
4261
4262         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4263                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4264         if (rc) {
4265                 cFYI(1, ("Send error in QFSInfo = %d", rc));
4266         } else {                /* decode response */
4267                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4268
4269                 if (rc || (pSMBr->ByteCount < 24))
4270                         rc = -EIO;      /* bad smb */
4271                 else {
4272                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4273
4274                         response_data =
4275                             (FILE_SYSTEM_INFO
4276                              *) (((char *) &pSMBr->hdr.Protocol) +
4277                                  data_offset);
4278                         FSData->f_bsize =
4279                             le32_to_cpu(response_data->BytesPerSector) *
4280                             le32_to_cpu(response_data->
4281                                         SectorsPerAllocationUnit);
4282                         FSData->f_blocks =
4283                             le64_to_cpu(response_data->TotalAllocationUnits);
4284                         FSData->f_bfree = FSData->f_bavail =
4285                             le64_to_cpu(response_data->FreeAllocationUnits);
4286                         cFYI(1,
4287                              ("Blocks: %lld  Free: %lld Block size %ld",
4288                               (unsigned long long)FSData->f_blocks,
4289                               (unsigned long long)FSData->f_bfree,
4290                               FSData->f_bsize));
4291                 }
4292         }
4293         cifs_buf_release(pSMB);
4294
4295         if (rc == -EAGAIN)
4296                 goto QFSInfoRetry;
4297
4298         return rc;
4299 }
4300
4301 int
4302 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
4303 {
4304 /* level 0x105  SMB_QUERY_FILE_SYSTEM_INFO */
4305         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4306         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4307         FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
4308         int rc = 0;
4309         int bytes_returned = 0;
4310         __u16 params, byte_count;
4311
4312         cFYI(1, ("In QFSAttributeInfo"));
4313 QFSAttributeRetry:
4314         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4315                       (void **) &pSMBr);
4316         if (rc)
4317                 return rc;
4318
4319         params = 2;     /* level */
4320         pSMB->TotalDataCount = 0;
4321         pSMB->MaxParameterCount = cpu_to_le16(2);
4322         /* BB find exact max SMB PDU from sess structure BB */
4323         pSMB->MaxDataCount = cpu_to_le16(1000);
4324         pSMB->MaxSetupCount = 0;
4325         pSMB->Reserved = 0;
4326         pSMB->Flags = 0;
4327         pSMB->Timeout = 0;
4328         pSMB->Reserved2 = 0;
4329         byte_count = params + 1 /* pad */ ;
4330         pSMB->TotalParameterCount = cpu_to_le16(params);
4331         pSMB->ParameterCount = pSMB->TotalParameterCount;
4332         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4333                 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4334         pSMB->DataCount = 0;
4335         pSMB->DataOffset = 0;
4336         pSMB->SetupCount = 1;
4337         pSMB->Reserved3 = 0;
4338         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4339         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
4340         pSMB->hdr.smb_buf_length += byte_count;
4341         pSMB->ByteCount = cpu_to_le16(byte_count);
4342
4343         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4344                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4345         if (rc) {
4346                 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
4347         } else {                /* decode response */
4348                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4349
4350                 if (rc || (pSMBr->ByteCount < 13)) {
4351                         /* BB also check if enough bytes returned */
4352                         rc = -EIO;      /* bad smb */
4353                 } else {
4354                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4355                         response_data =
4356                             (FILE_SYSTEM_ATTRIBUTE_INFO
4357                              *) (((char *) &pSMBr->hdr.Protocol) +
4358                                  data_offset);
4359                         memcpy(&tcon->fsAttrInfo, response_data,
4360                                sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4361                 }
4362         }
4363         cifs_buf_release(pSMB);
4364
4365         if (rc == -EAGAIN)
4366                 goto QFSAttributeRetry;
4367
4368         return rc;
4369 }
4370
4371 int
4372 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
4373 {
4374 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
4375         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4376         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4377         FILE_SYSTEM_DEVICE_INFO *response_data;
4378         int rc = 0;
4379         int bytes_returned = 0;
4380         __u16 params, byte_count;
4381
4382         cFYI(1, ("In QFSDeviceInfo"));
4383 QFSDeviceRetry:
4384         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4385                       (void **) &pSMBr);
4386         if (rc)
4387                 return rc;
4388
4389         params = 2;     /* level */
4390         pSMB->TotalDataCount = 0;
4391         pSMB->MaxParameterCount = cpu_to_le16(2);
4392         /* BB find exact max SMB PDU from sess structure BB */
4393         pSMB->MaxDataCount = cpu_to_le16(1000);
4394         pSMB->MaxSetupCount = 0;
4395         pSMB->Reserved = 0;
4396         pSMB->Flags = 0;
4397         pSMB->Timeout = 0;
4398         pSMB->Reserved2 = 0;
4399         byte_count = params + 1 /* pad */ ;
4400         pSMB->TotalParameterCount = cpu_to_le16(params);
4401         pSMB->ParameterCount = pSMB->TotalParameterCount;
4402         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4403                 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4404
4405         pSMB->DataCount = 0;
4406         pSMB->DataOffset = 0;
4407         pSMB->SetupCount = 1;
4408         pSMB->Reserved3 = 0;
4409         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4410         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
4411         pSMB->hdr.smb_buf_length += byte_count;
4412         pSMB->ByteCount = cpu_to_le16(byte_count);
4413
4414         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4415                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4416         if (rc) {
4417                 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
4418         } else {                /* decode response */
4419                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4420
4421                 if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO)))
4422                         rc = -EIO;      /* bad smb */
4423                 else {
4424                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4425                         response_data =
4426                             (FILE_SYSTEM_DEVICE_INFO *)
4427                                 (((char *) &pSMBr->hdr.Protocol) +
4428                                  data_offset);
4429                         memcpy(&tcon->fsDevInfo, response_data,
4430                                sizeof(FILE_SYSTEM_DEVICE_INFO));
4431                 }
4432         }
4433         cifs_buf_release(pSMB);
4434
4435         if (rc == -EAGAIN)
4436                 goto QFSDeviceRetry;
4437
4438         return rc;
4439 }
4440
4441 int
4442 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
4443 {
4444 /* level 0x200  SMB_QUERY_CIFS_UNIX_INFO */
4445         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4446         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4447         FILE_SYSTEM_UNIX_INFO *response_data;
4448         int rc = 0;
4449         int bytes_returned = 0;
4450         __u16 params, byte_count;
4451
4452         cFYI(1, ("In QFSUnixInfo"));
4453 QFSUnixRetry:
4454         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4455                       (void **) &pSMBr);
4456         if (rc)
4457                 return rc;
4458
4459         params = 2;     /* level */
4460         pSMB->TotalDataCount = 0;
4461         pSMB->DataCount = 0;
4462         pSMB->DataOffset = 0;
4463         pSMB->MaxParameterCount = cpu_to_le16(2);
4464         /* BB find exact max SMB PDU from sess structure BB */
4465         pSMB->MaxDataCount = cpu_to_le16(100);
4466         pSMB->MaxSetupCount = 0;
4467         pSMB->Reserved = 0;
4468         pSMB->Flags = 0;
4469         pSMB->Timeout = 0;
4470         pSMB->Reserved2 = 0;
4471         byte_count = params + 1 /* pad */ ;
4472         pSMB->ParameterCount = cpu_to_le16(params);
4473         pSMB->TotalParameterCount = pSMB->ParameterCount;
4474         pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4475                         smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4476         pSMB->SetupCount = 1;
4477         pSMB->Reserved3 = 0;
4478         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4479         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
4480         pSMB->hdr.smb_buf_length += byte_count;
4481         pSMB->ByteCount = cpu_to_le16(byte_count);
4482
4483         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4484                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4485         if (rc) {
4486                 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
4487         } else {                /* decode response */
4488                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4489
4490                 if (rc || (pSMBr->ByteCount < 13)) {
4491                         rc = -EIO;      /* bad smb */
4492                 } else {
4493                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4494                         response_data =
4495                             (FILE_SYSTEM_UNIX_INFO
4496                              *) (((char *) &pSMBr->hdr.Protocol) +
4497                                  data_offset);
4498                         memcpy(&tcon->fsUnixInfo, response_data,
4499                                sizeof(FILE_SYSTEM_UNIX_INFO));
4500                 }
4501         }
4502         cifs_buf_release(pSMB);
4503
4504         if (rc == -EAGAIN)
4505                 goto QFSUnixRetry;
4506
4507
4508         return rc;
4509 }
4510
4511 int
4512 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
4513 {
4514 /* level 0x200  SMB_SET_CIFS_UNIX_INFO */
4515         TRANSACTION2_SETFSI_REQ *pSMB = NULL;
4516         TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
4517         int rc = 0;
4518         int bytes_returned = 0;
4519         __u16 params, param_offset, offset, byte_count;
4520
4521         cFYI(1, ("In SETFSUnixInfo"));
4522 SETFSUnixRetry:
4523         /* BB switch to small buf init to save memory */
4524         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4525                       (void **) &pSMBr);
4526         if (rc)
4527                 return rc;
4528
4529         params = 4;     /* 2 bytes zero followed by info level. */
4530         pSMB->MaxSetupCount = 0;
4531         pSMB->Reserved = 0;
4532         pSMB->Flags = 0;
4533         pSMB->Timeout = 0;
4534         pSMB->Reserved2 = 0;
4535         param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum)
4536                                 - 4;
4537         offset = param_offset + params;
4538
4539         pSMB->MaxParameterCount = cpu_to_le16(4);
4540         /* BB find exact max SMB PDU from sess structure BB */
4541         pSMB->MaxDataCount = cpu_to_le16(100);
4542         pSMB->SetupCount = 1;
4543         pSMB->Reserved3 = 0;
4544         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
4545         byte_count = 1 /* pad */ + params + 12;
4546
4547         pSMB->DataCount = cpu_to_le16(12);
4548         pSMB->ParameterCount = cpu_to_le16(params);
4549         pSMB->TotalDataCount = pSMB->DataCount;
4550         pSMB->TotalParameterCount = pSMB->ParameterCount;
4551         pSMB->ParameterOffset = cpu_to_le16(param_offset);
4552         pSMB->DataOffset = cpu_to_le16(offset);
4553
4554         /* Params. */
4555         pSMB->FileNum = 0;
4556         pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
4557
4558         /* Data. */
4559         pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
4560         pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
4561         pSMB->ClientUnixCap = cpu_to_le64(cap);
4562
4563         pSMB->hdr.smb_buf_length += byte_count;
4564         pSMB->ByteCount = cpu_to_le16(byte_count);
4565
4566         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4567                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4568         if (rc) {
4569                 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
4570         } else {                /* decode response */
4571                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4572                 if (rc)
4573                         rc = -EIO;      /* bad smb */
4574         }
4575         cifs_buf_release(pSMB);
4576
4577         if (rc == -EAGAIN)
4578                 goto SETFSUnixRetry;
4579
4580         return rc;
4581 }
4582
4583
4584
4585 int
4586 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
4587                    struct kstatfs *FSData)
4588 {
4589 /* level 0x201  SMB_QUERY_CIFS_POSIX_INFO */
4590         TRANSACTION2_QFSI_REQ *pSMB = NULL;
4591         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
4592         FILE_SYSTEM_POSIX_INFO *response_data;
4593         int rc = 0;
4594         int bytes_returned = 0;
4595         __u16 params, byte_count;
4596
4597         cFYI(1, ("In QFSPosixInfo"));
4598 QFSPosixRetry:
4599         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4600                       (void **) &pSMBr);
4601         if (rc)
4602                 return rc;
4603
4604         params = 2;     /* level */
4605         pSMB->TotalDataCount = 0;
4606         pSMB->DataCount = 0;
4607         pSMB->DataOffset = 0;
4608         pSMB->MaxParameterCount = cpu_to_le16(2);
4609         /* BB find exact max SMB PDU from sess structure BB */
4610         pSMB->MaxDataCount = cpu_to_le16(100);
4611         pSMB->MaxSetupCount = 0;
4612         pSMB->Reserved = 0;
4613         pSMB->Flags = 0;
4614         pSMB->Timeout = 0;
4615         pSMB->Reserved2 = 0;
4616         byte_count = params + 1 /* pad */ ;
4617         pSMB->ParameterCount = cpu_to_le16(params);
4618         pSMB->TotalParameterCount = pSMB->ParameterCount;
4619         pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
4620                         smb_com_transaction2_qfsi_req, InformationLevel) - 4);
4621         pSMB->SetupCount = 1;
4622         pSMB->Reserved3 = 0;
4623         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
4624         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
4625         pSMB->hdr.smb_buf_length += byte_count;
4626         pSMB->ByteCount = cpu_to_le16(byte_count);
4627
4628         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4629                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4630         if (rc) {
4631                 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
4632         } else {                /* decode response */
4633                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4634
4635                 if (rc || (pSMBr->ByteCount < 13)) {
4636                         rc = -EIO;      /* bad smb */
4637                 } else {
4638                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4639                         response_data =
4640                             (FILE_SYSTEM_POSIX_INFO
4641                              *) (((char *) &pSMBr->hdr.Protocol) +
4642                                  data_offset);
4643                         FSData->f_bsize =
4644                                         le32_to_cpu(response_data->BlockSize);
4645                         FSData->f_blocks =
4646                                         le64_to_cpu(response_data->TotalBlocks);
4647                         FSData->f_bfree =
4648                             le64_to_cpu(response_data->BlocksAvail);
4649                         if (response_data->UserBlocksAvail == cpu_to_le64(-1)) {
4650                                 FSData->f_bavail = FSData->f_bfree;
4651                         } else {
4652                                 FSData->f_bavail =
4653                                     le64_to_cpu(response_data->UserBlocksAvail);
4654                         }
4655                         if (response_data->TotalFileNodes != cpu_to_le64(-1))
4656                                 FSData->f_files =
4657                                      le64_to_cpu(response_data->TotalFileNodes);
4658                         if (response_data->FreeFileNodes != cpu_to_le64(-1))
4659                                 FSData->f_ffree =
4660                                       le64_to_cpu(response_data->FreeFileNodes);
4661                 }
4662         }
4663         cifs_buf_release(pSMB);
4664
4665         if (rc == -EAGAIN)
4666                 goto QFSPosixRetry;
4667
4668         return rc;
4669 }
4670
4671
4672 /* We can not use write of zero bytes trick to
4673    set file size due to need for large file support.  Also note that
4674    this SetPathInfo is preferred to SetFileInfo based method in next
4675    routine which is only needed to work around a sharing violation bug
4676    in Samba which this routine can run into */
4677
4678 int
4679 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4680               __u64 size, bool SetAllocation,
4681               const struct nls_table *nls_codepage, int remap)
4682 {
4683         struct smb_com_transaction2_spi_req *pSMB = NULL;
4684         struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4685         struct file_end_of_file_info *parm_data;
4686         int name_len;
4687         int rc = 0;
4688         int bytes_returned = 0;
4689         __u16 params, byte_count, data_count, param_offset, offset;
4690
4691         cFYI(1, ("In SetEOF"));
4692 SetEOFRetry:
4693         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4694                       (void **) &pSMBr);
4695         if (rc)
4696                 return rc;
4697
4698         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4699                 name_len =
4700                     cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4701                                      PATH_MAX, nls_codepage, remap);
4702                 name_len++;     /* trailing null */
4703                 name_len *= 2;
4704         } else {        /* BB improve the check for buffer overruns BB */
4705                 name_len = strnlen(fileName, PATH_MAX);
4706                 name_len++;     /* trailing null */
4707                 strncpy(pSMB->FileName, fileName, name_len);
4708         }
4709         params = 6 + name_len;
4710         data_count = sizeof(struct file_end_of_file_info);
4711         pSMB->MaxParameterCount = cpu_to_le16(2);
4712         pSMB->MaxDataCount = cpu_to_le16(4100);
4713         pSMB->MaxSetupCount = 0;
4714         pSMB->Reserved = 0;
4715         pSMB->Flags = 0;
4716         pSMB->Timeout = 0;
4717         pSMB->Reserved2 = 0;
4718         param_offset = offsetof(struct smb_com_transaction2_spi_req,
4719                                 InformationLevel) - 4;
4720         offset = param_offset + params;
4721         if (SetAllocation) {
4722                 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4723                         pSMB->InformationLevel =
4724                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4725                 else
4726                         pSMB->InformationLevel =
4727                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4728         } else /* Set File Size */  {
4729             if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4730                     pSMB->InformationLevel =
4731                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4732             else
4733                     pSMB->InformationLevel =
4734                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4735         }
4736
4737         parm_data =
4738             (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
4739                                        offset);
4740         pSMB->ParameterOffset = cpu_to_le16(param_offset);
4741         pSMB->DataOffset = cpu_to_le16(offset);
4742         pSMB->SetupCount = 1;
4743         pSMB->Reserved3 = 0;
4744         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4745         byte_count = 3 /* pad */  + params + data_count;
4746         pSMB->DataCount = cpu_to_le16(data_count);
4747         pSMB->TotalDataCount = pSMB->DataCount;
4748         pSMB->ParameterCount = cpu_to_le16(params);
4749         pSMB->TotalParameterCount = pSMB->ParameterCount;
4750         pSMB->Reserved4 = 0;
4751         pSMB->hdr.smb_buf_length += byte_count;
4752         parm_data->FileSize = cpu_to_le64(size);
4753         pSMB->ByteCount = cpu_to_le16(byte_count);
4754         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4755                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4756         if (rc)
4757                 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
4758
4759         cifs_buf_release(pSMB);
4760
4761         if (rc == -EAGAIN)
4762                 goto SetEOFRetry;
4763
4764         return rc;
4765 }
4766
4767 int
4768 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4769                    __u16 fid, __u32 pid_of_opener, bool SetAllocation)
4770 {
4771         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
4772         char *data_offset;
4773         struct file_end_of_file_info *parm_data;
4774         int rc = 0;
4775         __u16 params, param_offset, offset, byte_count, count;
4776
4777         cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
4778                         (long long)size));
4779         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4780
4781         if (rc)
4782                 return rc;
4783
4784         pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4785         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4786
4787         params = 6;
4788         pSMB->MaxSetupCount = 0;
4789         pSMB->Reserved = 0;
4790         pSMB->Flags = 0;
4791         pSMB->Timeout = 0;
4792         pSMB->Reserved2 = 0;
4793         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4794         offset = param_offset + params;
4795
4796         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4797
4798         count = sizeof(struct file_end_of_file_info);
4799         pSMB->MaxParameterCount = cpu_to_le16(2);
4800         /* BB find exact max SMB PDU from sess structure BB */
4801         pSMB->MaxDataCount = cpu_to_le16(1000);
4802         pSMB->SetupCount = 1;
4803         pSMB->Reserved3 = 0;
4804         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4805         byte_count = 3 /* pad */  + params + count;
4806         pSMB->DataCount = cpu_to_le16(count);
4807         pSMB->ParameterCount = cpu_to_le16(params);
4808         pSMB->TotalDataCount = pSMB->DataCount;
4809         pSMB->TotalParameterCount = pSMB->ParameterCount;
4810         pSMB->ParameterOffset = cpu_to_le16(param_offset);
4811         parm_data =
4812                 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol)
4813                                 + offset);
4814         pSMB->DataOffset = cpu_to_le16(offset);
4815         parm_data->FileSize = cpu_to_le64(size);
4816         pSMB->Fid = fid;
4817         if (SetAllocation) {
4818                 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4819                         pSMB->InformationLevel =
4820                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
4821                 else
4822                         pSMB->InformationLevel =
4823                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
4824         } else /* Set File Size */  {
4825             if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4826                     pSMB->InformationLevel =
4827                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
4828             else
4829                     pSMB->InformationLevel =
4830                                 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
4831         }
4832         pSMB->Reserved4 = 0;
4833         pSMB->hdr.smb_buf_length += byte_count;
4834         pSMB->ByteCount = cpu_to_le16(byte_count);
4835         rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4836         if (rc) {
4837                 cFYI(1,
4838                      ("Send error in SetFileInfo (SetFileSize) = %d",
4839                       rc));
4840         }
4841
4842         /* Note: On -EAGAIN error only caller can retry on handle based calls
4843                 since file handle passed in no longer valid */
4844
4845         return rc;
4846 }
4847
4848 /* Some legacy servers such as NT4 require that the file times be set on
4849    an open handle, rather than by pathname - this is awkward due to
4850    potential access conflicts on the open, but it is unavoidable for these
4851    old servers since the only other choice is to go from 100 nanosecond DCE
4852    time and resort to the original setpathinfo level which takes the ancient
4853    DOS time format with 2 second granularity */
4854 int
4855 CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon,
4856                     const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener)
4857 {
4858         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
4859         char *data_offset;
4860         int rc = 0;
4861         __u16 params, param_offset, offset, byte_count, count;
4862
4863         cFYI(1, ("Set Times (via SetFileInfo)"));
4864         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4865
4866         if (rc)
4867                 return rc;
4868
4869         pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4870         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4871
4872         params = 6;
4873         pSMB->MaxSetupCount = 0;
4874         pSMB->Reserved = 0;
4875         pSMB->Flags = 0;
4876         pSMB->Timeout = 0;
4877         pSMB->Reserved2 = 0;
4878         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4879         offset = param_offset + params;
4880
4881         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4882
4883         count = sizeof(FILE_BASIC_INFO);
4884         pSMB->MaxParameterCount = cpu_to_le16(2);
4885         /* BB find max SMB PDU from sess */
4886         pSMB->MaxDataCount = cpu_to_le16(1000);
4887         pSMB->SetupCount = 1;
4888         pSMB->Reserved3 = 0;
4889         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4890         byte_count = 3 /* pad */  + params + count;
4891         pSMB->DataCount = cpu_to_le16(count);
4892         pSMB->ParameterCount = cpu_to_le16(params);
4893         pSMB->TotalDataCount = pSMB->DataCount;
4894         pSMB->TotalParameterCount = pSMB->ParameterCount;
4895         pSMB->ParameterOffset = cpu_to_le16(param_offset);
4896         pSMB->DataOffset = cpu_to_le16(offset);
4897         pSMB->Fid = fid;
4898         if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4899                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4900         else
4901                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4902         pSMB->Reserved4 = 0;
4903         pSMB->hdr.smb_buf_length += byte_count;
4904         pSMB->ByteCount = cpu_to_le16(byte_count);
4905         memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4906         rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4907         if (rc)
4908                 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc));
4909
4910         /* Note: On -EAGAIN error only caller can retry on handle based calls
4911                 since file handle passed in no longer valid */
4912
4913         return rc;
4914 }
4915
4916 int
4917 CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon,
4918                           bool delete_file, __u16 fid, __u32 pid_of_opener)
4919 {
4920         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
4921         char *data_offset;
4922         int rc = 0;
4923         __u16 params, param_offset, offset, byte_count, count;
4924
4925         cFYI(1, ("Set File Disposition (via SetFileInfo)"));
4926         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
4927
4928         if (rc)
4929                 return rc;
4930
4931         pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
4932         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
4933
4934         params = 6;
4935         pSMB->MaxSetupCount = 0;
4936         pSMB->Reserved = 0;
4937         pSMB->Flags = 0;
4938         pSMB->Timeout = 0;
4939         pSMB->Reserved2 = 0;
4940         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4941         offset = param_offset + params;
4942
4943         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4944
4945         count = 1;
4946         pSMB->MaxParameterCount = cpu_to_le16(2);
4947         /* BB find max SMB PDU from sess */
4948         pSMB->MaxDataCount = cpu_to_le16(1000);
4949         pSMB->SetupCount = 1;
4950         pSMB->Reserved3 = 0;
4951         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
4952         byte_count = 3 /* pad */  + params + count;
4953         pSMB->DataCount = cpu_to_le16(count);
4954         pSMB->ParameterCount = cpu_to_le16(params);
4955         pSMB->TotalDataCount = pSMB->DataCount;
4956         pSMB->TotalParameterCount = pSMB->ParameterCount;
4957         pSMB->ParameterOffset = cpu_to_le16(param_offset);
4958         pSMB->DataOffset = cpu_to_le16(offset);
4959         pSMB->Fid = fid;
4960         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO);
4961         pSMB->Reserved4 = 0;
4962         pSMB->hdr.smb_buf_length += byte_count;
4963         pSMB->ByteCount = cpu_to_le16(byte_count);
4964         *data_offset = delete_file ? 1 : 0;
4965         rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
4966         if (rc)
4967                 cFYI(1, ("Send error in SetFileDisposition = %d", rc));
4968
4969         return rc;
4970 }
4971
4972 int
4973 CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon,
4974                    const char *fileName, const FILE_BASIC_INFO *data,
4975                    const struct nls_table *nls_codepage, int remap)
4976 {
4977         TRANSACTION2_SPI_REQ *pSMB = NULL;
4978         TRANSACTION2_SPI_RSP *pSMBr = NULL;
4979         int name_len;
4980         int rc = 0;
4981         int bytes_returned = 0;
4982         char *data_offset;
4983         __u16 params, param_offset, offset, byte_count, count;
4984
4985         cFYI(1, ("In SetTimes"));
4986
4987 SetTimesRetry:
4988         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4989                       (void **) &pSMBr);
4990         if (rc)
4991                 return rc;
4992
4993         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4994                 name_len =
4995                     cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4996                                      PATH_MAX, nls_codepage, remap);
4997                 name_len++;     /* trailing null */
4998                 name_len *= 2;
4999         } else {        /* BB improve the check for buffer overruns BB */
5000                 name_len = strnlen(fileName, PATH_MAX);
5001                 name_len++;     /* trailing null */
5002                 strncpy(pSMB->FileName, fileName, name_len);
5003         }
5004
5005         params = 6 + name_len;
5006         count = sizeof(FILE_BASIC_INFO);
5007         pSMB->MaxParameterCount = cpu_to_le16(2);
5008         /* BB find max SMB PDU from sess structure BB */
5009         pSMB->MaxDataCount = cpu_to_le16(1000);
5010         pSMB->MaxSetupCount = 0;
5011         pSMB->Reserved = 0;
5012         pSMB->Flags = 0;
5013         pSMB->Timeout = 0;
5014         pSMB->Reserved2 = 0;
5015         param_offset = offsetof(struct smb_com_transaction2_spi_req,
5016                                 InformationLevel) - 4;
5017         offset = param_offset + params;
5018         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
5019         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5020         pSMB->DataOffset = cpu_to_le16(offset);
5021         pSMB->SetupCount = 1;
5022         pSMB->Reserved3 = 0;
5023         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5024         byte_count = 3 /* pad */  + params + count;
5025
5026         pSMB->DataCount = cpu_to_le16(count);
5027         pSMB->ParameterCount = cpu_to_le16(params);
5028         pSMB->TotalDataCount = pSMB->DataCount;
5029         pSMB->TotalParameterCount = pSMB->ParameterCount;
5030         if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
5031                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
5032         else
5033                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
5034         pSMB->Reserved4 = 0;
5035         pSMB->hdr.smb_buf_length += byte_count;
5036         memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
5037         pSMB->ByteCount = cpu_to_le16(byte_count);
5038         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5039                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5040         if (rc)
5041                 cFYI(1, ("SetPathInfo (times) returned %d", rc));
5042
5043         cifs_buf_release(pSMB);
5044
5045         if (rc == -EAGAIN)
5046                 goto SetTimesRetry;
5047
5048         return rc;
5049 }
5050
5051 /* Can not be used to set time stamps yet (due to old DOS time format) */
5052 /* Can be used to set attributes */
5053 #if 0  /* Possibly not needed - since it turns out that strangely NT4 has a bug
5054           handling it anyway and NT4 was what we thought it would be needed for
5055           Do not delete it until we prove whether needed for Win9x though */
5056 int
5057 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
5058                 __u16 dos_attrs, const struct nls_table *nls_codepage)
5059 {
5060         SETATTR_REQ *pSMB = NULL;
5061         SETATTR_RSP *pSMBr = NULL;
5062         int rc = 0;
5063         int bytes_returned;
5064         int name_len;
5065
5066         cFYI(1, ("In SetAttrLegacy"));
5067
5068 SetAttrLgcyRetry:
5069         rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
5070                       (void **) &pSMBr);
5071         if (rc)
5072                 return rc;
5073
5074         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5075                 name_len =
5076                         ConvertToUCS((__le16 *) pSMB->fileName, fileName,
5077                                 PATH_MAX, nls_codepage);
5078                 name_len++;     /* trailing null */
5079                 name_len *= 2;
5080         } else {        /* BB improve the check for buffer overruns BB */
5081                 name_len = strnlen(fileName, PATH_MAX);
5082                 name_len++;     /* trailing null */
5083                 strncpy(pSMB->fileName, fileName, name_len);
5084         }
5085         pSMB->attr = cpu_to_le16(dos_attrs);
5086         pSMB->BufferFormat = 0x04;
5087         pSMB->hdr.smb_buf_length += name_len + 1;
5088         pSMB->ByteCount = cpu_to_le16(name_len + 1);
5089         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5090                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5091         if (rc)
5092                 cFYI(1, ("Error in LegacySetAttr = %d", rc));
5093
5094         cifs_buf_release(pSMB);
5095
5096         if (rc == -EAGAIN)
5097                 goto SetAttrLgcyRetry;
5098
5099         return rc;
5100 }
5101 #endif /* temporarily unneeded SetAttr legacy function */
5102
5103 int
5104 CIFSSMBUnixSetInfo(const int xid, struct cifsTconInfo *tcon, char *fileName,
5105                    const struct cifs_unix_set_info_args *args,
5106                    const struct nls_table *nls_codepage, int remap)
5107 {
5108         TRANSACTION2_SPI_REQ *pSMB = NULL;
5109         TRANSACTION2_SPI_RSP *pSMBr = NULL;
5110         int name_len;
5111         int rc = 0;
5112         int bytes_returned = 0;
5113         FILE_UNIX_BASIC_INFO *data_offset;
5114         __u16 params, param_offset, offset, count, byte_count;
5115         __u64 mode = args->mode;
5116
5117         cFYI(1, ("In SetUID/GID/Mode"));
5118 setPermsRetry:
5119         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5120                       (void **) &pSMBr);
5121         if (rc)
5122                 return rc;
5123
5124         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5125                 name_len =
5126                     cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5127                                      PATH_MAX, nls_codepage, remap);
5128                 name_len++;     /* trailing null */
5129                 name_len *= 2;
5130         } else {        /* BB improve the check for buffer overruns BB */
5131                 name_len = strnlen(fileName, PATH_MAX);
5132                 name_len++;     /* trailing null */
5133                 strncpy(pSMB->FileName, fileName, name_len);
5134         }
5135
5136         params = 6 + name_len;
5137         count = sizeof(FILE_UNIX_BASIC_INFO);
5138         pSMB->MaxParameterCount = cpu_to_le16(2);
5139         /* BB find max SMB PDU from sess structure BB */
5140         pSMB->MaxDataCount = cpu_to_le16(1000);
5141         pSMB->MaxSetupCount = 0;
5142         pSMB->Reserved = 0;
5143         pSMB->Flags = 0;
5144         pSMB->Timeout = 0;
5145         pSMB->Reserved2 = 0;
5146         param_offset = offsetof(struct smb_com_transaction2_spi_req,
5147                                 InformationLevel) - 4;
5148         offset = param_offset + params;
5149         data_offset =
5150             (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
5151                                       offset);
5152         memset(data_offset, 0, count);
5153         pSMB->DataOffset = cpu_to_le16(offset);
5154         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5155         pSMB->SetupCount = 1;
5156         pSMB->Reserved3 = 0;
5157         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5158         byte_count = 3 /* pad */  + params + count;
5159         pSMB->ParameterCount = cpu_to_le16(params);
5160         pSMB->DataCount = cpu_to_le16(count);
5161         pSMB->TotalParameterCount = pSMB->ParameterCount;
5162         pSMB->TotalDataCount = pSMB->DataCount;
5163         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5164         pSMB->Reserved4 = 0;
5165         pSMB->hdr.smb_buf_length += byte_count;
5166         /* Samba server ignores set of file size to zero due to bugs in some
5167         older clients, but we should be precise - we use SetFileSize to
5168         set file size and do not want to truncate file size to zero
5169         accidently as happened on one Samba server beta by putting
5170         zero instead of -1 here */
5171         data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5172         data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5173         data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5174         data_offset->LastAccessTime = cpu_to_le64(args->atime);
5175         data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5176         data_offset->Uid = cpu_to_le64(args->uid);
5177         data_offset->Gid = cpu_to_le64(args->gid);
5178         /* better to leave device as zero when it is  */
5179         data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5180         data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5181         data_offset->Permissions = cpu_to_le64(mode);
5182
5183         if (S_ISREG(mode))
5184                 data_offset->Type = cpu_to_le32(UNIX_FILE);
5185         else if (S_ISDIR(mode))
5186                 data_offset->Type = cpu_to_le32(UNIX_DIR);
5187         else if (S_ISLNK(mode))
5188                 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5189         else if (S_ISCHR(mode))
5190                 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5191         else if (S_ISBLK(mode))
5192                 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5193         else if (S_ISFIFO(mode))
5194                 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5195         else if (S_ISSOCK(mode))
5196                 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5197
5198
5199         pSMB->ByteCount = cpu_to_le16(byte_count);
5200         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5201                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5202         if (rc)
5203                 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
5204
5205         cifs_buf_release(pSMB);
5206         if (rc == -EAGAIN)
5207                 goto setPermsRetry;
5208         return rc;
5209 }
5210
5211 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5212                   const int notify_subdirs, const __u16 netfid,
5213                   __u32 filter, struct file *pfile, int multishot,
5214                   const struct nls_table *nls_codepage)
5215 {
5216         int rc = 0;
5217         struct smb_com_transaction_change_notify_req *pSMB = NULL;
5218         struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL;
5219         struct dir_notify_req *dnotify_req;
5220         int bytes_returned;
5221
5222         cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid));
5223         rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
5224                       (void **) &pSMBr);
5225         if (rc)
5226                 return rc;
5227
5228         pSMB->TotalParameterCount = 0 ;
5229         pSMB->TotalDataCount = 0;
5230         pSMB->MaxParameterCount = cpu_to_le32(2);
5231         /* BB find exact data count max from sess structure BB */
5232         pSMB->MaxDataCount = 0; /* same in little endian or be */
5233 /* BB VERIFY verify which is correct for above BB */
5234         pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
5235                                              MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
5236
5237         pSMB->MaxSetupCount = 4;
5238         pSMB->Reserved = 0;
5239         pSMB->ParameterOffset = 0;
5240         pSMB->DataCount = 0;
5241         pSMB->DataOffset = 0;
5242         pSMB->SetupCount = 4; /* single byte does not need le conversion */
5243         pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
5244         pSMB->ParameterCount = pSMB->TotalParameterCount;
5245         if (notify_subdirs)
5246                 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
5247         pSMB->Reserved2 = 0;
5248         pSMB->CompletionFilter = cpu_to_le32(filter);
5249         pSMB->Fid = netfid; /* file handle always le */
5250         pSMB->ByteCount = 0;
5251
5252         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5253                          (struct smb_hdr *)pSMBr, &bytes_returned,
5254                          CIFS_ASYNC_OP);
5255         if (rc) {
5256                 cFYI(1, ("Error in Notify = %d", rc));
5257         } else {
5258                 /* Add file to outstanding requests */
5259                 /* BB change to kmem cache alloc */
5260                 dnotify_req = kmalloc(
5261                                                 sizeof(struct dir_notify_req),
5262                                                  GFP_KERNEL);
5263                 if (dnotify_req) {
5264                         dnotify_req->Pid = pSMB->hdr.Pid;
5265                         dnotify_req->PidHigh = pSMB->hdr.PidHigh;
5266                         dnotify_req->Mid = pSMB->hdr.Mid;
5267                         dnotify_req->Tid = pSMB->hdr.Tid;
5268                         dnotify_req->Uid = pSMB->hdr.Uid;
5269                         dnotify_req->netfid = netfid;
5270                         dnotify_req->pfile = pfile;
5271                         dnotify_req->filter = filter;
5272                         dnotify_req->multishot = multishot;
5273                         spin_lock(&GlobalMid_Lock);
5274                         list_add_tail(&dnotify_req->lhead,
5275                                         &GlobalDnotifyReqList);
5276                         spin_unlock(&GlobalMid_Lock);
5277                 } else
5278                         rc = -ENOMEM;
5279         }
5280         cifs_buf_release(pSMB);
5281         return rc;
5282 }
5283 #ifdef CONFIG_CIFS_XATTR
5284 ssize_t
5285 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5286                  const unsigned char *searchName,
5287                  char *EAData, size_t buf_size,
5288                  const struct nls_table *nls_codepage, int remap)
5289 {
5290                 /* BB assumes one setup word */
5291         TRANSACTION2_QPI_REQ *pSMB = NULL;
5292         TRANSACTION2_QPI_RSP *pSMBr = NULL;
5293         int rc = 0;
5294         int bytes_returned;
5295         int name_len;
5296         struct fea *temp_fea;
5297         char *temp_ptr;
5298         __u16 params, byte_count;
5299
5300         cFYI(1, ("In Query All EAs path %s", searchName));
5301 QAllEAsRetry:
5302         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5303                       (void **) &pSMBr);
5304         if (rc)
5305                 return rc;
5306
5307         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5308                 name_len =
5309                     cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5310                                      PATH_MAX, nls_codepage, remap);
5311                 name_len++;     /* trailing null */
5312                 name_len *= 2;
5313         } else {        /* BB improve the check for buffer overruns BB */
5314                 name_len = strnlen(searchName, PATH_MAX);
5315                 name_len++;     /* trailing null */
5316                 strncpy(pSMB->FileName, searchName, name_len);
5317         }
5318
5319         params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5320         pSMB->TotalDataCount = 0;
5321         pSMB->MaxParameterCount = cpu_to_le16(2);
5322         /* BB find exact max SMB PDU from sess structure BB */
5323         pSMB->MaxDataCount = cpu_to_le16(4000);
5324         pSMB->MaxSetupCount = 0;
5325         pSMB->Reserved = 0;
5326         pSMB->Flags = 0;
5327         pSMB->Timeout = 0;
5328         pSMB->Reserved2 = 0;
5329         pSMB->ParameterOffset = cpu_to_le16(offsetof(
5330         struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5331         pSMB->DataCount = 0;
5332         pSMB->DataOffset = 0;
5333         pSMB->SetupCount = 1;
5334         pSMB->Reserved3 = 0;
5335         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5336         byte_count = params + 1 /* pad */ ;
5337         pSMB->TotalParameterCount = cpu_to_le16(params);
5338         pSMB->ParameterCount = pSMB->TotalParameterCount;
5339         pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5340         pSMB->Reserved4 = 0;
5341         pSMB->hdr.smb_buf_length += byte_count;
5342         pSMB->ByteCount = cpu_to_le16(byte_count);
5343
5344         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5345                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5346         if (rc) {
5347                 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
5348         } else {                /* decode response */
5349                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5350
5351                 /* BB also check enough total bytes returned */
5352                 /* BB we need to improve the validity checking
5353                 of these trans2 responses */
5354                 if (rc || (pSMBr->ByteCount < 4))
5355                         rc = -EIO;      /* bad smb */
5356            /* else if (pFindData){
5357                         memcpy((char *) pFindData,
5358                                (char *) &pSMBr->hdr.Protocol +
5359                                data_offset, kl);
5360                 }*/ else {
5361                         /* check that length of list is not more than bcc */
5362                         /* check that each entry does not go beyond length
5363                            of list */
5364                         /* check that each element of each entry does not
5365                            go beyond end of list */
5366                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5367                         struct fealist *ea_response_data;
5368                         rc = 0;
5369                         /* validate_trans2_offsets() */
5370                         /* BB check if start of smb + data_offset > &bcc+ bcc */
5371                         ea_response_data = (struct fealist *)
5372                                 (((char *) &pSMBr->hdr.Protocol) +
5373                                 data_offset);
5374                         name_len = le32_to_cpu(ea_response_data->list_len);
5375                         cFYI(1, ("ea length %d", name_len));
5376                         if (name_len <= 8) {
5377                         /* returned EA size zeroed at top of function */
5378                                 cFYI(1, ("empty EA list returned from server"));
5379                         } else {
5380                                 /* account for ea list len */
5381                                 name_len -= 4;
5382                                 temp_fea = ea_response_data->list;
5383                                 temp_ptr = (char *)temp_fea;
5384                                 while (name_len > 0) {
5385                                         __u16 value_len;
5386                                         name_len -= 4;
5387                                         temp_ptr += 4;
5388                                         rc += temp_fea->name_len;
5389                                 /* account for prefix user. and trailing null */
5390                                         rc = rc + 5 + 1;
5391                                         if (rc < (int)buf_size) {
5392                                                 memcpy(EAData, "user.", 5);
5393                                                 EAData += 5;
5394                                                 memcpy(EAData, temp_ptr,
5395                                                        temp_fea->name_len);
5396                                                 EAData += temp_fea->name_len;
5397                                                 /* null terminate name */
5398                                                 *EAData = 0;
5399                                                 EAData = EAData + 1;
5400                                         } else if (buf_size == 0) {
5401                                                 /* skip copy - calc size only */
5402                                         } else {
5403                                                 /* stop before overrun buffer */
5404                                                 rc = -ERANGE;
5405                                                 break;
5406                                         }
5407                                         name_len -= temp_fea->name_len;
5408                                         temp_ptr += temp_fea->name_len;
5409                                         /* account for trailing null */
5410                                         name_len--;
5411                                         temp_ptr++;
5412                                         value_len =
5413                                               le16_to_cpu(temp_fea->value_len);
5414                                         name_len -= value_len;
5415                                         temp_ptr += value_len;
5416                                         /* BB check that temp_ptr is still
5417                                               within the SMB BB*/
5418
5419                                         /* no trailing null to account for
5420                                            in value len */
5421                                         /* go on to next EA */
5422                                         temp_fea = (struct fea *)temp_ptr;
5423                                 }
5424                         }
5425                 }
5426         }
5427         cifs_buf_release(pSMB);
5428         if (rc == -EAGAIN)
5429                 goto QAllEAsRetry;
5430
5431         return (ssize_t)rc;
5432 }
5433
5434 ssize_t CIFSSMBQueryEA(const int xid, struct cifsTconInfo *tcon,
5435                 const unsigned char *searchName, const unsigned char *ea_name,
5436                 unsigned char *ea_value, size_t buf_size,
5437                 const struct nls_table *nls_codepage, int remap)
5438 {
5439         TRANSACTION2_QPI_REQ *pSMB = NULL;
5440         TRANSACTION2_QPI_RSP *pSMBr = NULL;
5441         int rc = 0;
5442         int bytes_returned;
5443         int name_len;
5444         struct fea *temp_fea;
5445         char *temp_ptr;
5446         __u16 params, byte_count;
5447
5448         cFYI(1, ("In Query EA path %s", searchName));
5449 QEARetry:
5450         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5451                       (void **) &pSMBr);
5452         if (rc)
5453                 return rc;
5454
5455         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5456                 name_len =
5457                     cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5458                                      PATH_MAX, nls_codepage, remap);
5459                 name_len++;     /* trailing null */
5460                 name_len *= 2;
5461         } else {        /* BB improve the check for buffer overruns BB */
5462                 name_len = strnlen(searchName, PATH_MAX);
5463                 name_len++;     /* trailing null */
5464                 strncpy(pSMB->FileName, searchName, name_len);
5465         }
5466
5467         params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
5468         pSMB->TotalDataCount = 0;
5469         pSMB->MaxParameterCount = cpu_to_le16(2);
5470         /* BB find exact max SMB PDU from sess structure BB */
5471         pSMB->MaxDataCount = cpu_to_le16(4000);
5472         pSMB->MaxSetupCount = 0;
5473         pSMB->Reserved = 0;
5474         pSMB->Flags = 0;
5475         pSMB->Timeout = 0;
5476         pSMB->Reserved2 = 0;
5477         pSMB->ParameterOffset = cpu_to_le16(offsetof(
5478                 struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
5479         pSMB->DataCount = 0;
5480         pSMB->DataOffset = 0;
5481         pSMB->SetupCount = 1;
5482         pSMB->Reserved3 = 0;
5483         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5484         byte_count = params + 1 /* pad */ ;
5485         pSMB->TotalParameterCount = cpu_to_le16(params);
5486         pSMB->ParameterCount = pSMB->TotalParameterCount;
5487         pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5488         pSMB->Reserved4 = 0;
5489         pSMB->hdr.smb_buf_length += byte_count;
5490         pSMB->ByteCount = cpu_to_le16(byte_count);
5491
5492         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5493                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5494         if (rc) {
5495                 cFYI(1, ("Send error in Query EA = %d", rc));
5496         } else {                /* decode response */
5497                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5498
5499                 /* BB also check enough total bytes returned */
5500                 /* BB we need to improve the validity checking
5501                 of these trans2 responses */
5502                 if (rc || (pSMBr->ByteCount < 4))
5503                         rc = -EIO;      /* bad smb */
5504            /* else if (pFindData){
5505                         memcpy((char *) pFindData,
5506                                (char *) &pSMBr->hdr.Protocol +
5507                                data_offset, kl);
5508                 }*/ else {
5509                         /* check that length of list is not more than bcc */
5510                         /* check that each entry does not go beyond length
5511                            of list */
5512                         /* check that each element of each entry does not
5513                            go beyond end of list */
5514                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5515                         struct fealist *ea_response_data;
5516                         rc = -ENODATA;
5517                         /* validate_trans2_offsets() */
5518                         /* BB check if start of smb + data_offset > &bcc+ bcc*/
5519                         ea_response_data = (struct fealist *)
5520                                 (((char *) &pSMBr->hdr.Protocol) +
5521                                 data_offset);
5522                         name_len = le32_to_cpu(ea_response_data->list_len);
5523                         cFYI(1, ("ea length %d", name_len));
5524                         if (name_len <= 8) {
5525                         /* returned EA size zeroed at top of function */
5526                                 cFYI(1, ("empty EA list returned from server"));
5527                         } else {
5528                                 /* account for ea list len */
5529                                 name_len -= 4;
5530                                 temp_fea = ea_response_data->list;
5531                                 temp_ptr = (char *)temp_fea;
5532                                 /* loop through checking if we have a matching
5533                                 name and then return the associated value */
5534                                 while (name_len > 0) {
5535                                         __u16 value_len;
5536                                         name_len -= 4;
5537                                         temp_ptr += 4;
5538                                         value_len =
5539                                               le16_to_cpu(temp_fea->value_len);
5540                                 /* BB validate that value_len falls within SMB,
5541                                 even though maximum for name_len is 255 */
5542                                         if (memcmp(temp_fea->name, ea_name,
5543                                                   temp_fea->name_len) == 0) {
5544                                                 /* found a match */
5545                                                 rc = value_len;
5546                                 /* account for prefix user. and trailing null */
5547                                                 if (rc <= (int)buf_size) {
5548                                                         memcpy(ea_value,
5549                                                                 temp_fea->name+temp_fea->name_len+1,
5550                                                                 rc);
5551                                                         /* ea values, unlike ea
5552                                                            names, are not null
5553                                                            terminated */
5554                                                 } else if (buf_size == 0) {
5555                                                 /* skip copy - calc size only */
5556                                                 } else {
5557                                                 /* stop before overrun buffer */
5558                                                         rc = -ERANGE;
5559                                                 }
5560                                                 break;
5561                                         }
5562                                         name_len -= temp_fea->name_len;
5563                                         temp_ptr += temp_fea->name_len;
5564                                         /* account for trailing null */
5565                                         name_len--;
5566                                         temp_ptr++;
5567                                         name_len -= value_len;
5568                                         temp_ptr += value_len;
5569                                         /* No trailing null to account for in
5570                                            value_len.  Go on to next EA */
5571                                         temp_fea = (struct fea *)temp_ptr;
5572                                 }
5573                         }
5574                 }
5575         }
5576         cifs_buf_release(pSMB);
5577         if (rc == -EAGAIN)
5578                 goto QEARetry;
5579
5580         return (ssize_t)rc;
5581 }
5582
5583 int
5584 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
5585              const char *ea_name, const void *ea_value,
5586              const __u16 ea_value_len, const struct nls_table *nls_codepage,
5587              int remap)
5588 {
5589         struct smb_com_transaction2_spi_req *pSMB = NULL;
5590         struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
5591         struct fealist *parm_data;
5592         int name_len;
5593         int rc = 0;
5594         int bytes_returned = 0;
5595         __u16 params, param_offset, byte_count, offset, count;
5596
5597         cFYI(1, ("In SetEA"));
5598 SetEARetry:
5599         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
5600                       (void **) &pSMBr);
5601         if (rc)
5602                 return rc;
5603
5604         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5605                 name_len =
5606                     cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
5607                                      PATH_MAX, nls_codepage, remap);
5608                 name_len++;     /* trailing null */
5609                 name_len *= 2;
5610         } else {        /* BB improve the check for buffer overruns BB */
5611                 name_len = strnlen(fileName, PATH_MAX);
5612                 name_len++;     /* trailing null */
5613                 strncpy(pSMB->FileName, fileName, name_len);
5614         }
5615
5616         params = 6 + name_len;
5617
5618         /* done calculating parms using name_len of file name,
5619         now use name_len to calculate length of ea name
5620         we are going to create in the inode xattrs */
5621         if (ea_name == NULL)
5622                 name_len = 0;
5623         else
5624                 name_len = strnlen(ea_name, 255);
5625
5626         count = sizeof(*parm_data) + ea_value_len + name_len;
5627         pSMB->MaxParameterCount = cpu_to_le16(2);
5628         /* BB find max SMB PDU from sess */
5629         pSMB->MaxDataCount = cpu_to_le16(1000);
5630         pSMB->MaxSetupCount = 0;
5631         pSMB->Reserved = 0;
5632         pSMB->Flags = 0;
5633         pSMB->Timeout = 0;
5634         pSMB->Reserved2 = 0;
5635         param_offset = offsetof(struct smb_com_transaction2_spi_req,
5636                                 InformationLevel) - 4;
5637         offset = param_offset + params;
5638         pSMB->InformationLevel =
5639                 cpu_to_le16(SMB_SET_FILE_EA);
5640
5641         parm_data =
5642                 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
5643                                        offset);
5644         pSMB->ParameterOffset = cpu_to_le16(param_offset);
5645         pSMB->DataOffset = cpu_to_le16(offset);
5646         pSMB->SetupCount = 1;
5647         pSMB->Reserved3 = 0;
5648         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
5649         byte_count = 3 /* pad */  + params + count;
5650         pSMB->DataCount = cpu_to_le16(count);
5651         parm_data->list_len = cpu_to_le32(count);
5652         parm_data->list[0].EA_flags = 0;
5653         /* we checked above that name len is less than 255 */
5654         parm_data->list[0].name_len = (__u8)name_len;
5655         /* EA names are always ASCII */
5656         if (ea_name)
5657                 strncpy(parm_data->list[0].name, ea_name, name_len);
5658         parm_data->list[0].name[name_len] = 0;
5659         parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
5660         /* caller ensures that ea_value_len is less than 64K but
5661         we need to ensure that it fits within the smb */
5662
5663         /*BB add length check to see if it would fit in
5664              negotiated SMB buffer size BB */
5665         /* if (ea_value_len > buffer_size - 512 (enough for header)) */
5666         if (ea_value_len)
5667                 memcpy(parm_data->list[0].name+name_len+1,
5668                        ea_value, ea_value_len);
5669
5670         pSMB->TotalDataCount = pSMB->DataCount;
5671         pSMB->ParameterCount = cpu_to_le16(params);
5672         pSMB->TotalParameterCount = pSMB->ParameterCount;
5673         pSMB->Reserved4 = 0;
5674         pSMB->hdr.smb_buf_length += byte_count;
5675         pSMB->ByteCount = cpu_to_le16(byte_count);
5676         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
5677                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5678         if (rc)
5679                 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
5680
5681         cifs_buf_release(pSMB);
5682
5683         if (rc == -EAGAIN)
5684                 goto SetEARetry;
5685
5686         return rc;
5687 }
5688
5689 #endif