aboutsummaryrefslogtreecommitdiff
path: root/src/or/control.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2005-04-27 22:01:34 +0000
committerNick Mathewson <nickm@torproject.org>2005-04-27 22:01:34 +0000
commitfe65e57ca128e86d17bb5f624da7120ca8cf480c (patch)
treeaca5e95c99015167e46d52bed04bf5ae33753c20 /src/or/control.c
parent02546857d2c0e89e4b94cbeab088341f637318c6 (diff)
downloadtor-fe65e57ca128e86d17bb5f624da7120ca8cf480c.tar
tor-fe65e57ca128e86d17bb5f624da7120ca8cf480c.tar.gz
Re-do fragmented control message handling to work with new buf_t system.
svn:r4144
Diffstat (limited to 'src/or/control.c')
-rw-r--r--src/or/control.c57
1 files changed, 57 insertions, 0 deletions
diff --git a/src/or/control.c b/src/or/control.c
index 59dc68a02..32ccbf596 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -923,6 +923,46 @@ handle_control_closecircuit(connection_t *conn, uint32_t len,
return 0;
}
+static int
+handle_control_fragments(connection_t *conn, uint16_t command_type,
+ uint32_t body_len, char *body)
+{
+ if (command_type == CONTROL_CMD_FRAGMENTHEADER) {
+ if (conn->incoming_cmd) {
+ log_fn(LOG_WARN, "Dropping incomplete fragmented command");
+ tor_free(conn->incoming_cmd);
+ }
+ if (body_len < 6) {
+ send_control_error(conn, ERR_SYNTAX, "FRAGMENTHEADER too short.");
+ return 0;
+ }
+ conn->incoming_cmd_type = ntohs(get_uint16(body));
+ conn->incoming_cmd_len = ntohl(get_uint32(body+2));
+ conn->incoming_cmd_cur_len = 0;
+ conn->incoming_cmd = tor_malloc(conn->incoming_cmd_len);
+ body += 6;
+ body_len -= 6;
+ } else if (command_type == CONTROL_CMD_FRAGMENT) {
+ if (!conn->incoming_cmd) {
+ send_control_error(conn, ERR_SYNTAX, "Out-of-place FRAGMENT");
+ return 0;
+ }
+ } else {
+ tor_assert(0);
+ }
+
+ if (conn->incoming_cmd_cur_len + body_len > conn->incoming_cmd_len) {
+ tor_free(conn->incoming_cmd);
+ send_control_error(conn, ERR_SYNTAX,
+ "Fragmented data exceeds declared length");
+ return 0;
+ }
+ memcpy(conn->incoming_cmd + conn->incoming_cmd_cur_len,
+ body, body_len);
+ conn->incoming_cmd_cur_len += body_len;
+ return 0;
+}
+
/** Called when <b>conn</b> has no more bytes left on its outbuf. */
int
connection_control_finished_flushing(connection_t *conn) {
@@ -980,6 +1020,23 @@ connection_control_process_inbuf(connection_t *conn) {
goto again;
}
+ if (command_type == CONTROL_CMD_FRAGMENTHEADER ||
+ command_type == CONTROL_CMD_FRAGMENT) {
+ if (handle_control_fragments(conn, command_type, body_len, body))
+ return -1;
+ tor_free(body);
+ if (conn->incoming_cmd_cur_len != conn->incoming_cmd_len)
+ goto again;
+
+ command_type = conn->incoming_cmd_type;
+ body_len = conn->incoming_cmd_len;
+ body = conn->incoming_cmd;
+ conn->incoming_cmd = NULL;
+ } else if (conn->incoming_cmd) {
+ log_fn(LOG_WARN, "Dropping incomplete fragmented command");
+ tor_free(conn->incoming_cmd);
+ }
+
/* Okay, we're willing to process the command. */
switch (command_type)
{