mirror of
https://github.com/NLnetLabs/unbound.git
synced 2025-12-20 23:00:56 -05:00
edit config parser to support ipset
This commit is contained in:
parent
1a48bdebb5
commit
56af87e2f3
6 changed files with 394 additions and 285 deletions
|
|
@ -653,6 +653,9 @@ server:
|
|||
# local-zone: "8.b.d.0.1.0.0.2.ip6.arpa." nodefault
|
||||
# And for 64.100.in-addr.arpa. to 127.100.in-addr.arpa.
|
||||
|
||||
# Add example.com into ipset
|
||||
# local-zone: "example.com" ipset
|
||||
|
||||
# If unbound is running service for the local host then it is useful
|
||||
# to perform lan-wide lookups to the upstream, and unblock the
|
||||
# long list of local-zones above. If this unbound is a dns server
|
||||
|
|
@ -991,3 +994,14 @@ remote-control:
|
|||
# redis-server-port: 6379
|
||||
# # timeout (in ms) for communication with the redis server
|
||||
# redis-timeout: 100
|
||||
|
||||
# IPSet
|
||||
# Add specify domain into set via ipset.
|
||||
# Note: To enable ipset needs run unbound as root user.
|
||||
# ipset:
|
||||
# # set name for ip v4 addresses
|
||||
# name-v4: "list-v4"
|
||||
# # set name for ip v6 addresses
|
||||
# name-v6: "list-v6"
|
||||
#
|
||||
|
||||
|
|
|
|||
|
|
@ -2,10 +2,12 @@
|
|||
#include "ipset/ipset.h"
|
||||
#include "util/regional.h"
|
||||
#include "util/config_file.h"
|
||||
|
||||
#include "services/cache/dns.h"
|
||||
#include "sldns/parseutil.h"
|
||||
|
||||
#include "sldns/sbuffer.h"
|
||||
#include "sldns/wire2str.h"
|
||||
#include "sldns/parseutil.h"
|
||||
|
||||
#include <libmnl/libmnl.h>
|
||||
#include <linux/netfilter/nfnetlink.h>
|
||||
|
|
@ -21,8 +23,7 @@
|
|||
* @return: 0 for use by caller, to make notation easy, like:
|
||||
* return error_response(..).
|
||||
*/
|
||||
static int error_response(struct module_qstate* qstate, int id, int rcode)
|
||||
{
|
||||
static int error_response(struct module_qstate* qstate, int id, int rcode) {
|
||||
verbose(VERB_QUERY, "return error response %s",
|
||||
sldns_lookup_by_id(sldns_rcodes, rcode)?
|
||||
sldns_lookup_by_id(sldns_rcodes, rcode)->name:"??");
|
||||
|
|
@ -36,7 +37,7 @@ static int add_to_ipset(struct mnl_socket *mnl, const char *setname, const void
|
|||
struct nlmsghdr *nlh;
|
||||
struct nfgenmsg *nfg;
|
||||
struct nlattr *nested[2];
|
||||
char buffer[BUFF_LEN];
|
||||
static char buffer[BUFF_LEN];
|
||||
|
||||
if (strlen(setname) >= IPSET_MAXNAMELEN) {
|
||||
errno = ENAMETOOLONG;
|
||||
|
|
@ -49,7 +50,7 @@ static int add_to_ipset(struct mnl_socket *mnl, const char *setname, const void
|
|||
|
||||
nlh = mnl_nlmsg_put_header(buffer);
|
||||
nlh->nlmsg_type = IPSET_CMD_ADD | (NFNL_SUBSYS_IPSET << 8);
|
||||
nlh->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK|NLM_F_EXCL;
|
||||
nlh->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK|NLM_F_EXCL;
|
||||
|
||||
nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(struct nfgenmsg));
|
||||
nfg->nfgen_family = af;
|
||||
|
|
@ -71,29 +72,40 @@ static int add_to_ipset(struct mnl_socket *mnl, const char *setname, const void
|
|||
return 0;
|
||||
}
|
||||
|
||||
int ipset_update(struct dns_msg* return_msg, struct ipset_env *ie) {
|
||||
int i, j;
|
||||
static int ipset_update(struct module_env *env, struct dns_msg *return_msg, struct ipset_env *ie) {
|
||||
int ret;
|
||||
int af;
|
||||
uint16_t rrtype;
|
||||
size_t rr_len, rd_len;
|
||||
struct ub_packed_rrset_key *rrset;
|
||||
struct packed_rrset_data* d;
|
||||
uint8_t *rr_data;
|
||||
|
||||
struct mnl_socket *mnl;
|
||||
|
||||
int i, j;
|
||||
|
||||
const char *setname;
|
||||
|
||||
struct mnl_socket *mnl;
|
||||
struct ub_packed_rrset_key *rrset;
|
||||
struct packed_rrset_data *d;
|
||||
|
||||
int af;
|
||||
|
||||
static char dname[BUFF_LEN];
|
||||
const char *s;
|
||||
int dlen, plen;
|
||||
|
||||
struct config_strlist *p;
|
||||
|
||||
uint16_t rrtype;
|
||||
size_t rr_len, rd_len;
|
||||
|
||||
uint8_t *rr_data;
|
||||
|
||||
mnl = (struct mnl_socket *)ie->mnl;
|
||||
if (mnl == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < return_msg->rep->rrset_count; ++i) {
|
||||
for (i = 0; i < return_msg->rep->rrset_count; ++i) {
|
||||
setname = NULL;
|
||||
|
||||
rrset = return_msg->rep->rrsets[i];
|
||||
rrset = return_msg->rep->rrsets[i];
|
||||
|
||||
if (rrset->rk.type == htons(LDNS_RR_TYPE_A)) {
|
||||
af = AF_INET;
|
||||
|
|
@ -107,20 +119,46 @@ int ipset_update(struct dns_msg* return_msg, struct ipset_env *ie) {
|
|||
}
|
||||
}
|
||||
|
||||
if (setname != NULL) {
|
||||
d = (struct packed_rrset_data*)rrset->entry.data;
|
||||
for (j = 0; j < d->count + d->rrsig_count; j++) {
|
||||
rr_len = d->rr_len[j];
|
||||
rr_data = d->rr_data[j];
|
||||
if (setname != NULL) {
|
||||
dlen = sldns_wire2str_dname_buf(rrset->rk.dname, rrset->rk.dname_len, dname, BUFF_LEN);
|
||||
if (dlen == 0) {
|
||||
log_err("bad domain name");
|
||||
return -1;
|
||||
}
|
||||
if (dname[dlen - 1] == '.') {
|
||||
dlen--;
|
||||
dname[dlen] = 0;
|
||||
}
|
||||
|
||||
rd_len = sldns_read_uint16(rr_data);
|
||||
if (rr_len - 2 >= rd_len) {
|
||||
ret = add_to_ipset(mnl, setname, rr_data + 2, af);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
verbose(VERB_QUERY, "ipset domain name %d %s", dlen, dname);
|
||||
|
||||
for (p = env->cfg->local_zones_ipset; p; p = p->next) {
|
||||
plen = strlen(p->str);
|
||||
|
||||
verbose(VERB_QUERY, "ipset local_zones_ipset name %d %s", plen, p->str);
|
||||
|
||||
if (dlen >= plen) {
|
||||
s = dname + (dlen - plen);
|
||||
verbose(VERB_QUERY, "ipset start name %s", s);
|
||||
|
||||
if (strncasecmp(p->str, s, plen) == 0) {
|
||||
d = (struct packed_rrset_data*)rrset->entry.data;
|
||||
for (j = 0; j < d->count + d->rrsig_count; j++) {
|
||||
rr_len = d->rr_len[j];
|
||||
rr_data = d->rr_data[j];
|
||||
|
||||
rd_len = sldns_read_uint16(rr_data);
|
||||
if (rr_len - 2 >= rd_len) {
|
||||
ret = add_to_ipset(mnl, setname, rr_data + 2, af);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -222,7 +260,7 @@ void ipset_operate(struct module_qstate *qstate, enum module_ev event, int id,
|
|||
}
|
||||
|
||||
if(iq && (event == module_event_moddone)) {
|
||||
ipset_update(qstate->return_msg, ie);
|
||||
ipset_update(qstate->env, qstate->return_msg, ie);
|
||||
qstate->ext_state[id] = module_finished;
|
||||
return;
|
||||
}
|
||||
|
|
@ -287,3 +325,4 @@ struct module_func_block * ipset_get_funcblock(void) {
|
|||
return &ipset_block;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -255,6 +255,9 @@ config_create(void)
|
|||
cfg->neg_cache_size = 1 * 1024 * 1024;
|
||||
cfg->local_zones = NULL;
|
||||
cfg->local_zones_nodefault = NULL;
|
||||
#ifdef USE_IPSET
|
||||
cfg->local_zones_ipset = NULL;
|
||||
#endif
|
||||
cfg->local_zones_disable_default = 0;
|
||||
cfg->local_data = NULL;
|
||||
cfg->local_zone_overrides = NULL;
|
||||
|
|
@ -1318,6 +1321,9 @@ config_delview(struct config_view* p)
|
|||
free(p->name);
|
||||
config_deldblstrlist(p->local_zones);
|
||||
config_delstrlist(p->local_zones_nodefault);
|
||||
#ifdef USE_IPSET
|
||||
config_delstrlist(p->local_zones_ipset);
|
||||
#endif
|
||||
config_delstrlist(p->local_data);
|
||||
free(p);
|
||||
}
|
||||
|
|
@ -1408,6 +1414,9 @@ config_delete(struct config_file* cfg)
|
|||
free(cfg->val_nsec3_key_iterations);
|
||||
config_deldblstrlist(cfg->local_zones);
|
||||
config_delstrlist(cfg->local_zones_nodefault);
|
||||
#ifdef USE_IPSET
|
||||
config_delstrlist(cfg->local_zones_ipset);
|
||||
#endif
|
||||
config_delstrlist(cfg->local_data);
|
||||
config_deltrplstrlist(cfg->local_zone_overrides);
|
||||
config_del_strarray(cfg->tagname, cfg->num_tags);
|
||||
|
|
@ -2119,6 +2128,11 @@ cfg_parse_local_zone(struct config_file* cfg, const char* val)
|
|||
if(strcmp(type, "nodefault")==0) {
|
||||
return cfg_strlist_insert(&cfg->local_zones_nodefault,
|
||||
strdup(name));
|
||||
#ifdef USE_IPSET
|
||||
} else if(strcmp(type, "ipset")==0) {
|
||||
return cfg_strlist_insert(&cfg->local_zones_ipset,
|
||||
strdup(name));
|
||||
#endif
|
||||
} else {
|
||||
return cfg_str2list_insert(&cfg->local_zones, strdup(buf),
|
||||
strdup(type));
|
||||
|
|
@ -2393,3 +2407,4 @@ int options_remote_is_address(struct config_file* cfg)
|
|||
if(cfg->control_ifs.first->str[0] == 0) return 1;
|
||||
return (cfg->control_ifs.first->str[0] != '/');
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -384,6 +384,10 @@ struct config_file {
|
|||
struct config_str2list* local_zones;
|
||||
/** local zones nodefault list */
|
||||
struct config_strlist* local_zones_nodefault;
|
||||
#ifdef USE_IPSET
|
||||
/** local zones ipset list */
|
||||
struct config_strlist* local_zones_ipset;
|
||||
#endif
|
||||
/** do not add any default local zone */
|
||||
int local_zones_disable_default;
|
||||
/** local data RRs configured */
|
||||
|
|
@ -653,6 +657,10 @@ struct config_view {
|
|||
struct config_strlist* local_data;
|
||||
/** local zones nodefault list */
|
||||
struct config_strlist* local_zones_nodefault;
|
||||
#ifdef USE_IPSET
|
||||
/** local zones ipset list */
|
||||
struct config_strlist* local_zones_ipset;
|
||||
#endif
|
||||
/** Fallback to global local_zones when there is no match in the view
|
||||
* view specific tree. 1 for yes, 0 for no */
|
||||
int isfirst;
|
||||
|
|
@ -1187,3 +1195,4 @@ void w_config_adjust_directory(struct config_file* cfg);
|
|||
extern int fake_dsa, fake_sha1;
|
||||
|
||||
#endif /* UTIL_CONFIG_FILE_H */
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -175,7 +175,7 @@ toplevelvar: serverstart contents_server | stubstart contents_stub |
|
|||
forwardstart contents_forward | pythonstart contents_py |
|
||||
rcstart contents_rc | dtstart contents_dt | viewstart contents_view |
|
||||
dnscstart contents_dnsc | cachedbstart contents_cachedb |
|
||||
ipsetstart contents_ipset | authstart contents_auth
|
||||
ipsetstart contents_ipset | authstart contents_auth
|
||||
;
|
||||
|
||||
/* server: declaration */
|
||||
|
|
@ -1785,13 +1785,14 @@ server_local_zone: VAR_LOCAL_ZONE STRING_ARG STRING_ARG
|
|||
&& strcmp($3, "always_nxdomain")!=0
|
||||
&& strcmp($3, "noview")!=0
|
||||
&& strcmp($3, "inform")!=0 && strcmp($3, "inform_deny")!=0
|
||||
&& strcmp($3, "inform_redirect") != 0) {
|
||||
&& strcmp($3, "inform_redirect") != 0
|
||||
&& strcmp($3, "ipset") != 0) {
|
||||
yyerror("local-zone type: expected static, deny, "
|
||||
"refuse, redirect, transparent, "
|
||||
"typetransparent, inform, inform_deny, "
|
||||
"inform_redirect, always_transparent, "
|
||||
"always_refuse, always_nxdomain, noview "
|
||||
"or nodefault");
|
||||
", nodefault or ipset");
|
||||
free($2);
|
||||
free($3);
|
||||
} else if(strcmp($3, "nodefault")==0) {
|
||||
|
|
@ -1799,6 +1800,13 @@ server_local_zone: VAR_LOCAL_ZONE STRING_ARG STRING_ARG
|
|||
local_zones_nodefault, $2))
|
||||
fatal_exit("out of memory adding local-zone");
|
||||
free($3);
|
||||
#ifdef USE_IPSET
|
||||
} else if(strcmp($3, "ipset")==0) {
|
||||
if(!cfg_strlist_insert(&cfg_parser->cfg->
|
||||
local_zones_ipset, $2))
|
||||
fatal_exit("out of memory adding local-zone");
|
||||
free($3);
|
||||
#endif
|
||||
} else {
|
||||
if(!cfg_str2list_insert(&cfg_parser->cfg->local_zones,
|
||||
$2, $3))
|
||||
|
|
@ -2456,6 +2464,13 @@ view_local_zone: VAR_LOCAL_ZONE STRING_ARG STRING_ARG
|
|||
local_zones_nodefault, $2))
|
||||
fatal_exit("out of memory adding local-zone");
|
||||
free($3);
|
||||
#ifdef USE_IPSET
|
||||
} else if(strcmp($3, "ipset")==0) {
|
||||
if(!cfg_strlist_insert(&cfg_parser->cfg->views->
|
||||
local_zones_ipset, $2))
|
||||
fatal_exit("out of memory adding local-zone");
|
||||
free($3);
|
||||
#endif
|
||||
} else {
|
||||
if(!cfg_str2list_insert(
|
||||
&cfg_parser->cfg->views->local_zones,
|
||||
|
|
@ -3019,3 +3034,4 @@ validate_respip_action(const char* action)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue