Changeset 3121


Ignore:
Timestamp:
Mar 26, 2010 5:44:04 AM (10 years ago)
Author:
bennylp
Message:

Ticket #1046: Zeroconf/link-local/ActiveSync IPv4 adress 169.254.x.x may be used on Windows Mobile devices (thanks Jan Boquist for the info)

  • add treatment for special IPv4/IPv6 addresses: loopback address and link-local address
  • with this treatment, link-local address will only be used if there is no other non-loopback/non-link-local IP addresses, and loopback address will only be used if there's absolutely no other IP address
File:
1 edited

Legend:

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

    r3107 r3121  
    691691} 
    692692 
    693 static pj_bool_t is_usable_ip(const pj_sockaddr *addr) 
    694 { 
    695     if (addr->addr.sa_family==PJ_AF_INET) { 
    696         /* Only consider if the address is not 127.0.0.0/8 or 0.0.0.0/8. 
    697          * The 0.0.0.0/8 is a special IP class that doesn't seem to be 
    698          * practically useful for our purpose. 
    699          */ 
    700         if ((pj_ntohl(addr->ipv4.sin_addr.s_addr)>>24)==127) 
    701             return PJ_FALSE; 
    702         if ((pj_ntohl(addr->ipv4.sin_addr.s_addr)>>24)==0) 
    703             return PJ_FALSE; 
    704  
    705         return PJ_TRUE; 
    706  
    707     } else if (addr->addr.sa_family==PJ_AF_INET6) { 
    708         pj_sockaddr ipv6_loop; 
    709         const pj_str_t loop = { "::1", 3}; 
    710         pj_status_t status; 
    711  
    712         status = pj_sockaddr_set_str_addr(PJ_AF_INET6, &ipv6_loop, &loop); 
    713         if (status != PJ_SUCCESS) 
    714             return PJ_TRUE; 
    715  
    716         if (pj_memcmp(&addr->ipv6.sin6_addr, &ipv6_loop.ipv6.sin6_addr, 16)==0) 
    717             return PJ_FALSE; 
    718  
    719         return PJ_TRUE; 
    720     } else { 
    721         return PJ_TRUE; 
    722     } 
    723 } 
    724  
    725693/* Resolve the IP address of local machine */ 
    726694PJ_DEF(pj_status_t) pj_gethostip(int af, pj_sockaddr *addr) 
     
    729697    enum { 
    730698        CAND_CNT = 8, 
     699 
     700        /* Weighting to be applied to found addresses */ 
    731701        WEIGHT_HOSTNAME = 1,    /* hostname IP is not always valid! */ 
    732702        WEIGHT_DEF_ROUTE = 2, 
    733         WEIGHT_INTERFACE = 1 
     703        WEIGHT_INTERFACE = 1, 
     704        WEIGHT_LOOPBACK = -4, 
     705        WEIGHT_LINK_LOCAL = -3, 
     706        WEIGHT_DISABLED = -50, 
     707 
     708        MIN_WEIGHT = WEIGHT_DISABLED+1  /* minimum weight to use */ 
    734709    }; 
    735710    /* candidates: */ 
    736711    pj_sockaddr cand_addr[CAND_CNT]; 
    737     unsigned    cand_weight[CAND_CNT]; 
     712    int         cand_weight[CAND_CNT]; 
    738713    int         selected_cand; 
    739714    char        strip[PJ_INET6_ADDRSTRLEN+10]; 
     715    /* Special IPv4 addresses. */ 
     716    struct spec_ipv4_t 
     717    { 
     718        pj_uint32_t addr; 
     719        pj_uint32_t mask; 
     720        int         weight; 
     721    } spec_ipv4[] = 
     722    { 
     723        /* 127.0.0.0/8, loopback addr will be used if there is no other 
     724         * addresses. 
     725         */ 
     726        { 0x7f000000, 0xFF000000, WEIGHT_LOOPBACK }, 
     727 
     728        /* 0.0.0.0/8, special IP that doesn't seem to be practically useful */ 
     729        { 0x00000000, 0xFF000000, WEIGHT_DISABLED }, 
     730 
     731        /* 169.254.0.0/16, a zeroconf/link-local address, which has higher 
     732         * priority than loopback and will be used if there is no other 
     733         * valid addresses. 
     734         */ 
     735        { 0xa9fe0000, 0xFFFF0000, WEIGHT_LINK_LOCAL } 
     736    }; 
     737    /* Special IPv6 addresses */ 
     738    struct spec_ipv6_t 
     739    { 
     740        pj_uint8_t addr[16]; 
     741        pj_uint8_t mask[16]; 
     742        int        weight; 
     743    } spec_ipv6[] = 
     744    { 
     745        /* Loopback address, ::1/128 */ 
     746        { {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, 
     747          {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 
     748           0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}, 
     749          WEIGHT_LOOPBACK 
     750        }, 
     751 
     752        /* Link local, fe80::/10 */ 
     753        { {0xfe,0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 
     754          {0xff,0xc0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 
     755          WEIGHT_LINK_LOCAL 
     756        }, 
     757 
     758        /* Disabled, ::/128 */ 
     759        { {0x0,0x0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 
     760        { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 
     761          0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}, 
     762          WEIGHT_DISABLED 
     763        } 
     764    }; 
    740765    pj_addrinfo ai; 
    741766    pj_status_t status; 
     
    848873    } 
    849874 
     875    /* Apply weight adjustment for special IPv4/IPv6 addresses 
     876     * See http://trac.pjsip.org/repos/ticket/1046 
     877     */ 
     878    if (af == PJ_AF_INET) { 
     879        for (i=0; i<cand_cnt; ++i) { 
     880            unsigned j; 
     881            for (j=0; j<PJ_ARRAY_SIZE(spec_ipv4); ++j) { 
     882                    pj_uint32_t a = pj_ntohl(cand_addr[i].ipv4.sin_addr.s_addr); 
     883                    pj_uint32_t pa = spec_ipv4[j].addr; 
     884                    pj_uint32_t pm = spec_ipv4[j].mask; 
     885 
     886                    if ((a & pm) == pa) { 
     887                        cand_weight[i] += spec_ipv4[j].weight; 
     888                        break; 
     889                    } 
     890            } 
     891        } 
     892    } else if (af == PJ_AF_INET6) { 
     893        for (i=0; i<PJ_ARRAY_SIZE(spec_ipv6); ++i) { 
     894                unsigned j; 
     895                for (j=0; j<cand_cnt; ++j) { 
     896                    pj_uint8_t *a = cand_addr[j].ipv6.sin6_addr.s6_addr; 
     897                    pj_uint8_t am[16]; 
     898                    pj_uint8_t *pa = spec_ipv6[i].addr; 
     899                    pj_uint8_t *pm = spec_ipv6[i].mask; 
     900                    unsigned k; 
     901 
     902                    for (k=0; k<16; ++k) { 
     903                        am[k] = (a[k] & pm[k]) & 0xFF; 
     904                    } 
     905 
     906                    if (pj_memcmp(am, pa, 16)==0) { 
     907                        cand_weight[j] += spec_ipv6[i].weight; 
     908                    } 
     909                } 
     910        } 
     911    } else { 
     912        return PJ_EAFNOTSUP; 
     913    } 
     914 
    850915    /* Enumerate candidates to get the best IP address to choose */ 
    851916    selected_cand = -1; 
     
    855920                cand_weight[i])); 
    856921 
    857         if (!is_usable_ip(&cand_addr[i])) { 
     922        if (cand_weight[i] < MIN_WEIGHT) { 
    858923            continue; 
    859924        } 
Note: See TracChangeset for help on using the changeset viewer.