Subject: Re: bug#40343: 28.0.50; dns-set-servers fails on IPv6 available Windows

From: Robert Pluim <[email-masked]>
Date: Fri, 03 Apr 2020 10:42:24 +0200

>>>>> On Wed, 01 Apr 2020 23:55:12 +0900, Kazuhiro Ito <[email-masked]> said:

    Kazuhiro> I tested on Debian box as below.

    Kazuhiro> 1. /etc/init.d/networking stop
    Kazuhiro> 2. remove nameserver entry from /etc/resolv.conf

    Kazuhiro> On such condition, nslookup program outputs as below

    >> ;; connection timed out; no servers could be reached

    Kazuhiro> Here is code snippet communicating with nslookup in dns-set-servers.

    >> (with-temp-buffer
    >> (call-process "nslookup" nil t nil "localhost")
    >> (goto-char (point-min))
    >> (re-search-forward
    >> "^Address:[ \t]*\\([0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+\\)" nil t)
    >> (setq dns-servers (list (match-string 1))))

    Kazuhiro> On the above condition, re-search-forward doesn't match anything.  But
    Kazuhiro> next match-string is called unconditionally.  As far as I tested,
    Kazuhiro> match-string's result when last search didn't match is undefined.  it
    Kazuhiro> may return nil, string or raise an error.  Additionally, even if
    Kazuhiro> match-string returns nil, dns-servers is never set to nil.  It is set
    Kazuhiro> to (nil).

Thanks for that. This should fix all those cases:

diff --git a/lisp/net/dns.el b/lisp/net/dns.el
index 78d4827162..177df4e332 100644
--- a/lisp/net/dns.el
+++ b/lisp/net/dns.el
@@ -315,8 +315,8 @@ dns-servers-up-to-date-p
 (defun dns-set-servers ()
   "Set `dns-servers' to a list of DNS servers or nil if none are found.
 Parses \"/etc/resolv.conf\" or calls \"nslookup\"."
+  (setq dns-servers nil)
   (or (when (file-exists-p "/etc/resolv.conf")
-	(setq dns-servers nil)
 	(with-temp-buffer
 	  (insert-file-contents "/etc/resolv.conf")
 	  (goto-char (point-min))
@@ -327,9 +327,9 @@ dns-set-servers
 	(with-temp-buffer
 	  (call-process "nslookup" nil t nil "localhost")
 	  (goto-char (point-min))
-	  (re-search-forward
-	   "^Address:[ \t]*\\([0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+\\)" nil t)
-	  (setq dns-servers (list (match-string 1))))))
+          (when (re-search-forward
+	   "^Address:[ \t]*\\([0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+\\|[[:xdigit:]:]*\\)" nil t)
+	      (setq dns-servers (list (match-string 1)))))))
   (when (fboundp 'network-interface-list)
     (setq dns-servers-valid-for-interfaces (network-interface-list))))
 
@@ -357,7 +357,9 @@ dns-make-network-process
   `(let ((server ,server)
 	 (coding-system-for-read 'binary)
 	 (coding-system-for-write 'binary))
-     (if (fboundp 'make-network-process)
+     (if (and
+          (fboundp 'make-network-process)
+          (featurep 'make-network-process '(:type datagram)))
 	 (make-network-process
 	  :name "dns"
 	  :coding 'binary
@@ -365,9 +367,9 @@ dns-make-network-process
 	  :host server
 	  :service "domain"
 	  :type 'datagram)
-       ;; Older versions of Emacs doesn't have
-       ;; `make-network-process', so we fall back on opening a TCP
-       ;; connection to the DNS server.
+       ;; Older versions of Emacs do not have `make-network-process',
+       ;; and on MS-Windows datagram sockets are not supported, so we
+       ;; fall back on opening a TCP connection to the DNS server.
        (open-network-stream "dns" (current-buffer) server "domain"))))
 
 (defvar dns-cache (make-vector 4096 0))
@@ -400,7 +402,9 @@ dns-query
 	  type 'PTR))
 
   (if (not dns-servers)
-      (message "No DNS server configuration found")
+      (progn
+        (message "No DNS server configuration found")
+        nil)
     (with-temp-buffer
       (set-buffer-multibyte nil)
       (let ((process (condition-case ()