dnsmasq: bump to v2.8.7

This commit is contained in:
coolsnowwolf 2022-12-15 00:44:58 +08:00
parent 4a5a6e637e
commit 830bc8e815
10 changed files with 123 additions and 688 deletions

View File

@ -8,13 +8,13 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=dnsmasq
PKG_UPSTREAM_VERSION:=2.86
PKG_UPSTREAM_VERSION:=2.87
PKG_VERSION:=$(subst test,~~test,$(subst rc,~rc,$(PKG_UPSTREAM_VERSION)))
PKG_RELEASE:=$(AUTORELEASE)
PKG_SOURCE:=$(PKG_NAME)-$(PKG_UPSTREAM_VERSION).tar.xz
PKG_SOURCE_URL:=https://thekelleys.org.uk/dnsmasq
PKG_HASH:=28d52cfc9e2004ac4f85274f52b32e1647b4dbc9761b82e7de1e41c49907eb08
PKG_SOURCE_URL:=https://thekelleys.org.uk/dnsmasq/
PKG_HASH:=0228c0364a7f2356fd7e7f1549937cbf3099a78d3b2eb1ba5bb0c31e2b89de7a
PKG_LICENSE:=GPL-2.0
PKG_LICENSE_FILES:=COPYING
@ -30,6 +30,7 @@ PKG_CONFIG_DEPENDS:= CONFIG_PACKAGE_dnsmasq_$(BUILD_VARIANT)_dhcp \
CONFIG_PACKAGE_dnsmasq_$(BUILD_VARIANT)_dnssec \
CONFIG_PACKAGE_dnsmasq_$(BUILD_VARIANT)_auth \
CONFIG_PACKAGE_dnsmasq_$(BUILD_VARIANT)_ipset \
CONFIG_PACKAGE_dnsmasq_$(BUILD_VARIANT)_nftset \
CONFIG_PACKAGE_dnsmasq_$(BUILD_VARIANT)_conntrack \
CONFIG_PACKAGE_dnsmasq_$(BUILD_VARIANT)_noid \
CONFIG_PACKAGE_dnsmasq_$(BUILD_VARIANT)_broken_rtc \
@ -61,10 +62,11 @@ endef
define Package/dnsmasq-full
$(call Package/dnsmasq/Default)
TITLE += (with DNSSEC, DHCPv6, Auth DNS, IPset, Conntrack, NO_ID enabled by default)
TITLE += (with DNSSEC, DHCPv6, Auth DNS, IPset, Nftset, Conntrack, NO_ID enabled by default)
DEPENDS+=+PACKAGE_dnsmasq_full_dnssec:libnettle \
+PACKAGE_dnsmasq_full_ipset:kmod-ipt-ipset \
+PACKAGE_dnsmasq_full_conntrack:libnetfilter-conntrack
+PACKAGE_dnsmasq_full_conntrack:libnetfilter-conntrack \
+PACKAGE_dnsmasq_full_nftset:nftables-json
VARIANT:=full
PROVIDES:=dnsmasq
endef
@ -83,7 +85,7 @@ define Package/dnsmasq-full/description
$(call Package/dnsmasq/description)
This is a fully configurable variant with DHCPv4, DHCPv6, DNSSEC, Authoritative DNS
and IPset, Conntrack support & NO_ID enabled by default.
and nftset, Conntrack support & NO_ID enabled by default.
endef
define Package/dnsmasq/conffiles
@ -100,7 +102,7 @@ define Package/dnsmasq-full/config
config PACKAGE_dnsmasq_full_dhcpv6
bool "Build with DHCPv6 support."
depends on IPV6 && PACKAGE_dnsmasq_full_dhcp
default n
default y
config PACKAGE_dnsmasq_full_dnssec
bool "Build with DNSSEC support."
default n
@ -110,6 +112,9 @@ define Package/dnsmasq-full/config
config PACKAGE_dnsmasq_full_ipset
bool "Build with IPset support."
default y
config PACKAGE_dnsmasq_full_nftset
bool "Build with Nftset support."
default n
config PACKAGE_dnsmasq_full_conntrack
bool "Build with Conntrack support."
default n
@ -144,6 +149,7 @@ ifeq ($(BUILD_VARIANT),full)
$(if $(CONFIG_PACKAGE_dnsmasq_$(BUILD_VARIANT)_dnssec),-DHAVE_DNSSEC) \
$(if $(CONFIG_PACKAGE_dnsmasq_$(BUILD_VARIANT)_auth),,-DNO_AUTH) \
$(if $(CONFIG_PACKAGE_dnsmasq_$(BUILD_VARIANT)_ipset),,-DNO_IPSET) \
$(if $(CONFIG_PACKAGE_dnsmasq_$(BUILD_VARIANT)_nftset),-DHAVE_NFTSET,) \
$(if $(CONFIG_PACKAGE_dnsmasq_$(BUILD_VARIANT)_conntrack),-DHAVE_CONNTRACK,) \
$(if $(CONFIG_PACKAGE_dnsmasq_$(BUILD_VARIANT)_noid),-DNO_ID,) \
$(if $(CONFIG_PACKAGE_dnsmasq_$(BUILD_VARIANT)_broken_rtc),-DHAVE_BROKEN_RTC) \
@ -182,6 +188,7 @@ define Package/dnsmasq/install
$(INSTALL_DATA) ./files/dnsmasq_acl.json $(1)/usr/share/acl.d/
$(INSTALL_DIR) $(1)/etc/uci-defaults
$(INSTALL_BIN) ./files/50-dnsmasq-migrate-resolv-conf-auto.sh $(1)/etc/uci-defaults
$(INSTALL_BIN) ./files/50-dnsmasq-migrate-ipset.sh $(1)/etc/uci-defaults
endef
Package/dnsmasq-dhcpv6/install = $(Package/dnsmasq/install)

