aboutsummaryrefslogtreecommitdiffstats
path: root/src/process.c
diff options
context:
space:
mode:
authorPaul Eggert2016-05-23 08:56:42 -0700
committerPaul Eggert2016-05-23 08:57:12 -0700
commit918ef71538fd43049496e4370eba63e3096a4933 (patch)
tree19e31312429e267a3bcec128fb7825f1e476103c /src/process.c
parentc6493c68f8fd6a5e6893eb3837a1a27f8d8a98a8 (diff)
downloademacs-918ef71538fd43049496e4370eba63e3096a4933.tar.gz
emacs-918ef71538fd43049496e4370eba63e3096a4933.zip
Don’t use only last protocol from getaddrinfo
Problem reported by Ken Brown in: http://lists.gnu.org/archive/html/emacs-devel/2016-05/msg00483.html * src/process.c (conv_addrinfo_to_lisp): New function. (connect_network_socket): Arg is now a list of addrinfos, not merely IP addresses. All uses changed. Use protocol from each addrinfo. (Fmake_network_process): Accumulate protocols into addrinfos rather than just using the last one found. (check_for_dns): Accumulate protocols here, too. * src/process.h (struct Lisp_Process): Remove ai_protocol; no longer needed.
Diffstat (limited to 'src/process.c')
-rw-r--r--src/process.c63
1 files changed, 32 insertions, 31 deletions
diff --git a/src/process.c b/src/process.c
index d4bd19a24a9..9ca3e594355 100644
--- a/src/process.c
+++ b/src/process.c
@@ -2343,6 +2343,16 @@ conv_sockaddr_to_lisp (struct sockaddr *sa, ptrdiff_t len)
2343 return address; 2343 return address;
2344} 2344}
2345 2345
2346/* Convert an internal struct addrinfo to a Lisp object. */
2347
2348static Lisp_Object
2349conv_addrinfo_to_lisp (struct addrinfo *res)
2350{
2351 Lisp_Object protocol = make_number (res->ai_protocol);
2352 eassert (XINT (protocol) == res->ai_protocol);
2353 return Fcons (protocol, conv_sockaddr_to_lisp (res->ai_addr, res->ai_addrlen));
2354}
2355
2346 2356
2347/* Get family and required size for sockaddr structure to hold ADDRESS. */ 2357/* Get family and required size for sockaddr structure to hold ADDRESS. */
2348 2358
@@ -3097,14 +3107,13 @@ finish_after_tls_connection (Lisp_Object proc)
3097#endif 3107#endif
3098 3108
3099static void 3109static void
3100connect_network_socket (Lisp_Object proc, Lisp_Object ip_addresses, 3110connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos,
3101 Lisp_Object use_external_socket_p) 3111 Lisp_Object use_external_socket_p)
3102{ 3112{
3103 ptrdiff_t count = SPECPDL_INDEX (); 3113 ptrdiff_t count = SPECPDL_INDEX ();
3104 ptrdiff_t count1; 3114 ptrdiff_t count1;
3105 int s = -1, outch, inch; 3115 int s = -1, outch, inch;
3106 int xerrno = 0; 3116 int xerrno = 0;
3107 Lisp_Object ip_address;
3108 int family; 3117 int family;
3109 struct sockaddr *sa = NULL; 3118 struct sockaddr *sa = NULL;
3110 int ret; 3119 int ret;
@@ -3126,10 +3135,12 @@ connect_network_socket (Lisp_Object proc, Lisp_Object ip_addresses,
3126 count1 = SPECPDL_INDEX (); 3135 count1 = SPECPDL_INDEX ();
3127 s = -1; 3136 s = -1;
3128 3137
3129 while (!NILP (ip_addresses)) 3138 while (!NILP (addrinfos))
3130 { 3139 {
3131 ip_address = XCAR (ip_addresses); 3140 Lisp_Object addrinfo = XCAR (addrinfos);
3132 ip_addresses = XCDR (ip_addresses); 3141 addrinfos = XCDR (addrinfos);
3142 int protocol = XINT (XCAR (addrinfo));
3143 Lisp_Object ip_address = XCDR (addrinfo);
3133 3144
3134#ifdef WINDOWSNT 3145#ifdef WINDOWSNT
3135 retry_connect: 3146 retry_connect:
@@ -3147,7 +3158,7 @@ connect_network_socket (Lisp_Object proc, Lisp_Object ip_addresses,
3147 int socktype = p->socktype | SOCK_CLOEXEC; 3158 int socktype = p->socktype | SOCK_CLOEXEC;
3148 if (p->is_non_blocking_client) 3159 if (p->is_non_blocking_client)
3149 socktype |= SOCK_NONBLOCK; 3160 socktype |= SOCK_NONBLOCK;
3150 s = socket (family, socktype, p->ai_protocol); 3161 s = socket (family, socktype, protocol);
3151 if (s < 0) 3162 if (s < 0)
3152 { 3163 {
3153 xerrno = errno; 3164 xerrno = errno;
@@ -3624,10 +3635,10 @@ usage: (make-network-process &rest ARGS) */)
3624 Lisp_Object tem; 3635 Lisp_Object tem;
3625 Lisp_Object name, buffer, host, service, address; 3636 Lisp_Object name, buffer, host, service, address;
3626 Lisp_Object filter, sentinel, use_external_socket_p; 3637 Lisp_Object filter, sentinel, use_external_socket_p;
3627 Lisp_Object ip_addresses = Qnil; 3638 Lisp_Object addrinfos = Qnil;
3628 int socktype; 3639 int socktype;
3629 int family = -1; 3640 int family = -1;
3630 int ai_protocol = 0; 3641 enum { any_protocol = 0 };
3631#ifdef HAVE_GETADDRINFO_A 3642#ifdef HAVE_GETADDRINFO_A
3632 struct gaicb *dns_request = NULL; 3643 struct gaicb *dns_request = NULL;
3633#endif 3644#endif
@@ -3680,7 +3691,7 @@ usage: (make-network-process &rest ARGS) */)
3680 if (!get_lisp_to_sockaddr_size (address, &family)) 3691 if (!get_lisp_to_sockaddr_size (address, &family))
3681 error ("Malformed :address"); 3692 error ("Malformed :address");
3682 3693
3683 ip_addresses = list1 (address); 3694 addrinfos = list1 (Fcons (make_number (any_protocol), address));
3684 goto open_socket; 3695 goto open_socket;
3685 } 3696 }
3686 3697
@@ -3744,7 +3755,7 @@ usage: (make-network-process &rest ARGS) */)
3744 CHECK_STRING (service); 3755 CHECK_STRING (service);
3745 if (sizeof address_un.sun_path <= SBYTES (service)) 3756 if (sizeof address_un.sun_path <= SBYTES (service))
3746 error ("Service name too long"); 3757 error ("Service name too long");
3747 ip_addresses = list1 (service); 3758 addrinfos = list1 (Fcons (make_number (any_protocol), service));
3748 goto open_socket; 3759 goto open_socket;
3749 } 3760 }
3750#endif 3761#endif
@@ -3845,14 +3856,9 @@ usage: (make-network-process &rest ARGS) */)
3845 immediate_quit = 0; 3856 immediate_quit = 0;
3846 3857
3847 for (lres = res; lres; lres = lres->ai_next) 3858 for (lres = res; lres; lres = lres->ai_next)
3848 { 3859 addrinfos = Fcons (conv_addrinfo_to_lisp (lres), addrinfos);
3849 ip_addresses = Fcons (conv_sockaddr_to_lisp
3850 (lres->ai_addr, lres->ai_addrlen),
3851 ip_addresses);
3852 ai_protocol = lres->ai_protocol;
3853 }
3854 3860
3855 ip_addresses = Fnreverse (ip_addresses); 3861 addrinfos = Fnreverse (addrinfos);
3856 3862
3857 freeaddrinfo (res); 3863 freeaddrinfo (res);
3858 3864
@@ -3919,7 +3925,6 @@ usage: (make-network-process &rest ARGS) */)
3919 p->is_server = false; 3925 p->is_server = false;
3920 p->port = port; 3926 p->port = port;
3921 p->socktype = socktype; 3927 p->socktype = socktype;
3922 p->ai_protocol = ai_protocol;
3923#ifdef HAVE_GETADDRINFO_A 3928#ifdef HAVE_GETADDRINFO_A
3924 p->dns_request = NULL; 3929 p->dns_request = NULL;
3925#endif 3930#endif
@@ -3952,7 +3957,7 @@ usage: (make-network-process &rest ARGS) */)
3952#ifdef HAVE_GETADDRINFO_A 3957#ifdef HAVE_GETADDRINFO_A
3953 /* With async address resolution, the list of addresses is empty, so 3958 /* With async address resolution, the list of addresses is empty, so
3954 postpone connecting to the server. */ 3959 postpone connecting to the server. */
3955 if (!p->is_server && NILP (ip_addresses)) 3960 if (!p->is_server && NILP (addrinfos))
3956 { 3961 {
3957 p->dns_request = dns_request; 3962 p->dns_request = dns_request;
3958 p->status = Qconnect; 3963 p->status = Qconnect;
@@ -3960,7 +3965,7 @@ usage: (make-network-process &rest ARGS) */)
3960 } 3965 }
3961#endif 3966#endif
3962 3967
3963 connect_network_socket (proc, ip_addresses, use_external_socket_p); 3968 connect_network_socket (proc, addrinfos, use_external_socket_p);
3964 return proc; 3969 return proc;
3965} 3970}
3966 3971
@@ -4647,7 +4652,7 @@ static Lisp_Object
4647check_for_dns (Lisp_Object proc) 4652check_for_dns (Lisp_Object proc)
4648{ 4653{
4649 struct Lisp_Process *p = XPROCESS (proc); 4654 struct Lisp_Process *p = XPROCESS (proc);
4650 Lisp_Object ip_addresses = Qnil; 4655 Lisp_Object addrinfos = Qnil;
4651 4656
4652 /* Sanity check. */ 4657 /* Sanity check. */
4653 if (! p->dns_request) 4658 if (! p->dns_request)
@@ -4663,13 +4668,9 @@ check_for_dns (Lisp_Object proc)
4663 struct addrinfo *res; 4668 struct addrinfo *res;
4664 4669
4665 for (res = p->dns_request->ar_result; res; res = res->ai_next) 4670 for (res = p->dns_request->ar_result; res; res = res->ai_next)
4666 { 4671 addrinfos = Fcons (conv_addrinfo_to_lisp (res), addrinfos);
4667 ip_addresses = Fcons (conv_sockaddr_to_lisp
4668 (res->ai_addr, res->ai_addrlen),
4669 ip_addresses);
4670 }
4671 4672
4672 ip_addresses = Fnreverse (ip_addresses); 4673 addrinfos = Fnreverse (addrinfos);
4673 } 4674 }
4674 /* The DNS lookup failed. */ 4675 /* The DNS lookup failed. */
4675 else if (EQ (p->status, Qconnect)) 4676 else if (EQ (p->status, Qconnect))
@@ -4688,7 +4689,7 @@ check_for_dns (Lisp_Object proc)
4688 if (!EQ (p->status, Qconnect)) 4689 if (!EQ (p->status, Qconnect))
4689 return Qnil; 4690 return Qnil;
4690 4691
4691 return ip_addresses; 4692 return addrinfos;
4692} 4693}
4693 4694
4694#endif /* HAVE_GETADDRINFO_A */ 4695#endif /* HAVE_GETADDRINFO_A */
@@ -4871,9 +4872,9 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
4871 /* Check for pending DNS requests. */ 4872 /* Check for pending DNS requests. */
4872 if (p->dns_request) 4873 if (p->dns_request)
4873 { 4874 {
4874 Lisp_Object ip_addresses = check_for_dns (aproc); 4875 Lisp_Object addrinfos = check_for_dns (aproc);
4875 if (!NILP (ip_addresses) && !EQ (ip_addresses, Qt)) 4876 if (!NILP (addrinfos) && !EQ (addrinfos, Qt))
4876 connect_network_socket (aproc, ip_addresses, Qnil); 4877 connect_network_socket (aproc, addrinfos, Qnil);
4877 else 4878 else
4878 retry_for_async = true; 4879 retry_for_async = true;
4879 } 4880 }