aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/connect.c
diff options
context:
space:
mode:
authorPavel Shilovsky <piastryyy@gmail.com>2011-08-01 05:19:42 -0400
committerSteve French <sfrench@us.ibm.com>2011-08-01 08:49:38 -0400
commit98bac62c9f1d6151dca7e8087aacce2e90fd43d3 (patch)
tree1ef0e1b118e05ca369aa77aa328e56016ae1dae4 /fs/cifs/connect.c
parente7015fb1c508fe9b8c97707755ce08f5ace0afb9 (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.c116
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
419static bool
420check_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
419static int 476static int
420cifs_demultiplex_thread(void *p) 477cifs_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) {