Exemplo n.º 1
0
void
isc_buffer_compact(isc_buffer_t *b) {
	unsigned int length;
	void *src;

	/*
	 * Compact the used region by moving the remaining region so it occurs
	 * at the start of the buffer.  The used region is shrunk by the size
	 * of the consumed region, and the consumed region is then made empty.
	 */

	REQUIRE(ISC_BUFFER_VALID(b));

	src = isc_buffer_current(b);
	length = isc_buffer_remaininglength(b);
	(void)memmove(b->base, src, (size_t)length);

	if (b->active > b->current)
		b->active -= b->current;
	else
		b->active = 0;
	b->current = 0;
	b->used = length;
}
Exemplo n.º 2
0
isc_uint64_t
isc_buffer_getuint48(isc_buffer_t *b) {
	unsigned char *cp;
	isc_uint64_t result;

	/*
	 * Read an unsigned 48-bit integer in network byte order from 'b',
	 * convert it to host byte order, and return it.
	 */

	REQUIRE(ISC_BUFFER_VALID(b));
	REQUIRE(b->used - b->current >= 6);

	cp = isc_buffer_current(b);
	b->current += 6;
	result = ((isc_int64_t)(cp[0])) << 40;
	result |= ((isc_int64_t)(cp[1])) << 32;
	result |= ((isc_int64_t)(cp[2])) << 24;
	result |= ((isc_int64_t)(cp[3])) << 16;
	result |= ((isc_int64_t)(cp[4])) << 8;
	result |= ((isc_int64_t)(cp[5]));

	return (result);
}
Exemplo n.º 3
0
isc_result_t
dns_name_fromwire(dns_name_t *name, isc_buffer_t *source,
		  dns_decompress_t *dctx, unsigned int options,
		  isc_buffer_t *target)
{
	unsigned char *cdata, *ndata;
	unsigned int cused; /* Bytes of compressed name data used */
	unsigned int hops,  nused, labels, n, nmax;
	unsigned int current, new_current, biggest_pointer;
	isc_boolean_t done;
	fw_state state = fw_start;
	unsigned int c;
	unsigned char *offsets;
	dns_offsets_t odata;
	isc_boolean_t downcase;

	/*
	 * Copy the possibly-compressed name at source into target,
	 * decompressing it.
	 */

	REQUIRE(VALID_NAME(name));
	REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
		(target == NULL && ISC_BUFFER_VALID(name->buffer)));

	downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0);

	if (target == NULL && name->buffer != NULL) {
		target = name->buffer;
		isc_buffer_clear(target);
	}

	REQUIRE(dctx != NULL);
	REQUIRE(BINDABLE(name));

	INIT_OFFSETS(name, offsets, odata);

	/*
	 * Make 'name' empty in case of failure.
	 */
	MAKE_EMPTY(name);

	/*
	 * Initialize things to make the compiler happy; they're not required.
	 */
	n = 0;
	new_current = 0;

	/*
	 * Set up.
	 */
	labels = 0;
	hops = 0;
	done = ISC_FALSE;

	ndata = isc_buffer_used(target);
	nused = 0;

	/*
	 * Find the maximum number of uncompressed target name
	 * bytes we are willing to generate.  This is the smaller
	 * of the available target buffer length and the
	 * maximum legal domain name length (255).
	 */
	nmax = isc_buffer_availablelength(target);
	if (nmax > DNS_NAME_MAXWIRE)
		nmax = DNS_NAME_MAXWIRE;

	cdata = isc_buffer_current(source);
	cused = 0;

	current = source->current;
	biggest_pointer = current;

	/*
	 * Note:  The following code is not optimized for speed, but
	 * rather for correctness.  Speed will be addressed in the future.
	 */

	while (current < source->active && !done) {
		c = *cdata++;
		current++;
		if (hops == 0)
			cused++;

		switch (state) {
		case fw_start:
			if (c < 64) {
				offsets[labels] = nused;
				labels++;
				if (nused + c + 1 > nmax)
					goto full;
				nused += c + 1;
				*ndata++ = c;
				if (c == 0)
					done = ISC_TRUE;
				n = c;
				state = fw_ordinary;
			} else if (c >= 128 && c < 192) {
				/*
				 * 14 bit local compression pointer.
				 * Local compression is no longer an
				 * IETF draft.
				 */
				return (DNS_R_BADLABELTYPE);
			} else if (c >= 192) {
				/*
				 * Ordinary 14-bit pointer.
				 */
				if ((dctx->allowed & DNS_COMPRESS_GLOBAL14) ==
				    0)
					return (DNS_R_DISALLOWED);
				new_current = c & 0x3F;
				n = 1;
				state = fw_newcurrent;
			} else
				return (DNS_R_BADLABELTYPE);
			break;
		case fw_ordinary:
			if (downcase)
				c = maptolower[c];
			/* FALLTHROUGH */
		case fw_copy:
			*ndata++ = c;
			n--;
			if (n == 0)
				state = fw_start;
			break;
		case fw_newcurrent:
			new_current *= 256;
			new_current += c;
			n--;
			if (n != 0)
				break;
			if (new_current >= biggest_pointer)
				return (DNS_R_BADPOINTER);
			biggest_pointer = new_current;
			current = new_current;
			cdata = (unsigned char *)source->base +
				current;
			hops++;
			if (hops > DNS_POINTER_MAXHOPS)
				return (DNS_R_TOOMANYHOPS);
			state = fw_start;
			break;
		default:
			FATAL_ERROR(__FILE__, __LINE__,
				    "Unknown state %d", state);
			/* Does not return. */
		}
	}

	if (!done)
		return (ISC_R_UNEXPECTEDEND);

	name->ndata = (unsigned char *)target->base + target->used;
	name->labels = labels;
	name->length = nused;
	name->attributes |= DNS_NAMEATTR_ABSOLUTE;

	isc_buffer_forward(source, cused);
	isc_buffer_add(target, name->length);

	return (ISC_R_SUCCESS);

 full:
	if (nmax == DNS_NAME_MAXWIRE)
		/*
		 * The name did not fit even though we had a buffer
		 * big enough to fit a maximum-length name.
		 */
		return (DNS_R_NAMETOOLONG);
	else
		/*
		 * The name might fit if only the caller could give us a
		 * big enough buffer.
		 */
		return (ISC_R_NOSPACE);

}