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