예제 #1
0
int
label_compare(const uint8_t *left, const uint8_t *right)
{
	int left_length;
	int right_length;
	size_t size;
	int result;

	assert(left);
	assert(right);

	assert(label_is_normal(left));
	assert(label_is_normal(right));

	left_length = label_length(left);
	right_length = label_length(right);
	size = left_length < right_length ? left_length : right_length;

	result = memcmp(label_data(left), label_data(right), size);
	if (result) {
		return result;
	} else {
		return (int) left_length - (int) right_length;
	}
}
예제 #2
0
static void
encode_dname(query_type *q, domain_type *domain)
{
	while (domain->parent && query_get_dname_offset(q, domain) == 0) {
		query_put_dname_offset(q, domain, buffer_position(q->packet));
		DEBUG(DEBUG_NAME_COMPRESSION, 2,
		      (LOG_INFO, "dname: %s, number: %lu, offset: %u\n",
		       dname_to_string(domain_dname(domain), NULL),
		       (unsigned long) domain->number,
		       query_get_dname_offset(q, domain)));
		buffer_write(q->packet, dname_name(domain_dname(domain)),
			     label_length(dname_name(domain_dname(domain))) + 1U);
		domain = domain->parent;
	}
	if (domain->parent) {
		DEBUG(DEBUG_NAME_COMPRESSION, 2,
		      (LOG_INFO, "dname: %s, number: %lu, pointer: %u\n",
		       dname_to_string(domain_dname(domain), NULL),
		       (unsigned long) domain->number,
		       query_get_dname_offset(q, domain)));
		assert(query_get_dname_offset(q, domain) <= MAX_COMPRESSION_OFFSET);
		buffer_write_u16(q->packet,
				 0xc000 | query_get_dname_offset(q, domain));
	} else {
		buffer_write_u8(q->packet, 0);
	}
}
예제 #3
0
파일: dname.c 프로젝트: matje/rzonec
/**
 * Get the next label.
 *
 */
const uint8_t*
label_next(const uint8_t* label)
{
    assert(label);
    assert(label_is_normal(label));
    assert(!label_is_root(label));
    return label + label_length(label) + 1;
}
예제 #4
0
const char *
dname_to_string_r(const dname_type *dname, const dname_type *origin,
	char* buf)
{
	size_t i;
	size_t labels_to_convert = 0;
	int absolute = 1;
	char *dst;
	const uint8_t *src;
	if (!dname) {
		*buf = '\0';
		return buf;
	}
	if (dname->label_count == 1) {
		strlcpy(buf, ".", sizeof(buf));
		return buf;
	}
	labels_to_convert = dname->label_count - 1;

	if (origin && dname_is_subdomain(dname, origin)) {
		int common_labels = dname_label_match_count(dname, origin);
		labels_to_convert = dname->label_count - common_labels;
		absolute = 0;
	}

	dst = buf;
	src = dname_name(dname);
	for (i = 0; i < labels_to_convert; ++i) {
		size_t len = label_length(src);
		size_t j;
		++src;
		for (j = 0; j < len; ++j) {
			uint8_t ch = *src++;
			if (isalnum(ch) || ch == '-' || ch == '_') {
				*dst++ = ch;
			} else if (ch == '.' || ch == '\\') {
				*dst++ = '\\';
				*dst++ = ch;
			} else {
				snprintf(dst, 5, "\\%03u", (unsigned int)ch);
				dst += 4;
			}
		}
		*dst++ = '.';
	}
	if (absolute) {
		*dst = '\0';
	} else {
		*--dst = '\0';
	}
	return buf;
}
예제 #5
0
파일: dname.c 프로젝트: matje/rzonec
/**
 * Create new domain name.
 *
 */
dname_type*
dname_create(region_type* r, const char* str)
{
    uint8_t wire[DNAME_MAXLEN];
    uint8_t label_offsets[DNAME_MAXLEN];
    uint8_t label_count = 0;
    size_t size = 0;
    const uint8_t* label = wire;
    dname_type *dname;
    ssize_t i;
    assert(r);
    assert(str);
    if (!dname_str2wire(wire, str)) {
        fprintf(stderr, "[%s] error: parse dname %s failed", logstr, str);
        return NULL;
    }
    while (1) {
        if (label_is_pointer(label)) {
            return NULL;
        }
        label_offsets[label_count] = (uint8_t) (label - wire);
        ++label_count;
        size += label_length(label) + 1;
        if (label_is_root(label)) {
            break;
        }
        label = label_next(label);
    }
    if (size > DNAME_MAXLEN) {
        return NULL;
    }
    assert(label_count <= DNAME_MAXLEN / 2 + 1);
    /* reverse label offsets. */

    /* reverse label offsets. */
    for (i = 0; i < label_count / 2; ++i) {
        uint8_t tmp = label_offsets[i];
        label_offsets[i] = label_offsets[label_count - i - 1];
        label_offsets[label_count - i - 1] = tmp;
    }
    dname = (dname_type *) region_alloc(r, (sizeof(dname_type)
        + (label_count + size) * sizeof(uint8_t)));
    dname->size = size;
    dname->label_count = label_count;
    memcpy((uint8_t *) dname_label_offsets(dname), label_offsets,
        label_count * sizeof(uint8_t));
    memcpy((uint8_t *) dname_name(dname), wire, size * sizeof(uint8_t));
    return dname;
}
예제 #6
0
파일: dname.c 프로젝트: matje/rzonec
/**
 * Print domain name.
 *
 */
