Changeset 3040


Ignore:
Timestamp:
Dec 30, 2009 8:39:14 AM (14 years ago)
Author:
bennylp
Message:

Few fixes and enhancements to Windows IP helper, related to #1000:

  • enum_ipv4_ipv6_interface() function:
    • bug fix: function should return error if no interface is found
    • do not include interfaces that are down, loopback interface, interface with 0.0.0.0/24 address, interface with zero address, etc.
  • improve buffer robustness for enum_ipv4_interface() and enum_ipv4_ipv6_interface() functions, by supplying only small buffer, but added fallback to allocating the buffer from heap if the buffer is not large enough to contain the result.
File:
1 edited

Legend:

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

    r3038 r3040  
    200200                                       pj_sockaddr ifs[]) 
    201201{ 
    202     /* Provide enough buffer or otherwise it will fail with  
    203      * error 22 ("Not Enough Buffer") error. 
    204      */ 
    205     char ipTabBuff[1024]; 
    206     MIB_IPADDRTABLE *pTab; 
    207     ULONG tabSize; 
     202    char ipTabBuff[512]; 
     203    MIB_IPADDRTABLE *pTab = (MIB_IPADDRTABLE*)ipTabBuff; 
     204    ULONG tabSize = sizeof(ipTabBuff); 
    208205    unsigned i, count; 
    209206    DWORD rc = NO_ERROR; 
     
    211208    PJ_ASSERT_RETURN(p_cnt && ifs, PJ_EINVAL); 
    212209 
    213     pTab = (MIB_IPADDRTABLE*)ipTabBuff; 
    214  
    215210    /* Get IP address table */ 
    216     tabSize = sizeof(ipTabBuff); 
    217  
    218211    rc = MyGetIpAddrTable(pTab, &tabSize, FALSE); 
    219     if (rc != NO_ERROR) 
    220         return PJ_RETURN_OS_ERROR(rc); 
     212    if (rc != NO_ERROR) { 
     213        if (rc == ERROR_INSUFFICIENT_BUFFER) { 
     214            /* Retry with larger buffer */ 
     215            pTab = (MIB_IPADDRTABLE*)malloc(tabSize); 
     216            if (pTab) 
     217                rc = MyGetIpAddrTable(pTab, &tabSize, FALSE); 
     218        } 
     219 
     220        if (rc != NO_ERROR) { 
     221            if (pTab != (MIB_IPADDRTABLE*)ipTabBuff) 
     222                free(pTab); 
     223            return PJ_RETURN_OS_ERROR(rc); 
     224        } 
     225    } 
    221226 
    222227    /* Reset result */ 
     
    255260    } 
    256261 
     262    if (pTab != (MIB_IPADDRTABLE*)ipTabBuff) 
     263        free(pTab); 
     264 
    257265    return (*p_cnt) ? PJ_SUCCESS : PJ_ENOTFOUND; 
    258266} 
    259  
    260267 
    261268/* Enumerate local IP interface using GetAdapterAddresses(), 
     
    266273                                            pj_sockaddr ifs[]) 
    267274{ 
    268     pj_uint8_t buffer[1600]; 
     275    pj_uint8_t buffer[600]; 
    269276    IP_ADAPTER_ADDRESSES *adapter = (IP_ADAPTER_ADDRESSES*)buffer; 
    270277    ULONG size = sizeof(buffer); 
     278    ULONG flags; 
    271279    unsigned i; 
    272280    DWORD rc; 
    273281 
    274     rc = MyGetAdapterAddresses(af, 0, NULL, adapter, &size); 
    275     if (rc != ERROR_SUCCESS) 
    276         return PJ_RETURN_OS_ERROR(rc); 
    277  
     282    flags = GAA_FLAG_SKIP_FRIENDLY_NAME | 
     283            GAA_FLAG_SKIP_DNS_SERVER | 
     284            GAA_FLAG_SKIP_MULTICAST; 
     285 
     286    rc = MyGetAdapterAddresses(af, flags, NULL, adapter, &size); 
     287    if (rc != ERROR_SUCCESS) { 
     288        if (rc == ERROR_BUFFER_OVERFLOW) { 
     289            /* Retry with larger memory size */ 
     290            adapter = (IP_ADAPTER_ADDRESSES*) malloc(size); 
     291            if (adapter != NULL) 
     292                rc = MyGetAdapterAddresses(af, flags, NULL, adapter, &size); 
     293        }  
     294 
     295        if (rc != ERROR_SUCCESS) { 
     296            if (adapter != (IP_ADAPTER_ADDRESSES*)buffer) 
     297                free(adapter); 
     298            return PJ_RETURN_OS_ERROR(rc); 
     299        } 
     300    } 
     301 
     302    /* Reset result */ 
     303    pj_bzero(ifs, sizeof(ifs[0]) * (*p_cnt)); 
     304 
     305    /* Enumerate interface */ 
    278306    for (i=0; i<*p_cnt && adapter; adapter = adapter->Next) { 
    279307        if (adapter->FirstUnicastAddress) { 
    280308            SOCKET_ADDRESS *pAddr = &adapter->FirstUnicastAddress->Address; 
    281             if (pAddr->lpSockaddr->sa_family == PJ_AF_INET || 
    282                 pAddr->lpSockaddr->sa_family == PJ_AF_INET6) 
     309 
     310            /* Ignore address family which we didn't request, just in case */ 
     311            if (pAddr->lpSockaddr->sa_family != PJ_AF_INET && 
     312                pAddr->lpSockaddr->sa_family != PJ_AF_INET6) 
    283313            { 
    284                 ifs[i].addr.sa_family = pAddr->lpSockaddr->sa_family; 
    285                 pj_memcpy(&ifs[i], pAddr->lpSockaddr, pAddr->iSockaddrLength); 
    286                 ++i; 
     314                continue; 
    287315            } 
    288         } 
    289     } 
     316 
     317            /* Apply some filtering to known IPv4 unusable addresses */ 
     318            if (pAddr->lpSockaddr->sa_family == PJ_AF_INET) { 
     319                const pj_sockaddr_in *addr_in =  
     320                    (const pj_sockaddr_in*)pAddr->lpSockaddr; 
     321 
     322                /* Ignore 0.0.0.0 address (interface is down?) */ 
     323                if (addr_in->sin_addr.s_addr == 0) 
     324                    continue; 
     325 
     326                /* Ignore 0.0.0.0/8 address. This is a special address 
     327                 * which doesn't seem to have practical use. 
     328                 */ 
     329                if ((pj_ntohl(addr_in->sin_addr.s_addr) >> 24) == 0) 
     330                    continue; 
     331            } 
     332 
     333#if PJ_IP_HELPER_IGNORE_LOOPBACK_IF 
     334            /* Ignore loopback interfaces */ 
     335            /* This should have been IF_TYPE_SOFTWARE_LOOPBACK according to 
     336             * MSDN, and this macro should have been declared in Ipifcons.h,  
     337             * but some SDK versions don't have it. 
     338             */ 
     339            if (adapter->IfType == MIB_IF_TYPE_LOOPBACK) 
     340                continue; 
     341#endif 
     342 
     343            /* Ignore down interface */ 
     344            if (adapter->OperStatus != IfOperStatusUp) 
     345                continue; 
     346 
     347            ifs[i].addr.sa_family = pAddr->lpSockaddr->sa_family; 
     348            pj_memcpy(&ifs[i], pAddr->lpSockaddr, pAddr->iSockaddrLength); 
     349            ++i; 
     350        } 
     351    } 
     352 
     353    if (adapter != (IP_ADAPTER_ADDRESSES*)buffer) 
     354        free(adapter); 
    290355 
    291356    *p_cnt = i; 
    292     return PJ_SUCCESS; 
     357    return (*p_cnt) ? PJ_SUCCESS : PJ_ENOTFOUND; 
    293358} 
    294359 
Note: See TracChangeset for help on using the changeset viewer.