diff --git a/package/network/services/dnsmasq/Makefile b/package/network/services/dnsmasq/Makefile
index 7ba7d56b5266dc71bbf2ac456e52ce5147b68eae..46b68a24a679de05d7eaf7fcd8626296d424c200 100644
--- a/package/network/services/dnsmasq/Makefile
+++ b/package/network/services/dnsmasq/Makefile
@@ -8,12 +8,12 @@
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=dnsmasq
-PKG_VERSION:=2.78
-PKG_RELEASE:=10
+PKG_VERSION:=2.79rc1
+PKG_RELEASE:=1
 
 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
-PKG_SOURCE_URL:=http://thekelleys.org.uk/dnsmasq/
-PKG_HASH:=89949f438c74b0c7543f06689c319484bd126cc4b1f8c745c742ab397681252b
+PKG_SOURCE_URL:=http://thekelleys.org.uk/dnsmasq/release-candidates/
+PKG_HASH:=57d17a3a6cf34af5dcbc5107c45b05671bda9d250718fe073ca12c5f61099985
 
 PKG_LICENSE:=GPL-2.0
 PKG_LICENSE_FILES:=COPYING
diff --git a/package/network/services/dnsmasq/patches/210-dnssec-improve-timestamp-heuristic.patch b/package/network/services/dnsmasq/patches/210-dnssec-improve-timestamp-heuristic.patch
index 2f854d490b2405f7bab9830177fb0199c0a589d9..be1195abbd2dc37a09f5afac2866bad5f9eca437 100644
--- a/package/network/services/dnsmasq/patches/210-dnssec-improve-timestamp-heuristic.patch
+++ b/package/network/services/dnsmasq/patches/210-dnssec-improve-timestamp-heuristic.patch
@@ -10,7 +10,7 @@ Signed-off-by: Steven Barth <steven@midlink.org>
 
 --- a/src/dnssec.c
 +++ b/src/dnssec.c
