diff options
author | Lars Ingebrigtsen <larsi@gnus.org> | 2019-08-23 04:49:52 +0200 |
---|---|---|
committer | Lars Ingebrigtsen <larsi@gnus.org> | 2019-08-23 04:49:52 +0200 |
commit | 53cb3d3e0ddb666dc5b7774957ca863c668213cb (patch) | |
tree | 011cf32acf25b0cd86debf5b3c22be289e60bd87 /src/process.c | |
parent | b4d3a882a8423e81c418fc56b7a9677f5582fcc7 (diff) | |
parent | 29d485fb768fbe375d60fd80cb2dbdbd90f3becc (diff) | |
download | emacs-53cb3d3e0ddb666dc5b7774957ca863c668213cb.tar.gz |
Merge remote-tracking branch 'origin/netsec'
Diffstat (limited to 'src/process.c')
-rw-r--r-- | src/process.c | 108 |
1 files changed, 93 insertions, 15 deletions
diff --git a/src/process.c b/src/process.c index 066edbc83d6..7097b7ace17 100644 --- a/src/process.c +++ b/src/process.c @@ -276,6 +276,10 @@ static int read_process_output (Lisp_Object, int); static void create_pty (Lisp_Object); static void exec_sentinel (Lisp_Object, Lisp_Object); +static Lisp_Object +network_lookup_address_info_1 (Lisp_Object host, const char *service, + struct addrinfo *hints, struct addrinfo **res); + /* Number of bits set in connect_wait_mask. */ static int num_pending_connects; @@ -4106,7 +4110,7 @@ usage: (make-network-process &rest ARGS) */) if (!NILP (host)) { struct addrinfo *res, *lres; - int ret; + Lisp_Object msg; maybe_quit (); @@ -4115,20 +4119,11 @@ usage: (make-network-process &rest ARGS) */) hints.ai_family = family; hints.ai_socktype = socktype; - ret = getaddrinfo (SSDATA (host), portstring, &hints, &res); - if (ret) -#ifdef HAVE_GAI_STRERROR - { - synchronize_system_messages_locale (); - char const *str = gai_strerror (ret); - if (! NILP (Vlocale_coding_system)) - str = SSDATA (code_convert_string_norecord - (build_string (str), Vlocale_coding_system, 0)); - error ("%s/%s %s", SSDATA (host), portstring, str); - } -#else - error ("%s/%s getaddrinfo error %d", SSDATA (host), portstring, ret); -#endif + msg = network_lookup_address_info_1 (host, portstring, &hints, &res); + if (!EQ(msg, Qt)) + { + error ("%s", SSDATA (msg)); + } for (lres = res; lres; lres = lres->ai_next) addrinfos = Fcons (conv_addrinfo_to_lisp (lres), addrinfos); @@ -4576,6 +4571,88 @@ Data that is unavailable is returned as nil. */) #endif } +static Lisp_Object +network_lookup_address_info_1 (Lisp_Object host, const char *service, + struct addrinfo *hints, struct addrinfo **res) +{ + Lisp_Object msg = Qt; + int ret; + + if (STRING_MULTIBYTE (host) && SBYTES (host) != SCHARS (host)) + error ("Non-ASCII hostname %s detected, please use puny-encode-domain", + SSDATA (host)); + ret = getaddrinfo (SSDATA (host), service, hints, res); + if (ret) + { + if (service == NULL) + service = "0"; +#ifdef HAVE_GAI_STRERROR + synchronize_system_messages_locale (); + char const *str = gai_strerror (ret); + if (! NILP (Vlocale_coding_system)) + str = SSDATA (code_convert_string_norecord + (build_string (str), Vlocale_coding_system, 0)); + AUTO_STRING (format, "%s/%s %s"); + msg = CALLN (Fformat, format, host, build_string (service), build_string (str)); +#else + AUTO_STRING (format, "%s/%s getaddrinfo error %d"); + msg = CALLN (Fformat, format, host, build_string (service), make_number (ret)); +#endif + } + return msg; +} + +DEFUN ("network-lookup-address-info", Fnetwork_lookup_address_info, + Snetwork_lookup_address_info, 1, 2, 0, + doc: /* Look up ip address info of NAME. +Optional parameter FAMILY controls whether to look up IPv4 or IPv6 +addresses. The default of nil means both, symbol `ipv4' means IPv4 +only, symbol `ipv6' means IPv6 only. Returns a list of addresses, or +nil if none were found. Each address is a vector of integers. */) + (Lisp_Object name, Lisp_Object family) +{ + Lisp_Object addresses = Qnil; + Lisp_Object msg = Qnil; + + struct addrinfo *res, *lres; + struct addrinfo hints; + + memset (&hints, 0, sizeof hints); + if (EQ (family, Qnil)) + hints.ai_family = AF_UNSPEC; + else if (EQ (family, Qipv4)) + hints.ai_family = AF_INET; + else if (EQ (family, Qipv6)) +#ifdef AF_INET6 + hints.ai_family = AF_INET6; +#else + /* If we don't support IPv6, querying will never work anyway */ + return addresses; +#endif + else + error ("Unsupported lookup type"); + hints.ai_socktype = SOCK_DGRAM; + + msg = network_lookup_address_info_1 (name, NULL, &hints, &res); + if (!EQ(msg, Qt)) + { + message ("%s", SSDATA(msg)); + } + else + { + for (lres = res; lres; lres = lres->ai_next) + { + addresses = Fcons (conv_sockaddr_to_lisp + (lres->ai_addr, lres->ai_addrlen), + addresses); + } + addresses = Fnreverse (addresses); + + freeaddrinfo (res); + } + return addresses; +} + /* Turn off input and output for process PROC. */ static void @@ -8345,6 +8422,7 @@ returns non-`nil'. */); defsubr (&Sset_network_process_option); defsubr (&Smake_network_process); defsubr (&Sformat_network_address); + defsubr (&Snetwork_lookup_address_info); defsubr (&Snetwork_interface_list); defsubr (&Snetwork_interface_info); #ifdef DATAGRAM_SOCKETS |