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