[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[or-cvs] Re-do fragmented control message handling to work with new ...
- To: or-cvs@xxxxxxxxxxxxx
- Subject: [or-cvs] Re-do fragmented control message handling to work with new ...
- From: nickm@xxxxxxxx (Nick Mathewson)
- Date: Wed, 27 Apr 2005 18:01:37 -0400 (EDT)
- Delivered-to: archiver@seul.org
- Delivered-to: or-cvs-outgoing@seul.org
- Delivered-to: or-cvs@seul.org
- Delivery-date: Wed, 27 Apr 2005 18:02:10 -0400
- Reply-to: or-dev@xxxxxxxxxxxxx
- Sender: owner-or-cvs@xxxxxxxxxxxxx
Update of /home/or/cvsroot/tor/src/or
In directory moria.mit.edu:/tmp/cvs-serv14858/src/or
Modified Files:
buffers.c connection.c control.c or.h
Log Message:
Re-do fragmented control message handling to work with new buf_t system.
Index: buffers.c
===================================================================
RCS file: /home/or/cvsroot/tor/src/or/buffers.c,v
retrieving revision 1.143
retrieving revision 1.144
diff -u -d -r1.143 -r1.144
--- buffers.c 27 Apr 2005 20:02:52 -0000 1.143
+++ buffers.c 27 Apr 2005 22:01:34 -0000 1.144
@@ -968,7 +968,7 @@
{
uint32_t msglen;
uint16_t type;
- char tmp[10];
+ char tmp[4];
tor_assert(buf);
tor_assert(len_out);
@@ -985,77 +985,17 @@
return 0;
type = ntohs(get_uint16(tmp+2));
- if (type != CONTROL_CMD_FRAGMENTHEADER) {
- *len_out = msglen;
- *type_out = type;
- buf_remove_from_front(buf, 4);
- if (msglen) {
- *body_out = tor_malloc(msglen+1);
- fetch_from_buf(*body_out, msglen, buf);
- (*body_out)[msglen] = '\0';
- } else {
- *body_out = NULL;
- }
- return 1;
+ *len_out = msglen;
+ *type_out = type;
+ buf_remove_from_front(buf, 4);
+ if (msglen) {
+ *body_out = tor_malloc(msglen+1);
+ fetch_from_buf(*body_out, msglen, buf);
+ (*body_out)[msglen] = '\0';
} else {
- uint32_t totallen, sofar;
- char *cp, *endp, *outp;
-
- /* Okay, we have a fragmented message. Is it all here? */
- if (msglen < 6)
- return -1;
- peek_from_buf(tmp, 10, buf);
- type = htons(get_uint16(tmp+4));
- totallen = htonl(get_uint32(tmp+6));
- if (totallen < 65536)
- return -1;
-
- if (buf->datalen<4+6+totallen)
- /* The data can't possibly be here yet, no matter how well it's packed.*/
- return 0;
-
- /* Count how much data is really here. */
- sofar = msglen-6;
- cp = buf->cur+4+msglen;
- endp = buf->cur+buf->datalen;
- /* XXXXX!!!!!! This will not handle fragmented messages right now. */
- while (sofar < totallen) {
- if ((endp-cp)<4)
- return 0; /* Fragment header not all here. */
- msglen = ntohs(get_uint16(cp));
- if (ntohs(get_uint16(cp+2) != CONTROL_CMD_FRAGMENT))
- return -1; /* Missing fragment message; error. */
- if ((endp-cp) < (int)(4+msglen))
- return 0; /* Fragment not all here. */
- sofar += msglen;
- cp += (4+msglen);
- }
- if (sofar > totallen)
- return -1; /* Fragments add to more than expected; error. */
-
- /* Okay, everything is here. */
- *len_out = totallen;
- *type_out = type;
- *body_out = tor_malloc(totallen+1);
-
- /* copy FRAGMENTED packet contents. */
- msglen = ntohs(get_uint16(buf->mem));
- if (msglen>6)
- memcpy(*body_out,buf->mem+4+6,msglen-6);
- sofar = msglen-6;
- outp = *body_out+sofar;
- cp = buf->mem+4+msglen;
- while (sofar < totallen) {
- msglen = ntohs(get_uint16(cp));
- memcpy(outp,cp+4,msglen);
- outp += msglen;
- cp += 4+msglen;
- sofar -= msglen;
- }
- (*body_out)[totallen]='\0';
-
- return 1;
+ *body_out = NULL;
}
+ return 1;
}
/** Log an error and exit if <b>buf</b> is corrupted.
Index: connection.c
===================================================================
RCS file: /home/or/cvsroot/tor/src/or/connection.c,v
retrieving revision 1.365
retrieving revision 1.366
diff -u -d -r1.365 -r1.366
--- connection.c 26 Apr 2005 20:55:32 -0000 1.365
+++ connection.c 27 Apr 2005 22:01:34 -0000 1.366
@@ -209,6 +209,7 @@
crypto_free_pk_env(conn->identity_pkey);
tor_free(conn->nickname);
tor_free(conn->socks_request);
+ tor_free(conn->incoming_cmd);
tor_free(conn->read_event); /* Probably already freed by connection_free. */
tor_free(conn->write_event); /* Probably already freed by connection_free. */
Index: control.c
===================================================================
RCS file: /home/or/cvsroot/tor/src/or/control.c,v
retrieving revision 1.78
retrieving revision 1.79
diff -u -d -r1.78 -r1.79
--- control.c 17 Apr 2005 22:52:02 -0000 1.78
+++ control.c 27 Apr 2005 22:01:34 -0000 1.79
@@ -923,6 +923,46 @@
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 @@
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)
{
Index: or.h
===================================================================
RCS file: /home/or/cvsroot/tor/src/or/or.h,v
retrieving revision 1.596
retrieving revision 1.597
diff -u -d -r1.596 -r1.597
--- or.h 26 Apr 2005 18:52:16 -0000 1.596
+++ or.h 27 Apr 2005 22:01:34 -0000 1.597
@@ -639,6 +639,10 @@
/* Used only by control connections */
uint32_t event_mask;
+ uint16_t incoming_cmd_type;
+ uint32_t incoming_cmd_len;
+ uint32_t incoming_cmd_cur_len;
+ char *incoming_cmd;
};
typedef struct connection_t connection_t;