00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #ifndef _WSPIAPI_H_
00017 #define _WSPIAPI_H_
00018
00019 #include <stdio.h>
00020 #include <stdlib.h>
00021 #include <malloc.h>
00022 #include <string.h>
00023
00024 #define WspiapiMalloc(tSize) calloc(1, (tSize))
00025 #define WspiapiFree(p) free(p)
00026 #define WspiapiSwap(a, b, c) { (c) = (a); (a) = (b); (b) = (c); }
00027 #define getaddrinfo WspiapiGetAddrInfo
00028 #define getnameinfo WspiapiGetNameInfo
00029 #define freeaddrinfo WspiapiFreeAddrInfo
00030
00031 typedef int (WINAPI *WSPIAPI_PGETADDRINFO) (
00032 IN const char *nodename,
00033 IN const char *servname,
00034 IN const struct addrinfo *hints,
00035 OUT struct addrinfo **res);
00036
00037 typedef int (WINAPI *WSPIAPI_PGETNAMEINFO) (
00038 IN const struct sockaddr *sa,
00039 IN socklen_t salen,
00040 OUT char *host,
00041 IN size_t hostlen,
00042 OUT char *serv,
00043 IN size_t servlen,
00044 IN int flags);
00045
00046 typedef void (WINAPI *WSPIAPI_PFREEADDRINFO) (
00047 IN struct addrinfo *ai);
00048
00049
00050
00051 #ifdef __cplusplus
00052 extern "C" {
00053 #endif
00054
00056
00057
00059 __inline
00060 char *
00061 WINAPI
00062 WspiapiStrdup (
00063 IN const char * pszString)
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078 {
00079 char *pszMemory;
00080
00081 if (!pszString)
00082 return(NULL);
00083
00084 pszMemory = (char *) WspiapiMalloc(strlen(pszString) + 1);
00085 if (!pszMemory)
00086 return(NULL);
00087
00088 return(strcpy(pszMemory, pszString));
00089 }
00090
00091
00092 __inline
00093 BOOL
00094 WINAPI
00095 WspiapiParseV4Address (
00096 IN const char * pszAddress,
00097 OUT PDWORD pdwAddress)
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 {
00113 DWORD dwAddress = 0;
00114 const char *pcNext = NULL;
00115 int iCount = 0;
00116
00117
00118 for (pcNext = pszAddress; *pcNext != '\0'; pcNext++)
00119 if (*pcNext == '.')
00120 iCount++;
00121 if (iCount != 3)
00122 return FALSE;
00123
00124
00125
00126 dwAddress = inet_addr(pszAddress);
00127 if (dwAddress == INADDR_NONE)
00128 return FALSE;
00129
00130 *pdwAddress = dwAddress;
00131 return TRUE;
00132 }
00133
00134
00135
00136 __inline
00137 struct addrinfo *
00138 WINAPI
00139 WspiapiNewAddrInfo (
00140 IN int iSocketType,
00141 IN int iProtocol,
00142 IN WORD wPort,
00143 IN DWORD dwAddress)
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160 {
00161 struct addrinfo *ptNew;
00162 struct sockaddr_in *ptAddress;
00163
00164
00165 ptNew =
00166 (struct addrinfo *) WspiapiMalloc(sizeof(struct addrinfo));
00167 if (!ptNew)
00168 return NULL;
00169
00170 ptAddress =
00171 (struct sockaddr_in *) WspiapiMalloc(sizeof(struct sockaddr_in));
00172 if (!ptAddress)
00173 {
00174 WspiapiFree(ptNew);
00175 return NULL;
00176 }
00177 ptAddress->sin_family = AF_INET;
00178 ptAddress->sin_port = wPort;
00179 ptAddress->sin_addr.s_addr = dwAddress;
00180
00181
00182 ptNew->ai_family = PF_INET;
00183 ptNew->ai_socktype = iSocketType;
00184 ptNew->ai_protocol = iProtocol;
00185 ptNew->ai_addrlen = sizeof(struct sockaddr_in);
00186 ptNew->ai_addr = (struct sockaddr *) ptAddress;
00187
00188 return ptNew;
00189 }
00190
00191
00192
00193 __inline
00194 int
00195 WINAPI
00196 WspiapiQueryDNS(
00197 IN const char *pszNodeName,
00198 IN int iSocketType,
00199 IN int iProtocol,
00200 IN WORD wPort,
00201 OUT char *pszAlias,
00202 OUT struct addrinfo **pptResult)
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 {
00223 struct addrinfo **pptNext = pptResult;
00224 struct hostent *ptHost = NULL;
00225 char **ppAddresses;
00226
00227 *pptNext = NULL;
00228 pszAlias[0] = '\0';
00229
00230 ptHost = gethostbyname(pszNodeName);
00231 if (ptHost)
00232 {
00233 if ((ptHost->h_addrtype == AF_INET) &&
00234 (ptHost->h_length == sizeof(struct in_addr)))
00235 {
00236 for (ppAddresses = ptHost->h_addr_list;
00237 *ppAddresses != NULL;
00238 ppAddresses++)
00239 {
00240
00241 *pptNext = WspiapiNewAddrInfo(
00242 iSocketType,
00243 iProtocol,
00244 wPort,
00245 ((struct in_addr *) *ppAddresses)->s_addr);
00246 if (!*pptNext)
00247 return EAI_MEMORY;
00248
00249 pptNext = &((*pptNext)->ai_next);
00250 }
00251 }
00252
00253
00254 strcpy(pszAlias, ptHost->h_name);
00255 return 0;
00256 }
00257
00258 switch (WSAGetLastError())
00259 {
00260 case WSAHOST_NOT_FOUND: return EAI_NONAME;
00261 case WSATRY_AGAIN: return EAI_AGAIN;
00262 case WSANO_RECOVERY: return EAI_FAIL;
00263 case WSANO_DATA: return EAI_NODATA;
00264 default: return EAI_NONAME;
00265 }
00266 }
00267
00268
00269
00270 __inline
00271 int
00272 WINAPI
00273 WspiapiLookupNode(
00274 IN const char *pszNodeName,
00275 IN int iSocketType,
00276 IN int iProtocol,
00277 IN WORD wPort,
00278 IN BOOL bAI_CANONNAME,
00279 OUT struct addrinfo **pptResult)
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302 {
00303 int iError = 0;
00304 int iAliasCount = 0;
00305
00306 char szFQDN1[NI_MAXHOST] = "";
00307 char szFQDN2[NI_MAXHOST] = "";
00308 char *pszName = szFQDN1;
00309 char *pszAlias = szFQDN2;
00310 char *pszScratch = NULL;
00311 strcpy(pszName, pszNodeName);
00312
00313 for (;;)
00314 {
00315 iError = WspiapiQueryDNS(pszNodeName,
00316 iSocketType,
00317 iProtocol,
00318 wPort,
00319 pszAlias,
00320 pptResult);
00321 if (iError)
00322 break;
00323
00324
00325 if (*pptResult)
00326 break;
00327
00328
00329
00330 if ((!strlen(pszAlias)) ||
00331 (!strcmp(pszName, pszAlias)) ||
00332 (++iAliasCount == 16))
00333 {
00334 iError = EAI_FAIL;
00335 break;
00336 }
00337
00338
00339 WspiapiSwap(pszName, pszAlias, pszScratch);
00340 }
00341
00342 if (!iError && bAI_CANONNAME)
00343 {
00344 (*pptResult)->ai_canonname = WspiapiStrdup(pszAlias);
00345 if (!(*pptResult)->ai_canonname)
00346 iError = EAI_MEMORY;
00347 }
00348
00349 return iError;
00350 }
00351
00352
00353
00354 __inline
00355 int
00356 WINAPI
00357 WspiapiClone (
00358 IN WORD wPort,
00359 IN struct addrinfo *ptResult)
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375 {
00376 struct addrinfo *ptNext = NULL;
00377 struct addrinfo *ptNew = NULL;
00378
00379 for (ptNext = ptResult; ptNext != NULL; )
00380 {
00381
00382 ptNew = WspiapiNewAddrInfo(
00383 SOCK_DGRAM,
00384 ptNext->ai_protocol,
00385 wPort,
00386 ((struct sockaddr_in *) ptNext->ai_addr)->sin_addr.s_addr);
00387 if (!ptNew)
00388 break;
00389
00390
00391 ptNew->ai_next = ptNext->ai_next;
00392 ptNext->ai_next = ptNew;
00393 ptNext = ptNew->ai_next;
00394 }
00395
00396 if (ptNext != NULL)
00397 return EAI_MEMORY;
00398
00399 return 0;
00400 }
00401
00402
00403
00404 __inline
00405 void
00406 WINAPI
00407 WspiapiLegacyFreeAddrInfo (
00408 IN struct addrinfo *ptHead)
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419 {
00420 struct addrinfo *ptNext;
00421
00422 for (ptNext = ptHead; ptNext != NULL; ptNext = ptHead)
00423 {
00424 if (ptNext->ai_canonname)
00425 WspiapiFree(ptNext->ai_canonname);
00426
00427 if (ptNext->ai_addr)
00428 WspiapiFree(ptNext->ai_addr);
00429
00430 ptHead = ptNext->ai_next;
00431 WspiapiFree(ptNext);
00432 }
00433 }
00434
00435
00436
00437 __inline
00438 int
00439 WINAPI
00440 WspiapiLegacyGetAddrInfo(
00441 IN const char *pszNodeName,
00442 IN const char *pszServiceName,
00443 IN const struct addrinfo *ptHints,
00444 OUT struct addrinfo **pptResult)
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462 {
00463 int iError = 0;
00464 int iFlags = 0;
00465 int iFamily = PF_UNSPEC;
00466 int iSocketType = 0;
00467 int iProtocol = 0;
00468 WORD wPort = 0;
00469 DWORD dwAddress = 0;
00470
00471 struct servent *ptService = NULL;
00472 char *pc = NULL;
00473 BOOL bClone = FALSE;
00474 WORD wTcpPort = 0;
00475 WORD wUdpPort = 0;
00476
00477
00478
00479 *pptResult = NULL;
00480
00481
00483
00484
00485
00486
00487 if ((!pszNodeName) && (!pszServiceName))
00488 return EAI_NONAME;
00489
00490
00491 if (ptHints)
00492 {
00493
00494
00495 if ((ptHints->ai_addrlen != 0) ||
00496 (ptHints->ai_canonname != NULL) ||
00497 (ptHints->ai_addr != NULL) ||
00498 (ptHints->ai_next != NULL))
00499 {
00500 return EAI_FAIL;
00501 }
00502
00503
00504
00505
00506
00507
00508
00509 iFlags = ptHints->ai_flags;
00510 if ((iFlags & AI_CANONNAME) && !pszNodeName)
00511 return EAI_BADFLAGS;
00512
00513
00514 iFamily = ptHints->ai_family;
00515 if ((iFamily != PF_UNSPEC) && (iFamily != PF_INET))
00516 return EAI_FAMILY;
00517
00518
00519 iSocketType = ptHints->ai_socktype;
00520 if ((iSocketType != 0) &&
00521 (iSocketType != SOCK_STREAM) &&
00522 (iSocketType != SOCK_DGRAM) &&
00523 (iSocketType != SOCK_RAW))
00524 return EAI_SOCKTYPE;
00525
00526
00527 iProtocol = ptHints->ai_protocol;
00528 }
00529
00530
00532
00533
00534 if (pszServiceName)
00535 {
00536 wPort = (WORD) strtoul(pszServiceName, &pc, 10);
00537 if (*pc == '\0')
00538 {
00539 wPort = wTcpPort = wUdpPort = htons(wPort);
00540 if (iSocketType == 0)
00541 {
00542 bClone = TRUE;
00543 iSocketType = SOCK_STREAM;
00544 }
00545 }
00546 else
00547 {
00548 if ((iSocketType == 0) || (iSocketType == SOCK_DGRAM))
00549 {
00550 ptService = getservbyname(pszServiceName, "udp");
00551 if (ptService)
00552 wPort = wUdpPort = ptService->s_port;
00553 }
00554
00555 if ((iSocketType == 0) || (iSocketType == SOCK_STREAM))
00556 {
00557 ptService = getservbyname(pszServiceName, "tcp");
00558 if (ptService)
00559 wPort = wTcpPort = ptService->s_port;
00560 }
00561
00562
00563 if (wPort == 0)
00564 return (iSocketType ? EAI_SERVICE : EAI_NONAME);
00565
00566 if (iSocketType == 0)
00567 {
00568
00569 iSocketType = (wTcpPort) ? SOCK_STREAM : SOCK_DGRAM;
00570 bClone = (wTcpPort && wUdpPort);
00571 }
00572 }
00573 }
00574
00575
00576
00578
00579
00580
00581
00582
00583
00584
00585
00586 if ((!pszNodeName) || (WspiapiParseV4Address(pszNodeName, &dwAddress)))
00587 {
00588 if (!pszNodeName)
00589 {
00590 dwAddress = htonl((iFlags & AI_PASSIVE)
00591 ? INADDR_ANY
00592 : INADDR_LOOPBACK);
00593 }
00594
00595
00596 *pptResult =
00597 WspiapiNewAddrInfo(iSocketType, iProtocol, wPort, dwAddress);
00598 if (!(*pptResult))
00599 iError = EAI_MEMORY;
00600
00601 if (!iError && pszNodeName)
00602 {
00603
00604
00605 (*pptResult)->ai_flags |= AI_NUMERICHOST;
00606
00607
00608 if (iFlags & AI_CANONNAME)
00609 {
00610 (*pptResult)->ai_canonname =
00611 WspiapiStrdup(inet_ntoa(*((struct in_addr *) &dwAddress)));
00612 if (!(*pptResult)->ai_canonname)
00613 iError = EAI_MEMORY;
00614 }
00615 }
00616 }
00617
00618
00619
00620
00621 else if (iFlags & AI_NUMERICHOST)
00622 {
00623 iError = EAI_NONAME;
00624 }
00625
00626
00627
00628
00629 else
00630 {
00631 iError = WspiapiLookupNode(pszNodeName,
00632 iSocketType,
00633 iProtocol,
00634 wPort,
00635 (iFlags & AI_CANONNAME),
00636 pptResult);
00637 }
00638
00639 if (!iError && bClone)
00640 {
00641 iError = WspiapiClone(wUdpPort, *pptResult);
00642 }
00643
00644 if (iError)
00645 {
00646 WspiapiLegacyFreeAddrInfo(*pptResult);
00647 *pptResult = NULL;
00648 }
00649
00650 return (iError);
00651 }
00652
00653
00654
00655 __inline
00656 int
00657 WINAPI
00658 WspiapiLegacyGetNameInfo(
00659 IN const struct sockaddr *ptSocketAddress,
00660 IN socklen_t tSocketLength,
00661 OUT char *pszNodeName,
00662 IN size_t tNodeLength,
00663 OUT char *pszServiceName,
00664 IN size_t tServiceLength,
00665 IN int iFlags)
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686 {
00687 struct servent *ptService;
00688 WORD wPort;
00689 char szBuffer[] = "65535";
00690 char *pszService = szBuffer;
00691
00692 struct hostent *ptHost;
00693 struct in_addr tAddress;
00694 char *pszNode = NULL;
00695 char *pc = NULL;
00696
00697
00698
00699 if (!ptSocketAddress)
00700 return EAI_FAIL;
00701
00702 if ((ptSocketAddress->sa_family != AF_INET) ||
00703 (tSocketLength != sizeof(struct sockaddr_in)))
00704 {
00705 return EAI_FAMILY;
00706 }
00707
00708 if (!(pszNodeName && tNodeLength) &&
00709 !(pszServiceName && tServiceLength))
00710 {
00711 return EAI_NONAME;
00712 }
00713
00714
00715
00716
00717
00718 if ((iFlags & NI_NUMERICHOST) && (iFlags & NI_NAMEREQD))
00719 {
00720 return EAI_BADFLAGS;
00721 }
00722
00723
00724 if (pszServiceName && tServiceLength)
00725 {
00726 wPort = ((struct sockaddr_in *) ptSocketAddress)->sin_port;
00727
00728 if (iFlags & NI_NUMERICSERV)
00729 {
00730
00731 sprintf(szBuffer, "%u", ntohs(wPort));
00732 }
00733 else
00734 {
00735
00736 ptService = getservbyport(wPort,
00737 (iFlags & NI_DGRAM) ? "udp" : NULL);
00738 if (ptService && ptService->s_name)
00739 {
00740
00741 pszService = ptService->s_name;
00742 }
00743 else
00744 {
00745
00746 sprintf(szBuffer, "%u", ntohs(wPort));
00747 }
00748 }
00749
00750
00751 if (tServiceLength > strlen(pszService))
00752 strcpy(pszServiceName, pszService);
00753 else
00754 return EAI_FAIL;
00755 }
00756
00757
00758
00759 if (pszNodeName && tNodeLength)
00760 {
00761
00762 tAddress = ((struct sockaddr_in *) ptSocketAddress)->sin_addr;
00763
00764 if (iFlags & NI_NUMERICHOST)
00765 {
00766
00767 pszNode = inet_ntoa(tAddress);
00768 }
00769 else
00770 {
00771
00772 ptHost = gethostbyaddr((char *) &tAddress,
00773 sizeof(struct in_addr),
00774 AF_INET);
00775 if (ptHost && ptHost->h_name)
00776 {
00777
00778
00779 pszNode = ptHost->h_name;
00780 if ((iFlags & NI_NOFQDN) && (pc = strchr(pszNode, '.')))
00781 *pc = '\0';
00782 }
00783 else
00784 {
00785
00786 if (iFlags & NI_NAMEREQD)
00787 {
00788 switch (WSAGetLastError())
00789 {
00790 case WSAHOST_NOT_FOUND: return EAI_NONAME;
00791 case WSATRY_AGAIN: return EAI_AGAIN;
00792 case WSANO_RECOVERY: return EAI_FAIL;
00793 default: return EAI_NONAME;
00794 }
00795 }
00796 else
00797 pszNode = inet_ntoa(tAddress);
00798 }
00799 }
00800
00801 if (tNodeLength > strlen(pszNode))
00802 strcpy(pszNodeName, pszNode);
00803 else
00804 return EAI_FAIL;
00805 }
00806
00807 return 0;
00808 }
00809
00810
00811
00812 typedef struct
00813 {
00814 char const *pszName;
00815 FARPROC pfAddress;
00816 } WSPIAPI_FUNCTION;
00817
00818 #define WSPIAPI_FUNCTION_ARRAY \
00819 { \
00820 "getaddrinfo", (FARPROC) WspiapiLegacyGetAddrInfo, \
00821 "getnameinfo", (FARPROC) WspiapiLegacyGetNameInfo, \
00822 "freeaddrinfo", (FARPROC) WspiapiLegacyFreeAddrInfo, \
00823 }
00824
00825
00826
00827 __inline
00828 FARPROC
00829 WINAPI
00830 WspiapiLoad(
00831 IN WORD wFunction)
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855 {
00856 HMODULE hLibrary = NULL;
00857
00858
00859 static BOOL bInitialized = FALSE;
00860 static WSPIAPI_FUNCTION rgtGlobal[] = WSPIAPI_FUNCTION_ARRAY;
00861 static const int iNumGlobal = (sizeof(rgtGlobal) /
00862 sizeof(WSPIAPI_FUNCTION));
00863
00864
00865 WSPIAPI_FUNCTION rgtLocal[] = WSPIAPI_FUNCTION_ARRAY;
00866 FARPROC fScratch = NULL;
00867 int i = 0;
00868
00869
00870 if (bInitialized)
00871 return (rgtGlobal[wFunction].pfAddress);
00872
00873 do
00874 {
00875
00876
00877
00878 hLibrary = LoadLibraryA("ws2_32");
00879 if (hLibrary != NULL)
00880 {
00881 fScratch = GetProcAddress(hLibrary, "getaddrinfo");
00882 if (fScratch == NULL)
00883 {
00884 FreeLibrary(hLibrary);
00885 hLibrary = NULL;
00886 }
00887 }
00888 if (hLibrary != NULL)
00889 break;
00890
00891
00892
00893
00894
00895 hLibrary = LoadLibraryA("wship6");
00896 if (hLibrary != NULL)
00897 {
00898 fScratch = GetProcAddress(hLibrary, "getaddrinfo");
00899 if (fScratch == NULL)
00900 {
00901 FreeLibrary(hLibrary);
00902 hLibrary = NULL;
00903 }
00904 }
00905 } while (FALSE);
00906
00907
00908 if (hLibrary != NULL)
00909 {
00910
00911
00912
00913 for (i = 0; i < iNumGlobal; i++)
00914 {
00915 rgtLocal[i].pfAddress
00916 = GetProcAddress(hLibrary, rgtLocal[i].pszName);
00917 if (rgtLocal[i].pfAddress == NULL)
00918 {
00919 FreeLibrary(hLibrary);
00920 hLibrary = NULL;
00921 break;
00922 }
00923 }
00924
00925 if (hLibrary != NULL)
00926 {
00927
00928 for (i = 0; i < iNumGlobal; i++)
00929 rgtGlobal[i].pfAddress = rgtLocal[i].pfAddress;
00930 }
00931 }
00932
00933 bInitialized = TRUE;
00934 return (rgtGlobal[wFunction].pfAddress);
00935 }
00936
00937
00938
00939 __inline
00940 int
00941 WINAPI
00942 WspiapiGetAddrInfo(
00943 IN const char *nodename,
00944 IN const char *servname,
00945 IN const struct addrinfo *hints,
00946 OUT struct addrinfo **res)
00947 {
00948 static WSPIAPI_PGETADDRINFO pfGetAddrInfo = NULL;
00949
00950 if (!pfGetAddrInfo)
00951 pfGetAddrInfo = (WSPIAPI_PGETADDRINFO) WspiapiLoad(0);
00952 return ((*pfGetAddrInfo)
00953 (nodename, servname, hints, res));
00954 }
00955
00956
00957
00958 __inline
00959 int
00960 WINAPI
00961 WspiapiGetNameInfo (
00962 IN const struct sockaddr *sa,
00963 IN socklen_t salen,
00964 OUT char *host,
00965 IN size_t hostlen,
00966 OUT char *serv,
00967 IN size_t servlen,
00968 IN int flags)
00969 {
00970 static WSPIAPI_PGETNAMEINFO pfGetNameInfo = NULL;
00971
00972 if (!pfGetNameInfo)
00973 pfGetNameInfo = (WSPIAPI_PGETNAMEINFO) WspiapiLoad(1);
00974 return ((*pfGetNameInfo)
00975 (sa, salen, host, hostlen, serv, servlen, flags));
00976 }
00977
00978
00979
00980 __inline
00981 void
00982 WINAPI
00983 WspiapiFreeAddrInfo (
00984 IN struct addrinfo *ai)
00985 {
00986 static WSPIAPI_PFREEADDRINFO pfFreeAddrInfo = NULL;
00987
00988 if (!pfFreeAddrInfo)
00989 pfFreeAddrInfo = (WSPIAPI_PFREEADDRINFO) WspiapiLoad(2);
00990 (*pfFreeAddrInfo)(ai);
00991 }
00992
00993 #ifdef __cplusplus
00994 }
00995 #endif
00996
00997 #endif // _WSPIAPI_H_
00998