Skip to content

Commit

Permalink
CIFS: Move RFC1002 check to a separate function
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Pavel Shilovsky authored and Steve French committed Aug 1, 2011
1 parent e7015fb commit 98bac62
Showing 1 changed file with 67 additions and 49 deletions.
116 changes: 67 additions & 49 deletions fs/cifs/connect.c
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,63 @@ read_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg,
return rc;
}

static bool
check_rfc1002_header(struct TCP_Server_Info *server, char *buf)
{
char temp = *buf;
unsigned int pdu_length = be32_to_cpu(
((struct smb_hdr *)buf)->smb_buf_length);

/*
* The first byte big endian of the length field,
* is actually not part of the length but the type
* with the most common, zero, as regular data.
*/
if (temp == (char) RFC1002_SESSION_KEEP_ALIVE) {
return false;
} else if (temp == (char)RFC1002_POSITIVE_SESSION_RESPONSE) {
cFYI(1, "Good RFC 1002 session rsp");
return false;
} else if (temp == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
/*
* We get this from Windows 98 instead of an error on
* SMB negprot response.
*/
cFYI(1, "Negative RFC1002 Session Response Error 0x%x)",
pdu_length);
/* give server a second to clean up */
msleep(1000);
/*
* Always try 445 first on reconnect since we get NACK
* on some if we ever connected to port 139 (the NACK
* is since we do not begin with RFC1001 session
* initialize frame).
*/
cifs_set_port((struct sockaddr *)
&server->dstaddr, CIFS_PORT);
cifs_reconnect(server);
wake_up(&server->response_q);
return false;
} else if (temp != (char) 0) {
cERROR(1, "Unknown RFC 1002 frame");
cifs_dump_mem(" Received Data: ", buf, 4);
cifs_reconnect(server);
return false;
}

/* else we have an SMB response */
if ((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) ||
(pdu_length < sizeof(struct smb_hdr) - 1 - 4)) {
cERROR(1, "Invalid size SMB length %d pdu_length %d",
4, pdu_length+4);
cifs_reconnect(server);
wake_up(&server->response_q);
return false;
}

return true;
}

static int
cifs_demultiplex_thread(void *p)
{
Expand All @@ -429,7 +486,6 @@ cifs_demultiplex_thread(void *p)
struct list_head *tmp, *tmp2;
struct task_struct *task_to_wake = NULL;
struct mid_q_entry *mid_entry;
char temp;
bool isLargeBuf = false;
bool isMultiRsp;
int rc;
Expand Down Expand Up @@ -482,59 +538,21 @@ cifs_demultiplex_thread(void *p)
else if (rc == 1)
continue;

/* The right amount was read from socket - 4 bytes */
/* so we can now interpret the length field */

/* the first byte big endian of the length field,
is actually not part of the length but the type
with the most common, zero, as regular data */
temp = *buf;
/*
* The right amount was read from socket - 4 bytes,
* so we can now interpret the length field.
*/

/* Note that FC 1001 length is big endian on the wire,
but we convert it here so it is always manipulated
as host byte order */
/*
* Note that RFC 1001 length is big endian on the wire,
* but we convert it here so it is always manipulated
* as host byte order.
*/
pdu_length = be32_to_cpu(smb_buffer->smb_buf_length);

cFYI(1, "rfc1002 length 0x%x", pdu_length+4);

if (temp == (char) RFC1002_SESSION_KEEP_ALIVE) {
continue;
} else if (temp == (char)RFC1002_POSITIVE_SESSION_RESPONSE) {
cFYI(1, "Good RFC 1002 session rsp");
continue;
} else if (temp == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
/* we get this from Windows 98 instead of
an error on SMB negprot response */
cFYI(1, "Negative RFC1002 Session Response Error 0x%x)",
pdu_length);
/* give server a second to clean up */
msleep(1000);
/* always try 445 first on reconnect since we get NACK
* on some if we ever connected to port 139 (the NACK
* is since we do not begin with RFC1001 session
* initialize frame)
*/
cifs_set_port((struct sockaddr *)
&server->dstaddr, CIFS_PORT);
cifs_reconnect(server);
wake_up(&server->response_q);
continue;
} else if (temp != (char) 0) {
cERROR(1, "Unknown RFC 1002 frame");
cifs_dump_mem(" Received Data: ", buf, length);
cifs_reconnect(server);
continue;
}

/* else we have an SMB response */
if ((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) ||
(pdu_length < sizeof(struct smb_hdr) - 1 - 4)) {
cERROR(1, "Invalid size SMB length %d pdu_length %d",
length, pdu_length+4);
cifs_reconnect(server);
wake_up(&server->response_q);
if (!check_rfc1002_header(server, buf))
continue;
}

/* else length ok */
if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
Expand Down

0 comments on commit 98bac62

Please sign in to comment.