Esempio n. 1
0
/*
 * Find the longest match of name in the table.
 * If match is found return ISC_TRUE. prefix, suffix and offset are updated.
 * If no match is found return ISC_FALSE.
 */
isc_boolean_t
dns_compress_findglobal(dns_compress_t *cctx, const dns_name_t *name,
			dns_name_t *prefix, isc_uint16_t *offset)
{
	dns_name_t tname, nname;
	dns_compressnode_t *node = NULL;
	unsigned int labels, hash, n;

	REQUIRE(VALID_CCTX(cctx));
	REQUIRE(dns_name_isabsolute(name) == ISC_TRUE);
	REQUIRE(offset != NULL);

	if (cctx->count == 0)
		return (ISC_FALSE);

	labels = dns_name_countlabels(name);
	INSIST(labels > 0);

	dns_name_init(&tname, NULL);
	dns_name_init(&nname, NULL);

	for (n = 0; n < labels - 1; n++) {
		dns_name_getlabelsequence(name, n, labels - n, &tname);
		hash = dns_name_hash(&tname, ISC_FALSE) %
		       DNS_COMPRESS_TABLESIZE;
		for (node = cctx->table[hash]; node != NULL; node = node->next)
		{
			NODENAME(node, &nname);
			if ((cctx->allowed & DNS_COMPRESS_CASESENSITIVE) != 0) {
				if (dns_name_caseequal(&nname, &tname))
					break;
			} else {
				if (dns_name_equal(&nname, &tname))
					break;
			}
		}
		if (node != NULL)
			break;
	}

	/*
	 * If node == NULL, we found no match at all.
	 */
	if (node == NULL)
		return (ISC_FALSE);

	if (n == 0)
		dns_name_reset(prefix);
	else
		dns_name_getlabelsequence(name, 0, n, prefix);

	*offset = node->offset;
	return (ISC_TRUE);
}
Esempio n. 2
0
/*
 * Find the longest match of name in the table.
 * If match is found return ISC_TRUE. prefix, suffix and offset are updated.
 * If no match is found return ISC_FALSE.
 */
isc_boolean_t
dns_compress_findglobal(dns_compress_t *cctx, const dns_name_t *name,
			dns_name_t *prefix, isc_uint16_t *offset)
{
	dns_name_t tname;
	dns_compressnode_t *node = NULL;
	unsigned int labels, i, n;
	unsigned int numlabels;
	unsigned char *p;

	REQUIRE(VALID_CCTX(cctx));
	REQUIRE(dns_name_isabsolute(name) == ISC_TRUE);
	REQUIRE(offset != NULL);

	if (ISC_UNLIKELY((cctx->allowed & DNS_COMPRESS_ENABLED) == 0))
		return (ISC_FALSE);

	if (cctx->count == 0)
		return (ISC_FALSE);

	labels = dns_name_countlabels(name);
	INSIST(labels > 0);

	dns_name_init(&tname, NULL);

	numlabels = labels > 3U ? 3U : labels;
	p = name->ndata;

	for (n = 0; n < numlabels - 1; n++) {
		unsigned char ch, llen;
		unsigned int firstoffset, length;

		firstoffset = (unsigned int)(p - name->ndata);
		length = name->length - firstoffset;

		/*
		 * We calculate the table index using the first
		 * character in the first label of the suffix name.
		 */
		ch = p[1];
		i = tableindex[ch];
		if (ISC_LIKELY((cctx->allowed &
				DNS_COMPRESS_CASESENSITIVE) != 0))
		{
			for (node = cctx->table[i];
			     node != NULL;
			     node = node->next)
			{
				if (ISC_UNLIKELY(node->name.length != length))
					continue;

				if (ISC_LIKELY(memcmp(node->name.ndata,
						      p, length) == 0))
					goto found;
			}
		} else {
			for (node = cctx->table[i];
			     node != NULL;
			     node = node->next)
			{
				unsigned int l, count;
				unsigned char c;
				unsigned char *label1, *label2;

				if (ISC_UNLIKELY(node->name.length != length))
					continue;

				l = labels - n;
				if (ISC_UNLIKELY(node->name.labels != l))
					continue;

				label1 = node->name.ndata;
				label2 = p;
				while (ISC_LIKELY(l-- > 0)) {
					count = *label1++;
					if (count != *label2++)
						goto cont1;

					/* no bitstring support */
					INSIST(count <= 63);

					/* Loop unrolled for performance */
					while (ISC_LIKELY(count > 3)) {
						c = maptolower[label1[0]];
						if (c != maptolower[label2[0]])
							goto cont1;
						c = maptolower[label1[1]];
						if (c != maptolower[label2[1]])
							goto cont1;
						c = maptolower[label1[2]];
						if (c != maptolower[label2[2]])
							goto cont1;
						c = maptolower[label1[3]];
						if (c != maptolower[label2[3]])
							goto cont1;
						count -= 4;
						label1 += 4;
						label2 += 4;
					}
					while (ISC_LIKELY(count-- > 0)) {
						c = maptolower[*label1++];
						if (c != maptolower[*label2++])
							goto cont1;
					}
				}
				break;
 cont1:
				continue;
			}
		}

		if (node != NULL)
			break;

		llen = *p;
		p += llen + 1;
	}

 found:
	/*
	 * If node == NULL, we found no match at all.
	 */
	if (node == NULL)
		return (ISC_FALSE);

	if (n == 0)
		dns_name_reset(prefix);
	else
		dns_name_getlabelsequence(name, 0, n, prefix);

	*offset = (node->offset & 0x7fff);
	return (ISC_TRUE);
}
Esempio n. 3
0
static int setup_follow_possible_cname(dnskey_glob   *gs,
				       dnskey_lookup *dl)
{
	int ret;

	dl->cname_count++;

	/*
	 * If we are on an odd cycle (starting with 1),
	 * then convert to dns_name_t so that we can compare later.
	 *
	 * This detects loops in the CNAME processing, while still
	 * allowing an arbitrary number of CNAMEs to be followed. 
	 */
	if(dl->cname_count & 1) 
	{
		isc_buffer_t fqdn_src;
		isc_buffer_t *fqdn_dst;

		if(dl->cname_count == 1)
		{
			memset(&dl->last_cname, 0, sizeof(dl->last_cname));
			dns_name_init(&dl->last_cname, NULL);
		}
		else
		{
			dns_name_reset(&dl->last_cname);
		}

		fqdn_dst=NULL;

		isc_buffer_init(&fqdn_src, dl->fqdn, strlen(dl->fqdn));
		isc_buffer_add(&fqdn_src, strlen(dl->fqdn));

		isc_buffer_allocate(gs->iscmem, &fqdn_dst, strlen(dl->fqdn)+1);

#if 0
		if(dl->last_cname_used) {
			dns_name_free(&dl->last_cname, gs->iscmem);
		}
#endif
		dl->last_cname_used = 1;
		if(dns_name_fromtext(&dl->last_cname,
				     &fqdn_src,
				     NULL,
				     1,
				     fqdn_dst) != ISC_R_SUCCESS) {
			return 0;
		}

		/* something else here ? */
	}
				 
	ret = lwres_getrrsetbyname_init(dl->fqdn, dns_rdataclass_in,
					dns_rdatatype_cname, 0 /*flags*/,
					gs->lwctx,
					&dl->las);

	if(ret != ERRSET_SUCCESS) {
		return 0;
	}

	lwres_getrrsetbyname_xmit(gs->lwctx, &dl->las);

	return 1;
}