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