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