View File

@ -0,0 +1,32 @@
#!/bin/sh
ipsets=$(uci -q get dhcp.@dnsmasq[0].ipset)
[ -z "$ipsets" ] && exit 0
for ipset in $ipsets; do
names=${ipset##*/}
domains=${ipset%/*}
[ -z "$names" ] || [ -z "$domains" ] && continue
uci add dhcp ipset
OLDIFS="$IFS"
IFS=","
for name in $names; do
uci add_list dhcp.@ipset[-1].name="$name"
done
IFS="/"
for domain in ${domains:1}; do
uci add_list dhcp.@ipset[-1].domain="$domain"
done
IFS="$OLDIFS"
uci del_list dhcp.@dnsmasq[0].ipset="$ipset"
done
uci commit dhcp
exit 0

View File

@ -20,11 +20,10 @@ config dnsmasq
#list notinterface lo
#list bogusnxdomain '64.94.110.11'
option localservice 1 # disable to allow DNS requests from non-local subnets
option filter_aaaa 1
option filter_a 0
option cachesize 8000
option mini_ttl 3600
option ednspacket_max 1232
option filter_aaaa 0
option filter_a 0
#list addnmount /some/path # read-only mount path to expose it to dnsmasq
config dhcp lan
option interface lan

View File

@ -33,6 +33,7 @@ dnsmasq_ignore_opt() {
[ "${dnsmasq_features#* DNSSEC }" = "$dnsmasq_features" ] || dnsmasq_has_dnssec=1
[ "${dnsmasq_features#* TFTP }" = "$dnsmasq_features" ] || dnsmasq_has_tftp=1
[ "${dnsmasq_features#* ipset }" = "$dnsmasq_features" ] || dnsmasq_has_ipset=1
[ "${dnsmasq_features#* nftset }" = "$dnsmasq_features" ] || dnsmasq_has_nftset=1
fi
case "$opt" in
@ -55,6 +56,8 @@ dnsmasq_ignore_opt() {
[ -z "$dnsmasq_has_tftp" ] ;;
ipset)
[ -z "$dnsmasq_has_ipset" ] ;;
nftset)
[ -z "$dnsmasq_has_nftset" ] ;;
*)
return 1
esac
@ -169,10 +172,6 @@ append_address() {
xappend "--address=$1"
}
append_ipset() {
xappend "--ipset=$1"
}
append_connmark_allowlist() {
xappend "--connmark-allowlist=$1"
}
@ -205,8 +204,12 @@ ismounted() {
return 1
}
append_addnhosts() {
append_extramount() {
ismounted "$1" || append EXTRA_MOUNT "$1"
}
append_addnhosts() {
append_extramount "$1"
xappend "--addn-hosts=$1"
}
@ -796,29 +799,60 @@ dhcp_relay_add() {
dnsmasq_ipset_add() {
local cfg="$1"
local ipsets
local ipsets nftsets domains
add_ipset() {
ipsets="${ipsets:+$ipsets,}$1"
}
add_domain() {
xappend "--ipset=/$1/$ipsets"
add_nftset() {
local IFS=,
for set in $1; do
local fam="$family"
[ -n "$fam" ] || fam=$(echo "$set" | sed -nre \
's#^.*[^0-9]([46])$|^.*[-_]([46])[-_].*$|^([46])[^0-9].*$#\1\2\3#p')
[ -n "$fam" ] || \
fam=$(nft -t list set "$table_family" "$table" "$set" 2>&1 | sed -nre \
's#^\t\ttype .*\bipv([46])_addr\b.*$#\1#p')
[ -n "$fam" ] || \
logger -t dnsmasq "Cannot infer address family from non-existent nftables set '$set'"
nftsets="${nftsets:+$nftsets,}${fam:+$fam#}$table_family#$table#$set"
done
}
config_list_foreach "$cfg" "name" add_ipset
add_domain() {
# leading '/' is expected
domains="$domains/$1"
}
if [ -z "$ipsets" ]; then
config_get table "$cfg" table 'fw4'
config_get table_family "$cfg" table_family 'inet'
if [ "$table_family" = "ip" ] ; then
family="4"
elif [ "$table_family" = "ip6" ] ; then
family="6"
else
config_get family "$cfg" family
fi
config_list_foreach "$cfg" "name" add_ipset
config_list_foreach "$cfg" "name" add_nftset
config_list_foreach "$cfg" "domain" add_domain
if [ -z "$ipsets" ] || [ -z "$nftsets" ] || [ -z "$domains" ]; then
return 0
fi
config_list_foreach "$cfg" "domain" add_domain
xappend "--ipset=$domains/$ipsets"
xappend "--nftset=$domains/$nftsets"
}
dnsmasq_start()
{
local cfg="$1"
local disabled user_dhcpscript
local disabled user_dhcpscript logfacility
local resolvfile resolvdir localuse=0
config_get_bool disabled "$cfg" disabled 0
@ -934,9 +968,7 @@ dnsmasq_start()
append_bool "$cfg" filter_a "--filter-A"
append_parm "$cfg" logfacility "--log-facility"
append_parm "$cfg" mini_ttl "--min-ttl"
config_get logfacility "$cfg" "logfacility"
append_parm "$cfg" cachesize "--cache-size"
append_parm "$cfg" dnsforwardmax "--dns-forward-max"
append_parm "$cfg" port "--port"
@ -951,7 +983,6 @@ dnsmasq_start()
config_list_foreach "$cfg" "server" append_server
config_list_foreach "$cfg" "rev_server" append_rev_server
config_list_foreach "$cfg" "address" append_address
config_list_foreach "$cfg" "ipset" append_ipset
local connmark_allowlist_enable
config_get connmark_allowlist_enable "$cfg" connmark_allowlist_enable 0
@ -975,7 +1006,14 @@ dnsmasq_start()
config_list_foreach "$cfg" "addnhosts" append_addnhosts
config_list_foreach "$cfg" "bogusnxdomain" append_bogusnxdomain
append_parm "$cfg" "leasefile" "--dhcp-leasefile" "/tmp/dhcp.leases"
append_parm "$cfg" "serversfile" "--servers-file"
local serversfile
config_get serversfile "$cfg" "serversfile"
[ -n "$serversfile" ] && {
xappend "--servers-file=$serversfile"
append EXTRA_MOUNT "$serversfile"
}
append_parm "$cfg" "tftp_root" "--tftp-root"
append_parm "$cfg" "dhcp_boot" "--dhcp-boot"
append_parm "$cfg" "local_ttl" "--local-ttl"
@ -1137,7 +1175,6 @@ dnsmasq_start()
config_foreach filter_dnsmasq ipset dnsmasq_ipset_add "$cfg"
echo >> $CONFIGFILE_TMP
echo >> $CONFIGFILE_TMP
mv -f $CONFIGFILE_TMP $CONFIGFILE
mv -f $HOSTFILE_TMP $HOSTFILE
@ -1153,18 +1190,29 @@ dnsmasq_start()
done
}
config_list_foreach "$cfg" addnmount append_extramount
procd_open_instance $cfg
procd_set_param command $PROG -C $CONFIGFILE -k -x /var/run/dnsmasq/dnsmasq."${cfg}".pid
procd_set_param file $CONFIGFILE
[ -n "$user_dhcpscript" ] && procd_set_param env USER_DHCPSCRIPT="$user_dhcpscript"
procd_set_param respawn
local instance_ifc instance_netdev
config_get instance_ifc "$cfg" interface
[ -n "$instance_ifc" ] && network_get_device instance_netdev "$instance_ifc" &&
[ -n "$instance_netdev" ] && procd_set_param netdev $instance_netdev
procd_add_jail dnsmasq ubus log
procd_add_jail_mount $CONFIGFILE $DHCPBOGUSHOSTNAMEFILE $DHCPSCRIPT $DHCPSCRIPT_DEPENDS
procd_add_jail_mount $EXTRA_MOUNT $RFC6761FILE $TRUSTANCHORSFILE
procd_add_jail_mount $dnsmasqconffile $dnsmasqconfdir $resolvdir $user_dhcpscript
procd_add_jail_mount /etc/passwd /etc/group /etc/TZ /etc/hosts /etc/ethers
procd_add_jail_mount_rw /var/run/dnsmasq/ $leasefile
procd_add_jail_mount_rw /var/run/dnsmasq/ /var/etc/ $leasefile
case "$logfacility" in */*)
[ ! -e "$logfacility" ] && touch "$logfacility"
procd_add_jail_mount_rw "$logfacility"
esac
procd_close_instance
}

