qstate->return_msg->rep);
if(!reply_info_answer_encode(&qstate->return_msg->qinfo,
qstate->return_msg->rep, 0, qstate->query_flags,
- buf, 0, 1, qstate->env->scratch, 65535, &edns, 1, 0))
+ buf, 0, 1, qstate->env->scratch, 65535, &edns, 1, 0, 0))
return 0;
/* TTLs in the return_msg are relative to time(0) so we have to
repinfo->c, worker->scratchpad) ||
!reply_info_answer_encode(&msg->qinfo, msg->rep, id, flags,
repinfo->c->buffer, 0, 1, worker->scratchpad,
- udpsize, edns, (int)(edns->bits & EDNS_DO), secure)) {
+ udpsize, edns, (int)(edns->bits & EDNS_DO), secure, 0)) {
if(!inplace_cb_reply_servfail_call(&worker->env, qinfo, NULL, NULL,
LDNS_RCODE_SERVFAIL, edns, repinfo, worker->scratchpad,
worker->env.now_tv))
repinfo->c, worker->scratchpad) ||
!reply_info_answer_encode(qinfo, encode_rep, id, flags,
repinfo->c->buffer, timenow, 1, worker->scratchpad,
- udpsize, edns, (int)(edns->bits & EDNS_DO), *is_secure_answer)) {
+ udpsize, edns, (int)(edns->bits & EDNS_DO), *is_secure_answer, 0)) {
if(!inplace_cb_reply_servfail_call(&worker->env, qinfo, NULL, NULL,
LDNS_RCODE_SERVFAIL, edns, repinfo, worker->scratchpad,
worker->env.now_tv))
return 0;
}
+/** find the apex SOA RRset, if it exists */
+struct auth_rrset* auth_zone_get_soa_rrset(struct auth_zone* z)
+{
+ struct auth_data* apex;
+ struct auth_rrset* soa;
+ apex = az_find_name(z, z->name, z->namelen);
+ if(!apex) return NULL;
+ soa = az_domain_rrset(apex, LDNS_RR_TYPE_SOA);
+ return soa;
+}
+
/** find serial number of zone or false if none */
int
auth_zone_get_serial(struct auth_zone* z, uint32_t* serial)
*(uint16_t*)sldns_buffer_begin(buf),
sldns_buffer_read_u16_at(buf, 2),
buf, 0, 0, temp, udpsize, edns,
- (int)(edns->bits&EDNS_DO), 0)) {
+ (int)(edns->bits&EDNS_DO), 0, 0)) {
error_encode(buf, (LDNS_RCODE_SERVFAIL|BIT_AA), qinfo,
*(uint16_t*)sldns_buffer_begin(buf),
sldns_buffer_read_u16_at(buf, 2), edns);
/** read auth zone from zonefile. caller must lock zone. false on failure */
int auth_zone_read_zonefile(struct auth_zone* z, struct config_file* cfg);
+/** find the apex SOA RRset, if it exists. NULL if no SOA RRset. */
+struct auth_rrset* auth_zone_get_soa_rrset(struct auth_zone* z);
+
/** find serial number of zone or false if none (no SOA record) */
int auth_zone_get_serial(struct auth_zone* z, uint32_t* serial);
if(!inplace_cb_reply_local_call(env, qinfo, NULL, &rep, rcode, edns,
repinfo, temp, env->now_tv) || !reply_info_answer_encode(qinfo, &rep,
*(uint16_t*)sldns_buffer_begin(buf), sldns_buffer_read_u16_at(buf, 2),
- buf, 0, 0, temp, udpsize, edns, (int)(edns->bits&EDNS_DO), 0)) {
+ buf, 0, 0, temp, udpsize, edns, (int)(edns->bits&EDNS_DO), 0, 0)) {
error_encode(buf, (LDNS_RCODE_SERVFAIL|BIT_AA), qinfo,
*(uint16_t*)sldns_buffer_begin(buf),
sldns_buffer_read_u16_at(buf, 2), edns);
!reply_info_answer_encode(&m->s.qinfo, rep, r->qid,
r->qflags, r->buf, 0, 1,
m->s.env->scratch, udp_size, &r->edns,
- (int)(r->edns.bits & EDNS_DO), secure))
+ (int)(r->edns.bits & EDNS_DO), secure, 0))
{
fptr_ok(fptr_whitelist_mesh_cb(r->cb));
(*r->cb)(r->cb_arg, LDNS_RCODE_SERVFAIL, r->buf,
!reply_info_answer_encode(&m->s.qinfo, rep, r->qid,
r->qflags, r_buffer, 0, 1, m->s.env->scratch,
udp_size, &r->edns, (int)(r->edns.bits & EDNS_DO),
- secure))
+ secure, 0))
{
if(!inplace_cb_reply_servfail_call(m->s.env, &m->s.qinfo, &m->s,
rep, LDNS_RCODE_SERVFAIL, &r->edns, &r->query_reply, m->s.region, &r->start_time))
rpz_local_encode(struct module_env* env, struct query_info* qinfo,
struct edns_data* edns, struct comm_reply* repinfo, sldns_buffer* buf,
struct regional* temp, struct ub_packed_rrset_key* rrset, int ansec,
- int rcode)
+ int rcode, struct ub_packed_rrset_key* soa_rrset)
{
struct reply_info rep;
uint16_t udpsize;
+ struct ub_packed_rrset_key* rrsetlist[3];
memset(&rep, 0, sizeof(rep));
rep.flags = (uint16_t)((BIT_QR | BIT_AA | BIT_RA) | rcode);
rep.qdcount = 1;
rep.rrset_count = ansec;
+ rep.rrsets = rrsetlist;
if(ansec > 0) {
rep.an_numrrsets = 1;
- rep.rrsets = &rrset;
+ rep.rrsets[0] = rrset;
rep.ttl = ((struct packed_rrset_data*)rrset->entry.data)->rr_ttl[0];
}
+ if(soa_rrset != NULL) {
+ rep.ar_numrrsets = 1;
+ rep.rrsets[rep.rrset_count] = soa_rrset;
+ rep.rrset_count ++;
+ if(rep.ttl < ((struct packed_rrset_data*)soa_rrset->entry.data)->rr_ttl[0]) {
+ rep.ttl = ((struct packed_rrset_data*)soa_rrset->entry.data)->rr_ttl[0];
+ }
+ }
udpsize = edns->udp_size;
edns->edns_version = EDNS_ADVERTISED_VERSION;
repinfo, temp, env->now_tv) ||
!reply_info_answer_encode(qinfo, &rep,
*(uint16_t*)sldns_buffer_begin(buf), sldns_buffer_read_u16_at(buf, 2),
- buf, 0, 0, temp, udpsize, edns, (int)(edns->bits&EDNS_DO), 0)) {
+ buf, 0, 0, temp, udpsize, edns, (int)(edns->bits&EDNS_DO), 0,
+ 1 /* not minimal */ )) {
error_encode(buf, (LDNS_RCODE_SERVFAIL|BIT_AA), qinfo,
*(uint16_t*)sldns_buffer_begin(buf),
sldns_buffer_read_u16_at(buf, 2), edns);
rpz_apply_clientip_localdata_action(struct clientip_synthesized_rr* raddr,
struct module_env* env, struct query_info* qinfo,
struct edns_data* edns, struct comm_reply* repinfo, sldns_buffer* buf,
- struct regional* temp)
+ struct regional* temp, struct auth_zone* auth_zone)
{
struct local_rrset* rrset;
enum rpz_action action = RPZ_INVALID_ACTION;
struct ub_packed_rrset_key* rp = NULL;
+ struct ub_packed_rrset_key* rsoa = NULL;
int rcode = LDNS_RCODE_NOERROR|BIT_AA;
int rrset_count = 1;
return;
}
- rp->rk.flags |= PACKED_RRSET_FIXEDTTL;
+ rp->rk.flags |= PACKED_RRSET_FIXEDTTL | PACKED_RRSET_RPZ;
rp->rk.dname = qinfo->qname;
rp->rk.dname_len = qinfo->qname_len;
+ rp->entry.hash = rrset_key_hash(&rp->rk);
nodata:
+ if(auth_zone) {
+ struct auth_rrset* soa = NULL;
+ soa = auth_zone_get_soa_rrset(auth_zone);
+ if(soa) {
+ struct ub_packed_rrset_key csoa;
+ memset(&csoa, 0, sizeof(csoa));
+ csoa.entry.key = &csoa;
+ csoa.rk.rrset_class = htons(LDNS_RR_CLASS_IN);
+ csoa.rk.type = htons(LDNS_RR_TYPE_SOA);
+ csoa.rk.flags |= PACKED_RRSET_FIXEDTTL
+ | PACKED_RRSET_RPZ;
+ csoa.rk.dname = auth_zone->name;
+ csoa.rk.dname_len = auth_zone->namelen;
+ csoa.entry.hash = rrset_key_hash(&csoa.rk);
+ csoa.entry.data = soa->data;
+ rsoa = respip_copy_rrset(&csoa, temp);
+ if(!rsoa) {
+ verbose(VERB_ALGO, "rpz: local data action soa: out of memory");
+ return;
+ }
+ }
+
+ }
+
rpz_local_encode(env, qinfo, edns, repinfo, buf, temp, rp,
- rrset_count, rcode);
+ rrset_count, rcode, rsoa);
}
static inline struct dns_msg*
stats->rpz_action[client_action]++;
if(client_action == RPZ_LOCAL_DATA_ACTION) {
rpz_apply_clientip_localdata_action(node, env, qinfo,
- edns, repinfo, buf, temp);
+ edns, repinfo, buf, temp, *a_out);
} else {
if(*r_out && (*r_out)->log)
log_rpz_apply(((*z_out)?(*z_out)->name:NULL),
a.a. IN A
SECTION ANSWER
a.a. IN A 127.0.0.1
+SECTION ADDITIONAL
+rpz.example.com. 3600 IN SOA ns1.rpz.example.com. hostmaster.rpz.example.com. ( 1379078166 28800 7200 604800 7200 )
ENTRY_END
; should be synthesized
a.a. IN TXT
SECTION ANSWER
a.a. IN TXT "42"
+SECTION ADDITIONAL
+rpz.example.com. 3600 IN SOA ns1.rpz.example.com. hostmaster.rpz.example.com. ( 1379078166 28800 7200 604800 7200 )
ENTRY_END
; should be synthesized NODATA
REPLY QR AA RD RA NOERROR
SECTION QUESTION
a.a. IN AAAA
+SECTION ADDITIONAL
+rpz.example.com. 3600 IN SOA ns1.rpz.example.com. hostmaster.rpz.example.com. ( 1379078166 28800 7200 604800 7200 )
ENTRY_END
; should be DROPPED
reply_info_answer_encode(struct query_info* qinf, struct reply_info* rep,
uint16_t id, uint16_t qflags, sldns_buffer* pkt, time_t timenow,
int cached, struct regional* region, uint16_t udpsize,
- struct edns_data* edns, int dnssec, int secure)
+ struct edns_data* edns, int dnssec, int secure, int notminimal)
{
uint16_t flags;
unsigned int attach_edns = 0;
}
if(!reply_info_encode(qinf, rep, id, flags, pkt, timenow, region,
- udpsize, dnssec, MINIMAL_RESPONSES)) {
+ udpsize, dnssec, (notminimal?0:MINIMAL_RESPONSES))) {
log_err("reply encode: out of memory");
return 0;
}
* or if edns_present = 0, it is not included.
* @param dnssec: if 0 DNSSEC records are omitted from the answer.
* @param secure: if 1, the AD bit is set in the reply.
+ * @param notminimal: if 1, ignore minimalresponses and include additional
+ * section anyway.
* @return: 0 on error (server failure).
*/
int reply_info_answer_encode(struct query_info* qinf, struct reply_info* rep,
uint16_t id, uint16_t qflags, struct sldns_buffer* dest, time_t timenow,
int cached, struct regional* region, uint16_t udpsize,
- struct edns_data* edns, int dnssec, int secure);
+ struct edns_data* edns, int dnssec, int secure, int notminimal);
/**
* Regenerate the wireformat from the stored msg reply.