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