diff options
author | Pavel Shilovsky <piastryyy@gmail.com> | 2011-08-01 05:19:42 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2011-08-01 08:49:38 -0400 |
commit | 98bac62c9f1d6151dca7e8087aacce2e90fd43d3 (patch) | |
tree | 1ef0e1b118e05ca369aa77aa328e56016ae1dae4 /fs/cifs/connect.c | |
parent | e7015fb1c508fe9b8c97707755ce08f5ace0afb9 (diff) |
CIFS: Move RFC1002 check to a separate function
Reviewed-and-Tested-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Pavel Shilovsky <piastryyy@gmail.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r-- | fs/cifs/connect.c | 116 |
1 files changed, 67 insertions, 49 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index a2e9fcf4a996..2a53ade3e637 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -416,6 +416,63 @@ read_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg, | |||
416 | return rc; | 416 | return rc; |
417 | } | 417 | } |
418 | 418 | ||
419 | static bool | ||
420 | check_rfc1002_header(struct TCP_Server_Info *server, char *buf) | ||
421 | { | ||
422 | char temp = *buf; | ||
423 | unsigned int pdu_length = be32_to_cpu( | ||
424 | ((struct smb_hdr *)buf)->smb_buf_length); | ||
425 | |||
426 | /* | ||
427 | * The first byte big endian of the length field, | ||
428 | * is actually not part of the length but the type | ||
429 | * with the most common, zero, as regular data. | ||
430 | */ | ||
431 | if (temp == (char) RFC1002_SESSION_KEEP_ALIVE) { | ||
432 | return false; | ||
433 | } else if (temp == (char)RFC1002_POSITIVE_SESSION_RESPONSE) { | ||
434 | cFYI(1, "Good RFC 1002 session rsp"); | ||
435 | return false; | ||
436 | } else if (temp == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) { | ||
437 | /* | ||
438 | * We get this from Windows 98 instead of an error on | ||
439 | * SMB negprot response. | ||
440 | */ | ||
441 | cFYI(1, "Negative RFC1002 Session Response Error 0x%x)", | ||
442 | pdu_length); | ||
443 | /* give server a second to clean up */ | ||
444 | msleep(1000); | ||
445 | /* | ||
446 | * Always try 445 first on reconnect since we get NACK | ||
447 | * on some if we ever connected to port 139 (the NACK | ||
448 | * is since we do not begin with RFC1001 session | ||
449 | * initialize frame). | ||
450 | */ | ||
451 | cifs_set_port((struct sockaddr *) | ||
452 | &server->dstaddr, CIFS_PORT); | ||
453 | cifs_reconnect(server); | ||
454 | wake_up(&server->response_q); | ||
455 | return false; | ||
456 | } else if (temp != (char) 0) { | ||
457 | cERROR(1, "Unknown RFC 1002 frame"); | ||
458 | cifs_dump_mem(" Received Data: ", buf, 4); | ||
459 | cifs_reconnect(server); | ||
460 | return false; | ||
461 | } | ||
462 | |||
463 | /* else we have an SMB response */ | ||
464 | if ((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) || | ||
465 | (pdu_length < sizeof(struct smb_hdr) - 1 - 4)) { | ||
466 | cERROR(1, "Invalid size SMB length %d pdu_length %d", | ||
467 | 4, pdu_length+4); | ||
468 | cifs_reconnect(server); | ||
469 | wake_up(&server->response_q); | ||
470 | return false; | ||
471 | } | ||
472 | |||
473 | return true; | ||
474 | } | ||
475 | |||
419 | static int | 476 | static int |
420 | cifs_demultiplex_thread(void *p) | 477 | cifs_demultiplex_thread(void *p) |
421 | { | 478 | { |
@@ -429,7 +486,6 @@ cifs_demultiplex_thread(void *p) | |||
429 | struct list_head *tmp, *tmp2; | 486 | struct list_head *tmp, *tmp2; |
430 | struct task_struct *task_to_wake = NULL; | 487 | struct task_struct *task_to_wake = NULL; |
431 | struct mid_q_entry *mid_entry; | 488 | struct mid_q_entry *mid_entry; |
432 | char temp; | ||
433 | bool isLargeBuf = false; | 489 | bool isLargeBuf = false; |
434 | bool isMultiRsp; | 490 | bool isMultiRsp; |
435 | int rc; | 491 | int rc; |
@@ -482,59 +538,21 @@ incomplete_rcv: | |||
482 | else if (rc == 1) | 538 | else if (rc == 1) |
483 | continue; | 539 | continue; |
484 | 540 | ||
485 | /* The right amount was read from socket - 4 bytes */ | 541 | /* |
486 | /* so we can now interpret the length field */ | 542 | * The right amount was read from socket - 4 bytes, |
487 | 543 | * so we can now interpret the length field. | |
488 | /* the first byte big endian of the length field, | 544 | */ |
489 | is actually not part of the length but the type | ||
490 | with the most common, zero, as regular data */ | ||
491 | temp = *buf; | ||
492 | 545 | ||
493 | /* Note that FC 1001 length is big endian on the wire, | 546 | /* |
494 | but we convert it here so it is always manipulated | 547 | * Note that RFC 1001 length is big endian on the wire, |
495 | as host byte order */ | 548 | * but we convert it here so it is always manipulated |
549 | * as host byte order. | ||
550 | */ | ||
496 | pdu_length = be32_to_cpu(smb_buffer->smb_buf_length); | 551 | pdu_length = be32_to_cpu(smb_buffer->smb_buf_length); |
497 | 552 | ||
498 | cFYI(1, "rfc1002 length 0x%x", pdu_length+4); | 553 | cFYI(1, "rfc1002 length 0x%x", pdu_length+4); |
499 | 554 | if (!check_rfc1002_header(server, buf)) | |
500 | if (temp == (char) RFC1002_SESSION_KEEP_ALIVE) { | ||
501 | continue; | ||
502 | } else if (temp == (char)RFC1002_POSITIVE_SESSION_RESPONSE) { | ||
503 | cFYI(1, "Good RFC 1002 session rsp"); | ||
504 | continue; | ||
505 | } else if (temp == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) { | ||
506 | /* we get this from Windows 98 instead of | ||
507 | an error on SMB negprot response */ | ||
508 | cFYI(1, "Negative RFC1002 Session Response Error 0x%x)", | ||
509 | pdu_length); | ||
510 | /* give server a second to clean up */ | ||
511 | msleep(1000); | ||
512 | /* always try 445 first on reconnect since we get NACK | ||
513 | * on some if we ever connected to port 139 (the NACK | ||
514 | * is since we do not begin with RFC1001 session | ||
515 | * initialize frame) | ||
516 | */ | ||
517 | cifs_set_port((struct sockaddr *) | ||
518 | &server->dstaddr, CIFS_PORT); | ||
519 | cifs_reconnect(server); | ||
520 | wake_up(&server->response_q); | ||
521 | continue; | ||
522 | } else if (temp != (char) 0) { | ||
523 | cERROR(1, "Unknown RFC 1002 frame"); | ||
524 | cifs_dump_mem(" Received Data: ", buf, length); | ||
525 | cifs_reconnect(server); | ||
526 | continue; | ||
527 | } | ||
528 | |||
529 | /* else we have an SMB response */ | ||
530 | if ((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) || | ||
531 | (pdu_length < sizeof(struct smb_hdr) - 1 - 4)) { | ||
532 | cERROR(1, "Invalid size SMB length %d pdu_length %d", | ||
533 | length, pdu_length+4); | ||
534 | cifs_reconnect(server); | ||
535 | wake_up(&server->response_q); | ||
536 | continue; | 555 | continue; |
537 | } | ||
538 | 556 | ||
539 | /* else length ok */ | 557 | /* else length ok */ |
540 | if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) { | 558 | if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) { |