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