[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[or-cvs] r9073: Implement dns label compression. Clients do not need this mu (in tor/trunk: . src/or)



Author: nickm
Date: 2006-12-11 21:50:17 -0500 (Mon, 11 Dec 2006)
New Revision: 9073

Modified:
   tor/trunk/
   tor/trunk/src/or/eventdns.c
Log:
 r9254@Kushana:  nickm | 2006-10-17 17:23:36 -0400
 Implement dns label compression.  Clients do not need this much; dns servers definitely do.



Property changes on: tor/trunk
___________________________________________________________________
 svk:merge ticket from /tor/branches/eventdns [r9254] on c95137ef-5f19-0410-b913-86e773d04f59

Modified: tor/trunk/src/or/eventdns.c
===================================================================
--- tor/trunk/src/or/eventdns.c	2006-12-12 02:50:13 UTC (rev 9072)
+++ tor/trunk/src/or/eventdns.c	2006-12-12 02:50:17 UTC (rev 9073)
@@ -395,7 +395,7 @@
 struct server_request_section {
 	int n_items;
 	int j;
-	char buf[512];
+	u8 buf[512];
 };
 
 struct server_request {
@@ -1261,6 +1261,59 @@
 	}
 }
 
+/* This is an inefficient representation; only use it via the dnslabel_table_*
+ * functions. */
+#define MAX_LABELS 128
+struct dnslabel_entry { char *v; int pos; };
+struct dnslabel_table {
+	int n_labels;
+	struct dnslabel_entry labels[MAX_LABELS];
+};
+
+static void
+dnslabel_table_init(struct dnslabel_table *table)
+{
+	table->n_labels = 0;
+}
+
+static void
+dnslabel_clear(struct dnslabel_table *table)
+{
+	int i;
+	for (i = 0; i < table->n_labels; ++i)
+		free(table->labels[i].v);
+	table->n_labels = 0;
+}
+
+static int
+dnslabel_table_get_pos(const struct dnslabel_table *table, const char *label)
+{
+	int i;
+	for (i = 0; i < table->n_labels; ++i) {
+		if (!strcmp(label, table->labels[i].v))
+			return table->labels[i].pos;
+	}
+	return -1;
+}
+
+static int
+dnslabel_table_add(struct dnslabel_table *table, const char *label, int pos)
+{
+	char *v;
+	int p;
+	if (table->n_labels == MAX_LABELS)
+		return (-1);
+	v = strdup(label);
+	if (v == NULL)
+		return (-1);
+	p = table->n_labels++;
+	table->labels[p].v = v;
+	table->labels[p].pos = pos;
+
+	return (0);
+}
+
+
 // Converts a string to a length-prefixed set of DNS labels.
 // @buf must be strlen(name)+2 or longer. name and buf must
 // not overlap. name_len should be the length of name
@@ -1270,20 +1323,39 @@
 //
 // Returns the length of the data. negative on error
 //	 -1	 label was > 63 bytes
-//	 -2	 name was > 255 bytes
-static int
-dnsname_to_labels(u8 *const buf, const char *name, const int name_len) {
+//	 -2	 name too long to fit in buffer.
+//
+// XXXX Changed interface.
+static off_t
+dnsname_to_labels(u8 *const buf, size_t buf_len, off_t j,
+				  const char *name, const int name_len,
+				  struct dnslabel_table *table) {
 	const char *end = name + name_len;
-	int j = 0;	// current offset into buf
+	int ref = 0;
+	u16 _t;
 
+#define APPEND16(x) do {                           \
+        if (j + 2 > (off_t)buf_len)				   \
+            return (-2);                           \
+        _t = htons(x);                             \
+        memcpy(buf + j, &_t, 2);                   \
+        j += 2;                                    \
+    } while (0)
+
 	if (name_len > 255) return -2;
 
 	for (;;) {
 		const char *const start = name;
+		if (table && (ref = dnslabel_table_get_pos(table, name)) >= 0) {
+			APPEND16(ref | 0xc000);
+			return j;
+		}
 		name = strchr(name, '.');
 		if (!name) {
 			const unsigned int label_len = end - start;
 			if (label_len > 63) return -1;
+			if (j+label_len+1 > buf_len) return -2;
+			if (table) dnslabel_table_add(table, start, j);
 			buf[j++] = label_len;
 
 			memcpy(buf + j, start, end - start);
@@ -1293,6 +1365,8 @@
 			// append length of the label.
 			const unsigned int label_len = name - start;
 			if (label_len > 63) return -1;
+			if (j+label_len+1 > buf_len) return -2;
+			if (table) dnslabel_table_add(table, start, j);
 			buf[j++] = label_len;
 
 			memcpy(buf + j, start, name - start);
@@ -1329,18 +1403,9 @@
 						 u8 *const buf, size_t buf_len) {
 	off_t j = 0;	// current offset into buf
 	u16 _t;	 // used by the macros
-	u8 *labels;
-	int labels_len;
 
-#define APPEND16(x) do {                           \
-        if (j + 2 > (off_t)buf_len)				   \
-            return (-1);                           \
-        _t = htons(x);                             \
-        memcpy(buf + j, &_t, 2);                   \
-        j += 2;                                    \
-    } while (0)
 #define APPEND32(x) do {                           \
-        if (j + 4 > buf_len)                       \
+        if (j + 4 > (off_t)buf_len)                \
             return (-1);                           \
         _t32 = htonl(x);                           \
         memcpy(buf + j, &_t32, 4);                 \
@@ -1355,21 +1420,10 @@
 	APPEND16(0);  // no authority
 	APPEND16(0);  // no additional
 
-	labels = (u8 *) malloc(name_len + 2);
-	if (labels == NULL)
-		return -1;
-	labels_len = dnsname_to_labels(labels, name, name_len);
-	if (labels_len < 0) {
-		free(labels);
-		return labels_len;
+	j = dnsname_to_labels(buf, buf_len, j, name, name_len, NULL);
+	if (j < 0) {
+		return j;
 	}
-	if ((size_t)(j + labels_len) > buf_len) {
-		free(labels);
-		return (-1);
-	}
-	memcpy(buf + j, labels, labels_len);
-	j += labels_len;
-	free(labels);
 
 	APPEND16(type);
 	APPEND16(class);
@@ -1384,12 +1438,10 @@
 	struct server_request *req = TO_SERVER_REQUEST(_req);
 	struct server_request_section **secp;
 	int j;
-	char *buf;
+	u8 *buf;
 	int buf_len;
 	u16 _t;	 // used by the macros
 	u32 _t32; // used by the macros
-	u8 *labels;
-	int labels_len, name_len;
 
 	switch (section) {
 	case EVDNS_ANSWER_SECTION:
@@ -1414,23 +1466,11 @@
 	j = (*secp)->j;
 
 	// format is <label:name><u16:type><u16:class><u32:ttl><u16:len><data...>
-	name_len = strlen(name);
 
-	labels = (u8 *) malloc(name_len + 2);
-	if (labels == NULL)
-		return -1;
-	labels_len = dnsname_to_labels(labels, name, name_len);
-	if (labels_len < 0) {
-		free(labels);
-		return labels_len;
+	j = dnsname_to_labels(buf, buf_len, j, name, strlen(name), NULL);
+	if (j < 0) {
+		return j;
 	}
-	if ((size_t)(j + labels_len) > buf_len) {
-		free(labels);
-		return (-1);
-	}
-	memcpy(buf + j, labels, labels_len);
-	j += labels_len;
-	free(labels);
 
 	APPEND16(type);
 	APPEND16(class);