diff --git a/.dnsmasq.metadata b/.dnsmasq.metadata
new file mode 100644
index 0000000..c26dbef
--- /dev/null
+++ b/.dnsmasq.metadata
@@ -0,0 +1 @@
+3cb264e2505a06705203d616883db5ee6ac00026 SOURCES/dnsmasq-2.76.tar.gz
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..1dd44d3
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+SOURCES/dnsmasq-2.76.tar.gz
diff --git a/SOURCES/dnsmasq-2.76-CVE-2017-14491-2.patch b/SOURCES/dnsmasq-2.76-CVE-2017-14491-2.patch
new file mode 100644
index 0000000..3935566
--- /dev/null
+++ b/SOURCES/dnsmasq-2.76-CVE-2017-14491-2.patch
@@ -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/SOURCES/dnsmasq-2.76-CVE-2017-14491.patch b/SOURCES/dnsmasq-2.76-CVE-2017-14491.patch
new file mode 100644
index 0000000..4d8dbd5
--- /dev/null
+++ b/SOURCES/dnsmasq-2.76-CVE-2017-14491.patch
@@ -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/SOURCES/dnsmasq-2.76-CVE-2017-14492.patch b/SOURCES/dnsmasq-2.76-CVE-2017-14492.patch
new file mode 100644
index 0000000..b381148
--- /dev/null
+++ b/SOURCES/dnsmasq-2.76-CVE-2017-14492.patch
@@ -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/SOURCES/dnsmasq-2.76-CVE-2017-14493.patch b/SOURCES/dnsmasq-2.76-CVE-2017-14493.patch
new file mode 100644
index 0000000..5634803
--- /dev/null
+++ b/SOURCES/dnsmasq-2.76-CVE-2017-14493.patch
@@ -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/SOURCES/dnsmasq-2.76-CVE-2017-14494.patch b/SOURCES/dnsmasq-2.76-CVE-2017-14494.patch
new file mode 100644
index 0000000..3743a32
--- /dev/null
+++ b/SOURCES/dnsmasq-2.76-CVE-2017-14494.patch
@@ -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/SOURCES/dnsmasq-2.76-CVE-2017-14495.patch b/SOURCES/dnsmasq-2.76-CVE-2017-14495.patch
new file mode 100644
index 0000000..8ca5d0f
--- /dev/null
+++ b/SOURCES/dnsmasq-2.76-CVE-2017-14495.patch
@@ -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/SOURCES/dnsmasq-2.76-CVE-2017-14496.patch b/SOURCES/dnsmasq-2.76-CVE-2017-14496.patch
new file mode 100644
index 0000000..f32b919
--- /dev/null
+++ b/SOURCES/dnsmasq-2.76-CVE-2017-14496.patch
@@ -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/SOURCES/dnsmasq-2.76-coverity.patch b/SOURCES/dnsmasq-2.76-coverity.patch
new file mode 100644
index 0000000..87f41a0
--- /dev/null
+++ b/SOURCES/dnsmasq-2.76-coverity.patch
@@ -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/SOURCES/dnsmasq-2.76-dhcp-script-log.patch b/SOURCES/dnsmasq-2.76-dhcp-script-log.patch
new file mode 100644
index 0000000..ac26258
--- /dev/null
+++ b/SOURCES/dnsmasq-2.76-dhcp-script-log.patch
@@ -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/SOURCES/dnsmasq-2.76-dns-sleep-resume.patch b/SOURCES/dnsmasq-2.76-dns-sleep-resume.patch
new file mode 100644
index 0000000..4271d8d
--- /dev/null
+++ b/SOURCES/dnsmasq-2.76-dns-sleep-resume.patch
@@ -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/SOURCES/dnsmasq-2.76-dnssec-cache.patch b/SOURCES/dnsmasq-2.76-dnssec-cache.patch
new file mode 100644
index 0000000..8752c89
--- /dev/null
+++ b/SOURCES/dnsmasq-2.76-dnssec-cache.patch
@@ -0,0 +1,548 @@
+From b09d07ee2aa891c5b8dd2469c4a73c9dd61e2384 Mon Sep 17 00:00:00 2001
+From: Simon Kelley <simon@thekelleys.org.uk>
+Date: Wed, 25 Oct 2017 17:48:19 +0100
+Subject: [PATCH 1/2] Fix caching logic for validated answers.
+
+The current logic is naive in the case that there is more than
+one RRset in an answer (Typically, when a non-CNAME query is answered
+by one or more CNAME RRs, and then then an answer RRset.)
+
+If all the RRsets validate, then they are cached and marked as validated,
+but if any RRset doesn't validate, then the AD flag is not set (good) and
+ALL the RRsets are cached marked as not validated.
+
+This breaks when, eg, the answer contains a validated CNAME, pointing
+to a non-validated answer. A subsequent query for the CNAME without do
+will get an answer with the AD flag wrongly reset, and worse, the same
+query with do will get a cached answer without RRSIGS, rather than
+being forwarded.
+
+The code now records the validation of individual RRsets and that
+is used to correctly set the "validated" bits in the cache entries.
+
+(cherry picked from commit a6004d7f17687ac2455f724d0b57098c413f128d)
+---
+ src/dnsmasq.c |   2 +
+ src/dnsmasq.h |   5 +-
+ src/dnssec.c  | 174 +++++++++++++++++++++++++++++---------------------
+ src/forward.c |  19 ++++--
+ src/rfc1035.c |  58 ++++++++++++-----
+ 5 files changed, 162 insertions(+), 96 deletions(-)
+
+diff --git a/src/dnsmasq.c b/src/dnsmasq.c
+index 50b2029..f3d2671 100644
+--- a/src/dnsmasq.c
++++ b/src/dnsmasq.c
+@@ -118,6 +118,8 @@ int main (int argc, char **argv)
+       daemon->namebuff = safe_malloc(MAXDNAME * 2);
+       daemon->keyname = safe_malloc(MAXDNAME * 2);
+       daemon->workspacename = safe_malloc(MAXDNAME * 2);
++      /* one char flag per possible RR in answer section. */
++      daemon->rr_status = safe_malloc(256);
+     }
+ #endif
+ 
+diff --git a/src/dnsmasq.h b/src/dnsmasq.h
+index 5a68162..89d138a 100644
+--- a/src/dnsmasq.h
++++ b/src/dnsmasq.h
+@@ -1006,6 +1006,7 @@ extern struct daemon {
+ #ifdef HAVE_DNSSEC
+   char *keyname; /* MAXDNAME size buffer */
+   char *workspacename; /* ditto */
++  char *rr_status; /* 256 bytes as flags for individual RRs */
+ #endif
+   unsigned int local_answer, queries_forwarded, auth_answer;
+   struct frec *frec_list;
+@@ -1118,7 +1119,7 @@ size_t setup_reply(struct dns_header *header, size_t  qlen,
+ 		   unsigned long local_ttl);
+ int extract_addresses(struct dns_header *header, size_t qlen, char *namebuff, 
+ 		      time_t now, char **ipsets, int is_sign, int checkrebind,
+-		      int no_cache, int secure, int *doctored);
++		      int no_cache_dnssec, int secure, int *doctored, char *rr_status);
+ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,  
+ 		      struct in_addr local_addr, struct in_addr local_netmask, 
+ 		      time_t now, int ad_reqd, int do_bit, int have_pseudoheader);
+@@ -1151,7 +1152,7 @@ size_t dnssec_generate_query(struct dns_header *header, unsigned char *end, char
+ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t n, char *name, char *keyname, int class);
+ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class);
+ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int *class,
+-			  int check_unsigned, int *neganswer, int *nons);
++			  int check_unsigned, int *neganswer, int *nons, char *rr_status);
+ int dnskey_keytag(int alg, int flags, unsigned char *rdata, int rdlen);
+ size_t filter_rrsigs(struct dns_header *header, size_t plen);
+ unsigned char* hash_questions(struct dns_header *header, size_t plen, char *name);
+diff --git a/src/dnssec.c b/src/dnssec.c
+index f45c804..3121eb1 100644
+--- a/src/dnssec.c
++++ b/src/dnssec.c
+@@ -1177,8 +1177,7 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
+   if (qtype != T_DS || qclass != class)
+     rc = STAT_BOGUS;
+   else
+-    rc = dnssec_validate_reply(now, header, plen, name, keyname, NULL, 0, &neganswer, &nons);
+-  /* Note dnssec_validate_reply() will have cached positive answers */
++    rc = dnssec_validate_reply(now, header, plen, name, keyname, NULL, 0, &neganswer, &nons, NULL);
+   
+   if (rc == STAT_INSECURE)
+     rc = STAT_BOGUS;
+@@ -1962,18 +1961,25 @@ static int zone_status(char *name, int class, char *keyname, time_t now)
+    STAT_INSECURE at least one RRset not validated, because in unsigned zone.
+    STAT_BOGUS    signature is wrong, bad packet, no validation where there should be.
+    STAT_NEED_KEY need DNSKEY to complete validation (name is returned in keyname, class in *class)
+-   STAT_NEED_DS  need DS to complete validation (name is returned in keyname) 
++   STAT_NEED_DS  need DS to complete validation (name is returned in keyname)
++
++   If non-NULL, rr_status points to a char array which corressponds to the RRs in the 
++   answer section (only). This is set to 1 for each RR which is validated, and 0 for any which aren't.
+ */
+ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, 
+-			  int *class, int check_unsigned, int *neganswer, int *nons)
++			  int *class, int check_unsigned, int *neganswer, int *nons, char *rr_status)
+ {
+   static unsigned char **targets = NULL;
+   static int target_sz = 0;
+ 
+   unsigned char *ans_start, *p1, *p2;
+-  int type1, class1, rdlen1, type2, class2, rdlen2, qclass, qtype, targetidx;
++  int type1, class1, rdlen1 = 0, type2, class2, rdlen2, qclass, qtype, targetidx;
+   int i, j, rc;
++  int secure = STAT_SECURE;
+ 
++  if (rr_status)
++    memset(rr_status, 0, ntohs(header->ancount));
++  
+   if (neganswer)
+     *neganswer = 0;
+   
+@@ -2030,7 +2036,10 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
+   
+   for (p1 = ans_start, i = 0; i < ntohs(header->ancount) + ntohs(header->nscount); i++)
+     {
+-      if (!extract_name(header, plen, &p1, name, 1, 10))
++       if (i != 0 && !ADD_RDLEN(header, p1, plen, rdlen1))
++	 return STAT_BOGUS;
++
++       if (!extract_name(header, plen, &p1, name, 1, 10))
+ 	return STAT_BOGUS; /* bad packet */
+       
+       GETSHORT(type1, p1);
+@@ -2039,106 +2048,125 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
+       GETSHORT(rdlen1, p1);
+       
+       /* Don't try and validate RRSIGs! */
+-      if (type1 != T_RRSIG)
++      if (type1 == T_RRSIG)
++	continue;
++      
++      /* Check if we've done this RRset already */
++      for (p2 = ans_start, j = 0; j < i; j++)
+ 	{
+-	  /* Check if we've done this RRset already */
+-	  for (p2 = ans_start, j = 0; j < i; j++)
+-	    {
+-	      if (!(rc = extract_name(header, plen, &p2, name, 0, 10)))
+-		return STAT_BOGUS; /* bad packet */
+-	      
+-	      GETSHORT(type2, p2);
+-	      GETSHORT(class2, p2);
+-	      p2 += 4; /* TTL */
+-	      GETSHORT(rdlen2, p2);
+-	      
+-	      if (type2 == type1 && class2 == class1 && rc == 1)
+-		break; /* Done it before: name, type, class all match. */
+-	      
+-	      if (!ADD_RDLEN(header, p2, plen, rdlen2))
+-		return STAT_BOGUS;
+-	    }
++	  if (!(rc = extract_name(header, plen, &p2, name, 0, 10)))
++	    return STAT_BOGUS; /* bad packet */
++	  
++	  GETSHORT(type2, p2);
++	  GETSHORT(class2, p2);
++	  p2 += 4; /* TTL */
++	  GETSHORT(rdlen2, p2);
++	  
++	  if (type2 == type1 && class2 == class1 && rc == 1)
++	    break; /* Done it before: name, type, class all match. */
+ 	  
++	  if (!ADD_RDLEN(header, p2, plen, rdlen2))
++	    return STAT_BOGUS;
++	}
++      
++      if (j != i)
++	{
++	  /* Done already: copy the validation status */
++	  if (rr_status && (i < ntohs(header->ancount)))
++	    rr_status[i] = rr_status[j];
++	}
++      else
++	{
+ 	  /* Not done, validate now */
+-	  if (j == i)
++	  int sigcnt, rrcnt;
++	  char *wildname;
++	  
++	  if (!explore_rrset(header, plen, class1, type1, name, keyname, &sigcnt, &rrcnt))
++	    return STAT_BOGUS;
++	  
++	  /* No signatures for RRset. We can be configured to assume this is OK and return a INSECURE result. */
++	  if (sigcnt == 0)
+ 	    {
+-	      int sigcnt, rrcnt;
+-	      char *wildname;
+-	      
+-	      if (!explore_rrset(header, plen, class1, type1, name, keyname, &sigcnt, &rrcnt))
+-		return STAT_BOGUS;
+-
+-	      /* No signatures for RRset. We can be configured to assume this is OK and return a INSECURE result. */
+-	      if (sigcnt == 0)
++	      if (check_unsigned)
+ 		{
+-		  if (check_unsigned)
+-		    {
+-		      rc = zone_status(name, class1, keyname, now);
+-		      if (rc == STAT_SECURE)
+-			rc = STAT_BOGUS;
+-		       if (class)
+-			 *class = class1; /* Class for NEED_DS or NEED_KEY */
+-		    }
+-		  else 
+-		    rc = STAT_INSECURE; 
+-		  
+-		  return rc;
++		  rc = zone_status(name, class1, keyname, now);
++		  if (rc == STAT_SECURE)
++		    rc = STAT_BOGUS;
++		  if (class)
++		    *class = class1; /* Class for NEED_DS or NEED_KEY */
+ 		}
++	      else 
++		rc = STAT_INSECURE; 
+ 	      
++	      if (rc != STAT_INSECURE)
++		return rc;
++	    }
++	  else
++	    {
+ 	      /* explore_rrset() gives us key name from sigs in keyname.
+ 		 Can't overwrite name here. */
+ 	      strcpy(daemon->workspacename, keyname);
+ 	      rc = zone_status(daemon->workspacename, class1, keyname, now);
+-
+-	      if (rc != STAT_SECURE)
++	      
++	      if (rc == STAT_BOGUS || rc == STAT_NEED_KEY || rc == STAT_NEED_DS)
+ 		{
+ 		  /* Zone is insecure, don't need to validate RRset */
+ 		  if (class)
+ 		    *class = class1; /* Class for NEED_DS or NEED_KEY */
+ 		  return rc;
+-		} 
+-	      
+-	      rc = validate_rrset(now, header, plen, class1, type1, sigcnt, rrcnt, name, keyname, &wildname, NULL, 0, 0, 0);
++		}
+ 	      
+-	      if (rc == STAT_BOGUS || rc == STAT_NEED_KEY || rc == STAT_NEED_DS)
+-		{
+-		  if (class)
+-		    *class = class1; /* Class for DS or DNSKEY */
+-		  return rc;
+-		} 
+-	      else 
++	      /* Zone is insecure, don't need to validate RRset */
++	      if (rc == STAT_SECURE)
+ 		{
++		  rc = validate_rrset(now, header, plen, class1, type1, sigcnt,
++				      rrcnt, name, keyname, &wildname, NULL, 0, 0, 0);
++		  
++		  if (rc == STAT_BOGUS || rc == STAT_NEED_KEY || rc == STAT_NEED_DS)
++		    {
++		      if (class)
++			*class = class1; /* Class for DS or DNSKEY */
++		      return rc;
++		    } 
++		  
+ 		  /* rc is now STAT_SECURE or STAT_SECURE_WILDCARD */
+-		 
++		  
++		  /* Note that RR is validated */
++		   if (rr_status && (i < ntohs(header->ancount)))
++		     rr_status[i] = 1;
++		   
+ 		  /* Note if we've validated either the answer to the question
+ 		     or the target of a CNAME. Any not noted will need NSEC or
+ 		     to be in unsigned space. */
+-
+ 		  for (j = 0; j <targetidx; j++)
+ 		    if ((p2 = targets[j]))
+ 		      {
+-			if (!(rc = extract_name(header, plen, &p2, name, 0, 10)))
++			int rc1;
++			if (!(rc1 = extract_name(header, plen, &p2, name, 0, 10)))
+ 			  return STAT_BOGUS; /* bad packet */
+ 			
+-			if (class1 == qclass && rc == 1 && (type1 == T_CNAME || type1 == qtype || qtype == T_ANY ))
++			if (class1 == qclass && rc1 == 1 && (type1 == T_CNAME || type1 == qtype || qtype == T_ANY ))
+ 			  targets[j] = NULL;
+ 		      }
+-			    
+-		   /* An attacker replay a wildcard answer with a different
+-		      answer and overlay a genuine RR. To prove this
+-		      hasn't happened, the answer must prove that
+-		      the gennuine record doesn't exist. Check that here. 
+-		      Note that we may not yet have validated the NSEC/NSEC3 RRsets. 
+-		      That's not a problem since if the RRsets later fail
+-		      we'll return BOGUS then. */
+-		  if (rc == STAT_SECURE_WILDCARD && !prove_non_existence(header, plen, keyname, name, type1, class1, wildname, NULL))
++		  
++		  /* An attacker replay a wildcard answer with a different
++		     answer and overlay a genuine RR. To prove this
++		     hasn't happened, the answer must prove that
++		     the genuine record doesn't exist. Check that here. 
++		     Note that we may not yet have validated the NSEC/NSEC3 RRsets. 
++		     That's not a problem since if the RRsets later fail
++		     we'll return BOGUS then. */
++		  if (rc == STAT_SECURE_WILDCARD &&
++		      !prove_non_existence(header, plen, keyname, name, type1, class1, wildname, NULL))
+ 		    return STAT_BOGUS;
++
++		  rc = STAT_SECURE;
+ 		}
+ 	    }
+ 	}
+ 
+-      if (!ADD_RDLEN(header, p1, plen, rdlen1))
+-	return STAT_BOGUS;
++      if (rc == STAT_INSECURE)
++	secure = STAT_INSECURE;
+     }
+ 
+   /* OK, all the RRsets validate, now see if we have a missing answer or CNAME target. */
+@@ -2172,7 +2200,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
+ 	  }
+       }
+   
+-  return STAT_SECURE;
++  return secure;
+ }
+ 
+ 
+diff --git a/src/forward.c b/src/forward.c
+index a729c06..245c448 100644
+--- a/src/forward.c
++++ b/src/forward.c
+@@ -561,7 +561,8 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
+   char **sets = 0;
+   int munged = 0, is_sign;
+   size_t plen; 
+-
++  char *rr_status = NULL;
++  
+   (void)ad_reqd;
+   (void)do_bit;
+   (void)bogusanswer;
+@@ -651,6 +652,11 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
+ 	server->flags |= SERV_WARNED_RECURSIVE;
+     }  
+ 
++#ifdef HAVE_DNSSEC
++  if (option_bool(OPT_DNSSEC_VALID))
++    rr_status = daemon->rr_status;
++#endif
++
+   if (daemon->bogus_addr && RCODE(header) != NXDOMAIN &&
+       check_for_bogus_wildcard(header, n, daemon->namebuff, daemon->bogus_addr, now))
+     {
+@@ -676,7 +682,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
+ 	  cache_secure = 0;
+ 	}
+       
+-      if (extract_addresses(header, n, daemon->namebuff, now, sets, is_sign, check_rebind, no_cache, cache_secure, &doctored))
++      if (extract_addresses(header, n, daemon->namebuff, now, sets, is_sign, check_rebind, no_cache, cache_secure, &doctored, rr_status))
+ 	{
+ 	  my_syslog(LOG_WARNING, _("possible DNS-rebind attack detected: %s"), daemon->namebuff);
+ 	  munged = 1;
+@@ -856,7 +862,7 @@ void reply_query(int fd, int family, time_t now)
+   if (forward->forwardall == 0 || --forward->forwardall == 1 || RCODE(header) != REFUSED)
+     {
+       int check_rebind = 0, no_cache_dnssec = 0, cache_secure = 0, bogusanswer = 0;
+-
++      
+       if (option_bool(OPT_NO_REBIND))
+ 	check_rebind = !(forward->flags & FREC_NOREBIND);
+       
+@@ -896,7 +902,8 @@ void reply_query(int fd, int family, time_t now)
+ 		    status = dnssec_validate_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
+ 		  else
+ 		    status = dnssec_validate_reply(now, header, n, daemon->namebuff, daemon->keyname, &forward->class, 
+-						   option_bool(OPT_DNSSEC_NO_SIGN), NULL, NULL);
++						   option_bool(OPT_DNSSEC_NO_SIGN) && (server->flags & SERV_DO_DNSSEC),
++						   NULL, NULL, daemon->rr_status);
+ 		}
+ 	      
+ 	      /* Can't validate, as we're missing key data. Put this
+@@ -1480,7 +1487,9 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si
+       else if (status == STAT_NEED_DS)
+ 	new_status = dnssec_validate_ds(now, header, n, name, keyname, class);
+       else 
+-	new_status = dnssec_validate_reply(now, header, n, name, keyname, &class, option_bool(OPT_DNSSEC_NO_SIGN), NULL, NULL);
++	new_status = dnssec_validate_reply(now, header, n, name, keyname, &class,
++					   option_bool(OPT_DNSSEC_NO_SIGN) && (server->flags & SERV_DO_DNSSEC),
++					   NULL, NULL, daemon->rr_status);
+       
+       if (new_status != STAT_NEED_DS && new_status != STAT_NEED_KEY)
+ 	break;
+diff --git a/src/rfc1035.c b/src/rfc1035.c
+index f78b5cb..607412f 100644
+--- a/src/rfc1035.c
++++ b/src/rfc1035.c
+@@ -571,7 +571,8 @@ static int find_soa(struct dns_header *header, size_t qlen, char *name, int *doc
+    expired and cleaned out that way. 
+    Return 1 if we reject an address because it look like part of dns-rebinding attack. */
+ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t now, 
+-		      char **ipsets, int is_sign, int check_rebind, int no_cache_dnssec, int secure, int *doctored)
++		      char **ipsets, int is_sign, int check_rebind, int no_cache_dnssec,
++		      int secure, int *doctored, char *rr_status)
+ {
+   unsigned char *p, *p1, *endrr, *namep;
+   int i, j, qtype, qclass, aqtype, aqclass, ardlen, res, searched_soa = 0;
+@@ -582,6 +583,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
+ #else
+   (void)ipsets; /* unused */
+ #endif
++
+   
+   cache_start_insert();
+ 
+@@ -590,10 +592,16 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
+     {
+       searched_soa = 1;
+       ttl = find_soa(header, qlen, name, doctored);
+-#ifdef HAVE_DNSSEC
+-      if (*doctored && secure)
+-	return 0;
+-#endif
++
++      if (*doctored)
++	{
++	  if (secure)
++	    return 0;
++	  if (rr_status)
++	    for (i = 0; i < ntohs(header->ancount); i++)
++	      if (rr_status[i])
++		return 0;
++	}
+     }
+   
+   /* go through the questions. */
+@@ -604,7 +612,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
+       int found = 0, cname_count = CNAME_CHAIN;
+       struct crec *cpp = NULL;
+       int flags = RCODE(header) == NXDOMAIN ? F_NXDOMAIN : 0;
+-      int secflag = secure ?  F_DNSSECOK : 0;
++      int cname_short = 0;
+       unsigned long cttl = ULONG_MAX, attl;
+ 
+       namep = p;
+@@ -632,8 +640,9 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
+ 	      if (!(p1 = skip_questions(header, qlen)))
+ 		return 0;
+ 	      
+-	      for (j = ntohs(header->ancount); j != 0; j--) 
++	      for (j = 0; j < ntohs(header->ancount); j++) 
+ 		{
++		  int secflag = 0;
+ 		  unsigned char *tmp = namep;
+ 		  /* the loop body overwrites the original name, so get it back here. */
+ 		  if (!extract_name(header, qlen, &tmp, name, 1, 0) ||
+@@ -659,11 +668,21 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
+ 		    {
+ 		      if (!extract_name(header, qlen, &p1, name, 1, 0))
+ 			return 0;
+-		      
++
++		      if (rr_status && rr_status[j])
++			{
++			  /* validated RR anywhere in CNAME chain, don't cache. */
++			  if (cname_short || aqtype == T_CNAME)
++			    return 0;
++
++			  secflag = F_DNSSECOK;
++			}
++
+ 		      if (aqtype == T_CNAME)
+ 			{
+-			  if (!cname_count-- || secure)
+-			    return 0; /* looped CNAMES, or DNSSEC, which we can't cache. */
++			  if (!cname_count--)
++			    return 0; /* looped CNAMES, we can't cache. */
++			  cname_short = 1;
+ 			  goto cname_loop;
+ 			}
+ 		      
+@@ -685,7 +704,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
+ 		  ttl = find_soa(header, qlen, NULL, doctored);
+ 		}
+ 	      if (ttl)
+-		cache_insert(NULL, &addr, now, ttl, name_encoding | F_REVERSE | F_NEG | flags | secflag);	
++		cache_insert(NULL, &addr, now, ttl, name_encoding | F_REVERSE | F_NEG | flags | (secure ?  F_DNSSECOK : 0));	
+ 	    }
+ 	}
+       else
+@@ -713,8 +732,10 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
+ 	  if (!(p1 = skip_questions(header, qlen)))
+ 	    return 0;
+ 	  
+-	  for (j = ntohs(header->ancount); j != 0; j--) 
++	  for (j = 0; j < ntohs(header->ancount); j++) 
+ 	    {
++	      int secflag = 0;
++	      
+ 	      if (!(res = extract_name(header, qlen, &p1, name, 0, 10)))
+ 		return 0; /* bad packet */
+ 	      
+@@ -731,6 +752,10 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
+ 	      
+ 	      if (aqclass == C_IN && res != 2 && (aqtype == T_CNAME || aqtype == qtype))
+ 		{
++#ifdef HAVE_DNSSEC
++		  if (rr_status && rr_status[j])
++		      secflag = F_DNSSECOK;
++#endif		  
+ 		  if (aqtype == T_CNAME)
+ 		    {
+ 		      if (!cname_count--)
+@@ -822,7 +847,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
+ 		 pointing at this, inherit its TTL */
+ 	      if (ttl || cpp)
+ 		{
+-		  newc = cache_insert(name, NULL, now, ttl ? ttl : cttl, F_FORWARD | F_NEG | flags | secflag);	
++		  newc = cache_insert(name, NULL, now, ttl ? ttl : cttl, F_FORWARD | F_NEG | flags | (secure ? F_DNSSECOK : 0));	
+ 		  if (newc && cpp)
+ 		    {
+ 		      cpp->addr.cname.target.cache = newc;
+@@ -937,7 +962,7 @@ int check_for_local_domain(char *name, time_t now)
+   /* Note: the call to cache_find_by_name is intended to find any record which matches
+      ie A, AAAA, CNAME. */
+ 
+-  if ((crecp = cache_find_by_name(NULL, name, now, F_IPV4 | F_IPV6 | F_CNAME |F_NO_RR)) &&
++  if ((crecp = cache_find_by_name(NULL, name, now, F_IPV4 | F_IPV6 | F_CNAME | F_NO_RR)) &&
+       (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
+     return 1;
+   
+@@ -1689,8 +1714,9 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
+ 
+ 	  if (qtype == T_CNAME || qtype == T_ANY)
+ 	    {
+-	      if ((crecp = cache_find_by_name(NULL, name, now, F_CNAME)) &&
+-		  (qtype == T_CNAME || (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG  | (dryrun ? F_NO_RR : 0)))))
++	      if ((crecp = cache_find_by_name(NULL, name, now, F_CNAME | (dryrun ? F_NO_RR : 0))) &&
++		  (qtype == T_CNAME || (crecp->flags & F_CONFIG)) &&
++		  ((crecp->flags & F_CONFIG) || !do_bit || !(crecp->flags & F_DNSSECOK)))
+ 		{
+ 		  if (!(crecp->flags & F_DNSSECOK))
+ 		    sec_data = 0;
+-- 
+2.20.1
+
diff --git a/SOURCES/dnsmasq-2.76-dnssec-passthru.patch b/SOURCES/dnsmasq-2.76-dnssec-passthru.patch
new file mode 100644
index 0000000..b8e4365
--- /dev/null
+++ b/SOURCES/dnsmasq-2.76-dnssec-passthru.patch
@@ -0,0 +1,75 @@
+From 5fe8a0fc4d817fa6be42cd28c40752e38ee678b1 Mon Sep 17 00:00:00 2001
+From: Simon Kelley <simon@thekelleys.org.uk>
+Date: Fri, 29 Jun 2018 14:39:41 +0100
+Subject: [PATCH 2/2] Fix sometimes missing DNSSEC RRs when DNSSEC validation
+ not enabled.
+
+Dnsmasq does pass on the do-bit, and return DNSSEC RRs, irrespective
+of of having DNSSEC validation compiled in or enabled.
+
+The thing to understand here is that the cache does not store all the
+DNSSEC RRs, and dnsmasq doesn't have the (very complex) logic required
+to determine the set of DNSSEC RRs required in an answer. Therefore if
+the client wants the DNSSEC RRs, the query can not be answered from
+the cache. When DNSSEC validation is enabled, any query with the
+do-bit set is never answered from the cache, unless the domain is
+known not to be signed: the query is always forwarded. This ensures
+that the DNSEC RRs are included.
+
+The same thing should be true when DNSSEC validation is not enabled,
+but there's a bug in the logic.
+
+line 1666 of src/rfc1035.c looks like this
+
+ if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) || !do_bit || !(crecp->flags & F_DNSSECOK))
+
+{ ...answer from cache ... }
+
+So local stuff (hosts, DHCP, ) get answered. If the do_bit is not set
+then the query is answered, and if the domain is known not to be
+signed, the query is answered.
+
+Unfortunately, if DNSSEC validation is not turned on then the
+F_DNSSECOK bit is not valid, and it's always zero, so the question
+always gets answered from the cache, even when the do-bit is set.
+
+This code should look like that at line 1468, dealing with PTR queries
+
+  if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) ||
+      !do_bit ||
+      (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK)))
+
+where the F_DNSSECOK bit is only used when validation is enabled.
+
+(cherry picked from commit a997ca0da044719a0ce8a232d14da8b30022592b)
+---
+ src/rfc1035.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/src/rfc1035.c b/src/rfc1035.c
+index 607412f..96acae9 100644
+--- a/src/rfc1035.c
++++ b/src/rfc1035.c
+@@ -1632,7 +1632,9 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
+ 		    }
+ 
+ 		  /* If the client asked for DNSSEC  don't use cached data. */
+-		  if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) || !do_bit || !(crecp->flags & F_DNSSECOK))
++		  if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) ||
++		      !do_bit ||
++		      (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK)))
+ 		    do
+ 		      { 
+ 			/* don't answer wildcard queries with data not from /etc/hosts
+@@ -1716,7 +1718,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
+ 	    {
+ 	      if ((crecp = cache_find_by_name(NULL, name, now, F_CNAME | (dryrun ? F_NO_RR : 0))) &&
+ 		  (qtype == T_CNAME || (crecp->flags & F_CONFIG)) &&
+-		  ((crecp->flags & F_CONFIG) || !do_bit || !(crecp->flags & F_DNSSECOK)))
++		  ((crecp->flags & F_CONFIG) || !do_bit || (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK))))
+ 		{
+ 		  if (!(crecp->flags & F_DNSSECOK))
+ 		    sec_data = 0;
+-- 
+2.20.1
+
diff --git a/SOURCES/dnsmasq-2.76-file_offset32.patch b/SOURCES/dnsmasq-2.76-file_offset32.patch
new file mode 100644
index 0000000..f06996d
--- /dev/null
+++ b/SOURCES/dnsmasq-2.76-file_offset32.patch
@@ -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/SOURCES/dnsmasq-2.76-fix-crash-dns-resume.patch b/SOURCES/dnsmasq-2.76-fix-crash-dns-resume.patch
new file mode 100644
index 0000000..2857de0
--- /dev/null
+++ b/SOURCES/dnsmasq-2.76-fix-crash-dns-resume.patch
@@ -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/SOURCES/dnsmasq-2.76-fix-dhcp-option-arrangements.patch b/SOURCES/dnsmasq-2.76-fix-dhcp-option-arrangements.patch
new file mode 100644
index 0000000..7155b0f
--- /dev/null
+++ b/SOURCES/dnsmasq-2.76-fix-dhcp-option-arrangements.patch
@@ -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/SOURCES/dnsmasq-2.76-gita3303e196.patch b/SOURCES/dnsmasq-2.76-gita3303e196.patch
new file mode 100644
index 0000000..a437848
--- /dev/null
+++ b/SOURCES/dnsmasq-2.76-gita3303e196.patch
@@ -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/SOURCES/dnsmasq-2.76-inotify.patch b/SOURCES/dnsmasq-2.76-inotify.patch
new file mode 100644
index 0000000..6387d3f
--- /dev/null
+++ b/SOURCES/dnsmasq-2.76-inotify.patch
@@ -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/SOURCES/dnsmasq-2.76-label-man.patch b/SOURCES/dnsmasq-2.76-label-man.patch
new file mode 100644
index 0000000..74514bd
--- /dev/null
+++ b/SOURCES/dnsmasq-2.76-label-man.patch
@@ -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/SOURCES/dnsmasq-2.76-label-warning.patch b/SOURCES/dnsmasq-2.76-label-warning.patch
new file mode 100644
index 0000000..7c156ab
--- /dev/null
+++ b/SOURCES/dnsmasq-2.76-label-warning.patch
@@ -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/SOURCES/dnsmasq-2.76-min-query-port.patch b/SOURCES/dnsmasq-2.76-min-query-port.patch
new file mode 100644
index 0000000..856770c
--- /dev/null
+++ b/SOURCES/dnsmasq-2.76-min-query-port.patch
@@ -0,0 +1,85 @@
+From 333856b1c1b032f937dd24d604f98cdb6dfe3d91 Mon Sep 17 00:00:00 2001
+From: Simon Kelley <simon@thekelleys.org.uk>
+Date: Mon, 29 Jan 2018 22:49:27 +0000
+Subject: [PATCH] Default min-port to 1024 to avoid reserved ports.
+
+(cherry picked from commit baf553db0cdb50707ddab464fb3eff7786ea576c)
+---
+ man/dnsmasq.8      | 3 ++-
+ src/dns-protocol.h | 1 +
+ src/dnsmasq.c      | 3 ---
+ src/network.c      | 5 +----
+ src/option.c       | 1 +
+ 5 files changed, 5 insertions(+), 8 deletions(-)
+
+diff --git a/man/dnsmasq.8 b/man/dnsmasq.8
+index 1f1b048..9b7adde 100644
+--- a/man/dnsmasq.8
++++ b/man/dnsmasq.8
+@@ -182,7 +182,8 @@ OS: this was the default behaviour in versions prior to 2.43.
+ Do not use ports less than that given as source for outbound DNS
+ queries. Dnsmasq picks random ports as source for outbound queries:
+ when this option is given, the ports used will always to larger
+-than that specified. Useful for systems behind firewalls. 
++than that specified. Useful for systems behind firewalls. If not specified,
++defaults to 1024.
+ .TP
+ .B --max-port=<port>
+ Use ports lower than that given as source for outbound DNS queries.
+diff --git a/src/dns-protocol.h b/src/dns-protocol.h
+index 75d8ffb..dd69b28 100644
+--- a/src/dns-protocol.h
++++ b/src/dns-protocol.h
+@@ -16,6 +16,7 @@
+ 
+ #define NAMESERVER_PORT 53
+ #define TFTP_PORT       69
++#define MIN_PORT        1024           /* first non-reserved port */
+ #define MAX_PORT        65535u
+ 
+ #define IN6ADDRSZ       16
+diff --git a/src/dnsmasq.c b/src/dnsmasq.c
+index 83631ef..ae1aa96 100644
+--- a/src/dnsmasq.c
++++ b/src/dnsmasq.c
+@@ -220,9 +220,6 @@ int main (int argc, char **argv)
+     die(_("loop detection not available: set HAVE_LOOP in src/config.h"), NULL, EC_BADCONF);
+ #endif
+ 
+-  if (daemon->max_port != MAX_PORT && daemon->min_port == 0)
+-    daemon->min_port = 1024u;
+-
+   if (daemon->max_port < daemon->min_port)
+     die(_("max_port cannot be smaller than min_port"), NULL, EC_BADCONF);
+ 
+diff --git a/src/network.c b/src/network.c
+index fcd9d8d..d75f560 100644
+--- a/src/network.c
++++ b/src/network.c
+@@ -1149,10 +1149,7 @@ int random_sock(int family)
+       if (fix_fd(fd))
+ 	while(tries--)
+ 	  {
+-	    unsigned short port = rand16();
+-	    
+-            if (daemon->min_port != 0 || daemon->max_port != MAX_PORT)
+-              port = htons(daemon->min_port + (port % ((unsigned short)ports_avail)));
++	    unsigned short port = htons(daemon->min_port + (rand16() % ((unsigned short)ports_avail)));
+ 	    
+ 	    if (family == AF_INET) 
+ 	      {
+diff --git a/src/option.c b/src/option.c
+index 3469f53..22846f6 100644
+--- a/src/option.c
++++ b/src/option.c
+@@ -4521,6 +4521,7 @@ void read_opts(int argc, char **argv, char *compile_opts)
+   daemon->soa_retry = SOA_RETRY;
+   daemon->soa_expiry = SOA_EXPIRY;
+   daemon->max_port = MAX_PORT;
++  daemon->min_port = MIN_PORT;
+ 
+   add_txt("version.bind", "dnsmasq-" VERSION, 0 );
+   add_txt("authors.bind", "Simon Kelley", 0);
+-- 
+2.20.1
+
diff --git a/SOURCES/dnsmasq-2.76-misc-cleanups.patch b/SOURCES/dnsmasq-2.76-misc-cleanups.patch
new file mode 100644
index 0000000..e8a2132
--- /dev/null
+++ b/SOURCES/dnsmasq-2.76-misc-cleanups.patch
@@ -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/SOURCES/dnsmasq-2.76-pftables.patch b/SOURCES/dnsmasq-2.76-pftables.patch
new file mode 100644
index 0000000..fffd3a2
--- /dev/null
+++ b/SOURCES/dnsmasq-2.76-pftables.patch
@@ -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/SOURCES/dnsmasq-2.76-underflow.patch b/SOURCES/dnsmasq-2.76-underflow.patch
new file mode 100644
index 0000000..ac8188e
--- /dev/null
+++ b/SOURCES/dnsmasq-2.76-underflow.patch
@@ -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/SOURCES/dnsmasq-2.76-warning-fixes.patch b/SOURCES/dnsmasq-2.76-warning-fixes.patch
new file mode 100644
index 0000000..8b0bea8
--- /dev/null
+++ b/SOURCES/dnsmasq-2.76-warning-fixes.patch
@@ -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/SOURCES/dnsmasq.service b/SOURCES/dnsmasq.service
new file mode 100644
index 0000000..07fa92e
--- /dev/null
+++ b/SOURCES/dnsmasq.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=DNS caching server.
+After=network.target
+
+[Service]
+ExecStart=/usr/sbin/dnsmasq -k
+
+[Install]
+WantedBy=multi-user.target
diff --git a/SPECS/dnsmasq.spec b/SPECS/dnsmasq.spec
new file mode 100644
index 0000000..b715e18
--- /dev/null
+++ b/SPECS/dnsmasq.spec
@@ -0,0 +1,559 @@
+%define testrelease 0
+%define releasecandidate 0
+%if 0%{testrelease}
+  %define extrapath test-releases/
+  %define extraversion test30
+%endif
+%if 0%{releasecandidate}
+  %define extrapath release-candidates/
+  %define extraversion rc5
+%endif
+
+%define _hardened_build 1
+
+Name:           dnsmasq
+Version:        2.76
+Release:        9%{?extraversion}%{?dist}
+Summary:        A lightweight DHCP/caching DNS server
+
+Group:          System Environment/Daemons
+License:        GPLv2 or GPLv3
+URL:            http://www.thekelleys.org.uk/dnsmasq/
+Source0:        http://www.thekelleys.org.uk/dnsmasq/%{?extrapath}%{name}-%{version}%{?extraversion}.tar.gz
+Source1:        %{name}.service
+# upstream git: git://thekelleys.org.uk/dnsmasq.git
+
+# https://bugzilla.redhat.com/show_bug.cgi?id=1367772
+# commit 2675f2061525bc954be14988d64384b74aa7bf8b
+# after v2.76
+Patch1:         dnsmasq-2.76-dns-sleep-resume.patch
+# commit 591ed1e90503817938ccf5f127e677a8dd48b6d8
+Patch2:         dnsmasq-2.76-fix-dhcp-option-arrangements.patch
+# commit 396750cef533cf72c7e6a72e47a9c93e2e431cb7
+Patch3:         dnsmasq-2.76-pftables.patch
+# commit 16800ea072dd0cdf14d951c4bb8d2808b3dfe53d
+Patch4:         dnsmasq-2.76-fix-crash-dns-resume.patch
+# commit 13dee6f49e1d035b8069947be84ee8da2af0c420
+Patch5:		dnsmasq-2.76-warning-fixes.patch
+Patch6:		dnsmasq-2.76-label-warning.patch
+Patch7:		dnsmasq-2.76-label-man.patch
+Patch8:		dnsmasq-2.76-coverity.patch
+# commit c77fb9d8f09d136fa71bde2469c4fd11cefa6f4a
+# commit bf4e62c19e619f7edf8d03d58d33a5752f190bfd
+# commit 3a8b0f6fccf464b1ec6d24c0e00e540ab2b17705
+Patch9:		dnsmasq-2.76-dhcp-script-log.patch
+# Fix possible different sizes of off_t
+Patch10:	dnsmasq-2.76-file_offset32.patch
+Patch11:	dnsmasq-2.76-CVE-2017-14491.patch
+Patch12:	dnsmasq-2.76-CVE-2017-14492.patch
+Patch13:	dnsmasq-2.76-CVE-2017-14493.patch
+Patch14:	dnsmasq-2.76-CVE-2017-14494.patch
+Patch15:	dnsmasq-2.76-CVE-2017-14496.patch
+Patch16:	dnsmasq-2.76-CVE-2017-14495.patch
+# commit a3303e196e5d304ec955c4d63afb923ade66c6e8
+Patch17:	dnsmasq-2.76-gita3303e196.patch
+Patch18:	dnsmasq-2.76-underflow.patch
+Patch19:	dnsmasq-2.76-misc-cleanups.patch
+Patch20:	dnsmasq-2.76-CVE-2017-14491-2.patch
+Patch21:	dnsmasq-2.76-inotify.patch
+Patch22:	dnsmasq-2.76-min-query-port.patch
+# commit a6004d7f17687ac2455f724d0b57098c413f128d
+Patch23:	dnsmasq-2.76-dnssec-cache.patch
+# commit a997ca0da044719a0ce8a232d14da8b30022592b
+Patch24:	dnsmasq-2.76-dnssec-passthru.patch
+
+BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
+
+BuildRequires:  dbus-devel
+BuildRequires:  pkgconfig
+BuildRequires:  libidn-devel
+
+BuildRequires:  systemd
+Requires(post): systemd systemd-sysv chkconfig
+Requires(preun): systemd
+Requires(postun): systemd
+
+
+%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.
+
+%package        utils
+Summary:        Utilities for manipulating DHCP server leases
+Group:          System Environment/Daemons
+
+%description    utils
+Utilities that use the standard DHCP protocol to
+query/remove a DHCP server's leases.
+
+
+%prep
+%setup -q -n %{name}-%{version}%{?extraversion}
+
+%patch1 -p1
+%patch2 -p1
+%patch3 -p1
+%patch4 -p1
+%patch5 -p1
+%patch6 -p1
+%patch7 -p1
+%patch8 -p1 -b .coverity
+%patch9 -p1 -b .scriptlog
+%patch10 -p1 -b .off_t
+%patch11 -p1 -b .CVE-2017-14491
+%patch12 -p1 -b .CVE-2017-14492
+%patch13 -p1 -b .CVE-2017-14493
+%patch14 -p1 -b .CVE-2017-14494
+%patch15 -p1 -b .CVE-2017-14496
+%patch16 -p1 -b .CVE-2017-14495
+%patch17 -p1 -b .gita3303e196
+%patch18 -p1 -b .underflow
+%patch19 -p1 -b .misc
+%patch20 -p1 -b .CVE-2017-14491-2
+%patch21 -p1 -b .inotify
+%patch22 -p1 -b .rh1614331
+%patch23 -p1 -b .dnssec-cache
+%patch24 -p1 -b .dnssec-passthru
+
+# use /var/lib/dnsmasq instead of /var/lib/misc
+for file in dnsmasq.conf.example man/dnsmasq.8 man/es/dnsmasq.8 src/config.h; do
+    sed -i 's|/var/lib/misc/dnsmasq.leases|/var/lib/dnsmasq/dnsmasq.leases|g' "$file"
+done
+
+#enable dbus
+sed -i 's|/\* #define HAVE_DBUS \*/|#define HAVE_DBUS|g' src/config.h
+
+#enable IDN support
+sed -i 's|/\* #define HAVE_IDN \*/|#define HAVE_IDN|g' src/config.h
+
+#enable /etc/dnsmasq.d fix bz 526703, ignore RPM backup files
+cat << EOF >> dnsmasq.conf.example
+
+# Include all files in /etc/dnsmasq.d except RPM backup files
+conf-dir=/etc/dnsmasq.d,.rpmnew,.rpmsave,.rpmorig
+EOF
+
+
+%build
+make %{?_smp_mflags} CFLAGS="$RPM_OPT_FLAGS" LDFLAGS="$RPM_LD_FLAGS"
+make -C contrib/lease-tools %{?_smp_mflags} CFLAGS="$RPM_OPT_FLAGS" LDFLAGS="$RPM_LD_FLAGS"
+
+
+%install
+rm -rf $RPM_BUILD_ROOT
+# normally i'd do 'make install'...it's a bit messy, though
+mkdir -p $RPM_BUILD_ROOT%{_sbindir} \
+        $RPM_BUILD_ROOT%{_mandir}/man8 \
+        $RPM_BUILD_ROOT%{_var}/lib/dnsmasq \
+        $RPM_BUILD_ROOT%{_sysconfdir}/dnsmasq.d \
+        $RPM_BUILD_ROOT%{_sysconfdir}/dbus-1/system.d
+install src/dnsmasq $RPM_BUILD_ROOT%{_sbindir}/dnsmasq
+install dnsmasq.conf.example $RPM_BUILD_ROOT%{_sysconfdir}/dnsmasq.conf
+install dbus/dnsmasq.conf $RPM_BUILD_ROOT%{_sysconfdir}/dbus-1/system.d/
+install -m 644 man/dnsmasq.8 $RPM_BUILD_ROOT%{_mandir}/man8/
+
+# utils sub package
+mkdir -p $RPM_BUILD_ROOT%{_bindir} \
+         $RPM_BUILD_ROOT%{_mandir}/man1
+install -m 755 contrib/lease-tools/dhcp_release $RPM_BUILD_ROOT%{_bindir}/dhcp_release
+install -m 644 contrib/lease-tools/dhcp_release.1 $RPM_BUILD_ROOT%{_mandir}/man1/dhcp_release.1
+install -m 755 contrib/lease-tools/dhcp_release6 $RPM_BUILD_ROOT%{_bindir}/dhcp_release6
+install -m 644 contrib/lease-tools/dhcp_release6.1 $RPM_BUILD_ROOT%{_mandir}/man1/dhcp_release6.1
+install -m 755 contrib/lease-tools/dhcp_lease_time $RPM_BUILD_ROOT%{_bindir}/dhcp_lease_time
+install -m 644 contrib/lease-tools/dhcp_lease_time.1 $RPM_BUILD_ROOT%{_mandir}/man1/dhcp_lease_time.1
+
+# Systemd
+mkdir -p %{buildroot}%{_unitdir}
+install -m644 %{SOURCE1} %{buildroot}%{_unitdir}
+rm -rf %{buildroot}%{_initrddir}
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%post
+%systemd_post dnsmasq.service
+
+%preun
+%systemd_preun dnsmasq.service
+
+%postun
+%systemd_postun_with_restart dnsmasq.service
+
+%triggerun -- dnsmasq < 2.52-3
+%{_bindir}/systemd-sysv-convert --save dnsmasq >/dev/null 2>&1 ||:
+/sbin/chkconfig --del dnsmasq >/dev/null 2>&1 || :
+/bin/systemctl try-restart dnsmasq.service >/dev/null 2>&1 || :
+
+%files
+%defattr(-,root,root,-)
+%doc CHANGELOG COPYING COPYING-v3 FAQ doc.html setup.html dbus/DBus-interface
+%config(noreplace) %attr(644,root,root) %{_sysconfdir}/dnsmasq.conf
+%dir /etc/dnsmasq.d
+%dir %{_var}/lib/dnsmasq
+%config(noreplace) %attr(644,root,root) %{_sysconfdir}/dbus-1/system.d/dnsmasq.conf
+%{_unitdir}/%{name}.service
+%{_sbindir}/dnsmasq
+%{_mandir}/man8/dnsmasq*
+
+%files utils
+%{_bindir}/dhcp_*
+%{_mandir}/man1/dhcp_*
+
+%changelog
+* Tue Mar 26 2019 Petr Menšík <pemensik@redhat.com> - 2.79-9
+- Fix passing of dnssec enabled queries (#1638703)
+
+* Mon Mar 18 2019 Petr Menšík <pemensik@redhat.com> - 2.76-8
+- Stop using privileged port for outbound queries (#1614331)
+
+* Wed May 09 2018 Martin Sehnoutka <msehnout@redhat.com> - 2.76-7
+- Resolves: #1474515 dhcp-agent dnsmasq max files
+
+* Wed Sep 27 2017 Petr Menšík <pemensik@redhat.com> - 2.76-6
+- Small correction of CVE-2017-14491
+
+* Tue Sep 26 2017 Petr Menšík <pemensik@redhat.com> - 2.76-5
+- Fix CVE-2017-14491
+- Fix CVE-2017-14492
+- Fix CVE-2017-14493
+- Fix CVE-2017-14494
+- Fix CVE-2017-14496
+- Fix CVE-2017-14495
+- extra fixes
+
+* Thu Sep 14 2017 Petr Menšík <pemensik@redhat.com> - 2.76-4
+- Fix possible stack corruption on 32-bit architectures (#1188259)
+
+* Fri Mar 24 2017 Petr Menšík <pemensik@redhat.com> - 2.76-3
+- Log output of dhcp-script (#1188259)
+- Log format errors in dhcp-script init
+
+* Wed Mar 15 2017 Petr Menšík <pemensik@redhat.com> - 2.76-2
+- Fix a few coverity warnings
+- package is dual-licensed GPL v2 or v3
+- don't include /etc/dnsmasq.d in triplicate, ignore RPM backup files instead
+
+* Tue Feb 21 2017 Petr Menšík <pemensik@redhat.com> - 2.76-1
+- Rebase to 2.76 (#1375527)
+- Include also dhcp_release6 (#1375569)
+- Fix compilation warnings
+- Correct manual about interface aliases, warn if used without --bind*
+
+* Tue Sep 13 2016 Pavel Šimerda <psimerda@redhat.com> - 2.66-21
+- Related: #1367772 - fix dns server update
+
+* Thu Sep 08 2016 Pavel Šimerda <psimerda@redhat.com> - 2.66-20
+- Related: #1367772 - additional upstream patch
+
+* Tue Sep 06 2016 Pavel Šimerda <psimerda@redhat.com> - 2.66-19
+- Resolves: #1367772 - dns not updated after sleep and resume laptop
+
+* Fri Aug 26 2016 root - 2.66-18
+- Resolves: #1358427 - dhcp errors with hostnames beginning with numbers
+
+* Tue May 31 2016 Pavel Šimerda <psimerda@redhat.com> - 2.66-17
+- Resolves: #1275626 - modify the patch using new information
+
+* Mon May 30 2016 Pavel Šimerda <psimerda@redhat.com> - 2.66-16
+- Resolves: #1275626 - use the patch
+
+* Wed May 25 2016 Pavel Šimerda <psimerda@redhat.com> - 2.66-15
+- Resolves: #1275626 - dnsmasq crash with coredump on infiniband network with
+  OpenStack
+
+* Thu Jun 25 2015 Pavel Šimerda <psimerda@redhat.com> - 2.66-14
+- Resolves: #1232677 - handle IPv4 and IPv6 host entries properly
+
+* Wed Feb 25 2015 Pavel Šimerda <psimerda@redhat.com> - 2.66-13
+- Resolves: #1179756 - dnsmasq does not support MAC address based matching for
+  IPv6
+
+* Fri Jan 24 2014 Daniel Mach <dmach@redhat.com> - 2.66-12
+- Mass rebuild 2014-01-24
+
+* Fri Dec 27 2013 Daniel Mach <dmach@redhat.com> - 2.66-11
+- Mass rebuild 2013-12-27
+
+* Thu Aug 15 2013 Tomas Hozza <thozza@redhat.com> - 2.66-10
+- Use SO_REUSEPORT and SO_REUSEADDR if possible for DHCPv4/6 (#981973)
+
+* Mon Aug 12 2013 Tomas Hozza <thozza@redhat.com> - 2.66-9
+- Don't use SO_REUSEPORT on DHCPv4 socket to prevent conflicts with ISC DHCP (#981973)
+
+* Tue Jul 23 2013 Tomas Hozza <thozza@redhat.com> - 2.66-8
+- Fix crash when specified empty DHCP option
+
+* Tue Jun 11 2013 Tomas Hozza <thozza@redhat.com> - 2.66-7
+- use _hardened_build macro instead of hardcoded flags
+- include several fixies from upstream repo:
+  - Allow constructed ranges from interface address at end of range
+  - Dont BINDTODEVICE DHCP socket if more interfaces may come
+  - Fix option parsing for dhcp host
+  - Log forwarding table overflows
+  - Remove limit in prefix length in auth zone
+
+* Fri May 17 2013 Tomas Hozza <thozza@redhat.com> - 2.66-6
+- include several fixies from upstream repo:
+  - Tighten hostname checks in legal hostname() function
+  - Replace inet_addr() with inet_pton() in src/option.c
+  - Use dnsmasq as default DNS server for RA only if it's doing DNS
+  - Handle IPv4 interface address labels (aliases) in Linux (#962246)
+  - Fix failure to start with ENOTSOCK (#962874)
+
+* Tue Apr 30 2013 Tomas Hozza <thozza@redhat.com> - 2.66-5
+- dnsmasq unit file cleanup
+  - drop forking Type and PIDfile and rather start dnsmasq with "-k" option
+  - drop After syslog.target as this is by default
+
+* Thu Apr 25 2013 Tomas Hozza <thozza@redhat.com> - 2.66-4
+- include several fixes from upstream repo:
+  - Send TCP DNS messages in one packet
+  - Fix crash on SERVFAIL when using --conntrack option
+  - Fix regression in dhcp_lease_time utility
+  - Man page typos fixes
+  - Note that dhcp_lease_time and dhcp_release work only for IPv4
+  - Fix for --dhcp-match option to work also with BOOTP protocol
+
+* Sat Apr 20 2013 Tomas Hozza <thozza@redhat.com> - 2.66-3
+- Use Full RELRO when linking the daemon
+- compile the daemon with PIE
+- include two fixes from upstream git repo
+
+* Thu Apr 18 2013 Tomas Hozza <thozza@redhat.com> - 2.66-2
+- New stable version dnsmasq-2.66
+- Drop of merged patch
+
+* Fri Apr 12 2013 Tomas Hozza <thozza@redhat.com> - 2.66-1.rc5
+- Update to latest dnsmasq-2.66rc5
+- Include fix for segfault when lease limit is reached
+
+* Fri Mar 22 2013 Tomas Hozza <thozza@redhat.com> - 2.66-1.rc1
+- Update to latest dnsmasq-2.66rc1
+- Dropping unneeded patches
+- Enable IDN support
+
+* Fri Mar 15 2013 Tomas Hozza <thozza@redhat.com> - 2.65-5
+- Allocate dhcp_buff-ers also if daemon->ra_contexts to prevent SIGSEGV (#920300)
+
+* Thu Jan 31 2013 Tomas Hozza <thozza@redhat.com> - 2.65-4
+- Handle locally-routed DNS Queries (#904940)
+
+* Thu Jan 24 2013 Tomas Hozza <thozza@redhat.com> - 2.65-3
+- build dnsmasq with $RPM_OPT_FLAGS, $RPM_LD_FLAGS explicitly (#903362) 
+
+* Tue Jan 22 2013 Tomas Hozza <thozza@redhat.com> - 2.65-2
+- Fix for CVE-2013-0198 (checking of TCP connection interfaces) (#901555)
+
+* Sat Dec 15 2012 Tomas Hozza <thozza@redhat.com> - 2.65-1
+- new version 2.65
+
+* Wed Dec 05 2012 Tomas Hozza <thozza@redhat.com> - 2.64-1
+- New version 2.64
+- Merged patches dropped
+
+* Tue Nov 20 2012 Tomas Hozza <thozza@redhat.com> - 2.63-4
+- Remove EnvironmentFile from service file (#878343)
+
+* Mon Nov 19 2012 Tomas Hozza <thozza@redhat.com> - 2.63-3
+- dhcp6 support fixes (#867054)
+- removed "-s $HOSTNAME" from .service file (#753656, #822797)
+
+* Tue Oct 23 2012 Tomas Hozza <thozza@redhat.com> - 2.63-2
+- Introduce new systemd-rpm macros in dnsmasq spec file (#850096)
+
+* Thu Aug 23 2012 Douglas Schilling Landgraf <dougsland@redhat.com> - 2.63-1
+- Use .tar.gz compression, in upstream site there is no .lzma anymore
+- New version 2.63
+
+* Sat Feb 11 2012 Pádraig Brady <P@draigBrady.com> - 2.59-5
+- Compile DHCP lease management utils with RPM_OPT_FLAGS
+
+* Thu Feb  9 2012 Pádraig Brady <P@draigBrady.com> - 2.59-4
+- Include DHCP lease management utils in a subpackage
+
+* Fri Jan 13 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.59-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild
+
+* Fri Aug 26 2011 Douglas Schilling Landgraf <dougsland@redhat.com> - 2.59-2
+- do not enable service by default
+
+* Fri Aug 26 2011 Douglas Schilling Landgraf <dougsland@redhat.com> - 2.59-1
+- New version 2.59
+- Fix regression in 2.58 (IPv6 issue) - bz 744814
+
+* Fri Aug 26 2011 Douglas Schilling Landgraf <dougsland@redhat.com> - 2.58-1
+- Fixed License
+- New version 2.58
+
+* Mon Aug 08 2011 Patrick "Jima" Laughton <jima@fedoraproject.org> - 2.52-5
+- Include systemd unit file
+
+* Mon Aug 08 2011 Patrick "Jima" Laughton <jima@fedoraproject.org> - 2.52-3
+- Applied Jóhann's patch, minor cleanup
+
+* Tue Jul 26 2011 Jóhann B. Guðmundsson <johannbg@gmail.com> - 2.52-3
+- Introduce systemd unit file, drop SysV support
+
+* Tue Feb 08 2011 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.52-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild
+
+* Tue Jan 26 2010 Itamar Reis Peixoto <itamar@ispbrasil.com.br> - 2.52-1
+- New Version 2.52
+- fix condrestart() in initscript bz 547605
+- fix sed to enable DBUS(the '*' need some escaping) bz 553161
+
+* Sun Nov 22 2009 Itamar Reis Peixoto <itamar@ispbrasil.com.br> - 2.51-2
+- fix bz 512664
+
+* Sat Oct 17 2009 Itamar Reis Peixoto <itamar@ispbrasil.com.br> - 2.51-1
+- move initscript from patch to a plain text file
+- drop (dnsmasq-configuration.patch) and use sed instead
+- enable /etc/dnsmasq.d fix bz 526703
+- change requires to package name instead of file
+- new version 2.51
+
+* Mon Oct  5 2009 Mark McLoughlin <markmc@redhat.com> - 2.48-4
+- Fix multiple TFTP server vulnerabilities (CVE-2009-2957, CVE-2009-2958)
+
+* Wed Aug 12 2009 Ville Skyttä <ville.skytta@iki.fi> - 2.48-3
+- Use lzma compressed upstream tarball.
+
+* Fri Jul 24 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.48-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild
+
+* Wed Jun 10 2009 Patrick "Jima" Laughton <jima@beer.tclug.org> 2.48-1
+- Bugfix/feature enhancement update
+- Fixing BZ#494094
+
+* Fri May 29 2009 Patrick "Jima" Laughton <jima@beer.tclug.org> 2.47-1
+- Bugfix/feature enhancement update
+
+* Tue Feb 24 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.46-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild
+
+* Mon Dec 29 2008 Matěj Cepl <mcepl@redhat.com> - 2.45-2
+- rebuilt
+
+* Mon Jul 21 2008 Patrick "Jima" Laughton <jima@beer.tclug.org> 2.45-1
+- Upstream release (bugfixes)
+
+* Wed Jul 16 2008 Patrick "Jima" Laughton <jima@beer.tclug.org> 2.43-2
+- New upstream release, contains fixes for CVE-2008-1447/CERT VU#800113
+- Dropped patch for newer glibc (merged upstream)
+
+* Wed Feb 13 2008 Patrick "Jima" Laughton <jima@beer.tclug.org> 2.41-0.8
+- Added upstream-authored patch for newer glibc (thanks Simon!)
+
+* Wed Feb 13 2008 Patrick "Jima" Laughton <jima@beer.tclug.org> 2.41-0.7
+- New upstream release
+
+* Wed Jan 30 2008 Patrick "Jima" Laughton <jima@beer.tclug.org> 2.41-0.6.rc1
+- Release candidate
+- Happy Birthday Isaac!
+
+* Wed Jan 23 2008 Patrick "Jima" Laughton <jima@beer.tclug.org> 2.41-0.5.test30
+- Bugfix update
+
+* Mon Dec 31 2007 Patrick "Jima" Laughton <jima@beer.tclug.org> 2.41-0.4.test26
+- Bugfix/feature enhancement update
+
+* Thu Dec 13 2007 Patrick "Jima" Laughton <jima@beer.tclug.org> 2.41-0.3.test24
+- Upstream fix for fairly serious regression
+
+* Tue Dec 04 2007 Patrick "Jima" Laughton <jima@beer.tclug.org> 2.41-0.2.test20
+- New upstream test release
+- Moving dnsmasq.leases to /var/lib/dnsmasq/ as per BZ#407901
+- Ignoring dangerous-command-in-%%post rpmlint warning (as per above fix)
+- Patch consolidation/cleanup
+- Removed conditionals for Fedora <= 3 and Aurora 2.0
+
+* Tue Sep 18 2007 Patrick "Jima" Laughton <jima@beer.tclug.org> 2.40-1
+- Finalized upstream release
+- Removing URLs from patch lines (CVS is the authoritative source)
+- Added more magic to make spinning rc/test packages more seamless
+
+* Sun Aug 26 2007 Patrick "Jima" Laughton <jima@beer.tclug.org> 2.40-0.1.rc2
+- New upstream release candidate (feature-frozen), thanks Simon!
+- License clarification
+
+* Tue May 29 2007 Patrick "Jima" Laughton <jima@beer.tclug.org> 2.39-1
+- New upstream version (bugfixes, enhancements)
+
+* Mon Feb 12 2007 Patrick "Jima" Laughton <jima@beer.tclug.org> 2.38-1
+- New upstream version with bugfix for potential hang
+
+* Tue Feb 06 2007 Patrick "Jima" Laughton <jima@beer.tclug.org> 2.37-1
+- New upstream version
+
+* Wed Jan 24 2007 Patrick "Jima" Laughton <jima@beer.tclug.org> 2.36-1
+- New upstream version
+
+* Mon Nov 06 2006 Patrick "Jima" Laughton <jima@beer.tclug.org> 2.35-2
+- Stop creating /etc/sysconfig on %%install
+- Create /etc/dnsmasq.d on %%install
+
+* Mon Nov 06 2006 Patrick "Jima" Laughton <jima@beer.tclug.org> 2.35-1
+- Update to 2.35
+- Removed UPGRADING_to_2.0 from %%doc as per upstream change
+- Enabled conf-dir in default config as per RFE BZ#214220 (thanks Chris!)
+- Added %%dir /etc/dnsmasq.d to %%files as per above RFE
+
+* Tue Oct 24 2006 Patrick "Jima" Laughton <jima@beer.tclug.org> 2.34-2
+- Fixed BZ#212005
+- Moved %%postun scriptlet to %%post, where it made more sense
+- Render scriptlets safer
+- Minor cleanup for consistency
+
+* Thu Oct 19 2006 Patrick "Jima" Laughton <jima@beer.tclug.org> 2.34-1
+- Hardcoded version in patches, as I'm getting tired of updating them
+- Update to 2.34
+
+* Mon Aug 28 2006 Patrick "Jima" Laughton <jima@beer.tclug.org> 2.33-2
+- Rebuild for FC6
+
+* Tue Aug 15 2006 Patrick "Jima" Laughton <jima@beer.tclug.org> 2.33-1
+- Update
+
+* Sat Jul 22 2006 Patrick "Jima" Laughton <jima@beer.tclug.org> 2.32-3
+- Added pkgconfig BuildReq due to reduced buildroot
+
+* Thu Jul 20 2006 Patrick "Jima" Laughton <jima@beer.tclug.org> 2.32-2
+- Forced update due to dbus version bump
+
+* Mon Jun 12 2006 Patrick "Jima" Laughton <jima@beer.tclug.org> 2.32-1
+- Update from upstream
+- Patch from Dennis Gilmore fixed the conditionals to detect Aurora Linux
+
+* Mon May  8 2006 Patrick "Jima" Laughton <jima@auroralinux.org> 2.31-1
+- Removed dbus config patch (now provided upstream)
+- Patched in init script (no longer provided upstream)
+- Added DBus-interface to docs
+
+* Tue May  2 2006 Patrick "Jima" Laughton <jima@auroralinux.org> 2.30-4.2
+- More upstream-recommended cleanups :)
+- Killed sysconfig file (provides unneeded functionality)
+- Tweaked init script a little more
+
+* Tue May  2 2006 Patrick "Jima" Laughton <jima@auroralinux.org> 2.30-4
+- Moved options out of init script and into /etc/sysconfig/dnsmasq
+- Disabled DHCP_LEASE in sysconfig file, fixing bug #190379
+- Simon Kelley provided dbus/dnsmasq.conf, soon to be part of the tarball
+
+* Thu Apr 27 2006 Patrick "Jima" Laughton <jima@auroralinux.org> 2.30-3
+- Un-enabled HAVE_ISC_READER, a hack to enable a deprecated feature (request)
+- Split initscript & enable-dbus patches, conditionalized dbus for FC3
+- Tweaked name field in changelog entries (trying to be consistent)
+
+* Mon Apr 24 2006 Patrick "Jima" Laughton <jima@auroralinux.org> 2.30-2
+- Disabled stripping of binary while installing (oops)
+- Enabled HAVE_ISC_READER/HAVE_DBUS via patch
+- Added BuildReq for dbus-devel
+
+* Mon Apr 24 2006 Patrick "Jima" Laughton <jima@auroralinux.org> 2.30-1
+- Initial Fedora Extras RPM