Ignore:
Timestamp:
Dec 1, 2007 8:52:57 AM (16 years ago)
Author:
bennylp
Message:

More ticket #415: more IPv6 and some reorganization of the source codes

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjlib/src/pj/ip_helper_win32.c

    r1450 r1601  
    2828#   define PMIB_ICMP_EX void* 
    2929#endif 
     30#include <winsock2.h> 
     31 
     32/* If you encounter error "Cannot open include file: 'Iphlpapi.h' here, 
     33 * you need to install newer Platform SDK. Presumably you're using 
     34 * Microsoft Visual Studio 6? 
     35 */ 
    3036#include <Iphlpapi.h> 
    3137 
     
    4248                                           PULONG pdwSize,  
    4349                                           BOOL bOrder); 
     50#if defined(PJ_HAS_IPV6) && PJ_HAS_IPV6!=0 
     51typedef DWORD (WINAPI *PFN_GetAdapterAddresses)(ULONG Family, 
     52                                                ULONG Flags, 
     53                                                PVOID Reserved, 
     54                                                PIP_ADAPTER_ADDRESSES AdapterAddresses, 
     55                                                PULONG SizePointer); 
     56#endif  /* PJ_HAS_IPV6 */ 
    4457typedef DWORD (WINAPI *PFN_GetIpForwardTable)(PMIB_IPFORWARDTABLE pIpForwardTable, 
    4558                                              PULONG pdwSize,  
     
    4962static HANDLE s_hDLL; 
    5063static PFN_GetIpAddrTable s_pfnGetIpAddrTable; 
     64#if defined(PJ_HAS_IPV6) && PJ_HAS_IPV6!=0 
     65    static PFN_GetAdapterAddresses s_pfnGetAdapterAddresses; 
     66#endif  /* PJ_HAS_IPV6 */ 
    5167static PFN_GetIpForwardTable s_pfnGetIpForwardTable; 
    5268static PFN_GetIfEntry s_pfnGetIfEntry; 
     69 
    5370 
    5471static void unload_iphlp_module(void) 
     
    5875    s_pfnGetIpAddrTable = NULL; 
    5976    s_pfnGetIpForwardTable = NULL; 
     77    s_pfnGetIfEntry = NULL; 
     78#if defined(PJ_HAS_IPV6) && PJ_HAS_IPV6!=0 
     79    s_pfnGetAdapterAddresses = NULL; 
     80#endif 
    6081} 
    6182 
     
    91112} 
    92113 
     114#if defined(PJ_HAS_IPV6) && PJ_HAS_IPV6!=0 
     115static DWORD MyGetAdapterAddresses(ULONG Family, 
     116                                   ULONG Flags, 
     117                                   PVOID Reserved, 
     118                                   PIP_ADAPTER_ADDRESSES AdapterAddresses, 
     119                                   PULONG SizePointer) 
     120{ 
     121    if(NULL == s_pfnGetAdapterAddresses) { 
     122        s_pfnGetAdapterAddresses = (PFN_GetAdapterAddresses)  
     123            GetIpHlpApiProc(PJ_T("GetAdapterAddresses")); 
     124    } 
     125     
     126    if(NULL != s_pfnGetAdapterAddresses) { 
     127        return s_pfnGetAdapterAddresses(Family, Flags, Reserved, 
     128                                        AdapterAddresses, SizePointer); 
     129    } 
     130     
     131    return ERROR_NOT_SUPPORTED; 
     132} 
     133#endif  /* PJ_HAS_IPV6 */ 
    93134 
    94135#if PJ_IP_HELPER_IGNORE_LOOPBACK_IF 
     
    125166} 
    126167 
    127 /* 
    128  * Enumerate the local IP interface currently active in the host. 
    129  */ 
    130 PJ_DEF(pj_status_t) pj_enum_ip_interface(unsigned *p_cnt, 
    131                                          pj_in_addr ifs[]) 
     168/* Enumerate local IP interface using GetIpAddrTable() 
     169 * for IPv4 addresses only. 
     170 */ 
     171static pj_status_t enum_ipv4_interface(unsigned *p_cnt, 
     172                                       pj_sockaddr ifs[]) 
    132173{ 
    133174    /* Provide enough buffer or otherwise it will fail with  
     
    160201        MIB_IFROW ifRow; 
    161202 
    162         /* Some Windows returns 0.0.0.0! */ 
     203        /* Ignore 0.0.0.0 address (interface is down?) */ 
    163204        if (pTab->table[i].dwAddr == 0) 
    164205            continue; 
     
    175216#endif 
    176217 
    177         ifs[*p_cnt].s_addr = pTab->table[i].dwAddr; 
     218        ifs[*p_cnt].ipv4.sin_family = PJ_AF_INET; 
     219        ifs[*p_cnt].ipv4.sin_addr.s_addr = pTab->table[i].dwAddr; 
    178220        (*p_cnt)++; 
    179221    } 
    180222 
    181223    return PJ_SUCCESS; 
    182  
    183 } 
    184  
     224} 
     225 
     226 
     227/* Enumerate local IP interface using GetAdapterAddresses(), 
     228 * which works for both IPv4 and IPv6. 
     229 */ 
     230#if defined(PJ_HAS_IPV6) && PJ_HAS_IPV6!=0 
     231static pj_status_t enum_ipv4_ipv6_interface(int af, 
     232                                            unsigned *p_cnt, 
     233                                            pj_sockaddr ifs[]) 
     234{ 
     235    pj_uint8_t buffer[1024]; 
     236    IP_ADAPTER_ADDRESSES *adapter = (IP_ADAPTER_ADDRESSES*)buffer; 
     237    ULONG size = sizeof(buffer); 
     238    unsigned i; 
     239    DWORD rc; 
     240 
     241    rc = MyGetAdapterAddresses(af, 0, NULL, adapter, &size); 
     242    if (rc != ERROR_SUCCESS) 
     243        return PJ_RETURN_OS_ERROR(rc); 
     244 
     245    for (i=0; i<*p_cnt && adapter; ++i, adapter = adapter->Next) { 
     246        SOCKET_ADDRESS *pAddr = &adapter->FirstUnicastAddress->Address; 
     247        ifs[i].addr.sa_family = pAddr->lpSockaddr->sa_family; 
     248        pj_memcpy(&ifs[i], pAddr->lpSockaddr, pAddr->iSockaddrLength); 
     249    } 
     250 
     251    return PJ_SUCCESS; 
     252} 
     253#endif 
     254 
     255 
     256/* 
     257 * Enumerate the local IP interface currently active in the host. 
     258 */ 
     259PJ_DEF(pj_status_t) pj_enum_ip_interface(int af, 
     260                                         unsigned *p_cnt, 
     261                                         pj_sockaddr ifs[]) 
     262{ 
     263    pj_status_t status = -1; 
     264 
     265    PJ_ASSERT_RETURN(p_cnt && ifs, PJ_EINVAL); 
     266    PJ_ASSERT_RETURN(af==PJ_AF_UNSPEC || af==PJ_AF_INET || af==PJ_AF_INET6, 
     267                     PJ_EAFNOTSUP); 
     268 
     269#if defined(PJ_HAS_IPV6) && PJ_HAS_IPV6!=0 
     270    status = enum_ipv4_ipv6_interface(af, p_cnt, ifs); 
     271    if (status != PJ_SUCCESS && (af==PJ_AF_INET || af==PJ_AF_UNSPEC)) 
     272        status = enum_ipv4_interface(p_cnt, ifs); 
     273    return status; 
     274#else 
     275    if (af==PJ_AF_INET6) 
     276        return PJ_EIPV6NOTSUP; 
     277    else if (af != PJ_AF_INET && af != PJ_AF_UNSPEC) 
     278        return PJ_EAFNOTSUP; 
     279 
     280    status = enum_ipv4_interface(p_cnt, ifs); 
     281    return status; 
     282#endif 
     283} 
    185284 
    186285/* 
Note: See TracChangeset for help on using the changeset viewer.