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