Commit 13d86c73 authored by Jason A. Donenfeld's avatar Jason A. Donenfeld Committed by Simon Kelley

Add --ipset option.

parent 208fb610
...@@ -43,6 +43,9 @@ version 2.66 ...@@ -43,6 +43,9 @@ version 2.66
Thanks to Robert M. Albrecht for the bug report and Thanks to Robert M. Albrecht for the bug report and
chasing the problem. chasing the problem.
Add --ipset option. Thanks to Jason A. Donenfeld for the
patch.
version 2.65 version 2.65
Fix regression which broke forwarding of queries sent via Fix regression which broke forwarding of queries sent via
......
...@@ -65,7 +65,7 @@ version = -DVERSION='\"`$(top)/bld/get-version $(top)`\"' ...@@ -65,7 +65,7 @@ version = -DVERSION='\"`$(top)/bld/get-version $(top)`\"'
objs = cache.o rfc1035.o util.o option.o forward.o network.o \ objs = cache.o rfc1035.o util.o option.o forward.o network.o \
dnsmasq.o dhcp.o lease.o rfc2131.o netlink.o dbus.o bpf.o \ dnsmasq.o dhcp.o lease.o rfc2131.o netlink.o dbus.o bpf.o \
helper.o tftp.o log.o conntrack.o dhcp6.o rfc3315.o \ helper.o tftp.o log.o conntrack.o dhcp6.o rfc3315.o \
dhcp-common.o outpacket.o radv.o slaac.o auth.o dhcp-common.o outpacket.o radv.o slaac.o auth.o ipset.o
hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \ hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
dns-protocol.h radv-protocol.h dns-protocol.h radv-protocol.h
......
...@@ -69,6 +69,10 @@ ...@@ -69,6 +69,10 @@
# --address (and --server) work with IPv6 addresses too. # --address (and --server) work with IPv6 addresses too.
#address=/www.thekelleys.org.uk/fe80::20d:60ff:fe36:f83 #address=/www.thekelleys.org.uk/fe80::20d:60ff:fe36:f83
# Add the IPs of all queries to yahoo.com, google.com, and their
# subdomains to the vpn and search ipsets:
#ipset=/yahoo.com/google.com/vpn,search
# You can control how dnsmasq talks to a server: this forces # You can control how dnsmasq talks to a server: this forces
# queries to 10.1.2.3 to be routed via eth1 # queries to 10.1.2.3 to be routed via eth1
# server=10.1.2.3@eth1 # server=10.1.2.3@eth1
......
...@@ -412,6 +412,12 @@ additional facility that /#/ matches any domain. Thus ...@@ -412,6 +412,12 @@ additional facility that /#/ matches any domain. Thus
answered from /etc/hosts or DHCP and not sent to an upstream answered from /etc/hosts or DHCP and not sent to an upstream
nameserver by a more specific --server directive. nameserver by a more specific --server directive.
.TP .TP
.B --ipset=/<domain>/[domain/]<ipset>[,<ipset>]
Places the resolved IP addresses of queries for the specified domains
in the specified netfilter ip sets. Domains and subdomains are matched
in the same way as --address. These ip sets must already exist. See
ipset(8) for more details.
.TP
.B \-m, --mx-host=<mx name>[[,<hostname>],<preference>] .B \-m, --mx-host=<mx name>[[,<hostname>],<preference>]
Return an MX record named <mx name> pointing to the given hostname (if Return an MX record named <mx name> pointing to the given hostname (if
given), or given), or
......
...@@ -97,6 +97,10 @@ HAVE_CONNTRACK ...@@ -97,6 +97,10 @@ HAVE_CONNTRACK
a build-dependency on libnetfilter_conntrack, but the resulting binary will a build-dependency on libnetfilter_conntrack, but the resulting binary will
still run happily on a kernel without conntrack support. still run happily on a kernel without conntrack support.
HAVE_IPSET
define this to include the ability to selectively add resolved ip addresses
to given ipsets.
HAVE_AUTH HAVE_AUTH
define this to include the facility to act as an authoritative DNS define this to include the facility to act as an authoritative DNS
server for one or more zones. server for one or more zones.
...@@ -136,7 +140,7 @@ RESOLVFILE ...@@ -136,7 +140,7 @@ RESOLVFILE
/* #define HAVE_DBUS */ /* #define HAVE_DBUS */
/* #define HAVE_IDN */ /* #define HAVE_IDN */
/* #define HAVE_CONNTRACK */ /* #define HAVE_CONNTRACK */
/* #define HAVE_IPSET */
/* Default locations for important system files. */ /* Default locations for important system files. */
...@@ -323,6 +327,10 @@ HAVE_SOCKADDR_SA_LEN ...@@ -323,6 +327,10 @@ HAVE_SOCKADDR_SA_LEN
#undef HAVE_AUTH #undef HAVE_AUTH
#endif #endif
#ifndef HAVE_LINUX_NETWORK
#undef HAVE_IPSET
#endif
/* Define a string indicating which options are in use. /* Define a string indicating which options are in use.
DNSMASQP_COMPILE_OPTS is only defined in dnsmasq.c */ DNSMASQP_COMPILE_OPTS is only defined in dnsmasq.c */
...@@ -381,6 +389,10 @@ static char *compile_opts = ...@@ -381,6 +389,10 @@ static char *compile_opts =
"no-" "no-"
#endif #endif
"conntrack " "conntrack "
#ifndef HAVE_IPSET
"no-"
#endif
"ipset "
#ifndef HAVE_AUTH #ifndef HAVE_AUTH
"no-" "no-"
#endif #endif
......
...@@ -213,6 +213,11 @@ int main (int argc, char **argv) ...@@ -213,6 +213,11 @@ int main (int argc, char **argv)
#endif #endif
#ifdef HAVE_IPSET
if (daemon->ipsets)
ipset_init();
#endif
#ifdef HAVE_LINUX_NETWORK #ifdef HAVE_LINUX_NETWORK
netlink_init(); netlink_init();
......
...@@ -430,6 +430,12 @@ struct server { ...@@ -430,6 +430,12 @@ struct server {
struct server *next; struct server *next;
}; };
struct ipsets {
char **sets;
char *domain;
struct ipsets *next;
};
struct irec { struct irec {
union mysockaddr addr; union mysockaddr addr;
struct in_addr netmask; /* only valid for IPv4 */ struct in_addr netmask; /* only valid for IPv4 */
...@@ -779,6 +785,7 @@ extern struct daemon { ...@@ -779,6 +785,7 @@ extern struct daemon {
struct iname *if_names, *if_addrs, *if_except, *dhcp_except, *auth_peers; struct iname *if_names, *if_addrs, *if_except, *dhcp_except, *auth_peers;
struct bogus_addr *bogus_addr; struct bogus_addr *bogus_addr;
struct server *servers; struct server *servers;
struct ipsets *ipsets;
int log_fac; /* log facility */ int log_fac; /* log facility */
char *log_file; /* optional log file */ char *log_file; /* optional log file */
int max_logs; /* queue limit */ int max_logs; /* queue limit */
...@@ -903,7 +910,8 @@ size_t setup_reply(struct dns_header *header, size_t qlen, ...@@ -903,7 +910,8 @@ size_t setup_reply(struct dns_header *header, size_t qlen,
struct all_addr *addrp, unsigned int flags, struct all_addr *addrp, unsigned int flags,
unsigned long local_ttl); unsigned long local_ttl);
int extract_addresses(struct dns_header *header, size_t qlen, char *namebuff, int extract_addresses(struct dns_header *header, size_t qlen, char *namebuff,
time_t now, int is_sign, int checkrebind, int checking_disabled); time_t now, char **ipsets, int is_sign, int checkrebind,
int checking_disabled);
size_t answer_request(struct dns_header *header, char *limit, size_t qlen, size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
struct in_addr local_addr, struct in_addr local_netmask, time_t now); struct in_addr local_addr, struct in_addr local_netmask, time_t now);
int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name, int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name,
...@@ -1117,6 +1125,12 @@ void emit_dbus_signal(int action, struct dhcp_lease *lease, char *hostname); ...@@ -1117,6 +1125,12 @@ void emit_dbus_signal(int action, struct dhcp_lease *lease, char *hostname);
# endif # endif
#endif #endif
/* ipset.c */
#ifdef HAVE_IPSET
void ipset_init(void);
int add_to_ipset(const char *setname, const struct all_addr *ipaddr, int flags, int remove);
#endif
/* helper.c */ /* helper.c */
#if defined(HAVE_SCRIPT) #if defined(HAVE_SCRIPT)
int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd); int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd);
......
...@@ -439,9 +439,28 @@ static size_t process_reply(struct dns_header *header, time_t now, ...@@ -439,9 +439,28 @@ static size_t process_reply(struct dns_header *header, time_t now,
struct server *server, size_t n, int check_rebind, int checking_disabled) struct server *server, size_t n, int check_rebind, int checking_disabled)
{ {
unsigned char *pheader, *sizep; unsigned char *pheader, *sizep;
char **sets = 0;
int munged = 0, is_sign; int munged = 0, is_sign;
size_t plen; size_t plen;
#ifdef HAVE_IPSET
/* Similar algorithm to search_servers. */
struct ipsets *ipset_pos;
unsigned int namelen = strlen(daemon->namebuff);
unsigned int matchlen = 0;
for (ipset_pos = daemon->ipsets; ipset_pos; ipset_pos = ipset_pos->next)
{
unsigned int domainlen = strlen(ipset_pos->domain);
char *matchstart = daemon->namebuff + namelen - domainlen;
if (namelen >= domainlen && hostname_isequal(matchstart, ipset_pos->domain) &&
(domainlen == 0 || namelen == domainlen || *(matchstart - 1) == '.' ) &&
domainlen >= matchlen) {
matchlen = domainlen;
sets = ipset_pos->sets;
}
}
#endif
/* If upstream is advertising a larger UDP packet size /* If upstream is advertising a larger UDP packet size
than we allow, trim it so that we don't get overlarge than we allow, trim it so that we don't get overlarge
requests for the client. We can't do this for signed packets. */ requests for the client. We can't do this for signed packets. */
...@@ -494,7 +513,7 @@ static size_t process_reply(struct dns_header *header, time_t now, ...@@ -494,7 +513,7 @@ static size_t process_reply(struct dns_header *header, time_t now,
SET_RCODE(header, NOERROR); SET_RCODE(header, NOERROR);
} }
if (extract_addresses(header, n, daemon->namebuff, now, is_sign, check_rebind, checking_disabled)) if (extract_addresses(header, n, daemon->namebuff, now, sets, is_sign, check_rebind, checking_disabled))
{ {
my_syslog(LOG_WARNING, _("possible DNS-rebind attack detected: %s"), daemon->namebuff); my_syslog(LOG_WARNING, _("possible DNS-rebind attack detected: %s"), daemon->namebuff);
munged = 1; munged = 1;
......
/* ipset.c is Copyright (c) 2013 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
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; version 2 dated June, 1991, or
(at your option) version 3 dated 29 June, 2007.
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 <http://www.gnu.org/licenses/>.
*/
#include "dnsmasq.h"
#ifdef HAVE_IPSET
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/utsname.h>
#include <arpa/inet.h>
#include <linux/version.h>
#include <linux/netlink.h>
#include <linux/netfilter/nfnetlink.h>
#ifndef NFNL_SUBSYS_IPSET
#define NFNL_SUBSYS_IPSET 6
#define IPSET_ATTR_DATA 7
#define IPSET_ATTR_IP 1
#define IPSET_ATTR_IPADDR_IPV4 1
#define IPSET_ATTR_IPADDR_IPV6 2
#define IPSET_ATTR_PROTOCOL 1
#define IPSET_ATTR_SETNAME 2
#define IPSET_CMD_ADD 9
#define IPSET_CMD_DEL 10
#define IPSET_MAXNAMELEN 32
#define IPSET_PROTOCOL 6
#else
#include <linux/netfilter/ipset/ip_set.h>
#endif
/* data structure size in here is fixed */
#define BUFF_SZ 256
#define NL_ALIGN(len) (((len)+3) & ~(3))
static const struct sockaddr_nl snl = { .nl_family = AF_NETLINK };
static int ipset_sock, old_kernel;
static char *buffer;
static inline void add_attr(struct nlmsghdr *nlh, uint16_t type, size_t len, const void *data)
{
struct nlattr *attr = (void *)nlh + NL_ALIGN(nlh->nlmsg_len);
uint16_t payload_len = NL_ALIGN(sizeof(struct nlattr)) + len;
attr->nla_type = type;
attr->nla_len = payload_len;
memcpy((void *)attr + NL_ALIGN(sizeof(struct nlattr)), data, len);
nlh->nlmsg_len += NL_ALIGN(payload_len);
}
void ipset_init(void)
{
struct utsname utsname;
int version;
char *split;
if (uname(&utsname) < 0)
die(_("failed to find kernel version: %s"), NULL, EC_MISC);
split = strtok(utsname.release, ".");
version = (split ? atoi(split) : 0);
split = strtok(NULL, ".");
version = version * 256 + (split ? atoi(split) : 0);
split = strtok(NULL, ".");
version = version * 256 + (split ? atoi(split) : 0);
old_kernel = (version < KERNEL_VERSION(2,6,32));
if (old_kernel && (ipset_sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) != -1)
return;
if (!old_kernel &&
(buffer = safe_malloc(BUFF_SZ)) &&
(ipset_sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_NETFILTER)) != -1 &&
(bind(ipset_sock, (struct sockaddr *)&snl, sizeof(snl)) != -1))
return;
die (_("failed to create IPset control socket: %s"), NULL, EC_MISC);
}
static int new_add_to_ipset(const char *setname, const struct all_addr *ipaddr, int af, int remove)
{
struct nlmsghdr *nlh;
struct nfgenmsg *nfg;
struct nlattr *nested[2];
uint8_t proto;
int addrsz = INADDRSZ;
#ifdef HAVE_IPV6
if (af == AF_INET6)
addrsz = IN6ADDRSZ;
#endif
if (strlen(setname) >= IPSET_MAXNAMELEN)
{
errno = ENAMETOOLONG;
return -1;
}
memset(buffer, 0, sizeof(buffer));
nlh = (struct nlmsghdr *)buffer;
nlh->nlmsg_len = NL_ALIGN(sizeof(struct nlmsghdr));
nlh->nlmsg_type = (remove ? IPSET_CMD_DEL : IPSET_CMD_ADD) | (NFNL_SUBSYS_IPSET << 8);
nlh->nlmsg_flags = NLM_F_REQUEST;
nfg = (struct nfgenmsg *)(buffer + nlh->nlmsg_len);
nlh->nlmsg_len += NL_ALIGN(sizeof(struct nfgenmsg));
nfg->nfgen_family = af;
nfg->version = NFNETLINK_V0;
nfg->res_id = htons(0);
proto = IPSET_PROTOCOL;
add_attr(nlh, IPSET_ATTR_PROTOCOL, sizeof(proto), &proto);
add_attr(nlh, IPSET_ATTR_SETNAME, strlen(setname) + 1, setname);
nested[0] = (struct nlattr *)(buffer + NL_ALIGN(nlh->nlmsg_len));
nlh->nlmsg_len += NL_ALIGN(sizeof(struct nlattr));
nested[0]->nla_type = NLA_F_NESTED | IPSET_ATTR_DATA;
nested[1] = (struct nlattr *)(buffer + NL_ALIGN(nlh->nlmsg_len));
nlh->nlmsg_len += NL_ALIGN(sizeof(struct nlattr));
nested[1]->nla_type = NLA_F_NESTED | IPSET_ATTR_IP;
add_attr(nlh,
(af == AF_INET ? IPSET_ATTR_IPADDR_IPV4 : IPSET_ATTR_IPADDR_IPV6) | NLA_F_NET_BYTEORDER,
addrsz, &ipaddr->addr);
nested[1]->nla_len = (void *)buffer + NL_ALIGN(nlh->nlmsg_len) - (void *)nested[1];
nested[0]->nla_len = (void *)buffer + NL_ALIGN(nlh->nlmsg_len) - (void *)nested[0];
if (sendto(ipset_sock, buffer, nlh->nlmsg_len, 0, (struct sockaddr *)&snl, sizeof(snl)) < 0)
return -1;
return 0;
}
static int old_add_to_ipset(const char *setname, const struct all_addr *ipaddr, int remove)
{
socklen_t size;
struct ip_set_req_adt_get {
unsigned op;
unsigned version;
union {
char name[IPSET_MAXNAMELEN];
uint16_t index;
} set;
char typename[IPSET_MAXNAMELEN];
} req_adt_get;
struct ip_set_req_adt {
unsigned op;
uint16_t index;
uint32_t ip;
} req_adt;
if (strlen(setname) >= sizeof(req_adt_get.set.name))
{
errno = ENAMETOOLONG;
return -1;
}
req_adt_get.op = 0x10;
req_adt_get.version = 3;
strcpy(req_adt_get.set.name, setname);
size = sizeof(req_adt_get);
if (getsockopt(ipset_sock, SOL_IP, 83, &req_adt_get, &size) < 0)
return -1;
req_adt.op = remove ? 0x102 : 0x101;
req_adt.index = req_adt_get.set.index;
req_adt.ip = ntohl(ipaddr->addr.addr4.s_addr);
if (setsockopt(ipset_sock, SOL_IP, 83, &req_adt, sizeof(req_adt)) < 0)
return -1;
return 0;
}
int add_to_ipset(const char *setname, const struct all_addr *ipaddr, int flags, int remove)
{
int af = AF_INET;
#ifdef HAVE_IPV6
if (flags & F_IPV6)
{
af = AF_INET6;
/* old method only supports IPv4 */
if (old_kernel)
return -1;
}
#endif
return old_kernel ? old_add_to_ipset(setname, ipaddr, remove) : new_add_to_ipset(setname, ipaddr, af, remove);
}
#endif
...@@ -127,6 +127,7 @@ struct myoption { ...@@ -127,6 +127,7 @@ struct myoption {
#define LOPT_AUTHSOA 316 #define LOPT_AUTHSOA 316
#define LOPT_AUTHSFS 317 #define LOPT_AUTHSFS 317
#define LOPT_AUTHPEER 318 #define LOPT_AUTHPEER 318
#define LOPT_IPSET 319
#ifdef HAVE_GETOPT_LONG #ifdef HAVE_GETOPT_LONG
static const struct option opts[] = static const struct option opts[] =
...@@ -259,6 +260,7 @@ static const struct myoption opts[] = ...@@ -259,6 +260,7 @@ static const struct myoption opts[] =
{ "auth-soa", 1, 0, LOPT_AUTHSOA }, { "auth-soa", 1, 0, LOPT_AUTHSOA },
{ "auth-sec-servers", 1, 0, LOPT_AUTHSFS }, { "auth-sec-servers", 1, 0, LOPT_AUTHSFS },
{ "auth-peer", 1, 0, LOPT_AUTHPEER }, { "auth-peer", 1, 0, LOPT_AUTHPEER },
{ "ipset", 1, 0, LOPT_IPSET },
{ NULL, 0, 0, 0 } { NULL, 0, 0, 0 }
}; };
...@@ -397,6 +399,7 @@ static struct { ...@@ -397,6 +399,7 @@ static struct {
{ LOPT_AUTHSOA, ARG_ONE, "<serial>[,...]", gettext_noop("Set authoritive zone information"), NULL }, { LOPT_AUTHSOA, ARG_ONE, "<serial>[,...]", gettext_noop("Set authoritive zone information"), NULL },
{ LOPT_AUTHSFS, ARG_DUP, "<NS>[,<NS>...]", gettext_noop("Secondary authoritative nameservers for forward domains"), NULL }, { LOPT_AUTHSFS, ARG_DUP, "<NS>[,<NS>...]", gettext_noop("Secondary authoritative nameservers for forward domains"), NULL },
{ LOPT_AUTHPEER, ARG_DUP, "<ipaddr>[,<ipaddr>...]", gettext_noop("Peers which are allowed to do zone transfer"), NULL }, { LOPT_AUTHPEER, ARG_DUP, "<ipaddr>[,<ipaddr>...]", gettext_noop("Peers which are allowed to do zone transfer"), NULL },
{ LOPT_IPSET, ARG_DUP, "/<domain>/<ipset>[,<ipset>...]", gettext_noop("Specify ipsets to which matching domains should be added"), NULL },
{ 0, 0, NULL, NULL, NULL } { 0, 0, NULL, NULL, NULL }
}; };
...@@ -2021,6 +2024,74 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma ...@@ -2021,6 +2024,74 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
daemon->servers = newlist; daemon->servers = newlist;
break; break;
} }
case LOPT_IPSET: /* --ipset */
#ifndef HAVE_IPSET
ret_err(_("recompile with HAVE_IPSET defined to enable ipset directives"));
break;
#else
{
struct ipsets ipsets_head;
struct ipsets *ipsets = &ipsets_head;
int size;
char *end;
char **sets, **sets_pos;
memset(ipsets, 0, sizeof(struct ipsets));
unhide_metas(arg);
if (arg && *arg == '/')
{
arg++;
while ((end = split_chr(arg, '/')))
{
char *domain = NULL;
/* elide leading dots - they are implied in the search algorithm */
while (*arg == '.')
arg++;
/* # matches everything and becomes a zero length domain string */
if (strcmp(arg, "#") == 0 || !*arg)
domain = "";
else if (strlen(arg) != 0 && !(domain = canonicalise_opt(arg)))
option = '?';
ipsets->next = opt_malloc(sizeof(struct ipsets));
ipsets = ipsets->next;
memset(ipsets, 0, sizeof(struct ipsets));
ipsets->domain = domain;
arg = end;
}
}
else
{
ipsets->next = opt_malloc(sizeof(struct ipsets));
ipsets = ipsets->next;
memset(ipsets, 0, sizeof(struct ipsets));
ipsets->domain = "";
}
if (!arg || !*arg)
{
option = '?';
break;
}
size = 2;
for (end = arg; *end; ++end)
if (*end == ',')
++size;
sets = sets_pos = opt_malloc(sizeof(char *) * size);
do {
end = split(arg);
*sets_pos++ = opt_string_alloc(arg);
arg = end;
} while (end);
*sets_pos = 0;
for (ipsets = &ipsets_head; ipsets->next; ipsets = ipsets->next)
ipsets->next->sets = sets;
ipsets->next = daemon->ipsets;
daemon->ipsets = ipsets_head.next;
break;
}
#endif
case 'c': /* --cache-size */ case 'c': /* --cache-size */
{ {
......
...@@ -777,13 +777,18 @@ static int find_soa(struct dns_header *header, size_t qlen, char *name) ...@@ -777,13 +777,18 @@ static int find_soa(struct dns_header *header, size_t qlen, char *name)
expired and cleaned out that way. expired and cleaned out that way.
Return 1 if we reject an address because it look like part of dns-rebinding attack. */ Return 1 if we reject an address because it look like part of dns-rebinding attack. */
int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t now, int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t now,
int is_sign, int check_rebind, int checking_disabled) char **ipsets, int is_sign, int check_rebind, int checking_disabled)
{ {
unsigned char *p, *p1, *endrr, *namep; unsigned char *p, *p1, *endrr, *namep;
int i, j, qtype, qclass, aqtype, aqclass, ardlen, res, searched_soa = 0; int i, j, qtype, qclass, aqtype, aqclass, ardlen, res, searched_soa = 0;
unsigned long ttl = 0; unsigned long ttl = 0;
struct all_addr addr; struct all_addr addr;
#ifdef HAVE_IPSET
char **ipsets_cur;
#else
(void)ipsets; /* unused */
#endif
cache_start_insert(); cache_start_insert();
/* find_soa is needed for dns_doctor and logging side-effects, so don't call it lazily if there are any. */ /* find_soa is needed for dns_doctor and logging side-effects, so don't call it lazily if there are any. */
...@@ -966,6 +971,15 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t ...@@ -966,6 +971,15 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
(flags & F_IPV4) && (flags & F_IPV4) &&
private_net(addr.addr.addr4, !option_bool(OPT_LOCAL_REBIND))) private_net(addr.addr.addr4, !option_bool(OPT_LOCAL_REBIND)))
return 1; return 1;
#ifdef HAVE_IPSET
if (ipsets && (flags & (F_IPV4 | F_IPV6)))
{
ipsets_cur = ipsets;
while (*ipsets_cur)
add_to_ipset(*ipsets_cur++, &addr, flags, 0);
}
#endif
newc = cache_insert(name, &addr, now, attl, flags | F_FORWARD); newc = cache_insert(name, &addr, now, attl, flags | F_FORWARD);
if (newc && cpp) if (newc && cpp)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment