⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wspiapi.h

📁 IP协议分析工具ipdog开源代码 好东西
💻 H
📖 第 1 页 / 共 2 页
字号:
        {
            return EAI_FAIL;
        }
        
        // the spec has the "bad flags" error code, so presumably we
        // should check something here.  insisting that there aren't
        // any unspecified flags set would break forward compatibility,
        // however.  so we just check for non-sensical combinations.
        //
        // we cannot come up with a canonical name given a null node name.
        iFlags      = ptHints->ai_flags;
        if ((iFlags & AI_CANONNAME) && !pszNodeName)
            return EAI_BADFLAGS;

        // we only support a limited number of protocol families.
        iFamily     = ptHints->ai_family;
        if ((iFamily != PF_UNSPEC) && (iFamily != PF_INET))
            return EAI_FAMILY;

        // we only support only these socket types.
        iSocketType = ptHints->ai_socktype;
        if ((iSocketType != 0)                  &&
            (iSocketType != SOCK_STREAM)        &&
            (iSocketType != SOCK_DGRAM)         &&
            (iSocketType != SOCK_RAW))
            return EAI_SOCKTYPE;

        // REVIEW: What if ai_socktype and ai_protocol are at odds?
        iProtocol   = ptHints->ai_protocol;
    }


    ////////////////////////////////////////
    // do service lookup...

    if (pszServiceName)
    {
        wPort = (WORD) strtoul(pszServiceName, &pc, 10);
        if (*pc == '\0')        // numeric port string
        {
            wPort = wTcpPort = wUdpPort = htons(wPort);
            if (iSocketType == 0)
            {
                bClone      = TRUE;
                iSocketType = SOCK_STREAM;
            }
        }
        else                    // non numeric port string
        {
            if ((iSocketType == 0) || (iSocketType == SOCK_DGRAM))
            {
                ptService = getservbyname(pszServiceName, "udp");
                if (ptService)
                    wPort = wUdpPort = ptService->s_port;
            }

            if ((iSocketType == 0) || (iSocketType == SOCK_STREAM))
            {
                ptService = getservbyname(pszServiceName, "tcp");
                if (ptService)
                    wPort = wTcpPort = ptService->s_port;
            }
            
            // assumes 0 is an invalid service port...
            if (wPort == 0)     // no service exists
                return (iSocketType ? EAI_SERVICE : EAI_NONAME);

            if (iSocketType == 0)
            {
                // if both tcp and udp, process tcp now & clone udp later.
                iSocketType = (wTcpPort) ? SOCK_STREAM : SOCK_DGRAM;
                bClone      = (wTcpPort && wUdpPort); 
            }
        }
    }
    


    ////////////////////////////////////////
    // do node name lookup...

    // if we weren't given a node name,
    // return the wildcard or loopback address (depending on AI_PASSIVE).
    //
    // if we have a numeric host address string,
    // return the binary address.
    //
    if ((!pszNodeName) || (WspiapiParseV4Address(pszNodeName, &dwAddress)))
    {
        if (!pszNodeName)
        {
            dwAddress = htonl((iFlags & AI_PASSIVE)
                              ? INADDR_ANY
                              : INADDR_LOOPBACK);
        }
        
        // create an addrinfo structure...
        *pptResult =
            WspiapiNewAddrInfo(iSocketType, iProtocol, wPort, dwAddress);
        if (!(*pptResult))
            iError = EAI_MEMORY;
        
        if (!iError && pszNodeName)
        {
            // implementation specific behavior: set AI_NUMERICHOST
            // to indicate that we got a numeric host address string.
            (*pptResult)->ai_flags |= AI_NUMERICHOST;
            
            // return the numeric address string as the canonical name
            if (iFlags & AI_CANONNAME)
            {
                (*pptResult)->ai_canonname =
                    WspiapiStrdup(inet_ntoa(*((struct in_addr *) &dwAddress)));
                if (!(*pptResult)->ai_canonname)        
                    iError = EAI_MEMORY;
            }
        }
    }


    // if we do not have a numeric host address string and
    // AI_NUMERICHOST flag is set, return an error!
    else if (iFlags & AI_NUMERICHOST)
    {
        iError = EAI_NONAME;
    }
    

    // since we have a non-numeric node name,
    // we have to do a regular node name lookup.
    else
    {
        iError = WspiapiLookupNode(pszNodeName,
                                   iSocketType,
                                   iProtocol,
                                   wPort,
                                   (iFlags & AI_CANONNAME),
                                   pptResult);
    }

    if (!iError && bClone)
    {
        iError = WspiapiClone(wUdpPort, *pptResult);
    }

    if (iError)
    {
        WspiapiLegacyFreeAddrInfo(*pptResult);
        *pptResult  = NULL;        
    }

    return (iError);
}



__inline
int
WINAPI
WspiapiLegacyGetNameInfo(
    IN  const struct sockaddr           *ptSocketAddress,
    IN  socklen_t                       tSocketLength,
    OUT char                            *pszNodeName,
    IN  size_t                          tNodeLength,
    OUT char                            *pszServiceName,
    IN  size_t                          tServiceLength,
    IN  int                             iFlags)
