summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2006-12-12 02:50:17 +0000
committerNick Mathewson <nickm@torproject.org>2006-12-12 02:50:17 +0000
commite190acf78048da5ac060c0be29bc60864e6348b6 (patch)
treedf04a5bc1c6988ed46bae01e77c7315789455bc5 /src
parent0efcd826b2ebc19eda92d92cdf837172f2c65a80 (diff)
downloadtor-e190acf78048da5ac060c0be29bc60864e6348b6.tar.gz
tor-e190acf78048da5ac060c0be29bc60864e6348b6.zip
r9254@Kushana: nickm | 2006-10-17 17:23:36 -0400
Implement dns label compression. Clients do not need this much; dns servers definitely do. svn:r9073
Diffstat (limited to 'src')
-rw-r--r--src/or/eventdns.c134
1 files changed, 87 insertions, 47 deletions
diff --git a/src/or/eventdns.c b/src/or/eventdns.c
index cd94a8611f..bb18f0ab82 100644
--- a/src/or/eventdns.c
+++ b/src/or/eventdns.c
@@ -395,7 +395,7 @@ struct server_port {
struct server_request_section {
int n_items;
int j;
- char buf[512];
+ u8 buf[512];
};
struct server_request {
@@ -1261,6 +1261,59 @@ nameserver_ready_callback(int fd, short events, void *arg) {
}
}
+/* 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 @@ nameserver_ready_callback(int fd, short events, void *arg) {
//
// 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 @@ dnsname_to_labels(u8 *const buf, const char *name, const int name_len) {
// 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 @@ evdns_request_data_build(const char *const name, const int name_len, const u16 t
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 @@ evdns_request_data_build(const char *const name, const int name_len, const u16 t
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 @@ evdns_request_add_reply(struct evdns_request *_req, int section, const char *nam
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 @@ evdns_request_add_reply(struct evdns_request *_req, int section, const char *nam
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;
- }
- if ((size_t)(j + labels_len) > buf_len) {
- free(labels);
- return (-1);
+ j = dnsname_to_labels(buf, buf_len, j, name, strlen(name), NULL);
+ if (j < 0) {
+ return j;
}
- memcpy(buf + j, labels, labels_len);
- j += labels_len;
- free(labels);
APPEND16(type);
APPEND16(class);