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