// Sort A1 and A2 according to the values in A1
static void sort(StringArray& a1, StringArray& a2)
{
    assert(a1.size() == a2.size());

    // Shell sort -- simple and fast
    int h = 1;
    do {
	h = h * 3 + 1;
    } while (h <= a1.size());
    do {
	h /= 3;
	for (int i = h; i < a1.size(); i++)
	{
	    string v1 = a1[i];
	    string v2 = a2[i];
	    int j;
	    for (j = i; j >= h && smart_compare(a1[j - h], v1) > 0; j -= h)
	    {
		a1[j] = a1[j - h];
		a2[j] = a2[j - h];
	    }
	    if (i != j)
	    {
		a1[j] = v1;
		a2[j] = v2;
	    }
	}
    } while (h != 1);
}
Exemple #2
0
/** Find rrset. If equal to previous it is fast. hash if not so.
 * @param msg: the message with hash table.
 * @param pkt: the packet in wireformat (needed for compression ptrs).
 * @param dname: pointer to start of dname (compressed) in packet.
 * @param dnamelen: uncompressed wirefmt length of dname.
 * @param type: type of current rr.
 * @param dclass: class of current rr.
 * @param hash: hash value is returned if the rrset could not be found.
 * @param rrset_flags: is returned if the rrset could not be found.
 * @param prev_dname_first: dname of last seen RR. First seen dname.
 * @param prev_dname_last: dname of last seen RR. Last seen dname.
 * @param prev_dnamelen: dname len of last seen RR.
 * @param prev_type: type of last seen RR.
 * @param prev_dclass: class of last seen RR.
 * @param rrset_prev: last seen RRset.
 * @param section: the current section in the packet.
 * @param region: used to allocate temporary parsing data.
 * @return 0 on out of memory.
 */
static int
find_rrset(struct msg_parse* msg, sldns_buffer* pkt, uint8_t* dname, 
	size_t dnamelen, uint16_t type, uint16_t dclass, hashvalue_t* hash, 
	uint32_t* rrset_flags,
	uint8_t** prev_dname_first, uint8_t** prev_dname_last,
	size_t* prev_dnamelen, uint16_t* prev_type,
	uint16_t* prev_dclass, struct rrset_parse** rrset_prev,
	sldns_pkt_section section, struct regional* region)
{
	hashvalue_t dname_h = pkt_hash_rrset_first(pkt, dname);
	uint16_t covtype;
	if(*rrset_prev) {
		/* check if equal to previous item */
		if(type == *prev_type && dclass == *prev_dclass &&
			dnamelen == *prev_dnamelen &&
			smart_compare(pkt, dname, *prev_dname_first, 
				*prev_dname_last) == 0 &&
			type != LDNS_RR_TYPE_RRSIG) {
			/* same as previous */
			*prev_dname_last = dname;
			return 1;
		}
		/* check if rrsig over previous item */
		if(type == LDNS_RR_TYPE_RRSIG && dclass == *prev_dclass &&
			pkt_rrsig_covered_equals(pkt, sldns_buffer_current(pkt),
				*prev_type) &&
			smart_compare(pkt, dname, *prev_dname_first,
				*prev_dname_last) == 0) {
			/* covers previous */
			*prev_dname_last = dname;
			return 1;
		}
	}
	/* find by hashing and lookup in hashtable */
	*rrset_flags = pkt_rrset_flags(pkt, type, section);
	
	/* if rrsig - try to lookup matching data set first */
	if(type == LDNS_RR_TYPE_RRSIG && pkt_rrsig_covered(pkt, 
		sldns_buffer_current(pkt), &covtype)) {
		*hash = pkt_hash_rrset_rest(dname_h, covtype, dclass, 
			*rrset_flags);
		*rrset_prev = msgparse_hashtable_lookup(msg, pkt, *hash, 
			*rrset_flags, dname, dnamelen, covtype, dclass);
		if(!*rrset_prev && covtype == LDNS_RR_TYPE_NSEC) {
			/* if NSEC try with NSEC apex bit twiddled */
			*rrset_flags ^= PACKED_RRSET_NSEC_AT_APEX;
			*hash = pkt_hash_rrset_rest(dname_h, covtype, dclass, 
				*rrset_flags);
			*rrset_prev = msgparse_hashtable_lookup(msg, pkt, 
				*hash, *rrset_flags, dname, dnamelen, covtype, 
				dclass);
			if(!*rrset_prev) /* untwiddle if not found */
				*rrset_flags ^= PACKED_RRSET_NSEC_AT_APEX;
		}
		if(!*rrset_prev && covtype == LDNS_RR_TYPE_SOA) {
			/* if SOA try with SOA neg flag twiddled */
			*rrset_flags ^= PACKED_RRSET_SOA_NEG;
			*hash = pkt_hash_rrset_rest(dname_h, covtype, dclass, 
				*rrset_flags);
			*rrset_prev = msgparse_hashtable_lookup(msg, pkt, 
				*hash, *rrset_flags, dname, dnamelen, covtype, 
				dclass);
			if(!*rrset_prev) /* untwiddle if not found */
				*rrset_flags ^= PACKED_RRSET_SOA_NEG;
		}
		if(*rrset_prev) {
			*prev_dname_first = (*rrset_prev)->dname;
			*prev_dname_last = dname;
			*prev_dnamelen = dnamelen;
			*prev_type = covtype;
			*prev_dclass = dclass;
			return 1;
		}
	}
	if(type != LDNS_RR_TYPE_RRSIG) {
		int hasother = 0;
		/* find matching rrsig */
		*hash = pkt_hash_rrset_rest(dname_h, LDNS_RR_TYPE_RRSIG, 
			dclass, 0);
		*rrset_prev = msgparse_hashtable_lookup(msg, pkt, *hash, 
			0, dname, dnamelen, LDNS_RR_TYPE_RRSIG, 
			dclass);
		if(*rrset_prev && rrset_has_sigover(pkt, *rrset_prev, type,
			&hasother)) {
			/* yes! */
			*prev_dname_first = (*rrset_prev)->dname;
			*prev_dname_last = dname;
			*prev_dnamelen = dnamelen;
			*prev_type = type;
			*prev_dclass = dclass;
			*rrset_prev = change_rrsig_rrset(*rrset_prev, msg, 
				pkt, type, *rrset_flags, hasother, section, 
				region);
			if(!*rrset_prev) return 0;
			return 1;
		}
	}

	*hash = pkt_hash_rrset_rest(dname_h, type, dclass, *rrset_flags);
	*rrset_prev = msgparse_hashtable_lookup(msg, pkt, *hash, *rrset_flags, 
		dname, dnamelen, type, dclass);
	if(*rrset_prev)
		*prev_dname_first = (*rrset_prev)->dname;
	else 	*prev_dname_first = dname;
	*prev_dname_last = dname;
	*prev_dnamelen = dnamelen;
	*prev_type = type;
	*prev_dclass = dclass;
	return 1;
}