aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2016-03-05 12:12:58 +0200
committerEli Zaretskii2016-03-05 12:12:58 +0200
commitbc96f6e827ba079006ae87914395942fc79f3f26 (patch)
treec980a478b0229057db165de1fec6a40fc56b1f0b /src
parentac9a931d595dd83ebac61c6c9cf7388985fee277 (diff)
downloademacs-bc96f6e827ba079006ae87914395942fc79f3f26.tar.gz
emacs-bc96f6e827ba079006ae87914395942fc79f3f26.zip
Implement getaddrinfo fallback for MS-Windows
See http://lists.gnu.org/archive/html/emacs-devel/2016-02/msg01602.html for more details. * nt/mingw-cfg.site (ac_cv_func_getaddrinfo) (ac_cv_func_gai_strerror): Set to "yes", as the configure script's test program is not smart enough to auto-detect these. * nt/inc/sys/socket.h (getaddrinfo, freeaddrinfo): Redirect to sys_getaddrinfo and sys_freeaddrinfo. Provide prototypes for sys_getaddrinfo and sys_freeaddrinfo. * src/w32.c (init_winsock): Try loading getaddrinfo and freeaddrinfo from ws2_32.dll. (sys_getaddrinfo, sys_freeaddrinfo): New functions. * lib-src/pop.c [WINDOWSNT]: Include winsock2.h, not winsock.h, and also ws2tcpip.h. (getaddrinfo, freeaddrinfo) [WINDOWSNT]: Redirect to sys_getaddrinfo and sys_freeaddrinfo, respectively. (load_ws2, sys_getaddrinfo, sys_freeaddrinfo) [WINDOWSNT]: New functions.
Diffstat (limited to 'src')
-rw-r--r--src/w32.c125
1 files changed, 125 insertions, 0 deletions
diff --git a/src/w32.c b/src/w32.c
index 998f696bdf8..ccf7cc335ce 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -7202,6 +7202,10 @@ int (PASCAL *pfn_recvfrom) (SOCKET s, char * buf, int len, int flags,
7202int (PASCAL *pfn_sendto) (SOCKET s, const char * buf, int len, int flags, 7202int (PASCAL *pfn_sendto) (SOCKET s, const char * buf, int len, int flags,
7203 const struct sockaddr * to, int tolen); 7203 const struct sockaddr * to, int tolen);
7204 7204
7205int (PASCAL *pfn_getaddrinfo) (const char *, const char *,
7206 const struct addrinfo *, struct addrinfo **);
7207void (PASCAL *pfn_freeaddrinfo) (struct addrinfo *);
7208
7205/* SetHandleInformation is only needed to make sockets non-inheritable. */ 7209/* SetHandleInformation is only needed to make sockets non-inheritable. */
7206BOOL (WINAPI *pfn_SetHandleInformation) (HANDLE object, DWORD mask, DWORD flags); 7210BOOL (WINAPI *pfn_SetHandleInformation) (HANDLE object, DWORD mask, DWORD flags);
7207#ifndef HANDLE_FLAG_INHERIT 7211#ifndef HANDLE_FLAG_INHERIT
@@ -7284,6 +7288,16 @@ init_winsock (int load_now)
7284 LOAD_PROC (sendto); 7288 LOAD_PROC (sendto);
7285#undef LOAD_PROC 7289#undef LOAD_PROC
7286 7290
7291 /* Try loading functions not available before XP. */
7292 pfn_getaddrinfo = (void *) GetProcAddress (winsock_lib, "getaddrinfo");
7293 pfn_freeaddrinfo = (void *) GetProcAddress (winsock_lib, "freeaddrinfo");
7294 /* Paranoia: these two functions should go together, so if one
7295 is absent, we cannot use the other. */
7296 if (pfn_getaddrinfo == NULL)
7297 pfn_freeaddrinfo = NULL;
7298 else if (pfn_freeaddrinfo == NULL)
7299 pfn_getaddrinfo = NULL;
7300
7287 /* specify version 1.1 of winsock */ 7301 /* specify version 1.1 of winsock */
7288 if (pfn_WSAStartup (0x101, &winsockData) == 0) 7302 if (pfn_WSAStartup (0x101, &winsockData) == 0)
7289 { 7303 {
@@ -7734,6 +7748,117 @@ sys_getpeername (int s, struct sockaddr *addr, int * namelen)
7734} 7748}
7735 7749
7736int 7750int
7751sys_getaddrinfo (const char *node, const char *service,
7752 const struct addrinfo *hints, struct addrinfo **res)
7753{
7754 int rc;
7755
7756 if (winsock_lib == NULL)
7757 {
7758 errno = ENETDOWN;
7759 return SOCKET_ERROR;
7760 }
7761
7762 check_errno ();
7763 if (pfn_getaddrinfo)
7764 rc = pfn_getaddrinfo (node, service, hints, res);
7765 else
7766 {
7767 int port = 0;
7768 struct hostent *host_info;
7769 struct gai_storage {
7770 struct addrinfo addrinfo;
7771 struct sockaddr_in sockaddr_in;
7772 } *gai_storage;
7773
7774 /* We don't (yet) support any flags, as Emacs doesn't need that. */
7775 if (hints && hints->ai_flags != 0)
7776 return WSAEINVAL;
7777 /* NODE cannot be NULL, since process.c has fallbacks for that. */
7778 if (!node)
7779 return WSAHOST_NOT_FOUND;
7780
7781 if (service)
7782 {
7783 const char *protocol =
7784 (hints && hints->ai_socktype == SOCK_DGRAM) ? "udp" : "tcp";
7785 struct servent *srv = sys_getservbyname (service, protocol);
7786
7787 if (srv)
7788 port = srv->s_port;
7789 else if (*service >= '0' && *service <= '9')
7790 {
7791 char *endp;
7792
7793 port = strtoul (service, &endp, 10);
7794 if (*endp || port > 65536)
7795 return WSAHOST_NOT_FOUND;
7796 port = sys_htons ((unsigned short) port);
7797 }
7798 else
7799 return WSAHOST_NOT_FOUND;
7800 }
7801
7802 gai_storage = xzalloc (sizeof *gai_storage);
7803 gai_storage->sockaddr_in.sin_port = port;
7804 host_info = sys_gethostbyname (node);
7805 if (host_info)
7806 {
7807 memcpy (&gai_storage->sockaddr_in.sin_addr,
7808 host_info->h_addr, host_info->h_length);
7809 gai_storage->sockaddr_in.sin_family = host_info->h_addrtype;
7810 }
7811 else
7812 {
7813 /* Attempt to interpret host as numeric inet address. */
7814 unsigned long numeric_addr = sys_inet_addr (node);
7815
7816 if (numeric_addr == -1)
7817 {
7818 free (gai_storage);
7819 return WSAHOST_NOT_FOUND;
7820 }
7821
7822 memcpy (&gai_storage->sockaddr_in.sin_addr, &numeric_addr,
7823 sizeof (gai_storage->sockaddr_in.sin_addr));
7824 gai_storage->sockaddr_in.sin_family = (hints) ? hints->ai_family : 0;
7825 }
7826
7827 gai_storage->addrinfo.ai_addr =
7828 (struct sockaddr *)&gai_storage->sockaddr_in;
7829 gai_storage->addrinfo.ai_addrlen = sizeof (gai_storage->sockaddr_in);
7830 gai_storage->addrinfo.ai_protocol = (hints) ? hints->ai_protocol : 0;
7831 gai_storage->addrinfo.ai_socktype = (hints) ? hints->ai_socktype : 0;
7832 gai_storage->addrinfo.ai_family = gai_storage->sockaddr_in.sin_family;
7833 gai_storage->addrinfo.ai_next = NULL;
7834
7835 *res = &gai_storage->addrinfo;
7836 rc = 0;
7837 }
7838
7839 return rc;
7840}
7841
7842void
7843sys_freeaddrinfo (struct addrinfo *ai)
7844{
7845 if (winsock_lib == NULL)
7846 {
7847 errno = ENETDOWN;
7848 return;
7849 }
7850
7851 check_errno ();
7852 if (pfn_freeaddrinfo)
7853 pfn_freeaddrinfo (ai);
7854 else
7855 {
7856 eassert (ai->ai_next == NULL);
7857 xfree (ai);
7858 }
7859}
7860
7861int
7737sys_shutdown (int s, int how) 7862sys_shutdown (int s, int how)
7738{ 7863{
7739 if (winsock_lib == NULL) 7864 if (winsock_lib == NULL)