return NULL;
}
+/** allocate SOA record ubrrsetkey in region */
+static struct ub_packed_rrset_key*
+make_soa_ubrrset(struct auth_zone* auth_zone, struct auth_rrset* soa,
+ struct regional* temp)
+{
+ struct ub_packed_rrset_key csoa;
+ if(!soa)
+ return NULL;
+ 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;
+ return respip_copy_rrset(&csoa, temp);
+}
+
static void
rpz_apply_clientip_localdata_action(struct clientip_synthesized_rr* raddr,
struct module_env* env, struct query_info* qinfo,
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);
+ rsoa = make_soa_ubrrset(auth_zone, soa, 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, rsoa);
}
+/** add additional section SOA record to the reply.
+ * Since this gets fed into the normal iterator answer creation, it
+ * gets minimal-responses applied to it, that can remove the additional SOA
+ * again. */
+static int
+rpz_add_soa(struct reply_info* rep, struct module_qstate* ms,
+ struct auth_zone* az)
+{
+ struct auth_rrset* soa = NULL;
+ struct ub_packed_rrset_key* rsoa = NULL;
+ struct ub_packed_rrset_key** prevrrsets;
+ soa = auth_zone_get_soa_rrset(az);
+ if(!soa) return 1;
+ if(!rep) return 0;
+ rsoa = make_soa_ubrrset(az, soa, ms->region);
+ if(!rsoa) return 0;
+ prevrrsets = rep->rrsets;
+ rep->rrsets = regional_alloc_zero(ms->region,
+ sizeof(*rep->rrsets)*(rep->rrset_count+1));
+ if(prevrrsets && rep->rrset_count > 0)
+ memcpy(rep->rrsets, prevrrsets, rep->rrset_count*sizeof(*rep->rrsets));
+ rep->rrset_count++;
+ rep->ar_numrrsets++;
+ rep->rrsets[rep->rrset_count-1] = rsoa;
+ return 1;
+}
+
static inline struct dns_msg*
rpz_dns_msg_new(struct regional* region)
{
static inline struct dns_msg*
rpz_synthesize_nodata(struct rpz* ATTR_UNUSED(r), struct module_qstate* ms,
- struct query_info* qinfo)
+ struct query_info* qinfo, struct auth_zone* az)
{
struct dns_msg* msg = rpz_dns_msg_new(ms->region);
if(msg == NULL) { return msg; }
sec_status_insecure);
if(msg->rep)
msg->rep->authoritative = 1;
+ if(!rpz_add_soa(msg->rep, ms, az))
+ return NULL;
return msg;
}
static inline struct dns_msg*
rpz_synthesize_nxdomain(struct rpz* ATTR_UNUSED(r), struct module_qstate* ms,
- struct query_info* qinfo)
+ struct query_info* qinfo, struct auth_zone* az)
{
struct dns_msg* msg = rpz_dns_msg_new(ms->region);
if(msg == NULL) { return msg; }
sec_status_insecure);
if(msg->rep)
msg->rep->authoritative = 1;
+ if(!rpz_add_soa(msg->rep, ms, az))
+ return NULL;
return msg;
}
static inline struct dns_msg*
rpz_synthesize_localdata_from_rrset(struct rpz* ATTR_UNUSED(r), struct module_qstate* ms,
- struct query_info* qi, struct local_rrset* rrset)
+ struct query_info* qi, struct local_rrset* rrset, struct auth_zone* az)
{
struct dns_msg* msg = NULL;
struct reply_info* new_reply_info;
rp->rk.flags |= PACKED_RRSET_RPZ;
new_reply_info->rrsets[0] = rp;
msg->rep = new_reply_info;
+ if(!rpz_add_soa(msg->rep, ms, az))
+ return NULL;
return msg;
}
static inline struct dns_msg*
rpz_synthesize_nsip_localdata(struct rpz* r, struct module_qstate* ms,
- struct clientip_synthesized_rr* data)
+ struct clientip_synthesized_rr* data, struct auth_zone* az)
{
struct query_info* qi = &ms->qinfo;
struct local_rrset* rrset;
return NULL;
}
- return rpz_synthesize_localdata_from_rrset(r, ms, &ms->qinfo, rrset);
+ return rpz_synthesize_localdata_from_rrset(r, ms, &ms->qinfo, rrset, az);
}
/* copy'n'paste from localzone.c */
/* based on localzone.c:local_data_answer() */
static inline struct dns_msg*
rpz_synthesize_nsdname_localdata(struct rpz* r, struct module_qstate* ms,
- struct local_zone* z, struct matched_delegation_point const* match)
+ struct local_zone* z, struct matched_delegation_point const* match,
+ struct auth_zone* az)
{
struct local_data key;
struct local_data* ld;
return NULL;
}
- return rpz_synthesize_localdata_from_rrset(r, ms, &ms->qinfo, rrset);
+ return rpz_synthesize_localdata_from_rrset(r, ms, &ms->qinfo, rrset, az);
}
/* like local_data_answer for qname triggers after a cname */
static struct dns_msg*
rpz_synthesize_qname_localdata_msg(struct rpz* r, struct module_qstate* ms,
- struct query_info* qinfo, struct local_zone* z)
+ struct query_info* qinfo, struct local_zone* z, struct auth_zone* az)
{
struct local_data key;
struct local_data* ld;
verbose(VERB_ALGO, "rpz: qname after cname: type not found");
return NULL;
}
- return rpz_synthesize_localdata_from_rrset(r, ms, qinfo, rrset);
+ return rpz_synthesize_localdata_from_rrset(r, ms, qinfo, rrset, az);
}
static int
struct dns_msg*
rpz_apply_nsip_trigger(struct module_qstate* ms, struct rpz* r,
- struct clientip_synthesized_rr* raddr)
+ struct clientip_synthesized_rr* raddr, struct auth_zone* az)
{
enum rpz_action action = raddr->action;
struct dns_msg* ret = NULL;
if(action == RPZ_LOCAL_DATA_ACTION && raddr->data == NULL) {
verbose(VERB_ALGO, "rpz: bug: nsip local data action but no local data");
- ret = rpz_synthesize_nodata(r, ms, &ms->qinfo);
+ ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az);
goto done;
}
switch(action) {
case RPZ_NXDOMAIN_ACTION:
- ret = rpz_synthesize_nxdomain(r, ms, &ms->qinfo);
+ ret = rpz_synthesize_nxdomain(r, ms, &ms->qinfo, az);
break;
case RPZ_NODATA_ACTION:
- ret = rpz_synthesize_nodata(r, ms, &ms->qinfo);
+ ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az);
break;
case RPZ_TCP_ONLY_ACTION:
/* basically a passthru here but the tcp-only will be
ret = NULL;
break;
case RPZ_DROP_ACTION:
- ret = rpz_synthesize_nodata(r, ms, &ms->qinfo);
+ ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az);
ms->is_drop = 1;
break;
case RPZ_LOCAL_DATA_ACTION:
- ret = rpz_synthesize_nsip_localdata(r, ms, raddr);
- if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, &ms->qinfo); }
+ ret = rpz_synthesize_nsip_localdata(r, ms, raddr, az);
+ if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az); }
break;
case RPZ_PASSTHRU_ACTION:
ret = NULL;
struct dns_msg*
rpz_apply_nsdname_trigger(struct module_qstate* ms, struct rpz* r,
- struct local_zone* z, struct matched_delegation_point const* match)
+ struct local_zone* z, struct matched_delegation_point const* match,
+ struct auth_zone* az)
{
struct dns_msg* ret = NULL;
enum rpz_action action = localzone_type_to_rpz_action(z->type);
switch(action) {
case RPZ_NXDOMAIN_ACTION:
- ret = rpz_synthesize_nxdomain(r, ms, &ms->qinfo);
+ ret = rpz_synthesize_nxdomain(r, ms, &ms->qinfo, az);
break;
case RPZ_NODATA_ACTION:
- ret = rpz_synthesize_nodata(r, ms, &ms->qinfo);
+ ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az);
break;
case RPZ_TCP_ONLY_ACTION:
/* basically a passthru here but the tcp-only will be
ret = NULL;
break;
case RPZ_DROP_ACTION:
- ret = rpz_synthesize_nodata(r, ms, &ms->qinfo);
+ ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az);
ms->is_drop = 1;
break;
case RPZ_LOCAL_DATA_ACTION:
- ret = rpz_synthesize_nsdname_localdata(r, ms, z, match);
- if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, &ms->qinfo); }
+ ret = rpz_synthesize_nsdname_localdata(r, ms, z, match, az);
+ if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az); }
break;
case RPZ_PASSTHRU_ACTION:
ret = NULL;
lock_rw_unlock(&az->rpz_lock);
if(raddr == NULL && z == NULL) { return NULL; }
- else if(raddr != NULL) { return rpz_apply_nsip_trigger(ms, r, raddr); }
- else if(z != NULL) { return rpz_apply_nsdname_trigger(ms, r, z, &match); }
+ else if(raddr != NULL) { return rpz_apply_nsip_trigger(ms, r, raddr, a); }
+ else if(z != NULL) { return rpz_apply_nsdname_trigger(ms, r, z, &match, a); }
else { return NULL; }
}
}
switch(localzone_type_to_rpz_action(lzt)) {
case RPZ_NXDOMAIN_ACTION:
- ret = rpz_synthesize_nxdomain(r, ms, &is->qchase);
+ ret = rpz_synthesize_nxdomain(r, ms, &is->qchase, a);
break;
case RPZ_NODATA_ACTION:
- ret = rpz_synthesize_nodata(r, ms, &is->qchase);
+ ret = rpz_synthesize_nodata(r, ms, &is->qchase, a);
break;
case RPZ_TCP_ONLY_ACTION:
/* basically a passthru here but the tcp-only will be
ret = NULL;
break;
case RPZ_DROP_ACTION:
- ret = rpz_synthesize_nodata(r, ms, &is->qchase);
+ ret = rpz_synthesize_nodata(r, ms, &is->qchase, a);
ms->is_drop = 1;
break;
case RPZ_LOCAL_DATA_ACTION:
- ret = rpz_synthesize_qname_localdata_msg(r, ms, &is->qchase, z);
- if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, &is->qchase); }
+ ret = rpz_synthesize_qname_localdata_msg(r, ms, &is->qchase, z, a);
+ if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, &is->qchase, a); }
break;
case RPZ_PASSTHRU_ACTION:
ret = NULL;