@@ -903,18 +903,165 @@ char **make_augmented_environ(const char *const *vars)
903
903
return env ;
904
904
}
905
905
906
+ /*
907
+ * Note, this isn't a complete replacement for getaddrinfo. It assumes
908
+ * that service contains a numerical port, or that it it is null. It
909
+ * does a simple search using gethostbyname, and returns one IPv4 host
910
+ * if one was found.
911
+ */
912
+ static int WSAAPI getaddrinfo_stub (const char * node , const char * service ,
913
+ const struct addrinfo * hints ,
914
+ struct addrinfo * * res )
915
+ {
916
+ struct hostent * h = gethostbyname (node );
917
+ struct addrinfo * ai ;
918
+ struct sockaddr_in * sin ;
919
+
920
+ if (!h )
921
+ return WSAGetLastError ();
922
+
923
+ ai = xmalloc (sizeof (struct addrinfo ));
924
+ * res = ai ;
925
+ ai -> ai_flags = 0 ;
926
+ ai -> ai_family = AF_INET ;
927
+ ai -> ai_socktype = hints -> ai_socktype ;
928
+ switch (hints -> ai_socktype ) {
929
+ case SOCK_STREAM :
930
+ ai -> ai_protocol = IPPROTO_TCP ;
931
+ break ;
932
+ case SOCK_DGRAM :
933
+ ai -> ai_protocol = IPPROTO_UDP ;
934
+ break ;
935
+ default :
936
+ ai -> ai_protocol = 0 ;
937
+ break ;
938
+ }
939
+ ai -> ai_addrlen = sizeof (struct sockaddr_in );
940
+ ai -> ai_canonname = strdup (h -> h_name );
941
+
942
+ sin = xmalloc (ai -> ai_addrlen );
943
+ memset (sin , 0 , ai -> ai_addrlen );
944
+ sin -> sin_family = AF_INET ;
945
+ if (service )
946
+ sin -> sin_port = htons (atoi (service ));
947
+ sin -> sin_addr = * (struct in_addr * )h -> h_addr ;
948
+ ai -> ai_addr = (struct sockaddr * )sin ;
949
+ ai -> ai_next = 0 ;
950
+ return 0 ;
951
+ }
952
+
953
+ static void WSAAPI freeaddrinfo_stub (struct addrinfo * res )
954
+ {
955
+ free (res -> ai_canonname );
956
+ free (res -> ai_addr );
957
+ free (res );
958
+ }
959
+
960
+ static int WSAAPI getnameinfo_stub (const struct sockaddr * sa , socklen_t salen ,
961
+ char * host , DWORD hostlen ,
962
+ char * serv , DWORD servlen , int flags )
963
+ {
964
+ const struct sockaddr_in * sin = (const struct sockaddr_in * )sa ;
965
+ if (sa -> sa_family != AF_INET )
966
+ return EAI_FAMILY ;
967
+ if (!host && !serv )
968
+ return EAI_NONAME ;
969
+
970
+ if (host && hostlen > 0 ) {
971
+ struct hostent * ent = NULL ;
972
+ if (!(flags & NI_NUMERICHOST ))
973
+ ent = gethostbyaddr ((const char * )& sin -> sin_addr ,
974
+ sizeof (sin -> sin_addr ), AF_INET );
975
+
976
+ if (ent )
977
+ snprintf (host , hostlen , "%s" , ent -> h_name );
978
+ else if (flags & NI_NAMEREQD )
979
+ return EAI_NONAME ;
980
+ else
981
+ snprintf (host , hostlen , "%s" , inet_ntoa (sin -> sin_addr ));
982
+ }
983
+
984
+ if (serv && servlen > 0 ) {
985
+ struct servent * ent = NULL ;
986
+ if (!(flags & NI_NUMERICSERV ))
987
+ ent = getservbyport (sin -> sin_port ,
988
+ flags & NI_DGRAM ? "udp" : "tcp" );
989
+
990
+ if (ent )
991
+ snprintf (serv , servlen , "%s" , ent -> s_name );
992
+ else
993
+ snprintf (serv , servlen , "%d" , ntohs (sin -> sin_port ));
994
+ }
995
+
996
+ return 0 ;
997
+ }
998
+
999
+ static HMODULE ipv6_dll = NULL ;
1000
+ static void (WSAAPI * ipv6_freeaddrinfo )(struct addrinfo * res );
1001
+ static int (WSAAPI * ipv6_getaddrinfo )(const char * node , const char * service ,
1002
+ const struct addrinfo * hints ,
1003
+ struct addrinfo * * res );
1004
+ static int (WSAAPI * ipv6_getnameinfo )(const struct sockaddr * sa , socklen_t salen ,
1005
+ char * host , DWORD hostlen ,
1006
+ char * serv , DWORD servlen , int flags );
1007
+ /*
1008
+ * gai_strerror is an inline function in the ws2tcpip.h header, so we
1009
+ * don't need to try to load that one dynamically.
1010
+ */
1011
+
1012
+ static void socket_cleanup (void )
1013
+ {
1014
+ WSACleanup ();
1015
+ if (ipv6_dll )
1016
+ FreeLibrary (ipv6_dll );
1017
+ ipv6_dll = NULL ;
1018
+ ipv6_freeaddrinfo = freeaddrinfo_stub ;
1019
+ ipv6_getaddrinfo = getaddrinfo_stub ;
1020
+ ipv6_getnameinfo = getnameinfo_stub ;
1021
+ }
1022
+
906
1023
static void ensure_socket_initialization (void )
907
1024
{
908
1025
WSADATA wsa ;
909
1026
static int initialized = 0 ;
1027
+ const char * libraries [] = { "ws2_32.dll" , "wship6.dll" , NULL };
1028
+ const char * * name ;
910
1029
911
1030
if (initialized )
912
1031
return ;
913
1032
914
1033
if (WSAStartup (MAKEWORD (2 ,2 ), & wsa ))
915
1034
die ("unable to initialize winsock subsystem, error %d" ,
916
1035
WSAGetLastError ());
917
- atexit ((void (* )(void )) WSACleanup );
1036
+
1037
+ for (name = libraries ; * name ; name ++ ) {
1038
+ ipv6_dll = LoadLibrary (* name );
1039
+ if (!ipv6_dll )
1040
+ continue ;
1041
+
1042
+ ipv6_freeaddrinfo = (void (WSAAPI * )(struct addrinfo * ))
1043
+ GetProcAddress (ipv6_dll , "freeaddrinfo" );
1044
+ ipv6_getaddrinfo = (int (WSAAPI * )(const char * , const char * ,
1045
+ const struct addrinfo * ,
1046
+ struct addrinfo * * ))
1047
+ GetProcAddress (ipv6_dll , "getaddrinfo" );
1048
+ ipv6_getnameinfo = (int (WSAAPI * )(const struct sockaddr * ,
1049
+ socklen_t , char * , DWORD ,
1050
+ char * , DWORD , int ))
1051
+ GetProcAddress (ipv6_dll , "getnameinfo" );
1052
+ if (!ipv6_freeaddrinfo || !ipv6_getaddrinfo || !ipv6_getnameinfo ) {
1053
+ FreeLibrary (ipv6_dll );
1054
+ ipv6_dll = NULL ;
1055
+ } else
1056
+ break ;
1057
+ }
1058
+ if (!ipv6_freeaddrinfo || !ipv6_getaddrinfo || !ipv6_getnameinfo ) {
1059
+ ipv6_freeaddrinfo = freeaddrinfo_stub ;
1060
+ ipv6_getaddrinfo = getaddrinfo_stub ;
1061
+ ipv6_getnameinfo = getnameinfo_stub ;
1062
+ }
1063
+
1064
+ atexit (socket_cleanup );
918
1065
initialized = 1 ;
919
1066
}
920
1067
@@ -925,6 +1072,26 @@ struct hostent *mingw_gethostbyname(const char *host)
925
1072
return gethostbyname (host );
926
1073
}
927
1074
1075
+ void mingw_freeaddrinfo (struct addrinfo * res )
1076
+ {
1077
+ ipv6_freeaddrinfo (res );
1078
+ }
1079
+
1080
+ int mingw_getaddrinfo (const char * node , const char * service ,
1081
+ const struct addrinfo * hints , struct addrinfo * * res )
1082
+ {
1083
+ ensure_socket_initialization ();
1084
+ return ipv6_getaddrinfo (node , service , hints , res );
1085
+ }
1086
+
1087
+ int mingw_getnameinfo (const struct sockaddr * sa , socklen_t salen ,
1088
+ char * host , DWORD hostlen , char * serv , DWORD servlen ,
1089
+ int flags )
1090
+ {
1091
+ ensure_socket_initialization ();
1092
+ return ipv6_getnameinfo (sa , salen , host , hostlen , serv , servlen , flags );
1093
+ }
1094
+
928
1095
int mingw_socket (int domain , int type , int protocol )
929
1096
{
930
1097
int sockfd ;
0 commit comments