diff options
| author | Paul Eggert | 2016-05-23 08:56:42 -0700 |
|---|---|---|
| committer | Paul Eggert | 2016-05-23 08:57:12 -0700 |
| commit | 918ef71538fd43049496e4370eba63e3096a4933 (patch) | |
| tree | 19e31312429e267a3bcec128fb7825f1e476103c /src/process.c | |
| parent | c6493c68f8fd6a5e6893eb3837a1a27f8d8a98a8 (diff) | |
| download | emacs-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.c | 63 |
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 | |||
| 2348 | static Lisp_Object | ||
| 2349 | conv_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 | ||
| 3099 | static void | 3109 | static void |
| 3100 | connect_network_socket (Lisp_Object proc, Lisp_Object ip_addresses, | 3110 | connect_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 | |||
| 4647 | check_for_dns (Lisp_Object proc) | 4652 | check_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 | } |