emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] netsec e89c06e: Implement hostname->ip lookup function


From: Robert Pluim
Subject: [Emacs-diffs] netsec e89c06e: Implement hostname->ip lookup function
Date: Mon, 16 Jul 2018 13:45:54 -0400 (EDT)

branch: netsec
commit e89c06e8cea429620bc2cf4a98b9b741861b811a
Author: Robert Pluim <address@hidden>
Commit: Robert Pluim <address@hidden>

    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'
---
 etc/NEWS      |   3 ++
 src/process.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++++---------
 src/process.h |   2 +-
 src/w32.c     |  24 +++++++++-----
 4 files changed, 105 insertions(+), 24 deletions(-)

diff --git a/etc/NEWS b/etc/NEWS
index c69bbe9..28ce640 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -84,6 +84,9 @@ work right without some adjustment:
 
 * Changes in Emacs 27.1
 
+** New function 'network-lookup-address-info'.
+This does IPv4 and/or IPv6 address lookups on hostnames.
+
 ---
 ** New variable 'xft-ignore-color-fonts'.
 Default t means don't try to load color fonts when using Xft, as they
diff --git a/src/process.c b/src/process.c
index 3fccd96..2025398 100644
--- a/src/process.c
+++ b/src/process.c
@@ -2484,7 +2484,7 @@ usage:  (make-pipe-process &rest ARGS)  */)
    The address family of sa is not included in the result.  */
 
 Lisp_Object
-conv_sockaddr_to_lisp (struct sockaddr *sa, ptrdiff_t len)
+conv_sockaddr_to_lisp (struct sockaddr *sa, ptrdiff_t len, bool include_port)
 {
   Lisp_Object address;
   ptrdiff_t i;
@@ -2503,9 +2503,12 @@ conv_sockaddr_to_lisp (struct sockaddr *sa, ptrdiff_t 
len)
       {
        DECLARE_POINTER_ALIAS (sin, struct sockaddr_in, sa);
        len = sizeof (sin->sin_addr) + 1;
+        if (!include_port)
+          len--;
        address = Fmake_vector (make_number (len), Qnil);
        p = XVECTOR (address);
-       p->contents[--len] = make_number (ntohs (sin->sin_port));
+        if (include_port)
+          p->contents[--len] = make_number (ntohs (sin->sin_port));
        cp = (unsigned char *) &sin->sin_addr;
        break;
       }
@@ -2515,9 +2518,12 @@ conv_sockaddr_to_lisp (struct sockaddr *sa, ptrdiff_t 
len)
        DECLARE_POINTER_ALIAS (sin6, struct sockaddr_in6, sa);
        DECLARE_POINTER_ALIAS (ip6, uint16_t, &sin6->sin6_addr);
        len = sizeof (sin6->sin6_addr) / 2 + 1;
+        if (!include_port)
+          len--;
        address = Fmake_vector (make_number (len), Qnil);
        p = XVECTOR (address);
-       p->contents[--len] = make_number (ntohs (sin6->sin6_port));
+        if (include_port)
+          p->contents[--len] = make_number (ntohs (sin6->sin6_port));
        for (i = 0; i < len; i++)
          p->contents[i] = make_number (ntohs (ip6[i]));
        return address;
@@ -2568,7 +2574,7 @@ conv_addrinfo_to_lisp (struct addrinfo *res)
 {
   Lisp_Object protocol = make_number (res->ai_protocol);
   eassert (XINT (protocol) == res->ai_protocol);
-  return Fcons (protocol, conv_sockaddr_to_lisp (res->ai_addr, 
res->ai_addrlen));
+  return Fcons (protocol, conv_sockaddr_to_lisp (res->ai_addr, 
res->ai_addrlen, true));
 }
 
 
@@ -2710,7 +2716,8 @@ set up yet, this function will block until socket setup 
has completed.  */)
 
   channel = XPROCESS (process)->infd;
   return conv_sockaddr_to_lisp (datagram_address[channel].sa,
-                               datagram_address[channel].len);
+                               datagram_address[channel].len,
+                                true);
 }
 
 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,
 #endif
 
       contact = Fplist_put (contact, p->is_server? QClocal: QCremote,
-                           conv_sockaddr_to_lisp (sa, addrlen));
+                           conv_sockaddr_to_lisp (sa, addrlen, true));
 #ifdef HAVE_GETSOCKNAME
       if (!p->is_server)
        {
@@ -3580,7 +3587,7 @@ connect_network_socket (Lisp_Object proc, Lisp_Object 
addrinfos,
          DECLARE_POINTER_ALIAS (psa1, struct sockaddr, &sa1);
          if (getsockname (s, psa1, &len1) == 0)
            contact = Fplist_put (contact, QClocal,
-                                 conv_sockaddr_to_lisp (psa1, len1));
+                                 conv_sockaddr_to_lisp (psa1, len1, true));
        }
 #endif
     }
@@ -4253,7 +4260,8 @@ network_interface_list (void)
       namebuf[sizeof (ifq->ifr_name)] = 0;
       res = Fcons (Fcons (build_string (namebuf),
                          conv_sockaddr_to_lisp (&ifq->ifr_addr,
-                                                sizeof (struct sockaddr))),
+                                                sizeof (struct sockaddr),
+                                                 true)),
                   res);
     }
 
@@ -4456,9 +4464,9 @@ network_interface_info (Lisp_Object ifname)
     {
       any = 1;
 #ifdef HAVE_STRUCT_IFREQ_IFR_NETMASK
-      elt = conv_sockaddr_to_lisp (&rq.ifr_netmask, sizeof (rq.ifr_netmask));
+      elt = conv_sockaddr_to_lisp (&rq.ifr_netmask, sizeof (rq.ifr_netmask), 
true);
 #else
-      elt = conv_sockaddr_to_lisp (&rq.ifr_addr, sizeof (rq.ifr_addr));
+      elt = conv_sockaddr_to_lisp (&rq.ifr_addr, sizeof (rq.ifr_addr), true);
 #endif
     }
 #endif
@@ -4469,7 +4477,7 @@ network_interface_info (Lisp_Object ifname)
   if (ioctl (s, SIOCGIFBRDADDR, &rq) == 0)
     {
       any = 1;
-      elt = conv_sockaddr_to_lisp (&rq.ifr_broadaddr, sizeof 
(rq.ifr_broadaddr));
+      elt = conv_sockaddr_to_lisp (&rq.ifr_broadaddr, sizeof 
(rq.ifr_broadaddr), true);
     }
 #endif
   res = Fcons (elt, res);
@@ -4479,7 +4487,7 @@ network_interface_info (Lisp_Object ifname)
   if (ioctl (s, SIOCGIFADDR, &rq) == 0)
     {
       any = 1;
-      elt = conv_sockaddr_to_lisp (&rq.ifr_addr, sizeof (rq.ifr_addr));
+      elt = conv_sockaddr_to_lisp (&rq.ifr_addr, sizeof (rq.ifr_addr), true);
     }
 #endif
   res = Fcons (elt, res);
@@ -4527,6 +4535,67 @@ Data that is unavailable is returned as nil.  */)
 #endif
 }
 
+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;
+  struct addrinfo *res, *lres;
+  int ret;
+
+  struct addrinfo hints;
+
+  if (STRING_MULTIBYTE (name))
+    error ("Non-ASCII hostname \"%s\" detected, please use puny-encode-string",
+           SSDATA (name));
+  memset (&hints, 0, sizeof hints);
+  if (EQ (family, Qnil))
+    hints.ai_family = AF_UNSPEC;
+  if (EQ (family, Qipv4))
+    hints.ai_family = AF_INET;
+  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
+  hints.ai_socktype = SOCK_DGRAM;
+
+  ret = getaddrinfo (SSDATA (name), NULL, &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));
+      message ("\"%s\" \"%s\"", SSDATA (name), str);
+    }
+#else
+      message ("%s network-lookup-address-info error %d", SSDATA (name), ret);
+#endif
+  else
+    {
+      for (lres = res; lres; lres = lres->ai_next)
+        {
+          addresses = Fcons (conv_sockaddr_to_lisp
+                             (lres->ai_addr, lres->ai_addrlen, false),
+                             addresses);
+        }
+      addresses = Fnreverse (addresses);
+
+      freeaddrinfo (res);
+    }
+  return addresses;
+}
+
 /* Turn off input and output for process PROC.  */
 
 static void
@@ -4794,12 +4863,12 @@ server_accept_connection (Lisp_Object server, int 
channel)
   if (!NILP (service))
     contact = Fplist_put (contact, QCservice, service);
   contact = Fplist_put (contact, QCremote,
-                       conv_sockaddr_to_lisp (&saddr.sa, len));
+                       conv_sockaddr_to_lisp (&saddr.sa, len, true));
 #ifdef HAVE_GETSOCKNAME
   len = sizeof saddr;
   if (getsockname (s, &saddr.sa, &len) == 0)
     contact = Fplist_put (contact, QClocal,
-                         conv_sockaddr_to_lisp (&saddr.sa, len));
+                         conv_sockaddr_to_lisp (&saddr.sa, len, true));
 #endif
 
   pset_childp (p, contact);
