Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenaddrinfo.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS WinSock 2 API 00004 * FILE: addrinfo.c 00005 * PURPOSE: Protocol-Independent Address Resolution 00006 * PROGRAMMER: Alex Ionescu (alex@relsoft.net) 00007 */ 00008 00009 /* INCLUDES ******************************************************************/ 00010 #include "ws2_32.h" 00011 00012 //#define NDEBUG 00013 #include <debug.h> 00014 00015 /* DEFINES *******************************************************************/ 00016 00017 #define Swap(a, b, c) { (c) = (a); (a) = (b); (b) = (c); } 00018 #define FreeAddrInfoW(a) freeaddrinfo((LPADDRINFO)a) 00019 00020 /* FUNCTIONS *****************************************************************/ 00021 00022 /* FIXME: put into dnslib */ 00023 VOID 00024 WSAAPI 00025 Dns_Ip4AddressToReverseName_W(IN LPWSTR AddressBuffer, 00026 IN IN_ADDR Address) 00027 { 00028 /* Convert the address into IPv4 format */ 00029 wsprintfW(AddressBuffer, L"%u.%u.%u.%u.in-addr.arpa.", 00030 Address.S_un.S_un_b.s_b4, 00031 Address.S_un.S_un_b.s_b3, 00032 Address.S_un.S_un_b.s_b2, 00033 Address.S_un.S_un_b.s_b1); 00034 } 00035 00036 VOID 00037 WINAPI 00038 Dns_SplitHostFromDomainNameW(IN LPWSTR DomainName) 00039 { 00040 /* FIXME */ 00041 } 00042 00043 static 00044 INT 00045 WINAPI 00046 ConvertAddrinfoFromUnicodeToAnsi(IN PADDRINFOW Addrinfo) 00047 { 00048 LPSTR AnsiName; 00049 LPWSTR *UnicodeName; 00050 00051 /* Make sure we have a valid pointer */ 00052 if (Addrinfo) 00053 { 00054 do 00055 { 00056 /* Get the name */ 00057 UnicodeName = &Addrinfo->ai_canonname; 00058 00059 /* Check if it exists */ 00060 if (*UnicodeName) 00061 { 00062 /* Convert it */ 00063 AnsiName = AnsiDupFromUnicode(*UnicodeName); 00064 if (AnsiName) 00065 { 00066 /* Free the old one */ 00067 HeapFree(WsSockHeap, 0, *UnicodeName); 00068 00069 /* Set the new one */ 00070 *UnicodeName = (LPWSTR)AnsiName; 00071 } 00072 else 00073 { 00074 return GetLastError(); 00075 } 00076 } 00077 } while ((Addrinfo = Addrinfo->ai_next)); 00078 } 00079 00080 /* All done */ 00081 return ERROR_SUCCESS; 00082 } 00083 00084 static 00085 BOOL 00086 WINAPI 00087 ParseV4Address(IN PCWSTR AddressString, 00088 OUT PDWORD pAddress) 00089 { 00090 DWORD Address; 00091 LPWSTR Ip = 0; 00092 00093 /* Do the conversion, don't accept wildcard */ 00094 RtlIpv4StringToAddressW((LPWSTR)AddressString, 0, &Ip, (IN_ADDR *)&Address); 00095 00096 /* Return the address and success */ 00097 *pAddress = Address; 00098 return FALSE; 00099 } 00100 00101 static 00102 PADDRINFOW 00103 WINAPI 00104 NewAddrInfo(IN INT SocketType, 00105 IN INT Protocol, 00106 IN WORD Port, 00107 IN DWORD Address) 00108 { 00109 PADDRINFOW AddrInfo; 00110 PSOCKADDR_IN SockAddress; 00111 00112 /* Allocate a structure */ 00113 AddrInfo = HeapAlloc(WsSockHeap, 0, sizeof(ADDRINFOW)); 00114 if (!AddrInfo) return NULL; 00115 00116 /* Allocate a sockaddr */ 00117 SockAddress = HeapAlloc(WsSockHeap, 0, sizeof(SOCKADDR_IN)); 00118 if (!SockAddress) 00119 { 00120 /* Free the addrinfo and fail */ 00121 HeapFree(WsSockHeap, 0, AddrInfo); 00122 return NULL; 00123 } 00124 00125 /* Write data for socket address */ 00126 SockAddress->sin_family = AF_INET; 00127 SockAddress->sin_port = Port; 00128 SockAddress->sin_addr.s_addr = Address; 00129 00130 /* Fill out the addrinfo */ 00131 AddrInfo->ai_family = PF_INET; 00132 AddrInfo->ai_socktype = SocketType; 00133 AddrInfo->ai_protocol = Protocol; 00134 AddrInfo->ai_flags = 0; 00135 AddrInfo->ai_next = 0; 00136 AddrInfo->ai_canonname = NULL; 00137 AddrInfo->ai_addrlen = sizeof(SOCKADDR_IN); 00138 AddrInfo->ai_addr = (PSOCKADDR)SockAddress; 00139 00140 /* Return it */ 00141 return AddrInfo; 00142 } 00143 00144 static 00145 INT 00146 WINAPI 00147 CloneAddrInfo(IN WORD Port, 00148 IN PADDRINFOW ptResult) 00149 { 00150 PADDRINFOW Next = NULL; 00151 PADDRINFOW New = NULL; 00152 00153 /* Loop the chain */ 00154 for (Next = ptResult; Next;) 00155 { 00156 /* Create a new structure */ 00157 New = NewAddrInfo(SOCK_DGRAM, 00158 Next->ai_protocol, 00159 Port, 00160 ((PSOCKADDR_IN)Next->ai_addr)->sin_addr.s_addr); 00161 if (!New) break; 00162 00163 /* Link them */ 00164 New->ai_next = Next->ai_next; 00165 Next->ai_next = New; 00166 Next = New->ai_next; 00167 } 00168 00169 /* Check if we ran out of memory */ 00170 if (Next) return EAI_MEMORY; 00171 00172 /* Return success */ 00173 return 0; 00174 } 00175 00176 static 00177 INT 00178 WINAPI 00179 QueryDNS(IN LPCSTR NodeName, 00180 IN INT SocketType, 00181 IN INT Protocol, 00182 IN WORD Port, 00183 OUT CHAR Alias[NI_MAXHOST], 00184 OUT PADDRINFOW *pptResult) 00185 { 00186 PADDRINFOW *Next = pptResult; 00187 PHOSTENT Hostent = NULL; 00188 PCHAR *Addresses; 00189 00190 /* Assume nothing found */ 00191 *Next = NULL; 00192 Alias[0] = '\0'; 00193 00194 /* Get the hostent */ 00195 Hostent = gethostbyname(NodeName); 00196 if (Hostent) 00197 { 00198 /* Check for valid addresses */ 00199 if ((Hostent->h_addrtype == AF_INET) && 00200 (Hostent->h_length == sizeof(IN_ADDR))) 00201 { 00202 /* Loop every address in it */ 00203 for (Addresses = Hostent->h_addr_list; *Addresses; Addresses++) 00204 { 00205 /* Create an addrinfo structure for it*/ 00206 *Next = NewAddrInfo(SocketType, 00207 Protocol, 00208 Port, 00209 ((PIN_ADDR)*Addresses)->s_addr); 00210 if (!*Next) return EAI_MEMORY; 00211 00212 /* Move to the next entry */ 00213 Next = &((*Next)->ai_next); 00214 } 00215 } 00216 00217 /* Copy the canonical name */ 00218 strcpy(Alias, Hostent->h_name); 00219 00220 /* Return success */ 00221 return 0; 00222 } 00223 00224 /* Find out what the error was */ 00225 switch (GetLastError()) 00226 { 00227 /* Convert the Winsock Error to an EAI error */ 00228 case WSAHOST_NOT_FOUND: return EAI_NONAME; 00229 case WSATRY_AGAIN: return EAI_AGAIN; 00230 case WSANO_RECOVERY: return EAI_FAIL; 00231 case WSANO_DATA: return EAI_NODATA; 00232 default: return EAI_NONAME; 00233 } 00234 } 00235 00236 static 00237 INT 00238 WINAPI 00239 LookupNodeByAddr(IN LPWSTR pNodeBuffer, 00240 IN DWORD NodeBufferSize, 00241 IN BOOLEAN OnlyNodeName, 00242 IN PVOID Addr, 00243 IN DWORD AddrSize, 00244 IN INT AddressFamily) 00245 { 00246 GUID LookupGuid = SVCID_DNS_TYPE_PTR; 00247 PIN_ADDR Ip4Addr = Addr; 00248 WCHAR ReverseBuffer[76]; 00249 WSAQUERYSETW Restrictions, Reply; 00250 DWORD BufferLength; 00251 INT ErrorCode; 00252 HANDLE LookupHandle; 00253 00254 /* Validate the address */ 00255 if (!Addr) return WSAEFAULT; 00256 00257 /* Make sure the family and address size match */ 00258 if (AddressFamily == AF_INET6) 00259 { 00260 /* Check the address size for this type */ 00261 if (AddrSize != sizeof(IN6_ADDR)) return WSAEFAULT; 00262 Ip4Addr = (PIN_ADDR)&((PIN6_ADDR)Addr)->u.Byte[12]; 00263 } 00264 else if (AddressFamily == AF_INET) 00265 { 00266 /* Check the address size for this type */ 00267 if (AddrSize != sizeof(IN_ADDR)) return WSAEFAULT; 00268 } 00269 else 00270 { 00271 /* Address family not supported */ 00272 return WSAEAFNOSUPPORT; 00273 } 00274 00275 /* Check if this is a mapped V4 IPv6 or pure IPv4 */ 00276 if (((AddressFamily == AF_INET6) && (IN6_IS_ADDR_V4MAPPED(Addr))) || 00277 (AddressFamily == AF_INET)) 00278 { 00279 /* Get the reverse name */ 00280 Dns_Ip4AddressToReverseName_W(ReverseBuffer, *Ip4Addr); 00281 } 00282 /* FIXME: Not implemented for now 00283 else if ( */ 00284 00285 /* By this point we have the Reverse Name, so prepare for lookup */ 00286 RtlZeroMemory(&Restrictions, sizeof(Restrictions)); 00287 Restrictions.dwSize = sizeof(Restrictions); 00288 Restrictions.lpszServiceInstanceName = ReverseBuffer; 00289 Restrictions.lpServiceClassId = &LookupGuid; 00290 Restrictions.dwNameSpace = NS_DNS; 00291 00292 /* Now do the lookup */ 00293 ErrorCode = WSALookupServiceBeginW(&Restrictions, 00294 LUP_RETURN_NAME, 00295 &LookupHandle); 00296 if (ErrorCode == ERROR_SUCCESS) 00297 { 00298 /* Lookup succesfull, now get the data */ 00299 BufferLength = (NI_MAXHOST - 1) * sizeof(WCHAR) + sizeof(Restrictions); 00300 ErrorCode = WSALookupServiceNextW(LookupHandle, 00301 0, 00302 &BufferLength, 00303 &Restrictions); 00304 if (ErrorCode == ERROR_SUCCESS) 00305 { 00306 /* Now check if we have a name back */ 00307 Reply = Restrictions; 00308 if (!Reply.lpszServiceInstanceName) 00309 { 00310 /* Fail */ 00311 ErrorCode = WSAHOST_NOT_FOUND; 00312 } 00313 else 00314 { 00315 /* Check if the caller only wants the node name */ 00316 if (OnlyNodeName) 00317 { 00318 /* Split it and get only the partial host name */ 00319 Dns_SplitHostFromDomainNameW(Reply.lpszServiceInstanceName); 00320 } 00321 00322 /* Check the length and see if it's within our limit */ 00323 if (wcslen(Reply.lpszServiceInstanceName) + 1 > 00324 NodeBufferSize) 00325 { 00326 /* It's not, so fail */ 00327 ErrorCode = WSAEFAULT; 00328 } 00329 else 00330 { 00331 /* It will fit, let's copy it*/ 00332 wcscpy(pNodeBuffer, Reply.lpszServiceInstanceName); 00333 } 00334 } 00335 } 00336 } 00337 else if (ErrorCode == WSASERVICE_NOT_FOUND) 00338 { 00339 /* Normalize the error code */ 00340 ErrorCode = WSAHOST_NOT_FOUND; 00341 } 00342 00343 /* Finish the lookup if one was in progress */ 00344 if (LookupHandle) WSALookupServiceEnd(LookupHandle); 00345 00346 /* Return the error code */ 00347 return ErrorCode; 00348 } 00349 00350 static 00351 INT 00352 WINAPI 00353 GetServiceNameForPort(IN LPWSTR pServiceBuffer, 00354 IN DWORD ServiceBufferSize, 00355 IN WORD Port, 00356 IN DWORD Flags) 00357 { 00358 return ERROR_SUCCESS; 00359 } 00360 00361 static 00362 INT 00363 WINAPI 00364 LookupAddressForName(IN LPCSTR NodeName, 00365 IN INT SocketType, 00366 IN INT Protocol, 00367 IN WORD Port, 00368 IN BOOL bAI_CANONNAME, 00369 OUT PADDRINFOW *pptResult) 00370 { 00371 INT iError = 0; 00372 INT AliasCount = 0; 00373 CHAR szFQDN1[NI_MAXHOST] = ""; 00374 CHAR szFQDN2[NI_MAXHOST] = ""; 00375 PCHAR Name = szFQDN1; 00376 PCHAR Alias = szFQDN2; 00377 PCHAR Scratch = NULL; 00378 00379 /* Make a copy of the name */ 00380 strcpy(Name, NodeName); 00381 00382 /* Loop */ 00383 while (TRUE) 00384 { 00385 /* Do a DNS Query for the name */ 00386 iError = QueryDNS(NodeName, 00387 SocketType, 00388 Protocol, 00389 Port, 00390 Alias, 00391 pptResult); 00392 if (iError) break; 00393 00394 /* Exit if we have a result */ 00395 if (*pptResult) break; 00396 00397 /* Don't loop continously if this is a DNS misconfiguration */ 00398 if ((!strlen(Alias)) || (!strcmp(Name, Alias)) || (++AliasCount == 16)) 00399 { 00400 /* Exit the loop with a failure */ 00401 iError = EAI_FAIL; 00402 break; 00403 } 00404 00405 /* Restart loopup if we got a CNAME */ 00406 Swap(Name, Alias, Scratch); 00407 } 00408 00409 /* Check if we suceeded and the canonical name is requested */ 00410 if (!iError && bAI_CANONNAME) 00411 { 00412 /* Allocate memory for a copy */ 00413 (*pptResult)->ai_canonname = HeapAlloc(WsSockHeap, 0, 512); 00414 00415 /* Check if we had enough memory */ 00416 if (!(*pptResult)->ai_canonname) 00417 { 00418 /* Set failure code */ 00419 iError = EAI_MEMORY; 00420 } 00421 else 00422 { 00423 /* Convert the alias to UNICODE */ 00424 MultiByteToWideChar(CP_ACP, 00425 0, 00426 Alias, 00427 -1, 00428 (*pptResult)->ai_canonname, 00429 256); 00430 } 00431 } 00432 00433 /* Return to caller */ 00434 return iError; 00435 } 00436 00437 /* 00438 * @implemented 00439 */ 00440 INT 00441 WSAAPI 00442 GetAddrInfoW(IN PCWSTR pszNodeName, 00443 IN PCWSTR pszServiceName, 00444 IN const ADDRINFOW *ptHints, 00445 OUT PADDRINFOW *pptResult) 00446 { 00447 INT iError = 0; 00448 INT iFlags = 0; 00449 INT iFamily = PF_UNSPEC; 00450 INT iSocketType = 0; 00451 INT iProtocol = 0; 00452 WORD wPort = 0; 00453 DWORD dwAddress = 0; 00454 PSERVENT ptService = NULL; 00455 PCHAR pc = NULL; 00456 BOOL bClone = FALSE; 00457 WORD wTcpPort = 0; 00458 WORD wUdpPort = 0; 00459 WCHAR CanonicalName[0x42]; 00460 CHAR AnsiServiceName[256]; 00461 CHAR AnsiNodeName[256]; 00462 DPRINT("GetAddrInfoW: %S, %S, %p, %p\n", pszNodeName, pszServiceName, ptHints, pptResult); 00463 00464 /* Assume error */ 00465 *pptResult = NULL; 00466 00467 /* We must have at least one name to work with */ 00468 if (!(pszNodeName) && !(pszServiceName)) 00469 { 00470 /* Fail */ 00471 SetLastError(EAI_NONAME); 00472 return EAI_NONAME; 00473 } 00474 00475 /* Check if we got hints */ 00476 if (ptHints) 00477 { 00478 /* Make sure these are empty */ 00479 if ((ptHints->ai_addrlen) || 00480 (ptHints->ai_canonname) || 00481 (ptHints->ai_addr) || 00482 (ptHints->ai_next)) 00483 { 00484 /* Fail if they aren't */ 00485 SetLastError(EAI_FAIL); 00486 return EAI_FAIL; 00487 } 00488 00489 /* Save the flags and validate them */ 00490 iFlags = ptHints->ai_flags; 00491 if ((iFlags & AI_CANONNAME) && !pszNodeName) 00492 { 00493 return EAI_BADFLAGS; 00494 } 00495 00496 /* Save family and validate it */ 00497 iFamily = ptHints->ai_family; 00498 if ((iFamily != PF_UNSPEC) && (iFamily != PF_INET)) 00499 { 00500 return EAI_FAMILY; 00501 } 00502 00503 /* Save socket type and validate it */ 00504 iSocketType = ptHints->ai_socktype; 00505 if ((iSocketType != 0) && 00506 (iSocketType != SOCK_STREAM) && 00507 (iSocketType != SOCK_DGRAM) && 00508 (iSocketType != SOCK_RAW)) 00509 { 00510 return EAI_SOCKTYPE; 00511 } 00512 00513 /* Save the protocol */ 00514 iProtocol = ptHints->ai_protocol; 00515 } 00516 00517 /* Check if we have a service name */ 00518 if (pszServiceName) 00519 { 00520 /* We need to convert it to ANSI */ 00521 WideCharToMultiByte(CP_ACP, 00522 0, 00523 pszServiceName, 00524 -1, 00525 AnsiServiceName, 00526 256, 00527 NULL, 00528 0); 00529 00530 /* Get the port */ 00531 wPort = (WORD)strtoul(AnsiServiceName, &pc, 10); 00532 00533 /* Check if the port string is numeric */ 00534 if (*pc == '\0') 00535 { 00536 /* Get the port directly */ 00537 wPort = wTcpPort = wUdpPort = htons(wPort); 00538 00539 /* Check if this is both TCP and UDP */ 00540 if (iSocketType == 0) 00541 { 00542 /* Set it to TCP for now, but remember to clone */ 00543 bClone = TRUE; 00544 iSocketType = SOCK_STREAM; 00545 } 00546 } 00547 else 00548 { 00549 /* The port name was a string. Check if this is a UDP socket */ 00550 if ((iSocketType == 0) || (iSocketType == SOCK_DGRAM)) 00551 { 00552 /* It's UDP, do a getservbyname */ 00553 ptService = getservbyname(AnsiServiceName, "udp"); 00554 00555 /* If we got a servent, return the port from it */ 00556 if (ptService) wPort = wUdpPort = ptService->s_port; 00557 } 00558 00559 /* Check if this is a TCP socket */ 00560 if ((iSocketType == 0) || (iSocketType == SOCK_STREAM)) 00561 { 00562 /* It's TCP, do a getserbyname */ 00563 ptService = getservbyname(AnsiServiceName, "tcp"); 00564 00565 /* Return the port from the servent */ 00566 if (ptService) wPort = wTcpPort = ptService->s_port; 00567 } 00568 00569 /* If we got 0, then fail */ 00570 if (wPort == 0) 00571 { 00572 return iSocketType ? EAI_SERVICE : EAI_NONAME; 00573 } 00574 00575 /* Check if this was for both */ 00576 if (iSocketType == 0) 00577 { 00578 /* Do the TCP case right now */ 00579 iSocketType = (wTcpPort) ? SOCK_STREAM : SOCK_DGRAM; 00580 bClone = (wTcpPort && wUdpPort); 00581 } 00582 } 00583 } 00584 00585 /* Check if no node was given or if this is is a valid IPv4 address */ 00586 if ((!pszNodeName) || (ParseV4Address(pszNodeName, &dwAddress))) 00587 { 00588 /* Check if we don't have a node name */ 00589 if (!pszNodeName) 00590 { 00591 /* Make one up based on the flags */ 00592 dwAddress = htonl((iFlags & AI_PASSIVE) ? 00593 INADDR_ANY : INADDR_LOOPBACK); 00594 } 00595 00596 /* Create the Addr Info */ 00597 *pptResult = NewAddrInfo(iSocketType, iProtocol, wPort, dwAddress); 00598 00599 /* If we didn't get one back, assume out of memory */ 00600 if (!(*pptResult)) iError = EAI_MEMORY; 00601 00602 /* Check if we have success and a nodename */ 00603 if (!iError && pszNodeName) 00604 { 00605 /* Set AI_NUMERICHOST since this is a numeric string */ 00606 (*pptResult)->ai_flags |= AI_NUMERICHOST; 00607 00608 /* Check if the canonical name was requestd */ 00609 if (iFlags & AI_CANONNAME) 00610 { 00611 /* Get the canonical name */ 00612 GetNameInfoW((*pptResult)->ai_addr, 00613 (socklen_t)(*pptResult)->ai_addrlen, 00614 CanonicalName, 00615 0x41, 00616 NULL, 00617 0, 00618 2); 00619 00620 /* Allocate memory for a copy */ 00621 (*pptResult)->ai_canonname = HeapAlloc(WsSockHeap, 00622 0, 00623 wcslen(CanonicalName)); 00624 00625 if (!(*pptResult)->ai_canonname) 00626 { 00627 /* No memory for the copy */ 00628 iError = EAI_MEMORY; 00629 } 00630 else 00631 { 00632 /* Duplicate the string */ 00633 RtlMoveMemory((*pptResult)->ai_canonname, 00634 CanonicalName, 00635 wcslen(CanonicalName)); 00636 } 00637 } 00638 } 00639 } 00640 else if (iFlags & AI_NUMERICHOST) 00641 { 00642 /* No name for this request (we have a non-numeric name) */ 00643 iError = EAI_NONAME; 00644 } 00645 else 00646 { 00647 /* We need to convert it to ANSI */ 00648 WideCharToMultiByte(CP_ACP, 00649 0, 00650 pszNodeName, 00651 -1, 00652 AnsiNodeName, 00653 256, 00654 NULL, 00655 0); 00656 00657 /* Non-numeric name, do DNS lookup */ 00658 iError = LookupAddressForName(AnsiNodeName, 00659 iSocketType, 00660 iProtocol, 00661 wPort, 00662 (iFlags & AI_CANONNAME), 00663 pptResult); 00664 } 00665 00666 /* If all was good and the caller requested UDP and TCP */ 00667 if (!iError && bClone) 00668 { 00669 /* Process UDP now, we already did TCP */ 00670 iError = CloneAddrInfo(wUdpPort, *pptResult); 00671 } 00672 00673 /* If we've hit an error till here */ 00674 if (iError) 00675 { 00676 /* Free the address info and return nothing */ 00677 FreeAddrInfoW(*pptResult); 00678 *pptResult = NULL; 00679 } 00680 00681 /* Return to caller */ 00682 return iError; 00683 } 00684 00685 #undef freeaddrinfo 00686 /* 00687 * @implemented 00688 */ 00689 VOID 00690 WINAPI 00691 freeaddrinfo(PADDRINFOA AddrInfo) 00692 { 00693 PADDRINFOA NextInfo; 00694 00695 /* Loop the chain of structures */ 00696 for (NextInfo = AddrInfo; NextInfo; NextInfo = AddrInfo) 00697 { 00698 /* Check if there is a canonical name */ 00699 if (NextInfo->ai_canonname) 00700 { 00701 /* Free it */ 00702 HeapFree(WsSockHeap, 0, NextInfo->ai_canonname); 00703 } 00704 00705 /* Check if there is an address */ 00706 if (NextInfo->ai_addr) 00707 { 00708 /* Free it */ 00709 HeapFree(WsSockHeap, 0, NextInfo->ai_addr); 00710 } 00711 00712 /* Move to the next entry */ 00713 AddrInfo = NextInfo->ai_next; 00714 00715 /* Free this entry */ 00716 HeapFree(WsSockHeap, 0, NextInfo); 00717 } 00718 } 00719 00720 #undef getaddrinfo 00721 /* 00722 * @implemented 00723 */ 00724 INT 00725 WINAPI 00726 getaddrinfo(const char FAR *nodename, 00727 const char FAR *servname, 00728 const struct addrinfo FAR *hints, 00729 struct addrinfo FAR * FAR *res) 00730 { 00731 INT ErrorCode; 00732 LPWSTR UnicodeNodeName; 00733 LPWSTR UnicodeServName = NULL; 00734 DPRINT("getaddrinfo: %s, %s, %p, %p\n", nodename, servname, hints, res); 00735 00736 /* Check for WSAStartup */ 00737 if ((ErrorCode = WsQuickProlog()) != ERROR_SUCCESS) return ErrorCode; 00738 00739 /* Assume NULL */ 00740 *res = NULL; 00741 00742 /* Convert the node name */ 00743 UnicodeNodeName = UnicodeDupFromAnsi((LPSTR)nodename); 00744 if (!UnicodeNodeName) 00745 { 00746 /* Prepare to fail */ 00747 ErrorCode = GetLastError(); 00748 goto Quickie; 00749 } 00750 00751 /* Convert the servname too, if we have one */ 00752 if (servname) 00753 { 00754 UnicodeServName = UnicodeDupFromAnsi((LPSTR)servname); 00755 if (!UnicodeServName) 00756 { 00757 /* Prepare to fail */ 00758 ErrorCode = GetLastError(); 00759 goto Quickie; 00760 } 00761 } 00762 00763 /* Now call the unicode function */ 00764 ErrorCode = GetAddrInfoW(UnicodeNodeName, 00765 UnicodeServName, 00766 (PADDRINFOW)hints, 00767 (PADDRINFOW*)res); 00768 00769 /* Convert it to ANSI if we suceeded */ 00770 if (ErrorCode == ERROR_SUCCESS) ConvertAddrinfoFromUnicodeToAnsi((PADDRINFOW)*res); 00771 00772 Quickie: 00773 /* Check if we have a unicode node name and serv name */ 00774 if (UnicodeNodeName) HeapFree(WsSockHeap, 0, UnicodeNodeName); 00775 if (UnicodeServName) HeapFree(WsSockHeap, 0, UnicodeServName); 00776 00777 /* Check if we are in error */ 00778 if (ErrorCode != ERROR_SUCCESS) 00779 { 00780 /* Free the structure and return nothing */ 00781 freeaddrinfo(*res); 00782 *res = NULL; 00783 } 00784 00785 /* Set the last error and return */ 00786 SetLastError(ErrorCode); 00787 return ErrorCode; 00788 } 00789 00790 /* 00791 * @implemented 00792 */ 00793 INT 00794 WSAAPI 00795 GetNameInfoW(IN CONST SOCKADDR *pSockaddr, 00796 IN socklen_t SockaddrLength, 00797 OUT PWCHAR pNodeBuffer, 00798 IN DWORD NodeBufferSize, 00799 OUT PWCHAR pServiceBuffer, 00800 IN DWORD ServiceBufferSize, 00801 IN INT Flags) 00802 { 00803 DWORD AddressLength, AddrSize; 00804 PVOID Addr; 00805 SOCKADDR_IN Address; 00806 INT ErrorCode = ERROR_SUCCESS; 00807 00808 /* Check for valid socket */ 00809 if (!pSockaddr) return EAI_FAIL; 00810 00811 /* Check which family this is */ 00812 if (pSockaddr->sa_family == AF_INET) 00813 { 00814 /* IPv4 */ 00815 AddressLength = sizeof(SOCKADDR_IN); 00816 Addr = &((PSOCKADDR_IN)pSockaddr)->sin_addr; 00817 AddrSize = sizeof(IN_ADDR); 00818 } 00819 else if (pSockaddr->sa_family == AF_INET6) 00820 { 00821 /* IPv6 */ 00822 AddressLength = sizeof(SOCKADDR_IN6); 00823 Addr = &((PSOCKADDR_IN6)pSockaddr)->sin6_addr; 00824 AddrSize = sizeof(IN6_ADDR); 00825 } 00826 else 00827 { 00828 /* Unsupported family */ 00829 return EAI_FAMILY; 00830 } 00831 00832 /* Check for valid socket adress length */ 00833 if ((DWORD)SockaddrLength < AddressLength) return EAI_FAIL; 00834 00835 /* Check if we have a node name */ 00836 if (pNodeBuffer) 00837 { 00838 /* Check if only the numeric host is wanted */ 00839 if (!(Flags & NI_NUMERICHOST)) 00840 { 00841 /* Do the lookup by addr */ 00842 ErrorCode = LookupNodeByAddr(pNodeBuffer, 00843 NodeBufferSize, 00844 Flags & NI_NOFQDN, 00845 Addr, 00846 AddrSize, 00847 pSockaddr->sa_family); 00848 /* Check if we failed */ 00849 if (ErrorCode != ERROR_SUCCESS) 00850 { 00851 /* Fail if the caller REALLY wants the NAME itself? */ 00852 if (Flags & NI_NAMEREQD) goto quickie; 00853 } 00854 else 00855 { 00856 /* We suceeded, no need to get the numeric address */ 00857 goto SkipNumeric; 00858 } 00859 } 00860 00861 /* Copy the address */ 00862 RtlMoveMemory(&Address, pSockaddr, AddressLength); 00863 00864 /* Get the numeric address */ 00865 Address.sin_port = 0; 00866 ErrorCode = WSAAddressToStringW((LPSOCKADDR)&Address, 00867 AddressLength, 00868 NULL, 00869 pNodeBuffer, 00870 &NodeBufferSize); 00871 if (ErrorCode == SOCKET_ERROR) 00872 { 00873 /* Get the error code and exit with it */ 00874 ErrorCode = GetLastError(); 00875 goto quickie; 00876 } 00877 } 00878 00879 SkipNumeric: 00880 /* Check if we got a service name */ 00881 if (pServiceBuffer) 00882 { 00883 /* Handle this request */ 00884 ErrorCode = GetServiceNameForPort(pServiceBuffer, 00885 ServiceBufferSize, 00886 ((PSOCKADDR_IN)pSockaddr)->sin_port, 00887 Flags); 00888 } 00889 00890 /* Set the error and return it (or success) */ 00891 quickie: 00892 SetLastError(ErrorCode); 00893 return ErrorCode; 00894 } 00895 00896 #undef getnameinfo 00897 /* 00898 * @implemented 00899 */ 00900 INT 00901 WINAPI 00902 getnameinfo(const struct sockaddr FAR *sa, 00903 socklen_t salen, 00904 char FAR *host, 00905 DWORD hostlen, 00906 char FAR *serv, 00907 DWORD servlen, 00908 INT flags) 00909 { 00910 INT ErrorCode; 00911 WCHAR Buffer[256]; 00912 WCHAR ServiceBuffer[17]; 00913 DWORD HostLength = 0, ServLength = 0; 00914 PWCHAR ServiceString = NULL, HostString = NULL; 00915 DPRINT("getaddrinfo: %p, %p, %p, %lx\n", host, serv, sa, salen); 00916 00917 /* Check for WSAStartup */ 00918 if ((ErrorCode = WsQuickProlog()) != ERROR_SUCCESS) return ErrorCode; 00919 00920 /* Check if we have a host pointer */ 00921 if (host) 00922 { 00923 /* Setup the data for it */ 00924 HostString = Buffer; 00925 HostLength = sizeof(Buffer) / sizeof(WCHAR); 00926 } 00927 00928 /* Check if we have a service pointer */ 00929 if (serv) 00930 { 00931 /* Setup the data for it */ 00932 ServiceString = ServiceBuffer; 00933 ServLength = sizeof(ServiceBuffer) - 1; 00934 } 00935 00936 /* Now call the unicode function */ 00937 ErrorCode = GetNameInfoW(sa, 00938 salen, 00939 HostString, 00940 HostLength, 00941 ServiceString, 00942 ServLength, 00943 flags); 00944 00945 /* Check for success */ 00946 if (ErrorCode == ERROR_SUCCESS) 00947 { 00948 /* Check if we had a host pointer */ 00949 if (HostString) 00950 { 00951 /* Convert it back to ANSI */ 00952 ErrorCode = WideCharToMultiByte(CP_ACP, 00953 0, 00954 HostString, 00955 -1, 00956 host, 00957 hostlen, 00958 NULL, 00959 NULL); 00960 if (!ErrorCode) goto Quickie; 00961 } 00962 00963 /* Check if we have a service pointer */ 00964 if (ServiceString) 00965 { 00966 /* Convert it back to ANSI */ 00967 ErrorCode = WideCharToMultiByte(CP_ACP, 00968 0, 00969 ServiceString, 00970 -1, 00971 serv, 00972 servlen, 00973 NULL, 00974 NULL); 00975 if (!ErrorCode) goto Quickie; 00976 } 00977 00978 /* Return success */ 00979 return ERROR_SUCCESS; 00980 } 00981 00982 /* Set the last error and return */ 00983 Quickie: 00984 SetLastError(ErrorCode); 00985 return ErrorCode; 00986 } Generated on Fri May 25 2012 04:25:10 for ReactOS by
1.7.6.1
|