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