diff options
author | Pavel Shilovsky <piastry@etersoft.ru> | 2011-12-26 13:53:34 -0500 |
---|---|---|
committer | Steve French <smfrench@gmail.com> | 2012-07-24 11:25:20 -0400 |
commit | 2dc7e1c03316940dec899fa3206a595de000e99b (patch) | |
tree | c74127806717b23e226b3ee81135d091d859bd7a /fs/cifs/smb2transport.c | |
parent | ddfbefbd393fb1a935bdf27cba5ad2eb24a76e75 (diff) |
CIFS: Make transport routines work with SMB2
Reviewed-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Pavel Shilovsky <piastry@etersoft.ru>
Signed-off-by: Steve French <smfrench@gmail.com>
Diffstat (limited to 'fs/cifs/smb2transport.c')
-rw-r--r-- | fs/cifs/smb2transport.c | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c new file mode 100644 index 00000000000..b4b6b9a6c0f --- /dev/null +++ b/fs/cifs/smb2transport.c | |||
@@ -0,0 +1,151 @@ | |||
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 | |||
25 | #include <linux/fs.h> | ||
26 | #include <linux/list.h> | ||
27 | #include <linux/wait.h> | ||
28 | #include <linux/net.h> | ||
29 | #include <linux/delay.h> | ||
30 | #include <linux/uaccess.h> | ||
31 | #include <asm/processor.h> | ||
32 | #include <linux/mempool.h> | ||
33 | #include "smb2pdu.h" | ||
34 | #include "cifsglob.h" | ||
35 | #include "cifsproto.h" | ||
36 | #include "smb2proto.h" | ||
37 | #include "cifs_debug.h" | ||
38 | #include "smb2status.h" | ||
39 | |||
40 | /* | ||
41 | * Set message id for the request. Should be called after wait_for_free_request | ||
42 | * and when srv_mutex is held. | ||
43 | */ | ||
44 | static inline void | ||
45 | smb2_seq_num_into_buf(struct TCP_Server_Info *server, struct smb2_hdr *hdr) | ||
46 | { | ||
47 | hdr->MessageId = get_next_mid(server); | ||
48 | } | ||
49 | |||
50 | static struct mid_q_entry * | ||
51 | smb2_mid_entry_alloc(const struct smb2_hdr *smb_buffer, | ||
52 | struct TCP_Server_Info *server) | ||
53 | { | ||
54 | struct mid_q_entry *temp; | ||
55 | |||
56 | if (server == NULL) { | ||
57 | cERROR(1, "Null TCP session in smb2_mid_entry_alloc"); | ||
58 | return NULL; | ||
59 | } | ||
60 | |||
61 | temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS); | ||
62 | if (temp == NULL) | ||
63 | return temp; | ||
64 | else { | ||
65 | memset(temp, 0, sizeof(struct mid_q_entry)); | ||
66 | temp->mid = smb_buffer->MessageId; /* always LE */ | ||
67 | temp->pid = current->pid; | ||
68 | temp->command = smb_buffer->Command; /* Always LE */ | ||
69 | temp->when_alloc = jiffies; | ||
70 | temp->server = server; | ||
71 | |||
72 | /* | ||
73 | * The default is for the mid to be synchronous, so the | ||
74 | * default callback just wakes up the current task. | ||
75 | */ | ||
76 | temp->callback = cifs_wake_up_task; | ||
77 | temp->callback_data = current; | ||
78 | } | ||
79 | |||
80 | atomic_inc(&midCount); | ||
81 | temp->mid_state = MID_REQUEST_ALLOCATED; | ||
82 | return temp; | ||
83 | } | ||
84 | |||
85 | static int | ||
86 | smb2_get_mid_entry(struct cifs_ses *ses, struct smb2_hdr *buf, | ||
87 | struct mid_q_entry **mid) | ||
88 | { | ||
89 | if (ses->server->tcpStatus == CifsExiting) | ||
90 | return -ENOENT; | ||
91 | |||
92 | if (ses->server->tcpStatus == CifsNeedReconnect) { | ||
93 | cFYI(1, "tcp session dead - return to caller to retry"); | ||
94 | return -EAGAIN; | ||
95 | } | ||
96 | |||
97 | if (ses->status != CifsGood) { | ||
98 | /* check if SMB2 session is bad because we are setting it up */ | ||
99 | if ((buf->Command != SMB2_SESSION_SETUP) && | ||
100 | (buf->Command != SMB2_NEGOTIATE)) | ||
101 | return -EAGAIN; | ||
102 | /* else ok - we are setting up session */ | ||
103 | } | ||
104 | *mid = smb2_mid_entry_alloc(buf, ses->server); | ||
105 | if (*mid == NULL) | ||
106 | return -ENOMEM; | ||
107 | spin_lock(&GlobalMid_Lock); | ||
108 | list_add_tail(&(*mid)->qhead, &ses->server->pending_mid_q); | ||
109 | spin_unlock(&GlobalMid_Lock); | ||
110 | return 0; | ||
111 | } | ||
112 | |||
113 | int | ||
114 | smb2_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server, | ||
115 | bool log_error) | ||
116 | { | ||
117 | unsigned int len = get_rfc1002_length(mid->resp_buf); | ||
118 | |||
119 | dump_smb(mid->resp_buf, min_t(u32, 80, len)); | ||
120 | /* convert the length into a more usable form */ | ||
121 | /* BB - uncomment with SMB2 signing implementation */ | ||
122 | /* if ((len > 24) && | ||
123 | (server->sec_mode & (SECMODE_SIGN_REQUIRED|SECMODE_SIGN_ENABLED))) { | ||
124 | if (smb2_verify_signature(mid->resp_buf, server)) | ||
125 | cERROR(1, "Unexpected SMB signature"); | ||
126 | } */ | ||
127 | |||
128 | return map_smb2_to_linux_error(mid->resp_buf, log_error); | ||
129 | } | ||
130 | |||
131 | int | ||
132 | smb2_setup_request(struct cifs_ses *ses, struct kvec *iov, | ||
133 | unsigned int nvec, struct mid_q_entry **ret_mid) | ||
134 | { | ||
135 | int rc; | ||
136 | struct smb2_hdr *hdr = (struct smb2_hdr *)iov[0].iov_base; | ||
137 | struct mid_q_entry *mid; | ||
138 | |||
139 | smb2_seq_num_into_buf(ses->server, hdr); | ||
140 | |||
141 | rc = smb2_get_mid_entry(ses, hdr, &mid); | ||
142 | if (rc) | ||
143 | return rc; | ||
144 | /* rc = smb2_sign_smb2(iov, nvec, ses->server); | ||
145 | if (rc) | ||
146 | delete_mid(mid); */ | ||
147 | *ret_mid = mid; | ||
148 | return rc; | ||
149 | } | ||
150 | |||
151 | /* BB add missing functions here */ | ||