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