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