From 5744130b55f252af054504217e73b280e66ac60f Mon Sep 17 00:00:00 2001 From: Ged Murphy Date: Wed, 16 Jul 2008 12:49:15 +0000 Subject: [PATCH] - Implement freeaddrinfo and getaddrinfo. - Implement bare boned getprotobyname and getprotobynumber. - Make winsock functions return proper error codes instead of success (will help to identify any probs with network apps) - patch by Yuri Sidorov For future reference, freeaddrinfo and getaddrinfo should really call GetAddrInfoW and FreeAddrInfoW which should do the work, but our umode network layers are a mess anyway and by no means XP compatible See issue #3523 for more details. svn path=/trunk/; revision=34545 --- reactos/dll/win32/ws2_32/misc/ns.c | 278 ++++++++++++++++++++++---- reactos/dll/win32/ws2_32/misc/stubs.c | 100 +++++---- 2 files changed, 292 insertions(+), 86 deletions(-) diff --git a/reactos/dll/win32/ws2_32/misc/ns.c b/reactos/dll/win32/ws2_32/misc/ns.c index c9b29ea736c..c7a1872f973 100644 --- a/reactos/dll/win32/ws2_32/misc/ns.c +++ b/reactos/dll/win32/ws2_32/misc/ns.c @@ -35,7 +35,8 @@ WSAAddressToStringA(IN LPSOCKADDR lpsaAddress, { UNIMPLEMENTED - return 0; + WSASetLastError(WSASYSCALLFAILURE); + return SOCKET_ERROR; } @@ -52,7 +53,8 @@ WSAAddressToStringW(IN LPSOCKADDR lpsaAddress, { UNIMPLEMENTED - return 0; + WSASetLastError(WSASYSCALLFAILURE); + return SOCKET_ERROR; } @@ -66,7 +68,8 @@ WSAEnumNameSpaceProvidersA(IN OUT LPDWORD lpdwBufferLength, { UNIMPLEMENTED - return 0; + WSASetLastError(WSASYSCALLFAILURE); + return SOCKET_ERROR; } @@ -80,7 +83,8 @@ WSAEnumNameSpaceProvidersW(IN OUT LPDWORD lpdwBufferLength, { UNIMPLEMENTED - return 0; + WSASetLastError(WSASYSCALLFAILURE); + return SOCKET_ERROR; } @@ -96,7 +100,8 @@ WSAGetServiceClassInfoA(IN LPGUID lpProviderId, { UNIMPLEMENTED - return 0; + WSASetLastError(WSASYSCALLFAILURE); + return SOCKET_ERROR; } @@ -112,7 +117,8 @@ WSAGetServiceClassInfoW(IN LPGUID lpProviderId, { UNIMPLEMENTED - return 0; + WSASetLastError(WSASYSCALLFAILURE); + return SOCKET_ERROR; } @@ -127,7 +133,8 @@ WSAGetServiceClassNameByClassIdA(IN LPGUID lpServiceClassId, { UNIMPLEMENTED - return 0; + WSASetLastError(WSASYSCALLFAILURE); + return SOCKET_ERROR; } @@ -142,7 +149,8 @@ WSAGetServiceClassNameByClassIdW(IN LPGUID lpServiceClassId, { UNIMPLEMENTED - return 0; + WSASetLastError(WSASYSCALLFAILURE); + return SOCKET_ERROR; } @@ -155,7 +163,8 @@ WSAInstallServiceClassA(IN LPWSASERVICECLASSINFOA lpServiceClassInfo) { UNIMPLEMENTED - return 0; + WSASetLastError(WSASYSCALLFAILURE); + return SOCKET_ERROR; } @@ -168,7 +177,8 @@ WSAInstallServiceClassW(IN LPWSASERVICECLASSINFOW lpServiceClassInfo) { UNIMPLEMENTED - return 0; + WSASetLastError(WSASYSCALLFAILURE); + return SOCKET_ERROR; } @@ -183,7 +193,8 @@ WSALookupServiceBeginA(IN LPWSAQUERYSETA lpqsRestrictions, { UNIMPLEMENTED - return 0; + WSASetLastError(WSASYSCALLFAILURE); + return SOCKET_ERROR; } @@ -198,7 +209,8 @@ WSALookupServiceBeginW(IN LPWSAQUERYSETW lpqsRestrictions, { UNIMPLEMENTED - return 0; + WSASetLastError(WSASYSCALLFAILURE); + return SOCKET_ERROR; } @@ -211,7 +223,8 @@ WSALookupServiceEnd(IN HANDLE hLookup) { UNIMPLEMENTED - return 0; + WSASetLastError(WSASYSCALLFAILURE); + return SOCKET_ERROR; } @@ -227,7 +240,8 @@ WSALookupServiceNextA(IN HANDLE hLookup, { UNIMPLEMENTED - return 0; + WSASetLastError(WSASYSCALLFAILURE); + return SOCKET_ERROR; } @@ -243,7 +257,8 @@ WSALookupServiceNextW(IN HANDLE hLookup, { UNIMPLEMENTED - return 0; + WSASetLastError(WSASYSCALLFAILURE); + return SOCKET_ERROR; } @@ -256,7 +271,8 @@ WSARemoveServiceClass(IN LPGUID lpServiceClassId) { UNIMPLEMENTED - return 0; + WSASetLastError(WSASYSCALLFAILURE); + return SOCKET_ERROR; } @@ -271,7 +287,8 @@ WSASetServiceA(IN LPWSAQUERYSETA lpqsRegInfo, { UNIMPLEMENTED - return 0; + WSASetLastError(WSASYSCALLFAILURE); + return SOCKET_ERROR; } @@ -286,7 +303,8 @@ WSASetServiceW(IN LPWSAQUERYSETW lpqsRegInfo, { UNIMPLEMENTED - return 0; + WSASetLastError(WSASYSCALLFAILURE); + return SOCKET_ERROR; } @@ -798,25 +816,27 @@ gethostname(OUT CHAR FAR* name, * * @unimplemented */ + +static CHAR *no_aliases = 0; +static PROTOENT protocols[] = +{ + {"icmp",&no_aliases, IPPROTO_ICMP}, + {"tcp", &no_aliases, IPPROTO_TCP}, + {"udp", &no_aliases, IPPROTO_UDP}, + {NULL, NULL, 0} +}; + LPPROTOENT EXPORT getprotobyname(IN CONST CHAR FAR* name) { - static CHAR *udp_aliases = 0; - static PROTOENT udp = { "udp", &udp_aliases, 17 }; - static CHAR *tcp_aliases = 0; - static PROTOENT tcp = { "tcp", &tcp_aliases, 6 }; - - if(!_stricmp(name, "udp")) + UINT i; + for (i = 0; protocols[i].p_name; i++) { - return &udp; + if (_stricmp(protocols[i].p_name, name) == 0) + return &protocols[i]; } - else if (!_stricmp( name, "tcp")) - { - return &tcp; - } - - return 0; + return NULL; } /* @@ -826,9 +846,13 @@ LPPROTOENT EXPORT getprotobynumber(IN INT number) { - UNIMPLEMENTED - - return (LPPROTOENT)NULL; + UINT i; + for (i = 0; protocols[i].p_name; i++) + { + if (protocols[i].p_proto == number) + return &protocols[i]; + } + return NULL; } #define SKIPWS(ptr,act) \ @@ -1324,5 +1348,189 @@ inet_ntoa(IN IN_ADDR in) } -/* EOF */ +/* + * @implemented + */ +VOID +EXPORT +freeaddrinfo(struct addrinfo *pAddrInfo) +{ + struct addrinfo *next, *cur; + cur = pAddrInfo; + while (cur) + { + next = cur->ai_next; + if (cur->ai_addr) + HeapFree(GetProcessHeap(), 0, cur->ai_addr); + if (cur->ai_canonname) + HeapFree(GetProcessHeap(), 0, cur->ai_canonname); + HeapFree(GetProcessHeap(), 0, cur); + cur = next; + } +} + +struct addrinfo * +new_addrinfo(struct addrinfo *prev) +{ + struct addrinfo *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct addrinfo)); + if (prev) + prev->ai_next = ret; + return ret; +} + +/* + * @implemented + */ +INT +EXPORT +getaddrinfo(const char FAR * nodename, + const char FAR * servname, + const struct addrinfo FAR * hints, + struct addrinfo FAR * FAR * res) +{ + struct addrinfo *ret = NULL, *ai; + ULONG addr; + USHORT port; + struct servent *se; + char *proto; + LPPROTOENT pent; + DNS_STATUS dns_status; + PDNS_RECORD dp, currdns; + struct sockaddr_in *sin; + + if (res == NULL) + return WSAEINVAL; + if (nodename == NULL && servname == NULL) + return WSAHOST_NOT_FOUND; + + if (!WSAINITIALIZED) + return WSANOTINITIALISED; + + /* converting port number */ + port = strtoul(servname, NULL, 10); + /* service name was specified? */ + if (port == 0) + { + /* protocol was specified? */ + if (hints && hints->ai_protocol) + { + pent = getprotobynumber(hints->ai_protocol); + if (pent == NULL) + return WSAEINVAL; + proto = pent->p_name; + } + else + proto = NULL; + se = getservbyname(servname, proto); + if (se == NULL) + return WSAHOST_NOT_FOUND; + port = se->s_port; + } + + if (nodename) + { + /* Is it an IPv6 address? */ + if (strstr(nodename, ":")) + return WSAHOST_NOT_FOUND; + + /* Is it an IPv4 address? */ + addr = inet_addr(nodename); + if (addr != INADDR_NONE) + { + ai = new_addrinfo(NULL); + ai->ai_family = PF_INET; + ai->ai_addrlen = sizeof(struct sockaddr_in); + ai->ai_addr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ai->ai_addrlen); + sin = (struct sockaddr_in *)ai->ai_addr; + sin->sin_family = AF_INET; + sin->sin_port = port; + RtlCopyMemory(&sin->sin_addr, &addr, sizeof(sin->sin_addr)); + if (hints) + { + if (ai->ai_socktype == 0) + ai->ai_socktype = hints->ai_socktype; + if (ai->ai_protocol == 0) + ai->ai_protocol = hints->ai_protocol; + } + ret = ai; + } + else + { + /* resolving host name */ + dns_status = DnsQuery_A(nodename, + DNS_TYPE_A, + DNS_QUERY_STANDARD, + 0, + /* extra dns servers */ &dp, + 0); + + if (dns_status == 0) + { + ai = NULL; + for (currdns = dp; currdns; currdns = currdns->pNext ) + { + /* accept only A records */ + if (currdns->wType != DNS_TYPE_A) continue; + + ai = new_addrinfo(ai); + if (ret == NULL) + ret = ai; + ai->ai_family = PF_INET; + ai->ai_addrlen = sizeof(struct sockaddr_in); + ai->ai_addr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ai->ai_addrlen); + sin = (struct sockaddr_in *)ret->ai_addr; + sin->sin_family = AF_INET; + sin->sin_port = port; + RtlCopyMemory(&sin->sin_addr, &currdns->Data.A.IpAddress, sizeof(sin->sin_addr)); + if (hints) + { + if (ai->ai_socktype == 0) + ai->ai_socktype = hints->ai_socktype; + if (ai->ai_protocol == 0) + ai->ai_protocol = hints->ai_protocol; + } + } + DnsRecordListFree(dp, DnsFreeRecordList); + } + } + } + else + { + ai = new_addrinfo(NULL); + ai->ai_family = PF_INET; + ai->ai_addrlen = sizeof(struct sockaddr_in); + ai->ai_addr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ai->ai_addrlen); + sin = (struct sockaddr_in *)ret->ai_addr; + sin->sin_family = AF_INET; + sin->sin_port = port; + if (hints) + { + if (!(hints->ai_flags & AI_PASSIVE)) + { + sin->sin_addr.S_un.S_un_b.s_b1 = 127; + sin->sin_addr.S_un.S_un_b.s_b2 = 0; + sin->sin_addr.S_un.S_un_b.s_b3 = 0; + sin->sin_addr.S_un.S_un_b.s_b4 = 1; + } + if (ai->ai_socktype == 0) + ai->ai_socktype = hints->ai_socktype; + if (ai->ai_protocol == 0) + ai->ai_protocol = hints->ai_protocol; + } + } + + if (ret == NULL) + return WSAHOST_NOT_FOUND; + + if (hints && hints->ai_family != PF_UNSPEC && hints->ai_family != PF_INET) + { + freeaddrinfo(ret); + return WSAEAFNOSUPPORT; + } + + *res = ret; + return 0; +} + +/* EOF */ diff --git a/reactos/dll/win32/ws2_32/misc/stubs.c b/reactos/dll/win32/ws2_32/misc/stubs.c index cbfa1f842be..9418b53a4b1 100644 --- a/reactos/dll/win32/ws2_32/misc/stubs.c +++ b/reactos/dll/win32/ws2_32/misc/stubs.c @@ -307,7 +307,8 @@ WSACancelBlockingCall(VOID) UNIMPLEMENTED - return 0; + WSASetLastError(WSASYSCALLFAILURE); + return SOCKET_ERROR; } @@ -340,7 +341,8 @@ WSADuplicateSocketA(IN SOCKET s, UNIMPLEMENTED - return 0; + WSASetLastError(WSASYSCALLFAILURE); + return SOCKET_ERROR; } @@ -396,7 +398,8 @@ WSAEnumProtocolsA(IN LPINT lpiProtocols, { UNIMPLEMENTED - return 0; + WSASetLastError(WSASYSCALLFAILURE); + return SOCKET_ERROR; } @@ -411,7 +414,8 @@ WSAEnumProtocolsW(IN LPINT lpiProtocols, { UNIMPLEMENTED - return 0; + WSASetLastError(WSASYSCALLFAILURE); + return SOCKET_ERROR; } @@ -470,6 +474,7 @@ WSAGetQOSByName(IN SOCKET s, { UNIMPLEMENTED + WSASetLastError(WSASYSCALLFAILURE); return FALSE; } @@ -485,7 +490,8 @@ WSAHtonl(IN SOCKET s, { UNIMPLEMENTED - return 0; + WSASetLastError(WSASYSCALLFAILURE); + return SOCKET_ERROR; } @@ -500,7 +506,8 @@ WSAHtons(IN SOCKET s, { UNIMPLEMENTED - return 0; + WSASetLastError(WSASYSCALLFAILURE); + return SOCKET_ERROR; } @@ -533,6 +540,7 @@ WSAJoinLeaf(IN SOCKET s, { UNIMPLEMENTED + WSASetLastError(WSASYSCALLFAILURE); return INVALID_SOCKET; } @@ -548,7 +556,8 @@ WSANtohl(IN SOCKET s, { UNIMPLEMENTED - return 0; + WSASetLastError(WSASYSCALLFAILURE); + return SOCKET_ERROR; } @@ -563,7 +572,8 @@ WSANtohs(IN SOCKET s, { UNIMPLEMENTED - return 0; + WSASetLastError(WSASYSCALLFAILURE); + return SOCKET_ERROR; } @@ -604,7 +614,8 @@ WSAProviderConfigChange(IN OUT LPHANDLE lpNotificationHandle, { UNIMPLEMENTED - return 0; + WSASetLastError(WSASYSCALLFAILURE); + return SOCKET_ERROR; } @@ -617,7 +628,8 @@ WSACancelAsyncRequest(IN HANDLE hAsyncTaskHandle) { UNIMPLEMENTED - return 0; + WSASetLastError(WSASYSCALLFAILURE); + return SOCKET_ERROR; } /* WinSock Service Provider support functions */ @@ -635,7 +647,8 @@ WPUCompleteOverlappedRequest(IN SOCKET s, { UNIMPLEMENTED - return 0; + WSASetLastError(WSASYSCALLFAILURE); + return SOCKET_ERROR; } @@ -652,7 +665,7 @@ WSPStartup(IN WORD wVersionRequested, { UNIMPLEMENTED - return 0; + return WSASYSCALLFAILURE; } @@ -666,7 +679,8 @@ WSCDeinstallProvider(IN LPGUID lpProviderId, { UNIMPLEMENTED - return 0; + WSASetLastError(WSASYSCALLFAILURE); + return SOCKET_ERROR; } @@ -682,7 +696,8 @@ WSCEnumProtocols(IN LPINT lpiProtocols, { UNIMPLEMENTED - return 0; + WSASetLastError(WSASYSCALLFAILURE); + return SOCKET_ERROR; } @@ -698,7 +713,8 @@ WSCGetProviderPath(IN LPGUID lpProviderId, { UNIMPLEMENTED - return 0; + WSASetLastError(WSASYSCALLFAILURE); + return SOCKET_ERROR; } @@ -715,7 +731,8 @@ WSCInstallProvider(IN CONST LPGUID lpProviderId, { UNIMPLEMENTED - return 0; + WSASetLastError(WSASYSCALLFAILURE); + return SOCKET_ERROR; } @@ -729,7 +746,8 @@ WSCEnableNSProvider(IN LPGUID lpProviderId, { UNIMPLEMENTED - return 0; + WSASetLastError(WSASYSCALLFAILURE); + return SOCKET_ERROR; } @@ -746,7 +764,8 @@ WSCInstallNameSpace(IN LPWSTR lpszIdentifier, { UNIMPLEMENTED - return 0; + WSASetLastError(WSASYSCALLFAILURE); + return SOCKET_ERROR; } @@ -759,7 +778,8 @@ WSCUnInstallNameSpace(IN LPGUID lpProviderId) { UNIMPLEMENTED - return 0; + WSASetLastError(WSASYSCALLFAILURE); + return SOCKET_ERROR; } @@ -773,7 +793,7 @@ WSCWriteProviderOrder(IN LPDWORD lpwdCatalogEntryId, { UNIMPLEMENTED - return 0; + return WSASYSCALLFAILURE; } /* @@ -790,9 +810,10 @@ WSANSPIoctl(HANDLE hLookup, LPDWORD lpcbBytesReturned, LPWSACOMPLETION lpCompletion) { - //UNIMPLEMENTED + UNIMPLEMENTED - return 0; + WSASetLastError(WSASYSCALLFAILURE); + return SOCKET_ERROR; } @@ -809,7 +830,8 @@ WSCUpdateProvider(LPGUID lpProviderId, { UNIMPLEMENTED - return 0; + WSASetLastError(WSASYSCALLFAILURE); + return SOCKET_ERROR; } /* @@ -822,32 +844,7 @@ WSCWriteNameSpaceOrder(LPGUID lpProviderId, { UNIMPLEMENTED - return 0; -} - -/* - * @unimplemented - */ -VOID -EXPORT -freeaddrinfo(struct addrinfo *pAddrInfo) -{ - UNIMPLEMENTED -} - -/* - * @unimplemented - */ -INT -EXPORT -getaddrinfo(const char FAR * nodename, - const char FAR * servname, - const struct addrinfo FAR * hints, - struct addrinfo FAR * FAR * res) -{ - UNIMPLEMENTED - - return EAI_NONAME; + return WSASYSCALLFAILURE; } /* @@ -865,7 +862,8 @@ getnameinfo(const struct sockaddr FAR * sa, { UNIMPLEMENTED - return 0; + WSASetLastError(WSASYSCALLFAILURE); + return SOCKET_ERROR; } /* @@ -883,7 +881,7 @@ BOOL EXPORT WSApSetPostRoutine(PVOID Routine) { UNIMPLEMENTED - return 0; + return FALSE; } /* EOF */