Changeset 5349


Ignore:
Timestamp:
Jun 20, 2016 10:10:42 AM (8 years ago)
Author:
nanang
Message:

Close #1927: IPv6 support in DNS SRV:

  • support DNS A and AAAA resolution for each target in DNS SRV record
  • support fallback to DNS A and DNS AAAA resolution when DNS SRV record is not available
  • support IPv6 nameservers.
Location:
pjproject/trunk
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjlib-util/include/pjlib-util/resolver.h

    r3553 r5349  
    224224 
    225225} pj_dns_a_record; 
     226 
     227 
     228/** 
     229 * This structure represents DNS address record, i.e: DNS A and DNS AAAA 
     230 * records, as the result of parsing DNS response packet using 
     231 * #pj_dns_parse_addr_response(). 
     232 */ 
     233typedef struct pj_dns_addr_record 
     234{ 
     235    /** The target name being queried.   */ 
     236    pj_str_t            name; 
     237 
     238    /** If target name corresponds to a CNAME entry, the alias contains 
     239     *  the value of the CNAME entry, otherwise it will be empty. 
     240     */ 
     241    pj_str_t            alias; 
     242 
     243    /** Number of IP addresses. */ 
     244    unsigned            addr_count; 
     245 
     246    /** IP addresses of the host found in the response */ 
     247    struct { 
     248 
     249        /** IP address family */ 
     250        int             af; 
     251         
     252        /** IP address */ 
     253        union { 
     254            /** IPv4 address */ 
     255            pj_in_addr  v4; 
     256 
     257            /** IPv6 address */ 
     258            pj_in6_addr v6; 
     259        } ip; 
     260 
     261    } addr[PJ_DNS_MAX_IP_IN_A_REC]; 
     262 
     263    /** Internal buffer for hostname and alias. */ 
     264    char                buf_[128]; 
     265 
     266} pj_dns_addr_record; 
    226267 
    227268 
     
    409450 
    410451/** 
     452 * A utility function to parse a DNS response containing AAAA records into  
     453 * DNS AAAA record. 
     454 * 
     455 * @param pkt       The DNS response packet. 
     456 * @param rec       The structure to be initialized with the parsed 
     457 *                  DNS AAAA record from the packet. 
     458 * 
     459 * @return          PJ_SUCCESS if response can be parsed successfully. 
     460 */ 
     461PJ_DECL(pj_status_t) pj_dns_parse_addr_response( 
     462                                            const pj_dns_parsed_packet *pkt, 
     463                                            pj_dns_addr_record *rec); 
     464 
     465 
     466/** 
    411467 * Put the specified DNS packet into DNS cache. This function is mainly used 
    412468 * for testing the resolver, however it can also be used to inject entries 
  • pjproject/trunk/pjlib-util/include/pjlib-util/srv_resolver.h

    r3553 r5349  
    8585     * resolution when the SRV resolution fails. This option may 
    8686     * be specified together with PJ_DNS_SRV_FALLBACK_AAAA to 
    87      * make the resolver fallback to AAAA if SRV resolution fails, 
    88      * and then to DNS A resolution if the AAAA resolution fails. 
     87     * make the resolver fallback to both DNS A and DNS AAAA 
     88     * resolutions if SRV resolution fails. 
    8989     */ 
    9090    PJ_DNS_SRV_FALLBACK_A       = 1, 
     
    9393     * Specify if the resolver should fallback with DNS AAAA 
    9494     * resolution when the SRV resolution fails. This option may 
    95      * be specified together with PJ_DNS_SRV_FALLBACK_A to 
    96      * make the resolver fallback to AAAA if SRV resolution fails, 
    97      * and then to DNS A resolution if the AAAA resolution fails. 
     95     * be specified together with PJ_DNS_SRV_FALLBACK_AAAA to 
     96     * make the resolver fallback to both DNS A and DNS AAAA 
     97     * resolutions if SRV resolution fails. 
    9898     */ 
    9999    PJ_DNS_SRV_FALLBACK_AAAA    = 2, 
     
    101101    /** 
    102102     * Specify if the resolver should try to resolve with DNS AAAA 
    103      * resolution first of each targets in the DNS SRV record. If 
    104      * this option is not specified, the SRV resolver will query 
    105      * the DNS A record for the target instead. 
    106      */ 
    107     PJ_DNS_SRV_RESOLVE_AAAA     = 4 
     103     * resolution of each targets in the DNS SRV record. If this 
     104     * option is not specified, the SRV resolver will query the 
     105     * DNS A record for the target instead. 
     106     */ 
     107    PJ_DNS_SRV_RESOLVE_AAAA     = 4, 
     108 
     109    /** 
     110     * Specify if the resolver should try to resolve with DNS AAAA 
     111     * resolution only (i.e: without DNS A resolution) for each targets 
     112     * in the DNS SRV record. 
     113     */ 
     114    PJ_DNS_SRV_RESOLVE_AAAA_ONLY = 8 
    108115 
    109116} pj_dns_srv_option; 
     
    132139 
    133140        /** The host address. */ 
    134         pj_dns_a_record         server; 
     141        pj_dns_addr_record      server; 
    135142 
    136143    } entry[PJ_DNS_SRV_MAX_ADDR]; 
  • pjproject/trunk/pjlib-util/src/pjlib-util-test/resolver_test.c

    r4537 r5349  
    192192        size -= 6; 
    193193 
     194    } else if (rr->type == PJ_DNS_TYPE_AAAA) { 
     195 
     196        if (size < 18) 
     197            return -1; 
     198 
     199        /* RDLEN is 16 */ 
     200        write16(p, 16); 
     201 
     202        /* Address */ 
     203        pj_memcpy(p+2, &rr->rdata.aaaa.ip_addr, 16); 
     204 
     205        p += 18; 
     206        size -= 18; 
     207 
    194208    } else if (rr->type == PJ_DNS_TYPE_CNAME || 
    195209               rr->type == PJ_DNS_TYPE_NS || 
     
    331345        pj_fd_set_t rset; 
    332346        pj_time_val timeout = {0, 500}; 
    333         pj_sockaddr_in src_addr; 
     347        pj_sockaddr src_addr; 
    334348        pj_dns_parsed_packet *req; 
    335349        char pkt[1024]; 
     
    406420static void destroy(void); 
    407421 
    408 static int init(void) 
     422static int init(pj_bool_t use_ipv6) 
    409423{ 
    410424    pj_status_t status; 
     
    413427    int i; 
    414428 
    415     nameservers[0] = pj_str("127.0.0.1"); 
     429    if (use_ipv6) { 
     430        nameservers[0] = pj_str("::1"); 
     431        nameservers[1] = pj_str("::1"); 
     432    } else { 
     433        nameservers[0] = pj_str("127.0.0.1"); 
     434        nameservers[1] = pj_str("127.0.0.1"); 
     435    } 
    416436    ports[0] = 5553; 
    417     nameservers[1] = pj_str("127.0.0.1"); 
    418437    ports[1] = 5554; 
    419438 
     
    426445    pj_assert(status == PJ_SUCCESS); 
    427446 
     447    thread_quit = PJ_FALSE; 
     448 
    428449    for (i=0; i<2; ++i) { 
    429         pj_sockaddr_in addr; 
    430  
    431         status = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &g_server[i].sock); 
     450        pj_sockaddr addr; 
     451 
     452        status = pj_sock_socket((use_ipv6? pj_AF_INET6() : pj_AF_INET()), 
     453                                pj_SOCK_DGRAM(), 0, &g_server[i].sock); 
    432454        if (status != PJ_SUCCESS) 
    433455            return -10; 
    434456 
    435         pj_sockaddr_in_init(&addr, NULL, (pj_uint16_t)g_server[i].port); 
     457        pj_sockaddr_init((use_ipv6? pj_AF_INET6() : pj_AF_INET()), 
     458                         &addr, NULL, (pj_uint16_t)g_server[i].port); 
    436459 
    437460        status = pj_sock_bind(g_server[i].sock, &addr, sizeof(addr)); 
     
    687710 
    688711    rc = pj_dns_parse_a_response(&pkt, &rec); 
     712    pj_assert(rc == PJLIB_UTIL_EDNSNOANSWERREC); 
     713 
     714    return 0; 
     715} 
     716 
     717 
     718//////////////////////////////////////////////////////////////////////////// 
     719/* DNS A/AAAA parser tests */ 
     720static int addr_parser_test(void) 
     721{ 
     722    pj_dns_parsed_packet pkt; 
     723    pj_dns_addr_record rec; 
     724    pj_status_t rc; 
     725 
     726    PJ_LOG(3,(THIS_FILE, "  DNS A/AAAA record parser tests")); 
     727 
     728    pkt.q = PJ_POOL_ZALLOC_T(pool, pj_dns_parsed_query); 
     729    pkt.ans = (pj_dns_parsed_rr*) 
     730              pj_pool_calloc(pool, 32, sizeof(pj_dns_parsed_rr)); 
     731 
     732    /* Simple answer with direct A record, but with addition of 
     733     * a CNAME and another A to confuse the parser. 
     734     */ 
     735    PJ_LOG(3,(THIS_FILE, "    A RR with duplicate CNAME/A")); 
     736    pkt.hdr.flags = 0; 
     737    pkt.hdr.qdcount = 1; 
     738    pkt.q[0].type = PJ_DNS_TYPE_A; 
     739    pkt.q[0].dnsclass = 1; 
     740    pkt.q[0].name = pj_str("ahost"); 
     741    pkt.hdr.anscount = 4; 
     742 
     743    /* This is the RR corresponding to the query */ 
     744    pkt.ans[0].name = pj_str("ahost"); 
     745    pkt.ans[0].type = PJ_DNS_TYPE_A; 
     746    pkt.ans[0].dnsclass = 1; 
     747    pkt.ans[0].ttl = 1; 
     748    pkt.ans[0].rdata.a.ip_addr.s_addr = 0x01020304; 
     749 
     750    /* CNAME to confuse the parser */ 
     751    pkt.ans[1].name = pj_str("ahost"); 
     752    pkt.ans[1].type = PJ_DNS_TYPE_CNAME; 
     753    pkt.ans[1].dnsclass = 1; 
     754    pkt.ans[1].ttl = 1; 
     755    pkt.ans[1].rdata.cname.name = pj_str("bhost"); 
     756 
     757    /* DNS A RR to confuse the parser */ 
     758    pkt.ans[2].name = pj_str("bhost"); 
     759    pkt.ans[2].type = PJ_DNS_TYPE_A; 
     760    pkt.ans[2].dnsclass = 1; 
     761    pkt.ans[2].ttl = 1; 
     762    pkt.ans[2].rdata.a.ip_addr.s_addr = 0x0203; 
     763 
     764    /* Additional RR corresponding to the query, DNS AAAA RR */ 
     765    pkt.ans[3].name = pj_str("ahost"); 
     766    pkt.ans[3].type = PJ_DNS_TYPE_AAAA; 
     767    pkt.ans[3].dnsclass = 1; 
     768    pkt.ans[3].ttl = 1; 
     769    pkt.ans[3].rdata.aaaa.ip_addr.u6_addr32[0] = 0x01020304; 
     770 
     771 
     772    rc = pj_dns_parse_addr_response(&pkt, &rec); 
     773    pj_assert(rc == PJ_SUCCESS); 
     774    pj_assert(pj_strcmp2(&rec.name, "ahost")==0); 
     775    pj_assert(rec.alias.slen == 0); 
     776    pj_assert(rec.addr_count == 2); 
     777    pj_assert(rec.addr[0].af==pj_AF_INET() && rec.addr[0].ip.v4.s_addr == 0x01020304); 
     778    pj_assert(rec.addr[1].af==pj_AF_INET6() && rec.addr[1].ip.v6.u6_addr32[0] == 0x01020304); 
     779 
     780    /* Answer with the target corresponds to a CNAME entry, but not 
     781     * as the first record, and with additions of some CNAME and A 
     782     * entries to confuse the parser. 
     783     */ 
     784    PJ_LOG(3,(THIS_FILE, "    CNAME RR with duplicate CNAME/A")); 
     785    pkt.hdr.flags = 0; 
     786    pkt.hdr.qdcount = 1; 
     787    pkt.q[0].type = PJ_DNS_TYPE_A; 
     788    pkt.q[0].dnsclass = 1; 
     789    pkt.q[0].name = pj_str("ahost"); 
     790    pkt.hdr.anscount = 4; 
     791 
     792    /* This is the DNS A record for the alias */ 
     793    pkt.ans[0].name = pj_str("ahostalias"); 
     794    pkt.ans[0].type = PJ_DNS_TYPE_A; 
     795    pkt.ans[0].dnsclass = 1; 
     796    pkt.ans[0].ttl = 1; 
     797    pkt.ans[0].rdata.a.ip_addr.s_addr = 0x02020202; 
     798 
     799    /* CNAME entry corresponding to the query */ 
     800    pkt.ans[1].name = pj_str("ahost"); 
     801    pkt.ans[1].type = PJ_DNS_TYPE_CNAME; 
     802    pkt.ans[1].dnsclass = 1; 
     803    pkt.ans[1].ttl = 1; 
     804    pkt.ans[1].rdata.cname.name = pj_str("ahostalias"); 
     805 
     806    /* Another CNAME to confuse the parser */ 
     807    pkt.ans[2].name = pj_str("ahost"); 
     808    pkt.ans[2].type = PJ_DNS_TYPE_CNAME; 
     809    pkt.ans[2].dnsclass = 1; 
     810    pkt.ans[2].ttl = 1; 
     811    pkt.ans[2].rdata.cname.name = pj_str("ahostalias2"); 
     812 
     813    /* Another DNS A to confuse the parser */ 
     814    pkt.ans[3].name = pj_str("ahostalias2"); 
     815    pkt.ans[3].type = PJ_DNS_TYPE_A; 
     816    pkt.ans[3].dnsclass = 1; 
     817    pkt.ans[3].ttl = 1; 
     818    pkt.ans[3].rdata.a.ip_addr.s_addr = 0x03030303; 
     819 
     820    rc = pj_dns_parse_addr_response(&pkt, &rec); 
     821    pj_assert(rc == PJ_SUCCESS); 
     822    pj_assert(pj_strcmp2(&rec.name, "ahost")==0); 
     823    pj_assert(pj_strcmp2(&rec.alias, "ahostalias")==0); 
     824    pj_assert(rec.addr_count == 1); 
     825    pj_assert(rec.addr[0].ip.v4.s_addr == 0x02020202); 
     826 
     827    /* 
     828     * No query section. 
     829     */ 
     830    PJ_LOG(3,(THIS_FILE, "    No query section")); 
     831    pkt.hdr.qdcount = 0; 
     832    pkt.hdr.anscount = 0; 
     833 
     834    rc = pj_dns_parse_addr_response(&pkt, &rec); 
     835    pj_assert(rc == PJLIB_UTIL_EDNSINANSWER); 
     836 
     837    /* 
     838     * No answer section. 
     839     */ 
     840    PJ_LOG(3,(THIS_FILE, "    No answer section")); 
     841    pkt.hdr.flags = 0; 
     842    pkt.hdr.qdcount = 1; 
     843    pkt.q[0].type = PJ_DNS_TYPE_A; 
     844    pkt.q[0].dnsclass = 1; 
     845    pkt.q[0].name = pj_str("ahost"); 
     846    pkt.hdr.anscount = 0; 
     847 
     848    rc = pj_dns_parse_addr_response(&pkt, &rec); 
     849    pj_assert(rc == PJLIB_UTIL_EDNSNOANSWERREC); 
     850 
     851    /* 
     852     * Answer doesn't match query. 
     853     */ 
     854    PJ_LOG(3,(THIS_FILE, "    Answer doesn't match query")); 
     855    pkt.hdr.flags = 0; 
     856    pkt.hdr.qdcount = 1; 
     857    pkt.q[0].type = PJ_DNS_TYPE_A; 
     858    pkt.q[0].dnsclass = 1; 
     859    pkt.q[0].name = pj_str("ahost"); 
     860    pkt.hdr.anscount = 1; 
     861 
     862    /* An answer that doesn't match the query */ 
     863    pkt.ans[0].name = pj_str("ahostalias"); 
     864    pkt.ans[0].type = PJ_DNS_TYPE_A; 
     865    pkt.ans[0].dnsclass = 1; 
     866    pkt.ans[0].ttl = 1; 
     867    pkt.ans[0].rdata.a.ip_addr.s_addr = 0x02020202; 
     868 
     869    rc = pj_dns_parse_addr_response(&pkt, &rec); 
     870    pj_assert(rc == PJLIB_UTIL_EDNSNOANSWERREC); 
     871 
     872 
     873    /* 
     874     * DNS CNAME that doesn't have corresponding DNS A. 
     875     */ 
     876    PJ_LOG(3,(THIS_FILE, "    CNAME with no matching DNS A RR (1)")); 
     877    pkt.hdr.flags = 0; 
     878    pkt.hdr.qdcount = 1; 
     879    pkt.q[0].type = PJ_DNS_TYPE_A; 
     880    pkt.q[0].dnsclass = 1; 
     881    pkt.q[0].name = pj_str("ahost"); 
     882    pkt.hdr.anscount = 1; 
     883 
     884    /* The CNAME */ 
     885    pkt.ans[0].name = pj_str("ahost"); 
     886    pkt.ans[0].type = PJ_DNS_TYPE_CNAME; 
     887    pkt.ans[0].dnsclass = 1; 
     888    pkt.ans[0].ttl = 1; 
     889    pkt.ans[0].rdata.cname.name = pj_str("ahostalias"); 
     890 
     891    rc = pj_dns_parse_addr_response(&pkt, &rec); 
     892    pj_assert(rc == PJLIB_UTIL_EDNSNOANSWERREC); 
     893 
     894 
     895    /* 
     896     * DNS CNAME that doesn't have corresponding DNS A. 
     897     */ 
     898    PJ_LOG(3,(THIS_FILE, "    CNAME with no matching DNS A RR (2)")); 
     899    pkt.hdr.flags = 0; 
     900    pkt.hdr.qdcount = 1; 
     901    pkt.q[0].type = PJ_DNS_TYPE_A; 
     902    pkt.q[0].dnsclass = 1; 
     903    pkt.q[0].name = pj_str("ahost"); 
     904    pkt.hdr.anscount = 2; 
     905 
     906    /* The CNAME */ 
     907    pkt.ans[0].name = pj_str("ahost"); 
     908    pkt.ans[0].type = PJ_DNS_TYPE_CNAME; 
     909    pkt.ans[0].dnsclass = 1; 
     910    pkt.ans[0].ttl = 1; 
     911    pkt.ans[0].rdata.cname.name = pj_str("ahostalias"); 
     912 
     913    /* DNS A record, but the name doesn't match */ 
     914    pkt.ans[1].name = pj_str("ahost"); 
     915    pkt.ans[1].type = PJ_DNS_TYPE_A; 
     916    pkt.ans[1].dnsclass = 1; 
     917    pkt.ans[1].ttl = 1; 
     918    pkt.ans[1].rdata.a.ip_addr.s_addr = 0x01020304; 
     919 
     920    rc = pj_dns_parse_addr_response(&pkt, &rec); 
    689921    pj_assert(rc == PJLIB_UTIL_EDNSNOANSWERREC); 
    690922 
     
    10061238        res->ans[1].name = pj_str(alias); 
    10071239        res->ans[1].rdata.a.ip_addr.s_addr = IP_ADDR1; 
     1240 
     1241    } else if (pkt->q[0].type == PJ_DNS_TYPE_AAAA) { 
     1242        char *alias = "sipalias.somedomain.com"; 
     1243 
     1244        pj_assert(pj_strcmp2(&res->q[0].name, target)==0); 
     1245 
     1246        res->hdr.anscount = 2; 
     1247        res->ans[0].type = PJ_DNS_TYPE_CNAME; 
     1248        res->ans[0].dnsclass = 1; 
     1249        res->ans[0].ttl = 1000; /* resolver should select minimum TTL */ 
     1250        res->ans[0].name = res->q[0].name; 
     1251        res->ans[0].rdata.cname.name = pj_str(alias); 
     1252 
     1253        res->ans[1].type = PJ_DNS_TYPE_AAAA; 
     1254        res->ans[1].dnsclass = 1; 
     1255        res->ans[1].ttl = 1; 
     1256        res->ans[1].name = pj_str(alias); 
     1257        res->ans[1].rdata.aaaa.ip_addr.u6_addr32[0] = IP_ADDR1; 
     1258        res->ans[1].rdata.aaaa.ip_addr.u6_addr32[1] = IP_ADDR1; 
     1259        res->ans[1].rdata.aaaa.ip_addr.u6_addr32[2] = IP_ADDR1; 
     1260        res->ans[1].rdata.aaaa.ip_addr.u6_addr32[3] = IP_ADDR1; 
    10081261    } 
    10091262 
     
    10271280    PJ_ASSERT_ON_FAIL(pj_strcmp2(&rec->entry[0].server.alias, "sipalias.somedomain.com")==0, 
    10281281                      return); 
    1029     PJ_ASSERT_ON_FAIL(rec->entry[0].server.addr[0].s_addr == IP_ADDR1, return); 
     1282 
     1283    /* IPv4 only */ 
     1284    PJ_ASSERT_ON_FAIL(rec->entry[0].server.addr_count == 1, return); 
     1285    PJ_ASSERT_ON_FAIL(rec->entry[0].server.addr[0].ip.v4.s_addr == IP_ADDR1, return); 
    10301286    PJ_ASSERT_ON_FAIL(rec->entry[0].port == PORT1, return); 
    10311287 
    10321288     
    10331289} 
     1290 
    10341291 
    10351292static void srv_cb_1b(void *user_data, 
     
    10451302    PJ_ASSERT_ON_FAIL(rec->count == 0, return); 
    10461303} 
     1304 
     1305 
     1306static void srv_cb_1c(void *user_data, 
     1307                      pj_status_t status, 
     1308                      const pj_dns_srv_record *rec) 
     1309{ 
     1310    PJ_UNUSED_ARG(user_data); 
     1311 
     1312    pj_sem_post(sem); 
     1313 
     1314    PJ_ASSERT_ON_FAIL(status == PJ_SUCCESS, return); 
     1315    PJ_ASSERT_ON_FAIL(rec->count == 1, return); 
     1316    PJ_ASSERT_ON_FAIL(rec->entry[0].priority == 1, return); 
     1317    PJ_ASSERT_ON_FAIL(rec->entry[0].weight == 2, return); 
     1318 
     1319    PJ_ASSERT_ON_FAIL(pj_strcmp2(&rec->entry[0].server.name, "sip.somedomain.com")==0, 
     1320                      return); 
     1321    PJ_ASSERT_ON_FAIL(pj_strcmp2(&rec->entry[0].server.alias, "sipalias.somedomain.com")==0, 
     1322                      return); 
     1323    PJ_ASSERT_ON_FAIL(rec->entry[0].port == PORT1, return); 
     1324 
     1325    /* IPv4 and IPv6 */ 
     1326    PJ_ASSERT_ON_FAIL(rec->entry[0].server.addr_count == 2, return); 
     1327    PJ_ASSERT_ON_FAIL(rec->entry[0].server.addr[0].af == pj_AF_INET() && 
     1328                      rec->entry[0].server.addr[0].ip.v4.s_addr == IP_ADDR1, return); 
     1329    PJ_ASSERT_ON_FAIL(rec->entry[0].server.addr[1].af == pj_AF_INET6() && 
     1330                      rec->entry[0].server.addr[1].ip.v6.u6_addr32[0] == IP_ADDR1, return); 
     1331} 
     1332 
     1333 
     1334static void srv_cb_1d(void *user_data, 
     1335                      pj_status_t status, 
     1336                      const pj_dns_srv_record *rec) 
     1337{ 
     1338    PJ_UNUSED_ARG(user_data); 
     1339 
     1340    pj_sem_post(sem); 
     1341 
     1342    PJ_ASSERT_ON_FAIL(status == PJ_SUCCESS, return); 
     1343    PJ_ASSERT_ON_FAIL(rec->count == 1, return); 
     1344    PJ_ASSERT_ON_FAIL(rec->entry[0].priority == 1, return); 
     1345    PJ_ASSERT_ON_FAIL(rec->entry[0].weight == 2, return); 
     1346 
     1347    PJ_ASSERT_ON_FAIL(pj_strcmp2(&rec->entry[0].server.name, "sip.somedomain.com")==0, 
     1348                      return); 
     1349    PJ_ASSERT_ON_FAIL(pj_strcmp2(&rec->entry[0].server.alias, "sipalias.somedomain.com")==0, 
     1350                      return); 
     1351    PJ_ASSERT_ON_FAIL(rec->entry[0].port == PORT1, return); 
     1352 
     1353    /* IPv6 only */ 
     1354    PJ_ASSERT_ON_FAIL(rec->entry[0].server.addr_count == 1, return); 
     1355    PJ_ASSERT_ON_FAIL(rec->entry[0].server.addr[0].af == pj_AF_INET6() && 
     1356                      rec->entry[0].server.addr[0].ip.v6.u6_addr32[0] == IP_ADDR1, return); 
     1357} 
     1358 
    10471359 
    10481360static int srv_resolver_test(void) 
     
    10791391                    ((set.qretr_count + 2) * set.qretr_delay)); 
    10801392 
     1393 
     1394    /* DNS SRV option PJ_DNS_SRV_RESOLVE_AAAA */ 
     1395    PJ_LOG(3,(THIS_FILE, "  srv_resolve(): option PJ_DNS_SRV_RESOLVE_AAAA")); 
     1396 
     1397    g_server[0].action = ACTION_CB; 
     1398    g_server[0].action_cb = &action1_1; 
     1399    g_server[1].action = ACTION_CB; 
     1400    g_server[1].action_cb = &action1_1; 
     1401 
     1402    g_server[0].pkt_count = 0; 
     1403    g_server[1].pkt_count = 0; 
     1404 
     1405    status = pj_dns_srv_resolve(&domain, &res_name, 5061, pool, resolver, 
     1406                                PJ_DNS_SRV_RESOLVE_AAAA, 
     1407                                NULL, &srv_cb_1c, NULL); 
     1408    pj_assert(status == PJ_SUCCESS); 
     1409 
     1410    pj_sem_wait(sem); 
     1411 
     1412    pj_thread_sleep(1000); 
     1413 
     1414    /* DNS SRV option PJ_DNS_SRV_RESOLVE_AAAA_ONLY */ 
     1415    PJ_LOG(3,(THIS_FILE, "  srv_resolve(): option PJ_DNS_SRV_RESOLVE_AAAA_ONLY")); 
     1416 
     1417    g_server[0].action = ACTION_CB; 
     1418    g_server[0].action_cb = &action1_1; 
     1419    g_server[1].action = ACTION_CB; 
     1420    g_server[1].action_cb = &action1_1; 
     1421 
     1422    g_server[0].pkt_count = 0; 
     1423    g_server[1].pkt_count = 0; 
     1424 
     1425    status = pj_dns_srv_resolve(&domain, &res_name, 5061, pool, resolver, 
     1426                                PJ_DNS_SRV_RESOLVE_AAAA_ONLY, 
     1427                                NULL, &srv_cb_1d, NULL); 
     1428    pj_assert(status == PJ_SUCCESS); 
     1429 
     1430    pj_sem_wait(sem); 
     1431 
     1432    pj_thread_sleep(1000); 
     1433 
     1434 
    10811435    /* Successful scenario */ 
    10821436    PJ_LOG(3,(THIS_FILE, "  srv_resolve(): parallel queries")); 
     
    11031457    PJ_LOG(3,(THIS_FILE, "  srv_resolve(): cache expires scenario")); 
    11041458 
    1105  
    11061459    pj_thread_sleep(1000); 
    11071460 
     
    11141467 
    11151468    pj_sem_wait(sem); 
     1469 
    11161470 
    11171471    return 0; 
     
    11721526        res->ans[1].ttl = 1; 
    11731527        res->ans[1].rdata.a.ip_addr.s_addr = IP_ADDR2; 
     1528 
     1529    } else if (pkt->q[0].type == PJ_DNS_TYPE_AAAA) { 
     1530        char *alias = "sipalias01." TARGET; 
     1531 
     1532        pj_assert(pj_strcmp2(&res->q[0].name, TARGET)==0); 
     1533 
     1534        res->hdr.anscount = 2; 
     1535        res->ans[0].type = PJ_DNS_TYPE_CNAME; 
     1536        res->ans[0].dnsclass = 1; 
     1537        res->ans[0].name = res->q[0].name; 
     1538        res->ans[0].ttl = 1; 
     1539        res->ans[0].rdata.cname.name = pj_str(alias); 
     1540 
     1541        res->ans[1].type = PJ_DNS_TYPE_AAAA; 
     1542        res->ans[1].dnsclass = 1; 
     1543        res->ans[1].ttl = 1; 
     1544        res->ans[1].name = pj_str(alias); 
     1545        res->ans[1].rdata.aaaa.ip_addr.u6_addr32[0] = IP_ADDR2; 
     1546        res->ans[1].rdata.aaaa.ip_addr.u6_addr32[1] = IP_ADDR2; 
     1547        res->ans[1].rdata.aaaa.ip_addr.u6_addr32[2] = IP_ADDR2; 
     1548        res->ans[1].rdata.aaaa.ip_addr.u6_addr32[3] = IP_ADDR2; 
    11741549    } 
    11751550 
     
    11931568    PJ_ASSERT_ON_FAIL(pj_strcmp2(&rec->entry[0].server.alias, "sipalias01." TARGET)==0, 
    11941569                      return); 
    1195     PJ_ASSERT_ON_FAIL(rec->entry[0].server.addr[0].s_addr == IP_ADDR2, return); 
    11961570    PJ_ASSERT_ON_FAIL(rec->entry[0].port == PORT2, return); 
     1571 
     1572    /* IPv4 only */ 
     1573    PJ_ASSERT_ON_FAIL(rec->entry[0].server.addr_count == 1, return); 
     1574    PJ_ASSERT_ON_FAIL(rec->entry[0].server.addr[0].af == pj_AF_INET() && 
     1575                      rec->entry[0].server.addr[0].ip.v4.s_addr == IP_ADDR2, return); 
     1576} 
     1577 
     1578static void srv_cb_2a(void *user_data, 
     1579                      pj_status_t status, 
     1580                      const pj_dns_srv_record *rec) 
     1581{ 
     1582    PJ_UNUSED_ARG(user_data); 
     1583 
     1584    pj_sem_post(sem); 
     1585 
     1586    PJ_ASSERT_ON_FAIL(status == PJ_SUCCESS, return); 
     1587    PJ_ASSERT_ON_FAIL(rec->count == 1, return); 
     1588    PJ_ASSERT_ON_FAIL(rec->entry[0].priority == 0, return); 
     1589    PJ_ASSERT_ON_FAIL(rec->entry[0].weight == 0, return); 
     1590    PJ_ASSERT_ON_FAIL(pj_strcmp2(&rec->entry[0].server.name, TARGET)==0, 
     1591                      return); 
     1592    PJ_ASSERT_ON_FAIL(pj_strcmp2(&rec->entry[0].server.alias, "sipalias01." TARGET)==0, 
     1593                      return); 
     1594    PJ_ASSERT_ON_FAIL(rec->entry[0].port == PORT2, return); 
     1595 
     1596    /* IPv4 and IPv6 */ 
     1597    PJ_ASSERT_ON_FAIL(rec->entry[0].server.addr_count == 2, return); 
     1598    PJ_ASSERT_ON_FAIL(rec->entry[0].server.addr[0].af == pj_AF_INET() && 
     1599                      rec->entry[0].server.addr[0].ip.v4.s_addr == IP_ADDR2, return); 
     1600    PJ_ASSERT_ON_FAIL(rec->entry[0].server.addr[1].af == pj_AF_INET6() && 
     1601                      rec->entry[0].server.addr[1].ip.v6.u6_addr32[0] == IP_ADDR2, return); 
     1602} 
     1603 
     1604static void srv_cb_2b(void *user_data, 
     1605                      pj_status_t status, 
     1606                      const pj_dns_srv_record *rec) 
     1607{ 
     1608    PJ_UNUSED_ARG(user_data); 
     1609 
     1610    pj_sem_post(sem); 
     1611 
     1612    PJ_ASSERT_ON_FAIL(status == PJ_SUCCESS, return); 
     1613    PJ_ASSERT_ON_FAIL(rec->count == 1, return); 
     1614    PJ_ASSERT_ON_FAIL(rec->entry[0].priority == 0, return); 
     1615    PJ_ASSERT_ON_FAIL(rec->entry[0].weight == 0, return); 
     1616    PJ_ASSERT_ON_FAIL(pj_strcmp2(&rec->entry[0].server.name, TARGET)==0, 
     1617                      return); 
     1618    PJ_ASSERT_ON_FAIL(pj_strcmp2(&rec->entry[0].server.alias, "sipalias01." TARGET)==0, 
     1619                      return); 
     1620    PJ_ASSERT_ON_FAIL(rec->entry[0].port == PORT2, return); 
     1621 
     1622    /* IPv6 only */ 
     1623    PJ_ASSERT_ON_FAIL(rec->entry[0].server.addr_count == 1, return); 
     1624    PJ_ASSERT_ON_FAIL(rec->entry[0].server.addr[0].af == pj_AF_INET6() && 
     1625                      rec->entry[0].server.addr[0].ip.v6.u6_addr32[0] == IP_ADDR2, return); 
    11971626} 
    11981627 
     
    12031632    pj_str_t res_name = pj_str("_sip._udp."); 
    12041633 
     1634    /* Fallback test */ 
    12051635    PJ_LOG(3,(THIS_FILE, "  srv_resolve(): fallback test")); 
    12061636 
     
    12351665    pj_assert(g_server[0].pkt_count == 0); 
    12361666    pj_assert(g_server[1].pkt_count == 0); 
     1667 
     1668    /* Clear cache */ 
     1669    pj_thread_sleep(1000); 
     1670 
     1671    /* Fallback with PJ_DNS_SRV_FALLBACK_A and PJ_DNS_SRV_FALLBACK_AAAA */ 
     1672    PJ_LOG(3,(THIS_FILE, "  srv_resolve(): fallback to DNS A and AAAA")); 
     1673 
     1674    g_server[0].action = ACTION_CB; 
     1675    g_server[0].action_cb = &action2_1; 
     1676    g_server[1].action = ACTION_CB; 
     1677    g_server[1].action_cb = &action2_1; 
     1678 
     1679    status = pj_dns_srv_resolve(&domain, &res_name, PORT2, pool, resolver, 
     1680                                PJ_DNS_SRV_FALLBACK_A | PJ_DNS_SRV_FALLBACK_AAAA, 
     1681                                NULL, &srv_cb_2a, NULL); 
     1682    if (status != PJ_SUCCESS) { 
     1683        app_perror("   srv_resolve error", status); 
     1684        pj_assert(status == PJ_SUCCESS); 
     1685    } 
     1686 
     1687    pj_sem_wait(sem); 
     1688 
     1689    /* Clear cache */ 
     1690    pj_thread_sleep(1000); 
     1691 
     1692    /* Fallback with PJ_DNS_SRV_FALLBACK_AAAA only */ 
     1693    PJ_LOG(3,(THIS_FILE, "  srv_resolve(): fallback to DNS AAAA only")); 
     1694 
     1695    g_server[0].action = ACTION_CB; 
     1696    g_server[0].action_cb = &action2_1; 
     1697    g_server[1].action = ACTION_CB; 
     1698    g_server[1].action_cb = &action2_1; 
     1699 
     1700    status = pj_dns_srv_resolve(&domain, &res_name, PORT2, pool, resolver, 
     1701                                PJ_DNS_SRV_FALLBACK_AAAA, 
     1702                                NULL, &srv_cb_2b, NULL); 
     1703    if (status != PJ_SUCCESS) { 
     1704        app_perror("   srv_resolve error", status); 
     1705        pj_assert(status == PJ_SUCCESS); 
     1706    } 
     1707 
     1708    pj_sem_wait(sem); 
     1709 
     1710    /* Clear cache */ 
     1711    pj_thread_sleep(1000); 
    12371712 
    12381713    return 0; 
     
    13341809 
    13351810        for (j=0; j<PJ_DNS_MAX_IP_IN_A_REC; ++j) { 
    1336             pj_assert(rec->entry[i].server.addr[j].s_addr == IP_ADDR3+j); 
     1811            pj_assert(rec->entry[i].server.addr[j].ip.v4.s_addr == IP_ADDR3+j); 
    13371812        } 
    13381813    } 
     
    13751850    int rc; 
    13761851     
    1377     rc = init(); 
     1852    rc = init(PJ_FALSE); 
    13781853    if (rc != 0) 
    13791854        goto on_error; 
     
    13831858        goto on_error; 
    13841859 
     1860    rc = addr_parser_test(); 
     1861    if (rc != 0) 
     1862        goto on_error; 
     1863 
    13851864    rc = simple_test(); 
    13861865    if (rc != 0) 
     
    13961875 
    13971876    destroy(); 
     1877 
     1878 
     1879#if PJ_HAS_IPV6 
     1880    /* Similar tests using IPv6 socket and without parser tests */ 
     1881    PJ_LOG(3,(THIS_FILE, "  Re-run DNS resolution tests using IPv6 socket")); 
     1882 
     1883    rc = init(PJ_TRUE); 
     1884    if (rc != 0) 
     1885        goto on_error; 
     1886 
     1887    rc = simple_test(); 
     1888    if (rc != 0) 
     1889        goto on_error; 
     1890 
     1891    rc = dns_test(); 
     1892    if (rc != 0) 
     1893        goto on_error; 
     1894 
     1895    srv_resolver_test(); 
     1896    srv_resolver_fallback_test(); 
     1897    srv_resolver_many_test(); 
     1898 
     1899    destroy(); 
     1900#endif 
     1901 
    13981902    return 0; 
    13991903 
     
    14031907} 
    14041908 
    1405  
  • pjproject/trunk/pjlib-util/src/pjlib-util/resolver.c

    r5311 r5349  
    8080struct nameserver 
    8181{ 
    82     pj_sockaddr_in  addr;               /**< Server address.                */ 
     82    pj_sockaddr     addr;               /**< Server address.                */ 
    8383 
    8484    enum ns_state   state;              /**< Nameserver state.              */ 
     
    180180    pj_ioqueue_key_t    *udp_key;       /**< UDP socket ioqueue key.        */ 
    181181    unsigned char        udp_rx_pkt[UDPSZ];/**< UDP receive buffer.         */ 
    182     unsigned char        udp_tx_pkt[UDPSZ];/**< UDP receive buffer.         */ 
    183     pj_ssize_t           udp_len;       /**< Length of received packet.     */ 
     182    unsigned char        udp_tx_pkt[UDPSZ];/**< UDP transmit buffer.        */ 
    184183    pj_ioqueue_op_key_t  udp_op_rx_key; /**< UDP read operation key.        */ 
    185184    pj_ioqueue_op_key_t  udp_op_tx_key; /**< UDP write operation key.       */ 
    186     pj_sockaddr_in       udp_src_addr;  /**< Source address of packet       */ 
     185    pj_sockaddr          udp_src_addr;  /**< Source address of packet       */ 
    187186    int                  udp_addr_len;  /**< Source address length.         */ 
     187 
     188#if PJ_HAS_IPV6 
     189    /* IPv6 socket */ 
     190    pj_sock_t            udp6_sock;     /**< UDP socket.                    */ 
     191    pj_ioqueue_key_t    *udp6_key;      /**< UDP socket ioqueue key.        */ 
     192    unsigned char        udp6_rx_pkt[UDPSZ];/**< UDP receive buffer.        */ 
     193    //unsigned char      udp6_tx_pkt[UDPSZ];/**< UDP transmit buffer.       */ 
     194    pj_ioqueue_op_key_t  udp6_op_rx_key;/**< UDP read operation key.        */ 
     195    pj_ioqueue_op_key_t  udp6_op_tx_key;/**< UDP write operation key.       */ 
     196    pj_sockaddr          udp6_src_addr; /**< Source address of packet       */ 
     197    int                  udp6_addr_len; /**< Source address length.         */ 
     198#endif 
    188199 
    189200    /* Settings */ 
     
    238249        resv->udp_sock = PJ_INVALID_SOCKET; 
    239250    } 
     251 
     252#if PJ_HAS_IPV6 
     253    if (resv->udp6_key != NULL) { 
     254        pj_ioqueue_unregister(resv->udp6_key); 
     255        resv->udp6_key = NULL; 
     256        resv->udp6_sock = PJ_INVALID_SOCKET; 
     257    } else if (resv->udp6_sock != PJ_INVALID_SOCKET) { 
     258        pj_sock_close(resv->udp6_sock); 
     259        resv->udp6_sock = PJ_INVALID_SOCKET; 
     260    } 
     261#endif 
    240262} 
    241263 
     
    245267{ 
    246268    pj_ioqueue_callback socket_cb; 
     269    pj_sockaddr bound_addr; 
     270    pj_ssize_t rx_pkt_size; 
    247271    pj_status_t status; 
    248272 
     
    270294 
    271295    /* Start asynchronous read to the UDP socket */ 
    272     resv->udp_len = sizeof(resv->udp_rx_pkt); 
     296    rx_pkt_size = sizeof(resv->udp_rx_pkt); 
    273297    resv->udp_addr_len = sizeof(resv->udp_src_addr); 
    274298    status = pj_ioqueue_recvfrom(resv->udp_key, &resv->udp_op_rx_key, 
    275                                  resv->udp_rx_pkt, &resv->udp_len, 
     299                                 resv->udp_rx_pkt, &rx_pkt_size, 
    276300                                 PJ_IOQUEUE_ALWAYS_ASYNC, 
    277301                                 &resv->udp_src_addr, &resv->udp_addr_len); 
    278302    if (status != PJ_EPENDING) 
    279303        return status; 
     304 
     305 
     306#if PJ_HAS_IPV6 
     307    /* Also setup IPv6 socket */ 
     308 
     309    /* Create the UDP socket */ 
     310    status = pj_sock_socket(pj_AF_INET6(), pj_SOCK_DGRAM(), 0, 
     311                            &resv->udp6_sock); 
     312    if (status != PJ_SUCCESS) 
     313        return status; 
     314 
     315    /* Bind to any address/port */ 
     316    pj_sockaddr_init(pj_AF_INET6(), &bound_addr, NULL, 0); 
     317    status = pj_sock_bind(resv->udp6_sock, &bound_addr, 
     318                          pj_sockaddr_get_len(&bound_addr)); 
     319    if (status != PJ_SUCCESS) 
     320        return status; 
     321 
     322    /* Register to ioqueue */ 
     323    pj_bzero(&socket_cb, sizeof(socket_cb)); 
     324    socket_cb.on_read_complete = &on_read_complete; 
     325    status = pj_ioqueue_register_sock(resv->pool, resv->ioqueue, 
     326                                      resv->udp6_sock, resv, &socket_cb, 
     327                                      &resv->udp6_key); 
     328    if (status != PJ_SUCCESS) 
     329        return status; 
     330 
     331    pj_ioqueue_op_key_init(&resv->udp6_op_rx_key, 
     332                           sizeof(resv->udp6_op_rx_key)); 
     333    pj_ioqueue_op_key_init(&resv->udp6_op_tx_key, 
     334                           sizeof(resv->udp6_op_tx_key)); 
     335 
     336    /* Start asynchronous read to the UDP socket */ 
     337    rx_pkt_size = sizeof(resv->udp6_rx_pkt); 
     338    resv->udp6_addr_len = sizeof(resv->udp6_src_addr); 
     339    status = pj_ioqueue_recvfrom(resv->udp6_key, &resv->udp6_op_rx_key, 
     340                                 resv->udp6_rx_pkt, &rx_pkt_size, 
     341                                 PJ_IOQUEUE_ALWAYS_ASYNC, 
     342                                 &resv->udp6_src_addr, &resv->udp6_addr_len); 
     343    if (status != PJ_EPENDING) 
     344        return status; 
     345#else 
     346    PJ_UNUSED_ARG(bound_addr); 
     347#endif 
    280348 
    281349    return PJ_SUCCESS; 
     
    475543        struct nameserver *ns = &resolver->ns[i]; 
    476544 
    477         status = pj_sockaddr_in_init(&ns->addr, &servers[i],  
    478                                      (pj_uint16_t)(ports ? ports[i] : PORT)); 
     545        status = pj_sockaddr_init(pj_AF_INET(), &ns->addr, &servers[i],  
     546                                  (pj_uint16_t)(ports ? ports[i] : PORT)); 
     547        if (status != PJ_SUCCESS) 
     548            status = pj_sockaddr_init(pj_AF_INET6(), &ns->addr, &servers[i],  
     549                                      (pj_uint16_t)(ports ? ports[i] : PORT)); 
    479550        if (status != PJ_SUCCESS) { 
    480551            pj_mutex_unlock(resolver->mutex); 
     
    613684 
    614685    /* Check if the socket is available for sending */ 
    615     if (pj_ioqueue_is_pending(resolver->udp_key, &resolver->udp_op_tx_key)) { 
     686    if (pj_ioqueue_is_pending(resolver->udp_key, &resolver->udp_op_tx_key) 
     687#if PJ_HAS_IPV6 
     688        || pj_ioqueue_is_pending(resolver->udp6_key, 
     689                                 &resolver->udp6_op_tx_key) 
     690#endif 
     691        ) 
     692    { 
    616693        ++q->transmit_cnt; 
    617694        PJ_LOG(4,(resolver->name.ptr, 
     
    643720        struct nameserver *ns = &resolver->ns[servers[i]]; 
    644721 
    645         status = pj_ioqueue_sendto(resolver->udp_key, 
    646                                    &resolver->udp_op_tx_key, 
    647                                    resolver->udp_tx_pkt, &sent, 0, 
    648                                    &resolver->ns[servers[i]].addr, 
    649                                    sizeof(pj_sockaddr_in)); 
     722        if (ns->addr.addr.sa_family == pj_AF_INET()) { 
     723            status = pj_ioqueue_sendto(resolver->udp_key, 
     724                                       &resolver->udp_op_tx_key, 
     725                                       resolver->udp_tx_pkt, &sent, 0, 
     726                                       &ns->addr, 
     727                                       pj_sockaddr_get_len(&ns->addr)); 
     728        } 
     729#if PJ_HAS_IPV6 
     730        else { 
     731            status = pj_ioqueue_sendto(resolver->udp6_key, 
     732                                       &resolver->udp6_op_tx_key, 
     733                                       resolver->udp_tx_pkt, &sent, 0, 
     734                                       &ns->addr, 
     735                                       pj_sockaddr_get_len(&ns->addr)); 
     736        } 
     737#endif 
    650738 
    651739        PJ_PERROR(4,(resolver->name.ptr, status, 
     
    653741                  (q->transmit_cnt==0? "Transmitting":"Re-transmitting"), 
    654742                  (int)pkt_size, servers[i], 
    655                   pj_inet_ntop2(pj_AF_INET(), &ns->addr.sin_addr, addr, 
    656                                 sizeof(addr)), 
    657                   (int)pj_ntohs(ns->addr.sin_port), 
     743                  pj_sockaddr_print(&ns->addr, addr, sizeof(addr), 2), 
     744                  pj_sockaddr_get_port(&ns->addr), 
    658745                  pj_dns_get_type_name(q->key.qtype),  
    659746                  q->key.name)); 
     
    10291116 
    10301117 
     1118/*  
     1119 * DNS response containing A and/or AAAA packet.  
     1120 */ 
     1121PJ_DEF(pj_status_t) pj_dns_parse_addr_response( 
     1122                                            const pj_dns_parsed_packet *pkt, 
     1123                                            pj_dns_addr_record *rec) 
     1124{ 
     1125    enum { MAX_SEARCH = 20 }; 
     1126    pj_str_t hostname, alias = {NULL, 0}, *resname; 
     1127    pj_size_t bufstart = 0; 
     1128    pj_size_t bufleft; 
     1129    unsigned i, ansidx, cnt=0; 
     1130 
     1131    PJ_ASSERT_RETURN(pkt && rec, PJ_EINVAL); 
     1132 
     1133    /* Init the record */ 
     1134    pj_bzero(rec, sizeof(*rec)); 
     1135 
     1136    bufleft = sizeof(rec->buf_); 
     1137 
     1138    /* Return error if there's error in the packet. */ 
     1139    if (PJ_DNS_GET_RCODE(pkt->hdr.flags)) 
     1140        return PJ_STATUS_FROM_DNS_RCODE(PJ_DNS_GET_RCODE(pkt->hdr.flags)); 
     1141 
     1142    /* Return error if there's no query section */ 
     1143    if (pkt->hdr.qdcount == 0) 
     1144        return PJLIB_UTIL_EDNSINANSWER; 
     1145 
     1146    /* Return error if there's no answer */ 
     1147    if (pkt->hdr.anscount == 0) 
     1148        return PJLIB_UTIL_EDNSNOANSWERREC; 
     1149 
     1150    /* Get the hostname from the query. */ 
     1151    hostname = pkt->q[0].name; 
     1152 
     1153    /* Copy hostname to the record */ 
     1154    if (hostname.slen > (int)bufleft) { 
     1155        return PJ_ENAMETOOLONG; 
     1156    } 
     1157 
     1158    pj_memcpy(&rec->buf_[bufstart], hostname.ptr, hostname.slen); 
     1159    rec->name.ptr = &rec->buf_[bufstart]; 
     1160    rec->name.slen = hostname.slen; 
     1161 
     1162    bufstart += hostname.slen; 
     1163    bufleft -= hostname.slen; 
     1164 
     1165    /* Find the first RR which name matches the hostname. */ 
     1166    for (ansidx=0; ansidx < pkt->hdr.anscount; ++ansidx) { 
     1167        if (pj_stricmp(&pkt->ans[ansidx].name, &hostname)==0) 
     1168            break; 
     1169    } 
     1170 
     1171    if (ansidx == pkt->hdr.anscount) 
     1172        return PJLIB_UTIL_EDNSNOANSWERREC; 
     1173 
     1174    resname = &hostname; 
     1175 
     1176    /* Keep following CNAME records. */ 
     1177    while (pkt->ans[ansidx].type == PJ_DNS_TYPE_CNAME && 
     1178           cnt++ < MAX_SEARCH) 
     1179    { 
     1180        resname = &pkt->ans[ansidx].rdata.cname.name; 
     1181 
     1182        if (!alias.slen) 
     1183            alias = *resname; 
     1184 
     1185        for (i=0; i < pkt->hdr.anscount; ++i) { 
     1186            if (pj_stricmp(resname, &pkt->ans[i].name)==0) 
     1187                break; 
     1188        } 
     1189 
     1190        if (i==pkt->hdr.anscount) 
     1191            return PJLIB_UTIL_EDNSNOANSWERREC; 
     1192 
     1193        ansidx = i; 
     1194    } 
     1195 
     1196    if (cnt >= MAX_SEARCH) 
     1197        return PJLIB_UTIL_EDNSINANSWER; 
     1198 
     1199    if (pkt->ans[ansidx].type != PJ_DNS_TYPE_A && 
     1200        pkt->ans[ansidx].type != PJ_DNS_TYPE_AAAA) 
     1201    { 
     1202        return PJLIB_UTIL_EDNSINANSWER; 
     1203    } 
     1204 
     1205    /* Copy alias to the record, if present. */ 
     1206    if (alias.slen) { 
     1207        if (alias.slen > (int)bufleft) 
     1208            return PJ_ENAMETOOLONG; 
     1209 
     1210        pj_memcpy(&rec->buf_[bufstart], alias.ptr, alias.slen); 
     1211        rec->alias.ptr = &rec->buf_[bufstart]; 
     1212        rec->alias.slen = alias.slen; 
     1213 
     1214        bufstart += alias.slen; 
     1215        bufleft -= alias.slen; 
     1216    } 
     1217 
     1218    /* Get the IP addresses. */ 
     1219    cnt = 0; 
     1220    for (i=0; i < pkt->hdr.anscount && cnt < PJ_DNS_MAX_IP_IN_A_REC ; ++i) { 
     1221        if ((pkt->ans[i].type == PJ_DNS_TYPE_A || 
     1222             pkt->ans[i].type == PJ_DNS_TYPE_AAAA) && 
     1223            pj_stricmp(&pkt->ans[i].name, resname)==0) 
     1224        { 
     1225            if (pkt->ans[i].type == PJ_DNS_TYPE_A) { 
     1226                rec->addr[cnt].af = pj_AF_INET(); 
     1227                rec->addr[cnt].ip.v4 = pkt->ans[i].rdata.a.ip_addr; 
     1228            } else { 
     1229                rec->addr[cnt].af = pj_AF_INET6(); 
     1230                rec->addr[cnt].ip.v6 = pkt->ans[i].rdata.aaaa.ip_addr; 
     1231            } 
     1232            ++cnt; 
     1233        } 
     1234    } 
     1235    rec->addr_count = cnt; 
     1236 
     1237    if (cnt == 0) 
     1238        return PJLIB_UTIL_EDNSNOANSWERREC; 
     1239 
     1240    return PJ_SUCCESS; 
     1241} 
     1242 
     1243 
    10311244/* Set nameserver state */ 
    10321245static void set_nameserver_state(pj_dns_resolver *resolver, 
     
    10371250    struct nameserver *ns = &resolver->ns[index]; 
    10381251    enum ns_state old_state = ns->state; 
    1039     char addr[PJ_INET_ADDRSTRLEN]; 
     1252    char addr[PJ_INET6_ADDRSTRLEN]; 
    10401253 
    10411254    ns->state = state; 
     
    10511264 
    10521265    PJ_LOG(5, (resolver->name.ptr, "Nameserver %s:%d state changed %s --> %s", 
    1053                pj_inet_ntop2(pj_AF_INET(), &ns->addr.sin_addr, addr, 
    1054                              sizeof(addr)), 
    1055                (int)pj_ntohs(ns->addr.sin_port), 
     1266               pj_sockaddr_print(&ns->addr, addr, sizeof(addr), 2), 
     1267               pj_sockaddr_get_port(&ns->addr), 
    10561268               state_names[old_state], state_names[state])); 
    10571269} 
     
    11321344/* Update name server status */ 
    11331345static void report_nameserver_status(pj_dns_resolver *resolver, 
    1134                                      const pj_sockaddr_in *ns_addr, 
     1346                                     const pj_sockaddr *ns_addr, 
    11351347                                     const pj_dns_parsed_packet *pkt) 
    11361348{ 
     
    11691381        struct nameserver *ns = &resolver->ns[i]; 
    11701382 
    1171         if (ns->addr.sin_addr.s_addr == ns_addr->sin_addr.s_addr && 
    1172             ns->addr.sin_port == ns_addr->sin_port && 
    1173             ns->addr.sin_family == ns_addr->sin_family) 
    1174         { 
     1383        if (pj_sockaddr_cmp(&ns->addr, ns_addr) == 0) { 
    11751384            if (q_id == ns->q_id) { 
    11761385                /* Calculate response time */ 
     
    13951604    pj_dns_parsed_packet *dns_pkt; 
    13961605    pj_dns_async_query *q; 
    1397     char addr[PJ_INET_ADDRSTRLEN]; 
     1606    char addr[PJ_INET6_ADDRSTRLEN]; 
     1607    pj_sockaddr *src_addr; 
     1608    int *src_addr_len; 
     1609    unsigned char *rx_pkt; 
     1610    pj_ssize_t rx_pkt_size; 
    13981611    pj_status_t status; 
    13991612    PJ_USE_EXCEPTION; 
     
    14011614 
    14021615    resolver = (pj_dns_resolver *) pj_ioqueue_get_user_data(key); 
     1616    pj_assert(resolver); 
     1617 
     1618#if PJ_HAS_IPV6 
     1619    if (key == resolver->udp6_key) { 
     1620        src_addr = &resolver->udp6_src_addr; 
     1621        src_addr_len = &resolver->udp6_addr_len; 
     1622        rx_pkt = resolver->udp6_rx_pkt; 
     1623        rx_pkt_size = sizeof(resolver->udp6_rx_pkt); 
     1624    } else  
     1625#endif 
     1626    { 
     1627        src_addr = &resolver->udp_src_addr; 
     1628        src_addr_len = &resolver->udp_addr_len; 
     1629        rx_pkt = resolver->udp_rx_pkt; 
     1630        rx_pkt_size = sizeof(resolver->udp_rx_pkt); 
     1631    } 
     1632 
    14031633    pj_mutex_lock(resolver->mutex); 
    14041634 
     
    14121642        PJ_LOG(4,(resolver->name.ptr,  
    14131643                  "DNS resolver read error from %s:%d: %s",  
    1414                   pj_inet_ntop2(pj_AF_INET(), &resolver->udp_src_addr.sin_addr, 
    1415                                 addr, sizeof(addr)),  
    1416                   pj_ntohs(resolver->udp_src_addr.sin_port), 
     1644                  pj_sockaddr_print(src_addr, addr, sizeof(addr), 2), 
     1645                  pj_sockaddr_get_port(src_addr), 
    14171646                  errmsg)); 
    14181647 
     
    14231652              "Received %d bytes DNS response from %s:%d", 
    14241653              (int)bytes_read,  
    1425               pj_inet_ntop2(pj_AF_INET(), &resolver->udp_src_addr.sin_addr, 
    1426                             addr, sizeof(addr)),  
    1427               pj_ntohs(resolver->udp_src_addr.sin_port))); 
     1654              pj_sockaddr_print(src_addr, addr, sizeof(addr), 2), 
     1655              pj_sockaddr_get_port(src_addr))); 
    14281656 
    14291657 
     
    14401668    dns_pkt = NULL; 
    14411669    PJ_TRY { 
    1442         status = pj_dns_parse_packet(pool, resolver->udp_rx_pkt,  
     1670        status = pj_dns_parse_packet(pool, rx_pkt,  
    14431671                                     (unsigned)bytes_read, &dns_pkt); 
    14441672    } 
     
    14491677 
    14501678    /* Update nameserver status */ 
    1451     report_nameserver_status(resolver, &resolver->udp_src_addr, dns_pkt); 
     1679    report_nameserver_status(resolver, src_addr, dns_pkt); 
    14521680 
    14531681    /* Handle parse error */ 
     
    14581686        PJ_LOG(3,(resolver->name.ptr,  
    14591687                  "Error parsing DNS response from %s:%d: %s",  
    1460                   pj_inet_ntop2(pj_AF_INET(), &resolver->udp_src_addr.sin_addr, 
    1461                                 addr, sizeof(addr)), 
    1462                   pj_ntohs(resolver->udp_src_addr.sin_port),  
     1688                  pj_sockaddr_print(src_addr, addr, sizeof(addr), 2), 
     1689                  pj_sockaddr_get_port(src_addr), 
    14631690                  errmsg)); 
    14641691        goto read_next_packet; 
     
    14721699        PJ_LOG(5,(resolver->name.ptr,  
    14731700                  "DNS response from %s:%d id=%d discarded", 
    1474                   pj_inet_ntop2(pj_AF_INET(), &resolver->udp_src_addr.sin_addr, 
    1475                                 addr, sizeof(addr)),  
    1476                   pj_ntohs(resolver->udp_src_addr.sin_port), 
     1701                  pj_sockaddr_print(src_addr, addr, sizeof(addr), 2), 
     1702                  pj_sockaddr_get_port(src_addr), 
    14771703                  (unsigned)dns_pkt->hdr.id)); 
    14781704        goto read_next_packet; 
     
    15371763        pj_pool_release(pool); 
    15381764    } 
    1539     bytes_read = sizeof(resolver->udp_rx_pkt); 
    1540     resolver->udp_addr_len = sizeof(resolver->udp_src_addr); 
    1541     status = pj_ioqueue_recvfrom(resolver->udp_key, op_key,  
    1542                                  resolver->udp_rx_pkt, 
    1543                                  &bytes_read, PJ_IOQUEUE_ALWAYS_ASYNC, 
    1544                                  &resolver->udp_src_addr,  
    1545                                  &resolver->udp_addr_len); 
     1765 
     1766    status = pj_ioqueue_recvfrom(key, op_key, rx_pkt, &rx_pkt_size, 
     1767                                 PJ_IOQUEUE_ALWAYS_ASYNC, 
     1768                                 src_addr, src_addr_len); 
     1769 
    15461770    if (status != PJ_EPENDING) { 
    15471771        char errmsg[PJ_ERR_MSG_SIZE]; 
     
    16431867    PJ_LOG(3,(resolver->name.ptr, "  Name servers:")); 
    16441868    for (i=0; i<resolver->ns_count; ++i) { 
    1645         char addr[PJ_INET_ADDRSTRLEN]; 
     1869        char addr[PJ_INET6_ADDRSTRLEN]; 
    16461870        struct nameserver *ns = &resolver->ns[i]; 
    16471871 
    16481872        PJ_LOG(3,(resolver->name.ptr, 
    16491873                  "   NS %d: %s:%d (state=%s until %ds, rtt=%d ms)", 
    1650                   i, pj_inet_ntop2(pj_AF_INET(), &ns->addr.sin_addr, addr, 
    1651                                    sizeof(addr)), 
    1652                   pj_ntohs(ns->addr.sin_port), 
     1874                  i, 
     1875                  pj_sockaddr_print(&ns->addr, addr, sizeof(addr), 2), 
     1876                  pj_sockaddr_get_port(&ns->addr), 
    16531877                  state_names[ns->state], 
    16541878                  ns->state_expiry.sec - now.sec, 
  • pjproject/trunk/pjlib-util/src/pjlib-util/srv_resolver.c

    r5311 r5349  
    3838}; 
    3939 
     40#pragma pack(1) 
    4041struct srv_target 
    4142{ 
    4243    struct common           common; 
     44    struct common           common_aaaa; 
    4345    pj_dns_srv_async_query *parent; 
    4446    pj_str_t                target_name; 
    4547    pj_dns_async_query     *q_a; 
     48    pj_dns_async_query     *q_aaaa; 
    4649    char                    target_buf[PJ_MAX_HOSTNAME]; 
    4750    pj_str_t                cname; 
    4851    char                    cname_buf[PJ_MAX_HOSTNAME]; 
    49     unsigned                port; 
     52    pj_uint16_t             port; 
    5053    unsigned                priority; 
    5154    unsigned                weight; 
    5255    unsigned                sum; 
    5356    unsigned                addr_cnt; 
    54     pj_in_addr              addr[ADDR_MAX_COUNT]; 
     57    pj_sockaddr             addr[ADDR_MAX_COUNT];/**< Address family and IP.*/ 
    5558}; 
     59#pragma pack() 
    5660 
    5761struct pj_dns_srv_async_query 
     
    136140    query_job->def_port = (pj_uint16_t)def_port; 
    137141 
     142    /* Normalize query job option PJ_DNS_SRV_RESOLVE_AAAA_ONLY */ 
     143    if (query_job->option & PJ_DNS_SRV_RESOLVE_AAAA_ONLY) 
     144        query_job->option |= PJ_DNS_SRV_RESOLVE_AAAA; 
     145 
    138146    /* Start the asynchronous query_job */ 
    139147 
     
    177185            pj_dns_resolver_cancel_query(srv->q_a, PJ_FALSE); 
    178186            srv->q_a = NULL; 
     187            has_pending = PJ_TRUE; 
     188        } 
     189        if (srv->q_aaaa) { 
     190            pj_dns_resolver_cancel_query(srv->q_aaaa, PJ_FALSE); 
     191            srv->q_aaaa = NULL; 
    179192            has_pending = PJ_TRUE; 
    180193        } 
     
    315328    } 
    316329 
    317     /* Check for Additional Info section if A records are available, and 
    318      * fill in the IP address (so that we won't need to resolve the A  
     330    /* Check for Additional Info section if A/AAAA records are available, and 
     331     * fill in the IP address (so that we won't need to resolve the A/AAAA  
    319332     * record with another DNS query_job).  
    320333     */ 
     
    323336        unsigned j; 
    324337 
    325         if (rr->type != PJ_DNS_TYPE_A) 
     338        /* Skip non-A/AAAA record */ 
     339        if (rr->type != PJ_DNS_TYPE_A && rr->type != PJ_DNS_TYPE_AAAA) 
    326340            continue; 
    327341 
    328         /* Yippeaiyee!! There is an "A" record!  
     342        /* Also skip if: 
     343         * - it is A record and app only want AAAA record, or 
     344         * - it is AAAA record and app does not want AAAA record 
     345         */ 
     346        if ((rr->type == PJ_DNS_TYPE_A && 
     347            (query_job->option & PJ_DNS_SRV_RESOLVE_AAAA_ONLY)!=0) || 
     348            (rr->type == PJ_DNS_TYPE_AAAA && 
     349            (query_job->option & PJ_DNS_SRV_RESOLVE_AAAA)==0)) 
     350        { 
     351            continue; 
     352        }            
     353 
     354        /* Yippeaiyee!! There is an "A/AAAA" record!  
    329355         * Update the IP address of the corresponding SRV record. 
    330356         */ 
    331357        for (j=0; j<query_job->srv_cnt; ++j) { 
    332             if (pj_stricmp(&rr->name, &query_job->srv[j].target_name)==0 && 
    333                 query_job->srv[j].addr_cnt < ADDR_MAX_COUNT) 
    334             { 
     358            if (pj_stricmp(&rr->name, &query_job->srv[j].target_name)==0 
     359                && query_job->srv[j].addr_cnt < ADDR_MAX_COUNT) 
     360            { 
    335361                unsigned cnt = query_job->srv[j].addr_cnt; 
    336                 query_job->srv[j].addr[cnt].s_addr = rr->rdata.a.ip_addr.s_addr; 
     362                if (rr->type == PJ_DNS_TYPE_A) { 
     363                    pj_sockaddr_init(pj_AF_INET(), 
     364                                        &query_job->srv[j].addr[cnt], NULL, 
     365                                        query_job->srv[j].port); 
     366                    query_job->srv[j].addr[cnt].ipv4.sin_addr = 
     367                                                rr->rdata.a.ip_addr; 
     368                } else { 
     369                    pj_sockaddr_init(pj_AF_INET6(), 
     370                                        &query_job->srv[j].addr[cnt], NULL, 
     371                                        query_job->srv[j].port); 
     372                    query_job->srv[j].addr[cnt].ipv6.sin6_addr = 
     373                                                rr->rdata.aaaa.ip_addr; 
     374                } 
     375 
    337376                /* Only increment host_resolved once per SRV record */ 
    338377                if (query_job->srv[j].addr_cnt == 0) 
    339378                    ++query_job->host_resolved; 
     379 
    340380                ++query_job->srv[j].addr_cnt; 
    341381                break; 
     
    355395        } 
    356396        */ 
     397         
    357398    } 
    358399 
     
    363404    for (i=0; i<query_job->srv_cnt; ++i) { 
    364405        pj_in_addr addr; 
     406        pj_in6_addr addr6; 
    365407 
    366408        if (query_job->srv[i].addr_cnt != 0) { 
     
    369411        } 
    370412 
    371         if (pj_inet_pton(pj_AF_INET(), &query_job->srv[i].target_name, 
     413        if ((query_job->option & PJ_DNS_SRV_RESOLVE_AAAA_ONLY)==0 && 
     414            pj_inet_pton(pj_AF_INET(), &query_job->srv[i].target_name, 
    372415                         &addr) == PJ_SUCCESS) 
    373416        { 
    374             query_job->srv[i].addr[query_job->srv[i].addr_cnt++] = addr; 
     417            unsigned cnt = query_job->srv[i].addr_cnt; 
     418            pj_sockaddr_init(pj_AF_INET(), &query_job->srv[i].addr[cnt], 
     419                             NULL, query_job->srv[i].port); 
     420            query_job->srv[i].addr[cnt].ipv4.sin_addr = addr; 
     421            ++query_job->srv[i].addr_cnt; 
     422            ++query_job->host_resolved; 
     423        } else if ((query_job->option & PJ_DNS_SRV_RESOLVE_AAAA)!=0 && 
     424                   pj_inet_pton(pj_AF_INET6(), &query_job->srv[i].target_name, 
     425                                &addr6) == PJ_SUCCESS) 
     426        { 
     427            unsigned cnt = query_job->srv[i].addr_cnt; 
     428            pj_sockaddr_init(pj_AF_INET6(), &query_job->srv[i].addr[cnt], 
     429                             NULL, query_job->srv[i].port); 
     430            query_job->srv[i].addr[cnt].ipv6.sin6_addr = addr6; 
     431            ++query_job->srv[i].addr_cnt; 
    375432            ++query_job->host_resolved; 
    376433        } 
     
    388445 
    389446    for (i=0; i<query_job->srv_cnt; ++i) { 
    390         char addr[PJ_INET_ADDRSTRLEN]; 
     447        char addr[PJ_INET6_ADDRSTRLEN]; 
    391448 
    392449        if (query_job->srv[i].addr_cnt != 0) { 
    393             pj_inet_ntop(pj_AF_INET(), &query_job->srv[i].addr[0], 
    394                          addr, sizeof(addr)); 
     450            pj_sockaddr_print(&query_job->srv[i].addr[0], 
     451                         addr, sizeof(addr), 2); 
    395452        } else 
    396453            pj_ansi_strcpy(addr, "-"); 
     
    408465 
    409466 
    410 /* Start DNS A record queries for all SRV records in the query_job structure */ 
     467/* Start DNS A and/or AAAA record queries for all SRV records in 
     468 * the query_job structure. 
     469 */ 
    411470static pj_status_t resolve_hostnames(pj_dns_srv_async_query *query_job) 
    412471{ 
     
    415474 
    416475    query_job->dns_state = PJ_DNS_TYPE_A; 
     476 
    417477    for (i=0; i<query_job->srv_cnt; ++i) { 
    418478        struct srv_target *srv = &query_job->srv[i]; 
     
    424484 
    425485        srv->common.type = PJ_DNS_TYPE_A; 
     486        srv->common_aaaa.type = PJ_DNS_TYPE_AAAA; 
    426487        srv->parent = query_job; 
     488 
     489        status = PJ_SUCCESS; 
     490 
     491        /* Start DNA A record query */ 
     492        if ((query_job->option & PJ_DNS_SRV_RESOLVE_AAAA_ONLY) == 0) 
     493        { 
     494            status = pj_dns_resolver_start_query(query_job->resolver, 
     495                                                 &srv->target_name, 
     496                                                 PJ_DNS_TYPE_A, 0, 
     497                                                 &dns_callback, 
     498                                                 &srv->common, &srv->q_a); 
     499        } 
     500 
     501        /* Start DNA AAAA record query */ 
     502        if (status == PJ_SUCCESS && 
     503            (query_job->option & PJ_DNS_SRV_RESOLVE_AAAA) != 0) 
     504        { 
     505            status = pj_dns_resolver_start_query(query_job->resolver, 
     506                                                 &srv->target_name, 
     507                                                 PJ_DNS_TYPE_AAAA, 0, 
     508                                                 &dns_callback, 
     509                                                 &srv->common_aaaa, &srv->q_aaaa); 
     510        } 
    427511 
    428512        /* See also #1809: dns_callback() will be invoked synchronously when response 
     
    431515         * returning false error, so don't use that variable for counting errors. 
    432516         */ 
    433         status = pj_dns_resolver_start_query(query_job->resolver, 
    434                                              &srv->target_name, 
    435                                              PJ_DNS_TYPE_A, 0, 
    436                                              &dns_callback, 
    437                                              srv, &srv->q_a); 
    438517        if (status != PJ_SUCCESS) { 
    439518            query_job->host_resolved++; 
     
    465544        srv = (struct srv_target*) common; 
    466545        query_job = srv->parent; 
     546    } else if (common->type == PJ_DNS_TYPE_AAAA) { 
     547        srv = (struct srv_target*)((pj_int8_t*)common-sizeof(struct common)); 
     548        query_job = srv->parent; 
    467549    } else { 
    468550        pj_assert(!"Unexpected user data!"); 
     
    475557        /* We are getting SRV response */ 
    476558 
     559        /* Clear the outstanding job */ 
    477560        query_job->q_srv = NULL; 
    478561 
     
    508591         */ 
    509592        if (query_job->srv_cnt == 0) { 
     593            unsigned new_option = 0; 
     594 
    510595            /* Looks like we aren't getting any SRV responses. 
    511596             * Resolve the original target as A record by creating a  
     
    514599            PJ_LOG(4, (query_job->objname,  
    515600                       "DNS SRV resolution failed for %.*s, trying " 
    516                        "resolving A record for %.*s", 
     601                       "resolving A/AAAA record for %.*s", 
    517602                       (int)query_job->full_name.slen,  
    518603                       query_job->full_name.ptr, 
     
    527612            query_job->srv[i].weight = 0; 
    528613            query_job->srv[i].port = query_job->def_port; 
    529         }  
     614 
     615            /* Update query_job resolution option based on fallback option */ 
     616            if (query_job->option & PJ_DNS_SRV_FALLBACK_AAAA) 
     617                new_option |= (PJ_DNS_SRV_RESOLVE_AAAA | 
     618                               PJ_DNS_SRV_RESOLVE_AAAA_ONLY); 
     619            if (query_job->option & PJ_DNS_SRV_FALLBACK_A) 
     620                new_option &= (~PJ_DNS_SRV_RESOLVE_AAAA_ONLY); 
     621             
     622            query_job->option = new_option; 
     623        } 
    530624         
    531625 
    532         /* Resolve server hostnames (DNS A record) for hosts which don't have 
    533          * A record yet. 
     626        /* Resolve server hostnames (DNS A/AAAA record) for hosts which 
     627         * don't have A/AAAA record yet. 
    534628         */ 
    535629        if (query_job->host_resolved != query_job->srv_cnt) { 
     
    545639 
    546640    } else if (query_job->dns_state == PJ_DNS_TYPE_A) { 
    547  
    548         /* Clear the outstanding job */ 
    549         srv->q_a = NULL; 
     641        pj_bool_t is_type_a, srv_completed; 
     642 
     643        /* Clear outstanding job */ 
     644        if (common->type == PJ_DNS_TYPE_A) { 
     645            srv_completed = (srv->q_aaaa == NULL); 
     646            srv->q_a = NULL; 
     647        } else if (common->type == PJ_DNS_TYPE_AAAA) { 
     648            srv_completed = (srv->q_a == NULL); 
     649            srv->q_aaaa = NULL; 
     650        } else { 
     651            pj_assert(!"Unexpected job type"); 
     652            query_job->last_error = status = PJ_EINVALIDOP; 
     653            goto on_error; 
     654        } 
     655 
     656        is_type_a = (common->type == PJ_DNS_TYPE_A); 
    550657 
    551658        /* Check that we really have answer */ 
    552659        if (status==PJ_SUCCESS && pkt->hdr.anscount != 0) { 
    553             char addr[PJ_INET_ADDRSTRLEN]; 
    554             pj_dns_a_record rec; 
     660            char addr[PJ_INET6_ADDRSTRLEN]; 
     661            pj_dns_addr_record rec; 
    555662 
    556663            /* Parse response */ 
    557             status = pj_dns_parse_a_response(pkt, &rec); 
     664            status = pj_dns_parse_addr_response(pkt, &rec); 
    558665            if (status != PJ_SUCCESS) 
    559666                goto on_error; 
     
    562669 
    563670            /* Update CNAME alias, if present. */ 
    564             if (rec.alias.slen) { 
     671            if (srv->cname.slen==0 && rec.alias.slen) { 
    565672                pj_assert(rec.alias.slen <= (int)sizeof(srv->cname_buf)); 
    566673                srv->cname.ptr = srv->cname_buf; 
    567674                pj_strcpy(&srv->cname, &rec.alias); 
    568             } else { 
    569                 srv->cname.slen = 0; 
     675            //} else { 
     676                //srv->cname.slen = 0; 
    570677            } 
    571678 
    572679            /* Update IP address of the corresponding hostname or CNAME */ 
    573             if (srv->addr_cnt < ADDR_MAX_COUNT) { 
    574                 srv->addr[srv->addr_cnt++].s_addr = rec.addr[0].s_addr; 
    575  
    576                 PJ_LOG(5,(query_job->objname,  
    577                           "DNS A for %.*s: %s", 
    578                           (int)srv->target_name.slen,  
    579                           srv->target_name.ptr, 
    580                           pj_inet_ntop2(pj_AF_INET(), &rec.addr[0], 
    581                                         addr, sizeof(addr)))); 
    582             } 
    583  
    584             /* Check for multiple IP addresses */ 
    585             for (i=1; i<rec.addr_count && srv->addr_cnt < ADDR_MAX_COUNT; ++i) 
     680            for (i=0; i<rec.addr_count && srv->addr_cnt<ADDR_MAX_COUNT; ++i) 
    586681            { 
    587                 srv->addr[srv->addr_cnt++].s_addr = rec.addr[i].s_addr; 
    588  
    589                 PJ_LOG(5,(query_job->objname,  
    590                           "Additional DNS A for %.*s: %s", 
    591                           (int)srv->target_name.slen,  
    592                           srv->target_name.ptr, 
    593                           pj_inet_ntop2(pj_AF_INET(), &rec.addr[i], 
    594                                         addr, sizeof(addr)))); 
     682                pj_bool_t added = PJ_FALSE; 
     683 
     684                if (is_type_a && rec.addr[i].af == pj_AF_INET()) { 
     685                    pj_sockaddr_init(pj_AF_INET(), &srv->addr[srv->addr_cnt], 
     686                                     NULL, srv->port); 
     687                    srv->addr[srv->addr_cnt].ipv4.sin_addr = 
     688                                     rec.addr[i].ip.v4; 
     689                    added = PJ_TRUE; 
     690                } else if (!is_type_a && rec.addr[i].af == pj_AF_INET6()) { 
     691                    pj_sockaddr_init(pj_AF_INET6(), &srv->addr[srv->addr_cnt], 
     692                                     NULL, srv->port); 
     693                    srv->addr[srv->addr_cnt].ipv6.sin6_addr = 
     694                                     rec.addr[i].ip.v6; 
     695                    added = PJ_TRUE; 
     696                } else { 
     697                    /* Mismatched address family, e.g: getting IPv6 address in 
     698                     * DNS A query resolution. 
     699                     */ 
     700                    PJ_LOG(4,(query_job->objname,  
     701                              "Bad address family in DNS %s query for %.*s", 
     702                              (is_type_a? "A" : "AAAA"), 
     703                              (int)srv->target_name.slen,  
     704                              srv->target_name.ptr)); 
     705                } 
     706 
     707                if (added) { 
     708                    PJ_LOG(5,(query_job->objname,  
     709                              "DNS %s for %.*s: %s", 
     710                              (is_type_a? "A" : "AAAA"), 
     711                              (int)srv->target_name.slen,  
     712                              srv->target_name.ptr, 
     713                              pj_sockaddr_print(&srv->addr[srv->addr_cnt], 
     714                                                addr, sizeof(addr), 2))); 
     715 
     716                    ++srv->addr_cnt; 
     717                } 
    595718            } 
    596719 
     
    603726            /* Log error */ 
    604727            pj_strerror(status, errmsg, sizeof(errmsg)); 
    605             PJ_LOG(4,(query_job->objname, "DNS A record resolution failed: %s",  
     728            PJ_LOG(4,(query_job->objname, 
     729                      "DNS %s record resolution failed: %s", 
     730                      (is_type_a? "A" : "AAAA"), 
    606731                      errmsg)); 
    607732        } 
    608733 
    609         ++query_job->host_resolved; 
     734        /* Increment host resolved count when both DNS A and AAAA record 
     735         * queries for this server are completed. 
     736         */ 
     737        if (srv_completed) 
     738            ++query_job->host_resolved; 
    610739 
    611740    } else { 
     
    624753            unsigned j; 
    625754            struct srv_target *srv2 = &query_job->srv[i]; 
     755            pj_dns_addr_record *s = &srv_rec.entry[srv_rec.count].server; 
    626756 
    627757            srv_rec.entry[srv_rec.count].priority = srv2->priority; 
     
    635765            pj_assert(srv2->addr_cnt <= PJ_DNS_MAX_IP_IN_A_REC); 
    636766 
    637             for (j=0; j<srv2->addr_cnt; ++j) { 
    638                 srv_rec.entry[srv_rec.count].server.addr[j].s_addr =  
    639                     srv2->addr[j].s_addr; 
    640                 ++srv_rec.entry[srv_rec.count].server.addr_count; 
     767            for (j=0; j<srv2->addr_cnt; ++j) {           
     768                s->addr[j].af = srv2->addr[j].addr.sa_family; 
     769                if (s->addr[j].af == pj_AF_INET()) 
     770                    s->addr[j].ip.v4 = srv2->addr[j].ipv4.sin_addr; 
     771                else 
     772                    s->addr[j].ip.v6 = srv2->addr[j].ipv6.sin6_addr; 
     773                ++s->addr_count; 
    641774            } 
    642775 
     
    681814                  status, 
    682815                  pj_strerror(status,errmsg,sizeof(errmsg)).ptr)); 
     816 
     817        /* Cancel any pending query */ 
     818        pj_dns_srv_cancel_query(query_job, PJ_FALSE); 
     819 
    683820        (*query_job->cb)(query_job->token, status, NULL); 
    684821        return; 
  • pjproject/trunk/pjnath/src/pjnath/stun_sock.c

    r5296 r5349  
    417417        pj_assert(stun_sock->q == NULL); 
    418418 
    419         opt = PJ_DNS_SRV_FALLBACK_A; 
    420         if (stun_sock->af == pj_AF_INET6()) { 
    421             opt |= (PJ_DNS_SRV_RESOLVE_AAAA | PJ_DNS_SRV_FALLBACK_AAAA); 
    422         } 
     419        /* Init DNS resolution option */ 
     420        if (stun_sock->af == pj_AF_INET6()) 
     421            opt = (PJ_DNS_SRV_RESOLVE_AAAA_ONLY | PJ_DNS_SRV_FALLBACK_AAAA); 
     422        else 
     423            opt = PJ_DNS_SRV_FALLBACK_A; 
    423424 
    424425        status = pj_dns_srv_resolve(domain, &res_name, default_port,  
     
    575576    pj_assert(rec->count); 
    576577    pj_assert(rec->entry[0].server.addr_count); 
    577  
    578     PJ_TODO(SUPPORT_IPV6_IN_RESOLVER); 
    579     pj_assert(stun_sock->af == pj_AF_INET()); 
     578    pj_assert(rec->entry[0].server.addr[0].af == stun_sock->af); 
    580579 
    581580    /* Set the address */ 
    582     pj_sockaddr_in_init(&stun_sock->srv_addr.ipv4, NULL, 
    583                         rec->entry[0].port); 
    584     stun_sock->srv_addr.ipv4.sin_addr = rec->entry[0].server.addr[0]; 
     581    pj_sockaddr_init(stun_sock->af, &stun_sock->srv_addr, NULL, 
     582                     rec->entry[0].port); 
     583    if (stun_sock->af == pj_AF_INET6()) { 
     584        stun_sock->srv_addr.ipv6.sin6_addr =  
     585                                    rec->entry[0].server.addr[0].ip.v6; 
     586    } else { 
     587        stun_sock->srv_addr.ipv4.sin_addr =  
     588                                    rec->entry[0].server.addr[0].ip.v4; 
     589    } 
    585590 
    586591    /* Start sending Binding request */ 
  • pjproject/trunk/pjnath/src/pjnath/turn_session.c

    r5170 r5349  
    609609        } 
    610610 
     611        /* Init DNS resolution option for IPv6 */ 
     612        if (sess->af == pj_AF_INET6()) 
     613            opt |= PJ_DNS_SRV_RESOLVE_AAAA_ONLY; 
     614 
    611615        /* Fallback to DNS A only if default port is specified */ 
    612616        if (default_port>0 && default_port<65536) { 
    613             opt = PJ_DNS_SRV_FALLBACK_A; 
     617            if (sess->af == pj_AF_INET6()) 
     618                opt |= PJ_DNS_SRV_FALLBACK_AAAA; 
     619            else 
     620                opt |= PJ_DNS_SRV_FALLBACK_A; 
    614621            sess->default_port = (pj_uint16_t)default_port; 
    615622        } 
     
    17191726                  cnt<PJ_TURN_MAX_DNS_SRV_CNT; ++j)  
    17201727        { 
    1721             pj_sockaddr_in *addr = &sess->srv_addr_list[cnt].ipv4; 
    1722  
    1723             addr->sin_family = sess->af; 
    1724             addr->sin_port = pj_htons(rec->entry[i].port); 
    1725             addr->sin_addr.s_addr = rec->entry[i].server.addr[j].s_addr; 
    1726  
    1727             ++cnt; 
     1728            if (rec->entry[i].server.addr[j].af == sess->af) { 
     1729                pj_sockaddr *addr = &sess->srv_addr_list[cnt]; 
     1730 
     1731                addr->addr.sa_family = sess->af; 
     1732                pj_sockaddr_set_port(addr, rec->entry[i].port); 
     1733                if (sess->af == pj_AF_INET6()) 
     1734                    addr->ipv6.sin6_addr = rec->entry[i].server.addr[j].ip.v6; 
     1735                else 
     1736                    addr->ipv4.sin_addr = rec->entry[i].server.addr[j].ip.v4; 
     1737 
     1738                ++cnt; 
     1739            } 
    17281740        } 
    17291741    } 
  • pjproject/trunk/pjsip/src/pjsip/sip_resolve.c

    r5337 r5349  
    5454    pjsip_resolver_callback *cb; 
    5555    pj_dns_async_query      *object; 
     56    pj_dns_async_query      *object6; 
    5657    pj_status_t              last_error; 
    5758 
     
    6566    unsigned                 naptr_cnt; 
    6667    struct naptr_target      naptr[8]; 
     68 
     69    /* Query result */ 
     70    pjsip_server_addresses   server; 
    6771}; 
    6872 
     
    8185                           pj_status_t status, 
    8286                           pj_dns_parsed_packet *response); 
     87static void dns_aaaa_callback(void *user_data, 
     88                              pj_status_t status, 
     89                              pj_dns_parsed_packet *response); 
    8390 
    8491 
     
    207214    ip_addr_ver = get_ip_addr_ver(&target->addr.host); 
    208215 
    209     /* Initialize address family type */ 
     216    /* Initialize address family type. Unfortunately, target type doesn't 
     217     * really tell the address family type, except when IPv6 flag is 
     218     * explicitly set. 
     219     */ 
    210220    if ((ip_addr_ver == 6) || (type & PJSIP_TRANSPORT_IPV6)) 
    211221        af = pj_AF_INET6(); 
     
    402412 
    403413    if (query->query_type == PJ_DNS_TYPE_SRV) { 
     414        int opt = 0; 
     415 
     416        if (af == pj_AF_UNSPEC()) 
     417            opt = PJ_DNS_SRV_FALLBACK_A | PJ_DNS_SRV_FALLBACK_AAAA | 
     418                  PJ_DNS_SRV_RESOLVE_AAAA; 
     419        else if (af == pj_AF_INET6()) 
     420            opt = PJ_DNS_SRV_FALLBACK_AAAA | PJ_DNS_SRV_RESOLVE_AAAA_ONLY; 
     421        else /* af == pj_AF_INET() */ 
     422            opt = PJ_DNS_SRV_FALLBACK_A; 
    404423 
    405424        status = pj_dns_srv_resolve(&query->naptr[0].name, 
    406425                                    &query->naptr[0].res_type, 
    407426                                    query->req.def_port, pool, resolver->res, 
    408                                     PJ_TRUE, query, &srv_resolver_cb, NULL); 
     427                                    opt, query, &srv_resolver_cb, NULL); 
    409428 
    410429    } else if (query->query_type == PJ_DNS_TYPE_A) { 
    411430 
    412         status = pj_dns_resolver_start_query(resolver->res,  
    413                                              &query->naptr[0].name, 
    414                                              PJ_DNS_TYPE_A, 0,  
    415                                              &dns_a_callback, 
    416                                              query, &query->object); 
     431        /* Resolve DNS A record if address family is not fixed to IPv6 */ 
     432        if (af != pj_AF_INET6()) { 
     433            status = pj_dns_resolver_start_query(resolver->res,  
     434                                                 &query->naptr[0].name, 
     435                                                 PJ_DNS_TYPE_A, 0,  
     436                                                 &dns_a_callback, 
     437                                                 query, &query->object); 
     438        } 
     439 
     440        /* Resolve DNS AAAA record if address family is not fixed to IPv4 */ 
     441        if (af != pj_AF_INET()) { 
     442            status = pj_dns_resolver_start_query(resolver->res,  
     443                                                 &query->naptr[0].name, 
     444                                                 PJ_DNS_TYPE_AAAA, 0,  
     445                                                 &dns_aaaa_callback, 
     446                                                 query, &query->object6); 
     447        } 
    417448 
    418449    } else { 
     
    455486{ 
    456487    struct query *query = (struct query*) user_data; 
    457     pjsip_server_addresses srv; 
    458     pj_dns_a_record rec; 
    459     unsigned i; 
    460  
    461     rec.addr_count = 0; 
    462  
    463     /* Parse the response */ 
     488    pjsip_server_addresses *srv = &query->server; 
     489 
     490    /* Reset outstanding job */ 
     491    query->object = NULL; 
     492 
    464493    if (status == PJ_SUCCESS) { 
    465         status = pj_dns_parse_a_response(pkt, &rec); 
    466     } 
    467  
    468     if (status != PJ_SUCCESS) { 
     494        pj_dns_addr_record rec; 
     495        unsigned i; 
     496 
     497        /* Parse the response */ 
     498        rec.addr_count = 0; 
     499        status = pj_dns_parse_addr_response(pkt, &rec); 
     500 
     501        /* Build server addresses and call callback */ 
     502        for (i = 0; i < rec.addr_count && 
     503                    srv->count < PJSIP_MAX_RESOLVED_ADDRESSES; ++i) 
     504        { 
     505            /* Should not happen, just in case */ 
     506            if (rec.addr[i].af != pj_AF_INET()) 
     507                continue; 
     508 
     509            srv->entry[srv->count].type = query->naptr[0].type; 
     510            srv->entry[srv->count].priority = 0; 
     511            srv->entry[srv->count].weight = 0; 
     512            srv->entry[srv->count].addr_len = sizeof(pj_sockaddr_in); 
     513            pj_sockaddr_in_init(&srv->entry[srv->count].addr.ipv4, 
     514                                0, (pj_uint16_t)query->req.def_port); 
     515            srv->entry[srv->count].addr.ipv4.sin_addr = rec.addr[i].ip.v4; 
     516 
     517            ++srv->count; 
     518        } 
     519 
     520    } else { 
     521 
    469522        char errmsg[PJ_ERR_MSG_SIZE]; 
    470523 
     
    474527                  errmsg)); 
    475528 
    476         /* Call the callback */ 
    477         (*query->cb)(status, query->token, NULL); 
    478         return; 
    479     } 
    480  
    481     /* Build server addresses and call callback */ 
    482     srv.count = 0; 
    483     for (i = 0; i < rec.addr_count && 
    484                 srv.count < PJSIP_MAX_RESOLVED_ADDRESSES; ++i) 
    485     { 
    486         srv.entry[srv.count].type = query->naptr[0].type; 
    487         srv.entry[srv.count].priority = 0; 
    488         srv.entry[srv.count].weight = 0; 
    489         srv.entry[srv.count].addr_len = sizeof(pj_sockaddr_in); 
    490         pj_sockaddr_in_init(&srv.entry[srv.count].addr.ipv4, 
    491                             0, (pj_uint16_t)query->req.def_port); 
    492         srv.entry[srv.count].addr.ipv4.sin_addr.s_addr = 
    493             rec.addr[i].s_addr; 
    494  
    495         ++srv.count; 
    496     } 
    497  
    498     /* Call the callback */ 
    499     (*query->cb)(PJ_SUCCESS, query->token, &srv); 
     529        query->last_error = status; 
     530    } 
     531 
     532    /* Call the callback if all DNS queries have been completed */ 
     533    if (query->object == NULL && query->object6 == NULL) { 
     534        if (srv->count > 0) 
     535            (*query->cb)(PJ_SUCCESS, query->token, &query->server); 
     536        else 
     537            (*query->cb)(query->last_error, query->token, NULL); 
     538    } 
     539} 
     540 
     541 
     542/*  
     543 * This callback is called when target is resolved with DNS AAAA query. 
     544 */ 
     545static void dns_aaaa_callback(void *user_data, 
     546                              pj_status_t status, 
     547                              pj_dns_parsed_packet *pkt) 
     548{ 
     549    struct query *query = (struct query*) user_data; 
     550    pjsip_server_addresses *srv = &query->server; 
     551 
     552    /* Reset outstanding job */ 
     553    query->object6 = NULL; 
     554 
     555    if (status == PJ_SUCCESS) { 
     556        pj_dns_addr_record rec; 
     557        unsigned i; 
     558 
     559        /* Parse the response */ 
     560        rec.addr_count = 0; 
     561        status = pj_dns_parse_addr_response(pkt, &rec); 
     562 
     563        /* Build server addresses and call callback */ 
     564        for (i = 0; i < rec.addr_count && 
     565                    srv->count < PJSIP_MAX_RESOLVED_ADDRESSES; ++i) 
     566        { 
     567            /* Should not happen, just in case */ 
     568            if (rec.addr[i].af != pj_AF_INET6()) 
     569                continue; 
     570 
     571            srv->entry[srv->count].type = query->naptr[0].type | 
     572                                          PJSIP_TRANSPORT_IPV6; 
     573            srv->entry[srv->count].priority = 0; 
     574            srv->entry[srv->count].weight = 0; 
     575            srv->entry[srv->count].addr_len = sizeof(pj_sockaddr_in); 
     576            pj_sockaddr_init(pj_AF_INET6(), &srv->entry[srv->count].addr, 
     577                             0, (pj_uint16_t)query->req.def_port); 
     578            srv->entry[srv->count].addr.ipv6.sin6_addr = rec.addr[i].ip.v6; 
     579 
     580            ++srv->count; 
     581        } 
     582 
     583    } else { 
     584 
     585        char errmsg[PJ_ERR_MSG_SIZE]; 
     586 
     587        /* Log error */ 
     588        pj_strerror(status, errmsg, sizeof(errmsg)); 
     589        PJ_LOG(4,(query->objname, "DNS AAAA record resolution failed: %s",  
     590                  errmsg)); 
     591 
     592        query->last_error = status; 
     593    } 
     594 
     595    /* Call the callback if all DNS queries have been completed */ 
     596    if (query->object == NULL && query->object6 == NULL) { 
     597        if (srv->count > 0) 
     598            (*query->cb)(PJ_SUCCESS, query->token, &query->server); 
     599        else 
     600            (*query->cb)(query->last_error, query->token, NULL); 
     601    } 
    500602} 
    501603 
     
    515617        /* Log error */ 
    516618        pj_strerror(status, errmsg, sizeof(errmsg)); 
    517         PJ_LOG(4,(query->objname, "DNS A record resolution failed: %s",  
     619        PJ_LOG(4,(query->objname, "DNS A/AAAA record resolution failed: %s", 
    518620                  errmsg)); 
    519621 
     
    526628    srv.count = 0; 
    527629    for (i=0; i<rec->count; ++i) { 
     630        const pj_dns_addr_record *s = &rec->entry[i].server; 
    528631        unsigned j; 
    529632 
    530         for (j = 0; j < rec->entry[i].server.addr_count && 
     633        for (j = 0; j < s->addr_count && 
    531634                    srv.count < PJSIP_MAX_RESOLVED_ADDRESSES; ++j) 
    532635        { 
     
    535638            srv.entry[srv.count].weight = rec->entry[i].weight; 
    536639            srv.entry[srv.count].addr_len = sizeof(pj_sockaddr_in); 
    537             pj_sockaddr_in_init(&srv.entry[srv.count].addr.ipv4, 
    538                                 0, (pj_uint16_t)rec->entry[i].port); 
    539             srv.entry[srv.count].addr.ipv4.sin_addr.s_addr = 
    540                 rec->entry[i].server.addr[j].s_addr; 
     640            pj_sockaddr_init(s->addr[j].af, 
     641                             &srv.entry[srv.count].addr, 
     642                             0, (pj_uint16_t)rec->entry[i].port); 
     643            if (s->addr[j].af == pj_AF_INET6()) 
     644                srv.entry[srv.count].addr.ipv6.sin6_addr = s->addr[j].ip.v6; 
     645            else 
     646                srv.entry[srv.count].addr.ipv4.sin_addr = s->addr[j].ip.v4; 
     647 
     648            /* Update transport type if this is IPv6 */ 
     649            if (s->addr[j].af == pj_AF_INET6()) 
     650                srv.entry[srv.count].type |= PJSIP_TRANSPORT_IPV6; 
    541651 
    542652            ++srv.count; 
Note: See TracChangeset for help on using the changeset viewer.