⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 name.c

📁 bind-3.2.
💻 C
📖 第 1 页 / 共 5 页
字号:
				}				count = tailbits / 8;				if (tailbits % 8 != 0)					count++;				last = tail;				while (count > 0) {					*curr++ = *last++;					count--;				}				last = name->ndata + name->length;				while (head != last)					*curr++ = *head++;				name->length = (curr - name->ndata);				/*				 * The offsets table may now be invalid.				 */				set_offsets(name, offsets, NULL);				goto again;			}		}		n--;	}}isc_result_tdns_name_fromwire(dns_name_t *name, isc_buffer_t *source,		  dns_decompress_t *dctx, isc_boolean_t downcase,		  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 saw_bitstring, done;	fw_state state = fw_start;	unsigned int c;	unsigned char *offsets;	dns_offsets_t odata;	/*	 * 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)));	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;	saw_bitstring = ISC_FALSE;	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 if (c == DNS_LABELTYPE_BITSTRING) {				offsets[labels] = nused;				labels++;				if (nused == nmax)					goto full;				nused++;				*ndata++ = c;				saw_bitstring = ISC_TRUE;				state = fw_bitstring;			} 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_bitstring:			if (c == 0)				n = 256 / 8;			else				n = c / 8;			if ((c % 8) != 0)				n++;			if (nused + n + 1 > nmax)				goto full;			nused += n + 1;			*ndata++ = c;			state = fw_copy;			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;	if (saw_bitstring)		compact(name, offsets);	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);}isc_result_tdns_name_towire(dns_name_t *name, dns_compress_t *cctx, isc_buffer_t *target) {	unsigned int methods;	isc_uint16_t offset;	dns_name_t gp;	/* Global compression prefix */	isc_boolean_t gf;	/* Global compression target found */	isc_uint16_t go;	/* Global compression offset */	dns_offsets_t clo;	dns_name_t clname;	/*	 * Convert 'name' into wire format, compressing it as specified by the	 * compression context 'cctx', and storing the result in 'target'.	 */	REQUIRE(VALID_NAME(name));	REQUIRE(cctx != NULL);	REQUIRE(ISC_BUFFER_VALID(target));	/*	 * If 'name' doesn't have an offsets table, make a clone which	 * has one.	 */	if (name->offsets == NULL) {		DNS_NAME_INIT(&clname, clo);		dns_name_clone(name, &clname);		name = &clname;	}	DNS_NAME_INIT(&gp, NULL);	offset = target->used;	/*XXX*/	methods = dns_compress_getmethods(cctx);	if ((methods & DNS_COMPRESS_GLOBAL14) != 0)		gf = dns_compress_findglobal(cctx, name, &gp, &go);	else		gf = ISC_FALSE;	/*	 * If the offset is too high for 14 bit global compression, we're	 * out of luck.	 */	if (gf && go >= 0x4000)		gf = ISC_FALSE;	/*	 * Will the compression pointer reduce the message size?	 */	if (gf && (gp.length + 2) >= name->length)		gf = ISC_FALSE;	if (gf) {		if (target->length - target->used < gp.length)			return (ISC_R_NOSPACE);		(void)memcpy((unsigned char *)target->base + target->used,			     gp.ndata, (size_t)gp.length);		isc_buffer_add(target, gp.length);		go |= 0xc000;		if (target->length - target->used < 2)			return (ISC_R_NOSPACE);		isc_buffer_putuint16(target, go);		if (gp.length != 0)			dns_compress_add(cctx, name, &gp, offset);	} else {		if (target->length - target->used < name->length)			return (ISC_R_NOSPACE);		(void)memcpy((unsigned char *)target->base + target->used,			     name->ndata, (size_t)name->length);		isc_buffer_add(target, name->length);		dns_compress_add(cctx, name, name, offset);	}	return (ISC_R_SUCCESS);}isc_result_tdns_name_concatenate(dns_name_t *prefix, dns_name_t *suffix, dns_name_t *name,		     isc_buffer_t *target){	unsigned char *ndata, *offsets;	unsigned int nrem, labels, prefix_length, length, offset;	isc_boolean_t copy_prefix = ISC_TRUE;	isc_boolean_t copy_suffix = ISC_TRUE;	isc_boolean_t saw_bitstring = ISC_FALSE;	isc_boolean_t absolute = ISC_FALSE;	dns_name_t tmp_name;	dns_offsets_t odata;	/*	 * Concatenate 'prefix' and 'suffix'.	 */	REQUIRE(prefix == NULL || VALID_NAME(prefix));	REQUIRE(suffix == NULL || VALID_NAME(suffix));	REQUIRE(name == NULL || VALID_NAME(name));	REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||		(target == NULL && name != NULL && ISC_BUFFER_VALID(name->buffer)));	if (prefix == NULL || prefix->labels == 0)		copy_prefix = ISC_FALSE;	if (suffix == NULL || suffix->labels == 0)		copy_suffix = ISC_FALSE;	if (copy_prefix &&	    (prefix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {		absolute = ISC_TRUE;		REQUIRE(!copy_suffix);	}	if (name == NULL) {		DNS_NAME_INIT(&tmp_name, odata);		name = &tmp_name;	}	if (target == NULL) {		INSIST(name->buffer != NULL);		target = name->buffer;		isc_buffer_clear(name->buffer);	}	REQUIRE(BINDABLE(name));	/*	 * XXX IMPORTANT NOTE	 *	 * If the most-signficant label in prefix is a bitstring,	 * and the least-signficant label in suffix is a bitstring,	 * it's possible that compaction could convert them into	 * one label.  If this happens, then the final size will	 * be three bytes less than nrem.	 *	 * We do not check for this special case, and handling it is	 * a little messy; we can't just concatenate and compact,	 * because we may only have 255 bytes but might need 258 bytes	 * temporarily.  There are ways to do this with only 255 bytes,	 * which will be implemented later.	 *	 * For now, we simply reject these few cases as being too	 * long.	 */	/*	 * Set up.	 */	nrem = target->length - target->used;	ndata = (unsigned char *)target->base + target->used;	if (nrem > DNS_NAME_MAXWIRE)		nrem = DNS_NAME_MAXWIRE;	length = 0;	prefix_length = 0;	labels = 0;	if (copy_prefix) {		prefix_length = prefix->length;		length += prefix_length;		labels += prefix->labels;	}	if (copy_suffix) {		length += suffix->length;		labels += suffix->labels;	}	if (length > DNS_NAME_MAXWIRE) {		MAKE_EMPTY(name);		return (DNS_R_NAMETOOLONG);	}	if (length > nrem) {		MAKE_EMPTY(name);		return (ISC_R_NOSPACE);	}	if (copy_suffix) {		if ((suffix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)			absolute = ISC_TRUE;		if (copy_prefix &&		    suffix->ndata[0] == DNS_LABELTYPE_BITSTRING) {			/*			 * We only need to call compact() if both the			 * least-significant label of the suffix and the			 * most-significant label of the prefix are both			 * bitstrings.			 *			 * A further possible optimization, which we don't do,			 * is to not compact() if the suffix bitstring is			 * full.  It will usually not be full, so I don't			 * think this is worth it.			 */			if (prefix->offsets != NULL) {				offset = prefix->offsets[prefix->labels - 1];				if (prefix->ndata[offset] ==				    DNS_LABELTYPE_BITSTRING)					saw_bitstring = ISC_TRUE;			} else {				/*				 * We don't have an offsets table for prefix,				 * and rather than spend the effort to make it				 * we'll just compact(), which doesn't cost				 * more than computing the offsets table if				 * there is no bitstring in prefix.				 */				saw_bitstring = ISC_TRUE;			}		}		if (suffix == name && suffix->buffer == target)			memmove(ndata + prefix_length, suffix->ndata,				suffix->length);		else			memcpy(ndata + prefix_length, suffix->ndata,			       suffix->length);	}	/*	 * If 'prefix' and 'name' are the same object, and the object has	 * a dedicated buffer, and we're using it, then we don't have to	 * copy anything.	 */	if (copy_prefix && (prefix != name || prefix->buffer != target))		memcpy(ndata, prefix->ndata, prefix_length);	name->ndata = ndata;	name->labels = labels;	name->length = length;	if (absolute)		name->attributes = DNS_NAMEATTR_ABSOLUTE;	else		name->attributes = 0;	if (name->labels > 0 && (name->offsets != NULL || saw_bitstring)) {		INIT_OFFSETS(name, offsets, odata);		set_offsets(name, offsets, NULL);		if (saw_bitstring)			compact(name, offsets);	}	isc_buffer_add(target, name->length);	return (ISC_R_SUCCESS);}isc_result_tdns_name_split(dns_name_t *name,	       unsigned int suffixlabels, unsigned int nbits,	       dns_name_t *prefix, dns_name_t *suffix){	dns_offsets_t name_odata, prefix_odata, suffix_odata;	unsigned char *offsets, *prefix_offsets = NULL, *suffix_offsets;	isc_result_t result = ISC_R_SUCCESS;	unsigned int splitlabel, bitbytes, mod, len;	unsigned char *p, *src, *dst;	isc_boolean_t maybe_compact_prefix = ISC_FALSE;	REQUIRE(VALID_NAME(name));	REQUIRE(suffixlabels > 0);	REQUIRE((nbits == 0 && suffixlabels < name->labels) ||		(nbits != 0 && suffixlabels <= name->labels));	REQUIRE(prefix != NULL || suffix != NULL);	REQUIRE(prefix == NULL ||		(VALID_NAME(prefix) &&		 prefix->buffer != NULL &&		 BINDABLE(prefix)));	REQUIRE(suffix == NULL ||		(VALID_NAME(suffix) &&		 suffix->buffer != NULL &&		 BINDABLE(suffix)));	/*	 * When splitting bitstring labels, if prefix and suffix have the same	 * buffer, suffix will overwrite the ndata of prefix, corrupting it.	 * If prefix has the ndata of name, then it modifies the bitstring	 * label and suffix doesn't have the original available.  This latter	 * problem could be worked around if it is ever deemed desirable.	 */	REQUIRE(nbits == 0 || prefix == NULL || suffix == NULL ||		(prefix->buffer->base != suffix->buffer->base &&		 prefix->buffer->base != name->ndata));	SETUP_OFFSETS(name, offsets, name_odata);	splitlabel = name->labels - suffixlabels;	/*	 * Make p point at the count byte of the bitstring label,	 * if there is one (p will not be used if we are not	 * splitting bits).	 */	p = &name->ndata[offsets[splitlabel] + 1];	/*	 * When a bit count is specified, ensure that the label is a bitstring	 * label and it has more bits than the requested slice.	 */	REQUIRE(nbits == 0 ||		(*(p - 1) == DNS_LABELTYPE_BITSTRING && nbits < 256 &&		 (*p == 0 || *p > nbits)));	mod = nbits % 8;	if (prefix != NULL) {		if (nbits > 0) {			isc_buffer_clear(prefix->buffer);			/*			 * '2' is for the DNS_LABELTYPE_BITSTRING id			 * plus the existing number of bits byte.			 */			len = offsets[splitlabel] + 2;			src = name->ndata;			dst = prefix->buffer->base;			if (src != dst) {				/*				 * If these are overlapping names ...				 * wow.  How bizarre could that be?				 */				INSIST(! (src <= dst && src + len > dst) ||					 (dst <= src && dst + len > src));				memcpy(dst, src, len);				p = dst + len - 1;			}			/*			 * Set the new bit count.  Also, when a bitstring			 * label being split is maximal length, compaction			 * might be necessary on the prefix.			 */			if (*p == 0) {				maybe_compact_prefix = ISC_TRUE;				*p = 256 - nbits;			} else				*p = *p - nbits;			/*			 * Calculate the number of bytes necessary to hold			 * all of the bits left in the prefix.			 */			bitbytes = (*p - 1) / 8 + 1;			prefix->length = len + bitbytes;			if (prefix->length > prefix->buffer->length ) {				dns_name_invalidate(prefix);				return (ISC_R_NOSPACE);			}			/*			 * All of the bits now need to be shifted to the left			 * to fill in the space taken by the removed bit

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -