/** find and add DS or NSEC to delegation msg */ static void find_add_ds(struct module_env* env, struct regional* region, struct dns_msg* msg, struct delegpt* dp, time_t now) { /* Lookup the DS or NSEC at the delegation point. */ struct ub_packed_rrset_key* rrset = rrset_cache_lookup( env->rrset_cache, dp->name, dp->namelen, LDNS_RR_TYPE_DS, msg->qinfo.qclass, 0, now, 0); if(!rrset) { /* NOTE: this won't work for alternate NSEC schemes * (opt-in, NSEC3) */ rrset = rrset_cache_lookup(env->rrset_cache, dp->name, dp->namelen, LDNS_RR_TYPE_NSEC, msg->qinfo.qclass, 0, now, 0); /* Note: the PACKED_RRSET_NSEC_AT_APEX flag is not used. * since this is a referral, we need the NSEC at the parent * side of the zone cut, not the NSEC at apex side. */ if(rrset && nsec_has_type(rrset, LDNS_RR_TYPE_DS)) { lock_rw_unlock(&rrset->entry.lock); rrset = NULL; /* discard wrong NSEC */ } } if(rrset) { /* add it to auth section. This is the second rrset. */ if((msg->rep->rrsets[msg->rep->rrset_count] = packed_rrset_copy_region(rrset, region, now))) { msg->rep->ns_numrrsets++; msg->rep->rrset_count++; } lock_rw_unlock(&rrset->entry.lock); } }
/** * See if rrset exists in rrset cache. * If it does, the bit is checked, and if not expired, it is returned * allocated in region. * @param rrset_cache: rrset cache * @param qname: to lookup rrset name * @param qname_len: length of qname. * @param qtype: type of rrset to lookup, host order * @param qclass: class of rrset to lookup, host order * @param flags: flags for rrset to lookup * @param region: where to alloc result * @param checkbit: if true, a bit in the nsec typemap is checked for absence. * @param checktype: which bit to check * @param now: to check ttl against * @return rrset or NULL */ static struct ub_packed_rrset_key* grab_nsec(struct rrset_cache* rrset_cache, uint8_t* qname, size_t qname_len, uint16_t qtype, uint16_t qclass, uint32_t flags, struct regional* region, int checkbit, uint16_t checktype, uint32_t now) { struct ub_packed_rrset_key* r, *k = rrset_cache_lookup(rrset_cache, qname, qname_len, qtype, qclass, flags, now, 0); struct packed_rrset_data* d; if(!k) return NULL; d = (struct packed_rrset_data*)k->entry.data; if(d->ttl < now) { lock_rw_unlock(&k->entry.lock); return NULL; } /* only secure or unchecked records that have signatures. */ if( ! ( d->security == sec_status_secure || (d->security == sec_status_unchecked && d->rrsig_count > 0) ) ) { lock_rw_unlock(&k->entry.lock); return NULL; } /* check if checktype is absent */ if(checkbit && ( (qtype == LDNS_RR_TYPE_NSEC && nsec_has_type(k, checktype)) || (qtype == LDNS_RR_TYPE_NSEC3 && !nsec3_no_type(k, checktype)) )) { lock_rw_unlock(&k->entry.lock); return NULL; } /* looks OK! copy to region and return it */ r = packed_rrset_copy_region(k, region, now); /* if it failed, we return the NULL */ lock_rw_unlock(&k->entry.lock); return r; }