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