/*++

Routine Description
    protocol-independent address-to-name translation.
    as specified in RFC 2553, Section 6.5.
    this is the hacked version that only supports IPv4.
    
Arguments
    ptSocketAddress     socket address to translate.
    tSocketLength       length of above socket address.
    pszNodeName         where to return the node name.
    tNodeLength         size of above buffer.
    pszServiceName      where to return the service name.
    tServiceLength      size of above buffer.
    iFlags              flags of type NI_*.
    
Return Value
    returns zero if successful, an EAI_* error code if not.

--*/    
{
    struct servent  *ptService;
    WORD            wPort;    
    char            szBuffer[]  = "65535";
    char            *pszService = szBuffer;

    struct hostent  *ptHost;
    struct in_addr  tAddress;
    char            *pszNode    = NULL;
    char            *pc         = NULL;
    

    // sanity check ptSocketAddress and tSocketLength.
    if (!ptSocketAddress)
        return EAI_FAIL;
    
    if ((ptSocketAddress->sa_family != AF_INET)     ||
        (tSocketLength != sizeof(struct sockaddr_in)))
    {
        return EAI_FAMILY;
    }

    if (!(pszNodeName && tNodeLength) &&
        !(pszServiceName && tServiceLength))
    {
        return EAI_NONAME;    
    }

    // the draft has the "bad flags" error code, so presumably we
    // should check something here.  insisting that there aren't
    // any unspecified flags set would break forward compatibility,
    // however.  so we just check for non-sensical combinations.
    if ((iFlags & NI_NUMERICHOST) && (iFlags & NI_NAMEREQD))
    {                                                                       
        return EAI_BADFLAGS;
    }
        
    // translate the port to a service name (if requested).
    if (pszServiceName && tServiceLength)
    {
        wPort = ((struct sockaddr_in *) ptSocketAddress)->sin_port;
        
        if (iFlags & NI_NUMERICSERV)
        {
            // return numeric form of the address.
            sprintf(szBuffer, "%u", ntohs(wPort));
        }
        else
        {
            // return service name corresponding to port.
            ptService = getservbyport(wPort,
                                      (iFlags & NI_DGRAM) ? "udp" : NULL);
            if (ptService && ptService->s_name)
            {
                // lookup successful.
                pszService = ptService->s_name;
            }
            else
            {
                // DRAFT: return numeric form of the port!
                sprintf(szBuffer, "%u", ntohs(wPort));
            }
        }
        
        
        if (tServiceLength > strlen(pszService))
            strcpy(pszServiceName, pszService);
        else
            return EAI_FAIL;
    }

    
    // translate the address to a node name (if requested).
    if (pszNodeName && tNodeLength)
    {    
        // this is the IPv4-only version, so we have an IPv4 address.
        tAddress = ((struct sockaddr_in *) ptSocketAddress)->sin_addr;

        if (iFlags & NI_NUMERICHOST)
        {
            // return numeric form of the address.
            pszNode  = inet_ntoa(tAddress);
        }
        else
        {
            // return node name corresponding to address.
            ptHost = gethostbyaddr((char *) &tAddress,
                                   sizeof(struct in_addr),
                                   AF_INET);
            if (ptHost && ptHost->h_name)
            {
                // DNS lookup successful.
                // stop copying at a "." if NI_NOFQDN is specified.
                pszNode = ptHost->h_name;
                if ((iFlags & NI_NOFQDN) && (pc = strchr(pszNode, '.')))
                    *pc = '\0';
            }
            else
            {
                // DNS lookup failed.  return numeric form of the address.
                if (iFlags & NI_NAMEREQD)
                {
                    switch (WSAGetLastError())
                    {
                        case WSAHOST_NOT_FOUND: return EAI_NONAME;
                        case WSATRY_AGAIN:      return EAI_AGAIN;
                        case WSANO_RECOVERY:    return EAI_FAIL;
                        default:                return EAI_NONAME;
                    }
                }
                else
                    pszNode  = inet_ntoa(tAddress);
            }
        }

        if (tNodeLength > strlen(pszNode))
            strcpy(pszNodeName, pszNode);
        else
            return EAI_FAIL;
    }

    return 0;
}



typedef struct 
{
    char const          *pszName;
    FARPROC             pfAddress;
} WSPIAPI_FUNCTION;

#define WSPIAPI_FUNCTION_ARRAY                                  \
{                                                               \
    "getaddrinfo",      (FARPROC) WspiapiLegacyGetAddrInfo,     \
    "getnameinfo",      (FARPROC) WspiapiLegacyGetNameInfo,     \
    "freeaddrinfo",     (FARPROC) WspiapiLegacyFreeAddrInfo,    \
}



__inline
FARPROC
WINAPI
WspiapiLoad(
    IN  WORD                            wFunction)
