1 /* $Id$ */
2 /*
3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
5 *
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.
10 *
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.
15 *
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
19 */
20 #include <pjlib-util.h>
21 #include <pjlib.h>
22 #include "test.h"
23
24
25 #define THIS_FILE "srv_resolver_test.c"
26
27 ////////////////////////////////////////////////////////////////////////////
28 /*
29 * TODO: create various invalid DNS packets.
30 */
31
32
33 ////////////////////////////////////////////////////////////////////////////
34
35
36 #define ACTION_REPLY 0
37 #define ACTION_IGNORE -1
38 #define ACTION_CB -2
39
40 #undef s6_addr32
41 #define s6_addr32(addr, idx) *((pj_uint32_t *)(addr.s6_addr + idx*4))
42
43 static struct server_t
44 {
45 pj_sock_t sock;
46 pj_uint16_t port;
47 pj_thread_t *thread;
48
49 /* Action:
50 * 0: reply with the response in resp.
51 * -1: ignore query (to simulate timeout).
52 * other: reply with that error
53 */
54 int action;
55
56 pj_dns_parsed_packet resp;
57 void (*action_cb)(const pj_dns_parsed_packet *pkt,
58 pj_dns_parsed_packet **p_res);
59
60 unsigned pkt_count;
61
62 } g_server[2];
63
64 static pj_pool_t *pool;
65 static pj_dns_resolver *resolver;
66 static pj_bool_t thread_quit;
67 static pj_timer_heap_t *timer_heap;
68 static pj_ioqueue_t *ioqueue;
69 static pj_thread_t *poll_thread;
70 static pj_sem_t *sem;
71 static pj_dns_settings set;
72
73 #define MAX_LABEL 32
74
75 struct label_tab
76 {
77 unsigned count;
78
79 struct {
80 unsigned pos;
81 pj_str_t label;
82 } a[MAX_LABEL];
83 };
84
write16(pj_uint8_t * p,pj_uint16_t val)85 static void write16(pj_uint8_t *p, pj_uint16_t val)
86 {
87 p[0] = (pj_uint8_t)(val >> 8);
88 p[1] = (pj_uint8_t)(val & 0xFF);
89 }
90
write32(pj_uint8_t * p,pj_uint32_t val)91 static void write32(pj_uint8_t *p, pj_uint32_t val)
92 {
93 val = pj_htonl(val);
94 pj_memcpy(p, &val, 4);
95 }
96
print_name(pj_uint8_t * pkt,int size,pj_uint8_t * pos,const pj_str_t * name,struct label_tab * tab)97 static int print_name(pj_uint8_t *pkt, int size,
98 pj_uint8_t *pos, const pj_str_t *name,
99 struct label_tab *tab)
100 {
101 pj_uint8_t *p = pos;
102 const char *endlabel, *endname;
103 unsigned i;
104 pj_str_t label;
105
106 /* Check if name is in the table */
107 for (i=0; i<tab->count; ++i) {
108 if (pj_strcmp(&tab->a[i].label, name)==0)
109 break;
110 }
111
112 if (i != tab->count) {
113 write16(p, (pj_uint16_t)(tab->a[i].pos | (0xc0 << 8)));
114 return 2;
115 } else {
116 if (tab->count < MAX_LABEL) {
117 tab->a[tab->count].pos = (unsigned)(p-pkt);
118 tab->a[tab->count].label.ptr = (char*)(p+1);
119 tab->a[tab->count].label.slen = name->slen;
120 ++tab->count;
121 }
122 }
123
124 endlabel = name->ptr;
125 endname = name->ptr + name->slen;
126
127 label.ptr = (char*)name->ptr;
128
129 while (endlabel != endname) {
130
131 while (endlabel != endname && *endlabel != '.')
132 ++endlabel;
133
134 label.slen = (endlabel - label.ptr);
135
136 if (size < label.slen+1)
137 return -1;
138
139 *p = (pj_uint8_t)label.slen;
140 pj_memcpy(p+1, label.ptr, label.slen);
141
142 size -= (int)(label.slen+1);
143 p += (label.slen+1);
144
145 if (endlabel != endname && *endlabel == '.')
146 ++endlabel;
147 label.ptr = (char*)endlabel;
148 }
149
150 if (size == 0)
151 return -1;
152
153 *p++ = '\0';
154
155 return (int)(p-pos);
156 }
157
print_rr(pj_uint8_t * pkt,int size,pj_uint8_t * pos,const pj_dns_parsed_rr * rr,struct label_tab * tab)158 static int print_rr(pj_uint8_t *pkt, int size, pj_uint8_t *pos,
159 const pj_dns_parsed_rr *rr, struct label_tab *tab)
160 {
161 pj_uint8_t *p = pos;
162 int len;
163
164 len = print_name(pkt, size, pos, &rr->name, tab);
165 if (len < 0)
166 return -1;
167
168 p += len;
169 size -= len;
170
171 if (size < 8)
172 return -1;
173
174 pj_assert(rr->dnsclass == 1);
175
176 write16(p+0, (pj_uint16_t)rr->type); /* type */
177 write16(p+2, (pj_uint16_t)rr->dnsclass); /* class */
178 write32(p+4, rr->ttl); /* TTL */
179
180 p += 8;
181 size -= 8;
182
183 if (rr->type == PJ_DNS_TYPE_A) {
184
185 if (size < 6)
186 return -1;
187
188 /* RDLEN is 4 */
189 write16(p, 4);
190
191 /* Address */
192 pj_memcpy(p+2, &rr->rdata.a.ip_addr, 4);
193
194 p += 6;
195 size -= 6;
196
197 } else if (rr->type == PJ_DNS_TYPE_AAAA) {
198
199 if (size < 18)
200 return -1;
201
202 /* RDLEN is 16 */
203 write16(p, 16);
204
205 /* Address */
206 pj_memcpy(p+2, &rr->rdata.aaaa.ip_addr, 16);
207
208 p += 18;
209 size -= 18;
210
211 } else if (rr->type == PJ_DNS_TYPE_CNAME ||
212 rr->type == PJ_DNS_TYPE_NS ||
213 rr->type == PJ_DNS_TYPE_PTR) {
214
215 if (size < 4)
216 return -1;
217
218 len = print_name(pkt, size-2, p+2, &rr->rdata.cname.name, tab);
219 if (len < 0)
220 return -1;
221
222 write16(p, (pj_uint16_t)len);
223
224 p += (len + 2);
225 size -= (len + 2);
226
227 } else if (rr->type == PJ_DNS_TYPE_SRV) {
228
229 if (size < 10)
230 return -1;
231
232 write16(p+2, rr->rdata.srv.prio); /* Priority */
233 write16(p+4, rr->rdata.srv.weight); /* Weight */
234 write16(p+6, rr->rdata.srv.port); /* Port */
235
236 /* Target */
237 len = print_name(pkt, size-8, p+8, &rr->rdata.srv.target, tab);
238 if (len < 0)
239 return -1;
240
241 /* RDLEN */
242 write16(p, (pj_uint16_t)(len + 6));
243
244 p += (len + 8);
245 size -= (len + 8);
246
247 } else {
248 pj_assert(!"Not supported");
249 return -1;
250 }
251
252 return (int)(p-pos);
253 }
254
print_packet(const pj_dns_parsed_packet * rec,pj_uint8_t * pkt,int size)255 static int print_packet(const pj_dns_parsed_packet *rec, pj_uint8_t *pkt,
256 int size)
257 {
258 pj_uint8_t *p = pkt;
259 struct label_tab tab;
260 int i, len;
261
262 tab.count = 0;
263
264 #if 0
265 pj_enter_critical_section();
266 PJ_LOG(3,(THIS_FILE, "Sending response:"));
267 pj_dns_dump_packet(rec);
268 pj_leave_critical_section();
269 #endif
270
271 pj_assert(sizeof(pj_dns_hdr)==12);
272 if (size < (int)sizeof(pj_dns_hdr))
273 return -1;
274
275 /* Initialize header */
276 write16(p+0, rec->hdr.id);
277 write16(p+2, rec->hdr.flags);
278 write16(p+4, rec->hdr.qdcount);
279 write16(p+6, rec->hdr.anscount);
280 write16(p+8, rec->hdr.nscount);
281 write16(p+10, rec->hdr.arcount);
282
283 p = pkt + sizeof(pj_dns_hdr);
284 size -= sizeof(pj_dns_hdr);
285
286 /* Print queries */
287 for (i=0; i<rec->hdr.qdcount; ++i) {
288
289 len = print_name(pkt, size, p, &rec->q[i].name, &tab);
290 if (len < 0)
291 return -1;
292
293 p += len;
294 size -= len;
295
296 if (size < 4)
297 return -1;
298
299 /* Set type */
300 write16(p+0, (pj_uint16_t)rec->q[i].type);
301
302 /* Set class (IN=1) */
303 pj_assert(rec->q[i].dnsclass == 1);
304 write16(p+2, rec->q[i].dnsclass);
305
306 p += 4;
307 }
308
309 /* Print answers */
310 for (i=0; i<rec->hdr.anscount; ++i) {
311 len = print_rr(pkt, size, p, &rec->ans[i], &tab);
312 if (len < 0)
313 return -1;
314
315 p += len;
316 size -= len;
317 }
318
319 /* Print NS records */
320 for (i=0; i<rec->hdr.nscount; ++i) {
321 len = print_rr(pkt, size, p, &rec->ns[i], &tab);
322 if (len < 0)
323 return -1;
324
325 p += len;
326 size -= len;
327 }
328
329 /* Print additional records */
330 for (i=0; i<rec->hdr.arcount; ++i) {
331 len = print_rr(pkt, size, p, &rec->arr[i], &tab);
332 if (len < 0)
333 return -1;
334
335 p += len;
336 size -= len;
337 }
338
339 return (int)(p - pkt);
340 }
341
342
server_thread(void * p)343 static int server_thread(void *p)
344 {
345 struct server_t *srv = (struct server_t*)p;
346
347 while (!thread_quit) {
348 pj_fd_set_t rset;
349 pj_time_val timeout = {0, 500};
350 pj_sockaddr src_addr;
351 pj_dns_parsed_packet *req;
352 char pkt[1024];
353 pj_ssize_t pkt_len;
354 int rc, src_len;
355
356 PJ_FD_ZERO(&rset);
357 PJ_FD_SET(srv->sock, &rset);
358
359 rc = pj_sock_select((int)(srv->sock+1), &rset, NULL, NULL, &timeout);
360 if (rc != 1)
361 continue;
362
363 src_len = sizeof(src_addr);
364 pkt_len = sizeof(pkt);
365 rc = pj_sock_recvfrom(srv->sock, pkt, &pkt_len, 0,
366 &src_addr, &src_len);
367 if (rc != 0) {
368 app_perror("Server error receiving packet", rc);
369 continue;
370 }
371
372 PJ_LOG(5,(THIS_FILE, "Server %d processing packet", srv - &g_server[0]));
373 srv->pkt_count++;
374
375 rc = pj_dns_parse_packet(pool, pkt, (unsigned)pkt_len, &req);
376 if (rc != PJ_SUCCESS) {
377 app_perror("server error parsing packet", rc);
378 continue;
379 }
380
381 /* Verify packet */
382 if (req->hdr.qdcount != 1) {
383 PJ_LOG(5,(THIS_FILE, "server receive multiple queries in a packet"));
384 continue;
385 }
386
387 if (req->q[0].dnsclass != 1) {
388 PJ_LOG(5,(THIS_FILE, "server receive query with invalid DNS class"));
389 continue;
390 }
391
392 /* Simulate network RTT */
393 pj_thread_sleep(50);
394
395 if (srv->action == ACTION_IGNORE) {
396 continue;
397 } else if (srv->action == ACTION_REPLY) {
398 srv->resp.hdr.id = req->hdr.id;
399 pkt_len = print_packet(&srv->resp, (pj_uint8_t*)pkt, sizeof(pkt));
400 pj_sock_sendto(srv->sock, pkt, &pkt_len, 0, &src_addr, src_len);
401 } else if (srv->action == ACTION_CB) {
402 pj_dns_parsed_packet *resp;
403 (*srv->action_cb)(req, &resp);
404 resp->hdr.id = req->hdr.id;
405 pkt_len = print_packet(resp, (pj_uint8_t*)pkt, sizeof(pkt));
406 pj_sock_sendto(srv->sock, pkt, &pkt_len, 0, &src_addr, src_len);
407 } else if (srv->action > 0) {
408 req->hdr.flags |= PJ_DNS_SET_RCODE(srv->action);
409 pkt_len = print_packet(req, (pj_uint8_t*)pkt, sizeof(pkt));
410 pj_sock_sendto(srv->sock, pkt, &pkt_len, 0, &src_addr, src_len);
411 }
412 }
413
414 return 0;
415 }
416
poll_worker_thread(void * p)417 static int poll_worker_thread(void *p)
418 {
419 PJ_UNUSED_ARG(p);
420
421 while (!thread_quit) {
422 pj_time_val delay = {0, 100};
423 pj_timer_heap_poll(timer_heap, NULL);
424 pj_ioqueue_poll(ioqueue, &delay);
425 }
426
427 return 0;
428 }
429
430 static void destroy(void);
431
init(pj_bool_t use_ipv6)432 static int init(pj_bool_t use_ipv6)
433 {
434 pj_status_t status;
435 pj_str_t nameservers[2];
436 pj_uint16_t ports[2];
437 int i;
438
439 if (use_ipv6) {
440 nameservers[0] = pj_str("::1");
441 nameservers[1] = pj_str("::1");
442 } else {
443 nameservers[0] = pj_str("127.0.0.1");
444 nameservers[1] = pj_str("127.0.0.1");
445 }
446 ports[0] = 5553;
447 ports[1] = 5554;
448
449 g_server[0].port = ports[0];
450 g_server[1].port = ports[1];
451
452 pool = pj_pool_create(mem, NULL, 2000, 2000, NULL);
453
454 status = pj_sem_create(pool, NULL, 0, 2, &sem);
455 pj_assert(status == PJ_SUCCESS);
456
457 thread_quit = PJ_FALSE;
458
459 for (i=0; i<2; ++i) {
460 pj_sockaddr addr;
461
462 status = pj_sock_socket((use_ipv6? pj_AF_INET6() : pj_AF_INET()),
463 pj_SOCK_DGRAM(), 0, &g_server[i].sock);
464 if (status != PJ_SUCCESS)
465 return -10;
466
467 pj_sockaddr_init((use_ipv6? pj_AF_INET6() : pj_AF_INET()),
468 &addr, NULL, (pj_uint16_t)g_server[i].port);
469
470 status = pj_sock_bind(g_server[i].sock, &addr, pj_sockaddr_get_len(&addr));
471 if (status != PJ_SUCCESS)
472 return -20;
473
474 status = pj_thread_create(pool, NULL, &server_thread, &g_server[i],
475 0, 0, &g_server[i].thread);
476 if (status != PJ_SUCCESS)
477 return -30;
478 }
479
480 status = pj_timer_heap_create(pool, 16, &timer_heap);
481 pj_assert(status == PJ_SUCCESS);
482
483 status = pj_ioqueue_create(pool, 16, &ioqueue);
484 pj_assert(status == PJ_SUCCESS);
485
486 status = pj_dns_resolver_create(mem, NULL, 0, timer_heap, ioqueue, &resolver);
487 if (status != PJ_SUCCESS)
488 return -40;
489
490 pj_dns_resolver_get_settings(resolver, &set);
491 set.good_ns_ttl = 20;
492 set.bad_ns_ttl = 20;
493 pj_dns_resolver_set_settings(resolver, &set);
494
495 status = pj_dns_resolver_set_ns(resolver, 2, nameservers, ports);
496 pj_assert(status == PJ_SUCCESS);
497
498 status = pj_thread_create(pool, NULL, &poll_worker_thread, NULL, 0, 0, &poll_thread);
499 pj_assert(status == PJ_SUCCESS);
500
501 return 0;
502 }
503
504
destroy(void)505 static void destroy(void)
506 {
507 int i;
508
509 thread_quit = PJ_TRUE;
510
511 for (i=0; i<2; ++i) {
512 pj_thread_join(g_server[i].thread);
513 pj_sock_close(g_server[i].sock);
514 }
515
516 pj_thread_join(poll_thread);
517
518 pj_dns_resolver_destroy(resolver, PJ_FALSE);
519 pj_ioqueue_destroy(ioqueue);
520 pj_timer_heap_destroy(timer_heap);
521
522 pj_sem_destroy(sem);
523 pj_pool_release(pool);
524 }
525
526
527 ////////////////////////////////////////////////////////////////////////////
528 /* DNS A parser tests */
a_parser_test(void)529 static int a_parser_test(void)
530 {
531 pj_dns_parsed_packet pkt;
532 pj_dns_a_record rec;
533 pj_status_t rc;
534
535 PJ_LOG(3,(THIS_FILE, " DNS A record parser tests"));
536
537 pkt.q = PJ_POOL_ZALLOC_T(pool, pj_dns_parsed_query);
538 pkt.ans = (pj_dns_parsed_rr*)
539 pj_pool_calloc(pool, 32, sizeof(pj_dns_parsed_rr));
540
541 /* Simple answer with direct A record, but with addition of
542 * a CNAME and another A to confuse the parser.
543 */
544 PJ_LOG(3,(THIS_FILE, " A RR with duplicate CNAME/A"));
545 pkt.hdr.flags = 0;
546 pkt.hdr.qdcount = 1;
547 pkt.q[0].type = PJ_DNS_TYPE_A;
548 pkt.q[0].dnsclass = 1;
549 pkt.q[0].name = pj_str("ahost");
550 pkt.hdr.anscount = 3;
551
552 /* This is the RR corresponding to the query */
553 pkt.ans[0].name = pj_str("ahost");
554 pkt.ans[0].type = PJ_DNS_TYPE_A;
555 pkt.ans[0].dnsclass = 1;
556 pkt.ans[0].ttl = 1;
557 pkt.ans[0].rdata.a.ip_addr.s_addr = 0x01020304;
558
559 /* CNAME to confuse the parser */
560 pkt.ans[1].name = pj_str("ahost");
561 pkt.ans[1].type = PJ_DNS_TYPE_CNAME;
562 pkt.ans[1].dnsclass = 1;
563 pkt.ans[1].ttl = 1;
564 pkt.ans[1].rdata.cname.name = pj_str("bhost");
565
566 /* DNS A RR to confuse the parser */
567 pkt.ans[2].name = pj_str("bhost");
568 pkt.ans[2].type = PJ_DNS_TYPE_A;
569 pkt.ans[2].dnsclass = 1;
570 pkt.ans[2].ttl = 1;
571 pkt.ans[2].rdata.a.ip_addr.s_addr = 0x0203;
572
573
574 rc = pj_dns_parse_a_response(&pkt, &rec);
575 pj_assert(rc == PJ_SUCCESS);
576 pj_assert(pj_strcmp2(&rec.name, "ahost")==0);
577 pj_assert(rec.alias.slen == 0);
578 pj_assert(rec.addr_count == 1);
579 pj_assert(rec.addr[0].s_addr == 0x01020304);
580
581 /* Answer with the target corresponds to a CNAME entry, but not
582 * as the first record, and with additions of some CNAME and A
583 * entries to confuse the parser.
584 */
585 PJ_LOG(3,(THIS_FILE, " CNAME RR with duplicate CNAME/A"));
586 pkt.hdr.flags = 0;
587 pkt.hdr.qdcount = 1;
588 pkt.q[0].type = PJ_DNS_TYPE_A;
589 pkt.q[0].dnsclass = 1;
590 pkt.q[0].name = pj_str("ahost");
591 pkt.hdr.anscount = 4;
592
593 /* This is the DNS A record for the alias */
594 pkt.ans[0].name = pj_str("ahostalias");
595 pkt.ans[0].type = PJ_DNS_TYPE_A;
596 pkt.ans[0].dnsclass = 1;
597 pkt.ans[0].ttl = 1;
598 pkt.ans[0].rdata.a.ip_addr.s_addr = 0x02020202;
599
600 /* CNAME entry corresponding to the query */
601 pkt.ans[1].name = pj_str("ahost");
602 pkt.ans[1].type = PJ_DNS_TYPE_CNAME;
603 pkt.ans[1].dnsclass = 1;
604 pkt.ans[1].ttl = 1;
605 pkt.ans[1].rdata.cname.name = pj_str("ahostalias");
606
607 /* Another CNAME to confuse the parser */
608 pkt.ans[2].name = pj_str("ahost");
609 pkt.ans[2].type = PJ_DNS_TYPE_CNAME;
610 pkt.ans[2].dnsclass = 1;
611 pkt.ans[2].ttl = 1;
612 pkt.ans[2].rdata.cname.name = pj_str("ahostalias2");
613
614 /* Another DNS A to confuse the parser */
615 pkt.ans[3].name = pj_str("ahostalias2");
616 pkt.ans[3].type = PJ_DNS_TYPE_A;
617 pkt.ans[3].dnsclass = 1;
618 pkt.ans[3].ttl = 1;
619 pkt.ans[3].rdata.a.ip_addr.s_addr = 0x03030303;
620
621 rc = pj_dns_parse_a_response(&pkt, &rec);
622 pj_assert(rc == PJ_SUCCESS);
623 pj_assert(pj_strcmp2(&rec.name, "ahost")==0);
624 pj_assert(pj_strcmp2(&rec.alias, "ahostalias")==0);
625 pj_assert(rec.addr_count == 1);
626 pj_assert(rec.addr[0].s_addr == 0x02020202);
627
628 /*
629 * No query section.
630 */
631 PJ_LOG(3,(THIS_FILE, " No query section"));
632 pkt.hdr.qdcount = 0;
633 pkt.hdr.anscount = 0;
634
635 rc = pj_dns_parse_a_response(&pkt, &rec);
636 pj_assert(rc == PJLIB_UTIL_EDNSINANSWER);
637
638 /*
639 * No answer section.
640 */
641 PJ_LOG(3,(THIS_FILE, " No answer section"));
642 pkt.hdr.flags = 0;
643 pkt.hdr.qdcount = 1;
644 pkt.q[0].type = PJ_DNS_TYPE_A;
645 pkt.q[0].dnsclass = 1;
646 pkt.q[0].name = pj_str("ahost");
647 pkt.hdr.anscount = 0;
648
649 rc = pj_dns_parse_a_response(&pkt, &rec);
650 pj_assert(rc == PJLIB_UTIL_EDNSNOANSWERREC);
651
652 /*
653 * Answer doesn't match query.
654 */
655 PJ_LOG(3,(THIS_FILE, " Answer doesn't match query"));
656 pkt.hdr.flags = 0;
657 pkt.hdr.qdcount = 1;
658 pkt.q[0].type = PJ_DNS_TYPE_A;
659 pkt.q[0].dnsclass = 1;
660 pkt.q[0].name = pj_str("ahost");
661 pkt.hdr.anscount = 1;
662
663 /* An answer that doesn't match the query */
664 pkt.ans[0].name = pj_str("ahostalias");
665 pkt.ans[0].type = PJ_DNS_TYPE_A;
666 pkt.ans[0].dnsclass = 1;
667 pkt.ans[0].ttl = 1;
668 pkt.ans[0].rdata.a.ip_addr.s_addr = 0x02020202;
669
670 rc = pj_dns_parse_a_response(&pkt, &rec);
671 pj_assert(rc == PJLIB_UTIL_EDNSNOANSWERREC);
672
673
674 /*
675 * DNS CNAME that doesn't have corresponding DNS A.
676 */
677 PJ_LOG(3,(THIS_FILE, " CNAME with no matching DNS A RR (1)"));
678 pkt.hdr.flags = 0;
679 pkt.hdr.qdcount = 1;
680 pkt.q[0].type = PJ_DNS_TYPE_A;
681 pkt.q[0].dnsclass = 1;
682 pkt.q[0].name = pj_str("ahost");
683 pkt.hdr.anscount = 1;
684
685 /* The CNAME */
686 pkt.ans[0].name = pj_str("ahost");
687 pkt.ans[0].type = PJ_DNS_TYPE_CNAME;
688 pkt.ans[0].dnsclass = 1;
689 pkt.ans[0].ttl = 1;
690 pkt.ans[0].rdata.cname.name = pj_str("ahostalias");
691
692 rc = pj_dns_parse_a_response(&pkt, &rec);
693 pj_assert(rc == PJLIB_UTIL_EDNSNOANSWERREC);
694
695
696 /*
697 * DNS CNAME that doesn't have corresponding DNS A.
698 */
699 PJ_LOG(3,(THIS_FILE, " CNAME with no matching DNS A RR (2)"));
700 pkt.hdr.flags = 0;
701 pkt.hdr.qdcount = 1;
702 pkt.q[0].type = PJ_DNS_TYPE_A;
703 pkt.q[0].dnsclass = 1;
704 pkt.q[0].name = pj_str("ahost");
705 pkt.hdr.anscount = 2;
706
707 /* The CNAME */
708 pkt.ans[0].name = pj_str("ahost");
709 pkt.ans[0].type = PJ_DNS_TYPE_CNAME;
710 pkt.ans[0].dnsclass = 1;
711 pkt.ans[0].ttl = 1;
712 pkt.ans[0].rdata.cname.name = pj_str("ahostalias");
713
714 /* DNS A record, but the name doesn't match */
715 pkt.ans[1].name = pj_str("ahost");
716 pkt.ans[1].type = PJ_DNS_TYPE_A;
717 pkt.ans[1].dnsclass = 1;
718 pkt.ans[1].ttl = 1;
719 pkt.ans[1].rdata.a.ip_addr.s_addr = 0x01020304;
720
721 rc = pj_dns_parse_a_response(&pkt, &rec);
722 pj_assert(rc == PJLIB_UTIL_EDNSNOANSWERREC);
723 PJ_UNUSED_ARG(rc);
724
725 return 0;
726 }
727
728
729 ////////////////////////////////////////////////////////////////////////////
730 /* DNS A/AAAA parser tests */
addr_parser_test(void)731 static int addr_parser_test(void)
732 {
733 pj_dns_parsed_packet pkt;
734 pj_dns_addr_record rec;
735 pj_status_t rc;
736
737 PJ_LOG(3,(THIS_FILE, " DNS A/AAAA record parser tests"));
738
739 pkt.q = PJ_POOL_ZALLOC_T(pool, pj_dns_parsed_query);
740 pkt.ans = (pj_dns_parsed_rr*)
741 pj_pool_calloc(pool, 32, sizeof(pj_dns_parsed_rr));
742
743 /* Simple answer with direct A record, but with addition of
744 * a CNAME and another A to confuse the parser.
745 */
746 PJ_LOG(3,(THIS_FILE, " A RR with duplicate CNAME/A"));
747 pkt.hdr.flags = 0;
748 pkt.hdr.qdcount = 1;
749 pkt.q[0].type = PJ_DNS_TYPE_A;
750 pkt.q[0].dnsclass = 1;
751 pkt.q[0].name = pj_str("ahost");
752 pkt.hdr.anscount = 4;
753
754 /* This is the RR corresponding to the query */
755 pkt.ans[0].name = pj_str("ahost");
756 pkt.ans[0].type = PJ_DNS_TYPE_A;
757 pkt.ans[0].dnsclass = 1;
758 pkt.ans[0].ttl = 1;
759 pkt.ans[0].rdata.a.ip_addr.s_addr = 0x01020304;
760
761 /* CNAME to confuse the parser */
762 pkt.ans[1].name = pj_str("ahost");
763 pkt.ans[1].type = PJ_DNS_TYPE_CNAME;
764 pkt.ans[1].dnsclass = 1;
765 pkt.ans[1].ttl = 1;
766 pkt.ans[1].rdata.cname.name = pj_str("bhost");
767
768 /* DNS A RR to confuse the parser */
769 pkt.ans[2].name = pj_str("bhost");
770 pkt.ans[2].type = PJ_DNS_TYPE_A;
771 pkt.ans[2].dnsclass = 1;
772 pkt.ans[2].ttl = 1;
773 pkt.ans[2].rdata.a.ip_addr.s_addr = 0x0203;
774
775 /* Additional RR corresponding to the query, DNS AAAA RR */
776 pkt.ans[3].name = pj_str("ahost");
777 pkt.ans[3].type = PJ_DNS_TYPE_AAAA;
778 pkt.ans[3].dnsclass = 1;
779 pkt.ans[3].ttl = 1;
780 s6_addr32(pkt.ans[3].rdata.aaaa.ip_addr, 0) = 0x01020304;
781
782
783 rc = pj_dns_parse_addr_response(&pkt, &rec);
784 pj_assert(rc == PJ_SUCCESS);
785 pj_assert(pj_strcmp2(&rec.name, "ahost")==0);
786 pj_assert(rec.alias.slen == 0);
787 pj_assert(rec.addr_count == 2);
788 pj_assert(rec.addr[0].af==pj_AF_INET() && rec.addr[0].ip.v4.s_addr == 0x01020304);
789 pj_assert(rec.addr[1].af==pj_AF_INET6() && s6_addr32(rec.addr[1].ip.v6, 0) == 0x01020304);
790
791 /* Answer with the target corresponds to a CNAME entry, but not
792 * as the first record, and with additions of some CNAME and A
793 * entries to confuse the parser.
794 */
795 PJ_LOG(3,(THIS_FILE, " CNAME RR with duplicate CNAME/A"));
796 pkt.hdr.flags = 0;
797 pkt.hdr.qdcount = 1;
798 pkt.q[0].type = PJ_DNS_TYPE_A;
799 pkt.q[0].dnsclass = 1;
800 pkt.q[0].name = pj_str("ahost");
801 pkt.hdr.anscount = 4;
802
803 /* This is the DNS A record for the alias */
804 pkt.ans[0].name = pj_str("ahostalias");
805 pkt.ans[0].type = PJ_DNS_TYPE_A;
806 pkt.ans[0].dnsclass = 1;
807 pkt.ans[0].ttl = 1;
808 pkt.ans[0].rdata.a.ip_addr.s_addr = 0x02020202;
809
810 /* CNAME entry corresponding to the query */
811 pkt.ans[1].name = pj_str("ahost");
812 pkt.ans[1].type = PJ_DNS_TYPE_CNAME;
813 pkt.ans[1].dnsclass = 1;
814 pkt.ans[1].ttl = 1;
815 pkt.ans[1].rdata.cname.name = pj_str("ahostalias");
816
817 /* Another CNAME to confuse the parser */
818 pkt.ans[2].name = pj_str("ahost");
819 pkt.ans[2].type = PJ_DNS_TYPE_CNAME;
820 pkt.ans[2].dnsclass = 1;
821 pkt.ans[2].ttl = 1;
822 pkt.ans[2].rdata.cname.name = pj_str("ahostalias2");
823
824 /* Another DNS A to confuse the parser */
825 pkt.ans[3].name = pj_str("ahostalias2");
826 pkt.ans[3].type = PJ_DNS_TYPE_A;
827 pkt.ans[3].dnsclass = 1;
828 pkt.ans[3].ttl = 1;
829 pkt.ans[3].rdata.a.ip_addr.s_addr = 0x03030303;
830
831 rc = pj_dns_parse_addr_response(&pkt, &rec);
832 pj_assert(rc == PJ_SUCCESS);
833 pj_assert(pj_strcmp2(&rec.name, "ahost")==0);
834 pj_assert(pj_strcmp2(&rec.alias, "ahostalias")==0);
835 pj_assert(rec.addr_count == 1);
836 pj_assert(rec.addr[0].ip.v4.s_addr == 0x02020202);
837
838 /*
839 * No query section.
840 */
841 PJ_LOG(3,(THIS_FILE, " No query section"));
842 pkt.hdr.qdcount = 0;
843 pkt.hdr.anscount = 0;
844
845 rc = pj_dns_parse_addr_response(&pkt, &rec);
846 pj_assert(rc == PJLIB_UTIL_EDNSINANSWER);
847
848 /*
849 * No answer section.
850 */
851 PJ_LOG(3,(THIS_FILE, " No answer section"));
852 pkt.hdr.flags = 0;
853 pkt.hdr.qdcount = 1;
854 pkt.q[0].type = PJ_DNS_TYPE_A;
855 pkt.q[0].dnsclass = 1;
856 pkt.q[0].name = pj_str("ahost");
857 pkt.hdr.anscount = 0;
858
859 rc = pj_dns_parse_addr_response(&pkt, &rec);
860 pj_assert(rc == PJLIB_UTIL_EDNSNOANSWERREC);
861
862 /*
863 * Answer doesn't match query.
864 */
865 PJ_LOG(3,(THIS_FILE, " Answer doesn't match query"));
866 pkt.hdr.flags = 0;
867 pkt.hdr.qdcount = 1;
868 pkt.q[0].type = PJ_DNS_TYPE_A;
869 pkt.q[0].dnsclass = 1;
870 pkt.q[0].name = pj_str("ahost");
871 pkt.hdr.anscount = 1;
872
873 /* An answer that doesn't match the query */
874 pkt.ans[0].name = pj_str("ahostalias");
875 pkt.ans[0].type = PJ_DNS_TYPE_A;
876 pkt.ans[0].dnsclass = 1;
877 pkt.ans[0].ttl = 1;
878 pkt.ans[0].rdata.a.ip_addr.s_addr = 0x02020202;
879
880 rc = pj_dns_parse_addr_response(&pkt, &rec);
881 pj_assert(rc == PJLIB_UTIL_EDNSNOANSWERREC);
882
883
884 /*
885 * DNS CNAME that doesn't have corresponding DNS A.
886 */
887 PJ_LOG(3,(THIS_FILE, " CNAME with no matching DNS A RR (1)"));
888 pkt.hdr.flags = 0;
889 pkt.hdr.qdcount = 1;
890 pkt.q[0].type = PJ_DNS_TYPE_A;
891 pkt.q[0].dnsclass = 1;
892 pkt.q[0].name = pj_str("ahost");
893 pkt.hdr.anscount = 1;
894
895 /* The CNAME */
896 pkt.ans[0].name = pj_str("ahost");
897 pkt.ans[0].type = PJ_DNS_TYPE_CNAME;
898 pkt.ans[0].dnsclass = 1;
899 pkt.ans[0].ttl = 1;
900 pkt.ans[0].rdata.cname.name = pj_str("ahostalias");
901
902 rc = pj_dns_parse_addr_response(&pkt, &rec);
903 pj_assert(rc == PJLIB_UTIL_EDNSNOANSWERREC);
904
905
906 /*
907 * DNS CNAME that doesn't have corresponding DNS A.
908 */
909 PJ_LOG(3,(THIS_FILE, " CNAME with no matching DNS A RR (2)"));
910 pkt.hdr.flags = 0;
911 pkt.hdr.qdcount = 1;
912 pkt.q[0].type = PJ_DNS_TYPE_A;
913 pkt.q[0].dnsclass = 1;
914 pkt.q[0].name = pj_str("ahost");
915 pkt.hdr.anscount = 2;
916
917 /* The CNAME */
918 pkt.ans[0].name = pj_str("ahost");
919 pkt.ans[0].type = PJ_DNS_TYPE_CNAME;
920 pkt.ans[0].dnsclass = 1;
921 pkt.ans[0].ttl = 1;
922 pkt.ans[0].rdata.cname.name = pj_str("ahostalias");
923
924 /* DNS A record, but the name doesn't match */
925 pkt.ans[1].name = pj_str("ahost");
926 pkt.ans[1].type = PJ_DNS_TYPE_A;
927 pkt.ans[1].dnsclass = 1;
928 pkt.ans[1].ttl = 1;
929 pkt.ans[1].rdata.a.ip_addr.s_addr = 0x01020304;
930
931 rc = pj_dns_parse_addr_response(&pkt, &rec);
932 pj_assert(rc == PJLIB_UTIL_EDNSNOANSWERREC);
933 PJ_UNUSED_ARG(rc);
934
935 return 0;
936 }
937
938
939 ////////////////////////////////////////////////////////////////////////////
940 /* Simple DNS test */
941 #define IP_ADDR0 0x00010203
942
dns_callback(void * user_data,pj_status_t status,pj_dns_parsed_packet * resp)943 static void dns_callback(void *user_data,
944 pj_status_t status,
945 pj_dns_parsed_packet *resp)
946 {
947 PJ_UNUSED_ARG(user_data);
948
949 pj_sem_post(sem);
950
951 PJ_ASSERT_ON_FAIL(status == PJ_SUCCESS, return);
952 PJ_ASSERT_ON_FAIL(resp, return);
953 PJ_ASSERT_ON_FAIL(resp->hdr.anscount == 1, return);
954 PJ_ASSERT_ON_FAIL(resp->ans[0].type == PJ_DNS_TYPE_A, return);
955 PJ_ASSERT_ON_FAIL(resp->ans[0].rdata.a.ip_addr.s_addr == IP_ADDR0, return);
956
957 }
958
959
simple_test(void)960 static int simple_test(void)
961 {
962 pj_str_t name = pj_str("helloworld");
963 pj_dns_parsed_packet *r;
964 pj_status_t status;
965
966 PJ_LOG(3,(THIS_FILE, " simple successful test"));
967
968 g_server[0].pkt_count = 0;
969 g_server[1].pkt_count = 0;
970
971 g_server[0].action = ACTION_REPLY;
972 r = &g_server[0].resp;
973 r->hdr.qdcount = 1;
974 r->hdr.anscount = 1;
975 r->q = PJ_POOL_ZALLOC_T(pool, pj_dns_parsed_query);
976 r->q[0].type = PJ_DNS_TYPE_A;
977 r->q[0].dnsclass = 1;
978 r->q[0].name = name;
979 r->ans = PJ_POOL_ZALLOC_T(pool, pj_dns_parsed_rr);
980 r->ans[0].type = PJ_DNS_TYPE_A;
981 r->ans[0].dnsclass = 1;
982 r->ans[0].name = name;
983 r->ans[0].rdata.a.ip_addr.s_addr = IP_ADDR0;
984
985 g_server[1].action = ACTION_REPLY;
986 r = &g_server[1].resp;
987 r->hdr.qdcount = 1;
988 r->hdr.anscount = 1;
989 r->q = PJ_POOL_ZALLOC_T(pool, pj_dns_parsed_query);
990 r->q[0].type = PJ_DNS_TYPE_A;
991 r->q[0].dnsclass = 1;
992 r->q[0].name = name;
993 r->ans = PJ_POOL_ZALLOC_T(pool, pj_dns_parsed_rr);
994 r->ans[0].type = PJ_DNS_TYPE_A;
995 r->ans[0].dnsclass = 1;
996 r->ans[0].name = name;
997 r->ans[0].rdata.a.ip_addr.s_addr = IP_ADDR0;
998
999 status = pj_dns_resolver_start_query(resolver, &name, PJ_DNS_TYPE_A, 0,
1000 &dns_callback, NULL, NULL);
1001 if (status != PJ_SUCCESS)
1002 return -1000;
1003
1004 pj_sem_wait(sem);
1005 pj_thread_sleep(1000);
1006
1007
1008 /* Both servers must get packet */
1009 pj_assert(g_server[0].pkt_count == 1);
1010 pj_assert(g_server[1].pkt_count == 1);
1011
1012 return 0;
1013 }
1014
1015
1016 ////////////////////////////////////////////////////////////////////////////
1017 /* DNS nameserver fail-over test */
1018
dns_callback_1b(void * user_data,pj_status_t status,pj_dns_parsed_packet * resp)1019 static void dns_callback_1b(void *user_data,
1020 pj_status_t status,
1021 pj_dns_parsed_packet *resp)
1022 {
1023 PJ_UNUSED_ARG(user_data);
1024 PJ_UNUSED_ARG(resp);
1025
1026 pj_sem_post(sem);
1027
1028 PJ_ASSERT_ON_FAIL(status==PJ_STATUS_FROM_DNS_RCODE(PJ_DNS_RCODE_NXDOMAIN),
1029 return);
1030 }
1031
1032
1033
1034
1035 /* DNS test */
dns_test(void)1036 static int dns_test(void)
1037 {
1038 pj_str_t name = pj_str("name00");
1039 pj_status_t status;
1040
1041 PJ_LOG(3,(THIS_FILE, " simple error response test"));
1042
1043 g_server[0].pkt_count = 0;
1044 g_server[1].pkt_count = 0;
1045
1046 g_server[0].action = PJ_DNS_RCODE_NXDOMAIN;
1047 g_server[1].action = PJ_DNS_RCODE_NXDOMAIN;
1048
1049 status = pj_dns_resolver_start_query(resolver, &name, PJ_DNS_TYPE_A, 0,
1050 &dns_callback_1b, NULL, NULL);
1051 if (status != PJ_SUCCESS)
1052 return -1000;
1053
1054 pj_sem_wait(sem);
1055 pj_thread_sleep(1000);
1056
1057 /* Now only one of the servers should get packet, since both servers are
1058 * in STATE_ACTIVE state
1059 */
1060 pj_assert(g_server[0].pkt_count + g_server[1].pkt_count == 1);
1061
1062 /* Wait to allow active period to complete and get into probing state */
1063 PJ_LOG(3,(THIS_FILE, " waiting for active NS to expire (%d sec)",
1064 set.good_ns_ttl));
1065 pj_thread_sleep(set.good_ns_ttl * 1000);
1066
1067 /*
1068 * Fail-over test
1069 */
1070 PJ_LOG(3,(THIS_FILE, " failing server0"));
1071 g_server[0].action = ACTION_IGNORE;
1072 g_server[1].action = PJ_DNS_RCODE_NXDOMAIN;
1073
1074 g_server[0].pkt_count = 0;
1075 g_server[1].pkt_count = 0;
1076
1077 name = pj_str("name01");
1078 status = pj_dns_resolver_start_query(resolver, &name, PJ_DNS_TYPE_A, 0,
1079 &dns_callback_1b, NULL, NULL);
1080 if (status != PJ_SUCCESS)
1081 return -1000;
1082
1083 pj_sem_wait(sem);
1084
1085 /* Both servers must get packet as both are in probing state */
1086 pj_assert(g_server[0].pkt_count >= 1 && g_server[1].pkt_count == 1);
1087
1088 /*
1089 * Check that both servers still receive requests, since they are
1090 * in probing & active state.
1091 */
1092 PJ_LOG(3,(THIS_FILE, " checking both NS during probing period"));
1093 g_server[0].action = ACTION_IGNORE;
1094 g_server[1].action = PJ_DNS_RCODE_NXDOMAIN;
1095
1096 g_server[0].pkt_count = 0;
1097 g_server[1].pkt_count = 0;
1098
1099 name = pj_str("name02");
1100 status = pj_dns_resolver_start_query(resolver, &name, PJ_DNS_TYPE_A, 0,
1101 &dns_callback_1b, NULL, NULL);
1102 if (status != PJ_SUCCESS)
1103 return -1000;
1104
1105 pj_sem_wait(sem);
1106 pj_thread_sleep(1000);
1107
1108 /* Both servers must get packet as both are in probing & active state */
1109 pj_assert(g_server[0].pkt_count >= 1 && g_server[1].pkt_count == 1);
1110
1111 /* Wait to allow probing period to complete, server 0 will be in bad state */
1112 PJ_LOG(3,(THIS_FILE, " waiting for probing state to end (%d sec)",
1113 set.qretr_delay *
1114 (set.qretr_count+2) / 1000));
1115 pj_thread_sleep(set.qretr_delay * (set.qretr_count + 2));
1116
1117
1118 /*
1119 * Now only server 1 should get requests.
1120 */
1121 PJ_LOG(3,(THIS_FILE, " verifying only good NS is used"));
1122 g_server[0].action = PJ_DNS_RCODE_NXDOMAIN;
1123 g_server[1].action = PJ_DNS_RCODE_NXDOMAIN;
1124
1125 g_server[0].pkt_count = 0;
1126 g_server[1].pkt_count = 0;
1127
1128 name = pj_str("name03");
1129 status = pj_dns_resolver_start_query(resolver, &name, PJ_DNS_TYPE_A, 0,
1130 &dns_callback_1b, NULL, NULL);
1131 if (status != PJ_SUCCESS)
1132 return -1000;
1133
1134 pj_sem_wait(sem);
1135 pj_thread_sleep(1000);
1136
1137 /* Only server 1 get the request */
1138 pj_assert(g_server[0].pkt_count == 0);
1139 pj_assert(g_server[1].pkt_count == 1);
1140
1141 /* Wait to allow active & bad period to complete, both will be in probing state */
1142 PJ_LOG(3,(THIS_FILE, " waiting for active NS to expire (%d sec)",
1143 set.good_ns_ttl));
1144 pj_thread_sleep(set.good_ns_ttl * 1000);
1145
1146 /*
1147 * Now fail server 1 to switch to server 0
1148 */
1149 g_server[0].action = PJ_DNS_RCODE_NXDOMAIN;
1150 g_server[1].action = ACTION_IGNORE;
1151
1152 g_server[0].pkt_count = 0;
1153 g_server[1].pkt_count = 0;
1154
1155 name = pj_str("name04");
1156 status = pj_dns_resolver_start_query(resolver, &name, PJ_DNS_TYPE_A, 0,
1157 &dns_callback_1b, NULL, NULL);
1158 if (status != PJ_SUCCESS)
1159 return -1000;
1160
1161 pj_sem_wait(sem);
1162
1163 /* Wait to allow probing period to complete, server 0 remains active, server 1 will be bad */
1164 PJ_LOG(3,(THIS_FILE, " waiting for probing state (%d sec)",
1165 set.qretr_delay * (set.qretr_count+2) / 1000));
1166 pj_thread_sleep(1000 + set.qretr_delay * (set.qretr_count + 2));
1167
1168 /*
1169 * Now only server 0 should get requests.
1170 */
1171 PJ_LOG(3,(THIS_FILE, " verifying good NS"));
1172 g_server[0].action = PJ_DNS_RCODE_NXDOMAIN;
1173 g_server[1].action = ACTION_IGNORE;
1174
1175 g_server[0].pkt_count = 0;
1176 g_server[1].pkt_count = 0;
1177
1178 name = pj_str("name05");
1179 status = pj_dns_resolver_start_query(resolver, &name, PJ_DNS_TYPE_A, 0,
1180 &dns_callback_1b, NULL, NULL);
1181 if (status != PJ_SUCCESS)
1182 return -1000;
1183
1184 pj_sem_wait(sem);
1185 pj_thread_sleep(1000);
1186
1187 /* Only good NS should get request */
1188 pj_assert(g_server[0].pkt_count == 1);
1189 pj_assert(g_server[1].pkt_count == 0);
1190
1191
1192 return 0;
1193 }
1194
1195
1196 ////////////////////////////////////////////////////////////////////////////
1197 /* Resolver test, normal, with CNAME */
1198 #define IP_ADDR1 0x02030405
1199 #define PORT1 50061
1200
action1_1(const pj_dns_parsed_packet * pkt,pj_dns_parsed_packet ** p_res)1201 static void action1_1(const pj_dns_parsed_packet *pkt,
1202 pj_dns_parsed_packet **p_res)
1203 {
1204 pj_dns_parsed_packet *res;
1205 char *target = "sip.somedomain.com";
1206
1207 res = PJ_POOL_ZALLOC_T(pool, pj_dns_parsed_packet);
1208
1209 if (res->q == NULL) {
1210 res->q = PJ_POOL_ZALLOC_T(pool, pj_dns_parsed_query);
1211 }
1212 if (res->ans == NULL) {
1213 res->ans = (pj_dns_parsed_rr*)
1214 pj_pool_calloc(pool, 4, sizeof(pj_dns_parsed_rr));
1215 }
1216
1217 res->hdr.qdcount = 1;
1218 res->q[0].type = pkt->q[0].type;
1219 res->q[0].dnsclass = pkt->q[0].dnsclass;
1220 res->q[0].name = pkt->q[0].name;
1221
1222 if (pkt->q[0].type == PJ_DNS_TYPE_SRV) {
1223
1224 pj_assert(pj_strcmp2(&pkt->q[0].name, "_sip._udp.somedomain.com")==0);
1225
1226 res->hdr.anscount = 1;
1227 res->ans[0].type = PJ_DNS_TYPE_SRV;
1228 res->ans[0].dnsclass = 1;
1229 res->ans[0].name = res->q[0].name;
1230 res->ans[0].ttl = 1;
1231 res->ans[0].rdata.srv.prio = 1;
1232 res->ans[0].rdata.srv.weight = 2;
1233 res->ans[0].rdata.srv.port = PORT1;
1234 res->ans[0].rdata.srv.target = pj_str(target);
1235
1236 } else if (pkt->q[0].type == PJ_DNS_TYPE_A) {
1237 char *alias = "sipalias.somedomain.com";
1238
1239 pj_assert(pj_strcmp2(&res->q[0].name, target)==0);
1240
1241 res->hdr.anscount = 2;
1242 res->ans[0].type = PJ_DNS_TYPE_CNAME;
1243 res->ans[0].dnsclass = 1;
1244 res->ans[0].ttl = 1000; /* resolver should select minimum TTL */
1245 res->ans[0].name = res->q[0].name;
1246 res->ans[0].rdata.cname.name = pj_str(alias);
1247
1248 res->ans[1].type = PJ_DNS_TYPE_A;
1249 res->ans[1].dnsclass = 1;
1250 res->ans[1].ttl = 1;
1251 res->ans[1].name = pj_str(alias);
1252 res->ans[1].rdata.a.ip_addr.s_addr = IP_ADDR1;
1253
1254 } else if (pkt->q[0].type == PJ_DNS_TYPE_AAAA) {
1255 char *alias = "sipalias.somedomain.com";
1256
1257 pj_assert(pj_strcmp2(&res->q[0].name, target)==0);
1258
1259 res->hdr.anscount = 2;
1260 res->ans[0].type = PJ_DNS_TYPE_CNAME;
1261 res->ans[0].dnsclass = 1;
1262 res->ans[0].ttl = 1000; /* resolver should select minimum TTL */
1263 res->ans[0].name = res->q[0].name;
1264 res->ans[0].rdata.cname.name = pj_str(alias);
1265
1266 res->ans[1].type = PJ_DNS_TYPE_AAAA;
1267 res->ans[1].dnsclass = 1;
1268 res->ans[1].ttl = 1;
1269 res->ans[1].name = pj_str(alias);
1270 s6_addr32(res->ans[1].rdata.aaaa.ip_addr, 0) = IP_ADDR1;
1271 s6_addr32(res->ans[1].rdata.aaaa.ip_addr, 1) = IP_ADDR1;
1272 s6_addr32(res->ans[1].rdata.aaaa.ip_addr, 2) = IP_ADDR1;
1273 s6_addr32(res->ans[1].rdata.aaaa.ip_addr, 3) = IP_ADDR1;
1274 }
1275
1276 *p_res = res;
1277 }
1278
srv_cb_1(void * user_data,pj_status_t status,const pj_dns_srv_record * rec)1279 static void srv_cb_1(void *user_data,
1280 pj_status_t status,
1281 const pj_dns_srv_record *rec)
1282 {
1283 PJ_UNUSED_ARG(user_data);
1284
1285 pj_sem_post(sem);
1286
1287 PJ_ASSERT_ON_FAIL(status == PJ_SUCCESS, return);
1288 PJ_ASSERT_ON_FAIL(rec->count == 1, return);
1289 PJ_ASSERT_ON_FAIL(rec->entry[0].priority == 1, return);
1290 PJ_ASSERT_ON_FAIL(rec->entry[0].weight == 2, return);
1291 PJ_ASSERT_ON_FAIL(pj_strcmp2(&rec->entry[0].server.name, "sip.somedomain.com")==0,
1292 return);
1293 PJ_ASSERT_ON_FAIL(pj_strcmp2(&rec->entry[0].server.alias, "sipalias.somedomain.com")==0,
1294 return);
1295
1296 /* IPv4 only */
1297 PJ_ASSERT_ON_FAIL(rec->entry[0].server.addr_count == 1, return);
1298 PJ_ASSERT_ON_FAIL(rec->entry[0].server.addr[0].ip.v4.s_addr == IP_ADDR1, return);
1299 PJ_ASSERT_ON_FAIL(rec->entry[0].port == PORT1, return);
1300
1301
1302 }
1303
1304
srv_cb_1b(void * user_data,pj_status_t status,const pj_dns_srv_record * rec)1305 static void srv_cb_1b(void *user_data,
1306 pj_status_t status,
1307 const pj_dns_srv_record *rec)
1308 {
1309 PJ_UNUSED_ARG(user_data);
1310
1311 pj_sem_post(sem);
1312
1313 PJ_ASSERT_ON_FAIL(status==PJ_STATUS_FROM_DNS_RCODE(PJ_DNS_RCODE_NXDOMAIN),
1314 return);
1315 PJ_ASSERT_ON_FAIL(rec->count == 0, return);
1316 }
1317
1318
srv_cb_1c(void * user_data,pj_status_t status,const pj_dns_srv_record * rec)1319 static void srv_cb_1c(void *user_data,
1320 pj_status_t status,
1321 const pj_dns_srv_record *rec)
1322 {
1323 PJ_UNUSED_ARG(user_data);
1324
1325 pj_sem_post(sem);
1326
1327 PJ_ASSERT_ON_FAIL(status == PJ_SUCCESS, return);
1328 PJ_ASSERT_ON_FAIL(rec->count == 1, return);
1329 PJ_ASSERT_ON_FAIL(rec->entry[0].priority == 1, return);
1330 PJ_ASSERT_ON_FAIL(rec->entry[0].weight == 2, return);
1331
1332 PJ_ASSERT_ON_FAIL(pj_strcmp2(&rec->entry[0].server.name, "sip.somedomain.com")==0,
1333 return);
1334 PJ_ASSERT_ON_FAIL(pj_strcmp2(&rec->entry[0].server.alias, "sipalias.somedomain.com")==0,
1335 return);
1336 PJ_ASSERT_ON_FAIL(rec->entry[0].port == PORT1, return);
1337
1338 /* IPv4 and IPv6 */
1339 PJ_ASSERT_ON_FAIL(rec->entry[0].server.addr_count == 2, return);
1340 PJ_ASSERT_ON_FAIL(rec->entry[0].server.addr[0].af == pj_AF_INET() &&
1341 rec->entry[0].server.addr[0].ip.v4.s_addr == IP_ADDR1, return);
1342 PJ_ASSERT_ON_FAIL(rec->entry[0].server.addr[1].af == pj_AF_INET6() &&
1343 s6_addr32(rec->entry[0].server.addr[1].ip.v6, 0) == IP_ADDR1, return);
1344 }
1345
1346
srv_cb_1d(void * user_data,pj_status_t status,const pj_dns_srv_record * rec)1347 static void srv_cb_1d(void *user_data,
1348 pj_status_t status,
1349 const pj_dns_srv_record *rec)
1350 {
1351 PJ_UNUSED_ARG(user_data);
1352
1353 pj_sem_post(sem);
1354
1355 PJ_ASSERT_ON_FAIL(status == PJ_SUCCESS, return);
1356 PJ_ASSERT_ON_FAIL(rec->count == 1, return);
1357 PJ_ASSERT_ON_FAIL(rec->entry[0].priority == 1, return);
1358 PJ_ASSERT_ON_FAIL(rec->entry[0].weight == 2, return);
1359
1360 PJ_ASSERT_ON_FAIL(pj_strcmp2(&rec->entry[0].server.name, "sip.somedomain.com")==0,
1361 return);
1362 PJ_ASSERT_ON_FAIL(pj_strcmp2(&rec->entry[0].server.alias, "sipalias.somedomain.com")==0,
1363 return);
1364 PJ_ASSERT_ON_FAIL(rec->entry[0].port == PORT1, return);
1365
1366 /* IPv6 only */
1367 PJ_ASSERT_ON_FAIL(rec->entry[0].server.addr_count == 1, return);
1368 PJ_ASSERT_ON_FAIL(rec->entry[0].server.addr[0].af == pj_AF_INET6() &&
1369 s6_addr32(rec->entry[0].server.addr[0].ip.v6, 0) == IP_ADDR1, return);
1370 }
1371
1372
srv_resolver_test(void)1373 static int srv_resolver_test(void)
1374 {
1375 pj_status_t status;
1376 pj_str_t domain = pj_str("somedomain.com");
1377 pj_str_t res_name = pj_str("_sip._udp.");
1378
1379 /* Last servers state: server 0=active, server 1=bad*/
1380
1381 /* Successful scenario */
1382 PJ_LOG(3,(THIS_FILE, " srv_resolve(): success scenario"));
1383
1384 g_server[0].action = ACTION_CB;
1385 g_server[0].action_cb = &action1_1;
1386 g_server[1].action = ACTION_CB;
1387 g_server[1].action_cb = &action1_1;
1388
1389 g_server[0].pkt_count = 0;
1390 g_server[1].pkt_count = 0;
1391
1392 status = pj_dns_srv_resolve(&domain, &res_name, 5061, pool, resolver, PJ_TRUE,
1393 NULL, &srv_cb_1, NULL);
1394 pj_assert(status == PJ_SUCCESS);
1395
1396 pj_sem_wait(sem);
1397
1398 /* Because of previous tests, only NS 1 should get the request */
1399 pj_assert(g_server[0].pkt_count == 2); /* 2 because of SRV and A resolution */
1400 pj_assert(g_server[1].pkt_count == 0);
1401
1402
1403 /* Wait until cache expires */
1404 PJ_LOG(3,(THIS_FILE, " waiting for cache to expire (~1 secs).."));
1405 pj_thread_sleep(1000 + 100);
1406
1407
1408 /* DNS SRV option PJ_DNS_SRV_RESOLVE_AAAA */
1409 PJ_LOG(3,(THIS_FILE, " srv_resolve(): option PJ_DNS_SRV_RESOLVE_AAAA"));
1410
1411 g_server[0].action = ACTION_CB;
1412 g_server[0].action_cb = &action1_1;
1413 g_server[1].action = ACTION_CB;
1414 g_server[1].action_cb = &action1_1;
1415
1416 g_server[0].pkt_count = 0;
1417 g_server[1].pkt_count = 0;
1418
1419 status = pj_dns_srv_resolve(&domain, &res_name, 5061, pool, resolver,
1420 PJ_DNS_SRV_RESOLVE_AAAA,
1421 NULL, &srv_cb_1c, NULL);
1422 pj_assert(status == PJ_SUCCESS);
1423
1424 pj_sem_wait(sem);
1425 pj_thread_sleep(1000);
1426
1427 /* DNS SRV option PJ_DNS_SRV_RESOLVE_AAAA_ONLY */
1428 PJ_LOG(3,(THIS_FILE, " srv_resolve(): option PJ_DNS_SRV_RESOLVE_AAAA_ONLY"));
1429
1430 g_server[0].action = ACTION_CB;
1431 g_server[0].action_cb = &action1_1;
1432 g_server[1].action = ACTION_CB;
1433 g_server[1].action_cb = &action1_1;
1434
1435 g_server[0].pkt_count = 0;
1436 g_server[1].pkt_count = 0;
1437
1438 status = pj_dns_srv_resolve(&domain, &res_name, 5061, pool, resolver,
1439 PJ_DNS_SRV_RESOLVE_AAAA_ONLY,
1440 NULL, &srv_cb_1d, NULL);
1441 pj_assert(status == PJ_SUCCESS);
1442
1443 pj_sem_wait(sem);
1444 pj_thread_sleep(1000);
1445
1446
1447 /* Successful scenario */
1448 PJ_LOG(3,(THIS_FILE, " srv_resolve(): parallel queries"));
1449 g_server[0].pkt_count = 0;
1450 g_server[1].pkt_count = 0;
1451
1452 status = pj_dns_srv_resolve(&domain, &res_name, 5061, pool, resolver, PJ_TRUE,
1453 NULL, &srv_cb_1, NULL);
1454 pj_assert(status == PJ_SUCCESS);
1455
1456
1457 status = pj_dns_srv_resolve(&domain, &res_name, 5061, pool, resolver, PJ_TRUE,
1458 NULL, &srv_cb_1, NULL);
1459 pj_assert(status == PJ_SUCCESS);
1460
1461 pj_sem_wait(sem);
1462 pj_sem_wait(sem);
1463
1464 /* Only server one should get a query */
1465 pj_assert(g_server[0].pkt_count == 2); /* 2 because of SRV and A resolution */
1466 pj_assert(g_server[1].pkt_count == 0);
1467
1468 /* Since TTL is one, subsequent queries should fail */
1469 PJ_LOG(3,(THIS_FILE, " srv_resolve(): cache expires scenario"));
1470
1471 pj_thread_sleep(1000 + 100);
1472
1473 g_server[0].action = PJ_DNS_RCODE_NXDOMAIN;
1474 g_server[1].action = PJ_DNS_RCODE_NXDOMAIN;
1475
1476 status = pj_dns_srv_resolve(&domain, &res_name, 5061, pool, resolver, PJ_TRUE,
1477 NULL, &srv_cb_1b, NULL);
1478 pj_assert(status == PJ_SUCCESS);
1479
1480 pj_sem_wait(sem);
1481 pj_thread_sleep(1000);
1482
1483 return status;
1484 }
1485
1486
1487 ////////////////////////////////////////////////////////////////////////////
1488 /* Fallback because there's no SRV in answer */
1489 #define TARGET "domain2.com"
1490 #define IP_ADDR2 0x02030405
1491 #define PORT2 50062
1492
action2_1(const pj_dns_parsed_packet * pkt,pj_dns_parsed_packet ** p_res)1493 static void action2_1(const pj_dns_parsed_packet *pkt,
1494 pj_dns_parsed_packet **p_res)
1495 {
1496 pj_dns_parsed_packet *res;
1497
1498 res = PJ_POOL_ZALLOC_T(pool, pj_dns_parsed_packet);
1499
1500 res->q = PJ_POOL_ZALLOC_T(pool, pj_dns_parsed_query);
1501 res->ans = (pj_dns_parsed_rr*)
1502 pj_pool_calloc(pool, 4, sizeof(pj_dns_parsed_rr));
1503
1504 res->hdr.qdcount = 1;
1505 res->q[0].type = pkt->q[0].type;
1506 res->q[0].dnsclass = pkt->q[0].dnsclass;
1507 res->q[0].name = pkt->q[0].name;
1508
1509 if (pkt->q[0].type == PJ_DNS_TYPE_SRV) {
1510
1511 pj_assert(pj_strcmp2(&pkt->q[0].name, "_sip._udp." TARGET)==0);
1512
1513 res->hdr.anscount = 1;
1514 res->ans[0].type = PJ_DNS_TYPE_A; // <-- this will cause the fallback
1515 res->ans[0].dnsclass = 1;
1516 res->ans[0].name = res->q[0].name;
1517 res->ans[0].ttl = 1;
1518 res->ans[0].rdata.srv.prio = 1;
1519 res->ans[0].rdata.srv.weight = 2;
1520 res->ans[0].rdata.srv.port = PORT2;
1521 res->ans[0].rdata.srv.target = pj_str("sip01." TARGET);
1522
1523 } else if (pkt->q[0].type == PJ_DNS_TYPE_A) {
1524 char *alias = "sipalias01." TARGET;
1525
1526 pj_assert(pj_strcmp2(&res->q[0].name, TARGET)==0);
1527
1528 res->hdr.anscount = 2;
1529 res->ans[0].type = PJ_DNS_TYPE_CNAME;
1530 res->ans[0].dnsclass = 1;
1531 res->ans[0].name = res->q[0].name;
1532 res->ans[0].ttl = 1;
1533 res->ans[0].rdata.cname.name = pj_str(alias);
1534
1535 res->ans[1].type = PJ_DNS_TYPE_A;
1536 res->ans[1].dnsclass = 1;
1537 res->ans[1].name = pj_str(alias);
1538 res->ans[1].ttl = 1;
1539 res->ans[1].rdata.a.ip_addr.s_addr = IP_ADDR2;
1540
1541 } else if (pkt->q[0].type == PJ_DNS_TYPE_AAAA) {
1542 char *alias = "sipalias01." TARGET;
1543
1544 pj_assert(pj_strcmp2(&res->q[0].name, TARGET)==0);
1545
1546 res->hdr.anscount = 2;
1547 res->ans[0].type = PJ_DNS_TYPE_CNAME;
1548 res->ans[0].dnsclass = 1;
1549 res->ans[0].name = res->q[0].name;
1550 res->ans[0].ttl = 1;
1551 res->ans[0].rdata.cname.name = pj_str(alias);
1552
1553 res->ans[1].type = PJ_DNS_TYPE_AAAA;
1554 res->ans[1].dnsclass = 1;
1555 res->ans[1].ttl = 1;
1556 res->ans[1].name = pj_str(alias);
1557 s6_addr32(res->ans[1].rdata.aaaa.ip_addr, 0) = IP_ADDR2;
1558 s6_addr32(res->ans[1].rdata.aaaa.ip_addr, 1) = IP_ADDR2;
1559 s6_addr32(res->ans[1].rdata.aaaa.ip_addr, 2) = IP_ADDR2;
1560 s6_addr32(res->ans[1].rdata.aaaa.ip_addr, 3) = IP_ADDR2;
1561 }
1562
1563 *p_res = res;
1564 }
1565
1566 #define SRV_CB_CHECK(cond, err) if(!(cond)) { *cb_err=err; goto on_return; }
1567
srv_cb_2(void * user_data,pj_status_t status,const pj_dns_srv_record * rec)1568 static void srv_cb_2(void *user_data,
1569 pj_status_t status,
1570 const pj_dns_srv_record *rec)
1571 {
1572 int *cb_err = (int*)user_data;
1573
1574 SRV_CB_CHECK(status == PJ_SUCCESS, -10);
1575 SRV_CB_CHECK(rec->count == 1, -20);
1576 SRV_CB_CHECK(rec->entry[0].priority == 0, -30);
1577 SRV_CB_CHECK(rec->entry[0].weight == 0, -40);
1578 SRV_CB_CHECK(pj_strcmp2(&rec->entry[0].server.name, TARGET)==0, -50);
1579 SRV_CB_CHECK(pj_strcmp2(&rec->entry[0].server.alias,
1580 "sipalias01." TARGET)==0, -60);
1581 SRV_CB_CHECK(rec->entry[0].port == PORT2, -70);
1582
1583 /* IPv4 only */
1584 SRV_CB_CHECK(rec->entry[0].server.addr_count == 1, -80);
1585 SRV_CB_CHECK(rec->entry[0].server.addr[0].af == pj_AF_INET() &&
1586 rec->entry[0].server.addr[0].ip.v4.s_addr == IP_ADDR2, -90);
1587
1588 on_return:
1589 pj_sem_post(sem);
1590 }
1591
srv_cb_2a(void * user_data,pj_status_t status,const pj_dns_srv_record * rec)1592 static void srv_cb_2a(void *user_data,
1593 pj_status_t status,
1594 const pj_dns_srv_record *rec)
1595 {
1596 int *cb_err = (int*)user_data;
1597
1598 SRV_CB_CHECK(status == PJ_SUCCESS, -10);
1599 SRV_CB_CHECK(rec->count == 1, -20);
1600 SRV_CB_CHECK(rec->entry[0].priority == 0, -30);
1601 SRV_CB_CHECK(rec->entry[0].weight == 0, -40);
1602 SRV_CB_CHECK(pj_strcmp2(&rec->entry[0].server.name, TARGET)==0, -50);
1603 SRV_CB_CHECK(pj_strcmp2(&rec->entry[0].server.alias,
1604 "sipalias01." TARGET)==0, -60);
1605 SRV_CB_CHECK(rec->entry[0].port == PORT2, -70);
1606
1607 /* IPv4 and IPv6 */
1608 SRV_CB_CHECK(rec->entry[0].server.addr_count == 2, -80);
1609 SRV_CB_CHECK(rec->entry[0].server.addr[0].af == pj_AF_INET() &&
1610 rec->entry[0].server.addr[0].ip.v4.s_addr == IP_ADDR2, -90);
1611 SRV_CB_CHECK(rec->entry[0].server.addr[1].af == pj_AF_INET6() &&
1612 s6_addr32(rec->entry[0].server.addr[1].ip.v6, 0) == IP_ADDR2,
1613 -100);
1614
1615 on_return:
1616 pj_sem_post(sem);
1617 }
1618
srv_cb_2b(void * user_data,pj_status_t status,const pj_dns_srv_record * rec)1619 static void srv_cb_2b(void *user_data,
1620 pj_status_t status,
1621 const pj_dns_srv_record *rec)
1622 {
1623 int *cb_err = (int*)user_data;
1624
1625 SRV_CB_CHECK(status == PJ_SUCCESS, -10);
1626 SRV_CB_CHECK(rec->count == 1, -20);
1627 SRV_CB_CHECK(rec->entry[0].priority == 0, -30);
1628 SRV_CB_CHECK(rec->entry[0].weight == 0, -40);
1629 SRV_CB_CHECK(pj_strcmp2(&rec->entry[0].server.name, TARGET)==0, -50);
1630 SRV_CB_CHECK(pj_strcmp2(&rec->entry[0].server.alias,
1631 "sipalias01." TARGET)==0, -60);
1632 SRV_CB_CHECK(rec->entry[0].port == PORT2, -70);
1633
1634 /* IPv6 only */
1635 SRV_CB_CHECK(rec->entry[0].server.addr_count == 1, -80);
1636 SRV_CB_CHECK(rec->entry[0].server.addr[0].af == pj_AF_INET6() &&
1637 s6_addr32(rec->entry[0].server.addr[0].ip.v6, 0) == IP_ADDR2,
1638 -90);
1639
1640 on_return:
1641 pj_sem_post(sem);
1642 }
1643
srv_resolver_fallback_test(void)1644 static int srv_resolver_fallback_test(void)
1645 {
1646 pj_status_t status;
1647 pj_str_t domain = pj_str(TARGET);
1648 pj_str_t res_name = pj_str("_sip._udp.");
1649 int cb_err = 0;
1650
1651 /* Fallback test */
1652 PJ_LOG(3,(THIS_FILE, " srv_resolve(): fallback test"));
1653
1654 g_server[0].action = ACTION_CB;
1655 g_server[0].action_cb = &action2_1;
1656 g_server[1].action = ACTION_CB;
1657 g_server[1].action_cb = &action2_1;
1658
1659 status = pj_dns_srv_resolve(&domain, &res_name, PORT2, pool, resolver, PJ_TRUE,
1660 &cb_err, &srv_cb_2, NULL);
1661 if (status != PJ_SUCCESS) {
1662 app_perror(" srv_resolve error", status);
1663 return -10;
1664 }
1665
1666 pj_sem_wait(sem);
1667
1668 if (cb_err != 0) {
1669 PJ_LOG(3,("test", " srv_resolve cb error, code=%d", cb_err));
1670 return -20;
1671 }
1672
1673 /* Subsequent query should just get the response from the cache */
1674 PJ_LOG(3,(THIS_FILE, " srv_resolve(): cache test"));
1675 g_server[0].pkt_count = 0;
1676 g_server[1].pkt_count = 0;
1677
1678 status = pj_dns_srv_resolve(&domain, &res_name, PORT2, pool, resolver, PJ_TRUE,
1679 &cb_err, &srv_cb_2, NULL);
1680 if (status != PJ_SUCCESS) {
1681 app_perror(" srv_resolve error", status);
1682 return -30;
1683 }
1684
1685 pj_sem_wait(sem);
1686
1687 if (cb_err != 0) {
1688 PJ_LOG(3,("test", " srv_resolve cb error, code=%d", cb_err));
1689 return -40;
1690 }
1691
1692 if (g_server[0].pkt_count != 0 || g_server[1].pkt_count != 0) {
1693 PJ_LOG(3,("test", " srv_resolve() not from cache"));
1694 return -50;
1695 }
1696
1697 /* Clear cache */
1698 pj_thread_sleep(1000);
1699
1700 /* Fallback with PJ_DNS_SRV_FALLBACK_A and PJ_DNS_SRV_FALLBACK_AAAA */
1701 PJ_LOG(3,(THIS_FILE, " srv_resolve(): fallback to DNS A and AAAA"));
1702
1703 g_server[0].action = ACTION_CB;
1704 g_server[0].action_cb = &action2_1;
1705 g_server[1].action = ACTION_CB;
1706 g_server[1].action_cb = &action2_1;
1707
1708 status = pj_dns_srv_resolve(&domain, &res_name, PORT2, pool, resolver,
1709 PJ_DNS_SRV_FALLBACK_A | PJ_DNS_SRV_FALLBACK_AAAA,
1710 &cb_err, &srv_cb_2a, NULL);
1711 if (status != PJ_SUCCESS) {
1712 app_perror(" srv_resolve error", status);
1713 return -60;
1714 }
1715
1716 pj_sem_wait(sem);
1717
1718 if (cb_err != 0) {
1719 PJ_LOG(3,("test", " srv_resolve cb error, code=%d", cb_err));
1720 return -70;
1721 }
1722
1723 /* Clear cache */
1724 pj_thread_sleep(1000);
1725
1726 /* Fallback with PJ_DNS_SRV_FALLBACK_AAAA only */
1727 PJ_LOG(3,(THIS_FILE, " srv_resolve(): fallback to DNS AAAA only"));
1728
1729 g_server[0].action = ACTION_CB;
1730 g_server[0].action_cb = &action2_1;
1731 g_server[1].action = ACTION_CB;
1732 g_server[1].action_cb = &action2_1;
1733
1734 status = pj_dns_srv_resolve(&domain, &res_name, PORT2, pool, resolver,
1735 PJ_DNS_SRV_FALLBACK_AAAA,
1736 &cb_err, &srv_cb_2b, NULL);
1737 if (status != PJ_SUCCESS) {
1738 app_perror(" srv_resolve error", status);
1739 return -80;
1740 }
1741
1742 pj_sem_wait(sem);
1743
1744 if (cb_err != 0) {
1745 PJ_LOG(3,("test", " srv_resolve cb error, code=%d", cb_err));
1746 return -90;
1747 }
1748
1749 /* Clear cache */
1750 pj_thread_sleep(1000);
1751
1752 return 0;
1753 }
1754
1755
1756 ////////////////////////////////////////////////////////////////////////////
1757 /* Too many SRV or A entries */
1758 #define DOMAIN3 "d3"
1759 #define SRV_COUNT3 (PJ_DNS_SRV_MAX_ADDR+1)
1760 #define A_COUNT3 (PJ_DNS_MAX_IP_IN_A_REC+1)
1761 #define PORT3 50063
1762 #define IP_ADDR3 0x03030303
1763
action3_1(const pj_dns_parsed_packet * pkt,pj_dns_parsed_packet ** p_res)1764 static void action3_1(const pj_dns_parsed_packet *pkt,
1765 pj_dns_parsed_packet **p_res)
1766 {
1767 pj_dns_parsed_packet *res;
1768 unsigned i;
1769
1770 res = PJ_POOL_ZALLOC_T(pool, pj_dns_parsed_packet);
1771
1772 if (res->q == NULL) {
1773 res->q = PJ_POOL_ZALLOC_T(pool, pj_dns_parsed_query);
1774 }
1775
1776 res->hdr.qdcount = 1;
1777 res->q[0].type = pkt->q[0].type;
1778 res->q[0].dnsclass = pkt->q[0].dnsclass;
1779 res->q[0].name = pkt->q[0].name;
1780
1781 if (pkt->q[0].type == PJ_DNS_TYPE_SRV) {
1782
1783 pj_assert(pj_strcmp2(&pkt->q[0].name, "_sip._udp." DOMAIN3)==0);
1784
1785 res->hdr.anscount = SRV_COUNT3;
1786 res->ans = (pj_dns_parsed_rr*)
1787 pj_pool_calloc(pool, SRV_COUNT3, sizeof(pj_dns_parsed_rr));
1788
1789 for (i=0; i<SRV_COUNT3; ++i) {
1790 char *target;
1791
1792 res->ans[i].type = PJ_DNS_TYPE_SRV;
1793 res->ans[i].dnsclass = 1;
1794 res->ans[i].name = res->q[0].name;
1795 res->ans[i].ttl = 1;
1796 res->ans[i].rdata.srv.prio = (pj_uint16_t)i;
1797 res->ans[i].rdata.srv.weight = 2;
1798 res->ans[i].rdata.srv.port = (pj_uint16_t)(PORT3+i);
1799
1800 target = (char*)pj_pool_alloc(pool, 16);
1801 sprintf(target, "sip%02d." DOMAIN3, i);
1802 res->ans[i].rdata.srv.target = pj_str(target);
1803 }
1804
1805 } else if (pkt->q[0].type == PJ_DNS_TYPE_A) {
1806
1807 //pj_assert(pj_strcmp2(&res->q[0].name, "sip." DOMAIN3)==0);
1808
1809 res->hdr.anscount = A_COUNT3;
1810 res->ans = (pj_dns_parsed_rr*)
1811 pj_pool_calloc(pool, A_COUNT3, sizeof(pj_dns_parsed_rr));
1812
1813 for (i=0; i<A_COUNT3; ++i) {
1814 res->ans[i].type = PJ_DNS_TYPE_A;
1815 res->ans[i].dnsclass = 1;
1816 res->ans[i].ttl = 1;
1817 res->ans[i].name = res->q[0].name;
1818 res->ans[i].rdata.a.ip_addr.s_addr = IP_ADDR3+i;
1819 }
1820 }
1821
1822 *p_res = res;
1823 }
1824
srv_cb_3(void * user_data,pj_status_t status,const pj_dns_srv_record * rec)1825 static void srv_cb_3(void *user_data,
1826 pj_status_t status,
1827 const pj_dns_srv_record *rec)
1828 {
1829 unsigned i;
1830 int *cb_err = (int*)user_data;
1831
1832 PJ_UNUSED_ARG(status);
1833 PJ_UNUSED_ARG(rec);
1834
1835 SRV_CB_CHECK(status == PJ_SUCCESS, -10);
1836 SRV_CB_CHECK(rec->count == PJ_DNS_SRV_MAX_ADDR, -20);
1837
1838 for (i=0; i<PJ_DNS_SRV_MAX_ADDR; ++i) {
1839 unsigned j;
1840
1841 SRV_CB_CHECK(rec->entry[i].priority == i, -30);
1842 SRV_CB_CHECK(rec->entry[i].weight == 2, -40);
1843 //pj_assert(pj_strcmp2(&rec->entry[i].server.name, "sip." DOMAIN3)==0);
1844 SRV_CB_CHECK(rec->entry[i].server.alias.slen == 0, -50);
1845 SRV_CB_CHECK(rec->entry[i].port == PORT3+i, -60);
1846
1847 SRV_CB_CHECK(rec->entry[i].server.addr_count == PJ_DNS_MAX_IP_IN_A_REC, -70);
1848
1849 for (j=0; j<PJ_DNS_MAX_IP_IN_A_REC; ++j) {
1850 SRV_CB_CHECK(rec->entry[i].server.addr[j].ip.v4.s_addr == IP_ADDR3+j, -80);
1851 }
1852 }
1853
1854 on_return:
1855 pj_sem_post(sem);
1856 }
1857
srv_resolver_many_test(void)1858 static int srv_resolver_many_test(void)
1859 {
1860 pj_status_t status;
1861 pj_str_t domain = pj_str(DOMAIN3);
1862 pj_str_t res_name = pj_str("_sip._udp.");
1863 int cb_err = 0;
1864
1865 /* Successful scenario */
1866 PJ_LOG(3,(THIS_FILE, " srv_resolve(): too many entries test"));
1867
1868 g_server[0].action = ACTION_CB;
1869 g_server[0].action_cb = &action3_1;
1870 g_server[1].action = ACTION_CB;
1871 g_server[1].action_cb = &action3_1;
1872
1873 g_server[0].pkt_count = 0;
1874 g_server[1].pkt_count = 0;
1875
1876 status = pj_dns_srv_resolve(&domain, &res_name, 1, pool, resolver, PJ_TRUE,
1877 &cb_err, &srv_cb_3, NULL);
1878 if (status != PJ_SUCCESS) {
1879 app_perror(" srv_resolve error", status);
1880 return -10;
1881 }
1882
1883 pj_sem_wait(sem);
1884
1885 if (cb_err != 0) {
1886 PJ_LOG(3,("test", " srv_resolve cb error, code=%d", cb_err));
1887 return -20;
1888 }
1889
1890 return 0;
1891 }
1892
1893
1894 ////////////////////////////////////////////////////////////////////////////
1895
1896
resolver_test(void)1897 int resolver_test(void)
1898 {
1899 int rc;
1900
1901 rc = init(PJ_FALSE);
1902 if (rc != 0)
1903 goto on_error;
1904
1905 rc = a_parser_test();
1906 if (rc != 0)
1907 goto on_error;
1908
1909 rc = addr_parser_test();
1910 if (rc != 0)
1911 goto on_error;
1912
1913 rc = simple_test();
1914 if (rc != 0)
1915 goto on_error;
1916
1917 rc = dns_test();
1918 if (rc != 0)
1919 goto on_error;
1920
1921 rc = srv_resolver_test();
1922 if (rc != 0)
1923 goto on_error;
1924
1925 rc = srv_resolver_fallback_test();
1926 if (rc != 0)
1927 goto on_error;
1928
1929 rc = srv_resolver_many_test();
1930 if (rc != 0)
1931 goto on_error;
1932
1933 destroy();
1934
1935
1936 #if PJ_HAS_IPV6
1937 /* Similar tests using IPv6 socket and without parser tests */
1938 PJ_LOG(3,(THIS_FILE, "Re-run DNS resolution tests using IPv6 socket"));
1939
1940 rc = init(PJ_TRUE);
1941 if (rc != 0)
1942 goto on_error;
1943
1944 rc = simple_test();
1945 if (rc != 0)
1946 goto on_error;
1947
1948 rc = dns_test();
1949 if (rc != 0)
1950 goto on_error;
1951
1952 rc = srv_resolver_test();
1953 if (rc != 0)
1954 goto on_error;
1955
1956 rc = srv_resolver_fallback_test();
1957 if (rc != 0)
1958 goto on_error;
1959
1960 rc = srv_resolver_many_test();
1961 if (rc != 0)
1962 goto on_error;
1963
1964 destroy();
1965 #endif
1966
1967 return 0;
1968
1969 on_error:
1970 destroy();
1971 return rc;
1972 }
1973
1974