dnsmasq: add version 2.76 and align with stx 3.0 96/3596/1
authorJackie Huang <jackie.huang@windriver.com>
Wed, 6 May 2020 07:45:06 +0000 (15:45 +0800)
committerJackie Huang <jackie.huang@windriver.com>
Wed, 6 May 2020 14:11:09 +0000 (22:11 +0800)
- Add recipe for version 2.76 and set as the preferred
  version (or it will select 2.80)
- Add patches from dnsmasq-2.76-7.el7.tis.7.src.rpm
- Align the spec file from dnsmasq-2.76-7.el7.tis.7.src.rpm
- Add dependency on dnsmasq so it will be installed in image

Issue-ID: INF-85
Signed-off-by: Jackie Huang <jackie.huang@windriver.com>
Change-Id: I0f0ab584686c2aa94b8ec2156f98f1298ea19293

33 files changed:
meta-stx/conf/distro/include/stx-preferred-vers.inc
meta-stx/recipes-core/stx-config-files/config-files_1.0.0.bb
meta-stx/recipes-support/dnsmasq/dnsmasq/99_dnsmasq [new file with mode: 0644]
meta-stx/recipes-support/dnsmasq/dnsmasq/dnsmasq-resolvconf-helper [new file with mode: 0644]
meta-stx/recipes-support/dnsmasq/dnsmasq/dnsmasq-resolvconf.service [new file with mode: 0644]
meta-stx/recipes-support/dnsmasq/dnsmasq/dnsmasq.resolvconf [new file with mode: 0755]
meta-stx/recipes-support/dnsmasq/dnsmasq/init [new file with mode: 0644]
meta-stx/recipes-support/dnsmasq/dnsmasq/lua.patch [new file with mode: 0644]
meta-stx/recipes-support/dnsmasq/dnsmasq/stx/close-tftp-sockets-immediately.patch [new file with mode: 0644]
meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-CVE-2017-14491-2.patch [new file with mode: 0644]
meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-CVE-2017-14491.patch [new file with mode: 0644]
meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-CVE-2017-14492.patch [new file with mode: 0644]
meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-CVE-2017-14493.patch [new file with mode: 0644]
meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-CVE-2017-14494.patch [new file with mode: 0644]
meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-CVE-2017-14495.patch [new file with mode: 0644]
meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-CVE-2017-14496.patch [new file with mode: 0644]
meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-coverity.patch [new file with mode: 0644]
meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-dhcp-script-log.patch [new file with mode: 0644]
meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-dns-sleep-resume.patch [new file with mode: 0644]
meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-file_offset32.patch [new file with mode: 0644]
meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-fix-crash-dns-resume.patch [new file with mode: 0644]
meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-fix-dhcp-option-arrangements.patch [new file with mode: 0644]
meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-gita3303e196.patch [new file with mode: 0644]
meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-inotify.patch [new file with mode: 0644]
meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-label-man.patch [new file with mode: 0644]
meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-label-warning.patch [new file with mode: 0644]
meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-misc-cleanups.patch [new file with mode: 0644]
meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-pftables.patch [new file with mode: 0644]
meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-underflow.patch [new file with mode: 0644]
meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-warning-fixes.patch [new file with mode: 0644]
meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-update-ipv6-leases-from-config.patch [new file with mode: 0644]
meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq.service [new file with mode: 0644]
meta-stx/recipes-support/dnsmasq/dnsmasq_2.76.bb [new file with mode: 0644]

index 81f949b..d48c279 100644 (file)
@@ -14,6 +14,7 @@
 #  limitations under the License.
 
 PREFERRED_VERSION_ceph = "13.2.2"
+PREFERRED_VERSION_dnsmasq = "2.76"
 PREFERRED_VERSION_keyutils = "1.6"
 PREFERRED_VERSION_python-voluptuous = "0.8.9"
 PREFERRED_VERSION_python3-cherrypy = "18.2.0"
index b61260c..cde5170 100644 (file)
@@ -146,7 +146,7 @@ RDEPENDS_audit-config += " \
        audit-python \
        "
 RDEPENDS_dhclient-config += "dhcp-client"
-RDEPENDS_dnsmasq-config += ""
+RDEPENDS_dnsmasq-config += "dnsmasq"
 RDEPENDS_docker-config += "docker-ce logrotate "
 RDEPENDS_initscripts-config += "initscripts"
 RDEPENDS_filesystem-scripts += ""
diff --git a/meta-stx/recipes-support/dnsmasq/dnsmasq/99_dnsmasq b/meta-stx/recipes-support/dnsmasq/dnsmasq/99_dnsmasq
new file mode 100644 (file)
index 0000000..f52ce4e
--- /dev/null
@@ -0,0 +1 @@
+d root root 0755 /run/dnsmasq none
diff --git a/meta-stx/recipes-support/dnsmasq/dnsmasq/dnsmasq-resolvconf-helper b/meta-stx/recipes-support/dnsmasq/dnsmasq/dnsmasq-resolvconf-helper
new file mode 100644 (file)
index 0000000..db54d46
--- /dev/null
@@ -0,0 +1,62 @@
+#!/bin/bash
+#
+# Borrowing heavily from the dnsmasq initscript's version of support for
+# resolvconf, intended for use in systemd-only configurations.
+#
+PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
+DAEMON=/usr/sbin/dnsmasq
+NAME=dnsmasq
+
+# Most configuration options in /etc/default/dnsmasq are deprecated
+# but still honoured.
+if [ -r /etc/default/$NAME ]; then
+   . /etc/default/$NAME
+fi
+
+start_resolvconf()
+{
+   # If interface "lo" is explicitly disabled in /etc/default/dnsmasq
+   # Then dnsmasq won't be providing local DNS, so don't add it to
+   # the resolvconf server set.
+   for interface in $DNSMASQ_EXCEPT
+   do
+      [ $interface = lo ] && return
+   done
+
+   if [ -x /sbin/resolvconf ] ; then
+      echo "nameserver 127.0.0.1" |
+      /sbin/resolvconf -a lo.$NAME
+   fi
+   return 0
+}
+
+stop_resolvconf()
+{
+   if [ -x /sbin/resolvconf ] ; then
+      /sbin/resolvconf -d lo.$NAME
+   fi
+   return 0
+}
+
+case "$1" in
+   start)
+      start_resolvconf
+      exit 0
+      ;;
+   stop)
+      stop_resolvconf
+      exit 0
+      ;;
+   restart)
+      stop_resolvconf
+      start_resolvconf
+      exit 0
+      ;;
+   *)
+      echo "Usage: /etc/init.d/$NAME {start|stop|restart}" >&2
+      exit 3
+      ;;
+esac
+
+exit 0
+
diff --git a/meta-stx/recipes-support/dnsmasq/dnsmasq/dnsmasq-resolvconf.service b/meta-stx/recipes-support/dnsmasq/dnsmasq/dnsmasq-resolvconf.service
new file mode 100644 (file)
index 0000000..2980f7d
--- /dev/null
@@ -0,0 +1,17 @@
+[Unit]
+Description=DNS forwarder and DHCP server
+After=network.target
+
+[Service]
+Type=forking
+PIDFile=/run/dnsmasq.pid
+ExecStartPre=/usr/bin/dnsmasq --test
+ExecStart=/usr/bin/dnsmasq -x /run/dnsmasq.pid -7 /etc/dnsmasq.d --local-service
+ExecStartPost=/usr/bin/dnsmasq-resolvconf-helper start
+ExecStopPre=/usr/bin/dnsmasq-resolvconf-helper stop
+ExecStop=/bin/kill $MAINPID
+ExecReload=/bin/kill -HUP $MAINPID
+
+[Install]
+WantedBy=multi-user.target
+
diff --git a/meta-stx/recipes-support/dnsmasq/dnsmasq/dnsmasq.resolvconf b/meta-stx/recipes-support/dnsmasq/dnsmasq/dnsmasq.resolvconf
new file mode 100755 (executable)
index 0000000..06cd25c
--- /dev/null
@@ -0,0 +1,84 @@
+#!/bin/sh
+#
+# Script to update the resolver list for dnsmasq
+#
+# N.B. Resolvconf may run us even if dnsmasq is not (yet) running.
+# If dnsmasq is installed then we go ahead and update the resolver list
+# in case dnsmasq is started later.
+#
+# Assumption: On entry, PWD contains the resolv.conf-type files.
+#
+# This file is part of the dnsmasq package.
+#
+
+set -e
+
+RUN_DIR="/run/dnsmasq"
+RSLVRLIST_FILE="${RUN_DIR}/resolv.conf"
+TMP_FILE="${RSLVRLIST_FILE}_new.$$"
+MY_NAME_FOR_RESOLVCONF="dnsmasq"
+
+[ -x /usr/bin/dnsmasq ] || exit 0
+[ -x /lib/resolvconf/list-records ] || exit 1
+
+PATH=/bin:/sbin
+
+report_err() { echo "$0: Error: $*" >&2 ; }
+
+# Stores arguments (minus duplicates) in RSLT, separated by spaces
+# Doesn't work properly if an argument itself contains whitespace
+uniquify()
+{
+       RSLT=""
+       while [ "$1" ] ; do
+               for E in $RSLT ; do
+                       [ "$1" = "$E" ] && { shift ; continue 2 ; }
+               done
+               RSLT="${RSLT:+$RSLT }$1"
+               shift
+       done
+}
+
+if [ ! -d "$RUN_DIR" ] && ! mkdir --parents --mode=0755 "$RUN_DIR" ; then
+       report_err "Failed trying to create directory $RUN_DIR"
+       exit 1
+fi
+
+RSLVCNFFILES=""
+for F in $(/lib/resolvconf/list-records --after "lo.$MY_NAME_FOR_RESOLVCONF") ; do
+       case "$F" in
+           "lo.$MY_NAME_FOR_RESOLVCONF")
+               # Omit own record
+               ;;
+           lo.*)
+               # Include no more records after one for a local nameserver
+               RSLVCNFFILES="${RSLVCNFFILES:+$RSLVCNFFILES }$F"
+               break
+               ;;
+         *)
+               RSLVCNFFILES="${RSLVCNFFILES:+$RSLVCNFFILES }$F"
+               ;;
+       esac
+done
+
+NMSRVRS=""
+if [ "$RSLVCNFFILES" ] ; then
+       uniquify $(sed -n -e 's/^[[:space:]]*nameserver[[:space:]]\+//p' $RSLVCNFFILES)
+       NMSRVRS="$RSLT"
+fi
+
+# Dnsmasq uses the mtime of $RSLVRLIST_FILE, with a resolution of one second,
+# to detect changes in the file. This means that if a resolvconf update occurs
+# within one second of the previous one then dnsmasq may fail to notice the
+# more recent change. To work around this problem we sleep one second here
+# if necessary in order to ensure that the new mtime is different.
+if [ -f "$RSLVRLIST_FILE" ] && [ "$(stat -c %X "$RSLVRLIST_FILE")" = "$(date +%s)" ] ; then
+       sleep 1
+fi
+
+clean_up() { rm -f "$TMP_FILE" ; }
+trap clean_up EXIT
+: >| "$TMP_FILE"
+for N in $NMSRVRS ; do echo "nameserver $N" >> "$TMP_FILE" ; done
+mv -f "$TMP_FILE" "$RSLVRLIST_FILE"
+
diff --git a/meta-stx/recipes-support/dnsmasq/dnsmasq/init b/meta-stx/recipes-support/dnsmasq/dnsmasq/init
new file mode 100644 (file)
index 0000000..51c95df
--- /dev/null
@@ -0,0 +1,117 @@
+#!/bin/sh
+DAEMON=/usr/bin/dnsmasq
+NAME=dnsmasq
+DESC="DNS forwarder and DHCP server"
+ARGS="-7 /etc/dnsmasq.d"
+
+test -f $DAEMON || exit 0
+
+set -e
+
+if [ -r /etc/default/$NAME ]
+then
+       . /etc/default/$NAME
+fi
+
+DNSMASQ_CONF="/etc/dnsmasq.conf"
+test "/etc/dnsmasq.d/*" != '/etc/dnsmasq.d/*' && DNSMASQ_CONF="${DNSMASQ_CONF} /etc/dnsmasq.d/*"
+
+test -z "${PIDFILE}" && PIFILE="/run/dnsmasq.pid"
+
+if [ -z "$IGNORE_RESOLVCONF" ]
+then
+       egrep -h -q '^no-resolv' ${DNSMASQ_CONF} && IGNORE_RESOLVCONF="yes"
+fi
+
+# RESOLV_CONF:
+# If the resolvconf package is installed then use the resolv conf file
+# that it provides as the default.  Otherwise use /etc/resolv.conf as
+# the default.
+#
+# If IGNORE_RESOLVCONF is set in /etc/default/dnsmasq or an explicit
+# filename is set there then this inhibits the use of the resolvconf-provided
+# information.
+#
+# Note that if the resolvconf package is installed it is not possible to
+# override it just by configuration in /etc/dnsmasq.conf, it is necessary
+# to set IGNORE_RESOLVCONF=yes in /etc/default/dnsmasq.
+
+test -z "$RESOLV_CONF" -a "$IGNORE_RESOLVCONF" != "yes" -a -x /sbin/resolvconf && \
+       RESOLV_CONF=/run/dnsmasq/resolv.conf
+
+start_resolvconf()
+{
+        if [ "$IGNORE_RESOLVCONF" != "yes" -a -x /sbin/resolvconf ]
+       then
+               echo "nameserver 127.0.0.1" | /sbin/resolvconf -a lo.$NAME
+       fi
+       :
+}
+
+stop_resolvconf()
+{
+       if [ "$IGNORE_RESOLVCONF" != "yes" -a -x /sbin/resolvconf ]
+       then
+               /sbin/resolvconf -d lo.$NAME
+       fi
+       :
+}
+
+case "$1" in
+    start)
+        echo -n "starting $DESC: $NAME... "
+       test -d /var/lib/misc/ || mkdir /var/lib/misc/
+       start-stop-daemon -S -x $DAEMON -- $ARGS \
+               ${RESOLV_CONF:+ -r $RESOLV_CONF} \
+               ${PIDFILE:+ -x $PIDFILE}
+       test $? -eq 0 && start_resolvconf
+       echo "done."
+       ;;
+    stop)
+        echo -n "stopping $DESC: $NAME... "
+       stop_resolvconf
+       start-stop-daemon -K -x $DAEMON
+       echo "done."
+       ;;
+    status)
+       echo -n "dnsmasq "
+       start-stop-daemon -q -K -t -x $DAEMON
+       RET=$?
+       if [ "$RET" = "0" ]; then
+               PID=`cat ${PIDFILE}`
+               echo "($PID) is running"
+       else
+               echo "is not running"
+               exit $RET
+       fi
+       ;;
+    restart)
+        echo "restarting $DESC: $NAME... "
+       $0 stop
+       $0 start
+       echo "done."
+       ;;
+    reload)
+       echo -n "reloading $DESC: $NAME... "
+       killall -HUP $(basename ${DAEMON})
+       echo "done."
+       ;;
+    systemd-start-resolvconf)
+       start_resolvconf
+       ;;
+    systemd-stop-resolvconf)
+       stop_resolvconf
+       ;;
+    systemd-exec)
+       test -d /var/lib/misc/ || mkdir /var/lib/misc/
+       exec $DAEMON --keep-in-foreground $ARGS \
+               ${RESOLV_CONF:+ -r $RESOLV_CONF} \
+               ${PIDFILE:+ -x $PIDFILE}
+       ;;
+    *)
+       echo "Usage: $0 {start|stop|status|restart|reload}"
+       exit 1
+       ;;
+esac
+
+exit 0
diff --git a/meta-stx/recipes-support/dnsmasq/dnsmasq/lua.patch b/meta-stx/recipes-support/dnsmasq/dnsmasq/lua.patch
new file mode 100644 (file)
index 0000000..6281c78
--- /dev/null
@@ -0,0 +1,26 @@
+From 7a7ba871bc9280e76c13ffd87c7d9aaa72dad88d Mon Sep 17 00:00:00 2001
+From: Joe MacDonald <joe_macdonald@mentor.com>
+Date: Tue, 9 Sep 2014 10:24:58 -0400
+Subject: [PATCH] Upstream-status: Inappropriate [OE specific]
+
+Signed-off-by: Christopher Larson <chris_larson@mentor.com>
+
+---
+ Makefile | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/Makefile b/Makefile
+index dd0513b..c49e84f 100644
+--- a/Makefile
++++ b/Makefile
+@@ -57,8 +57,8 @@ idn_cflags =    `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_IDN $(PKG_CONFIG) -
+ idn_libs =      `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_IDN $(PKG_CONFIG) --libs libidn` 
+ ct_cflags =     `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_CONNTRACK $(PKG_CONFIG) --cflags libnetfilter_conntrack`
+ ct_libs =       `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_CONNTRACK $(PKG_CONFIG) --libs libnetfilter_conntrack`
+-lua_cflags =    `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LUASCRIPT $(PKG_CONFIG) --cflags lua5.1` 
+-lua_libs =      `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LUASCRIPT $(PKG_CONFIG) --libs lua5.1` 
++lua_cflags =    `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LUASCRIPT $(PKG_CONFIG) --cflags lua`
++lua_libs =      `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LUASCRIPT $(PKG_CONFIG) --libs lua`
+ nettle_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DNSSEC $(PKG_CONFIG) --cflags nettle hogweed`
+ nettle_libs =   `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DNSSEC $(PKG_CONFIG) --libs nettle hogweed`
+ gmp_libs =      `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DNSSEC NO_GMP --copy -lgmp`
diff --git a/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/close-tftp-sockets-immediately.patch b/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/close-tftp-sockets-immediately.patch
new file mode 100644 (file)
index 0000000..9ca838b
--- /dev/null
@@ -0,0 +1,28 @@
+From 858e259bf7125695c068301d0ef56cc4750d6544 Mon Sep 17 00:00:00 2001
+From: Don Penney <don.penney@windriver.com>
+Date: Thu, 15 Sep 2016 13:32:03 -0400
+Subject: [PATCH 1/1] Close tftp sockets immediately
+
+---
+ src/tftp.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/src/tftp.c b/src/tftp.c
+index d7d050f..ecc6ce8 100644
+--- a/src/tftp.c
++++ b/src/tftp.c
+@@ -768,9 +768,11 @@ int do_tftp_script_run(void)
+   if ((transfer = daemon->tftp_done_trans))
+     {
+       daemon->tftp_done_trans = transfer->next;
++#if 0 /* Disable delayed closing of TFTP UDP socket */
+ #ifdef HAVE_SCRIPT
+       queue_tftp(transfer->file->size, transfer->file->filename, &transfer->peer);
+ #endif
++#endif
+       free_transfer(transfer);
+       return 1;
+     }
+-- 
+1.9.1
+
diff --git a/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-CVE-2017-14491-2.patch b/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-CVE-2017-14491-2.patch
new file mode 100644 (file)
index 0000000..3935566
--- /dev/null
@@ -0,0 +1,68 @@
+From 62cb936cb7ad5f219715515ae7d32dd281a5aa1f Mon Sep 17 00:00:00 2001
+From: Simon Kelley <simon@thekelleys.org.uk>
+Date: Tue, 26 Sep 2017 22:00:11 +0100
+Subject: Security fix, CVE-2017-14491, DNS heap buffer overflow.
+
+Further fix to 0549c73b7ea6b22a3c49beb4d432f185a81efcbc
+Handles case when RR name is not a pointer to the question,
+only occurs for some auth-mode replies, therefore not
+detected by fuzzing (?)
+---
+ src/rfc1035.c | 27 +++++++++++++++------------
+ 1 file changed, 15 insertions(+), 12 deletions(-)
+
+diff --git a/src/rfc1035.c b/src/rfc1035.c
+index 27af023..56ab88b 100644
+--- a/src/rfc1035.c
++++ b/src/rfc1035.c
+@@ -1086,32 +1086,35 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int
+   va_start(ap, format);   /* make ap point to 1st unamed argument */
+-  /* nameoffset (1 or 2) + type (2) + class (2) + ttl (4) + 0 (2) */
+-  CHECK_LIMIT(12);
+-
+   if (nameoffset > 0)
+     {
++      CHECK_LIMIT(2);
+       PUTSHORT(nameoffset | 0xc000, p);
+     }
+   else
+     {
+       char *name = va_arg(ap, char *);
+-      if (name)
+-      p = do_rfc1035_name(p, name, limit);
+-        if (!p)
+-          {
+-            va_end(ap);
+-            goto truncated;
+-          }
+-
++      if (name && !(p = do_rfc1035_name(p, name, limit)))
++      {
++        va_end(ap);
++        goto truncated;
++      }
++      
+       if (nameoffset < 0)
+       {
++        CHECK_LIMIT(2);
+         PUTSHORT(-nameoffset | 0xc000, p);
+       }
+       else
+-      *p++ = 0;
++      {
++        CHECK_LIMIT(1);
++        *p++ = 0;
++      }
+     }
++  /* type (2) + class (2) + ttl (4) + rdlen (2) */
++  CHECK_LIMIT(10);
++  
+   PUTSHORT(type, p);
+   PUTSHORT(class, p);
+   PUTLONG(ttl, p);      /* TTL */
+-- 
+2.7.4
+
diff --git a/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-CVE-2017-14491.patch b/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-CVE-2017-14491.patch
new file mode 100644 (file)
index 0000000..4d8dbd5
--- /dev/null
@@ -0,0 +1,262 @@
+From 8868a04895b27d42d42e364f1a0c0196c1505b04 Mon Sep 17 00:00:00 2001
+From: Simon Kelley <simon@thekelleys.org.uk>
+Date: Mon, 25 Sep 2017 18:17:11 +0100
+Subject: [PATCH 1/9]     Security fix, CVE-2017-14491 DNS heap buffer
+ overflow.
+
+    Fix heap overflow in DNS code. This is a potentially serious
+    security hole. It allows an attacker who can make DNS
+    requests to dnsmasq, and who controls the contents of
+    a domain, which is thereby queried, to overflow
+    (by 2 bytes) a heap buffer and either crash, or
+    even take control of, dnsmasq.
+---
+ src/dnsmasq.h |  2 +-
+ src/dnssec.c  |  2 +-
+ src/option.c  |  2 +-
+ src/rfc1035.c | 50 +++++++++++++++++++++++++++++++++++++++++---------
+ src/rfc2131.c |  4 ++--
+ src/rfc3315.c |  4 ++--
+ src/util.c    |  7 ++++++-
+ 7 files changed, 54 insertions(+), 17 deletions(-)
+
+diff --git a/src/dnsmasq.h b/src/dnsmasq.h
+index 1179492..06e5579 100644
+--- a/src/dnsmasq.h
++++ b/src/dnsmasq.h
+@@ -1162,7 +1162,7 @@ u32 rand32(void);
+ u64 rand64(void);
+ int legal_hostname(char *c);
+ char *canonicalise(char *s, int *nomem);
+-unsigned char *do_rfc1035_name(unsigned char *p, char *sval);
++unsigned char *do_rfc1035_name(unsigned char *p, char *sval, char *limit);
+ void *safe_malloc(size_t size);
+ void safe_pipe(int *fd, int read_noblock);
+ void *whine_malloc(size_t size);
+diff --git a/src/dnssec.c b/src/dnssec.c
+index 3c77c7d..f45c804 100644
+--- a/src/dnssec.c
++++ b/src/dnssec.c
+@@ -2227,7 +2227,7 @@ size_t dnssec_generate_query(struct dns_header *header, unsigned char *end, char
+   p = (unsigned char *)(header+1);
+       
+-  p = do_rfc1035_name(p, name);
++  p = do_rfc1035_name(p, name, NULL);
+   *p++ = 0;
+   PUTSHORT(type, p);
+   PUTSHORT(class, p);
+diff --git a/src/option.c b/src/option.c
+index eb78b1a..3469f53 100644
+--- a/src/option.c
++++ b/src/option.c
+@@ -1378,7 +1378,7 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags)
+                   }
+                 
+                 p = newp;
+-                end = do_rfc1035_name(p + len, dom);
++                end = do_rfc1035_name(p + len, dom, NULL);
+                 *end++ = 0;
+                 len = end - p;
+                 free(dom);
+diff --git a/src/rfc1035.c b/src/rfc1035.c
+index 24d08c1..78410d6 100644
+--- a/src/rfc1035.c
++++ b/src/rfc1035.c
+@@ -1049,6 +1049,7 @@ int check_for_ignored_address(struct dns_header *header, size_t qlen, struct bog
+   return 0;
+ }
++
+ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int nameoffset, unsigned char **pp, 
+                       unsigned long ttl, int *offset, unsigned short type, unsigned short class, char *format, ...)
+ {
+@@ -1058,12 +1059,21 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int
+   unsigned short usval;
+   long lval;
+   char *sval;
++#define CHECK_LIMIT(size) \
++  if (limit && p + (size) > (unsigned char*)limit) \
++    { \
++      va_end(ap); \
++      goto truncated; \
++    }
+   if (truncp && *truncp)
+     return 0;
+- 
++
+   va_start(ap, format);   /* make ap point to 1st unamed argument */
+-  
++
++  /* nameoffset (1 or 2) + type (2) + class (2) + ttl (4) + 0 (2) */
++  CHECK_LIMIT(12);
++
+   if (nameoffset > 0)
+     {
+       PUTSHORT(nameoffset | 0xc000, p);
+@@ -1072,7 +1082,13 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int
+     {
+       char *name = va_arg(ap, char *);
+       if (name)
+-      p = do_rfc1035_name(p, name);
++      p = do_rfc1035_name(p, name, limit);
++        if (!p)
++          {
++            va_end(ap);
++            goto truncated;
++          }
++
+       if (nameoffset < 0)
+       {
+         PUTSHORT(-nameoffset | 0xc000, p);
+@@ -1093,6 +1109,7 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int
+       {
+ #ifdef HAVE_IPV6
+       case '6':
++        CHECK_LIMIT(IN6ADDRSZ);
+       sval = va_arg(ap, char *); 
+       memcpy(p, sval, IN6ADDRSZ);
+       p += IN6ADDRSZ;
+@@ -1100,36 +1117,47 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int
+ #endif
+       
+       case '4':
++        CHECK_LIMIT(INADDRSZ);
+       sval = va_arg(ap, char *); 
+       memcpy(p, sval, INADDRSZ);
+       p += INADDRSZ;
+       break;
+       
+       case 'b':
++        CHECK_LIMIT(1);
+       usval = va_arg(ap, int);
+       *p++ = usval;
+       break;
+       
+       case 's':
++        CHECK_LIMIT(2);
+       usval = va_arg(ap, int);
+       PUTSHORT(usval, p);
+       break;
+       
+       case 'l':
++        CHECK_LIMIT(4);
+       lval = va_arg(ap, long);
+       PUTLONG(lval, p);
+       break;
+       
+       case 'd':
+-      /* get domain-name answer arg and store it in RDATA field */
+-      if (offset)
+-        *offset = p - (unsigned char *)header;
+-      p = do_rfc1035_name(p, va_arg(ap, char *));
+-      *p++ = 0;
++        /* get domain-name answer arg and store it in RDATA field */
++        if (offset)
++          *offset = p - (unsigned char *)header;
++        p = do_rfc1035_name(p, va_arg(ap, char *), limit);
++        if (!p)
++          {
++            va_end(ap);
++            goto truncated;
++          }
++        CHECK_LIMIT(1);
++        *p++ = 0;
+       break;
+       
+       case 't':
+       usval = va_arg(ap, int);
++        CHECK_LIMIT(usval);
+       sval = va_arg(ap, char *);
+       if (usval != 0)
+         memcpy(p, sval, usval);
+@@ -1141,20 +1169,24 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int
+       usval = sval ? strlen(sval) : 0;
+       if (usval > 255)
+         usval = 255;
++        CHECK_LIMIT(usval + 1);
+       *p++ = (unsigned char)usval;
+       memcpy(p, sval, usval);
+       p += usval;
+       break;
+       }
++#undef CHECK_LIMIT
+   va_end(ap); /* clean up variable argument pointer */
+   
+   j = p - sav - 2;
+-  PUTSHORT(j, sav);     /* Now, store real RDLength */
++ /* this has already been checked against limit before */
++ PUTSHORT(j, sav);     /* Now, store real RDLength */
+   
+   /* check for overflow of buffer */
+   if (limit && ((unsigned char *)limit - p) < 0)
+     {
++truncated:
+       if (truncp)
+       *truncp = 1;
+       return 0;
+diff --git a/src/rfc2131.c b/src/rfc2131.c
+index 8b99d4b..75893a6 100644
+--- a/src/rfc2131.c
++++ b/src/rfc2131.c
+@@ -2420,10 +2420,10 @@ static void do_options(struct dhcp_context *context,
+             if (fqdn_flags & 0x04)
+               {
+-                p = do_rfc1035_name(p, hostname);
++                p = do_rfc1035_name(p, hostname, NULL);
+                 if (domain)
+                   {
+-                    p = do_rfc1035_name(p, domain);
++                    p = do_rfc1035_name(p, domain, NULL);
+                     *p++ = 0;
+                   }
+               }
+diff --git a/src/rfc3315.c b/src/rfc3315.c
+index 3f4d69c..73bdee4 100644
+--- a/src/rfc3315.c
++++ b/src/rfc3315.c
+@@ -1472,10 +1472,10 @@ static struct dhcp_netid *add_options(struct state *state, int do_refresh)
+       if ((p = expand(len + 2)))
+       {
+         *(p++) = state->fqdn_flags;
+-        p = do_rfc1035_name(p, state->hostname);
++        p = do_rfc1035_name(p, state->hostname, NULL);
+         if (state->send_domain)
+           {
+-            p = do_rfc1035_name(p, state->send_domain);
++            p = do_rfc1035_name(p, state->send_domain, NULL);
+             *p = 0;
+           }
+       }
+diff --git a/src/util.c b/src/util.c
+index 1a9f228..be9f8a6 100644
+--- a/src/util.c
++++ b/src/util.c
+@@ -218,15 +218,20 @@ char *canonicalise(char *in, int *nomem)
+   return ret;
+ }
+-unsigned char *do_rfc1035_name(unsigned char *p, char *sval)
++unsigned char *do_rfc1035_name(unsigned char *p, char *sval, char *limit)
+ {
+   int j;
+   
+   while (sval && *sval)
+     {
++      if (limit && p + 1 > (unsigned char*)limit)
++        return p;
++
+       unsigned char *cp = p++;
+       for (j = 0; *sval && (*sval != '.'); sval++, j++)
+       {
++          if (limit && p + 1 > (unsigned char*)limit)
++            return p;
+ #ifdef HAVE_DNSSEC
+         if (option_bool(OPT_DNSSEC_VALID) && *sval == NAME_ESCAPE)
+           *p++ = (*(++sval))-1;
+-- 
+2.9.5
+
diff --git a/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-CVE-2017-14492.patch b/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-CVE-2017-14492.patch
new file mode 100644 (file)
index 0000000..b381148
--- /dev/null
@@ -0,0 +1,31 @@
+From c14b8b511ac55f6933aebefbd6cc27c1ec74ad58 Mon Sep 17 00:00:00 2001
+From: Simon Kelley <simon@thekelleys.org.uk>
+Date: Mon, 25 Sep 2017 18:47:15 +0100
+Subject: [PATCH 2/9]     Security fix, CVE-2017-14492, DHCPv6 RA heap
+ overflow.
+
+    Fix heap overflow in IPv6 router advertisement code.
+    This is a potentially serious security hole, as a
+    crafted RA request can overflow a buffer and crash or
+    control dnsmasq. Attacker must be on the local network.
+---
+ src/radv.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/src/radv.c b/src/radv.c
+index 749b666..d09fe0e 100644
+--- a/src/radv.c
++++ b/src/radv.c
+@@ -198,6 +198,9 @@ void icmp6_packet(time_t now)
+       /* look for link-layer address option for logging */
+       if (sz >= 16 && packet[8] == ICMP6_OPT_SOURCE_MAC && (packet[9] * 8) + 8 <= sz)
+       {
++        if ((packet[9] * 8 - 2) * 3 - 1 >= MAXDNAME) {
++          return;
++        }
+         print_mac(daemon->namebuff, &packet[10], (packet[9] * 8) - 2);
+         mac = daemon->namebuff;
+       }
+-- 
+2.9.5
+
diff --git a/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-CVE-2017-14493.patch b/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-CVE-2017-14493.patch
new file mode 100644 (file)
index 0000000..5634803
--- /dev/null
@@ -0,0 +1,30 @@
+From 5086b12a4b1269d1576b5bab01f72c6fa19c55bc Mon Sep 17 00:00:00 2001
+From: Simon Kelley <simon@thekelleys.org.uk>
+Date: Mon, 25 Sep 2017 18:52:50 +0100
+Subject: [PATCH 3/9]     Security fix, CVE-2017-14493, DHCPv6 - Stack buffer
+ overflow.
+
+    Fix stack overflow in DHCPv6 code. An attacker who can send
+    a DHCPv6 request to dnsmasq can overflow the stack frame and
+    crash or control dnsmasq.
+---
+ src/rfc3315.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/src/rfc3315.c b/src/rfc3315.c
+index 73bdee4..8d18a28 100644
+--- a/src/rfc3315.c
++++ b/src/rfc3315.c
+@@ -206,6 +206,9 @@ static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz,
+   /* RFC-6939 */
+   if ((opt = opt6_find(opts, end, OPTION6_CLIENT_MAC, 3)))
+     {
++      if (opt6_len(opt) - 2 > DHCP_CHADDR_MAX) {
++        return 0;
++      }
+       state->mac_type = opt6_uint(opt, 0, 2);
+       state->mac_len = opt6_len(opt) - 2;
+       memcpy(&state->mac[0], opt6_ptr(opt, 2), state->mac_len);
+-- 
+2.9.5
+
diff --git a/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-CVE-2017-14494.patch b/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-CVE-2017-14494.patch
new file mode 100644 (file)
index 0000000..3743a32
--- /dev/null
@@ -0,0 +1,30 @@
+From 8c8fe650dc17aad0fbafc920fde719218dc4568d Mon Sep 17 00:00:00 2001
+From: Simon Kelley <simon@thekelleys.org.uk>
+Date: Mon, 25 Sep 2017 20:05:11 +0100
+Subject: [PATCH 4/9]     Security fix, CVE-2017-14494, Infoleak handling
+ DHCPv6 forwarded requests.
+
+    Fix information leak in DHCPv6. A crafted DHCPv6 packet can
+    cause dnsmasq to forward memory from outside the packet
+    buffer to a DHCPv6 server when acting as a relay.
+---
+ src/rfc3315.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/src/rfc3315.c b/src/rfc3315.c
+index 8d18a28..03b3f84 100644
+--- a/src/rfc3315.c
++++ b/src/rfc3315.c
+@@ -216,6 +216,9 @@ static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz,
+   
+   for (opt = opts; opt; opt = opt6_next(opt, end))
+     {
++      if (opt6_ptr(opt, 0) + opt6_len(opt) >= end) {
++        return 0;
++      }
+       int o = new_opt6(opt6_type(opt));
+       if (opt6_type(opt) == OPTION6_RELAY_MSG)
+       {
+-- 
+2.9.5
+
diff --git a/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-CVE-2017-14495.patch b/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-CVE-2017-14495.patch
new file mode 100644 (file)
index 0000000..8ca5d0f
--- /dev/null
@@ -0,0 +1,41 @@
+From f2ad2cecb55825f7e4409222de1688b9ceebceda Mon Sep 17 00:00:00 2001
+From: Simon Kelley <simon@thekelleys.org.uk>
+Date: Mon, 25 Sep 2017 20:16:50 +0100
+Subject: [PATCH 6/9]     Security fix, CVE-2017-14495, OOM in DNS response
+ creation.
+
+    Fix out-of-memory Dos vulnerability. An attacker which can
+    send malicious DNS queries to dnsmasq can trigger memory
+    allocations in the add_pseudoheader function
+    The allocated memory is never freed which leads to a DoS
+    through memory exhaustion. dnsmasq is vulnerable only
+    if one of the following option is specified:
+    --add-mac, --add-cpe-id or --add-subnet.
+---
+ src/edns0.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/src/edns0.c b/src/edns0.c
+index eed135e..5bdc133 100644
+--- a/src/edns0.c
++++ b/src/edns0.c
+@@ -192,9 +192,15 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
+         !(p = skip_section(p, 
+                            ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount), 
+                            header, plen)))
++      {
++      free(buff);
+       return plen;
++      }
+       if (p + 11 > limit)
+-       return plen; /* Too big */
++      {
++        free(buff);
++        return plen; /* Too big */
++      }
+       *p++ = 0; /* empty name */
+       PUTSHORT(T_OPT, p);
+       PUTSHORT(udp_sz, p); /* max packet length, 512 if not given in EDNS0 header */
+-- 
+2.9.5
+
diff --git a/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-CVE-2017-14496.patch b/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-CVE-2017-14496.patch
new file mode 100644 (file)
index 0000000..f32b919
--- /dev/null
@@ -0,0 +1,66 @@
+From 5ab67e936085a9e584c9b3e43f442ef5bee7f40e Mon Sep 17 00:00:00 2001
+From: Simon Kelley <simon@thekelleys.org.uk>
+Date: Mon, 25 Sep 2017 20:11:58 +0100
+Subject: [PATCH 5/9]     Security fix, CVE-2017-14496, Integer underflow in
+ DNS response creation.
+
+    Fix DoS in DNS. Invalid boundary checks in the
+    add_pseudoheader function allows a memcpy call with negative
+    size An attacker which can send malicious DNS queries
+    to dnsmasq can trigger a DoS remotely.
+    dnsmasq is vulnerable only if one of the following option is
+    specified: --add-mac, --add-cpe-id or --add-subnet.
+---
+ src/edns0.c | 13 ++++++++++++-
+ 1 file changed, 12 insertions(+), 1 deletion(-)
+
+diff --git a/src/edns0.c b/src/edns0.c
+index d2b514b..eed135e 100644
+--- a/src/edns0.c
++++ b/src/edns0.c
+@@ -144,7 +144,7 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
+         GETSHORT(len, p);
+         
+         /* malformed option, delete the whole OPT RR and start again. */
+-        if (i + len > rdlen)
++        if (i + 4 + len > rdlen)
+           {
+             rdlen = 0;
+             is_last = 0;
+@@ -193,6 +193,8 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
+                            ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount), 
+                            header, plen)))
+       return plen;
++      if (p + 11 > limit)
++       return plen; /* Too big */
+       *p++ = 0; /* empty name */
+       PUTSHORT(T_OPT, p);
+       PUTSHORT(udp_sz, p); /* max packet length, 512 if not given in EDNS0 header */
+@@ -204,6 +206,11 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
+       /* Copy back any options */
+       if (buff)
+       {
++          if (p + rdlen > limit)
++          {
++            free(buff);
++            return plen; /* Too big */
++          }
+         memcpy(p, buff, rdlen);
+         free(buff);
+         p += rdlen;
+@@ -217,8 +224,12 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
+   /* Add new option */
+   if (optno != 0 && replace != 2)
+     {
++      if (p + 4 > limit)
++       return plen; /* Too big */
+       PUTSHORT(optno, p);
+       PUTSHORT(optlen, p);
++      if (p + optlen > limit)
++       return plen; /* Too big */
+       memcpy(p, opt, optlen);
+       p += optlen;  
+       PUTSHORT(p - datap, lenp);
+-- 
+2.9.5
+
diff --git a/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-coverity.patch b/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-coverity.patch
new file mode 100644 (file)
index 0000000..87f41a0
--- /dev/null
@@ -0,0 +1,254 @@
+From 7ab5d6bd1f8b018c73341f50a395405dee6873d8 Mon Sep 17 00:00:00 2001
+From: rpm-build <rpm-build>
+Date: Wed, 15 Mar 2017 14:26:04 +0100
+Subject: [PATCH] Coverity fixes
+
+---
+ src/dbus.c        |  2 +-
+ src/dhcp-common.c |  2 +-
+ src/dhcp.c        |  4 ++--
+ src/dnsmasq.h     |  2 +-
+ src/edns0.c       |  2 ++
+ src/inotify.c     |  9 ++++++---
+ src/lease.c       |  4 ++--
+ src/network.c     |  8 ++++----
+ src/option.c      | 16 +++++++++++-----
+ src/tftp.c        |  2 +-
+ src/util.c        |  2 +-
+ 11 files changed, 32 insertions(+), 21 deletions(-)
+
+diff --git a/src/dbus.c b/src/dbus.c
+index 2e1a48e..f27ec3e 100644
+--- a/src/dbus.c
++++ b/src/dbus.c
+@@ -550,7 +550,7 @@ static DBusMessage *dbus_add_lease(DBusMessage* message)
+                                        "Invalid IP address '%s'", ipaddr);
+    
+   hw_len = parse_hex((char*)hwaddr, dhcp_chaddr, DHCP_CHADDR_MAX, NULL, &hw_type);
+-  if (hw_type == 0 && hw_len != 0)
++  if (hw_type == 0 && hw_len > 0)
+     hw_type = ARPHRD_ETHER;
+   
+   lease_set_hwaddr(lease, dhcp_chaddr, clid, hw_len, hw_type,
+diff --git a/src/dhcp-common.c b/src/dhcp-common.c
+index 08528e8..ebf06b6 100644
+--- a/src/dhcp-common.c
++++ b/src/dhcp-common.c
+@@ -487,7 +487,7 @@ void  bindtodevice(char *device, int fd)
+ {
+   struct ifreq ifr;
+   
+-  strcpy(ifr.ifr_name, device);
++  strncpy(ifr.ifr_name, device, IF_NAMESIZE-1);
+   /* only allowed by root. */
+   if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) == -1 &&
+       errno != EPERM)
+diff --git a/src/dhcp.c b/src/dhcp.c
+index 10f1fb9..37bb71e 100644
+--- a/src/dhcp.c
++++ b/src/dhcp.c
+@@ -246,7 +246,7 @@ void dhcp_packet(time_t now, int pxe_fd)
+             }
+           else 
+             {
+-              strncpy(ifr.ifr_name,  bridge->iface, IF_NAMESIZE);
++              strncpy(ifr.ifr_name,  bridge->iface, IF_NAMESIZE-1);
+               break;
+             }
+         }
+@@ -270,7 +270,7 @@ void dhcp_packet(time_t now, int pxe_fd)
+       is_relay_reply = 1; 
+       iov.iov_len = sz;
+ #ifdef HAVE_LINUX_NETWORK
+-      strncpy(arp_req.arp_dev, ifr.ifr_name, 16);
++      strncpy(arp_req.arp_dev, ifr.ifr_name, IF_NAMESIZE-1);
+ #endif 
+     }
+   else
+diff --git a/src/dnsmasq.h b/src/dnsmasq.h
+index dfd15aa..1179492 100644
+--- a/src/dnsmasq.h
++++ b/src/dnsmasq.h
+@@ -180,7 +180,7 @@ struct event_desc {
+ #define EC_INIT_OFFSET 10
+ /* Trust the compiler dead-code eliminator.... */
+-#define option_bool(x) (((x) < 32) ? daemon->options & (1u << (x)) : daemon->options2 & (1u << ((x) - 32)))
++#define option_bool(x) (((x) < 32) ? daemon->options & (1u << ((x)&0x1F)) : daemon->options2 & (1u << ((x) - 32)))
+ #define OPT_BOGUSPRIV      0
+ #define OPT_FILTER         1
+diff --git a/src/edns0.c b/src/edns0.c
+index c7a101e..d2b514b 100644
+--- a/src/edns0.c
++++ b/src/edns0.c
+@@ -263,6 +263,8 @@ static size_t add_dns_client(struct dns_header *header, size_t plen, unsigned ch
+         encode[8] = 0;
+       }
+     }
++  else
++    encode[0] = '\0';
+   return add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_NOMDEVICEID, (unsigned char *)encode, strlen(encode), 0, replace); 
+ }
+diff --git a/src/inotify.c b/src/inotify.c
+index 603ce9d..fcc0d97 100644
+--- a/src/inotify.c
++++ b/src/inotify.c
+@@ -224,17 +224,20 @@ int inotify_check(time_t now)
+       
+       if (rc <= 0)
+       break;
++      else
++        inotify_buffer[rc] = '\0';
+       
+       for (p = inotify_buffer; rc - (p - inotify_buffer) >= (int)sizeof(struct inotify_event); p += sizeof(struct inotify_event) + in->len) 
+       {
+         in = (struct inotify_event*)p;
+-        
++
+         for (res = daemon->resolv_files; res; res = res->next)
+-          if (res->wd == in->wd && in->len != 0 && strcmp(res->file, in->name) == 0)
++          if (res->wd == in->wd && in->len != 0 && strncmp(res->file, in->name, NAME_MAX) == 0)
+             hit = 1;
+         /* ignore emacs backups and dotfiles */
+-        if (in->len == 0 || 
++        if (in->len == 0 ||
++            in->len > NAME_MAX+1 ||
+             in->name[in->len - 1] == '~' ||
+             (in->name[0] == '#' && in->name[in->len - 1] == '#') ||
+             in->name[0] == '.')
+diff --git a/src/lease.c b/src/lease.c
+index 20cac90..9ad106d 100644
+--- a/src/lease.c
++++ b/src/lease.c
+@@ -827,9 +827,9 @@ void lease_set_hwaddr(struct dhcp_lease *lease, const unsigned char *hwaddr,
+   if (hw_len != lease->hwaddr_len ||
+       hw_type != lease->hwaddr_type || 
+-      (hw_len != 0 && memcmp(lease->hwaddr, hwaddr, hw_len) != 0))
++      (hw_len > 0 && memcmp(lease->hwaddr, hwaddr, hw_len) != 0))
+     {
+-      if (hw_len != 0)
++      if (hw_len > 0)
+       memcpy(lease->hwaddr, hwaddr, hw_len);
+       lease->hwaddr_len = hw_len;
+       lease->hwaddr_type = hw_type;
+diff --git a/src/network.c b/src/network.c
+index 6119039..fcd9d8d 100644
+--- a/src/network.c
++++ b/src/network.c
+@@ -188,7 +188,7 @@ int loopback_exception(int fd, int family, struct all_addr *addr, char *name)
+   struct ifreq ifr;
+   struct irec *iface;
+-  strncpy(ifr.ifr_name, name, IF_NAMESIZE);
++  strncpy(ifr.ifr_name, name, IF_NAMESIZE-1);
+   if (ioctl(fd, SIOCGIFFLAGS, &ifr) != -1 &&
+       ifr.ifr_flags & IFF_LOOPBACK)
+     {
+@@ -1206,7 +1206,7 @@ int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp)
+     return 0;
+     
+ #if defined(SO_BINDTODEVICE)
+-  if (intname[0] != 0 &&
++  if (intname && intname[0] != 0 &&
+       setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, intname, IF_NAMESIZE) == -1)
+     return 0;
+ #endif
+@@ -1245,7 +1245,7 @@ static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
+   /* may have a suitable one already */
+   for (sfd = daemon->sfds; sfd; sfd = sfd->next )
+     if (sockaddr_isequal(&sfd->source_addr, addr) &&
+-      strcmp(intname, sfd->interface) == 0 &&
++      intname && strcmp(intname, sfd->interface) == 0 &&
+       ifindex == sfd->ifindex) 
+       return sfd;
+   
+@@ -1437,7 +1437,7 @@ void add_update_server(int flags,
+       serv->flags |= SERV_HAS_DOMAIN;
+       
+       if (interface)
+-      strcpy(serv->interface, interface);      
++      strncpy(serv->interface, interface, sizeof(serv->interface)-1);
+       if (addr)
+       serv->addr = *addr;
+       if (source_addr)
+diff --git a/src/option.c b/src/option.c
+index 5503b79..eb78b1a 100644
+--- a/src/option.c
++++ b/src/option.c
+@@ -3929,13 +3929,15 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
+       
+     case LOPT_HOST_REC: /* --host-record */
+       {
+-      struct host_record *new = opt_malloc(sizeof(struct host_record));
+-      memset(new, 0, sizeof(struct host_record));
+-      new->ttl = -1;
++      struct host_record *new;
+       if (!arg || !(comma = split(arg)))
+         ret_err(_("Bad host-record"));
+       
++      new = opt_malloc(sizeof(struct host_record));
++      memset(new, 0, sizeof(struct host_record));
++      new->ttl = -1;
++
+       while (arg)
+         {
+           struct all_addr addr;
+@@ -3956,10 +3958,11 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
+             {
+               int nomem;
+               char *canon = canonicalise(arg, &nomem);
+-              struct name_list *nl = opt_malloc(sizeof(struct name_list));
++              struct name_list *nl;
+               if (!canon)
+                 ret_err(_("Bad name in host-record"));
++              nl = opt_malloc(sizeof(struct name_list));
+               nl->name = canon;
+               /* keep order, so that PTR record goes to first name */
+               nl->next = NULL;
+@@ -4023,7 +4026,10 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
+           !atoi_check8(algo, &new->algo) ||
+           !atoi_check8(digest, &new->digest_type) ||
+           !(new->name = canonicalise_opt(arg)))
+-        ret_err(_("bad trust anchor"));
++        {
++          free(new);
++          ret_err(_("bad trust anchor"));
++        }
+           
+       /* Upper bound on length */
+       len = (2*strlen(keyhex))+1;
+diff --git a/src/tftp.c b/src/tftp.c
+index 5e4a32a..bd8c622 100644
+--- a/src/tftp.c
++++ b/src/tftp.c
+@@ -234,7 +234,7 @@ void tftp_request(struct listener *listen, time_t now)
+ #endif
+       }
+-      strncpy(ifr.ifr_name, name, IF_NAMESIZE);
++      strncpy(ifr.ifr_name, name, IF_NAMESIZE-1);
+       if (ioctl(listen->tftpfd, SIOCGIFMTU, &ifr) != -1)
+       {
+         mtu = ifr.ifr_mtu;  
+diff --git a/src/util.c b/src/util.c
+index 93b24f5..1a9f228 100644
+--- a/src/util.c
++++ b/src/util.c
+@@ -491,7 +491,7 @@ int parse_hex(char *in, unsigned char *out, int maxlen,
+                 int j, bytes = (1 + (r - in))/2;
+                 for (j = 0; j < bytes; j++)
+                   { 
+-                    char sav = sav;
++                    char sav;
+                     if (j < bytes - 1)
+                       {
+                         sav = in[(j+1)*2];
+-- 
+2.9.3
+
diff --git a/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-dhcp-script-log.patch b/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-dhcp-script-log.patch
new file mode 100644 (file)
index 0000000..ac26258
--- /dev/null
@@ -0,0 +1,582 @@
+From 87444dc6977b61096127dcdfe87dc6cf2c0167d6 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= <pemensik@redhat.com>
+Date: Sun, 16 Apr 2017 20:20:08 +0100
+Subject: [PATCH] Capture and log  STDOUT and STDERR output from dhcp-script.
+
+(cherry picked from commit c77fb9d8f09d136fa71bde2469c4fd11cefa6f4a)
+
+Compile-time check on buffer sizes for leasefile parsing code.
+
+(cherry picked from commit bf4e62c19e619f7edf8d03d58d33a5752f190bfd)
+
+Improve error handling with shcp-script "init" mode.
+
+(cherry picked from commit 3a8b0f6fccf464b1ec6d24c0e00e540ab2b17705)
+
+Tweak logging introduced in 3a8b0f6fccf464b1ec6d24c0e00e540ab2b17705
+
+(cherry picked from commit efff74c1aea14757ce074db28e02671c7f7bb5f5)
+
+Don't die() on failing to parse lease-script output.
+
+(cherry picked from commit 05f76dab89d5b879519a4f45b0cccaa1fc3d162d)
+---
+ man/dnsmasq.8       |   4 +-
+ src/dhcp-common.c   |  16 +++---
+ src/dhcp-protocol.h |   4 ++
+ src/dnsmasq.c       |   8 +++
+ src/dnsmasq.h       |  54 +++++++++---------
+ src/helper.c        |  56 +++++++++++++++++-
+ src/lease.c         | 159 +++++++++++++++++++++++++++++++---------------------
+ src/log.c           |   4 +-
+ src/rfc3315.c       |   2 +-
+ 9 files changed, 202 insertions(+), 105 deletions(-)
+
+diff --git a/man/dnsmasq.8 b/man/dnsmasq.8
+index 0521534..97d0a4f 100644
+--- a/man/dnsmasq.8
++++ b/man/dnsmasq.8
+@@ -1551,8 +1551,8 @@ database.
+ All file descriptors are
+-closed except stdin, stdout and stderr which are open to /dev/null
+-(except in debug mode).
++closed except stdin, which is open to /dev/null, and stdout and stderr which capture output for logging by dnsmasq. 
++(In debug mode, stdio, stdout and stderr file are left as those inherited from the invoker of dnsmasq).
+ The script is not invoked concurrently: at most one instance
+ of the script is ever running (dnsmasq waits for an instance of script to exit
+diff --git a/src/dhcp-common.c b/src/dhcp-common.c
+index 08528e8..ecc752b 100644
+--- a/src/dhcp-common.c
++++ b/src/dhcp-common.c
+@@ -20,11 +20,11 @@
+ void dhcp_common_init(void)
+ {
+-    /* These each hold a DHCP option max size 255
+-       and get a terminating zero added */
+-  daemon->dhcp_buff = safe_malloc(256);
+-  daemon->dhcp_buff2 = safe_malloc(256); 
+-  daemon->dhcp_buff3 = safe_malloc(256);
++  /* These each hold a DHCP option max size 255
++     and get a terminating zero added */
++  daemon->dhcp_buff = safe_malloc(DHCP_BUFF_SZ);
++  daemon->dhcp_buff2 = safe_malloc(DHCP_BUFF_SZ); 
++  daemon->dhcp_buff3 = safe_malloc(DHCP_BUFF_SZ);
+   
+   /* dhcp_packet is used by v4 and v6, outpacket only by v6 
+      sizeof(struct dhcp_packet) is as good an initial size as any,
+@@ -855,14 +855,14 @@ void log_context(int family, struct dhcp_context *context)
+       if (context->flags & CONTEXT_RA_STATELESS)
+       {
+         if (context->flags & CONTEXT_TEMPLATE)
+-          strncpy(daemon->dhcp_buff, context->template_interface, 256);
++          strncpy(daemon->dhcp_buff, context->template_interface, DHCP_BUFF_SZ);
+         else
+           strcpy(daemon->dhcp_buff, daemon->addrbuff);
+       }
+       else 
+ #endif
+-      inet_ntop(family, start, daemon->dhcp_buff, 256);
+-      inet_ntop(family, end, daemon->dhcp_buff3, 256);
++      inet_ntop(family, start, daemon->dhcp_buff, DHCP_BUFF_SZ);
++      inet_ntop(family, end, daemon->dhcp_buff3, DHCP_BUFF_SZ);
+       my_syslog(MS_DHCP | LOG_INFO, 
+               (context->flags & CONTEXT_RA_STATELESS) ? 
+               _("%s stateless on %s%.0s%.0s%s") :
+diff --git a/src/dhcp-protocol.h b/src/dhcp-protocol.h
+index a31d829..0ea449b 100644
+--- a/src/dhcp-protocol.h
++++ b/src/dhcp-protocol.h
+@@ -19,6 +19,10 @@
+ #define DHCP_CLIENT_ALTPORT 1068
+ #define PXE_PORT 4011
++/* These each hold a DHCP option max size 255
++   and get a terminating zero added */
++#define DHCP_BUFF_SZ 256
++
+ #define BOOTREQUEST              1
+ #define BOOTREPLY                2
+ #define DHCP_COOKIE              0x63825363
+diff --git a/src/dnsmasq.c b/src/dnsmasq.c
+index 045ec53..9cd4052 100644
+--- a/src/dnsmasq.c
++++ b/src/dnsmasq.c
+@@ -1294,6 +1294,7 @@ static void async_event(int pipe, time_t now)
+               daemon->tcp_pids[i] = 0;
+       break;
+       
++#if defined(HAVE_SCRIPT)      
+       case EVENT_KILLED:
+       my_syslog(LOG_WARNING, _("script process killed by signal %d"), ev.data);
+       break;
+@@ -1307,12 +1308,19 @@ static void async_event(int pipe, time_t now)
+                 daemon->lease_change_command, strerror(ev.data));
+       break;
++      case EVENT_SCRIPT_LOG:
++      my_syslog(MS_SCRIPT | LOG_DEBUG, "%s", msg ? msg : "");
++        free(msg);
++      msg = NULL;
++      break;
++
+       /* necessary for fatal errors in helper */
+       case EVENT_USER_ERR:
+       case EVENT_DIE:
+       case EVENT_LUA_ERR:
+       fatal_event(&ev, msg);
+       break;
++#endif
+       case EVENT_REOPEN:
+       /* Note: this may leave TCP-handling processes with the old file still open.
+diff --git a/src/dnsmasq.h b/src/dnsmasq.h
+index 1896a64..0cfd3c6 100644
+--- a/src/dnsmasq.h
++++ b/src/dnsmasq.h
+@@ -145,30 +145,31 @@ struct event_desc {
+   int event, data, msg_sz;
+ };
+-#define EVENT_RELOAD    1
+-#define EVENT_DUMP      2
+-#define EVENT_ALARM     3
+-#define EVENT_TERM      4
+-#define EVENT_CHILD     5
+-#define EVENT_REOPEN    6
+-#define EVENT_EXITED    7
+-#define EVENT_KILLED    8
+-#define EVENT_EXEC_ERR  9
+-#define EVENT_PIPE_ERR  10
+-#define EVENT_USER_ERR  11
+-#define EVENT_CAP_ERR   12
+-#define EVENT_PIDFILE   13
+-#define EVENT_HUSER_ERR 14
+-#define EVENT_GROUP_ERR 15
+-#define EVENT_DIE       16
+-#define EVENT_LOG_ERR   17
+-#define EVENT_FORK_ERR  18
+-#define EVENT_LUA_ERR   19
+-#define EVENT_TFTP_ERR  20
+-#define EVENT_INIT      21
+-#define EVENT_NEWADDR   22
+-#define EVENT_NEWROUTE  23
+-#define EVENT_TIME_ERR  24
++#define EVENT_RELOAD     1
++#define EVENT_DUMP       2
++#define EVENT_ALARM      3
++#define EVENT_TERM       4
++#define EVENT_CHILD      5
++#define EVENT_REOPEN     6
++#define EVENT_EXITED     7
++#define EVENT_KILLED     8
++#define EVENT_EXEC_ERR   9
++#define EVENT_PIPE_ERR   10
++#define EVENT_USER_ERR   11
++#define EVENT_CAP_ERR    12
++#define EVENT_PIDFILE    13
++#define EVENT_HUSER_ERR  14
++#define EVENT_GROUP_ERR  15
++#define EVENT_DIE        16
++#define EVENT_LOG_ERR    17
++#define EVENT_FORK_ERR   18
++#define EVENT_LUA_ERR    19
++#define EVENT_TFTP_ERR   20
++#define EVENT_INIT       21
++#define EVENT_NEWADDR    22
++#define EVENT_NEWROUTE   23
++#define EVENT_TIME_ERR   24
++#define EVENT_SCRIPT_LOG 25
+ /* Exit codes. */
+ #define EC_GOOD        0
+@@ -242,8 +243,9 @@ struct event_desc {
+ /* extra flags for my_syslog, we use a couple of facilities since they are known 
+    not to occupy the same bits as priorities, no matter how syslog.h is set up. */
+-#define MS_TFTP LOG_USER
+-#define MS_DHCP LOG_DAEMON 
++#define MS_TFTP   LOG_USER
++#define MS_DHCP   LOG_DAEMON
++#define MS_SCRIPT LOG_MAIL
+ struct all_addr {
+   union {
+diff --git a/src/helper.c b/src/helper.c
+index 9c37e37..de31383 100644
+--- a/src/helper.c
++++ b/src/helper.c
+@@ -14,6 +14,7 @@
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
++#include <stdio.h>
+ #include "dnsmasq.h"
+ #ifdef HAVE_SCRIPT
+@@ -135,7 +136,7 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
+       max_fd != STDIN_FILENO && max_fd != pipefd[0] && 
+       max_fd != event_fd && max_fd != err_fd)
+       close(max_fd);
+-  
++
+ #ifdef HAVE_LUASCRIPT
+   if (daemon->luascript)
+     {
+@@ -189,6 +190,7 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
+       unsigned char *buf = (unsigned char *)daemon->namebuff;
+       unsigned char *end, *extradata, *alloc_buff = NULL;
+       int is6, err = 0;
++      int pipeout[2];
+       free(alloc_buff);
+       
+@@ -472,16 +474,54 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
+       if (!daemon->lease_change_command)
+       continue;
++      /* Pipe to capture stdout and stderr from script */
++      if (!option_bool(OPT_DEBUG) && pipe(pipeout) == -1)
++      continue;
++      
+       /* possible fork errors are all temporary resource problems */
+       while ((pid = fork()) == -1 && (errno == EAGAIN || errno == ENOMEM))
+       sleep(2);
+       if (pid == -1)
+-      continue;
++        {
++        if (!option_bool(OPT_DEBUG))
++          {
++            close(pipeout[0]);
++            close(pipeout[1]);
++          }
++        continue;
++        }
+       
+       /* wait for child to complete */
+       if (pid != 0)
+       {
++        if (!option_bool(OPT_DEBUG))
++          {
++            FILE *fp;
++        
++            close(pipeout[1]);
++            
++            /* Read lines sent to stdout/err by the script and pass them back to be logged */
++            if (!(fp = fdopen(pipeout[0], "r")))
++              close(pipeout[0]);
++            else
++              {
++                while (fgets(daemon->packet, daemon->packet_buff_sz, fp))
++                  {
++                    /* do not include new lines, log will append them */
++                    size_t len = strlen(daemon->packet);
++                    if (len > 0)
++                      {
++                        --len;
++                        if (daemon->packet[len] == '\n')
++                          daemon->packet[len] = 0;
++                      }
++                    send_event(event_fd, EVENT_SCRIPT_LOG, 0, daemon->packet);
++                  }
++                fclose(fp);
++              }
++          }
++        
+         /* reap our children's children, if necessary */
+         while (1)
+           {
+@@ -504,6 +544,15 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
+         
+         continue;
+       }
++
++      if (!option_bool(OPT_DEBUG))
++      {
++        /* map stdout/stderr of script to pipeout */
++        close(pipeout[0]);
++        dup2(pipeout[1], STDOUT_FILENO);
++        dup2(pipeout[1], STDERR_FILENO);
++        close(pipeout[1]);
++      }
+       
+       if (data.action != ACTION_TFTP && data.action != ACTION_ARP)
+       {
+@@ -579,7 +628,8 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
+           hostname = NULL;
+         
+         my_setenv("DNSMASQ_LOG_DHCP", option_bool(OPT_LOG_OPTS) ? "1" : NULL, &err);
+-    }
++      }
++      
+       /* we need to have the event_fd around if exec fails */
+       if ((i = fcntl(event_fd, F_GETFD)) != -1)
+       fcntl(event_fd, F_SETFD, i | FD_CLOEXEC);
+diff --git a/src/lease.c b/src/lease.c
+index 20cac90..64047f9 100644
+--- a/src/lease.c
++++ b/src/lease.c
+@@ -21,94 +21,62 @@
+ static struct dhcp_lease *leases = NULL, *old_leases = NULL;
+ static int dns_dirty, file_dirty, leases_left;
+-void lease_init(time_t now)
++static int read_leases(time_t now, FILE *leasestream)
+ {
+   unsigned long ei;
+   struct all_addr addr;
+   struct dhcp_lease *lease;
+   int clid_len, hw_len, hw_type;
+-  FILE *leasestream;
+-  
+-  leases_left = daemon->dhcp_max;
+-  
+-  if (option_bool(OPT_LEASE_RO))
+-    {
+-      /* run "<lease_change_script> init" once to get the
+-       initial state of the database. If leasefile-ro is
+-       set without a script, we just do without any 
+-       lease database. */
+-#ifdef HAVE_SCRIPT
+-      if (daemon->lease_change_command)
+-      {
+-        strcpy(daemon->dhcp_buff, daemon->lease_change_command);
+-        strcat(daemon->dhcp_buff, " init");
+-        leasestream = popen(daemon->dhcp_buff, "r");
+-      }
+-      else
++  int items;
++  char *domain = NULL;
++
++  *daemon->dhcp_buff3 = *daemon->dhcp_buff2 = '\0';
++
++  /* client-id max length is 255 which is 255*2 digits + 254 colons
++     borrow DNS packet buffer which is always larger than 1000 bytes
++
++     Check various buffers are big enough for the code below */
++
++#if (DHCP_BUFF_SZ < 255) || (MAXDNAME < 64) || (PACKETSZ+MAXDNAME+RRFIXEDSZ  < 764)
++# error Buffer size breakage in leasefile parsing.
+ #endif
+-      {
+-          file_dirty = dns_dirty = 0;
+-          return;
+-        }
+-    }
+-  else
+-    {
+-      /* NOTE: need a+ mode to create file if it doesn't exist */
+-      leasestream = daemon->lease_stream = fopen(daemon->lease_file, "a+");
+-      
+-      if (!leasestream)
+-      die(_("cannot open or create lease file %s: %s"), daemon->lease_file, EC_FILE);
+-      
+-      /* a+ mode leaves pointer at end. */
+-      rewind(leasestream);
+-    }
+-  
+-  /* client-id max length is 255 which is 255*2 digits + 254 colons 
+-     borrow DNS packet buffer which is always larger than 1000 bytes */
+-  if (leasestream)
+-    while (fscanf(leasestream, "%255s %255s", daemon->dhcp_buff3, daemon->dhcp_buff2) == 2)
++    while ((items=fscanf(leasestream, "%255s %255s", daemon->dhcp_buff3, daemon->dhcp_buff2)) == 2)
+       {
++      *daemon->namebuff = *daemon->dhcp_buff = *daemon->packet = '\0';
++      hw_len = hw_type = clid_len = 0;
++      
+ #ifdef HAVE_DHCP6
+       if (strcmp(daemon->dhcp_buff3, "duid") == 0)
+         {
+           daemon->duid_len = parse_hex(daemon->dhcp_buff2, (unsigned char *)daemon->dhcp_buff2, 130, NULL, NULL);
++          if (daemon->duid_len < 0)
++            return 0;
+           daemon->duid = safe_malloc(daemon->duid_len);
+           memcpy(daemon->duid, daemon->dhcp_buff2, daemon->duid_len);
+           continue;
+         }
+ #endif
+-
+-      ei = atol(daemon->dhcp_buff3);
+       
+       if (fscanf(leasestream, " %64s %255s %764s",
+                  daemon->namebuff, daemon->dhcp_buff, daemon->packet) != 3)
+-        break;
++        return 0;
+       
+-      clid_len = 0;
+-      if (strcmp(daemon->packet, "*") != 0)
+-        clid_len = parse_hex(daemon->packet, (unsigned char *)daemon->packet, 255, NULL, NULL);
+-      
+-      if (inet_pton(AF_INET, daemon->namebuff, &addr.addr.addr4) &&
+-          (lease = lease4_allocate(addr.addr.addr4)))
++      if (inet_pton(AF_INET, daemon->namebuff, &addr.addr.addr4))
+         {
++          if ((lease = lease4_allocate(addr.addr.addr4)))
++            domain = get_domain(lease->addr);
++          
+           hw_len = parse_hex(daemon->dhcp_buff2, (unsigned char *)daemon->dhcp_buff2, DHCP_CHADDR_MAX, NULL, &hw_type);
+           /* For backwards compatibility, no explict MAC address type means ether. */
+           if (hw_type == 0 && hw_len != 0)
+             hw_type = ARPHRD_ETHER; 
+-
+-          lease_set_hwaddr(lease, (unsigned char *)daemon->dhcp_buff2, (unsigned char *)daemon->packet, 
+-                           hw_len, hw_type, clid_len, now, 0);
+-          
+-          if (strcmp(daemon->dhcp_buff, "*") !=  0)
+-            lease_set_hostname(lease, daemon->dhcp_buff, 0, get_domain(lease->addr), NULL);
+         }
+ #ifdef HAVE_DHCP6
+       else if (inet_pton(AF_INET6, daemon->namebuff, &addr.addr.addr6))
+         {
+           char *s = daemon->dhcp_buff2;
+           int lease_type = LEASE_NA;
+-          int iaid;
+           if (s[0] == 'T')
+             {
+@@ -116,23 +84,30 @@ void lease_init(time_t now)
+               s++;
+             }
+           
+-          iaid = strtoul(s, NULL, 10);
+-          
+           if ((lease = lease6_allocate(&addr.addr.addr6, lease_type)))
+             {
+-              lease_set_hwaddr(lease, NULL, (unsigned char *)daemon->packet, 0, 0, clid_len, now, 0);
+-              lease_set_iaid(lease, iaid);
+-              if (strcmp(daemon->dhcp_buff, "*") !=  0)
+-                lease_set_hostname(lease, daemon->dhcp_buff, 0, get_domain6((struct in6_addr *)lease->hwaddr), NULL);
++              lease_set_iaid(lease, strtoul(s, NULL, 10));
++              domain = get_domain6((struct in6_addr *)lease->hwaddr);
+             }
+         }
+ #endif
+       else
+-        break;
++        return 0;
+       if (!lease)
+         die (_("too many stored leases"), NULL, EC_MISC);
+-              
++
++      if (strcmp(daemon->packet, "*") != 0)
++        clid_len = parse_hex(daemon->packet, (unsigned char *)daemon->packet, 255, NULL, NULL);
++      
++      lease_set_hwaddr(lease, (unsigned char *)daemon->dhcp_buff2, (unsigned char *)daemon->packet, 
++                       hw_len, hw_type, clid_len, now, 0);
++      
++      if (strcmp(daemon->dhcp_buff, "*") !=  0)
++        lease_set_hostname(lease, daemon->dhcp_buff, 0, domain, NULL);
++
++      ei = atol(daemon->dhcp_buff3);
++
+ #ifdef HAVE_BROKEN_RTC
+       if (ei != 0)
+         lease->expires = (time_t)ei + now;
+@@ -148,7 +123,62 @@ void lease_init(time_t now)
+       /* set these correctly: the "old" events are generated later from
+          the startup synthesised SIGHUP. */
+       lease->flags &= ~(LEASE_NEW | LEASE_CHANGED);
++      
++      *daemon->dhcp_buff3 = *daemon->dhcp_buff2 = '\0';
+       }
++    
++    return (items == 0 || items == EOF);
++}
++
++void lease_init(time_t now)
++{
++  FILE *leasestream;
++
++  leases_left = daemon->dhcp_max;
++
++  if (option_bool(OPT_LEASE_RO))
++    {
++      /* run "<lease_change_script> init" once to get the
++       initial state of the database. If leasefile-ro is
++       set without a script, we just do without any
++       lease database. */
++#ifdef HAVE_SCRIPT
++      if (daemon->lease_change_command)
++      {
++        strcpy(daemon->dhcp_buff, daemon->lease_change_command);
++        strcat(daemon->dhcp_buff, " init");
++        leasestream = popen(daemon->dhcp_buff, "r");
++      }
++      else
++#endif
++      {
++          file_dirty = dns_dirty = 0;
++          return;
++        }
++
++    }
++  else
++    {
++      /* NOTE: need a+ mode to create file if it doesn't exist */
++      leasestream = daemon->lease_stream = fopen(daemon->lease_file, "a+");
++
++      if (!leasestream)
++      die(_("cannot open or create lease file %s: %s"), daemon->lease_file, EC_FILE);
++
++      /* a+ mode leaves pointer at end. */
++      rewind(leasestream);
++    }
++
++  if (leasestream)
++    {
++      if (!read_leases(now, leasestream))
++      my_syslog(MS_DHCP | LOG_ERR, _("failed to parse lease database, invalid line: %s %s %s %s ..."),
++                daemon->dhcp_buff3, daemon->dhcp_buff2,
++                daemon->namebuff, daemon->dhcp_buff);
++
++      if (ferror(leasestream))
++      die(_("failed to read lease file %s: %s"), daemon->lease_file, EC_FILE);
++    }
+   
+ #ifdef HAVE_SCRIPT
+   if (!daemon->lease_stream)
+@@ -162,6 +192,7 @@ void lease_init(time_t now)
+           errno = ENOENT;
+         else if (WEXITSTATUS(rc) == 126)
+           errno = EACCES;
++
+         die(_("cannot run lease-init script %s: %s"), daemon->lease_change_command, EC_FILE);
+       }
+       
+diff --git a/src/log.c b/src/log.c
+index 8e66629..5fc860b 100644
+--- a/src/log.c
++++ b/src/log.c
+@@ -288,7 +288,9 @@ void my_syslog(int priority, const char *format, ...)
+     func = "-tftp";
+   else if ((LOG_FACMASK & priority) == MS_DHCP)
+     func = "-dhcp";
+-      
++  else if ((LOG_FACMASK & priority) == MS_SCRIPT)
++    func = "-script";
++          
+ #ifdef LOG_PRI
+   priority = LOG_PRI(priority);
+ #else
+diff --git a/src/rfc3315.c b/src/rfc3315.c
+index 3f4d69c..a3715cd 100644
+--- a/src/rfc3315.c
++++ b/src/rfc3315.c
+@@ -1975,7 +1975,7 @@ static void log6_packet(struct state *state, char *type, struct in6_addr *addr,
+   if (addr)
+     {
+-      inet_ntop(AF_INET6, addr, daemon->dhcp_buff2, 255);
++      inet_ntop(AF_INET6, addr, daemon->dhcp_buff2, DHCP_BUFF_SZ - 1);
+       strcat(daemon->dhcp_buff2, " ");
+     }
+   else
+-- 
+2.9.3
+
diff --git a/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-dns-sleep-resume.patch b/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-dns-sleep-resume.patch
new file mode 100644 (file)
index 0000000..4271d8d
--- /dev/null
@@ -0,0 +1,119 @@
+From 2675f2061525bc954be14988d64384b74aa7bf8b Mon Sep 17 00:00:00 2001
+From: Beniamino Galvani <bgalvani@redhat.com>
+Date: Sun, 28 Aug 2016 20:44:05 +0100
+Subject: [PATCH] Handle binding upstream servers to an interface
+ (--server=1.2.3.4@eth0) when the named interface is destroyed and recreated
+ in the kernel.
+
+---
+ CHANGELOG     |  5 +++++
+ src/dnsmasq.h |  1 +
+ src/network.c | 31 +++++++++++++++++++++++++++++--
+ 3 files changed, 35 insertions(+), 2 deletions(-)
+
+diff --git a/src/dnsmasq.h b/src/dnsmasq.h
+index 27385a9..f239ce5 100644
+--- a/src/dnsmasq.h
++++ b/src/dnsmasq.h
+@@ -488,6 +488,7 @@ struct serverfd {
+   int fd;
+   union mysockaddr source_addr;
+   char interface[IF_NAMESIZE+1];
++  unsigned int ifindex, used;
+   struct serverfd *next;
+ };
+diff --git a/src/network.c b/src/network.c
+index e7722fd..ddf8d31 100644
+--- a/src/network.c
++++ b/src/network.c
+@@ -1204,6 +1204,7 @@ int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp)
+ static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
+ {
+   struct serverfd *sfd;
++  unsigned int ifindex = 0;
+   int errsave;
+   /* when using random ports, servers which would otherwise use
+@@ -1224,11 +1225,15 @@ static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
+       return NULL;
+ #endif
+     }
++
++  if (intname && strlen(intname) != 0)
++    ifindex = if_nametoindex(intname); /* index == 0 when not binding to an interface */
+       
+   /* may have a suitable one already */
+   for (sfd = daemon->sfds; sfd; sfd = sfd->next )
+     if (sockaddr_isequal(&sfd->source_addr, addr) &&
+-      strcmp(intname, sfd->interface) == 0)
++      strcmp(intname, sfd->interface) == 0 &&
++      ifindex == sfd->ifindex) 
+       return sfd;
+   
+   /* need to make a new one. */
+@@ -1250,11 +1255,13 @@ static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
+       errno = errsave;
+       return NULL;
+     }
+-    
++
+   strcpy(sfd->interface, intname); 
+   sfd->source_addr = *addr;
+   sfd->next = daemon->sfds;
++  sfd->ifindex = ifindex;
+   daemon->sfds = sfd;
++
+   return sfd; 
+ }
+@@ -1429,12 +1436,16 @@ void check_servers(void)
+ {
+   struct irec *iface;
+   struct server *serv;
++  struct serverfd *sfd, *tmp, **up;
+   int port = 0, count;
+   /* interface may be new since startup */
+   if (!option_bool(OPT_NOWILD))
+     enumerate_interfaces(0);
+   
++  for (sfd = daemon->sfds; sfd; sfd = sfd->next)
++    sfd->used = 0;
++
+ #ifdef HAVE_DNSSEC
+  /* Disable DNSSEC validation when using server=/domain/.... servers
+     unless there's a configured trust anchor. */
+@@ -1505,6 +1516,8 @@ void check_servers(void)
+             serv->flags |= SERV_MARK;
+             continue;
+           }
++
++        serv->sfd->used = 1;
+       }
+       
+       if (!(serv->flags & SERV_NO_REBIND) && !(serv->flags & SERV_LITERAL_ADDRESS))
+@@ -1547,6 +1560,20 @@ void check_servers(void)
+   if (count - 1 > SERVERS_LOGGED)
+     my_syslog(LOG_INFO, _("using %d more nameservers"), count - SERVERS_LOGGED - 1);
++  /* Remove unused sfds */
++  for (sfd = daemon->sfds, up = &daemon->sfds; sfd; sfd = tmp)
++    {
++       tmp = sfd->next;
++       if (!sfd->used) 
++      {
++        *up = sfd->next;
++        close(sfd->fd);
++        free(sfd);
++      } 
++      else
++      up = &sfd->next;
++    }
++  
+   cleanup_servers();
+ }
+-- 
+2.7.4
+
diff --git a/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-file_offset32.patch b/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-file_offset32.patch
new file mode 100644 (file)
index 0000000..f06996d
--- /dev/null
@@ -0,0 +1,12 @@
+diff --git a/src/helper.c b/src/helper.c
+index de31383..a843b41 100644
+--- a/src/helper.c
++++ b/src/helper.c
+@@ -14,7 +14,6 @@
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+-#include <stdio.h>
+ #include "dnsmasq.h"
+ #ifdef HAVE_SCRIPT
diff --git a/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-fix-crash-dns-resume.patch b/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-fix-crash-dns-resume.patch
new file mode 100644 (file)
index 0000000..2857de0
--- /dev/null
@@ -0,0 +1,29 @@
+From 16800ea072dd0cdf14d951c4bb8d2808b3dfe53d Mon Sep 17 00:00:00 2001
+From: Simon Kelley <simon@thekelleys.org.uk>
+Date: Tue, 30 Aug 2016 23:07:06 +0100
+Subject: [PATCH] Fix crash introduced in
+ 2675f2061525bc954be14988d64384b74aa7bf8b
+
+---
+ src/network.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/src/network.c b/src/network.c
+index ddf8d31..d87d08f 100644
+--- a/src/network.c
++++ b/src/network.c
+@@ -1516,8 +1516,9 @@ void check_servers(void)
+             serv->flags |= SERV_MARK;
+             continue;
+           }
+-
+-        serv->sfd->used = 1;
++        
++        if (serv->sfd)
++          serv->sfd->used = 1;
+       }
+       
+       if (!(serv->flags & SERV_NO_REBIND) && !(serv->flags & SERV_LITERAL_ADDRESS))
+-- 
+2.9.3
+
diff --git a/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-fix-dhcp-option-arrangements.patch b/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-fix-dhcp-option-arrangements.patch
new file mode 100644 (file)
index 0000000..7155b0f
--- /dev/null
@@ -0,0 +1,49 @@
+From 591ed1e90503817938ccf5f127e677a8dd48b6d8 Mon Sep 17 00:00:00 2001
+From: Simon Kelley <simon@thekelleys.org.uk>
+Date: Mon, 11 Jul 2016 18:18:42 +0100
+Subject: [PATCH] Fix bad behaviour with some DHCP option arrangements.
+
+The check that there's enough space to store the DHCP agent-id
+at the end of the packet could succeed when it should fail
+if the END option is in either of the oprion-overload areas.
+That could overwrite legit options in the request and cause
+bad behaviour. It's highly unlikely that any sane DHCP client
+would trigger this bug, and it's never been seen, but this
+fixes the problem.
+
+Also fix off-by-one in bounds checking of option processing.
+Worst case scenario on that is a read one byte beyond the
+end off a buffer with a crafted packet, and maybe therefore
+a SIGV crash if the memory after the buffer is not mapped.
+
+Thanks to Timothy Becker for spotting these.
+---
+ src/rfc2131.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/src/rfc2131.c b/src/rfc2131.c
+index b7c167e..8b99d4b 100644
+--- a/src/rfc2131.c
++++ b/src/rfc2131.c
+@@ -186,7 +186,8 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
+            be enough free space at the end of the packet to copy the option. */
+         unsigned char *sopt;
+         unsigned int total = option_len(opt) + 2;
+-        unsigned char *last_opt = option_find(mess, sz, OPTION_END, 0);
++        unsigned char *last_opt = option_find1(&mess->options[0] + sizeof(u32), ((unsigned char *)mess) + sz,
++                                               OPTION_END, 0);
+         if (last_opt && last_opt < end - total)
+           {
+             end -= total;
+@@ -1606,7 +1607,7 @@ static unsigned char *option_find1(unsigned char *p, unsigned char *end, int opt
+ {
+   while (1) 
+     {
+-      if (p > end)
++      if (p >= end)
+       return NULL;
+       else if (*p == OPTION_END)
+       return opt == OPTION_END ? p : NULL;
+-- 
+2.9.3
+
diff --git a/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-gita3303e196.patch b/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-gita3303e196.patch
new file mode 100644 (file)
index 0000000..a437848
--- /dev/null
@@ -0,0 +1,45 @@
+From 2c1aec1e979a209eb2f2b035314a8c973b4ac269 Mon Sep 17 00:00:00 2001
+From: Simon Kelley <simon@thekelleys.org.uk>
+Date: Thu, 7 Sep 2017 20:45:00 +0100
+Subject: [PATCH 7/9]     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 5bdc133..a8d0167 100644
+--- a/src/edns0.c
++++ b/src/edns0.c
+@@ -221,7 +221,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 9b464d3..0f8f462 100644
+--- a/src/forward.c
++++ b/src/forward.c
+@@ -1408,6 +1408,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
+-- 
+2.9.5
+
diff --git a/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-inotify.patch b/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-inotify.patch
new file mode 100644 (file)
index 0000000..6387d3f
--- /dev/null
@@ -0,0 +1,14 @@
+diff --git a/src/dnsmasq.c b/src/dnsmasq.c
+index e1d3bbd..99e5437 100644
+--- a/src/dnsmasq.c
++++ b/src/dnsmasq.c
+@@ -358,7 +358,8 @@ int main (int argc, char **argv)
+     }
+ #ifdef HAVE_INOTIFY
+-  if (daemon->port != 0 || daemon->dhcp || daemon->doing_dhcp6)
++  if ((daemon->port != 0 || daemon->dhcp || daemon->doing_dhcp6)
++      && (!option_bool(OPT_NO_RESOLV) || daemon->dynamic_dirs))
+     inotify_dnsmasq_init();
+   else
+     daemon->inotifyfd = -1;
diff --git a/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-label-man.patch b/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-label-man.patch
new file mode 100644 (file)
index 0000000..74514bd
--- /dev/null
@@ -0,0 +1,36 @@
+From 6eaafb18e56928881bae371ba8bb05ee93f55d54 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= <pemensik@redhat.com>
+Date: Tue, 14 Mar 2017 15:24:58 +0100
+Subject: [PATCH 2/2] Document real behaviour of labels with --interface
+
+---
+ man/dnsmasq.8 | 12 +++++++-----
+ 1 file changed, 7 insertions(+), 5 deletions(-)
+
+diff --git a/man/dnsmasq.8 b/man/dnsmasq.8
+index 523c823..6e93cf1 100644
+--- a/man/dnsmasq.8
++++ b/man/dnsmasq.8
+@@ -203,12 +203,14 @@ or
+ options are given dnsmasq listens on all available interfaces except any
+ given in
+ .B \--except-interface
+-options. IP alias interfaces (eg "eth1:0") cannot be used with
+-.B --interface
++options. IP alias interface names (eg "eth1:0") can be used only in
++.B \--bind-interfaces
+ or
+-.B --except-interface
+-options, use --listen-address instead. A simple wildcard, consisting
+-of a trailing '*', can be used in 
++.B \--bind-dynamic
++mode. Use
++.B \--listen-address
++in the default mode instead. A simple wildcard, consisting of a trailing '*',
++can be used in
+ .B \--interface 
+ and
+ .B \--except-interface
+-- 
+2.9.3
+
diff --git a/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-label-warning.patch b/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-label-warning.patch
new file mode 100644 (file)
index 0000000..7c156ab
--- /dev/null
@@ -0,0 +1,93 @@
+From c3d10a1132ada7baa80914f61abb720f94400465 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= <pemensik@redhat.com>
+Date: Tue, 14 Mar 2017 15:23:22 +0100
+Subject: [PATCH 1/2] Warn when using label in default mode
+
+---
+ src/dnsmasq.c |  2 ++
+ src/dnsmasq.h |  3 ++-
+ src/network.c | 13 +++++++++++++
+ 3 files changed, 17 insertions(+), 1 deletion(-)
+
+diff --git a/src/dnsmasq.c b/src/dnsmasq.c
+index 456b0e8..d2cc7cc 100644
+--- a/src/dnsmasq.c
++++ b/src/dnsmasq.c
+@@ -771,6 +771,8 @@ int main (int argc, char **argv)
+   if (option_bool(OPT_NOWILD))
+     warn_bound_listeners();
++  else if (!option_bool(OPT_CLEVERBIND))
++    warn_wild_labels();
+   warn_int_names();
+   
+diff --git a/src/dnsmasq.h b/src/dnsmasq.h
+index a27fbc1..6b44e53 100644
+--- a/src/dnsmasq.h
++++ b/src/dnsmasq.h
+@@ -522,7 +522,7 @@ struct ipsets {
+ struct irec {
+   union mysockaddr addr;
+   struct in_addr netmask; /* only valid for IPv4 */
+-  int tftp_ok, dhcp_ok, mtu, done, warned, dad, dns_auth, index, multicast_done, found;
++  int tftp_ok, dhcp_ok, mtu, done, warned, dad, dns_auth, index, multicast_done, found, label;
+   char *name; 
+   struct irec *next;
+ };
+@@ -1252,6 +1252,7 @@ int enumerate_interfaces(int reset);
+ void create_wildcard_listeners(void);
+ void create_bound_listeners(int die);
+ void warn_bound_listeners(void);
++void warn_wild_labels(void);
+ void warn_int_names(void);
+ int is_dad_listeners(void);
+ int iface_check(int family, struct all_addr *addr, char *name, int *auth_dns);
+diff --git a/src/network.c b/src/network.c
+index eb41624..e5ceb76 100644
+--- a/src/network.c
++++ b/src/network.c
+@@ -244,6 +244,7 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
+   int tftp_ok = !!option_bool(OPT_TFTP);
+   int dhcp_ok = 1;
+   int auth_dns = 0;
++  int is_label = 0;
+ #if defined(HAVE_DHCP) || defined(HAVE_TFTP)
+   struct iname *tmp;
+ #endif
+@@ -264,6 +265,8 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
+   
+   if (!label)
+     label = ifr.ifr_name;
++  else
++    is_label = strcmp(label, ifr.ifr_name);
+  
+   /* maintain a list of all addresses on all interfaces for --local-service option */
+   if (option_bool(OPT_LOCAL_SERVICE))
+@@ -482,6 +485,7 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
+       iface->found = 1;
+       iface->done = iface->multicast_done = iface->warned = 0;
+       iface->index = if_index;
++      iface->label = is_label;
+       if ((iface->name = whine_malloc(strlen(ifr.ifr_name)+1)))
+       {
+         strcpy(iface->name, ifr.ifr_name);
+@@ -1034,6 +1038,15 @@ void warn_bound_listeners(void)
+     my_syslog(LOG_WARNING, _("LOUD WARNING: use --bind-dynamic rather than --bind-interfaces to avoid DNS amplification attacks via these interface(s)")); 
+ }
++void warn_wild_labels(void)
++{
++  struct irec *iface;
++
++  for (iface = daemon->interfaces; iface; iface = iface->next)
++    if (iface->found && iface->name && iface->label)
++      my_syslog(LOG_WARNING, _("warning: using interface %s instead"), iface->name);
++}
++
+ void warn_int_names(void)
+ {
+   struct interface_name *intname;
+-- 
+2.9.3
+
diff --git a/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-misc-cleanups.patch b/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-misc-cleanups.patch
new file mode 100644 (file)
index 0000000..e8a2132
--- /dev/null
@@ -0,0 +1,63 @@
+From 3947ab0069e443e72debe26379b8517fac8f6e41 Mon Sep 17 00:00:00 2001
+From: Simon Kelley <simon@thekelleys.org.uk>
+Date: Mon, 25 Sep 2017 20:19:55 +0100
+Subject: [PATCH 8/9]     Misc code cleanups arising from Google analysis.    
+ No security impleications or CVEs.
+
+---
+ src/edns0.c   | 2 +-
+ src/rfc1035.c | 4 +++-
+ src/rfc2131.c | 2 +-
+ 3 files changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/src/edns0.c b/src/edns0.c
+index a8d0167..0552d38 100644
+--- a/src/edns0.c
++++ b/src/edns0.c
+@@ -159,7 +159,7 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
+             /* delete option if we're to replace it. */
+             p -= 4;
+             rdlen -= len + 4;
+-            memcpy(p, p+len+4, rdlen - i);
++            memmove(p, p+len+4, rdlen - i);
+             PUTSHORT(rdlen, lenp);
+             lenp -= 2;
+           }
+diff --git a/src/rfc1035.c b/src/rfc1035.c
+index 78410d6..917bac2 100644
+--- a/src/rfc1035.c
++++ b/src/rfc1035.c
+@@ -37,7 +37,7 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
+       /* end marker */
+       {
+         /* check that there are the correct no of bytes after the name */
+-        if (!CHECK_LEN(header, p, plen, extrabytes))
++        if (!CHECK_LEN(header, p1 ? p1 : p, plen, extrabytes))
+           return 0;
+         
+         if (isExtract)
+@@ -485,6 +485,8 @@ static unsigned char *do_doctor(unsigned char *p, int count, struct dns_header *
+           {
+             unsigned int i, len = *p1;
+             unsigned char *p2 = p1;
++            if ((p1 + len - p) >= rdlen)
++              return 0; /* bad packet */
+             /* make counted string zero-term  and sanitise */
+             for (i = 0; i < len; i++)
+               {
+diff --git a/src/rfc2131.c b/src/rfc2131.c
+index 75893a6..71d5846 100644
+--- a/src/rfc2131.c
++++ b/src/rfc2131.c
+@@ -155,7 +155,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
+         for (offset = 0; offset < (len - 5); offset += elen + 5)
+           {
+             elen = option_uint(opt, offset + 4 , 1);
+-            if (option_uint(opt, offset, 4) == BRDBAND_FORUM_IANA)
++            if (option_uint(opt, offset, 4) == BRDBAND_FORUM_IANA && offset + elen + 5 <= len)
+               {
+                 unsigned char *x = option_ptr(opt, offset + 5);
+                 unsigned char *y = option_ptr(opt, offset + elen + 5);
+-- 
+2.9.5
+
diff --git a/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-pftables.patch b/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-pftables.patch
new file mode 100644 (file)
index 0000000..fffd3a2
--- /dev/null
@@ -0,0 +1,149 @@
+From 396750cef533cf72c7e6a72e47a9c93e2e431cb7 Mon Sep 17 00:00:00 2001
+From: Simon Kelley <simon@thekelleys.org.uk>
+Date: Sat, 13 Aug 2016 22:34:11 +0100
+Subject: [PATCH] Refactor openBSD pftables code to remove blatant copyright
+ violation.
+
+---
+ src/tables.c | 90 +++++++++++++++++++++---------------------------------------
+ 1 file changed, 32 insertions(+), 58 deletions(-)
+
+diff --git a/src/tables.c b/src/tables.c
+index aae1252..4fa3487 100644
+--- a/src/tables.c
++++ b/src/tables.c
+@@ -53,52 +53,6 @@ static char *pfr_strerror(int errnum)
+     }
+ }
+-static int pfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags)
+-{
+-  struct pfioc_table io;
+-  
+-  if (size < 0 || (size && tbl == NULL)) 
+-    {
+-      errno = EINVAL;
+-      return (-1);
+-    }
+-  bzero(&io, sizeof io);
+-  io.pfrio_flags = flags;
+-  io.pfrio_buffer = tbl;
+-  io.pfrio_esize = sizeof(*tbl);
+-  io.pfrio_size = size;
+-  if (ioctl(dev, DIOCRADDTABLES, &io))
+-    return (-1);
+-  if (nadd != NULL)
+-    *nadd = io.pfrio_nadd;
+-  return (0);
+-}
+-
+-static int fill_addr(const struct all_addr *ipaddr, int flags, struct pfr_addr* addr) {
+-  if ( !addr || !ipaddr)
+-    {
+-      my_syslog(LOG_ERR, _("error: fill_addr missused"));
+-      return -1;
+-    }
+-  bzero(addr, sizeof(*addr));
+-#ifdef HAVE_IPV6
+-  if (flags & F_IPV6) 
+-    {
+-      addr->pfra_af = AF_INET6;
+-      addr->pfra_net = 0x80;
+-      memcpy(&(addr->pfra_ip6addr), &(ipaddr->addr), sizeof(struct in6_addr));
+-    } 
+-  else 
+-#endif
+-    {
+-      addr->pfra_af = AF_INET;
+-      addr->pfra_net = 0x20;
+-      addr->pfra_ip4addr.s_addr = ipaddr->addr.addr4.s_addr;
+-    }
+-  return 1;
+-}
+-
+-/*****************************************************************************/
+ void ipset_init(void) 
+ {
+@@ -111,14 +65,13 @@ void ipset_init(void)
+ }
+ int add_to_ipset(const char *setname, const struct all_addr *ipaddr,
+-                    int flags, int remove)
++               int flags, int remove)
+ {
+   struct pfr_addr addr;
+   struct pfioc_table io;
+   struct pfr_table table;
+-  int n = 0, rc = 0;
+-  if ( dev == -1 ) 
++  if (dev == -1) 
+     {
+       my_syslog(LOG_ERR, _("warning: no opened pf devices %s"), pf_device);
+       return -1;
+@@ -126,31 +79,52 @@ int add_to_ipset(const char *setname, const struct all_addr *ipaddr,
+   bzero(&table, sizeof(struct pfr_table));
+   table.pfrt_flags |= PFR_TFLAG_PERSIST;
+-  if ( strlen(setname) >= PF_TABLE_NAME_SIZE )
++  if (strlen(setname) >= PF_TABLE_NAME_SIZE)
+     {
+       my_syslog(LOG_ERR, _("error: cannot use table name %s"), setname);
+       errno = ENAMETOOLONG;
+       return -1;
+     }
+   
+-  if ( strlcpy(table.pfrt_name, setname,
+-               sizeof(table.pfrt_name)) >= sizeof(table.pfrt_name)) 
++  if (strlcpy(table.pfrt_name, setname,
++            sizeof(table.pfrt_name)) >= sizeof(table.pfrt_name)) 
+     {
+       my_syslog(LOG_ERR, _("error: cannot strlcpy table name %s"), setname);
+       return -1;
+     }
+   
+-  if ((rc = pfr_add_tables(&table, 1, &n, 0))) 
++  bzero(&io, sizeof io);
++  io.pfrio_flags = 0;
++  io.pfrio_buffer = &table;
++  io.pfrio_esize = sizeof(table);
++  io.pfrio_size = 1;
++  if (ioctl(dev, DIOCRADDTABLES, &io))
+     {
+-      my_syslog(LOG_WARNING, _("warning: pfr_add_tables: %s(%d)"),
+-              pfr_strerror(errno),rc);
++      my_syslog(LOG_WARNING, _("IPset: error:%s"), pfr_strerror(errno));
++      
+       return -1;
+     }
++  
+   table.pfrt_flags &= ~PFR_TFLAG_PERSIST;
+-  if (n)
++  if (io.pfrio_nadd)
+     my_syslog(LOG_INFO, _("info: table created"));
+-  
+-  fill_addr(ipaddr,flags,&addr);
++ 
++  bzero(&addr, sizeof(addr));
++#ifdef HAVE_IPV6
++  if (flags & F_IPV6) 
++    {
++      addr.pfra_af = AF_INET6;
++      addr.pfra_net = 0x80;
++      memcpy(&(addr.pfra_ip6addr), &(ipaddr->addr), sizeof(struct in6_addr));
++    } 
++  else 
++#endif
++    {
++      addr.pfra_af = AF_INET;
++      addr.pfra_net = 0x20;
++      addr.pfra_ip4addr.s_addr = ipaddr->addr.addr4.s_addr;
++    }
++
+   bzero(&io, sizeof(io));
+   io.pfrio_flags = 0;
+   io.pfrio_table = table;
+-- 
+2.9.3
+
diff --git a/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-underflow.patch b/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-underflow.patch
new file mode 100644 (file)
index 0000000..ac8188e
--- /dev/null
@@ -0,0 +1,74 @@
+From d4f2e0b8d8f0b5daa0d468f62a0d5f1df58ac325 Mon Sep 17 00:00:00 2001
+From: Doran Moppert <dmoppert@redhat.com>
+Date: Tue, 26 Sep 2017 14:48:20 +0930
+Subject: [PATCH 9/9]     google patch hand-applied
+
+---
+ src/edns0.c   | 10 +++++-----
+ src/forward.c |  4 ++++
+ src/rfc1035.c |  6 ++++--
+ 3 files changed, 13 insertions(+), 7 deletions(-)
+
+diff --git a/src/edns0.c b/src/edns0.c
+index 0552d38..bec4a36 100644
+--- a/src/edns0.c
++++ b/src/edns0.c
+@@ -212,11 +212,11 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
+       /* Copy back any options */
+       if (buff)
+       {
+-          if (p + rdlen > limit)
+-          {
+-            free(buff);
+-            return plen; /* Too big */
+-          }
++        if (p + rdlen > limit)
++        {
++          free(buff);
++          return plen; /* Too big */
++        }
+         memcpy(p, buff, rdlen);
+         free(buff);
+         p += rdlen;
+diff --git a/src/forward.c b/src/forward.c
+index 0f8f462..a729c06 100644
+--- a/src/forward.c
++++ b/src/forward.c
+@@ -1412,6 +1412,10 @@ void receive_query(struct listener *listen, time_t now)
+       udp_size = PACKETSZ; /* Sanity check - can't reduce below default. RFC 6891 6.2.3 */
+     }
++  // Make sure the udp size is not smaller than the incoming message so that we
++  // do not underflow
++  if (udp_size < n) udp_size = n;
++
+ #ifdef HAVE_AUTH
+   if (auth_dns)
+     {
+diff --git a/src/rfc1035.c b/src/rfc1035.c
+index 917bac2..ae65702 100644
+--- a/src/rfc1035.c
++++ b/src/rfc1035.c
+@@ -1182,8 +1182,8 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int
+   va_end(ap); /* clean up variable argument pointer */
+   
+   j = p - sav - 2;
+- /* this has already been checked against limit before */
+- PUTSHORT(j, sav);     /* Now, store real RDLength */
++  /* this has already been checked against limit before */
++  PUTSHORT(j, sav);     /* Now, store real RDLength */
+   
+   /* check for overflow of buffer */
+   if (limit && ((unsigned char *)limit - p) < 0)
+@@ -1243,6 +1243,8 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
+   int nxdomain = 0, auth = 1, trunc = 0, sec_data = 1;
+   struct mx_srv_record *rec;
+   size_t len;
++  // Make sure we do not underflow here too.
++  if (qlen > (limit - ((char *)header))) return 0;
+   
+   if (ntohs(header->ancount) != 0 ||
+       ntohs(header->nscount) != 0 ||
+-- 
+2.9.5
+
diff --git a/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-warning-fixes.patch b/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-2.76-warning-fixes.patch
new file mode 100644 (file)
index 0000000..8b0bea8
--- /dev/null
@@ -0,0 +1,60 @@
+From 13dee6f49e1d035b8069947be84ee8da2af0c420 Mon Sep 17 00:00:00 2001
+From: Simon Kelley <simon@thekelleys.org.uk>
+Date: Tue, 28 Feb 2017 16:51:58 +0000
+Subject: [PATCH] Compilation warning fixes.
+
+---
+ src/dbus.c   | 9 ++++-----
+ src/option.c | 3 ++-
+ 2 files changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/src/dbus.c b/src/dbus.c
+index 7e0d342..2e1a48e 100644
+--- a/src/dbus.c
++++ b/src/dbus.c
+@@ -549,17 +549,16 @@ static DBusMessage *dbus_add_lease(DBusMessage* message)
+     return dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
+                                        "Invalid IP address '%s'", ipaddr);
+    
+-  hw_len = parse_hex((char*)hwaddr, dhcp_chaddr, DHCP_CHADDR_MAX, NULL,
+-                   &hw_type);
++  hw_len = parse_hex((char*)hwaddr, dhcp_chaddr, DHCP_CHADDR_MAX, NULL, &hw_type);
+   if (hw_type == 0 && hw_len != 0)
+     hw_type = ARPHRD_ETHER;
+-
+-    lease_set_hwaddr(lease, dhcp_chaddr, clid, hw_len, hw_type,
++  
++  lease_set_hwaddr(lease, dhcp_chaddr, clid, hw_len, hw_type,
+                    clid_len, now, 0);
+   lease_set_expires(lease, expires, now);
+   if (hostname_len != 0)
+     lease_set_hostname(lease, hostname, 0, get_domain(lease->addr), NULL);
+-    
++  
+   lease_update_file(now);
+   lease_update_dns(0);
+diff --git a/src/option.c b/src/option.c
+index 4a5ef5f..e03b1e3 100644
+--- a/src/option.c
++++ b/src/option.c
+@@ -4089,7 +4089,7 @@ static void read_file(char *file, FILE *f, int hard_opt)
+     {
+       int white, i;
+       volatile int option = (hard_opt == LOPT_REV_SERV) ? 0 : hard_opt;
+-      char *errmess, *p, *arg = NULL, *start;
++      char *errmess, *p, *arg, *start;
+       size_t len;
+       /* Memory allocation failure longjmps here if mem_recover == 1 */ 
+@@ -4100,6 +4100,7 @@ static void read_file(char *file, FILE *f, int hard_opt)
+         mem_recover = 1;
+       }
+       
++      arg = NULL;
+       lineno++;
+       errmess = NULL;
+       
+-- 
+2.9.3
+
diff --git a/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-update-ipv6-leases-from-config.patch b/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq-update-ipv6-leases-from-config.patch
new file mode 100644 (file)
index 0000000..1304435
--- /dev/null
@@ -0,0 +1,83 @@
+From 1a91b72146893dab1cca1354dd3b0a8fa74d6b55 Mon Sep 17 00:00:00 2001
+From: Scott Little <scott.little@windriver.com>
+Date: Tue, 18 Oct 2016 13:07:56 -0400
+Subject: WRS: Patch22: dnsmasq-update-ipv6-leases-from-config.patch
+
+---
+ src/lease.c | 53 +++++++++++++++++++++++++++++++++++++++++++----------
+ 1 file changed, 43 insertions(+), 10 deletions(-)
+
+diff --git a/src/lease.c b/src/lease.c
+index 69e698c..bc56c47 100644
+--- a/src/lease.c
++++ b/src/lease.c
+@@ -210,6 +210,18 @@ void lease_init(time_t now)
+   dns_dirty = 1;
+ }
++static int lease_match_config_addr(struct dhcp_lease *lease, struct dhcp_config *config)
++{
++    if (!(lease->flags & (LEASE_TA | LEASE_NA)) && (config->flags & CONFIG_ADDR))
++      return (lease->addr.s_addr == config->addr.s_addr);
++#ifdef HAVE_DHCP6
++    else if ((lease->flags & (LEASE_TA | LEASE_NA)) && (config->flags & CONFIG_ADDR6))
++      return IN6_ARE_ADDR_EQUAL(&config->addr6, &lease->addr6);
++#endif
++    else
++      return 0;
++}
++
+ void lease_update_from_configs(void)
+ {
+   /* changes to the config may change current leases. */
+@@ -218,16 +230,37 @@ void lease_update_from_configs(void)
+   struct dhcp_config *config;
+   char *name;
+   
+-  for (lease = leases; lease; lease = lease->next)
+-    if (lease->flags & (LEASE_TA | LEASE_NA))
+-      continue;
+-    else if ((config = find_config(daemon->dhcp_conf, NULL, lease->clid, lease->clid_len, 
+-                                 lease->hwaddr, lease->hwaddr_len, lease->hwaddr_type, NULL)) && 
+-           (config->flags & CONFIG_NAME) &&
+-           (!(config->flags & CONFIG_ADDR) || config->addr.s_addr == lease->addr.s_addr))
+-      lease_set_hostname(lease, config->hostname, 1, get_domain(lease->addr), NULL);
+-    else if ((name = host_from_dns(lease->addr)))
+-      lease_set_hostname(lease, name, 1, get_domain(lease->addr), NULL); /* updates auth flag only */
++  for (lease = leases; lease; lease = lease->next) {
++    if (lease->flags & LEASE_TA)
++      continue;  /* we do not update temporary ipv6 leases */
++
++    config = find_config(daemon->dhcp_conf, NULL, lease->clid, lease->clid_len,
++                         (lease->hwaddr_len > 0 ? lease->hwaddr : NULL),
++                         lease->hwaddr_len, lease->hwaddr_type, NULL);
++    if (config)
++      {
++        if ((!(config->flags & (CONFIG_ADDR | CONFIG_ADDR6))) ||
++            lease_match_config_addr(lease, config))
++          {
++            /*
++             * Either we matched on a config that doesn't have an address in
++             * which case we'll just use the hostname, or we matched on a
++             * config that has the same IP address.
++             */
++            if (!(lease->flags & (LEASE_TA | LEASE_NA)))
++              lease_set_hostname(lease, config->hostname, 1, get_domain(lease->addr), NULL);
++#ifdef HAVE_DHCP6
++            else
++              lease_set_hostname(lease, config->hostname, 1, get_domain6(&lease->addr6), NULL);
++#endif
++            continue;  /* lease updated; move on to next lease */
++          }
++      }
++
++    /* attempt to find a matching DNS cache entry for an IPv4 entry */
++    if (!(lease->flags & (LEASE_TA | LEASE_NA)) && (name = host_from_dns(lease->addr)))
++       lease_set_hostname(lease, name, 1, get_domain(lease->addr), NULL); /* updates auth flag only */
++  }
+ }
+  
+ static void ourprintf(int *errp, char *format, ...)
+-- 
+2.7.4
+
diff --git a/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq.service b/meta-stx/recipes-support/dnsmasq/dnsmasq/stx/dnsmasq.service
new file mode 100644 (file)
index 0000000..572db30
--- /dev/null
@@ -0,0 +1,9 @@
+[Unit]
+Description=DNS caching server.
+After=network.target
+
+[Service]
+ExecStart=/usr/bin/dnsmasq -k
+
+[Install]
+WantedBy=multi-user.target
diff --git a/meta-stx/recipes-support/dnsmasq/dnsmasq_2.76.bb b/meta-stx/recipes-support/dnsmasq/dnsmasq_2.76.bb
new file mode 100644 (file)
index 0000000..3258f44
--- /dev/null
@@ -0,0 +1,135 @@
+SUMMARY = "Lightweight, easy to configure DNS forwarder and DHCP server"
+DESCRIPTION = "\
+Dnsmasq is lightweight, easy to configure DNS forwarder and DHCP server. \
+It is designed to provide DNS and, optionally, DHCP, to a small network. \
+It can serve the names of local machines which are not in the global \
+DNS. The DHCP server integrates with the DNS server and allows machines \
+with DHCP-allocated addresses to appear in the DNS with names configured \
+either in each host or in a central configuration file. Dnsmasq supports \
+static and dynamic DHCP leases and BOOTP for network booting of diskless \
+machines. \
+"
+HOMEPAGE = "http://www.thekelleys.org.uk/dnsmasq"
+SECTION = "net"
+
+# GPLv3 was added in version 2.41 as license option
+LICENSE = "GPLv2 | GPLv3"
+LIC_FILES_CHKSUM = "\
+    file://COPYING;md5=0636e73ff0215e8d672dc4c32c317bb3 \
+    file://COPYING-v3;md5=d32239bcb673463ab874e80d47fae504 \
+"
+
+SRC_URI = " \
+    http://www.thekelleys.org.uk/${BPN}/${BP}.tar.gz \
+    file://init \
+    file://dnsmasq-resolvconf.service \
+    file://lua.patch \
+    \
+    file://stx/dnsmasq-2.76-dns-sleep-resume.patch \
+    file://stx/dnsmasq-2.76-fix-dhcp-option-arrangements.patch \
+    file://stx/dnsmasq-2.76-pftables.patch \
+    file://stx/dnsmasq-2.76-fix-crash-dns-resume.patch \
+    file://stx/dnsmasq-2.76-warning-fixes.patch \
+    file://stx/dnsmasq-2.76-label-warning.patch \
+    file://stx/dnsmasq-2.76-label-man.patch \
+    file://stx/dnsmasq-2.76-coverity.patch \
+    file://stx/dnsmasq-2.76-dhcp-script-log.patch \
+    file://stx/dnsmasq-2.76-file_offset32.patch \
+    file://stx/dnsmasq-2.76-CVE-2017-14491.patch \
+    file://stx/dnsmasq-2.76-CVE-2017-14492.patch \
+    file://stx/dnsmasq-2.76-CVE-2017-14493.patch \
+    file://stx/dnsmasq-2.76-CVE-2017-14494.patch \
+    file://stx/dnsmasq-2.76-CVE-2017-14496.patch \
+    file://stx/dnsmasq-2.76-CVE-2017-14495.patch \
+    file://stx/dnsmasq-2.76-gita3303e196.patch \
+    file://stx/dnsmasq-2.76-underflow.patch \
+    file://stx/dnsmasq-2.76-misc-cleanups.patch \
+    file://stx/dnsmasq-2.76-CVE-2017-14491-2.patch \
+    file://stx/dnsmasq-2.76-inotify.patch \
+    file://stx/dnsmasq-update-ipv6-leases-from-config.patch \
+    file://stx/close-tftp-sockets-immediately.patch \
+    file://stx/dnsmasq.service \
+"
+SRC_URI[md5sum] = "6610f8233ca89b15a1bb47c788ffb84f"
+SRC_URI[sha256sum] = "777c4762d2fee3738a0380401f2d087b47faa41db2317c60660d69ad10a76c32"
+
+inherit pkgconfig update-rc.d systemd
+
+INITSCRIPT_NAME = "dnsmasq"
+INITSCRIPT_PARAMS = "defaults"
+
+PACKAGECONFIG ?= "dbus idn"
+PACKAGECONFIG[dbus] = ",,dbus"
+PACKAGECONFIG[idn] = ",,libidn"
+PACKAGECONFIG[conntrack] = ",,libnetfilter-conntrack"
+PACKAGECONFIG[lua] = ",,lua"
+PACKAGECONFIG[resolvconf] = ",,,resolvconf"
+
+EXTRA_OEMAKE = "\
+    'COPTS=${@bb.utils.contains('PACKAGECONFIG', 'dbus', '-DHAVE_DBUS', '', d)} \
+           ${@bb.utils.contains('PACKAGECONFIG', 'idn', '-DHAVE_IDN', '', d)} \
+           ${@bb.utils.contains('PACKAGECONFIG', 'conntrack', '-DHAVE_CONNTRACK', '', d)} \
+           ${@bb.utils.contains('PACKAGECONFIG', 'lua', '-DHAVE_LUASCRIPT', '', d)}' \
+    'CFLAGS=${CFLAGS}' \
+    'LDFLAGS=${LDFLAGS}' \
+"
+
+SRC_URI += "${@bb.utils.contains('PACKAGECONFIG', 'resolvconf', 'file://dnsmasq.resolvconf file://99_dnsmasq file://dnsmasq-resolvconf-helper', '', d)}"
+
+do_compile_append() {
+    # build dhcp_release
+    cd ${S}/contrib/lease-tools
+    oe_runmake
+}
+
+do_install () {
+    oe_runmake "PREFIX=${D}${prefix}" \
+               "BINDIR=${D}${bindir}" \
+               "MANDIR=${D}${mandir}" \
+               install
+
+    install -d ${D}${sysconfdir}/
+    install -d ${D}${sysconfdir}/init.d
+    install -d ${D}${sysconfdir}/dnsmasq.d
+
+    install -m 644 ${S}/dnsmasq.conf.example ${D}${sysconfdir}/dnsmasq.conf
+    cat << EOF >> ${D}${sysconfdir}/dnsmasq.conf
+
+# Include all files in /etc/dnsmasq.d except RPM backup files
+conf-dir=/etc/dnsmasq.d,.rpmnew,.rpmsave,.rpmorig
+EOF
+
+    install -m 755 ${WORKDIR}/init ${D}${sysconfdir}/init.d/dnsmasq
+
+    install -d ${D}${systemd_system_unitdir}
+
+    if [ "${@bb.utils.filter('PACKAGECONFIG', 'resolvconf', d)}" ]; then
+        install -m 0644 ${WORKDIR}/dnsmasq-resolvconf.service ${D}${systemd_system_unitdir}/dnsmasq.service
+    else
+        install -m 0644 ${WORKDIR}/stx/dnsmasq.service ${D}${systemd_system_unitdir}/dnsmasq.service
+    fi
+
+    install -m 0755 ${S}/contrib/lease-tools/dhcp_release ${D}${bindir}
+    install -m 0755 ${S}/contrib/lease-tools/dhcp_release6 ${D}${bindir}
+    install -m 0755 ${S}/contrib/lease-tools/dhcp_lease_time ${D}${bindir}
+
+    if [ "${@bb.utils.filter('PACKAGECONFIG', 'dbus', d)}" ]; then
+        install -d ${D}${sysconfdir}/dbus-1/system.d
+        install -m 644 dbus/dnsmasq.conf ${D}${sysconfdir}/dbus-1/system.d/
+    fi
+    if [ "${@bb.utils.filter('PACKAGECONFIG', 'resolvconf', d)}" ]; then
+        install -d ${D}${sysconfdir}/resolvconf/update.d/
+        install -m 0755 ${WORKDIR}/dnsmasq.resolvconf ${D}${sysconfdir}/resolvconf/update.d/dnsmasq
+
+        install -d ${D}${sysconfdir}/default/volatiles
+        install -m 0644 ${WORKDIR}/99_dnsmasq ${D}${sysconfdir}/default/volatiles
+        install -m 0755 ${WORKDIR}/dnsmasq-resolvconf-helper ${D}${bindir}
+    fi
+}
+
+CONFFILES_${PN} = "${sysconfdir}/dnsmasq.conf"
+
+RPROVIDES_${PN} += "${PN}-systemd"
+RREPLACES_${PN} += "${PN}-systemd"
+RCONFLICTS_${PN} += "${PN}-systemd"
+SYSTEMD_SERVICE_${PN} = "dnsmasq.service"