View File

@ -1,179 +0,0 @@
From 03345ecefeb0d82e3c3a4c28f27c3554f0611b39 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Thu, 31 Mar 2022 21:35:20 +0100
Subject: Fix write-after-free error in DHCPv6 code. CVE-2022-0934 refers.
---
CHANGELOG | 3 +++
src/rfc3315.c | 48 +++++++++++++++++++++++++++---------------------
2 files changed, 30 insertions(+), 21 deletions(-)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -92,6 +92,9 @@ version 2.86
of filename). Thanks to Ed Wildgoose for the initial patch
and motivation for this.
+ Fix write-after-free error in DHCPv6 server code.
+ CVE-2022-0934 refers.
+
version 2.85
Fix problem with DNS retries in 2.83/2.84.
--- a/src/rfc3315.c
+++ b/src/rfc3315.c
@@ -33,9 +33,9 @@ struct state {
unsigned int mac_len, mac_type;
};
-static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz,
+static int dhcp6_maybe_relay(struct state *state, unsigned char *inbuff, size_t sz,
struct in6_addr *client_addr, int is_unicast, time_t now);
-static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_t sz, int is_unicast, time_t now);
+static int dhcp6_no_relay(struct state *state, int msg_type, unsigned char *inbuff, size_t sz, int is_unicast, time_t now);
static void log6_opts(int nest, unsigned int xid, void *start_opts, void *end_opts);
static void log6_packet(struct state *state, char *type, struct in6_addr *addr, char *string);
static void log6_quiet(struct state *state, char *type, struct in6_addr *addr, char *string);
@@ -104,12 +104,12 @@ unsigned short dhcp6_reply(struct dhcp_c
}
/* This cost me blood to write, it will probably cost you blood to understand - srk. */
-static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz,
+static int dhcp6_maybe_relay(struct state *state, unsigned char *inbuff, size_t sz,
struct in6_addr *client_addr, int is_unicast, time_t now)
{
void *end = inbuff + sz;
void *opts = inbuff + 34;
- int msg_type = *((unsigned char *)inbuff);
+ int msg_type = *inbuff;
unsigned char *outmsgtypep;
void *opt;
struct dhcp_vendor *vendor;
@@ -259,15 +259,15 @@ static int dhcp6_maybe_relay(struct stat
return 1;
}
-static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_t sz, int is_unicast, time_t now)
+static int dhcp6_no_relay(struct state *state, int msg_type, unsigned char *inbuff, size_t sz, int is_unicast, time_t now)
{
void *opt;
- int i, o, o1, start_opts;
+ int i, o, o1, start_opts, start_msg;
struct dhcp_opt *opt_cfg;
struct dhcp_netid *tagif;
struct dhcp_config *config = NULL;
struct dhcp_netid known_id, iface_id, v6_id;
- unsigned char *outmsgtypep;
+ unsigned char outmsgtype;
struct dhcp_vendor *vendor;
struct dhcp_context *context_tmp;
struct dhcp_mac *mac_opt;
@@ -296,12 +296,13 @@ static int dhcp6_no_relay(struct state *
v6_id.next = state->tags;
state->tags = &v6_id;
- /* copy over transaction-id, and save pointer to message type */
- if (!(outmsgtypep = put_opt6(inbuff, 4)))
+ start_msg = save_counter(-1);
+ /* copy over transaction-id */
+ if (!put_opt6(inbuff, 4))
return 0;
start_opts = save_counter(-1);
- state->xid = outmsgtypep[3] | outmsgtypep[2] << 8 | outmsgtypep[1] << 16;
-
+ state->xid = inbuff[3] | inbuff[2] << 8 | inbuff[1] << 16;
+
/* We're going to be linking tags from all context we use.
mark them as unused so we don't link one twice and break the list */
for (context_tmp = state->context; context_tmp; context_tmp = context_tmp->current)
@@ -347,7 +348,7 @@ static int dhcp6_no_relay(struct state *
(msg_type == DHCP6REQUEST || msg_type == DHCP6RENEW || msg_type == DHCP6RELEASE || msg_type == DHCP6DECLINE))
{
- *outmsgtypep = DHCP6REPLY;
+ outmsgtype = DHCP6REPLY;
o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6USEMULTI);
put_opt6_string("Use multicast");
@@ -619,11 +620,11 @@ static int dhcp6_no_relay(struct state *
struct dhcp_netid *solicit_tags;
struct dhcp_context *c;
- *outmsgtypep = DHCP6ADVERTISE;
+ outmsgtype = DHCP6ADVERTISE;
if (opt6_find(state->packet_options, state->end, OPTION6_RAPID_COMMIT, 0))
{
- *outmsgtypep = DHCP6REPLY;
+ outmsgtype = DHCP6REPLY;
state->lease_allocate = 1;
o = new_opt6(OPTION6_RAPID_COMMIT);
end_opt6(o);
@@ -809,7 +810,7 @@ static int dhcp6_no_relay(struct state *
int start = save_counter(-1);
/* set reply message type */
- *outmsgtypep = DHCP6REPLY;
+ outmsgtype = DHCP6REPLY;
state->lease_allocate = 1;
log6_quiet(state, "DHCPREQUEST", NULL, ignore ? _("ignored") : NULL);
@@ -924,7 +925,7 @@ static int dhcp6_no_relay(struct state *
int address_assigned = 0;
/* set reply message type */
- *outmsgtypep = DHCP6REPLY;
+ outmsgtype = DHCP6REPLY;
log6_quiet(state, msg_type == DHCP6RENEW ? "DHCPRENEW" : "DHCPREBIND", NULL, NULL);
@@ -1057,7 +1058,7 @@ static int dhcp6_no_relay(struct state *
int good_addr = 0;
/* set reply message type */
- *outmsgtypep = DHCP6REPLY;
+ outmsgtype = DHCP6REPLY;
log6_quiet(state, "DHCPCONFIRM", NULL, NULL);
@@ -1121,7 +1122,7 @@ static int dhcp6_no_relay(struct state *
log6_quiet(state, "DHCPINFORMATION-REQUEST", NULL, ignore ? _("ignored") : state->hostname);
if (ignore)
return 0;
- *outmsgtypep = DHCP6REPLY;
+ outmsgtype = DHCP6REPLY;
tagif = add_options(state, 1);
break;
}
@@ -1130,7 +1131,7 @@ static int dhcp6_no_relay(struct state *
case DHCP6RELEASE:
{
/* set reply message type */
- *outmsgtypep = DHCP6REPLY;
+ outmsgtype = DHCP6REPLY;
log6_quiet(state, "DHCPRELEASE", NULL, NULL);
@@ -1195,7 +1196,7 @@ static int dhcp6_no_relay(struct state *
case DHCP6DECLINE:
{
/* set reply message type */
- *outmsgtypep = DHCP6REPLY;
+ outmsgtype = DHCP6REPLY;
log6_quiet(state, "DHCPDECLINE", NULL, NULL);
@@ -1275,7 +1276,12 @@ static int dhcp6_no_relay(struct state *
}
}
-
+
+ /* Fill in the message type. Note that we store the offset,
+ not a direct pointer, since the packet memory may have been
+ reallocated. */
+ ((unsigned char *)(daemon->outpacket.iov_base))[start_msg] = outmsgtype;
+
log_tags(tagif, state->xid);
log6_opts(0, state->xid, daemon->outpacket.iov_base + start_opts, daemon->outpacket.iov_base + save_counter(-1));

View File

@ -1,204 +0,0 @@
From 37a70d39e0cd49f086b757937fa8735e6263cd7a Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Thu, 7 Oct 2021 23:12:59 +0100
Subject: [PATCH] Add --filter and --filter-AAAA options.
---
CHANGELOG | 5 ++++-
man/dnsmasq.8 | 6 ++++++
src/dnsmasq.h | 10 ++++++++--
src/edns0.c | 2 +-
src/forward.c | 18 ++++++++++++++----
src/option.c | 8 +++++++-
src/rrfilter.c | 37 +++++++++++++++++++++++++++----------
7 files changed, 67 insertions(+), 19 deletions(-)
--- a/man/dnsmasq.8
+++ b/man/dnsmasq.8
@@ -348,6 +348,12 @@ the public DNS and can cause problems by triggering dial-on-demand links. This f
to filter such requests. The requests blocked are for records of types SOA and SRV, and type ANY where the
requested name has underscores, to catch LDAP requests.
.TP
+.B --filter-A
+Remove A records from answers. No IPv4 addresses will be returned.
+.TP
+.B --filter-AAAA
+Remove AAAA records from answers. No IPv6 addresses will be returned.
+.TP
.B \-r, --resolv-file=<file>
Read the IP addresses of the upstream nameservers from <file>, instead of
/etc/resolv.conf. For the format of this file see
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -275,7 +275,9 @@ struct event_desc {
#define OPT_UMBRELLA_DEVID 64
#define OPT_CMARK_ALST_EN 65
#define OPT_QUIET_TFTP 66
-#define OPT_LAST 67
+#define OPT_FILTER_A 67
+#define OPT_FILTER_AAAA 68
+#define OPT_LAST 69
#define OPTION_BITS (sizeof(unsigned int)*8)
#define OPTION_SIZE ( (OPT_LAST/OPTION_BITS)+((OPT_LAST%OPTION_BITS)!=0) )
@@ -1735,7 +1737,11 @@ int do_poll(int timeout);
size_t rrfilter(struct dns_header *header, size_t plen, int mode);
u16 *rrfilter_desc(int type);
int expand_workspace(unsigned char ***wkspc, int *szp, int new);
-
+/* modes. */
+#define RRFILTER_EDNS0 0
+#define RRFILTER_DNSSEC 1
+#define RRFILTER_A 2
+#define RRFILTER_AAAA 3
/* edns0.c */
unsigned char *find_pseudoheader(struct dns_header *header, size_t plen,
size_t *len, unsigned char **p, int *is_sign, int *is_last);
--- a/src/edns0.c
+++ b/src/edns0.c
@@ -178,7 +178,7 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
memcpy(buff, datap, rdlen);
/* now, delete OPT RR */
- plen = rrfilter(header, plen, 0);
+ plen = rrfilter(header, plen, RRFILTER_EDNS0);
/* Now, force addition of a new one */
p = NULL;
--- a/src/forward.c
+++ b/src/forward.c
@@ -607,7 +607,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
if (added_pheader)
{
/* client didn't send EDNS0, we added one, strip it off before returning answer. */
- n = rrfilter(header, n, 0);
+ n = rrfilter(header, n, RRFILTER_EDNS0);
pheader = NULL;
}
else
@@ -696,7 +696,17 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
cache_secure = 0;
}
}
-
+
+ /* Before extract_addresses() */
+ if (rcode == NOERROR)
+ {
+ if (option_bool(OPT_FILTER_A))
+ n = rrfilter(header, n, RRFILTER_A);
+
+ if (option_bool(OPT_FILTER_AAAA))
+ n = rrfilter(header, n, RRFILTER_AAAA);
+ }
+
if (extract_addresses(header, n, daemon->namebuff, now, sets, is_sign, check_rebind, no_cache, cache_secure, &doctored))
{
my_syslog(LOG_WARNING, _("possible DNS-rebind attack detected: %s"), daemon->namebuff);
@@ -726,7 +736,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
/* If the requestor didn't set the DO bit, don't return DNSSEC info. */
if (!do_bit)
- n = rrfilter(header, n, 1);
+ n = rrfilter(header, n, RRFILTER_DNSSEC);
}
#endif
@@ -750,7 +760,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
u16 swap = htons((u16)ede);
n = add_pseudoheader(header, n, limit, daemon->edns_pktsz, EDNS0_OPTION_EDE, (unsigned char *)&swap, 2, do_bit, 1);
}
-
+
return n;
}
--- a/src/option.c
+++ b/src/option.c
@@ -174,7 +174,9 @@ struct myoption {
#define LOPT_CMARK_ALST_EN 365
#define LOPT_CMARK_ALST 366
#define LOPT_QUIET_TFTP 367
-
+#define LOPT_FILTER_A 369
+#define LOPT_FILTER_AAAA 370
+
#ifdef HAVE_GETOPT_LONG
static const struct option opts[] =
#else
@@ -211,6 +213,8 @@ static const struct myoption opts[] =
{ "ignore-address", 1, 0, LOPT_IGNORE_ADDR },
{ "selfmx", 0, 0, 'e' },
{ "filterwin2k", 0, 0, 'f' },
+ { "filter-A", 0, 0, LOPT_FILTER_A },
+ { "filter-AAAA", 0, 0, LOPT_FILTER_AAAA },
{ "pid-file", 2, 0, 'x' },
{ "strict-order", 0, 0, 'o' },
{ "server", 1, 0, 'S' },
@@ -380,6 +384,8 @@ static struct {
{ 'e', OPT_SELFMX, NULL, gettext_noop("Return self-pointing MX records for local hosts."), NULL },
{ 'E', OPT_EXPAND, NULL, gettext_noop("Expand simple names in /etc/hosts with domain-suffix."), NULL },
{ 'f', OPT_FILTER, NULL, gettext_noop("Don't forward spurious DNS requests from Windows hosts."), NULL },
+ { LOPT_FILTER_A, OPT_FILTER_A, NULL, gettext_noop("Don't include IPv4 addresses in DNS answers."), NULL },
+ { LOPT_FILTER_AAAA, OPT_FILTER_AAAA, NULL, gettext_noop("Don't include IPv6 addresses in DNS answers."), NULL },
{ 'F', ARG_DUP, "<ipaddr>,...", gettext_noop("Enable DHCP in the range given with lease duration."), NULL },
{ 'g', ARG_ONE, "<groupname>", gettext_noop("Change to this group after startup (defaults to %s)."), CHGRP },
{ 'G', ARG_DUP, "<hostspec>", gettext_noop("Set address or hostname for a specified machine."), NULL },
--- a/src/rrfilter.c
+++ b/src/rrfilter.c
@@ -156,7 +156,7 @@ static int check_rrs(unsigned char *p, struct dns_header *header, size_t plen, i
}
-/* mode is 0 to remove EDNS0, 1 to filter DNSSEC RRs */
+/* mode may be remove EDNS0 or DNSSEC RRs or remove A or AAAA from answer section. */
size_t rrfilter(struct dns_header *header, size_t plen, int mode)
{
static unsigned char **rrs;
@@ -192,20 +192,37 @@ size_t rrfilter(struct dns_header *header, size_t plen, int mode)
if (!ADD_RDLEN(header, p, plen, rdlen))
return plen;
- /* Don't remove the answer. */
- if (i < ntohs(header->ancount) && type == qtype && class == qclass)
- continue;
-
- if (mode == 0) /* EDNS */
+ if (mode == RRFILTER_EDNS0) /* EDNS */
{
/* EDNS mode, remove T_OPT from additional section only */
if (i < (ntohs(header->nscount) + ntohs(header->ancount)) || type != T_OPT)
continue;
}
- else if (type != T_NSEC && type != T_NSEC3 && type != T_RRSIG)
- /* DNSSEC mode, remove SIGs and NSECs from all three sections. */
- continue;
-
+ else if (mode == RRFILTER_DNSSEC)
+ {
+ if (type != T_NSEC && type != T_NSEC3 && type != T_RRSIG)
+ /* DNSSEC mode, remove SIGs and NSECs from all three sections. */
+ continue;
+
+ /* Don't remove the answer. */
+ if (i < ntohs(header->ancount) && type == qtype && class == qclass)
+ continue;
+ }
+ else
+ {
+ /* Only looking at answer section now. */
+ if (i >= ntohs(header->ancount))
+ break;
+
+ if (class != C_IN)
+ continue;
+
+ if (mode == RRFILTER_A && type != T_A)
+ continue;
+
+ if (mode == RRFILTER_AAAA && type != T_AAAA)
+ continue;
+ }
if (!expand_workspace(&rrs, &rr_sz, rr_found + 1))
return plen;

View File

@ -13,7 +13,7 @@ Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
--- a/src/dnsmasq.c
+++ b/src/dnsmasq.c
@@ -95,10 +95,6 @@ int main (int argc, char **argv)
@@ -103,10 +103,6 @@ int main (int argc, char **argv)
read_opts(argc, argv, compile_opts);
@ -26,7 +26,7 @@ Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -1201,7 +1201,7 @@ extern struct daemon {
@@ -1229,7 +1229,7 @@ extern struct daemon {
int inotifyfd;
#endif
#if defined(HAVE_LINUX_NETWORK)
@ -35,7 +35,7 @@ Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
#elif defined(HAVE_BSD_NETWORK)
int dhcp_raw_fd, dhcp_icmp_fd, routefd;
#endif
@@ -1388,9 +1388,6 @@ int read_write(int fd, unsigned char *pa
@@ -1422,9 +1422,6 @@ int read_write(int fd, unsigned char *pa
void close_fds(long max_fd, int spare1, int spare2, int spare3);
int wildcard_match(const char* wildcard, const char* match);
int wildcard_matchn(const char* wildcard, const char* match, int num);
@ -140,7 +140,7 @@ Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
my_syslog(LOG_ERR, _("failed to update ipset %s: %s"), setname, strerror(errno));
--- a/src/util.c
+++ b/src/util.c
@@ -796,22 +796,3 @@ int wildcard_matchn(const char* wildcard
@@ -833,22 +833,3 @@ int wildcard_matchn(const char* wildcard
return (!num) || (*wildcard == *match);
}

View File

@ -1,6 +1,6 @@
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -1564,14 +1564,26 @@ void emit_dbus_signal(int action, struct
@@ -1598,14 +1598,26 @@ void emit_dbus_signal(int action, struct
/* ubus.c */
#ifdef HAVE_UBUS
@ -151,7 +151,7 @@
if (!ADD_RDLEN(header, p, qlen, rdlen))
return 0; /* bad packet */
}
@@ -563,7 +632,7 @@ int extract_addresses(struct dns_header
@@ -568,7 +637,7 @@ int extract_addresses(struct dns_header
cache_start_insert();
/* find_soa is needed for dns_doctor side effects, so don't call it lazily if there are any. */
@ -269,7 +269,7 @@
struct ubus_context *ubus = (struct ubus_context *)daemon->ubus;
--- a/src/dnsmasq.c
+++ b/src/dnsmasq.c
@@ -1972,6 +1972,10 @@ static void check_dns_listeners(time_t n
@@ -1998,6 +1998,10 @@ static void check_dns_listeners(time_t n
daemon->pipe_to_parent = pipefd[1];
}

View File

@ -1,166 +0,0 @@
From 93ac8f9d469ff08d41170eb6934842b3626d5fdd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org>
Date: Wed, 23 Dec 2015 22:10:44 +0100
Subject: [PATCH] DHCPv6: Honor assigning IPv6 address based on MAC address
Currently IPv6 addresses are assigned to tuple (IAID, DUID). When system
changes IAID/DUID then old assigned IPv6 address cannot be reused, even
when in config file was DHCPv6 assignment based on MAC address (and not on
DUID).
IAID/DUID is changed when rebooting from one operating system to another;
or after reinstalling system. In reality it is normal that DUID of some
machine is changed, so people rather assign also IPv6 addresses based on
MAC address.
So assigning IPv6 based on MAC address in dnsmasq is currently semi-broken.
This patch tries to fix it and honors IPv6 config rules with MAC address,
to always assign particular IPv6 address to specific MAC address (when
configured). And ignores the fact if IAID/DUID was changed.
Normally IPv6 address should be assigned by IAID/DUID (which also state
DHCPv6 RFCs), but dnsmasq has already some support for assigning IPv6
address based on MAC address, when users configured in config file.
So this patch just tries to fix above problem for user configuration with
MAC addresses. It does not change assignment based on DUID.
---
src/rfc3315.c | 55 +++++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 47 insertions(+), 8 deletions(-)
--- a/src/rfc3315.c
+++ b/src/rfc3315.c
@@ -48,7 +48,7 @@ static int build_ia(struct state *state,
static void end_ia(int t1cntr, unsigned int min_time, int do_fuzz);
static void mark_context_used(struct state *state, struct in6_addr *addr);
static void mark_config_used(struct dhcp_context *context, struct in6_addr *addr);
-static int check_address(struct state *state, struct in6_addr *addr);
+static int check_address(struct state *state, struct dhcp_config *config, struct in6_addr *addr);
static int config_valid(struct dhcp_config *config, struct dhcp_context *context, struct in6_addr *addr, struct state *state, time_t now);
static struct addrlist *config_implies(struct dhcp_config *config, struct dhcp_context *context, struct in6_addr *addr);
static void add_address(struct state *state, struct dhcp_context *context, unsigned int lease_time, void *ia_option,
@@ -688,8 +688,13 @@ static int dhcp6_no_relay(struct state *
}
else if (!(c = address6_available(state->context, &req_addr, solicit_tags, plain_range)))
continue; /* not an address we're allowed */
- else if (!check_address(state, &req_addr))
+ else if (!check_address(state, config, &req_addr))
continue; /* address leased elsewhere */
+ else if (state->mac_len && config &&
+ config_has_mac(config, state->mac, state->mac_len, state->mac_type) &&
+ match_netid(c->filter, solicit_tags, plain_range) &&
+ !config_implies(config, c, &req_addr))
+ continue; /* another static address is configured */
/* add address to output packet */
add_address(state, c, lease_time, ia_option, &min_time, &req_addr, now);
@@ -701,7 +706,10 @@ static int dhcp6_no_relay(struct state *
/* Suggest configured address(es) */
for (c = state->context; c; c = c->current)
- if (!(c->flags & CONTEXT_CONF_USED) &&
+ if ((!(c->flags & CONTEXT_CONF_USED) ||
+ (state->mac_len && config &&
+ config_has_mac(config, state->mac, state->mac_len, state->mac_type)
+ )) &&
match_netid(c->filter, solicit_tags, plain_range) &&
config_valid(config, c, &addr, state, now))
{
@@ -725,6 +733,11 @@ static int dhcp6_no_relay(struct state *
req_addr = ltmp->addr6;
if ((c = address6_available(state->context, &req_addr, solicit_tags, plain_range)))
{
+ if (state->mac_len && config &&
+ config_has_mac(config, state->mac, state->mac_len, state->mac_type) &&
+ match_netid(c->filter, solicit_tags, plain_range) &&
+ !config_implies(config, c, &req_addr))
+ continue; /* skip this lease because another static address is configured */
add_address(state, c, c->lease_time, NULL, &min_time, &req_addr, now);
mark_context_used(state, &req_addr);
get_context_tag(state, c);
@@ -859,7 +872,7 @@ static int dhcp6_no_relay(struct state *
put_opt6_string(_("address unavailable"));
end_opt6(o1);
}
- else if (!check_address(state, &req_addr))
+ else if (!check_address(state, config, &req_addr))
{
/* Address leased to another DUID/IAID */
o1 = new_opt6(OPTION6_STATUS_CODE);
@@ -989,6 +1002,16 @@ static int dhcp6_no_relay(struct state *
{
unsigned int lease_time;
+ /* check if another static address is preferred */
+ if (state->mac_len && config &&
+ config_has_mac(config, state->mac, state->mac_len, state->mac_type) &&
+ !config_implies(config, this_context, &req_addr))
+ {
+ preferred_time = valid_time = 0;
+ message = _("deprecated");
+ }
+ else
+ {
get_context_tag(state, this_context);
if (config_implies(config, this_context, &req_addr) && have_config(config, CONFIG_TIME))
@@ -1014,6 +1037,7 @@ static int dhcp6_no_relay(struct state *
if (preferred_time == 0)
message = _("deprecated");
+ }
address_assigned = 1;
}
@@ -1070,11 +1094,22 @@ static int dhcp6_no_relay(struct state *
ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
{
struct in6_addr req_addr;
+ struct dhcp_context *c;
+ int config_addr_ok = 1;
/* alignment */
memcpy(&req_addr, opt6_ptr(ia_option, 0), IN6ADDRSZ);
+
+ c = address6_valid(state->context, &req_addr, tagif, 1);
+
+ if (c && state->mac_len && config &&
+ config_has_mac(config, state->mac, state->mac_len, state->mac_type) &&
+ !config_implies(config, c, &req_addr))
+ {
+ config_addr_ok = 0;
+ }
- if (!address6_valid(state->context, &req_addr, tagif, 1))
+ if (!c || !config_addr_ok)
{
o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6NOTONLINK);
@@ -1692,11 +1727,15 @@ static void mark_config_used(struct dhcp
context->flags |= CONTEXT_CONF_USED;
}
-/* make sure address not leased to another CLID/IAID */
-static int check_address(struct state *state, struct in6_addr *addr)
+/* check that ipv6 address belongs to config with same mac address as in state or ipv6 address is not leased to another CLID/IAID */
+static int check_address(struct state *state, struct dhcp_config *config, struct in6_addr *addr)
{
struct dhcp_lease *lease;
+ if (state->mac_len && config &&
+ config_has_mac(config, state->mac, state->mac_len, state->mac_type))
+ return 1;
+
if (!(lease = lease6_find_by_addr(addr, 128, 0)))
return 1;
@@ -1773,7 +1812,7 @@ static int config_valid(struct dhcp_conf
{
setaddr6part(addr, addrpart+i);
- if (check_address(state, addr))
+ if (check_address(state, config, addr))
return 1;
}
}

View File

@ -1,102 +0,0 @@
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -1118,7 +1118,7 @@ extern struct daemon {
int max_logs; /* queue limit */
int cachesize, ftabsize;
int port, query_port, min_port, max_port;
- unsigned long local_ttl, neg_ttl, max_ttl, min_cache_ttl, max_cache_ttl, auth_ttl, dhcp_ttl, use_dhcp_ttl;
+ unsigned long local_ttl, neg_ttl, min_ttl, max_ttl, min_cache_ttl, max_cache_ttl, auth_ttl, dhcp_ttl, use_dhcp_ttl;
char *dns_client_id;
u32 umbrella_org;
u32 umbrella_asset;
--- a/src/option.c
+++ b/src/option.c
@@ -174,6 +174,7 @@ struct myoption {
#define LOPT_CMARK_ALST_EN 365
#define LOPT_CMARK_ALST 366
#define LOPT_QUIET_TFTP 367
+#define LOPT_MINTTL 368
#define LOPT_FILTER_A 369
#define LOPT_FILTER_AAAA 370
@@ -296,6 +297,7 @@ static const struct myoption opts[] =
{ "dhcp-name-match", 1, 0, LOPT_NAME_MATCH },
{ "dhcp-broadcast", 2, 0, LOPT_BROADCAST },
{ "neg-ttl", 1, 0, LOPT_NEGTTL },
+ { "min-ttl", 1, 0, LOPT_MINTTL },
{ "max-ttl", 1, 0, LOPT_MAXTTL },
{ "min-cache-ttl", 1, 0, LOPT_MINCTTL },
{ "max-cache-ttl", 1, 0, LOPT_MAXCTTL },
@@ -431,6 +433,7 @@ static struct {
{ 't', ARG_ONE, "<host_name>", gettext_noop("Specify default target in an MX record."), NULL },
{ 'T', ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for replies from /etc/hosts."), NULL },
{ LOPT_NEGTTL, ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for negative caching."), NULL },
+ { LOPT_MINTTL, ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for minimum TTL to send to clients."), NULL },
{ LOPT_MAXTTL, ARG_ONE, "<integer>", gettext_noop("Specify time-to-live in seconds for maximum TTL to send to clients."), NULL },
{ LOPT_MAXCTTL, ARG_ONE, "<integer>", gettext_noop("Specify time-to-live ceiling for cache."), NULL },
{ LOPT_MINCTTL, ARG_ONE, "<integer>", gettext_noop("Specify time-to-live floor for cache."), NULL },
@@ -3053,6 +3056,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
case 'T': /* --local-ttl */
case LOPT_NEGTTL: /* --neg-ttl */
+ case LOPT_MINTTL: /* --min-ttl */
case LOPT_MAXTTL: /* --max-ttl */
case LOPT_MINCTTL: /* --min-cache-ttl */
case LOPT_MAXCTTL: /* --max-cache-ttl */
@@ -3064,6 +3068,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
ret_err(gen_err);
else if (option == LOPT_NEGTTL)
daemon->neg_ttl = (unsigned long)ttl;
+ else if (option == LOPT_MINTTL)
+ daemon->min_ttl = (unsigned long)ttl;
else if (option == LOPT_MAXTTL)
daemon->max_ttl = (unsigned long)ttl;
else if (option == LOPT_MINCTTL)
--- a/src/rfc1035.c
+++ b/src/rfc1035.c
@@ -607,6 +607,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
for (j = 0; j < ntohs(header->ancount); j++)
{
int secflag = 0;
+ unsigned long mttl = 0;
if (!(res = extract_name(header, qlen, &p1, name, 0, 10)))
return 0; /* bad packet */
@@ -615,6 +616,14 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
GETLONG(attl, p1);
if ((daemon->max_ttl != 0) && (attl > daemon->max_ttl) && !is_sign)
+ {
+ mttl = daemon->max_ttl;
+ }
+ if ((daemon->min_ttl != 0) && (attl < daemon->min_ttl) && !is_sign)
+ {
+ mttl = daemon->min_ttl;
+ }
+ if (mttl != 0)
{
(p1) -= 4;
PUTLONG(daemon->max_ttl, p1);
@@ -722,6 +731,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
for (j = 0; j < ntohs(header->ancount); j++)
{
int secflag = 0;
+ unsigned long mttl = 0;
if (!(res = extract_name(header, qlen, &p1, name, 0, 10)))
return 0; /* bad packet */
@@ -730,6 +740,14 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
GETSHORT(aqclass, p1);
GETLONG(attl, p1);
if ((daemon->max_ttl != 0) && (attl > daemon->max_ttl) && !is_sign)
+ {
+ mttl = daemon->max_ttl;
+ }
+ if ((daemon->min_ttl != 0) && (attl < daemon->min_ttl) && !is_sign)
+ {
+ mttl = daemon->min_ttl;
+ }
+ if (mttl != 0)
{
(p1) -= 4;
PUTLONG(daemon->max_ttl, p1);