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