@@ -8031,7 +8100,7 @@ init_process_emacs (int sockfd)
       union u_sockaddr sa;
       socklen_t salen = sizeof sa;
       if (getsockname (sockfd, &sa.sa, &salen) == 0)
-       sockname = conv_sockaddr_to_lisp (&sa.sa, salen);
+       sockname = conv_sockaddr_to_lisp (&sa.sa, salen, true);
     }
 # endif
   Vinternal__daemon_sockname = sockname;
@@ -8269,6 +8338,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
diff --git a/src/process.h b/src/process.h
index 6bc2214..504e5e6 100644
--- a/src/process.h
+++ b/src/process.h
@@ -278,7 +278,7 @@ extern Lisp_Object system_process_attributes (Lisp_Object);
 
 extern void record_deleted_pid (pid_t, Lisp_Object);
 struct sockaddr;
-extern Lisp_Object conv_sockaddr_to_lisp (struct sockaddr *, ptrdiff_t);
+extern Lisp_Object conv_sockaddr_to_lisp (struct sockaddr *, ptrdiff_t, bool);
 extern void hold_keyboard_input (void);
 extern void unhold_keyboard_input (void);
 extern bool kbd_on_hold_p (void);
diff --git a/src/w32.c b/src/w32.c
index c848b33..4759b08 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -9210,7 +9210,8 @@ network_interface_get_info (Lisp_Object ifname)
          if (NILP (ifname))
            res = Fcons (Fcons (build_string (namebuf),
                                conv_sockaddr_to_lisp ((struct sockaddr*) &sa,
-                                                      sizeof (struct 
sockaddr))),
+                                                      sizeof (struct sockaddr),
+                                                       false)),
                         res);
          else if (strcmp (namebuf, SSDATA (ifname)) == 0)
            {
@@ -9257,7 +9258,8 @@ network_interface_get_info (Lisp_Object ifname)
                  sa.sin_addr.s_addr = net_mask;
                  sa.sin_port = 0;
                  res = Fcons (conv_sockaddr_to_lisp ((struct sockaddr *) &sa,
-                                                     sizeof (struct sockaddr)),
+                                                     sizeof (struct sockaddr),
+                                                      false),
                               res);
                }
              else
@@ -9274,14 +9276,16 @@ network_interface_get_info (Lisp_Object ifname)
                  sa.sin_addr.s_addr = bcast_addr;
                  sa.sin_port = 0;
                  res = Fcons (conv_sockaddr_to_lisp ((struct sockaddr *) &sa,
-                                                     sizeof (struct sockaddr)),
+                                                     sizeof (struct sockaddr),
+                                                      false),
                               res);
 
                  /* IP address.  */
                  sa.sin_addr.s_addr = ip_addr;
                  sa.sin_port = 0;
                  res = Fcons (conv_sockaddr_to_lisp ((struct sockaddr *) &sa,
-                                                     sizeof (struct sockaddr)),
+                                                     sizeof (struct sockaddr),
+                                                      false),
                               res);
                }
              else
@@ -9299,7 +9303,8 @@ network_interface_get_info (Lisp_Object ifname)
              sa.sin_addr.s_addr = sys_inet_addr ("127.0.0.1");
              res = Fcons (Fcons (build_string ("lo"),
                                  conv_sockaddr_to_lisp ((struct sockaddr*) &sa,
-                                                        sizeof (struct 
sockaddr))),
+                                                        sizeof (struct 
sockaddr),
+                                                         false)),
                           res);
            }
          else if (strcmp (SSDATA (ifname), "lo") == 0)
@@ -9315,15 +9320,18 @@ network_interface_get_info (Lisp_Object ifname)
                           res);
              sa.sin_addr.s_addr = sys_inet_addr ("255.0.0.0");
              res = Fcons (conv_sockaddr_to_lisp ((struct sockaddr *) &sa,
-                                                 sizeof (struct sockaddr)),
+                                                 sizeof (struct sockaddr),
+                                                  false),
                           res);
              sa.sin_addr.s_addr = sys_inet_addr ("0.0.0.0");
              res = Fcons (conv_sockaddr_to_lisp ((struct sockaddr *) &sa,
-                                                 sizeof (struct sockaddr)),
+                                                 sizeof (struct sockaddr),
+                                                  false),
                           res);
              sa.sin_addr.s_addr = sys_inet_addr ("127.0.0.1");
              res = Fcons (conv_sockaddr_to_lisp ((struct sockaddr *) &sa,
-                                                 sizeof (struct sockaddr)),
+                                                 sizeof (struct sockaddr),
+                                                  false),
                           res);
            }
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]