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