1
/* $Id: resolver_test.c 4537 2013-06-19 06:47:43Z riza $ */
3
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
#include <pjlib-util.h>
25
#define THIS_FILE "srv_resolver_test.c"
27
////////////////////////////////////////////////////////////////////////////
29
* TODO: create various invalid DNS packets.
33
////////////////////////////////////////////////////////////////////////////
36
#define ACTION_REPLY 0
37
#define ACTION_IGNORE -1
40
static struct server_t
47
* 0: reply with the response in resp.
48
* -1: ignore query (to simulate timeout).
49
* other: reply with that error
53
pj_dns_parsed_packet resp;
54
void (*action_cb)(const pj_dns_parsed_packet *pkt,
55
pj_dns_parsed_packet **p_res);
61
static pj_pool_t *pool;
62
static pj_dns_resolver *resolver;
63
static pj_bool_t thread_quit;
64
static pj_timer_heap_t *timer_heap;
65
static pj_ioqueue_t *ioqueue;
66
static pj_thread_t *poll_thread;
68
static pj_dns_settings set;
82
static void write16(pj_uint8_t *p, pj_uint16_t val)
84
p[0] = (pj_uint8_t)(val >> 8);
85
p[1] = (pj_uint8_t)(val & 0xFF);
88
static void write32(pj_uint8_t *p, pj_uint32_t val)
91
pj_memcpy(p, &val, 4);
94
static int print_name(pj_uint8_t *pkt, int size,
95
pj_uint8_t *pos, const pj_str_t *name,
96
struct label_tab *tab)
99
const char *endlabel, *endname;
103
/* Check if name is in the table */
104
for (i=0; i<tab->count; ++i) {
105
if (pj_strcmp(&tab->a[i].label, name)==0)
109
if (i != tab->count) {
110
write16(p, (pj_uint16_t)(tab->a[i].pos | (0xc0 << 8)));
113
if (tab->count < MAX_LABEL) {
114
tab->a[tab->count].pos = (unsigned)(p-pkt);
115
tab->a[tab->count].label.ptr = (char*)(p+1);
116
tab->a[tab->count].label.slen = name->slen;
121
endlabel = name->ptr;
122
endname = name->ptr + name->slen;
124
label.ptr = (char*)name->ptr;
126
while (endlabel != endname) {
128
while (endlabel != endname && *endlabel != '.')
131
label.slen = (endlabel - label.ptr);
133
if (size < label.slen+1)
136
*p = (pj_uint8_t)label.slen;
137
pj_memcpy(p+1, label.ptr, label.slen);
139
size -= (int)(label.slen+1);
142
if (endlabel != endname && *endlabel == '.')
144
label.ptr = (char*)endlabel;
155
static int print_rr(pj_uint8_t *pkt, int size, pj_uint8_t *pos,
156
const pj_dns_parsed_rr *rr, struct label_tab *tab)
161
len = print_name(pkt, size, pos, &rr->name, tab);
171
pj_assert(rr->dnsclass == 1);
173
write16(p+0, (pj_uint16_t)rr->type); /* type */
174
write16(p+2, (pj_uint16_t)rr->dnsclass); /* class */
175
write32(p+4, rr->ttl); /* TTL */
180
if (rr->type == PJ_DNS_TYPE_A) {
189
pj_memcpy(p+2, &rr->rdata.a.ip_addr, 4);
194
} else if (rr->type == PJ_DNS_TYPE_CNAME ||
195
rr->type == PJ_DNS_TYPE_NS ||
196
rr->type == PJ_DNS_TYPE_PTR) {
201
len = print_name(pkt, size-2, p+2, &rr->rdata.cname.name, tab);
205
write16(p, (pj_uint16_t)len);
210
} else if (rr->type == PJ_DNS_TYPE_SRV) {
215
write16(p+2, rr->rdata.srv.prio); /* Priority */
216
write16(p+4, rr->rdata.srv.weight); /* Weight */
217
write16(p+6, rr->rdata.srv.port); /* Port */
220
len = print_name(pkt, size-8, p+8, &rr->rdata.srv.target, tab);
225
write16(p, (pj_uint16_t)(len + 6));
231
pj_assert(!"Not supported");
238
static int print_packet(const pj_dns_parsed_packet *rec, pj_uint8_t *pkt,
242
struct label_tab tab;
248
pj_enter_critical_section();
249
PJ_LOG(3,(THIS_FILE, "Sending response:"));
250
pj_dns_dump_packet(rec);
251
pj_leave_critical_section();
254
pj_assert(sizeof(pj_dns_hdr)==12);
255
if (size < (int)sizeof(pj_dns_hdr))
258
/* Initialize header */
259
write16(p+0, rec->hdr.id);
260
write16(p+2, rec->hdr.flags);
261
write16(p+4, rec->hdr.qdcount);
262
write16(p+6, rec->hdr.anscount);
263
write16(p+8, rec->hdr.nscount);
264
write16(p+10, rec->hdr.arcount);
266
p = pkt + sizeof(pj_dns_hdr);
267
size -= sizeof(pj_dns_hdr);
270
for (i=0; i<rec->hdr.qdcount; ++i) {
272
len = print_name(pkt, size, p, &rec->q[i].name, &tab);
283
write16(p+0, (pj_uint16_t)rec->q[i].type);
285
/* Set class (IN=1) */
286
pj_assert(rec->q[i].dnsclass == 1);
287
write16(p+2, rec->q[i].dnsclass);
293
for (i=0; i<rec->hdr.anscount; ++i) {
294
len = print_rr(pkt, size, p, &rec->ans[i], &tab);
302
/* Print NS records */
303
for (i=0; i<rec->hdr.nscount; ++i) {
304
len = print_rr(pkt, size, p, &rec->ns[i], &tab);
312
/* Print additional records */
313
for (i=0; i<rec->hdr.arcount; ++i) {
314
len = print_rr(pkt, size, p, &rec->arr[i], &tab);
322
return (int)(p - pkt);
326
static int server_thread(void *p)
328
struct server_t *srv = (struct server_t*)p;
330
while (!thread_quit) {
332
pj_time_val timeout = {0, 500};
333
pj_sockaddr_in src_addr;
334
pj_dns_parsed_packet *req;
340
PJ_FD_SET(srv->sock, &rset);
342
rc = pj_sock_select((int)(srv->sock+1), &rset, NULL, NULL, &timeout);
346
src_len = sizeof(src_addr);
347
pkt_len = sizeof(pkt);
348
rc = pj_sock_recvfrom(srv->sock, pkt, &pkt_len, 0,
349
&src_addr, &src_len);
351
app_perror("Server error receiving packet", rc);
355
PJ_LOG(5,(THIS_FILE, "Server %d processing packet", srv - &g_server[0]));
358
rc = pj_dns_parse_packet(pool, pkt, (unsigned)pkt_len, &req);
359
if (rc != PJ_SUCCESS) {
360
app_perror("server error parsing packet", rc);
365
pj_assert(req->hdr.qdcount == 1);
366
pj_assert(req->q[0].dnsclass == 1);
368
/* Simulate network RTT */
371
if (srv->action == ACTION_IGNORE) {
373
} else if (srv->action == ACTION_REPLY) {
374
srv->resp.hdr.id = req->hdr.id;
375
pkt_len = print_packet(&srv->resp, (pj_uint8_t*)pkt, sizeof(pkt));
376
pj_sock_sendto(srv->sock, pkt, &pkt_len, 0, &src_addr, src_len);
377
} else if (srv->action == ACTION_CB) {
378
pj_dns_parsed_packet *resp;
379
(*srv->action_cb)(req, &resp);
380
resp->hdr.id = req->hdr.id;
381
pkt_len = print_packet(resp, (pj_uint8_t*)pkt, sizeof(pkt));
382
pj_sock_sendto(srv->sock, pkt, &pkt_len, 0, &src_addr, src_len);
383
} else if (srv->action > 0) {
384
req->hdr.flags |= PJ_DNS_SET_RCODE(srv->action);
385
pkt_len = print_packet(req, (pj_uint8_t*)pkt, sizeof(pkt));
386
pj_sock_sendto(srv->sock, pkt, &pkt_len, 0, &src_addr, src_len);
393
static int poll_worker_thread(void *p)
397
while (!thread_quit) {
398
pj_time_val delay = {0, 100};
399
pj_timer_heap_poll(timer_heap, NULL);
400
pj_ioqueue_poll(ioqueue, &delay);
406
static void destroy(void);
408
static int init(void)
411
pj_str_t nameservers[2];
412
pj_uint16_t ports[2];
415
nameservers[0] = pj_str("127.0.0.1");
417
nameservers[1] = pj_str("127.0.0.1");
420
g_server[0].port = ports[0];
421
g_server[1].port = ports[1];
423
pool = pj_pool_create(mem, NULL, 2000, 2000, NULL);
425
status = pj_sem_create(pool, NULL, 0, 2, &sem);
426
pj_assert(status == PJ_SUCCESS);
428
for (i=0; i<2; ++i) {
431
status = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &g_server[i].sock);
432
if (status != PJ_SUCCESS)
435
pj_sockaddr_in_init(&addr, NULL, (pj_uint16_t)g_server[i].port);
437
status = pj_sock_bind(g_server[i].sock, &addr, sizeof(addr));
438
if (status != PJ_SUCCESS)
441
status = pj_thread_create(pool, NULL, &server_thread, &g_server[i],
442
0, 0, &g_server[i].thread);
443
if (status != PJ_SUCCESS)
447
status = pj_timer_heap_create(pool, 16, &timer_heap);
448
pj_assert(status == PJ_SUCCESS);
450
status = pj_ioqueue_create(pool, 16, &ioqueue);
451
pj_assert(status == PJ_SUCCESS);
453
status = pj_dns_resolver_create(mem, NULL, 0, timer_heap, ioqueue, &resolver);
454
if (status != PJ_SUCCESS)
457
pj_dns_resolver_get_settings(resolver, &set);
458
set.good_ns_ttl = 20;
460
pj_dns_resolver_set_settings(resolver, &set);
462
status = pj_dns_resolver_set_ns(resolver, 2, nameservers, ports);
463
pj_assert(status == PJ_SUCCESS);
465
status = pj_thread_create(pool, NULL, &poll_worker_thread, NULL, 0, 0, &poll_thread);
466
pj_assert(status == PJ_SUCCESS);
472
static void destroy(void)
476
thread_quit = PJ_TRUE;
478
for (i=0; i<2; ++i) {
479
pj_thread_join(g_server[i].thread);
480
pj_sock_close(g_server[i].sock);
483
pj_thread_join(poll_thread);
485
pj_dns_resolver_destroy(resolver, PJ_FALSE);
486
pj_ioqueue_destroy(ioqueue);
487
pj_timer_heap_destroy(timer_heap);
490
pj_pool_release(pool);
494
////////////////////////////////////////////////////////////////////////////
495
/* DNS A parser tests */
496
static int a_parser_test(void)
498
pj_dns_parsed_packet pkt;
502
PJ_LOG(3,(THIS_FILE, " DNS A record parser tests"));
504
pkt.q = PJ_POOL_ZALLOC_T(pool, pj_dns_parsed_query);
505
pkt.ans = (pj_dns_parsed_rr*)
506
pj_pool_calloc(pool, 32, sizeof(pj_dns_parsed_rr));
508
/* Simple answer with direct A record, but with addition of
509
* a CNAME and another A to confuse the parser.
511
PJ_LOG(3,(THIS_FILE, " A RR with duplicate CNAME/A"));
514
pkt.q[0].type = PJ_DNS_TYPE_A;
515
pkt.q[0].dnsclass = 1;
516
pkt.q[0].name = pj_str("ahost");
517
pkt.hdr.anscount = 3;
519
/* This is the RR corresponding to the query */
520
pkt.ans[0].name = pj_str("ahost");
521
pkt.ans[0].type = PJ_DNS_TYPE_A;
522
pkt.ans[0].dnsclass = 1;
524
pkt.ans[0].rdata.a.ip_addr.s_addr = 0x01020304;
526
/* CNAME to confuse the parser */
527
pkt.ans[1].name = pj_str("ahost");
528
pkt.ans[1].type = PJ_DNS_TYPE_CNAME;
529
pkt.ans[1].dnsclass = 1;
531
pkt.ans[1].rdata.cname.name = pj_str("bhost");
533
/* DNS A RR to confuse the parser */
534
pkt.ans[2].name = pj_str("bhost");
535
pkt.ans[2].type = PJ_DNS_TYPE_A;
536
pkt.ans[2].dnsclass = 1;
538
pkt.ans[2].rdata.a.ip_addr.s_addr = 0x0203;
541
rc = pj_dns_parse_a_response(&pkt, &rec);
542
pj_assert(rc == PJ_SUCCESS);
543
pj_assert(pj_strcmp2(&rec.name, "ahost")==0);
544
pj_assert(rec.alias.slen == 0);
545
pj_assert(rec.addr_count == 1);
546
pj_assert(rec.addr[0].s_addr == 0x01020304);
548
/* Answer with the target corresponds to a CNAME entry, but not
549
* as the first record, and with additions of some CNAME and A
550
* entries to confuse the parser.
552
PJ_LOG(3,(THIS_FILE, " CNAME RR with duplicate CNAME/A"));
555
pkt.q[0].type = PJ_DNS_TYPE_A;
556
pkt.q[0].dnsclass = 1;
557
pkt.q[0].name = pj_str("ahost");
558
pkt.hdr.anscount = 4;
560
/* This is the DNS A record for the alias */
561
pkt.ans[0].name = pj_str("ahostalias");
562
pkt.ans[0].type = PJ_DNS_TYPE_A;
563
pkt.ans[0].dnsclass = 1;
565
pkt.ans[0].rdata.a.ip_addr.s_addr = 0x02020202;
567
/* CNAME entry corresponding to the query */
568
pkt.ans[1].name = pj_str("ahost");
569
pkt.ans[1].type = PJ_DNS_TYPE_CNAME;
570
pkt.ans[1].dnsclass = 1;
572
pkt.ans[1].rdata.cname.name = pj_str("ahostalias");
574
/* Another CNAME to confuse the parser */
575
pkt.ans[2].name = pj_str("ahost");
576
pkt.ans[2].type = PJ_DNS_TYPE_CNAME;
577
pkt.ans[2].dnsclass = 1;
579
pkt.ans[2].rdata.cname.name = pj_str("ahostalias2");
581
/* Another DNS A to confuse the parser */
582
pkt.ans[3].name = pj_str("ahostalias2");
583
pkt.ans[3].type = PJ_DNS_TYPE_A;
584
pkt.ans[3].dnsclass = 1;
586
pkt.ans[3].rdata.a.ip_addr.s_addr = 0x03030303;
588
rc = pj_dns_parse_a_response(&pkt, &rec);
589
pj_assert(rc == PJ_SUCCESS);
590
pj_assert(pj_strcmp2(&rec.name, "ahost")==0);
591
pj_assert(pj_strcmp2(&rec.alias, "ahostalias")==0);
592
pj_assert(rec.addr_count == 1);
593
pj_assert(rec.addr[0].s_addr == 0x02020202);
598
PJ_LOG(3,(THIS_FILE, " No query section"));
600
pkt.hdr.anscount = 0;
602
rc = pj_dns_parse_a_response(&pkt, &rec);
603
pj_assert(rc == PJLIB_UTIL_EDNSINANSWER);
608
PJ_LOG(3,(THIS_FILE, " No answer section"));
611
pkt.q[0].type = PJ_DNS_TYPE_A;
612
pkt.q[0].dnsclass = 1;
613
pkt.q[0].name = pj_str("ahost");
614
pkt.hdr.anscount = 0;
616
rc = pj_dns_parse_a_response(&pkt, &rec);
617
pj_assert(rc == PJLIB_UTIL_EDNSNOANSWERREC);
620
* Answer doesn't match query.
622
PJ_LOG(3,(THIS_FILE, " Answer doesn't match query"));
625
pkt.q[0].type = PJ_DNS_TYPE_A;
626
pkt.q[0].dnsclass = 1;
627
pkt.q[0].name = pj_str("ahost");
628
pkt.hdr.anscount = 1;
630
/* An answer that doesn't match the query */
631
pkt.ans[0].name = pj_str("ahostalias");
632
pkt.ans[0].type = PJ_DNS_TYPE_A;
633
pkt.ans[0].dnsclass = 1;
635
pkt.ans[0].rdata.a.ip_addr.s_addr = 0x02020202;
637
rc = pj_dns_parse_a_response(&pkt, &rec);
638
pj_assert(rc == PJLIB_UTIL_EDNSNOANSWERREC);
642
* DNS CNAME that doesn't have corresponding DNS A.
644
PJ_LOG(3,(THIS_FILE, " CNAME with no matching DNS A RR (1)"));
647
pkt.q[0].type = PJ_DNS_TYPE_A;
648
pkt.q[0].dnsclass = 1;
649
pkt.q[0].name = pj_str("ahost");
650
pkt.hdr.anscount = 1;
653
pkt.ans[0].name = pj_str("ahost");
654
pkt.ans[0].type = PJ_DNS_TYPE_CNAME;
655
pkt.ans[0].dnsclass = 1;
657
pkt.ans[0].rdata.cname.name = pj_str("ahostalias");
659
rc = pj_dns_parse_a_response(&pkt, &rec);
660
pj_assert(rc == PJLIB_UTIL_EDNSNOANSWERREC);
664
* DNS CNAME that doesn't have corresponding DNS A.
666
PJ_LOG(3,(THIS_FILE, " CNAME with no matching DNS A RR (2)"));
669
pkt.q[0].type = PJ_DNS_TYPE_A;
670
pkt.q[0].dnsclass = 1;
671
pkt.q[0].name = pj_str("ahost");
672
pkt.hdr.anscount = 2;
675
pkt.ans[0].name = pj_str("ahost");
676
pkt.ans[0].type = PJ_DNS_TYPE_CNAME;
677
pkt.ans[0].dnsclass = 1;
679
pkt.ans[0].rdata.cname.name = pj_str("ahostalias");
681
/* DNS A record, but the name doesn't match */
682
pkt.ans[1].name = pj_str("ahost");
683
pkt.ans[1].type = PJ_DNS_TYPE_A;
684
pkt.ans[1].dnsclass = 1;
686
pkt.ans[1].rdata.a.ip_addr.s_addr = 0x01020304;
688
rc = pj_dns_parse_a_response(&pkt, &rec);
689
pj_assert(rc == PJLIB_UTIL_EDNSNOANSWERREC);
695
////////////////////////////////////////////////////////////////////////////
696
/* Simple DNS test */
697
#define IP_ADDR0 0x00010203
699
static void dns_callback(void *user_data,
701
pj_dns_parsed_packet *resp)
703
PJ_UNUSED_ARG(user_data);
707
PJ_ASSERT_ON_FAIL(status == PJ_SUCCESS, return);
708
PJ_ASSERT_ON_FAIL(resp, return);
709
PJ_ASSERT_ON_FAIL(resp->hdr.anscount == 1, return);
710
PJ_ASSERT_ON_FAIL(resp->ans[0].type == PJ_DNS_TYPE_A, return);
711
PJ_ASSERT_ON_FAIL(resp->ans[0].rdata.a.ip_addr.s_addr == IP_ADDR0, return);
716
static int simple_test(void)
718
pj_str_t name = pj_str("helloworld");
719
pj_dns_parsed_packet *r;
722
PJ_LOG(3,(THIS_FILE, " simple successful test"));
724
g_server[0].pkt_count = 0;
725
g_server[1].pkt_count = 0;
727
g_server[0].action = ACTION_REPLY;
728
r = &g_server[0].resp;
731
r->q = PJ_POOL_ZALLOC_T(pool, pj_dns_parsed_query);
732
r->q[0].type = PJ_DNS_TYPE_A;
733
r->q[0].dnsclass = 1;
735
r->ans = PJ_POOL_ZALLOC_T(pool, pj_dns_parsed_rr);
736
r->ans[0].type = PJ_DNS_TYPE_A;
737
r->ans[0].dnsclass = 1;
738
r->ans[0].name = name;
739
r->ans[0].rdata.a.ip_addr.s_addr = IP_ADDR0;
741
g_server[1].action = ACTION_REPLY;
742
r = &g_server[1].resp;
745
r->q = PJ_POOL_ZALLOC_T(pool, pj_dns_parsed_query);
746
r->q[0].type = PJ_DNS_TYPE_A;
747
r->q[0].dnsclass = 1;
749
r->ans = PJ_POOL_ZALLOC_T(pool, pj_dns_parsed_rr);
750
r->ans[0].type = PJ_DNS_TYPE_A;
751
r->ans[0].dnsclass = 1;
752
r->ans[0].name = name;
753
r->ans[0].rdata.a.ip_addr.s_addr = IP_ADDR0;
755
status = pj_dns_resolver_start_query(resolver, &name, PJ_DNS_TYPE_A, 0,
756
&dns_callback, NULL, NULL);
757
if (status != PJ_SUCCESS)
761
pj_thread_sleep(1000);
764
/* Both servers must get packet */
765
pj_assert(g_server[0].pkt_count == 1);
766
pj_assert(g_server[1].pkt_count == 1);
772
////////////////////////////////////////////////////////////////////////////
773
/* DNS nameserver fail-over test */
775
static void dns_callback_1b(void *user_data,
777
pj_dns_parsed_packet *resp)
779
PJ_UNUSED_ARG(user_data);
784
PJ_ASSERT_ON_FAIL(status==PJ_STATUS_FROM_DNS_RCODE(PJ_DNS_RCODE_NXDOMAIN),
792
static int dns_test(void)
794
pj_str_t name = pj_str("name00");
797
PJ_LOG(3,(THIS_FILE, " simple error response test"));
799
g_server[0].pkt_count = 0;
800
g_server[1].pkt_count = 0;
802
g_server[0].action = PJ_DNS_RCODE_NXDOMAIN;
803
g_server[1].action = PJ_DNS_RCODE_NXDOMAIN;
805
status = pj_dns_resolver_start_query(resolver, &name, PJ_DNS_TYPE_A, 0,
806
&dns_callback_1b, NULL, NULL);
807
if (status != PJ_SUCCESS)
811
pj_thread_sleep(1000);
813
/* Now only server 0 should get packet, since both servers are
814
* in STATE_ACTIVE state
816
pj_assert((g_server[0].pkt_count == 1 && g_server[1].pkt_count == 0) ||
817
(g_server[1].pkt_count == 1 && g_server[0].pkt_count == 0));
819
/* Wait to allow probing period to complete */
820
PJ_LOG(3,(THIS_FILE, " waiting for active NS to expire (%d sec)",
822
pj_thread_sleep(set.good_ns_ttl * 1000);
827
PJ_LOG(3,(THIS_FILE, " failing server0"));
828
g_server[0].action = ACTION_IGNORE;
829
g_server[1].action = PJ_DNS_RCODE_NXDOMAIN;
831
g_server[0].pkt_count = 0;
832
g_server[1].pkt_count = 0;
834
name = pj_str("name01");
835
status = pj_dns_resolver_start_query(resolver, &name, PJ_DNS_TYPE_A, 0,
836
&dns_callback_1b, NULL, NULL);
837
if (status != PJ_SUCCESS)
843
* Check that both servers still receive requests, since they are
846
PJ_LOG(3,(THIS_FILE, " checking both NS during probing period"));
847
g_server[0].action = ACTION_IGNORE;
848
g_server[1].action = PJ_DNS_RCODE_NXDOMAIN;
850
g_server[0].pkt_count = 0;
851
g_server[1].pkt_count = 0;
853
name = pj_str("name02");
854
status = pj_dns_resolver_start_query(resolver, &name, PJ_DNS_TYPE_A, 0,
855
&dns_callback_1b, NULL, NULL);
856
if (status != PJ_SUCCESS)
860
pj_thread_sleep(set.qretr_delay * set.qretr_count);
862
/* Both servers must get requests */
863
pj_assert(g_server[0].pkt_count >= 1);
864
pj_assert(g_server[1].pkt_count == 1);
866
/* Wait to allow probing period to complete */
867
PJ_LOG(3,(THIS_FILE, " waiting for probing state to end (%d sec)",
869
(set.qretr_count+2) / 1000));
870
pj_thread_sleep(set.qretr_delay * (set.qretr_count + 2));
874
* Now only server 1 should get requests.
876
PJ_LOG(3,(THIS_FILE, " verifying only good NS is used"));
877
g_server[0].action = PJ_DNS_RCODE_NXDOMAIN;
878
g_server[1].action = PJ_DNS_RCODE_NXDOMAIN;
880
g_server[0].pkt_count = 0;
881
g_server[1].pkt_count = 0;
883
name = pj_str("name03");
884
status = pj_dns_resolver_start_query(resolver, &name, PJ_DNS_TYPE_A, 0,
885
&dns_callback_1b, NULL, NULL);
886
if (status != PJ_SUCCESS)
890
pj_thread_sleep(1000);
892
/* Both servers must get requests */
893
pj_assert(g_server[0].pkt_count == 0);
894
pj_assert(g_server[1].pkt_count == 1);
896
/* Wait to allow probing period to complete */
897
PJ_LOG(3,(THIS_FILE, " waiting for active NS to expire (%d sec)",
899
pj_thread_sleep(set.good_ns_ttl * 1000);
902
* Now fail server 1 to switch to server 0
904
g_server[0].action = PJ_DNS_RCODE_NXDOMAIN;
905
g_server[1].action = ACTION_IGNORE;
907
g_server[0].pkt_count = 0;
908
g_server[1].pkt_count = 0;
910
name = pj_str("name04");
911
status = pj_dns_resolver_start_query(resolver, &name, PJ_DNS_TYPE_A, 0,
912
&dns_callback_1b, NULL, NULL);
913
if (status != PJ_SUCCESS)
918
/* Wait to allow probing period to complete */
919
PJ_LOG(3,(THIS_FILE, " waiting for probing state (%d sec)",
920
set.qretr_delay * (set.qretr_count+2) / 1000));
921
pj_thread_sleep(set.qretr_delay * (set.qretr_count + 2));
924
* Now only server 0 should get requests.
926
PJ_LOG(3,(THIS_FILE, " verifying good NS"));
927
g_server[0].action = PJ_DNS_RCODE_NXDOMAIN;
928
g_server[1].action = ACTION_IGNORE;
930
g_server[0].pkt_count = 0;
931
g_server[1].pkt_count = 0;
933
name = pj_str("name05");
934
status = pj_dns_resolver_start_query(resolver, &name, PJ_DNS_TYPE_A, 0,
935
&dns_callback_1b, NULL, NULL);
936
if (status != PJ_SUCCESS)
940
pj_thread_sleep(1000);
942
/* Only good NS should get request */
943
pj_assert(g_server[0].pkt_count == 1);
944
pj_assert(g_server[1].pkt_count == 0);
951
////////////////////////////////////////////////////////////////////////////
952
/* Resolver test, normal, with CNAME */
953
#define IP_ADDR1 0x02030405
956
static void action1_1(const pj_dns_parsed_packet *pkt,
957
pj_dns_parsed_packet **p_res)
959
pj_dns_parsed_packet *res;
960
char *target = "sip.somedomain.com";
962
res = PJ_POOL_ZALLOC_T(pool, pj_dns_parsed_packet);
964
if (res->q == NULL) {
965
res->q = PJ_POOL_ZALLOC_T(pool, pj_dns_parsed_query);
967
if (res->ans == NULL) {
968
res->ans = (pj_dns_parsed_rr*)
969
pj_pool_calloc(pool, 4, sizeof(pj_dns_parsed_rr));
972
res->hdr.qdcount = 1;
973
res->q[0].type = pkt->q[0].type;
974
res->q[0].dnsclass = pkt->q[0].dnsclass;
975
res->q[0].name = pkt->q[0].name;
977
if (pkt->q[0].type == PJ_DNS_TYPE_SRV) {
979
pj_assert(pj_strcmp2(&pkt->q[0].name, "_sip._udp.somedomain.com")==0);
981
res->hdr.anscount = 1;
982
res->ans[0].type = PJ_DNS_TYPE_SRV;
983
res->ans[0].dnsclass = 1;
984
res->ans[0].name = res->q[0].name;
986
res->ans[0].rdata.srv.prio = 1;
987
res->ans[0].rdata.srv.weight = 2;
988
res->ans[0].rdata.srv.port = PORT1;
989
res->ans[0].rdata.srv.target = pj_str(target);
991
} else if (pkt->q[0].type == PJ_DNS_TYPE_A) {
992
char *alias = "sipalias.somedomain.com";
994
pj_assert(pj_strcmp2(&res->q[0].name, target)==0);
996
res->hdr.anscount = 2;
997
res->ans[0].type = PJ_DNS_TYPE_CNAME;
998
res->ans[0].dnsclass = 1;
999
res->ans[0].ttl = 1000; /* resolver should select minimum TTL */
1000
res->ans[0].name = res->q[0].name;
1001
res->ans[0].rdata.cname.name = pj_str(alias);
1003
res->ans[1].type = PJ_DNS_TYPE_A;
1004
res->ans[1].dnsclass = 1;
1005
res->ans[1].ttl = 1;
1006
res->ans[1].name = pj_str(alias);
1007
res->ans[1].rdata.a.ip_addr.s_addr = IP_ADDR1;
1013
static void srv_cb_1(void *user_data,
1015
const pj_dns_srv_record *rec)
1017
PJ_UNUSED_ARG(user_data);
1021
PJ_ASSERT_ON_FAIL(status == PJ_SUCCESS, return);
1022
PJ_ASSERT_ON_FAIL(rec->count == 1, return);
1023
PJ_ASSERT_ON_FAIL(rec->entry[0].priority == 1, return);
1024
PJ_ASSERT_ON_FAIL(rec->entry[0].weight == 2, return);
1025
PJ_ASSERT_ON_FAIL(pj_strcmp2(&rec->entry[0].server.name, "sip.somedomain.com")==0,
1027
PJ_ASSERT_ON_FAIL(pj_strcmp2(&rec->entry[0].server.alias, "sipalias.somedomain.com")==0,
1029
PJ_ASSERT_ON_FAIL(rec->entry[0].server.addr[0].s_addr == IP_ADDR1, return);
1030
PJ_ASSERT_ON_FAIL(rec->entry[0].port == PORT1, return);
1035
static void srv_cb_1b(void *user_data,
1037
const pj_dns_srv_record *rec)
1039
PJ_UNUSED_ARG(user_data);
1043
PJ_ASSERT_ON_FAIL(status==PJ_STATUS_FROM_DNS_RCODE(PJ_DNS_RCODE_NXDOMAIN),
1045
PJ_ASSERT_ON_FAIL(rec->count == 0, return);
1048
static int srv_resolver_test(void)
1051
pj_str_t domain = pj_str("somedomain.com");
1052
pj_str_t res_name = pj_str("_sip._udp.");
1054
/* Successful scenario */
1055
PJ_LOG(3,(THIS_FILE, " srv_resolve(): success scenario"));
1057
g_server[0].action = ACTION_CB;
1058
g_server[0].action_cb = &action1_1;
1059
g_server[1].action = ACTION_CB;
1060
g_server[1].action_cb = &action1_1;
1062
g_server[0].pkt_count = 0;
1063
g_server[1].pkt_count = 0;
1065
status = pj_dns_srv_resolve(&domain, &res_name, 5061, pool, resolver, PJ_TRUE,
1066
NULL, &srv_cb_1, NULL);
1067
pj_assert(status == PJ_SUCCESS);
1071
/* Because of previous tests, only NS 1 should get the request */
1072
pj_assert(g_server[0].pkt_count == 2); /* 2 because of SRV and A resolution */
1073
pj_assert(g_server[1].pkt_count == 0);
1076
/* Wait until cache expires and nameserver state moves out from STATE_PROBING */
1077
PJ_LOG(3,(THIS_FILE, " waiting for cache to expire (~15 secs).."));
1078
pj_thread_sleep(1000 +
1079
((set.qretr_count + 2) * set.qretr_delay));
1081
/* Successful scenario */
1082
PJ_LOG(3,(THIS_FILE, " srv_resolve(): parallel queries"));
1083
g_server[0].pkt_count = 0;
1084
g_server[1].pkt_count = 0;
1086
status = pj_dns_srv_resolve(&domain, &res_name, 5061, pool, resolver, PJ_TRUE,
1087
NULL, &srv_cb_1, NULL);
1088
pj_assert(status == PJ_SUCCESS);
1091
status = pj_dns_srv_resolve(&domain, &res_name, 5061, pool, resolver, PJ_TRUE,
1092
NULL, &srv_cb_1, NULL);
1093
pj_assert(status == PJ_SUCCESS);
1098
/* Only server one should get a query */
1099
pj_assert(g_server[0].pkt_count == 2); /* 2 because of SRV and A resolution */
1100
pj_assert(g_server[1].pkt_count == 0);
1102
/* Since TTL is one, subsequent queries should fail */
1103
PJ_LOG(3,(THIS_FILE, " srv_resolve(): cache expires scenario"));
1106
pj_thread_sleep(1000);
1108
g_server[0].action = PJ_DNS_RCODE_NXDOMAIN;
1109
g_server[1].action = PJ_DNS_RCODE_NXDOMAIN;
1111
status = pj_dns_srv_resolve(&domain, &res_name, 5061, pool, resolver, PJ_TRUE,
1112
NULL, &srv_cb_1b, NULL);
1113
pj_assert(status == PJ_SUCCESS);
1121
////////////////////////////////////////////////////////////////////////////
1122
/* Fallback because there's no SRV in answer */
1123
#define TARGET "domain2.com"
1124
#define IP_ADDR2 0x02030405
1127
static void action2_1(const pj_dns_parsed_packet *pkt,
1128
pj_dns_parsed_packet **p_res)
1130
pj_dns_parsed_packet *res;
1132
res = PJ_POOL_ZALLOC_T(pool, pj_dns_parsed_packet);
1134
res->q = PJ_POOL_ZALLOC_T(pool, pj_dns_parsed_query);
1135
res->ans = (pj_dns_parsed_rr*)
1136
pj_pool_calloc(pool, 4, sizeof(pj_dns_parsed_rr));
1138
res->hdr.qdcount = 1;
1139
res->q[0].type = pkt->q[0].type;
1140
res->q[0].dnsclass = pkt->q[0].dnsclass;
1141
res->q[0].name = pkt->q[0].name;
1143
if (pkt->q[0].type == PJ_DNS_TYPE_SRV) {
1145
pj_assert(pj_strcmp2(&pkt->q[0].name, "_sip._udp." TARGET)==0);
1147
res->hdr.anscount = 1;
1148
res->ans[0].type = PJ_DNS_TYPE_A; // <-- this will cause the fallback
1149
res->ans[0].dnsclass = 1;
1150
res->ans[0].name = res->q[0].name;
1151
res->ans[0].ttl = 1;
1152
res->ans[0].rdata.srv.prio = 1;
1153
res->ans[0].rdata.srv.weight = 2;
1154
res->ans[0].rdata.srv.port = PORT2;
1155
res->ans[0].rdata.srv.target = pj_str("sip01." TARGET);
1157
} else if (pkt->q[0].type == PJ_DNS_TYPE_A) {
1158
char *alias = "sipalias01." TARGET;
1160
pj_assert(pj_strcmp2(&res->q[0].name, TARGET)==0);
1162
res->hdr.anscount = 2;
1163
res->ans[0].type = PJ_DNS_TYPE_CNAME;
1164
res->ans[0].dnsclass = 1;
1165
res->ans[0].name = res->q[0].name;
1166
res->ans[0].ttl = 1;
1167
res->ans[0].rdata.cname.name = pj_str(alias);
1169
res->ans[1].type = PJ_DNS_TYPE_A;
1170
res->ans[1].dnsclass = 1;
1171
res->ans[1].name = pj_str(alias);
1172
res->ans[1].ttl = 1;
1173
res->ans[1].rdata.a.ip_addr.s_addr = IP_ADDR2;
1179
static void srv_cb_2(void *user_data,
1181
const pj_dns_srv_record *rec)
1183
PJ_UNUSED_ARG(user_data);
1187
PJ_ASSERT_ON_FAIL(status == PJ_SUCCESS, return);
1188
PJ_ASSERT_ON_FAIL(rec->count == 1, return);
1189
PJ_ASSERT_ON_FAIL(rec->entry[0].priority == 0, return);
1190
PJ_ASSERT_ON_FAIL(rec->entry[0].weight == 0, return);
1191
PJ_ASSERT_ON_FAIL(pj_strcmp2(&rec->entry[0].server.name, TARGET)==0,
1193
PJ_ASSERT_ON_FAIL(pj_strcmp2(&rec->entry[0].server.alias, "sipalias01." TARGET)==0,
1195
PJ_ASSERT_ON_FAIL(rec->entry[0].server.addr[0].s_addr == IP_ADDR2, return);
1196
PJ_ASSERT_ON_FAIL(rec->entry[0].port == PORT2, return);
1199
static int srv_resolver_fallback_test(void)
1202
pj_str_t domain = pj_str(TARGET);
1203
pj_str_t res_name = pj_str("_sip._udp.");
1205
PJ_LOG(3,(THIS_FILE, " srv_resolve(): fallback test"));
1207
g_server[0].action = ACTION_CB;
1208
g_server[0].action_cb = &action2_1;
1209
g_server[1].action = ACTION_CB;
1210
g_server[1].action_cb = &action2_1;
1212
status = pj_dns_srv_resolve(&domain, &res_name, PORT2, pool, resolver, PJ_TRUE,
1213
NULL, &srv_cb_2, NULL);
1214
if (status != PJ_SUCCESS) {
1215
app_perror(" srv_resolve error", status);
1216
pj_assert(status == PJ_SUCCESS);
1221
/* Subsequent query should just get the response from the cache */
1222
PJ_LOG(3,(THIS_FILE, " srv_resolve(): cache test"));
1223
g_server[0].pkt_count = 0;
1224
g_server[1].pkt_count = 0;
1226
status = pj_dns_srv_resolve(&domain, &res_name, PORT2, pool, resolver, PJ_TRUE,
1227
NULL, &srv_cb_2, NULL);
1228
if (status != PJ_SUCCESS) {
1229
app_perror(" srv_resolve error", status);
1230
pj_assert(status == PJ_SUCCESS);
1235
pj_assert(g_server[0].pkt_count == 0);
1236
pj_assert(g_server[1].pkt_count == 0);
1242
////////////////////////////////////////////////////////////////////////////
1243
/* Too many SRV or A entries */
1244
#define DOMAIN3 "d3"
1245
#define SRV_COUNT3 (PJ_DNS_SRV_MAX_ADDR+1)
1246
#define A_COUNT3 (PJ_DNS_MAX_IP_IN_A_REC+1)
1248
#define IP_ADDR3 0x03030303
1250
static void action3_1(const pj_dns_parsed_packet *pkt,
1251
pj_dns_parsed_packet **p_res)
1253
pj_dns_parsed_packet *res;
1256
res = PJ_POOL_ZALLOC_T(pool, pj_dns_parsed_packet);
1258
if (res->q == NULL) {
1259
res->q = PJ_POOL_ZALLOC_T(pool, pj_dns_parsed_query);
1262
res->hdr.qdcount = 1;
1263
res->q[0].type = pkt->q[0].type;
1264
res->q[0].dnsclass = pkt->q[0].dnsclass;
1265
res->q[0].name = pkt->q[0].name;
1267
if (pkt->q[0].type == PJ_DNS_TYPE_SRV) {
1269
pj_assert(pj_strcmp2(&pkt->q[0].name, "_sip._udp." DOMAIN3)==0);
1271
res->hdr.anscount = SRV_COUNT3;
1272
res->ans = (pj_dns_parsed_rr*)
1273
pj_pool_calloc(pool, SRV_COUNT3, sizeof(pj_dns_parsed_rr));
1275
for (i=0; i<SRV_COUNT3; ++i) {
1278
res->ans[i].type = PJ_DNS_TYPE_SRV;
1279
res->ans[i].dnsclass = 1;
1280
res->ans[i].name = res->q[0].name;
1281
res->ans[i].ttl = 1;
1282
res->ans[i].rdata.srv.prio = (pj_uint16_t)i;
1283
res->ans[i].rdata.srv.weight = 2;
1284
res->ans[i].rdata.srv.port = (pj_uint16_t)(PORT3+i);
1286
target = (char*)pj_pool_alloc(pool, 16);
1287
sprintf(target, "sip%02d." DOMAIN3, i);
1288
res->ans[i].rdata.srv.target = pj_str(target);
1291
} else if (pkt->q[0].type == PJ_DNS_TYPE_A) {
1293
//pj_assert(pj_strcmp2(&res->q[0].name, "sip." DOMAIN3)==0);
1295
res->hdr.anscount = A_COUNT3;
1296
res->ans = (pj_dns_parsed_rr*)
1297
pj_pool_calloc(pool, A_COUNT3, sizeof(pj_dns_parsed_rr));
1299
for (i=0; i<A_COUNT3; ++i) {
1300
res->ans[i].type = PJ_DNS_TYPE_A;
1301
res->ans[i].dnsclass = 1;
1302
res->ans[i].ttl = 1;
1303
res->ans[i].name = res->q[0].name;
1304
res->ans[i].rdata.a.ip_addr.s_addr = IP_ADDR3+i;
1311
static void srv_cb_3(void *user_data,
1313
const pj_dns_srv_record *rec)
1317
PJ_UNUSED_ARG(user_data);
1318
PJ_UNUSED_ARG(status);
1321
pj_assert(status == PJ_SUCCESS);
1322
pj_assert(rec->count == PJ_DNS_SRV_MAX_ADDR);
1324
for (i=0; i<PJ_DNS_SRV_MAX_ADDR; ++i) {
1327
pj_assert(rec->entry[i].priority == i);
1328
pj_assert(rec->entry[i].weight == 2);
1329
//pj_assert(pj_strcmp2(&rec->entry[i].server.name, "sip." DOMAIN3)==0);
1330
pj_assert(rec->entry[i].server.alias.slen == 0);
1331
pj_assert(rec->entry[i].port == PORT3+i);
1333
pj_assert(rec->entry[i].server.addr_count == PJ_DNS_MAX_IP_IN_A_REC);
1335
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);
1343
static int srv_resolver_many_test(void)
1346
pj_str_t domain = pj_str(DOMAIN3);
1347
pj_str_t res_name = pj_str("_sip._udp.");
1349
/* Successful scenario */
1350
PJ_LOG(3,(THIS_FILE, " srv_resolve(): too many entries test"));
1352
g_server[0].action = ACTION_CB;
1353
g_server[0].action_cb = &action3_1;
1354
g_server[1].action = ACTION_CB;
1355
g_server[1].action_cb = &action3_1;
1357
g_server[0].pkt_count = 0;
1358
g_server[1].pkt_count = 0;
1360
status = pj_dns_srv_resolve(&domain, &res_name, 1, pool, resolver, PJ_TRUE,
1361
NULL, &srv_cb_3, NULL);
1362
pj_assert(status == PJ_SUCCESS);
1370
////////////////////////////////////////////////////////////////////////////
1373
int resolver_test(void)
1381
rc = a_parser_test();
1393
srv_resolver_test();
1394
srv_resolver_fallback_test();
1395
srv_resolver_many_test();