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