1 /* 2 * axfr.c -- generating AXFR responses. 3 * 4 * Copyright (c) 2001-2006, NLnet Labs. All rights reserved. 5 * 6 * See LICENSE for the license. 7 * 8 */ 9 10 #include "config.h" 11 12 #include "axfr.h" 13 #include "dns.h" 14 #include "packet.h" 15 #include "options.h" 16 17 #define AXFR_TSIG_SIGN_EVERY_NTH 96 /* tsig sign every N packets. */ 18 19 query_state_type 20 query_axfr(struct nsd *nsd, struct query *query) 21 { 22 domain_type *closest_match; 23 domain_type *closest_encloser; 24 int exact; 25 int added; 26 uint16_t total_added = 0; 27 28 if (query->axfr_is_done) 29 return QUERY_PROCESSED; 30 31 if (query->maxlen > AXFR_MAX_MESSAGE_LEN) 32 query->maxlen = AXFR_MAX_MESSAGE_LEN; 33 34 assert(!query_overflow(query)); 35 /* only keep running values for most packets */ 36 query->tsig_prepare_it = 0; 37 query->tsig_update_it = 1; 38 if(query->tsig_sign_it) { 39 /* prepare for next updates */ 40 query->tsig_prepare_it = 1; 41 query->tsig_sign_it = 0; 42 } 43 44 if (query->axfr_zone == NULL) { 45 domain_type* qdomain; 46 /* Start AXFR. */ 47 STATUP(nsd, raxfr); 48 exact = namedb_lookup(nsd->db, 49 query->qname, 50 &closest_match, 51 &closest_encloser); 52 53 qdomain = closest_encloser; 54 query->axfr_zone = domain_find_zone(nsd->db, closest_encloser); 55 56 if (!exact 57 || query->axfr_zone == NULL 58 || query->axfr_zone->apex != qdomain 59 || query->axfr_zone->soa_rrset == NULL) 60 { 61 /* No SOA no transfer */ 62 RCODE_SET(query->packet, RCODE_NOTAUTH); 63 return QUERY_PROCESSED; 64 } 65 ZTATUP(nsd, query->axfr_zone, raxfr); 66 67 query->axfr_current_domain = qdomain; 68 query->axfr_current_rrset = NULL; 69 query->axfr_current_rr = 0; 70 if(query->tsig.status == TSIG_OK) { 71 query->tsig_sign_it = 1; /* sign first packet in stream */ 72 } 73 74 query_add_compression_domain(query, qdomain, QHEADERSZ); 75 76 assert(query->axfr_zone->soa_rrset->rr_count == 1); 77 added = packet_encode_rr(query, 78 query->axfr_zone->apex, 79 &query->axfr_zone->soa_rrset->rrs[0], 80 query->axfr_zone->soa_rrset->rrs[0].ttl); 81 if (!added) { 82 /* XXX: This should never happen... generate error code? */ 83 abort(); 84 } 85 ++total_added; 86 } else { 87 /* 88 * Query name and EDNS need not be repeated after the 89 * first response packet. 90 */ 91 query->edns.status = EDNS_NOT_PRESENT; 92 buffer_set_limit(query->packet, QHEADERSZ); 93 QDCOUNT_SET(query->packet, 0); 94 query_prepare_response(query); 95 } 96 97 /* Add zone RRs until answer is full. */ 98 while (query->axfr_current_domain != NULL && 99 domain_is_subdomain(query->axfr_current_domain, 100 query->axfr_zone->apex)) 101 { 102 if (!query->axfr_current_rrset) { 103 query->axfr_current_rrset = domain_find_any_rrset( 104 query->axfr_current_domain, 105 query->axfr_zone); 106 query->axfr_current_rr = 0; 107 } 108 while (query->axfr_current_rrset) { 109 if (query->axfr_current_rrset != query->axfr_zone->soa_rrset 110 && query->axfr_current_rrset->zone == query->axfr_zone) 111 { 112 while (query->axfr_current_rr < query->axfr_current_rrset->rr_count) { 113 added = packet_encode_rr( 114 query, 115 query->axfr_current_domain, 116 &query->axfr_current_rrset->rrs[query->axfr_current_rr], 117 query->axfr_current_rrset->rrs[query->axfr_current_rr].ttl); 118 if (!added) 119 goto return_answer; 120 ++total_added; 121 ++query->axfr_current_rr; 122 } 123 } 124 125 query->axfr_current_rrset = query->axfr_current_rrset->next; 126 query->axfr_current_rr = 0; 127 } 128 assert(query->axfr_current_domain); 129 query->axfr_current_domain 130 = domain_next(query->axfr_current_domain); 131 } 132 133 /* Add terminating SOA RR. */ 134 assert(query->axfr_zone->soa_rrset->rr_count == 1); 135 added = packet_encode_rr(query, 136 query->axfr_zone->apex, 137 &query->axfr_zone->soa_rrset->rrs[0], 138 query->axfr_zone->soa_rrset->rrs[0].ttl); 139 if (added) { 140 ++total_added; 141 query->tsig_sign_it = 1; /* sign last packet */ 142 query->axfr_is_done = 1; 143 } 144 145 return_answer: 146 AA_SET(query->packet); 147 ANCOUNT_SET(query->packet, total_added); 148 NSCOUNT_SET(query->packet, 0); 149 ARCOUNT_SET(query->packet, 0); 150 151 /* check if it needs tsig signatures */ 152 if(query->tsig.status == TSIG_OK) { 153 if(query->tsig.updates_since_last_prepare >= AXFR_TSIG_SIGN_EVERY_NTH) { 154 query->tsig_sign_it = 1; 155 } 156 } 157 query_clear_compression_tables(query); 158 return QUERY_IN_AXFR; 159 } 160 161 /* 162 * Answer if this is an AXFR or IXFR query. 163 */ 164 query_state_type 165 answer_axfr_ixfr(struct nsd *nsd, struct query *q) 166 { 167 struct acl_options *acl = NULL; 168 /* Is it AXFR? */ 169 switch (q->qtype) { 170 case TYPE_AXFR: 171 if (q->tcp) { 172 struct zone_options* zone_opt; 173 zone_opt = zone_options_find(nsd->options, q->qname); 174 if(!zone_opt || 175 acl_check_incoming(zone_opt->pattern->provide_xfr, q, &acl)==-1) 176 { 177 if (verbosity >= 2) { 178 char a[128]; 179 addr2str(&q->addr, a, sizeof(a)); 180 VERBOSITY(2, (LOG_INFO, "axfr for %s from %s refused, %s", 181 dname_to_string(q->qname, NULL), a, acl?"blocked":"no acl matches")); 182 } 183 DEBUG(DEBUG_XFRD,1, (LOG_INFO, "axfr refused, %s", 184 acl?"blocked":"no acl matches")); 185 if (!zone_opt) { 186 RCODE_SET(q->packet, RCODE_NOTAUTH); 187 } else { 188 RCODE_SET(q->packet, RCODE_REFUSE); 189 } 190 return QUERY_PROCESSED; 191 } 192 DEBUG(DEBUG_XFRD,1, (LOG_INFO, "axfr admitted acl %s %s", 193 acl->ip_address_spec, acl->key_name?acl->key_name:"NOKEY")); 194 if (verbosity >= 1) { 195 char a[128]; 196 addr2str(&q->addr, a, sizeof(a)); 197 VERBOSITY(1, (LOG_INFO, "%s for %s from %s", 198 (q->qtype==TYPE_AXFR?"axfr":"ixfr"), 199 dname_to_string(q->qname, NULL), a)); 200 } 201 return query_axfr(nsd, q); 202 } 203 /** Fallthrough: AXFR over UDP queries are discarded. */ 204 /* fallthrough */ 205 case TYPE_IXFR: 206 RCODE_SET(q->packet, RCODE_IMPL); 207 return QUERY_PROCESSED; 208 default: 209 return QUERY_DISCARDED; 210 } 211 } 212