Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 262002
b: refs/heads/master
c: 98bac62
h: refs/heads/master
v: v3
  • Loading branch information
Pavel Shilovsky authored and Steve French committed Aug 1, 2011
1 parent 93ddad8 commit 01c4c88
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 50 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: e7015fb1c508fe9b8c97707755ce08f5ace0afb9
refs/heads/master: 98bac62c9f1d6151dca7e8087aacce2e90fd43d3
116 changes: 67 additions & 49 deletions trunk/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 01c4c88

Please sign in to comment.