const dname_type * dname_replace(region_type* region, const dname_type* name, const dname_type* src, const dname_type* dest) { /* nomenclature: name is said to be <x>.<src>. x can be null. */ dname_type* res; int x_labels = name->label_count - src->label_count; int x_len = name->name_size - src->name_size; int i; assert(dname_is_subdomain(name, src)); /* check if final size is acceptable */ if(x_len+dest->name_size > MAXDOMAINLEN) return NULL; res = (dname_type*)region_alloc(region, sizeof(dname_type) + (x_labels+dest->label_count + x_len+dest->name_size) *sizeof(uint8_t)); res->name_size = x_len+dest->name_size; res->label_count = x_labels+dest->label_count; for(i=0; i<dest->label_count; i++) ((uint8_t*)dname_label_offsets(res))[i] = dname_label_offsets(dest)[i] + x_len; for(i=dest->label_count; i<res->label_count; i++) ((uint8_t*)dname_label_offsets(res))[i] = dname_label_offsets(name)[i - dest->label_count + src->label_count]; memcpy((uint8_t*)dname_name(res), dname_name(name), x_len); memcpy((uint8_t*)dname_name(res)+x_len, dname_name(dest), dest->name_size); assert(dname_is_subdomain(res, dest)); return res; }
/** create and write a zone */ int write_zone_to_udb(udb_base* udb, zone_type* zone, struct timespec* mtime, const char* file_str) { udb_ptr z; /* make udb dirty */ udb_base_set_userflags(udb, 1); /* find or create zone */ if(udb_zone_search(udb, &z, dname_name(domain_dname(zone->apex)), domain_dname(zone->apex)->name_size)) { /* wipe existing contents */ udb_zone_clear(udb, &z); } else { if(!udb_zone_create(udb, &z, dname_name(domain_dname( zone->apex)), domain_dname(zone->apex)->name_size)) { udb_base_set_userflags(udb, 0); return 0; } } /* set mtime */ ZONE(&z)->mtime = (uint64_t)mtime->tv_sec; ZONE(&z)->mtime_nsec = (uint64_t)mtime->tv_nsec; ZONE(&z)->is_changed = 0; udb_zone_set_log_str(udb, &z, NULL); udb_zone_set_file_str(udb, &z, file_str); /* write zone */ if(!write_zone(udb, &z, zone)) { udb_base_set_userflags(udb, 0); return 0; } udb_ptr_unlink(&z, udb); udb_base_set_userflags(udb, 0); return 1; }
static void encode_dname(query_type *q, domain_type *domain) { while (domain->parent && query_get_dname_offset(q, domain) == 0) { query_put_dname_offset(q, domain, buffer_position(q->packet)); DEBUG(DEBUG_NAME_COMPRESSION, 2, (LOG_INFO, "dname: %s, number: %lu, offset: %u\n", dname_to_string(domain_dname(domain), NULL), (unsigned long) domain->number, query_get_dname_offset(q, domain))); buffer_write(q->packet, dname_name(domain_dname(domain)), label_length(dname_name(domain_dname(domain))) + 1U); domain = domain->parent; } if (domain->parent) { DEBUG(DEBUG_NAME_COMPRESSION, 2, (LOG_INFO, "dname: %s, number: %lu, pointer: %u\n", dname_to_string(domain_dname(domain), NULL), (unsigned long) domain->number, query_get_dname_offset(q, domain))); assert(query_get_dname_offset(q, domain) <= MAX_COMPRESSION_OFFSET); buffer_write_u16(q->packet, 0xc000 | query_get_dname_offset(q, domain)); } else { buffer_write_u8(q->packet, 0); } }
const dname_type * dname_concatenate(region_type *region, const dname_type *left, const dname_type *right) { uint8_t temp[MAXDOMAINLEN]; assert(left->name_size + right->name_size - 1 <= MAXDOMAINLEN); memcpy(temp, dname_name(left), left->name_size - 1); memcpy(temp + left->name_size - 1, dname_name(right), right->name_size); return dname_make(region, temp, 0); }
/** * Make wildcard synthesis. * */ int dname_make_wildcard(struct region *region, struct dname const *dname, struct dname const **wildcard) { uint8_t name_size; uint8_t label_count; uint8_t *names; uint8_t *labels; struct dname *new_dname; unsigned int i; /* * Checks: * dname label_count + 1 < MAXLABELS * dname size + 2 < MAXDOMAINLEN */ if (dname->label_count > (MAXLABELS - 1)) { return EINVAL; } if (dname->name_size > (MAXDOMAINLEN - 2)) { return EINVAL; } label_count = dname->label_count + 1; name_size = dname->name_size + 2; new_dname = (struct dname *) region_alloc(region, sizeof(dname_type) + (label_count * sizeof(uint8_t)) + (name_size * sizeof(uint8_t))); if (new_dname == NULL) { return ENOMEM; } new_dname->label_count = label_count; new_dname->name_size = name_size; labels = (uint8_t *) dname_label_offsets(new_dname); memcpy(labels, dname_label_offsets(dname), dname->label_count * sizeof(uint8_t)); for (i = 0; i < dname->label_count; i++) { labels[i] += 2; } labels[i] = 0; names = (uint8_t *) dname_name(new_dname); *names++ = '\001'; *names++ = '*'; memcpy(names, dname_name(dname), dname->name_size * sizeof(uint8_t)); *wildcard = new_dname; return 0; }
int packet_encode_rr(query_type *q, domain_type *owner, rr_type *rr) { size_t truncation_mark; uint16_t rdlength = 0; size_t rdlength_pos; uint16_t j; assert(q); assert(owner); assert(rr); /* * If the record does not in fit in the packet the packet size * will be restored to the mark. */ truncation_mark = buffer_position(q->packet); encode_dname(q, owner); buffer_write_u16(q->packet, rr->type); buffer_write_u16(q->packet, rr->klass); buffer_write_u32(q->packet, rr->ttl); /* Reserve space for rdlength. */ rdlength_pos = buffer_position(q->packet); buffer_skip(q->packet, sizeof(rdlength)); for (j = 0; j < rr->rdata_count; ++j) { switch (rdata_atom_wireformat_type(rr->type, j)) { case RDATA_WF_COMPRESSED_DNAME: encode_dname(q, rdata_atom_domain(rr->rdatas[j])); break; case RDATA_WF_UNCOMPRESSED_DNAME: { const dname_type *dname = domain_dname( rdata_atom_domain(rr->rdatas[j])); buffer_write(q->packet, dname_name(dname), dname->name_size); break; } default: buffer_write(q->packet, rdata_atom_data(rr->rdatas[j]), rdata_atom_size(rr->rdatas[j])); break; } } if (!query_overflow(q)) { rdlength = (buffer_position(q->packet) - rdlength_pos - sizeof(rdlength)); buffer_write_u16_at(q->packet, rdlength_pos, rdlength); return 1; } else { buffer_set_position(q->packet, truncation_mark); query_clear_dname_offsets(q, truncation_mark); assert(!query_overflow(q)); return 0; } }
/** delete an RR */ void udb_del_rr(udb_base* udb, udb_ptr* z, rr_type* rr) { /* marshal the rdata (uncompressed) into a buffer */ uint8_t rdata[MAX_RDLENGTH]; size_t rdatalen = rr_marshal_rdata(rr, rdata, sizeof(rdata)); assert(udb); udb_zone_del_rr(udb, z, dname_name(domain_dname(rr->owner)), domain_dname(rr->owner)->name_size, rr->type, rr->klass, rdata, rdatalen); }
const char * dname_to_string_r(const dname_type *dname, const dname_type *origin, char* buf) { size_t i; size_t labels_to_convert = 0; int absolute = 1; char *dst; const uint8_t *src; if (!dname) { *buf = '\0'; return buf; } if (dname->label_count == 1) { strlcpy(buf, ".", sizeof(buf)); return buf; } labels_to_convert = dname->label_count - 1; if (origin && dname_is_subdomain(dname, origin)) { int common_labels = dname_label_match_count(dname, origin); labels_to_convert = dname->label_count - common_labels; absolute = 0; } dst = buf; src = dname_name(dname); for (i = 0; i < labels_to_convert; ++i) { size_t len = label_length(src); size_t j; ++src; for (j = 0; j < len; ++j) { uint8_t ch = *src++; if (isalnum(ch) || ch == '-' || ch == '_') { *dst++ = ch; } else if (ch == '.' || ch == '\\') { *dst++ = '\\'; *dst++ = ch; } else { snprintf(dst, 5, "\\%03u", (unsigned int)ch); dst += 4; } } *dst++ = '.'; } if (absolute) { *dst = '\0'; } else { *--dst = '\0'; } return buf; }
void xfrd_copy_soa(xfrd_soa_t* soa, rr_type* rr) { const uint8_t* rr_ns_wire = dname_name(domain_dname(rdata_atom_domain(rr->rdatas[0]))); uint8_t rr_ns_len = domain_dname(rdata_atom_domain(rr->rdatas[0]))->name_size; const uint8_t* rr_em_wire = dname_name(domain_dname(rdata_atom_domain(rr->rdatas[1]))); uint8_t rr_em_len = domain_dname(rdata_atom_domain(rr->rdatas[1]))->name_size; if(rr->type != TYPE_SOA || rr->rdata_count != 7) { log_msg(LOG_ERR, "xfrd: copy_soa called with bad rr, type %d rrs %u.", rr->type, rr->rdata_count); return; } DEBUG(DEBUG_XFRD,1, (LOG_INFO, "xfrd: copy_soa rr, type %d rrs %u, ttl %u.", rr->type, rr->rdata_count, rr->ttl)); soa->type = htons(rr->type); soa->klass = htons(rr->klass); soa->ttl = htonl(rr->ttl); soa->rdata_count = htons(rr->rdata_count); /* copy dnames */ soa->prim_ns[0] = rr_ns_len; memcpy(soa->prim_ns+1, rr_ns_wire, rr_ns_len); soa->email[0] = rr_em_len; memcpy(soa->email+1, rr_em_wire, rr_em_len); /* already in network format */ memcpy(&soa->serial, rdata_atom_data(rr->rdatas[2]), sizeof(uint32_t)); memcpy(&soa->refresh, rdata_atom_data(rr->rdatas[3]), sizeof(uint32_t)); memcpy(&soa->retry, rdata_atom_data(rr->rdatas[4]), sizeof(uint32_t)); memcpy(&soa->expire, rdata_atom_data(rr->rdatas[5]), sizeof(uint32_t)); memcpy(&soa->minimum, rdata_atom_data(rr->rdatas[6]), sizeof(uint32_t)); DEBUG(DEBUG_XFRD,1, (LOG_INFO, "xfrd: copy_soa rr, serial %u refresh %u retry %u expire %u", ntohl(soa->serial), ntohl(soa->refresh), ntohl(soa->retry), ntohl(soa->expire))); }
/** * Create new domain name. * */ dname_type* dname_create(region_type* r, const char* str) { uint8_t wire[DNAME_MAXLEN]; uint8_t label_offsets[DNAME_MAXLEN]; uint8_t label_count = 0; size_t size = 0; const uint8_t* label = wire; dname_type *dname; ssize_t i; assert(r); assert(str); if (!dname_str2wire(wire, str)) { fprintf(stderr, "[%s] error: parse dname %s failed", logstr, str); return NULL; } while (1) { if (label_is_pointer(label)) { return NULL; } label_offsets[label_count] = (uint8_t) (label - wire); ++label_count; size += label_length(label) + 1; if (label_is_root(label)) { break; } label = label_next(label); } if (size > DNAME_MAXLEN) { return NULL; } assert(label_count <= DNAME_MAXLEN / 2 + 1); /* reverse label offsets. */ /* reverse label offsets. */ for (i = 0; i < label_count / 2; ++i) { uint8_t tmp = label_offsets[i]; label_offsets[i] = label_offsets[label_count - i - 1]; label_offsets[label_count - i - 1] = tmp; } dname = (dname_type *) region_alloc(r, (sizeof(dname_type) + (label_count + size) * sizeof(uint8_t))); dname->size = size; dname->label_count = label_count; memcpy((uint8_t *) dname_label_offsets(dname), label_offsets, label_count * sizeof(uint8_t)); memcpy((uint8_t *) dname_name(dname), wire, size * sizeof(uint8_t)); return dname; }
/** write rr */ int udb_write_rr(udb_base* udb, udb_ptr* z, rr_type* rr) { /* marshal the rdata (uncompressed) into a buffer */ uint8_t rdata[MAX_RDLENGTH]; size_t rdatalen = 0; unsigned i; assert(rr); for(i=0; i<rr->rdata_count; i++) { rdatalen += add_rdata(rr, i, rdata+rdatalen, sizeof(rdata)-rdatalen); } assert(udb); return udb_zone_add_rr(udb, z, dname_name(domain_dname(rr->owner)), domain_dname(rr->owner)->name_size, rr->type, rr->klass, rr->ttl, rdata, rdatalen); }
/** * Print domain name. * */ void dname_print(FILE* fd, dname_type* dname) { static char buf[DNAME_MAXLEN*5]; size_t i; size_t labels_to_convert; char* dst; const uint8_t* src; if (!dname || !fd) { return; } assert(dname->label_count > 0); if (dname->label_count == 1) { fprintf(fd, "."); return; } labels_to_convert = dname->label_count - 1; dst = buf; src = dname_name(dname); for (i = 0; i < labels_to_convert; ++i) { size_t len = label_length(src); size_t j; ++src; for (j = 0; j < len; ++j) { uint8_t ch = *src++; if (isalnum(ch) || ch == '-' || ch == '_') { *dst++ = ch; } else if (ch == '.' || ch == '\\' || ch == '(' || ch == ')' || ch == ';') { *dst++ = '\\'; *dst++ = ch; } else { snprintf(dst, 5, "\\%03u", (unsigned int)ch); dst += 4; } } *dst++ = '.'; } *dst = '\0'; fprintf(fd, "%s", buf); return; }
void xfrd_setup_packet(buffer_type* packet, uint16_t type, uint16_t klass, const dname_type* dname) { /* Set up the header */ buffer_clear(packet); ID_SET(packet, qid_generate()); FLAGS_SET(packet, 0); OPCODE_SET(packet, OPCODE_QUERY); QDCOUNT_SET(packet, 1); ANCOUNT_SET(packet, 0); NSCOUNT_SET(packet, 0); ARCOUNT_SET(packet, 0); buffer_skip(packet, QHEADERSZ); /* The question record. */ buffer_write(packet, dname_name(dname), dname->name_size); buffer_write_u16(packet, type); buffer_write_u16(packet, klass); }
/** add an rdata (uncompressed) to the destination */ static size_t add_rdata(rr_type* rr, unsigned i, uint8_t* buf, size_t buflen) { switch(rdata_atom_wireformat_type(rr->type, i)) { case RDATA_WF_COMPRESSED_DNAME: case RDATA_WF_UNCOMPRESSED_DNAME: { const dname_type* dname = domain_dname( rdata_atom_domain(rr->rdatas[i])); if(dname->name_size > buflen) return 0; memmove(buf, dname_name(dname), dname->name_size); return dname->name_size; } default: break; } if(rdata_atom_size(rr->rdatas[i]) > buflen) return 0; memmove(buf, rdata_atom_data(rr->rdatas[i]), rdata_atom_size(rr->rdatas[i])); return rdata_atom_size(rr->rdatas[i]); }
int rdata_atoms_to_unknown_string(buffer_type *output, rrtype_descriptor_type *descriptor, size_t rdata_count, rdata_atom_type *rdatas) { size_t i; size_t size = rdata_maximum_wireformat_size(descriptor, rdata_count, rdatas); buffer_printf(output, " \\# %lu ", (unsigned long) size); for (i = 0; i < rdata_count; ++i) { if (rdata_atom_is_domain(descriptor->type, i)) { const dname_type *dname = domain_dname(rdata_atom_domain(rdatas[i])); hex_to_string( output, dname_name(dname), dname->name_size); } else { hex_to_string(output, rdata_atom_data(rdatas[i]), rdata_atom_size(rdatas[i])); } } return 1; }
const dname_type * dname_make(region_type *region, const uint8_t *name, int normalize) { size_t name_size = 0; uint8_t label_offsets[MAXDOMAINLEN]; uint8_t label_count = 0; const uint8_t *label = name; dname_type *result; ssize_t i; assert(name); while (1) { if (label_is_pointer(label)) return NULL; label_offsets[label_count] = (uint8_t) (label - name); ++label_count; name_size += label_length(label) + 1; if (label_is_root(label)) break; label = label_next(label); } if (name_size > MAXDOMAINLEN) return NULL; assert(label_count <= MAXDOMAINLEN / 2 + 1); /* Reverse label offsets. */ for (i = 0; i < label_count / 2; ++i) { uint8_t tmp = label_offsets[i]; label_offsets[i] = label_offsets[label_count - i - 1]; label_offsets[label_count - i - 1] = tmp; } result = (dname_type *) region_alloc( region, (sizeof(dname_type) + (label_count + name_size) * sizeof(uint8_t))); result->name_size = name_size; result->label_count = label_count; memcpy((uint8_t *) dname_label_offsets(result), label_offsets, label_count * sizeof(uint8_t)); if (normalize) { uint8_t *dst = (uint8_t *) dname_name(result); const uint8_t *src = name; while (!label_is_root(src)) { ssize_t len = label_length(src); *dst++ = *src++; for (i = 0; i < len; ++i) { *dst++ = DNAME_NORMALIZE(*src++); } } *dst = *src; } else { memcpy((uint8_t *) dname_name(result), name, name_size * sizeof(uint8_t)); } return result; }
ssize_t rdata_wireformat_to_rdata_atoms(region_type *region, domain_table_type *owners, uint16_t rrtype, uint16_t data_size, buffer_type *packet, rdata_atom_type **rdatas) { size_t end = buffer_position(packet) + data_size; size_t i; rdata_atom_type temp_rdatas[MAXRDATALEN]; rrtype_descriptor_type *descriptor = rrtype_descriptor_by_type(rrtype); region_type *temp_region; assert(descriptor->maximum <= MAXRDATALEN); if (!buffer_available(packet, data_size)) { return -1; } temp_region = region_create(xalloc, free); for (i = 0; i < descriptor->maximum; ++i) { int is_domain = 0; int is_normalized = 0; int is_wirestore = 0; size_t length = 0; int required = i < descriptor->minimum; switch (rdata_atom_wireformat_type(rrtype, i)) { case RDATA_WF_COMPRESSED_DNAME: case RDATA_WF_UNCOMPRESSED_DNAME: is_domain = 1; is_normalized = 1; break; case RDATA_WF_LITERAL_DNAME: is_domain = 1; is_wirestore = 1; break; case RDATA_WF_BYTE: length = sizeof(uint8_t); break; case RDATA_WF_SHORT: length = sizeof(uint16_t); break; case RDATA_WF_LONG: length = sizeof(uint32_t); break; case RDATA_WF_TEXTS: case RDATA_WF_LONG_TEXT: length = end - buffer_position(packet); break; case RDATA_WF_TEXT: case RDATA_WF_BINARYWITHLENGTH: /* Length is stored in the first byte. */ length = 1; if (buffer_position(packet) + length <= end) { length += buffer_current(packet)[length - 1]; } break; case RDATA_WF_A: length = sizeof(in_addr_t); break; case RDATA_WF_AAAA: length = IP6ADDRLEN; break; case RDATA_WF_ILNP64: length = IP6ADDRLEN/2; break; case RDATA_WF_EUI48: length = EUI48ADDRLEN; break; case RDATA_WF_EUI64: length = EUI64ADDRLEN; break; case RDATA_WF_BINARY: /* Remaining RDATA is binary. */ length = end - buffer_position(packet); break; case RDATA_WF_APL: length = (sizeof(uint16_t) /* address family */ + sizeof(uint8_t) /* prefix */ + sizeof(uint8_t)); /* length */ if (buffer_position(packet) + length <= end) { /* Mask out negation bit. */ length += (buffer_current(packet)[length - 1] & APL_LENGTH_MASK); } break; case RDATA_WF_IPSECGATEWAY: switch(rdata_atom_data(temp_rdatas[1])[0]) /* gateway type */ { default: case IPSECKEY_NOGATEWAY: length = 0; break; case IPSECKEY_IP4: length = IP4ADDRLEN; break; case IPSECKEY_IP6: length = IP6ADDRLEN; break; case IPSECKEY_DNAME: is_domain = 1; is_normalized = 1; is_wirestore = 1; break; } break; } if (is_domain) { const dname_type *dname; if (!required && buffer_position(packet) == end) { break; } dname = dname_make_from_packet( temp_region, packet, 1, is_normalized); if (!dname || buffer_position(packet) > end) { /* Error in domain name. */ region_destroy(temp_region); return -1; } if(is_wirestore) { temp_rdatas[i].data = (uint16_t *) region_alloc( region, sizeof(uint16_t) + ((size_t)dname->name_size)); temp_rdatas[i].data[0] = dname->name_size; memcpy(temp_rdatas[i].data+1, dname_name(dname), dname->name_size); } else { temp_rdatas[i].domain = domain_table_insert(owners, dname); temp_rdatas[i].domain->usage ++; } } else { if (buffer_position(packet) + length > end) { if (required) { /* Truncated RDATA. */ region_destroy(temp_region); return -1; } else { break; } } if (!required && buffer_position(packet) == end) { break; } temp_rdatas[i].data = (uint16_t *) region_alloc( region, sizeof(uint16_t) + length); temp_rdatas[i].data[0] = length; buffer_read(packet, temp_rdatas[i].data + 1, length); } } if (buffer_position(packet) < end) { /* Trailing garbage. */ region_destroy(temp_region); return -1; } *rdatas = (rdata_atom_type *) region_alloc_array_init( region, temp_rdatas, i, sizeof(rdata_atom_type)); region_destroy(temp_region); return (ssize_t)i; }
void namedb_write_zonefile(struct nsd* nsd, struct zone_options* zopt) { const char* zfile; int notexist = 0; zone_type* zone; /* if no zone exists, it has no contents or it has no zonefile * configured, then no need to write data to disk */ if(!zopt->pattern->zonefile) return; zone = namedb_find_zone(nsd->db, (const dname_type*)zopt->node.key); if(!zone || !zone->apex || !zone->soa_rrset) return; /* write if file does not exist, or if changed */ /* so, determine filename, create directory components, check exist*/ zfile = config_make_zonefile(zopt, nsd); if(!create_path_components(zfile, ¬exist)) { log_msg(LOG_ERR, "could not write zone %s to file %s because " "the path could not be created", zopt->name, zfile); return; } /* if not changed, do not write. */ if(notexist || zone->is_changed) { char logs[4096]; char bakfile[4096]; struct timespec mtime; udb_ptr zudb; if(nsd->db->udb) { if(!udb_zone_search(nsd->db->udb, &zudb, dname_name(domain_dname(zone->apex)), domain_dname(zone->apex)->name_size)) return; /* zone does not exist in db */ } /* write to zfile~ first, then rename if that works */ snprintf(bakfile, sizeof(bakfile), "%s~", zfile); if(nsd->db->udb && ZONE(&zudb)->log_str.data) { udb_ptr s; udb_ptr_new(&s, nsd->db->udb, &ZONE(&zudb)->log_str); strlcpy(logs, (char*)udb_ptr_data(&s), sizeof(logs)); udb_ptr_unlink(&s, nsd->db->udb); } else if(zone->logstr) { strlcpy(logs, zone->logstr, sizeof(logs)); } else logs[0] = 0; VERBOSITY(1, (LOG_INFO, "writing zone %s to file %s", zone->opts->name, zfile)); if(!write_to_zonefile(zone, bakfile, logs)) { if(nsd->db->udb) udb_ptr_unlink(&zudb, nsd->db->udb); (void)unlink(bakfile); /* delete failed file */ return; /* error already printed */ } if(rename(bakfile, zfile) == -1) { log_msg(LOG_ERR, "rename(%s to %s) failed: %s", bakfile, zfile, strerror(errno)); if(nsd->db->udb) udb_ptr_unlink(&zudb, nsd->db->udb); (void)unlink(bakfile); /* delete failed file */ return; } zone->is_changed = 0; /* fetch the mtime of the just created zonefile so we * do not waste effort reading it back in */ if(!file_get_mtime(zfile, &mtime, ¬exist)) { get_time(&mtime); } if(nsd->db->udb) { ZONE(&zudb)->mtime = (uint64_t)mtime.tv_sec; ZONE(&zudb)->mtime_nsec = (uint64_t)mtime.tv_nsec; ZONE(&zudb)->is_changed = 0; udb_zone_set_log_str(nsd->db->udb, &zudb, NULL); udb_ptr_unlink(&zudb, nsd->db->udb); } else { zone->mtime = mtime; if(zone->filename) region_recycle(nsd->db->region, zone->filename, strlen(zone->filename)+1); zone->filename = region_strdup(nsd->db->region, zfile); if(zone->logstr) region_recycle(nsd->db->region, zone->logstr, strlen(zone->logstr)+1); zone->logstr = NULL; } } }
/** classify the query in a number of different types, each has separate * ratelimiting, so that positive queries are not impeded by others */ static uint16_t rrl_classify(query_type* query, const uint8_t** d, size_t* d_len) { if(RCODE(query->packet) == RCODE_NXDOMAIN) { if(query->zone && query->zone->apex) { *d = dname_name(domain_dname(query->zone->apex)); *d_len = domain_dname(query->zone->apex)->name_size; } return rrl_type_nxdomain; } if(RCODE(query->packet) != RCODE_OK) { if(query->zone && query->zone->apex) { *d = dname_name(domain_dname(query->zone->apex)); *d_len = domain_dname(query->zone->apex)->name_size; } return rrl_type_error; } if(query->delegation_domain) { *d = dname_name(domain_dname(query->delegation_domain)); *d_len = domain_dname(query->delegation_domain)->name_size; return rrl_type_referral; } if(query->qtype == TYPE_ANY) { if(query->qname) { *d = dname_name(query->qname); *d_len = query->qname->name_size; } return rrl_type_any; } if(query->qtype == TYPE_RRSIG) { if(query->qname) { *d = dname_name(query->qname); *d_len = query->qname->name_size; } return rrl_type_rrsig; } if(query->wildcard_domain) { *d = dname_name(domain_dname(query->wildcard_domain)); *d_len = domain_dname(query->wildcard_domain)->name_size; return rrl_type_wildcard; } if(ANCOUNT(query->packet) == 0) { if(query->zone && query->zone->apex) { *d = dname_name(domain_dname(query->zone->apex)); *d_len = domain_dname(query->zone->apex)->name_size; } return rrl_type_nodata; } if(query->qtype == TYPE_DNSKEY) { if(query->qname) { *d = dname_name(query->qname); *d_len = query->qname->name_size; } return rrl_type_dnskey; } /* positive */ if(query->qname) { *d = dname_name(query->qname); *d_len = query->qname->name_size; } return rrl_type_positive; }