@@ -903,18 +903,165 @@ char **make_augmented_environ(const char *const *vars)
903903 return env ;
904904}
905905
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+
9061023static void ensure_socket_initialization (void )
9071024{
9081025 WSADATA wsa ;
9091026 static int initialized = 0 ;
1027+ const char * libraries [] = { "ws2_32.dll" , "wship6.dll" , NULL };
1028+ const char * * name ;
9101029
9111030 if (initialized )
9121031 return ;
9131032
9141033 if (WSAStartup (MAKEWORD (2 ,2 ), & wsa ))
9151034 die ("unable to initialize winsock subsystem, error %d" ,
9161035 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 );
9181065 initialized = 1 ;
9191066}
9201067
@@ -925,6 +1072,26 @@ struct hostent *mingw_gethostbyname(const char *host)
9251072 return gethostbyname (host );
9261073}
9271074
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+
9281095int mingw_socket (int domain , int type , int protocol )
9291096{
9301097 int sockfd ;
0 commit comments