/** test dname_strict_subdomain */ static void dname_test_strict_subdomain(void) { unit_show_func("util/data/dname.c", "dname_strict_subdomain"); unit_assert(!dname_strict_subdomain( (uint8_t*)"", 1, (uint8_t*)"", 1)); unit_assert(dname_strict_subdomain( (uint8_t*)"\003com", 2, (uint8_t*)"", 1)); unit_assert(!dname_strict_subdomain( (uint8_t*)"", 1, (uint8_t*)"\003com", 2)); unit_assert(dname_strict_subdomain( (uint8_t*)"\007example\003com", 3, (uint8_t*)"\003com", 2)); unit_assert(!dname_strict_subdomain( (uint8_t*)"\003com", 2, (uint8_t*)"\007example\003com", 3)); unit_assert(dname_strict_subdomain( (uint8_t*)"\007example\003com", 3, (uint8_t*)"", 1)); unit_assert(!dname_strict_subdomain( (uint8_t*)"\003net", 2, (uint8_t*)"\003com", 2)); unit_assert(!dname_strict_subdomain( (uint8_t*)"\003net", 2, (uint8_t*)"\003org", 2)); unit_assert(!dname_strict_subdomain( (uint8_t*)"\007example\003net", 3, (uint8_t*)"\003org", 2)); unit_assert(!dname_strict_subdomain( (uint8_t*)"\003net", 2, (uint8_t*)"\007example\003org", 3)); }
/** returns true if the node is terminal so no deeper domain names exist */ static int is_terminal(struct local_data* d) { /* for empty nonterminals, the deeper domain names are sorted * right after them, so simply check the next name in the tree */ struct local_data* n = (struct local_data*)rbtree_next(&d->node); if(n == (struct local_data*)RBTREE_NULL) return 1; /* last in tree, no deeper node */ if(dname_strict_subdomain(n->name, n->namelabs, d->name, d->namelabs)) return 0; /* there is a deeper node */ return 1; }
int iter_msg_from_zone(struct dns_msg* msg, struct delegpt* dp, enum response_type type, uint16_t dclass) { if(!msg || !dp || !msg->rep || !dp->name) return 0; /* SOA RRset - always from reply zone */ if(reply_find_rrset_section_an(msg->rep, dp->name, dp->namelen, LDNS_RR_TYPE_SOA, dclass) || reply_find_rrset_section_ns(msg->rep, dp->name, dp->namelen, LDNS_RR_TYPE_SOA, dclass)) return 1; if(type == RESPONSE_TYPE_REFERRAL) { size_t i; /* if it adds a single label, i.e. we expect .com, * and referral to example.com. NS ... , then origin zone * is .com. For a referral to sub.example.com. NS ... then * we do not know, since example.com. may be in between. */ for(i=0; i<msg->rep->an_numrrsets+msg->rep->ns_numrrsets; i++) { struct ub_packed_rrset_key* s = msg->rep->rrsets[i]; if(ntohs(s->rk.type) == LDNS_RR_TYPE_NS && ntohs(s->rk.rrset_class) == dclass) { int l = dname_count_labels(s->rk.dname); if(l == dp->namelabs + 1 && dname_strict_subdomain(s->rk.dname, l, dp->name, dp->namelabs)) return 1; } } return 0; } log_assert(type==RESPONSE_TYPE_ANSWER || type==RESPONSE_TYPE_CNAME); /* not a referral, and not lame delegation (upwards), so, * any NS rrset must be from the zone itself */ if(reply_find_rrset_section_an(msg->rep, dp->name, dp->namelen, LDNS_RR_TYPE_NS, dclass) || reply_find_rrset_section_ns(msg->rep, dp->name, dp->namelen, LDNS_RR_TYPE_NS, dclass)) return 1; /* a DNSKEY set is expected at the zone apex as well */ /* this is for 'minimal responses' for DNSKEYs */ if(reply_find_rrset_section_an(msg->rep, dp->name, dp->namelen, LDNS_RR_TYPE_DNSKEY, dclass)) return 1; return 0; }
struct iter_hints_stub* hints_lookup_stub(struct iter_hints* hints, uint8_t* qname, uint16_t qclass, struct delegpt* cache_dp) { size_t len; int labs; struct iter_hints_stub *r; /* first lookup the stub */ labs = dname_count_size_labels(qname, &len); r = (struct iter_hints_stub*)name_tree_lookup(&hints->tree, qname, len, labs, qclass); if(!r) return NULL; /* If there is no cache (root prime situation) */ if(cache_dp == NULL) { if(r->dp->namelabs != 1) return r; /* no cache dp, use any non-root stub */ return NULL; } /* * If the stub is same as the delegation we got * And has noprime set, we need to 'prime' to use this stub instead. */ if(r->noprime && query_dname_compare(cache_dp->name, r->dp->name)==0) return r; /* use this stub instead of cached dp */ /* * If our cached delegation point is above the hint, we need to prime. */ if(dname_strict_subdomain(r->dp->name, r->dp->namelabs, cache_dp->name, cache_dp->namelabs)) return r; /* need to prime this stub */ return NULL; }
/** iterate over the kiddies of the given name and set their parent ptr */ static void set_kiddo_parents(struct local_zone* z, struct local_zone* match, struct local_zone* newp) { /* both zones and z are locked already */ /* in the sorted rbtree, the kiddies of z are located after z */ /* z must be present in the tree */ struct local_zone* p = z; p = (struct local_zone*)rbtree_next(&p->node); while(p!=(struct local_zone*)RBTREE_NULL && p->dclass == z->dclass && dname_strict_subdomain(p->name, p->namelabs, z->name, z->namelabs)) { /* update parent ptr */ /* only when matches with existing parent pointer, so that * deeper child structures are not touched, i.e. * update of x, and a.x, b.x, f.b.x, g.b.x, c.x, y * gets to update a.x, b.x and c.x */ lock_rw_wrlock(&p->lock); if(p->parent == match) p->parent = newp; lock_rw_unlock(&p->lock); p = (struct local_zone*)rbtree_next(&p->node); } }
int dname_strict_subdomain_c(uint8_t* d1, uint8_t* d2) { return dname_strict_subdomain(d1, dname_count_labels(d1), d2, dname_count_labels(d2)); }