diff options
| author | Robert Pluim | 2018-07-16 19:43:41 +0200 |
|---|---|---|
| committer | Robert Pluim | 2018-07-16 19:44:54 +0200 |
| commit | e89c06e8cea429620bc2cf4a98b9b741861b811a (patch) | |
| tree | fbd168a342c20512c982bc7641b5bbbf870818d8 /src/process.c | |
| parent | fab6139b8954c4d33c4430a722337e09939aa777 (diff) | |
| download | emacs-e89c06e8cea429620bc2cf4a98b9b741861b811a.tar.gz emacs-e89c06e8cea429620bc2cf4a98b9b741861b811a.zip | |
Implement hostname->ip lookup function
* src/process.c (conv_sockaddr_to_lisp): Add include_port
argument. Don't put a port in the result if this is false.
(conv_addrinfo_to_lisp, Fprocess_datagram_address)
(connect_network_socket, network_interface_list)
(network_interface_info, server_accept_connection)
(init_process_emacs): Update callers.
(Fnetwork_lookup_address_info): New function. Performs hostname to
ip address lookups.
* src/w32.c (network_interface_get_info): Update callers of
conv_sockaddr_to_lisp
* etc/NEWS : mention addition of 'network-lookup-address-info'
Diffstat (limited to 'src/process.c')
| -rw-r--r-- | src/process.c | 100 |
1 files changed, 85 insertions, 15 deletions
diff --git a/src/process.c b/src/process.c index 3fccd962da6..2025398c22d 100644 --- a/src/process.c +++ b/src/process.c | |||
| @@ -2484,7 +2484,7 @@ usage: (make-pipe-process &rest ARGS) */) | |||
| 2484 | The address family of sa is not included in the result. */ | 2484 | The address family of sa is not included in the result. */ |
| 2485 | 2485 | ||
| 2486 | Lisp_Object | 2486 | Lisp_Object |
| 2487 | conv_sockaddr_to_lisp (struct sockaddr *sa, ptrdiff_t len) | 2487 | conv_sockaddr_to_lisp (struct sockaddr *sa, ptrdiff_t len, bool include_port) |
| 2488 | { | 2488 | { |
| 2489 | Lisp_Object address; | 2489 | Lisp_Object address; |
| 2490 | ptrdiff_t i; | 2490 | ptrdiff_t i; |
| @@ -2503,9 +2503,12 @@ conv_sockaddr_to_lisp (struct sockaddr *sa, ptrdiff_t len) | |||
| 2503 | { | 2503 | { |
| 2504 | DECLARE_POINTER_ALIAS (sin, struct sockaddr_in, sa); | 2504 | DECLARE_POINTER_ALIAS (sin, struct sockaddr_in, sa); |
| 2505 | len = sizeof (sin->sin_addr) + 1; | 2505 | len = sizeof (sin->sin_addr) + 1; |
| 2506 | if (!include_port) | ||
| 2507 | len--; | ||
| 2506 | address = Fmake_vector (make_number (len), Qnil); | 2508 | address = Fmake_vector (make_number (len), Qnil); |
| 2507 | p = XVECTOR (address); | 2509 | p = XVECTOR (address); |
| 2508 | p->contents[--len] = make_number (ntohs (sin->sin_port)); | 2510 | if (include_port) |
| 2511 | p->contents[--len] = make_number (ntohs (sin->sin_port)); | ||
| 2509 | cp = (unsigned char *) &sin->sin_addr; | 2512 | cp = (unsigned char *) &sin->sin_addr; |
| 2510 | break; | 2513 | break; |
| 2511 | } | 2514 | } |
| @@ -2515,9 +2518,12 @@ conv_sockaddr_to_lisp (struct sockaddr *sa, ptrdiff_t len) | |||
| 2515 | DECLARE_POINTER_ALIAS (sin6, struct sockaddr_in6, sa); | 2518 | DECLARE_POINTER_ALIAS (sin6, struct sockaddr_in6, sa); |
| 2516 | DECLARE_POINTER_ALIAS (ip6, uint16_t, &sin6->sin6_addr); | 2519 | DECLARE_POINTER_ALIAS (ip6, uint16_t, &sin6->sin6_addr); |
| 2517 | len = sizeof (sin6->sin6_addr) / 2 + 1; | 2520 | len = sizeof (sin6->sin6_addr) / 2 + 1; |
| 2521 | if (!include_port) | ||
| 2522 | len--; | ||
| 2518 | address = Fmake_vector (make_number (len), Qnil); | 2523 | address = Fmake_vector (make_number (len), Qnil); |
| 2519 | p = XVECTOR (address); | 2524 | p = XVECTOR (address); |
| 2520 | p->contents[--len] = make_number (ntohs (sin6->sin6_port)); | 2525 | if (include_port) |
| 2526 | p->contents[--len] = make_number (ntohs (sin6->sin6_port)); | ||
| 2521 | for (i = 0; i < len; i++) | 2527 | for (i = 0; i < len; i++) |
| 2522 | p->contents[i] = make_number (ntohs (ip6[i])); | 2528 | p->contents[i] = make_number (ntohs (ip6[i])); |
| 2523 | return address; | 2529 | return address; |
| @@ -2568,7 +2574,7 @@ conv_addrinfo_to_lisp (struct addrinfo *res) | |||
| 2568 | { | 2574 | { |
| 2569 | Lisp_Object protocol = make_number (res->ai_protocol); | 2575 | Lisp_Object protocol = make_number (res->ai_protocol); |
| 2570 | eassert (XINT (protocol) == res->ai_protocol); | 2576 | eassert (XINT (protocol) == res->ai_protocol); |
| 2571 | return Fcons (protocol, conv_sockaddr_to_lisp (res->ai_addr, res->ai_addrlen)); | 2577 | return Fcons (protocol, conv_sockaddr_to_lisp (res->ai_addr, res->ai_addrlen, true)); |
| 2572 | } | 2578 | } |
| 2573 | 2579 | ||
| 2574 | 2580 | ||
| @@ -2710,7 +2716,8 @@ set up yet, this function will block until socket setup has completed. */) | |||
| 2710 | 2716 | ||
| 2711 | channel = XPROCESS (process)->infd; | 2717 | channel = XPROCESS (process)->infd; |
| 2712 | return conv_sockaddr_to_lisp (datagram_address[channel].sa, | 2718 | return conv_sockaddr_to_lisp (datagram_address[channel].sa, |
| 2713 | datagram_address[channel].len); | 2719 | datagram_address[channel].len, |
| 2720 | true); | ||
| 2714 | } | 2721 | } |
| 2715 | 2722 | ||
| 2716 | DEFUN ("set-process-datagram-address", Fset_process_datagram_address, Sset_process_datagram_address, | 2723 | DEFUN ("set-process-datagram-address", Fset_process_datagram_address, Sset_process_datagram_address, |
| @@ -3571,7 +3578,7 @@ connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos, | |||
| 3571 | #endif | 3578 | #endif |
| 3572 | 3579 | ||
| 3573 | contact = Fplist_put (contact, p->is_server? QClocal: QCremote, | 3580 | contact = Fplist_put (contact, p->is_server? QClocal: QCremote, |
| 3574 | conv_sockaddr_to_lisp (sa, addrlen)); | 3581 | conv_sockaddr_to_lisp (sa, addrlen, true)); |
| 3575 | #ifdef HAVE_GETSOCKNAME | 3582 | #ifdef HAVE_GETSOCKNAME |
| 3576 | if (!p->is_server) | 3583 | if (!p->is_server) |
| 3577 | { | 3584 | { |
| @@ -3580,7 +3587,7 @@ connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos, | |||
| 3580 | DECLARE_POINTER_ALIAS (psa1, struct sockaddr, &sa1); | 3587 | DECLARE_POINTER_ALIAS (psa1, struct sockaddr, &sa1); |
| 3581 | if (getsockname (s, psa1, &len1) == 0) | 3588 | if (getsockname (s, psa1, &len1) == 0) |
| 3582 | contact = Fplist_put (contact, QClocal, | 3589 | contact = Fplist_put (contact, QClocal, |
| 3583 | conv_sockaddr_to_lisp (psa1, len1)); | 3590 | conv_sockaddr_to_lisp (psa1, len1, true)); |
| 3584 | } | 3591 | } |
| 3585 | #endif | 3592 | #endif |
| 3586 | } | 3593 | } |
| @@ -4253,7 +4260,8 @@ network_interface_list (void) | |||
| 4253 | namebuf[sizeof (ifq->ifr_name)] = 0; | 4260 | namebuf[sizeof (ifq->ifr_name)] = 0; |
| 4254 | res = Fcons (Fcons (build_string (namebuf), | 4261 | res = Fcons (Fcons (build_string (namebuf), |
| 4255 | conv_sockaddr_to_lisp (&ifq->ifr_addr, | 4262 | conv_sockaddr_to_lisp (&ifq->ifr_addr, |
| 4256 | sizeof (struct sockaddr))), | 4263 | sizeof (struct sockaddr), |
| 4264 | true)), | ||
| 4257 | res); | 4265 | res); |
| 4258 | } | 4266 | } |
| 4259 | 4267 | ||
| @@ -4456,9 +4464,9 @@ network_interface_info (Lisp_Object ifname) | |||
| 4456 | { | 4464 | { |
| 4457 | any = 1; | 4465 | any = 1; |
| 4458 | #ifdef HAVE_STRUCT_IFREQ_IFR_NETMASK | 4466 | #ifdef HAVE_STRUCT_IFREQ_IFR_NETMASK |
| 4459 | elt = conv_sockaddr_to_lisp (&rq.ifr_netmask, sizeof (rq.ifr_netmask)); | 4467 | elt = conv_sockaddr_to_lisp (&rq.ifr_netmask, sizeof (rq.ifr_netmask), true); |
| 4460 | #else | 4468 | #else |
| 4461 | elt = conv_sockaddr_to_lisp (&rq.ifr_addr, sizeof (rq.ifr_addr)); | 4469 | elt = conv_sockaddr_to_lisp (&rq.ifr_addr, sizeof (rq.ifr_addr), true); |
| 4462 | #endif | 4470 | #endif |
| 4463 | } | 4471 | } |
| 4464 | #endif | 4472 | #endif |
| @@ -4469,7 +4477,7 @@ network_interface_info (Lisp_Object ifname) | |||
| 4469 | if (ioctl (s, SIOCGIFBRDADDR, &rq) == 0) | 4477 | if (ioctl (s, SIOCGIFBRDADDR, &rq) == 0) |
| 4470 | { | 4478 | { |
| 4471 | any = 1; | 4479 | any = 1; |
| 4472 | elt = conv_sockaddr_to_lisp (&rq.ifr_broadaddr, sizeof (rq.ifr_broadaddr)); | 4480 | elt = conv_sockaddr_to_lisp (&rq.ifr_broadaddr, sizeof (rq.ifr_broadaddr), true); |
| 4473 | } | 4481 | } |
| 4474 | #endif | 4482 | #endif |
| 4475 | res = Fcons (elt, res); | 4483 | res = Fcons (elt, res); |
| @@ -4479,7 +4487,7 @@ network_interface_info (Lisp_Object ifname) | |||
| 4479 | if (ioctl (s, SIOCGIFADDR, &rq) == 0) | 4487 | if (ioctl (s, SIOCGIFADDR, &rq) == 0) |
| 4480 | { | 4488 | { |
| 4481 | any = 1; | 4489 | any = 1; |
| 4482 | elt = conv_sockaddr_to_lisp (&rq.ifr_addr, sizeof (rq.ifr_addr)); | 4490 | elt = conv_sockaddr_to_lisp (&rq.ifr_addr, sizeof (rq.ifr_addr), true); |
| 4483 | } | 4491 | } |
| 4484 | #endif | 4492 | #endif |
| 4485 | res = Fcons (elt, res); | 4493 | res = Fcons (elt, res); |
| @@ -4527,6 +4535,67 @@ Data that is unavailable is returned as nil. */) | |||
| 4527 | #endif | 4535 | #endif |
| 4528 | } | 4536 | } |
| 4529 | 4537 | ||
| 4538 | DEFUN ("network-lookup-address-info", Fnetwork_lookup_address_info, | ||
| 4539 | Snetwork_lookup_address_info, 1, 2, 0, | ||
| 4540 | doc: /* Look up ip address info of NAME. | ||
| 4541 | Optional parameter FAMILY controls whether to look up IPv4 or IPv6 | ||
| 4542 | addresses. The default of nil means both, symbol `ipv4' means IPv4 | ||
| 4543 | only, symbol `ipv6' means IPv6 only. Returns a list of addresses, or | ||
| 4544 | nil if none were found. Each address is a vector of integers. */) | ||
| 4545 | (Lisp_Object name, Lisp_Object family) | ||
| 4546 | { | ||
| 4547 | Lisp_Object addresses = Qnil; | ||
| 4548 | struct addrinfo *res, *lres; | ||
| 4549 | int ret; | ||
| 4550 | |||
| 4551 | struct addrinfo hints; | ||
| 4552 | |||
| 4553 | if (STRING_MULTIBYTE (name)) | ||
| 4554 | error ("Non-ASCII hostname \"%s\" detected, please use puny-encode-string", | ||
| 4555 | SSDATA (name)); | ||
| 4556 | memset (&hints, 0, sizeof hints); | ||
| 4557 | if (EQ (family, Qnil)) | ||
| 4558 | hints.ai_family = AF_UNSPEC; | ||
| 4559 | if (EQ (family, Qipv4)) | ||
| 4560 | hints.ai_family = AF_INET; | ||
| 4561 | if (EQ (family, Qipv6)) | ||
| 4562 | #ifdef AF_INET6 | ||
| 4563 | hints.ai_family = AF_INET6; | ||
| 4564 | #else | ||
| 4565 | /* If we don't support IPv6, querying will never work anyway */ | ||
| 4566 | return addresses; | ||
| 4567 | #endif | ||
| 4568 | hints.ai_socktype = SOCK_DGRAM; | ||
| 4569 | |||
| 4570 | ret = getaddrinfo (SSDATA (name), NULL, &hints, &res); | ||
| 4571 | if (ret) | ||
| 4572 | #ifdef HAVE_GAI_STRERROR | ||
| 4573 | { | ||
| 4574 | synchronize_system_messages_locale (); | ||
| 4575 | char const *str = gai_strerror (ret); | ||
| 4576 | if (! NILP (Vlocale_coding_system)) | ||
| 4577 | str = SSDATA (code_convert_string_norecord | ||
| 4578 | (build_string (str), Vlocale_coding_system, 0)); | ||
| 4579 | message ("\"%s\" \"%s\"", SSDATA (name), str); | ||
| 4580 | } | ||
| 4581 | #else | ||
| 4582 | message ("%s network-lookup-address-info error %d", SSDATA (name), ret); | ||
| 4583 | #endif | ||
| 4584 | else | ||
| 4585 | { | ||
| 4586 | for (lres = res; lres; lres = lres->ai_next) | ||
| 4587 | { | ||
| 4588 | addresses = Fcons (conv_sockaddr_to_lisp | ||
| 4589 | (lres->ai_addr, lres->ai_addrlen, false), | ||
| 4590 | addresses); | ||
| 4591 | } | ||
| 4592 | addresses = Fnreverse (addresses); | ||
| 4593 | |||
| 4594 | freeaddrinfo (res); | ||
| 4595 | } | ||
| 4596 | return addresses; | ||
| 4597 | } | ||
| 4598 | |||
| 4530 | /* Turn off input and output for process PROC. */ | 4599 | /* Turn off input and output for process PROC. */ |
| 4531 | 4600 | ||
| 4532 | static void | 4601 | static void |
| @@ -4794,12 +4863,12 @@ server_accept_connection (Lisp_Object server, int channel) | |||
| 4794 | if (!NILP (service)) | 4863 | if (!NILP (service)) |
| 4795 | contact = Fplist_put (contact, QCservice, service); | 4864 | contact = Fplist_put (contact, QCservice, service); |
| 4796 | contact = Fplist_put (contact, QCremote, | 4865 | contact = Fplist_put (contact, QCremote, |
| 4797 | conv_sockaddr_to_lisp (&saddr.sa, len)); | 4866 | conv_sockaddr_to_lisp (&saddr.sa, len, true)); |
| 4798 | #ifdef HAVE_GETSOCKNAME | 4867 | #ifdef HAVE_GETSOCKNAME |
| 4799 | len = sizeof saddr; | 4868 | len = sizeof saddr; |
| 4800 | if (getsockname (s, &saddr.sa, &len) == 0) | 4869 | if (getsockname (s, &saddr.sa, &len) == 0) |
| 4801 | contact = Fplist_put (contact, QClocal, | 4870 | contact = Fplist_put (contact, QClocal, |
| 4802 | conv_sockaddr_to_lisp (&saddr.sa, len)); | 4871 | conv_sockaddr_to_lisp (&saddr.sa, len, true)); |
| 4803 | #endif | 4872 | #endif |
| 4804 | 4873 | ||
| 4805 | pset_childp (p, contact); | 4874 | pset_childp (p, contact); |
| @@ -8031,7 +8100,7 @@ init_process_emacs (int sockfd) | |||
| 8031 | union u_sockaddr sa; | 8100 | union u_sockaddr sa; |
| 8032 | socklen_t salen = sizeof sa; | 8101 | socklen_t salen = sizeof sa; |
| 8033 | if (getsockname (sockfd, &sa.sa, &salen) == 0) | 8102 | if (getsockname (sockfd, &sa.sa, &salen) == 0) |
| 8034 | sockname = conv_sockaddr_to_lisp (&sa.sa, salen); | 8103 | sockname = conv_sockaddr_to_lisp (&sa.sa, salen, true); |
| 8035 | } | 8104 | } |
| 8036 | # endif | 8105 | # endif |
| 8037 | Vinternal__daemon_sockname = sockname; | 8106 | Vinternal__daemon_sockname = sockname; |
| @@ -8269,6 +8338,7 @@ returns non-`nil'. */); | |||
| 8269 | defsubr (&Sset_network_process_option); | 8338 | defsubr (&Sset_network_process_option); |
| 8270 | defsubr (&Smake_network_process); | 8339 | defsubr (&Smake_network_process); |
| 8271 | defsubr (&Sformat_network_address); | 8340 | defsubr (&Sformat_network_address); |
| 8341 | defsubr (&Snetwork_lookup_address_info); | ||
| 8272 | defsubr (&Snetwork_interface_list); | 8342 | defsubr (&Snetwork_interface_list); |
| 8273 | defsubr (&Snetwork_interface_info); | 8343 | defsubr (&Snetwork_interface_info); |
| 8274 | #ifdef DATAGRAM_SOCKETS | 8344 | #ifdef DATAGRAM_SOCKETS |