diff options
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/cifsglob.h | 9 | ||||
-rw-r--r-- | fs/cifs/connect.c | 5 | ||||
-rw-r--r-- | fs/cifs/smb2ops.c | 19 | ||||
-rw-r--r-- | fs/cifs/smb2pdu.c | 40 | ||||
-rw-r--r-- | fs/cifs/smb2pdu.h | 12 |
5 files changed, 56 insertions, 29 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index f6f40635abca..f5af2527fc69 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -179,6 +179,7 @@ struct smb_rqst { | |||
179 | enum smb_version { | 179 | enum smb_version { |
180 | Smb_1 = 1, | 180 | Smb_1 = 1, |
181 | Smb_21, | 181 | Smb_21, |
182 | Smb_30, | ||
182 | }; | 183 | }; |
183 | 184 | ||
184 | struct mid_q_entry; | 185 | struct mid_q_entry; |
@@ -372,6 +373,8 @@ struct smb_version_operations { | |||
372 | 373 | ||
373 | struct smb_version_values { | 374 | struct smb_version_values { |
374 | char *version_string; | 375 | char *version_string; |
376 | __u16 protocol_id; | ||
377 | __u32 req_capabilities; | ||
375 | __u32 large_lock_type; | 378 | __u32 large_lock_type; |
376 | __u32 exclusive_lock_type; | 379 | __u32 exclusive_lock_type; |
377 | __u32 shared_lock_type; | 380 | __u32 shared_lock_type; |
@@ -1496,7 +1499,13 @@ extern mempool_t *cifs_mid_poolp; | |||
1496 | #define SMB1_VERSION_STRING "1.0" | 1499 | #define SMB1_VERSION_STRING "1.0" |
1497 | extern struct smb_version_operations smb1_operations; | 1500 | extern struct smb_version_operations smb1_operations; |
1498 | extern struct smb_version_values smb1_values; | 1501 | extern struct smb_version_values smb1_values; |
1502 | #define SMB20_VERSION_STRING "2.0" | ||
1503 | /*extern struct smb_version_operations smb20_operations; */ /* not needed yet */ | ||
1504 | extern struct smb_version_values smb20_values; | ||
1499 | #define SMB21_VERSION_STRING "2.1" | 1505 | #define SMB21_VERSION_STRING "2.1" |
1500 | extern struct smb_version_operations smb21_operations; | 1506 | extern struct smb_version_operations smb21_operations; |
1501 | extern struct smb_version_values smb21_values; | 1507 | extern struct smb_version_values smb21_values; |
1508 | #define SMB30_VERSION_STRING "3.0" | ||
1509 | /*extern struct smb_version_operations smb30_operations; */ /* not needed yet */ | ||
1510 | extern struct smb_version_values smb30_values; | ||
1502 | #endif /* _CIFS_GLOB_H */ | 1511 | #endif /* _CIFS_GLOB_H */ |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index a792282f02f7..2fdbe08a7a23 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -272,6 +272,7 @@ static const match_table_t cifs_cacheflavor_tokens = { | |||
272 | static const match_table_t cifs_smb_version_tokens = { | 272 | static const match_table_t cifs_smb_version_tokens = { |
273 | { Smb_1, SMB1_VERSION_STRING }, | 273 | { Smb_1, SMB1_VERSION_STRING }, |
274 | { Smb_21, SMB21_VERSION_STRING }, | 274 | { Smb_21, SMB21_VERSION_STRING }, |
275 | { Smb_30, SMB30_VERSION_STRING }, | ||
275 | }; | 276 | }; |
276 | 277 | ||
277 | static int ip_connect(struct TCP_Server_Info *server); | 278 | static int ip_connect(struct TCP_Server_Info *server); |
@@ -1074,6 +1075,10 @@ cifs_parse_smb_version(char *value, struct smb_vol *vol) | |||
1074 | vol->ops = &smb21_operations; | 1075 | vol->ops = &smb21_operations; |
1075 | vol->vals = &smb21_values; | 1076 | vol->vals = &smb21_values; |
1076 | break; | 1077 | break; |
1078 | case Smb_30: | ||
1079 | vol->ops = &smb21_operations; /* currently identical with 2.1 */ | ||
1080 | vol->vals = &smb30_values; | ||
1081 | break; | ||
1077 | #endif | 1082 | #endif |
1078 | default: | 1083 | default: |
1079 | cERROR(1, "Unknown vers= option specified: %s", value); | 1084 | cERROR(1, "Unknown vers= option specified: %s", value); |
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index 1570cbea4a49..4d9dbe0b7385 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c | |||
@@ -645,6 +645,25 @@ struct smb_version_operations smb21_operations = { | |||
645 | 645 | ||
646 | struct smb_version_values smb21_values = { | 646 | struct smb_version_values smb21_values = { |
647 | .version_string = SMB21_VERSION_STRING, | 647 | .version_string = SMB21_VERSION_STRING, |
648 | .protocol_id = SMB21_PROT_ID, | ||
649 | .req_capabilities = 0, /* MBZ on negotiate req until SMB3 dialect */ | ||
650 | .large_lock_type = 0, | ||
651 | .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK, | ||
652 | .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK, | ||
653 | .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK, | ||
654 | .header_size = sizeof(struct smb2_hdr), | ||
655 | .max_header_size = MAX_SMB2_HDR_SIZE, | ||
656 | .read_rsp_size = sizeof(struct smb2_read_rsp) - 1, | ||
657 | .lock_cmd = SMB2_LOCK, | ||
658 | .cap_unix = 0, | ||
659 | .cap_nt_find = SMB2_NT_FIND, | ||
660 | .cap_large_files = SMB2_LARGE_FILES, | ||
661 | }; | ||
662 | |||
663 | struct smb_version_values smb30_values = { | ||
664 | .version_string = SMB30_VERSION_STRING, | ||
665 | .protocol_id = SMB30_PROT_ID, | ||
666 | .req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU, | ||
648 | .large_lock_type = 0, | 667 | .large_lock_type = 0, |
649 | .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK, | 668 | .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK, |
650 | .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK, | 669 | .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK, |
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 5ad88b4b9990..cf33622cdac8 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * fs/cifs/smb2pdu.c | 2 | * fs/cifs/smb2pdu.c |
3 | * | 3 | * |
4 | * Copyright (C) International Business Machines Corp., 2009, 2011 | 4 | * Copyright (C) International Business Machines Corp., 2009, 2012 |
5 | * Etersoft, 2012 | 5 | * Etersoft, 2012 |
6 | * Author(s): Steve French (sfrench@us.ibm.com) | 6 | * Author(s): Steve French (sfrench@us.ibm.com) |
7 | * Pavel Shilovsky (pshilovsky@samba.org) 2012 | 7 | * Pavel Shilovsky (pshilovsky@samba.org) 2012 |
@@ -304,24 +304,6 @@ free_rsp_buf(int resp_buftype, void *rsp) | |||
304 | cifs_buf_release(rsp); | 304 | cifs_buf_release(rsp); |
305 | } | 305 | } |
306 | 306 | ||
307 | #define SMB2_NUM_PROT 2 | ||
308 | |||
309 | #define SMB2_PROT 0 | ||
310 | #define SMB21_PROT 1 | ||
311 | #define BAD_PROT 0xFFFF | ||
312 | |||
313 | #define SMB2_PROT_ID 0x0202 | ||
314 | #define SMB21_PROT_ID 0x0210 | ||
315 | #define BAD_PROT_ID 0xFFFF | ||
316 | |||
317 | static struct { | ||
318 | int index; | ||
319 | __le16 name; | ||
320 | } smb2protocols[] = { | ||
321 | {SMB2_PROT, cpu_to_le16(SMB2_PROT_ID)}, | ||
322 | {SMB21_PROT, cpu_to_le16(SMB21_PROT_ID)}, | ||
323 | {BAD_PROT, cpu_to_le16(BAD_PROT_ID)} | ||
324 | }; | ||
325 | 307 | ||
326 | /* | 308 | /* |
327 | * | 309 | * |
@@ -348,7 +330,6 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) | |||
348 | int resp_buftype; | 330 | int resp_buftype; |
349 | struct TCP_Server_Info *server; | 331 | struct TCP_Server_Info *server; |
350 | unsigned int sec_flags; | 332 | unsigned int sec_flags; |
351 | u16 i; | ||
352 | u16 temp = 0; | 333 | u16 temp = 0; |
353 | int blob_offset, blob_length; | 334 | int blob_offset, blob_length; |
354 | char *security_blob; | 335 | char *security_blob; |
@@ -377,11 +358,10 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) | |||
377 | 358 | ||
378 | req->hdr.SessionId = 0; | 359 | req->hdr.SessionId = 0; |
379 | 360 | ||
380 | for (i = 0; i < SMB2_NUM_PROT; i++) | 361 | req->Dialects[0] = cpu_to_le16(ses->server->vals->protocol_id); |
381 | req->Dialects[i] = smb2protocols[i].name; | ||
382 | 362 | ||
383 | req->DialectCount = cpu_to_le16(i); | 363 | req->DialectCount = cpu_to_le16(1); /* One vers= at a time for now */ |
384 | inc_rfc1001_len(req, i * 2); | 364 | inc_rfc1001_len(req, 2); |
385 | 365 | ||
386 | /* only one of SMB2 signing flags may be set in SMB2 request */ | 366 | /* only one of SMB2 signing flags may be set in SMB2 request */ |
387 | if ((sec_flags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) | 367 | if ((sec_flags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) |
@@ -391,7 +371,7 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) | |||
391 | 371 | ||
392 | req->SecurityMode = cpu_to_le16(temp); | 372 | req->SecurityMode = cpu_to_le16(temp); |
393 | 373 | ||
394 | req->Capabilities = cpu_to_le32(SMB2_GLOBAL_CAP_DFS); | 374 | req->Capabilities = cpu_to_le32(ses->server->vals->req_capabilities); |
395 | 375 | ||
396 | memcpy(req->ClientGUID, cifs_client_guid, SMB2_CLIENT_GUID_SIZE); | 376 | memcpy(req->ClientGUID, cifs_client_guid, SMB2_CLIENT_GUID_SIZE); |
397 | 377 | ||
@@ -411,10 +391,14 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) | |||
411 | 391 | ||
412 | cFYI(1, "mode 0x%x", rsp->SecurityMode); | 392 | cFYI(1, "mode 0x%x", rsp->SecurityMode); |
413 | 393 | ||
414 | if (rsp->DialectRevision == smb2protocols[SMB21_PROT].name) | 394 | /* BB we may eventually want to match the negotiated vs. requested |
395 | dialect, even though we are only requesting one at a time */ | ||
396 | if (rsp->DialectRevision == cpu_to_le16(SMB20_PROT_ID)) | ||
397 | cFYI(1, "negotiated smb2.0 dialect"); | ||
398 | else if (rsp->DialectRevision == cpu_to_le16(SMB21_PROT_ID)) | ||
415 | cFYI(1, "negotiated smb2.1 dialect"); | 399 | cFYI(1, "negotiated smb2.1 dialect"); |
416 | else if (rsp->DialectRevision == smb2protocols[SMB2_PROT].name) | 400 | else if (rsp->DialectRevision == cpu_to_le16(SMB30_PROT_ID)) |
417 | cFYI(1, "negotiated smb2 dialect"); | 401 | cFYI(1, "negotiated smb3.0 dialect"); |
418 | else { | 402 | else { |
419 | cERROR(1, "Illegal dialect returned by server %d", | 403 | cERROR(1, "Illegal dialect returned by server %d", |
420 | le16_to_cpu(rsp->DialectRevision)); | 404 | le16_to_cpu(rsp->DialectRevision)); |
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h index da099225b1a9..4cb4ced258cb 100644 --- a/fs/cifs/smb2pdu.h +++ b/fs/cifs/smb2pdu.h | |||
@@ -163,9 +163,15 @@ struct smb2_negotiate_req { | |||
163 | __le32 Capabilities; | 163 | __le32 Capabilities; |
164 | __u8 ClientGUID[SMB2_CLIENT_GUID_SIZE]; | 164 | __u8 ClientGUID[SMB2_CLIENT_GUID_SIZE]; |
165 | __le64 ClientStartTime; /* MBZ */ | 165 | __le64 ClientStartTime; /* MBZ */ |
166 | __le16 Dialects[2]; /* variable length */ | 166 | __le16 Dialects[1]; /* One dialect (vers=) at a time for now */ |
167 | } __packed; | 167 | } __packed; |
168 | 168 | ||
169 | /* Dialects */ | ||
170 | #define SMB20_PROT_ID 0x0202 | ||
171 | #define SMB21_PROT_ID 0x0210 | ||
172 | #define SMB30_PROT_ID 0x0300 | ||
173 | #define BAD_PROT_ID 0xFFFF | ||
174 | |||
169 | /* SecurityMode flags */ | 175 | /* SecurityMode flags */ |
170 | #define SMB2_NEGOTIATE_SIGNING_ENABLED 0x0001 | 176 | #define SMB2_NEGOTIATE_SIGNING_ENABLED 0x0001 |
171 | #define SMB2_NEGOTIATE_SIGNING_REQUIRED 0x0002 | 177 | #define SMB2_NEGOTIATE_SIGNING_REQUIRED 0x0002 |
@@ -173,6 +179,10 @@ struct smb2_negotiate_req { | |||
173 | #define SMB2_GLOBAL_CAP_DFS 0x00000001 | 179 | #define SMB2_GLOBAL_CAP_DFS 0x00000001 |
174 | #define SMB2_GLOBAL_CAP_LEASING 0x00000002 /* Resp only New to SMB2.1 */ | 180 | #define SMB2_GLOBAL_CAP_LEASING 0x00000002 /* Resp only New to SMB2.1 */ |
175 | #define SMB2_GLOBAL_CAP_LARGE_MTU 0X00000004 /* Resp only New to SMB2.1 */ | 181 | #define SMB2_GLOBAL_CAP_LARGE_MTU 0X00000004 /* Resp only New to SMB2.1 */ |
182 | #define SMB2_GLOBAL_CAP_MULTI_CHANNEL 0x00000008 /* New to SMB3 */ | ||
183 | #define SMB2_GLOBAL_CAP_PERSISTENT_HANDLES 0x00000010 /* New to SMB3 */ | ||
184 | #define SMB2_GLOBAL_CAP_DIRECTORY_LEASING 0x00000020 /* New to SMB3 */ | ||
185 | #define SMB2_GLOBAL_CAP_ENCRYPTION 0x00000040 /* New to SMB3 */ | ||
176 | /* Internal types */ | 186 | /* Internal types */ |
177 | #define SMB2_NT_FIND 0x00100000 | 187 | #define SMB2_NT_FIND 0x00100000 |
178 | #define SMB2_LARGE_FILES 0x00200000 | 188 | #define SMB2_LARGE_FILES 0x00200000 |