Changeset 5349
- Timestamp:
- Jun 20, 2016 10:10:42 AM (8 years ago)
- Location:
- pjproject/trunk
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjlib-util/include/pjlib-util/resolver.h
r3553 r5349 224 224 225 225 } 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 */ 233 typedef 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; 226 267 227 268 … … 409 450 410 451 /** 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 */ 461 PJ_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 /** 411 467 * Put the specified DNS packet into DNS cache. This function is mainly used 412 468 * 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 85 85 * resolution when the SRV resolution fails. This option may 86 86 * 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 AAAAresolution fails.87 * make the resolver fallback to both DNS A and DNS AAAA 88 * resolutions if SRV resolution fails. 89 89 */ 90 90 PJ_DNS_SRV_FALLBACK_A = 1, … … 93 93 * Specify if the resolver should fallback with DNS AAAA 94 94 * resolution when the SRV resolution fails. This option may 95 * be specified together with PJ_DNS_SRV_FALLBACK_A to96 * make the resolver fallback to AAAA if SRV resolution fails,97 * and then to DNS A resolution if the AAAAresolution 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. 98 98 */ 99 99 PJ_DNS_SRV_FALLBACK_AAAA = 2, … … 101 101 /** 102 102 * 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 108 115 109 116 } pj_dns_srv_option; … … 132 139 133 140 /** The host address. */ 134 pj_dns_a _recordserver;141 pj_dns_addr_record server; 135 142 136 143 } entry[PJ_DNS_SRV_MAX_ADDR]; -
pjproject/trunk/pjlib-util/src/pjlib-util-test/resolver_test.c
r4537 r5349 192 192 size -= 6; 193 193 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 194 208 } else if (rr->type == PJ_DNS_TYPE_CNAME || 195 209 rr->type == PJ_DNS_TYPE_NS || … … 331 345 pj_fd_set_t rset; 332 346 pj_time_val timeout = {0, 500}; 333 pj_sockaddr _insrc_addr;347 pj_sockaddr src_addr; 334 348 pj_dns_parsed_packet *req; 335 349 char pkt[1024]; … … 406 420 static void destroy(void); 407 421 408 static int init( void)422 static int init(pj_bool_t use_ipv6) 409 423 { 410 424 pj_status_t status; … … 413 427 int i; 414 428 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 } 416 436 ports[0] = 5553; 417 nameservers[1] = pj_str("127.0.0.1");418 437 ports[1] = 5554; 419 438 … … 426 445 pj_assert(status == PJ_SUCCESS); 427 446 447 thread_quit = PJ_FALSE; 448 428 449 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); 432 454 if (status != PJ_SUCCESS) 433 455 return -10; 434 456 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); 436 459 437 460 status = pj_sock_bind(g_server[i].sock, &addr, sizeof(addr)); … … 687 710 688 711 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 */ 720 static 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); 689 921 pj_assert(rc == PJLIB_UTIL_EDNSNOANSWERREC); 690 922 … … 1006 1238 res->ans[1].name = pj_str(alias); 1007 1239 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; 1008 1261 } 1009 1262 … … 1027 1280 PJ_ASSERT_ON_FAIL(pj_strcmp2(&rec->entry[0].server.alias, "sipalias.somedomain.com")==0, 1028 1281 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); 1030 1286 PJ_ASSERT_ON_FAIL(rec->entry[0].port == PORT1, return); 1031 1287 1032 1288 1033 1289 } 1290 1034 1291 1035 1292 static void srv_cb_1b(void *user_data, … … 1045 1302 PJ_ASSERT_ON_FAIL(rec->count == 0, return); 1046 1303 } 1304 1305 1306 static 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 1334 static 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 1047 1359 1048 1360 static int srv_resolver_test(void) … … 1079 1391 ((set.qretr_count + 2) * set.qretr_delay)); 1080 1392 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 1081 1435 /* Successful scenario */ 1082 1436 PJ_LOG(3,(THIS_FILE, " srv_resolve(): parallel queries")); … … 1103 1457 PJ_LOG(3,(THIS_FILE, " srv_resolve(): cache expires scenario")); 1104 1458 1105 1106 1459 pj_thread_sleep(1000); 1107 1460 … … 1114 1467 1115 1468 pj_sem_wait(sem); 1469 1116 1470 1117 1471 return 0; … … 1172 1526 res->ans[1].ttl = 1; 1173 1527 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; 1174 1549 } 1175 1550 … … 1193 1568 PJ_ASSERT_ON_FAIL(pj_strcmp2(&rec->entry[0].server.alias, "sipalias01." TARGET)==0, 1194 1569 return); 1195 PJ_ASSERT_ON_FAIL(rec->entry[0].server.addr[0].s_addr == IP_ADDR2, return);1196 1570 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 1578 static 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 1604 static 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); 1197 1626 } 1198 1627 … … 1203 1632 pj_str_t res_name = pj_str("_sip._udp."); 1204 1633 1634 /* Fallback test */ 1205 1635 PJ_LOG(3,(THIS_FILE, " srv_resolve(): fallback test")); 1206 1636 … … 1235 1665 pj_assert(g_server[0].pkt_count == 0); 1236 1666 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); 1237 1712 1238 1713 return 0; … … 1334 1809 1335 1810 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); 1337 1812 } 1338 1813 } … … 1375 1850 int rc; 1376 1851 1377 rc = init( );1852 rc = init(PJ_FALSE); 1378 1853 if (rc != 0) 1379 1854 goto on_error; … … 1383 1858 goto on_error; 1384 1859 1860 rc = addr_parser_test(); 1861 if (rc != 0) 1862 goto on_error; 1863 1385 1864 rc = simple_test(); 1386 1865 if (rc != 0) … … 1396 1875 1397 1876 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 1398 1902 return 0; 1399 1903 … … 1403 1907 } 1404 1908 1405 -
pjproject/trunk/pjlib-util/src/pjlib-util/resolver.c
r5311 r5349 80 80 struct nameserver 81 81 { 82 pj_sockaddr _inaddr; /**< Server address. */82 pj_sockaddr addr; /**< Server address. */ 83 83 84 84 enum ns_state state; /**< Nameserver state. */ … … 180 180 pj_ioqueue_key_t *udp_key; /**< UDP socket ioqueue key. */ 181 181 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. */ 184 183 pj_ioqueue_op_key_t udp_op_rx_key; /**< UDP read operation key. */ 185 184 pj_ioqueue_op_key_t udp_op_tx_key; /**< UDP write operation key. */ 186 pj_sockaddr _inudp_src_addr; /**< Source address of packet */185 pj_sockaddr udp_src_addr; /**< Source address of packet */ 187 186 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 188 199 189 200 /* Settings */ … … 238 249 resv->udp_sock = PJ_INVALID_SOCKET; 239 250 } 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 240 262 } 241 263 … … 245 267 { 246 268 pj_ioqueue_callback socket_cb; 269 pj_sockaddr bound_addr; 270 pj_ssize_t rx_pkt_size; 247 271 pj_status_t status; 248 272 … … 270 294 271 295 /* Start asynchronous read to the UDP socket */ 272 r esv->udp_len= sizeof(resv->udp_rx_pkt);296 rx_pkt_size = sizeof(resv->udp_rx_pkt); 273 297 resv->udp_addr_len = sizeof(resv->udp_src_addr); 274 298 status = pj_ioqueue_recvfrom(resv->udp_key, &resv->udp_op_rx_key, 275 resv->udp_rx_pkt, &r esv->udp_len,299 resv->udp_rx_pkt, &rx_pkt_size, 276 300 PJ_IOQUEUE_ALWAYS_ASYNC, 277 301 &resv->udp_src_addr, &resv->udp_addr_len); 278 302 if (status != PJ_EPENDING) 279 303 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 280 348 281 349 return PJ_SUCCESS; … … 475 543 struct nameserver *ns = &resolver->ns[i]; 476 544 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)); 479 550 if (status != PJ_SUCCESS) { 480 551 pj_mutex_unlock(resolver->mutex); … … 613 684 614 685 /* 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 { 616 693 ++q->transmit_cnt; 617 694 PJ_LOG(4,(resolver->name.ptr, … … 643 720 struct nameserver *ns = &resolver->ns[servers[i]]; 644 721 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 650 738 651 739 PJ_PERROR(4,(resolver->name.ptr, status, … … 653 741 (q->transmit_cnt==0? "Transmitting":"Re-transmitting"), 654 742 (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), 658 745 pj_dns_get_type_name(q->key.qtype), 659 746 q->key.name)); … … 1029 1116 1030 1117 1118 /* 1119 * DNS response containing A and/or AAAA packet. 1120 */ 1121 PJ_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 1031 1244 /* Set nameserver state */ 1032 1245 static void set_nameserver_state(pj_dns_resolver *resolver, … … 1037 1250 struct nameserver *ns = &resolver->ns[index]; 1038 1251 enum ns_state old_state = ns->state; 1039 char addr[PJ_INET _ADDRSTRLEN];1252 char addr[PJ_INET6_ADDRSTRLEN]; 1040 1253 1041 1254 ns->state = state; … … 1051 1264 1052 1265 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), 1056 1268 state_names[old_state], state_names[state])); 1057 1269 } … … 1132 1344 /* Update name server status */ 1133 1345 static void report_nameserver_status(pj_dns_resolver *resolver, 1134 const pj_sockaddr _in*ns_addr,1346 const pj_sockaddr *ns_addr, 1135 1347 const pj_dns_parsed_packet *pkt) 1136 1348 { … … 1169 1381 struct nameserver *ns = &resolver->ns[i]; 1170 1382 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) { 1175 1384 if (q_id == ns->q_id) { 1176 1385 /* Calculate response time */ … … 1395 1604 pj_dns_parsed_packet *dns_pkt; 1396 1605 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; 1398 1611 pj_status_t status; 1399 1612 PJ_USE_EXCEPTION; … … 1401 1614 1402 1615 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 1403 1633 pj_mutex_lock(resolver->mutex); 1404 1634 … … 1412 1642 PJ_LOG(4,(resolver->name.ptr, 1413 1643 "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), 1417 1646 errmsg)); 1418 1647 … … 1423 1652 "Received %d bytes DNS response from %s:%d", 1424 1653 (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))); 1428 1656 1429 1657 … … 1440 1668 dns_pkt = NULL; 1441 1669 PJ_TRY { 1442 status = pj_dns_parse_packet(pool, r esolver->udp_rx_pkt,1670 status = pj_dns_parse_packet(pool, rx_pkt, 1443 1671 (unsigned)bytes_read, &dns_pkt); 1444 1672 } … … 1449 1677 1450 1678 /* Update nameserver status */ 1451 report_nameserver_status(resolver, &resolver->udp_src_addr, dns_pkt);1679 report_nameserver_status(resolver, src_addr, dns_pkt); 1452 1680 1453 1681 /* Handle parse error */ … … 1458 1686 PJ_LOG(3,(resolver->name.ptr, 1459 1687 "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), 1463 1690 errmsg)); 1464 1691 goto read_next_packet; … … 1472 1699 PJ_LOG(5,(resolver->name.ptr, 1473 1700 "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), 1477 1703 (unsigned)dns_pkt->hdr.id)); 1478 1704 goto read_next_packet; … … 1537 1763 pj_pool_release(pool); 1538 1764 } 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 1546 1770 if (status != PJ_EPENDING) { 1547 1771 char errmsg[PJ_ERR_MSG_SIZE]; … … 1643 1867 PJ_LOG(3,(resolver->name.ptr, " Name servers:")); 1644 1868 for (i=0; i<resolver->ns_count; ++i) { 1645 char addr[PJ_INET _ADDRSTRLEN];1869 char addr[PJ_INET6_ADDRSTRLEN]; 1646 1870 struct nameserver *ns = &resolver->ns[i]; 1647 1871 1648 1872 PJ_LOG(3,(resolver->name.ptr, 1649 1873 " 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), 1653 1877 state_names[ns->state], 1654 1878 ns->state_expiry.sec - now.sec, -
pjproject/trunk/pjlib-util/src/pjlib-util/srv_resolver.c
r5311 r5349 38 38 }; 39 39 40 #pragma pack(1) 40 41 struct srv_target 41 42 { 42 43 struct common common; 44 struct common common_aaaa; 43 45 pj_dns_srv_async_query *parent; 44 46 pj_str_t target_name; 45 47 pj_dns_async_query *q_a; 48 pj_dns_async_query *q_aaaa; 46 49 char target_buf[PJ_MAX_HOSTNAME]; 47 50 pj_str_t cname; 48 51 char cname_buf[PJ_MAX_HOSTNAME]; 49 unsignedport;52 pj_uint16_t port; 50 53 unsigned priority; 51 54 unsigned weight; 52 55 unsigned sum; 53 56 unsigned addr_cnt; 54 pj_ in_addr addr[ADDR_MAX_COUNT];57 pj_sockaddr addr[ADDR_MAX_COUNT];/**< Address family and IP.*/ 55 58 }; 59 #pragma pack() 56 60 57 61 struct pj_dns_srv_async_query … … 136 140 query_job->def_port = (pj_uint16_t)def_port; 137 141 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 138 146 /* Start the asynchronous query_job */ 139 147 … … 177 185 pj_dns_resolver_cancel_query(srv->q_a, PJ_FALSE); 178 186 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; 179 192 has_pending = PJ_TRUE; 180 193 } … … 315 328 } 316 329 317 /* Check for Additional Info section if A records are available, and318 * 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 319 332 * record with another DNS query_job). 320 333 */ … … 323 336 unsigned j; 324 337 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) 326 340 continue; 327 341 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! 329 355 * Update the IP address of the corresponding SRV record. 330 356 */ 331 357 for (j=0; j<query_job->srv_cnt; ++j) { 332 if (pj_stricmp(&rr->name, &query_job->srv[j].target_name)==0 && 333 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 { 335 361 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 337 376 /* Only increment host_resolved once per SRV record */ 338 377 if (query_job->srv[j].addr_cnt == 0) 339 378 ++query_job->host_resolved; 379 340 380 ++query_job->srv[j].addr_cnt; 341 381 break; … … 355 395 } 356 396 */ 397 357 398 } 358 399 … … 363 404 for (i=0; i<query_job->srv_cnt; ++i) { 364 405 pj_in_addr addr; 406 pj_in6_addr addr6; 365 407 366 408 if (query_job->srv[i].addr_cnt != 0) { … … 369 411 } 370 412 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, 372 415 &addr) == PJ_SUCCESS) 373 416 { 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; 375 432 ++query_job->host_resolved; 376 433 } … … 388 445 389 446 for (i=0; i<query_job->srv_cnt; ++i) { 390 char addr[PJ_INET _ADDRSTRLEN];447 char addr[PJ_INET6_ADDRSTRLEN]; 391 448 392 449 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); 395 452 } else 396 453 pj_ansi_strcpy(addr, "-"); … … 408 465 409 466 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 */ 411 470 static pj_status_t resolve_hostnames(pj_dns_srv_async_query *query_job) 412 471 { … … 415 474 416 475 query_job->dns_state = PJ_DNS_TYPE_A; 476 417 477 for (i=0; i<query_job->srv_cnt; ++i) { 418 478 struct srv_target *srv = &query_job->srv[i]; … … 424 484 425 485 srv->common.type = PJ_DNS_TYPE_A; 486 srv->common_aaaa.type = PJ_DNS_TYPE_AAAA; 426 487 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 } 427 511 428 512 /* See also #1809: dns_callback() will be invoked synchronously when response … … 431 515 * returning false error, so don't use that variable for counting errors. 432 516 */ 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);438 517 if (status != PJ_SUCCESS) { 439 518 query_job->host_resolved++; … … 465 544 srv = (struct srv_target*) common; 466 545 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; 467 549 } else { 468 550 pj_assert(!"Unexpected user data!"); … … 475 557 /* We are getting SRV response */ 476 558 559 /* Clear the outstanding job */ 477 560 query_job->q_srv = NULL; 478 561 … … 508 591 */ 509 592 if (query_job->srv_cnt == 0) { 593 unsigned new_option = 0; 594 510 595 /* Looks like we aren't getting any SRV responses. 511 596 * Resolve the original target as A record by creating a … … 514 599 PJ_LOG(4, (query_job->objname, 515 600 "DNS SRV resolution failed for %.*s, trying " 516 "resolving A record for %.*s",601 "resolving A/AAAA record for %.*s", 517 602 (int)query_job->full_name.slen, 518 603 query_job->full_name.ptr, … … 527 612 query_job->srv[i].weight = 0; 528 613 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 } 530 624 531 625 532 /* Resolve server hostnames (DNS A record) for hosts which don't have533 * A record yet.626 /* Resolve server hostnames (DNS A/AAAA record) for hosts which 627 * don't have A/AAAA record yet. 534 628 */ 535 629 if (query_job->host_resolved != query_job->srv_cnt) { … … 545 639 546 640 } 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); 550 657 551 658 /* Check that we really have answer */ 552 659 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; 555 662 556 663 /* Parse response */ 557 status = pj_dns_parse_a _response(pkt, &rec);664 status = pj_dns_parse_addr_response(pkt, &rec); 558 665 if (status != PJ_SUCCESS) 559 666 goto on_error; … … 562 669 563 670 /* Update CNAME alias, if present. */ 564 if ( rec.alias.slen) {671 if (srv->cname.slen==0 && rec.alias.slen) { 565 672 pj_assert(rec.alias.slen <= (int)sizeof(srv->cname_buf)); 566 673 srv->cname.ptr = srv->cname_buf; 567 674 pj_strcpy(&srv->cname, &rec.alias); 568 } else {569 srv->cname.slen = 0;675 //} else { 676 //srv->cname.slen = 0; 570 677 } 571 678 572 679 /* 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) 586 681 { 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 } 595 718 } 596 719 … … 603 726 /* Log error */ 604 727 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"), 606 731 errmsg)); 607 732 } 608 733 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; 610 739 611 740 } else { … … 624 753 unsigned j; 625 754 struct srv_target *srv2 = &query_job->srv[i]; 755 pj_dns_addr_record *s = &srv_rec.entry[srv_rec.count].server; 626 756 627 757 srv_rec.entry[srv_rec.count].priority = srv2->priority; … … 635 765 pj_assert(srv2->addr_cnt <= PJ_DNS_MAX_IP_IN_A_REC); 636 766 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; 641 774 } 642 775 … … 681 814 status, 682 815 pj_strerror(status,errmsg,sizeof(errmsg)).ptr)); 816 817 /* Cancel any pending query */ 818 pj_dns_srv_cancel_query(query_job, PJ_FALSE); 819 683 820 (*query_job->cb)(query_job->token, status, NULL); 684 821 return; -
pjproject/trunk/pjnath/src/pjnath/stun_sock.c
r5296 r5349 417 417 pj_assert(stun_sock->q == NULL); 418 418 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; 423 424 424 425 status = pj_dns_srv_resolve(domain, &res_name, default_port, … … 575 576 pj_assert(rec->count); 576 577 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); 580 579 581 580 /* 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 } 585 590 586 591 /* Start sending Binding request */ -
pjproject/trunk/pjnath/src/pjnath/turn_session.c
r5170 r5349 609 609 } 610 610 611 /* Init DNS resolution option for IPv6 */ 612 if (sess->af == pj_AF_INET6()) 613 opt |= PJ_DNS_SRV_RESOLVE_AAAA_ONLY; 614 611 615 /* Fallback to DNS A only if default port is specified */ 612 616 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; 614 621 sess->default_port = (pj_uint16_t)default_port; 615 622 } … … 1719 1726 cnt<PJ_TURN_MAX_DNS_SRV_CNT; ++j) 1720 1727 { 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 } 1728 1740 } 1729 1741 } -
pjproject/trunk/pjsip/src/pjsip/sip_resolve.c
r5337 r5349 54 54 pjsip_resolver_callback *cb; 55 55 pj_dns_async_query *object; 56 pj_dns_async_query *object6; 56 57 pj_status_t last_error; 57 58 … … 65 66 unsigned naptr_cnt; 66 67 struct naptr_target naptr[8]; 68 69 /* Query result */ 70 pjsip_server_addresses server; 67 71 }; 68 72 … … 81 85 pj_status_t status, 82 86 pj_dns_parsed_packet *response); 87 static void dns_aaaa_callback(void *user_data, 88 pj_status_t status, 89 pj_dns_parsed_packet *response); 83 90 84 91 … … 207 214 ip_addr_ver = get_ip_addr_ver(&target->addr.host); 208 215 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 */ 210 220 if ((ip_addr_ver == 6) || (type & PJSIP_TRANSPORT_IPV6)) 211 221 af = pj_AF_INET6(); … … 402 412 403 413 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; 404 423 405 424 status = pj_dns_srv_resolve(&query->naptr[0].name, 406 425 &query->naptr[0].res_type, 407 426 query->req.def_port, pool, resolver->res, 408 PJ_TRUE, query, &srv_resolver_cb, NULL);427 opt, query, &srv_resolver_cb, NULL); 409 428 410 429 } else if (query->query_type == PJ_DNS_TYPE_A) { 411 430 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 } 417 448 418 449 } else { … … 455 486 { 456 487 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 464 493 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 469 522 char errmsg[PJ_ERR_MSG_SIZE]; 470 523 … … 474 527 errmsg)); 475 528 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 */ 545 static 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 } 500 602 } 501 603 … … 515 617 /* Log error */ 516 618 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", 518 620 errmsg)); 519 621 … … 526 628 srv.count = 0; 527 629 for (i=0; i<rec->count; ++i) { 630 const pj_dns_addr_record *s = &rec->entry[i].server; 528 631 unsigned j; 529 632 530 for (j = 0; j < rec->entry[i].server.addr_count &&633 for (j = 0; j < s->addr_count && 531 634 srv.count < PJSIP_MAX_RESOLVED_ADDRESSES; ++j) 532 635 { … … 535 638 srv.entry[srv.count].weight = rec->entry[i].weight; 536 639 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; 541 651 542 652 ++srv.count;
Note: See TracChangeset
for help on using the changeset viewer.