- Response actions based on IP address from Jinmei Tatuya (Infoblox).

git-svn-id: file:///svn/unbound/trunk@4035 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards
2017-03-07 14:58:51 +00:00
parent 570564a375
commit cae9809e11
32 changed files with 4878 additions and 2495 deletions
+262
View File
@@ -558,6 +558,267 @@ rnd_test(void)
ub_randfree(r);
}
#include "respip/respip.h"
#include "services/localzone.h"
#include "util/data/packed_rrset.h"
typedef struct addr_action {char* ip; char* sact; enum respip_action act;}
addr_action_t;
/** Utility function that verifies that the respip set has actions as expected */
static void
verify_respip_set_actions(struct respip_set* set, addr_action_t actions[],
int actions_len)
{
int i = 0;
struct rbtree_type* tree = respip_set_get_tree(set);
for (i=0; i<actions_len; i++) {
struct sockaddr_storage addr;
int net;
socklen_t addrlen;
struct resp_addr* node;
netblockstrtoaddr(actions[i].ip, UNBOUND_DNS_PORT, &addr,
&addrlen, &net);
node = (struct resp_addr*)addr_tree_find(tree, &addr, addrlen, net);
/** we have the node and the node has the correct action
* and has no data */
unit_assert(node);
unit_assert(actions[i].act ==
resp_addr_get_action(node));
unit_assert(resp_addr_get_rrset(node) == NULL);
}
unit_assert(actions_len && i == actions_len);
unit_assert(actions_len == (int)tree->count);
}
/** Global respip actions test; apply raw config data and verify that
* all the nodes in the respip set, looked up by address, have expected
* actions */
static void
respip_conf_actions_test(void)
{
addr_action_t config_response_ip[] = {
{"192.0.1.0/24", "deny", respip_deny},
{"192.0.2.0/24", "redirect", respip_redirect},
{"192.0.3.0/26", "inform", respip_inform},
{"192.0.4.0/27", "inform_deny", respip_inform_deny},
{"2001:db8:1::/48", "always_transparent", respip_always_transparent},
{"2001:db8:2::/49", "always_refuse", respip_always_refuse},
{"2001:db8:3::/50", "always_nxdomain", respip_always_nxdomain},
};
int i;
struct respip_set* set = respip_set_create();
struct config_file cfg;
int clen = sizeof(config_response_ip) / sizeof(addr_action_t);
unit_assert(set);
unit_show_feature("global respip config actions apply");
memset(&cfg, 0, sizeof(cfg));
for(i=0; i<clen; i++) {
char* ip = strdup(config_response_ip[i].ip);
char* sact = strdup(config_response_ip[i].sact);
unit_assert(ip && sact);
if(!cfg_str2list_insert(&cfg.respip_actions, ip, sact))
unit_assert(0);
}
unit_assert(respip_global_apply_cfg(set, &cfg));
verify_respip_set_actions(set, config_response_ip, clen);
}
/** Per-view respip actions test; apply raw configuration with two views
* and verify that actions are as expected in respip sets of both views */
static void
respip_view_conf_actions_test(void)
{
addr_action_t config_response_ip_view1[] = {
{"192.0.1.0/24", "deny", respip_deny},
{"192.0.2.0/24", "redirect", respip_redirect},
{"192.0.3.0/26", "inform", respip_inform},
{"192.0.4.0/27", "inform_deny", respip_inform_deny},
};
addr_action_t config_response_ip_view2[] = {
{"2001:db8:1::/48", "always_transparent", respip_always_transparent},
{"2001:db8:2::/49", "always_refuse", respip_always_refuse},
{"2001:db8:3::/50", "always_nxdomain", respip_always_nxdomain},
};
int i;
struct config_file cfg;
int clen1 = sizeof(config_response_ip_view1) / sizeof(addr_action_t);
int clen2 = sizeof(config_response_ip_view2) / sizeof(addr_action_t);
struct config_view* cv1;
struct config_view* cv2;
int have_respip_cfg = 0;
struct views* views = NULL;
struct view* v = NULL;
unit_show_feature("per-view respip config actions apply");
memset(&cfg, 0, sizeof(cfg));
cv1 = (struct config_view*)calloc(1, sizeof(struct config_view));
cv2 = (struct config_view*)calloc(1, sizeof(struct config_view));
unit_assert(cv1 && cv2);
cv1->name = strdup("view1");
cv2->name = strdup("view2");
unit_assert(cv1->name && cv2->name);
cv1->next = cv2;
cfg.views = cv1;
for(i=0; i<clen1; i++) {
char* ip = strdup(config_response_ip_view1[i].ip);
char* sact = strdup(config_response_ip_view1[i].sact);
unit_assert(ip && sact);
if(!cfg_str2list_insert(&cv1->respip_actions, ip, sact))
unit_assert(0);
}
for(i=0; i<clen2; i++) {
char* ip = strdup(config_response_ip_view2[i].ip);
char* sact = strdup(config_response_ip_view2[i].sact);
unit_assert(ip && sact);
if(!cfg_str2list_insert(&cv2->respip_actions, ip, sact))
unit_assert(0);
}
views = views_create();
unit_assert(views);
unit_assert(views_apply_cfg(views, &cfg));
unit_assert(respip_views_apply_cfg(views, &cfg, &have_respip_cfg));
/* now verify the respip sets in each view */
v = views_find_view(views, "view1", 0);
unit_assert(v);
verify_respip_set_actions(v->respip_set, config_response_ip_view1, clen1);
v = views_find_view(views, "view2", 0);
unit_assert(v);
verify_respip_set_actions(v->respip_set, config_response_ip_view2, clen2);
}
typedef struct addr_data {char* ip; char* data;} addr_data_t;
/** find the respip address node in the specified tree (by address lookup)
* and verify type and address of the specified rdata (by index) in this
* node's rrset */
static void
verify_rrset(struct respip_set* set, const char* ipstr,
const char* rdatastr, size_t rdi, uint16_t type)
{
struct sockaddr_storage addr;
int net;
char buf[65536];
socklen_t addrlen;
struct rbtree_type* tree;
struct resp_addr* node;
const struct ub_packed_rrset_key* rrs;
netblockstrtoaddr(ipstr, UNBOUND_DNS_PORT, &addr, &addrlen, &net);
tree = respip_set_get_tree(set);
node = (struct resp_addr*)addr_tree_find(tree, &addr, addrlen, net);
unit_assert(node);
unit_assert((rrs = resp_addr_get_rrset(node)));
unit_assert(ntohs(rrs->rk.type) == type);
packed_rr_to_string((struct ub_packed_rrset_key*)rrs,
rdi, 0, buf, sizeof(buf));
unit_assert(strstr(buf, rdatastr));
}
/** Dataset used to test redirect rrset initialization for both
* global and per-view respip redirect configuration */
static addr_data_t config_response_ip_data[] = {
{"192.0.1.0/24", "A 1.2.3.4"},
{"192.0.1.0/24", "A 11.12.13.14"},
{"192.0.2.0/24", "CNAME www.example.com."},
{"2001:db8:1::/48", "AAAA 2001:db8:1::2:1"},
};
/** Populate raw respip redirect config data, used for both global and
* view-based respip redirect test case */
static void
cfg_insert_respip_data(struct config_str2list** respip_actions,
struct config_str2list** respip_data)
{
int clen = sizeof(config_response_ip_data) / sizeof(addr_data_t);
int i = 0;
/* insert actions (duplicate netblocks don't matter) */
for(i=0; i<clen; i++) {
char* ip = strdup(config_response_ip_data[i].ip);
char* sact = strdup("redirect");
unit_assert(ip && sact);
if(!cfg_str2list_insert(respip_actions, ip, sact))
unit_assert(0);
}
/* insert data */
for(i=0; i<clen; i++) {
char* ip = strdup(config_response_ip_data[i].ip);
char* data = strdup(config_response_ip_data[i].data);
unit_assert(ip && data);
if(!cfg_str2list_insert(respip_data, ip, data))
unit_assert(0);
}
}
/** Test global respip redirect w/ data directives */
static void
respip_conf_data_test(void)
{
struct respip_set* set = respip_set_create();
struct config_file cfg;
unit_show_feature("global respip config data apply");
memset(&cfg, 0, sizeof(cfg));
cfg_insert_respip_data(&cfg.respip_actions, &cfg.respip_data);
/* apply configuration and verify rrsets */
unit_assert(respip_global_apply_cfg(set, &cfg));
verify_rrset(set, "192.0.1.0/24", "1.2.3.4", 0, LDNS_RR_TYPE_A);
verify_rrset(set, "192.0.1.0/24", "11.12.13.14", 1, LDNS_RR_TYPE_A);
verify_rrset(set, "192.0.2.0/24", "www.example.com", 0, LDNS_RR_TYPE_CNAME);
verify_rrset(set, "2001:db8:1::/48", "2001:db8:1::2:1", 0, LDNS_RR_TYPE_AAAA);
}
/** Test per-view respip redirect w/ data directives */
static void
respip_view_conf_data_test(void)
{
struct config_file cfg;
struct config_view* cv;
int have_respip_cfg = 0;
struct views* views = NULL;
struct view* v = NULL;
unit_show_feature("per-view respip config data apply");
memset(&cfg, 0, sizeof(cfg));
cv = (struct config_view*)calloc(1, sizeof(struct config_view));
unit_assert(cv);
cv->name = strdup("view1");
unit_assert(cv->name);
cfg.views = cv;
cfg_insert_respip_data(&cv->respip_actions, &cv->respip_data);
views = views_create();
unit_assert(views);
unit_assert(views_apply_cfg(views, &cfg));
/* apply configuration and verify rrsets */
unit_assert(respip_views_apply_cfg(views, &cfg, &have_respip_cfg));
v = views_find_view(views, "view1", 0);
unit_assert(v);
verify_rrset(v->respip_set, "192.0.1.0/24", "1.2.3.4",
0, LDNS_RR_TYPE_A);
verify_rrset(v->respip_set, "192.0.1.0/24", "11.12.13.14",
1, LDNS_RR_TYPE_A);
verify_rrset(v->respip_set, "192.0.2.0/24", "www.example.com",
0, LDNS_RR_TYPE_CNAME);
verify_rrset(v->respip_set, "2001:db8:1::/48", "2001:db8:1::2:1",
0, LDNS_RR_TYPE_AAAA);
}
/** respip unit tests */
static void respip_test(void)
{
respip_view_conf_data_test();
respip_conf_data_test();
respip_view_conf_actions_test();
respip_conf_actions_test();
}
void unit_show_func(const char* file, const char* func)
{
printf("test %s:%s\n", file, func);
@@ -604,6 +865,7 @@ main(int argc, char* argv[])
checklock_start();
neg_test();
rnd_test();
respip_test();
verify_test();
net_test();
config_memsize_test();