import of dnsmasq-2.24.tar.gz
diff --git a/src/forward.c b/src/forward.c
index 082ee74..064f5f9 100644
--- a/src/forward.c
+++ b/src/forward.c
@@ -90,7 +90,7 @@
 #endif
 	}
       else
-#ifdef HAVE_IPV
+#ifdef HAVE_IPV6
 	{
 	  struct in6_pktinfo *pkt = (struct in6_pktinfo *)CMSG_DATA(cmptr);
 	  pkt->ipi6_ifindex = iface; /* Need iface for IPv6 to handle link-local addrs */
@@ -160,9 +160,11 @@
     else if (serv->flags & SERV_HAS_DOMAIN)
       {
 	unsigned int domainlen = strlen(serv->domain);
+	char *matchstart = qdomain + namelen - domainlen;
 	if (namelen >= domainlen &&
-	    hostname_isequal(qdomain + namelen - domainlen, serv->domain) &&
-	    domainlen >= matchlen)
+	    hostname_isequal(matchstart, serv->domain) &&
+	    domainlen >= matchlen &&
+	    (namelen == domainlen || *(serv->domain) == '.' || *(matchstart-1) == '.' ))
 	  {
 	    unsigned short sflag = serv->addr.sa.sa_family == AF_INET ? F_IPV4 : F_IPV6;
 	    *type = SERV_HAS_DOMAIN;
@@ -210,9 +212,8 @@
 /* returns new last_server */	
 static void forward_query(struct daemon *daemon, int udpfd, union mysockaddr *udpaddr,
 			  struct all_addr *dst_addr, unsigned int dst_iface,
-			  HEADER *header, int plen, time_t now)
+			  HEADER *header, int plen, time_t now, struct frec *forward)
 {
-  struct frec *forward;
   char *domain = NULL;
   int type = 0;
   struct all_addr *addrp = NULL;
@@ -224,7 +225,7 @@
   /* may be no servers available. */
   if (!daemon->servers)
     forward = NULL;
-  else if ((forward = lookup_frec_by_sender(ntohs(header->id), udpaddr, crc)))
+  else if (forward || (forward = lookup_frec_by_sender(ntohs(header->id), udpaddr, crc)))
     {
       /* retry on existing query, send to all available servers  */
       domain = forward->sentto->domain;
@@ -337,9 +338,12 @@
     }	  
   
   /* could not send on, return empty answer or address if known for whole domain */
-  plen = setup_reply(header, (unsigned int)plen, addrp, flags, daemon->local_ttl);
-  send_from(udpfd, daemon->options & OPT_NOWILD, (char *)header, plen, udpaddr, dst_addr, dst_iface);
-  
+  if (udpfd != -1)
+    {
+      plen = setup_reply(header, (unsigned int)plen, addrp, flags, daemon->local_ttl);
+      send_from(udpfd, daemon->options & OPT_NOWILD, (char *)header, plen, udpaddr, dst_addr, dst_iface);
+    }
+
   return;
 }
 
@@ -371,7 +375,7 @@
       server && !(server->flags & SERV_WARNED_RECURSIVE))
     {
       prettyprint_addr(&server->addr, daemon->namebuff);
-      syslog(LOG_WARNING, "nameserver %s refused to do a recursive query", daemon->namebuff);
+      syslog(LOG_WARNING, _("nameserver %s refused to do a recursive query"), daemon->namebuff);
       if (!(daemon->options & OPT_LOG))
 	server->flags |= SERV_WARNED_RECURSIVE;
     }  
@@ -445,40 +449,62 @@
     {
        struct server *server = forward->sentto;
        
+       if ((header->rcode == SERVFAIL || header->rcode == REFUSED) && forward->forwardall == 0)
+	 /* for broken servers, attempt to send to another one. */
+	 {
+	   unsigned char *pheader;
+	   unsigned int plen;
+	   int nn;
+	   /* recreate query from reply */
+	   pheader = find_pseudoheader(header, n, &plen, NULL);
+	   header->ancount = htons(0);
+	   header->nscount = htons(0);
+	   header->arcount = htons(0);
+	   if ((nn = resize_packet(header, n, pheader, plen)))
+	     {
+	       forward->forwardall = 1;
+	       header->qr = 0;
+	       header->tc = 0;
+	       forward_query(daemon, -1, NULL, NULL, 0, header, nn, now, forward);
+	       return;
+	     }
+	 }   
+
        if ((forward->sentto->flags & SERV_TYPE) == 0)
 	 {
 	   if (header->rcode == SERVFAIL || header->rcode == REFUSED)
 	     server = NULL;
 	   else
-	    {
-	      /* find good server by address if possible, otherwise assume the last one we sent to */ 
-	      struct server *last_server;
-	      for (last_server = daemon->servers; last_server; last_server = last_server->next)
-		if (!(last_server->flags & (SERV_LITERAL_ADDRESS | SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_NO_ADDR)) &&
-		    sockaddr_isequal(&last_server->addr, &serveraddr))
-		  {
-		    server = last_server;
-		    break;
-		  }
-	    } 
+	     {
+	       struct server *last_server;
+	       /* find good server by address if possible, otherwise assume the last one we sent to */ 
+	       for (last_server = daemon->servers; last_server; last_server = last_server->next)
+		 if (!(last_server->flags & (SERV_LITERAL_ADDRESS | SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_NO_ADDR)) &&
+		     sockaddr_isequal(&last_server->addr, &serveraddr))
+		   {
+		     server = last_server;
+		     break;
+		   }
+	     } 
 	   daemon->last_server = server;
 	 }
-       
-      if ((n = process_reply(daemon, header, now, forward->crc, server, (unsigned int)n)))
-	{
-	  header->id = htons(forward->orig_id);
-	  header->ra = 1; /* recursion if available */
-	  send_from(forward->fd, daemon->options & OPT_NOWILD, daemon->packet, n, 
-		    &forward->source, &forward->dest, forward->iface);
-	}
-	 
+	         
       /* If the answer is an error, keep the forward record in place in case
 	 we get a good reply from another server. Kill it when we've
 	 had replies from all to avoid filling the forwarding table when
 	 everything is broken */
       if (forward->forwardall == 0 || --forward->forwardall == 1 || 
 	  (header->rcode != REFUSED && header->rcode != SERVFAIL))
-	forward->new_id = 0; /* cancel */
+	{
+	  if ((n = process_reply(daemon, header, now, forward->crc, server, (unsigned int)n)))
+	    {
+	      header->id = htons(forward->orig_id);
+	      header->ra = 1; /* recursion if available */
+	      send_from(forward->fd, daemon->options & OPT_NOWILD, daemon->packet, n, 
+			&forward->source, &forward->dest, forward->iface);
+	    }
+	  forward->new_id = 0; /* cancel */
+	}
     }
 }
 
@@ -650,7 +676,7 @@
     send_from(listen->fd, daemon->options & OPT_NOWILD, (char *)header, m, &source_addr, &dst_addr, if_index);
   else
     forward_query(daemon, listen->fd, &source_addr, &dst_addr, if_index,
-		  header, n, now);
+		  header, n, now, NULL);
 }
 
 static int read_write(int fd, unsigned char *packet, int size, int rw)
@@ -870,7 +896,7 @@
       if (!warntime || difftime(now, warntime) > LOGRATE)
 	{
 	  warntime = now;
-	  syslog(LOG_WARNING, "forwarding table overflow: check for server loops.");
+	  syslog(LOG_WARNING, _("forwarding table overflow: check for server loops."));
 	}
       return NULL;
     }