-@@ -462,17 +462,24 @@ static time_t timestamp_time;
+@@ -143,17 +143,24 @@ static time_t timestamp_time;
  int setup_timestamp(void)
  {
    struct stat statbuf;
@@ -36,7 +36,7 @@ Signed-off-by: Steven Barth <steven@midlink.org>
  	{
  	  /* time already OK, update timestamp, and do key checking from the start. */
  	  if (utimes(daemon->timestamp_file, NULL) == -1)
-@@ -493,7 +500,7 @@ int setup_timestamp(void)
+@@ -174,7 +181,7 @@ int setup_timestamp(void)
  
  	  close(fd);
  	  
diff --git a/package/network/services/dnsmasq/patches/240-ubus.patch b/package/network/services/dnsmasq/patches/240-ubus.patch
index d21ca0dbaa4434e86edb2e78d96050b4d7cd55ca..415c7a5e4ccf6de4edc16a8cf9b80d63f87e1d32 100644
--- a/package/network/services/dnsmasq/patches/240-ubus.patch
+++ b/package/network/services/dnsmasq/patches/240-ubus.patch
@@ -74,7 +74,7 @@
  int main (int argc, char **argv)
  {
    int bind_fallback = 0;
-@@ -911,6 +971,7 @@ int main (int argc, char **argv)
+@@ -928,6 +988,7 @@ int main (int argc, char **argv)
        set_dbus_listeners();
  #endif	
    
@@ -82,7 +82,7 @@
  #ifdef HAVE_DHCP
        if (daemon->dhcp || daemon->relay4)
  	{
-@@ -1041,6 +1102,8 @@ int main (int argc, char **argv)
+@@ -1058,6 +1119,8 @@ int main (int argc, char **argv)
        check_dbus_listeners();
  #endif
        
@@ -104,7 +104,7 @@
  mostly_clean :
 --- a/src/dnsmasq.h
 +++ b/src/dnsmasq.h
-@@ -1397,6 +1397,8 @@ void emit_dbus_signal(int action, struct
+@@ -1415,6 +1415,8 @@ void emit_dbus_signal(int action, struct
  #  endif
  #endif
  
diff --git a/package/network/services/dnsmasq/patches/250-Fix-infinite-retries-in-strict-order-mode.patch b/package/network/services/dnsmasq/patches/250-Fix-infinite-retries-in-strict-order-mode.patch
deleted file mode 100644
index faff680e03bc113cdca513edb8e5fedec7c08986..0000000000000000000000000000000000000000
--- a/package/network/services/dnsmasq/patches/250-Fix-infinite-retries-in-strict-order-mode.patch
+++ /dev/null
@@ -1,45 +0,0 @@
-From ef3d137a646fa8309e1ff5184e3e145eef40cc4d Mon Sep 17 00:00:00 2001
-From: Simon Kelley <simon@thekelleys.org.uk>
-Date: Tue, 5 Dec 2017 22:37:29 +0000
-Subject: [PATCH] Fix infinite retries in strict-order mode.
-
- If all configured dns servers return refused in
- response to a query; dnsmasq will end up in an infinite loop
- retransmitting the dns query resulting into high CPU load.
- Problem is caused by the dns refuse retransmission logic which does
- not check for the end of a dns server list iteration in strict mode.
- Having one configured dns server returning a refused reply easily
- triggers this problem in strict order mode. This was introduced in
- 9396752c115b3ab733fa476b30da73237e12e7ba
-
- Thanks to Hans Dedecker <dedeckeh@gmail.com> for spotting this
- and the initial patch.
----
- src/forward.c | 14 ++++++++++++--
- 1 file changed, 12 insertions(+), 2 deletions(-)
-
---- a/src/forward.c
-+++ b/src/forward.c
-@@ -797,10 +797,20 @@ void reply_query(int fd, int family, tim
-       unsigned char *pheader;
-       size_t plen;
-       int is_sign;
--      
-+
-+      /* In strict order mode, there must be a server later in the chain
-+	 left to send to, otherwise without the forwardall mechanism,
-+	 code further on will cycle around the list forwever if they
-+	 all return REFUSED. Note that server is always non-NULL before 
-+	 this executes. */
-+      if (option_bool(OPT_ORDER))
-+	for (server = forward->sentto->next; server; server = server->next)
-+	  if (!(server->flags & (SERV_LITERAL_ADDRESS | SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_NO_ADDR | SERV_LOOP)))
-+	    break;
-+
-       /* recreate query from reply */
-       pheader = find_pseudoheader(header, (size_t)n, &plen, NULL, &is_sign, NULL);
--      if (!is_sign)
-+      if (!is_sign && server)
- 	{
- 	  header->ancount = htons(0);
- 	  header->nscount = htons(0);
diff --git a/package/network/services/dnsmasq/patches/260-dnssec-SIGINT.patch b/package/network/services/dnsmasq/patches/260-dnssec-SIGINT.patch
deleted file mode 100644
index e280142f7562edc6038a1b2b725e54f72c3cb5ce..0000000000000000000000000000000000000000
--- a/package/network/services/dnsmasq/patches/260-dnssec-SIGINT.patch
+++ /dev/null
@@ -1,120 +0,0 @@
-From 3c973ad92d317df736d5a8fde67baba6b102d91e Mon Sep 17 00:00:00 2001
-From: Simon Kelley <simon@thekelleys.org.uk>
-Date: Sun, 14 Jan 2018 21:05:37 +0000
-Subject: [PATCH] Use SIGINT (instead of overloading SIGHUP) to turn on DNSSEC
- time validation.
-
----
- src/dnsmasq.c |   36 +++++++++++++++++++++++++-----------
- src/dnsmasq.h |    1 +
- src/helper.c  |    3 ++-
- 5 files changed, 38 insertions(+), 14 deletions(-)
-
---- a/src/dnsmasq.c
-+++ b/src/dnsmasq.c
-@@ -137,7 +137,8 @@ int main (int argc, char **argv)
-   sigaction(SIGTERM, &sigact, NULL);
-   sigaction(SIGALRM, &sigact, NULL);
-   sigaction(SIGCHLD, &sigact, NULL);
--
-+  sigaction(SIGINT, &sigact, NULL);
-+  
-   /* ignore SIGPIPE */
-   sigact.sa_handler = SIG_IGN;
-   sigaction(SIGPIPE, &sigact, NULL);
-@@ -815,7 +816,7 @@ int main (int argc, char **argv)
-       
-       daemon->dnssec_no_time_check = option_bool(OPT_DNSSEC_TIME);
-       if (option_bool(OPT_DNSSEC_TIME) && !daemon->back_to_the_future)
--	my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until first cache reload"));
-+	my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until receipt of SIGINT"));
-       
-       if (rc == 1)
- 	my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until system time valid"));
-@@ -1142,7 +1143,7 @@ static void sig_handler(int sig)
-     {
-       /* ignore anything other than TERM during startup
- 	 and in helper proc. (helper ignore TERM too) */
--      if (sig == SIGTERM)
-+      if (sig == SIGTERM || sig == SIGINT)
- 	exit(EC_MISC);
-     }
-   else if (pid != getpid())
-@@ -1168,6 +1169,15 @@ static void sig_handler(int sig)
- 	event = EVENT_DUMP;
-       else if (sig == SIGUSR2)
- 	event = EVENT_REOPEN;
-+      else if (sig == SIGINT)
-+	{
-+	  /* Handle SIGINT normally in debug mode, so
-+	     ctrl-c continues to operate. */
-+	  if (option_bool(OPT_DEBUG))
-+	    exit(EC_MISC);
-+	  else
-+	    event = EVENT_TIME;
-+	}
-       else
- 	return;
- 
-@@ -1295,14 +1305,7 @@ static void async_event(int pipe, time_t
-       {
-       case EVENT_RELOAD:
- 	daemon->soa_sn++; /* Bump zone serial, as it may have changed. */
--
--#ifdef HAVE_DNSSEC
--	if (daemon->dnssec_no_time_check && option_bool(OPT_DNSSEC_VALID) && option_bool(OPT_DNSSEC_TIME))
--	  {
--	    my_syslog(LOG_INFO, _("now checking DNSSEC signature timestamps"));
--	    daemon->dnssec_no_time_check = 0;
--	  } 
--#endif
-+	
- 	/* fall through */
- 	
-       case EVENT_INIT:
-@@ -1411,6 +1414,17 @@ static void async_event(int pipe, time_t
- 	poll_resolv(0, 1, now);
- 	break;
- 
-+      case EVENT_TIME:
-+#ifdef HAVE_DNSSEC
-+	if (daemon->dnssec_no_time_check && option_bool(OPT_DNSSEC_VALID) && option_bool(OPT_DNSSEC_TIME))
-+	  {
-+	    my_syslog(LOG_INFO, _("now checking DNSSEC signature timestamps"));
-+	    daemon->dnssec_no_time_check = 0;
-+	    clear_cache_and_reload(now);
-+	  }
-+#endif
-+	break;
-+	
-       case EVENT_TERM:
- 	/* Knock all our children on the head. */
- 	for (i = 0; i < MAX_PROCS; i++)
---- a/src/dnsmasq.h
-+++ b/src/dnsmasq.h
-@@ -175,6 +175,7 @@ struct event_desc {
- #define EVENT_NEWROUTE   23
- #define EVENT_TIME_ERR   24
- #define EVENT_SCRIPT_LOG 25
-+#define EVENT_TIME       26
- 
- /* Exit codes. */
- #define EC_GOOD        0
---- a/src/helper.c
-+++ b/src/helper.c
-@@ -97,13 +97,14 @@ int create_helper(int event_fd, int err_
-       return pipefd[1];
-     }
- 
--  /* ignore SIGTERM, so that we can clean up when the main process gets hit
-+  /* ignore SIGTERM and SIGINT, so that we can clean up when the main process gets hit
-      and SIGALRM so that we can use sleep() */
-   sigact.sa_handler = SIG_IGN;
-   sigact.sa_flags = 0;
-   sigemptyset(&sigact.sa_mask);
-   sigaction(SIGTERM, &sigact, NULL);
-   sigaction(SIGALRM, &sigact, NULL);
-+  sigaction(SIGINT, &sigact, NULL);
- 
-   if (!option_bool(OPT_DEBUG) && uid != 0)
-     {
diff --git a/package/network/services/dnsmasq/patches/270-dnssec-wildcards.patch b/package/network/services/dnsmasq/patches/270-dnssec-wildcards.patch
deleted file mode 100644
index d13ac2cbadaac6d12103785f9bada723dd5a02c5..0000000000000000000000000000000000000000
--- a/package/network/services/dnsmasq/patches/270-dnssec-wildcards.patch
+++ /dev/null
@@ -1,202 +0,0 @@
-From 4fe6744a220eddd3f1749b40cac3dfc510787de6 Mon Sep 17 00:00:00 2001
-From: Simon Kelley <simon@thekelleys.org.uk>
-Date: Fri, 19 Jan 2018 12:26:08 +0000
-Subject: [PATCH] DNSSEC fix for wildcard NSEC records. CVE-2017-15107
- applies.
-
-It's OK for NSEC records to be expanded from wildcards,
-but in that case, the proof of non-existence is only valid
-starting at the wildcard name, *.<domain> NOT the name expanded
-from the wildcard. Without this check it's possible for an
-attacker to craft an NSEC which wrongly proves non-existence
-in a domain which includes a wildcard for NSEC.
----
- src/dnssec.c |  117 +++++++++++++++++++++++++++++++++++++++++++++++++++-------
- 2 files changed, 114 insertions(+), 15 deletions(-)
-
---- a/src/dnssec.c
-+++ b/src/dnssec.c
-@@ -424,15 +424,17 @@ static void from_wire(char *name)
- static int count_labels(char *name)
- {
-   int i;
--
-+  char *p;
-+  
-   if (*name == 0)
-     return 0;
- 
--  for (i = 0; *name; name++)
--    if (*name == '.')
-+  for (p = name, i = 0; *p; p++)
-+    if (*p == '.')
-       i++;
- 
--  return i+1;
-+  /* Don't count empty first label. */
-+  return *name == '.' ? i : i+1;
- }
- 
- /* Implement RFC1982 wrapped compare for 32-bit numbers */
-@@ -1412,8 +1414,8 @@ static int hostname_cmp(const char *a, c
-     }
- }
- 
--static int prove_non_existence_nsec(struct dns_header *header, size_t plen, unsigned char **nsecs, int nsec_count,
--				    char *workspace1, char *workspace2, char *name, int type, int *nons)
-+static int prove_non_existence_nsec(struct dns_header *header, size_t plen, unsigned char **nsecs, unsigned char **labels, int nsec_count,
-+				    char *workspace1_in, char *workspace2, char *name, int type, int *nons)
- {
-   int i, rc, rdlen;
-   unsigned char *p, *psave;
-@@ -1426,6 +1428,9 @@ static int prove_non_existence_nsec(stru
-   /* Find NSEC record that proves name doesn't exist */
-   for (i = 0; i < nsec_count; i++)
-     {
-+      char *workspace1 = workspace1_in;
-+      int sig_labels, name_labels;
-+
-       p = nsecs[i];
-       if (!extract_name(header, plen, &p, workspace1, 1, 10))
- 	return 0;
-@@ -1434,7 +1439,27 @@ static int prove_non_existence_nsec(stru
-       psave = p;
-       if (!extract_name(header, plen, &p, workspace2, 1, 10))
- 	return 0;
--      
-+
-+      /* If NSEC comes from wildcard expansion, use original wildcard
-+	 as name for computation. */
-+      sig_labels = *labels[i];
-+      name_labels = count_labels(workspace1);
-+
-+      if (sig_labels < name_labels)
-+	{
-+	  int k;
-+	  for (k = name_labels - sig_labels; k != 0; k--)
-+	    {
-+	      while (*workspace1 != '.' && *workspace1 != 0)
-+		workspace1++;
-+	      if (k != 1 && *workspace1 == '.')
-+		workspace1++;
-+	    }
-+	  
-+	  workspace1--;
-+	  *workspace1 = '*';
-+	}
-+	  
-       rc = hostname_cmp(workspace1, name);
-       
-       if (rc == 0)
-@@ -1832,24 +1857,26 @@ static int prove_non_existence_nsec3(str
- 
- static int prove_non_existence(struct dns_header *header, size_t plen, char *keyname, char *name, int qtype, int qclass, char *wildname, int *nons)
- {
--  static unsigned char **nsecset = NULL;
--  static int nsecset_sz = 0;
-+  static unsigned char **nsecset = NULL, **rrsig_labels = NULL;
-+  static int nsecset_sz = 0, rrsig_labels_sz = 0;
-   
-   int type_found = 0;
--  unsigned char *p = skip_questions(header, plen);
-+  unsigned char *auth_start, *p = skip_questions(header, plen);
-   int type, class, rdlen, i, nsecs_found;
-   
-   /* Move to NS section */
-   if (!p || !(p = skip_section(p, ntohs(header->ancount), header, plen)))
-     return 0;
-+
-+  auth_start = p;
-   
-   for (nsecs_found = 0, i = ntohs(header->nscount); i != 0; i--)
-     {
-       unsigned char *pstart = p;
-       
--      if (!(p = skip_name(p, header, plen, 10)))
-+      if (!extract_name(header, plen, &p, daemon->workspacename, 1, 10))
- 	return 0;
--      
-+	  
-       GETSHORT(type, p); 
-       GETSHORT(class, p);
-       p += 4; /* TTL */
-@@ -1866,7 +1893,69 @@ static int prove_non_existence(struct dn
- 	  if (!expand_workspace(&nsecset, &nsecset_sz, nsecs_found))
- 	    return 0; 
- 	  
--	  nsecset[nsecs_found++] = pstart;
-+	  if (type == T_NSEC)
-+	    {
-+	      /* If we're looking for NSECs, find the corresponding SIGs, to 
-+		 extract the labels value, which we need in case the NSECs
-+		 are the result of wildcard expansion.
-+		 Note that the NSEC may not have been validated yet
-+		 so if there are multiple SIGs, make sure the label value
-+		 is the same in all, to avoid be duped by a rogue one.
-+		 If there are no SIGs, that's an error */
-+	      unsigned char *p1 = auth_start;
-+	      int res, j, rdlen1, type1, class1;
-+	      
-+	      if (!expand_workspace(&rrsig_labels, &rrsig_labels_sz, nsecs_found))
-+		return 0;
-+	      
-+	      rrsig_labels[nsecs_found] = NULL;
-+	      
-+	      for (j = ntohs(header->nscount); j != 0; j--)
-+		{
-+		  if (!(res = extract_name(header, plen, &p1, daemon->workspacename, 0, 10)))
-+		    return 0;
-+
-+		   GETSHORT(type1, p1); 
-+		   GETSHORT(class1, p1);
-+		   p1 += 4; /* TTL */
-+		   GETSHORT(rdlen1, p1);
-+
-+		   if (!CHECK_LEN(header, p1, plen, rdlen1))
-+		     return 0;
-+		   
-+		   if (res == 1 && class1 == qclass && type1 == T_RRSIG)
-+		     {
-+		       int type_covered;
-+		       unsigned char *psav = p1;
-+		       
-+		       if (rdlen1 < 18)
-+			 return 0; /* bad packet */
-+
-+		       GETSHORT(type_covered, p1);
-+
-+		       if (type_covered == T_NSEC)
-+			 {
-+			   p1++; /* algo */
-+			   
-+			   /* labels field must be the same in every SIG we find. */
-+			   if (!rrsig_labels[nsecs_found])
-+			     rrsig_labels[nsecs_found] = p1;
-+			   else if (*rrsig_labels[nsecs_found] != *p1) /* algo */
-+			     return 0;
-+			   }
-+		       p1 = psav;
-+		     }
-+		   
-+		   if (!ADD_RDLEN(header, p1, plen, rdlen1))
-+		     return 0;
-+		}
-+
-+	      /* Must have found at least one sig. */
-+	      if (!rrsig_labels[nsecs_found])
-+		return 0;
-+	    }
-+
-+	  nsecset[nsecs_found++] = pstart;   
- 	}
-       
-       if (!ADD_RDLEN(header, p, plen, rdlen))
-@@ -1874,7 +1963,7 @@ static int prove_non_existence(struct dn
-     }
-   
-   if (type_found == T_NSEC)
--    return prove_non_existence_nsec(header, plen, nsecset, nsecs_found, daemon->workspacename, keyname, name, qtype, nons);
-+    return prove_non_existence_nsec(header, plen, nsecset, rrsig_labels, nsecs_found, daemon->workspacename, keyname, name, qtype, nons);
-   else if (type_found == T_NSEC3)
-     return prove_non_existence_nsec3(header, plen, nsecset, nsecs_found, daemon->workspacename, keyname, name, qtype, wildname, nons);
-   else