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