Changeset 6045


Ignore:
Timestamp:
Jul 26, 2019 9:32:14 AM (9 months ago)
Author:
nanang
Message:

Close #2217: Omit deprecated IPv6 addresses from ICE candidates.

Location:
pjproject/trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjlib/include/pj/ip_helper.h

    r3553 r6045  
    2727 
    2828#include <pj/sock.h> 
     29#include <pj/string.h> 
    2930 
    3031PJ_BEGIN_DECL 
     
    5354} pj_ip_route_entry; 
    5455 
     56/** 
     57 * This structure describes options for pj_enum_ip_interface2(). 
     58 */ 
     59typedef struct pj_enum_ip_option 
     60{ 
     61    /** 
     62     * Family of the address to be retrieved. Application may specify 
     63     * pj_AF_UNSPEC() to retrieve all addresses, or pj_AF_INET() or 
     64     * pj_AF_INET6() to retrieve interfaces with specific address family. 
     65     * 
     66     * Default: pj_AF_UNSPEC(). 
     67     */ 
     68    int                 af; 
     69 
     70    /** 
     71     * IPv6 addresses can have a DEPRECATED flag, if this flag is set, any 
     72     * DEPRECATED IPv6 address will be omitted. Currently this is only 
     73     * available for Linux, on other platforms, if this flag is set, 
     74     * pj_enum_ip_interface2() will return PJ_ENOTSUP. 
     75     * 
     76     * Default: PJ_FALSE. 
     77     */ 
     78    pj_bool_t           omit_deprecated_ipv6; 
     79 
     80} pj_enum_ip_option; 
     81 
     82 
     83/** 
     84 * Get default values of IP enumeration option. 
     85 * 
     86 * @param opt       The IP enumeration option. 
     87 */ 
     88PJ_INLINE(void) pj_enum_ip_option_default(pj_enum_ip_option *opt) 
     89{ 
     90    pj_bzero(opt, sizeof(*opt)); 
     91} 
     92 
    5593 
    5694/** 
     
    76114 
    77115/** 
     116 * Enumerate the local IP interfaces currently active in the host with 
     117 * capability to filter DEPRECATED IPv6 addresses (currently only for Linux). 
     118 * 
     119 * @param opt       The option, default option will be used if NULL. 
     120 * @param count     On input, specify the number of entries. On output, 
     121 *                  it will be filled with the actual number of entries. 
     122 * @param ifs       Array of socket (with flags) addresses, which address part 
     123 *                  will be filled with the interface address. The address 
     124 *                  family part will be initialized with the address 
     125 *                  family of the IP address. 
     126 * 
     127 * @return          PJ_SUCCESS on success, or the appropriate error code. 
     128 */ 
     129PJ_DECL(pj_status_t) pj_enum_ip_interface2(const pj_enum_ip_option *opt, 
     130                                           unsigned *count, 
     131                                           pj_sockaddr ifs[]); 
     132 
     133/** 
    78134 * Enumerate the IP routing table for this host. 
    79135 * 
  • pjproject/trunk/pjlib/src/pj/ip_helper_generic.c

    r4355 r6045  
    2626#include <pj/sock.h> 
    2727 
     28 
     29#if defined(PJ_LINUX) && PJ_LINUX!=0 
     30/* The following headers are used to get DEPRECATED addresses */ 
     31#include <arpa/inet.h> 
     32#include <asm/types.h> 
     33#include <linux/netlink.h> 
     34#include <linux/rtnetlink.h> 
     35#include <sys/socket.h> 
     36#include <unistd.h> 
     37#endif 
     38 
    2839/* Set to 1 to enable tracing */ 
    2940#if 0 
     
    408419} 
    409420 
     421static pj_status_t get_ipv6_deprecated(unsigned *count, pj_sockaddr addr[]) 
     422{ 
     423#if defined(PJ_LINUX) && PJ_LINUX!=0 
     424    struct { 
     425        struct nlmsghdr        nlmsg_info; 
     426        struct ifaddrmsg    ifaddrmsg_info; 
     427    } netlink_req; 
     428 
     429    long pagesize = sysconf(_SC_PAGESIZE); 
     430    if (!pagesize) 
     431        pagesize = 4096; /* Assume pagesize is 4096 if sysconf() failed */ 
     432 
     433    int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); 
     434    if (fd < 0) 
     435        return PJ_RETURN_OS_ERROR(pj_get_native_netos_error()); 
     436 
     437    bzero(&netlink_req, sizeof(netlink_req)); 
     438 
     439    netlink_req.nlmsg_info.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); 
     440    netlink_req.nlmsg_info.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; 
     441    netlink_req.nlmsg_info.nlmsg_type = RTM_GETADDR; 
     442    netlink_req.nlmsg_info.nlmsg_pid = getpid(); 
     443    netlink_req.ifaddrmsg_info.ifa_family = AF_INET6; 
     444 
     445    int rtn = send(fd, &netlink_req, netlink_req.nlmsg_info.nlmsg_len, 0); 
     446    if (rtn < 0) 
     447        return PJ_RETURN_OS_ERROR(pj_get_native_netos_error()); 
     448 
     449    char read_buffer[pagesize]; 
     450    size_t idx = 0; 
     451 
     452    while(1) { 
     453        bzero(read_buffer, pagesize); 
     454        int read_size = recv(fd, read_buffer, pagesize, 0); 
     455        if (read_size < 0) 
     456            return PJ_RETURN_OS_ERROR(pj_get_native_netos_error()); 
     457 
     458        struct nlmsghdr *nlmsg_ptr = (struct nlmsghdr *) read_buffer; 
     459        int nlmsg_len = read_size; 
     460 
     461        if (nlmsg_len < sizeof (struct nlmsghdr)) 
     462            return PJ_ETOOSMALL; 
     463 
     464        if (nlmsg_ptr->nlmsg_type == NLMSG_DONE) 
     465            break; 
     466 
     467        for(; NLMSG_OK(nlmsg_ptr, nlmsg_len); 
     468            nlmsg_ptr = NLMSG_NEXT(nlmsg_ptr, nlmsg_len)) 
     469        { 
     470            struct ifaddrmsg *ifaddrmsg_ptr; 
     471            struct rtattr *rtattr_ptr; 
     472            int ifaddrmsg_len; 
     473 
     474            ifaddrmsg_ptr = (struct ifaddrmsg*)NLMSG_DATA(nlmsg_ptr); 
     475 
     476            if (ifaddrmsg_ptr->ifa_flags & IFA_F_DEPRECATED || 
     477                ifaddrmsg_ptr->ifa_flags & IFA_F_TENTATIVE) 
     478            { 
     479                rtattr_ptr = (struct rtattr*)IFA_RTA(ifaddrmsg_ptr); 
     480                ifaddrmsg_len = IFA_PAYLOAD(nlmsg_ptr); 
     481 
     482                for(;RTA_OK(rtattr_ptr, ifaddrmsg_len); 
     483                    rtattr_ptr = RTA_NEXT(rtattr_ptr, ifaddrmsg_len)) 
     484                { 
     485                    switch(rtattr_ptr->rta_type) { 
     486                    case IFA_ADDRESS: 
     487                        // Check if addr can contains more data 
     488                        if (idx >= *count) 
     489                            break; 
     490                        // Store deprecated IP 
     491                        char deprecatedAddr[PJ_INET6_ADDRSTRLEN]; 
     492                        inet_ntop(ifaddrmsg_ptr->ifa_family, 
     493                                  RTA_DATA(rtattr_ptr), 
     494                                  deprecatedAddr, 
     495                                  sizeof(deprecatedAddr)); 
     496                        pj_str_t pj_addr_str; 
     497                        pj_cstr(&pj_addr_str, deprecatedAddr); 
     498                        pj_sockaddr_init(pj_AF_INET6(), &addr[idx], 
     499                                         &pj_addr_str, 0); 
     500                        ++idx; 
     501                    default: 
     502                        break; 
     503                    } 
     504                } 
     505            } 
     506        } 
     507    } 
     508 
     509    close(fd); 
     510    *count = idx; 
     511 
     512    return PJ_SUCCESS; 
     513#else 
     514    *count = 0; 
     515    return PJ_ENOTSUP; 
     516#endif 
     517} 
     518 
     519 
     520/* 
     521 * Enumerate the local IP interface currently active in the host. 
     522 */ 
     523PJ_DEF(pj_status_t) pj_enum_ip_interface2( const pj_enum_ip_option *opt, 
     524                                           unsigned *p_cnt, 
     525                                           pj_sockaddr ifs[]) 
     526{ 
     527    pj_enum_ip_option opt_; 
     528 
     529    if (opt) 
     530        opt_ = *opt; 
     531    else 
     532        pj_enum_ip_option_default(&opt_); 
     533 
     534    if (opt_.af != pj_AF_INET() && opt_.omit_deprecated_ipv6) { 
     535        pj_sockaddr addrs[*p_cnt]; 
     536        pj_sockaddr deprecatedAddrs[*p_cnt]; 
     537        unsigned deprecatedCount = *p_cnt; 
     538        unsigned cnt = 0; 
     539        pj_status_t status; 
     540 
     541        status = get_ipv6_deprecated(&deprecatedCount, deprecatedAddrs); 
     542        if (status != PJ_SUCCESS) 
     543            return status; 
     544 
     545        status = pj_enum_ip_interface(opt_.af, p_cnt, addrs); 
     546        if (status != PJ_SUCCESS) 
     547            return status; 
     548 
     549        for (int i = 0; i < *p_cnt; ++i) { 
     550            ifs[cnt++] = addrs[i]; 
     551 
     552            if (addrs[i].addr.sa_family != pj_AF_INET6()) 
     553                continue; 
     554 
     555            for (int j = 0; j < deprecatedCount; ++j) { 
     556                if (pj_sockaddr_cmp(&addrs[i], &deprecatedAddrs[j]) == 0) { 
     557                    cnt--; 
     558                    break; 
     559                } 
     560            } 
     561        } 
     562 
     563        *p_cnt = cnt; 
     564        return *p_cnt ? PJ_SUCCESS : PJ_ENOTFOUND; 
     565    } 
     566 
     567    return pj_enum_ip_interface(opt_.af, p_cnt, ifs); 
     568} 
  • pjproject/trunk/pjlib/src/pj/ip_helper_symbian.cpp

    r3553 r6045  
    139139 
    140140/* 
     141 * Enumerate the local IP interface currently active in the host. 
     142 */ 
     143PJ_DEF(pj_status_t) pj_enum_ip_interface2( const pj_enum_ip_option *opt, 
     144                                           unsigned *count, 
     145                                           pj_sockaddr ifs[]) 
     146{ 
     147    pj_enum_ip_option opt_; 
     148 
     149    if (opt && opt->omit_deprecated_ipv6) 
     150        return PJ_ENOTSUP; 
     151 
     152    if (opt) 
     153        opt_ = *opt; 
     154    else 
     155        pj_enum_ip_option_default(&opt_); 
     156 
     157    return pj_enum_ip_interface(opt_.af, count, ifs); 
     158} 
     159 
     160/* 
    141161 * Enumerate the IP routing table for this host. 
    142162 */ 
  • pjproject/trunk/pjlib/src/pj/ip_helper_win32.c

    r3553 r6045  
    380380} 
    381381 
     382 
     383/* 
     384 * Enumerate the local IP interface currently active in the host. 
     385 */ 
     386PJ_DEF(pj_status_t) pj_enum_ip_interface2( const pj_enum_ip_option *opt, 
     387                                           unsigned *p_cnt, 
     388                                           pj_sockaddr ifs[]) 
     389{ 
     390    pj_enum_ip_option opt_; 
     391 
     392    if (opt && opt->omit_deprecated_ipv6) 
     393        return PJ_ENOTSUP; 
     394 
     395    if (opt) 
     396        opt_ = *opt; 
     397    else 
     398        pj_enum_ip_option_default(&opt_); 
     399 
     400    return pj_enum_ip_interface(opt_.af, p_cnt, ifs); 
     401} 
     402 
     403 
    382404/* 
    383405 * Enumerate the IP routing table for this host. 
  • pjproject/trunk/pjlib/src/pj/ip_helper_winphone8.c

    r5539 r6045  
    4242 
    4343/* 
     44 * Enumerate the local IP interface currently active in the host. 
     45 */ 
     46PJ_DEF(pj_status_t) pj_enum_ip_interface2( const pj_enum_ip_option *opt, 
     47                                           unsigned *p_cnt, 
     48                                           pj_sockaddr ifs[]) 
     49{ 
     50    PJ_UNUSED_ARG(opt); 
     51    PJ_UNUSED_ARG(ifs); 
     52 
     53    PJ_ASSERT_RETURN(p_cnt, PJ_EINVAL); 
     54 
     55    *p_cnt = 0; 
     56 
     57    return PJ_ENOTSUP; 
     58} 
     59 
     60 
     61 
     62 
     63/* 
    4464 * Enumerate the IP routing table for this host. 
    4565 */ 
  • pjproject/trunk/pjnath/src/pjnath/stun_sock.c

    r5997 r6045  
    683683    } else { 
    684684        pj_sockaddr def_addr; 
    685         pj_uint16_t port = pj_sockaddr_get_port(&info->bound_addr);  
     685        pj_uint16_t port = pj_sockaddr_get_port(&info->bound_addr); 
     686        pj_enum_ip_option enum_opt; 
    686687        unsigned i; 
    687688 
     
    698699         
    699700        /* Enum all IP interfaces in the host */ 
     701        pj_enum_ip_option_default(&enum_opt); 
     702        enum_opt.af = stun_sock->af; 
     703        enum_opt.omit_deprecated_ipv6 = PJ_TRUE; 
    700704        info->alias_cnt = PJ_ARRAY_SIZE(info->aliases); 
    701         status = pj_enum_ip_interface(stun_sock->af, &info->alias_cnt,  
    702                                       info->aliases); 
     705        status = pj_enum_ip_interface2(&enum_opt, &info->alias_cnt,  
     706                                       info->aliases); 
     707        if (status == PJ_ENOTSUP) { 
     708            /* Try again without omitting deprecated IPv6 addresses */ 
     709            enum_opt.omit_deprecated_ipv6 = PJ_FALSE; 
     710            status = pj_enum_ip_interface2(&enum_opt, &info->alias_cnt,  
     711                                           info->aliases); 
     712        } 
     713 
    703714        if (status != PJ_SUCCESS) { 
    704715            /* If enumeration fails, just return the default address */ 
Note: See TracChangeset for help on using the changeset viewer.