diff options
| author | Eli Zaretskii | 2016-03-05 12:12:58 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2016-03-05 12:12:58 +0200 |
| commit | bc96f6e827ba079006ae87914395942fc79f3f26 (patch) | |
| tree | c980a478b0229057db165de1fec6a40fc56b1f0b /src | |
| parent | ac9a931d595dd83ebac61c6c9cf7388985fee277 (diff) | |
| download | emacs-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.c | 125 |
1 files changed, 125 insertions, 0 deletions
| @@ -7202,6 +7202,10 @@ int (PASCAL *pfn_recvfrom) (SOCKET s, char * buf, int len, int flags, | |||
| 7202 | int (PASCAL *pfn_sendto) (SOCKET s, const char * buf, int len, int flags, | 7202 | int (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 | ||
| 7205 | int (PASCAL *pfn_getaddrinfo) (const char *, const char *, | ||
| 7206 | const struct addrinfo *, struct addrinfo **); | ||
| 7207 | void (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. */ |
| 7206 | BOOL (WINAPI *pfn_SetHandleInformation) (HANDLE object, DWORD mask, DWORD flags); | 7210 | BOOL (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 | ||
| 7736 | int | 7750 | int |
| 7751 | sys_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 | |||
| 7842 | void | ||
| 7843 | sys_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 | |||
| 7861 | int | ||
| 7737 | sys_shutdown (int s, int how) | 7862 | sys_shutdown (int s, int how) |
| 7738 | { | 7863 | { |
| 7739 | if (winsock_lib == NULL) | 7864 | if (winsock_lib == NULL) |