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