/* * 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); }
/* * 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); }
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; }