PageRenderTime 50ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/header/Microsoft SDKs/Windows/v7.0A/Include/WSPiApi.h

https://github.com/nihon-tc/Rtest
C Header | 1073 lines | 631 code | 170 blank | 272 comment | 142 complexity | 5cb16550971c448d0b93d3a1694b607b MD5 | raw file
  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. wspiapi.h
  5. Abstract:
  6. The file contains protocol independent API functions.
  7. Revision History:
  8. Wed Jul 12 10:50:31 2000, Created
  9. --*/
  10. #ifndef _WSPIAPI_H_
  11. #define _WSPIAPI_H_
  12. #pragma once
  13. #if (NTDDI_VERSION >= NTDDI_WIN2K)
  14. #include <stdio.h> // sprintf()
  15. #include <stdlib.h> // calloc(), strtoul()
  16. #include <malloc.h> // calloc()
  17. #include <string.h> // strlen(), strcmp(), strstr()
  18. #if defined(__GOT_SECURE_LIB__) && __GOT_SECURE_LIB__ >= 200402L
  19. #define _WSPIAPI_STRCPY_S strcpy_s
  20. #define _WSPIAPI_STRCAT_S strcat_s
  21. #define _WSPIAPI_STRNCPY_S strncpy_s
  22. #define _WSPIAPI_SPRINTF_S_1 sprintf_s
  23. #else
  24. #define _WSPIAPI_STRCPY_S(_Dst, _Size, _Src) strcpy((_Dst), (_Src))
  25. #define _WSPIAPI_STRCAT_S(_Dst, _Size, _Src) strcat((_Dst), (_Src))
  26. #define _WSPIAPI_STRNCPY_S(_Dst, _Size, _Src, _Count) strncpy((_Dst), (_Src), (_Count)); (_Dst)[(_Size) - 1] = 0
  27. #define _WSPIAPI_SPRINTF_S_1(_Dst, _Size, _Format, _Arg1) sprintf((_Dst), (_Format), (_Arg1))
  28. #endif // defined(__GOT_SECURE_LIB__) && __GOT_SECURE_LIB__ >= 200402L
  29. #if !defined(_WSPIAPI_COUNTOF)
  30. #if !defined(__cplusplus)
  31. #define _WSPIAPI_COUNTOF(_Array) (sizeof(_Array) / sizeof(_Array[0]))
  32. #else
  33. template <typename __CountofType, size_t _N>
  34. char (&__wspiapi_countof_helper(__CountofType (&_Array)[_N]))[_N];
  35. #define _WSPIAPI_COUNTOF(_Array) sizeof(__wspiapi_countof_helper(_Array))
  36. #endif
  37. #endif
  38. #define WspiapiMalloc(tSize) calloc(1, (tSize))
  39. #define WspiapiFree(p) free(p)
  40. #define WspiapiSwap(a, b, c) { (c) = (a); (a) = (b); (b) = (c); }
  41. #define getaddrinfo WspiapiGetAddrInfo
  42. #define getnameinfo WspiapiGetNameInfo
  43. #define freeaddrinfo WspiapiFreeAddrInfo
  44. //
  45. // These function pointers are also within the #if (NTDDI_VERSION >= WIN2K)
  46. // because they are used by the other functions defined in this file available
  47. // only on win2k and above.
  48. //
  49. typedef int (WINAPI *WSPIAPI_PGETADDRINFO) (
  50. __in const char *nodename,
  51. __in const char *servname,
  52. __in const struct addrinfo *hints,
  53. __out struct addrinfo **res);
  54. typedef int (WINAPI *WSPIAPI_PGETNAMEINFO) (
  55. __in_bcount(salen) const struct sockaddr *sa,
  56. __in socklen_t salen,
  57. __out_bcount(hostlen) char *host,
  58. __in size_t hostlen,
  59. __out_bcount(servlen) char *serv,
  60. __in size_t servlen,
  61. __in int flags);
  62. typedef void (WINAPI *WSPIAPI_PFREEADDRINFO) (
  63. __in struct addrinfo *ai);
  64. #ifdef __cplusplus
  65. extern "C" {
  66. #endif
  67. ////////////////////////////////////////////////////////////
  68. // v4 only versions of getaddrinfo and friends.
  69. // NOTE: gai_strerror is inlined in ws2tcpip.h
  70. ////////////////////////////////////////////////////////////
  71. _inline
  72. char *
  73. WINAPI
  74. WspiapiStrdup (
  75. __in const char * pszString)
  76. /*++
  77. Routine Description
  78. allocates enough storage via calloc() for a copy of the string,
  79. copies the string into the new memory, and returns a pointer to it.
  80. Arguments
  81. pszString string to copy into new memory
  82. Return Value
  83. a pointer to the newly allocated storage with the string in it.
  84. NULL if enough memory could not be allocated, or string was NULL.
  85. --*/
  86. {
  87. char *pszMemory;
  88. size_t cchMemory;
  89. if (!pszString)
  90. return(NULL);
  91. cchMemory = strlen(pszString) + 1;
  92. pszMemory = (char *) WspiapiMalloc(cchMemory);
  93. if (!pszMemory)
  94. return(NULL);
  95. _WSPIAPI_STRCPY_S(pszMemory, cchMemory, pszString);
  96. return pszMemory;
  97. }
  98. __inline
  99. BOOL
  100. WINAPI
  101. WspiapiParseV4Address (
  102. __in const char * pszAddress,
  103. __out PDWORD pdwAddress)
  104. /*++
  105. Routine Description
  106. get the IPv4 address (in network byte order) from its string
  107. representation. the syntax should be a.b.c.d.
  108. Arguments
  109. pszArgument string representation of the IPv4 address
  110. ptAddress pointer to the resulting IPv4 address
  111. Return Value
  112. Returns FALSE if there is an error, TRUE for success.
  113. --*/
  114. {
  115. DWORD dwAddress = 0;
  116. const char *pcNext = NULL;
  117. int iCount = 0;
  118. // ensure there are 3 '.' (periods)
  119. for (pcNext = pszAddress; *pcNext != '\0'; pcNext++)
  120. if (*pcNext == '.')
  121. iCount++;
  122. if (iCount != 3)
  123. return FALSE;
  124. // return an error if dwAddress is INADDR_NONE (255.255.255.255)
  125. // since this is never a valid argument to getaddrinfo.
  126. dwAddress = inet_addr(pszAddress);
  127. if (dwAddress == INADDR_NONE)
  128. return FALSE;
  129. *pdwAddress = dwAddress;
  130. return TRUE;
  131. }
  132. __inline
  133. struct addrinfo *
  134. WINAPI
  135. WspiapiNewAddrInfo (
  136. __in int iSocketType,
  137. __in int iProtocol,
  138. __in WORD wPort,
  139. __in DWORD dwAddress)
  140. /*++
  141. Routine Description
  142. allocate an addrinfo structure and populate fields.
  143. IPv4 specific internal function, not exported.
  144. Arguments
  145. iSocketType SOCK_*. can be wildcarded (zero).
  146. iProtocol IPPROTO_*. can be wildcarded (zero).
  147. wPort port number of service (in network order).
  148. dwAddress IPv4 address (in network order).
  149. Return Value
  150. returns an addrinfo struct, or NULL if out of memory.
  151. --*/
  152. {
  153. struct addrinfo *ptNew;
  154. struct sockaddr_in *ptAddress;
  155. // allocate a new addrinfo structure.
  156. ptNew =
  157. (struct addrinfo *) WspiapiMalloc(sizeof(struct addrinfo));
  158. if (!ptNew)
  159. return NULL;
  160. ptAddress =
  161. (struct sockaddr_in *) WspiapiMalloc(sizeof(struct sockaddr_in));
  162. if (!ptAddress)
  163. {
  164. WspiapiFree(ptNew);
  165. return NULL;
  166. }
  167. ptAddress->sin_family = AF_INET;
  168. ptAddress->sin_port = wPort;
  169. ptAddress->sin_addr.s_addr = dwAddress;
  170. // fill in the fields...
  171. ptNew->ai_family = PF_INET;
  172. ptNew->ai_socktype = iSocketType;
  173. ptNew->ai_protocol = iProtocol;
  174. ptNew->ai_addrlen = sizeof(struct sockaddr_in);
  175. ptNew->ai_addr = (struct sockaddr *) ptAddress;
  176. return ptNew;
  177. }
  178. __inline
  179. int
  180. WINAPI
  181. WspiapiQueryDNS(
  182. __in const char *pszNodeName,
  183. __in int iSocketType,
  184. __in int iProtocol,
  185. __in WORD wPort,
  186. __out char pszAlias[NI_MAXHOST],
  187. __deref_out struct addrinfo **pptResult)
  188. /*++
  189. Routine Description
  190. helper routine for WspiapiLookupNode.
  191. performs name resolution by querying the DNS for A records.
  192. *pptResult would need to be freed if an error is returned.
  193. Arguments
  194. pszNodeName name of node to resolve.
  195. iSocketType SOCK_*. can be wildcarded (zero).
  196. iProtocol IPPROTO_*. can be wildcarded (zero).
  197. wPort port number of service (in network order).
  198. pszAlias where to return the alias. must be of size NI_MAXHOST.
  199. pptResult where to return the result.
  200. Return Value
  201. Returns 0 on success, an EAI_* style error value otherwise.
  202. --*/
  203. {
  204. struct addrinfo **pptNext = pptResult;
  205. struct hostent *ptHost = NULL;
  206. char **ppAddresses;
  207. *pptNext = NULL;
  208. pszAlias[0] = '\0';
  209. ptHost = gethostbyname(pszNodeName);
  210. if (ptHost)
  211. {
  212. if ((ptHost->h_addrtype == AF_INET) &&
  213. (ptHost->h_length == sizeof(struct in_addr)))
  214. {
  215. for (ppAddresses = ptHost->h_addr_list;
  216. *ppAddresses != NULL;
  217. ppAddresses++)
  218. {
  219. // create an addrinfo structure...
  220. *pptNext = WspiapiNewAddrInfo(
  221. iSocketType,
  222. iProtocol,
  223. wPort,
  224. ((struct in_addr *) *ppAddresses)->s_addr);
  225. if (!*pptNext)
  226. return EAI_MEMORY;
  227. pptNext = &((*pptNext)->ai_next);
  228. }
  229. }
  230. // pick up the canonical name.
  231. _WSPIAPI_STRNCPY_S(pszAlias, NI_MAXHOST, ptHost->h_name, NI_MAXHOST - 1);
  232. return 0;
  233. }
  234. switch (WSAGetLastError())
  235. {
  236. case WSAHOST_NOT_FOUND: return EAI_NONAME;
  237. case WSATRY_AGAIN: return EAI_AGAIN;
  238. case WSANO_RECOVERY: return EAI_FAIL;
  239. case WSANO_DATA: return EAI_NODATA;
  240. default: return EAI_NONAME;
  241. }
  242. }
  243. __inline
  244. int
  245. WINAPI
  246. WspiapiLookupNode(
  247. __in const char *pszNodeName,
  248. __in int iSocketType,
  249. __in int iProtocol,
  250. __in WORD wPort,
  251. __in BOOL bAI_CANONNAME,
  252. __deref_out struct addrinfo **pptResult)
  253. /*++
  254. Routine Description
  255. resolve a nodename and return a list of addrinfo structures.
  256. IPv4 specific internal function, not exported.
  257. *pptResult would need to be freed if an error is returned.
  258. NOTE: if bAI_CANONNAME is true, the canonical name should be
  259. returned in the first addrinfo structure.
  260. Arguments
  261. pszNodeName name of node to resolve.
  262. iSocketType SOCK_*. can be wildcarded (zero).
  263. iProtocol IPPROTO_*. can be wildcarded (zero).
  264. wPort port number of service (in network order).
  265. bAI_CANONNAME whether the AI_CANONNAME flag is set.
  266. pptResult where to return result.
  267. Return Value
  268. Returns 0 on success, an EAI_* style error value otherwise.
  269. --*/
  270. {
  271. int iError = 0;
  272. int iAliasCount = 0;
  273. char szFQDN1[NI_MAXHOST] = "";
  274. char szFQDN2[NI_MAXHOST] = "";
  275. char *pszName = szFQDN1;
  276. char *pszAlias = szFQDN2;
  277. char *pszScratch = NULL;
  278. _WSPIAPI_STRNCPY_S(pszName, NI_MAXHOST, pszNodeName, NI_MAXHOST - 1);
  279. for (;;)
  280. {
  281. iError = WspiapiQueryDNS(pszNodeName,
  282. iSocketType,
  283. iProtocol,
  284. wPort,
  285. pszAlias,
  286. pptResult);
  287. if (iError)
  288. break;
  289. // if we found addresses, then we are done.
  290. if (*pptResult)
  291. break;
  292. // stop infinite loops due to DNS misconfiguration. there appears
  293. // to be no particular recommended limit in RFCs 1034 and 1035.
  294. if ((!strlen(pszAlias)) ||
  295. (!strcmp(pszName, pszAlias)) ||
  296. (++iAliasCount == 16))
  297. {
  298. iError = EAI_FAIL;
  299. break;
  300. }
  301. // there was a new CNAME, look again.
  302. WspiapiSwap(pszName, pszAlias, pszScratch);
  303. }
  304. if (!iError && bAI_CANONNAME)
  305. {
  306. (*pptResult)->ai_canonname = WspiapiStrdup(pszAlias);
  307. if (!(*pptResult)->ai_canonname)
  308. iError = EAI_MEMORY;
  309. }
  310. return iError;
  311. }
  312. __inline
  313. int
  314. WINAPI
  315. WspiapiClone (
  316. __in WORD wPort,
  317. __in struct addrinfo *ptResult)
  318. /*++
  319. Routine Description
  320. clone every addrinfo structure in ptResult for the UDP service.
  321. ptResult would need to be freed if an error is returned.
  322. Arguments
  323. wPort port number of UDP service.
  324. ptResult list of addrinfo structures, each
  325. of whose node needs to be cloned.
  326. Return Value
  327. Returns 0 on success, an EAI_MEMORY on allocation failure.
  328. --*/
  329. {
  330. struct addrinfo *ptNext = NULL;
  331. struct addrinfo *ptNew = NULL;
  332. for (ptNext = ptResult; ptNext != NULL; )
  333. {
  334. // create an addrinfo structure...
  335. ptNew = WspiapiNewAddrInfo(
  336. SOCK_DGRAM,
  337. ptNext->ai_protocol,
  338. wPort,
  339. ((struct sockaddr_in *) ptNext->ai_addr)->sin_addr.s_addr);
  340. if (!ptNew)
  341. break;
  342. // link the cloned addrinfo
  343. ptNew->ai_next = ptNext->ai_next;
  344. ptNext->ai_next = ptNew;
  345. ptNext = ptNew->ai_next;
  346. }
  347. if (ptNext != NULL)
  348. return EAI_MEMORY;
  349. return 0;
  350. }
  351. __inline
  352. void
  353. WINAPI
  354. WspiapiLegacyFreeAddrInfo (
  355. __in struct addrinfo *ptHead)
  356. /*++
  357. Routine Description
  358. Free an addrinfo structure (or chain of structures).
  359. As specified in RFC 2553, Section 6.4.
  360. Arguments
  361. ptHead structure (chain) to free
  362. --*/
  363. {
  364. struct addrinfo *ptNext; // next strcture to free
  365. for (ptNext = ptHead; ptNext != NULL; ptNext = ptHead)
  366. {
  367. if (ptNext->ai_canonname)
  368. WspiapiFree(ptNext->ai_canonname);
  369. if (ptNext->ai_addr)
  370. WspiapiFree(ptNext->ai_addr);
  371. ptHead = ptNext->ai_next;
  372. WspiapiFree(ptNext);
  373. }
  374. }
  375. __inline
  376. int
  377. WINAPI
  378. WspiapiLegacyGetAddrInfo(
  379. __in const char *pszNodeName,
  380. __in const char *pszServiceName,
  381. __in const struct addrinfo *ptHints,
  382. __deref_out struct addrinfo **pptResult)
  383. /*++
  384. Routine Description
  385. Protocol-independent name-to-address translation.
  386. As specified in RFC 2553, Section 6.4.
  387. This is the hacked version that only supports IPv4.
  388. Arguments
  389. pszNodeName node name to lookup.
  390. pszServiceName service name to lookup.
  391. ptHints hints about how to process request.
  392. pptResult where to return result.
  393. Return Value
  394. returns zero if successful, an EAI_* error code if not.
  395. --*/
  396. {
  397. int iError = 0;
  398. int iFlags = 0;
  399. int iFamily = PF_UNSPEC;
  400. int iSocketType = 0;
  401. int iProtocol = 0;
  402. WORD wPort = 0;
  403. DWORD dwAddress = 0;
  404. struct servent *ptService = NULL;
  405. char *pc = NULL;
  406. BOOL bClone = FALSE;
  407. WORD wTcpPort = 0;
  408. WORD wUdpPort = 0;
  409. // initialize pptResult with default return value.
  410. *pptResult = NULL;
  411. ////////////////////////////////////////
  412. // validate arguments...
  413. //
  414. // both the node name and the service name can't be NULL.
  415. if ((!pszNodeName) && (!pszServiceName))
  416. return EAI_NONAME;
  417. // validate hints.
  418. if (ptHints)
  419. {
  420. // all members other than ai_flags, ai_family, ai_socktype
  421. // and ai_protocol must be zero or a null pointer.
  422. if ((ptHints->ai_addrlen != 0) ||
  423. (ptHints->ai_canonname != NULL) ||
  424. (ptHints->ai_addr != NULL) ||
  425. (ptHints->ai_next != NULL))
  426. {
  427. return EAI_FAIL;
  428. }
  429. // the spec has the "bad flags" error code, so presumably we
  430. // should check something here. insisting that there aren't
  431. // any unspecified flags set would break forward compatibility,
  432. // however. so we just check for non-sensical combinations.
  433. //
  434. // we cannot come up with a canonical name given a null node name.
  435. iFlags = ptHints->ai_flags;
  436. if ((iFlags & AI_CANONNAME) && !pszNodeName)
  437. return EAI_BADFLAGS;
  438. // we only support a limited number of protocol families.
  439. iFamily = ptHints->ai_family;
  440. if ((iFamily != PF_UNSPEC) && (iFamily != PF_INET))
  441. return EAI_FAMILY;
  442. // we only support only these socket types.
  443. iSocketType = ptHints->ai_socktype;
  444. if ((iSocketType != 0) &&
  445. (iSocketType != SOCK_STREAM) &&
  446. (iSocketType != SOCK_DGRAM) &&
  447. (iSocketType != SOCK_RAW))
  448. return EAI_SOCKTYPE;
  449. // REVIEW: What if ai_socktype and ai_protocol are at odds?
  450. iProtocol = ptHints->ai_protocol;
  451. }
  452. ////////////////////////////////////////
  453. // do service lookup...
  454. if (pszServiceName)
  455. {
  456. wPort = (WORD) strtoul(pszServiceName, &pc, 10);
  457. if (*pc == '\0') // numeric port string
  458. {
  459. wPort = wTcpPort = wUdpPort = htons(wPort);
  460. if (iSocketType == 0)
  461. {
  462. bClone = TRUE;
  463. iSocketType = SOCK_STREAM;
  464. }
  465. }
  466. else // non numeric port string
  467. {
  468. if ((iSocketType == 0) || (iSocketType == SOCK_DGRAM))
  469. {
  470. ptService = getservbyname(pszServiceName, "udp");
  471. if (ptService)
  472. wPort = wUdpPort = ptService->s_port;
  473. }
  474. if ((iSocketType == 0) || (iSocketType == SOCK_STREAM))
  475. {
  476. ptService = getservbyname(pszServiceName, "tcp");
  477. if (ptService)
  478. wPort = wTcpPort = ptService->s_port;
  479. }
  480. // assumes 0 is an invalid service port...
  481. if (wPort == 0) // no service exists
  482. return (iSocketType ? EAI_SERVICE : EAI_NONAME);
  483. if (iSocketType == 0)
  484. {
  485. // if both tcp and udp, process tcp now & clone udp later.
  486. iSocketType = (wTcpPort) ? SOCK_STREAM : SOCK_DGRAM;
  487. bClone = (wTcpPort && wUdpPort);
  488. }
  489. }
  490. }
  491. ////////////////////////////////////////
  492. // do node name lookup...
  493. // if we weren't given a node name,
  494. // return the wildcard or loopback address (depending on AI_PASSIVE).
  495. //
  496. // if we have a numeric host address string,
  497. // return the binary address.
  498. //
  499. if ((!pszNodeName) || (WspiapiParseV4Address(pszNodeName, &dwAddress)))
  500. {
  501. if (!pszNodeName)
  502. {
  503. dwAddress = htonl((iFlags & AI_PASSIVE)
  504. ? INADDR_ANY
  505. : INADDR_LOOPBACK);
  506. }
  507. // create an addrinfo structure...
  508. *pptResult =
  509. WspiapiNewAddrInfo(iSocketType, iProtocol, wPort, dwAddress);
  510. if (!(*pptResult))
  511. iError = EAI_MEMORY;
  512. if (!iError && pszNodeName)
  513. {
  514. // implementation specific behavior: set AI_NUMERICHOST
  515. // to indicate that we got a numeric host address string.
  516. (*pptResult)->ai_flags |= AI_NUMERICHOST;
  517. // return the numeric address string as the canonical name
  518. if (iFlags & AI_CANONNAME)
  519. {
  520. (*pptResult)->ai_canonname =
  521. WspiapiStrdup(inet_ntoa(*((struct in_addr *) &dwAddress)));
  522. if (!(*pptResult)->ai_canonname)
  523. iError = EAI_MEMORY;
  524. }
  525. }
  526. }
  527. // if we do not have a numeric host address string and
  528. // AI_NUMERICHOST flag is set, return an error!
  529. else if (iFlags & AI_NUMERICHOST)
  530. {
  531. iError = EAI_NONAME;
  532. }
  533. // since we have a non-numeric node name,
  534. // we have to do a regular node name lookup.
  535. else
  536. {
  537. iError = WspiapiLookupNode(pszNodeName,
  538. iSocketType,
  539. iProtocol,
  540. wPort,
  541. (iFlags & AI_CANONNAME),
  542. pptResult);
  543. }
  544. if (!iError && bClone)
  545. {
  546. iError = WspiapiClone(wUdpPort, *pptResult);
  547. }
  548. if (iError)
  549. {
  550. WspiapiLegacyFreeAddrInfo(*pptResult);
  551. *pptResult = NULL;
  552. }
  553. return (iError);
  554. }
  555. __inline
  556. int
  557. WINAPI
  558. WspiapiLegacyGetNameInfo(
  559. __in_bcount(tSocketLength) const struct sockaddr *ptSocketAddress,
  560. __in socklen_t tSocketLength,
  561. __out_bcount(tNodeLength) char *pszNodeName,
  562. __in size_t tNodeLength,
  563. __out_bcount(tServiceLength) char *pszServiceName,
  564. __in size_t tServiceLength,
  565. __in int iFlags)
  566. /*++
  567. Routine Description
  568. protocol-independent address-to-name translation.
  569. as specified in RFC 2553, Section 6.5.
  570. this is the hacked version that only supports IPv4.
  571. Arguments
  572. ptSocketAddress socket address to translate.
  573. tSocketLength length of above socket address.
  574. pszNodeName where to return the node name.
  575. tNodeLength size of above buffer.
  576. pszServiceName where to return the service name.
  577. tServiceLength size of above buffer.
  578. iFlags flags of type NI_*.
  579. Return Value
  580. returns zero if successful, an EAI_* error code if not.
  581. --*/
  582. {
  583. struct servent *ptService;
  584. WORD wPort;
  585. char szBuffer[] = "65535";
  586. char *pszService = szBuffer;
  587. struct hostent *ptHost;
  588. struct in_addr tAddress;
  589. char *pszNode = NULL;
  590. char *pc = NULL;
  591. // sanity check ptSocketAddress and tSocketLength.
  592. if ((!ptSocketAddress) || (tSocketLength < sizeof(struct sockaddr)))
  593. return EAI_FAIL;
  594. if (ptSocketAddress->sa_family != AF_INET)
  595. return EAI_FAMILY;
  596. if (tSocketLength < sizeof(struct sockaddr_in))
  597. return EAI_FAIL;
  598. if (!(pszNodeName && tNodeLength) &&
  599. !(pszServiceName && tServiceLength))
  600. {
  601. return EAI_NONAME;
  602. }
  603. // the draft has the "bad flags" error code, so presumably we
  604. // should check something here. insisting that there aren't
  605. // any unspecified flags set would break forward compatibility,
  606. // however. so we just check for non-sensical combinations.
  607. if ((iFlags & NI_NUMERICHOST) && (iFlags & NI_NAMEREQD))
  608. {
  609. return EAI_BADFLAGS;
  610. }
  611. // translate the port to a service name (if requested).
  612. if (pszServiceName && tServiceLength)
  613. {
  614. wPort = ((struct sockaddr_in *) ptSocketAddress)->sin_port;
  615. if (iFlags & NI_NUMERICSERV)
  616. {
  617. // return numeric form of the address.
  618. _WSPIAPI_SPRINTF_S_1(szBuffer, _WSPIAPI_COUNTOF(szBuffer), "%u", ntohs(wPort));
  619. }
  620. else
  621. {
  622. // return service name corresponding to port.
  623. ptService = getservbyport(wPort,
  624. (iFlags & NI_DGRAM) ? "udp" : NULL);
  625. if (ptService && ptService->s_name)
  626. {
  627. // lookup successful.
  628. pszService = ptService->s_name;
  629. }
  630. else
  631. {
  632. // DRAFT: return numeric form of the port!
  633. _WSPIAPI_SPRINTF_S_1(szBuffer, _WSPIAPI_COUNTOF(szBuffer), "%u", ntohs(wPort));
  634. }
  635. }
  636. if (tServiceLength > strlen(pszService))
  637. _WSPIAPI_STRCPY_S(pszServiceName, tServiceLength, pszService);
  638. else
  639. return EAI_FAIL;
  640. }
  641. // translate the address to a node name (if requested).
  642. if (pszNodeName && tNodeLength)
  643. {
  644. // this is the IPv4-only version, so we have an IPv4 address.
  645. tAddress = ((struct sockaddr_in *) ptSocketAddress)->sin_addr;
  646. if (iFlags & NI_NUMERICHOST)
  647. {
  648. // return numeric form of the address.
  649. pszNode = inet_ntoa(tAddress);
  650. }
  651. else
  652. {
  653. // return node name corresponding to address.
  654. ptHost = gethostbyaddr((char *) &tAddress,
  655. sizeof(struct in_addr),
  656. AF_INET);
  657. if (ptHost && ptHost->h_name)
  658. {
  659. // DNS lookup successful.
  660. // stop copying at a "." if NI_NOFQDN is specified.
  661. pszNode = ptHost->h_name;
  662. if ((iFlags & NI_NOFQDN) &&
  663. ((pc = strchr(pszNode, '.')) != NULL))
  664. *pc = '\0';
  665. }
  666. else
  667. {
  668. // DNS lookup failed. return numeric form of the address.
  669. if (iFlags & NI_NAMEREQD)
  670. {
  671. switch (WSAGetLastError())
  672. {
  673. case WSAHOST_NOT_FOUND: return EAI_NONAME;
  674. case WSATRY_AGAIN: return EAI_AGAIN;
  675. case WSANO_RECOVERY: return EAI_FAIL;
  676. default: return EAI_NONAME;
  677. }
  678. }
  679. else
  680. pszNode = inet_ntoa(tAddress);
  681. }
  682. }
  683. if (tNodeLength > strlen(pszNode))
  684. _WSPIAPI_STRCPY_S(pszNodeName, tNodeLength, pszNode);
  685. else
  686. return EAI_FAIL;
  687. }
  688. return 0;
  689. }
  690. typedef struct
  691. {
  692. char const *pszName;
  693. FARPROC pfAddress;
  694. } WSPIAPI_FUNCTION;
  695. #define WSPIAPI_FUNCTION_ARRAY \
  696. { \
  697. "getaddrinfo", (FARPROC) WspiapiLegacyGetAddrInfo, \
  698. "getnameinfo", (FARPROC) WspiapiLegacyGetNameInfo, \
  699. "freeaddrinfo", (FARPROC) WspiapiLegacyFreeAddrInfo, \
  700. }
  701. __inline
  702. FARPROC
  703. WINAPI
  704. WspiapiLoad(
  705. __in WORD wFunction)
  706. /*++
  707. Routine Description
  708. try to locate the address family independent name resolution routines
  709. (i.e. getaddrinfo, getnameinfo, freeaddrinfo, gai_strerror).
  710. Locks
  711. this function call is not synchronized. hence the library containing
  712. the routines might be loaded multiple times. another option is to
  713. synchronize through a spin lock using a static local variable and the
  714. InterlockedExchange operation.
  715. Arguments
  716. wFunction ordinal # of the function to get the pointer to
  717. 0 getaddrinfo
  718. 1 getnameinfo
  719. 2 freeaddrinfo
  720. Return Value
  721. address of the library/legacy routine
  722. --*/
  723. {
  724. HMODULE hLibrary = NULL;
  725. // these static variables store state across calls, across threads.
  726. static BOOL bInitialized = FALSE;
  727. static WSPIAPI_FUNCTION rgtGlobal[] = WSPIAPI_FUNCTION_ARRAY;
  728. static const int iNumGlobal = (sizeof(rgtGlobal) /
  729. sizeof(WSPIAPI_FUNCTION));
  730. // we overwrite rgtGlobal only if all routines exist in library.
  731. WSPIAPI_FUNCTION rgtLocal[] = WSPIAPI_FUNCTION_ARRAY;
  732. FARPROC fScratch = NULL;
  733. int i = 0;
  734. if (bInitialized) // WspiapiLoad has already been called once
  735. return (rgtGlobal[wFunction].pfAddress);
  736. for (;;) // breakout loop
  737. {
  738. CHAR SystemDir[MAX_PATH + 1];
  739. CHAR Path[MAX_PATH + 8];
  740. if (GetSystemDirectoryA(SystemDir, MAX_PATH) == 0)
  741. {
  742. break;
  743. }
  744. // in Whistler and beyond...
  745. // the routines are present in the WinSock 2 library (ws2_32.dll).
  746. // printf("Looking in ws2_32 for getaddrinfo...\n");
  747. _WSPIAPI_STRCPY_S(Path, _WSPIAPI_COUNTOF(Path), SystemDir);
  748. _WSPIAPI_STRCAT_S(Path, _WSPIAPI_COUNTOF(Path), "\\ws2_32");
  749. hLibrary = LoadLibraryA(Path);
  750. if (hLibrary != NULL)
  751. {
  752. fScratch = GetProcAddress(hLibrary, "getaddrinfo");
  753. if (fScratch == NULL)
  754. {
  755. FreeLibrary(hLibrary);
  756. hLibrary = NULL;
  757. }
  758. }
  759. if (hLibrary != NULL)
  760. break;
  761. // in the IPv6 Technology Preview...
  762. // the routines are present in the IPv6 WinSock library (wship6.dll).
  763. // printf("Looking in wship6 for getaddrinfo...\n");
  764. _WSPIAPI_STRCPY_S(Path, _WSPIAPI_COUNTOF(Path), SystemDir);
  765. _WSPIAPI_STRCAT_S(Path, _WSPIAPI_COUNTOF(Path), "\\wship6");
  766. hLibrary = LoadLibraryA(Path);
  767. if (hLibrary != NULL)
  768. {
  769. fScratch = GetProcAddress(hLibrary, "getaddrinfo");
  770. if (fScratch == NULL)
  771. {
  772. FreeLibrary(hLibrary);
  773. hLibrary = NULL;
  774. }
  775. }
  776. break;
  777. }
  778. if (hLibrary != NULL)
  779. {
  780. // use routines from this library...
  781. // since getaddrinfo is here, we expect all routines to be here,
  782. // but will fall back to IPv4-only if any of them is missing.
  783. for (i = 0; i < iNumGlobal; i++)
  784. {
  785. rgtLocal[i].pfAddress
  786. = GetProcAddress(hLibrary, rgtLocal[i].pszName);
  787. if (rgtLocal[i].pfAddress == NULL)
  788. {
  789. FreeLibrary(hLibrary);
  790. hLibrary = NULL;
  791. break;
  792. }
  793. }
  794. if (hLibrary != NULL)
  795. {
  796. // printf("found!\n");
  797. for (i = 0; i < iNumGlobal; i++)
  798. rgtGlobal[i].pfAddress = rgtLocal[i].pfAddress;
  799. }
  800. }
  801. bInitialized = TRUE;
  802. return (rgtGlobal[wFunction].pfAddress);
  803. }
  804. __inline
  805. int
  806. WINAPI
  807. WspiapiGetAddrInfo(
  808. __in_opt const char *nodename,
  809. __in_opt const char *servname,
  810. __in_opt const struct addrinfo *hints,
  811. __deref_out struct addrinfo **res)
  812. {
  813. int iError;
  814. static WSPIAPI_PGETADDRINFO pfGetAddrInfo = NULL;
  815. if (!pfGetAddrInfo)
  816. pfGetAddrInfo = (WSPIAPI_PGETADDRINFO) WspiapiLoad(0);
  817. iError = (*pfGetAddrInfo)(nodename, servname, hints, res);
  818. WSASetLastError(iError);
  819. return iError;
  820. }
  821. __inline
  822. int
  823. WINAPI
  824. WspiapiGetNameInfo (
  825. __in_bcount(salen) const struct sockaddr *sa,
  826. __in socklen_t salen,
  827. __out_bcount(hostlen) char *host,
  828. __in size_t hostlen,
  829. __out_bcount(servlen) char *serv,
  830. __in size_t servlen,
  831. __in int flags)
  832. {
  833. int iError;
  834. static WSPIAPI_PGETNAMEINFO pfGetNameInfo = NULL;
  835. if (!pfGetNameInfo)
  836. pfGetNameInfo = (WSPIAPI_PGETNAMEINFO) WspiapiLoad(1);
  837. iError = (*pfGetNameInfo)(sa, salen, host, hostlen, serv, servlen, flags);
  838. WSASetLastError(iError);
  839. return iError;
  840. }
  841. __inline
  842. void
  843. WINAPI
  844. WspiapiFreeAddrInfo (
  845. __in struct addrinfo *ai)
  846. {
  847. static WSPIAPI_PFREEADDRINFO pfFreeAddrInfo = NULL;
  848. if (!pfFreeAddrInfo)
  849. pfFreeAddrInfo = (WSPIAPI_PFREEADDRINFO) WspiapiLoad(2);
  850. (*pfFreeAddrInfo)(ai);
  851. }
  852. #ifdef __cplusplus
  853. }
  854. #endif
  855. #endif // if (NTDDI_VERSION >= WIN2K)
  856. #endif // _WSPIAPI_H_