From 49f6243027d910032f014be15b2c4ac2175c25f8 Mon Sep 17 00:00:00 2001 From: Robert Pluim Date: Thu, 31 Jan 2019 14:20:32 +0100 Subject: [PATCH] Use IPv6 localhost when family is 'ipv6 This fixes Bug#34193 * src/process.c (Fmake_network_process): Explicitly use ::1 when using IPv6 with 'local. Update docstring. * test/lisp/net/network-stream-tests.el (make-ipv6-tcp-server-with-unspecified-port): (make-ipv6-tcp-server-with-specified-port): Test creating ipv6 local server. (make-server): Add optional family argument, default ipv4 (echo-server-with-local-ipv4): Test connecting to 'local ipv4 (echo-server-with-local-ipv6): Test connecting to 'local ipv6 * doc/lispref/processes.texi (Network Processes): Describe behavior when using 'local. * etc/NEWS: Document new 'make-network-process' behavior when connecting to 'local with ipv6. --- doc/lispref/processes.texi | 4 +- etc/NEWS | 5 +++ src/process.c | 16 +++++++- test/lisp/net/network-stream-tests.el | 59 ++++++++++++++++++++++++++- 4 files changed, 79 insertions(+), 5 deletions(-) diff --git a/doc/lispref/processes.texi b/doc/lispref/processes.texi index fd6686e8828..7b02759b307 100644 --- a/doc/lispref/processes.texi +++ b/doc/lispref/processes.texi @@ -2640,7 +2640,9 @@ Specify the host to connect to. @var{host} should be a host name or Internet address, as a string, or the symbol @code{local} to specify the local host. If you specify @var{host} for a server, it must specify a valid address for the local host, and only clients -connecting to that address will be accepted. +connecting to that address will be accepted. When using @code{local}, +by default IPv4 will be used, specify a @var{family} of @code{ipv6} to +override this. @item :service @var{service} @var{service} specifies a port number to connect to; or, for a server, diff --git a/etc/NEWS b/etc/NEWS index cac379fe7eb..2e3d92f2515 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -324,6 +324,11 @@ write alists of variables to ".dir-locals.el". This is the same syntax that you can see in the example of a ".dir-locals.el" file in the node "(emacs) Directory Variables" of the user manual. ++++ +** Network connections using 'local can now use IPv6. +'make-network-process' now uses the correct loopback address when +asked to use :host 'local and :family 'ipv6. + * Changes in Specialized Modes and Packages in Emacs 27.1 diff --git a/src/process.c b/src/process.c index 728c14a7624..9502ef461e8 100644 --- a/src/process.c +++ b/src/process.c @@ -3733,6 +3733,8 @@ also nil, meaning that this process is not associated with any buffer. address. The symbol `local' specifies the local host. If specified for a server process, it must be a valid name or address for the local host, and only clients connecting to that address will be accepted. +`local' will use IPv4 by default, use a FAMILY of 'ipv6 to override +this. :service SERVICE -- SERVICE is name of the service desired, or an integer specifying a port number to connect to. If SERVICE is t, @@ -3983,14 +3985,24 @@ usage: (make-network-process &rest ARGS) */) #ifdef HAVE_LOCAL_SOCKETS if (family != AF_LOCAL) #endif - host = build_string ("127.0.0.1"); + { + if (family == AF_INET6) + host = build_string ("::1"); + else + host = build_string ("127.0.0.1"); + } } else { if (EQ (host, Qlocal)) + { /* Depending on setup, "localhost" may map to different IPv4 and/or IPv6 addresses, so it's better to be explicit (Bug#6781). */ - host = build_string ("127.0.0.1"); + if (family == AF_INET6) + host = build_string ("::1"); + else + host = build_string ("127.0.0.1"); + } CHECK_STRING (host); } diff --git a/test/lisp/net/network-stream-tests.el b/test/lisp/net/network-stream-tests.el index 6ad0c25903f..6151c3064c4 100644 --- a/test/lisp/net/network-stream-tests.el +++ b/test/lisp/net/network-stream-tests.el @@ -71,12 +71,39 @@ (= (aref (process-contact server :local) 4) 57869))) (delete-process server))) -(defun make-server (host) +(ert-deftest make-ipv6-tcp-server-with-unspecified-port () + (let ((server + (make-network-process + :name "server" + :server t + :noquery t + :family 'ipv6 + :service t + :host 'local))) + (should (and (arrayp (process-contact server :local)) + (numberp (aref (process-contact server :local) 8)) + (> (aref (process-contact server :local) 8) 0))) + (delete-process server))) + +(ert-deftest make-ipv6-tcp-server-with-specified-port () + (let ((server + (make-network-process + :name "server" + :server t + :noquery t + :family 'ipv6 + :service 57870 + :host 'local))) + (should (and (arrayp (process-contact server :local)) + (= (aref (process-contact server :local) 8) 57870))) + (delete-process server))) + +(defun make-server (host &optional family) (make-network-process :name "server" :server t :noquery t - :family 'ipv4 + :family (or family 'ipv4) :coding 'raw-text-unix :buffer (get-buffer-create "*server*") :service t @@ -129,6 +156,34 @@ (should (equal (buffer-string) "foo\n"))) (delete-process server))) +(ert-deftest echo-server-with-local-ipv4 () + (let* ((server (make-server 'local 'ipv4)) + (port (aref (process-contact server :local) 4)) + (proc (make-network-process :name "foo" + :buffer (generate-new-buffer "*foo*") + :host 'local + :family 'ipv4 + :service port))) + (with-current-buffer (process-buffer proc) + (process-send-string proc "echo foo") + (sleep-for 0.1) + (should (equal (buffer-string) "foo\n"))) + (delete-process server))) + +(ert-deftest echo-server-with-local-ipv6 () + (let* ((server (make-server 'local 'ipv6)) + (port (aref (process-contact server :local) 8)) + (proc (make-network-process :name "foo" + :buffer (generate-new-buffer "*foo*") + :host 'local + :family 'ipv6 + :service port))) + (with-current-buffer (process-buffer proc) + (process-send-string proc "echo foo") + (sleep-for 0.1) + (should (equal (buffer-string) "foo\n"))) + (delete-process server))) + (ert-deftest echo-server-with-ip () (let* ((server (make-server 'local)) (port (aref (process-contact server :local) 4)) -- 2.39.5