void dname_print(FILE* fd, dname_type* dname)
{
    static char buf[DNAME_MAXLEN*5];
    size_t i;
    size_t labels_to_convert;
    char* dst;
    const uint8_t* src;

    if (!dname || !fd) {
        return;
    }
    assert(dname->label_count > 0);
    if (dname->label_count == 1) {
        fprintf(fd, ".");
        return;
    }
    labels_to_convert = dname->label_count - 1;
    dst = buf;
    src = dname_name(dname);
    for (i = 0; i < labels_to_convert; ++i) {
        size_t len = label_length(src);
        size_t j;
        ++src;
        for (j = 0; j < len; ++j) {
            uint8_t ch = *src++;
            if (isalnum(ch) || ch == '-' || ch == '_') {
                *dst++ = ch;
            } else if (ch == '.' || ch == '\\' || ch == '(' || ch == ')'
                || ch == ';') {
                *dst++ = '\\';
                *dst++ = ch;
            } else {
                snprintf(dst, 5, "\\%03u", (unsigned int)ch);
                dst += 4;
            }
        }
        *dst++ = '.';
    }
    *dst = '\0';
    fprintf(fd, "%s", buf);
    return;
}
예제 #7
0
const dname_type *
dname_make(region_type *region, const uint8_t *name, int normalize)
{
	size_t name_size = 0;
	uint8_t label_offsets[MAXDOMAINLEN];
	uint8_t label_count = 0;
	const uint8_t *label = name;
	dname_type *result;
	ssize_t i;

	assert(name);

	while (1) {
		if (label_is_pointer(label))
			return NULL;

		label_offsets[label_count] = (uint8_t) (label - name);
		++label_count;
		name_size += label_length(label) + 1;

		if (label_is_root(label))
			break;

		label = label_next(label);
	}

	if (name_size > MAXDOMAINLEN)
		return NULL;

	assert(label_count <= MAXDOMAINLEN / 2 + 1);

	/* Reverse label offsets.  */
	for (i = 0; i < label_count / 2; ++i) {
		uint8_t tmp = label_offsets[i];
		label_offsets[i] = label_offsets[label_count - i - 1];
		label_offsets[label_count - i - 1] = tmp;
	}

	result = (dname_type *) region_alloc(
		region,
		(sizeof(dname_type)
		 + (label_count + name_size) * sizeof(uint8_t)));
	result->name_size = name_size;
	result->label_count = label_count;
	memcpy((uint8_t *) dname_label_offsets(result),
	       label_offsets,
	       label_count * sizeof(uint8_t));
	if (normalize) {
		uint8_t *dst = (uint8_t *) dname_name(result);
		const uint8_t *src = name;
		while (!label_is_root(src)) {
			ssize_t len = label_length(src);
			*dst++ = *src++;
			for (i = 0; i < len; ++i) {
				*dst++ = DNAME_NORMALIZE(*src++);
			}
		}
		*dst = *src;
	} else {
		memcpy((uint8_t *) dname_name(result),
		       name,
		       name_size * sizeof(uint8_t));
	}
	return result;
}
예제 #8
0
int
dname_make_wire_from_packet(uint8_t *buf, buffer_type *packet,
                       int allow_pointers)
{
	int done = 0;
	uint8_t visited[(MAX_PACKET_SIZE+7)/8];
	size_t dname_length = 0;
	const uint8_t *label;
	ssize_t mark = -1;

	memset(visited, 0, (buffer_limit(packet)+7)/8);

	while (!done) {
		if (!buffer_available(packet, 1)) {
/* 			error("dname out of bounds"); */
			return 0;
		}

		if (get_bit(visited, buffer_position(packet))) {
/* 			error("dname loops"); */
			return 0;
		}
		set_bit(visited, buffer_position(packet));

		label = buffer_current(packet);
		if (label_is_pointer(label)) {
			size_t pointer;
			if (!allow_pointers) {
				return 0;
			}
			if (!buffer_available(packet, 2)) {
/* 				error("dname pointer out of bounds"); */
				return 0;
			}
			pointer = label_pointer_location(label);
			if (pointer >= buffer_limit(packet)) {
/* 				error("dname pointer points outside packet"); */
				return 0;
			}
			buffer_skip(packet, 2);
			if (mark == -1) {
				mark = buffer_position(packet);
			}
			buffer_set_position(packet, pointer);
		} else if (label_is_normal(label)) {
			size_t length = label_length(label) + 1;
			done = label_is_root(label);
			if (!buffer_available(packet, length)) {
/* 				error("dname label out of bounds"); */
				return 0;
			}
			if (dname_length + length >= MAXDOMAINLEN+1) {
/* 				error("dname too large"); */
				return 0;
			}
			buffer_read(packet, buf + dname_length, length);
			dname_length += length;
		} else {
/* 			error("bad label type"); */
			return 0;
		}
	}

	if (mark != -1) {
		buffer_set_position(packet, mark);
	}

	return dname_length;
}