--- /dev/null
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_pkg_swig.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_PKG_SWIG([major.minor.micro], [action-if-found], [action-if-not-found])
+#
+# DESCRIPTION
+#
+# This macro searches for a SWIG installation on your system. If found,
+# then SWIG is AC_SUBST'd; if not found, then $SWIG is empty. If SWIG is
+# found, then SWIG_LIB is set to the SWIG library path, and AC_SUBST'd.
+#
+# You can use the optional first argument to check if the version of the
+# available SWIG is greater than or equal to the value of the argument. It
+# should have the format: N[.N[.N]] (N is a number between 0 and 999. Only
+# the first N is mandatory.) If the version argument is given (e.g.
+# 1.3.17), AX_PKG_SWIG checks that the swig package is this version number
+# or higher.
+#
+# As usual, action-if-found is executed if SWIG is found, otherwise
+# action-if-not-found is executed.
+#
+# In configure.in, use as:
+#
+# AX_PKG_SWIG(1.3.17, [], [ AC_MSG_ERROR([SWIG is required to build..]) ])
+# AX_SWIG_ENABLE_CXX
+# AX_SWIG_MULTI_MODULE_SUPPORT
+# AX_SWIG_PYTHON
+#
+# LICENSE
+#
+# Copyright (c) 2008 Sebastian Huber <sebastian-huber@web.de>
+# Copyright (c) 2008 Alan W. Irwin
+# Copyright (c) 2008 Rafael Laboissiere <rafael@laboissiere.net>
+# Copyright (c) 2008 Andrew Collier
+# Copyright (c) 2011 Murray Cumming <murrayc@openismus.com>
+# Copyright (c) 2018 Reini Urban <rurban@cpan.org>
+# Copyright (c) 2021 Vincent Danjean <Vincent.Danjean@ens-lyon.org>
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see <https://www.gnu.org/licenses/>.
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Archive. When you make and distribute a
+# modified version of the Autoconf Macro, you may extend this special
+# exception to the GPL to apply to your modified version as well.
+
+#serial 15
+
+AC_DEFUN([AX_PKG_SWIG],[
+ # Find path to the "swig" executable.
+ AC_PATH_PROGS([SWIG],[swig swig3.0 swig2.0])
+ if test -z "$SWIG" ; then
+ m4_ifval([$3],[$3],[:])
+ elif test -z "$1" ; then
+ m4_ifval([$2],[$2],[:])
+ else
+ AC_MSG_CHECKING([SWIG version])
+ [swig_version=`$SWIG -version 2>&1 | grep 'SWIG Version' | sed 's/.*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/g'`]
+ AC_MSG_RESULT([$swig_version])
+ if test -n "$swig_version" ; then
+ # Calculate the required version number components
+ [required=$1]
+ [required_major=`echo $required | sed 's/[^0-9].*//'`]
+ if test -z "$required_major" ; then
+ [required_major=0]
+ fi
+ [required=`echo $required. | sed 's/[0-9]*[^0-9]//'`]
+ [required_minor=`echo $required | sed 's/[^0-9].*//'`]
+ if test -z "$required_minor" ; then
+ [required_minor=0]
+ fi
+ [required=`echo $required. | sed 's/[0-9]*[^0-9]//'`]
+ [required_patch=`echo $required | sed 's/[^0-9].*//'`]
+ if test -z "$required_patch" ; then
+ [required_patch=0]
+ fi
+ # Calculate the available version number components
+ [available=$swig_version]
+ [available_major=`echo $available | sed 's/[^0-9].*//'`]
+ if test -z "$available_major" ; then
+ [available_major=0]
+ fi
+ [available=`echo $available | sed 's/[0-9]*[^0-9]//'`]
+ [available_minor=`echo $available | sed 's/[^0-9].*//'`]
+ if test -z "$available_minor" ; then
+ [available_minor=0]
+ fi
+ [available=`echo $available | sed 's/[0-9]*[^0-9]//'`]
+ [available_patch=`echo $available | sed 's/[^0-9].*//'`]
+ if test -z "$available_patch" ; then
+ [available_patch=0]
+ fi
+ # Convert the version tuple into a single number for easier comparison.
+ # Using base 100 should be safe since SWIG internally uses BCD values
+ # to encode its version number.
+ required_swig_vernum=`expr $required_major \* 10000 \
+ \+ $required_minor \* 100 \+ $required_patch`
+ available_swig_vernum=`expr $available_major \* 10000 \
+ \+ $available_minor \* 100 \+ $available_patch`
+
+ if test $available_swig_vernum -lt $required_swig_vernum; then
+ AC_MSG_WARN([SWIG version >= $1 is required. You have $swig_version.])
+ SWIG=''
+ m4_ifval([$3],[$3],[])
+ else
+ AC_MSG_CHECKING([for SWIG library])
+ SWIG_LIB=`$SWIG -swiglib | tr '\r\n' ' '`
+ AC_MSG_RESULT([$SWIG_LIB])
+ m4_ifval([$2],[$2],[])
+ fi
+ else
+ AC_MSG_WARN([cannot determine SWIG version])
+ SWIG=''
+ m4_ifval([$3],[$3],[])
+ fi
+ fi
+ AC_SUBST([SWIG_LIB])
+])
return rrset;
}
-struct rpz*
-rpz_create(struct config_auth* p)
+/** delete the cname override */
+static void
+delete_cname_override(struct rpz* r)
{
- struct rpz* r = calloc(1, sizeof(*r));
- if(!r)
- goto err;
-
- r->region = regional_create_custom(sizeof(struct regional));
- if(!r->region) {
- goto err;
- }
-
- if(!(r->local_zones = local_zones_create())){
- goto err;
- }
-
- r->nsdname_zones = local_zones_create();
- if(r->local_zones == NULL){
- goto err;
- }
-
- if(!(r->respip_set = respip_set_create())) {
- goto err;
- }
-
- r->client_set = rpz_clientip_synthesized_set_create();
- if(r->client_set == NULL) {
- goto err;
+ if(r->cname_override) {
+ /* The cname override is what is allocated in the region. */
+ regional_free_all(r->region);
+ r->cname_override = NULL;
}
+}
- r->ns_set = rpz_clientip_synthesized_set_create();
- if(r->ns_set == NULL) {
- goto err;
+/** Apply rpz config elements to the rpz structure, false on failure. */
+static int
+rpz_apply_cfg_elements(struct rpz* r, struct config_auth* p)
+{
+ if(p->rpz_taglist && p->rpz_taglistlen) {
+ r->taglistlen = p->rpz_taglistlen;
+ r->taglist = memdup(p->rpz_taglist, r->taglistlen);
+ if(!r->taglist) {
+ log_err("malloc failure on RPZ taglist alloc");
+ return 0;
+ }
}
- r->taglistlen = p->rpz_taglistlen;
- r->taglist = memdup(p->rpz_taglist, r->taglistlen);
if(p->rpz_action_override) {
r->action_override = rpz_config_to_action(p->rpz_action_override);
}
if(!p->rpz_cname) {
log_err("rpz: override with cname action found, but no "
"rpz-cname-override configured");
- goto err;
+ return 0;
}
if(sldns_str2wire_dname_buf(p->rpz_cname, nm, &nmlen) != 0) {
log_err("rpz: cannot parse cname override: %s",
p->rpz_cname);
- goto err;
+ return 0;
}
r->cname_override = new_cname_override(r->region, nm, nmlen);
if(!r->cname_override) {
- goto err;
+ return 0;
}
}
r->log = p->rpz_log;
if(p->rpz_log_name) {
if(!(r->log_name = strdup(p->rpz_log_name))) {
log_err("malloc failure on RPZ log_name strdup");
- goto err;
+ return 0;
}
}
+ return 1;
+}
+
+struct rpz*
+rpz_create(struct config_auth* p)
+{
+ struct rpz* r = calloc(1, sizeof(*r));
+ if(!r)
+ goto err;
+
+ r->region = regional_create_custom(sizeof(struct regional));
+ if(!r->region) {
+ goto err;
+ }
+
+ if(!(r->local_zones = local_zones_create())){
+ goto err;
+ }
+
+ r->nsdname_zones = local_zones_create();
+ if(r->local_zones == NULL){
+ goto err;
+ }
+
+ if(!(r->respip_set = respip_set_create())) {
+ goto err;
+ }
+
+ r->client_set = rpz_clientip_synthesized_set_create();
+ if(r->client_set == NULL) {
+ goto err;
+ }
+
+ r->ns_set = rpz_clientip_synthesized_set_create();
+ if(r->ns_set == NULL) {
+ goto err;
+ }
+
+ if(!rpz_apply_cfg_elements(r, p))
+ goto err;
return r;
err:
if(r) {
return NULL;
}
+int
+rpz_config(struct rpz* r, struct config_auth* p)
+{
+ /* If the zonefile changes, it is read later, after which
+ * rpz_clear and rpz_finish_config is called. */
+
+ /* free taglist, if any */
+ if(r->taglist) {
+ free(r->taglist);
+ r->taglist = NULL;
+ r->taglistlen = 0;
+ }
+
+ /* free logname, if any */
+ if(r->log_name) {
+ free(r->log_name);
+ r->log_name = NULL;
+ }
+
+ delete_cname_override(r);
+
+ if(!rpz_apply_cfg_elements(r, p))
+ return 0;
+ return 1;
+}
+
/**
* Remove RPZ zone name from dname
* Copy dname to newdname, without the originlen number of trailing bytes
/** Find entry for RR type in the list of rrsets for the clientip. */
static struct local_rrset*
rpz_find_synthesized_rrset(uint16_t qtype,
- struct clientip_synthesized_rr* data)
+ struct clientip_synthesized_rr* data, int alias_ok)
{
- struct local_rrset* cursor = data->data;
+ struct local_rrset* cursor = data->data, *cname = NULL;
while( cursor != NULL) {
struct packed_rrset_key* packed_rrset = &cursor->rrset->rk;
if(htons(qtype) == packed_rrset->type) {
return cursor;
}
+ if(ntohs(packed_rrset->type) == LDNS_RR_TYPE_CNAME && alias_ok)
+ cname = cursor;
cursor = cursor->next;
}
+ if(alias_ok)
+ return cname;
return NULL;
}
struct local_rrset* rrset;
struct packed_rrset_data* d;
size_t index;
- rrset = rpz_find_synthesized_rrset(rr_type, node);
+ rrset = rpz_find_synthesized_rrset(rr_type, node, 0);
if(rrset == NULL)
return 0; /* type not found, ignore */
d = (struct packed_rrset_data*)rrset->rrset->entry.data;
}
/* check query type / rr type */
- rrset = rpz_find_synthesized_rrset(qinfo->qtype, raddr);
+ rrset = rpz_find_synthesized_rrset(qinfo->qtype, raddr, 1);
if(rrset == NULL) {
verbose(VERB_ALGO, "rpz: unable to find local-data for query");
rrset_count = 0;
rrset_count, rcode, rsoa);
}
+/** Apply the cname override action, during worker request callback.
+ * false on failure. */
+static int
+rpz_apply_cname_override_action(struct rpz* r,
+ struct query_info* qinfo, struct regional* temp)
+{
+ if(!r)
+ return 0;
+ qinfo->local_alias = regional_alloc_zero(temp,
+ sizeof(struct local_rrset));
+ if(qinfo->local_alias == NULL)
+ return 0; /* out of memory */
+ qinfo->local_alias->rrset = respip_copy_rrset(r->cname_override, temp);
+ if(qinfo->local_alias->rrset == NULL) {
+ qinfo->local_alias = NULL;
+ return 0; /* out of memory */
+ }
+ qinfo->local_alias->rrset->rk.dname = qinfo->qname;
+ qinfo->local_alias->rrset->rk.dname_len = qinfo->qname_len;
+ return 1;
+}
+
/** 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
msg = rpz_dns_msg_new(ms->region);
if(msg == NULL) { return NULL; }
+ msg->qinfo = *qi;
new_reply_info = construct_reply_info_base(ms->region,
LDNS_RCODE_NOERROR | BIT_QR | BIT_AA | BIT_RA,
1, /* qd */
static inline struct dns_msg*
rpz_synthesize_nsip_localdata(struct rpz* r, struct module_qstate* ms,
- struct clientip_synthesized_rr* data, struct auth_zone* az)
+ struct query_info* qi, struct clientip_synthesized_rr* data,
+ struct auth_zone* az)
{
- struct query_info* qi = &ms->qinfo;
struct local_rrset* rrset;
- rrset = rpz_find_synthesized_rrset(qi->qtype, data);
+ rrset = rpz_find_synthesized_rrset(qi->qtype, data, 1);
if(rrset == NULL) {
verbose(VERB_ALGO, "rpz: nsip: no matching local data found");
return NULL;
}
- return rpz_synthesize_localdata_from_rrset(r, ms, &ms->qinfo, rrset, az);
+ return rpz_synthesize_localdata_from_rrset(r, ms, qi, rrset, az);
}
/* copy'n'paste from localzone.c */
static struct local_rrset*
local_data_find_type(struct local_data* data, uint16_t type, int alias_ok)
{
- struct local_rrset* p;
+ struct local_rrset* p, *cname = NULL;
type = htons(type);
for(p = data->rrsets; p; p = p->next) {
if(p->rrset->rk.type == type)
return p;
if(alias_ok && p->rrset->rk.type == htons(LDNS_RR_TYPE_CNAME))
- return p;
+ cname = p;
}
+ if(alias_ok)
+ return cname;
return NULL;
}
/* 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 auth_zone* az)
+ struct query_info* qi, struct local_zone* z,
+ struct matched_delegation_point const* match, struct auth_zone* az)
{
struct local_data key;
struct local_data* ld;
return NULL;
}
- rrset = local_data_find_type(ld, ms->qinfo.qtype, 1);
+ rrset = local_data_find_type(ld, qi->qtype, 1);
if(rrset == NULL) {
verbose(VERB_ALGO, "rpz: nsdname: no matching local data found");
return NULL;
}
- return rpz_synthesize_localdata_from_rrset(r, ms, &ms->qinfo, rrset, az);
+ return rpz_synthesize_localdata_from_rrset(r, ms, qi, rrset, az);
}
/* like local_data_answer for qname triggers after a cname */
key.namelabs = dname_count_labels(qinfo->qname);
ld = (struct local_data*)rbtree_search(&z->data, &key.node);
if(ld == NULL) {
- verbose(VERB_ALGO, "rpz: qname after cname: name not found");
+ verbose(VERB_ALGO, "rpz: qname: name not found");
return NULL;
}
rrset = local_data_find_type(ld, qinfo->qtype, 1);
if(rrset == NULL) {
- verbose(VERB_ALGO, "rpz: qname after cname: type not found");
+ verbose(VERB_ALGO, "rpz: qname: type not found");
return NULL;
}
return rpz_synthesize_localdata_from_rrset(r, ms, qinfo, rrset, az);
}
+/** Synthesize a CNAME message for RPZ action override */
+static struct dns_msg*
+rpz_synthesize_cname_override_msg(struct rpz* r, struct module_qstate* ms,
+ struct query_info* qinfo)
+{
+ struct dns_msg* msg = NULL;
+ struct reply_info* new_reply_info;
+ struct ub_packed_rrset_key* rp;
+
+ msg = rpz_dns_msg_new(ms->region);
+ if(msg == NULL) { return NULL; }
+
+ msg->qinfo = *qinfo;
+ new_reply_info = construct_reply_info_base(ms->region,
+ LDNS_RCODE_NOERROR | BIT_QR | BIT_AA | BIT_RA,
+ 1, /* qd */
+ 0, /* ttl */
+ 0, /* prettl */
+ 0, /* expttl */
+ 1, /* an */
+ 0, /* ns */
+ 0, /* ar */
+ 1, /* total */
+ sec_status_insecure,
+ LDNS_EDE_NONE);
+ if(new_reply_info == NULL) {
+ log_err("out of memory");
+ return NULL;
+ }
+ new_reply_info->authoritative = 1;
+
+ rp = respip_copy_rrset(r->cname_override, ms->region);
+ if(rp == NULL) {
+ log_err("out of memory");
+ return NULL;
+ }
+ rp->rk.dname = qinfo->qname;
+ rp->rk.dname_len = qinfo->qname_len;
+ /* this rrset is from the rpz data, or synthesized.
+ * It is not actually from the network, so we flag it with this
+ * flags as a fake RRset. If later the cache is used to look up
+ * rrsets, then the fake ones are not returned (if you look without
+ * the flag). For like CNAME lookups from the iterator or A, AAAA
+ * lookups for nameserver targets, it would use the without flag
+ * actual data. So that the actual network data and fake data
+ * are kept track of separately. */
+ rp->rk.flags |= PACKED_RRSET_RPZ;
+ new_reply_info->rrsets[0] = rp;
+
+ msg->rep = new_reply_info;
+ return msg;
+}
+
static int
rpz_synthesize_qname_localdata(struct module_env* env, struct rpz* r,
struct local_zone* z, enum localzone_type lzt, struct query_info* qinfo,
struct local_data* ld = NULL;
int ret = 0;
if(r->action_override == RPZ_CNAME_OVERRIDE_ACTION) {
- qinfo->local_alias = regional_alloc_zero(temp, sizeof(struct local_rrset));
- if(qinfo->local_alias == NULL) {
- return 0; /* out of memory */
- }
- qinfo->local_alias->rrset = regional_alloc_init(temp, r->cname_override,
- sizeof(*r->cname_override));
- if(qinfo->local_alias->rrset == NULL) {
- return 0; /* out of memory */
- }
- qinfo->local_alias->rrset->rk.dname = qinfo->qname;
- qinfo->local_alias->rrset->rk.dname_len = qinfo->qname_len;
+ if(!rpz_apply_cname_override_action(r, qinfo, temp))
+ return 0;
if(r->log) {
log_rpz_apply("qname", z->name, NULL, RPZ_CNAME_OVERRIDE_ACTION,
qinfo, repinfo, NULL, r->log_name);
}
static struct dns_msg*
-rpz_apply_nsip_trigger(struct module_qstate* ms, struct rpz* r,
- struct clientip_synthesized_rr* raddr, struct auth_zone* az)
+rpz_apply_nsip_trigger(struct module_qstate* ms, struct query_info* qchase,
+ struct rpz* r, 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, az);
+ ret = rpz_synthesize_nodata(r, ms, qchase, az);
goto done;
}
switch(action) {
case RPZ_NXDOMAIN_ACTION:
- ret = rpz_synthesize_nxdomain(r, ms, &ms->qinfo, az);
+ ret = rpz_synthesize_nxdomain(r, ms, qchase, az);
break;
case RPZ_NODATA_ACTION:
- ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az);
+ ret = rpz_synthesize_nodata(r, ms, qchase, 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, az);
+ ret = rpz_synthesize_nodata(r, ms, qchase, az);
ms->is_drop = 1;
break;
case RPZ_LOCAL_DATA_ACTION:
- ret = rpz_synthesize_nsip_localdata(r, ms, raddr, az);
- if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az); }
+ ret = rpz_synthesize_nsip_localdata(r, ms, qchase, raddr, az);
+ if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, qchase, az); }
break;
case RPZ_PASSTHRU_ACTION:
ret = NULL;
ms->rpz_passthru = 1;
break;
+ case RPZ_CNAME_OVERRIDE_ACTION:
+ ret = rpz_synthesize_cname_override_msg(r, ms, qchase);
+ break;
default:
verbose(VERB_ALGO, "rpz: nsip: bug: unhandled or invalid action: '%s'",
rpz_action_to_string(action));
}
static 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 auth_zone* az)
+rpz_apply_nsdname_trigger(struct module_qstate* ms, struct query_info* qchase,
+ struct rpz* r, 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, az);
+ ret = rpz_synthesize_nxdomain(r, ms, qchase, az);
break;
case RPZ_NODATA_ACTION:
- ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az);
+ ret = rpz_synthesize_nodata(r, ms, qchase, 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, az);
+ ret = rpz_synthesize_nodata(r, ms, qchase, az);
ms->is_drop = 1;
break;
case RPZ_LOCAL_DATA_ACTION:
- ret = rpz_synthesize_nsdname_localdata(r, ms, z, match, az);
- if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az); }
+ ret = rpz_synthesize_nsdname_localdata(r, ms, qchase, z, match, az);
+ if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, qchase, az); }
break;
case RPZ_PASSTHRU_ACTION:
ret = NULL;
ms->rpz_passthru = 1;
break;
+ case RPZ_CNAME_OVERRIDE_ACTION:
+ ret = rpz_synthesize_cname_override_msg(r, ms, qchase);
+ break;
default:
- verbose(VERB_ALGO, "rpz: nsip: bug: unhandled or invalid action: '%s'",
+ verbose(VERB_ALGO, "rpz: nsdname: bug: unhandled or invalid action: '%s'",
rpz_action_to_string(action));
ret = NULL;
}
/* the nsdname has precedence over the nsip triggers */
z = rpz_delegation_point_zone_lookup(is->dp, r->nsdname_zones,
- ms->qinfo.qclass, &match);
+ is->qchase.qclass, &match);
if(z != NULL) {
lock_rw_unlock(&a->lock);
break;
if(z) {
lock_rw_unlock(&z->lock);
}
- return rpz_apply_nsip_trigger(ms, r, raddr, a);
+ return rpz_apply_nsip_trigger(ms, &is->qchase, r, raddr, a);
}
- return rpz_apply_nsdname_trigger(ms, r, z, &match, a);
+ return rpz_apply_nsdname_trigger(ms, &is->qchase, r, z, &match, a);
}
struct dns_msg* rpz_callback_from_iterator_cname(struct module_qstate* ms,
dname_str(is->qchase.qname, nm);
dname_str(z->name, zn);
if(strcmp(zn, nm) != 0)
- verbose(VERB_ALGO, "rpz: qname trigger after cname %s on %s, with action=%s",
+ verbose(VERB_ALGO, "rpz: qname trigger %s on %s, with action=%s",
zn, nm, rpz_action_to_string(localzone_type_to_rpz_action(lzt)));
else
- verbose(VERB_ALGO, "rpz: qname trigger after cname %s, with action=%s",
+ verbose(VERB_ALGO, "rpz: qname trigger %s, with action=%s",
nm, rpz_action_to_string(localzone_type_to_rpz_action(lzt)));
}
switch(localzone_type_to_rpz_action(lzt)) {
ms->rpz_passthru = 1;
break;
default:
- verbose(VERB_ALGO, "rpz: qname trigger after cname: bug: unhandled or invalid action: '%s'",
+ verbose(VERB_ALGO, "rpz: qname trigger: bug: unhandled or invalid action: '%s'",
rpz_action_to_string(localzone_type_to_rpz_action(lzt)));
ret = NULL;
}
az, qinfo, repinfo, taglist, taglen, stats, z_out, a_out, r_out);
client_action = ((node == NULL) ? RPZ_INVALID_ACTION : node->action);
+ if(node != NULL && *r_out &&
+ (*r_out)->action_override != RPZ_NO_OVERRIDE_ACTION) {
+ client_action = (*r_out)->action_override;
+ }
if(client_action == RPZ_PASSTHRU_ACTION) {
+ if(*r_out && (*r_out)->log)
+ log_rpz_apply(
+ (node?"clientip":"qname"),
+ ((*z_out)?(*z_out)->name:NULL),
+ (node?&node->node:NULL),
+ client_action, qinfo, repinfo, NULL,
+ (*r_out)->log_name);
*passthru = 1;
+ ret = 0;
+ goto done;
}
if(*z_out == NULL || (client_action != RPZ_INVALID_ACTION &&
client_action != RPZ_PASSTHRU_ACTION)) {
if(client_action == RPZ_LOCAL_DATA_ACTION) {
rpz_apply_clientip_localdata_action(node, env, qinfo,
edns, repinfo, buf, temp, *a_out);
+ ret = 1;
+ } else if(client_action == RPZ_CNAME_OVERRIDE_ACTION) {
+ if(!rpz_apply_cname_override_action(*r_out, qinfo,
+ temp)) {
+ ret = 0;
+ goto done;
+ }
+ ret = 0;
} else {
- if(*r_out && (*r_out)->log)
- log_rpz_apply(
- (node?"clientip":"qname"),
- ((*z_out)?(*z_out)->name:NULL),
- (node?&node->node:NULL),
- client_action, qinfo, repinfo, NULL,
- (*r_out)->log_name);
local_zones_zone_answer(*z_out /*likely NULL, no zone*/, env, qinfo, edns,
repinfo, buf, temp, 0 /* no local data used */,
rpz_action_to_localzone_type(client_action));
LDNS_RCODE_WIRE(sldns_buffer_begin(buf))
== LDNS_RCODE_NXDOMAIN)
LDNS_RA_CLR(sldns_buffer_begin(buf));
+ ret = 1;
}
- ret = 1;
+ if(*r_out && (*r_out)->log)
+ log_rpz_apply(
+ (node?"clientip":"qname"),
+ ((*z_out)?(*z_out)->name:NULL),
+ (node?&node->node:NULL),
+ client_action, qinfo, repinfo, NULL,
+ (*r_out)->log_name);
goto done;
}
ret = -1;