diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index 7c3a3ab..c91fd78 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -562,6 +562,7 @@ struct server {
 #ifdef HAVE_LOOP
   u32 uid;
 #endif
+  int trust; /* -1 unknown, 0 untrust, 1 trust */
   struct server *next;
 };

@@ -1014,6 +1015,16 @@ struct dhcp_relay {
   struct dhcp_relay *current, *next;
 };

+struct net_mask_t {
+  struct in_addr net;
+  in_addr_t mask;
+};
+
+struct net_list_t {
+  int entries;
+  struct net_mask_t *nets;
+};
+
 extern struct daemon {
   char *name;
   char *runfile;
@@ -1054,6 +1065,7 @@ extern struct daemon {
   struct iname *if_names, *if_addrs, *if_except, *dhcp_except;
   struct bogus_addr *bogus_addr, *ignore_addr;
+  struct net_list_t *chnroutes_list;
   struct server *servers;
   struct ipsets *ipsets;
   int log_fac;

@@ -1234,7 +1246,8 @@ int check_for_bogus_wildcard(struct dns_header *header, size_t qlen,
                              char *name, struct bogus_addr *baddr, time_t now);
-int check_for_ignored_address(struct dns_header *header, size_t qlen,
-                              struct bogus_addr *baddr);
+int check_for_ignored_address(struct dns_header *header, size_t qlen,
+                              struct bogus_addr *baddr,
+                              const struct net_list_t *netlist);

 char *parse_server(char *arg, union mysockaddr *addr,
                    union mysockaddr *source_addr, char *interface,
-                   int *flags);
+                   int *flags, int *trust);

diff --git a/src/option.c b/src/option.c
index 1a9c9c7..e98f71e 100644
--- a/src/option.c
+++ b/src/option.c
@@ -159,6 +159,7 @@ struct myoption {
 #define LOPT_DHCPTTL       348
 #define LOPT_TFTP_MTU      349
 #define LOPT_REPLY_DELAY   350
+#define LOPT_CHNROUTES_FILE 999
 #define LOPT_RAPID_COMMIT  351

 static const struct myoption opts[] =
@@ -204,6 +205,7 @@ static const struct myoption opts[] =
     { "bogus-priv", 0, 0, 'b' },
     { "bogus-nxdomain", 1, 0, 'B' },
     { "ignore-address", 1, 0, LOPT_IGNORE_ADDR },
+    { "chnroutes-file", 1, 0, LOPT_CHNROUTES_FILE },
     { "selfmx", 0, 0, 'e' },

@@ -514,6 +516,9 @@ static struct {
   { LOPT_IGNORE_ADDR, ARG_DUP, "<ipaddr>",
     gettext_noop("Ignore DNS responses containing ipaddr."), NULL },
+  { LOPT_CHNROUTES_FILE, ARG_ONE, "<path>",
+    gettext_noop("Trust dns server not containing ipaddr, untrust dns server containing ipaddr."),
+    NULL },
   { LOPT_DHCPTTL, ARG_ONE, "<ttl>",
     gettext_noop("Set TTL in DNS responses with DHCP-derived addresses."), NULL },

@@ -780,6 +785,15 @@ static char *parse_mysockaddr(char *arg, union mysockaddr *addr)
   return NULL;
 }

-char *parse_server(char *arg, union mysockaddr *addr,
-                   union mysockaddr *source_addr,
-                   char *interface, int *flags)
+char *parse_server(char *arg, union mysockaddr *addr,
+                   union mysockaddr *source_addr,
+                   char *interface, int *flags, int *trust)
 {
   int source_port = 0, serv_port = NAMESERVER_PORT;
-  char *portno, *source;
+  char *portno, *source, *trust_type;
+
+  *trust = -1;
+
+  if ((trust_type = split_chr(arg, ',')) &&
+      !atoi_check16(trust_type, trust))
+    return _("bad trust type");

   if (!arg || strlen(arg) == 0)
     {
@@ -1650,6 +1664,47 @@ static void server_list_free(struct server *list)
     }
 }

+static int parse_chnroutes(const char *filename,
+                           struct net_list_t *list)
+{
+  FILE *fp;
+  char line[64];
+  int i = 0;
+
+  fp = fopen(filename, "r");
+  if (!fp)
+    return -1;
+
+  list->entries = 0;
+  while (fgets(line, sizeof(line), fp))
+    list->entries++;
+
+  rewind(fp);
+  list->nets = calloc(list->entries, sizeof(struct net_mask_t));
+
+  while (fgets(line, sizeof(line), fp)) {
+    char *p = strchr(line, '/');
+    int prefix = 32;
+
+    if (p) {
+      *p++ = 0;
+      prefix = atoi(p);
+    }
+
+    inet_aton(line, &list->nets[i].net);
+    list->nets[i].mask =
+      htonl(~((1U << (32 - prefix)) - 1));
+    i++;
+  }
+
+  fclose(fp);
+  return 0;
+}
+
@@ -2508,6 +2563,16 @@ static int one_opt(int option, char *arg, char *errstr,
       break;

+    case LOPT_CHNROUTES_FILE:
+      {
+        struct net_list_t *l = opt_malloc(sizeof(*l));
+        if (parse_chnroutes(arg, l) < 0)
+          ret_err(_("cannot read chnroutes file"));
+        daemon->chnroutes_list = l;
+        break;
+      }

     case 'a': /* --listen-address */
       do {

@@ -2622,7 +2687,8 @@ static int one_opt(int option, char *arg, char *errstr,
       else
         {
-          char *err = parse_server(arg, &newlist->addr,
-                                   &newlist->source_addr,
-                                   newlist->interface, &newlist->flags);
+          char *err = parse_server(arg, &newlist->addr,
+                                   &newlist->source_addr,
+                                   newlist->interface,
+                                   &newlist->flags,
+                                   &newlist->trust);
           if (err)
             {
               server_list_free(newlist);
diff --git a/src/rfc1035.c b/src/rfc1035.c
index fefe63d..af83b90 100644
--- a/src/rfc1035.c
+++ b/src/rfc1035.c
@@ -1116,6 +1116,31 @@ int check_for_bogus_wildcard(struct dns_header *header, size_t qlen,
   return 0;
 }

-int check_for_ignored_address(struct dns_header *header,
-                              size_t qlen,
-                              struct bogus_addr *baddr)
+static int test_ip_in_list(struct in_addr ip,
+                           const struct net_list_t *list)
+{
+  uint32_t a = ntohl(ip.s_addr);
+  int i;
+
+  if (!list)
+    return 0;
+
+  for (i = 0; i < list->entries; i++)
+    if ((a & list->nets[i].mask) ==
+        (ntohl(list->nets[i].net.s_addr) & list->nets[i].mask))
+      return 1;
+
+  return 0;
+}
+
+int check_for_ignored_address(struct dns_header *header,
+                              size_t qlen,
+                              struct bogus_addr *baddr,
+                              const struct net_list_t *netlist)
 {
   unsigned char *p;
   int i, qtype, qclass, rdlen;
@@ -1140,6 +1165,17 @@ int check_for_ignored_address(struct dns_header *header,
         {
           if (!CHECK_LEN(header, p, qlen, INADDRSZ))
             return 0;
+
+          if (baddr) {
+            struct bogus_addr *baddrp;
+            for (baddrp = baddr; baddrp; baddrp = baddrp->next)
+              if (memcmp(&baddrp->addr, p, INADDRSZ) == 0)
+                return 1;
+          }
+
+          if (netlist) {
+            struct in_addr addr;
+            memcpy(&addr, p, INADDRSZ);
+            if (test_ip_in_list(addr, netlist))
+              return 1;
+          }
         }

       if (!ADD_RDLEN(header, p, qlen, rdlen))
diff --git a/src/forward.c b/src/forward.c
index fde554d..a7c3b1e 100644
--- a/src/forward.c
+++ b/src/forward.c
@@ -819,9 +819,22 @@ void reply_query(int fd, int family, time_t now)
   daemon->log_source_addr = &forward->source;

   if (daemon->ignore_addr && RCODE(header) == NOERROR &&
-      check_for_ignored_address(header, n, daemon->ignore_addr))
+      check_for_ignored_address(header, n,
+                                daemon->ignore_addr, NULL))
     return;

+  if ((server->trust == 0 || server->trust == 1) &&
+      daemon->chnroutes_list &&
+      RCODE(header) == NOERROR)
+    {
+      int c = check_for_ignored_address(header, n,
+                                        NULL,
+                                        daemon->chnroutes_list);
+
+      if (server->trust == 0 && c == 0)
+        return;
+      if (server->trust == 1 && c == 1)
+        return;
+    }
+
   if ((RCODE(header) == REFUSED || RCODE(header) == SERVFAIL) &&
       forward->forwardall == 0)

