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