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