Commit de050bec authored by Niels Möller's avatar Niels Möller
Browse files

* src/channel.c (receive_data_common): New function, with

processing and checks common for handle_channel_data and
handle_channel_extended_data. Invoke CHANNEL_RECEIVE with length
and pointer, avoiding allocation fo an extra copy.
(handle_channel_data, handle_channel_extended_data): Use it.

Rev: src/channel.c:1.125.2.11
parent 7e53eac2
...@@ -939,67 +939,76 @@ handle_adjust_window(struct ssh_connection *connection, ...@@ -939,67 +939,76 @@ handle_adjust_window(struct ssh_connection *connection,
SSH_CONNECTION_ERROR(connection, "Invalid CHANNEL_WINDOW_ADJUST message."); SSH_CONNECTION_ERROR(connection, "Invalid CHANNEL_WINDOW_ADJUST message.");
} }
/* FIXME: Pass length, pointer to receive, to avoid unnecessary /* Common processing for ordinary and "extended" data. */
allocation and copying. */ static int
receive_data_common(struct ssh_channel *channel,
int type, uint32_t length, const uint8_t *data)
{
if (channel->receive
&& !(channel->flags & (CHANNEL_RECEIVED_EOF
| CHANNEL_RECEIVED_CLOSE)))
{
if (channel->flags & CHANNEL_SENT_CLOSE)
{
werror("Ignoring data on channel which is closing\n");
return 1;
}
else
{
if (length > channel->rec_max_packet)
{
werror("Channel data larger than rec_max_packet. Extra data ignored.\n");
length = channel->rec_max_packet;
}
if (length > channel->rec_window_size)
{
/* Truncate data to fit window */
werror("Channel data overflow. Extra data ignored.\n");
debug(" (type = %i, data->length=%i, rec_window_size=%i).\n",
type, length, channel->rec_window_size);
length = channel->rec_window_size;
}
if (!length)
{
/* Ignore data packet */
return 1;
}
channel->rec_window_size -= length;
CHANNEL_RECEIVE(channel, type, length, data);
}
return 1;
}
else
return 0;
}
static void static void
handle_channel_data(struct ssh_connection *connection, handle_channel_data(struct ssh_connection *connection,
struct simple_buffer *buffer) struct simple_buffer *buffer)
{ {
uint32_t channel_number; uint32_t channel_number;
struct lsh_string *data; uint32_t length;
const uint8_t *data;
if (parse_uint32(buffer, &channel_number) if (parse_uint32(buffer, &channel_number)
&& ( (data = parse_string_copy(buffer)) ) && parse_string(buffer, &length, &data)
&& parse_eod(buffer)) && parse_eod(buffer))
{ {
struct ssh_channel *channel = lookup_channel(connection, channel_number); struct ssh_channel *channel
= lookup_channel(connection, channel_number);
if (channel && channel->receive if (channel)
&& !(channel->flags & (CHANNEL_RECEIVED_EOF
| CHANNEL_RECEIVED_CLOSE)))
{ {
if (channel->flags & CHANNEL_SENT_CLOSE) if (!receive_data_common(channel, CHANNEL_DATA,
{ length, data))
lsh_string_free(data); werror("Data on closed channel %i\n", channel_number);
werror("Ignoring data on channel which is closing\n");
return;
}
else
{
uint32_t length = lsh_string_length(data);
if (length > channel->rec_max_packet)
{
werror("Channel data larger than rec_max_packet. Extra data ignored.\n");
lsh_string_trunc(data, channel->rec_max_packet);
}
if (length > channel->rec_window_size)
{
/* Truncate data to fit window */
werror("Channel data overflow. Extra data ignored.\n");
debug(" (data->length=%i, rec_window_size=%i).\n",
length, channel->rec_window_size);
lsh_string_trunc(data, channel->rec_window_size);
}
if (!length)
{
/* Ignore data packet */
lsh_string_free(data);
return;
}
channel->rec_window_size -= length;
CHANNEL_RECEIVE(channel, CHANNEL_DATA, data);
}
} }
else else
{ werror("Data on non-existant channel %i\n", channel_number);
werror("Data on closed or non-existant channel %i\n",
channel_number);
lsh_string_free(data);
}
} }
else else
SSH_CONNECTION_ERROR(connection, "Invalid CHANNEL_DATA message."); SSH_CONNECTION_ERROR(connection, "Invalid CHANNEL_DATA message.");
...@@ -1011,75 +1020,32 @@ handle_channel_extended_data(struct ssh_connection *connection, ...@@ -1011,75 +1020,32 @@ handle_channel_extended_data(struct ssh_connection *connection,
{ {
uint32_t channel_number; uint32_t channel_number;
uint32_t type; uint32_t type;
struct lsh_string *data; uint32_t length;
const uint8_t *data;
if (parse_uint32(buffer, &channel_number) if (parse_uint32(buffer, &channel_number)
&& parse_uint32(buffer, &type) && parse_uint32(buffer, &type)
&& ( (data = parse_string_copy(buffer)) ) && parse_string(buffer, &length, &data)
&& parse_eod(buffer)) && parse_eod(buffer))
{ {
struct ssh_channel *channel = lookup_channel(connection, channel_number); struct ssh_channel *channel
= lookup_channel(connection, channel_number);
if (channel && channel->receive
&& !(channel->flags & (CHANNEL_RECEIVED_EOF if (channel)
| CHANNEL_RECEIVED_CLOSE)))
{ {
if (channel->flags & CHANNEL_SENT_CLOSE) if (type != SSH_EXTENDED_DATA_STDERR)
{ werror("Unknown type %i of extended data.\n", type);
lsh_string_free(data);
werror("Ignoring extended data on channel which is closing\n"); else if (!receive_data_common(channel, CHANNEL_STDERR_DATA,
return; length, data))
} werror("Extended data on closed channel %i\n", channel_number);
else }
{
uint32_t length = lsh_string_length(data);
if (length > channel->rec_max_packet)
{
werror("Channel data larger than rec_max_packet. Extra data ignored.\n");
lsh_string_trunc(data, channel->rec_max_packet);
}
if (length > channel->rec_window_size)
{
/* Truncate data to fit window */
werror("Channel extended data overflow. "
"Extra data ignored.\n");
debug(" (data->length=%i, rec_window_size=%i).\n",
length, channel->rec_window_size);
lsh_string_trunc(data, channel->rec_window_size);
}
if (!length)
{
/* Ignore data packet */
lsh_string_free(data);
return;
}
channel->rec_window_size -= length;
switch(type)
{
case SSH_EXTENDED_DATA_STDERR:
CHANNEL_RECEIVE(channel, CHANNEL_STDERR_DATA, data);
break;
default:
werror("Unknown type %i of extended data.\n",
type);
lsh_string_free(data);
}
}
}
else else
{ werror("Extended data on non-existant channel %i\n", channel_number);
werror("Extended data on closed or non-existant channel %i\n",
channel_number);
lsh_string_free(data);
}
} }
else else
SSH_CONNECTION_ERROR(connection, "Invalid CHANNEL_EXTENDED_DATA message."); SSH_CONNECTION_ERROR(connection,
"Invalid CHANNEL_EXTENDED_DATA message.");
} }
static void static void
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment