/* wship6_import.c uses functions imported from getaddrinfo.c Because of getaddrinfo.c is GPL, So wship6_import.c is also GPL. Please rewrite these functions, to make this code to mingw licenced one. */ /***************************************************************************** * getaddrinfo.c: getaddrinfo/getnameinfo replacement functions ***************************************************************************** * Copyright (C) 2005 the VideoLAN team * Copyright (C) 2002-2004 Rémi Denis-Courmont * $Id: getaddrinfo.c 12850 2005-10-16 14:42:15Z courmisch $ * * Author: Rémi Denis-Courmont * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. *****************************************************************************/ #include #include #include #include #include #define WSH_NOTIFY_BIND 0x00000001 #define WSH_NOTIFY_LISTEN 0x00000002 #define WSH_NOTIFY_CONNECT 0x00000004 #define WSH_NOTIFY_ACCEPT 0x00000008 #define WSH_NOTIFY_SHUTDOWN_RECEIVE 0x00000010 #define WSH_NOTIFY_SHUTDOWN_SEND 0x00000020 #define WSH_NOTIFY_SHUTDOWN_ALL 0x00000040 #define WSH_NOTIFY_CLOSE 0x00000080 #define WSH_NOTIFY_CONNECT_ERROR 0x00000100 #define SOL_INTERNAL 0xFFFE #define SO_CONTEXT 1 typedef enum _SOCKADDR_ADDRESS_INFO { SockaddrAddressInfoNormal, SockaddrAddressInfoWildcard, SockaddrAddressInfoBroadcast, SockaddrAddressInfoLoopback } SOCKADDR_ADDRESS_INFO, *PSOCKADDR_ADDRESS_INFO; typedef enum _SOCKADDR_ENDPOINT_INFO { SockaddrEndpointInfoNormal, SockaddrEndpointInfoWildcard, SockaddrEndpointInfoReserved } SOCKADDR_ENDPOINT_INFO, *PSOCKADDR_ENDPOINT_INFO; typedef struct _SOCKADDR_INFO { SOCKADDR_ADDRESS_INFO AddressInfo; SOCKADDR_ENDPOINT_INFO EndpointInfo; } SOCKADDR_INFO, *PSOCKADDR_INFO; /* "Protocol" is a builtin class name in ObjC. */ typedef struct _WINSOCK_MAPPING { DWORD Rows; DWORD Columns; struct { DWORD AddressFamily; DWORD SocketType; DWORD Protocol; } Mapping[1]; } WINSOCK_MAPPING, *PWINSOCK_MAPPING; /*************************************************************** name: wship6 dll: wship6.dll ***************************************************************/ extern int load_wship6(void); extern void free_wship6(void); typedef INT (*type_WSHAddressToString)( IN LPSOCKADDR Address, IN INT AddressLength, IN LPWSAPROTOCOL_INFOW ProtocolInfo, OPTIONAL OUT LPWSTR AddressString, IN OUT LPDWORD AddressStringLength ); typedef INT (*type_WSHEnumProtocols)( IN LPINT lpiProtocols, OPTIONAL IN LPWSTR lpTransportKeyName, IN OUT LPVOID lpProtocolBuffer, IN OUT LPDWORD lpdwBufferLength ); typedef INT (*type_WSHGetProviderGuid)( IN LPWSTR ProviderName, OUT LPGUID ProviderGuid ); typedef INT (*type_WSHGetSockaddrType)( IN PSOCKADDR Sockaddr, IN DWORD SockaddrLength, OUT PSOCKADDR_INFO SockaddrInfo ); typedef INT (*type_WSHGetSocketInformation)( IN PVOID HelperDllSocketContext, IN SOCKET SocketHandle, IN HANDLE TdiAddressObjectHandle, IN HANDLE TdiConnectionObjectHandle, IN INT Level, IN INT OptionName, OUT PCHAR OptionValue, OUT INT OptionLength ); typedef INT (*type_WSHGetWSAProtocolInfo)( IN LPWSTR ProviderName, OUT LPWSAPROTOCOL_INFOW *ProtocolInfo, OUT LPDWORD ProtocolInfoEntries ); typedef INT (*type_WSHGetWildcardSockaddr)( IN PVOID HelperDllSocketContext, OUT PSOCKADDR Sockaddr, OUT PINT SockaddrLength ); typedef DWORD (*type_WSHGetWinsockMapping)( OUT PWINSOCK_MAPPING Mapping, IN DWORD MappingLength ); typedef INT (*type_WSHIoctl)( IN PVOID HelperDllSocketContext, IN SOCKET SocketHandle, IN HANDLE TdiAddressObjectHandle, IN HANDLE TdiConnectionObjectHandle, IN DWORD IoControlCode, IN LPVOID InputBuffer, IN DWORD InputBufferLength, IN LPVOID OutputBuffer, IN DWORD OutputBufferLength, OUT LPDWORD NumberOfBytesReturned, IN LPWSAOVERLAPPED Overlapped, IN LPWSAOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine, OUT LPBOOL NeedsCompletion ); typedef INT (*type_WSHJoinLeaf)( IN PVOID HelperDllSocketContext, IN SOCKET SocketHandle, IN HANDLE TdiAddressObjectHandle, IN HANDLE TdiConnectionObjectHandle, IN PVOID LeafHelperDllSocketContext, IN SOCKET LeafSocketHandle, IN PSOCKADDR Sockaddr, IN DWORD SockaddrLength, IN LPWSABUF CallerData, IN LPWSABUF CalleeData, IN LPQOS SocketQOS, IN LPQOS GroupQOS, IN DWORD Flags ); typedef INT (*type_WSHNotify)( IN PVOID HelperDllSocketContext, IN SOCKET SocketHandle, IN HANDLE TdiAddressObjectHandle, IN HANDLE TdiConnectionObjectHandle, IN DWORD NotifyEvent ); typedef INT (*type_WSHOpenSocket)( IN OUT PINT AddressFamily, IN OUT PINT SocketType, IN OUT PINT Protocol, OUT PUNICODE_STRING TransportDeviceName, OUT PVOID HelperDllSocketContext, OUT PDWORD NotificationEvents ); typedef INT (*type_WSHOpenSocket2)( IN OUT PINT AddressFamily, IN OUT PINT SocketType, IN OUT PINT Protocol, IN GROUP Group, IN DWORD Flags, OUT PUNICODE_STRING TransportDeviceName, OUT PVOID *HelperDllSocketContext, OUT PDWORD NotificationEvents ); typedef INT (*type_WSHSetSocketInformation)( IN PVOID HelperDllSocketContext, IN SOCKET SocketHandle, IN HANDLE TdiAddressObjectHandle, IN HANDLE TdiConnectionObjectHandle, IN INT Level, IN INT OptionName, IN PCHAR OptionValue, IN INT OptionLength ); typedef INT (*type_WSHStringToAddress)( IN LPWSTR AddressString, IN DWORD AddressFamily, IN LPWSAPROTOCOL_INFOW ProtocolInfo, OPTIONAL OUT LPSOCKADDR Address, IN OUT LPDWORD AddressStringLength ); typedef void(*type_freeaddrinfo)(struct addrinfo* ai); typedef int(*type_getaddrinfo)( const TCHAR* nodename, const TCHAR* servname, const struct addrinfo* hints, struct addrinfo** res); typedef int(*type_getnameinfo)( const struct sockaddr* sa, socklen_t salen, TCHAR* host, DWORD hostlen, TCHAR* serv, DWORD servlen, int flags); typedef char* (*type_gai_strerror)(int ecode); static struct wship6_ { type_WSHAddressToString WSHAddressToString; type_WSHEnumProtocols WSHEnumProtocols; type_WSHGetProviderGuid WSHGetProviderGuid; type_WSHGetSockaddrType WSHGetSockaddrType; type_WSHGetSocketInformation WSHGetSocketInformation; type_WSHGetWSAProtocolInfo WSHGetWSAProtocolInfo; type_WSHGetWildcardSockaddr WSHGetWildcardSockaddr; type_WSHGetWinsockMapping WSHGetWinsockMapping; type_WSHIoctl WSHIoctl; type_WSHJoinLeaf WSHJoinLeaf; type_WSHNotify WSHNotify; type_WSHOpenSocket WSHOpenSocket; type_WSHOpenSocket2 WSHOpenSocket2; type_WSHSetSocketInformation WSHSetSocketInformation; type_WSHStringToAddress WSHStringToAddress; type_freeaddrinfo freeaddrinfo; type_getaddrinfo getaddrinfo; type_getnameinfo getnameinfo; type_gai_strerror gai_strerror; } wship6; static volatile HANDLE h_wship6 = NULL; void free_wship6(void) { if(h_wship6){ FreeLibrary(h_wship6); h_wship6 = NULL; } } int load_wship6(void) { if(!h_wship6){ char buf[MAX_PATH]; GetSystemDirectory(buf,MAX_PATH); strcat(buf,"\\wship6.dll"); h_wship6 = LoadLibrary(buf); if(!h_wship6){ return -1; } } wship6.WSHAddressToString = (type_WSHAddressToString)GetProcAddress(h_wship6,"WSHAddressToString"); if(!wship6.WSHAddressToString){ free_wship6(); return -1; } wship6.WSHEnumProtocols = (type_WSHEnumProtocols)GetProcAddress(h_wship6,"WSHEnumProtocols"); if(!wship6.WSHEnumProtocols){ free_wship6(); return -1; } wship6.WSHGetProviderGuid = (type_WSHGetProviderGuid)GetProcAddress(h_wship6,"WSHGetProviderGuid"); if(!wship6.WSHGetProviderGuid){ free_wship6(); return -1; } wship6.WSHGetSockaddrType = (type_WSHGetSockaddrType)GetProcAddress(h_wship6,"WSHGetSockaddrType"); if(!wship6.WSHGetSockaddrType){ free_wship6(); return -1; } wship6.WSHGetSocketInformation = (type_WSHGetSocketInformation)GetProcAddress(h_wship6,"WSHGetSocketInformation"); if(!wship6.WSHGetSocketInformation){ free_wship6(); return -1; } wship6.WSHGetWSAProtocolInfo = (type_WSHGetWSAProtocolInfo)GetProcAddress(h_wship6,"WSHGetWSAProtocolInfo"); if(!wship6.WSHGetWSAProtocolInfo){ free_wship6(); return -1; } wship6.WSHGetWildcardSockaddr = (type_WSHGetWildcardSockaddr)GetProcAddress(h_wship6,"WSHGetWildcardSockaddr"); if(!wship6.WSHGetWildcardSockaddr){ free_wship6(); return -1; } wship6.WSHGetWinsockMapping = (type_WSHGetWinsockMapping)GetProcAddress(h_wship6,"WSHGetWinsockMapping"); if(!wship6.WSHGetWinsockMapping){ free_wship6(); return -1; } wship6.WSHIoctl = (type_WSHIoctl)GetProcAddress(h_wship6,"WSHIoctl"); if(!wship6.WSHIoctl){ free_wship6(); return -1; } wship6.WSHJoinLeaf = (type_WSHJoinLeaf)GetProcAddress(h_wship6,"WSHJoinLeaf"); if(!wship6.WSHJoinLeaf){ free_wship6(); return -1; } wship6.WSHNotify = (type_WSHNotify)GetProcAddress(h_wship6,"WSHNotify"); if(!wship6.WSHNotify){ free_wship6(); return -1; } wship6.WSHOpenSocket = (type_WSHOpenSocket)GetProcAddress(h_wship6,"WSHOpenSocket"); if(!wship6.WSHOpenSocket){ free_wship6(); return -1; } wship6.WSHOpenSocket2 = (type_WSHOpenSocket2)GetProcAddress(h_wship6,"WSHOpenSocket2"); if(!wship6.WSHOpenSocket2){ free_wship6(); return -1; } wship6.WSHSetSocketInformation = (type_WSHSetSocketInformation)GetProcAddress(h_wship6,"WSHSetSocketInformation"); if(!wship6.WSHSetSocketInformation){ free_wship6(); return -1; } wship6.WSHStringToAddress = (type_WSHStringToAddress)GetProcAddress(h_wship6,"WSHStringToAddress"); if(!wship6.WSHStringToAddress){ free_wship6(); return -1; } wship6.freeaddrinfo = (type_freeaddrinfo)GetProcAddress(h_wship6,"freeaddrinfo"); if(!wship6.freeaddrinfo){ free_wship6(); return -1; } wship6.getaddrinfo = (type_getaddrinfo)GetProcAddress(h_wship6,"getaddrinfo"); if(!wship6.getaddrinfo){ free_wship6(); return -1; } wship6.getnameinfo = (type_getnameinfo)GetProcAddress(h_wship6,"getnameinfo"); if(!wship6.getnameinfo){ free_wship6(); return -1; } wship6.gai_strerror = (type_gai_strerror)GetProcAddress(h_wship6,"gai_strerror"); if(!wship6.gai_strerror){ free_wship6(); return -1; } return 0; } INT WSHAddressToString( IN LPSOCKADDR Address, IN INT AddressLength, IN LPWSAPROTOCOL_INFOW ProtocolInfo, OPTIONAL OUT LPWSTR AddressString, IN OUT LPDWORD AddressStringLength ) { if(h_wship6){ return wship6.WSHAddressToString(Address,AddressLength,ProtocolInfo,AddressString,AddressStringLength); } return (INT )WSAEINVAL; } INT WSHEnumProtocols( IN LPINT lpiProtocols, OPTIONAL IN LPWSTR lpTransportKeyName, IN OUT LPVOID lpProtocolBuffer, IN OUT LPDWORD lpdwBufferLength ) { if(h_wship6){ return wship6.WSHEnumProtocols(lpiProtocols,lpTransportKeyName,lpProtocolBuffer,lpdwBufferLength); } WSASetLastError(WSAEINVAL); return (INT )SOCKET_ERROR; } INT WSHGetProviderGuid( IN LPWSTR ProviderName, OUT LPGUID ProviderGuid ) { if(h_wship6){ return wship6.WSHGetProviderGuid(ProviderName,ProviderGuid); } return (INT )WSAEINVAL; } INT WSHGetSockaddrType( IN PSOCKADDR Sockaddr, IN DWORD SockaddrLength, OUT PSOCKADDR_INFO SockaddrInfo ) { if(h_wship6){ return wship6.WSHGetSockaddrType(Sockaddr,SockaddrLength,SockaddrInfo); } return (INT )WSAEINVAL; } INT WSHGetSocketInformation( IN PVOID HelperDllSocketContext, IN SOCKET SocketHandle, IN HANDLE TdiAddressObjectHandle, IN HANDLE TdiConnectionObjectHandle, IN INT Level, IN INT OptionName, OUT PCHAR OptionValue, OUT INT OptionLength ) { if(h_wship6){ return wship6.WSHGetSocketInformation(HelperDllSocketContext,SocketHandle,TdiAddressObjectHandle,TdiConnectionObjectHandle,Level,OptionName,OptionValue,OptionLength); } return (INT )WSAEINVAL; } INT WSHGetWSAProtocolInfo( IN LPWSTR ProviderName, OUT LPWSAPROTOCOL_INFOW *ProtocolInfo, OUT LPDWORD ProtocolInfoEntries ) { if(h_wship6){ return wship6.WSHGetWSAProtocolInfo(ProviderName,ProtocolInfo,ProtocolInfoEntries); } return (INT )WSAEFAULT; } INT WSHGetWildcardSockaddr( IN PVOID HelperDllSocketContext, OUT PSOCKADDR Sockaddr, OUT PINT SockaddrLength ) { if(h_wship6){ return wship6.WSHGetWildcardSockaddr(HelperDllSocketContext,Sockaddr,SockaddrLength); } return (INT )WSAEINVAL; } DWORD WSHGetWinsockMapping( OUT PWINSOCK_MAPPING Mapping, IN DWORD MappingLength ) { if(h_wship6){ return wship6.WSHGetWinsockMapping(Mapping,MappingLength); } return (DWORD )0; } INT WSHIoctl( IN PVOID HelperDllSocketContext, IN SOCKET SocketHandle, IN HANDLE TdiAddressObjectHandle, IN HANDLE TdiConnectionObjectHandle, IN DWORD IoControlCode, IN LPVOID InputBuffer, IN DWORD InputBufferLength, IN LPVOID OutputBuffer, IN DWORD OutputBufferLength, OUT LPDWORD NumberOfBytesReturned, IN LPWSAOVERLAPPED Overlapped, IN LPWSAOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine, OUT LPBOOL NeedsCompletion ) { if(h_wship6){ return wship6.WSHIoctl(HelperDllSocketContext,SocketHandle,TdiAddressObjectHandle,TdiConnectionObjectHandle,IoControlCode,InputBuffer,InputBufferLength,OutputBuffer,OutputBufferLength,NumberOfBytesReturned,Overlapped,CompletionRoutine,NeedsCompletion); } return (INT )WSAEINVAL; } INT WSHJoinLeaf( IN PVOID HelperDllSocketContext, IN SOCKET SocketHandle, IN HANDLE TdiAddressObjectHandle, IN HANDLE TdiConnectionObjectHandle, IN PVOID LeafHelperDllSocketContext, IN SOCKET LeafSocketHandle, IN PSOCKADDR Sockaddr, IN DWORD SockaddrLength, IN LPWSABUF CallerData, IN LPWSABUF CalleeData, IN LPQOS SocketQOS, IN LPQOS GroupQOS, IN DWORD Flags ) { if(h_wship6){ return wship6.WSHJoinLeaf(HelperDllSocketContext,SocketHandle,TdiAddressObjectHandle,TdiConnectionObjectHandle,LeafHelperDllSocketContext,LeafSocketHandle,Sockaddr,SockaddrLength,CallerData,CalleeData,SocketQOS,GroupQOS,Flags); } return (INT )WSAEINVAL; } INT WSHNotify( IN PVOID HelperDllSocketContext, IN SOCKET SocketHandle, IN HANDLE TdiAddressObjectHandle, IN HANDLE TdiConnectionObjectHandle, IN DWORD NotifyEvent ) { if(h_wship6){ return wship6.WSHNotify(HelperDllSocketContext,SocketHandle,TdiAddressObjectHandle,TdiConnectionObjectHandle,NotifyEvent); } return (INT )WSAEINVAL; } INT WSHOpenSocket( IN OUT PINT AddressFamily, IN OUT PINT SocketType, IN OUT PINT Protocol, OUT PUNICODE_STRING TransportDeviceName, OUT PVOID HelperDllSocketContext, OUT PDWORD NotificationEvents ) { if(h_wship6){ return wship6.WSHOpenSocket(AddressFamily,SocketType,Protocol,TransportDeviceName,HelperDllSocketContext,NotificationEvents); } return (INT )WSAEINVAL; } INT WSHOpenSocket2( IN OUT PINT AddressFamily, IN OUT PINT SocketType, IN OUT PINT Protocol, IN GROUP Group, IN DWORD Flags, OUT PUNICODE_STRING TransportDeviceName, OUT PVOID *HelperDllSocketContext, OUT PDWORD NotificationEvents ) { if(h_wship6){ return wship6.WSHOpenSocket2(AddressFamily,SocketType,Protocol,Group,Flags,TransportDeviceName,HelperDllSocketContext,NotificationEvents); } return (INT )WSAEINVAL; } INT WSHSetSocketInformation( IN PVOID HelperDllSocketContext, IN SOCKET SocketHandle, IN HANDLE TdiAddressObjectHandle, IN HANDLE TdiConnectionObjectHandle, IN INT Level, IN INT OptionName, IN PCHAR OptionValue, IN INT OptionLength ) { if(h_wship6){ return wship6.WSHSetSocketInformation(HelperDllSocketContext,SocketHandle,TdiAddressObjectHandle,TdiConnectionObjectHandle,Level,OptionName,OptionValue,OptionLength); } return (INT )WSAEINVAL; } INT WSHStringToAddress( IN LPWSTR AddressString, IN DWORD AddressFamily, IN LPWSAPROTOCOL_INFOW ProtocolInfo, OPTIONAL OUT LPSOCKADDR Address, IN OUT LPDWORD AddressStringLength ) { if(h_wship6){ return wship6.WSHStringToAddress(AddressString,AddressFamily,ProtocolInfo,Address,AddressStringLength); } return (INT )WSAEINVAL; } static const char * __gai_strerror( int errnum ); static int __getnameinfo( const struct sockaddr *sa, socklen_t salen, char *host, int hostlen, char *serv, int servlen, int flags ); static void __freeaddrinfo (struct addrinfo *res); static int __getaddrinfo (const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res); void freeaddrinfo(struct addrinfo* ai) { if(h_wship6){ wship6.freeaddrinfo(ai); }else{ __freeaddrinfo(ai); } } int getaddrinfo( const TCHAR* nodename, const TCHAR* servname, const struct addrinfo* hints, struct addrinfo** res) { if(h_wship6){ return wship6.getaddrinfo(nodename,servname,hints,res); } return __getaddrinfo(nodename,servname,hints,res); } int getnameinfo( const struct sockaddr* sa, socklen_t salen, TCHAR* host, DWORD hostlen, TCHAR* serv, DWORD servlen, int flags) { if(h_wship6){ return wship6.getnameinfo(sa,salen,host,hostlen,serv,servlen,flags); } return __getnameinfo(sa,salen,host,hostlen,serv,servlen,flags); } char* gai_strerror(int ecode) { if(h_wship6){ return wship6.gai_strerror(ecode); } return (char*)__gai_strerror(ecode); } /***************************************************************/ /***************************************************************/ /* */ /* If wship6.dll is absent, emulate with IPv4 functions */ /* */ /* These codes are from Video Lan Clients getaddrinfo.c. */ /* Because of these coes wship6_import.c is GPL */ /* */ /***************************************************************/ #ifndef EAI_SYSTEM # define EAI_SYSTEM -1 /* value doesn't matter */ #endif static struct { int code; const char *msg; } const __gai_errlist[] = { { 0, "Error 0" }, { EAI_BADFLAGS, "Invalid flag used" }, { EAI_NONAME, "Host or service not found" }, { EAI_AGAIN, "Temporary name service failure" }, { EAI_FAIL, "Non-recoverable name service failure" }, { EAI_NODATA, "No data for host name" }, { EAI_FAMILY, "Unsupported address family" }, { EAI_SOCKTYPE, "Unsupported socket type" }, { EAI_SERVICE, "Incompatible service for socket type" }, // { EAI_ADDRFAMILY, "Unavailable address family for host name" }, // { EAI_MEMORY, "Memory allocation failure" }, { EAI_SYSTEM, "System error" }, { 0, NULL } }; static const char *__gai_unknownerr = "Unrecognized error number"; /**************************************************************************** * Converts an EAI_* error code into human readable english text. ****************************************************************************/ #define _NI_MASK (NI_NUMERICHOST|NI_NUMERICSERV|NI_NOFQDN|NI_NAMEREQD|\ NI_DGRAM) #define _AI_MASK (AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST) static int gai_error_from_WSAerror( int wsaerror ) { switch(wsaerror) { case WSAHOST_NOT_FOUND: return EAI_NONAME; case WSANO_DATA: return EAI_NODATA; case WSANO_RECOVERY: return EAI_FAIL; case WSATRY_AGAIN: return EAI_AGAIN; } return EAI_SYSTEM; } static const char * __gai_strerror( int errnum ) { int i; for (i = 0; __gai_errlist[i].msg != NULL; i++) if (errnum == __gai_errlist[i].code) return __gai_errlist[i].msg; return __gai_unknownerr; } static int __getnameinfo( const struct sockaddr *sa, socklen_t salen, char *host, int hostlen, char *serv, int servlen, int flags ) { if (((unsigned)salen < sizeof (struct sockaddr_in)) || (sa->sa_family != AF_INET)) return EAI_FAMILY; else if (flags & (~_NI_MASK)) return EAI_BADFLAGS; else { const struct sockaddr_in *addr; addr = (const struct sockaddr_in *)sa; if (host != NULL) { int solved = 0; /* host name resolution */ if (!(flags & NI_NUMERICHOST)) { struct hostent *hent; hent = gethostbyaddr ((const void*)&addr->sin_addr, 4, AF_INET); if (hent != NULL) { strncpy (host, hent->h_name, hostlen); host[hostlen - 1] = '\0'; /* * only keep first part of hostname * if user don't want fully qualified * domain name */ if (flags & NI_NOFQDN) { char *ptr; ptr = strchr (host, '.'); if (ptr != NULL) *ptr = 0; } solved = 1; } else if (flags & NI_NAMEREQD) return gai_error_from_WSAerror (WSAGetLastError()); } if (!solved) { /* inet_ntoa() can't fail */ strncpy (host, inet_ntoa (addr->sin_addr), hostlen); host[hostlen - 1] = '\0'; } } if (serv != NULL) { struct servent *sent = NULL; sent = NULL; if (sent == NULL) { snprintf (serv, servlen, "%u", (unsigned int)ntohs (addr->sin_port)); serv[servlen - 1] = '\0'; } } } return 0; } static void __freeaddrinfo (struct addrinfo *res) { if (res != NULL) { if (res->ai_canonname != NULL) free (res->ai_canonname); if (res->ai_addr != NULL) free (res->ai_addr); if (res->ai_next != NULL) free (res->ai_next); free (res); } } /* * Internal function that builds an addrinfo struct. */ static struct addrinfo * makeaddrinfo (int af, int type, int proto, const struct sockaddr *addr, size_t addrlen, const char *canonname) { struct addrinfo *res; res = (struct addrinfo *)malloc (sizeof (struct addrinfo)); if (res != NULL) { res->ai_flags = 0; res->ai_family = af; res->ai_socktype = type; res->ai_protocol = proto; res->ai_addrlen = addrlen; res->ai_addr = malloc (addrlen); res->ai_canonname = NULL; res->ai_next = NULL; if (res->ai_addr != NULL) { memcpy (res->ai_addr, addr, addrlen); if (canonname != NULL) { res->ai_canonname = strdup (canonname); if (res->ai_canonname != NULL) return res; /* success ! */ } else return res; } } /* failsafe */ __freeaddrinfo (res); return NULL; } static struct addrinfo * makeipv4info (int type, int proto, u_long ip, u_short port, const char *name) { struct sockaddr_in addr; memset (&addr, 0, sizeof (addr)); addr.sin_family = AF_INET; addr.sin_port = port; addr.sin_addr.s_addr = ip; return makeaddrinfo (AF_INET, type, proto, (struct sockaddr*)&addr, sizeof (addr), name); } /* * getaddrinfo() non-thread-safe IPv4-only implementation * Address-family-independant hostname to address resolution. * * This is meant for IPv6-unaware systems that do probably not provide * getaddrinfo(), but still have old function gethostbyname(). * * Only UDP and TCP over IPv4 are supported here. */ static int __getaddrinfo (const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res) { struct addrinfo *info; u_long ip; u_short port; int protocol = 0, flags = 0; const char *name = NULL; if (hints != NULL) { flags = hints->ai_flags; if (flags & ~_AI_MASK) return EAI_BADFLAGS; /* only accept AF_INET and AF_UNSPEC */ if (hints->ai_family && (hints->ai_family != AF_INET)) return EAI_FAMILY; /* protocol sanity check */ switch (hints->ai_socktype) { case SOCK_STREAM: protocol = IPPROTO_TCP; break; case SOCK_DGRAM: protocol = IPPROTO_UDP; break; case SOCK_RAW: case 0: break; default: return EAI_SOCKTYPE; } if (hints->ai_protocol && protocol && (protocol != hints->ai_protocol)) return EAI_SERVICE; } *res = NULL; /* default values */ if (node == NULL) { if (flags & AI_PASSIVE) ip = htonl (INADDR_ANY); else ip = htonl (INADDR_LOOPBACK); } else if ((ip = inet_addr (node)) == INADDR_NONE) { struct hostent *entry = NULL; /* hostname resolution */ if (!(flags & AI_NUMERICHOST)) entry = gethostbyname (node); if (entry == NULL) return EAI_NONAME; if ((entry->h_length != 4) || (entry->h_addrtype != AF_INET)) return EAI_FAMILY; ip = *((u_long *) entry->h_addr); if (flags & AI_CANONNAME) name = entry->h_name; } if ((flags & AI_CANONNAME) && (name == NULL)) name = node; /* service resolution */ if (service == NULL) port = 0; else { long d; char *end; d = strtoul (service, &end, 0); if (end[0] /* service is not a number */ || (d > 65535)) { struct servent *entry; const char *protoname; switch (protocol) { case IPPROTO_TCP: protoname = "tcp"; break; case IPPROTO_UDP: protoname = "udp"; break; default: protoname = NULL; } entry = getservbyname (service, protoname); if (entry == NULL) return EAI_SERVICE; port = entry->s_port; } else port = htons ((u_short)d); } /* building results... */ if ((!protocol) || (protocol == IPPROTO_UDP)) { info = makeipv4info (SOCK_DGRAM, IPPROTO_UDP, ip, port, name); if (info == NULL) { WSASetLastError(WSA_NOT_ENOUGH_MEMORY); return EAI_SYSTEM; } if (flags & AI_PASSIVE) info->ai_flags |= AI_PASSIVE; *res = info; } if ((!protocol) || (protocol == IPPROTO_TCP)) { info = makeipv4info (SOCK_STREAM, IPPROTO_TCP, ip, port, name); if (info == NULL) { WSASetLastError(WSA_NOT_ENOUGH_MEMORY); return EAI_SYSTEM; } info->ai_next = *res; if (flags & AI_PASSIVE) info->ai_flags |= AI_PASSIVE; *res = info; } return 0; }