From aa52029f6ebc614c8fd1f37d5328bfb0ffb2d2a0 Mon Sep 17 00:00:00 2001 From: RISCi_ATOM Date: Mon, 2 Oct 2017 13:22:32 -0400 Subject: [PATCH] Bump dnsmasq version to v2.78 to fix several CVEs Fixes CVE-2017-14491, CVE-2017-14492, CVE-2017-14493, CVE-2017-14494, 2017-CVE-14495, 2017-CVE-14496 --- package/network/services/dnsmasq/Makefile | 22 +- .../services/dnsmasq/files/dhcp-script.sh | 46 +++ .../network/services/dnsmasq/files/dhcp.conf | 2 +- .../services/dnsmasq/files/dnsmasq.init | 371 ++++++++++++++---- .../services/dnsmasq/files/dnsmasq_acl.json | 4 + .../services/dnsmasq/files/rfc6761.conf | 15 + ...eak-ICMP-ping-check-logic-for-DHCPv4.patch | 25 -- ...ing-check-of-configured-DHCP-address.patch | 28 -- ...s-if-first-returns-REFUSED-when-stri.patch | 31 -- .../025-backport-fix-CVE-2017-13704.patch | 94 ----- .../030-fix-arcount-edns0-behaviour.patch | 44 --- ...0-fix-poll-h-include-warning-on-musl.patch | 2 +- .../services/dnsmasq/patches/240-ubus.patch | 126 ++++++ 13 files changed, 513 insertions(+), 297 deletions(-) create mode 100755 package/network/services/dnsmasq/files/dhcp-script.sh create mode 100644 package/network/services/dnsmasq/files/dnsmasq_acl.json create mode 100644 package/network/services/dnsmasq/files/rfc6761.conf delete mode 100644 package/network/services/dnsmasq/patches/010-Tweak-ICMP-ping-check-logic-for-DHCPv4.patch delete mode 100644 package/network/services/dnsmasq/patches/011-Remove-ping-check-of-configured-DHCP-address.patch delete mode 100644 package/network/services/dnsmasq/patches/020-Try-other-servers-if-first-returns-REFUSED-when-stri.patch delete mode 100644 package/network/services/dnsmasq/patches/025-backport-fix-CVE-2017-13704.patch delete mode 100644 package/network/services/dnsmasq/patches/030-fix-arcount-edns0-behaviour.patch create mode 100644 package/network/services/dnsmasq/patches/240-ubus.patch diff --git a/package/network/services/dnsmasq/Makefile b/package/network/services/dnsmasq/Makefile index be7a2d1c0f..9a024ceadf 100644 --- a/package/network/services/dnsmasq/Makefile +++ b/package/network/services/dnsmasq/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=dnsmasq -PKG_VERSION:=2.77 -PKG_RELEASE:=6 +PKG_VERSION:=2.78 +PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=http://thekelleys.org.uk/dnsmasq/ -PKG_HASH:=6eac3b1c50ae25170e3ff8c96ddb55236cf45007633fdb8a35b1f3e02f5f8b8a +PKG_HASH:=89949f438c74b0c7543f06689c319484bd126cc4b1f8c745c742ab397681252b PKG_LICENSE:=GPL-2.0 PKG_LICENSE_FILES:=COPYING @@ -37,6 +37,7 @@ define Package/dnsmasq/Default CATEGORY:=Base system TITLE:=DNS and DHCP server URL:=http://www.thekelleys.org.uk/dnsmasq/ + DEPENDS:=+libubus USERID:=dnsmasq=453:dnsmasq=453 endef @@ -48,14 +49,14 @@ endef define Package/dnsmasq-dhcpv6 $(call Package/dnsmasq/Default) TITLE += (with DHCPv6 support) - DEPENDS:=@IPV6 + DEPENDS+=@IPV6 VARIANT:=dhcpv6 endef define Package/dnsmasq-full $(call Package/dnsmasq/Default) TITLE += (with DNSSEC, DHCPv6, Auth DNS, IPset, Conntrack, NO_ID enabled by default) - DEPENDS:=+PACKAGE_dnsmasq_full_dnssec:libnettle \ + DEPENDS+=+PACKAGE_dnsmasq_full_dnssec:libnettle \ +PACKAGE_dnsmasq_full_ipset:kmod-ipt-ipset \ +PACKAGE_dnsmasq_full_conntrack:libnetfilter-conntrack VARIANT:=full @@ -137,7 +138,7 @@ endif MAKE_FLAGS := \ $(TARGET_CONFIGURE_OPTS) \ - CFLAGS="$(TARGET_CFLAGS)" \ + CFLAGS="$(TARGET_CFLAGS) $(TARGET_CPPFLAGS)" \ LDFLAGS="$(TARGET_LDFLAGS)" \ COPTS="$(COPTS)" \ PREFIX="/usr" @@ -150,8 +151,17 @@ define Package/dnsmasq/install $(INSTALL_DATA) ./files/dnsmasq.conf $(1)/etc/dnsmasq.conf $(INSTALL_DIR) $(1)/etc/init.d $(INSTALL_BIN) ./files/dnsmasq.init $(1)/etc/init.d/dnsmasq + $(INSTALL_DIR) $(1)/etc/hotplug.d/dhcp + $(INSTALL_DIR) $(1)/etc/hotplug.d/neigh $(INSTALL_DIR) $(1)/etc/hotplug.d/ntp + $(INSTALL_DIR) $(1)/etc/hotplug.d/tftp $(INSTALL_DATA) ./files/dnsmasqsec.hotplug $(1)/etc/hotplug.d/ntp/25-dnsmasqsec + $(INSTALL_DIR) $(1)/usr/share/dnsmasq + $(INSTALL_DATA) ./files/rfc6761.conf $(1)/usr/share/dnsmasq/ + $(INSTALL_DIR) $(1)/usr/lib/dnsmasq + $(INSTALL_BIN) ./files/dhcp-script.sh $(1)/usr/lib/dnsmasq/dhcp-script.sh + $(INSTALL_DIR) $(1)/usr/share/acl.d + $(INSTALL_DATA) ./files/dnsmasq_acl.json $(1)/usr/share/acl.d/ endef Package/dnsmasq-dhcpv6/install = $(Package/dnsmasq/install) diff --git a/package/network/services/dnsmasq/files/dhcp-script.sh b/package/network/services/dnsmasq/files/dhcp-script.sh new file mode 100755 index 0000000000..86032694c1 --- /dev/null +++ b/package/network/services/dnsmasq/files/dhcp-script.sh @@ -0,0 +1,46 @@ +#!/bin/sh + +[ -f "$USER_DHCPSCRIPT" ] && . "$USER_DHCPSCRIPT" "$@" + +case "$1" in + add) + export ACTION="add" + export MACADDR="$2" + export IPADDR="$3" + export HOSTNAME="$4" + exec /sbin/hotplug-call dhcp + ;; + del) + export ACTION="remove" + export MACADDR="$2" + export IPADDR="$3" + export HOSTNAME="$4" + exec /sbin/hotplug-call dhcp + ;; + old) + export ACTION="update" + export MACADDR="$2" + export IPADDR="$3" + export HOSTNAME="$4" + exec /sbin/hotplug-call dhcp + ;; + arp-add) + export ACTION="add" + export MACADDR="$2" + export IPADDR="$3" + exec /sbin/hotplug-call neigh + ;; + arp-del) + export ACTION="remove" + export MACADDR="$2" + export IPADDR="$3" + exec /sbin/hotplug-call neigh + ;; + tftp) + export ACTION="add" + export TFTP_SIZE="$2" + export TFTP_ADDR="$3" + export TFTP_PATH="$4" + exec /sbin/hotplug-call tftp + ;; +esac diff --git a/package/network/services/dnsmasq/files/dhcp.conf b/package/network/services/dnsmasq/files/dhcp.conf index 362b90a293..360c7d79ee 100644 --- a/package/network/services/dnsmasq/files/dhcp.conf +++ b/package/network/services/dnsmasq/files/dhcp.conf @@ -15,7 +15,7 @@ config dnsmasq option leasefile '/tmp/dhcp.leases' option resolvfile '/tmp/resolv.conf.auto' #list server '/mycompany.local/1.2.3.4' - #option nonwildcard 1 + option nonwildcard 1 # bind to & keep track of interfaces #list interface br-lan #list notinterface lo #list bogusnxdomain '64.94.110.11' diff --git a/package/network/services/dnsmasq/files/dnsmasq.init b/package/network/services/dnsmasq/files/dnsmasq.init index a762cd3309..0149643959 100644 --- a/package/network/services/dnsmasq/files/dnsmasq.init +++ b/package/network/services/dnsmasq/files/dnsmasq.init @@ -8,6 +8,8 @@ PROG=/usr/sbin/dnsmasq ADD_LOCAL_DOMAIN=1 ADD_LOCAL_HOSTNAME=1 +ADD_WAN_FQDN=0 +ADD_LOCAL_FQDN="" BASECONFIGFILE="/var/etc/dnsmasq.conf" BASEHOSTFILE="/tmp/hosts/dhcp" @@ -15,6 +17,10 @@ BASETIMESTAMPFILE="/etc/dnsmasq.time" TRUSTANCHORSFILE="/usr/share/dnsmasq/trust-anchors.conf" TIMEVALIDFILE="/var/state/dnsmasqsec" BASEDHCPSTAMPFILE="/var/run/dnsmasq" +RFC6761FILE="/usr/share/dnsmasq/rfc6761.conf" +DHCPSCRIPT="/usr/lib/dnsmasq/dhcp-script.sh" + +DNSMASQ_DHCP_VER=4 xappend() { local value="$1" @@ -83,12 +89,24 @@ log_once() { logger -t dnsmasq "$@" } +has_handler() { + local file + + for file in /etc/hotplug.d/dhcp/* /etc/hotplug.d/tftp/* /etc/hotplug.d/neigh/*; do + [ -f "$file" ] && return 0 + done + + return 1 +} + append_bool() { local section="$1" local option="$2" local value="$3" + local default="$4" local _loctmp - config_get_bool _loctmp "$section" "$option" 0 + [ -z "$default" ] && default="0" + config_get_bool _loctmp "$section" "$option" "$default" [ $_loctmp -gt 0 ] && xappend "$value" } @@ -107,6 +125,10 @@ append_server() { xappend "--server=$1" } +append_rev_server() { + xappend "--rev-server=$1" +} + append_address() { xappend "--address=$1" } @@ -116,12 +138,12 @@ append_ipset() { } append_interface() { - network_get_device ifname "$1" || return + network_get_device ifname "$1" || ifname="$1" xappend "--interface=$ifname" } append_notinterface() { - network_get_device ifname "$1" || return + network_get_device ifname "$1" || ifname="$1" xappend "--except-interface=$ifname" } @@ -137,6 +159,10 @@ append_pxe_service() { xappend "--pxe-service=$1" } +append_interface_name() { + xappend "--interface-name=$1,$2" +} + filter_dnsmasq() { local cfg="$1" func="$2" match_cfg="$3" found_cfg @@ -180,6 +206,7 @@ dhcp_remoteid_add() { } dhcp_circuitid_add() { + # TODO: DHCPV6 does not have circuitid; catch "option6:" local cfg="$1" config_get networkid "$cfg" networkid @@ -212,6 +239,7 @@ dhcp_userclass_add() { } dhcp_vendorclass_add() { + # TODO: DHCPV6 vendor class has stricter definitions; catch? fixup? local cfg="$1" config_get networkid "$cfg" networkid @@ -245,6 +273,7 @@ dhcp_match_add() { dhcp_host_add() { local cfg="$1" + local hosttag nametime addrs duids config_get_bool force "$cfg" force 0 @@ -256,7 +285,9 @@ dhcp_host_add() { config_get name "$cfg" name config_get ip "$cfg" ip - [ -n "$ip" -o -n "$name" ] || return 0 + config_get hostid "$cfg" hostid + + [ -n "$ip" -o -n "$name" -o -n "$hostid" ] || return 0 config_get_bool dns "$cfg" dns 0 [ "$dns" = "1" -a -n "$ip" -a -n "$name" ] && { @@ -264,36 +295,105 @@ dhcp_host_add() { } config_get mac "$cfg" mac + config_get duid "$cfg" duid + config_get tag "$cfg" tag + if [ -n "$mac" ]; then # --dhcp-host=00:20:e0:3b:13:af,192.168.0.199,lap + # many MAC are possible to track a laptop ON/OFF dock macs="" for m in $mac; do append macs "$m" ","; done - else - # --dhcp-host=lap,192.168.0.199 + fi + + if [ $DNSMASQ_DHCP_VER -eq 6 -a -n "$duid" ]; then + # --dhcp-host=id:00:03:00:01:12:00:00:01:02:03,[::beef],lap + # one (virtual) machine gets one DUID per RFC3315 + duids="id:${duid// */}" + fi + + if [ -z "$macs" -a -z "$duids" ]; then + # --dhcp-host=lap,192.168.0.199,[::beef] [ -n "$name" ] || return 0 macs="$name" name="" fi - config_get tag "$cfg" tag + if [ -n "$hostid" ]; then + hex_to_hostid hostid "$hostid" + fi - if [ "$DHCPv6CAPABLE" -eq 1 ]; then - config_get duid "$cfg" duid - config_get hostid "$cfg" hostid - if [ -n "$hostid" ]; then - hex_to_hostid hostid "$hostid" - fi + tags="" + if [ -n "$tag" ]; then + for t in $tag; do append tags "$t" ",set:"; done fi config_get_bool broadcast "$cfg" broadcast 0 - [ "$broadcast" = "0" ] && broadcast= - config_get leasetime "$cfg" leasetime - xappend "--dhcp-host=$macs${duid:+,id:$duid}${networkid:+,net:$networkid}${broadcast:+,set:needs-broadcast}${tag:+,set:$tag}${ip:+,$ip${hostid:+,[::$hostid]}}${name:+,$name}${leasetime:+,$leasetime}" + [ "$broadcast" = "0" ] && broadcast= || broadcast=",set:needs-broadcast" + + hosttag="${networkid:+,set:${networkid}}${tags:+,set:${tags}}$broadcast" + nametime="${name:+,$name}${leasetime:+,$leasetime}" + + if [ $DNSMASQ_DHCP_VER -eq 6 ]; then + addrs="${ip:+,$ip}${hostid:+,[::$hostid]}" + xappend "--dhcp-host=$macs${duids:+,$duids}$hosttag$addrs$nametime" + else + xappend "--dhcp-host=$macs$hosttag${ip:+,$ip}$nametime" + fi +} + +dhcp_this_host_add() { + local net="$1" + local ifname="$2" + local mode="$3" + local routerstub routername ifdashname + local lanaddr lanaddr6 lanaddrs6 ulaprefix + + if [ "$mode" -gt 0 ] ; then + ifdashname="${ifname//./-}" + routerstub="$( md5sum /etc/os-release )" + routerstub="router-${routerstub// */}" + routername="$( uci_get system @system[0] hostname $routerstub )" + + if [ "$mode" -gt 1 ] ; then + if [ "$mode" -gt 2 ] ; then + if [ "$mode" -gt 3 ] ; then + append_interface_name "$ifdashname.$routername.$DOMAIN" "$ifname" + fi + + append_interface_name "$routername.$DOMAIN" "$ifname" + fi + + # All IP addresses discovered by dnsmasq will be labeled (except fe80::) + append_interface_name "$routername" "$ifname" + + else + # This uses a static host file entry for only limited addresses. + # Use dnsmasq option "--expandhosts" to enable FQDN on host files. + ulaprefix="$(uci_get network @globals[0] ula_prefix)" + network_get_ipaddr lanaddr "$net" + network_get_ipaddrs6 lanaddrs6 "$net" + + if [ -n "$lanaddr" ] ; then + dhcp_domain_add "" "$routername" "$lanaddr" + fi + + if [ -n "$ulaprefix" -a -n "$lanaddrs6" ] ; then + for lanaddr6 in $lanaddrs6 ; do + case "$lanaddr6" in + "${ulaprefix%%:/*}"*) + dhcp_domain_add "" "$routername" "$lanaddr6" + ;; + esac + done + fi + fi + fi } dhcp_tag_add() { + # NOTE: dnsmasq has explicit "option6:" prefix for DHCPv6 so no collisions local cfg="$1" tag="$cfg" @@ -324,6 +424,7 @@ dhcp_mac_add() { } dhcp_boot_add() { + # TODO: BOOTURL is different between DHCPv4 and DHCPv6 local cfg="$1" config_get networkid "$cfg" networkid @@ -346,24 +447,30 @@ dhcp_boot_add() { dhcp_add() { local cfg="$1" + local dhcp6range="::" + local nettag + local tags + config_get net "$cfg" interface [ -n "$net" ] || return 0 - config_get dhcpv4 "$cfg" dhcpv4 - [ "$dhcpv4" != "disabled" ] || return 0 - config_get networkid "$cfg" networkid [ -n "$networkid" ] || networkid="$net" - network_get_subnet subnet "$net" || return 0 network_get_device ifname "$net" || return 0 - network_get_protocol proto "$net" || return 0 [ "$cachelocal" = "0" ] && network_get_dnsserver dnsserver "$net" && { DNS_SERVERS="$DNS_SERVERS $dnsserver" } - append_bool "$cfg" ignore "--no-dhcp-interface=$ifname" && return 0 + append_bool "$cfg" ignore "--no-dhcp-interface=$ifname" && { + # Many ISP do not have useful names for DHCP customers (your WAN). + dhcp_this_host_add "$net" "$ifname" "$ADD_WAN_FQDN" + return 0 + } + + network_get_subnet subnet "$net" || return 0 + network_get_protocol proto "$net" || return 0 # Do not support non-static interfaces for now [ static = "$proto" ] || return 0 @@ -375,21 +482,107 @@ dhcp_add() { config_get_bool force "$cfg" force 0 [ $force -gt 0 ] || dhcp_check "$ifname" || return 0 - config_get start "$cfg" start - config_get limit "$cfg" limit - config_get leasetime "$cfg" leasetime + config_get start "$cfg" start 100 + config_get limit "$cfg" limit 150 + config_get leasetime "$cfg" leasetime 12h config_get options "$cfg" options config_get_bool dynamicdhcp "$cfg" dynamicdhcp 1 - leasetime="${leasetime:-12h}" - start="$(dhcp_calc "${start:-100}")" - limit="${limit:-150}" - [ "$limit" -gt 0 ] && limit=$((limit-1)) + config_get dhcpv4 "$cfg" dhcpv4 + config_get dhcpv6 "$cfg" dhcpv6 + + config_get ra "$cfg" ra + config_get ra_management "$cfg" ra_management + config_get ra_preference "$cfg" ra_preference + config_get dns "$cfg" dns + + config_list_foreach "$cfg" "interface_name" append_interface_name "$ifname" + + # Put the router host name on this DHCP served interface address(es) + dhcp_this_host_add "$net" "$ifname" "$ADD_LOCAL_FQDN" + + start="$( dhcp_calc "$start" )" + + add_tag() { + tags="${tags}tag:$1," + } + config_list_foreach "$cfg" tag add_tag + + nettag="${networkid:+set:${networkid},}" + + if [ "$limit" -gt 0 ] ; then + limit=$((limit-1)) + fi + eval "$(ipcalc.sh "${subnet%%/*}" $netmask $start $limit)" - if [ "$dynamicdhcp" = "0" ]; then END="static"; fi - xappend "--dhcp-range=$networkid,$START,$END,$NETMASK,$leasetime${options:+ $options}" - dhcp_option_add "$cfg" "$networkid" + if [ "$dynamicdhcp" = "0" ] ; then + END="static" + dhcp6range="::,static" + else + dhcp6range="::1000,::ffff" + fi + + + if [ "$dhcpv4" != "disabled" ] ; then + xappend "--dhcp-range=$tags$nettag$START,$END,$NETMASK,$leasetime${options:+ $options}" + fi + + + if [ $DNSMASQ_DHCP_VER -eq 6 -a "$ra" = "server" ] ; then + # Note: dnsmasq cannot just be a DHCPv6 server (all-in-1) + # and let some other machine(s) send RA pointing to it. + + case $ra_preference in + *high*) + xappend "--ra-param=$ifname,high,0,7200" + ;; + *low*) + xappend "--ra-param=$ifname,low,0,7200" + ;; + *) + # Send UNSOLICITED RA at default interval and live for 2 hours. + # TODO: convert flexible lease time into route life time (only seconds). + xappend "--ra-param=$ifname,0,7200" + ;; + esac + + if [ "$dhcpv6" = "disabled" ] ; then + ra_management="3" + fi + + + case $ra_management in + 0) + # SLACC with DCHP for extended options + xappend "--dhcp-range=$nettag::,constructor:$ifname,ra-stateless,ra-names" + ;; + 2) + # DHCP address and RA only for management redirection + xappend "--dhcp-range=$nettag$dhcp6range,constructor:$ifname,$leasetime" + ;; + 3) + # SLAAC only but dnsmasq attempts to link HOSTNAME, DHCPv4 MAC, and SLAAC + xappend "--dhcp-range=$nettag::,constructor:$ifname,ra-only,ra-names" + ;; + *) + # SLAAC and full DHCP + xappend "--dhcp-range=$nettag$dhcp6range,constructor:$ifname,slaac,ra-names,$leasetime" + ;; + esac + + if [ -n "$dns" ]; then + dnss="" + for d in $dns; do append dnss "[$d]" ","; done + else + dnss="[::]" + fi + + dhcp_option_append "option6:dns-server,$dnss" "$networkid" + fi + + dhcp_option_add "$cfg" "$networkid" 0 + dhcp_option_add "$cfg" "$networkid" 2 } dhcp_option_append() { @@ -401,21 +594,24 @@ dhcp_option_append() { } dhcp_option_add() { + # NOTE: dnsmasq has explicit "option6:" prefix for DHCPv6 so no collisions local cfg="$1" local networkid="$2" local force="$3" + local opt="dhcp_option" [ "$force" = "0" ] && force= + [ "$force" = "2" ] && opt="dhcp_option_force" local list_len - config_get list_len "$cfg" dhcp_option_LENGTH + config_get list_len "$cfg" "${opt}_LENGTH" if [ -n "$list_len" ]; then - config_list_foreach "$cfg" dhcp_option dhcp_option_append "$networkid" "$force" + config_list_foreach "$cfg" "$opt" dhcp_option_append "$networkid" "$force" else - config_get dhcp_option "$cfg" dhcp_option + config_get dhcp_option "$cfg" "$opt" - [ -n "$dhcp_option" ] && echo "Warning: the 'option dhcp_option' syntax is deprecated, use 'list dhcp_option'" >&2 + [ -n "$dhcp_option" ] && echo "Warning: the 'option $opt' syntax is deprecated, use 'list $opt'" >&2 local option for option in $dhcp_option; do @@ -533,7 +729,7 @@ dhcp_relay_add() { dnsmasq_start() { - local cfg="$1" disabled + local cfg="$1" disabled resolvfile user_dhcpscript config_get_bool disabled "$cfg" disabled 0 [ "$disabled" -gt 0 ] && return 0 @@ -566,6 +762,41 @@ dnsmasq_start() $PROG --version | grep -osqE "^Compile time options:.* DHCPv6( |$)" && DHCPv6CAPABLE=1 || DHCPv6CAPABLE=0 + + if [ -x /usr/sbin/odhcpd -a -x /etc/init.d/odhcpd ] ; then + local odhcpd_is_main odhcpd_is_enabled + config_get odhcpd_is_main odhcpd maindhcp 0 + /etc/init.d/odhcpd enabled && odhcpd_is_enabled=1 || odhcpd_is_enabled=0 + + + if [ "$odhcpd_is_enabled" -eq 0 -a "$DHCPv6CAPABLE" -eq 1 ] ; then + # DHCP V4 and V6 in DNSMASQ + DNSMASQ_DHCP_VER=6 + elif [ "$odhcpd_is_main" -gt 0 ] ; then + # ODHCPD is doing it all + DNSMASQ_DHCP_VER=0 + else + # You have ODHCPD but use DNSMASQ for DHCPV4 + DNSMASQ_DHCP_VER=4 + fi + + elif [ "$DHCPv6CAPABLE" -eq 1 ] ; then + # DHCP V4 and V6 in DNSMASQ + DNSMASQ_DHCP_VER=6 + else + DNSMASQ_DHCP_VER=4 + fi + + # Allow DHCP/DHCPv6 to be handled by ISC DHCPD + if [ -x /usr/sbin/dhcpd ] ; then + if [ -x /etc/init.d/dhcpd ] ; then + /etc/init.d/dhcpd enabled && DNSMASQ_DHCP_VER=0 + fi + if [ -x /etc/init.d/dhcpd6 -a "$DNSMASQ_DHCP_VER" -gt 0 ] ; then + /etc/init.d/dhcpd6 enabled && DNSMASQ_DHCP_VER=4 + fi + fi + append_bool "$cfg" authoritative "--dhcp-authoritative" append_bool "$cfg" nodaemon "--no-daemon" append_bool "$cfg" domainneeded "--domain-needed" @@ -578,12 +809,11 @@ dnsmasq_start() append_bool "$cfg" localise_queries "--localise-queries" append_bool "$cfg" readethers "--read-ethers" append_bool "$cfg" dbus "--enable-dbus" - append_bool "$cfg" boguspriv "--bogus-priv" append_bool "$cfg" expandhosts "--expand-hosts" config_get tftp_root "$cfg" "tftp_root" [ -n "$tftp_root" ] && mkdir -p "$tftp_root" && append_bool "$cfg" enable_tftp "--enable-tftp" append_bool "$cfg" tftp_no_fail "--tftp-no-fail" - append_bool "$cfg" nonwildcard "--bind-dynamic" + append_bool "$cfg" nonwildcard "--bind-dynamic" 1 append_bool "$cfg" fqdn "--dhcp-fqdn" append_bool "$cfg" proxydnssec "--proxy-dnssec" append_bool "$cfg" localservice "--local-service" @@ -594,7 +824,7 @@ dnsmasq_start() append_bool "$cfg" noping "--no-ping" append_parm "$cfg" logfacility "--log-facility" - append_parm "$cfg" dhcpscript "--dhcp-script" + append_parm "$cfg" cachesize "--cache-size" append_parm "$cfg" dnsforwardmax "--dns-forward-max" append_parm "$cfg" port "--port" @@ -606,6 +836,7 @@ dnsmasq_start() append_parm "$cfg" "domain" "--domain" append_parm "$cfg" "local" "--server" 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 config_list_foreach "$cfg" "interface" append_interface @@ -613,7 +844,6 @@ 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" "resolvfile" "--resolv-file" "/tmp/resolv.conf.auto" append_parm "$cfg" "serversfile" "--servers-file" append_parm "$cfg" "tftp_root" "--tftp-root" append_parm "$cfg" "dhcp_boot" "--dhcp-boot" @@ -624,12 +854,21 @@ dnsmasq_start() config_get_bool ADD_LOCAL_DOMAIN "$cfg" add_local_domain 1 config_get_bool ADD_LOCAL_HOSTNAME "$cfg" add_local_hostname 1 + config_get ADD_LOCAL_FQDN "$cfg" add_local_fqdn "" + config_get ADD_WAN_FQDN "$cfg" add_wan_fqdn 0 + + if [ -z "$ADD_LOCAL_FQDN" ] ; then + # maintain support for previous UCI + ADD_LOCAL_FQDN="$ADD_LOCAL_HOSTNAME" + fi config_get_bool readethers "$cfg" readethers [ "$readethers" = "1" -a \! -e "/etc/ethers" ] && touch /etc/ethers - config_get resolvfile $cfg resolvfile - config_get dhcpscript $cfg dhcpscript + config_get user_dhcpscript $cfg dhcpscript + if has_handler || [ -n "$user_dhcpscript" ]; then + xappend "--dhcp-script=$DHCPSCRIPT" + fi config_get leasefile $cfg leasefile "/tmp/dhcp.leases" [ -n "$leasefile" -a \! -e "$leasefile" ] && touch "$leasefile" @@ -642,6 +881,8 @@ dnsmasq_start() [ -n "$resolvfile" -a \! -e "$resolvfile" ] && touch "$resolvfile" fi + [ -n "$resolvfile" ] && xappend "--resolv-file=$resolvfile" + config_get hostsfile "$cfg" dhcphostsfile [ -e "$hostsfile" ] && xappend "--dhcp-hostsfile=$hostsfile" @@ -688,6 +929,7 @@ dnsmasq_start() } dhcp_option_add "$cfg" "" 0 + dhcp_option_add "$cfg" "" 2 xappend "--dhcp-broadcast=tag:needs-broadcast" @@ -721,37 +963,31 @@ dnsmasq_start() config_foreach filter_dnsmasq hostrecord dhcp_hostrecord_add "$cfg" config_foreach filter_dnsmasq relay dhcp_relay_add "$cfg" - # add own hostname - [ $ADD_LOCAL_HOSTNAME -eq 1 ] && { - local lanaddr lanaddr6 - local ulaprefix="$(uci_get network @globals[0] ula_prefix)" - local hostname="$(uci_get system @system[0] hostname Lede)" - - network_get_ipaddr lanaddr "lan" && { - dhcp_domain_add "" "$hostname" "$lanaddr" - } - - [ -n "$ulaprefix" ] && network_get_ipaddrs6 lanaddr6 "lan" && { - for lanaddr6 in $lanaddr6; do - case "$lanaddr6" in - "${ulaprefix%%:/*}"*) - dhcp_domain_add "" "$hostname" "$lanaddr6" - ;; - esac - done - } - } - echo >> $CONFIGFILE_TMP config_foreach filter_dnsmasq srvhost dhcp_srv_add "$cfg" config_foreach filter_dnsmasq mxhost dhcp_mx_add "$cfg" echo >> $CONFIGFILE_TMP - config_get odhcpd_is_active odhcpd maindhcp - if [ "$odhcpd_is_active" != "1" ]; then + config_get_bool boguspriv "$cfg" boguspriv 1 + [ "$boguspriv" -gt 0 ] && { + xappend "--bogus-priv" + [ -r "$RFC6761FILE" ] && xappend "--conf-file=$RFC6761FILE" + } + + if [ "$DNSMASQ_DHCP_VER" -gt 4 ] ; then + # Enable RA feature for when/if it is constructed, + # and RA is selected per interface pool (RA, DHCP, or both), + # but no one (should) want RA broadcast in syslog + config_foreach filter_dnsmasq dhcp dhcp_add "$cfg" + xappend "--enable-ra" + xappend "--quiet-ra" + append_bool "$cfg" quietdhcp "--quiet-dhcp6" + + elif [ "$DNSMASQ_DHCP_VER" -gt 0 ] ; then config_foreach filter_dnsmasq dhcp dhcp_add "$cfg" fi + echo >> $CONFIGFILE_TMP config_foreach filter_dnsmasq cname dhcp_cname_add "$cfg" echo >> $CONFIGFILE_TMP @@ -773,6 +1009,7 @@ dnsmasq_start() 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 dnsmasqconffile="/etc/dnsmasq.${cfg}.conf" @@ -781,7 +1018,7 @@ dnsmasq_start() fi procd_add_jail dnsmasq ubus log - procd_add_jail_mount $CONFIGFILE $TRUSTANCHORSFILE $HOSTFILE /etc/passwd /etc/group /etc/TZ /dev/null /dev/urandom $dnsmasqconffile $dnsmasqconfdir $resolvfile $dhcpscript /etc/hosts /etc/ethers $EXTRA_MOUNT + 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 procd_close_instance diff --git a/package/network/services/dnsmasq/files/dnsmasq_acl.json b/package/network/services/dnsmasq/files/dnsmasq_acl.json new file mode 100644 index 0000000000..00ec7d0f03 --- /dev/null +++ b/package/network/services/dnsmasq/files/dnsmasq_acl.json @@ -0,0 +1,4 @@ +{ + "user": "dnsmasq", + "publish": [ "dnsmasq" ] +} diff --git a/package/network/services/dnsmasq/files/rfc6761.conf b/package/network/services/dnsmasq/files/rfc6761.conf new file mode 100644 index 0000000000..ebc1a12118 --- /dev/null +++ b/package/network/services/dnsmasq/files/rfc6761.conf @@ -0,0 +1,15 @@ +# RFC6761 included configuration file for dnsmasq +# +# includes a list of domains that should not be forwarded to Internet name servers +# to reduce burden on them, asking questions that they won't know the answer to. + +server=/bind/ +server=/example/ +server=/example.com/ +server=/example.org/ +server=/example.net/ +server=/invalid/ +server=/local/ +server=/localhost/ +server=/onion/ +server=/test/ diff --git a/package/network/services/dnsmasq/patches/010-Tweak-ICMP-ping-check-logic-for-DHCPv4.patch b/package/network/services/dnsmasq/patches/010-Tweak-ICMP-ping-check-logic-for-DHCPv4.patch deleted file mode 100644 index 571ff3683d..0000000000 --- a/package/network/services/dnsmasq/patches/010-Tweak-ICMP-ping-check-logic-for-DHCPv4.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 4bb68866a8aeb31db8100492bceae051e33be5d0 Mon Sep 17 00:00:00 2001 -From: Simon Kelley -Date: Thu, 15 Jun 2017 23:18:44 +0100 -Subject: [PATCH] Tweak ICMP ping check logic for DHCPv4. - ---- - src/rfc2131.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/rfc2131.c b/src/rfc2131.c -index 1c850e5..75792da 100644 ---- a/src/rfc2131.c -+++ b/src/rfc2131.c -@@ -1040,7 +1040,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index, - else if (have_config(config, CONFIG_DECLINED) && - difftime(now, config->decline_time) < (float)DECLINE_BACKOFF) - my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it was previously declined"), addrs); -- else if (!do_icmp_ping(now, config->addr, 0, loopback)) -+ else if ((!lease || lease->addr.s_addr != config->addr.s_addr) && !do_icmp_ping(now, config->addr, 0, loopback)) - my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it is in use by another host"), addrs); - else - conf = config->addr; --- -1.9.1 - diff --git a/package/network/services/dnsmasq/patches/011-Remove-ping-check-of-configured-DHCP-address.patch b/package/network/services/dnsmasq/patches/011-Remove-ping-check-of-configured-DHCP-address.patch deleted file mode 100644 index 67f90e172d..0000000000 --- a/package/network/services/dnsmasq/patches/011-Remove-ping-check-of-configured-DHCP-address.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 1d224949cced9e82440d00b3dbaf32c262bac2ff Mon Sep 17 00:00:00 2001 -From: Simon Kelley -Date: Sat, 8 Jul 2017 20:52:55 +0100 -Subject: [PATCH 1/2] Remove ping-check of configured DHCP address. - -This was added in 5ce3e76fbf89e942e8c54ef3e3389facf0d9067a but -it trips over too many buggy clients that leave an interface configured -even in DHCPDISCOVER case. ---- - src/rfc2131.c | 2 -- - 1 file changed, 2 deletions(-) - -diff --git a/src/rfc2131.c b/src/rfc2131.c -index 86230b4..785e15c 100644 ---- a/src/rfc2131.c -+++ b/src/rfc2131.c -@@ -1040,8 +1040,6 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index, - else if (have_config(config, CONFIG_DECLINED) && - difftime(now, config->decline_time) < (float)DECLINE_BACKOFF) - my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it was previously declined"), addrs); -- else if ((!lease || lease->addr.s_addr != config->addr.s_addr) && !do_icmp_ping(now, config->addr, 0, loopback)) -- my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it is in use by another host"), addrs); - else - conf = config->addr; - } --- -2.13.2 - diff --git a/package/network/services/dnsmasq/patches/020-Try-other-servers-if-first-returns-REFUSED-when-stri.patch b/package/network/services/dnsmasq/patches/020-Try-other-servers-if-first-returns-REFUSED-when-stri.patch deleted file mode 100644 index cdab607009..0000000000 --- a/package/network/services/dnsmasq/patches/020-Try-other-servers-if-first-returns-REFUSED-when-stri.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 9396752c115b3ab733fa476b30da73237e12e7ba Mon Sep 17 00:00:00 2001 -From: Hans Dedecker -Date: Tue, 27 Jun 2017 22:08:47 +0100 -Subject: [PATCH] Try other servers if first returns REFUSED when - --strict-order active. - -If a DNS server replies REFUSED for a given DNS query in strict order mode -no failover to the next DNS server is triggered as the failover logic only -covers non strict mode. -As a result the client will be returned the REFUSED reply without first -falling back to the secondary DNS server(s). - -Make failover support work as well for strict mode config in case REFUSED is -replied by deleting the strict order check and rely only on forwardall being -equal to 0 which is the case in non strict mode when a single server has been -contacted or when strict order mode has been configured. ---- - CHANGELOG | 4 ++++ - src/forward.c | 1 - - 2 files changed, 4 insertions(+), 1 deletion(-) - ---- a/src/forward.c -+++ b/src/forward.c -@@ -790,7 +790,6 @@ void reply_query(int fd, int family, tim - /* Note: if we send extra options in the EDNS0 header, we can't recreate - the query from the reply. */ - if (RCODE(header) == REFUSED && -- !option_bool(OPT_ORDER) && - forward->forwardall == 0 && - !(forward->flags & FREC_HAS_EXTRADATA)) - /* for broken servers, attempt to send to another one. */ diff --git a/package/network/services/dnsmasq/patches/025-backport-fix-CVE-2017-13704.patch b/package/network/services/dnsmasq/patches/025-backport-fix-CVE-2017-13704.patch deleted file mode 100644 index bba9a08060..0000000000 --- a/package/network/services/dnsmasq/patches/025-backport-fix-CVE-2017-13704.patch +++ /dev/null @@ -1,94 +0,0 @@ -From 63437ffbb58837b214b4b92cb1c54bc5f3279928 Mon Sep 17 00:00:00 2001 -From: Simon Kelley -Date: Wed, 6 Sep 2017 22:34:21 +0100 -Subject: [PATCH] Fix CVE-2017-13704, which resulted in a crash on a large DNS - query. - -A DNS query recieved by UDP which exceeds 512 bytes (or the EDNS0 packet size, -if different.) is enough to cause SIGSEGV. ---- - CHANGELOG | 7 +++++++ - src/auth.c | 5 ----- - src/forward.c | 8 ++++++++ - src/rfc1035.c | 5 ----- - 4 files changed, 15 insertions(+), 10 deletions(-) - -diff --git a/CHANGELOG b/CHANGELOG -index 3a640f3..7e65912 100644 ---- a/CHANGELOG -+++ b/CHANGELOG -@@ -17,6 +17,13 @@ version 2.78 - --strict-order active. Thanks to Hans Dedecker - for the patch - -+ Fix regression in 2.77, ironically added as a security -+ improvement, which resulted in a crash when a DNS -+ query exceeded 512 bytes (or the EDNS0 packet size, -+ if different.) Thanks to Christian Kujau, Arne Woerner -+ Juan Manuel Fernandez and Kevin Darbyshire-Bryant for -+ chasing this one down. CVE-2017-13704 applies. -+ - - version 2.77 - Generate an error when configured with a CNAME loop, -diff --git a/src/auth.c b/src/auth.c -index 2c24e16..7f95f98 100644 ---- a/src/auth.c -+++ b/src/auth.c -@@ -119,11 +119,6 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n - struct cname *a, *candidate; - unsigned int wclen; - -- /* Clear buffer beyond request to avoid risk of -- information disclosure. */ -- memset(((char *)header) + qlen, 0, -- (limit - ((char *)header)) - qlen); -- - if (ntohs(header->qdcount) == 0 || OPCODE(header) != QUERY ) - return 0; - -diff --git a/src/forward.c b/src/forward.c -index f22556a..e3fa94b 100644 ---- a/src/forward.c -+++ b/src/forward.c -@@ -1188,6 +1188,10 @@ void receive_query(struct listener *listen, time_t now) - (msg.msg_flags & MSG_TRUNC) || - (header->hb3 & HB3_QR)) - return; -+ -+ /* Clear buffer beyond request to avoid risk of -+ information disclosure. */ -+ memset(daemon->packet + n, 0, daemon->edns_pktsz - n); - - source_addr.sa.sa_family = listen->family; - -@@ -1688,6 +1692,10 @@ unsigned char *tcp_request(int confd, time_t now, - - if (size < (int)sizeof(struct dns_header)) - continue; -+ -+ /* Clear buffer beyond request to avoid risk of -+ information disclosure. */ -+ memset(payload + size, 0, 65536 - size); - - query_count++; - -diff --git a/src/rfc1035.c b/src/rfc1035.c -index 26f5301..af2fe46 100644 ---- a/src/rfc1035.c -+++ b/src/rfc1035.c -@@ -1223,11 +1223,6 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, - struct mx_srv_record *rec; - size_t len; - -- /* Clear buffer beyond request to avoid risk of -- information disclosure. */ -- memset(((char *)header) + qlen, 0, -- (limit - ((char *)header)) - qlen); -- - if (ntohs(header->ancount) != 0 || - ntohs(header->nscount) != 0 || - ntohs(header->qdcount) == 0 || --- -1.7.10.4 - diff --git a/package/network/services/dnsmasq/patches/030-fix-arcount-edns0-behaviour.patch b/package/network/services/dnsmasq/patches/030-fix-arcount-edns0-behaviour.patch deleted file mode 100644 index fffc8de6c4..0000000000 --- a/package/network/services/dnsmasq/patches/030-fix-arcount-edns0-behaviour.patch +++ /dev/null @@ -1,44 +0,0 @@ -From a3303e196e5d304ec955c4d63afb923ade66c6e8 Mon Sep 17 00:00:00 2001 -From: Simon Kelley -Date: Thu, 7 Sep 2017 20:45:00 +0100 -Subject: [PATCH] Don't return arcount=1 if EDNS0 RR won't fit in the packet. - -Omitting the EDNS0 RR but setting arcount gives a malformed packet. -Also, don't accept UDP packet size less than 512 in recieved EDNS0. ---- - src/edns0.c | 5 ++++- - src/forward.c | 2 ++ - 2 files changed, 6 insertions(+), 1 deletion(-) - -diff --git a/src/edns0.c b/src/edns0.c -index 3fde17f..f5b798c 100644 ---- a/src/edns0.c -+++ b/src/edns0.c -@@ -208,7 +208,10 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l - free(buff); - p += rdlen; - } -- header->arcount = htons(ntohs(header->arcount) + 1); -+ -+ /* Only bump arcount if RR is going to fit */ -+ if (((ssize_t)optlen) <= (limit - (p + 4))) -+ header->arcount = htons(ntohs(header->arcount) + 1); - } - - if (((ssize_t)optlen) > (limit - (p + 4))) -diff --git a/src/forward.c b/src/forward.c -index e3fa94b..942b02d 100644 ---- a/src/forward.c -+++ b/src/forward.c -@@ -1412,6 +1412,8 @@ void receive_query(struct listener *listen, time_t now) - defaults to 512 */ - if (udp_size > daemon->edns_pktsz) - udp_size = daemon->edns_pktsz; -+ else if (udp_size < PACKETSZ) -+ udp_size = PACKETSZ; /* Sanity check - can't reduce below default. RFC 6891 6.2.3 */ - } - - #ifdef HAVE_AUTH --- -1.7.10.4 - diff --git a/package/network/services/dnsmasq/patches/230-fix-poll-h-include-warning-on-musl.patch b/package/network/services/dnsmasq/patches/230-fix-poll-h-include-warning-on-musl.patch index 19300f7d66..37b11abc1d 100644 --- a/package/network/services/dnsmasq/patches/230-fix-poll-h-include-warning-on-musl.patch +++ b/package/network/services/dnsmasq/patches/230-fix-poll-h-include-warning-on-musl.patch @@ -7,7 +7,7 @@ Signed-off-by: Kevin Darbyshire-Bryant --- a/src/dnsmasq.h +++ b/src/dnsmasq.h -@@ -82,7 +82,7 @@ typedef unsigned long long u64; +@@ -88,7 +88,7 @@ typedef unsigned long long u64; #if defined(HAVE_SOLARIS_NETWORK) # include #endif diff --git a/package/network/services/dnsmasq/patches/240-ubus.patch b/package/network/services/dnsmasq/patches/240-ubus.patch new file mode 100644 index 0000000000..2d37b5d2fd --- /dev/null +++ b/package/network/services/dnsmasq/patches/240-ubus.patch @@ -0,0 +1,126 @@ +--- a/src/dnsmasq.c ++++ b/src/dnsmasq.c +@@ -19,6 +19,8 @@ + + #include "dnsmasq.h" + ++#include ++ + struct daemon *daemon; + + static volatile pid_t pid = 0; +@@ -32,6 +34,62 @@ 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); + ++static struct ubus_context *ubus; ++static struct blob_buf b; ++ ++static struct ubus_object_type ubus_object_type = { ++ .name = "dnsmasq", ++}; ++ ++static struct ubus_object ubus_object = { ++ .name = "dnsmasq", ++ .type = &ubus_object_type, ++}; ++ ++void ubus_event_bcast(const char *type, const char *mac, const char *ip, const char *name) ++{ ++ if (!ubus || !ubus_object.has_subscribers) ++ return; ++ ++ blob_buf_init(&b, 0); ++ if (mac) ++ blobmsg_add_string(&b, "mac", mac); ++ if (ip) ++ blobmsg_add_string(&b, "ip", ip); ++ if (name) ++ blobmsg_add_string(&b, "name", name); ++ ubus_notify(ubus, &ubus_object, type, b.head, -1); ++} ++ ++static void set_ubus_listeners(void) ++{ ++ if (!ubus) ++ return; ++ ++ poll_listen(ubus->sock.fd, POLLIN); ++ poll_listen(ubus->sock.fd, POLLERR); ++ poll_listen(ubus->sock.fd, POLLHUP); ++} ++ ++static void check_ubus_listeners() ++{ ++ if (!ubus) { ++ ubus = ubus_connect(NULL); ++ if (ubus) ++ ubus_add_object(ubus, &ubus_object); ++ else ++ return; ++ } ++ ++ if (poll_check(ubus->sock.fd, POLLIN)) ++ ubus_handle_event(ubus); ++ ++ if (poll_check(ubus->sock.fd, POLLHUP)) { ++ ubus_free(ubus); ++ ubus = NULL; ++ } ++} ++ + int main (int argc, char **argv) + { + int bind_fallback = 0; +@@ -911,6 +969,7 @@ int main (int argc, char **argv) + set_dbus_listeners(); + #endif + ++ set_ubus_listeners(); + #ifdef HAVE_DHCP + if (daemon->dhcp || daemon->relay4) + { +@@ -1041,6 +1100,8 @@ int main (int argc, char **argv) + check_dbus_listeners(); + #endif + ++ check_ubus_listeners(); ++ + check_dns_listeners(now); + + #ifdef HAVE_TFTP +--- a/Makefile ++++ b/Makefile +@@ -85,7 +85,7 @@ all : $(BUILDDIR) + @cd $(BUILDDIR) && $(MAKE) \ + top="$(top)" \ + build_cflags="$(version) $(dbus_cflags) $(idn2_cflags) $(idn_cflags) $(ct_cflags) $(lua_cflags) $(nettle_cflags)" \ +- build_libs="$(dbus_libs) $(idn2_libs) $(idn_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) $(gmp_libs)" \ ++ build_libs="$(dbus_libs) $(idn2_libs) $(idn_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) $(gmp_libs) -lubox -lubus" \ + -f $(top)/Makefile dnsmasq + + mostly_clean : +--- a/src/dnsmasq.h ++++ b/src/dnsmasq.h +@@ -1397,6 +1397,8 @@ void emit_dbus_signal(int action, struct + # endif + #endif + ++void ubus_event_bcast(const char *type, const char *mac, const char *ip, const char *name); ++ + /* ipset.c */ + #ifdef HAVE_IPSET + void ipset_init(void); +--- a/src/rfc2131.c ++++ b/src/rfc2131.c +@@ -1621,6 +1621,10 @@ static void log_packet(char *type, void + daemon->namebuff, + string ? string : "", + err ? err : ""); ++ if (!strcmp(type, "DHCPACK")) ++ ubus_event_bcast("dhcp.ack", addr ? inet_ntoa(a) : NULL, daemon->namebuff, string ? string : NULL); ++ else if (!strcmp(type, "DHCPRELEASE")) ++ ubus_event_bcast("dhcp.release", addr ? inet_ntoa(a) : NULL, daemon->namebuff, string ? string : NULL); + } + + static void log_options(unsigned char *start, u32 xid) -- 2.25.1