mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-27 22:03:31 +01:00
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
This commit is contained in:
parent
0efcd826b2
commit
e190acf780
@ -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;
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user