/**
 * Store potential poison in the cache (only if hardening disabled).
 * The rrset is stored in the cache but removed from the message.
 * So that it will be used for infrastructure purposes, but not be
 * returned to the client.
 * @param pkt: packet
 * @param msg: message parsed
 * @param env: environment with cache
 * @param rrset: to store.
 */
static void
store_rrset(ldns_buffer* pkt, struct msg_parse* msg, struct module_env* env,
            struct rrset_parse* rrset)
{
    struct ub_packed_rrset_key* k;
    struct packed_rrset_data* d;
    struct rrset_ref ref;
    uint32_t now = *env->now;

    k = alloc_special_obtain(env->alloc);
    if(!k)
        return;
    k->entry.data = NULL;
    if(!parse_copy_decompress_rrset(pkt, msg, rrset, NULL, k)) {
        alloc_special_release(env->alloc, k);
        return;
    }
    d = (struct packed_rrset_data*)k->entry.data;
    packed_rrset_ttl_add(d, now);
    ref.key = k;
    ref.id = k->id;
    /*ignore ret: it was in the cache, ref updated */
    (void)rrset_cache_update(env->rrset_cache, &ref,
                             env->alloc, now);
}
Example #2
0
struct ub_packed_rrset_key* 
packed_rrset_copy_alloc(struct ub_packed_rrset_key* key, 
	struct alloc_cache* alloc, time_t now)
{
	struct packed_rrset_data* fd, *dd;
	struct ub_packed_rrset_key* dk = alloc_special_obtain(alloc);
	if(!dk) return NULL;
	fd = (struct packed_rrset_data*)key->entry.data;
	dk->entry.hash = key->entry.hash;
	dk->rk = key->rk;
	dk->rk.dname = (uint8_t*)memdup(key->rk.dname, key->rk.dname_len);
	if(!dk->rk.dname) {
		alloc_special_release(alloc, dk);
		return NULL;
	}
	dd = (struct packed_rrset_data*)memdup(fd, packed_rrset_sizeof(fd));
	if(!dd) {
		free(dk->rk.dname);
		alloc_special_release(alloc, dk);
		return NULL;
	}
	packed_rrset_ptr_fixup(dd);
	dk->entry.data = (void*)dd;
	packed_rrset_ttl_add(dd, now);
	return dk;
}
Example #3
0
int
dns_cache_store(struct module_env* env, struct query_info* msgqinf,
        struct reply_info* msgrep, int is_referral, time_t leeway, int pside,
	struct regional* region, uint32_t flags)
{
	struct reply_info* rep = NULL;
	/* alloc, malloc properly (not in region, like msg is) */
	rep = reply_info_copy(msgrep, env->alloc, NULL);
	if(!rep)
		return 0;
	/* ttl must be relative ;i.e. 0..86400 not  time(0)+86400.
	 * the env->now is added to message and RRsets in this routine. */
	/* the leeway is used to invalidate other rrsets earlier */

	if(is_referral) {
		/* store rrsets */
		struct rrset_ref ref;
		size_t i;
		for(i=0; i<rep->rrset_count; i++) {
			packed_rrset_ttl_add((struct packed_rrset_data*)
				rep->rrsets[i]->entry.data, *env->now);
			ref.key = rep->rrsets[i];
			ref.id = rep->rrsets[i]->id;
			/*ignore ret: it was in the cache, ref updated */
			/* no leeway for typeNS */
			(void)rrset_cache_update(env->rrset_cache, &ref, 
				env->alloc, *env->now + 
				((ntohs(ref.key->rk.type)==LDNS_RR_TYPE_NS
				 && !pside) ? 0:leeway));
		}
		free(rep);
		return 1;
	} else {
		/* store msg, and rrsets */
		struct query_info qinf;
		hashvalue_type h;

		qinf = *msgqinf;
		qinf.qname = memdup(msgqinf->qname, msgqinf->qname_len);
		if(!qinf.qname) {
			reply_info_parsedelete(rep, env->alloc);
			return 0;
		}
		/* fixup flags to be sensible for a reply based on the cache */
		/* this module means that RA is available. It is an answer QR. 
		 * Not AA from cache. Not CD in cache (depends on client bit). */
		rep->flags |= (BIT_RA | BIT_QR);
		rep->flags &= ~(BIT_AA | BIT_CD);
		h = query_info_hash(&qinf, (uint16_t)flags);
		dns_cache_store_msg(env, &qinf, h, rep, leeway, pside, msgrep,
			flags, region);
		/* qname is used inside query_info_entrysetup, and set to 
		 * NULL. If it has not been used, free it. free(0) is safe. */
		free(qinf.qname);
	}
	return 1;
}