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