| 1 |
1 |
/*
|
| 2 |
2 |
* LibSylph -- E-Mail client library
|
| 3 |
|
* Copyright (C) 1999-2009 Hiroyuki Yamamoto
|
|
3 |
* Copyright (C) 1999-2011 Hiroyuki Yamamoto
|
| 4 |
4 |
*
|
| 5 |
5 |
* This library is free software; you can redistribute it and/or
|
| 6 |
6 |
* modify it under the terms of the GNU Lesser General Public
|
| ... | ... | |
| 150 |
150 |
const gchar *hostname,
|
| 151 |
151 |
gushort port);
|
| 152 |
152 |
#else
|
|
153 |
#ifdef G_OS_WIN32
|
|
154 |
typedef int (*GetAddrInfoFunc) (const char *node,
|
|
155 |
const char *service,
|
|
156 |
const struct addrinfo *hints,
|
|
157 |
struct addrinfo **res);
|
|
158 |
typedef void (*FreeAddrInfoFunc) (struct addrinfo *res);
|
|
159 |
|
|
160 |
static GetAddrInfoFunc getaddrinfo_func = NULL;
|
|
161 |
static FreeAddrInfoFunc freeaddrinfo_func = NULL;
|
|
162 |
|
|
163 |
#undef getaddrinfo
|
|
164 |
#define getaddrinfo my_getaddrinfo
|
|
165 |
#undef freeaddrinfo
|
|
166 |
#define freeaddrinfo my_freeaddrinfo
|
|
167 |
#endif
|
|
168 |
|
| 153 |
169 |
static SockDesc sock_connect_by_getaddrinfo (const gchar *hostname,
|
| 154 |
170 |
gushort port);
|
| 155 |
171 |
#endif
|
| ... | ... | |
| 777 |
793 |
#endif
|
| 778 |
794 |
}
|
| 779 |
795 |
|
| 780 |
|
#ifndef INET6
|
|
796 |
#if !defined(INET6) || defined(G_OS_WIN32)
|
| 781 |
797 |
static gint my_inet_aton(const gchar *hostname, struct in_addr *inp)
|
| 782 |
798 |
{
|
| 783 |
799 |
#if HAVE_INET_ATON
|
| ... | ... | |
| 797 |
813 |
#endif
|
| 798 |
814 |
#endif /* HAVE_INET_ATON */
|
| 799 |
815 |
}
|
|
816 |
#endif /* !defined(INET6) || defined(G_OS_WIN32) */
|
| 800 |
817 |
|
|
818 |
#ifndef INET6
|
| 801 |
819 |
static gint sock_connect_by_hostname(gint sock, const gchar *hostname,
|
| 802 |
820 |
gushort port)
|
| 803 |
821 |
{
|
| ... | ... | |
| 833 |
851 |
#else /* INET6 */
|
| 834 |
852 |
|
| 835 |
853 |
#ifdef G_OS_WIN32
|
|
854 |
static gboolean win32_ipv6_supported(void)
|
|
855 |
{
|
|
856 |
static gboolean ipv6_checked = FALSE;
|
|
857 |
HMODULE hmodule;
|
|
858 |
|
|
859 |
if (ipv6_checked)
|
|
860 |
return getaddrinfo_func != NULL;
|
|
861 |
|
|
862 |
hmodule = GetModuleHandleA("ws2_32");
|
|
863 |
if (hmodule) {
|
|
864 |
getaddrinfo_func =
|
|
865 |
(GetAddrInfoFunc)GetProcAddress(hmodule, "getaddrinfo");
|
|
866 |
freeaddrinfo_func =
|
|
867 |
(FreeAddrInfoFunc)GetProcAddress(hmodule, "freeaddrinfo");
|
|
868 |
if (!getaddrinfo_func || !freeaddrinfo_func) {
|
|
869 |
getaddrinfo_func = NULL;
|
|
870 |
freeaddrinfo_func = NULL;
|
|
871 |
}
|
|
872 |
}
|
|
873 |
|
|
874 |
if (getaddrinfo_func)
|
|
875 |
debug_print("ws2_32 has IPv6 functions.\n");
|
|
876 |
else
|
|
877 |
debug_print("ws2_32 does not have IPv6 functions.\n");
|
|
878 |
|
|
879 |
ipv6_checked = TRUE;
|
|
880 |
return getaddrinfo_func != NULL;
|
|
881 |
}
|
|
882 |
|
|
883 |
/* subset of getaddrinfo() */
|
|
884 |
static int my_getaddrinfo(const char *node, const char *service,
|
|
885 |
const struct addrinfo *hintp,
|
|
886 |
struct addrinfo **res)
|
|
887 |
{
|
|
888 |
struct addrinfo *ai;
|
|
889 |
struct sockaddr_in addr, *paddr;
|
|
890 |
struct addrinfo hints;
|
|
891 |
gint port = 0;
|
|
892 |
|
|
893 |
if (win32_ipv6_supported())
|
|
894 |
return getaddrinfo_func(node, service, hintp, res);
|
|
895 |
|
|
896 |
if (!hintp) {
|
|
897 |
memset(&hints, 0, sizeof(hints));
|
|
898 |
hints.ai_family = AF_INET;
|
|
899 |
hints.ai_socktype = SOCK_STREAM;
|
|
900 |
} else
|
|
901 |
memcpy(&hints, hintp, sizeof(hints));
|
|
902 |
|
|
903 |
if (hints.ai_family != AF_UNSPEC && hints.ai_family != AF_INET)
|
|
904 |
return EAI_FAMILY;
|
|
905 |
if (hints.ai_socktype == 0)
|
|
906 |
hints.ai_socktype = SOCK_STREAM;
|
|
907 |
if (hints.ai_protocol == 0)
|
|
908 |
hints.ai_protocol = IPPROTO_TCP;
|
|
909 |
if (hints.ai_socktype != SOCK_STREAM)
|
|
910 |
return EAI_SOCKTYPE;
|
|
911 |
if (hints.ai_protocol != IPPROTO_TCP)
|
|
912 |
return EAI_SOCKTYPE;
|
|
913 |
#if 0
|
|
914 |
if (!node && !service)
|
|
915 |
return EAI_NONAME;
|
|
916 |
#endif
|
|
917 |
if (!node || !service)
|
|
918 |
return EAI_NONAME;
|
|
919 |
|
|
920 |
port = atoi(service);
|
|
921 |
|
|
922 |
memset(&addr, 0, sizeof(addr));
|
|
923 |
addr.sin_family = AF_INET;
|
|
924 |
addr.sin_port = htons(port);
|
|
925 |
|
|
926 |
if (!my_inet_aton(node, &addr.sin_addr)) {
|
|
927 |
struct hostent *hp;
|
|
928 |
|
|
929 |
if ((hp = my_gethostbyname(node)) == NULL) {
|
|
930 |
fprintf(stderr, "%s: unknown host.\n", node);
|
|
931 |
errno = 0;
|
|
932 |
return EAI_NONAME;
|
|
933 |
}
|
|
934 |
if (hp->h_length != 4 && hp->h_length != 8) {
|
|
935 |
fprintf(stderr, "illegal address length received for host %s\n", node);
|
|
936 |
errno = 0;
|
|
937 |
return EAI_FAIL;
|
|
938 |
}
|
|
939 |
|
|
940 |
memcpy(&addr.sin_addr, hp->h_addr, hp->h_length);
|
|
941 |
}
|
|
942 |
|
|
943 |
ai = g_malloc0(sizeof(struct addrinfo));
|
|
944 |
paddr = g_malloc0(sizeof(struct sockaddr_in));
|
|
945 |
memcpy(paddr, &addr, sizeof(struct sockaddr_in));
|
|
946 |
|
|
947 |
ai->ai_flags = 0;
|
|
948 |
ai->ai_family = AF_INET;
|
|
949 |
ai->ai_socktype = hints.ai_socktype;
|
|
950 |
ai->ai_protocol = hints.ai_protocol;
|
|
951 |
ai->ai_addrlen = sizeof(struct sockaddr_in);
|
|
952 |
ai->ai_addr = (struct sockaddr *)paddr;
|
|
953 |
ai->ai_canonname = NULL;
|
|
954 |
ai->ai_next = NULL;
|
|
955 |
|
|
956 |
*res = ai;
|
|
957 |
|
|
958 |
return 0;
|
|
959 |
}
|
|
960 |
|
|
961 |
static void my_freeaddrinfo(struct addrinfo *res)
|
|
962 |
{
|
|
963 |
if (win32_ipv6_supported()) {
|
|
964 |
freeaddrinfo_func(res);
|
|
965 |
return;
|
|
966 |
}
|
|
967 |
|
|
968 |
if (res) {
|
|
969 |
g_free(res->ai_addr);
|
|
970 |
g_free(res);
|
|
971 |
}
|
|
972 |
}
|
|
973 |
|
| 836 |
974 |
/* MinGW defines gai_strerror() in ws2tcpip.h, but it is not implemented. */
|
| 837 |
975 |
#undef gai_strerror
|
| 838 |
976 |
const gchar *gai_strerror(gint errcode)
|