cadacae46b82e715e7604c7beeb7110c41c782bb
[pandora-kernel.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_strlcpy_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((4 * plen) + 2, GFP_KERNEL);
99                 if (!*dst)
100                         goto cifs_strlcpy_to_host_ErrExit;
101                 cifs_strfromUCS_le(*dst, (__le16 *)src, plen, nls_codepage);
102                 (*dst)[plen] = 0;
103                 (*dst)[plen+1] = 0; /* needed for Unicode */
104         } else {
105                 plen = strnlen(src, maxlen);
106                 *dst = kmalloc(plen + 2, GFP_KERNEL);
107                 if (!*dst)
108                         goto cifs_strlcpy_to_host_ErrExit;
109                 strlcpy(*dst, src, plen);
110         }
111         return 0;
112
113 cifs_strlcpy_to_host_ErrExit:
114         cERROR(1, ("Failed to allocate buffer for string\n"));
115         return -ENOMEM;
116 }
117
118
119 /* Mark as invalid, all open files on tree connections since they
120    were closed when session to server was lost */
121 static void mark_open_files_invalid(struct cifsTconInfo *pTcon)
122 {
123         struct cifsFileInfo *open_file = NULL;
124         struct list_head *tmp;
125         struct list_head *tmp1;
126
127 /* list all files open on tree connection and mark them invalid */
128         write_lock(&GlobalSMBSeslock);
129         list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
130                 open_file = list_entry(tmp, struct cifsFileInfo, tlist);
131                 open_file->invalidHandle = true;
132         }
133         write_unlock(&GlobalSMBSeslock);
134         /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
135            to this tcon */
136 }
137
138 /* Allocate and return pointer to an SMB request buffer, and set basic
139    SMB information in the SMB header.  If the return code is zero, this
140    function must have filled in request_buf pointer */
141 static int
142 small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
143                 void **request_buf)
144 {
145         int rc = 0;
146
147         /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
148            check for tcp and smb session status done differently
149            for those three - in the calling routine */
150         if (tcon) {
151                 if (tcon->tidStatus == CifsExiting) {
152                         /* only tree disconnect, open, and write,
153                         (and ulogoff which does not have tcon)
154                         are allowed as we start force umount */
155                         if ((smb_command != SMB_COM_WRITE_ANDX) &&
156                            (smb_command != SMB_COM_OPEN_ANDX) &&
157                            (smb_command != SMB_COM_TREE_DISCONNECT)) {
158                                 cFYI(1, ("can not send cmd %d while umounting",
159                                         smb_command));
160                                 return -ENODEV;
161                         }
162                 }
163                 if ((tcon->ses) && (tcon->ses->status != CifsExiting) &&
164                                   (tcon->ses->server)) {
165                         struct nls_table *nls_codepage;
166                                 /* Give Demultiplex thread up to 10 seconds to
167                                    reconnect, should be greater than cifs socket
168                                    timeout which is 7 seconds */
169                         while (tcon->ses->server->tcpStatus ==
170                                                          CifsNeedReconnect) {
171                                 wait_event_interruptible_timeout(tcon->ses->server->response_q,
172                                         (tcon->ses->server->tcpStatus ==
173                                                         CifsGood), 10 * HZ);
174                                 if (tcon->ses->server->tcpStatus ==
175                                                         CifsNeedReconnect) {
176                                         /* on "soft" mounts we wait once */
177                                         if (!tcon->retry ||
178                                            (tcon->ses->status == CifsExiting)) {
179                                                 cFYI(1, ("gave up waiting on "
180                                                       "reconnect in smb_init"));
181                                                 return -EHOSTDOWN;
182                                         } /* else "hard" mount - keep retrying
183                                              until process is killed or server
184                                              comes back on-line */
185                                 } else /* TCP session is reestablished now */
186                                         break;
187                         }
188
189                         nls_codepage = load_nls_default();
190                 /* need to prevent multiple threads trying to
191                 simultaneously reconnect the same SMB session */
192                         down(&tcon->ses->sesSem);
193                         if (tcon->ses->need_reconnect)
194                                 rc = cifs_setup_session(0, tcon->ses,
195                                                         nls_codepage);
196                         if (!rc && (tcon->need_reconnect)) {
197                                 mark_open_files_invalid(tcon);
198                                 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
199                                               tcon, nls_codepage);
200                                 up(&tcon->ses->sesSem);
201                                 /* BB FIXME add code to check if wsize needs
202                                    update due to negotiated smb buffer size
203                                    shrinking */
204                                 if (rc == 0) {
205                                         atomic_inc(&tconInfoReconnectCount);
206                                         /* tell server Unix caps we support */
207                                         if (tcon->ses->capabilities & CAP_UNIX)
208                                                 reset_cifs_unix_caps(
209                                                 0 /* no xid */,
210                                                 tcon,
211                                                 NULL /* we do not know sb */,
212                                                 NULL /* no vol info */);
213                                 }
214
215                                 cFYI(1, ("reconnect tcon rc = %d", rc));
216                                 /* Removed call to reopen open files here.
217                                    It is safer (and faster) to reopen files
218                                    one at a time as needed in read and write */
219
220                                 /* Check if handle based operation so we
221                                    know whether we can continue or not without
222                                    returning to caller to reset file handle */
223                                 switch (smb_command) {
224                                         case SMB_COM_READ_ANDX:
225                                         case SMB_COM_WRITE_ANDX:
226                                         case SMB_COM_CLOSE:
227                                         case SMB_COM_FIND_CLOSE2:
228                                         case SMB_COM_LOCKING_ANDX: {
229                                                 unload_nls(nls_codepage);
230                                                 return -EAGAIN;
231                                         }
232                                 }
233                         } else {
234                                 up(&tcon->ses->sesSem);
235                         }
236                         unload_nls(nls_codepage);
237
238                 } else {
239                         return -EIO;
240                 }
241         }
242         if (rc)
243                 return rc;
244
245         *request_buf = cifs_small_buf_get();
246         if (*request_buf == NULL) {
247                 /* BB should we add a retry in here if not a writepage? */
248                 return -ENOMEM;
249         }
250
251         header_assemble((struct smb_hdr *) *request_buf, smb_command,
252                         tcon, wct);
253
254         if (tcon != NULL)
255                 cifs_stats_inc(&tcon->num_smbs_sent);
256
257         return rc;
258 }
259
260 int
261 small_smb_init_no_tc(const int smb_command, const int wct,
262                      struct cifsSesInfo *ses, void **request_buf)
263 {
264         int rc;
265         struct smb_hdr *buffer;
266
267         rc = small_smb_init(smb_command, wct, NULL, request_buf);
268         if (rc)
269                 return rc;
270
271         buffer = (struct smb_hdr *)*request_buf;
272         buffer->Mid = GetNextMid(ses->server);
273         if (ses->capabilities & CAP_UNICODE)
274                 buffer->Flags2 |= SMBFLG2_UNICODE;
275         if (ses->capabilities & CAP_STATUS32)
276                 buffer->Flags2 |= SMBFLG2_ERR_STATUS;
277
278         /* uid, tid can stay at zero as set in header assemble */
279
280         /* BB add support for turning on the signing when
281         this function is used after 1st of session setup requests */
282
283         return rc;
284 }
285
286 /* If the return code is zero, this function must fill in request_buf pointer */
287 static int
288 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
289          void **request_buf /* returned */ ,
290          void **response_buf /* returned */ )
291 {
292         int rc = 0;
293
294         /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
295            check for tcp and smb session status done differently
296            for those three - in the calling routine */
297         if (tcon) {
298                 if (tcon->tidStatus == CifsExiting) {
299                         /* only tree disconnect, open, and write,
300                           (and ulogoff which does not have tcon)
301                           are allowed as we start force umount */
302                         if ((smb_command != SMB_COM_WRITE_ANDX) &&
303                            (smb_command != SMB_COM_OPEN_ANDX) &&
304                            (smb_command != SMB_COM_TREE_DISCONNECT)) {
305                                 cFYI(1, ("can not send cmd %d while umounting",
306                                         smb_command));
307                                 return -ENODEV;
308                         }
309                 }
310
311                 if ((tcon->ses) && (tcon->ses->status != CifsExiting) &&
312                                   (tcon->ses->server)) {
313                         struct nls_table *nls_codepage;
314                                 /* Give Demultiplex thread up to 10 seconds to
315                                    reconnect, should be greater than cifs socket
316                                    timeout which is 7 seconds */
317                         while (tcon->ses->server->tcpStatus ==
318                                                         CifsNeedReconnect) {
319                                 wait_event_interruptible_timeout(tcon->ses->server->response_q,
320                                         (tcon->ses->server->tcpStatus ==
321                                                         CifsGood), 10 * HZ);
322                                 if (tcon->ses->server->tcpStatus ==
323                                                 CifsNeedReconnect) {
324                                         /* on "soft" mounts we wait once */
325                                         if (!tcon->retry ||
326                                            (tcon->ses->status == CifsExiting)) {
327                                                 cFYI(1, ("gave up waiting on "
328                                                       "reconnect in smb_init"));
329                                                 return -EHOSTDOWN;
330                                         } /* else "hard" mount - keep retrying
331                                              until process is killed or server
332                                              comes on-line */
333                                 } else /* TCP session is reestablished now */
334                                         break;
335                         }
336                         nls_codepage = load_nls_default();
337                 /* need to prevent multiple threads trying to
338                 simultaneously reconnect the same SMB session */
339                         down(&tcon->ses->sesSem);
340                         if (tcon->ses->need_reconnect)
341                                 rc = cifs_setup_session(0, tcon->ses,
342                                                         nls_codepage);
343                         if (!rc && (tcon->need_reconnect)) {
344                                 mark_open_files_invalid(tcon);
345                                 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
346                                               tcon, nls_codepage);
347                                 up(&tcon->ses->sesSem);
348                                 /* BB FIXME add code to check if wsize needs
349                                 update due to negotiated smb buffer size
350                                 shrinking */
351                                 if (rc == 0) {
352                                         atomic_inc(&tconInfoReconnectCount);
353                                         /* tell server Unix caps we support */
354                                         if (tcon->ses->capabilities & CAP_UNIX)
355                                                 reset_cifs_unix_caps(
356                                                 0 /* no xid */,
357                                                 tcon,
358                                                 NULL /* do not know sb */,
359                                                 NULL /* no vol info */);
360                                 }
361
362                                 cFYI(1, ("reconnect tcon rc = %d", rc));
363                                 /* Removed call to reopen open files here.
364                                    It is safer (and faster) to reopen files
365                                    one at a time as needed in read and write */
366
367                                 /* Check if handle based operation so we
368                                    know whether we can continue or not without
369                                    returning to caller to reset file handle */
370                                 switch (smb_command) {
371                                         case SMB_COM_READ_ANDX:
372                                         case SMB_COM_WRITE_ANDX:
373                                         case SMB_COM_CLOSE:
374                                         case SMB_COM_FIND_CLOSE2:
375                                         case SMB_COM_LOCKING_ANDX: {
376                                                 unload_nls(nls_codepage);
377                                                 return -EAGAIN;
378                                         }
379                                 }
380                         } else {
381                                 up(&tcon->ses->sesSem);
382                         }
383                         unload_nls(nls_codepage);
384
385                 } else {
386                         return -EIO;
387                 }
388         }
389         if (rc)
390                 return rc;
391
392         *request_buf = cifs_buf_get();
393         if (*request_buf == NULL) {
394                 /* BB should we add a retry in here if not a writepage? */
395                 return -ENOMEM;
396         }
397     /* Although the original thought was we needed the response buf for  */
398     /* potential retries of smb operations it turns out we can determine */
399     /* from the mid flags when the request buffer can be resent without  */
400     /* having to use a second distinct buffer for the response */
401         if (response_buf)
402                 *response_buf = *request_buf;
403
404         header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
405                         wct);
406
407         if (tcon != NULL)
408                 cifs_stats_inc(&tcon->num_smbs_sent);
409
410         return rc;
411 }
412
413 static int validate_t2(struct smb_t2_rsp *pSMB)
414 {
415         int rc = -EINVAL;
416         int total_size;
417         char *pBCC;
418
419         /* check for plausible wct, bcc and t2 data and parm sizes */
420         /* check for parm and data offset going beyond end of smb */
421         if (pSMB->hdr.WordCount >= 10) {
422                 if ((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
423                    (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
424                         /* check that bcc is at least as big as parms + data */
425                         /* check that bcc is less than negotiated smb buffer */
426                         total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
427                         if (total_size < 512) {
428                                 total_size +=
429                                         le16_to_cpu(pSMB->t2_rsp.DataCount);
430                                 /* BCC le converted in SendReceive */
431                                 pBCC = (pSMB->hdr.WordCount * 2) +
432                                         sizeof(struct smb_hdr) +
433                                         (char *)pSMB;
434                                 if ((total_size <= (*(u16 *)pBCC)) &&
435                                    (total_size <
436                                         CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
437                                         return 0;
438                                 }
439                         }
440                 }
441         }
442         cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
443                 sizeof(struct smb_t2_rsp) + 16);
444         return rc;
445 }
446 int
447 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
448 {
449         NEGOTIATE_REQ *pSMB;
450         NEGOTIATE_RSP *pSMBr;
451         int rc = 0;
452         int bytes_returned;
453         int i;
454         struct TCP_Server_Info *server;
455         u16 count;
456         unsigned int secFlags;
457         u16 dialect;
458
459         if (ses->server)
460                 server = ses->server;
461         else {
462                 rc = -EIO;
463                 return rc;
464         }
465         rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
466                       (void **) &pSMB, (void **) &pSMBr);
467         if (rc)
468                 return rc;
469
470         /* if any of auth flags (ie not sign or seal) are overriden use them */
471         if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
472                 secFlags = ses->overrideSecFlg;  /* BB FIXME fix sign flags? */
473         else /* if override flags set only sign/seal OR them with global auth */
474                 secFlags = extended_security | ses->overrideSecFlg;
475
476         cFYI(1, ("secFlags 0x%x", secFlags));
477
478         pSMB->hdr.Mid = GetNextMid(server);
479         pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
480
481         if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
482                 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
483         else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
484                 cFYI(1, ("Kerberos only mechanism, enable extended security"));
485                 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
486         }
487
488         count = 0;
489         for (i = 0; i < CIFS_NUM_PROT; i++) {
490                 strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
491                 count += strlen(protocols[i].name) + 1;
492                 /* null at end of source and target buffers anyway */
493         }
494         pSMB->hdr.smb_buf_length += count;
495         pSMB->ByteCount = cpu_to_le16(count);
496
497         rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
498                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
499         if (rc != 0)
500                 goto neg_err_exit;
501
502         dialect = le16_to_cpu(pSMBr->DialectIndex);
503         cFYI(1, ("Dialect: %d", dialect));
504         /* Check wct = 1 error case */
505         if ((pSMBr->hdr.WordCount < 13) || (dialect == BAD_PROT)) {
506                 /* core returns wct = 1, but we do not ask for core - otherwise
507                 small wct just comes when dialect index is -1 indicating we
508                 could not negotiate a common dialect */
509                 rc = -EOPNOTSUPP;
510                 goto neg_err_exit;
511 #ifdef CONFIG_CIFS_WEAK_PW_HASH
512         } else if ((pSMBr->hdr.WordCount == 13)
513                         && ((dialect == LANMAN_PROT)
514                                 || (dialect == LANMAN2_PROT))) {
515                 __s16 tmp;
516                 struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
517
518                 if ((secFlags & CIFSSEC_MAY_LANMAN) ||
519                         (secFlags & CIFSSEC_MAY_PLNTXT))
520                         server->secType = LANMAN;
521                 else {
522                         cERROR(1, ("mount failed weak security disabled"
523                                    " in /proc/fs/cifs/SecurityFlags"));
524                         rc = -EOPNOTSUPP;
525                         goto neg_err_exit;
526                 }
527                 server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
528                 server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
529                 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
530                                 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
531                 server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs);
532                 GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey);
533                 /* even though we do not use raw we might as well set this
534                 accurately, in case we ever find a need for it */
535                 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
536                         server->max_rw = 0xFF00;
537                         server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
538                 } else {
539                         server->max_rw = 0;/* do not need to use raw anyway */
540                         server->capabilities = CAP_MPX_MODE;
541                 }
542                 tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
543                 if (tmp == -1) {
544                         /* OS/2 often does not set timezone therefore
545                          * we must use server time to calc time zone.
546                          * Could deviate slightly from the right zone.
547                          * Smallest defined timezone difference is 15 minutes
548                          * (i.e. Nepal).  Rounding up/down is done to match
549                          * this requirement.
550                          */
551                         int val, seconds, remain, result;
552                         struct timespec ts, utc;
553                         utc = CURRENT_TIME;
554                         ts = cnvrtDosUnixTm(le16_to_cpu(rsp->SrvTime.Date),
555                                                 le16_to_cpu(rsp->SrvTime.Time));
556                         cFYI(1, ("SrvTime %d sec since 1970 (utc: %d) diff: %d",
557                                 (int)ts.tv_sec, (int)utc.tv_sec,
558                                 (int)(utc.tv_sec - ts.tv_sec)));
559                         val = (int)(utc.tv_sec - ts.tv_sec);
560                         seconds = abs(val);
561                         result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
562                         remain = seconds % MIN_TZ_ADJ;
563                         if (remain >= (MIN_TZ_ADJ / 2))
564                                 result += MIN_TZ_ADJ;
565                         if (val < 0)
566                                 result = -result;
567                         server->timeAdj = result;
568                 } else {
569                         server->timeAdj = (int)tmp;
570                         server->timeAdj *= 60; /* also in seconds */
571                 }
572                 cFYI(1, ("server->timeAdj: %d seconds", server->timeAdj));
573
574
575                 /* BB get server time for time conversions and add
576                 code to use it and timezone since this is not UTC */
577
578                 if (rsp->EncryptionKeyLength ==
579                                 cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
580                         memcpy(server->cryptKey, rsp->EncryptionKey,
581                                 CIFS_CRYPTO_KEY_SIZE);
582                 } else if (server->secMode & SECMODE_PW_ENCRYPT) {
583                         rc = -EIO; /* need cryptkey unless plain text */
584                         goto neg_err_exit;
585                 }
586
587                 cFYI(1, ("LANMAN negotiated"));
588                 /* we will not end up setting signing flags - as no signing
589                 was in LANMAN and server did not return the flags on */
590                 goto signing_check;
591 #else /* weak security disabled */
592         } else if (pSMBr->hdr.WordCount == 13) {
593                 cERROR(1, ("mount failed, cifs module not built "
594                           "with CIFS_WEAK_PW_HASH support"));
595                         rc = -EOPNOTSUPP;
596 #endif /* WEAK_PW_HASH */
597                 goto neg_err_exit;
598         } else if (pSMBr->hdr.WordCount != 17) {
599                 /* unknown wct */
600                 rc = -EOPNOTSUPP;
601                 goto neg_err_exit;
602         }
603         /* else wct == 17 NTLM */
604         server->secMode = pSMBr->SecurityMode;
605         if ((server->secMode & SECMODE_USER) == 0)
606                 cFYI(1, ("share mode security"));
607
608         if ((server->secMode & SECMODE_PW_ENCRYPT) == 0)
609 #ifdef CONFIG_CIFS_WEAK_PW_HASH
610                 if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
611 #endif /* CIFS_WEAK_PW_HASH */
612                         cERROR(1, ("Server requests plain text password"
613                                   " but client support disabled"));
614
615         if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
616                 server->secType = NTLMv2;
617         else if (secFlags & CIFSSEC_MAY_NTLM)
618                 server->secType = NTLM;
619         else if (secFlags & CIFSSEC_MAY_NTLMV2)
620                 server->secType = NTLMv2;
621         else if (secFlags & CIFSSEC_MAY_KRB5)
622                 server->secType = Kerberos;
623         else if (secFlags & CIFSSEC_MAY_LANMAN)
624                 server->secType = LANMAN;
625 /* #ifdef CONFIG_CIFS_EXPERIMENTAL
626         else if (secFlags & CIFSSEC_MAY_PLNTXT)
627                 server->secType = ??
628 #endif */
629         else {
630                 rc = -EOPNOTSUPP;
631                 cERROR(1, ("Invalid security type"));
632                 goto neg_err_exit;
633         }
634         /* else ... any others ...? */
635
636         /* one byte, so no need to convert this or EncryptionKeyLen from
637            little endian */
638         server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
639         /* probably no need to store and check maxvcs */
640         server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
641                         (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
642         server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
643         cFYI(DBG2, ("Max buf = %d", ses->server->maxBuf));
644         GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
645         server->capabilities = le32_to_cpu(pSMBr->Capabilities);
646         server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
647         server->timeAdj *= 60;
648         if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
649                 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
650                        CIFS_CRYPTO_KEY_SIZE);
651         } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
652                         && (pSMBr->EncryptionKeyLength == 0)) {
653                 /* decode security blob */
654         } else if (server->secMode & SECMODE_PW_ENCRYPT) {
655                 rc = -EIO; /* no crypt key only if plain text pwd */
656                 goto neg_err_exit;
657         }
658
659         /* BB might be helpful to save off the domain of server here */
660
661         if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
662                 (server->capabilities & CAP_EXTENDED_SECURITY)) {
663                 count = pSMBr->ByteCount;
664                 if (count < 16) {
665                         rc = -EIO;
666                         goto neg_err_exit;
667                 }
668                 read_lock(&cifs_tcp_ses_lock);
669                 if (server->srv_count > 1) {
670                         read_unlock(&cifs_tcp_ses_lock);
671                         if (memcmp(server->server_GUID,
672                                    pSMBr->u.extended_response.
673                                    GUID, 16) != 0) {
674                                 cFYI(1, ("server UID changed"));
675                                 memcpy(server->server_GUID,
676                                         pSMBr->u.extended_response.GUID,
677                                         16);
678                         }
679                 } else {
680                         read_unlock(&cifs_tcp_ses_lock);
681                         memcpy(server->server_GUID,
682                                pSMBr->u.extended_response.GUID, 16);
683                 }
684
685                 if (count == 16) {
686                         server->secType = RawNTLMSSP;
687                 } else {
688                         rc = decode_negTokenInit(pSMBr->u.extended_response.
689                                                  SecurityBlob,
690                                                  count - 16,
691                                                  &server->secType);
692                         if (rc == 1)
693                                 rc = 0;
694                         else
695                                 rc = -EINVAL;
696                 }
697         } else
698                 server->capabilities &= ~CAP_EXTENDED_SECURITY;
699
700 #ifdef CONFIG_CIFS_WEAK_PW_HASH
701 signing_check:
702 #endif
703         if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
704                 /* MUST_SIGN already includes the MAY_SIGN FLAG
705                    so if this is zero it means that signing is disabled */
706                 cFYI(1, ("Signing disabled"));
707                 if (server->secMode & SECMODE_SIGN_REQUIRED) {
708                         cERROR(1, ("Server requires "
709                                    "packet signing to be enabled in "
710                                    "/proc/fs/cifs/SecurityFlags."));
711                         rc = -EOPNOTSUPP;
712                 }
713                 server->secMode &=
714                         ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
715         } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
716                 /* signing required */
717                 cFYI(1, ("Must sign - secFlags 0x%x", secFlags));
718                 if ((server->secMode &
719                         (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
720                         cERROR(1,
721                                 ("signing required but server lacks support"));
722                         rc = -EOPNOTSUPP;
723                 } else
724                         server->secMode |= SECMODE_SIGN_REQUIRED;
725         } else {
726                 /* signing optional ie CIFSSEC_MAY_SIGN */
727                 if ((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
728                         server->secMode &=
729                                 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
730         }
731
732 neg_err_exit:
733         cifs_buf_release(pSMB);
734
735         cFYI(1, ("negprot rc %d", rc));
736         return rc;
737 }
738
739 int
740 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
741 {
742         struct smb_hdr *smb_buffer;
743         int rc = 0;
744
745         cFYI(1, ("In tree disconnect"));
746
747         /* BB: do we need to check this? These should never be NULL. */
748         if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
749                 return -EIO;
750
751         /*
752          * No need to return error on this operation if tid invalidated and
753          * closed on server already e.g. due to tcp session crashing. Also,
754          * the tcon is no longer on the list, so no need to take lock before
755          * checking this.
756          */
757         if (tcon->need_reconnect)
758                 return 0;
759
760         rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
761                             (void **)&smb_buffer);
762         if (rc)
763                 return rc;
764
765         rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0);
766         if (rc)
767                 cFYI(1, ("Tree disconnect failed %d", rc));
768
769         /* No need to return error on this operation if tid invalidated and
770            closed on server already e.g. due to tcp session crashing */
771         if (rc == -EAGAIN)
772                 rc = 0;
773
774         return rc;
775 }
776
777 int
778 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
779 {
780         LOGOFF_ANDX_REQ *pSMB;
781         int rc = 0;
782
783         cFYI(1, ("In SMBLogoff for session disconnect"));
784
785         /*
786          * BB: do we need to check validity of ses and server? They should
787          * always be valid since we have an active reference. If not, that
788          * should probably be a BUG()
789          */
790         if (!ses || !ses->server)
791                 return -EIO;
792
793         down(&ses->sesSem);
794         if (ses->need_reconnect)
795                 goto session_already_dead; /* no need to send SMBlogoff if uid
796                                               already closed due to reconnect */
797         rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
798         if (rc) {
799                 up(&ses->sesSem);
800                 return rc;
801         }
802
803         pSMB->hdr.Mid = GetNextMid(ses->server);
804
805         if (ses->server->secMode &
806                    (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
807                         pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
808
809         pSMB->hdr.Uid = ses->Suid;
810
811         pSMB->AndXCommand = 0xFF;
812         rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0);
813 session_already_dead:
814         up(&ses->sesSem);
815
816         /* if session dead then we do not need to do ulogoff,
817                 since server closed smb session, no sense reporting
818                 error */
819         if (rc == -EAGAIN)
820                 rc = 0;
821         return rc;
822 }
823
824 int
825 CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
826                  __u16 type, const struct nls_table *nls_codepage, int remap)
827 {
828         TRANSACTION2_SPI_REQ *pSMB = NULL;
829         TRANSACTION2_SPI_RSP *pSMBr = NULL;
830         struct unlink_psx_rq *pRqD;
831         int name_len;
832         int rc = 0;
833         int bytes_returned = 0;
834         __u16 params, param_offset, offset, byte_count;
835
836         cFYI(1, ("In POSIX delete"));
837 PsxDelete:
838         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
839                       (void **) &pSMBr);
840         if (rc)
841                 return rc;
842
843         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
844                 name_len =
845                     cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
846                                      PATH_MAX, nls_codepage, remap);
847                 name_len++;     /* trailing null */
848                 name_len *= 2;
849         } else { /* BB add path length overrun check */
850                 name_len = strnlen(fileName, PATH_MAX);
851                 name_len++;     /* trailing null */
852                 strncpy(pSMB->FileName, fileName, name_len);
853         }
854
855         params = 6 + name_len;
856         pSMB->MaxParameterCount = cpu_to_le16(2);
857         pSMB->MaxDataCount = 0; /* BB double check this with jra */
858         pSMB->MaxSetupCount = 0;
859         pSMB->Reserved = 0;
860         pSMB->Flags = 0;
861         pSMB->Timeout = 0;
862         pSMB->Reserved2 = 0;
863         param_offset = offsetof(struct smb_com_transaction2_spi_req,
864                                 InformationLevel) - 4;
865         offset = param_offset + params;
866
867         /* Setup pointer to Request Data (inode type) */
868         pRqD = (struct unlink_psx_rq *)(((char *)&pSMB->hdr.Protocol) + offset);
869         pRqD->type = cpu_to_le16(type);
870         pSMB->ParameterOffset = cpu_to_le16(param_offset);
871         pSMB->DataOffset = cpu_to_le16(offset);
872         pSMB->SetupCount = 1;
873         pSMB->Reserved3 = 0;
874         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
875         byte_count = 3 /* pad */  + params + sizeof(struct unlink_psx_rq);
876
877         pSMB->DataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
878         pSMB->TotalDataCount = cpu_to_le16(sizeof(struct unlink_psx_rq));
879         pSMB->ParameterCount = cpu_to_le16(params);
880         pSMB->TotalParameterCount = pSMB->ParameterCount;
881         pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK);
882         pSMB->Reserved4 = 0;
883         pSMB->hdr.smb_buf_length += byte_count;
884         pSMB->ByteCount = cpu_to_le16(byte_count);
885         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
886                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
887         if (rc)
888                 cFYI(1, ("Posix delete returned %d", rc));
889         cifs_buf_release(pSMB);
890
891         cifs_stats_inc(&tcon->num_deletes);
892
893         if (rc == -EAGAIN)
894                 goto PsxDelete;
895
896         return rc;
897 }
898
899 int
900 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
901                const struct nls_table *nls_codepage, int remap)
902 {
903         DELETE_FILE_REQ *pSMB = NULL;
904         DELETE_FILE_RSP *pSMBr = NULL;
905         int rc = 0;
906         int bytes_returned;
907         int name_len;
908
909 DelFileRetry:
910         rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
911                       (void **) &pSMBr);
912         if (rc)
913                 return rc;
914
915         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
916                 name_len =
917                     cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
918                                      PATH_MAX, nls_codepage, remap);
919                 name_len++;     /* trailing null */
920                 name_len *= 2;
921         } else {                /* BB improve check for buffer overruns BB */
922                 name_len = strnlen(fileName, PATH_MAX);
923                 name_len++;     /* trailing null */
924                 strncpy(pSMB->fileName, fileName, name_len);
925         }
926         pSMB->SearchAttributes =
927             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
928         pSMB->BufferFormat = 0x04;
929         pSMB->hdr.smb_buf_length += name_len + 1;
930         pSMB->ByteCount = cpu_to_le16(name_len + 1);
931         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
932                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
933         cifs_stats_inc(&tcon->num_deletes);
934         if (rc)
935                 cFYI(1, ("Error in RMFile = %d", rc));
936
937         cifs_buf_release(pSMB);
938         if (rc == -EAGAIN)
939                 goto DelFileRetry;
940
941         return rc;
942 }
943
944 int
945 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
946              const struct nls_table *nls_codepage, int remap)
947 {
948         DELETE_DIRECTORY_REQ *pSMB = NULL;
949         DELETE_DIRECTORY_RSP *pSMBr = NULL;
950         int rc = 0;
951         int bytes_returned;
952         int name_len;
953
954         cFYI(1, ("In CIFSSMBRmDir"));
955 RmDirRetry:
956         rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
957                       (void **) &pSMBr);
958         if (rc)
959                 return rc;
960
961         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
962                 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
963                                          PATH_MAX, nls_codepage, remap);
964                 name_len++;     /* trailing null */
965                 name_len *= 2;
966         } else {                /* BB improve check for buffer overruns BB */
967                 name_len = strnlen(dirName, PATH_MAX);
968                 name_len++;     /* trailing null */
969                 strncpy(pSMB->DirName, dirName, name_len);
970         }
971
972         pSMB->BufferFormat = 0x04;
973         pSMB->hdr.smb_buf_length += name_len + 1;
974         pSMB->ByteCount = cpu_to_le16(name_len + 1);
975         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
976                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
977         cifs_stats_inc(&tcon->num_rmdirs);
978         if (rc)
979                 cFYI(1, ("Error in RMDir = %d", rc));
980
981         cifs_buf_release(pSMB);
982         if (rc == -EAGAIN)
983                 goto RmDirRetry;
984         return rc;
985 }
986
987 int
988 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
989              const char *name, const struct nls_table *nls_codepage, int remap)
990 {
991         int rc = 0;
992         CREATE_DIRECTORY_REQ *pSMB = NULL;
993         CREATE_DIRECTORY_RSP *pSMBr = NULL;
994         int bytes_returned;
995         int name_len;
996
997         cFYI(1, ("In CIFSSMBMkDir"));
998 MkDirRetry:
999         rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
1000                       (void **) &pSMBr);
1001         if (rc)
1002                 return rc;
1003
1004         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1005                 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
1006                                             PATH_MAX, nls_codepage, remap);
1007                 name_len++;     /* trailing null */
1008                 name_len *= 2;
1009         } else {                /* BB improve check for buffer overruns BB */
1010                 name_len = strnlen(name, PATH_MAX);
1011                 name_len++;     /* trailing null */
1012                 strncpy(pSMB->DirName, name, name_len);
1013         }
1014
1015         pSMB->BufferFormat = 0x04;
1016         pSMB->hdr.smb_buf_length += name_len + 1;
1017         pSMB->ByteCount = cpu_to_le16(name_len + 1);
1018         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1019                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1020         cifs_stats_inc(&tcon->num_mkdirs);
1021         if (rc)
1022                 cFYI(1, ("Error in Mkdir = %d", rc));
1023
1024         cifs_buf_release(pSMB);
1025         if (rc == -EAGAIN)
1026                 goto MkDirRetry;
1027         return rc;
1028 }
1029
1030 int
1031 CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags,
1032                 __u64 mode, __u16 *netfid, FILE_UNIX_BASIC_INFO *pRetData,
1033                 __u32 *pOplock, const char *name,
1034                 const struct nls_table *nls_codepage, int remap)
1035 {
1036         TRANSACTION2_SPI_REQ *pSMB = NULL;
1037         TRANSACTION2_SPI_RSP *pSMBr = NULL;
1038         int name_len;
1039         int rc = 0;
1040         int bytes_returned = 0;
1041         __u16 params, param_offset, offset, byte_count, count;
1042         OPEN_PSX_REQ *pdata;
1043         OPEN_PSX_RSP *psx_rsp;
1044
1045         cFYI(1, ("In POSIX Create"));
1046 PsxCreat:
1047         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1048                       (void **) &pSMBr);
1049         if (rc)
1050                 return rc;
1051
1052         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1053                 name_len =
1054                     cifsConvertToUCS((__le16 *) pSMB->FileName, name,
1055                                      PATH_MAX, nls_codepage, remap);
1056                 name_len++;     /* trailing null */
1057                 name_len *= 2;
1058         } else {        /* BB improve the check for buffer overruns BB */
1059                 name_len = strnlen(name, PATH_MAX);
1060                 name_len++;     /* trailing null */
1061                 strncpy(pSMB->FileName, name, name_len);
1062         }
1063
1064         params = 6 + name_len;
1065         count = sizeof(OPEN_PSX_REQ);
1066         pSMB->MaxParameterCount = cpu_to_le16(2);
1067         pSMB->MaxDataCount = cpu_to_le16(1000); /* large enough */
1068         pSMB->MaxSetupCount = 0;
1069         pSMB->Reserved = 0;
1070         pSMB->Flags = 0;
1071         pSMB->Timeout = 0;
1072         pSMB->Reserved2 = 0;
1073         param_offset = offsetof(struct smb_com_transaction2_spi_req,
1074                                 InformationLevel) - 4;
1075         offset = param_offset + params;
1076         pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1077         pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1078         pdata->Permissions = cpu_to_le64(mode);
1079         pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1080         pdata->OpenFlags =  cpu_to_le32(*pOplock);
1081         pSMB->ParameterOffset = cpu_to_le16(param_offset);
1082         pSMB->DataOffset = cpu_to_le16(offset);
1083         pSMB->SetupCount = 1;
1084         pSMB->Reserved3 = 0;
1085         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1086         byte_count = 3 /* pad */  + params + count;
1087
1088         pSMB->DataCount = cpu_to_le16(count);
1089         pSMB->ParameterCount = cpu_to_le16(params);
1090         pSMB->TotalDataCount = pSMB->DataCount;
1091         pSMB->TotalParameterCount = pSMB->ParameterCount;
1092         pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN);
1093         pSMB->Reserved4 = 0;
1094         pSMB->hdr.smb_buf_length += byte_count;
1095         pSMB->ByteCount = cpu_to_le16(byte_count);
1096         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1097                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1098         if (rc) {
1099                 cFYI(1, ("Posix create returned %d", rc));
1100                 goto psx_create_err;
1101         }
1102
1103         cFYI(1, ("copying inode info"));
1104         rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1105
1106         if (rc || (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP))) {
1107                 rc = -EIO;      /* bad smb */
1108                 goto psx_create_err;
1109         }
1110
1111         /* copy return information to pRetData */
1112         psx_rsp = (OPEN_PSX_RSP *)((char *) &pSMBr->hdr.Protocol
1113                         + le16_to_cpu(pSMBr->t2.DataOffset));
1114
1115         *pOplock = le16_to_cpu(psx_rsp->OplockFlags);
1116         if (netfid)
1117                 *netfid = psx_rsp->Fid;   /* cifs fid stays in le */
1118         /* Let caller know file was created so we can set the mode. */
1119         /* Do we care about the CreateAction in any other cases? */
1120         if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1121                 *pOplock |= CIFS_CREATE_ACTION;
1122         /* check to make sure response data is there */
1123         if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1124                 pRetData->Type = cpu_to_le32(-1); /* unknown */
1125                 cFYI(DBG2, ("unknown type"));
1126         } else {
1127                 if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP)
1128                                         + sizeof(FILE_UNIX_BASIC_INFO)) {
1129                         cERROR(1, ("Open response data too small"));
1130                         pRetData->Type = cpu_to_le32(-1);
1131                         goto psx_create_err;
1132                 }
1133                 memcpy((char *) pRetData,
1134                         (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1135                         sizeof(FILE_UNIX_BASIC_INFO));
1136         }
1137
1138 psx_create_err:
1139         cifs_buf_release(pSMB);
1140
1141         cifs_stats_inc(&tcon->num_mkdirs);
1142
1143         if (rc == -EAGAIN)
1144                 goto PsxCreat;
1145
1146         return rc;
1147 }
1148
1149 static __u16 convert_disposition(int disposition)
1150 {
1151         __u16 ofun = 0;
1152
1153         switch (disposition) {
1154                 case FILE_SUPERSEDE:
1155                         ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1156                         break;
1157                 case FILE_OPEN:
1158                         ofun = SMBOPEN_OAPPEND;
1159                         break;
1160                 case FILE_CREATE:
1161                         ofun = SMBOPEN_OCREATE;
1162                         break;
1163                 case FILE_OPEN_IF:
1164                         ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
1165                         break;
1166                 case FILE_OVERWRITE:
1167                         ofun = SMBOPEN_OTRUNC;
1168                         break;
1169                 case FILE_OVERWRITE_IF:
1170                         ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
1171                         break;
1172                 default:
1173                         cFYI(1, ("unknown disposition %d", disposition));
1174                         ofun =  SMBOPEN_OAPPEND; /* regular open */
1175         }
1176         return ofun;
1177 }
1178
1179 static int
1180 access_flags_to_smbopen_mode(const int access_flags)
1181 {
1182         int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
1183
1184         if (masked_flags == GENERIC_READ)
1185                 return SMBOPEN_READ;
1186         else if (masked_flags == GENERIC_WRITE)
1187                 return SMBOPEN_WRITE;
1188
1189         /* just go for read/write */
1190         return SMBOPEN_READWRITE;
1191 }
1192
1193 int
1194 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
1195             const char *fileName, const int openDisposition,
1196             const int access_flags, const int create_options, __u16 *netfid,
1197             int *pOplock, FILE_ALL_INFO *pfile_info,
1198             const struct nls_table *nls_codepage, int remap)
1199 {
1200         int rc = -EACCES;
1201         OPENX_REQ *pSMB = NULL;
1202         OPENX_RSP *pSMBr = NULL;
1203         int bytes_returned;
1204         int name_len;
1205         __u16 count;
1206
1207 OldOpenRetry:
1208         rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
1209                       (void **) &pSMBr);
1210         if (rc)
1211                 return rc;
1212
1213         pSMB->AndXCommand = 0xFF;       /* none */
1214
1215         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1216                 count = 1;      /* account for one byte pad to word boundary */
1217                 name_len =
1218                    cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1219                                     fileName, PATH_MAX, nls_codepage, remap);
1220                 name_len++;     /* trailing null */
1221                 name_len *= 2;
1222         } else {                /* BB improve check for buffer overruns BB */
1223                 count = 0;      /* no pad */
1224                 name_len = strnlen(fileName, PATH_MAX);
1225                 name_len++;     /* trailing null */
1226                 strncpy(pSMB->fileName, fileName, name_len);
1227         }
1228         if (*pOplock & REQ_OPLOCK)
1229                 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1230         else if (*pOplock & REQ_BATCHOPLOCK)
1231                 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1232
1233         pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1234         pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
1235         pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
1236         /* set file as system file if special file such
1237            as fifo and server expecting SFU style and
1238            no Unix extensions */
1239
1240         if (create_options & CREATE_OPTION_SPECIAL)
1241                 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
1242         else /* BB FIXME BB */
1243                 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/);
1244
1245         if (create_options & CREATE_OPTION_READONLY)
1246                 pSMB->FileAttributes |= cpu_to_le16(ATTR_READONLY);
1247
1248         /* BB FIXME BB */
1249 /*      pSMB->CreateOptions = cpu_to_le32(create_options &
1250                                                  CREATE_OPTIONS_MASK); */
1251         /* BB FIXME END BB */
1252
1253         pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
1254         pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition));
1255         count += name_len;
1256         pSMB->hdr.smb_buf_length += count;
1257
1258         pSMB->ByteCount = cpu_to_le16(count);
1259         /* long_op set to 1 to allow for oplock break timeouts */
1260         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1261                         (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1262         cifs_stats_inc(&tcon->num_opens);
1263         if (rc) {
1264                 cFYI(1, ("Error in Open = %d", rc));
1265         } else {
1266         /* BB verify if wct == 15 */
1267
1268 /*              *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
1269
1270                 *netfid = pSMBr->Fid;   /* cifs fid stays in le */
1271                 /* Let caller know file was created so we can set the mode. */
1272                 /* Do we care about the CreateAction in any other cases? */
1273         /* BB FIXME BB */
1274 /*              if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1275                         *pOplock |= CIFS_CREATE_ACTION; */
1276         /* BB FIXME END */
1277
1278                 if (pfile_info) {
1279                         pfile_info->CreationTime = 0; /* BB convert CreateTime*/
1280                         pfile_info->LastAccessTime = 0; /* BB fixme */
1281                         pfile_info->LastWriteTime = 0; /* BB fixme */
1282                         pfile_info->ChangeTime = 0;  /* BB fixme */
1283                         pfile_info->Attributes =
1284                                 cpu_to_le32(le16_to_cpu(pSMBr->FileAttributes));
1285                         /* the file_info buf is endian converted by caller */
1286                         pfile_info->AllocationSize =
1287                                 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1288                         pfile_info->EndOfFile = pfile_info->AllocationSize;
1289                         pfile_info->NumberOfLinks = cpu_to_le32(1);
1290                         pfile_info->DeletePending = 0;
1291                 }
1292         }
1293
1294         cifs_buf_release(pSMB);
1295         if (rc == -EAGAIN)
1296                 goto OldOpenRetry;
1297         return rc;
1298 }
1299
1300 int
1301 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
1302             const char *fileName, const int openDisposition,
1303             const int access_flags, const int create_options, __u16 *netfid,
1304             int *pOplock, FILE_ALL_INFO *pfile_info,
1305             const struct nls_table *nls_codepage, int remap)
1306 {
1307         int rc = -EACCES;
1308         OPEN_REQ *pSMB = NULL;
1309         OPEN_RSP *pSMBr = NULL;
1310         int bytes_returned;
1311         int name_len;
1312         __u16 count;
1313
1314 openRetry:
1315         rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
1316                       (void **) &pSMBr);
1317         if (rc)
1318                 return rc;
1319
1320         pSMB->AndXCommand = 0xFF;       /* none */
1321
1322         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1323                 count = 1;      /* account for one byte pad to word boundary */
1324                 name_len =
1325                     cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
1326                                      fileName, PATH_MAX, nls_codepage, remap);
1327                 name_len++;     /* trailing null */
1328                 name_len *= 2;
1329                 pSMB->NameLength = cpu_to_le16(name_len);
1330         } else {                /* BB improve check for buffer overruns BB */
1331                 count = 0;      /* no pad */
1332                 name_len = strnlen(fileName, PATH_MAX);
1333                 name_len++;     /* trailing null */
1334                 pSMB->NameLength = cpu_to_le16(name_len);
1335                 strncpy(pSMB->fileName, fileName, name_len);
1336         }
1337         if (*pOplock & REQ_OPLOCK)
1338                 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1339         else if (*pOplock & REQ_BATCHOPLOCK)
1340                 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1341         pSMB->DesiredAccess = cpu_to_le32(access_flags);
1342         pSMB->AllocationSize = 0;
1343         /* set file as system file if special file such
1344            as fifo and server expecting SFU style and
1345            no Unix extensions */
1346         if (create_options & CREATE_OPTION_SPECIAL)
1347                 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1348         else
1349                 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1350
1351         /* XP does not handle ATTR_POSIX_SEMANTICS */
1352         /* but it helps speed up case sensitive checks for other
1353         servers such as Samba */
1354         if (tcon->ses->capabilities & CAP_UNIX)
1355                 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1356
1357         if (create_options & CREATE_OPTION_READONLY)
1358                 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1359
1360         pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1361         pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1362         pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1363         /* BB Expirement with various impersonation levels and verify */
1364         pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1365         pSMB->SecurityFlags =
1366             SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1367
1368         count += name_len;
1369         pSMB->hdr.smb_buf_length += count;
1370
1371         pSMB->ByteCount = cpu_to_le16(count);
1372         /* long_op set to 1 to allow for oplock break timeouts */
1373         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1374                         (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
1375         cifs_stats_inc(&tcon->num_opens);
1376         if (rc) {
1377                 cFYI(1, ("Error in Open = %d", rc));
1378         } else {
1379                 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
1380                 *netfid = pSMBr->Fid;   /* cifs fid stays in le */
1381                 /* Let caller know file was created so we can set the mode. */
1382                 /* Do we care about the CreateAction in any other cases? */
1383                 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1384                         *pOplock |= CIFS_CREATE_ACTION;
1385                 if (pfile_info) {
1386                         memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1387                                 36 /* CreationTime to Attributes */);
1388                         /* the file_info buf is endian converted by caller */
1389                         pfile_info->AllocationSize = pSMBr->AllocationSize;
1390                         pfile_info->EndOfFile = pSMBr->EndOfFile;
1391                         pfile_info->NumberOfLinks = cpu_to_le32(1);
1392                         pfile_info->DeletePending = 0;
1393                 }
1394         }
1395
1396         cifs_buf_release(pSMB);
1397         if (rc == -EAGAIN)
1398                 goto openRetry;
1399         return rc;
1400 }
1401
1402 int
1403 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1404             const unsigned int count, const __u64 lseek, unsigned int *nbytes,
1405             char **buf, int *pbuf_type)
1406 {
1407         int rc = -EACCES;
1408         READ_REQ *pSMB = NULL;
1409         READ_RSP *pSMBr = NULL;
1410         char *pReadData = NULL;
1411         int wct;
1412         int resp_buf_type = 0;
1413         struct kvec iov[1];
1414
1415         cFYI(1, ("Reading %d bytes on fid %d", count, netfid));
1416         if (tcon->ses->capabilities & CAP_LARGE_FILES)
1417                 wct = 12;
1418         else {
1419                 wct = 10; /* old style read */
1420                 if ((lseek >> 32) > 0)  {
1421                         /* can not handle this big offset for old */
1422                         return -EIO;
1423                 }
1424         }
1425
1426         *nbytes = 0;
1427         rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
1428         if (rc)
1429                 return rc;
1430
1431         /* tcon and ses pointer are checked in smb_init */
1432         if (tcon->ses->server == NULL)
1433                 return -ECONNABORTED;
1434
1435         pSMB->AndXCommand = 0xFF;       /* none */
1436         pSMB->Fid = netfid;
1437         pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
1438         if (wct == 12)
1439                 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
1440
1441         pSMB->Remaining = 0;
1442         pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
1443         pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
1444         if (wct == 12)
1445                 pSMB->ByteCount = 0;  /* no need to do le conversion since 0 */
1446         else {
1447                 /* old style read */
1448                 struct smb_com_readx_req *pSMBW =
1449                         (struct smb_com_readx_req *)pSMB;
1450                 pSMBW->ByteCount = 0;
1451         }
1452
1453         iov[0].iov_base = (char *)pSMB;
1454         iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1455         rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1456                          &resp_buf_type, CIFS_STD_OP | CIFS_LOG_ERROR);
1457         cifs_stats_inc(&tcon->num_reads);
1458         pSMBr = (READ_RSP *)iov[0].iov_base;
1459         if (rc) {
1460                 cERROR(1, ("Send error in read = %d", rc));
1461         } else {
1462                 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
1463                 data_length = data_length << 16;
1464                 data_length += le16_to_cpu(pSMBr->DataLength);
1465                 *nbytes = data_length;
1466
1467                 /*check that DataLength would not go beyond end of SMB */
1468                 if ((data_length > CIFSMaxBufSize)
1469                                 || (data_length > count)) {
1470                         cFYI(1, ("bad length %d for count %d",
1471                                  data_length, count));
1472                         rc = -EIO;
1473                         *nbytes = 0;
1474                 } else {
1475                         pReadData = (char *) (&pSMBr->hdr.Protocol) +
1476                                         le16_to_cpu(pSMBr->DataOffset);
1477 /*                      if (rc = copy_to_user(buf, pReadData, data_length)) {
1478                                 cERROR(1,("Faulting on read rc = %d",rc));
1479                                 rc = -EFAULT;
1480                         }*/ /* can not use copy_to_user when using page cache*/
1481                         if (*buf)
1482                                 memcpy(*buf, pReadData, data_length);
1483                 }
1484         }
1485
1486 /*      cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1487         if (*buf) {
1488                 if (resp_buf_type == CIFS_SMALL_BUFFER)
1489                         cifs_small_buf_release(iov[0].iov_base);
1490                 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1491                         cifs_buf_release(iov[0].iov_base);
1492         } else if (resp_buf_type != CIFS_NO_BUFFER) {
1493                 /* return buffer to caller to free */
1494                 *buf = iov[0].iov_base;
1495                 if (resp_buf_type == CIFS_SMALL_BUFFER)
1496                         *pbuf_type = CIFS_SMALL_BUFFER;
1497                 else if (resp_buf_type == CIFS_LARGE_BUFFER)
1498                         *pbuf_type = CIFS_LARGE_BUFFER;
1499         } /* else no valid buffer on return - leave as null */
1500
1501         /* Note: On -EAGAIN error only caller can retry on handle based calls
1502                 since file handle passed in no longer valid */
1503         return rc;
1504 }
1505
1506
1507 int
1508 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1509              const int netfid, const unsigned int count,
1510              const __u64 offset, unsigned int *nbytes, const char *buf,
1511              const char __user *ubuf, const int long_op)
1512 {
1513         int rc = -EACCES;
1514         WRITE_REQ *pSMB = NULL;
1515         WRITE_RSP *pSMBr = NULL;
1516         int bytes_returned, wct;
1517         __u32 bytes_sent;
1518         __u16 byte_count;
1519
1520         /* cFYI(1, ("write at %lld %d bytes", offset, count));*/
1521         if (tcon->ses == NULL)
1522                 return -ECONNABORTED;
1523
1524         if (tcon->ses->capabilities & CAP_LARGE_FILES)
1525                 wct = 14;
1526         else {
1527                 wct = 12;
1528                 if ((offset >> 32) > 0) {
1529                         /* can not handle big offset for old srv */
1530                         return -EIO;
1531                 }
1532         }
1533
1534         rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1535                       (void **) &pSMBr);
1536         if (rc)
1537                 return rc;
1538         /* tcon and ses pointer are checked in smb_init */
1539         if (tcon->ses->server == NULL)
1540                 return -ECONNABORTED;
1541
1542         pSMB->AndXCommand = 0xFF;       /* none */
1543         pSMB->Fid = netfid;
1544         pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1545         if (wct == 14)
1546                 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1547
1548         pSMB->Reserved = 0xFFFFFFFF;
1549         pSMB->WriteMode = 0;
1550         pSMB->Remaining = 0;
1551
1552         /* Can increase buffer size if buffer is big enough in some cases ie we
1553         can send more if LARGE_WRITE_X capability returned by the server and if
1554         our buffer is big enough or if we convert to iovecs on socket writes
1555         and eliminate the copy to the CIFS buffer */
1556         if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1557                 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1558         } else {
1559                 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1560                          & ~0xFF;
1561         }
1562
1563         if (bytes_sent > count)
1564                 bytes_sent = count;
1565         pSMB->DataOffset =
1566                 cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1567         if (buf)
1568                 memcpy(pSMB->Data, buf, bytes_sent);
1569         else if (ubuf) {
1570                 if (copy_from_user(pSMB->Data, ubuf, bytes_sent)) {
1571                         cifs_buf_release(pSMB);
1572                         return -EFAULT;
1573                 }
1574         } else if (count != 0) {
1575                 /* No buffer */
1576                 cifs_buf_release(pSMB);
1577                 return -EINVAL;
1578         } /* else setting file size with write of zero bytes */
1579         if (wct == 14)
1580                 byte_count = bytes_sent + 1; /* pad */
1581         else /* wct == 12 */
1582                 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1583
1584         pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1585         pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1586         pSMB->hdr.smb_buf_length += byte_count;
1587
1588         if (wct == 14)
1589                 pSMB->ByteCount = cpu_to_le16(byte_count);
1590         else { /* old style write has byte count 4 bytes earlier
1591                   so 4 bytes pad  */
1592                 struct smb_com_writex_req *pSMBW =
1593                         (struct smb_com_writex_req *)pSMB;
1594                 pSMBW->ByteCount = cpu_to_le16(byte_count);
1595         }
1596
1597         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1598                          (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1599         cifs_stats_inc(&tcon->num_writes);
1600         if (rc) {
1601                 cFYI(1, ("Send error in write = %d", rc));
1602                 *nbytes = 0;
1603         } else {
1604                 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1605                 *nbytes = (*nbytes) << 16;
1606                 *nbytes += le16_to_cpu(pSMBr->Count);
1607         }
1608
1609         cifs_buf_release(pSMB);
1610
1611         /* Note: On -EAGAIN error only caller can retry on handle based calls
1612                 since file handle passed in no longer valid */
1613
1614         return rc;
1615 }
1616
1617 int
1618 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1619              const int netfid, const unsigned int count,
1620              const __u64 offset, unsigned int *nbytes, struct kvec *iov,
1621              int n_vec, const int long_op)
1622 {
1623         int rc = -EACCES;
1624         WRITE_REQ *pSMB = NULL;
1625         int wct;
1626         int smb_hdr_len;
1627         int resp_buf_type = 0;
1628
1629         *nbytes = 0;
1630
1631         cFYI(1, ("write2 at %lld %d bytes", (long long)offset, count));
1632
1633         if (tcon->ses->capabilities & CAP_LARGE_FILES) {
1634                 wct = 14;
1635         } else {
1636                 wct = 12;
1637                 if ((offset >> 32) > 0) {
1638                         /* can not handle big offset for old srv */
1639                         return -EIO;
1640                 }
1641         }
1642         rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1643         if (rc)
1644                 return rc;
1645         /* tcon and ses pointer are checked in smb_init */
1646         if (tcon->ses->server == NULL)
1647                 return -ECONNABORTED;
1648
1649         pSMB->AndXCommand = 0xFF;       /* none */
1650         pSMB->Fid = netfid;
1651         pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1652         if (wct == 14)
1653                 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1654         pSMB->Reserved = 0xFFFFFFFF;
1655         pSMB->WriteMode = 0;
1656         pSMB->Remaining = 0;
1657
1658         pSMB->DataOffset =
1659             cpu_to_le16(offsetof(struct smb_com_write_req, Data) - 4);
1660
1661         pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
1662         pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
1663         smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1664         if (wct == 14)
1665                 pSMB->hdr.smb_buf_length += count+1;
1666         else /* wct == 12 */
1667                 pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */
1668         if (wct == 14)
1669                 pSMB->ByteCount = cpu_to_le16(count + 1);
1670         else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
1671                 struct smb_com_writex_req *pSMBW =
1672                                 (struct smb_com_writex_req *)pSMB;
1673                 pSMBW->ByteCount = cpu_to_le16(count + 5);
1674         }
1675         iov[0].iov_base = pSMB;
1676         if (wct == 14)
1677                 iov[0].iov_len = smb_hdr_len + 4;
1678         else /* wct == 12 pad bigger by four bytes */
1679                 iov[0].iov_len = smb_hdr_len + 8;
1680
1681
1682         rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1683                           long_op);
1684         cifs_stats_inc(&tcon->num_writes);
1685         if (rc) {
1686                 cFYI(1, ("Send error Write2 = %d", rc));
1687         } else if (resp_buf_type == 0) {
1688                 /* presumably this can not happen, but best to be safe */
1689                 rc = -EIO;
1690         } else {
1691                 WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
1692                 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1693                 *nbytes = (*nbytes) << 16;
1694                 *nbytes += le16_to_cpu(pSMBr->Count);
1695         }
1696
1697 /*      cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
1698         if (resp_buf_type == CIFS_SMALL_BUFFER)
1699                 cifs_small_buf_release(iov[0].iov_base);
1700         else if (resp_buf_type == CIFS_LARGE_BUFFER)
1701                 cifs_buf_release(iov[0].iov_base);
1702
1703         /* Note: On -EAGAIN error only caller can retry on handle based calls
1704                 since file handle passed in no longer valid */
1705
1706         return rc;
1707 }
1708
1709
1710 int
1711 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1712             const __u16 smb_file_id, const __u64 len,
1713             const __u64 offset, const __u32 numUnlock,
1714             const __u32 numLock, const __u8 lockType, const bool waitFlag)
1715 {
1716         int rc = 0;
1717         LOCK_REQ *pSMB = NULL;
1718 /*      LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */
1719         int bytes_returned;
1720         int timeout = 0;
1721         __u16 count;
1722
1723         cFYI(1, ("CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock));
1724         rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1725
1726         if (rc)
1727                 return rc;
1728
1729         if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1730                 timeout = CIFS_ASYNC_OP; /* no response expected */
1731                 pSMB->Timeout = 0;
1732         } else if (waitFlag) {
1733                 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1734                 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1735         } else {
1736                 pSMB->Timeout = 0;
1737         }
1738
1739         pSMB->NumberOfLocks = cpu_to_le16(numLock);
1740         pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1741         pSMB->LockType = lockType;
1742         pSMB->AndXCommand = 0xFF;       /* none */
1743         pSMB->Fid = smb_file_id; /* netfid stays le */
1744
1745         if ((numLock != 0) || (numUnlock != 0)) {
1746                 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1747                 /* BB where to store pid high? */
1748                 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1749                 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1750                 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1751                 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1752                 count = sizeof(LOCKING_ANDX_RANGE);
1753         } else {
1754                 /* oplock break */
1755                 count = 0;
1756         }
1757         pSMB->hdr.smb_buf_length += count;
1758         pSMB->ByteCount = cpu_to_le16(count);
1759
1760         if (waitFlag) {
1761                 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1762                         (struct smb_hdr *) pSMB, &bytes_returned);
1763                 cifs_small_buf_release(pSMB);
1764         } else {
1765                 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB,
1766                                       timeout);
1767                 /* SMB buffer freed by function above */
1768         }
1769         cifs_stats_inc(&tcon->num_locks);
1770         if (rc)
1771                 cFYI(1, ("Send error in Lock = %d", rc));
1772
1773         /* Note: On -EAGAIN error only caller can retry on handle based calls
1774         since file handle passed in no longer valid */
1775         return rc;
1776 }
1777
1778 int
1779 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1780                 const __u16 smb_file_id, const int get_flag, const __u64 len,
1781                 struct file_lock *pLockData, const __u16 lock_type,
1782                 const bool waitFlag)
1783 {
1784         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
1785         struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1786         struct cifs_posix_lock *parm_data;
1787         int rc = 0;
1788         int timeout = 0;
1789         int bytes_returned = 0;
1790         int resp_buf_type = 0;
1791         __u16 params, param_offset, offset, byte_count, count;
1792         struct kvec iov[1];
1793
1794         cFYI(1, ("Posix Lock"));
1795
1796         if (pLockData == NULL)
1797                 return -EINVAL;
1798
1799         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
1800
1801         if (rc)
1802                 return rc;
1803
1804         pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
1805
1806         params = 6;
1807         pSMB->MaxSetupCount = 0;
1808         pSMB->Reserved = 0;
1809         pSMB->Flags = 0;
1810         pSMB->Reserved2 = 0;
1811         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1812         offset = param_offset + params;
1813
1814         count = sizeof(struct cifs_posix_lock);
1815         pSMB->MaxParameterCount = cpu_to_le16(2);
1816         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
1817         pSMB->SetupCount = 1;
1818         pSMB->Reserved3 = 0;
1819         if (get_flag)
1820                 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
1821         else
1822                 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1823         byte_count = 3 /* pad */  + params + count;
1824         pSMB->DataCount = cpu_to_le16(count);
1825         pSMB->ParameterCount = cpu_to_le16(params);
1826         pSMB->TotalDataCount = pSMB->DataCount;
1827         pSMB->TotalParameterCount = pSMB->ParameterCount;
1828         pSMB->ParameterOffset = cpu_to_le16(param_offset);
1829         parm_data = (struct cifs_posix_lock *)
1830                         (((char *) &pSMB->hdr.Protocol) + offset);
1831
1832         parm_data->lock_type = cpu_to_le16(lock_type);
1833         if (waitFlag) {
1834                 timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
1835                 parm_data->lock_flags = cpu_to_le16(1);
1836                 pSMB->Timeout = cpu_to_le32(-1);
1837         } else
1838                 pSMB->Timeout = 0;
1839
1840         parm_data->pid = cpu_to_le32(current->tgid);
1841         parm_data->start = cpu_to_le64(pLockData->fl_start);
1842         parm_data->length = cpu_to_le64(len);  /* normalize negative numbers */
1843
1844         pSMB->DataOffset = cpu_to_le16(offset);
1845         pSMB->Fid = smb_file_id;
1846         pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
1847         pSMB->Reserved4 = 0;
1848         pSMB->hdr.smb_buf_length += byte_count;
1849         pSMB->ByteCount = cpu_to_le16(byte_count);
1850         if (waitFlag) {
1851                 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
1852                         (struct smb_hdr *) pSMBr, &bytes_returned);
1853         } else {
1854                 iov[0].iov_base = (char *)pSMB;
1855                 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1856                 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1857                                 &resp_buf_type, timeout);
1858                 pSMB = NULL; /* request buf already freed by SendReceive2. Do
1859                                 not try to free it twice below on exit */
1860                 pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
1861         }
1862
1863         if (rc) {
1864                 cFYI(1, ("Send error in Posix Lock = %d", rc));
1865         } else if (get_flag) {
1866                 /* lock structure can be returned on get */
1867                 __u16 data_offset;
1868                 __u16 data_count;
1869                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1870
1871                 if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
1872                         rc = -EIO;      /* bad smb */
1873                         goto plk_err_exit;
1874                 }
1875                 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1876                 data_count  = le16_to_cpu(pSMBr->t2.DataCount);
1877                 if (data_count < sizeof(struct cifs_posix_lock)) {
1878                         rc = -EIO;
1879                         goto plk_err_exit;
1880                 }
1881                 parm_data = (struct cifs_posix_lock *)
1882                         ((char *)&pSMBr->hdr.Protocol + data_offset);
1883                 if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
1884                         pLockData->fl_type = F_UNLCK;
1885         }
1886
1887 plk_err_exit:
1888         if (pSMB)
1889                 cifs_small_buf_release(pSMB);
1890
1891         if (resp_buf_type == CIFS_SMALL_BUFFER)
1892                 cifs_small_buf_release(iov[0].iov_base);
1893         else if (resp_buf_type == CIFS_LARGE_BUFFER)
1894                 cifs_buf_release(iov[0].iov_base);
1895
1896         /* Note: On -EAGAIN error only caller can retry on handle based calls
1897            since file handle passed in no longer valid */
1898
1899         return rc;
1900 }
1901
1902
1903 int
1904 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1905 {
1906         int rc = 0;
1907         CLOSE_REQ *pSMB = NULL;
1908         cFYI(1, ("In CIFSSMBClose"));
1909
1910 /* do not retry on dead session on close */
1911         rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1912         if (rc == -EAGAIN)
1913                 return 0;
1914         if (rc)
1915                 return rc;
1916
1917         pSMB->FileID = (__u16) smb_file_id;
1918         pSMB->LastWriteTime = 0xFFFFFFFF;
1919         pSMB->ByteCount = 0;
1920         rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1921         cifs_stats_inc(&tcon->num_closes);
1922         if (rc) {
1923                 if (rc != -EINTR) {
1924                         /* EINTR is expected when user ctl-c to kill app */
1925                         cERROR(1, ("Send error in Close = %d", rc));
1926                 }
1927         }
1928
1929         /* Since session is dead, file will be closed on server already */
1930         if (rc == -EAGAIN)
1931                 rc = 0;
1932
1933         return rc;
1934 }
1935
1936 int
1937 CIFSSMBFlush(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1938 {
1939         int rc = 0;
1940         FLUSH_REQ *pSMB = NULL;
1941         cFYI(1, ("In CIFSSMBFlush"));
1942
1943         rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
1944         if (rc)
1945                 return rc;
1946
1947         pSMB->FileID = (__u16) smb_file_id;
1948         pSMB->ByteCount = 0;
1949         rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
1950         cifs_stats_inc(&tcon->num_flushes);
1951         if (rc)
1952                 cERROR(1, ("Send error in Flush = %d", rc));
1953
1954         return rc;
1955 }
1956
1957 int
1958 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1959               const char *fromName, const char *toName,
1960               const struct nls_table *nls_codepage, int remap)
1961 {
1962         int rc = 0;
1963         RENAME_REQ *pSMB = NULL;
1964         RENAME_RSP *pSMBr = NULL;
1965         int bytes_returned;
1966         int name_len, name_len2;
1967         __u16 count;
1968
1969         cFYI(1, ("In CIFSSMBRename"));
1970 renameRetry:
1971         rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1972                       (void **) &pSMBr);
1973         if (rc)
1974                 return rc;
1975
1976         pSMB->BufferFormat = 0x04;
1977         pSMB->SearchAttributes =
1978             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1979                         ATTR_DIRECTORY);
1980
1981         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1982                 name_len =
1983                     cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1984                                      PATH_MAX, nls_codepage, remap);
1985                 name_len++;     /* trailing null */
1986                 name_len *= 2;
1987                 pSMB->OldFileName[name_len] = 0x04;     /* pad */
1988         /* protocol requires ASCII signature byte on Unicode string */
1989                 pSMB->OldFileName[name_len + 1] = 0x00;
1990                 name_len2 =
1991                     cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1992                                      toName, PATH_MAX, nls_codepage, remap);
1993                 name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
1994                 name_len2 *= 2; /* convert to bytes */
1995         } else {        /* BB improve the check for buffer overruns BB */
1996                 name_len = strnlen(fromName, PATH_MAX);
1997                 name_len++;     /* trailing null */
1998                 strncpy(pSMB->OldFileName, fromName, name_len);
1999                 name_len2 = strnlen(toName, PATH_MAX);
2000                 name_len2++;    /* trailing null */
2001                 pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
2002                 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2003                 name_len2++;    /* trailing null */
2004                 name_len2++;    /* signature byte */
2005         }
2006
2007         count = 1 /* 1st signature byte */  + name_len + name_len2;
2008         pSMB->hdr.smb_buf_length += count;
2009         pSMB->ByteCount = cpu_to_le16(count);
2010
2011         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2012                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2013         cifs_stats_inc(&tcon->num_renames);
2014         if (rc)
2015                 cFYI(1, ("Send error in rename = %d", rc));
2016
2017         cifs_buf_release(pSMB);
2018
2019         if (rc == -EAGAIN)
2020                 goto renameRetry;
2021
2022         return rc;
2023 }
2024
2025 int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon,
2026                 int netfid, const char *target_name,
2027                 const struct nls_table *nls_codepage, int remap)
2028 {
2029         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
2030         struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2031         struct set_file_rename *rename_info;
2032         char *data_offset;
2033         char dummy_string[30];
2034         int rc = 0;
2035         int bytes_returned = 0;
2036         int len_of_str;
2037         __u16 params, param_offset, offset, count, byte_count;
2038
2039         cFYI(1, ("Rename to File by handle"));
2040         rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
2041                         (void **) &pSMBr);
2042         if (rc)
2043                 return rc;
2044
2045         params = 6;
2046         pSMB->MaxSetupCount = 0;
2047         pSMB->Reserved = 0;
2048         pSMB->Flags = 0;
2049         pSMB->Timeout = 0;
2050         pSMB->Reserved2 = 0;
2051         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
2052         offset = param_offset + params;
2053
2054         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2055         rename_info = (struct set_file_rename *) data_offset;
2056         pSMB->MaxParameterCount = cpu_to_le16(2);
2057         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB from sess */
2058         pSMB->SetupCount = 1;
2059         pSMB->Reserved3 = 0;
2060         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2061         byte_count = 3 /* pad */  + params;
2062         pSMB->ParameterCount = cpu_to_le16(params);
2063         pSMB->TotalParameterCount = pSMB->ParameterCount;
2064         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2065         pSMB->DataOffset = cpu_to_le16(offset);
2066         /* construct random name ".cifs_tmp<inodenum><mid>" */
2067         rename_info->overwrite = cpu_to_le32(1);
2068         rename_info->root_fid  = 0;
2069         /* unicode only call */
2070         if (target_name == NULL) {
2071                 sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
2072                 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2073                                         dummy_string, 24, nls_codepage, remap);
2074         } else {
2075                 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
2076                                         target_name, PATH_MAX, nls_codepage,
2077                                         remap);
2078         }
2079         rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
2080         count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
2081         byte_count += count;
2082         pSMB->DataCount = cpu_to_le16(count);
2083         pSMB->TotalDataCount = pSMB->DataCount;
2084         pSMB->Fid = netfid;
2085         pSMB->InformationLevel =
2086                 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
2087         pSMB->Reserved4 = 0;
2088         pSMB->hdr.smb_buf_length += byte_count;
2089         pSMB->ByteCount = cpu_to_le16(byte_count);
2090         rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
2091                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2092         cifs_stats_inc(&pTcon->num_t2renames);
2093         if (rc)
2094                 cFYI(1, ("Send error in Rename (by file handle) = %d", rc));
2095
2096         cifs_buf_release(pSMB);
2097
2098         /* Note: On -EAGAIN error only caller can retry on handle based calls
2099                 since file handle passed in no longer valid */
2100
2101         return rc;
2102 }
2103
2104 int
2105 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char *fromName,
2106             const __u16 target_tid, const char *toName, const int flags,
2107             const struct nls_table *nls_codepage, int remap)
2108 {
2109         int rc = 0;
2110         COPY_REQ *pSMB = NULL;
2111         COPY_RSP *pSMBr = NULL;
2112         int bytes_returned;
2113         int name_len, name_len2;
2114         __u16 count;
2115
2116         cFYI(1, ("In CIFSSMBCopy"));
2117 copyRetry:
2118         rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
2119                         (void **) &pSMBr);
2120         if (rc)
2121                 return rc;
2122
2123         pSMB->BufferFormat = 0x04;
2124         pSMB->Tid2 = target_tid;
2125
2126         pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
2127
2128         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2129                 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
2130                                             fromName, PATH_MAX, nls_codepage,
2131                                             remap);
2132                 name_len++;     /* trailing null */
2133                 name_len *= 2;
2134                 pSMB->OldFileName[name_len] = 0x04;     /* pad */
2135                 /* protocol requires ASCII signature byte on Unicode string */
2136                 pSMB->OldFileName[name_len + 1] = 0x00;
2137                 name_len2 =
2138                     cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2139                                 toName, PATH_MAX, nls_codepage, remap);
2140                 name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2141                 name_len2 *= 2; /* convert to bytes */
2142         } else {        /* BB improve the check for buffer overruns BB */
2143                 name_len = strnlen(fromName, PATH_MAX);
2144                 name_len++;     /* trailing null */
2145                 strncpy(pSMB->OldFileName, fromName, name_len);
2146                 name_len2 = strnlen(toName, PATH_MAX);
2147                 name_len2++;    /* trailing null */
2148                 pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
2149                 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2150                 name_len2++;    /* trailing null */
2151                 name_len2++;    /* signature byte */
2152         }
2153
2154         count = 1 /* 1st signature byte */  + name_len + name_len2;
2155         pSMB->hdr.smb_buf_length += count;
2156         pSMB->ByteCount = cpu_to_le16(count);
2157
2158         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2159                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2160         if (rc) {
2161                 cFYI(1, ("Send error in copy = %d with %d files copied",
2162                         rc, le16_to_cpu(pSMBr->CopyCount)));
2163         }
2164         cifs_buf_release(pSMB);
2165
2166         if (rc == -EAGAIN)
2167                 goto copyRetry;
2168
2169         return rc;
2170 }
2171
2172 int
2173 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
2174                       const char *fromName, const char *toName,
2175                       const struct nls_table *nls_codepage)
2176 {
2177         TRANSACTION2_SPI_REQ *pSMB = NULL;
2178         TRANSACTION2_SPI_RSP *pSMBr = NULL;
2179         char *data_offset;
2180         int name_len;
2181         int name_len_target;
2182         int rc = 0;
2183         int bytes_returned = 0;
2184         __u16 params, param_offset, offset, byte_count;
2185
2186         cFYI(1, ("In Symlink Unix style"));
2187 createSymLinkRetry:
2188         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2189                       (void **) &pSMBr);
2190         if (rc)
2191                 return rc;
2192
2193         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2194                 name_len =
2195                     cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
2196                                   /* find define for this maxpathcomponent */
2197                                   , nls_codepage);
2198                 name_len++;     /* trailing null */
2199                 name_len *= 2;
2200
2201         } else {        /* BB improve the check for buffer overruns BB */
2202                 name_len = strnlen(fromName, PATH_MAX);
2203                 name_len++;     /* trailing null */
2204                 strncpy(pSMB->FileName, fromName, name_len);
2205         }
2206         params = 6 + name_len;
2207         pSMB->MaxSetupCount = 0;
2208         pSMB->Reserved = 0;
2209         pSMB->Flags = 0;
2210         pSMB->Timeout = 0;
2211         pSMB->Reserved2 = 0;
2212         param_offset = offsetof(struct smb_com_transaction2_spi_req,
2213                                 InformationLevel) - 4;
2214         offset = param_offset + params;
2215
2216         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2217         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2218                 name_len_target =
2219                     cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
2220                                   /* find define for this maxpathcomponent */
2221                                   , nls_codepage);
2222                 name_len_target++;      /* trailing null */
2223                 name_len_target *= 2;
2224         } else {        /* BB improve the check for buffer overruns BB */
2225                 name_len_target = strnlen(toName, PATH_MAX);
2226                 name_len_target++;      /* trailing null */
2227                 strncpy(data_offset, toName, name_len_target);
2228         }
2229
2230         pSMB->MaxParameterCount = cpu_to_le16(2);
2231         /* BB find exact max on data count below from sess */
2232         pSMB->MaxDataCount = cpu_to_le16(1000);
2233         pSMB->SetupCount = 1;
2234         pSMB->Reserved3 = 0;
2235         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2236         byte_count = 3 /* pad */  + params + name_len_target;
2237         pSMB->DataCount = cpu_to_le16(name_len_target);
2238         pSMB->ParameterCount = cpu_to_le16(params);
2239         pSMB->TotalDataCount = pSMB->DataCount;
2240         pSMB->TotalParameterCount = pSMB->ParameterCount;
2241         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2242         pSMB->DataOffset = cpu_to_le16(offset);
2243         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
2244         pSMB->Reserved4 = 0;
2245         pSMB->hdr.smb_buf_length += byte_count;
2246         pSMB->ByteCount = cpu_to_le16(byte_count);
2247         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2248                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2249         cifs_stats_inc(&tcon->num_symlinks);
2250         if (rc)
2251                 cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc));
2252
2253         cifs_buf_release(pSMB);
2254
2255         if (rc == -EAGAIN)
2256                 goto createSymLinkRetry;
2257
2258         return rc;
2259 }
2260
2261 int
2262 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2263                        const char *fromName, const char *toName,
2264                        const struct nls_table *nls_codepage, int remap)
2265 {
2266         TRANSACTION2_SPI_REQ *pSMB = NULL;
2267         TRANSACTION2_SPI_RSP *pSMBr = NULL;
2268         char *data_offset;
2269         int name_len;
2270         int name_len_target;
2271         int rc = 0;
2272         int bytes_returned = 0;
2273         __u16 params, param_offset, offset, byte_count;
2274
2275         cFYI(1, ("In Create Hard link Unix style"));
2276 createHardLinkRetry:
2277         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2278                       (void **) &pSMBr);
2279         if (rc)
2280                 return rc;
2281
2282         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2283                 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
2284                                             PATH_MAX, nls_codepage, remap);
2285                 name_len++;     /* trailing null */
2286                 name_len *= 2;
2287
2288         } else {        /* BB improve the check for buffer overruns BB */
2289                 name_len = strnlen(toName, PATH_MAX);
2290                 name_len++;     /* trailing null */
2291                 strncpy(pSMB->FileName, toName, name_len);
2292         }
2293         params = 6 + name_len;
2294         pSMB->MaxSetupCount = 0;
2295         pSMB->Reserved = 0;
2296         pSMB->Flags = 0;
2297         pSMB->Timeout = 0;
2298         pSMB->Reserved2 = 0;
2299         param_offset = offsetof(struct smb_com_transaction2_spi_req,
2300                                 InformationLevel) - 4;
2301         offset = param_offset + params;
2302
2303         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2304         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2305                 name_len_target =
2306                     cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
2307                                      nls_codepage, remap);
2308                 name_len_target++;      /* trailing null */
2309                 name_len_target *= 2;
2310         } else {        /* BB improve the check for buffer overruns BB */
2311                 name_len_target = strnlen(fromName, PATH_MAX);
2312                 name_len_target++;      /* trailing null */
2313                 strncpy(data_offset, fromName, name_len_target);
2314         }
2315
2316         pSMB->MaxParameterCount = cpu_to_le16(2);
2317         /* BB find exact max on data count below from sess*/
2318         pSMB->MaxDataCount = cpu_to_le16(1000);
2319         pSMB->SetupCount = 1;
2320         pSMB->Reserved3 = 0;
2321         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2322         byte_count = 3 /* pad */  + params + name_len_target;
2323         pSMB->ParameterCount = cpu_to_le16(params);
2324         pSMB->TotalParameterCount = pSMB->ParameterCount;
2325         pSMB->DataCount = cpu_to_le16(name_len_target);
2326         pSMB->TotalDataCount = pSMB->DataCount;
2327         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2328         pSMB->DataOffset = cpu_to_le16(offset);
2329         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
2330         pSMB->Reserved4 = 0;
2331         pSMB->hdr.smb_buf_length += byte_count;
2332         pSMB->ByteCount = cpu_to_le16(byte_count);
2333         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2334                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2335         cifs_stats_inc(&tcon->num_hardlinks);
2336         if (rc)
2337                 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
2338
2339         cifs_buf_release(pSMB);
2340         if (rc == -EAGAIN)
2341                 goto createHardLinkRetry;
2342
2343         return rc;
2344 }
2345
2346 int
2347 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
2348                    const char *fromName, const char *toName,
2349                    const struct nls_table *nls_codepage, int remap)
2350 {
2351         int rc = 0;
2352         NT_RENAME_REQ *pSMB = NULL;
2353         RENAME_RSP *pSMBr = NULL;
2354         int bytes_returned;
2355         int name_len, name_len2;
2356         __u16 count;
2357
2358         cFYI(1, ("In CIFSCreateHardLink"));
2359 winCreateHardLinkRetry:
2360
2361         rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
2362                       (void **) &pSMBr);
2363         if (rc)
2364                 return rc;
2365
2366         pSMB->SearchAttributes =
2367             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2368                         ATTR_DIRECTORY);
2369         pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
2370         pSMB->ClusterCount = 0;
2371
2372         pSMB->BufferFormat = 0x04;
2373
2374         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2375                 name_len =
2376                     cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
2377                                      PATH_MAX, nls_codepage, remap);
2378                 name_len++;     /* trailing null */
2379                 name_len *= 2;
2380
2381                 /* protocol specifies ASCII buffer format (0x04) for unicode */
2382                 pSMB->OldFileName[name_len] = 0x04;
2383                 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
2384                 name_len2 =
2385                     cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
2386                                      toName, PATH_MAX, nls_codepage, remap);
2387                 name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
2388                 name_len2 *= 2; /* convert to bytes */
2389         } else {        /* BB improve the check for buffer overruns BB */
2390                 name_len = strnlen(fromName, PATH_MAX);
2391                 name_len++;     /* trailing null */
2392                 strncpy(pSMB->OldFileName, fromName, name_len);
2393                 name_len2 = strnlen(toName, PATH_MAX);
2394                 name_len2++;    /* trailing null */
2395                 pSMB->OldFileName[name_len] = 0x04;     /* 2nd buffer format */
2396                 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
2397                 name_len2++;    /* trailing null */
2398                 name_len2++;    /* signature byte */
2399         }
2400
2401         count = 1 /* string type byte */  + name_len + name_len2;
2402         pSMB->hdr.smb_buf_length += count;
2403         pSMB->ByteCount = cpu_to_le16(count);
2404
2405         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2406                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2407         cifs_stats_inc(&tcon->num_hardlinks);
2408         if (rc)
2409                 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
2410
2411         cifs_buf_release(pSMB);
2412         if (rc == -EAGAIN)
2413                 goto winCreateHardLinkRetry;
2414
2415         return rc;
2416 }
2417
2418 int
2419 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
2420                         const unsigned char *searchName,
2421                         char *symlinkinfo, const int buflen,
2422                         const struct nls_table *nls_codepage)
2423 {
2424 /* SMB_QUERY_FILE_UNIX_LINK */
2425         TRANSACTION2_QPI_REQ *pSMB = NULL;
2426         TRANSACTION2_QPI_RSP *pSMBr = NULL;
2427         int rc = 0;
2428         int bytes_returned;
2429         int name_len;
2430         __u16 params, byte_count;
2431
2432         cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
2433
2434 querySymLinkRetry:
2435         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2436                       (void **) &pSMBr);
2437         if (rc)
2438                 return rc;
2439
2440         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2441                 name_len =
2442                     cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
2443                                   PATH_MAX, nls_codepage);
2444                 name_len++;     /* trailing null */
2445                 name_len *= 2;
2446         } else {        /* BB improve the check for buffer overruns BB */
2447                 name_len = strnlen(searchName, PATH_MAX);
2448                 name_len++;     /* trailing null */
2449                 strncpy(pSMB->FileName, searchName, name_len);
2450         }
2451
2452         params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
2453         pSMB->TotalDataCount = 0;
2454         pSMB->MaxParameterCount = cpu_to_le16(2);
2455         /* BB find exact max data count below from sess structure BB */
2456         pSMB->MaxDataCount = cpu_to_le16(4000);
2457         pSMB->MaxSetupCount = 0;
2458         pSMB->Reserved = 0;
2459         pSMB->Flags = 0;
2460         pSMB->Timeout = 0;
2461         pSMB->Reserved2 = 0;
2462         pSMB->ParameterOffset = cpu_to_le16(offsetof(
2463         struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
2464         pSMB->DataCount = 0;
2465         pSMB->DataOffset = 0;
2466         pSMB->SetupCount = 1;
2467         pSMB->Reserved3 = 0;
2468         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2469         byte_count = params + 1 /* pad */ ;
2470         pSMB->TotalParameterCount = cpu_to_le16(params);
2471         pSMB->ParameterCount = pSMB->TotalParameterCount;
2472         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
2473         pSMB->Reserved4 = 0;
2474         pSMB->hdr.smb_buf_length += byte_count;
2475         pSMB->ByteCount = cpu_to_le16(byte_count);
2476
2477         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2478                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2479         if (rc) {
2480                 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
2481         } else {
2482                 /* decode response */
2483
2484                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2485                 if (rc || (pSMBr->ByteCount < 2))
2486                 /* BB also check enough total bytes returned */
2487                         rc = -EIO;      /* bad smb */
2488                 else {
2489                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2490                         __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2491
2492                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2493                                 name_len = UniStrnlen((wchar_t *) ((char *)
2494                                         &pSMBr->hdr.Protocol + data_offset),
2495                                         min_t(const int, buflen, count) / 2);
2496                         /* BB FIXME investigate remapping reserved chars here */
2497                                 cifs_strfromUCS_le(symlinkinfo,
2498                                         (__le16 *) ((char *)&pSMBr->hdr.Protocol
2499                                                         + data_offset),
2500                                         name_len, nls_codepage);
2501                         } else {
2502                                 strncpy(symlinkinfo,
2503                                         (char *) &pSMBr->hdr.Protocol +
2504                                                 data_offset,
2505                                         min_t(const int, buflen, count));
2506                         }
2507                         symlinkinfo[buflen] = 0;
2508         /* just in case so calling code does not go off the end of buffer */
2509                 }
2510         }
2511         cifs_buf_release(pSMB);
2512         if (rc == -EAGAIN)
2513                 goto querySymLinkRetry;
2514         return rc;
2515 }
2516
2517 #ifdef CONFIG_CIFS_EXPERIMENTAL
2518 /* Initialize NT TRANSACT SMB into small smb request buffer.
2519    This assumes that all NT TRANSACTS that we init here have
2520    total parm and data under about 400 bytes (to fit in small cifs
2521    buffer size), which is the case so far, it easily fits. NB:
2522         Setup words themselves and ByteCount
2523         MaxSetupCount (size of returned setup area) and
2524         MaxParameterCount (returned parms size) must be set by caller */
2525 static int
2526 smb_init_nttransact(const __u16 sub_command, const int setup_count,
2527                    const int parm_len, struct cifsTconInfo *tcon,
2528                    void **ret_buf)
2529 {
2530         int rc;
2531         __u32 temp_offset;
2532         struct smb_com_ntransact_req *pSMB;
2533
2534         rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
2535                                 (void **)&pSMB);
2536         if (rc)
2537                 return rc;
2538         *ret_buf = (void *)pSMB;
2539         pSMB->Reserved = 0;
2540         pSMB->TotalParameterCount = cpu_to_le32(parm_len);
2541         pSMB->TotalDataCount  = 0;
2542         pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2543                                           MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2544         pSMB->ParameterCount = pSMB->TotalParameterCount;
2545         pSMB->DataCount  = pSMB->TotalDataCount;
2546         temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
2547                         (setup_count * 2) - 4 /* for rfc1001 length itself */;
2548         pSMB->ParameterOffset = cpu_to_le32(temp_offset);
2549         pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
2550         pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
2551         pSMB->SubCommand = cpu_to_le16(sub_command);
2552         return 0;
2553 }
2554
2555 static int
2556 validate_ntransact(char *buf, char **ppparm, char **ppdata,
2557                    __u32 *pparmlen, __u32 *pdatalen)
2558 {
2559         char *end_of_smb;
2560         __u32 data_count, data_offset, parm_count, parm_offset;
2561         struct smb_com_ntransact_rsp *pSMBr;
2562
2563         *pdatalen = 0;
2564         *pparmlen = 0;
2565
2566         if (buf == NULL)
2567                 return -EINVAL;
2568
2569         pSMBr = (struct smb_com_ntransact_rsp *)buf;
2570
2571         /* ByteCount was converted from little endian in SendReceive */
2572         end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
2573                         (char *)&pSMBr->ByteCount;
2574
2575         data_offset = le32_to_cpu(pSMBr->DataOffset);
2576         data_count = le32_to_cpu(pSMBr->DataCount);
2577         parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
2578         parm_count = le32_to_cpu(pSMBr->ParameterCount);
2579
2580         *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
2581         *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
2582
2583         /* should we also check that parm and data areas do not overlap? */
2584         if (*ppparm > end_of_smb) {
2585                 cFYI(1, ("parms start after end of smb"));
2586                 return -EINVAL;
2587         } else if (parm_count + *ppparm > end_of_smb) {
2588                 cFYI(1, ("parm end after end of smb"));
2589                 return -EINVAL;
2590         } else if (*ppdata > end_of_smb) {
2591                 cFYI(1, ("data starts after end of smb"));
2592                 return -EINVAL;
2593         } else if (data_count + *ppdata > end_of_smb) {
2594                 cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
2595                         *ppdata, data_count, (data_count + *ppdata),
2596                         end_of_smb, pSMBr));
2597                 return -EINVAL;
2598         } else if (parm_count + data_count > pSMBr->ByteCount) {
2599                 cFYI(1, ("parm count and data count larger than SMB"));
2600                 return -EINVAL;
2601         }
2602         *pdatalen = data_count;
2603         *pparmlen = parm_count;
2604         return 0;
2605 }
2606 #endif /* CIFS_EXPERIMENTAL */
2607
2608 int
2609 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2610                         const unsigned char *searchName,
2611                         char *symlinkinfo, const int buflen, __u16 fid,
2612                         const struct nls_table *nls_codepage)
2613 {
2614         int rc = 0;
2615         int bytes_returned;
2616         int name_len;
2617         struct smb_com_transaction_ioctl_req *pSMB;
2618         struct smb_com_transaction_ioctl_rsp *pSMBr;
2619
2620         cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
2621         rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2622                       (void **) &pSMBr);
2623         if (rc)
2624                 return rc;
2625
2626         pSMB->TotalParameterCount = 0 ;
2627         pSMB->TotalDataCount = 0;
2628         pSMB->MaxParameterCount = cpu_to_le32(2);
2629         /* BB find exact data count max from sess structure BB */
2630         pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
2631                                           MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2632         pSMB->MaxSetupCount = 4;
2633         pSMB->Reserved = 0;
2634         pSMB->ParameterOffset = 0;
2635         pSMB->DataCount = 0;
2636         pSMB->DataOffset = 0;
2637         pSMB->SetupCount = 4;
2638         pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
2639         pSMB->ParameterCount = pSMB->TotalParameterCount;
2640         pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
2641         pSMB->IsFsctl = 1; /* FSCTL */
2642         pSMB->IsRootFlag = 0;
2643         pSMB->Fid = fid; /* file handle always le */
2644         pSMB->ByteCount = 0;
2645
2646         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2647                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2648         if (rc) {
2649                 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
2650         } else {                /* decode response */
2651                 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
2652                 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
2653                 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
2654                 /* BB also check enough total bytes returned */
2655                         rc = -EIO;      /* bad smb */
2656                 else {
2657                         if (data_count && (data_count < 2048)) {
2658                                 char *end_of_smb = 2 /* sizeof byte count */ +
2659                                                 pSMBr->ByteCount +
2660                                                 (char *)&pSMBr->ByteCount;
2661
2662                                 struct reparse_data *reparse_buf =
2663                                                 (struct reparse_data *)
2664                                                 ((char *)&pSMBr->hdr.Protocol
2665                                                                  + data_offset);
2666                                 if ((char *)reparse_buf >= end_of_smb) {
2667                                         rc = -EIO;
2668                                         goto qreparse_out;
2669                                 }
2670                                 if ((reparse_buf->LinkNamesBuf +
2671                                         reparse_buf->TargetNameOffset +
2672                                         reparse_buf->TargetNameLen) >
2673                                                 end_of_smb) {
2674                                         cFYI(1, ("reparse buf beyond SMB"));
2675                                         rc = -EIO;
2676                                         goto qreparse_out;
2677                                 }
2678
2679                                 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2680                                         name_len = UniStrnlen((wchar_t *)
2681                                                 (reparse_buf->LinkNamesBuf +
2682                                                 reparse_buf->TargetNameOffset),
2683                                                 min(buflen/2,
2684                                                 reparse_buf->TargetNameLen / 2));
2685                                         cifs_strfromUCS_le(symlinkinfo,
2686                                                 (__le16 *) (reparse_buf->LinkNamesBuf +
2687                                                 reparse_buf->TargetNameOffset),
2688                                                 name_len, nls_codepage);
2689                                 } else { /* ASCII names */
2690                                         strncpy(symlinkinfo,
2691                                                 reparse_buf->LinkNamesBuf +
2692                                                 reparse_buf->TargetNameOffset,
2693                                                 min_t(const int, buflen,
2694                                                    reparse_buf->TargetNameLen));
2695                                 }
2696                         } else {
2697                                 rc = -EIO;
2698                                 cFYI(1, ("Invalid return data count on "
2699                                          "get reparse info ioctl"));
2700                         }
2701                         symlinkinfo[buflen] = 0; /* just in case so the caller
2702                                         does not go off the end of the buffer */
2703                         cFYI(1, ("readlink result - %s", symlinkinfo));
2704                 }
2705         }
2706 qreparse_out:
2707         cifs_buf_release(pSMB);
2708
2709         /* Note: On -EAGAIN error only caller can retry on handle based calls
2710                 since file handle passed in no longer valid */
2711
2712         return rc;
2713 }
2714
2715 #ifdef CONFIG_CIFS_POSIX
2716
2717 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
2718 static void cifs_convert_ace(posix_acl_xattr_entry *ace,
2719                              struct cifs_posix_ace *cifs_ace)
2720 {
2721         /* u8 cifs fields do not need le conversion */
2722         ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
2723         ace->e_tag  = cpu_to_le16(cifs_ace->cifs_e_tag);
2724         ace->e_id   = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
2725         /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
2726
2727         return;
2728 }
2729
2730 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
2731 static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen,
2732                                const int acl_type, const int size_of_data_area)
2733 {
2734         int size =  0;
2735         int i;
2736         __u16 count;
2737         struct cifs_posix_ace *pACE;
2738         struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)src;
2739         posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)trgt;
2740
2741         if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
2742                 return -EOPNOTSUPP;
2743
2744         if (acl_type & ACL_TYPE_ACCESS) {
2745                 count = le16_to_cpu(cifs_acl->access_entry_count);
2746                 pACE = &cifs_acl->ace_array[0];
2747                 size = sizeof(struct cifs_posix_acl);
2748                 size += sizeof(struct cifs_posix_ace) * count;
2749                 /* check if we would go beyond end of SMB */
2750                 if (size_of_data_area < size) {
2751                         cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
2752                                 size_of_data_area, size));
2753                         return -EINVAL;
2754                 }
2755         } else if (acl_type & ACL_TYPE_DEFAULT) {
2756                 count = le16_to_cpu(cifs_acl->access_entry_count);
2757                 size = sizeof(struct cifs_posix_acl);
2758                 size += sizeof(struct cifs_posix_ace) * count;
2759 /* skip past access ACEs to get to default ACEs */
2760                 pACE = &cifs_acl->ace_array[count];
2761                 count = le16_to_cpu(cifs_acl->default_entry_count);
2762                 size += sizeof(struct cifs_posix_ace) * count;
2763                 /* check if we would go beyond end of SMB */
2764                 if (size_of_data_area < size)
2765                         return -EINVAL;
2766         } else {
2767                 /* illegal type */
2768                 return -EINVAL;
2769         }
2770
2771         size = posix_acl_xattr_size(count);
2772         if ((buflen == 0) || (local_acl == NULL)) {
2773                 /* used to query ACL EA size */
2774         } else if (size > buflen) {
2775                 return -ERANGE;
2776         } else /* buffer big enough */ {
2777                 local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
2778                 for (i = 0; i < count ; i++) {
2779                         cifs_convert_ace(&local_acl->a_entries[i], pACE);
2780                         pACE++;
2781                 }
2782         }
2783         return size;
2784 }
2785
2786 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace,
2787                                      const posix_acl_xattr_entry *local_ace)
2788 {
2789         __u16 rc = 0; /* 0 = ACL converted ok */
2790
2791         cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
2792         cifs_ace->cifs_e_tag =  le16_to_cpu(local_ace->e_tag);
2793         /* BB is there a better way to handle the large uid? */
2794         if (local_ace->e_id == cpu_to_le32(-1)) {
2795         /* Probably no need to le convert -1 on any arch but can not hurt */
2796                 cifs_ace->cifs_uid = cpu_to_le64(-1);
2797         } else
2798                 cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
2799         /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2800         return rc;
2801 }
2802
2803 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2804 static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
2805                                const int buflen, const int acl_type)
2806 {
2807         __u16 rc = 0;
2808         struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
2809         posix_acl_xattr_header *local_acl = (posix_acl_xattr_header *)pACL;
2810         int count;
2811         int i;
2812
2813         if ((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2814                 return 0;
2815
2816         count = posix_acl_xattr_count((size_t)buflen);
2817         cFYI(1, ("setting acl with %d entries from buf of length %d and "
2818                 "version of %d",
2819                 count, buflen, le32_to_cpu(local_acl->a_version)));
2820         if (le32_to_cpu(local_acl->a_version) != 2) {
2821                 cFYI(1, ("unknown POSIX ACL version %d",
2822                      le32_to_cpu(local_acl->a_version)));
2823                 return 0;
2824         }
2825         cifs_acl->version = cpu_to_le16(1);
2826         if (acl_type == ACL_TYPE_ACCESS)
2827                 cifs_acl->access_entry_count = cpu_to_le16(count);
2828         else if (acl_type == ACL_TYPE_DEFAULT)
2829                 cifs_acl->default_entry_count = cpu_to_le16(count);
2830         else {
2831                 cFYI(1, ("unknown ACL type %d", acl_type));
2832                 return 0;
2833         }
2834         for (i = 0; i < count; i++) {
2835                 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2836                                         &local_acl->a_entries[i]);
2837                 if (rc != 0) {
2838                         /* ACE not converted */
2839                         break;
2840                 }
2841         }
2842         if (rc == 0) {
2843                 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2844                 rc += sizeof(struct cifs_posix_acl);
2845                 /* BB add check to make sure ACL does not overflow SMB */
2846         }
2847         return rc;
2848 }
2849
2850 int
2851 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2852                    const unsigned char *searchName,
2853                    char *acl_inf, const int buflen, const int acl_type,
2854                    const struct nls_table *nls_codepage, int remap)
2855 {
2856 /* SMB_QUERY_POSIX_ACL */
2857         TRANSACTION2_QPI_REQ *pSMB = NULL;
2858         TRANSACTION2_QPI_RSP *pSMBr = NULL;
2859         int rc = 0;
2860         int bytes_returned;
2861         int name_len;
2862         __u16 params, byte_count;
2863
2864         cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2865
2866 queryAclRetry:
2867         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2868                 (void **) &pSMBr);
2869         if (rc)
2870                 return rc;
2871
2872         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2873                 name_len =
2874                         cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2875                                          PATH_MAX, nls_codepage, remap);
2876                 name_len++;     /* trailing null */
2877                 name_len *= 2;
2878                 pSMB->FileName[name_len] = 0;
2879                 pSMB->FileName[name_len+1] = 0;
2880         } else {        /* BB improve the check for buffer overruns BB */
2881                 name_len = strnlen(searchName, PATH_MAX);
2882                 name_len++;     /* trailing null */
2883                 strncpy(pSMB->FileName, searchName, name_len);
2884         }
2885
2886         params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
2887         pSMB->TotalDataCount = 0;
2888         pSMB->MaxParameterCount = cpu_to_le16(2);
2889         /* BB find exact max data count below from sess structure BB */
2890         pSMB->MaxDataCount = cpu_to_le16(4000);
2891         pSMB->MaxSetupCount = 0;
2892         pSMB->Reserved = 0;
2893         pSMB->Flags = 0;
2894         pSMB->Timeout = 0;
2895         pSMB->Reserved2 = 0;
2896         pSMB->ParameterOffset = cpu_to_le16(
2897                 offsetof(struct smb_com_transaction2_qpi_req,
2898                          InformationLevel) - 4);
2899         pSMB->DataCount = 0;
2900         pSMB->DataOffset = 0;
2901         pSMB->SetupCount = 1;
2902         pSMB->Reserved3 = 0;
2903         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2904         byte_count = params + 1 /* pad */ ;
2905         pSMB->TotalParameterCount = cpu_to_le16(params);
2906         pSMB->ParameterCount = pSMB->TotalParameterCount;
2907         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2908         pSMB->Reserved4 = 0;
2909         pSMB->hdr.smb_buf_length += byte_count;
2910         pSMB->ByteCount = cpu_to_le16(byte_count);
2911
2912         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2913                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2914         cifs_stats_inc(&tcon->num_acl_get);
2915         if (rc) {
2916                 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2917         } else {
2918                 /* decode response */
2919
2920                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2921                 if (rc || (pSMBr->ByteCount < 2))
2922                 /* BB also check enough total bytes returned */
2923                         rc = -EIO;      /* bad smb */
2924                 else {
2925                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2926                         __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2927                         rc = cifs_copy_posix_acl(acl_inf,
2928                                 (char *)&pSMBr->hdr.Protocol+data_offset,
2929                                 buflen, acl_type, count);
2930                 }
2931         }
2932         cifs_buf_release(pSMB);
2933         if (rc == -EAGAIN)
2934                 goto queryAclRetry;
2935         return rc;
2936 }
2937
2938 int
2939 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2940                    const unsigned char *fileName,
2941                    const char *local_acl, const int buflen,
2942                    const int acl_type,
2943                    const struct nls_table *nls_codepage, int remap)
2944 {
2945         struct smb_com_transaction2_spi_req *pSMB = NULL;
2946         struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2947         char *parm_data;
2948         int name_len;
2949         int rc = 0;
2950         int bytes_returned = 0;
2951         __u16 params, byte_count, data_count, param_offset, offset;
2952
2953         cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2954 setAclRetry:
2955         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2956                       (void **) &pSMBr);
2957         if (rc)
2958                 return rc;
2959         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2960                 name_len =
2961                         cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2962                                       PATH_MAX, nls_codepage, remap);
2963                 name_len++;     /* trailing null */
2964                 name_len *= 2;
2965         } else {        /* BB improve the check for buffer overruns BB */
2966                 name_len = strnlen(fileName, PATH_MAX);
2967                 name_len++;     /* trailing null */
2968                 strncpy(pSMB->FileName, fileName, name_len);
2969         }
2970         params = 6 + name_len;
2971         pSMB->MaxParameterCount = cpu_to_le16(2);
2972         /* BB find max SMB size from sess */
2973         pSMB->MaxDataCount = cpu_to_le16(1000);
2974         pSMB->MaxSetupCount = 0;
2975         pSMB->Reserved = 0;
2976         pSMB->Flags = 0;
2977         pSMB->Timeout = 0;
2978         pSMB->Reserved2 = 0;
2979         param_offset = offsetof(struct smb_com_transaction2_spi_req,
2980                                 InformationLevel) - 4;
2981         offset = param_offset + params;
2982         parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2983         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2984
2985         /* convert to on the wire format for POSIX ACL */
2986         data_count = ACL_to_cifs_posix(parm_data, local_acl, buflen, acl_type);
2987
2988         if (data_count == 0) {
2989                 rc = -EOPNOTSUPP;
2990                 goto setACLerrorExit;
2991         }
2992         pSMB->DataOffset = cpu_to_le16(offset);
2993         pSMB->SetupCount = 1;
2994         pSMB->Reserved3 = 0;
2995         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2996         pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2997         byte_count = 3 /* pad */  + params + data_count;
2998         pSMB->DataCount = cpu_to_le16(data_count);