diff --git a/package/network/services/dnsmasq/Makefile b/package/network/services/dnsmasq/Makefile index 90a81b5f65..950de69b95 100644 --- a/package/network/services/dnsmasq/Makefile +++ b/package/network/services/dnsmasq/Makefile @@ -8,13 +8,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=dnsmasq -PKG_UPSTREAM_VERSION:=2.85 +PKG_UPSTREAM_VERSION:=2.87 PKG_VERSION:=$(subst test,~~test,$(subst rc,~rc,$(PKG_UPSTREAM_VERSION))) -PKG_RELEASE:=$(AUTORELEASE) +PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_UPSTREAM_VERSION).tar.xz -PKG_SOURCE_URL:=http://thekelleys.org.uk/dnsmasq -PKG_HASH:=ad98d3803df687e5b938080f3d25c628fe41c878752d03fbc6199787fee312fa +PKG_SOURCE_URL:=https://thekelleys.org.uk/dnsmasq/ +PKG_HASH:=0228c0364a7f2356fd7e7f1549937cbf3099a78d3b2eb1ba5bb0c31e2b89de7a PKG_LICENSE:=GPL-2.0 PKG_LICENSE_FILES:=COPYING @@ -180,6 +180,7 @@ define Package/dnsmasq/install $(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/ + $(INSTALL_DATA) ./files/dnsmasqsec_hotplug_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 endef diff --git a/package/network/services/dnsmasq/files/dhcp-script.sh b/package/network/services/dnsmasq/files/dhcp-script.sh index 470097bf6b..86032694c1 100755 --- a/package/network/services/dnsmasq/files/dhcp-script.sh +++ b/package/network/services/dnsmasq/files/dhcp-script.sh @@ -2,52 +2,45 @@ [ -f "$USER_DHCPSCRIPT" ] && . "$USER_DHCPSCRIPT" "$@" -. /usr/share/libubox/jshn.sh - -json_init -json_add_array env -hotplugobj="" - -case "$1" in - add | del | old | arp-add | arp-del) - json_add_string "" "MACADDR=$2" - json_add_string "" "IPADDR=$3" - ;; -esac - case "$1" in add) - json_add_string "" "ACTION=add" - json_add_string "" "HOSTNAME=$4" - hotplugobj="dhcp" + export ACTION="add" + export MACADDR="$2" + export IPADDR="$3" + export HOSTNAME="$4" + exec /sbin/hotplug-call dhcp ;; del) - json_add_string "" "ACTION=remove" - json_add_string "" "HOSTNAME=$4" - hotplugobj="dhcp" + export ACTION="remove" + export MACADDR="$2" + export IPADDR="$3" + export HOSTNAME="$4" + exec /sbin/hotplug-call dhcp ;; old) - json_add_string "" "ACTION=update" - json_add_string "" "HOSTNAME=$4" - hotplugobj="dhcp" + export ACTION="update" + export MACADDR="$2" + export IPADDR="$3" + export HOSTNAME="$4" + exec /sbin/hotplug-call dhcp ;; arp-add) - json_add_string "" "ACTION=add" - hotplugobj="neigh" + export ACTION="add" + export MACADDR="$2" + export IPADDR="$3" + exec /sbin/hotplug-call neigh ;; arp-del) - json_add_string "" "ACTION=remove" - hotplugobj="neigh" + export ACTION="remove" + export MACADDR="$2" + export IPADDR="$3" + exec /sbin/hotplug-call neigh ;; tftp) - json_add_string "" "ACTION=add" - json_add_string "" "TFTP_SIZE=$2" - json_add_string "" "TFTP_ADDR=$3" - json_add_string "" "TFTP_PATH=$4" - hotplugobj="tftp" + export ACTION="add" + export TFTP_SIZE="$2" + export TFTP_ADDR="$3" + export TFTP_PATH="$4" + exec /sbin/hotplug-call tftp ;; esac - -json_close_array env - -[ -n "$hotplugobj" ] && ubus call hotplug.${hotplugobj} call "$(json_dump)" diff --git a/package/network/services/dnsmasq/files/dhcp.conf b/package/network/services/dnsmasq/files/dhcp.conf index c76015f2b8..8c42ef782e 100644 --- a/package/network/services/dnsmasq/files/dhcp.conf +++ b/package/network/services/dnsmasq/files/dhcp.conf @@ -21,7 +21,6 @@ config dnsmasq #list bogusnxdomain '64.94.110.11' option localservice 1 # disable to allow DNS requests from non-local subnets option ednspacket_max 1232 - option filter_aaaa 0 config dhcp lan option interface lan diff --git a/package/network/services/dnsmasq/files/dnsmasq.init b/package/network/services/dnsmasq/files/dnsmasq.init index f62bc836cf..b47c5b9e01 100644 --- a/package/network/services/dnsmasq/files/dnsmasq.init +++ b/package/network/services/dnsmasq/files/dnsmasq.init @@ -173,6 +173,10 @@ append_ipset() { xappend "--ipset=$1" } +append_connmark_allowlist() { + xappend "--connmark-allowlist=$1" +} + append_interface() { network_get_device ifname "$1" || ifname="$1" xappend "--interface=$ifname" @@ -193,12 +197,12 @@ ismounted() { for dirname in $EXTRA_MOUNT ; do case "$filename" in "${dirname}/"* | "${dirname}" ) - return 1 + return 0 ;; esac done - return 0 + return 1 } append_addnhosts() { @@ -237,7 +241,7 @@ dhcp_subscrid_add() { config_get subscriberid "$cfg" subscriberid [ -n "$subscriberid" ] || return 0 - xappend "--dhcp-subscrid=$networkid,$subscriberid" + xappend "--dhcp-subscrid=set:$networkid,$subscriberid" config_get_bool force "$cfg" force 0 @@ -253,7 +257,7 @@ dhcp_remoteid_add() { config_get remoteid "$cfg" remoteid [ -n "$remoteid" ] || return 0 - xappend "--dhcp-remoteid=$networkid,$remoteid" + xappend "--dhcp-remoteid=set:$networkid,$remoteid" config_get_bool force "$cfg" force 0 @@ -270,7 +274,7 @@ dhcp_circuitid_add() { config_get circuitid "$cfg" circuitid [ -n "$circuitid" ] || return 0 - xappend "--dhcp-circuitid=$networkid,$circuitid" + xappend "--dhcp-circuitid=set:$networkid,$circuitid" config_get_bool force "$cfg" force 0 @@ -286,7 +290,7 @@ dhcp_userclass_add() { config_get userclass "$cfg" userclass [ -n "$userclass" ] || return 0 - xappend "--dhcp-userclass=$networkid,$userclass" + xappend "--dhcp-userclass=set:$networkid,$userclass" config_get_bool force "$cfg" force 0 @@ -303,7 +307,7 @@ dhcp_vendorclass_add() { config_get vendorclass "$cfg" vendorclass [ -n "$vendorclass" ] || return 0 - xappend "--dhcp-vendorclass=$networkid,$vendorclass" + xappend "--dhcp-vendorclass=set:$networkid,$vendorclass" config_get_bool force "$cfg" force 0 @@ -319,7 +323,7 @@ dhcp_match_add() { config_get match "$cfg" match [ -n "$match" ] || return 0 - xappend "--dhcp-match=$networkid,$match" + xappend "--dhcp-match=set:$networkid,$match" config_get_bool force "$cfg" force 0 @@ -328,7 +332,7 @@ dhcp_match_add() { dhcp_host_add() { local cfg="$1" - local hosttag nametime addrs duids macs tags + local hosttag nametime addrs duids macs tags mtags config_get_bool force "$cfg" force 0 @@ -353,6 +357,11 @@ dhcp_host_add() { config_get duid "$cfg" duid config_get tag "$cfg" tag + add_tag() { + mtags="${mtags}tag:$1," + } + config_list_foreach "$cfg" match_tag add_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 @@ -390,9 +399,9 @@ dhcp_host_add() { if [ $DNSMASQ_DHCP_VER -eq 6 ]; then addrs="${ip:+,$ip}${hostid:+,[::$hostid]}" - xappend "--dhcp-host=$macs${duids:+,$duids}$hosttag$addrs$nametime" + xappend "--dhcp-host=$mtags$macs${duids:+,$duids}$hosttag$addrs$nametime" else - xappend "--dhcp-host=$macs$hosttag${ip:+,$ip}$nametime" + xappend "--dhcp-host=$mtags$macs$hosttag${ip:+,$ip}$nametime" fi } @@ -811,7 +820,7 @@ dnsmasq_ipset_add() { 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 @@ -825,12 +834,14 @@ dnsmasq_start() CONFIGFILE_TMP="${CONFIGFILE}.$$" HOSTFILE="${BASEHOSTFILE}.${cfg}" HOSTFILE_TMP="${HOSTFILE}.$$" + HOSTFILE_DIR="$(dirname "$HOSTFILE")" BASEDHCPSTAMPFILE_CFG="${BASEDHCPSTAMPFILE}.${cfg}" # before we can call xappend + umask u=rwx,g=rx,o=rx mkdir -p /var/run/dnsmasq/ mkdir -p $(dirname $CONFIGFILE) - mkdir -p $(dirname $HOSTFILE) + mkdir -p "$HOSTFILE_DIR" mkdir -p /var/lib/misc chown dnsmasq:dnsmasq /var/run/dnsmasq @@ -920,13 +931,9 @@ dnsmasq_start() append_bool "$cfg" noping "--no-ping" append_bool "$cfg" rapidcommit "--dhcp-rapid-commit" append_bool "$cfg" scriptarp "--script-arp" - append_bool "$cfg" filter_aaaa "--filter-aaaa" - append_bool "$cfg" filter_https "--filter-https" - append_bool "$cfg" filter_unknown "--filter-unknown" 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" @@ -942,6 +949,14 @@ dnsmasq_start() 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 + [ "$connmark_allowlist_enable" -gt 0 ] && { + append_parm "$cfg" "connmark_allowlist_enable" "--connmark-allowlist-enable" + config_list_foreach "$cfg" "connmark_allowlist" append_connmark_allowlist + } + [ -n "$BOOT" ] || { config_list_foreach "$cfg" "interface" append_interface config_list_foreach "$cfg" "notinterface" append_notinterface @@ -951,13 +966,20 @@ dnsmasq_start() xappend "--addn-hosts=$HOSTFILE" append EXTRA_MOUNT "$HOSTFILE" else - xappend "--addn-hosts=$(dirname $HOSTFILE)" - append EXTRA_MOUNT "$(dirname $HOSTFILE)" + xappend "--addn-hosts=$HOSTFILE_DIR" + append EXTRA_MOUNT "$HOSTFILE_DIR" fi 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" @@ -1141,20 +1163,29 @@ dnsmasq_start() [ -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 + case "$logfacility" in */*) + [ ! -e "$logfacility" ] && touch "$logfacility" + procd_add_jail_mount_rw "$logfacility" + esac procd_close_instance config_get_bool dns_redirect "$cfg" dns_redirect 0 config_get dns_port "$cfg" port 53 [ $dns_redirect = 1 ] && { - ip6tables -t nat -w -A PREROUTING -m comment --comment "Dnsmasq" -p udp --dport 53 -j REDIRECT --to-ports $dns_port 2>/dev/null iptables -t nat -w -A PREROUTING -m comment --comment "Dnsmasq" -p udp --dport 53 -j REDIRECT --to-ports $dns_port + ip6tables -t nat -w -A PREROUTING -m comment --comment "Dnsmasq" -p udp --dport 53 -j REDIRECT --to-ports $dns_port 2>/dev/null } } @@ -1175,7 +1206,7 @@ dnsmasq_stop() iptables_clear() { - for ipt in "ip6tables -t nat -w" "iptables -t nat -w"; do + for ipt in "iptables -t nat -w" "ip6tables -t nat -w"; do for i in $(seq 1 $($ipt -nL PREROUTING | grep -c "Dnsmasq")); do local index=$($ipt --line-number -nL PREROUTING | grep "Dnsmasq" | head -1 | awk '{print $1}') $ipt -D PREROUTING $index 2>/dev/null diff --git a/package/network/services/dnsmasq/files/dnsmasq_acl.json b/package/network/services/dnsmasq/files/dnsmasq_acl.json index 47d7c29302..00ec7d0f03 100644 --- a/package/network/services/dnsmasq/files/dnsmasq_acl.json +++ b/package/network/services/dnsmasq/files/dnsmasq_acl.json @@ -1,12 +1,4 @@ { "user": "dnsmasq", - "publish": [ "dnsmasq" ], - "access": { - "hotplug.dhcp": { - "methods": [ "call" ] - }, - "hotplug.neigh": { - "methods": [ "call" ] - } - } + "publish": [ "dnsmasq" ] } diff --git a/package/network/services/dnsmasq/files/dnsmasqsec.hotplug b/package/network/services/dnsmasq/files/dnsmasqsec.hotplug index a59148600b..71f5e68b2d 100644 --- a/package/network/services/dnsmasq/files/dnsmasqsec.hotplug +++ b/package/network/services/dnsmasq/files/dnsmasqsec.hotplug @@ -5,7 +5,6 @@ TIMEVALIDFILE="/var/state/dnsmasqsec" [ -f "$TIMEVALIDFILE" ] || { echo "ntpd says time is valid" >$TIMEVALIDFILE /etc/init.d/dnsmasq enabled && { - initscript=dnsmasq . /lib/functions/procd.sh procd_send_signal dnsmasq '*' INT } diff --git a/package/network/services/dnsmasq/files/dnsmasqsec_hotplug_acl.json b/package/network/services/dnsmasq/files/dnsmasqsec_hotplug_acl.json new file mode 100644 index 0000000000..861ecbe034 --- /dev/null +++ b/package/network/services/dnsmasq/files/dnsmasqsec_hotplug_acl.json @@ -0,0 +1,8 @@ +{ + "user": "ntp", + "access": { + "service": { + "methods": [ "signal" ] + } + } +} diff --git a/package/network/services/dnsmasq/patches/100-remove-old-runtime-kernel-support.patch b/package/network/services/dnsmasq/patches/100-remove-old-runtime-kernel-support.patch index b601bce1a9..b1b134a98c 100644 --- a/package/network/services/dnsmasq/patches/100-remove-old-runtime-kernel-support.patch +++ b/package/network/services/dnsmasq/patches/100-remove-old-runtime-kernel-support.patch @@ -13,7 +13,7 @@ Signed-off-by: Kevin Darbyshire-Bryant --- 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 --- a/src/dnsmasq.h +++ b/src/dnsmasq.h -@@ -1144,7 +1144,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 #elif defined(HAVE_BSD_NETWORK) int dhcp_raw_fd, dhcp_icmp_fd, routefd; #endif -@@ -1326,9 +1326,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 my_syslog(LOG_ERR, _("failed to update ipset %s: %s"), setname, strerror(errno)); --- a/src/util.c +++ b/src/util.c -@@ -786,22 +786,3 @@ int wildcard_matchn(const char* wildcard +@@ -833,22 +833,3 @@ int wildcard_matchn(const char* wildcard return (!num) || (*wildcard == *match); } diff --git a/package/network/services/dnsmasq/patches/200-ubus_dns.patch b/package/network/services/dnsmasq/patches/200-ubus_dns.patch new file mode 100644 index 0000000000..c4cc1df207 --- /dev/null +++ b/package/network/services/dnsmasq/patches/200-ubus_dns.patch @@ -0,0 +1,282 @@ +--- a/src/dnsmasq.h ++++ b/src/dnsmasq.h +@@ -1598,14 +1598,26 @@ void emit_dbus_signal(int action, struct + + /* ubus.c */ + #ifdef HAVE_UBUS ++struct blob_attr; ++typedef void (*ubus_dns_notify_cb)(struct blob_attr *msg, void *priv); ++ + char *ubus_init(void); + void set_ubus_listeners(void); + void check_ubus_listeners(void); ++void drop_ubus_listeners(void); ++struct blob_buf *ubus_dns_notify_prepare(void); ++int ubus_dns_notify(const char *type, ubus_dns_notify_cb cb, void *priv); + void ubus_event_bcast(const char *type, const char *mac, const char *ip, const char *name, const char *interface); + # ifdef HAVE_CONNTRACK + void ubus_event_bcast_connmark_allowlist_refused(u32 mark, const char *name); + void ubus_event_bcast_connmark_allowlist_resolved(u32 mark, const char *pattern, const char *ip, u32 ttl); + # endif ++#else ++struct blob_buf; ++static inline struct blob_buf *ubus_dns_notify_prepare(void) ++{ ++ return NULL; ++} + #endif + + /* ipset.c */ +--- a/src/rfc1035.c ++++ b/src/rfc1035.c +@@ -13,8 +13,10 @@ + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +- + #include "dnsmasq.h" ++#ifdef HAVE_UBUS ++#include ++#endif + + int extract_name(struct dns_header *header, size_t plen, unsigned char **pp, + char *name, int isExtract, int extrabytes) +@@ -394,9 +396,64 @@ static int private_net6(struct in6_addr + ((u32 *)a)[0] == htonl(0x20010db8); /* RFC 6303 4.6 */ + } + ++#ifdef HAVE_UBUS ++static void ubus_dns_doctor_cb(struct blob_attr *msg, void *priv) ++{ ++ static const struct blobmsg_policy policy = { ++ .name = "address", ++ .type = BLOBMSG_TYPE_STRING, ++ }; ++ struct blob_attr *val; ++ char **dest = priv; ++ ++ blobmsg_parse(&policy, 1, &val, blobmsg_data(msg), blobmsg_data_len(msg)); ++ if (val) ++ *dest = blobmsg_get_string(val); ++} ++ ++static int ubus_dns_doctor(const char *name, int ttl, void *p, int af) ++{ ++ struct blob_buf *b; ++ char *addr; ++ ++ if (!name) ++ return 0; ++ ++ b = ubus_dns_notify_prepare(); ++ if (!b) ++ return 0; ++ ++ blobmsg_add_string(b, "name", name); ++ ++ blobmsg_add_u32(b, "ttl", ttl); ++ ++ blobmsg_add_string(b, "type", af == AF_INET6 ? "AAAA" : "A"); ++ ++ addr = blobmsg_alloc_string_buffer(b, "address", INET6_ADDRSTRLEN); ++ if (!addr) ++ return 0; ++ ++ inet_ntop(af, p, addr, INET6_ADDRSTRLEN); ++ blobmsg_add_string_buffer(b); ++ ++ addr = NULL; ++ ubus_dns_notify("dns_result", ubus_dns_doctor_cb, &addr); ++ ++ if (!addr) ++ return 0; ++ ++ return inet_pton(af, addr, p) == 1; ++} ++#else ++static int ubus_dns_doctor(const char *name, int ttl, void *p, int af) ++{ ++ return 0; ++} ++#endif ++ + static unsigned char *do_doctor(unsigned char *p, int count, struct dns_header *header, size_t qlen, int *doctored) + { +- int i, qtype, qclass, rdlen; ++ int i, qtype, qclass, rdlen, ttl; + + for (i = count; i != 0; i--) + { +@@ -405,7 +462,7 @@ static unsigned char *do_doctor(unsigned + + GETSHORT(qtype, p); + GETSHORT(qclass, p); +- p += 4; /* ttl */ ++ GETLONG(ttl, p); /* ttl */ + GETSHORT(rdlen, p); + + if (qclass == C_IN && qtype == T_A) +@@ -416,6 +473,9 @@ static unsigned char *do_doctor(unsigned + if (!CHECK_LEN(header, p, qlen, INADDRSZ)) + return 0; + ++ if (ubus_dns_doctor(daemon->namebuff, ttl, p, AF_INET)) ++ *doctored = 1; ++ + /* alignment */ + memcpy(&addr, p, INADDRSZ); + +@@ -433,13 +493,22 @@ static unsigned char *do_doctor(unsigned + addr.s_addr &= ~doctor->mask.s_addr; + addr.s_addr |= (doctor->out.s_addr & doctor->mask.s_addr); + /* Since we munged the data, the server it came from is no longer authoritative */ +- header->hb3 &= ~HB3_AA; + *doctored = 1; + memcpy(p, &addr, INADDRSZ); + break; + } + } +- ++ else if (qclass == C_IN && qtype == T_AAAA) ++ { ++ if (!CHECK_LEN(header, p, qlen, IN6ADDRSZ)) ++ return 0; ++ ++ if (ubus_dns_doctor(daemon->namebuff, ttl, p, AF_INET6)) ++ *doctored = 1; ++ } ++ ++ if (*doctored) ++ header->hb3 &= ~HB3_AA; + if (!ADD_RDLEN(header, p, qlen, rdlen)) + return 0; /* bad packet */ + } +@@ -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. */ +- if (daemon->doctors || option_bool(OPT_DNSSEC_VALID)) ++ if (daemon->doctors || option_bool(OPT_DNSSEC_VALID) || ubus_dns_notify_prepare()) + { + searched_soa = 1; + ttl = find_soa(header, qlen, doctored); +--- a/src/ubus.c ++++ b/src/ubus.c +@@ -72,6 +72,13 @@ static struct ubus_object ubus_object = + .subscribe_cb = ubus_subscribe_cb, + }; + ++static struct ubus_object_type ubus_dns_object_type = ++ { .name = "dnsmasq.dns" }; ++ ++static struct ubus_object ubus_dns_object = { ++ .type = &ubus_dns_object_type, ++}; ++ + static void ubus_subscribe_cb(struct ubus_context *ctx, struct ubus_object *obj) + { + (void)ctx; +@@ -105,13 +112,21 @@ static void ubus_disconnect_cb(struct ub + char *ubus_init() + { + struct ubus_context *ubus = NULL; ++ char *dns_name; + int ret = 0; + + if (!(ubus = ubus_connect(NULL))) + return NULL; + ++ dns_name = whine_malloc(strlen(daemon->ubus_name) + 5); ++ sprintf(dns_name, "%s.dns", daemon->ubus_name); ++ + ubus_object.name = daemon->ubus_name; ++ ubus_dns_object.name = dns_name; ++ + ret = ubus_add_object(ubus, &ubus_object); ++ if (!ret) ++ ret = ubus_add_object(ubus, &ubus_dns_object); + if (ret) + { + ubus_destroy(ubus); +@@ -181,6 +196,17 @@ void check_ubus_listeners() + } \ + } while (0) + ++void drop_ubus_listeners() ++{ ++ struct ubus_context *ubus = (struct ubus_context *)daemon->ubus; ++ ++ if (!ubus) ++ return; ++ ++ ubus_free(ubus); ++ ubus = NULL; ++} ++ + static int ubus_handle_metrics(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +@@ -328,6 +354,50 @@ fail: + } \ + } while (0) + ++struct blob_buf *ubus_dns_notify_prepare(void) ++{ ++ struct ubus_context *ubus = (struct ubus_context *)daemon->ubus; ++ ++ if (!ubus || !ubus_dns_object.has_subscribers) ++ return NULL; ++ ++ blob_buf_init(&b, 0); ++ return &b; ++} ++ ++struct ubus_dns_notify_req { ++ struct ubus_notify_request req; ++ ubus_dns_notify_cb cb; ++ void *priv; ++}; ++ ++static void dns_notify_cb(struct ubus_notify_request *req, int type, struct blob_attr *msg) ++{ ++ struct ubus_dns_notify_req *dreq = container_of(req, struct ubus_dns_notify_req, req); ++ ++ dreq->cb(msg, dreq->priv); ++} ++ ++int ubus_dns_notify(const char *type, ubus_dns_notify_cb cb, void *priv) ++{ ++ struct ubus_context *ubus = (struct ubus_context *)daemon->ubus; ++ struct ubus_dns_notify_req dreq; ++ int ret; ++ ++ if (!ubus || !ubus_dns_object.has_subscribers) ++ return 0; ++ ++ ret = ubus_notify_async(ubus, &ubus_dns_object, type, b.head, &dreq.req); ++ if (ret) ++ return ret; ++ ++ dreq.req.data_cb = dns_notify_cb; ++ dreq.cb = cb; ++ dreq.priv = priv; ++ ++ return ubus_complete_request(ubus, &dreq.req.req, 100); ++} ++ + void ubus_event_bcast(const char *type, const char *mac, const char *ip, const char *name, const char *interface) + { + struct ubus_context *ubus = (struct ubus_context *)daemon->ubus; +--- a/src/dnsmasq.c ++++ b/src/dnsmasq.c +@@ -1998,6 +1998,10 @@ static void check_dns_listeners(time_t n + daemon->pipe_to_parent = pipefd[1]; + } + ++#ifdef HAVE_UBUS ++ drop_ubus_listeners(); ++#endif ++ + /* start with no upstream connections. */ + for (s = daemon->servers; s; s = s->next) + s->tcpfd = -1; diff --git a/package/network/services/dnsmasq/patches/910-mini-ttl.patch b/package/network/services/dnsmasq/patches/910-mini-ttl.patch deleted file mode 100644 index fd92ba12ac..0000000000 --- a/package/network/services/dnsmasq/patches/910-mini-ttl.patch +++ /dev/null @@ -1,80 +0,0 @@ ---- a/src/dnsmasq.h -+++ b/src/dnsmasq.h -@@ -1116,7 +1116,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_PXE_VENDOR 361 - #define LOPT_DYNHOST 362 - #define LOPT_LOG_DEBUG 363 -+#define LOPT_MINTTL 364 - - #ifdef HAVE_GETOPT_LONG - static const struct option opts[] = -@@ -292,6 +293,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 }, -@@ -425,6 +427,7 @@ static struct { - { 't', ARG_ONE, "", gettext_noop("Specify default target in an MX record."), NULL }, - { 'T', ARG_ONE, "", gettext_noop("Specify time-to-live in seconds for replies from /etc/hosts."), NULL }, - { LOPT_NEGTTL, ARG_ONE, "", gettext_noop("Specify time-to-live in seconds for negative caching."), NULL }, -+ { LOPT_MINTTL, ARG_ONE, "", gettext_noop("Specify time-to-live in seconds for minimum TTL to send to clients."), NULL }, - { LOPT_MAXTTL, ARG_ONE, "", gettext_noop("Specify time-to-live in seconds for maximum TTL to send to clients."), NULL }, - { LOPT_MAXCTTL, ARG_ONE, "", gettext_noop("Specify time-to-live ceiling for cache."), NULL }, - { LOPT_MINCTTL, ARG_ONE, "", gettext_noop("Specify time-to-live floor for cache."), NULL }, -@@ -3047,6 +3050,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 */ -@@ -3058,6 +3062,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 -@@ -704,7 +704,7 @@ int extract_addresses(struct dns_header - 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 */ - -@@ -712,6 +712,14 @@ int extract_addresses(struct dns_header - 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); diff --git a/package/network/services/dnsmasq/patches/911-dnsmasq-filter-aaaa+https+unknown.patch b/package/network/services/dnsmasq/patches/911-dnsmasq-filter-aaaa+https+unknown.patch deleted file mode 100644 index ce2141f208..0000000000 --- a/package/network/services/dnsmasq/patches/911-dnsmasq-filter-aaaa+https+unknown.patch +++ /dev/null @@ -1,143 +0,0 @@ -diff --git a/src/cache.c b/src/cache.c -index 8add610..c94132e 100644 ---- a/src/cache.c -+++ b/src/cache.c -@@ -66,6 +66,7 @@ static const struct { - { 52, "TLSA" }, - { 53, "SMIMEA" }, - { 55, "HIP" }, -+ { 65, "HTTPS"}, - { 249, "TKEY" }, - { 250, "TSIG" }, - { 251, "IXFR" }, -@@ -1805,6 +1806,20 @@ char *record_source(unsigned int index) - return ""; - } - -+// patch: function returns integer 1 if query type is unknown. -+// known types are defined in cache.c:typestr:36. -+int is_query_type_unknown(unsigned short type) -+{ -+ unsigned int i; -+ for (i = 0; i < (sizeof(typestr)/sizeof(typestr[0])); i++) -+ if (typestr[i].type == type) -+ { -+ return 0; -+ } -+ return 1; -+} -+// end of patch -+ - char *querystr(char *desc, unsigned short type) - { - unsigned int i; -diff --git a/src/dns-protocol.h b/src/dns-protocol.h -index 496a4bb..ed0d64a 100644 ---- a/src/dns-protocol.h -+++ b/src/dns-protocol.h -@@ -71,6 +71,7 @@ - #define T_NSEC 47 - #define T_DNSKEY 48 - #define T_NSEC3 50 -+#define T_HTTPS 65 - #define T_TKEY 249 - #define T_TSIG 250 - #define T_AXFR 252 -diff --git a/src/dnsmasq.h b/src/dnsmasq.h -index 8674823..d067741 100644 ---- a/src/dnsmasq.h -+++ b/src/dnsmasq.h -@@ -275,7 +275,10 @@ struct event_desc { - #define OPT_SINGLE_PORT 60 - #define OPT_LEASE_RENEW 61 - #define OPT_LOG_DEBUG 62 --#define OPT_LAST 63 -+#define OPT_FILTER_AAAA 63 -+#define OPT_FILTER_HTTPS 64 -+#define OPT_FILTER_UNKNOWN 65 -+#define OPT_LAST 66 - - #define OPTION_BITS (sizeof(unsigned int)*8) - #define OPTION_SIZE ( (OPT_LAST/OPTION_BITS)+((OPT_LAST%OPTION_BITS)!=0) ) -@@ -1247,6 +1250,10 @@ void cache_init(void); - void next_uid(struct crec *crecp); - void log_query(unsigned int flags, char *name, union all_addr *addr, char *arg); - char *record_source(unsigned int index); -+// patch: function returns integer 1 if query type is unknown -+// known types are defined in cache.c:typestr:36. -+int is_query_type_unknown(unsigned short type); -+// end of patch - char *querystr(char *desc, unsigned short type); - int cache_find_non_terminal(char *name, time_t now); - struct crec *cache_find_by_addr(struct crec *crecp, -diff --git a/src/option.c b/src/option.c -index ffce9fc..3993c10 100644 ---- a/src/option.c -+++ b/src/option.c -@@ -174,6 +174,9 @@ struct myoption { - #define LOPT_DYNHOST 362 - #define LOPT_LOG_DEBUG 363 - #define LOPT_MINTTL 364 -+#define LOPT_FILTER_AAAA 365 -+#define LOPT_FILTER_HTTPS 366 -+#define LOPT_FILTER_UNKNOWN 367 - - #ifdef HAVE_GETOPT_LONG - static const struct option opts[] = -@@ -353,6 +356,9 @@ static const struct myoption opts[] = - { "dhcp-ignore-clid", 0, 0, LOPT_IGNORE_CLID }, - { "dynamic-host", 1, 0, LOPT_DYNHOST }, - { "log-debug", 0, 0, LOPT_LOG_DEBUG }, -+ { "filter-aaaa", 0, 0, LOPT_FILTER_AAAA }, -+ { "filter-https", 0, 0, LOPT_FILTER_HTTPS }, -+ { "filter-unknown", 0, 0, LOPT_FILTER_UNKNOWN }, - { NULL, 0, 0, 0 } - }; - -@@ -539,6 +545,9 @@ static struct { - { LOPT_DUMPFILE, ARG_ONE, "", gettext_noop("Path to debug packet dump file"), NULL }, - { LOPT_DUMPMASK, ARG_ONE, "", gettext_noop("Mask which packets to dump"), NULL }, - { LOPT_SCRIPT_TIME, OPT_LEASE_RENEW, NULL, gettext_noop("Call dhcp-script when lease expiry changes."), NULL }, -+ { LOPT_FILTER_AAAA, OPT_FILTER_AAAA, NULL, gettext_noop("Filter all AAAA requests."), NULL }, -+ { LOPT_FILTER_HTTPS, OPT_FILTER_HTTPS, NULL, gettext_noop("Filter all HTTPS/query type 65 requests."), NULL }, -+ { LOPT_FILTER_UNKNOWN, OPT_FILTER_UNKNOWN, NULL, gettext_noop("Filter all unknown query types (known are defined in cache.c)."), NULL }, - { 0, 0, NULL, NULL, NULL } - }; - -diff --git a/src/rfc1035.c b/src/rfc1035.c -index 6fc4f26..395634b 100644 ---- a/src/rfc1035.c -+++ b/src/rfc1035.c -@@ -1987,6 +1987,32 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, - } - } - -+ //patch to filter aaaa forwards -+ if (qtype == T_AAAA && option_bool(OPT_FILTER_AAAA) ){ -+ //return a null reply -+ ans = 1; -+ if (!dryrun) log_query(F_CONFIG | F_IPV6 | F_NEG, name, &addr, NULL); -+ break; -+ } -+ //end of patch -+ //patch to filter https/query type 65 forwards -+ if (qtype == T_HTTPS && option_bool(OPT_FILTER_HTTPS) ){ -+ //return a null reply -+ ans = 1; -+ if (!dryrun) log_query(F_CONFIG | F_IPV4 | F_NEG, name, &addr, NULL); -+ break; -+ } -+ //end of patch -+ //patch to filter all unknown query types -+ //known types are defined in cache.c:typestr:36. -+ if (is_query_type_unknown(qtype) && option_bool(OPT_FILTER_UNKNOWN)) { -+ //return a null reply -+ ans = 1; -+ if (!dryrun) log_query(F_CONFIG | F_NEG, name, NULL, NULL); -+ break; -+ } -+ //end of patch -+ - if (!ans) - return 0; /* failed to answer a question */ - }