diff --git a/package/network/services/dnsmasq/Makefile b/package/network/services/dnsmasq/Makefile index dd9df245a..79c228aff 100644 --- a/package/network/services/dnsmasq/Makefile +++ b/package/network/services/dnsmasq/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=dnsmasq PKG_VERSION:=2.78 -PKG_RELEASE:=2 +PKG_RELEASE:=7 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=http://thekelleys.org.uk/dnsmasq/ @@ -17,12 +17,14 @@ PKG_HASH:=89949f438c74b0c7543f06689c319484bd126cc4b1f8c745c742ab397681252b PKG_LICENSE:=GPL-2.0 PKG_LICENSE_FILES:=COPYING +PKG_CPE_ID:=cpe:/a:thekelleys:dnsmasq PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(BUILD_VARIANT)/$(PKG_NAME)-$(PKG_VERSION) PKG_INSTALL:=1 PKG_BUILD_PARALLEL:=1 -PKG_CONFIG_DEPENDS:=CONFIG_PACKAGE_dnsmasq_$(BUILD_VARIANT)_dhcpv6 \ +PKG_CONFIG_DEPENDS:= CONFIG_PACKAGE_dnsmasq_$(BUILD_VARIANT)_dhcp \ + CONFIG_PACKAGE_dnsmasq_$(BUILD_VARIANT)_dhcpv6 \ CONFIG_PACKAGE_dnsmasq_$(BUILD_VARIANT)_dnssec \ CONFIG_PACKAGE_dnsmasq_$(BUILD_VARIANT)_auth \ CONFIG_PACKAGE_dnsmasq_$(BUILD_VARIANT)_ipset \ @@ -75,8 +77,8 @@ endef define Package/dnsmasq-full/description $(call Package/dnsmasq/description) -This is a fully configurable variant with DHCPv6, DNSSEC, Authoritative DNS and -IPset, Conntrack support & NO_ID enabled by default. +This is a fully configurable variant with DHCPv4, DHCPv6, DNSSEC, Authoritative DNS +and IPset, Conntrack support & NO_ID enabled by default. endef define Package/dnsmasq/conffiles @@ -86,9 +88,12 @@ endef define Package/dnsmasq-full/config if PACKAGE_dnsmasq-full + config PACKAGE_dnsmasq_full_dhcp + bool "Build with DHCP support." + default y config PACKAGE_dnsmasq_full_dhcpv6 bool "Build with DHCPv6 support." - depends on IPV6 + depends on IPV6 && PACKAGE_dnsmasq_full_dhcp default n config PACKAGE_dnsmasq_full_dnssec bool "Build with DNSSEC support." @@ -124,7 +129,8 @@ ifeq ($(BUILD_VARIANT),nodhcpv6) endif ifeq ($(BUILD_VARIANT),full) - COPTS += $(if $(CONFIG_PACKAGE_dnsmasq_$(BUILD_VARIANT)_dhcpv6),,-DNO_DHCP6) \ + COPTS += $(if $(CONFIG_PACKAGE_dnsmasq_$(BUILD_VARIANT)_dhcp),,-DNO_DHCP) \ + $(if $(CONFIG_PACKAGE_dnsmasq_$(BUILD_VARIANT)_dhcpv6),,-DNO_DHCP6) \ $(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) \ diff --git a/package/network/services/dnsmasq/files/dnsmasq.init b/package/network/services/dnsmasq/files/dnsmasq.init index 9bbffe679..dcc18e34d 100644 --- a/package/network/services/dnsmasq/files/dnsmasq.init +++ b/package/network/services/dnsmasq/files/dnsmasq.init @@ -13,7 +13,6 @@ ADD_LOCAL_FQDN="" BASECONFIGFILE="/var/etc/dnsmasq.conf" BASEHOSTFILE="/tmp/hosts/dhcp" -BASETIMESTAMPFILE="/etc/dnsmasq.time" TRUSTANCHORSFILE="/usr/share/dnsmasq/trust-anchors.conf" TIMEVALIDFILE="/var/state/dnsmasqsec" BASEDHCPSTAMPFILE="/var/run/dnsmasq" @@ -295,7 +294,7 @@ dhcp_host_add() { config_get_bool dns "$cfg" dns 0 [ "$dns" = "1" -a -n "$ip" -a -n "$name" ] && { - echo "$ip $name${DOMAIN:+.$DOMAIN}" >> $HOSTFILE + echo "$ip $name${DOMAIN:+.$DOMAIN}" >> $HOSTFILE_TMP } config_get mac "$cfg" mac @@ -636,7 +635,7 @@ dhcp_domain_add() { record="${record:+$record }$name" done - echo "$ip $record" >> $HOSTFILE + echo "$ip $record" >> $HOSTFILE_TMP } dhcp_srv_add() { @@ -742,7 +741,7 @@ dnsmasq_start() CONFIGFILE="${BASECONFIGFILE}.${cfg}" CONFIGFILE_TMP="${CONFIGFILE}.$$" HOSTFILE="${BASEHOSTFILE}.${cfg}" - TIMESTAMPFILE="${BASETIMESTAMPFILE}.${cfg}" + HOSTFILE_TMP="${HOSTFILE}.$$" BASEDHCPSTAMPFILE_CFG="${BASEDHCPSTAMPFILE}.${cfg}" # before we can call xappend @@ -752,14 +751,17 @@ dnsmasq_start() mkdir -p /var/lib/misc chown dnsmasq:dnsmasq /var/run/dnsmasq - [ -f "$TIMESTAMPFILE" ] && rm -f "$TIMESTAMPFILE" - echo "# auto-generated config file from /etc/config/dhcp" > $CONFIGFILE_TMP - echo "# auto-generated config file from /etc/config/dhcp" > $HOSTFILE + echo "# auto-generated config file from /etc/config/dhcp" > $HOSTFILE_TMP + + local dnsmasqconffile="/etc/dnsmasq.${cfg}.conf" + if [ ! -r "$dnsmasqconffile" ]; then + dnsmasqconffile=/etc/dnsmasq.conf + fi # if we did this last, we could override auto-generated config - [ -f /etc/dnsmasq.conf ] && { - xappend "--conf-file=/etc/dnsmasq.conf" + [ -f "${dnsmasqconffile}" ] && { + xappend "--conf-file=${dnsmasqconffile}" } $PROG --version | grep -osqE "^Compile time options:.* DHCPv6( |$)" && DHCPv6CAPABLE=1 || DHCPv6CAPABLE=0 @@ -997,6 +999,7 @@ dnsmasq_start() echo >> $CONFIGFILE_TMP mv -f $CONFIGFILE_TMP $CONFIGFILE + mv -f $HOSTFILE_TMP $HOSTFILE [ "$resolvfile" = "/tmp/resolv.conf.auto" ] && { rm -f /tmp/resolv.conf @@ -1015,11 +1018,6 @@ dnsmasq_start() [ -n "$user_dhcpscript" ] && procd_set_param env USER_DHCPSCRIPT="$user_dhcpscript" procd_set_param respawn - local dnsmasqconffile="/etc/dnsmasq.${cfg}.conf" - if [ ! -r "$dnsmasqconffile" ]; then - dnsmasqconffile=/etc/dnsmasq.conf - fi - procd_add_jail dnsmasq ubus log procd_add_jail_mount $CONFIGFILE $TRUSTANCHORSFILE $HOSTFILE $RFC6761FILE /etc/passwd /etc/group /etc/TZ /dev/null /dev/urandom $dnsmasqconffile $dnsmasqconfdir $resolvfile $user_dhcpscript /etc/hosts /etc/ethers /sbin/hotplug-call $EXTRA_MOUNT $DHCPSCRIPT procd_add_jail_mount_rw /var/run/dnsmasq/ $leasefile @@ -1046,7 +1044,7 @@ dnsmasq_stop() service_triggers() { - procd_add_reload_trigger "dhcp" + procd_add_reload_trigger "dhcp" "system" procd_add_raw_trigger "interface.*" 2000 /etc/init.d/dnsmasq reload } @@ -1086,7 +1084,7 @@ start_service() { reload_service() { rc_procd start_service "$@" - return 0 + procd_send_signal dnsmasq "$@" } stop_service() { diff --git a/package/network/services/dnsmasq/patches/240-ubus.patch b/package/network/services/dnsmasq/patches/240-ubus.patch index 2d37b5d2f..d21ca0dba 100644 --- a/package/network/services/dnsmasq/patches/240-ubus.patch +++ b/package/network/services/dnsmasq/patches/240-ubus.patch @@ -9,7 +9,7 @@ struct daemon *daemon; static volatile pid_t pid = 0; -@@ -32,6 +34,62 @@ static void fatal_event(struct event_des +@@ -32,6 +34,64 @@ static void fatal_event(struct event_des static int read_event(int fd, struct event_desc *evp, char **msg); static void poll_resolv(int force, int do_reload, time_t now); @@ -25,7 +25,7 @@ + .type = &ubus_object_type, +}; + -+void ubus_event_bcast(const char *type, const char *mac, const char *ip, const char *name) ++void ubus_event_bcast(const char *type, const char *mac, const char *ip, const char *name, const char *interface) +{ + if (!ubus || !ubus_object.has_subscribers) + return; @@ -37,6 +37,8 @@ + blobmsg_add_string(&b, "ip", ip); + if (name) + blobmsg_add_string(&b, "name", name); ++ if (interface) ++ blobmsg_add_string(&b, "interface", interface); + ubus_notify(ubus, &ubus_object, type, b.head, -1); +} + @@ -72,7 +74,7 @@ int main (int argc, char **argv) { int bind_fallback = 0; -@@ -911,6 +969,7 @@ int main (int argc, char **argv) +@@ -911,6 +971,7 @@ int main (int argc, char **argv) set_dbus_listeners(); #endif @@ -80,7 +82,7 @@ #ifdef HAVE_DHCP if (daemon->dhcp || daemon->relay4) { -@@ -1041,6 +1100,8 @@ int main (int argc, char **argv) +@@ -1041,6 +1102,8 @@ int main (int argc, char **argv) check_dbus_listeners(); #endif @@ -106,7 +108,7 @@ # endif #endif -+void ubus_event_bcast(const char *type, const char *mac, const char *ip, const char *name); ++void ubus_event_bcast(const char *type, const char *mac, const char *ip, const char *name, const char *interface); + /* ipset.c */ #ifdef HAVE_IPSET @@ -118,9 +120,9 @@ string ? string : "", err ? err : ""); + if (!strcmp(type, "DHCPACK")) -+ ubus_event_bcast("dhcp.ack", addr ? inet_ntoa(a) : NULL, daemon->namebuff, string ? string : NULL); ++ ubus_event_bcast("dhcp.ack", daemon->namebuff, addr ? inet_ntoa(a) : NULL, string ? string : NULL, interface); + else if (!strcmp(type, "DHCPRELEASE")) -+ ubus_event_bcast("dhcp.release", addr ? inet_ntoa(a) : NULL, daemon->namebuff, string ? string : NULL); ++ ubus_event_bcast("dhcp.release", daemon->namebuff, addr ? inet_ntoa(a) : NULL, string ? string : NULL, interface); } static void log_options(unsigned char *start, u32 xid) diff --git a/package/network/services/dnsmasq/patches/250-Fix-infinite-retries-in-strict-order-mode.patch b/package/network/services/dnsmasq/patches/250-Fix-infinite-retries-in-strict-order-mode.patch new file mode 100644 index 000000000..faff680e0 --- /dev/null +++ b/package/network/services/dnsmasq/patches/250-Fix-infinite-retries-in-strict-order-mode.patch @@ -0,0 +1,45 @@ +From ef3d137a646fa8309e1ff5184e3e145eef40cc4d Mon Sep 17 00:00:00 2001 +From: Simon Kelley +Date: Tue, 5 Dec 2017 22:37:29 +0000 +Subject: [PATCH] Fix infinite retries in strict-order mode. + + If all configured dns servers return refused in + response to a query; dnsmasq will end up in an infinite loop + retransmitting the dns query resulting into high CPU load. + Problem is caused by the dns refuse retransmission logic which does + not check for the end of a dns server list iteration in strict mode. + Having one configured dns server returning a refused reply easily + triggers this problem in strict order mode. This was introduced in + 9396752c115b3ab733fa476b30da73237e12e7ba + + Thanks to Hans Dedecker for spotting this + and the initial patch. +--- + src/forward.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +--- a/src/forward.c ++++ b/src/forward.c +@@ -797,10 +797,20 @@ void reply_query(int fd, int family, tim + unsigned char *pheader; + size_t plen; + int is_sign; +- ++ ++ /* In strict order mode, there must be a server later in the chain ++ left to send to, otherwise without the forwardall mechanism, ++ code further on will cycle around the list forwever if they ++ all return REFUSED. Note that server is always non-NULL before ++ this executes. */ ++ if (option_bool(OPT_ORDER)) ++ for (server = forward->sentto->next; server; server = server->next) ++ if (!(server->flags & (SERV_LITERAL_ADDRESS | SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_NO_ADDR | SERV_LOOP))) ++ break; ++ + /* recreate query from reply */ + pheader = find_pseudoheader(header, (size_t)n, &plen, NULL, &is_sign, NULL); +- if (!is_sign) ++ if (!is_sign && server) + { + header->ancount = htons(0); + header->nscount = htons(0);