/*++

Routine Description
    try to locate the address family independent name resolution routines
    (i.e. getaddrinfo, getnameinfo, freeaddrinfo, gai_strerror).
    
Locks
    this function call is not synchronized.  hence the library containing
    the routines might be loaded multiple times.  another option is to
    synchronize through a spin lock using a static local variable and the
    InterlockedExchange operation.  

    
Arguments
    wFunction           ordinal # of the function to get the pointer to
                        0   getaddrinfo
                        1   getnameinfo
                        2   freeaddrinfo
    
Return Value
    address of the library/legacy routine

--*/
{
    HMODULE                 hLibrary        = NULL;

    // these static variables store state across calls, across threads.
    static BOOL             bInitialized    = FALSE;
    static WSPIAPI_FUNCTION rgtGlobal[]     = WSPIAPI_FUNCTION_ARRAY;
    static const int        iNumGlobal      = (sizeof(rgtGlobal) /
                                               sizeof(WSPIAPI_FUNCTION));
    
    // we overwrite rgtGlobal only if all routines exist in library.
    WSPIAPI_FUNCTION        rgtLocal[]      = WSPIAPI_FUNCTION_ARRAY;
    FARPROC                 fScratch        = NULL;
    int                     i               = 0;
    
    
    if (bInitialized)           // WspiapiLoad has already been called once
        return (rgtGlobal[wFunction].pfAddress);

    do                          // breakout loop
    {
        // in Whistler and beyond...
        // the routines are present in the WinSock 2 library (ws2_32.dll).
        // printf("Looking in ws2_32 for getaddrinfo...\n");
        hLibrary = LoadLibraryA("ws2_32");
        if (hLibrary != NULL)
        {
            fScratch = GetProcAddress(hLibrary, "getaddrinfo");
            if (fScratch == NULL)
            {
                FreeLibrary(hLibrary);
                hLibrary = NULL;
            }
        }
        if (hLibrary != NULL)
            break;
        

        // in the IPv6 Technology Preview...        
        // the routines are present in the IPv6 WinSock library (wship6.dll).
        // printf("Looking in wship6 for getaddrinfo...\n");
        hLibrary = LoadLibraryA("wship6");
        if (hLibrary != NULL)
        {
            fScratch = GetProcAddress(hLibrary, "getaddrinfo");
            if (fScratch == NULL)
            {
                FreeLibrary(hLibrary);
                hLibrary = NULL;
            }
        }
    } while (FALSE);


    if (hLibrary != NULL)
    {
        // use routines from this library...
        // since getaddrinfo is here, we expect all routines to be here,
        // but will fall back to IPv4-only if any of them is missing.
        for (i = 0; i < iNumGlobal; i++)
        {
            rgtLocal[i].pfAddress
                = GetProcAddress(hLibrary, rgtLocal[i].pszName);
            if (rgtLocal[i].pfAddress == NULL)
            {
                FreeLibrary(hLibrary);
                hLibrary = NULL;
                break;
            }
        }

        if (hLibrary != NULL)
        {
            // printf("found!\n");
            for (i = 0; i < iNumGlobal; i++)
                rgtGlobal[i].pfAddress = rgtLocal[i].pfAddress;
        }
    }
    
    bInitialized = TRUE;
    return (rgtGlobal[wFunction].pfAddress);
}



__inline
int
WINAPI
WspiapiGetAddrInfo(
    IN const char                       *nodename,
    IN const char                       *servname,
    IN const struct addrinfo            *hints,
    OUT struct addrinfo                 **res)
{
    static WSPIAPI_PGETADDRINFO     pfGetAddrInfo   = NULL;

    if (!pfGetAddrInfo)
        pfGetAddrInfo   = (WSPIAPI_PGETADDRINFO) WspiapiLoad(0);
    return ((*pfGetAddrInfo)
            (nodename, servname, hints, res));
}



__inline
int
WINAPI
WspiapiGetNameInfo (
    IN  const struct sockaddr           *sa,
    IN  socklen_t                       salen,
    OUT char                            *host,
    IN  size_t                          hostlen,
    OUT char                            *serv,
    IN  size_t                          servlen,
    IN  int                             flags)
{
    static WSPIAPI_PGETNAMEINFO     pfGetNameInfo   = NULL;
    
    if (!pfGetNameInfo)
        pfGetNameInfo   = (WSPIAPI_PGETNAMEINFO) WspiapiLoad(1);
    return ((*pfGetNameInfo)
            (sa, salen, host, hostlen, serv, servlen, flags));
}



__inline
void
WINAPI
WspiapiFreeAddrInfo (
    IN  struct addrinfo                 *ai)
{
    static WSPIAPI_PFREEADDRINFO    pfFreeAddrInfo   = NULL;

    if (!pfFreeAddrInfo)
        pfFreeAddrInfo  = (WSPIAPI_PFREEADDRINFO) WspiapiLoad(2);
    (*pfFreeAddrInfo)(ai);
}

#ifdef  __cplusplus
}
#endif

#endif // _WSPIAPI_H_

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -