smb2transport.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. /*
  2. * fs/cifs/smb2transport.c
  3. *
  4. * Copyright (C) International Business Machines Corp., 2002, 2011
  5. * Etersoft, 2012
  6. * Author(s): Steve French (sfrench@us.ibm.com)
  7. * Jeremy Allison (jra@samba.org) 2006
  8. * Pavel Shilovsky (pshilovsky@samba.org) 2012
  9. *
  10. * This library is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU Lesser General Public License as published
  12. * by the Free Software Foundation; either version 2.1 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * This library is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  18. * the GNU Lesser General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Lesser General Public License
  21. * along with this library; if not, write to the Free Software
  22. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  23. */
  24. #include <linux/fs.h>
  25. #include <linux/list.h>
  26. #include <linux/wait.h>
  27. #include <linux/net.h>
  28. #include <linux/delay.h>
  29. #include <linux/uaccess.h>
  30. #include <asm/processor.h>
  31. #include <linux/mempool.h>
  32. #include "smb2pdu.h"
  33. #include "cifsglob.h"
  34. #include "cifsproto.h"
  35. #include "smb2proto.h"
  36. #include "cifs_debug.h"
  37. #include "smb2status.h"
  38. /*
  39. * Set message id for the request. Should be called after wait_for_free_request
  40. * and when srv_mutex is held.
  41. */
  42. static inline void
  43. smb2_seq_num_into_buf(struct TCP_Server_Info *server, struct smb2_hdr *hdr)
  44. {
  45. hdr->MessageId = get_next_mid(server);
  46. }
  47. static struct mid_q_entry *
  48. smb2_mid_entry_alloc(const struct smb2_hdr *smb_buffer,
  49. struct TCP_Server_Info *server)
  50. {
  51. struct mid_q_entry *temp;
  52. if (server == NULL) {
  53. cERROR(1, "Null TCP session in smb2_mid_entry_alloc");
  54. return NULL;
  55. }
  56. temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);
  57. if (temp == NULL)
  58. return temp;
  59. else {
  60. memset(temp, 0, sizeof(struct mid_q_entry));
  61. temp->mid = smb_buffer->MessageId; /* always LE */
  62. temp->pid = current->pid;
  63. temp->command = smb_buffer->Command; /* Always LE */
  64. temp->when_alloc = jiffies;
  65. temp->server = server;
  66. /*
  67. * The default is for the mid to be synchronous, so the
  68. * default callback just wakes up the current task.
  69. */
  70. temp->callback = cifs_wake_up_task;
  71. temp->callback_data = current;
  72. }
  73. atomic_inc(&midCount);
  74. temp->mid_state = MID_REQUEST_ALLOCATED;
  75. return temp;
  76. }
  77. static int
  78. smb2_get_mid_entry(struct cifs_ses *ses, struct smb2_hdr *buf,
  79. struct mid_q_entry **mid)
  80. {
  81. if (ses->server->tcpStatus == CifsExiting)
  82. return -ENOENT;
  83. if (ses->server->tcpStatus == CifsNeedReconnect) {
  84. cFYI(1, "tcp session dead - return to caller to retry");
  85. return -EAGAIN;
  86. }
  87. if (ses->status != CifsGood) {
  88. /* check if SMB2 session is bad because we are setting it up */
  89. if ((buf->Command != SMB2_SESSION_SETUP) &&
  90. (buf->Command != SMB2_NEGOTIATE))
  91. return -EAGAIN;
  92. /* else ok - we are setting up session */
  93. }
  94. *mid = smb2_mid_entry_alloc(buf, ses->server);
  95. if (*mid == NULL)
  96. return -ENOMEM;
  97. spin_lock(&GlobalMid_Lock);
  98. list_add_tail(&(*mid)->qhead, &ses->server->pending_mid_q);
  99. spin_unlock(&GlobalMid_Lock);
  100. return 0;
  101. }
  102. int
  103. smb2_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
  104. bool log_error)
  105. {
  106. unsigned int len = get_rfc1002_length(mid->resp_buf);
  107. dump_smb(mid->resp_buf, min_t(u32, 80, len));
  108. /* convert the length into a more usable form */
  109. /* BB - uncomment with SMB2 signing implementation */
  110. /* if ((len > 24) &&
  111. (server->sec_mode & (SECMODE_SIGN_REQUIRED|SECMODE_SIGN_ENABLED))) {
  112. if (smb2_verify_signature(mid->resp_buf, server))
  113. cERROR(1, "Unexpected SMB signature");
  114. } */
  115. return map_smb2_to_linux_error(mid->resp_buf, log_error);
  116. }
  117. int
  118. smb2_setup_request(struct cifs_ses *ses, struct kvec *iov,
  119. unsigned int nvec, struct mid_q_entry **ret_mid)
  120. {
  121. int rc;
  122. struct smb2_hdr *hdr = (struct smb2_hdr *)iov[0].iov_base;
  123. struct mid_q_entry *mid;
  124. smb2_seq_num_into_buf(ses->server, hdr);
  125. rc = smb2_get_mid_entry(ses, hdr, &mid);
  126. if (rc)
  127. return rc;
  128. /* rc = smb2_sign_smb2(iov, nvec, ses->server);
  129. if (rc)
  130. delete_mid(mid); */
  131. *ret_mid = mid;
  132. return rc;
  133. }
  134. int
  135. smb2_setup_async_request(struct TCP_Server_Info *server, struct kvec *iov,
  136. unsigned int nvec, struct mid_q_entry **ret_mid)
  137. {
  138. int rc = 0;
  139. struct smb2_hdr *hdr = (struct smb2_hdr *)iov[0].iov_base;
  140. struct mid_q_entry *mid;
  141. smb2_seq_num_into_buf(server, hdr);
  142. mid = smb2_mid_entry_alloc(hdr, server);
  143. if (mid == NULL)
  144. return -ENOMEM;
  145. /* rc = smb2_sign_smb2(iov, nvec, server);
  146. if (rc) {
  147. DeleteMidQEntry(mid);
  148. return rc;
  149. }*/
  150. *ret_mid = mid;
  151. return rc;
  152. }